the terms of the MIT X11, this means that this code can be
used for any purposes by anyone.
-** mono/metadata/sgen*: Mono's Copying Collector
-
- This new garbage collector is licensed under the terms of
- the MIT X11 license, in hopes that the GC could be reused
- by third party projects, follows the same spirit than the
- Boehm GC.
-
** mono/arch/*/XXX-codegen.h
This are C macros that are useful when generating native
.PHONY: update_submodules
EXTRA_DIST= \
+ README.md \
LICENSE \
autogen.sh \
build-mingw32.sh \
+++ /dev/null
-This is Mono.
-
- 1. Installation
- 2. Using Mono
- 3. Directory Roadmap
- 4. git submodules maintenance
- 5. Reporting bugs
-
-1. Compilation and Installation
-===============================
-
- a. Build Requirements
- ---------------------
-
- On Itanium, you must obtain libunwind:
-
- http://www.hpl.hp.com/research/linux/libunwind/download.php4
-
- On Solaris, make sure that you used GNU tar to unpack this package, as
- Solaris tar will not unpack this correctly, and you will get strange errors.
-
- On Solaris, make sure that you use the GNU toolchain to build the software.
-
- Optional dependencies:
-
- * libgdiplus
-
- If you want to get support for System.Drawing, you will need to get
- Libgdiplus. This library in turn requires glib and pkg-config:
-
- * pkg-config
-
- Available from: http://www.freedesktop.org/Software/pkgconfig
-
- * glib 2.4
-
- Available from: http://www.gtk.org/
-
- * libzlib
-
- This library and the development headers are required for compression
- file support in the 2.0 profile.
-
- b. Building the Software
- ------------------------
-
- If you obtained this package as an officially released tarball,
- this is very simple, use configure and make:
-
- ./configure --prefix=/usr/local
- make
- make install
-
- Mono supports a JIT engine on x86, SPARC, SPARCv9, S/390,
- S/390x, AMD64, ARM and PowerPC systems.
-
- If you obtained this as a snapshot, you will need an existing
- Mono installation. To upgrade your installation, unpack both
- mono and mcs:
-
- tar xzf mcs-XXXX.tar.gz
- tar xzf mono-XXXX.tar.gz
- mv mono-XXX mono
- mv mcs-XXX mcs
- cd mono
- ./autogen.sh --prefix=/usr/local
- make
-
- The Mono build system is silent for most compilation commands.
- To enable a more verbose compile (for example, to pinpoint
- problems in your makefiles or your system) pass the V=1 flag to make, like this:
-
- make V=1
-
-
- c. Building the software from GIT
- ---------------------------------
-
- If you are building the software from GIT, make sure that you
- have up-to-date mcs and mono sources:
-
- If you are an anonymous user:
- git clone git://github.com/mono/mono.git
-
- If you are a Mono contributors with read/write privileges:
- git clone git@github.com:mono/mono.git
-
-
- Then, go into the mono directory, and configure:
-
- cd mono
- ./autogen.sh --prefix=/usr/local
- make
-
- For people with non-standard installations of the auto* utils and of
- pkg-config (common on misconfigured OSX and windows boxes), you could get
- an error like this:
-
- ./configure: line 19176: syntax error near unexpected token `PKG_CHECK_MODULES(BASE_DEPENDENCIES,' ...
-
- This means that you need to set the ACLOCAL_FLAGS environment var
- when invoking autogen.sh, like this:
-
- ACLOCAL_FLAGS="-I $acprefix/share/aclocal" ./autogen.sh --prefix=/usr/loca
-
- where $acprefix is the prefix where aclocal has been installed.
-
- This will automatically go into the mcs/ tree and build the
- binaries there.
-
- This assumes that you have a working mono installation, and that
- there's a C# compiler named 'mcs', and a corresponding IL
- runtime called 'mono'. You can use two make variables
- EXTERNAL_MCS and EXTERNAL_RUNTIME to override these. e.g., you
- can say
-
- make EXTERNAL_MCS=/foo/bar/mcs EXTERNAL_RUNTIME=/somewhere/else/mono
-
- If you don't have a working Mono installation
- ---------------------------------------------
-
- If you don't have a working Mono installation, an obvious choice
- is to install the latest released packages of 'mono' for your
- distribution and running autogen.sh; make; make install in the
- mono module directory.
-
- You can also try a slightly more risky approach: this may not work,
- so start from the released tarball as detailed above.
-
- This works by first getting the latest version of the 'monolite'
- distribution, which contains just enough to run the 'mcs'
- compiler. You do this with:
-
- # Run the following line after ./autogen.sh
- make get-monolite-latest
-
- This will download and automatically gunzip and untar the
- tarball, and place the files appropriately so that you can then
- just run:
-
- make EXTERNAL_MCS=${PWD}/mcs/class/lib/monolite/gmcs.exe
-
- And that will use the files downloaded by 'make get-monolite-latest.
-
- Testing and Installation
- ------------------------
-
- You can run (part of) the mono and mcs testsuites with the command:
-
- make check
-
- All tests should pass.
-
- If you want more extensive tests, including those that test the
- class libraries, you need to re-run 'configure' with the
- '--enable-nunit-tests' flag, and try
-
- make -k check
-
- Expect to find a few testsuite failures. As a sanity check, you
- can compare the failures you got with
-
- https://wrench.mono-project.com/Wrench/
-
- You can now install mono with:
-
- make install
-
- You can verify your installation by using the mono-test-install
- script, it can diagnose some common problems with Mono's install.
-
- Failure to follow these steps may result in a broken installation.
-
- d. Configuration Options
- ------------------------
-
- The following are the configuration options that someone
- building Mono might want to use:
-
- --with-sgen=yes,no
-
- Generational GC support: Used to enable or disable the
- compilation of a Mono runtime with the SGen garbage collector.
-
- On platforms that support it, after building Mono, you
- will have both a mono binary and a mono-sgen binary.
- Mono uses Boehm, while mono-sgen uses the Simple
- Generational GC.
-
- --with-gc=[boehm, included, sgen, none]
-
- Selects the default Boehm garbage collector engine to
- use, the default is the "included" value.
-
- included:
- This is the default value, and its
- the most feature complete, it will allow Mono
- to use typed allocations and support the
- debugger.
-
- It is essentially a slightly modified Boehm GC
-
- boehm:
- This is used to use a system-install Boehm GC,
- it is useful to test new features available in
- Boehm GC, but we do not recommend that people
- use this, as it disables a few features.
-
- none:
- Disables the inclusion of a garbage
- collector.
-
- --with-tls=__thread,pthread
-
- Controls how Mono should access thread local storage,
- pthread forces Mono to use the pthread APIs, while
- __thread uses compiler-optimized access to it.
-
- Although __thread is faster, it requires support from
- the compiler, kernel and libc. Old Linux systems do
- not support with __thread.
-
- This value is typically pre-configured and there is no
- need to set it, unless you are trying to debug a
- problem.
-
- --with-sigaltstack=yes,no
-
- Experimental: Use at your own risk, it is known to
- cause problems with garbage collection and is hard to
- reproduce those bugs.
-
- This controls whether Mono will install a special
- signal handler to handle stack overflows. If set to
- "yes", it will turn stack overflows into the
- StackOverflowException. Otherwise when a stack
- overflow happens, your program will receive a
- segmentation fault.
-
- The configure script will try to detect if your
- operating system supports this. Some older Linux
- systems do not support this feature, or you might want
- to override the auto-detection.
-
- --with-static_mono=yes,no
-
- This controls whether `mono' should link against a
- static library (libmono.a) or a shared library
- (libmono.so).
-
- This defaults to yes, and will improve the performance
- of the `mono' program.
-
- This only affects the `mono' binary, the shared
- library libmono.so will always be produced for
- developers that want to embed the runtime in their
- application.
-
- --with-xen-opt=yes,no
-
- The default value for this is `yes', and it makes Mono
- generate code which might be slightly slower on
- average systems, but the resulting executable will run
- faster under the Xen virtualization system.
-
- --with-large-heap=yes,no
-
- Enable support for GC heaps larger than 3GB.
-
- This value is set to `no' by default.
-
- --enable-small-config=yes,no
-
- Enable some tweaks to reduce memory usage and disk footprint at
- the expense of some capabilities. Typically this means that the
- number of threads that can be created is limited (256), that the
- maxmimum heap size is also reduced (256 MB) and other such limitations
- that still make mono useful, but more suitable to embedded devices
- (like mobile phones).
-
- This value is set to `no' by default.
-
- --with-ikvm-native=yes,no
-
- Controls whether the IKVM JNI interface library is
- built or not. This is used if you are planning on
- using the IKVM Java Virtual machine with Mono.
-
- This defaults to `yes'.
-
- --with-profile4=yes,no
-
- Whether you want to build the 4.x profile libraries
- and runtime.
-
- It defaults to `yes'.
-
- --with-moonlight=yes,no
-
- Whether you want to generate the Silverlight/Moonlight
- libraries and toolchain in addition to the default
- (1.1 and 2.0 APIs).
-
- This will produce the `smcs' compiler which will reference
- the Silverlight modified assemblies (mscorlib.dll,
- System.dll, System.Code.dll and System.Xml.Core.dll) and turn
- on the LINQ extensions for the compiler.
-
- --with-moon-gc=boehm,sgen
-
- Select the GC to use for Moonlight.
-
- boehm:
- Selects the Boehm Garbage Collector, with the same flags
- as the regular Mono build. This is the default.
-
- sgen:
- Selects the new SGen Garbage Collector, which provides
- Generational GC support, using the same flags as the
- mono-sgen build.
-
- This defaults to `boehm'.
-
- --with-libgdiplus=installed,sibling,<path>
-
- This is used to configure where should Mono look for
- libgdiplus when running the System.Drawing tests.
-
- It defaults to `installed', which means that the
- library is available to Mono through the regular
- system setup.
-
- `sibling' can be used to specify that a libgdiplus
- that resides as a sibling of this directory (mono)
- should be used.
-
- Or you can specify a path to a libgdiplus.
-
- --disable-shared-memory
-
- Use this option to disable the use of shared memory in
- Mono (this is equivalent to setting the MONO_DISABLE_SHM
- environment variable, although this removes the feature
- completely).
-
- Disabling the shared memory support will disable certain
- features like cross-process named mutexes.
-
- --enable-minimal=LIST
-
- Use this feature to specify optional runtime
- components that you might not want to include. This
- is only useful for developers embedding Mono that
- require a subset of Mono functionality.
-
- The list is a comma-separated list of components that
- should be removed, these are:
-
- aot:
- Disables support for the Ahead of Time
- compilation.
-
- attach:
- Support for the Mono.Management assembly and the
- VMAttach API (allowing code to be injected into
- a target VM)
-
- com:
- Disables COM support.
-
- debug:
- Drop debugging support.
-
- decimal:
- Disables support for System.Decimal.
-
- full_messages:
- By default Mono comes with a full table
- of messages for error codes. This feature
- turns off uncommon error messages and reduces
- the runtime size.
-
- generics:
- Generics support. Disabling this will not
- allow Mono to run any 2.0 libraries or
- code that contains generics.
-
- jit:
- Removes the JIT engine from the build, this reduces
- the executable size, and requires that all code
- executed by the virtual machine be compiled with
- Full AOT before execution.
-
- large_code:
- Disables support for large assemblies.
-
- logging:
- Disables support for debug logging.
-
- pinvoke:
- Support for Platform Invocation services,
- disabling this will drop support for any
- libraries using DllImport.
-
- portability:
- Removes support for MONO_IOMAP, the environment
- variables for simplifying porting applications that
- are case-insensitive and that mix the Unix and Windows path separators.
-
- profiler:
- Disables support for the default profiler.
-
- reflection_emit:
- Drop System.Reflection.Emit support
-
- reflection_emit_save:
- Drop support for saving dynamically created
- assemblies (AssemblyBuilderAccess.Save) in
- System.Reflection.Emit.
-
- shadow_copy:
- Disables support for AppDomain's shadow copies
- (you can disable this if you do not plan on
- using appdomains).
-
- simd:
- Disables support for the Mono.SIMD intrinsics
- library.
-
- ssa:
- Disables compilation for the SSA optimization
- framework, and the various SSA-based
- optimizations.
-
- --enable-llvm
- --enable-loadedllvm
-
- This enables the use of LLVM as a code generation engine
- for Mono. The LLVM code generator and optimizer will be
- used instead of Mono's built-in code generator for both
- Just in Time and Ahead of Time compilations.
-
- See the http://www.mono-project.com/Mono_LLVM for the
- full details and up-to-date information on this feature.
-
- You will need to have an LLVM built that Mono can link
- against,
-
- The --enable-loadedllvm variant will make the llvm backend
- into a runtime-loadable module instead of linking it directly
- into the main mono binary.
-
- --enable-big-arrays
-
- This enables the use arrays whose indexes are larger
- than Int32.MaxValue.
-
- By default Mono has the same limitation as .NET on
- Win32 and Win64 and limits array indexes to 32-bit
- values (even on 64-bit systems).
-
- In certain scenarios where large arrays are required,
- you can pass this flag and Mono will be built to
- support 64-bit arrays.
-
- This is not the default as it breaks the C embedding
- ABI that we have exposed through the Mono development
- cycle.
-
- --enable-parallel-mark
-
- Use this option to enable the garbage collector to use
- multiple CPUs to do its work. This helps performance
- on multi-CPU machines as the work is divided across CPUS.
-
- This option is not currently the default as we have
- not done much testing with Mono.
-
- --enable-dtrace
-
- On Solaris and MacOS X builds a version of the Mono
- runtime that contains DTrace probes and can
- participate in the system profiling using DTrace.
-
-
- --disable-dev-random
-
- Mono uses /dev/random to obtain good random data for
- any source that requires random numbers. If your
- system does not support this, you might want to
- disable it.
-
- There are a number of runtime options to control this
- also, see the man page.
-
- --enable-nacl
-
- This configures the Mono compiler to generate code
- suitable to be used by Google's Native Client:
-
- http://code.google.com/p/nativeclient/
-
- Currently this is used with Mono's AOT engine as
- Native Client does not support JIT engines yet.
-
-2. Using Mono
-=============
-
- Once you have installed the software, you can run a few programs:
-
- * runtime engine
-
- mono program.exe
-
- * C# compiler
-
- mcs program.cs
-
- * CIL Disassembler
-
- monodis program.exe
-
- See the man pages for mono(1), mint(1), monodis(1) and mcs(2)
- for further details.
-
-3. Directory Roadmap
-====================
-
- docs/
- Technical documents about the Mono runtime.
-
- data/
- Configuration files installed as part of the Mono runtime.
-
- mono/
- The core of the Mono Runtime.
-
- metadata/
- The object system and metadata reader.
-
- mini/
- The Just in Time Compiler.
-
- dis/
- CIL executable Disassembler
-
- cli/
- Common code for the JIT and the interpreter.
-
- io-layer/
- The I/O layer and system abstraction for
- emulating the .NET IO model.
-
- cil/
- Common Intermediate Representation, XML
- definition of the CIL bytecodes.
-
- interp/
- Interpreter for CLI executables (obsolete).
-
- arch/
- Architecture specific portions.
-
- man/
-
- Manual pages for the various Mono commands and programs.
-
- samples/
-
- Some simple sample programs on uses of the Mono
- runtime as an embedded library.
-
- scripts/
-
- Scripts used to invoke Mono and the corresponding program.
-
- runtime/
-
- A directory that contains the Makefiles that link the
- mono/ and mcs/ build systems.
-
- ../olive/
-
- If the directory ../olive is present (as an
- independent checkout) from the Mono module, that
- directory is automatically configured to share the
- same prefix than this module gets.
-
-
-4. Git submodules maintenance
-=============================
-
-Read documentation at http://mono-project.com/Git_Submodule_Maintenance
-
-
-5. Reporting bugs
-=================
-
-To submit bug reports, please use Xamarin's Bugzilla:
-
- https://bugzilla.xamarin.com/
-
-Please use the search facility to ensure the same bug hasn't already
-been submitted and follow our guidelines on how to make a good bug
-report:
-
- http://mono-project.com/Bugs#How_to_make_a_good_bug_report
--- /dev/null
+Mono is a software platform designed to allow developers to easily create cross platform applications.
+Mono is an open source implementation of Microsoft's .NET Framework based on the ECMA standards for C# and the Common Language Runtime.
+
+1. [Installation](#compilation-and-installation)
+2. [Using Mono](#using-mono)
+3. [Directory Roadmap](#directory-roadmap)
+4. [Git submodules maintenance](#git-submodules-maintenance)
+5. [Reporting bugs](#reporting-bugs)
+
+Compilation and Installation
+============================
+
+a. Build Requirements
+---------------------
+
+* On Itanium, you must obtain libunwind: http://www.hpl.hp.com/research/linux/libunwind/download.php4
+
+* On Solaris
+
+ 1. Make sure that you used GNU tar to unpack this package, as
+ Solaris tar will not unpack this correctly, and you will get strange errors.
+
+ 2. Make sure that you use the GNU toolchain to build the software.
+
+ 3. Optional dependencies
+
+ * libgdiplus - Required for System.Drawing. This library in turn requires glib and pkg-config
+
+ * pkg-config - Available at: http://www.freedesktop.org/Software/pkgconfig
+
+ * glib 2.4 - Available at: http://www.gtk.org/
+
+ * libzlib - This library and the development headers are required for compression
+file support in the 2.0 profile.
+
+b. Building the Software
+------------------------
+
+If you obtained this package as an officially released tarball,
+this is very simple, use configure and make:
+
+`./configure --prefix=/usr/local ; make ; make install`
+
+Mono supports a JIT engine on x86, SPARC, SPARCv9, S/390,
+S/390x, AMD64, ARM and PowerPC systems.
+
+If you obtained this as a snapshot, you will need an existing
+Mono installation. To upgrade your installation, unpack both
+mono and mcs:
+
+ tar xzf mcs-XXXX.tar.gz
+ tar xzf mono-XXXX.tar.gz
+ mv mono-XXX mono
+ mv mcs-XXX mcs
+ cd mono
+ ./autogen.sh --prefix=/usr/local
+ make
+
+The Mono build system is silent for most compilation commands.
+To enable a more verbose compile (for example, to pinpoint
+problems in your makefiles or your system) pass the V=1 flag to make, like this:
+
+` make V=1`
+
+
+c. Building the software from GIT
+---------------------------------
+
+If you are building the software from GIT, make sure that you
+have up-to-date mcs and mono sources:
+
+ * If you are an anonymous user: `git clone git://github.com/mono/mono.git`
+
+ * If you are a Mono contributor with read/write privileges: `git clone git@github.com:mono/mono.git`
+
+Then, go into the mono directory, and configure:
+
+ cd mono
+ ./autogen.sh --prefix=/usr/local
+ make
+
+For people with non-standard installations of the auto* utils and of
+pkg-config (common on misconfigured OSX and windows boxes), you could get
+an error like this:
+
+`./configure: line 19176: syntax error near unexpected token 'PKG_CHECK_MODULES(BASE_DEPENDENCIES,' ...`
+
+This means that you need to set the ACLOCAL_FLAGS environment variable
+when invoking autogen.sh, like this: `ACLOCAL_FLAGS="-I $acprefix/share/aclocal" ./autogen.sh --prefix=/usr/local`
+where $acprefix is the prefix where aclocal has been installed.
+This will automatically go into the mcs/ tree and build the
+binaries there.
+
+This assumes that you have a working mono installation, and that
+there's a C# compiler named 'mcs', and a corresponding IL
+runtime called 'mono'. You can use two make variables
+EXTERNAL_MCS and EXTERNAL_RUNTIME to override these. e.g., you
+can say:
+
+`make EXTERNAL_MCS=/foo/bar/mcs EXTERNAL_RUNTIME=/somewhere/else/mono`
+
+If you don't have a working Mono installation
+---------------------------------------------
+
+If you don't have a working Mono installation, an obvious choice
+is to install the latest released packages of 'mono' for your
+distribution and running `autogen.sh; make; make install` in the
+mono module directory.
+
+You can also try a slightly more risky approach: this may not work,
+so start from the released tarball as detailed above.
+
+This works by first getting the latest version of the 'monolite'
+distribution, which contains just enough to run the 'mcs'
+compiler. You do this with:
+
+ # Run the following line after ./autogen.sh
+ make get-monolite-latest
+
+This will download and automatically gunzip and untar the
+tarball, and place the files appropriately so that you can then
+just run: `make EXTERNAL_MCS=${PWD}/mcs/class/lib/monolite/gmcs.exe`
+
+That will use the files downloaded by 'make get-monolite-latest.
+
+Testing and Installation
+------------------------
+
+You can run *(part of)* the mono and mcs test suites with the command: `make check`.
+All tests should pass.
+
+If you want more *extensive* tests, including those that test the
+class libraries, you need to re-run 'configure' with the
+'--enable-nunit-tests' flag, and try: `make -k check`
+
+Expect to find a few test suite failures. As a sanity check, you
+can compare the failures you got with
+
+`https://wrench.mono-project.com/Wrench/`
+
+You can now install mono with: `make install`
+
+You can verify your installation by using the mono-test-install
+script, it can diagnose some common problems with Mono's install.
+Failure to follow these steps may result in a broken installation.
+
+d. Configuration Options
+------------------------
+
+The following are the configuration options that someone
+building Mono might want to use:
+
+* `--with-sgen=yes,no` - Generational GC support: Used to enable or disable the
+compilation of a Mono runtime with the SGen garbage collector.
+
+ * On platforms that support it, after building Mono, you
+will have both a mono binary and a mono-sgen binary.
+Mono uses Boehm, while mono-sgen uses the Simple
+Generational GC.
+
+* `--with-gc=[boehm, included, sgen, none]` - Selects the default Boehm garbage
+collector engine to use.
+
+ * *included*: (*slighty modified Boehm GC*)
+This is the default value, and its
+the most feature complete, it will allow Mono
+to use typed allocations and support the
+debugger.
+
+ * *boehm*:
+This is used to use a system-install Boehm GC,
+it is useful to test new features available in
+Boehm GC, but we do not recommend that people
+use this, as it disables a few features.
+
+ * *none*:
+Disables the inclusion of a garbage collector.
+
+ * This defaults to `included`.
+
+* `--with-tls=__thread,pthread`
+
+ * Controls how Mono should access thread local storage,
+pthread forces Mono to use the pthread APIs, while
+__thread uses compiler-optimized access to it.
+
+ * Although __thread is faster, it requires support from
+the compiler, kernel and libc. Old Linux systems do
+not support with __thread.
+
+ * This value is typically pre-configured and there is no
+need to set it, unless you are trying to debug a problem.
+
+* `--with-sigaltstack=yes,no`
+
+ * **Experimental**: Use at your own risk, it is known to
+cause problems with garbage collection and is hard to
+reproduce those bugs.
+
+ * This controls whether Mono will install a special
+signal handler to handle stack overflows. If set to
+`yes`, it will turn stack overflows into the
+StackOverflowException. Otherwise when a stack
+overflow happens, your program will receive a
+segmentation fault.
+
+ * The configure script will try to detect if your
+operating system supports this. Some older Linux
+systems do not support this feature, or you might want
+to override the auto-detection.
+
+* `--with-static_mono=yes,no`
+
+ * This controls whether `mono` should link against a
+static library (libmono.a) or a shared library
+(libmono.so).
+
+ * This defaults to `yes`, and will improve the performance
+of the `mono` program.
+
+ * This only affects the `mono' binary, the shared
+library libmono.so will always be produced for
+developers that want to embed the runtime in their
+application.
+
+* `--with-xen-opt=yes,no` - Optimize code for Xen virtualization.
+
+ * It makes Mono generate code which might be slightly
+slower on average systems, but the resulting executable will run
+faster under the Xen virtualization system.
+
+ * This defaults to `yes`.
+
+* `--with-large-heap=yes,no` - Enable support for GC heaps larger than 3GB.
+
+ * This defaults to `no`.
+
+* `--enable-small-config=yes,no` - Enable some tweaks to reduce memory usage
+and disk footprint at the expense of some capabilities.
+
+ * Typically this means that the number of threads that can be created
+is limited (256), that the maximum heap size is also reduced (256 MB)
+and other such limitations that still make mono useful, but more suitable
+to embedded devices (like mobile phones).
+
+ * This defaults to `no`.
+
+* `--with-ikvm-native=yes,no` - Controls whether the IKVM JNI interface library is
+built or not.
+
+ * This is used if you are planning on
+using the IKVM Java Virtual machine with Mono.
+
+ * This defaults to `yes`.
+
+* `--with-profile4=yes,no` - Whether you want to build the 4.x profile libraries
+and runtime.
+
+ * This defaults to `yes`.
+
+* `--with-moonlight=yes,no`
+
+ * Whether you want to generate the Silverlight/Moonlight
+libraries and toolchain in addition to the default
+(1.1 and 2.0 APIs).
+
+ * This will produce the `smcs` compiler which will reference
+the Silverlight modified assemblies (mscorlib.dll,
+System.dll, System.Code.dll and System.Xml.Core.dll) and turn
+on the LINQ extensions for the compiler.
+
+* `--with-moon-gc=boehm,sgen` - Select the GC to use for Moonlight.
+
+ * *boehm*:
+Selects the Boehm Garbage Collector, with the same flags
+as the regular Mono build. This is the default.
+
+ * *sgen*:
+Selects the new SGen Garbage Collector, which provides
+Generational GC support, using the same flags as the
+mono-sgen build.
+
+ * This defaults to `boehm`.
+
+* `--with-libgdiplus=installed,sibling,<path>` - Configure where Mono
+searches for libgdiplus when running System.Drawing tests.
+
+ * It defaults to `installed`, which means that the
+library is available to Mono through the regular
+system setup.
+
+ * `sibling' can be used to specify that a libgdiplus
+that resides as a sibling of this directory (mono)
+should be used.
+
+ * Or you can specify a path to a libgdiplus.
+
+* `--disable-shared-memory`
+
+ * Use this option to disable the use of shared memory in
+Mono (this is equivalent to setting the MONO_DISABLE_SHM
+environment variable, although this removes the feature
+completely).
+
+ * Disabling the shared memory support will disable certain
+features like cross-process named mutexes.
+
+* `--enable-minimal=LIST`
+
+ * Use this feature to specify optional runtime
+components that you might not want to include. This
+is only useful for developers embedding Mono that
+require a subset of Mono functionality.
+ * The list is a comma-separated list of components that
+should be removed, these are:
+
+ * `aot`:
+Disables support for the Ahead of Time compilation.
+
+ * `attach`:
+Support for the Mono.Management assembly and the
+VMAttach API (allowing code to be injected into
+a target VM)
+
+ * `com`:
+Disables COM support.
+
+ * `debug`:
+Drop debugging support.
+
+ * `decimal`:
+Disables support for System.Decimal.
+
+ * `full_messages`:
+By default Mono comes with a full table
+of messages for error codes. This feature
+turns off uncommon error messages and reduces
+the runtime size.
+
+ * `generics`:
+Generics support. Disabling this will not
+allow Mono to run any 2.0 libraries or
+code that contains generics.
+
+ * `jit`:
+Removes the JIT engine from the build, this reduces
+the executable size, and requires that all code
+executed by the virtual machine be compiled with
+Full AOT before execution.
+
+ * `large_code`:
+Disables support for large assemblies.
+
+ * `logging`:
+Disables support for debug logging.
+
+ * `pinvoke`:
+Support for Platform Invocation services,
+disabling this will drop support for any
+libraries using DllImport.
+
+ * `portability`:
+Removes support for MONO_IOMAP, the environment
+variables for simplifying porting applications that
+are case-insensitive and that mix the Unix and Windows path separators.
+
+ * `profiler`:
+Disables support for the default profiler.
+
+ * `reflection_emit`:
+Drop System.Reflection.Emit support
+
+ * `reflection_emit_save`:
+Drop support for saving dynamically created
+assemblies (AssemblyBuilderAccess.Save) in
+System.Reflection.Emit.
+
+ * `shadow_copy`:
+Disables support for AppDomain's shadow copies
+(you can disable this if you do not plan on
+using appdomains).
+
+ * `simd`:
+Disables support for the Mono.SIMD intrinsics
+library.
+
+ * `ssa`:
+Disables compilation for the SSA optimization
+framework, and the various SSA-based optimizations.
+
+* `--enable-llvm`
+* `--enable-loadedllvm`
+
+ * This enables the use of LLVM as a code generation engine
+for Mono. The LLVM code generator and optimizer will be
+used instead of Mono's built-in code generator for both
+Just in Time and Ahead of Time compilations.
+
+ * See the http://www.mono-project.com/Mono_LLVM for the
+full details and up-to-date information on this feature.
+
+ * You will need to have an LLVM built that Mono can link
+against.
+
+ * The --enable-loadedllvm variant will make the LLVM backend
+into a runtime-loadable module instead of linking it directly
+into the main mono binary.
+
+* `--enable-big-arrays` - Enable use of arrays with indexes larger
+than Int32.MaxValue.
+
+ * By default Mono has the same limitation as .NET on
+Win32 and Win64 and limits array indexes to 32-bit
+values (even on 64-bit systems).
+
+ * In certain scenarios where large arrays are required,
+you can pass this flag and Mono will be built to
+support 64-bit arrays.
+
+ * This is not the default as it breaks the C embedding
+ABI that we have exposed through the Mono development
+cycle.
+
+* `--enable-parallel-mark`
+
+ * Use this option to enable the garbage collector to use
+multiple CPUs to do its work. This helps performance
+on multi-CPU machines as the work is divided across CPUS.
+
+ * This option is not currently the default as we have
+not done much testing with Mono.
+
+* `--enable-dtrace`
+
+ * On Solaris and MacOS X builds a version of the Mono
+runtime that contains DTrace probes and can
+participate in the system profiling using DTrace.
+
+
+* `--disable-dev-random`
+
+ * Mono uses /dev/random to obtain good random data for
+any source that requires random numbers. If your
+system does not support this, you might want to
+disable it.
+
+ * There are a number of runtime options to control this
+also, see the man page.
+
+* `--enable-nacl`
+
+ * This configures the Mono compiler to generate code
+suitable to be used by Google's Native Client:
+http://code.google.com/p/nativeclient/
+
+ * Currently this is used with Mono's AOT engine as
+Native Client does not support JIT engines yet.
+
+Using Mono
+==========
+
+Once you have installed the software, you can run a few programs:
+
+* `mono program.exe` runtime engine
+
+* `mcs program.cs` C# compiler
+
+* `monodis program.exe` CIL Disassembler
+
+See the man pages for mono(1), mint(1), monodis(1) and mcs(2)
+for further details.
+
+Directory Roadmap
+=================
+
+* `docs/` - Technical documents about the Mono runtime.
+
+* `data/` - Configuration files installed as part of the Mono runtime.
+
+* `mono/` - The core of the Mono Runtime.
+
+ * `metadata/` - The object system and metadata reader.
+
+ * `mini/` - The Just in Time Compiler.
+
+ * `dis/` - CIL executable Disassembler
+
+ * `cli/` - Common code for the JIT and the interpreter.
+
+ * `io-layer/` - The I/O layer and system abstraction for
+emulating the .NET IO model.
+
+ * `cil/` - Common Intermediate Representation, XML
+definition of the CIL bytecodes.
+
+ * `interp/` - Interpreter for CLI executables (obsolete).
+
+ * `arch/` - Architecture specific portions.
+
+* `man/` - Manual pages for the various Mono commands and programs.
+
+* `samples/` -Some simple sample programs on uses of the Mono
+runtime as an embedded library.
+
+* `scripts/` - Scripts used to invoke Mono and the corresponding program.
+
+* `runtime/` - A directory that contains the Makefiles that link the
+mono/ and mcs/ build systems.
+
+* `../olive/`
+
+ * If the directory ../olive is present (as an
+independent checkout) from the Mono module, that
+directory is automatically configured to share the
+same prefix than this module gets.
+
+
+Git submodules maintenance
+==========================
+
+Read documentation at http://mono-project.com/Git_Submodule_Maintenance
+
+Maintainer
+==========
+
+Mono is maintained by miguel@xamarin.com
+
+Reporting bugs
+==============
+
+To submit bug reports, please use Xamarin's Bugzilla:
+
+https://bugzilla.xamarin.com/
+
+Please use the search facility to ensure the same bug hasn't already
+been submitted and follow our guidelines on how to make a good bug
+report:
+
+http://mono-project.com/Bugs#How_to_make_a_good_bug_report
# Plug in the extension module
#
has_ext_mod=false
+ext_mod_args=''
for PARAM; do
- if test "$PARAM" = "--enable-extension-module" ; then
- has_ext_mod=true
- fi
+ if [[ $PARAM =~ "--enable-extension-module" ]] ; then
+ has_ext_mod=true
+ if [[ $PARAM =~ "=" ]] ; then
+ ext_mod_args=`echo $PARAM | cut -d= -f2`
+ fi
+ fi
done
if test x$has_ext_mod = xtrue; then
pushd ../mono-extensions/scripts
- sh ./prepare-repo.sh || exit 1
+ sh ./prepare-repo.sh $ext_mod_args || exit 1
popd
else
cat mono/mini/Makefile.am.in > mono/mini/Makefile.am
# Process this file with autoconf to produce a configure script.
#AC_PREREQ([2.62])
-AC_INIT(mono, [3.2.5],
+AC_INIT(mono, [3.2.7],
[http://bugzilla.xamarin.com/enter_bug.cgi?classification=Mono])
-AC_CONFIG_SRCDIR([README])
+AC_CONFIG_SRCDIR([README.md])
AC_CONFIG_MACRO_DIR([m4])
AC_CANONICAL_SYSTEM
AC_CANONICAL_HOST
CFLAGS_FOR_LIBGC="$CFLAGS_FOR_LIBGC $BROKEN_DARWIN_FLAGS"
CPPFLAGS_FOR_EGLIB="$CPPFLAGS_FOR_EGLIB $BROKEN_DARWIN_CPPFLAGS"
CFLAGS_FOR_EGLIB="$CFLAGS_FOR_EGLIB $BROKEN_DARWIN_FLAGS"
- extra_runtime_ldflags="-stack_size,0x800000"
;;
x*64-*-darwin*)
- extra_runtime_ldflags="-stack_size,0x800000"
;;
arm*-darwin*)
has_dtrace=no
AC_ARG_ENABLE(executables, [ --disable-executables disable the build of the runtime executables], enable_executables=$enableval, enable_executables=yes)
AM_CONDITIONAL(DISABLE_EXECUTABLES, test x$enable_executables = xno)
-AC_ARG_ENABLE(extension-module, [ --enable-extension-module enables usage of the extension module], has_extension_module=$enableval, has_extension_module=no)
+has_extension_module=no
+AC_ARG_ENABLE(extension-module, [ --enable-extension-module=LIST enable the core-extensions from LIST],
+[
+ for extension in `echo "$enable_extension_module" | sed -e "s/,/ /g"`; do
+ if test x$extension = xdefault ; then
+ has_extension_module=yes;
+ fi
+ done
+ if test x$enable_extension_module = xyes; then
+ has_extension_module=yes;
+ fi
+], [])
+
AM_CONDITIONAL([HAS_EXTENSION_MODULE], [test x$has_extension_module != xno])
if test x$has_extension_module != xno ; then
fi
havekqueue=no
- AC_CHECK_FUNCS(kqueue, , AC_MSG_CHECKING(for kqueue in sys/event.h)
- AC_TRY_LINK([#include <sys/event.h>],
- [ kqueue(); ],[havekqueue=yes],[]))
+
+ AC_CHECK_HEADERS(sys/event.h)
+ AC_CHECK_FUNCS(kqueue, [havekqueue=yes], )
dnl **************************************
dnl * Darwin has a race that prevents us from using reliably:
dnl * and very few folks run Mono on large web servers on OSX, falling
dnl * back
dnl **************************************
- if test x$havekqueue = xyes; then
+ if test "x$havekqueue" = "xyes" -a "x$ac_cv_header_sys_event_h" = "xyes"; then
if x$platform_darwin = xno; then
AC_DEFINE(USE_KQUEUE_FOR_THREADPOOL, 1, [Use kqueue for the threadpool])
fi
AC_CHECK_FUNCS(futimens utimensat)
AC_CHECK_FUNCS(fstatat mknodat readlinkat)
AC_CHECK_FUNCS(readv writev preadv pwritev)
+ AC_CHECK_FUNCS(setpgid)
AC_CHECK_SIZEOF(size_t)
AC_CHECK_TYPES([blksize_t], [AC_DEFINE(HAVE_BLKSIZE_T)], ,
[#include <sys/types.h>
AC_CHECK_FUNCS(GetProcessId)
AC_CHECK_DECLS(InterlockedExchange64, [], [], [[#include <windows.h>]])
AC_CHECK_DECLS(InterlockedCompareExchange64, [], [], [[#include <windows.h>]])
+ AC_CHECK_DECLS(InterlockedDecrement64, [], [], [[#include <windows.h>]])
AC_CHECK_DECLS(InterlockedIncrement64, [], [], [[#include <windows.h>]])
AC_CHECK_DECLS(InterlockedAdd, [], [], [[#include <windows.h>]])
AC_CHECK_DECLS(InterlockedAdd64, [], [], [[#include <windows.h>]])
+ AC_CHECK_DECLS(__readfsdword, [], [], [[#include <windows.h>]])
fi
dnl socklen_t check
fi
LLVM_LIBS="$LLVM_LDFLAGS $LLVM_LIBS -lstdc++"
- expected_llvm_version="3.3svn-mono/2c9642d"
+ expected_llvm_version="3.4svn-mono-mono/e656cac"
# Should be something like '2.6' or '2.7svn'
llvm_version=`$LLVM_CONFIG --version`
fi
fi
-mono_debugger_supported=no
-AC_ARG_ENABLE(mono-debugger, [ --disable-mono-debugger disable support for the mdb debugger], try_mono_debugger=$enableval, try_mono_debugger=yes)
-if test "x$try_mono_debugger" = "xyes"; then
- if test "x$TARGET" = "xAMD64" -o "x$TARGET" = "xX86" -o "x$TARGET" = "xS390x"; then
- if test x$use_included_gc = xyes; then
- case "$host" in
- *-*-*linux*)
- mono_debugger_supported=yes
- ;;
- *86-apple-darwin*)
- mono_debugger_supported=yes
- ;;
- esac
- fi
- fi
-fi
-
-# disable the debugger entirely when building with moonlight
-if test "x$with_moonlight" != "xno"; then
- mono_debugger_supported=no
-fi
-
-# mdb support for sgen is broken, disable it until further notice.
-mono_debugger_supported=no
-
-AC_MSG_CHECKING(if the Mono Debugger is supported on this platform)
-if test "x$mono_debugger_supported" = "xyes"; then
- BOEHM_DEFINES="$BOEHM_DEFINES -DMONO_DEBUGGER_SUPPORTED"
- CPPFLAGS_FOR_LIBGC="$CPPFLAGS_FOR_LIBGC -DMONO_DEBUGGER_SUPPORTED"
-fi
-AM_CONDITIONAL(MONO_DEBUGGER_SUPPORTED, test x$mono_debugger_supported = xyes)
-AC_MSG_RESULT($mono_debugger_supported)
-
AC_ARG_ENABLE(icall-symbol-map,[ --enable-icall-symbol-map Generate tables which map icall functions to their C symbols], icall_symbol_map=$enableval, icall_symbol_map=no)
if test "x$icall_symbol_map" = "xyes"; then
AC_DEFINE(ENABLE_ICALL_SYMBOL_MAP, 1, [Icall symbol map enabled])
return 0;
], [
arm_v5=yes
+
+ arm_ver=ARMv5
], [])
AC_TRY_COMPILE([], [
], [
arm_v5=yes
arm_v6=yes
+
+ arm_ver=ARMv6
], [])
AC_TRY_COMPILE([], [
arm_v5=yes
arm_v6=yes
arm_v7=yes
+
+ arm_ver=ARMv7
], [])
+ AC_MSG_RESULT($arm_ver)
+
if test x$arm_v5 = xyes; then
AC_DEFINE(HAVE_ARMV5, 1, [ARM v5])
CPPFLAGS_FOR_LIBGC="$CPPFLAGS_FOR_LIBGC -DHAVE_ARMV5=1"
Adding global locks is not to be taken lightly.
The current lock hierarchy:
-loader lock
- domain lock
- domain jit lock
+loader lock (global)
+ domain lock (complex)
+ domain jit lock (complex)
+ marshal lock
simple locks
Examples:
You can take the loader lock without holding a domain lock.
- You cannot take a domain lock if the loader lock is held.
+ You can take the domain load while holding the loader lock
+ You cannot take the loader lock if only the domain lock is held.
You cannot take a domain lock while holding the lock to another domain.
+
+
+TODO:
+
+We have a few known ok violation. We need a way to whitelist them.
+
+Known ok issues:
+
+ERROR: tried to acquire lock DomainLock at mono_domain_code_reserve_align while holding DomainLock at mono_class_create_runtime_vtable: Hierarchy violation.
+ This is triggered when building the vtable of a non-root domain and fetching a vtable trampoline for an offset that has not been built. We'll take the root
+ domain lock while holding the other one.
+ This is ok since we never allow locking to have in the other direction, IOW, the root-domain lock is one level down from the other domain-locks.
+
+WARNING: tried to acquire lock ImageDataLock at mono_image_init_name_cache while holding ImageDataLock at mono_class_from_name
+WARNING: tried to acquire lock ImageDataLock at mono_image_init_name_cache while holding ImageDataLock at mono_image_add_to_name_cache
+ Both of those happen when filling up the name_cache, as it needs to alloc image memory.
+ This one is fixable by spliting mono_image_init_name_cache into a locked and an unlocked variants and calling them appropriatedly.
+
*/
public enum Lock {
DomainLock,
DomainAssembliesLock,
DomainJitCodeHashLock,
+ IcallLock,
+ AssemblyBindingLock,
+ MarshalLock,
}
public class SimLock
case Lock.DomainLock:
return 1;
case Lock.DomainJitCodeHashLock:
+ case Lock.MarshalLock:
return 2;
default:
return 3;
get { return kind == Lock.LoaderLock; }
}
+ public bool IsResursiveLock {
+ get { return kind == Lock.LoaderLock || kind == Lock.DomainLock; }
+ }
+
/*locked is already owned by the thread, 'this' is the new one*/
bool Compare (SimThread thread, SimLock locked, out bool isWarning, out string msg)
{
"mono_loader_unlock",
"mono_image_lock",
"mono_image_unlock",
+ "mono_icall_lock",
+ "mono_icall_unlock",
+ "add_record",
+ "mono_locks_lock_acquired",
+ "mono_locks_lock_released",
};
public Trace (string[] fields) {
public int CompareTo(Symbol other) {
return offset - other.offset;
}
+
+ public void AdjustSize (Symbol next) {
+ size = next.offset - this.offset;
+ }
}
public interface SymbolTable {
string line;
while ((line = proc.StandardOutput.ReadLine ()) != null) {
string[] fields = line.Split(new char[] {' ', '\t'}, StringSplitOptions.RemoveEmptyEntries);
- if (fields.Length < 4)
- continue;
- if (!(fields [1].Equals ("g") || fields [1].Equals ("d")))
+ if (fields.Length < 7)
continue;
- if (!fields [2].Equals ("*UND*"))
+
+ if (!fields [3].Equals ("FUN"))
continue;
int offset = fields [0].ParseHex ();
- string name = fields [3];
+ string name = fields [6];
+ if (name.StartsWith ("_"))
+ name = name.Substring (1);
+
if (offset != 0)
list.Add (new Symbol (offset, 0, name));
}
table = new Symbol [list.Count];
list.CopyTo (table, 0);
Array.Sort (table);
+ for (int i = 1; i < table.Length; ++i) {
+ table [i - 1].AdjustSize (table [i]);
+ }
}
public string Translate (int offset) {
return FAILED ("int to pointer and back conversions fail %d != %d", iv, iv2);
uv = 0;
- ptr = GUINT_TO_POINTER (iv);
+ ptr = GUINT_TO_POINTER (uv);
uv2 = GPOINTER_TO_UINT (ptr);
- if (iv != iv2)
- return FAILED ("uint to pointer and back conversions fail %u != %d", iv, iv2);
+ if (uv != uv2)
+ return FAILED ("uint to pointer and back conversions fail %u != %d", uv, uv2);
uv = 1;
- ptr = GUINT_TO_POINTER (iv);
+ ptr = GUINT_TO_POINTER (uv);
uv2 = GPOINTER_TO_UINT (ptr);
- if (iv != iv2)
- return FAILED ("uint to pointer and back conversions fail %u != %d", iv, iv2);
+ if (uv != uv2)
+ return FAILED ("uint to pointer and back conversions fail %u != %d", uv, uv2);
uv = UINT32_MAX;
- ptr = GUINT_TO_POINTER (iv);
+ ptr = GUINT_TO_POINTER (uv);
uv2 = GPOINTER_TO_UINT (ptr);
- if (iv != iv2)
- return FAILED ("uint to pointer and back conversions fail %u != %d", iv, iv2);
+ if (uv != uv2)
+ return FAILED ("uint to pointer and back conversions fail %u != %d", uv, uv2);
return NULL;
-Subproject commit c02349ea22f33a8658170b89796bd70ba81563b2
+Subproject commit 92df59f033ef81a9b5a9cc6b09d44ed18d244517
#include <AvailabilityMacros.h>
#include "mono/utils/mono-compiler.h"
-#ifdef MONO_DEBUGGER_SUPPORTED
-#include "include/libgc-mono-debugger.h"
-#endif
-
/* From "Inside Mac OS X - Mach-O Runtime Architecture" published by Apple
Page 49:
"The space beneath the stack pointer, where a new stack frame would normally
GC_use_mach_handler_thread = 1;
}
-#ifdef MONO_DEBUGGER_SUPPORTED
-GCThreadFunctions *gc_thread_vtable = NULL;
-
-void *
-GC_mono_debugger_get_stack_ptr (void)
-{
- GC_thread me;
-
- me = GC_lookup_thread (pthread_self ());
- return &me->stop_info.stack_ptr;
-}
-#endif
-
#endif
-noinst_HEADERS = libgc-mono-debugger.h
-
EXTRA_DIST = $(srcdir)/*.h
SUBDIRS = private
+++ /dev/null
-#ifndef LIBGC_MONO_DEBUGGER_H
-#define LIBGC_MONO_DEBUGGER_H
-
-#if defined(_IN_LIBGC) || defined(_IN_THE_MONO_DEBUGGER)
-
-typedef struct
-{
- void (* initialize) (void);
-
- void (* thread_created) (pthread_t tid, void *stack_ptr);
- void (* thread_exited) (pthread_t tid, void *stack_ptr);
-
- void (* stop_world) (void);
- void (* start_world) (void);
-} GCThreadFunctions;
-
-extern GCThreadFunctions *gc_thread_vtable;
-
-extern void *
-GC_mono_debugger_get_stack_ptr (void);
-
-#else
-#error "This header is only intended to be used by the Mono Debugger"
-#endif
-
-#endif
-
#undef PACKAGE_VERSION
#include "mono/utils/mono-compiler.h"
-#ifdef MONO_DEBUGGER_SUPPORTED
-#include "include/libgc-mono-debugger.h"
-#endif
-
#ifdef NACL
volatile int __nacl_thread_suspension_needed = 0;
pthread_t nacl_thread_parker = -1;
/* We should have previously waited for it to become zero. */
# endif /* PARALLEL_MARK */
++GC_stop_count;
-#ifdef MONO_DEBUGGER_SUPPORTED
- if (gc_thread_vtable && gc_thread_vtable->stop_world)
- gc_thread_vtable->stop_world ();
- else
-#endif
pthread_stop_world ();
# ifdef PARALLEL_MARK
GC_release_mark_lock();
void GC_start_world()
{
-#ifdef MONO_DEBUGGER_SUPPORTED
- if (gc_thread_vtable && gc_thread_vtable->start_world)
- gc_thread_vtable->start_world();
- else
-#endif
pthread_start_world ();
}
/* We hold the allocation lock. */
void GC_stop_init()
{
-#ifdef MONO_DEBUGGER_SUPPORTED
- if (gc_thread_vtable && gc_thread_vtable->initialize)
- gc_thread_vtable->initialize ();
- else
-#endif
pthread_stop_init ();
}
-#ifdef MONO_DEBUGGER_SUPPORTED
-
-GCThreadFunctions *gc_thread_vtable = NULL;
-
-void *
-GC_mono_debugger_get_stack_ptr (void)
-{
- GC_thread me;
-
- me = GC_lookup_thread (pthread_self ());
- return &me->stop_info.stack_ptr;
-}
-
-#endif
-
#endif
static GC_bool keys_initialized;
-#ifdef MONO_DEBUGGER_SUPPORTED
-#include "include/libgc-mono-debugger.h"
-#endif
-
/* Recover the contents of the freelist array fl into the global one gfl.*/
/* Note that the indexing scheme differs, in that gfl has finer size */
/* resolution, even if not all entries are used. */
} else {
prev -> next = p -> next;
}
-#ifdef MONO_DEBUGGER_SUPPORTED
- if (gc_thread_vtable && gc_thread_vtable->thread_exited)
- gc_thread_vtable->thread_exited (id, &p->stop_info.stack_ptr);
-#endif
#ifdef GC_DARWIN_THREADS
mach_port_deallocate(mach_task_self(), p->stop_info.mach_thread);
t -> stop_info.stack_ptr = (ptr_t)(&dummy);
# endif
t -> flags = DETACHED | MAIN_THREAD;
-#ifdef MONO_DEBUGGER_SUPPORTED
- if (gc_thread_vtable && gc_thread_vtable->thread_created)
-# ifdef GC_DARWIN_THREADS
- gc_thread_vtable->thread_created (mach_thread_self (), &t->stop_info.stack_ptr);
-# else
- gc_thread_vtable->thread_created (pthread_self (), &t->stop_info.stack_ptr);
-# endif
-#endif
if (pthread_self () == main_pthread_self) {
t->stack = main_stack;
t->stack_size = main_stack_size;
/* This is also < 100% convincing. We should also read this */
/* from /proc, but the hook to do so isn't there yet. */
# endif /* IA64 */
-#ifdef MONO_DEBUGGER_SUPPORTED
- if (gc_thread_vtable && gc_thread_vtable->thread_created)
-# ifdef GC_DARWIN_THREADS
- gc_thread_vtable->thread_created (mach_thread_self(), &me->stop_info.stack_ptr);
-# else
- gc_thread_vtable->thread_created (my_pthread, &me->stop_info.stack_ptr);
-# endif
-#endif
UNLOCK();
if (start) *start = si -> start_routine;
actively waits for the debugger front end to connect to the Mono process.
Mono will print out to stdout the IP address and port where it is listening.
.TP
+.I setpgid=[y/n]
+If set to yes, Mono will call \fBsetpgid(0, 0)\fB on startup, if that function
+is available on the system. This is useful for ensuring that signals delivered
+to a process that is executing the debuggee are not propagated to the debuggee,
+e.g. when Ctrl-C sends \fBSIGINT\fB to the \fBsdb\fB tool.
+.TP
.I suspend=[y/n]
Defaults to yes, with the default option Mono will suspend the vm on startup
until it connects successfully to a debugger front end. If you set it to 'n', in
thisdir = class/Facades
-monotouch_SUBDIRS = System.Collections.Concurrent System.Collections System.ComponentModel.Annotations System.ComponentModel.EventBasedAsync System.ComponentModel System.Diagnostics.Contracts System.Diagnostics.Debug System.Diagnostics.Tools System.Globalization System.IO System.Linq.Expressions System.Linq.Parallel System.Linq.Queryable System.Linq System.Net.NetworkInformation System.Net.Primitives System.Net.Requests System.ObjectModel System.Reflection.Extensions System.Reflection.Primitives System.Reflection System.Resources.ResourceManager System.Runtime.Extensions System.Runtime.InteropServices System.Runtime.Numerics System.Runtime.Serialization.Json System.Runtime.Serialization.Primitives System.Runtime.Serialization.Xml System.Runtime System.Security.Principal System.ServiceModel.Http System.ServiceModel.Primitives System.Text.Encoding.Extensions System.Text.Encoding System.Text.RegularExpressions System.Threading.Tasks.Parallel System.Threading.Tasks System.Threading System.Xml.ReaderWriter System.Xml.XDocument System.Xml.XmlSerializer
+monotouch_SUBDIRS = System.Collections.Concurrent System.Collections System.ComponentModel.Annotations System.ComponentModel.EventBasedAsync System.ComponentModel \
+ System.Diagnostics.Contracts System.Diagnostics.Debug System.Diagnostics.Tools System.Dynamic.Runtime System.Globalization System.IO System.Linq.Expressions \
+ System.Linq.Parallel System.Linq.Queryable System.Linq System.Net.NetworkInformation System.Net.Primitives System.Net.Requests System.ObjectModel \
+ System.Reflection.Extensions System.Reflection.Primitives System.Reflection System.Resources.ResourceManager System.Runtime.Extensions \
+ System.Runtime.InteropServices System.Runtime.InteropServices.WindowsRuntime System.Runtime.Numerics System.Runtime.Serialization.Json \
+ System.Runtime.Serialization.Primitives System.Runtime.Serialization.Xml System.Runtime System.Security.Principal System.ServiceModel.Http \
+ System.ServiceModel.Primitives System.Text.Encoding.Extensions System.Text.Encoding System.Text.RegularExpressions System.Threading.Tasks.Parallel \
+ System.Threading.Tasks System.Threading System.Xml.ReaderWriter System.Xml.XDocument System.Xml.XmlSerializer
-net_4_5_SUBDIRS = $(monotouch_SUBDIRS) System.Dynamic.Runtime System.Reflection.Emit.ILGeneration System.Reflection.Emit.Lightweight System.Reflection.Emit
+mobile_static_SUBDIRS = $(monotouch_SUBDIRS)
+
+net_4_5_SUBDIRS = $(monotouch_SUBDIRS) System.Reflection.Emit.ILGeneration System.Reflection.Emit.Lightweight System.Reflection.Emit
monodroid_SUBDIRS = $(net_4_5_SUBDIRS)
+SUBDIRS = $(net_4_5_SUBDIRS)
+
include $(MCS_BUILD_DIR)/rules.make
dist-local: dist-default
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
-
+#if !FULL_AOT_RUNTIME
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Dynamic.BinaryOperationBinder))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Dynamic.BindingRestrictions))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Dynamic.CallInfo))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.CompilerServices.CallSiteBinder))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.CompilerServices.CallSiteHelpers))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.CompilerServices.DynamicAttribute))]
+#endif
+[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.CompilerServices.ConditionalWeakTable<,>))]
// THE SOFTWARE.
//
-#if !MONOTOUCH
+#if !FULL_AOT_RUNTIME
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Linq.Expressions.BlockExpression))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Linq.Expressions.CatchBlock))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Linq.Expressions.DebugInfoExpression))]
// THE SOFTWARE.
//
-#if !MONOTOUCH
+#if !FULL_AOT_RUNTIME
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Reflection.Emit.FlowControl))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Reflection.Emit.OpCode))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Reflection.Emit.OpCodes))]
--- /dev/null
+//
+// Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+using System;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+[assembly: AssemblyTitle ("System.Runtime.InteropServices.WindowsRuntime.dll")]
+[assembly: AssemblyDescription ("System.Runtime.InteropServices.WindowsRuntime.dll")]
+[assembly: AssemblyDefaultAlias ("System.Runtime.InteropServices.WindowsRuntime.dll")]
+[assembly: AssemblyCompany ("Xamarin, Inc.")]
+[assembly: AssemblyProduct ("Mono Common Language Infrastructure")]
+[assembly: AssemblyCopyright ("Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.com)")]
+[assembly: AssemblyVersion ("4.0.0.0")]
+[assembly: AssemblyInformationalVersion ("4.0.0.0")]
+[assembly: AssemblyFileVersion ("4.0.0.0")]
+[assembly: AssemblyDelaySign (true)]
+[assembly: AssemblyKeyFile ("../../msfinal.pub")]
+
+[assembly: ReferenceAssembly]
+
+
--- /dev/null
+MCS_BUILD_DIR = ../../../build
+
+thisdir = class/Facades/System.Runtime.InteropServices.WindowsRuntime
+SUBDIRS =
+include $(MCS_BUILD_DIR)/rules.make
+
+LIBRARY_SUBDIR = Facades
+LIBRARY_INSTALL_DIR = $(mono_libdir)/mono/$(FRAMEWORK_VERSION)/Facades
+
+LIBRARY = System.Runtime.InteropServices.WindowsRuntime.dll
+
+KEY_FILE = ../../msfinal.pub
+SIGN_FLAGS = /delaysign /keyfile:$(KEY_FILE) /nowarn:1616,1699
+LIB_MCS_FLAGS = $(SIGN_FLAGS) /r:mscorlib
+
+PLATFORM_DEBUG_FLAGS =
+
+NO_TEST = yes
+
+include $(MCS_BUILD_DIR)/library.make
+
+
--- /dev/null
+TypeForwarders.cs
+AssemblyInfo.cs
+
--- /dev/null
+//
+// Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.WindowsRuntime.DefaultInterfaceAttribute))]
+[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken))]
+[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.WindowsRuntime.EventRegistrationTokenTable<>))]
+[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.WindowsRuntime.IActivationFactory))]
+[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.WindowsRuntime.InterfaceImplementedInVersionAttribute))]
+[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.WindowsRuntime.ReadOnlyArrayAttribute))]
+[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.WindowsRuntime.ReturnValueNameAttribute))]
+[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeMarshal))]
+[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.WindowsRuntime.WriteOnlyArrayAttribute))]
// THE SOFTWARE.
//
-#if !MONOTOUCH
+#if !FULL_AOT_RUNTIME
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.ComImportAttribute))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.DispatchWrapper))]
[assembly: System.Runtime.CompilerServices.TypeForwardedToAttribute(typeof(System.Runtime.InteropServices.ErrorWrapper))]
void AddMetadata (string name, string value)
{
+ var options = IsDynamic ?
+ ParseOptions.AllowItemsMetadataAndSplit : ParseOptions.AllowItemsNoMetadataAndSplit;
+
if (parent_item_group != null) {
Expression e = new Expression ();
- e.Parse (value, ParseOptions.AllowItemsNoMetadataAndSplit);
+ e.Parse (value, options);
evaluatedMetadata [name] = (string) e.ConvertTo (parent_item_group.ParentProject,
typeof (string), ExpressionOptions.ExpandItemRefs);
} else
using System;
using System.Text;
using System.Xml;
+using System.Collections.Generic;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
internal XmlElement XmlElement {
get { return propertyElement; }
}
+
+ internal IEnumerable<string> GetAttributes ()
+ {
+ if (!FromXml)
+ yield break;
+ foreach (XmlAttribute attr in propertyElement.Attributes)
+ yield return attr.Value;
+ }
}
internal enum PropertyType {
List <BuildProperty> properties;
Dictionary <string, BuildProperty> propertiesByName;
bool evaluated;
+ bool isDynamic;
public BuildPropertyGroup ()
: this (null, null, null, false)
}
internal BuildPropertyGroup (XmlElement xmlElement, Project project, ImportedProject importedProject, bool readOnly)
+ : this (xmlElement, project, importedProject, readOnly, false)
+ {
+ }
+
+ internal BuildPropertyGroup (XmlElement xmlElement, Project project, ImportedProject importedProject, bool readOnly, bool isDynamic)
{
this.importedProject = importedProject;
this.parentCollection = null;
this.parentProject = project;
this.propertyGroup = xmlElement;
this.read_only = readOnly;
+ this.isDynamic = isDynamic;
if (FromXml) {
this.properties = new List <BuildProperty> ();
internal void Evaluate ()
{
- if (evaluated)
+ if (!isDynamic && evaluated)
return;
foreach (BuildProperty bp in properties)
internal XmlElement XmlElement {
get { return propertyGroup; }
}
+
+ internal IEnumerable<string> GetAttributes ()
+ {
+ foreach (XmlAttribute attrib in XmlElement.Attributes)
+ yield return attrib.Value;
+
+ foreach (BuildProperty bp in properties) {
+ foreach (string attr in bp.GetAttributes ())
+ yield return attr;
+ }
+ }
}
}
}
internal BuildTaskPropertyGroup (XmlElement element, Target target)
- : base (element, target.Project, null, false)
+ : base (element, target.Project, null, false, true)
{
}
return true;
}
- public IEnumerable<string> GetAttributes ()
+ IEnumerable<string> IBuildTask.GetAttributes ()
{
- foreach (XmlAttribute attrib in XmlElement.Attributes)
- yield return attrib.Value;
+ return GetAttributes ();
}
}
using System;
-namespace Microsoft.Build.BuildEngine {
+#if MICROSOFT_BUILD_DLL
+namespace Microsoft.Build.Logging
+#else
+namespace Microsoft.Build.BuildEngine
+#endif
+{
public delegate void ColorResetter ();
}
using System;
-namespace Microsoft.Build.BuildEngine {
+#if MICROSOFT_BUILD_DLL
+namespace Microsoft.Build.Logging
+#else
+namespace Microsoft.Build.BuildEngine
+#endif
+{
public delegate void ColorSetter (ConsoleColor color);
}
using System.Text;
using Microsoft.Build.Framework;
-namespace Microsoft.Build.BuildEngine {
+#if MICROSOFT_BUILD_DLL
+namespace Microsoft.Build.Logging
+#else
+namespace Microsoft.Build.BuildEngine
+#endif
+{
public class ConsoleLogger : ILogger {
string parameters;
- int indent;
LoggerVerbosity verbosity;
WriteHandler writeHandler;
- int errorCount;
- int warningCount;
- DateTime buildStart;
- bool performanceSummary;
- bool showSummary;
bool skipProjectStartedText;
- List<string> errors, warnings;
- bool projectFailed;
ConsoleColor errorColor, warningColor, eventColor, messageColor, highMessageColor;
ColorSetter colorSet;
ColorResetter colorReset;
IEventSource eventSource;
bool no_message_color, use_colors;
- bool noItemAndPropertyList;
-
- List<BuildEvent> events;
- Dictionary<string, List<string>> errorsTable;
- Dictionary<string, List<string>> warningsTable;
- SortedDictionary<string, PerfInfo> targetPerfTable, tasksPerfTable;
- string current_events_string;
+ ConsoleLoggerParameter config = new ConsoleLoggerParameter ();
public ConsoleLogger ()
: this (LoggerVerbosity.Normal, null, null, null)
}
public ConsoleLogger (LoggerVerbosity verbosity)
- : this (LoggerVerbosity.Normal, null, null, null)
+ : this (verbosity, null, null, null)
{
}
ColorResetter colorReset)
{
this.verbosity = verbosity;
- this.indent = 0;
- this.errorCount = 0;
- this.warningCount = 0;
if (write == null)
this.writeHandler += new WriteHandler (WriteHandlerFunction);
else
this.writeHandler += write;
- this.performanceSummary = false;
- this.showSummary = true;
this.skipProjectStartedText = false;
- errors = new List<string> ();
- warnings = new List<string> ();
this.colorSet = colorSet;
this.colorReset = colorReset;
- events = new List<BuildEvent> ();
- errorsTable = new Dictionary<string, List<string>> ();
- warningsTable = new Dictionary<string, List<string>> ();
- targetPerfTable = new SortedDictionary<string, PerfInfo> ();
- tasksPerfTable = new SortedDictionary<string, PerfInfo> ();
-
//defaults
errorColor = ConsoleColor.DarkRed;
warningColor = ConsoleColor.DarkYellow;
}
}
}
+
+ private void WriteHandlerFunction (string message)
+ {
+ Console.WriteLine (message);
+ }
bool TryParseConsoleColor (string color_str, ref ConsoleColor color)
{
}
}
+ class ConsoleLoggerParameter
+ {
+ public ConsoleLoggerParameter ()
+ {
+ ShowSummary = true;
+ }
+ public bool PerformanceSummary { get; set; }
+ public bool ShowSummary { get; set; }
+ public bool NoItemAndPropertyList { get; set; }
+ }
+
public void ApplyParameter (string parameterName,
string parameterValue)
{
switch (parameterName) {
case "PerformanceSummary":
- this.performanceSummary = true;
+ config.PerformanceSummary = true;
break;
case "Summary":
- this.showSummary = true;
+ config.ShowSummary = true;
break;
case "NoSummary":
- this.showSummary = false;
+ config.ShowSummary = false;
break;
case "NoItemAndPropertyList":
- this.noItemAndPropertyList = true;
+ config.NoItemAndPropertyList = true;
break;
default:
if (parameterName.StartsWith ("Verbosity="))
if (!String.IsNullOrEmpty (parameters))
ParseParameters ();
}
-
- public void BuildStartedHandler (object sender, BuildStartedEventArgs args)
+
+ Dictionary<object,BuildRecord> build_records = new Dictionary<object, BuildRecord> ();
+
+ object dummy_key = new object ();
+
+ BuildRecord GetBuildRecord (object sender)
{
- if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
- WriteLine (String.Empty);
- WriteLine (String.Format ("Build started {0}.", args.Timestamp));
- WriteLine ("__________________________________________________");
+ BuildRecord r;
+ // FIXME: our Microsoft.Build.Engine shouldn't give different "sender" object for each event
+ // during the same build run. But it actually does.
+ // It is problematic for parallel build because it is impossible to determine right "ongoing build"
+ // record for the event without correct sender object.
+ // Hence we expect sender as a valid object only if it is IBuildEngine4 -
+ // only Microsoft.Build.Internal.BuildEngine4 implements it so far.
+ // (Used IBuildEngine3 because it needs to build for NET_4_0).
+#if NET_4_0
+ var key = sender as IBuildEngine3 ?? dummy_key;
+#else
+ var key = dummy_key;
+#endif
+ if (!build_records.TryGetValue (key, out r)) {
+ r = new BuildRecord (this);
+ build_records.Add (key, r);
}
- buildStart = args.Timestamp;
+ return r;
+ }
- PushEvent (args);
+ public void BuildStartedHandler (object sender, BuildStartedEventArgs args)
+ {
+ GetBuildRecord (sender).BuildStartedHandler (sender, args);
}
public void BuildFinishedHandler (object sender, BuildFinishedEventArgs args)
{
- BuildFinishedHandlerActual (args);
-
- // Reset
- events.Clear ();
- errorsTable.Clear ();
- warningsTable.Clear ();
- targetPerfTable.Clear ();
- tasksPerfTable.Clear ();
- errors.Clear ();
- warnings.Clear ();
-
- indent = 0;
- errorCount = 0;
- warningCount = 0;
- projectFailed = false;
+ GetBuildRecord (sender).BuildFinishedHandler (args);
+ build_records.Remove (sender);
}
-
- void BuildFinishedHandlerActual (BuildFinishedEventArgs args)
+
+ void PushEvent<T> (object sender, T args) where T: BuildStatusEventArgs
{
- if (!IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
- PopEvent (args);
- return;
- }
-
- TimeSpan timeElapsed = args.Timestamp - buildStart;
- if (performanceSummary || verbosity == LoggerVerbosity.Diagnostic)
- DumpPerformanceSummary ();
-
- if (args.Succeeded == true && !projectFailed) {
- WriteLine ("Build succeeded.");
- } else {
- WriteLine ("Build FAILED.");
- }
- if (warnings.Count > 0) {
- WriteLine (Environment.NewLine + "Warnings:");
- SetColor (warningColor);
-
- WriteLine (String.Empty);
- foreach (KeyValuePair<string, List<string>> pair in warningsTable) {
- if (!String.IsNullOrEmpty (pair.Key))
- WriteLine (pair.Key);
-
- string indent_str = String.IsNullOrEmpty (pair.Key) ? String.Empty : "\t";
- foreach (string msg in pair.Value)
- WriteLine (String.Format ("{0}{1}", indent_str, msg));
-
- WriteLine (String.Empty);
- }
-
- ResetColor ();
- }
-
- if (errors.Count > 0) {
- WriteLine ("Errors:");
- SetColor (errorColor);
-
- WriteLine (String.Empty);
- foreach (KeyValuePair<string, List<string>> pair in errorsTable) {
- if (!String.IsNullOrEmpty (pair.Key))
- WriteLine (pair.Key);
-
- string indent_str = String.IsNullOrEmpty (pair.Key) ? String.Empty : "\t";
- foreach (string msg in pair.Value)
- WriteLine (String.Format ("{0}{1}", indent_str, msg));
-
- WriteLine (String.Empty);
- }
- ResetColor ();
- }
-
- if (showSummary == true){
- WriteLine (String.Format ("\t {0} Warning(s)", warningCount));
- WriteLine (String.Format ("\t {0} Error(s)", errorCount));
- WriteLine (String.Empty);
- WriteLine (String.Format ("Time Elapsed {0}", timeElapsed));
- }
-
- PopEvent (args);
+ GetBuildRecord (sender).PushEvent (sender, args);
+ }
+ void PopEvent<T> (object sender, T args) where T: BuildStatusEventArgs
+ {
+ GetBuildRecord (sender).PopEvent (args);
}
-
public void ProjectStartedHandler (object sender, ProjectStartedEventArgs args)
{
- if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
- SetColor (eventColor);
- WriteLine (String.Format ("Project \"{0}\" ({1} target(s)):", args.ProjectFile,
- String.IsNullOrEmpty (args.TargetNames) ? "default" : args.TargetNames));
- ResetColor ();
- DumpProperties (args.Properties);
- DumpItems (args.Items);
- }
+ GetBuildRecord (sender).ProjectStartedHandler (args);
}
-
public void ProjectFinishedHandler (object sender, ProjectFinishedEventArgs args)
{
- if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
- if (indent == 1)
- indent --;
- SetColor (eventColor);
- WriteLine (String.Format ("Done building project \"{0}\".{1}", args.ProjectFile,
- args.Succeeded ? String.Empty : "-- FAILED"));
- ResetColor ();
- WriteLine (String.Empty);
- }
- if (!projectFailed)
- // no project has failed yet, so update the flag
- projectFailed = !args.Succeeded;
- }
-
+ GetBuildRecord (sender).ProjectFinishedHandler (args);
+ }
public void TargetStartedHandler (object sender, TargetStartedEventArgs args)
{
- if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
- indent++;
- SetColor (eventColor);
- WriteLine (String.Empty);
- WriteLine (String.Format ("Target {0}:",args.TargetName));
- ResetColor ();
- }
+ GetBuildRecord (sender).TargetStartedHandler (args);
}
-
public void TargetFinishedHandler (object sender, TargetFinishedEventArgs args)
{
- if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed) ||
- (!args.Succeeded && IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal))) {
- SetColor (eventColor);
- WriteLine (String.Format ("Done building target \"{0}\" in project \"{1}\".{2}",
- args.TargetName, args.ProjectFile,
- args.Succeeded ? String.Empty : "-- FAILED"));
- ResetColor ();
- WriteLine (String.Empty);
- }
- indent--;
+ GetBuildRecord (sender).TargetFinishedHandler (args);
}
-
public void TaskStartedHandler (object sender, TaskStartedEventArgs args)
{
- if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed)) {
- SetColor (eventColor);
- WriteLine (String.Format ("Task \"{0}\"",args.TaskName));
- ResetColor ();
- }
- indent++;
+ GetBuildRecord (sender).TaskStartedHandler (args);
}
-
public void TaskFinishedHandler (object sender, TaskFinishedEventArgs args)
{
- indent--;
- if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed) ||
- (!args.Succeeded && IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal))) {
- SetColor (eventColor);
- if (args.Succeeded)
- WriteLine (String.Format ("Done executing task \"{0}\"", args.TaskName));
- else
- WriteLine (String.Format ("Task \"{0}\" execution -- FAILED", args.TaskName));
- ResetColor ();
- }
+ GetBuildRecord (sender).TaskFinishedHandler (args);
}
-
public void MessageHandler (object sender, BuildMessageEventArgs args)
{
- if (IsMessageOk (args)) {
- if (no_message_color) {
- ExecutePendingEventHandlers ();
- WriteLine (args.Message);
- } else {
- ExecutePendingEventHandlers ();
- SetColor (args.Importance == MessageImportance.High ? highMessageColor : messageColor);
- WriteLine (args.Message);
- ResetColor ();
- }
- }
+ GetBuildRecord (sender).MessageHandler (args);
}
-
public void WarningHandler (object sender, BuildWarningEventArgs args)
{
- string msg = FormatWarningEvent (args);
- if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Quiet)) {
- ExecutePendingEventHandlers ();
- SetColor (warningColor);
- WriteLineWithoutIndent (msg);
- ResetColor ();
- }
- warnings.Add (msg);
-
- List<string> list = null;
- if (!warningsTable.TryGetValue (EventsAsString, out list))
- warningsTable [EventsAsString] = list = new List<string> ();
- list.Add (msg);
-
- warningCount++;
+ GetBuildRecord (sender).WarningHandler (args);
}
-
public void ErrorHandler (object sender, BuildErrorEventArgs args)
{
- string msg = FormatErrorEvent (args);
- if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Quiet)) {
- ExecutePendingEventHandlers ();
- SetColor (errorColor);
- WriteLineWithoutIndent (msg);
- ResetColor ();
- }
- errors.Add (msg);
-
- List<string> list = null;
- if (!errorsTable.TryGetValue (EventsAsString, out list))
- errorsTable [EventsAsString] = list = new List<string> ();
- list.Add (msg);
- errorCount++;
+ GetBuildRecord (sender).ErrorHandler (args);
}
[MonoTODO]
public void CustomEventHandler (object sender, CustomBuildEventArgs args)
{
- }
-
- private void WriteLine (string message)
- {
- if (indent > 0) {
- StringBuilder sb = new StringBuilder ();
- for (int i = 0; i < indent; i++)
- sb.Append ('\t');
-
- string indent_str = sb.ToString ();
-
- foreach (string line in message.Split (new string[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries))
- writeHandler (indent_str + line);
- } else {
- writeHandler (message);
- }
- }
-
- void PushEvent<T> (object sender, T args) where T: BuildStatusEventArgs
- {
- PushEvent (args);
- }
-
- void PushEvent<T> (T args) where T: BuildStatusEventArgs
- {
- BuildEvent be = new BuildEvent {
- EventArgs = args,
- StartHandlerHasExecuted = false,
- ConsoleLogger = this
- };
-
- events.Add (be);
- current_events_string = null;
- }
-
- void PopEvent<T> (object sender, T finished_args) where T: BuildStatusEventArgs
- {
- PopEvent (finished_args);
- }
-
- void PopEvent<T> (T finished_args) where T: BuildStatusEventArgs
- {
- if (events.Count == 0)
- throw new InvalidOperationException ("INTERNAL ERROR: Trying to pop from an empty events stack");
-
- BuildEvent be = events [events.Count - 1];
- if (performanceSummary || verbosity == LoggerVerbosity.Diagnostic) {
- var args = be.EventArgs;
- TargetStartedEventArgs tgt_args = args as TargetStartedEventArgs;
- if (tgt_args != null) {
- AddPerfInfo (tgt_args.TargetName, args.Timestamp, targetPerfTable);
- } else {
- TaskStartedEventArgs tsk_args = args as TaskStartedEventArgs;
- if (tsk_args != null)
- AddPerfInfo (tsk_args.TaskName, args.Timestamp, tasksPerfTable);
- }
- }
-
- be.ExecuteFinishedHandler (finished_args);
- events.RemoveAt (events.Count - 1);
- current_events_string = null;
- }
-
- void ExecutePendingEventHandlers ()
- {
- foreach (var be in events)
- be.ExecuteStartedHandler ();
- }
-
- string EventsToString ()
- {
- StringBuilder sb = new StringBuilder ();
-
- string last_imported_target_file = String.Empty;
- for (int i = 0; i < events.Count; i ++) {
- var args = events [i].EventArgs;
- ProjectStartedEventArgs pargs = args as ProjectStartedEventArgs;
- if (pargs != null) {
- sb.AppendFormat ("{0} ({1}) ->\n", pargs.ProjectFile,
- String.IsNullOrEmpty (pargs.TargetNames) ?
- "default targets" :
- pargs.TargetNames);
- last_imported_target_file = String.Empty;
- continue;
- }
-
- TargetStartedEventArgs targs = args as TargetStartedEventArgs;
- if (targs != null) {
- if (targs.TargetFile != targs.ProjectFile && targs.TargetFile != last_imported_target_file)
- // target from an imported file,
- // and it hasn't been mentioned as yet
- sb.AppendFormat ("{0} ", targs.TargetFile);
-
- last_imported_target_file = targs.TargetFile;
- sb.AppendFormat ("({0} target) ->\n", targs.TargetName);
- }
- }
-
- return sb.ToString ();
- }
-
- void AddPerfInfo (string name, DateTime start, IDictionary<string, PerfInfo> perf_table)
- {
- PerfInfo pi;
- if (!perf_table.TryGetValue (name, out pi)) {
- pi = new PerfInfo ();
- perf_table [name] = pi;
- }
-
- pi.Time += DateTime.Now - start;
- pi.NumberOfCalls ++;
- }
-
- void DumpPerformanceSummary ()
- {
- SetColor (eventColor);
- WriteLine ("Target perfomance summary:");
- ResetColor ();
-
- foreach (var pi in targetPerfTable.OrderBy (pair => pair.Value.Time))
- WriteLine (String.Format ("{0,10:0.000} ms {1,-50} {2,5} calls", pi.Value.Time.TotalMilliseconds, pi.Key, pi.Value.NumberOfCalls));
-
- WriteLine (String.Empty);
-
- SetColor (eventColor);
- WriteLine ("Tasks perfomance summary:");
- ResetColor ();
-
- foreach (var pi in tasksPerfTable.OrderBy (pair => pair.Value.Time))
- WriteLine (String.Format ("{0,10:0.000} ms {1,-50} {2,5} calls", pi.Value.Time.TotalMilliseconds, pi.Key, pi.Value.NumberOfCalls));
-
- WriteLine (String.Empty);
- }
-
- private void WriteLineWithoutIndent (string message)
- {
- writeHandler (message);
- }
-
- private void WriteHandlerFunction (string message)
- {
- Console.WriteLine (message);
+ build_records [sender].CustomHandler (args);
}
void SetColor (ConsoleColor color)
eventSource.ErrorRaised -= ErrorHandler;
}
- static bool InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t";
-
- private string FormatErrorEvent (BuildErrorEventArgs args)
- {
- // For some reason we get an 1-char empty string as Subcategory somtimes.
- string subprefix = args.Subcategory == null || args.Subcategory == "" || args.Subcategory == " " ? "" : " ";
- string subcat = subprefix == "" ? "" : args.Subcategory;
-
- if (args.LineNumber != 0){
- if (args.ColumnNumber != 0 && !InEmacs)
- return String.Format ("{0}({1},{2}): {3}{4}error {5}: {6}",
- args.File, args.LineNumber, args.ColumnNumber,
- subprefix, subcat, args.Code, args.Message);
-
- return String.Format ("{0}({1}): {2}{3}error {4}: {5}",
- args.File, args.LineNumber,
- subprefix, subcat, args.Code, args.Message);
- } else {
- return String.Format ("{0}: {1}{2}error {3}: {4}", args.File, subprefix, subcat, args.Code,
- args.Message);
- }
- }
-
- private string FormatWarningEvent (BuildWarningEventArgs args)
- {
- // For some reason we get an 1-char empty string as Subcategory somtimes.
- string subprefix = args.Subcategory == null || args.Subcategory == "" || args.Subcategory == " " ? "" : " ";
- string subcat = subprefix == "" ? "" : args.Subcategory;
-
- // FIXME: show more complicated args
- if (args.LineNumber != 0){
-
- if (args.ColumnNumber != 0 && !InEmacs) {
- return String.Format ("{0}({1},{2}): {3}{4}warning {5}: {6}",
- args.File, args.LineNumber, args.ColumnNumber,
- subprefix, subcat, args.Code, args.Message);
- }
- return String.Format ("{0}({1}): {2}{3}warning {4}: {5}",
- args.File, args.LineNumber,
- subprefix, subcat, args.Code, args.Message);
- } else {
- return String.Format ("{0}: {1} warning {2}: {3}", args.File, args.Subcategory, args.Code,
- args.Message);
- }
- }
-
- private bool IsMessageOk (BuildMessageEventArgs bsea)
- {
- if (bsea.Importance == MessageImportance.High && IsVerbosityGreaterOrEqual (LoggerVerbosity.Minimal)) {
- return true;
- } else if (bsea.Importance == MessageImportance.Normal && IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
- return true;
- } else if (bsea.Importance == MessageImportance.Low && IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed)) {
- return true;
- } else
- return false;
- }
-
- private bool IsVerbosityGreaterOrEqual (LoggerVerbosity v)
- {
- if (v == LoggerVerbosity.Diagnostic) {
- return LoggerVerbosity.Diagnostic <= verbosity;
- } else if (v == LoggerVerbosity.Detailed) {
- return LoggerVerbosity.Detailed <= verbosity;
- } else if (v == LoggerVerbosity.Normal) {
- return LoggerVerbosity.Normal <= verbosity;
- } else if (v == LoggerVerbosity.Minimal) {
- return LoggerVerbosity.Minimal <= verbosity;
- } else if (v == LoggerVerbosity.Quiet) {
- return true;
- } else
- return false;
- }
-
- void DumpProperties (IEnumerable properties)
- {
- if (noItemAndPropertyList || !IsVerbosityGreaterOrEqual (LoggerVerbosity.Diagnostic))
- return;
-
- SetColor (eventColor);
- WriteLine (String.Empty);
- WriteLine ("Initial Properties:");
- ResetColor ();
-
- if (properties == null)
- return;
-
- var dict = new SortedDictionary<string, string> ();
- foreach (DictionaryEntry de in properties)
- dict [(string)de.Key] = (string)de.Value;
-
- foreach (KeyValuePair<string, string> pair in dict)
- WriteLine (String.Format ("{0} = {1}", pair.Key, pair.Value));
- }
-
- void DumpItems (IEnumerable items)
- {
- if (noItemAndPropertyList || !IsVerbosityGreaterOrEqual (LoggerVerbosity.Diagnostic) || items == null)
- return;
-
- SetColor (eventColor);
- WriteLine (String.Empty);
- WriteLine ("Initial Items:");
- ResetColor ();
- if (items == null)
- return;
-
- var items_table = new SortedDictionary<string, List<ITaskItem>> ();
- foreach (DictionaryEntry de in items) {
- string key = (string)de.Key;
- if (!items_table.ContainsKey (key))
- items_table [key] = new List<ITaskItem> ();
-
- items_table [key].Add ((ITaskItem) de.Value);
- }
-
- foreach (string name in items_table.Keys) {
- WriteLine (name);
- indent ++;
- foreach (ITaskItem item in items_table [name])
- WriteLine (item.ItemSpec);
- indent--;
- }
- }
-
public string Parameters {
get {
return parameters;
if (value == null)
throw new ArgumentNullException ();
parameters = value;
- }
- }
-
- string EventsAsString {
- get {
- if (current_events_string == null)
- current_events_string = EventsToString ();
- return current_events_string;
+ ParseParameters ();
}
}
public bool ShowSummary {
- get { return showSummary; }
- set { showSummary = value; }
+ get { return config.ShowSummary; }
+ set { config.ShowSummary = value; }
}
public bool SkipProjectStartedText {
get { return writeHandler; }
set { writeHandler = value; }
}
+
+ class BuildRecord
+ {
+ readonly ConsoleLogger parent;
+
+ readonly List<BuildEvent> events;
+ readonly Dictionary<string, List<string>> errorsTable;
+ readonly Dictionary<string, List<string>> warningsTable;
+ readonly SortedDictionary<string, PerfInfo> targetPerfTable, tasksPerfTable;
+ List<string> errors, warnings;
+ int indent;
+ int errorCount;
+ int warningCount;
+ bool projectFailed;
+ DateTime buildStart;
+
+ string current_events_string;
+
+ ConsoleColor eventColor {
+ get { return parent.eventColor; }
+ }
+ LoggerVerbosity verbosity {
+ get { return parent.Verbosity; }
+ }
+
+ public BuildRecord (ConsoleLogger parent)
+ {
+ this.parent = parent;
+
+ this.indent = 0;
+ this.errorCount = 0;
+ this.warningCount = 0;
+ errors = new List<string> ();
+ warnings = new List<string> ();
+ events = new List<BuildEvent> ();
+ errorsTable = new Dictionary<string, List<string>> ();
+ warningsTable = new Dictionary<string, List<string>> ();
+ targetPerfTable = new SortedDictionary<string, PerfInfo> ();
+ tasksPerfTable = new SortedDictionary<string, PerfInfo> ();
+ }
+
+ internal void PushEvent<T> (object sender, T args) where T: BuildStatusEventArgs
+ {
+ BuildEvent be = new BuildEvent {
+ Sender = sender,
+ EventArgs = args,
+ StartHandlerHasExecuted = false,
+ ConsoleLogger = this.parent
+ };
+
+ events.Add (be);
+ current_events_string = null;
+ }
+
+ void PopEvent<T> (object sender, T finished_args) where T: BuildStatusEventArgs
+ {
+ PopEvent (finished_args);
+ }
+
+ internal void PopEvent<T> (T finished_args) where T: BuildStatusEventArgs
+ {
+ if (events.Count == 0)
+ throw new InvalidOperationException ("INTERNAL ERROR: Trying to pop from an empty events stack");
+
+ BuildEvent be = events [events.Count - 1];
+ if (parent.config.PerformanceSummary || verbosity == LoggerVerbosity.Diagnostic) {
+ var args = be.EventArgs;
+ TargetStartedEventArgs tgt_args = args as TargetStartedEventArgs;
+ if (tgt_args != null) {
+ AddPerfInfo (tgt_args.TargetName, args.Timestamp, targetPerfTable);
+ } else {
+ TaskStartedEventArgs tsk_args = args as TaskStartedEventArgs;
+ if (tsk_args != null)
+ AddPerfInfo (tsk_args.TaskName, args.Timestamp, tasksPerfTable);
+ }
+ }
+
+ be.ExecuteFinishedHandler (finished_args);
+ events.RemoveAt (events.Count - 1);
+ current_events_string = null;
+ }
+
+ public void ResetBuildState ()
+ {
+ // Reset
+ events.Clear ();
+ errorsTable.Clear ();
+ warningsTable.Clear ();
+ targetPerfTable.Clear ();
+ tasksPerfTable.Clear ();
+ errors.Clear ();
+ warnings.Clear ();
+
+ indent = 0;
+ errorCount = 0;
+ warningCount = 0;
+ projectFailed = false;
+ }
+
+ void AddPerfInfo (string name, DateTime start, IDictionary<string, PerfInfo> perf_table)
+ {
+ PerfInfo pi;
+ if (!perf_table.TryGetValue (name, out pi)) {
+ pi = new PerfInfo ();
+ perf_table [name] = pi;
+ }
+
+ pi.Time += DateTime.Now - start;
+ pi.NumberOfCalls ++;
+ }
+
+ public void BuildStartedHandler (object sender, BuildStartedEventArgs args)
+ {
+ if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
+ WriteLine (String.Empty);
+ WriteLine (String.Format ("Build started {0}.", args.Timestamp));
+ WriteLine ("__________________________________________________");
+ }
+ buildStart = args.Timestamp;
+
+ PushEvent (sender, args);
+ }
+
+ public void BuildFinishedHandler (BuildFinishedEventArgs args)
+ {
+ BuildFinishedHandlerActual (args);
+
+ ResetBuildState ();
+ }
+
+ void BuildFinishedHandlerActual (BuildFinishedEventArgs args)
+ {
+ if (!IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
+ PopEvent (args);
+ return;
+ }
+
+ TimeSpan timeElapsed = args.Timestamp - buildStart;
+ if (parent.config.PerformanceSummary || verbosity == LoggerVerbosity.Diagnostic)
+ DumpPerformanceSummary ();
+
+ if (args.Succeeded == true && !projectFailed) {
+ WriteLine ("Build succeeded.");
+ } else {
+ WriteLine ("Build FAILED.");
+ }
+ if (warnings.Count > 0) {
+ WriteLine (Environment.NewLine + "Warnings:");
+ SetColor (parent.warningColor);
+
+ WriteLine (String.Empty);
+ foreach (KeyValuePair<string, List<string>> pair in warningsTable) {
+ if (!String.IsNullOrEmpty (pair.Key))
+ WriteLine (pair.Key);
+
+ string indent_str = String.IsNullOrEmpty (pair.Key) ? String.Empty : "\t";
+ foreach (string msg in pair.Value)
+ WriteLine (String.Format ("{0}{1}", indent_str, msg));
+
+ WriteLine (String.Empty);
+ }
+
+ ResetColor ();
+ }
+
+ if (errors.Count > 0) {
+ WriteLine ("Errors:");
+ SetColor (parent.errorColor);
+
+ WriteLine (String.Empty);
+ foreach (KeyValuePair<string, List<string>> pair in errorsTable) {
+ if (!String.IsNullOrEmpty (pair.Key))
+ WriteLine (pair.Key);
+
+ string indent_str = String.IsNullOrEmpty (pair.Key) ? String.Empty : "\t";
+ foreach (string msg in pair.Value)
+ WriteLine (String.Format ("{0}{1}", indent_str, msg));
+
+ WriteLine (String.Empty);
+ }
+ ResetColor ();
+ }
+
+ if (parent.ShowSummary == true){
+ WriteLine (String.Format ("\t {0} Warning(s)", warningCount));
+ WriteLine (String.Format ("\t {0} Error(s)", errorCount));
+ WriteLine (String.Empty);
+ WriteLine (String.Format ("Time Elapsed {0}", timeElapsed));
+ }
+
+ PopEvent (args);
+ }
+
+ public void ProjectStartedHandler (ProjectStartedEventArgs args)
+ {
+ if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
+ SetColor (eventColor);
+ WriteLine (String.Format ("Project \"{0}\" ({1} target(s)):", args.ProjectFile,
+ String.IsNullOrEmpty (args.TargetNames) ? "default" : args.TargetNames));
+ ResetColor ();
+ DumpProperties (args.Properties);
+ DumpItems (args.Items);
+ }
+ }
+
+ public void ProjectFinishedHandler (ProjectFinishedEventArgs args)
+ {
+ if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
+ if (indent == 1)
+ indent --;
+ SetColor (eventColor);
+ WriteLine (String.Format ("Done building project \"{0}\".{1}", args.ProjectFile,
+ args.Succeeded ? String.Empty : "-- FAILED"));
+ ResetColor ();
+ WriteLine (String.Empty);
+ }
+ if (!projectFailed)
+ // no project has failed yet, so update the flag
+ projectFailed = !args.Succeeded;
+ }
+
+ public void TargetStartedHandler (TargetStartedEventArgs args)
+ {
+ if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
+ indent++;
+ SetColor (eventColor);
+ WriteLine (String.Empty);
+ WriteLine (String.Format ("Target {0}:",args.TargetName));
+ ResetColor ();
+ }
+ }
+
+ public void TargetFinishedHandler (TargetFinishedEventArgs args)
+ {
+ if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed) ||
+ (!args.Succeeded && IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal))) {
+ SetColor (eventColor);
+ WriteLine (String.Format ("Done building target \"{0}\" in project \"{1}\".{2}",
+ args.TargetName, args.ProjectFile,
+ args.Succeeded ? String.Empty : "-- FAILED"));
+ ResetColor ();
+ WriteLine (String.Empty);
+ }
+ indent--;
+ }
+
+ public void TaskStartedHandler (TaskStartedEventArgs args)
+ {
+ if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed)) {
+ SetColor (eventColor);
+ WriteLine (String.Format ("Task \"{0}\"",args.TaskName));
+ ResetColor ();
+ }
+ indent++;
+ }
+
+ public void TaskFinishedHandler (TaskFinishedEventArgs args)
+ {
+ indent--;
+ if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed) ||
+ (!args.Succeeded && IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal))) {
+ SetColor (eventColor);
+ if (args.Succeeded)
+ WriteLine (String.Format ("Done executing task \"{0}\"", args.TaskName));
+ else
+ WriteLine (String.Format ("Task \"{0}\" execution -- FAILED", args.TaskName));
+ ResetColor ();
+ }
+ }
+
+ public void MessageHandler (BuildMessageEventArgs args)
+ {
+ if (IsMessageOk (args)) {
+ if (parent.no_message_color) {
+ ExecutePendingEventHandlers ();
+ WriteLine (args.Message);
+ } else {
+ ExecutePendingEventHandlers ();
+ SetColor (args.Importance == MessageImportance.High ? parent.highMessageColor : parent.messageColor);
+ WriteLine (args.Message);
+ ResetColor ();
+ }
+ }
+ }
+
+ public void WarningHandler (BuildWarningEventArgs args)
+ {
+ string msg = FormatWarningEvent (args);
+ if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Quiet)) {
+ ExecutePendingEventHandlers ();
+ SetColor (parent.warningColor);
+ WriteLineWithoutIndent (msg);
+ ResetColor ();
+ }
+ warnings.Add (msg);
+
+ List<string> list = null;
+ if (!warningsTable.TryGetValue (EventsAsString, out list))
+ warningsTable [EventsAsString] = list = new List<string> ();
+ list.Add (msg);
+
+ warningCount++;
+ }
+
+ public void ErrorHandler (BuildErrorEventArgs args)
+ {
+ string msg = FormatErrorEvent (args);
+ if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Quiet)) {
+ ExecutePendingEventHandlers ();
+ SetColor (parent.errorColor);
+ WriteLineWithoutIndent (msg);
+ ResetColor ();
+ }
+ errors.Add (msg);
+
+ List<string> list = null;
+ if (!errorsTable.TryGetValue (EventsAsString, out list))
+ errorsTable [EventsAsString] = list = new List<string> ();
+ list.Add (msg);
+ errorCount++;
+ }
+
+ public void CustomHandler (CustomBuildEventArgs args)
+ {
+ }
+
+ private bool IsVerbosityGreaterOrEqual (LoggerVerbosity v)
+ {
+ if (v == LoggerVerbosity.Diagnostic) {
+ return LoggerVerbosity.Diagnostic <= verbosity;
+ } else if (v == LoggerVerbosity.Detailed) {
+ return LoggerVerbosity.Detailed <= verbosity;
+ } else if (v == LoggerVerbosity.Normal) {
+ return LoggerVerbosity.Normal <= verbosity;
+ } else if (v == LoggerVerbosity.Minimal) {
+ return LoggerVerbosity.Minimal <= verbosity;
+ } else if (v == LoggerVerbosity.Quiet) {
+ return true;
+ } else
+ return false;
+ }
+
+ void DumpItems (IEnumerable items)
+ {
+ if (parent.config.NoItemAndPropertyList || !IsVerbosityGreaterOrEqual (LoggerVerbosity.Diagnostic) || items == null)
+ return;
+
+ SetColor (eventColor);
+ WriteLine (String.Empty);
+ WriteLine ("Initial Items:");
+ ResetColor ();
+ if (items == null)
+ return;
+
+ var items_table = new SortedDictionary<string, List<ITaskItem>> ();
+ foreach (DictionaryEntry de in items) {
+ string key = (string)de.Key;
+ if (!items_table.ContainsKey (key))
+ items_table [key] = new List<ITaskItem> ();
+
+ items_table [key].Add ((ITaskItem) de.Value);
+ }
+
+ foreach (string name in items_table.Keys) {
+ WriteLine (name);
+ indent ++;
+ foreach (ITaskItem item in items_table [name])
+ WriteLine (item.ItemSpec);
+ indent--;
+ }
+ }
+
+ string EventsAsString {
+ get {
+ if (current_events_string == null)
+ current_events_string = EventsToString ();
+ return current_events_string;
+ }
+ }
+
+ private bool IsMessageOk (BuildMessageEventArgs bsea)
+ {
+ if (bsea.Importance == MessageImportance.High && IsVerbosityGreaterOrEqual (LoggerVerbosity.Minimal)) {
+ return true;
+ } else if (bsea.Importance == MessageImportance.Normal && IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) {
+ return true;
+ } else if (bsea.Importance == MessageImportance.Low && IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed)) {
+ return true;
+ } else
+ return false;
+ }
+
+ void DumpProperties (IEnumerable properties)
+ {
+ if (parent.config.NoItemAndPropertyList || !IsVerbosityGreaterOrEqual (LoggerVerbosity.Diagnostic))
+ return;
+
+ SetColor (eventColor);
+ WriteLine (String.Empty);
+ WriteLine ("Initial Properties:");
+ ResetColor ();
+
+ if (properties == null)
+ return;
+
+ var dict = new SortedDictionary<string, string> ();
+ foreach (DictionaryEntry de in properties)
+ dict [(string)de.Key] = (string)de.Value;
+
+ foreach (KeyValuePair<string, string> pair in dict)
+ WriteLine (String.Format ("{0} = {1}", pair.Key, pair.Value));
+ }
+
+ private void WriteLine (string message)
+ {
+ if (indent > 0) {
+ StringBuilder sb = new StringBuilder ();
+ for (int i = 0; i < indent; i++)
+ sb.Append ('\t');
+
+ string indent_str = sb.ToString ();
+
+ foreach (string line in message.Split (new string[] {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries))
+ parent.writeHandler (indent_str + line);
+ } else {
+ parent.writeHandler (message);
+ }
+ }
+
+ void ExecutePendingEventHandlers ()
+ {
+ foreach (var be in events)
+ be.ExecuteStartedHandler ();
+ }
+
+ string EventsToString ()
+ {
+ StringBuilder sb = new StringBuilder ();
+
+ string last_imported_target_file = String.Empty;
+ for (int i = 0; i < events.Count; i ++) {
+ var args = events [i].EventArgs;
+ ProjectStartedEventArgs pargs = args as ProjectStartedEventArgs;
+ if (pargs != null) {
+ sb.AppendFormat ("{0} ({1}) ->\n", pargs.ProjectFile,
+ String.IsNullOrEmpty (pargs.TargetNames) ?
+ "default targets" :
+ pargs.TargetNames);
+ last_imported_target_file = String.Empty;
+ continue;
+ }
+
+ TargetStartedEventArgs targs = args as TargetStartedEventArgs;
+ if (targs != null) {
+ if (targs.TargetFile != targs.ProjectFile && targs.TargetFile != last_imported_target_file)
+ // target from an imported file,
+ // and it hasn't been mentioned as yet
+ sb.AppendFormat ("{0} ", targs.TargetFile);
+
+ last_imported_target_file = targs.TargetFile;
+ sb.AppendFormat ("({0} target) ->\n", targs.TargetName);
+ }
+ }
+
+ return sb.ToString ();
+ }
+
+ void DumpPerformanceSummary ()
+ {
+ SetColor (eventColor);
+ WriteLine ("Target perfomance summary:");
+ ResetColor ();
+
+ foreach (var pi in targetPerfTable.OrderBy (pair => pair.Value.Time))
+ WriteLine (String.Format ("{0,10:0.000} ms {1,-50} {2,5} calls", pi.Value.Time.TotalMilliseconds, pi.Key, pi.Value.NumberOfCalls));
+
+ WriteLine (String.Empty);
+
+ SetColor (eventColor);
+ WriteLine ("Tasks perfomance summary:");
+ ResetColor ();
+
+ foreach (var pi in tasksPerfTable.OrderBy (pair => pair.Value.Time))
+ WriteLine (String.Format ("{0,10:0.000} ms {1,-50} {2,5} calls", pi.Value.Time.TotalMilliseconds, pi.Key, pi.Value.NumberOfCalls));
+
+ WriteLine (String.Empty);
+ }
+
+ private string FormatErrorEvent (BuildErrorEventArgs args)
+ {
+ // For some reason we get an 1-char empty string as Subcategory somtimes.
+ string subprefix = args.Subcategory == null || args.Subcategory == "" || args.Subcategory == " " ? "" : " ";
+ string subcat = subprefix == "" ? "" : args.Subcategory;
+
+ if (args.LineNumber != 0){
+ if (args.ColumnNumber != 0 && !InEmacs)
+ return String.Format ("{0}({1},{2}): {3}{4}error {5}: {6}",
+ args.File, args.LineNumber, args.ColumnNumber,
+ subprefix, subcat, args.Code, args.Message);
+
+ return String.Format ("{0}({1}): {2}{3}error {4}: {5}",
+ args.File, args.LineNumber,
+ subprefix, subcat, args.Code, args.Message);
+ } else {
+ return String.Format ("{0}: {1}{2}error {3}: {4}", args.File, subprefix, subcat, args.Code,
+ args.Message);
+ }
+ }
+
+ static bool InEmacs = Environment.GetEnvironmentVariable ("EMACS") == "t";
+
+ private string FormatWarningEvent (BuildWarningEventArgs args)
+ {
+ // For some reason we get an 1-char empty string as Subcategory somtimes.
+ string subprefix = args.Subcategory == null || args.Subcategory == "" || args.Subcategory == " " ? "" : " ";
+ string subcat = subprefix == "" ? "" : args.Subcategory;
+
+ // FIXME: show more complicated args
+ if (args.LineNumber != 0){
+
+ if (args.ColumnNumber != 0 && !InEmacs) {
+ return String.Format ("{0}({1},{2}): {3}{4}warning {5}: {6}",
+ args.File, args.LineNumber, args.ColumnNumber,
+ subprefix, subcat, args.Code, args.Message);
+ }
+ return String.Format ("{0}({1}): {2}{3}warning {4}: {5}",
+ args.File, args.LineNumber,
+ subprefix, subcat, args.Code, args.Message);
+ } else {
+ return String.Format ("{0}: {1} warning {2}: {3}", args.File, args.Subcategory, args.Code,
+ args.Message);
+ }
+ }
+
+ void SetColor (ConsoleColor color)
+ {
+ if (parent.use_colors)
+ parent.colorSet (color);
+ }
+
+ void ResetColor ()
+ {
+ if (parent.use_colors)
+ parent.colorReset ();
+ }
+
+ private void WriteLineWithoutIndent (string message)
+ {
+ parent.writeHandler (message);
+ }
+ }
}
class BuildEvent {
+ public object Sender;
public BuildStatusEventArgs EventArgs;
public bool StartHandlerHasExecuted;
public ConsoleLogger ConsoleLogger;
return;
if (EventArgs is ProjectStartedEventArgs)
- ConsoleLogger.ProjectStartedHandler (null, (ProjectStartedEventArgs)EventArgs);
+ ConsoleLogger.ProjectStartedHandler (Sender, (ProjectStartedEventArgs)EventArgs);
else if (EventArgs is TargetStartedEventArgs)
- ConsoleLogger.TargetStartedHandler (null, (TargetStartedEventArgs)EventArgs);
+ ConsoleLogger.TargetStartedHandler (Sender, (TargetStartedEventArgs)EventArgs);
else if (EventArgs is TaskStartedEventArgs)
- ConsoleLogger.TaskStartedHandler (null, (TaskStartedEventArgs)EventArgs);
+ ConsoleLogger.TaskStartedHandler (Sender, (TaskStartedEventArgs)EventArgs);
else if (!(EventArgs is BuildStartedEventArgs))
throw new InvalidOperationException ("Unexpected event on the stack, type: " + EventArgs.GetType ());
return;
if (EventArgs is ProjectStartedEventArgs)
- ConsoleLogger.ProjectFinishedHandler (null, finished_args as ProjectFinishedEventArgs);
+ ConsoleLogger.ProjectFinishedHandler (Sender, finished_args as ProjectFinishedEventArgs);
else if (EventArgs is TargetStartedEventArgs)
- ConsoleLogger.TargetFinishedHandler (null, finished_args as TargetFinishedEventArgs);
+ ConsoleLogger.TargetFinishedHandler (Sender, finished_args as TargetFinishedEventArgs);
else if (EventArgs is TaskStartedEventArgs)
- ConsoleLogger.TaskFinishedHandler (null, finished_args as TaskFinishedEventArgs);
+ ConsoleLogger.TaskFinishedHandler (Sender, finished_args as TaskFinishedEventArgs);
else if (!(EventArgs is BuildStartedEventArgs))
throw new InvalidOperationException ("Unexpected event on the stack, type: " + EventArgs.GetType ());
}
using System.Text;
using Microsoft.Build.Framework;
-namespace Microsoft.Build.BuildEngine {
+#if MICROSOFT_BUILD_DLL
+namespace Microsoft.Build.Logging
+#else
+namespace Microsoft.Build.BuildEngine
+#endif
+{
public class FileLogger : ConsoleLogger {
StreamWriter sw;
string logfile;
internal bool Build (string built_targets_key)
{
bool executeOnErrors;
- return Build (built_targets_key, out executeOnErrors);
+ return Build (built_targets_key, null, out executeOnErrors);
}
- bool Build (string built_targets_key, out bool executeOnErrors)
+ bool Build (string built_targets_key, string parentTarget, out bool executeOnErrors)
{
+ string message;
+ if (parentTarget != null)
+ message = string.Format ("\"{0}\" in project \"{1}\" (\"{2}\"); \"{3}\" depends on it", Name, project.FullFileName, TargetFile, parentTarget);
+ else
+ message = string.Format ("\"{0}\" in project \"{1}\" (\"{2}\")", Name, project.FullFileName, TargetFile);
+
project.PushThisFileProperty (TargetFile);
try {
+ LogMessage (MessageImportance.Low, "Building target {0}.", message);
return BuildActual (built_targets_key, out executeOnErrors);
} finally {
+ LogMessage (MessageImportance.Low, "Done building target {0}.", message);
project.PopThisFileProperty ();
}
}
}
if (t.BuildState == BuildState.NotStarted)
- if (!t.Build (null, out executeOnErrors))
+ if (!t.Build (null, Name, out executeOnErrors))
return false;
if (t.BuildState == BuildState.Started)
ITaskItem [] OutputsAsITaskItems {
get {
- string outputs = targetElement.GetAttribute ("Outputs");
- if (outputs == String.Empty)
- return new ITaskItem [0];
+ var outputs = targetElement.GetAttribute ("Returns");
+ if (string.IsNullOrEmpty (outputs)) {
+ outputs = targetElement.GetAttribute ("Outputs");
+ if (string.IsNullOrEmpty (outputs))
+ return new ITaskItem [0];
+ }
Expression e = new Expression ();
e.Parse (outputs, ParseOptions.AllowItemsNoMetadataAndSplit);
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-namespace Microsoft.Build.BuildEngine {
+#if MICROSOFT_BUILD_DLL
+namespace Microsoft.Build.Logging
+#else
+namespace Microsoft.Build.BuildEngine
+#endif
+{
public delegate void WriteHandler (string message);
}
}
void ItemGroupInsideTarget (string xml, params string[] messages)
+ {
+ ItemGroupInsideTarget (xml, 1, messages);
+ }
+
+ void ItemGroupInsideTarget (string xml, int expectedTargetCount, params string[] messages)
{
var logger = CreateLogger (xml);
for (int i = 0; i < messages.Length; i++)
logger.CheckLoggedMessageHead (messages [i], i.ToString ());
Assert.AreEqual(0, logger.NormalMessageCount, "Extra messages found");
+ Assert.AreEqual(0, logger.WarningMessageCount, "Extra warningmessages found");
- Assert.AreEqual(1, logger.TargetStarted, "TargetStarted count");
- Assert.AreEqual(1, logger.TargetFinished, "TargetFinished count");
+ Assert.AreEqual(expectedTargetCount, logger.TargetStarted, "TargetStarted count");
+ Assert.AreEqual(expectedTargetCount, logger.TargetFinished, "TargetFinished count");
Assert.AreEqual(messages.Length, logger.TaskStarted, "TaskStarted count");
Assert.AreEqual(messages.Length, logger.TaskFinished, "TaskFinished count");
}
</Target>
</Project>", "Sun", "Rain");
}
+
+ [Test]
+ public void PropertyGroupInsideTarget_Condition ()
+ {
+ ItemGroupInsideTarget (
+ @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"" ToolsVersion=""4.0"">
+ <ItemGroup>
+ <Shells Include=""/bin/sh;/bin/bash;/bin/false"" />
+ </ItemGroup>
+
+ <Target Name='Main'>
+ <PropertyGroup>
+ <HasBash Condition=""'%(Shells.Filename)' == 'bash'"">true</HasBash>
+ </PropertyGroup>
+
+ <ItemGroup Condition=""'$(HasBash)' == 'true'"">
+ <Weather Include='Rain' />
+ </ItemGroup>
+ <Message Text='%(Weather.Identity)' />
+ </Target>
+ </Project>", "Rain");
+ }
+
+ [Test]
+ // Bug #14661
+ public void ItemGroupInsideTarget_Expression_in_Metadata ()
+ {
+ ItemGroupInsideTarget (
+ @"<Project xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"" ToolsVersion=""4.0"">
+ <ItemGroup>
+ <Foo Include='output1'>
+ <Inputs>input1a;input1b</Inputs>
+ </Foo>
+ <Foo Include='output2'>
+ <Inputs>input2a;input2b</Inputs>
+ </Foo>
+ </ItemGroup>
+
+ <Target Name='Main' DependsOnTargets='_PrepareItems' Inputs='@(_Foo)' Outputs='%(Result)'>
+ <Message Text='COMPILE: @(_Foo) - %(_Foo.Result)' />
+ </Target>
+
+ <Target Name='_PrepareItems'>
+ <ItemGroup>
+ <_Foo Include='%(Foo.Inputs)'>
+ <Result>%(Foo.Identity)</Result>
+ </_Foo>
+ </ItemGroup>
+ </Target>
+ </Project>",
+ 3, "COMPILE: input1a;input1b - output1", "COMPILE: input2a;input2b - output2");
+ }
+
#endif
[Test]
}
#endif
+ [Test]
+ public void TestTargetReturns ()
+ {
+ engine = new Engine (Consts.BinPath);
+ project = engine.CreateNewProject ();
+ project.Load (Path.Combine ("Test", Path.Combine ("resources", "TestReturns.csproj")));
+
+ var logger = new TestMessageLogger ();
+ engine.RegisterLogger (logger);
+
+ bool result = project.Build ("Main");
+ if (!result) {
+ logger.DumpMessages ();
+ Assert.Fail ("Build failed");
+ }
+
+ logger.CheckLoggedMessageHead ("Result: Bar", "A1");
+
+ Assert.AreEqual (0, logger.NormalMessageCount, "Unexpected extra messages found");
+ }
+
}
}
--- /dev/null
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+
+ <Target Name="GetFoo" Outputs="Out" Returns="Bar" />
+
+ <Target Name="Main">
+ <MSBuild Projects="TestReturns.csproj" Targets="GetFoo">
+ <Output TaskParameter="TargetOutputs" ItemName="FooResult"/>
+ </MSBuild>
+
+ <Message Text="Result: %(FooResult.Identity)" />
+ </Target>
+
+</Project>
../../build/common/MonoTODOAttribute.cs
Assembly/AssemblyInfo.cs
Microsoft.Build.Framework/AnyEventHandler.cs
+Microsoft.Build.Framework/BuildEngineResult.cs
Microsoft.Build.Framework/BuildErrorEventArgs.cs
Microsoft.Build.Framework/BuildErrorEventHandler.cs
Microsoft.Build.Framework/BuildEventArgs.cs
+Microsoft.Build.Framework/BuildEventContext.cs
Microsoft.Build.Framework/BuildFinishedEventArgs.cs
Microsoft.Build.Framework/BuildFinishedEventHandler.cs
Microsoft.Build.Framework/BuildMessageEventArgs.cs
Microsoft.Build.Framework/ExternalProjectStartedEventArgs.cs
Microsoft.Build.Framework/IBuildEngine.cs
Microsoft.Build.Framework/IBuildEngine2.cs
+Microsoft.Build.Framework/IBuildEngine3.cs
+Microsoft.Build.Framework/IBuildEngine4.cs
Microsoft.Build.Framework/ICancelableTask.cs
+Microsoft.Build.Framework/IEventRedirector.cs
Microsoft.Build.Framework/IEventSource.cs
+Microsoft.Build.Framework/IForwardingLogger.cs
Microsoft.Build.Framework/ILogger.cs
Microsoft.Build.Framework/INodeLogger.cs
Microsoft.Build.Framework/ITask.cs
+Microsoft.Build.Framework/ITaskFactory.cs
+Microsoft.Build.Framework/ITaskFactory2.cs
Microsoft.Build.Framework/ITaskHost.cs
Microsoft.Build.Framework/ITaskItem.cs
Microsoft.Build.Framework/ITaskItem2.cs
Microsoft.Build.Framework/ProjectFinishedEventHandler.cs
Microsoft.Build.Framework/ProjectStartedEventArgs.cs
Microsoft.Build.Framework/ProjectStartedEventHandler.cs
+Microsoft.Build.Framework/RegisteredTaskObjectLifetime.cs
Microsoft.Build.Framework/RequiredAttribute.cs
Microsoft.Build.Framework/TargetFinishedEventArgs.cs
Microsoft.Build.Framework/TargetFinishedEventHandler.cs
Microsoft.Build.Framework/TaskCommandLineEventArgs.cs
Microsoft.Build.Framework/TaskFinishedEventArgs.cs
Microsoft.Build.Framework/TaskFinishedEventHandler.cs
+Microsoft.Build.Framework/TaskPropertyInfo.cs
Microsoft.Build.Framework/TaskStartedEventArgs.cs
Microsoft.Build.Framework/TaskStartedEventHandler.cs
+
--- /dev/null
+using System;
+using System.Collections.Generic;
+
+namespace Microsoft.Build.Framework
+{
+ [SerializableAttribute]
+ public struct BuildEngineResult
+ {
+ public BuildEngineResult (bool result, List<IDictionary<string, ITaskItem[]>> targetOutputsPerProject)
+ {
+ this.result = result;
+ this.outputs = targetOutputsPerProject;
+ }
+
+ readonly bool result;
+ public bool Result {
+ get { return result; }
+ }
+
+ readonly IList<IDictionary<string, ITaskItem[]>> outputs;
+ public IList<IDictionary<string, ITaskItem[]>> TargetOutputsPerProject {
+ get { return outputs; }
+ }
+ }
+}
string senderName;
int threadId;
DateTime timestamp;
-
+ BuildEventContext context;
+
protected BuildEventArgs ()
: this (null, null, null)
{
this.senderName = senderName;
this.threadId = Thread.CurrentThread.GetHashCode ();
this.timestamp = eventTimestamp;
+ this.context = BuildEventContext.NewInstance ();
}
public string HelpKeyword {
return timestamp;
}
}
+
+ public BuildEventContext BuildEventContext {
+ get { return context; }
+ set {
+ if (value == null)
+ throw new ArgumentNullException ("value");
+ context = value;
+ }
+ }
}
}
--- /dev/null
+using System;
+
+
+namespace Microsoft.Build.Framework
+{
+ [Serializable]
+ public class BuildEventContext
+ {
+ static readonly Random rnd = new Random ();
+
+ public static BuildEventContext Invalid = new BuildEventContext (
+ InvalidSubmissionId,
+ InvalidNodeId,
+ InvalidProjectInstanceId,
+ InvalidTargetId,
+ InvalidProjectContextId,
+ InvalidTaskId);
+
+ internal static BuildEventContext NewInstance ()
+ {
+ return new BuildEventContext (rnd.Next (), rnd.Next (), rnd.Next (), rnd.Next ());
+ }
+
+ public BuildEventContext (int nodeId, int targetId, int projectContextId, int taskId)
+ : this (nodeId, rnd.Next (), targetId, projectContextId, taskId)
+ {
+ }
+
+ public BuildEventContext (int nodeId, int projectInstanceId, int targetId, int projectContextId, int taskId)
+ : this (rnd.Next (), nodeId, projectInstanceId, targetId, projectContextId, taskId)
+ {
+ }
+
+ public BuildEventContext (int submissionId, int nodeId, int projectInstanceId, int targetId, int projectContextId, int taskId)
+ {
+ SubmissionId = submissionId;
+ NodeId = nodeId;
+ ProjectInstanceId = projectInstanceId;
+ TargetId = targetId;
+ ProjectContextId = projectContextId;
+ TaskId = taskId;
+ }
+
+ public const int InvalidSubmissionId = -1;
+ public const int InvalidNodeId = -2;
+ public const int InvalidProjectInstanceId = -1;
+ public const int InvalidTargetId = -1;
+ public const int InvalidProjectContextId = -2;
+ public const int InvalidTaskId = -1;
+
+ public int SubmissionId { get; private set; }
+ public int NodeId { get; private set; }
+ public int ProjectInstanceId { get; private set; }
+ public int TargetId { get; private set; }
+ public int ProjectContextId { get; private set; }
+ public int TaskId { get; private set; }
+
+ // MSDN document says "true if the references are equal, false otherwise." but that doesn't make sense.
+ public override bool Equals (object other)
+ {
+ var o = other as BuildEventContext;
+ return (object) o != null &&
+ o.NodeId == NodeId &&
+ o.ProjectContextId == ProjectContextId &&
+ o.ProjectInstanceId == ProjectInstanceId &&
+ o.SubmissionId == SubmissionId &&
+ o.TargetId == TargetId &&
+ o.TaskId == TaskId;
+ }
+
+ public override int GetHashCode ()
+ {
+ return
+ (NodeId << 5) +
+ (ProjectContextId << 4) +
+ (ProjectInstanceId << 3) +
+ (SubmissionId << 2) +
+ (TargetId << 1) +
+ TaskId;
+ }
+
+ public static bool operator == (BuildEventContext left, BuildEventContext right)
+ {
+ return (object) left == null ? (object)right == null : left.Equals (right);
+ }
+
+ public static bool operator != (BuildEventContext left, BuildEventContext right)
+ {
+ return (object) left == null ? (object)right != null : !left.Equals (right);
+ }
+ }
+}
+
+
--- /dev/null
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Microsoft.Build.Framework
+{
+ [MonoTODO]
+ public interface IBuildEngine3 : IBuildEngine2
+ {
+ BuildEngineResult BuildProjectFilesInParallel (
+ string[] projectFileNames,
+ string[] targetNames,
+ IDictionary[] globalProperties,
+ IList<string>[] removeGlobalProperties,
+ string[] toolsVersion,
+ bool returnTargetOutputs
+ );
+ void Reacquire ();
+ void Yield ();
+ }
+}
+
--- /dev/null
+#if NET_4_5
+using System;
+
+namespace Microsoft.Build.Framework
+{
+ [MonoTODO]
+ public interface IBuildEngine4 : IBuildEngine3
+ {
+ object GetRegisteredTaskObject (object key, RegisteredTaskObjectLifetime lifetime);
+ void RegisterTaskObject (object key, object obj, RegisteredTaskObjectLifetime lifetime, bool allowEarlyCollection);
+ object UnregisterTaskObject (object key, RegisteredTaskObjectLifetime lifetime);
+ }
+}
+
+#endif
--- /dev/null
+using System;
+
+namespace Microsoft.Build.Framework
+{
+ public interface IEventRedirector
+ {
+ void ForwardEvent (BuildEventArgs buildEvent);
+ }
+}
+
--- /dev/null
+using System;
+
+#if NET_4_0
+
+namespace Microsoft.Build.Framework
+{
+ public interface IForwardingLogger : INodeLogger, ILogger
+ {
+ IEventRedirector BuildEventRedirector { get; set; }
+ int NodeId { get; set; }
+ }
+}
+
+#endif
+
--- /dev/null
+using System;
+using System.Collections.Generic;
+
+namespace Microsoft.Build.Framework
+{
+ public interface ITaskFactory
+ {
+ string FactoryName { get; }
+ Type TaskType { get; }
+ void CleanupTask (ITask task);
+ ITask CreateTask (IBuildEngine taskFactoryLoggingHost);
+ TaskPropertyInfo [] GetTaskParameters ();
+ bool Initialize (string taskName, IDictionary<string, TaskPropertyInfo> parameterGroup, string taskBody, IBuildEngine taskFactoryLoggingHost);
+ }
+}
+
--- /dev/null
+using System;
+using System.Collections.Generic;
+
+namespace Microsoft.Build.Framework
+{
+ public interface ITaskFactory2 : ITaskFactory
+ {
+ ITask CreateTask (IBuildEngine taskFactoryLoggingHost, IDictionary<string, string> taskIdentityParameters);
+ bool Initialize (string taskName, IDictionary<string, string> factoryIdentityParameters, IDictionary<string, TaskPropertyInfo> parameterGroup, string taskBody, IBuildEngine taskFactoryLoggingHost);
+ }
+}
+
--- /dev/null
+#if NET_4_5
+namespace Microsoft.Build.Framework
+{
+ public enum RegisteredTaskObjectLifetime
+ {
+ AppDomain,
+ Build
+ }
+}
+#endif
+
--- /dev/null
+using System;
+using System.Collections.Generic;
+
+namespace Microsoft.Build.Framework
+{
+ [Serializable]
+ public class TaskPropertyInfo
+ {
+ public TaskPropertyInfo (string name, Type typeOfParameter, bool output, bool required)
+ {
+ Name = name;
+ PropertyType = typeOfParameter;
+ Output = output;
+ Required = required;
+ }
+
+ public string Name { get; private set; }
+ public bool Output { get; private set; }
+ public Type PropertyType { get; private set; }
+ public bool Required { get; private set; }
+ }
+}
+
Microsoft.Build.Framework/BuildErrorEventArgsTest.cs
Microsoft.Build.Framework/BuildEventArgsTest.cs
+Microsoft.Build.Framework/BuildEventContextTest.cs
Microsoft.Build.Framework/BuildFinishedEventArgsTest.cs
Microsoft.Build.Framework/BuildMessageEventArgsTest.cs
Microsoft.Build.Framework/BuildStartedEventArgsTest.cs
--- /dev/null
+using System;
+using Microsoft.Build.Framework;
+using NUnit.Framework;
+
+namespace MonoTests.Microsoft.Build.Framework
+{
+ [TestFixture]
+ public class BuildEventContextTest
+ {
+ [Test]
+ public void Compare ()
+ {
+ Assert.IsTrue (BuildEventContext.Invalid == BuildEventContext.Invalid, "#1");
+ Assert.IsFalse (BuildEventContext.Invalid != BuildEventContext.Invalid, "#2");
+ var inst = new BuildEventContext (0, 0, 0, 0);
+ Assert.IsFalse (BuildEventContext.Invalid == inst, "#3");
+ Assert.IsTrue (BuildEventContext.Invalid != inst, "#4");
+ Assert.IsFalse (BuildEventContext.Invalid == null, "#5");
+ Assert.IsTrue (BuildEventContext.Invalid != null, "#6");
+ Assert.IsFalse (BuildEventContext.Invalid.Equals (null), "#7");
+ Assert.IsFalse (BuildEventContext.Invalid.Equals (inst), "#8");
+ Assert.IsTrue (BuildEventContext.Invalid.Equals (BuildEventContext.Invalid), "#9");
+ Assert.IsFalse (inst.Equals (null), "#10");
+ Assert.IsTrue (inst.Equals (inst), "#11");
+ Assert.IsFalse (inst.Equals (BuildEventContext.Invalid), "#12");
+ }
+ }
+}
+
CheckLoggedMessageAny (testLogger, "Number: 2 Color: Red-- Items in ExampColl: ExampColl2: Item5", "A3");
CheckLoggedMessageAny (testLogger, "Number: 3 Color: Green-- Items in ExampColl: ExampColl2: Item6", "A4");
CheckLoggedMessageAny (testLogger, "Number: 2 Color: -- Items in ExampColl: Item2 ExampColl2: ", "A5");
- Assert.AreEqual (0, testLogger.Count, "A6");
+ Assert.AreEqual (0, testLogger.NormalMessageCount, "A6");
+ Assert.AreEqual (0, testLogger.WarningMessageCount, "A7");
CheckEngineEventCounts (testLogger, 1, 1, 4, 4);
}
CheckLoggedMessageAny (testLogger, "Identity: Item4 -- Items in ExampColl: Item4;Item4", "A5");
CheckLoggedMessageAny (testLogger, "Identity: Item5 -- Items in ExampColl: Item5", "A6");
CheckLoggedMessageAny (testLogger, "Identity: Item6 -- Items in ExampColl: Item6", "A7");
- Assert.AreEqual (0, testLogger.Count, "A8");
+ Assert.AreEqual (0, testLogger.NormalMessageCount, "A8");
+ Assert.AreEqual (0, testLogger.WarningMessageCount, "A7");
CheckEngineEventCounts (testLogger, 1, 1, 6, 6);
}
}
}
+ public int WarningMessageCount {
+ get {
+ int count = 0, i = 0;
+ while (i++ < messages.Count) {
+ var importance = messages [i - 1].Importance;
+ if (importance == MessageImportance.High)
+ count++;
+ }
+ return count;
+ }
+ }
+
public int CheckHead (string text, MessageImportance importance)
{
string actual_msg;
{
// If changing something here then update
// ToolLocationHelper.GetPathToDotNetFramework also
- public enum TargetDotNetFrameworkVersion
+ #if MICROSOFT_BUILD_DLL
+ internal
+ #else
+ public
+ #endif
+ enum TargetDotNetFrameworkVersion
{
Version11,
Version20,
namespace Microsoft.Build.Utilities
{
- public sealed class TaskItem : MarshalByRefObject, ITaskItem
+#if !MICROSOFT_BUILD_DLL
+ public
+#endif
+ sealed class TaskItem : MarshalByRefObject, ITaskItem
{
IDictionary metadata;
string itemSpec;
namespace Microsoft.Build.Utilities
{
- public static class ToolLocationHelper
+ #if MICROSOFT_BUILD_DLL
+ internal
+ #else
+ public
+ #endif
+ static class ToolLocationHelper
{
static string lib_mono_dir;
static string [] mono_dir;
*.vs10x
*.docstates
*.suo
+Microsoft.Build.Internal/ExpressionParser.cs
/r:System.Core.dll \
/r:System.Xml.dll \
/r:Microsoft.Build.Engine.dll \
- /r:Microsoft.Build.Framework.dll
+ /r:Microsoft.Build.Framework.dll \
+ /d:MICROSOFT_BUILD_DLL
-TEST_MCS_FLAGS = /r:System.Core.dll \
- /r:Microsoft.Build.Engine.dll \
- /r:Microsoft.Build.Framework.dll
+TEST_MCS_FLAGS = $(LIB_MCS_FLAGS)
EXTRA_DISTFILES = \
+ Microsoft.Build.Internal/ExpressionParser.jay \
Test/FunctionalTestReferenceProject.csproj \
Test/FunctionalTestReferenceProject3.csproj \
Test/Microsoft.Build.Test.csproj \
Test/Microsoft.Build.csproj
+EXPR_PARSER = Microsoft.Build.Internal/ExpressionParser
+
+$(EXPR_PARSER).cs: $(EXPR_PARSER).jay $(topdir)/jay/skeleton.cs
+ (cd Microsoft.Build.Internal; $(topdir)/../jay/jay -ctv < $(topdir)/../jay/skeleton.cs ExpressionParser.jay > ExpressionParser.cs)
+
+BUILT_SOURCES = $(EXPR_PARSER).cs
+
include ../../build/library.make
export TESTING_MONO=a
XBUILD_DIR=../../tools/xbuild
+XBUILD_FRAMEWORK_FOLDERS_PATH=xbuild-testing
include $(XBUILD_DIR)/xbuild_targets.make
//
-// ProjectItemDefinitionInstance.cs
+// ElementLocation.cs
//
// Author:
-// Atsushi Enomoto (atsushi@veritas-vos-liberabit.com)
+// Atsushi Enomoto (atsushi@xamarin.com)
//
-// Copyright (C) 2012 Xamarin Inc.
+// Copyright (C) 2013 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_4_5
using Microsoft.Build.Framework;
using System;
namespace Microsoft.Build.Construction
{
[Serializable]
- public abstract class ElementLocation
+#if NET_4_5
+ public
+#endif
+ abstract class ElementLocation
{
public abstract int Column { get; }
public abstract string File { get; }
public string LocationString {
get { return Line == 0 ? File : String.Format ("{0} ({1}{2})", File, Line, Column != 0 ? "," + Column : String.Empty); }
}
+
+ public override bool Equals (object other)
+ {
+ var o = other as ElementLocation;
+ return (object) o != null && o.File == File && o.Line == Line && o.Column == Column;
+ }
+
+ public override int GetHashCode ()
+ {
+ return (File.GetHashCode () << 16) + (Line << 8) + Column;
+ }
}
}
-
-#endif
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Xml;
using Microsoft.Build.Exceptions;
using Microsoft.Build.Internal;
internal override string XmlName {
get { return "Choose"; }
}
- internal override ProjectElement LoadChildElement (string name)
+ internal override ProjectElement LoadChildElement (XmlReader reader)
{
+ var name = reader.LocalName;
switch (name) {
case "Otherwise":
var other = ContainingProject.CreateOtherwiseElement ();
internal override void Load (XmlReader reader)
{
+ FillLocation (reader);
LoadValue (reader);
}
{
public abstract class ProjectElement
{
+ internal const string MSBuildNamespace = "http://schemas.microsoft.com/developer/msbuild/2003";
+
internal ProjectElement ()
{
linkedListNode = new LinkedListNode<ProjectElement> (this);
internal virtual void Load (XmlReader reader)
{
reader.ReadToFollowing (XmlName);
+ FillLocation (reader);
while (reader.MoveToNextAttribute ()) {
LoadAttribute (reader.Name, reader.Value);
}
+ reader.MoveToElement ();
LoadValue (reader);
}
internal virtual void LoadAttribute (string name, string value)
Condition = value;
break;
default:
- throw new InvalidProjectFileException (string.Format (
+ throw new InvalidProjectFileException (Location, null, string.Format (
"Attribute \"{0}\" is not known on node \"{1}\" [type {2}].", name, XmlName,
GetType ()));
}
if (!string.IsNullOrWhiteSpace (attributeValue))
writer.WriteAttributeString (attributeName, attributeValue);
}
+
+#if NET_4_5
+ public ElementLocation Location { get; private set; }
+ public ElementLocation LabelLocation { get; private set; }
+ public ElementLocation ConditionLocation { get; private set; }
+#else
+ internal ElementLocation Location { get; private set; }
+ internal ElementLocation LabelLocation { get; private set; }
+ internal ElementLocation ConditionLocation { get; private set; }
+#endif
+
+ internal void FillLocation (XmlReader reader)
+ {
+ var l = reader as IXmlLineInfo;
+ if (l != null && l.HasLineInfo ())
+ Location = new ProjectElementLocation (reader.BaseURI, l);
+ if (reader.MoveToAttribute ("Condition") && l.HasLineInfo ())
+ ConditionLocation = new ProjectElementLocation (reader.BaseURI, l);
+ if (reader.MoveToAttribute ("Label") && l.HasLineInfo ())
+ LabelLocation = new ProjectElementLocation (reader.BaseURI, l);
+ reader.MoveToElement ();
+ }
+
+ class ProjectElementLocation : ElementLocation
+ {
+ public ProjectElementLocation (string file, IXmlLineInfo li)
+ {
+ this.file = file;
+ this.line = li.LineNumber;
+ this.column = li.LinePosition;
+ }
+
+ string file;
+ int line;
+ int column;
+
+ public override string File { get { return file; } }
+ public override int Line { get { return line; } }
+ public override int Column { get { return column; } }
+ }
+
+ internal InvalidProjectFileException CreateError (XmlReader reader, string message, int columnOffset = 0)
+ {
+ var li = reader as IXmlLineInfo;
+ bool valid = li != null && li.HasLineInfo ();
+ throw new InvalidProjectFileException (reader.BaseURI, valid ? li.LineNumber : 0, valid ? li.LinePosition + columnOffset : 0, 0, 0, message, null, null, null);
+ }
}
}
using System.Collections.Generic;
using System.Linq;
using System.Xml;
+using Microsoft.Build.Exceptions;
using Microsoft.Build.Internal;
namespace Microsoft.Build.Construction
child.Save (writer);
}
+ internal override void Load (XmlReader reader)
+ {
+ reader.Read ();
+ reader.MoveToContent ();
+ FillLocation (reader);
+ if (reader.LocalName != XmlName || reader.NamespaceURI != MSBuildNamespace)
+ throw CreateError (reader, string.Format ("Unexpected XML {0} \"{1}\" in namespace \"{2}\" appeared, while \"{3}\" in namespace \"{4}\" is expected.",
+ reader.NodeType, reader.LocalName, reader.NamespaceURI, XmlName, MSBuildNamespace), -1);
+ while (reader.MoveToNextAttribute ()) {
+ LoadAttribute (reader.Name, reader.Value);
+ }
+ LoadValue (reader);
+ }
+
internal override void LoadValue (XmlReader reader)
{
while (reader.Read ()) {
if (reader.NodeType == XmlNodeType.Element) {
- var child = LoadChildElement (reader.Name);
+ var child = LoadChildElement (reader);
child.Load (reader.ReadSubtree ());
} else if (reader.NodeType == XmlNodeType.Comment) {
var commentElement = new ProjectCommentElement (ContainingProject);
}
}
- internal abstract ProjectElement LoadChildElement (string name);
+ internal abstract ProjectElement LoadChildElement (XmlReader reader);
}
}
{
while (reader.Read () && reader.NodeType != XmlNodeType.Element)
;
+ FillLocation (reader);
using (XmlReader subReader = reader.ReadSubtree ()) {
document = new XmlDocument ();
document.Load (subReader);
using System;
using System.Xml;
+using Microsoft.Build.Exceptions;
+
+
namespace Microsoft.Build.Construction
{
[System.Diagnostics.DebuggerDisplayAttribute ("Project={Project} Condition={Condition}")]
SaveAttribute (writer, "Project", Project);
base.SaveValue (writer);
}
+
+ internal override void LoadValue (XmlReader reader)
+ {
+ if (string.IsNullOrWhiteSpace (Project))
+ throw new InvalidProjectFileException (Location, null, "Project attribute is null or empty on an Import element");
+ base.LoadValue (reader);
+ }
internal override void LoadAttribute (string name, string value)
{
using System;
using System.Collections.Generic;
using Microsoft.Build.Internal;
+using System.Xml;
namespace Microsoft.Build.Construction
{
return import;
}
internal override string XmlName { get { return "ImportGroup"; } }
- internal override ProjectElement LoadChildElement (string name)
+ internal override ProjectElement LoadChildElement (XmlReader reader)
{
return AddImport (null);
}
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Xml;
using Microsoft.Build.Internal;
namespace Microsoft.Build.Construction
internal override string XmlName {
get { return ItemType; }
}
- internal override ProjectElement LoadChildElement (string name)
+ internal override ProjectElement LoadChildElement (XmlReader reader)
{
- return AddMetadata (name, null);
+ return AddMetadata (reader.LocalName, null);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Xml;
using Microsoft.Build.Internal;
namespace Microsoft.Build.Construction
internal override string XmlName {
get { return "ItemDefinitionGroup"; }
}
- internal override ProjectElement LoadChildElement (string name)
+ internal override ProjectElement LoadChildElement (XmlReader reader)
{
- return AddItemDefinition (name);
+ return AddItemDefinition (reader.LocalName);
}
}
}
using System.Linq;
using Microsoft.Build.Internal;
using System.Xml;
+using Microsoft.Build.Exceptions;
namespace Microsoft.Build.Construction
{
}
string @remove;
public string Remove { get { return @remove ?? String.Empty; } set { @remove = value; } }
+ #if NET_4_5
+ string keepDuplicates;
+ public string KeepDuplicates { get { return keepDuplicates ?? String.Empty; } set { keepDuplicates = value; } }
+ string keepMetadata;
+ public string KeepMetadata { get { return keepMetadata ?? String.Empty; } set { keepMetadata = value; } }
+ string removeMetadata;
+ public string RemoveMetadata { get { return removeMetadata ?? String.Empty; } set { removeMetadata = value; } }
+ #endif
public ProjectMetadataElement AddMetadata (string name, string unevaluatedValue)
{
var metadata = ContainingProject.CreateMetadataElement (name, unevaluatedValue);
{
SaveAttribute (writer, "Include", Include);
SaveAttribute (writer, "Exclude", Exclude);
+#if NET_4_5
+ SaveAttribute (writer, "KeepDuplicates", KeepDuplicates);
+ SaveAttribute (writer, "KeepMetadata", KeepMetadata);
+ SaveAttribute (writer, "RemoveMetadata", RemoveMetadata);
+#endif
SaveAttribute (writer, "Remove", Remove);
base.SaveValue (writer);
}
+
internal override void LoadAttribute (string name, string value)
{
switch (name) {
case "Exclude":
Exclude = value;
break;
+#if NET_4_5
+ case "KeepDuplicates":
+ KeepDuplicates = value;
+ break;
+ case "KeepMetadata":
+ KeepMetadata = value;
+ break;
+ case "RemoveMetadata":
+ RemoveMetadata = value;
+ break;
+#endif
case "Remove":
Remove = value;
break;
break;
}
}
- internal override ProjectElement LoadChildElement (string name)
+ internal override void LoadValue (XmlReader reader)
+ {
+ if (string.IsNullOrWhiteSpace (Include) && string.IsNullOrEmpty (Remove))
+ throw new InvalidProjectFileException (Location, null, string.Format ("Both Include and Remove attribute are null or empty on '{0}' item", ItemType));
+ base.LoadValue (reader);
+ }
+ internal override ProjectElement LoadChildElement (XmlReader reader)
{
- var metadata = ContainingProject.CreateMetadataElement (name);
+ var metadata = ContainingProject.CreateMetadataElement (reader.LocalName);
AppendChild (metadata);
return metadata;
}
+#if NET_4_5
+ public ElementLocation ExcludeLocation { get; private set; }
+ public ElementLocation IncludeLocation { get; private set; }
+ public ElementLocation KeepDuplicatesLocation { get; private set; }
+ public ElementLocation RemoveLocation { get; private set; }
+ public ElementLocation RemoveMetadataLocation { get; private set; }
+#else
+ ElementLocation ExcludeLocation { get; set; }
+ ElementLocation IncludeLocation { get; set; }
+ ElementLocation KeepDuplicatesLocation { get; set; }
+ ElementLocation RemoveLocation { get; set; }
+ ElementLocation RemoveMetadataLocation { get; set; }
+#endif
}
}
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
+using System;
using System.Collections.Generic;
using System.Linq;
+using System.Xml;
using Microsoft.Build.Internal;
-using System;
namespace Microsoft.Build.Construction
{
get { return "ItemGroup"; }
}
- internal override ProjectElement LoadChildElement (string name)
+ internal override ProjectElement LoadChildElement (XmlReader reader)
{
- var item = ContainingProject.CreateItemElement (name);
+ var item = ContainingProject.CreateItemElement (reader.LocalName);
AppendChild (item);
return item;
}
break;
}
}
+
+ #if NET_4_5
+ public
+ #endif
+ ElementLocation ExecuteTargetsAttributeLocation { get; set; }
}
}
using System.Collections.Generic;
using System;
using System.Linq;
+using System.Xml;
using Microsoft.Build.Exceptions;
using Microsoft.Build.Internal;
internal override string XmlName {
get { return "Otherwise"; }
}
- internal override ProjectElement LoadChildElement (string name)
+ internal override ProjectElement LoadChildElement (XmlReader reader)
{
- switch (name) {
+ switch (reader.LocalName) {
case "PropertyGroup":
var property = ContainingProject.CreatePropertyGroupElement ();
AppendChild (property);
return when;
default:
throw new InvalidProjectFileException (string.Format (
- "Child \"{0}\" is not a known node type.", name));
+ "Child \"{0}\" is not a known node type.", reader.LocalName));
}
}
}
get { return taskParameter ?? String.Empty; }
set { taskParameter = value; }
}
+ #if NET_4_5
+ ElementLocation taskParameterLocation;
+ public ElementLocation TaskParameterLocation {
+ get { return taskParameterLocation; }
+ set { taskParameterLocation = value; }
+ }
+ #endif
internal override string XmlName {
get { return "Output"; }
}
get { return "PropertyGroup"; }
}
- internal override ProjectElement LoadChildElement (string name)
+ internal override ProjectElement LoadChildElement (XmlReader reader)
{
- return AddProperty (name, null);
+ switch (reader.LocalName) {
+ case "ItemGroup":
+ case "PropertyGroup":
+ throw CreateError (reader, string.Format ("{0} is a reserved name that cannot be used for a property.", reader.LocalName));
+ // others need to be checked too, but things like "Project" are somehow allowed...
+ }
+ return AddProperty (reader.LocalName, null);
}
}
}
string directoryPath;
public string DirectoryPath {
- get { return directoryPath ?? String.Empty; }
- internal set { directoryPath = value; }
+ get { return directoryPath ?? Directory.GetCurrentDirectory (); }
+ set { directoryPath = value; }
}
public ICollection<ProjectPropertyElement> Properties {
string toolsVersion;
public string ToolsVersion {
- get { return toolsVersion ?? "4.0"; }
+ get { return toolsVersion ?? string.Empty; }
set { toolsVersion = value; }
}
ProjectRootElement (ProjectCollection projectCollection)
{
+ ToolsVersion = "4.0";
}
public static ProjectRootElement Create ()
public static ProjectRootElement Create (XmlReader xmlReader, ProjectCollection projectCollection)
{
- // yes, this should create en empty project
var result = Create (projectCollection);
+ result.ToolsVersion = null;
+ result.Load (xmlReader);
return result;
}
public void Save ()
{
+ if (FullPath == null)
+ throw new InvalidOperationException ("This project was not given the file path to write to.");
Save (Encoding);
}
}
}
- internal override ProjectElement LoadChildElement (string name)
+ internal override ProjectElement LoadChildElement (XmlReader reader)
{
- switch (name) {
+ switch (reader.LocalName) {
case "PropertyGroup":
var prop = CreatePropertyGroupElement ();
AppendChild (prop);
AppendChild (def);
return def;
case "UsingTask":
- return AddUsingTask (null, null, null);
+ var ut = AddUsingTask (null, null, null);
+ return ut;
case "Choose":
var choose = CreateChooseElement ();
AppendChild (choose);
AppendChild (ext);
return ext;
default:
- throw new InvalidProjectFileException (string.Format (
- "Child \"{0}\" is not a known node type.", name));
+ throw CreateError (reader, string.Format ("Child \"{0}\" is not a known node type.", reader.LocalName), -1);
}
}
internal override void Save (XmlWriter writer)
{
- writer.WriteStartElement (XmlName, "http://schemas.microsoft.com/developer/msbuild/2003");
+ writer.WriteStartElement (XmlName, MSBuildNamespace);
SaveValue (writer);
writer.WriteEndElement ();
}
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Xml;
using Microsoft.Build.Internal;
namespace Microsoft.Build.Construction
get { return "Target"; }
}
- internal override ProjectElement LoadChildElement (string name)
+#if NET_4_5
+ public ElementLocation AfterTargetsLocation { get; private set; }
+ public ElementLocation BeforeTargetsLocation { get; private set; }
+ public ElementLocation DependsOnTargetsLocation { get; private set; }
+ public ElementLocation InputsLocation { get; private set; }
+ public ElementLocation KeepDuplicateOutputsLocation { get; private set; }
+ public ElementLocation NameLocation { get; private set; }
+ public ElementLocation OutputsLocation { get; private set; }
+ public ElementLocation ReturnsLocation { get; private set; }
+#else
+ internal ElementLocation AfterTargetsLocation { get; set; }
+ internal ElementLocation BeforeTargetsLocation { get; set; }
+ internal ElementLocation DependsOnTargetsLocation { get; set; }
+ internal ElementLocation InputsLocation { get; set; }
+ internal ElementLocation KeepDuplicateOutputsLocation { get; set; }
+ internal ElementLocation LabelLocation { get; set; }
+ internal ElementLocation NameLocation { get; set; }
+ internal ElementLocation OutputsLocation { get; set; }
+ internal ElementLocation ReturnsLocation { get; set; }
+#endif
+
+ internal override ProjectElement LoadChildElement (XmlReader reader)
{
- switch (name) {
+ switch (reader.LocalName) {
case "OnError":
var error = new ProjectOnErrorElement (ContainingProject);
AppendChild (error);
case "ItemGroup":
return AddItemGroup ();
default:
- return AddTask (name);
+ return AddTask (reader.LocalName);
}
}
+ // This seriously needs to change to become able to fill ElementLocation...
internal override void LoadAttribute (string name, string value)
{
switch (name) {
internal override string XmlName {
get { return Name; }
}
- internal override ProjectElement LoadChildElement (string name)
+ internal override ProjectElement LoadChildElement (XmlReader reader)
{
- switch (name) {
+ switch (reader.LocalName) {
case "Output":
var output = ContainingProject.CreateOutputElement (null, null, null);
AppendChild (output);
return output;
default:
throw new InvalidProjectFileException (string.Format (
- "Child \"{0}\" is not a known node type.", name));
+ "Child \"{0}\" is not a known node type.", reader.LocalName));
}
}
internal override void LoadAttribute (string name, string value)
case "ContinueOnError":
ContinueOnError = value;
break;
+#if NET_4_5
+ case "ExecuteTargets":
+ ExecuteTargets = value;
+ break;
+ case "MSBuildArchitecture":
+ MSBuildArchitecture = value;
+ break;
+ case "MSBuildRuntime":
+ MSBuildRuntime = value;
+ break;
+#endif
case "xmlns":
break;
case "Label":
base.SaveValue (writer);
}
private Dictionary<string, string> parameters = new Dictionary<string, string> ();
+
+ public string ExecuteTargets { get; set; }
+ #if NET_4_5
+ public ElementLocation ExecuteTargetsLocation { get; set; }
+ public ElementLocation ContinueOnErrorLocation { get; set; }
+ public string MSBuildArchitecture { get; set; }
+ public ElementLocation MSBuildArchitectureLocation { get; set; }
+ public string MSBuildRuntime { get; set; }
+ public ElementLocation MSBuildRuntimeLocation { get; set; }
+ #endif
}
}
}
internal override void LoadValue (XmlReader reader)
{
- reader.MoveToElement ();
TaskBody = reader.ReadInnerXml ();
}
}
//
using System;
+using System.Xml;
using Microsoft.Build.Exceptions;
namespace Microsoft.Build.Construction
internal override string XmlName {
get { return "UsingTask"; }
}
- internal override ProjectElement LoadChildElement (string name)
+ internal override ProjectElement LoadChildElement (XmlReader reader)
{
- switch (name) {
+ switch (reader.LocalName) {
case "ParameterGroup":
return AddParameterGroup ();
case "Task":
return AddUsingTaskBody (null, null);
default:
throw new InvalidProjectFileException (string.Format (
- "Child \"{0}\" is not a known node type.", name));
+ "Child \"{0}\" is not a known node type.", reader.LocalName));
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Xml;
using Microsoft.Build.Exceptions;
using Microsoft.Build.Internal;
internal override string XmlName {
get { return "When"; }
}
- internal override ProjectElement LoadChildElement (string name)
+ internal override ProjectElement LoadChildElement (XmlReader reader)
{
- switch (name) {
+ switch (reader.LocalName) {
case "PropertyGroup":
var property = ContainingProject.CreatePropertyGroupElement ();
AppendChild (property);
return when;
default:
throw new InvalidProjectFileException (string.Format (
- "Child \"{0}\" is not a known node type.", name));
+ "Child \"{0}\" is not a known node type.", reader.LocalName));
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Xml;
using Microsoft.Build.Internal;
namespace Microsoft.Build.Construction
internal override string XmlName {
get { return "ParameterGroup"; }
}
- internal override ProjectElement LoadChildElement (string name)
+ internal override ProjectElement LoadChildElement (XmlReader reader)
{
- return AddParameter (name);
+ return AddParameter (reader.LocalName);
}
}
}
// Author:
// Leszek Ciesielski (skolima@gmail.com)
// Rolf Bjarne Kvinge (rolf@xamarin.com)
+// Atsushi Enomoto (atsushi@xamarin.com)
//
// (C) 2011 Leszek Ciesielski
-// Copyright (C) 2011 Xamarin Inc. (http://www.xamarin.com)
+// Copyright (C) 2011,2013 Xamarin Inc. (http://www.xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
using System.Text;
using System.Xml;
using Microsoft.Build.Construction;
-using Microsoft.Build.Internal;
+using Microsoft.Build.Exceptions;
using Microsoft.Build.Execution;
using Microsoft.Build.Framework;
+using Microsoft.Build.Internal;
+using Microsoft.Build.Internal.Expressions;
using Microsoft.Build.Logging;
+using System.Collections;
+
+// Basically there are two semantic Project object models and their relationship is not obvious
+// (apart from Microsoft.Build.Construction.ProjectRootElement which is a "construction rule").
+//
+// Microsoft.Build.Evaluation.Project holds some "editable" project model, and it supports
+// detailed loader API (such as Items and AllEvaluatedItems).
+// ProjectPoperty holds UnevaluatedValue and gives EvaluatedValue too.
+//
+// Microsoft.Build.Execution.ProjectInstance holds "snapshot" of a project, and it lacks
+// detailed loader API. It does not give us Unevaluated property value.
+// On the other hand, it supports Targets object model. What Microsoft.Build.Evaluation.Project
+// offers there is actually a list of Microsoft.Build.Execution.ProjectInstance objects.
+// It should be also noted that only ProjectInstance has Evaluate() method (Project doesn't).
+//
+// And both API holds different set of descendant types for each and cannot really share the
+// loader code. That is lame.
+//
+// So, can either of them be used to construct the other model? Both API models share the same
+// "governor", which is Microsoft.Build.Evaluation.ProjectCollection/ Project is added to
+// its LoadedProjects list, while ProjectInstance isn't. Project cannot be loaded to load
+// a ProjectInstance, at least within the same ProjectCollection.
+//
+// On the other hand, can ProjectInstance be used to load a Project? Maybe. Since Project and
+// its descendants need Microsoft.Build.Construction.ProjectElement family as its API model
+// is part of the public API. Then I still have to understand how those AllEvaluatedItems/
+// AllEvaluatedProperties members make sense. EvaluationCounter is another propery in question.
namespace Microsoft.Build.Evaluation
{
- [DebuggerDisplay("{FullPath} EffectiveToolsVersion={ToolsVersion} #GlobalProperties="
- +"{data.globalProperties.Count} #Properties={data.Properties.Count} #ItemTypes="
- +"{data.ItemTypes.Count} #ItemDefinitions={data.ItemDefinitions.Count} #Items="
- +"{data.Items.Count} #Targets={data.Targets.Count}")]
- public class Project
- {
+ [DebuggerDisplay ("{FullPath} EffectiveToolsVersion={ToolsVersion} #GlobalProperties="
+ + "{data.globalProperties.Count} #Properties={data.Properties.Count} #ItemTypes="
+ + "{data.ItemTypes.Count} #ItemDefinitions={data.ItemDefinitions.Count} #Items="
+ + "{data.Items.Count} #Targets={data.Targets.Count}")]
+ public class Project
+ {
public Project (XmlReader xml)
: this (ProjectRootElement.Create (xml))
{
}
- public Project (XmlReader xml, IDictionary<string, string> globalProperties,
- string toolsVersion)
+
+ public Project (XmlReader xml, IDictionary<string, string> globalProperties,
+ string toolsVersion)
: this (ProjectRootElement.Create (xml), globalProperties, toolsVersion)
{
}
- public Project (XmlReader xml, IDictionary<string, string> globalProperties,
- string toolsVersion, ProjectCollection projectCollection)
+
+ public Project (XmlReader xml, IDictionary<string, string> globalProperties,
+ string toolsVersion, ProjectCollection projectCollection)
: this (ProjectRootElement.Create (xml), globalProperties, toolsVersion, projectCollection)
{
}
- public Project (XmlReader xml, IDictionary<string, string> globalProperties,
- string toolsVersion, ProjectCollection projectCollection,
- ProjectLoadSettings loadSettings)
+
+ public Project (XmlReader xml, IDictionary<string, string> globalProperties,
+ string toolsVersion, ProjectCollection projectCollection,
+ ProjectLoadSettings loadSettings)
: this (ProjectRootElement.Create (xml), globalProperties, toolsVersion, projectCollection, loadSettings)
{
}
- public Project (ProjectRootElement xml) : this(xml, null, null)
- {
- }
- public Project (ProjectRootElement xml, IDictionary<string, string> globalProperties,
- string toolsVersion)
- : this(xml, globalProperties, toolsVersion, ProjectCollection.GlobalProjectCollection)
- {
- }
- public Project (ProjectRootElement xml, IDictionary<string, string> globalProperties,
- string toolsVersion, ProjectCollection projectCollection)
- : this(xml, globalProperties, toolsVersion, projectCollection, ProjectLoadSettings.Default)
- {
- }
-
- public Project (ProjectRootElement xml, IDictionary<string, string> globalProperties,
- string toolsVersion, ProjectCollection projectCollection,
- ProjectLoadSettings loadSettings)
- {
- ProjectCollection = projectCollection;
- Xml = xml;
- GlobalProperties = globalProperties;
- ToolsVersion = toolsVersion;
- }
-
- public Project (string projectFile) : this(projectFile, null, null)
- {
- }
-
- public Project (string projectFile, IDictionary<string, string> globalProperties,
- string toolsVersion)
- : this(projectFile, globalProperties, toolsVersion, ProjectCollection.GlobalProjectCollection, ProjectLoadSettings.Default)
- {
- }
-
- public Project (string projectFile, IDictionary<string, string> globalProperties,
- string toolsVersion, ProjectCollection projectCollection)
- : this(projectFile, globalProperties, toolsVersion, projectCollection, ProjectLoadSettings.Default)
- {
- }
-
- public Project (string projectFile, IDictionary<string, string> globalProperties,
- string toolsVersion, ProjectCollection projectCollection,
- ProjectLoadSettings loadSettings)
- {
- throw new NotImplementedException ();
- }
-
- public IDictionary<string, string> GlobalProperties { get; private set; }
- public ProjectCollection ProjectCollection { get; private set; }
- public string ToolsVersion { get; private set; }
- public ProjectRootElement Xml { get; private set; }
-
- public ICollection<ProjectItem> GetItemsIgnoringCondition (string itemType)
- {
- return new CollectionFromEnumerable<ProjectItem> (
- new FilteredEnumerable<ProjectItemElement> (Xml.Items).
- Where (p => p.ItemType.Equals (itemType, StringComparison.OrdinalIgnoreCase)).
- Select (p => new ProjectItem(p)));
- }
- public void RemoveItems (IEnumerable<ProjectItem> items)
- {
- var removal = new List<ProjectItem> (items);
- foreach (var item in removal) {
- var parent = item.Xml.Parent;
- parent.RemoveChild (item.Xml);
- if (parent.Count == 0)
- parent.Parent.RemoveChild (parent);
- }
- }
-
- public IList<ProjectItem> AddItem (string itemType, string unevaluatedInclude)
- {
- throw new NotImplementedException ();
- }
-
- public IList<ProjectItem> AddItem (string itemType, string unevaluatedInclude,
- IEnumerable<KeyValuePair<string, string>> metadata)
- {
- throw new NotImplementedException ();
- }
-
- public IList<ProjectItem> AddItemFast (string itemType, string unevaluatedInclude)
- {
- throw new NotImplementedException ();
- }
-
- public IList<ProjectItem> AddItemFast (string itemType, string unevaluatedInclude,
- IEnumerable<KeyValuePair<string, string>> metadata)
- {
- throw new NotImplementedException ();
- }
-
- public bool Build ()
- {
- throw new NotImplementedException ();
- }
-
- public bool Build (IEnumerable<ILogger> loggers)
- {
- throw new NotImplementedException ();
- }
-
- public bool Build (string target)
- {
- throw new NotImplementedException ();
- }
-
- public bool Build (string[] targets)
- {
- throw new NotImplementedException ();
- }
-
- public bool Build (ILogger logger)
- {
- throw new NotImplementedException ();
- }
-
- public bool Build (string[] targets, IEnumerable<ILogger> loggers)
- {
- throw new NotImplementedException ();
- }
-
- public bool Build (IEnumerable<ILogger> loggers, IEnumerable<ForwardingLoggerRecord> remoteLoggers)
- {
- throw new NotImplementedException ();
- }
-
- public bool Build (string target, IEnumerable<ILogger> loggers)
- {
- throw new NotImplementedException ();
- }
-
- public bool Build (string[] targets, IEnumerable<ILogger> loggers, IEnumerable<ForwardingLoggerRecord> remoteLoggers)
- {
- throw new NotImplementedException ();
- }
-
- public bool Build (string target, IEnumerable<ILogger> loggers, IEnumerable<ForwardingLoggerRecord> remoteLoggers)
- {
- throw new NotImplementedException ();
- }
-
- public ProjectInstance CreateProjectInstance ()
- {
- throw new NotImplementedException ();
- }
-
- public string ExpandString (string unexpandedValue)
- {
- throw new NotImplementedException ();
- }
-
- public static string GetEvaluatedItemIncludeEscaped (ProjectItem item)
- {
- throw new NotImplementedException ();
- }
-
- public static string GetEvaluatedItemIncludeEscaped (ProjectItemDefinition item)
- {
- throw new NotImplementedException ();
- }
-
- public ICollection<ProjectItem> GetItems (string itemType)
- {
- throw new NotImplementedException ();
- }
-
- public ICollection<ProjectItem> GetItemsByEvaluatedInclude (string evaluatedInclude)
- {
- throw new NotImplementedException ();
- }
-
- public IEnumerable<ProjectElement> GetLogicalProject ()
- {
- throw new NotImplementedException ();
- }
-
- public static string GetMetadataValueEscaped (ProjectMetadata metadatum)
- {
- throw new NotImplementedException ();
- }
-
- public static string GetMetadataValueEscaped (ProjectItem item, string name)
- {
- throw new NotImplementedException ();
- }
-
- public static string GetMetadataValueEscaped (ProjectItemDefinition item, string name)
- {
- throw new NotImplementedException ();
- }
-
- public string GetPropertyValue (string name)
- {
- throw new NotImplementedException ();
- }
-
- public static string GetPropertyValueEscaped (ProjectProperty property)
- {
- throw new NotImplementedException ();
- }
-
- public ProjectProperty GetProperty (string name)
- {
- throw new NotImplementedException ();
- }
-
- public void MarkDirty ()
- {
- throw new NotImplementedException ();
- }
-
- public void ReevaluateIfNecessary ()
- {
- throw new NotImplementedException ();
- }
-
- public bool RemoveGlobalProperty (string name)
- {
- throw new NotImplementedException ();
- }
-
- public bool RemoveItem (ProjectItem item)
- {
- throw new NotImplementedException ();
- }
-
- public bool RemoveProperty (ProjectProperty property)
- {
- throw new NotImplementedException ();
- }
-
- public void Save ()
- {
- throw new NotImplementedException ();
- }
-
- public void Save (TextWriter writer)
- {
- throw new NotImplementedException ();
- }
-
- public void Save (string path)
- {
- throw new NotImplementedException ();
- }
-
- public void Save (Encoding encoding)
- {
- throw new NotImplementedException ();
- }
-
- public void Save (string path, Encoding encoding)
- {
- throw new NotImplementedException ();
- }
-
- public void SaveLogicalProject (TextWriter writer)
- {
- throw new NotImplementedException ();
- }
-
- public bool SetGlobalProperty (string name, string escapedValue)
- {
- throw new NotImplementedException ();
- }
-
- public ProjectProperty SetProperty (string name, string unevaluatedValue)
- {
- throw new NotImplementedException ();
- }
-
- public ICollection<ProjectMetadata> AllEvaluatedItemDefinitionMetadata {
- get { throw new NotImplementedException (); }
- }
-
- public ICollection<ProjectItem> AllEvaluatedItems {
- get { throw new NotImplementedException (); }
- }
-
- public ICollection<ProjectProperty> AllEvaluatedProperties {
- get { throw new NotImplementedException (); }
- }
-
- public IDictionary<string, List<string>> ConditionedProperties {
- get { throw new NotImplementedException (); }
- }
-
- public string DirectoryPath {
- get { throw new NotImplementedException (); }
- }
-
- public bool DisableMarkDirty { get; set; }
-
- public int EvaluationCounter {
- get { throw new NotImplementedException (); }
- }
-
- public string FullPath {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public IList<ResolvedImport> Imports {
- get { throw new NotImplementedException (); }
- }
-
- public IList<ResolvedImport> ImportsIncludingDuplicates {
- get { throw new NotImplementedException (); }
- }
-
- public bool IsBuildEnabled {
- get { throw new NotImplementedException (); }
- }
-
- public bool IsDirty {
- get { throw new NotImplementedException (); }
- }
-
- public IDictionary<string, ProjectItemDefinition> ItemDefinitions {
- get { throw new NotImplementedException (); }
- }
-
- public ICollection<ProjectItem> Items {
- get { throw new NotImplementedException (); }
- }
-
- public ICollection<ProjectItem> ItemsIgnoringCondition {
- get { throw new NotImplementedException (); }
- }
-
- public ICollection<string> ItemTypes {
- get { throw new NotImplementedException (); }
- }
-
- public ICollection<ProjectProperty> Properties {
- get { throw new NotImplementedException (); }
- }
-
- public bool SkipEvaluation { get; set; }
-
- public IDictionary<string, ProjectTargetInstance> Targets {
- get { throw new NotImplementedException (); }
- }
- }
+ public Project (ProjectRootElement xml) : this (xml, null, null)
+ {
+ }
+
+ public Project (ProjectRootElement xml, IDictionary<string, string> globalProperties,
+ string toolsVersion)
+ : this (xml, globalProperties, toolsVersion, ProjectCollection.GlobalProjectCollection)
+ {
+ }
+
+ public Project (ProjectRootElement xml, IDictionary<string, string> globalProperties,
+ string toolsVersion, ProjectCollection projectCollection)
+ : this (xml, globalProperties, toolsVersion, projectCollection, ProjectLoadSettings.Default)
+ {
+ }
+
+ public Project (ProjectRootElement xml, IDictionary<string, string> globalProperties,
+ string toolsVersion, ProjectCollection projectCollection,
+ ProjectLoadSettings loadSettings)
+ {
+ if (projectCollection == null)
+ throw new ArgumentNullException ("projectCollection");
+ this.Xml = xml;
+ this.GlobalProperties = globalProperties ?? new Dictionary<string, string> ();
+ this.ToolsVersion = toolsVersion;
+ this.ProjectCollection = projectCollection;
+ this.load_settings = loadSettings;
+
+ Initialize (null);
+ }
+
+ Project (ProjectRootElement imported, Project parent)
+ {
+ this.Xml = imported;
+ this.GlobalProperties = parent.GlobalProperties;
+ this.ToolsVersion = parent.ToolsVersion;
+ this.ProjectCollection = parent.ProjectCollection;
+ this.load_settings = parent.load_settings;
+
+ Initialize (parent);
+ }
+
+ public Project (string projectFile)
+ : this (projectFile, null, null)
+ {
+ }
+
+ public Project (string projectFile, IDictionary<string, string> globalProperties,
+ string toolsVersion)
+ : this (projectFile, globalProperties, toolsVersion, ProjectCollection.GlobalProjectCollection, ProjectLoadSettings.Default)
+ {
+ }
+
+ public Project (string projectFile, IDictionary<string, string> globalProperties,
+ string toolsVersion, ProjectCollection projectCollection)
+ : this (projectFile, globalProperties, toolsVersion, projectCollection, ProjectLoadSettings.Default)
+ {
+ }
+
+ public Project (string projectFile, IDictionary<string, string> globalProperties,
+ string toolsVersion, ProjectCollection projectCollection,
+ ProjectLoadSettings loadSettings)
+ : this (ProjectRootElement.Create (projectFile), globalProperties, toolsVersion, projectCollection, loadSettings)
+ {
+ }
+
+ ProjectLoadSettings load_settings;
+
+ public IDictionary<string, string> GlobalProperties { get; private set; }
+
+ public ProjectCollection ProjectCollection { get; private set; }
+
+ public string ToolsVersion { get; private set; }
+
+ public ProjectRootElement Xml { get; private set; }
+
+ string dir_path;
+ Dictionary<string, ProjectItemDefinition> item_definitions;
+ List<ResolvedImport> raw_imports;
+ List<ProjectItem> raw_items;
+ List<ProjectItem> all_evaluated_items;
+ List<ProjectProperty> properties;
+ Dictionary<string, ProjectTargetInstance> targets;
+
+ void Initialize (Project parent)
+ {
+ dir_path = Directory.GetCurrentDirectory ();
+ raw_imports = new List<ResolvedImport> ();
+ item_definitions = new Dictionary<string, ProjectItemDefinition> ();
+ targets = new Dictionary<string, ProjectTargetInstance> ();
+ raw_items = new List<ProjectItem> ();
+
+ // FIXME: this is likely hack. Test ImportedProject.Properties to see what exactly should happen.
+ if (parent != null) {
+ properties = parent.properties;
+ } else {
+ properties = new List<ProjectProperty> ();
+
+ foreach (DictionaryEntry p in Environment.GetEnvironmentVariables ())
+ // FIXME: this is kind of workaround for unavoidable issue that PLATFORM=* is actually given
+ // on some platforms and that prevents setting default "PLATFORM=AnyCPU" property.
+ if (!string.Equals ("PLATFORM", (string) p.Key, StringComparison.OrdinalIgnoreCase))
+ this.properties.Add (new EnvironmentProjectProperty (this, (string)p.Key, (string)p.Value));
+ foreach (var p in GlobalProperties)
+ this.properties.Add (new GlobalProjectProperty (this, p.Key, p.Value));
+ var tools = ProjectCollection.GetToolset (this.ToolsVersion) ?? ProjectCollection.GetToolset (this.ProjectCollection.DefaultToolsVersion);
+ foreach (var p in ProjectCollection.GetReservedProperties (tools, this))
+ this.properties.Add (p);
+ foreach (var p in ProjectCollection.GetWellKnownProperties (this))
+ this.properties.Add (p);
+ }
+
+ ProcessXml (parent);
+
+ ProjectCollection.AddProject (this);
+ }
+
+ void ProcessXml (Project parent)
+ {
+ // this needs to be initialized here (regardless of that items won't be evaluated at property evaluation;
+ // Conditions could incorrectly reference items and lack of this list causes NRE.
+ all_evaluated_items = new List<ProjectItem> ();
+
+ // property evaluation happens couple of times.
+ // At first step, all non-imported properties are evaluated TOO, WHILE those properties are being evaluated.
+ // This means, Include and IncludeGroup elements with Condition attribute MAY contain references to
+ // properties and they will be expanded.
+ var elements = EvaluatePropertiesAndImports (Xml.Children).ToArray (); // ToArray(): to not lazily evaluate elements.
+
+ // next, evaluate items
+ EvaluateItems (elements);
+
+ // finally, evaluate targets and tasks
+ EvaluateTargets (elements);
+ }
+
+ IEnumerable<ProjectElement> EvaluatePropertiesAndImports (IEnumerable<ProjectElement> elements)
+ {
+ // First step: evaluate Properties
+ foreach (var child in elements) {
+ yield return child;
+ var pge = child as ProjectPropertyGroupElement;
+ if (pge != null && Evaluate (pge.Condition))
+ foreach (var p in pge.Properties)
+ // do not allow overwriting reserved or well-known properties by user
+ if (!this.properties.Any (_ => (_.IsReservedProperty || _.IsWellKnownProperty) && _.Name.Equals (p.Name, StringComparison.InvariantCultureIgnoreCase)))
+ if (Evaluate (p.Condition))
+ this.properties.Add (new XmlProjectProperty (this, p, PropertyType.Normal, ProjectCollection.OngoingImports.Any ()));
+
+ var ige = child as ProjectImportGroupElement;
+ if (ige != null && Evaluate (ige.Condition)) {
+ foreach (var incc in ige.Imports) {
+ foreach (var e in Import (incc))
+ yield return e;
+ }
+ }
+ var inc = child as ProjectImportElement;
+ if (inc != null && Evaluate (inc.Condition))
+ foreach (var e in Import (inc))
+ yield return e;
+ }
+ }
+
+ internal IEnumerable<T> GetAllItems<T> (string include, string exclude, Func<string,T> creator, Func<string,ITaskItem> taskItemCreator, Func<string,bool> itemTypeCheck, Action<T,string> assignRecurse)
+ {
+ return ProjectCollection.GetAllItems<T> (ExpandString, include, exclude, creator, taskItemCreator, DirectoryPath, assignRecurse,
+ t => all_evaluated_items.Any (i => i.EvaluatedInclude == t.ItemSpec && itemTypeCheck (i.ItemType)));
+ }
+
+ void EvaluateItems (IEnumerable<ProjectElement> elements)
+ {
+ foreach (var child in elements) {
+ var ige = child as ProjectItemGroupElement;
+ if (ige != null) {
+ foreach (var p in ige.Items) {
+ if (!Evaluate (ige.Condition) || !Evaluate (p.Condition))
+ continue;
+ Func<string,ProjectItem> creator = s => new ProjectItem (this, p, s);
+ foreach (var item in GetAllItems<ProjectItem> (p.Include, p.Exclude, creator, s => new ProjectTaskItem (p, s), it => string.Equals (it, p.ItemType, StringComparison.OrdinalIgnoreCase), (t, s) => t.RecursiveDir = s)) {
+ raw_items.Add (item);
+ all_evaluated_items.Add (item);
+ }
+ }
+ }
+ var def = child as ProjectItemDefinitionGroupElement;
+ if (def != null) {
+ foreach (var p in def.ItemDefinitions) {
+ if (Evaluate (p.Condition)) {
+ ProjectItemDefinition existing;
+ if (!item_definitions.TryGetValue (p.ItemType, out existing))
+ item_definitions.Add (p.ItemType, (existing = new ProjectItemDefinition (this, p.ItemType)));
+ existing.AddItems (p);
+ }
+ }
+ }
+ }
+ all_evaluated_items.Sort ((p1, p2) => string.Compare (p1.ItemType, p2.ItemType, StringComparison.OrdinalIgnoreCase));
+ }
+
+ void EvaluateTargets (IEnumerable<ProjectElement> elements)
+ {
+ foreach (var child in elements) {
+ var te = child as ProjectTargetElement;
+ if (te != null)
+ this.targets.Add (te.Name, new ProjectTargetInstance (te));
+ }
+ }
+
+ IEnumerable<ProjectElement> Import (ProjectImportElement import)
+ {
+ string dir = ProjectCollection.GetEvaluationTimeThisFileDirectory (() => FullPath);
+ string path = WindowsCompatibilityExtensions.NormalizeFilePath (ExpandString (import.Project));
+ path = Path.IsPathRooted (path) ? path : dir != null ? Path.Combine (dir, path) : Path.GetFullPath (path);
+ if (ProjectCollection.OngoingImports.Contains (path)) {
+ switch (load_settings) {
+ case ProjectLoadSettings.RejectCircularImports:
+ throw new InvalidProjectFileException (import.Location, null, string.Format ("Circular imports was detected: {0} (resolved as \"{1}\") is already on \"importing\" stack", import.Project, path));
+ }
+ return new ProjectElement [0]; // do not import circular references
+ }
+ ProjectCollection.OngoingImports.Push (path);
+ try {
+ using (var reader = XmlReader.Create (path)) {
+ var root = ProjectRootElement.Create (reader, ProjectCollection);
+ raw_imports.Add (new ResolvedImport (import, root, true));
+ return this.EvaluatePropertiesAndImports (root.Children).ToArray ();
+ }
+ } finally {
+ ProjectCollection.OngoingImports.Pop ();
+ }
+ }
+
+ public ICollection<ProjectItem> GetItemsIgnoringCondition (string itemType)
+ {
+ return new CollectionFromEnumerable<ProjectItem> (raw_items.Where (p => p.ItemType.Equals (itemType, StringComparison.OrdinalIgnoreCase)));
+ }
+
+ public void RemoveItems (IEnumerable<ProjectItem> items)
+ {
+ var removal = new List<ProjectItem> (items);
+ foreach (var item in removal) {
+ var parent = item.Xml.Parent;
+ parent.RemoveChild (item.Xml);
+ if (parent.Count == 0)
+ parent.Parent.RemoveChild (parent);
+ }
+ }
+
+ static readonly Dictionary<string, string> empty_metadata = new Dictionary<string, string> ();
+
+ public IList<ProjectItem> AddItem (string itemType, string unevaluatedInclude)
+ {
+ return AddItem (itemType, unevaluatedInclude, empty_metadata);
+ }
+
+ public IList<ProjectItem> AddItem (string itemType, string unevaluatedInclude,
+ IEnumerable<KeyValuePair<string, string>> metadata)
+ {
+ // FIXME: needs several check that AddItemFast() does not process (see MSDN for details).
+
+ return AddItemFast (itemType, unevaluatedInclude, metadata);
+ }
+
+ public IList<ProjectItem> AddItemFast (string itemType, string unevaluatedInclude)
+ {
+ return AddItemFast (itemType, unevaluatedInclude, empty_metadata);
+ }
+
+ public IList<ProjectItem> AddItemFast (string itemType, string unevaluatedInclude,
+ IEnumerable<KeyValuePair<string, string>> metadata)
+ {
+ throw new NotImplementedException ();
+ }
+
+ static readonly char [] target_sep = new char[] {';'};
+
+ public bool Build ()
+ {
+ return Build (Xml.DefaultTargets.Split (target_sep, StringSplitOptions.RemoveEmptyEntries));
+ }
+
+ public bool Build (IEnumerable<ILogger> loggers)
+ {
+ return Build (Xml.DefaultTargets.Split (target_sep, StringSplitOptions.RemoveEmptyEntries), loggers);
+ }
+
+ public bool Build (string target)
+ {
+ return string.IsNullOrWhiteSpace (target) ? Build () : Build (new string [] {target});
+ }
+
+ public bool Build (string[] targets)
+ {
+ return Build (targets, new ILogger [0]);
+ }
+
+ public bool Build (ILogger logger)
+ {
+ return Build (Xml.DefaultTargets.Split (target_sep, StringSplitOptions.RemoveEmptyEntries), new ILogger [] {logger});
+ }
+
+ public bool Build (string[] targets, IEnumerable<ILogger> loggers)
+ {
+ return Build (targets, loggers, new ForwardingLoggerRecord [0]);
+ }
+
+ public bool Build (IEnumerable<ILogger> loggers, IEnumerable<ForwardingLoggerRecord> remoteLoggers)
+ {
+ return Build (Xml.DefaultTargets.Split (target_sep, StringSplitOptions.RemoveEmptyEntries), loggers, remoteLoggers);
+ }
+
+ public bool Build (string target, IEnumerable<ILogger> loggers)
+ {
+ return Build (new string [] { target }, loggers);
+ }
+
+ public bool Build (string[] targets, IEnumerable<ILogger> loggers, IEnumerable<ForwardingLoggerRecord> remoteLoggers)
+ {
+ // Unlike ProjectInstance.Build(), there is no place to fill outputs by targets, so ignore them
+ // (i.e. we don't use the overload with output).
+ //
+ // This does not check FullPath, so don't call GetProjectInstanceForBuild() directly.
+ return new BuildManager ().GetProjectInstanceForBuildInternal (this).Build (targets, loggers, remoteLoggers);
+ }
+
+ public bool Build (string target, IEnumerable<ILogger> loggers, IEnumerable<ForwardingLoggerRecord> remoteLoggers)
+ {
+ return Build (new string [] { target }, loggers, remoteLoggers);
+ }
+
+ public ProjectInstance CreateProjectInstance ()
+ {
+ var ret = new ProjectInstance (Xml, GlobalProperties, ToolsVersion, ProjectCollection);
+ // FIXME: maybe fill other properties to the result.
+ return ret;
+ }
+
+ bool Evaluate (string unexpandedValue)
+ {
+ return string.IsNullOrWhiteSpace (unexpandedValue) || new ExpressionEvaluator (this, null).EvaluateAsBoolean (unexpandedValue);
+ }
+
+ public string ExpandString (string unexpandedValue)
+ {
+ return ExpandString (unexpandedValue, null);
+ }
+
+ string ExpandString (string unexpandedValue, string replacementForMissingStuff)
+ {
+ return new ExpressionEvaluator (this, replacementForMissingStuff).Evaluate (unexpandedValue);
+ }
+
+ public static string GetEvaluatedItemIncludeEscaped (ProjectItem item)
+ {
+ return ProjectCollection.Escape (item.EvaluatedInclude);
+ }
+
+ public static string GetEvaluatedItemIncludeEscaped (ProjectItemDefinition item)
+ {
+ // ?? ItemDefinition does not have Include attribute. What's the point here?
+ throw new NotImplementedException ();
+ }
+
+ public ICollection<ProjectItem> GetItems (string itemType)
+ {
+ return new CollectionFromEnumerable<ProjectItem> (Items.Where (p => p.ItemType.Equals (itemType, StringComparison.OrdinalIgnoreCase)));
+ }
+
+ public ICollection<ProjectItem> GetItemsByEvaluatedInclude (string evaluatedInclude)
+ {
+ return new CollectionFromEnumerable<ProjectItem> (Items.Where (p => p.EvaluatedInclude.Equals (evaluatedInclude, StringComparison.OrdinalIgnoreCase)));
+ }
+
+ public IEnumerable<ProjectElement> GetLogicalProject ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static string GetMetadataValueEscaped (ProjectMetadata metadatum)
+ {
+ return ProjectCollection.Escape (metadatum.EvaluatedValue);
+ }
+
+ public static string GetMetadataValueEscaped (ProjectItem item, string name)
+ {
+ var md = item.Metadata.FirstOrDefault (m => m.Name.Equals (name, StringComparison.OrdinalIgnoreCase));
+ return md != null ? ProjectCollection.Escape (md.EvaluatedValue) : null;
+ }
+
+ public static string GetMetadataValueEscaped (ProjectItemDefinition item, string name)
+ {
+ var md = item.Metadata.FirstOrDefault (m => m.Name.Equals (name, StringComparison.OrdinalIgnoreCase));
+ return md != null ? ProjectCollection.Escape (md.EvaluatedValue) : null;
+ }
+
+ public string GetPropertyValue (string name)
+ {
+ var prop = GetProperty (name);
+ return prop != null ? prop.EvaluatedValue : string.Empty;
+ }
+
+ public static string GetPropertyValueEscaped (ProjectProperty property)
+ {
+ // WTF happens here.
+ //return ProjectCollection.Escape (property.EvaluatedValue);
+ return property.EvaluatedValue;
+ }
+
+ public ProjectProperty GetProperty (string name)
+ {
+ return properties.FirstOrDefault (p => p.Name.Equals (name, StringComparison.OrdinalIgnoreCase));
+ }
+
+ public void MarkDirty ()
+ {
+ if (!DisableMarkDirty)
+ is_dirty = true;
+ }
+
+ public void ReevaluateIfNecessary ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ public bool RemoveGlobalProperty (string name)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public bool RemoveItem (ProjectItem item)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public bool RemoveProperty (ProjectProperty property)
+ {
+ var removed = properties.FirstOrDefault (p => p.Name.Equals (property.Name, StringComparison.OrdinalIgnoreCase));
+ if (removed == null)
+ return false;
+ properties.Remove (removed);
+ return true;
+ }
+
+ public void Save ()
+ {
+ Xml.Save ();
+ }
+
+ public void Save (TextWriter writer)
+ {
+ Xml.Save (writer);
+ }
+
+ public void Save (string path)
+ {
+ Save (path, Encoding.Default);
+ }
+
+ public void Save (Encoding encoding)
+ {
+ Save (FullPath, encoding);
+ }
+
+ public void Save (string path, Encoding encoding)
+ {
+ using (var writer = new StreamWriter (path, false, encoding))
+ Save (writer);
+ }
+
+ public void SaveLogicalProject (TextWriter writer)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public bool SetGlobalProperty (string name, string escapedValue)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public ProjectProperty SetProperty (string name, string unevaluatedValue)
+ {
+ var p = new ManuallyAddedProjectProperty (this, name, unevaluatedValue);
+ properties.Add (p);
+ return p;
+ }
+
+ public ICollection<ProjectMetadata> AllEvaluatedItemDefinitionMetadata {
+ get { throw new NotImplementedException (); }
+ }
+
+ public ICollection<ProjectItem> AllEvaluatedItems {
+ get { return all_evaluated_items; }
+ }
+
+ public ICollection<ProjectProperty> AllEvaluatedProperties {
+ get { return properties; }
+ }
+
+ public IDictionary<string, List<string>> ConditionedProperties {
+ get {
+ // this property returns different instances every time.
+ var dic = new Dictionary<string, List<string>> ();
+
+ // but I dunno HOW this evaluates
+
+ throw new NotImplementedException ();
+ }
+ }
+
+ public string DirectoryPath {
+ get { return dir_path; }
+ }
+
+ public bool DisableMarkDirty { get; set; }
+
+ public int EvaluationCounter {
+ get { throw new NotImplementedException (); }
+ }
+
+ public string FullPath {
+ get { return Xml.FullPath; }
+ set { Xml.FullPath = value; }
+ }
+
+ class ResolvedImportComparer : IEqualityComparer<ResolvedImport>
+ {
+ public static ResolvedImportComparer Instance = new ResolvedImportComparer ();
+
+ public bool Equals (ResolvedImport x, ResolvedImport y)
+ {
+ return x.ImportedProject.FullPath.Equals (y.ImportedProject.FullPath);
+ }
+ public int GetHashCode (ResolvedImport obj)
+ {
+ return obj.ImportedProject.FullPath.GetHashCode ();
+ }
+ }
+
+ public IList<ResolvedImport> Imports {
+ get { return raw_imports.Distinct (ResolvedImportComparer.Instance).ToList (); }
+ }
+
+ public IList<ResolvedImport> ImportsIncludingDuplicates {
+ get { return raw_imports; }
+ }
+
+ public bool IsBuildEnabled {
+ get { return ProjectCollection.IsBuildEnabled; }
+ }
+
+ bool is_dirty;
+ public bool IsDirty {
+ get { return is_dirty; }
+ }
+
+ public IDictionary<string, ProjectItemDefinition> ItemDefinitions {
+ get { return item_definitions; }
+ }
+
+ [MonoTODO ("should be different from AllEvaluatedItems")]
+ public ICollection<ProjectItem> Items {
+ get { return AllEvaluatedItems; }
+ }
+
+ public ICollection<ProjectItem> ItemsIgnoringCondition {
+ get { return raw_items; }
+ }
+
+ public ICollection<string> ItemTypes {
+ get { return new CollectionFromEnumerable<string> (raw_items.Select (i => i.ItemType).Distinct ()); }
+ }
+
+ [MonoTODO ("should be different from AllEvaluatedProperties")]
+ public ICollection<ProjectProperty> Properties {
+ get { return AllEvaluatedProperties; }
+ }
+
+ public bool SkipEvaluation { get; set; }
+
+ public IDictionary<string, ProjectTargetInstance> Targets {
+ get { return targets; }
+ }
+
+ // These are required for reserved property, represents dynamically changing property values.
+ // This should resolve to either the project file path or that of the imported file.
+ internal string GetEvaluationTimeThisFileDirectory ()
+ {
+ var file = GetEvaluationTimeThisFile ();
+ var dir = Path.IsPathRooted (file) ? Path.GetDirectoryName (file) : Directory.GetCurrentDirectory ();
+ return dir + Path.DirectorySeparatorChar;
+ }
+
+ internal string GetEvaluationTimeThisFile ()
+ {
+ return ProjectCollection.OngoingImports.Count > 0 ? ProjectCollection.OngoingImports.Peek () : FullPath ?? string.Empty;
+ }
+
+ internal string GetFullPath (string pathRelativeToProject)
+ {
+ if (Path.IsPathRooted (pathRelativeToProject))
+ return pathRelativeToProject;
+ return Path.GetFullPath (Path.Combine (DirectoryPath, pathRelativeToProject));
+ }
+ }
}
--- /dev/null
+//
+// ProjectChangedEventArgs.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@xamarin.com>
+//
+// Copyright (C) 2013 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Linq;
+
+namespace Microsoft.Build.Evaluation
+{
+ public class ProjectChangedEventArgs : EventArgs
+ {
+ internal ProjectChangedEventArgs (Project project)
+ {
+ Project = project;
+ }
+ public Project Project { get; private set; }
+ }
+}
// Author:
// Leszek Ciesielski (skolima@gmail.com)
// Rolf Bjarne Kvinge (rolf@xamarin.com)
+// Atsushi Enomoto (atsushi@xamarin.com)
//
// (C) 2011 Leszek Ciesielski
-// Copyright (C) 2011 Xamarin Inc.
+// Copyright (C) 2011,2013 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
//
using Microsoft.Build.Construction;
+using Microsoft.Build.Execution;
using Microsoft.Build.Framework;
using Microsoft.Build.Logging;
-
+using Microsoft.Build.Utilities;
using System;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using System.Reflection;
+using System.Globalization;
namespace Microsoft.Build.Evaluation
{
- public class ProjectCollection : IDisposable
- {
- public ProjectCollection ()
- {
- }
-
- public ProjectCollection (IDictionary<string, string> globalProperties)
- : this (globalProperties, null, ToolsetDefinitionLocations.Registry | ToolsetDefinitionLocations.ConfigurationFile)
- {
- }
-
- public ProjectCollection (ToolsetDefinitionLocations toolsetDefinitionLocations)
- : this (null, null, toolsetDefinitionLocations)
- {
- }
-
- public ProjectCollection (IDictionary<string, string> globalProperties, IEnumerable<ILogger> loggers,
- ToolsetDefinitionLocations toolsetDefinitionLocations)
- : this (globalProperties, loggers, null, toolsetDefinitionLocations, 1, false)
- {
- }
-
- public ProjectCollection (IDictionary<string, string> globalProperties,
- IEnumerable<ILogger> loggers, IEnumerable<ForwardingLoggerRecord> remoteLoggers,
- ToolsetDefinitionLocations toolsetDefinitionLocations,
- int maxNodeCount, bool onlyLogCriticalEvents)
- {
- throw new NotImplementedException ();
- }
-
- public static string Escape (string unescapedString)
- {
- return unescapedString;
- }
-
- public static ProjectCollection GlobalProjectCollection {
- get { return globalProjectCollection; }
- }
-
- public void Dispose ()
- {
- Dispose (true);
- GC.SuppressFinalize (this);
- }
-
- protected virtual void Dispose (bool disposing)
- {
- if (disposing) {
- }
- }
-
- static ProjectCollection globalProjectCollection = new ProjectCollection ();
-
- public ICollection<Project> GetLoadedProjects (string fullPath)
- {
- throw new NotImplementedException ();
- }
-
- public ToolsetDefinitionLocations ToolsetLocations {
- get { throw new NotImplementedException (); }
- }
+ public class ProjectCollection : IDisposable
+ {
+ public delegate void ProjectAddedEventHandler (object target, ProjectAddedToProjectCollectionEventArgs args);
+
+ public class ProjectAddedToProjectCollectionEventArgs : EventArgs
+ {
+ public ProjectAddedToProjectCollectionEventArgs (ProjectRootElement project)
+ {
+ if (project == null)
+ throw new ArgumentNullException ("project");
+ ProjectRootElement = project;
+ }
+
+ public ProjectRootElement ProjectRootElement { get; private set; }
+ }
+
+ // static members
+
+ static readonly ProjectCollection global_project_collection;
+
+ static ProjectCollection ()
+ {
+ #if NET_4_5
+ global_project_collection = new ProjectCollection (new ReadOnlyDictionary<string, string> (new Dictionary<string, string> ()));
+ #else
+ global_project_collection = new ProjectCollection (new Dictionary<string, string> ());
+ #endif
+ }
+
+ public static string Escape (string unescapedString)
+ {
+ return Mono.XBuild.Utilities.MSBuildUtils.Escape (unescapedString);
+ }
+
+ public static string Unescape (string escapedString)
+ {
+ return Mono.XBuild.Utilities.MSBuildUtils.Unescape (escapedString);
+ }
+
+ public static ProjectCollection GlobalProjectCollection {
+ get { return global_project_collection; }
+ }
+
+ // semantic model part
+
+ public ProjectCollection ()
+ : this (null)
+ {
+ }
+
+ public ProjectCollection (IDictionary<string, string> globalProperties)
+ : this (globalProperties, null, ToolsetDefinitionLocations.Registry | ToolsetDefinitionLocations.ConfigurationFile)
+ {
+ }
+ public ProjectCollection (ToolsetDefinitionLocations toolsetDefinitionLocations)
+ : this (null, null, toolsetDefinitionLocations)
+ {
+ }
+
+ public ProjectCollection (IDictionary<string, string> globalProperties, IEnumerable<ILogger> loggers,
+ ToolsetDefinitionLocations toolsetDefinitionLocations)
+ : this (globalProperties, loggers, null, toolsetDefinitionLocations, 1, false)
+ {
+ }
+
+ public ProjectCollection (IDictionary<string, string> globalProperties,
+ IEnumerable<ILogger> loggers, IEnumerable<ForwardingLoggerRecord> remoteLoggers,
+ ToolsetDefinitionLocations toolsetDefinitionLocations,
+ int maxNodeCount, bool onlyLogCriticalEvents)
+ {
+ global_properties = globalProperties ?? new Dictionary<string, string> ();
+ this.loggers = loggers != null ? loggers.ToList () : new List<ILogger> ();
+ toolset_locations = toolsetDefinitionLocations;
+ MaxNodeCount = maxNodeCount;
+ OnlyLogCriticalEvents = onlyLogCriticalEvents;
+
+ LoadDefaultToolsets ();
+ }
+
+ [MonoTODO ("not fired yet")]
+ public event ProjectAddedEventHandler ProjectAdded;
+ [MonoTODO ("not fired yet")]
+ public event EventHandler<ProjectChangedEventArgs> ProjectChanged;
+ [MonoTODO ("not fired yet")]
+ public event EventHandler<ProjectCollectionChangedEventArgs> ProjectCollectionChanged;
+ [MonoTODO ("not fired yet")]
+ public event EventHandler<ProjectXmlChangedEventArgs> ProjectXmlChanged;
+
+ public void AddProject (Project project)
+ {
+ this.loaded_projects.Add (project);
+ if (ProjectAdded != null)
+ ProjectAdded (this, new ProjectAddedToProjectCollectionEventArgs (project.Xml));
+ }
+
+ public int Count {
+ get { return loaded_projects.Count; }
+ }
+
+ string default_tools_version;
+ public string DefaultToolsVersion {
+ get { return default_tools_version; }
+ set {
+ if (GetToolset (value) == null)
+ throw new InvalidOperationException (string.Format ("Toolset '{0}' does not exist", value));
+ default_tools_version = value;
+ }
+ }
+
+ public void Dispose ()
+ {
+ Dispose (true);
+ GC.SuppressFinalize (this);
+ }
+
+ protected virtual void Dispose (bool disposing)
+ {
+ if (disposing) {
+ }
+ }
+
+ public ICollection<Project> GetLoadedProjects (string fullPath)
+ {
+ return LoadedProjects.Where (p => p.FullPath != null && Path.GetFullPath (p.FullPath) == Path.GetFullPath (fullPath)).ToList ();
+ }
+
+ readonly IDictionary<string, string> global_properties;
+
+ public IDictionary<string, string> GlobalProperties {
+ get { return global_properties; }
+ }
+
+ readonly List<Project> loaded_projects = new List<Project> ();
+
+ public Project LoadProject (string fileName)
+ {
+ return LoadProject (fileName, DefaultToolsVersion);
+ }
+
+ public Project LoadProject (string fileName, string toolsVersion)
+ {
+ return LoadProject (fileName, null, toolsVersion);
+ }
+
+ public Project LoadProject (string fileName, IDictionary<string,string> globalProperties, string toolsVersion)
+ {
+ var ret = new Project (fileName, globalProperties, toolsVersion);
+ loaded_projects.Add (ret);
+ return ret;
+ }
+
+ // These methods somehow don't add the project to ProjectCollection...
+ public Project LoadProject (XmlReader xmlReader)
+ {
+ return LoadProject (xmlReader, DefaultToolsVersion);
+ }
+
+ public Project LoadProject (XmlReader xmlReader, string toolsVersion)
+ {
+ return LoadProject (xmlReader, null, toolsVersion);
+ }
+
+ public Project LoadProject (XmlReader xmlReader, IDictionary<string,string> globalProperties, string toolsVersion)
+ {
+ return new Project (xmlReader, globalProperties, toolsVersion);
+ }
+
+ public ICollection<Project> LoadedProjects {
+ get { return loaded_projects; }
+ }
+
+ readonly List<ILogger> loggers = new List<ILogger> ();
+ [MonoTODO]
+ public ICollection<ILogger> Loggers {
+ get { return loggers; }
+ }
+
+ [MonoTODO]
+ public bool OnlyLogCriticalEvents { get; set; }
+
+ [MonoTODO]
+ public bool SkipEvaluation { get; set; }
+
+ readonly ToolsetDefinitionLocations toolset_locations;
+ public ToolsetDefinitionLocations ToolsetLocations {
+ get { return toolset_locations; }
+ }
+
+ readonly List<Toolset> toolsets = new List<Toolset> ();
+ // so what should we do without ToolLocationHelper in Microsoft.Build.Utilities.dll? There is no reference to it in this dll.
public ICollection<Toolset> Toolsets {
- get { throw new NotImplementedException (); }
- }
+ // For ConfigurationFile and None, they cannot be added externally.
+ get { return (ToolsetLocations & ToolsetDefinitionLocations.Registry) != 0 ? toolsets : toolsets.ToList (); }
+ }
+
+ public Toolset GetToolset (string toolsVersion)
+ {
+ return Toolsets.FirstOrDefault (t => t.ToolsVersion == toolsVersion);
+ }
+
+ //FIXME: should also support config file, depending on ToolsetLocations
+ void LoadDefaultToolsets ()
+ {
+ AddToolset (new Toolset ("2.0",
+ ToolLocationHelper.GetPathToDotNetFramework (TargetDotNetFrameworkVersion.Version20), this, null));
+ AddToolset (new Toolset ("3.0",
+ ToolLocationHelper.GetPathToDotNetFramework (TargetDotNetFrameworkVersion.Version30), this, null));
+ AddToolset (new Toolset ("3.5",
+ ToolLocationHelper.GetPathToDotNetFramework (TargetDotNetFrameworkVersion.Version35), this, null));
+#if NET_4_0
+ AddToolset (new Toolset ("4.0",
+ ToolLocationHelper.GetPathToDotNetFramework (TargetDotNetFrameworkVersion.Version40), this, null));
+#endif
+#if NET_4_5
+ AddToolset (new Toolset ("12.0",
+ ToolLocationHelper.GetMSBuildInstallPath ("12.0"), this, ToolLocationHelper.GetPathToDotNetFramework (TargetDotNetFrameworkVersion.Version40)));
+#endif
+ default_tools_version = toolsets.First ().ToolsVersion;
+ }
+
+ [MonoTODO ("not verified at all")]
+ public void AddToolset (Toolset toolset)
+ {
+ toolsets.Add (toolset);
+ }
+
+ [MonoTODO ("not verified at all")]
+ public void RemoveAllToolsets ()
+ {
+ toolsets.Clear ();
+ }
+
+ [MonoTODO ("not verified at all")]
+ public void RegisterLogger (ILogger logger)
+ {
+ loggers.Add (logger);
+ }
+
+ [MonoTODO ("not verified at all")]
+ public void RegisterLoggers (IEnumerable<ILogger> loggers)
+ {
+ foreach (var logger in loggers)
+ this.loggers.Add (logger);
+ }
public void UnloadAllProjects ()
{
- throw new NotImplementedException ();
+ throw new NotImplementedException ();
}
+ [MonoTODO ("Not verified at all")]
public void UnloadProject (Project project)
{
- throw new NotImplementedException ();
+ this.loaded_projects.Remove (project);
}
+ [MonoTODO ("Not verified at all")]
public void UnloadProject (ProjectRootElement projectRootElement)
{
- throw new NotImplementedException ();
+ foreach (var proj in loaded_projects.Where (p => p.Xml == projectRootElement).ToArray ())
+ UnloadProject (proj);
}
public static Version Version {
- get { throw new NotImplementedException (); }
- }
- }
+ get { throw new NotImplementedException (); }
+ }
+
+ // Execution part
+
+ [MonoTODO]
+ public bool DisableMarkDirty { get; set; }
+
+ [MonoTODO]
+ public HostServices HostServices { get; set; }
+
+ [MonoTODO]
+ public bool IsBuildEnabled { get; set; }
+
+ internal string BuildStartupDirectory { get; set; }
+
+ internal int MaxNodeCount { get; private set; }
+
+ Stack<string> ongoing_imports = new Stack<string> ();
+
+ internal Stack<string> OngoingImports {
+ get { return ongoing_imports; }
+ }
+
+ // common part
+ internal static IEnumerable<EnvironmentProjectProperty> GetWellKnownProperties (Project project)
+ {
+ Func<string,string,EnvironmentProjectProperty> create = (name, value) => new EnvironmentProjectProperty (project, name, value, true);
+ return GetWellKnownProperties (create);
+ }
+
+ internal static IEnumerable<ProjectPropertyInstance> GetWellKnownProperties (ProjectInstance project)
+ {
+ Func<string,string,ProjectPropertyInstance> create = (name, value) => new ProjectPropertyInstance (name, true, value);
+ return GetWellKnownProperties (create);
+ }
+
+ static IEnumerable<T> GetWellKnownProperties<T> (Func<string,string,T> create)
+ {
+ var ext = Environment.GetEnvironmentVariable ("MSBuildExtensionsPath") ?? DefaultExtensionsPath;
+ yield return create ("MSBuildExtensionsPath", ext);
+ var ext32 = Environment.GetEnvironmentVariable ("MSBuildExtensionsPath32") ?? DefaultExtensionsPath;
+ yield return create ("MSBuildExtensionsPath32", ext32);
+ var ext64 = Environment.GetEnvironmentVariable ("MSBuildExtensionsPath64") ?? DefaultExtensionsPath;
+ yield return create ("MSBuildExtensionsPath64", ext64);
+ }
+
+ static string extensions_path;
+ internal static string DefaultExtensionsPath {
+ get {
+ if (extensions_path == null) {
+ // NOTE: code from mcs/tools/gacutil/driver.cs
+ PropertyInfo gac = typeof (System.Environment).GetProperty (
+ "GacPath", BindingFlags.Static | BindingFlags.NonPublic);
+
+ if (gac != null) {
+ MethodInfo get_gac = gac.GetGetMethod (true);
+ string gac_path = (string) get_gac.Invoke (null, null);
+ extensions_path = Path.GetFullPath (Path.Combine (
+ gac_path, Path.Combine ("..", "xbuild")));
+ }
+ }
+ return extensions_path;
+ }
+ }
+
+ internal IEnumerable<ReservedProjectProperty> GetReservedProperties (Toolset toolset, Project project)
+ {
+ Func<string,Func<string>,ReservedProjectProperty> create = (name, value) => new ReservedProjectProperty (project, name, value);
+ return GetReservedProperties<ReservedProjectProperty> (toolset, project.Xml, create, () => project.FullPath);
+ }
+
+ internal IEnumerable<ProjectPropertyInstance> GetReservedProperties (Toolset toolset, ProjectInstance project, ProjectRootElement xml)
+ {
+ Func<string,Func<string>,ProjectPropertyInstance> create = (name, value) => new ProjectPropertyInstance (name, true, null, value);
+ return GetReservedProperties<ProjectPropertyInstance> (toolset, xml, create, () => project.FullPath);
+ }
+
+ // seealso http://msdn.microsoft.com/en-us/library/ms164309.aspx
+ IEnumerable<T> GetReservedProperties<T> (Toolset toolset, ProjectRootElement project, Func<string,Func<string>,T> create, Func<string> projectFullPath)
+ {
+ yield return create ("MSBuildBinPath", () => toolset.ToolsPath);
+ // FIXME: add MSBuildLastTaskResult
+ // FIXME: add MSBuildNodeCount
+ // FIXME: add MSBuildProgramFiles32
+ yield return create ("MSBuildProjectDefaultTargets", () => project.DefaultTargets);
+ yield return create ("MSBuildProjectDirectory", () => project.DirectoryPath + Path.DirectorySeparatorChar);
+ yield return create ("MSBuildProjectDirectoryNoRoot", () => project.DirectoryPath.Substring (Path.GetPathRoot (project.DirectoryPath).Length));
+ yield return create ("MSBuildProjectExtension", () => Path.GetExtension (project.FullPath));
+ yield return create ("MSBuildProjectFile", () => Path.GetFileName (project.FullPath));
+ yield return create ("MSBuildProjectFullPath", () => project.FullPath);
+ yield return create ("MSBuildProjectName", () => Path.GetFileNameWithoutExtension (project.FullPath));
+ yield return create ("MSBuildStartupDirectory", () => BuildStartupDirectory);
+ yield return create ("MSBuildThisFile", () => Path.GetFileName (GetEvaluationTimeThisFile (projectFullPath)));
+ yield return create ("MSBuildThisFileFullPath", () => GetEvaluationTimeThisFile (projectFullPath));
+ yield return create ("MSBuildThisFileName", () => Path.GetFileNameWithoutExtension (GetEvaluationTimeThisFile (projectFullPath)));
+ yield return create ("MSBuildThisFileExtension", () => Path.GetExtension (GetEvaluationTimeThisFile (projectFullPath)));
+
+ yield return create ("MSBuildThisFileDirectory", () => Path.GetDirectoryName (GetEvaluationTimeThisFileDirectory (projectFullPath)));
+ yield return create ("MSBuildThisFileDirectoryNoRoot", () => {
+ string dir = GetEvaluationTimeThisFileDirectory (projectFullPath) + Path.DirectorySeparatorChar;
+ return dir.Substring (Path.GetPathRoot (dir).Length);
+ });
+ yield return create ("MSBuildToolsPath", () => toolset.ToolsPath);
+ yield return create ("MSBuildToolsVersion", () => toolset.ToolsVersion);
+ }
+
+ // These are required for reserved property, represents dynamically changing property values.
+ // This should resolve to either the project file path or that of the imported file.
+ internal string GetEvaluationTimeThisFileDirectory (Func<string> nonImportingTimeFullPath)
+ {
+ var file = GetEvaluationTimeThisFile (nonImportingTimeFullPath);
+ var dir = Path.IsPathRooted (file) ? Path.GetDirectoryName (file) : Directory.GetCurrentDirectory ();
+ return dir + Path.DirectorySeparatorChar;
+ }
+
+ internal string GetEvaluationTimeThisFile (Func<string> nonImportingTimeFullPath)
+ {
+ return OngoingImports.Count > 0 ? OngoingImports.Peek () : (nonImportingTimeFullPath () ?? string.Empty);
+ }
+
+ static readonly char [] item_target_sep = {';'};
+
+ internal static IEnumerable<T> GetAllItems<T> (Func<string,string> expandString, string include, string exclude, Func<string,T> creator, Func<string,ITaskItem> taskItemCreator, string directory, Action<T,string> assignRecurse, Func<ITaskItem,bool> isDuplicate)
+ {
+ var includes = expandString (include).Trim ().Split (item_target_sep, StringSplitOptions.RemoveEmptyEntries);
+ var excludes = expandString (exclude).Trim ().Split (item_target_sep, StringSplitOptions.RemoveEmptyEntries);
+
+ if (includes.Length == 0)
+ yield break;
+ if (includes.Length == 1 && includes [0].IndexOf ('*') < 0 && excludes.Length == 0) {
+ // for most case - shortcut.
+ var item = creator (includes [0]);
+ yield return item;
+ } else {
+ var ds = new Microsoft.Build.BuildEngine.DirectoryScanner () {
+ BaseDirectory = new DirectoryInfo (directory),
+ Includes = includes.Where (s => !string.IsNullOrWhiteSpace (s)).Select (i => taskItemCreator (i)).ToArray (),
+ Excludes = excludes.Where (s => !string.IsNullOrWhiteSpace (s)).Select (e => taskItemCreator (e)).ToArray (),
+ };
+ ds.Scan ();
+ foreach (var taskItem in ds.MatchedItems) {
+ if (isDuplicate (taskItem))
+ continue; // skip duplicate
+ var item = creator (taskItem.ItemSpec);
+ string recurse = taskItem.GetMetadata ("RecursiveDir");
+ assignRecurse (item, recurse);
+ yield return item;
+ }
+ }
+ }
+
+ static readonly char [] path_sep = {Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar};
+
+ internal static string GetWellKnownMetadata (string name, string file, Func<string,string> getFullPath, string recursiveDir)
+ {
+ switch (name.ToLower (CultureInfo.InvariantCulture)) {
+ case "fullpath":
+ return getFullPath (file);
+ case "rootdir":
+ return Path.GetPathRoot (getFullPath (file));
+ case "filename":
+ return Path.GetFileNameWithoutExtension (file);
+ case "extension":
+ return Path.GetExtension (file);
+ case "relativedir":
+ var idx = file.LastIndexOfAny (path_sep);
+ return idx < 0 ? string.Empty : file.Substring (0, idx + 1);
+ case "directory":
+ var fp = getFullPath (file);
+ return Path.GetDirectoryName (fp).Substring (Path.GetPathRoot (fp).Length);
+ case "recursivedir":
+ return recursiveDir;
+ case "identity":
+ return file;
+ case "modifiedtime":
+ return new FileInfo (getFullPath (file)).LastWriteTime.ToString ("yyyy-MM-dd HH:mm:ss.fffffff");
+ case "createdtime":
+ return new FileInfo (getFullPath (file)).CreationTime.ToString ("yyyy-MM-dd HH:mm:ss.fffffff");
+ case "accessedtime":
+ return new FileInfo (getFullPath (file)).LastAccessTime.ToString ("yyyy-MM-dd HH:mm:ss.fffffff");
+ }
+ return null;
+ }
+ }
}
--- /dev/null
+using System;
+using Microsoft.Build.Construction;
+
+namespace Microsoft.Build.Evaluation
+{
+ public class ProjectCollectionChangedEventArgs : EventArgs
+ {
+ public ProjectCollectionChangedEventArgs (ProjectCollectionChangedState state)
+ {
+ State = state;
+ }
+
+ public ProjectCollectionChangedState State { get; private set; }
+ }
+}
+
--- /dev/null
+using System;
+using Microsoft.Build.Construction;
+
+namespace Microsoft.Build.Evaluation
+{
+ public enum ProjectCollectionChangedState
+ {
+ DefaultToolsVersion,
+ DisableMarkDirty,
+ GlobalProperties,
+ HostServices,
+ IsBuildEnabled,
+ Loggers,
+ OnlyLogCriticalEvents,
+ SkipEvaluation,
+ Toolsets
+ }
+}
+
// Author:
// Leszek Ciesielski (skolima@gmail.com)
// Rolf Bjarne Kvinge (rolf@xamarin.com)
+// Atsushi Enomoto (atsushi@xamarin.com)
//
// (C) 2011 Leszek Ciesielski
-// Copyright (C) 2011 Xamarin Inc.
+// Copyright (C) 2011,2013 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
using System;
using System.Collections.Generic;
using System.Diagnostics;
-
+using System.Linq;
using Microsoft.Build.Construction;
+using System.IO;
+using Microsoft.Build.Framework;
namespace Microsoft.Build.Evaluation
{
- [DebuggerDisplay("{ItemType}={EvaluatedInclude} [{UnevaluatedInclude}] #DirectMetadata={DirectMetadataCount}")]
- public class ProjectItem
- {
- internal ProjectItem (ProjectItemElement xml)
- {
- Xml = xml;
- }
-
- public ProjectMetadata GetMetadata (string name)
- {
- throw new NotImplementedException ();
- }
-
- public string GetMetadataValue (string name)
- {
- throw new NotImplementedException ();
- }
-
- public bool HasMetadata (string name)
- {
- throw new NotImplementedException ();
- }
-
- public bool RemoveMetadata (string name)
- {
- throw new NotImplementedException ();
- }
-
- public void Rename (string name)
- {
- throw new NotImplementedException ();
- }
-
- public void SetMetadataValue (string name, string unevaluatedValue)
- {
- throw new NotImplementedException ();
- }
-
- public IEnumerable<ProjectMetadata> DirectMetadata {
- get { throw new NotImplementedException (); }
- }
-
- public int DirectMetadataCount {
- get { throw new NotImplementedException (); }
- }
-
- public string EvaluatedInclude {
- get { throw new NotImplementedException (); }
- }
-
- public bool IsImported {
- get { throw new NotImplementedException (); }
- }
-
- public string ItemType {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public ICollection<ProjectMetadata> Metadata {
- get { throw new NotImplementedException (); }
- }
-
- public int MetadataCount {
- get { throw new NotImplementedException (); }
- }
-
- public Project Project {
- get { throw new NotImplementedException (); }
- }
-
- public string UnevaluatedInclude {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public ProjectItemElement Xml { get; private set; }
-
- }
+ [DebuggerDisplay ("{ItemType}={EvaluatedInclude} [{UnevaluatedInclude}] #DirectMetadata={DirectMetadataCount}")]
+ public class ProjectItem
+ {
+ internal ProjectItem (Project project, ProjectItemElement xml, string evaluatedInclude)
+ {
+ this.project = project;
+ this.xml = xml;
+ if (project.ItemDefinitions.ContainsKey (ItemType))
+ foreach (var md in project.ItemDefinitions [ItemType].Metadata)
+ metadata.Add (md);
+ foreach (var md in xml.Metadata)
+ metadata.Add (new ProjectMetadata (project, ItemType, metadata, m => metadata.Remove (m), md));
+ this.evaluated_include = evaluatedInclude;
+ is_imported = project.ProjectCollection.OngoingImports.Any ();
+ }
+
+ readonly Project project;
+ readonly ProjectItemElement xml;
+ readonly List<ProjectMetadata> metadata = new List<ProjectMetadata> ();
+ readonly bool is_imported;
+ readonly string evaluated_include;
+
+ internal string RecursiveDir { get; set; }
+
+ public ProjectMetadata GetMetadata (string name)
+ {
+ return metadata.FirstOrDefault (m => m.Name == name);
+ }
+
+ public string GetMetadataValue (string name)
+ {
+ if (name == null)
+ throw new ArgumentNullException ("name");
+ var wk = ProjectCollection.GetWellKnownMetadata (name, EvaluatedInclude, project.GetFullPath, RecursiveDir);
+ if (wk != null)
+ return wk;
+ var m = GetMetadata (name);
+ return m != null ? m.EvaluatedValue : string.Empty;
+ }
+
+ public bool HasMetadata (string name)
+ {
+ return GetMetadata (name) != null;
+ }
+
+ public bool RemoveMetadata (string name)
+ {
+ var m = GetMetadata (name);
+ if (m == null)
+ return false;
+ return metadata.Remove (m);
+ }
+
+ public void Rename (string name)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public ProjectMetadata SetMetadataValue (string name, string unevaluatedValue)
+ {
+ // This has to do several tasks:
+ // - it cannot directly change Xml.Metadata because the ProjectItemElement might be shared
+ // among multiple ProjectItems.
+ // - hence it has to create another ProjectItemElement instance and add it to the project
+ // XML construction, with specific Include value that is assigned to this instance, and
+ // metadata values that are assigned to this instance.
+ throw new NotImplementedException ();
+ }
+
+ public IEnumerable<ProjectMetadata> DirectMetadata {
+ get {
+ var list = new List<ProjectMetadata> ();
+ foreach (var xm in xml.Metadata)
+ yield return new ProjectMetadata (project, ItemType, list, p => list.Remove (p), xm);
+ }
+ }
+
+ public int DirectMetadataCount {
+ get { return xml.Metadata.Count; }
+ }
+
+ public string EvaluatedInclude {
+ get { return evaluated_include; }
+ }
+
+ public bool IsImported {
+ get { return is_imported; }
+ }
+
+ public string ItemType {
+ get { return Xml.ItemType; }
+ set { Xml.ItemType = value; }
+ }
+
+ public ICollection<ProjectMetadata> Metadata {
+ get { return metadata; }
+ }
+
+ public int MetadataCount {
+ get { return metadata.Count; }
+ }
+
+ public Project Project {
+ get { return project; }
+ }
+
+ public string UnevaluatedInclude {
+ get { return Xml.Include; }
+ set { Xml.Include = value; }
+ }
+
+ public ProjectItemElement Xml {
+ get { return xml; }
+ }
+ }
}
//
// Author:
// Rolf Bjarne Kvinge (rolf@xamarin.com)
+// Atsushi Enomoto (atsushi@xamarin.com)
//
-// Copyright (C) 2011 Xamarin Inc.
+// Copyright (C) 2011,2013 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
//
using System;
+using System.Collections.Generic;
+using Microsoft.Build.Construction;
namespace Microsoft.Build.Evaluation
{
- public class ProjectItemDefinition
- {
- private ProjectItemDefinition ()
- {
- throw new NotImplementedException ();
- }
- }
-}
+ public class ProjectItemDefinition
+ {
+ internal ProjectItemDefinition (Project project, string itemType)
+ {
+ this.project = project;
+ this.item_type = itemType;
+ }
+
+ Project project;
+ string item_type;
+ List<ProjectMetadata> metadata = new List<ProjectMetadata> ();
+
+ public string ItemType {
+ get { return item_type; }
+ }
+ public IEnumerable<ProjectMetadata> Metadata {
+ get { return metadata; }
+ }
+
+ public int MetadataCount {
+ get { return metadata.Count; }
+ }
+
+ public Project Project {
+ get { return project; }
+ }
+
+ internal void AddItems (ProjectItemDefinitionElement xml)
+ {
+ foreach (var item in xml.Metadata)
+ metadata.Add (new ProjectMetadata (project, ItemType, metadata, m => metadata.Remove (m), item));
+ }
+ }
+}
//
// Author:
// Rolf Bjarne Kvinge (rolf@xamarin.com)
+// Atsushi Enomoto (atsushi@xamarin.com)
//
-// Copyright (C) 2011 Xamarin Inc.
+// Copyright (C) 2011,2013 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
//
using Microsoft.Build.Construction;
-
using System;
+using System.Collections.Generic;
+using System.Linq;
namespace Microsoft.Build.Evaluation
{
- public class ProjectMetadata
- {
- private ProjectMetadata ()
- {
- throw new NotImplementedException ();
- }
+ public class ProjectMetadata
+ {
+ internal ProjectMetadata (Project project, string itemType, IEnumerable<ProjectMetadata> existingMetadata, Action<ProjectMetadata> remover, ProjectMetadataElement xml)
+ {
+ this.xml = xml;
+ this.project = project;
+ item_type = itemType;
+ predecessor = existingMetadata.FirstOrDefault (m => m.Name == xml.Name);
+ if (predecessor != null)
+ remover (predecessor);
+ is_imported = Project.ProjectCollection.OngoingImports.Any ();
+ }
+
+ readonly Project project;
+ readonly string item_type;
+ readonly ProjectMetadataElement xml;
+ readonly ProjectMetadata predecessor;
+ readonly bool is_imported;
- public string EvaluatedValue {
- get { throw new NotImplementedException (); }
- }
+ public string EvaluatedValue {
+ get { return project.ExpandString (xml.Value); }
+ }
- public bool IsImported {
- get { throw new NotImplementedException (); }
- }
+ public bool IsImported {
+ get { return is_imported; }
+ }
- public string ItemType {
- get { throw new NotImplementedException (); }
- }
+ public string ItemType {
+ get { return item_type; }
+ }
- public string Name {
- get { throw new NotImplementedException (); }
- }
+ public string Name {
+ get { return xml.Name; }
+ }
- public ProjectMetadata Predecessor {
- get { throw new NotImplementedException (); }
- }
+ public ProjectMetadata Predecessor {
+ get { return predecessor; }
+ }
- public Project Project {
- get { throw new NotImplementedException (); }
- }
+ public Project Project {
+ get { return project; }
+ }
- public string UnevaluatedValue {
- get { throw new NotImplementedException (); }
- }
+ public string UnevaluatedValue {
+ get { return xml.Value; }
+ }
- public ProjectMetadataElement Xml {
- get { throw new NotImplementedException (); }
- }
- }
+ public ProjectMetadataElement Xml {
+ get { return xml; }
+ }
+ }
}
//
// Author:
// Rolf Bjarne Kvinge (rolf@xamarin.com)
+// Atsushi Enomoto (atsushi@xamarin.com)
//
-// Copyright (C) 2011 Xamarin Inc.
+// Copyright (C) 2011,2013 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
//
using System;
+using System.Linq;
using Microsoft.Build.Construction;
+using Microsoft.Build.Internal;
+using System.Collections.Generic;
+using System.Reflection;
+using System.IO;
namespace Microsoft.Build.Evaluation
{
// members are abstract and had been there since 4.0.
// I take this as doc bug, as non-abstract to abstract is a
// breaking change and I'd rather believe API designer's sanity.
- public abstract class ProjectProperty
- {
- internal ProjectProperty () // hide default ctor
+ public abstract class ProjectProperty
+ {
+ internal ProjectProperty (Project project) // hide default ctor
{
+ Project = project;
}
- public string EvaluatedValue {
- get {
- throw new NotImplementedException ();
- }
- }
+ public string EvaluatedValue {
+ get { return InternalEvaluatedValue; }
+ }
public abstract bool IsEnvironmentProperty { get; }
+
public abstract bool IsGlobalProperty { get; }
+
+ [MonoTODO]
public abstract bool IsImported { get; }
+
public abstract bool IsReservedProperty { get; }
- public string Name {
- get {
- throw new NotImplementedException ();
- }
+ internal virtual bool IsWellKnownProperty {
+ get { return false; }
}
+ public abstract string Name { get; }
+
public abstract ProjectProperty Predecessor { get; }
- public Project Project {
+ public Project Project { get; private set; }
+
+ public abstract string UnevaluatedValue { get; set; }
+
+ public abstract ProjectPropertyElement Xml { get; }
+
+ internal abstract string InternalEvaluatedValue { get; }
+ }
+
+ // copy from MS.Build.Engine/BuildProperty.cs
+ internal enum PropertyType {
+ Reserved,
+ Global,
+ Normal,
+ Environment
+ }
+
+ internal abstract class BaseProjectProperty : ProjectProperty
+ {
+ public BaseProjectProperty (Project project, PropertyType propertyType, string name)
+ : base (project)
+ {
+ property_type = propertyType;
+ this.name = name;
+ predecessor = project.Properties.FirstOrDefault (p => p.Name == name);
+ if (predecessor != null)
+ project.RemoveProperty (predecessor);
+ }
+
+ PropertyType property_type;
+
+ readonly string name;
+ public override string Name {
+ get { return name; }
+ }
+
+ public override bool IsEnvironmentProperty {
+ get { return property_type == PropertyType.Environment; }
+ }
+ public override bool IsGlobalProperty {
+ get { return property_type == PropertyType.Global; }
+ }
+ public override bool IsImported {
+ get { return false; }
+ }
+ public override bool IsReservedProperty {
+ get { return property_type == PropertyType.Reserved; }
+ }
+ readonly ProjectProperty predecessor;
+ public override ProjectProperty Predecessor {
+ get { return predecessor; }
+ }
+ }
+
+ internal abstract class ImmutableProjectProperty : BaseProjectProperty
+ {
+ public ImmutableProjectProperty (Project project, PropertyType propertyType, string name)
+ : base (project, propertyType, name)
+ {
+ }
+
+ internal override string InternalEvaluatedValue {
+ get { return UnevaluatedValue; }
+ }
+ }
+
+ internal abstract class MutableProjectProperty : BaseProjectProperty
+ {
+ public MutableProjectProperty (Project project, PropertyType propertyType, string name)
+ : base (project, propertyType, name)
+ {
+ }
+
+ string evaluated_value; // see UpdateEvaluatedValue().
+ internal void UpdateEvaluatedValue ()
+ {
+ evaluated_value = Project.ExpandString (UnevaluatedValue);
+ }
+
+ internal override string InternalEvaluatedValue {
+ get { return evaluated_value; }
+ }
+ }
+
+ internal class XmlProjectProperty : MutableProjectProperty
+ {
+ public XmlProjectProperty (Project project, ProjectPropertyElement xml, PropertyType propertyType, bool isImported)
+ : base (project, propertyType, xml.Name)
+ {
+ this.xml = xml;
+ this.is_imported = isImported;
+ UpdateEvaluatedValue ();
+ }
+
+ readonly ProjectPropertyElement xml;
+ readonly bool is_imported;
+
+ public override bool IsImported {
+ get { return is_imported; }
+ }
+
+ public override string UnevaluatedValue {
+ get { return xml.Value; }
+ set { xml.Value = value; }
+ }
+
+ public override ProjectPropertyElement Xml {
+ get { return xml; }
+ }
+ }
+
+ internal class EnvironmentProjectProperty : ImmutableProjectProperty
+ {
+ static string extensions_path;
+ internal static string DefaultExtensionsPath {
get {
- throw new NotImplementedException ();
+ if (extensions_path == null) {
+ // NOTE: code from mcs/tools/gacutil/driver.cs
+ PropertyInfo gac = typeof (System.Environment).GetProperty (
+ "GacPath", BindingFlags.Static | BindingFlags.NonPublic);
+
+ if (gac != null) {
+ MethodInfo get_gac = gac.GetGetMethod (true);
+ string gac_path = (string) get_gac.Invoke (null, null);
+ extensions_path = Path.GetFullPath (Path.Combine (
+ gac_path, Path.Combine ("..", "xbuild")));
+ }
+ }
+ return extensions_path;
}
}
+
+ public EnvironmentProjectProperty (Project project, string name, string value, bool wellknown = false)
+ : base (project, PropertyType.Environment, name)
+ {
+ this.value = value;
+ this.wellknown = wellknown;
+ }
+
+ readonly string value;
+ readonly bool wellknown;
- public abstract string UnevaluatedValue { get; set; }
- public abstract ProjectPropertyElement Xml { get; }
- }
-}
+ internal override bool IsWellKnownProperty {
+ get { return wellknown; }
+ }
+ // It can override possible another environment vairable property BUT never gives Predecessor.
+ public override ProjectProperty Predecessor {
+ get { return null; }
+ }
+
+ public override string UnevaluatedValue {
+ get { return value; }
+ set { throw new InvalidOperationException (string.Format ("You cannot change value of environment property '{0}'.", Name)); }
+ }
+ public override ProjectPropertyElement Xml {
+ get { return null; }
+ }
+ }
+
+ internal class GlobalProjectProperty : ImmutableProjectProperty
+ {
+ public GlobalProjectProperty (Project project, string name, string value)
+ : base (project, PropertyType.Global, name)
+ {
+ this.value = value;
+ }
+
+ readonly string value;
+
+ public override string UnevaluatedValue {
+ get { return value; }
+ set { throw new InvalidOperationException (string.Format ("You cannot change value of global property '{0}'.", Name)); }
+ }
+ public override ProjectPropertyElement Xml {
+ get { return null; }
+ }
+ }
+
+ internal class ManuallyAddedProjectProperty : MutableProjectProperty
+ {
+ public ManuallyAddedProjectProperty (Project project, string name, string value)
+ : base (project, PropertyType.Normal, name)
+ {
+ this.UnevaluatedValue = value;
+ }
+
+ public override string UnevaluatedValue { get; set; }
+
+ public override ProjectPropertyElement Xml {
+ get { return null; }
+ }
+ }
+
+ internal class ReservedProjectProperty : ImmutableProjectProperty
+ {
+ public ReservedProjectProperty (Project project, string name, Func<string> value)
+ : base (project, PropertyType.Reserved, name)
+ {
+ this.value = value;
+ }
+
+ // make sure it does not give access to any possible attempted overrrides.
+ public override ProjectProperty Predecessor {
+ get { return null; }
+ }
+
+ readonly Func<string> value;
+ public override string UnevaluatedValue {
+ get { return value (); }
+ set { throw new InvalidOperationException (string.Format ("You cannot change value of reserved property '{0}'.", Name)); }
+ }
+
+ public override ProjectPropertyElement Xml {
+ get { return null; }
+ }
+ }
+}
--- /dev/null
+//
+// ProjectXmlChangedEventArgs.cs
+//
+// Author:
+// Atsushi Enomoto <atsushi@xamarin.com>
+//
+// Copyright (C) 2013 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using Microsoft.Build.Construction;
+using System;
+using System.Linq;
+
+namespace Microsoft.Build.Evaluation
+{
+ public class ProjectXmlChangedEventArgs : EventArgs
+ {
+ internal ProjectXmlChangedEventArgs (ProjectRootElement projectXml, string reason)
+ {
+ ProjectXml = projectXml;
+ Reason = reason;
+ }
+ public ProjectRootElement ProjectXml { get; private set; }
+ public string Reason { get; private set; }
+ }
+}
//
using Microsoft.Build.Construction;
-
using System;
namespace Microsoft.Build.Evaluation
{
- [System.Runtime.InteropServices.StructLayout (System.Runtime.InteropServices.LayoutKind.Sequential)]
- public struct ResolvedImport
- {
- private ProjectImportElement import;
- private ProjectRootElement root;
+ [System.Runtime.InteropServices.StructLayout (System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public struct ResolvedImport
+ {
+ internal ResolvedImport (ProjectImportElement import, ProjectRootElement root, bool isImported)
+ {
+ this.import = import;
+ this.root = root;
+ this.imported = isImported;
+ }
+
+ readonly ProjectImportElement import;
+ readonly ProjectRootElement root;
+ readonly bool imported;
- public ProjectImportElement ImportingElement {
- get { return import; }
- }
+ public ProjectImportElement ImportingElement {
+ get { return import; }
+ }
- public ProjectRootElement ImportedProject {
- get { return root; }
- }
- }
+ public ProjectRootElement ImportedProject {
+ get { return root; }
+ }
+
+ public bool IsImported {
+ get { return imported; }
+ }
+ }
}
--- /dev/null
+using System;
+using System.Collections.Generic;
+using Microsoft.Build.Execution;
+
+namespace Microsoft.Build.Evaluation
+{
+ #if NET_4_5
+ public
+ #endif
+ class SubToolset
+ {
+ internal SubToolset (IDictionary<string, ProjectPropertyInstance> properties, string subToolsetVersion)
+ {
+ Properties = properties;
+ SubToolsetVersion = subToolsetVersion;
+ }
+
+ public IDictionary<string, ProjectPropertyInstance> Properties { get; private set; }
+ public string SubToolsetVersion { get; private set; }
+ }
+}
+
//
// Author:
// Rolf Bjarne Kvinge (rolf@xamarin.com)
+// Atsushi Enomoto (atsushi@xamarin.com)
//
-// Copyright (C) 2011 Xamarin Inc.
+// Copyright (C) 2011,2013 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
using System;
using System.Collections.Generic;
-
+using System.Linq;
using Microsoft.Build.Execution;
namespace Microsoft.Build.Evaluation
{
- public class Toolset
- {
- public Toolset (string toolsVersion, string toolsPath,
- ProjectCollection projectCollection, string msbuildOverrideTasksPath)
- {
- throw new NotImplementedException ();
- }
-
- public Toolset (string toolsVersion, string toolsPath,
- IDictionary<string, string> buildProperties, ProjectCollection projectCollection,
- string msbuildOverrideTasksPath)
- {
- throw new NotImplementedException ();
- }
-
- public IDictionary<string, ProjectPropertyInstance> Properties {
- get { throw new NotImplementedException (); }
- }
-
- public string ToolsPath {
- get { throw new NotImplementedException (); }
- }
-
- public string ToolsVersion {
- get { throw new NotImplementedException (); }
- }
- }
+ public class Toolset
+ {
+ public Toolset (string toolsVersion, string toolsPath,
+ ProjectCollection projectCollection, string msbuildOverrideTasksPath)
+ : this (toolsVersion, toolsPath, null, projectCollection, msbuildOverrideTasksPath)
+ {
+ }
+
+ public Toolset (string toolsVersion, string toolsPath,
+ IDictionary<string, string> buildProperties, ProjectCollection projectCollection,
+ string msbuildOverrideTasksPath)
+ : this (toolsVersion, toolsPath, buildProperties, projectCollection, null, msbuildOverrideTasksPath)
+ {
+ }
+
+#if NET_4_5
+ public
+#endif
+ Toolset (string toolsVersion, string toolsPath, IDictionary<string, string> buildProperties,
+ ProjectCollection projectCollection, IDictionary<string, SubToolset> subToolsets,
+ string msbuildOverrideTasksPath)
+ {
+ ToolsVersion = toolsVersion;
+ ToolsPath = toolsPath;
+ Properties =
+ buildProperties == null ?
+ new Dictionary<string, ProjectPropertyInstance> () :
+ buildProperties.Select (p => new ProjectPropertyInstance (p.Key, true, p.Value)).ToDictionary (e => e.Name);
+#if NET_4_5
+ SubToolsets = subToolsets ?? new Dictionary<string, SubToolset> ();
+#endif
+ }
+
+#if NET_4_5
+ public string DefaultSubToolsetVersion { get; private set; }
+ public IDictionary<string, SubToolset> SubToolsets { get; private set; }
+#endif
+
+ public IDictionary<string, ProjectPropertyInstance> Properties { get; private set; }
+
+ public string ToolsPath { get; private set; }
+
+ public string ToolsVersion { get; private set; }
+ }
}
--- /dev/null
+using System;
+using System.Runtime.Serialization;
+
+namespace Microsoft.Build.Exceptions
+{
+ public class BuildAbortedException : Exception
+ {
+ public BuildAbortedException ()
+ : this ("Build aborted")
+ {
+ }
+
+ public BuildAbortedException (string message)
+ : base (message)
+ {
+ }
+
+ public BuildAbortedException (string message, Exception innerException)
+ : base (message, innerException)
+ {
+ }
+ protected BuildAbortedException (SerializationInfo info, StreamingContext context)
+ : base (info, context)
+ {
+ ErrorCode = info.GetString ("errorCode");
+ }
+
+ internal BuildAbortedException (string message, string errorCode)
+ : base (message + " error code: " + errorCode)
+ {
+ ErrorCode = errorCode;
+ }
+
+ public string ErrorCode { get; private set; }
+
+ public override void GetObjectData (SerializationInfo info, StreamingContext context)
+ {
+ base.GetObjectData (info, context);
+ info.AddValue ("errorCode", ErrorCode);
+ }
+ }
+}
+
--- /dev/null
+using System;
+using System.Runtime.Serialization;
+using Microsoft.Build.Framework;
+
+namespace Microsoft.Build.Exceptions
+{
+ public class InternalLoggerException : Exception
+ {
+ public InternalLoggerException ()
+ : this ("Build aborted")
+ {
+ }
+
+ public InternalLoggerException (string message)
+ : base (message)
+ {
+ }
+
+ public InternalLoggerException (string message, Exception innerException)
+ : base (message, innerException)
+ {
+ }
+
+ internal InternalLoggerException (string message, Exception innerException, BuildEventArgs buildEventArgs, string errorCode, string helpKeyword, bool initializationException)
+ : base (message, innerException)
+ {
+ BuildEventArgs = buildEventArgs;
+ ErrorCode = errorCode;
+ HelpKeyword = helpKeyword;
+ InitializationException = initializationException;
+ }
+
+ internal InternalLoggerException (SerializationInfo info, StreamingContext context)
+ : base (info, context)
+ {
+ BuildEventArgs = (BuildEventArgs) info.GetValue ("buildEventArgs", typeof (BuildEventArgs));
+ ErrorCode = info.GetString ("errorCode");
+ HelpKeyword = info.GetString ("helpKeyword");
+ InitializationException = info.GetBoolean ("initializationException");
+ }
+
+ public BuildEventArgs BuildEventArgs { get; private set; }
+ public string ErrorCode { get; private set; }
+ public string HelpKeyword { get; private set; }
+ public bool InitializationException { get; private set; }
+
+ public override void GetObjectData (SerializationInfo info, StreamingContext context)
+ {
+ base.GetObjectData (info, context);
+ info.AddValue ("buildEventArgs", BuildEventArgs);
+ info.AddValue ("errorCode", ErrorCode);
+ info.AddValue ("helpKeyword", HelpKeyword);
+ info.AddValue ("initializationException", InitializationException);
+ }
+ }
+}
+
using System;
using System.Runtime.Serialization;
+using Microsoft.Build.Construction;
+using Microsoft.Build.Internal.Expressions;
namespace Microsoft.Build.Exceptions
{
: base(message, innerException)
{
}
+ internal InvalidProjectFileException (ILocation start, string message,
+ string errorSubcategory = null, string errorCode = null, string helpKeyword = null)
+ : this (start != null ? start.File : null, 0, start != null ? start.Column : 0, 0, 0, message, errorSubcategory, errorCode, helpKeyword)
+ {
+ }
+ internal InvalidProjectFileException (ElementLocation start, ElementLocation end, string message,
+ string errorSubcategory = null, string errorCode = null, string helpKeyword = null)
+ : this (start != null ? start.File : null, start != null ? start.Line : 0, start != null ? start.Column : 0,
+ end != null ? end.Line : 0, end != null ? end.Column : 0,
+ message, errorSubcategory, errorCode, helpKeyword)
+ {
+ }
public InvalidProjectFileException (string projectFile, int lineNumber, int columnNumber,
int endLineNumber, int endColumnNumber, string message,
string errorSubcategory, string errorCode, string helpKeyword)
+ : base(message)
{
+ ProjectFile = projectFile;
+ LineNumber = lineNumber;
+ ColumnNumber = columnNumber;
+ EndLineNumber = endLineNumber;
+ EndColumnNumber = endColumnNumber;
+ ErrorSubcategory = errorSubcategory;
+ ErrorCode = errorCode;
+ HelpKeyword = helpKeyword;
}
public override void GetObjectData (SerializationInfo info, StreamingContext context)
{
public string HelpKeyword { get; private set; }
public int LineNumber { get; private set; }
public override string Message {
- get { return ProjectFile == null ? base.Message : base.Message + " " + ProjectFile; }
+ get { return ProjectFile == null ? base.Message : base.Message + " " + GetLocation (); }
}
public string ProjectFile { get; private set; }
+
+ string GetLocation ()
+ {
+ string start = LineNumber == 0 ? string.Empty : ColumnNumber > 0 ? string.Format ("{0},{1}", LineNumber, ColumnNumber) : string.Format ("{0}", LineNumber);
+ string end = EndLineNumber == 0 ? string.Empty : EndColumnNumber > 0 ? string.Format (" - {0},{1}", EndLineNumber, EndColumnNumber) : string.Format (" - {0}", EndLineNumber);
+ return LineNumber == 0 ? ProjectFile : String.Format (" at: {0} ({1}{2})", ProjectFile, start, end);
+ }
}
}
--- /dev/null
+using System;
+using System.Runtime.Serialization;
+
+namespace Microsoft.Build.Exceptions
+{
+ public class InvalidToolsetDefinitionException : Exception
+ {
+ public InvalidToolsetDefinitionException ()
+ : this ("Invalid toolset definition")
+ {
+ }
+
+ public InvalidToolsetDefinitionException (string message)
+ : base (message)
+ {
+ }
+
+ public InvalidToolsetDefinitionException (string message, Exception innerException)
+ : base (message, innerException)
+ {
+ }
+ protected InvalidToolsetDefinitionException (SerializationInfo info, StreamingContext context)
+ : base (info, context)
+ {
+ ErrorCode = info.GetString ("errorCode");
+ }
+
+ internal InvalidToolsetDefinitionException (string message, string errorCode)
+ : base (message + " error code: " + errorCode)
+ {
+ ErrorCode = errorCode;
+ }
+
+ public string ErrorCode { get; private set; }
+
+ public override void GetObjectData (SerializationInfo info, StreamingContext context)
+ {
+ base.GetObjectData (info, context);
+ info.AddValue ("errorCode", ErrorCode);
+ }
+ }
+}
//
// Author:
// Rolf Bjarne Kvinge (rolf@xamarin.com)
+// Atsushi Enomoto (atsushi@xamarin.com)
//
-// Copyright (C) 2011 Xamarin Inc.
+// Copyright (C) 2011,2013 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
//
using Microsoft.Build.Evaluation;
-
using System;
+using System.Collections.Generic;
+using System.Threading;
+using Microsoft.Build.Internal;
+using System.Linq;
namespace Microsoft.Build.Execution
{
- public class BuildManager
- {
- public BuildManager ()
- {
- throw new NotImplementedException ();
- }
+ public class BuildManager
+ {
+ static BuildManager default_manager = new BuildManager ();
- public BuildManager (string hostName)
- {
- throw new NotImplementedException ();
- }
+ public static BuildManager DefaultBuildManager {
+ get { return default_manager; }
+ }
+
+ public BuildManager ()
+ {
+ }
- public void BeginBuild (BuildParameters parameters)
- {
- throw new NotImplementedException ();
- }
+ public BuildManager (string hostName)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public void Dispose ()
+ {
+ WaitHandle.WaitAll (submissions.Select (s => s.WaitHandle).ToArray ());
+ BuildNodeManager.Stop ();
+ }
- public BuildResult Build (BuildParameters parameters, BuildRequestData requestData)
- {
- throw new NotImplementedException ();
- }
+ ~BuildManager ()
+ {
+ // maybe processes created by out-of-process nodes should be signaled.
+ BuildNodeManager.Stop ();
+ }
- public BuildResult BuildRequest (BuildRequestData requestData)
- {
- throw new NotImplementedException ();
- }
+ readonly List<BuildSubmission> submissions = new List<BuildSubmission> ();
+
+ BuildParameters ongoing_build_parameters;
+
+ internal BuildParameters OngoingBuildParameters {
+ get { return ongoing_build_parameters; }
+ }
- public void CancelAllSubmissions ()
- {
- throw new NotImplementedException ();
- }
+ public void BeginBuild (BuildParameters parameters)
+ {
+ if (ongoing_build_parameters != null)
+ throw new InvalidOperationException ("There is already ongoing build");
+ ongoing_build_parameters = parameters.Clone ();
+ }
- public void EndBuild ()
- {
- throw new NotImplementedException ();
- }
+ public BuildResult Build (BuildParameters parameters, BuildRequestData requestData)
+ {
+ BeginBuild (parameters);
+ var ret = BuildRequest (requestData);
+ EndBuild ();
+ return ret;
+ }
- public ProjectInstance GetProjectInstanceForBuild (Project project)
- {
- throw new NotImplementedException ();
- }
+ public BuildResult BuildRequest (BuildRequestData requestData)
+ {
+ var sub = PendBuildRequest (requestData);
+ sub.Execute ();
+ return sub.BuildResult;
+ }
+
+ public void CancelAllSubmissions ()
+ {
+ foreach (var sub in submissions) {
+ try {
+ if (!sub.IsCompleted)
+ sub.Cancel ();
+ } catch (InvalidOperationException) {
+ // some submissions could be already done during this iteration. Ignore that.
+ }
+ }
+ submissions.Clear ();
+ }
- public BuildSubmission PendBuildRequest (BuildRequestData requestData)
- {
- throw new NotImplementedException ();
- }
+ public void EndBuild ()
+ {
+ if (ongoing_build_parameters == null)
+ throw new InvalidOperationException ("Build has not started");
+ if (submissions.Count > 0)
+ WaitHandle.WaitAll (submissions.Select (s => s.WaitHandle).ToArray ());
+ BuildNodeManager.Stop ();
+ ongoing_build_parameters = null;
+ }
+
+ Dictionary<Project,ProjectInstance> instances = new Dictionary<Project, ProjectInstance> ();
- public void ResetCaches ()
- {
- throw new NotImplementedException ();
- }
+ public ProjectInstance GetProjectInstanceForBuild (Project project)
+ {
+ if (project == null)
+ throw new ArgumentNullException ("project");
+ if (project.FullPath == null)
+ throw new ArgumentNullException ("project", "FullPath parameter in the project cannot be null.");
+ if (project.FullPath == string.Empty)
+ throw new ArgumentException ("FullPath parameter in the project cannot be empty.", "project");
+ // other than that, any invalid path character is accepted...
+
+ return GetProjectInstanceForBuildInternal (project);
+ }
+
+ internal ProjectInstance GetProjectInstanceForBuildInternal (Project project)
+ {
+ if (!instances.ContainsKey (project))
+ instances [project] = project.CreateProjectInstance ();
+ return instances [project];
+ }
- public static BuildManager DefaultBuildManager {
- get { throw new NotImplementedException (); }
- }
- }
-}
+ public BuildSubmission PendBuildRequest (BuildRequestData requestData)
+ {
+ if (ongoing_build_parameters == null)
+ throw new InvalidOperationException ("This method cannot be called before calling BeginBuild method.");
+ var sub = new BuildSubmission (this, requestData);
+ submissions.Add (sub);
+ return sub;
+ }
+ public void ResetCaches ()
+ {
+ if (OngoingBuildParameters != null)
+ throw new InvalidOperationException ("Cannot reset caches while builds are in progress.");
+
+ BuildNodeManager.ResetCaches ();
+ }
+
+ BuildNodeManager build_node_manager;
+
+ internal BuildNodeManager BuildNodeManager {
+ get {
+ if (build_node_manager == null)
+ build_node_manager = new BuildNodeManager (this);
+ return build_node_manager;
+ }
+ }
+ }
+}
//
// Author:
// Rolf Bjarne Kvinge (rolf@xamarin.com)
+// Atsushi Enomoto (atsushi@xamarin.com)
//
-// Copyright (C) 2011 Xamarin Inc.
+// Copyright (C) 2011,2013 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
using Microsoft.Build.Evaluation;
using Microsoft.Build.Framework;
using Microsoft.Build.Logging;
-
using System;
using System.Collections.Generic;
using System.Globalization;
+using System.Linq;
using System.Threading;
+using System.Collections;
namespace Microsoft.Build.Execution
{
- public class BuildParameters
- {
- public BuildParameters ()
- {
- throw new NotImplementedException ();
- }
-
- public BuildParameters (ProjectCollection projectCollection)
- {
- throw new NotImplementedException ();
- }
-
- public BuildParameters Clone ()
- {
- throw new NotImplementedException ();
- }
-
- public Toolset GetToolset (string toolsVersion)
- {
- throw new NotImplementedException ();
- }
-
- public ThreadPriority BuildThreadPriority {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public CultureInfo Culture {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public string DefaultToolsVersion {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public bool DetailedSummary {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public bool EnableNodeReuse {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public IDictionary<string, string> EnvironmentProperties {
- get { throw new NotImplementedException (); }
- }
-
- public IEnumerable<ForwardingLoggerRecord> ForwardingLoggers {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public IDictionary<string, string> GlobalProperties {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public HostServices HostServices {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public bool LegacyThreadingSemantics { get; set; }
-
- public IEnumerable<ILogger> Loggers {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public int MaxNodeCount {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public int MemoryUseLimit {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public string NodeExeLocation {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public bool OnlyLogCriticalEvents {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public bool ResetCaches { get; set; }
-
- public bool SaveOperatingEnvironment {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public ToolsetDefinitionLocations ToolsetDefinitionLocations {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public ICollection<Toolset> Toolsets {
- get { throw new NotImplementedException (); }
- }
-
- public CultureInfo UICulture {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public bool UseSynchronousLogging {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
- }
+ public class BuildParameters
+ {
+ public BuildParameters ()
+ : this (new ProjectCollection ())
+ {
+ }
+
+ public BuildParameters (ProjectCollection projectCollection)
+ {
+ if (projectCollection == null)
+ throw new ArgumentNullException ("projectCollection");
+ projects = projectCollection;
+
+ EnableNodeReuse = true;
+ Culture = CultureInfo.CurrentCulture;
+ UICulture = CultureInfo.CurrentUICulture;
+ MaxNodeCount = projectCollection.MaxNodeCount;
+
+ // these properties are copied, while some members (such as Loggers) are not.
+ this.DefaultToolsVersion = projectCollection.DefaultToolsVersion;
+ this.ToolsetDefinitionLocations = projectCollection.ToolsetLocations;
+ this.GlobalProperties = projectCollection.GlobalProperties;
+ environment_properties = new Dictionary<string,string> ();
+ foreach (DictionaryEntry p in Environment.GetEnvironmentVariables ())
+ environment_properties [(string) p.Key] = (string) p.Value;
+ }
+
+ readonly ProjectCollection projects;
+ Dictionary<string,string> environment_properties;
+
+ internal ProjectCollection ProjectCollection {
+ get { return projects; }
+ }
+
+ public BuildParameters Clone ()
+ {
+ var ret = (BuildParameters) MemberwiseClone ();
+ ret.ForwardingLoggers = ForwardingLoggers == null ? null : ForwardingLoggers.ToArray ();
+ ret.GlobalProperties = GlobalProperties == null ? null : GlobalProperties.ToDictionary (p => p.Key, p => p.Value);
+ ret.Loggers = Loggers == null ? null : new List<ILogger> (Loggers);
+ ret.environment_properties = new Dictionary<string, string> (environment_properties);
+ return ret;
+ }
+
+ public Toolset GetToolset (string toolsVersion)
+ {
+ // can return null.
+ return projects.Toolsets.FirstOrDefault (t => t.ToolsVersion == toolsVersion);
+ }
+
+ [MonoTODO]
+ public ThreadPriority BuildThreadPriority { get; set; }
+
+ [MonoTODO]
+ public CultureInfo Culture { get; set; }
+
+ public string DefaultToolsVersion { get; set; }
+
+ [MonoTODO]
+ public bool DetailedSummary { get; set; }
+
+ public bool EnableNodeReuse { get; set; }
+
+ [MonoTODO]
+ public IDictionary<string, string> EnvironmentProperties {
+ get { return environment_properties; }
+ }
+
+ [MonoTODO]
+ public IEnumerable<ForwardingLoggerRecord> ForwardingLoggers { get; set; }
+
+ [MonoTODO]
+ public IDictionary<string, string> GlobalProperties { get; set; }
+
+ public HostServices HostServices { get; set; }
+
+ [MonoTODO]
+ public bool LegacyThreadingSemantics { get; set; }
+
+ [MonoTODO]
+ public IEnumerable<ILogger> Loggers { get; set; }
+
+ [MonoTODO]
+ public int MaxNodeCount { get; set; }
+
+ [MonoTODO]
+ public int MemoryUseLimit { get; set; }
+
+ [MonoTODO]
+ public string NodeExeLocation { get; set; }
+
+ [MonoTODO]
+ public bool OnlyLogCriticalEvents { get; set; }
+
+ [MonoTODO]
+ public bool ResetCaches { get; set; }
+
+ [MonoTODO]
+ public bool SaveOperatingEnvironment { get; set; }
+
+ [MonoTODO]
+ public ToolsetDefinitionLocations ToolsetDefinitionLocations { get; set; }
+
+ [MonoTODO]
+ public ICollection<Toolset> Toolsets {
+ get { return projects.Toolsets; }
+ }
+
+ [MonoTODO]
+ public CultureInfo UICulture { get; set; }
+
+ [MonoTODO]
+ public bool UseSynchronousLogging { get; set; }
+ }
}
//
// Author:
// Rolf Bjarne Kvinge (rolf@xamarin.com)
+// Atsushi Enomoto (atsushi@xamarin.com)
//
-// Copyright (C) 2011 Xamarin Inc.
+// Copyright (C) 2011,2013 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
//
using System;
+using System.Linq;
using System.Collections.Generic;
namespace Microsoft.Build.Execution
{
- public class BuildRequestData
- {
- public BuildRequestData (ProjectInstance projectInstance, string[] targetsToBuild)
- : this (projectInstance, targetsToBuild, null, BuildRequestDataFlags.None)
- {
- }
+ public class BuildRequestData
+ {
+ public BuildRequestData (ProjectInstance projectInstance, string[] targetsToBuild)
+ : this (projectInstance, targetsToBuild, null, BuildRequestDataFlags.None)
+ {
+ }
- public BuildRequestData (ProjectInstance projectInstance, string[] targetsToBuild, HostServices hostServices)
- : this (projectInstance, targetsToBuild, hostServices, BuildRequestDataFlags.None)
- {
- }
+ public BuildRequestData (ProjectInstance projectInstance, string[] targetsToBuild, HostServices hostServices)
+ : this (projectInstance, targetsToBuild, hostServices, BuildRequestDataFlags.None)
+ {
+ }
- public BuildRequestData (ProjectInstance projectInstance, string[] targetsToBuild, HostServices hostServices,
- BuildRequestDataFlags flags)
- {
- throw new NotImplementedException ();
- }
+ public BuildRequestData (ProjectInstance projectInstance, string[] targetsToBuild, HostServices hostServices,
+ BuildRequestDataFlags flags)
+ {
+ ProjectInstance = projectInstance;
+ TargetNames = targetsToBuild;
+ HostServices = hostServices;
+ Flags = flags;
+ }
- public BuildRequestData (string projectFullPath, IDictionary<string, string> globalProperties,
- string toolsVersion, string[] targetsToBuild, HostServices hostServices)
- : this (projectFullPath, globalProperties, toolsVersion, targetsToBuild, hostServices, BuildRequestDataFlags.None)
- {
- }
+ public BuildRequestData (string projectFullPath, IDictionary<string, string> globalProperties,
+ string toolsVersion, string[] targetsToBuild, HostServices hostServices)
+ : this (projectFullPath, globalProperties, toolsVersion, targetsToBuild, hostServices, BuildRequestDataFlags.None)
+ {
+ }
- public BuildRequestData (string projectFullPath, IDictionary<string, string> globalProperties,
- string toolsVersion, string[] targetsToBuild, HostServices hostServices, BuildRequestDataFlags flags)
- {
- throw new NotImplementedException ();
- }
+ public BuildRequestData (string projectFullPath, IDictionary<string, string> globalProperties,
+ string toolsVersion, string[] targetsToBuild, HostServices hostServices, BuildRequestDataFlags flags)
+ : this (new ProjectInstance (projectFullPath, globalProperties, toolsVersion), targetsToBuild, hostServices, flags)
+ {
+ ExplicitlySpecifiedToolsVersion = toolsVersion;
+ }
- public string ExplicitlySpecifiedToolsVersion { get; private set; }
- public BuildRequestDataFlags Flags { get; private set; }
- public HostServices HostServices { get; private set; }
- public string ProjectFullPath { get; private set; }
- public ProjectInstance ProjectInstance { get; private set; }
- public ICollection<string> TargetNames { get; private set; }
+ public string ExplicitlySpecifiedToolsVersion { get; private set; }
- ICollection<ProjectPropertyInstance> GlobalProperties {
- get { throw new NotImplementedException (); }
- }
- }
+ [MonoTODO ("unused")]
+ public BuildRequestDataFlags Flags { get; private set; }
+
+ [MonoTODO ("unused")]
+ public HostServices HostServices { get; private set; }
+
+ public string ProjectFullPath {
+ get { return ProjectInstance.FullPath; }
+ }
+
+ [MonoTODO ("unused")]
+ public ProjectInstance ProjectInstance { get; private set; }
+
+ [MonoTODO]
+ public IEnumerable<string> PropertiesToTransfer { get; private set; }
+
+ [MonoTODO]
+ public ICollection<string> TargetNames { get; private set; }
+
+ ICollection<ProjectPropertyInstance> GlobalProperties {
+ get { return ProjectInstance.Properties.Where (p => ProjectInstance.GlobalProperties.Any (i => i.Key == p.Name)).ToArray (); } // we can use == as it should be identical match there.
+ }
+ }
}
using System;
using System.Collections.Generic;
+using System.Linq;
namespace Microsoft.Build.Execution
{
- public class BuildResult
- {
- public void AddResultsForTarget (string target, TargetResult result)
- {
- throw new NotImplementedException ();
- }
-
- public bool HasResultsForTarget (string target)
- {
- throw new NotImplementedException ();
- }
-
- public void MergeResults (BuildResult results)
- {
- throw new NotImplementedException ();
- }
-
- public bool CircularDependency {
- get { throw new NotImplementedException (); }
- }
-
- public int ConfigurationId {
- get { throw new NotImplementedException (); }
- }
-
- public Exception Exception {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public int GlobalRequestId {
- get { throw new NotImplementedException (); }
- }
-
- public ITargetResult this [string target] {
- get { throw new NotImplementedException (); }
- }
-
- public int NodeRequestId {
- get { throw new NotImplementedException (); }
- }
-
- public BuildResultCode OverallResult {
- get { throw new NotImplementedException (); }
- }
-
- public int ParentGlobalRequestId {
- get { throw new NotImplementedException (); }
- }
-
- public IDictionary<string, TargetResult> ResultsByTarget {
- get { throw new NotImplementedException (); }
- }
-
- public int SubmissionId {
- get { throw new NotImplementedException (); }
- }
-
- }
+ public class BuildResult
+ {
+ public BuildResult ()
+ {
+ ResultsByTarget = new Dictionary<string, TargetResult> ();
+ }
+
+ public void AddResultsForTarget (string target, TargetResult result)
+ {
+ ResultsByTarget.Add (target, result);
+ }
+
+ public bool HasResultsForTarget (string target)
+ {
+ return ResultsByTarget.ContainsKey (target);
+ }
+
+ public void MergeResults (BuildResult results)
+ {
+ if (ConfigurationId != results.ConfigurationId)
+ throw new InvalidOperationException ("Argument BuildResults have inconsistent ConfigurationId.");
+ if (GlobalRequestId != results.GlobalRequestId)
+ throw new InvalidOperationException ("Argument BuildResults have inconsistent GlobalRequestId.");
+ if (NodeRequestId != results.NodeRequestId)
+ throw new InvalidOperationException ("Argument BuildResults have inconsistent NodeRequestId.");
+ if (ParentGlobalRequestId != results.ParentGlobalRequestId)
+ throw new InvalidOperationException ("Argument BuildResults have inconsistent ParentGlobalRequestId.");
+ if (SubmissionId != results.SubmissionId)
+ throw new InvalidOperationException ("Argument BuildResults have inconsistent SubmissionId.");
+
+ CircularDependency |= results.CircularDependency;
+ Exception = Exception ?? results.Exception;
+ foreach (var p in results.ResultsByTarget)
+ ResultsByTarget.Add (p.Key, p.Value);
+ }
+
+ public bool CircularDependency { get; internal set; }
+
+ public int ConfigurationId { get; internal set; }
+
+ public Exception Exception { get; set; }
+
+ public int GlobalRequestId { get; internal set; }
+
+ public ITargetResult this [string target] {
+ get { return ResultsByTarget [target]; }
+ }
+
+ public int NodeRequestId { get; internal set; }
+
+ BuildResultCode? overall_result;
+ public BuildResultCode OverallResult {
+ get {
+ if (overall_result == null)
+ throw new InvalidOperationException ("Build has not finished");
+ return overall_result.Value;
+ }
+ internal set { overall_result = value; }
+ }
+
+ public int ParentGlobalRequestId { get; internal set; }
+
+ public IDictionary<string, TargetResult> ResultsByTarget { get; private set; }
+
+ public int SubmissionId { get; internal set; }
+ }
}
//
// Author:
// Rolf Bjarne Kvinge (rolf@xamarin.com)
+// Atsushi Enomoto (atsushi@xamarin.com)
//
-// Copyright (C) 2011 Xamarin Inc.
+// Copyright (C) 2011,2013 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
//
using System;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Linq;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Internal;
+using System.Collections.Generic;
namespace Microsoft.Build.Execution
{
- public class BuildSubmission
- {
- private BuildSubmission ()
- {
- throw new NotImplementedException ();
- }
- }
+ public class BuildSubmission
+ {
+ static Random rnd = new Random ();
+
+ internal BuildSubmission (BuildManager build, BuildRequestData requestData)
+ {
+ BuildManager = build;
+ this.request = requestData;
+ SubmissionId = rnd.Next ();
+ }
+
+ BuildRequestData request;
+ BuildSubmissionCompleteCallback callback;
+ bool is_started, is_completed, is_canceled;
+ ManualResetEvent wait_handle = new ManualResetEvent (true);
+
+ public object AsyncContext { get; private set; }
+ public BuildManager BuildManager { get; private set; }
+ public BuildResult BuildResult { get; set; }
+ public bool IsCompleted {
+ get { return is_completed; }
+ }
+ public int SubmissionId { get; private set; }
+ public WaitHandle WaitHandle {
+ get { return wait_handle; }
+ }
+
+ internal BuildRequestData BuildRequest {
+ get { return this.request; }
+ }
+
+ internal void Cancel ()
+ {
+ if (is_canceled)
+ throw new InvalidOperationException ("Build has already canceled");
+ is_canceled = true;
+ }
+
+ public BuildResult Execute ()
+ {
+ ExecuteAsync (null, null);
+ WaitHandle.WaitOne ();
+ return BuildResult;
+ }
+
+ internal BuildResult InternalExecute ()
+ {
+ BuildResult = new BuildResult () { SubmissionId = SubmissionId };
+ try {
+ var engine = new BuildEngine4 (this);
+ string toolsVersion = request.ExplicitlySpecifiedToolsVersion ?? request.ProjectInstance.ToolsVersion ?? BuildManager.OngoingBuildParameters.DefaultToolsVersion;
+ var outputs = new Dictionary<string,string> ();
+ engine.BuildProject (() => is_canceled, BuildResult, request.ProjectInstance, request.TargetNames, BuildManager.OngoingBuildParameters.GlobalProperties, outputs, toolsVersion);
+ } catch (Exception ex) {
+ BuildResult.Exception = ex;
+ BuildResult.OverallResult = BuildResultCode.Failure;
+ }
+ is_completed = true;
+ if (callback != null)
+ callback (this);
+ wait_handle.Set ();
+ return BuildResult;
+ }
+
+ public void ExecuteAsync (BuildSubmissionCompleteCallback callback, object context)
+ {
+ if (is_completed)
+ throw new InvalidOperationException ("Build has already completed");
+ if (is_canceled)
+ throw new InvalidOperationException ("Build has already canceled");
+ if (is_started)
+ throw new InvalidOperationException ("Build has already started");
+ is_started = true;
+ this.AsyncContext = context;
+ this.callback = callback;
+ wait_handle.Reset ();
+
+ BuildManager.BuildNodeManager.Enqueue (this);
+ }
+ }
}
--- /dev/null
+namespace Microsoft.Build.Execution
+{
+ public delegate void BuildSubmissionCompleteCallback (BuildSubmission submission);
+}
+
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-using Microsoft.Build.Framework;
using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Build.Framework;
namespace Microsoft.Build.Execution
{
- public class HostServices
- {
- public ITaskHost GetHostObject (string projectFile, string targetName, string taskName)
- {
- throw new NotImplementedException ();
- }
+ public class HostServices
+ {
+ class HostObjectRegistration
+ {
+ public string ProjectFile { get; set; }
+ public string TargetName { get; set; }
+ public string TaskName { get; set; }
+ public ITaskHost HostObject { get; set; }
+ }
+
+ readonly List<HostObjectRegistration> hosts = new List<HostObjectRegistration> ();
+ readonly Dictionary<string,NodeAffinity> node_affinities = new Dictionary<string, NodeAffinity> ();
+
+ HostObjectRegistration GetHostRegistration (string projectFile, string targetName, string taskName)
+ {
+ if (projectFile == null)
+ throw new ArgumentNullException ("projectFile");
+ if (targetName == null)
+ throw new ArgumentNullException ("targetName");
+ if (taskName == null)
+ throw new ArgumentNullException ("taskName");
+ return hosts.FirstOrDefault (h =>
+ string.Equals (projectFile, h.ProjectFile, StringComparison.OrdinalIgnoreCase) &&
+ string.Equals (targetName, h.TargetName, StringComparison.OrdinalIgnoreCase) &&
+ string.Equals (taskName, h.TaskName, StringComparison.OrdinalIgnoreCase));
+ }
+
+ public ITaskHost GetHostObject (string projectFile, string targetName, string taskName)
+ {
+ var reg = GetHostRegistration (projectFile, targetName, taskName);
+ return reg != null ? reg.HostObject : null;
+ }
- public NodeAffinity GetNodeAffinity (string projectFile)
- {
- throw new NotImplementedException ();
- }
+ public NodeAffinity GetNodeAffinity (string projectFile)
+ {
+ if (projectFile == null)
+ throw new ArgumentNullException ("projectFile");
+ NodeAffinity na;
+ return node_affinities.TryGetValue (projectFile, out na) ? na : NodeAffinity.Any;
+ }
+
+ IEnumerable<HostObjectRegistration> GetRegistrationsByProject (string project)
+ {
+ return hosts.Where (h => string.Equals (project, h.ProjectFile, StringComparison.OrdinalIgnoreCase));
+ }
- public void OnRenameProject (string oldFullPath, string newFullPath)
- {
- throw new NotImplementedException ();
- }
+ public void OnRenameProject (string oldFullPath, string newFullPath)
+ {
+ if (oldFullPath == null)
+ throw new ArgumentNullException ("oldFullPath");
+ if (newFullPath == null)
+ throw new ArgumentNullException ("newFullPath");
+ foreach (var reg in GetRegistrationsByProject (oldFullPath))
+ reg.ProjectFile = newFullPath;
+ }
- public void RegisterHostObject (string projectFile, string targetName, string taskName, ITaskHost hostObject)
- {
- throw new NotImplementedException ();
- }
+ public void RegisterHostObject (string projectFile, string targetName, string taskName, ITaskHost hostObject)
+ {
+ if (hostObject == null)
+ throw new ArgumentNullException ("hostObject");
+ var reg = GetHostRegistration (projectFile, targetName, taskName);
+ if (reg != null)
+ reg.HostObject = hostObject;
+ else
+ hosts.Add (new HostObjectRegistration () { ProjectFile = projectFile, TargetName = targetName, TaskName = taskName, HostObject = hostObject });
+ }
- public void SetNodeAffinity (string projectFile, NodeAffinity nodeAffinity)
- {
- throw new NotImplementedException ();
- }
+ public void SetNodeAffinity (string projectFile, NodeAffinity nodeAffinity)
+ {
+ if (projectFile == null)
+ throw new ArgumentNullException ("projectFile");
+ node_affinities [projectFile] = nodeAffinity;
+ }
- public void UnregisterProject (string projectFullPath)
- {
- throw new NotImplementedException ();
- }
- }
+ public void UnregisterProject (string projectFullPath)
+ {
+ if (projectFullPath == null)
+ throw new ArgumentNullException ("projectFullPath");
+ var removed = GetRegistrationsByProject (projectFullPath).ToArray ();
+ foreach (var r in removed)
+ hosts.Remove (r);
+ }
+ }
}
--- /dev/null
+//
+// NodeEngineShutdownReason.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Build.BuildEngine;
+using Microsoft.Build.Execution;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Evaluation;
+using System.Linq;
+using System.IO;
+
+namespace Microsoft.Build.Internal
+{
+ public enum NodeEngineShutdownReason
+ {
+ BuildComplete,
+ BuildCompleteReuse,
+ ConnectionFailed,
+ Error,
+ }
+}
--- /dev/null
+//
+// OutOfProcNode.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Build.BuildEngine;
+using Microsoft.Build.Execution;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Evaluation;
+using System.Linq;
+using System.IO;
+
+namespace Microsoft.Build.Internal
+{
+ // from MSDN: this class has deprecated and there is no alternative.
+ public class OutOfProcNode
+ {
+ public NodeEngineShutdownReason Run (out Exception shutdownException)
+ {
+ throw new NotImplementedException ();
+ }
+ }
+}
//
// Author:
// Rolf Bjarne Kvinge (rolf@xamarin.com)
+// Atsushi Enomoto (atsushi@xamarin.com)
//
-// Copyright (C) 2011 Xamarin Inc.
+// Copyright (C) 2011,2013 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
//
using System;
+using System.Collections;
using System.Collections.Generic;
+using System.Linq;
using Microsoft.Build.Construction;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Framework;
+using Microsoft.Build.Internal.Expressions;
using Microsoft.Build.Logging;
+//
+// It is not always consistent to reuse Project and its evaluation stuff mostly because
+// both BuildParameters.ctor() and Project.ctor() takes arbitrary ProjectCollection, which are not very likely eqivalent
+// (as BuildParameters.ctor(), unlike Project.ctor(...), is known to create a new ProjectCollection instance).
+//
+// However, that inconsistency could happen even if you only use ProjectInstance and BuildParameters.
+// They both have constructors that take ProjectCollection and there is no guarantee that the arguments are the same.
+// BuildManager.Build() does not fail because of inconsistent ProjectCollection instance on .NET.
+//
+// Anyhow, I'm not going to instantiate Project within ProjectInstance code for another reason:
+// ProjectCollection.GetLoadedProject() does not return any Project instnace for corresponding ProjectInstance
+// (or I should say, ProjectRootElement for both).
+using Microsoft.Build.Internal;
+using System.Xml;
+using Microsoft.Build.Exceptions;
+using System.IO;
+
+
namespace Microsoft.Build.Execution
{
public class ProjectInstance
public ProjectInstance (ProjectRootElement xml, IDictionary<string, string> globalProperties,
string toolsVersion, ProjectCollection projectCollection)
{
- InitializeProperties ();
-
- throw new NotImplementedException ();
+ projects = projectCollection;
+ global_properties = globalProperties ?? new Dictionary<string, string> ();
+ tools_version = !string.IsNullOrEmpty (toolsVersion) ? toolsVersion :
+ !string.IsNullOrEmpty (xml.ToolsVersion) ? xml.ToolsVersion :
+ projects.DefaultToolsVersion;
+ InitializeProperties (xml, null);
}
public ProjectInstance (string projectFile, IDictionary<string, string> globalProperties,
string toolsVersion, ProjectCollection projectCollection)
+ : this (ProjectRootElement.Create (projectFile), globalProperties, toolsVersion, projectCollection)
+ {
+ }
+
+ ProjectCollection projects;
+ IDictionary<string, string> global_properties;
+
+ string full_path, directory;
+ #if NET_4_5
+ ElementLocation location;
+ #endif
+
+ Dictionary<string, ProjectItemDefinitionInstance> item_definitions;
+ List<ResolvedImport> raw_imports; // maybe we don't need this...
+ List<ProjectItemInstance> all_evaluated_items;
+ List<ProjectItemInstance> raw_items;
+ List<ProjectPropertyInstance> properties;
+ Dictionary<string, ProjectTargetInstance> targets;
+ string tools_version;
+
+ List<string> GetDefaultTargets (ProjectRootElement xml)
{
- InitializeProperties ();
+ var ret = xml.DefaultTargets.Split (item_target_sep, StringSplitOptions.RemoveEmptyEntries).Select (s => s.Trim ()).ToList ();
+ if (ret.Count == 0 && xml.Targets.Any ())
+ ret.Add (xml.Targets.First ().Name);
+ return ret;
+ }
+
+ void InitializeProperties (ProjectRootElement xml, ProjectInstance parent)
+ {
+ #if NET_4_5
+ location = xml.Location;
+ #endif
+ full_path = xml.FullPath;
+ directory = string.IsNullOrWhiteSpace (xml.DirectoryPath) ? System.IO.Directory.GetCurrentDirectory () : xml.DirectoryPath;
+ DefaultTargets = GetDefaultTargets (xml);
+ InitialTargets = xml.InitialTargets.Split (item_target_sep, StringSplitOptions.RemoveEmptyEntries).Select (s => s.Trim ()).ToList ();
+
+ raw_imports = new List<ResolvedImport> ();
+ item_definitions = new Dictionary<string, ProjectItemDefinitionInstance> ();
+ targets = new Dictionary<string, ProjectTargetInstance> ();
+ raw_items = new List<ProjectItemInstance> ();
- throw new NotImplementedException ();
+ // FIXME: this is likely hack. Test ImportedProject.Properties to see what exactly should happen.
+ if (parent != null) {
+ properties = parent.properties;
+ } else {
+ properties = new List<ProjectPropertyInstance> ();
+
+ foreach (DictionaryEntry p in Environment.GetEnvironmentVariables ())
+ // FIXME: this is kind of workaround for unavoidable issue that PLATFORM=* is actually given
+ // on some platforms and that prevents setting default "PLATFORM=AnyCPU" property.
+ if (!string.Equals ("PLATFORM", (string) p.Key, StringComparison.OrdinalIgnoreCase))
+ this.properties.Add (new ProjectPropertyInstance ((string) p.Key, false, (string) p.Value));
+ foreach (var p in global_properties)
+ this.properties.Add (new ProjectPropertyInstance (p.Key, false, p.Value));
+ var tools = projects.GetToolset (tools_version) ?? projects.GetToolset (projects.DefaultToolsVersion);
+ foreach (var p in projects.GetReservedProperties (tools, this, xml))
+ this.properties.Add (p);
+ foreach (var p in ProjectCollection.GetWellKnownProperties (this))
+ this.properties.Add (p);
+ }
+
+ ProcessXml (parent, xml);
}
- void InitializeProperties ()
+ static readonly char [] item_target_sep = {';'};
+
+ void ProcessXml (ProjectInstance parent, ProjectRootElement xml)
{
- DefaultTargets = new List<string> ();
- InitialTargets = new List<string> ();
+ TaskDatabase = new BuildTaskDatabase (this, xml);
+
+ // this needs to be initialized here (regardless of that items won't be evaluated at property evaluation;
+ // Conditions could incorrectly reference items and lack of this list causes NRE.
+ all_evaluated_items = new List<ProjectItemInstance> ();
+
+ // property evaluation happens couple of times.
+ // At first step, all non-imported properties are evaluated TOO, WHILE those properties are being evaluated.
+ // This means, Include and IncludeGroup elements with Condition attribute MAY contain references to
+ // properties and they will be expanded.
+ var elements = EvaluatePropertiesAndImports (xml.Children).ToArray (); // ToArray(): to not lazily evaluate elements.
+
+ // next, evaluate items
+ EvaluateItems (xml, elements);
+
+ // finally, evaluate targets and tasks
+ EvaluateTasks (elements);
}
- Dictionary<string, string> global_properties = new Dictionary<string, string> ();
+ IEnumerable<ProjectElement> EvaluatePropertiesAndImports (IEnumerable<ProjectElement> elements)
+ {
+ // First step: evaluate Properties
+ foreach (var child in elements) {
+ yield return child;
+ var pge = child as ProjectPropertyGroupElement;
+ if (pge != null && EvaluateCondition (pge.Condition))
+ foreach (var p in pge.Properties)
+ // do not allow overwriting reserved or well-known properties by user
+ if (!this.properties.Any (_ => (_.IsImmutable) && _.Name.Equals (p.Name, StringComparison.InvariantCultureIgnoreCase)))
+ if (EvaluateCondition (p.Condition))
+ this.properties.Add (new ProjectPropertyInstance (p.Name, false, ExpandString (p.Value)));
+
+ var ige = child as ProjectImportGroupElement;
+ if (ige != null && EvaluateCondition (ige.Condition)) {
+ foreach (var incc in ige.Imports) {
+ foreach (var e in Import (incc))
+ yield return e;
+ }
+ }
+ var inc = child as ProjectImportElement;
+ if (inc != null && EvaluateCondition (inc.Condition))
+ foreach (var e in Import (inc))
+ yield return e;
+ }
+ }
+ internal IEnumerable<T> GetAllItems<T> (string include, string exclude, Func<string,T> creator, Func<string,ITaskItem> taskItemCreator, Func<string,bool> itemTypeCheck, Action<T,string> assignRecurse)
+ {
+ return ProjectCollection.GetAllItems<T> (ExpandString, include, exclude, creator, taskItemCreator, Directory, assignRecurse,
+ t => all_evaluated_items.Any (i => i.EvaluatedInclude == t.ItemSpec && itemTypeCheck (i.ItemType)));
+ }
+
+ void EvaluateItems (ProjectRootElement xml, IEnumerable<ProjectElement> elements)
+ {
+ foreach (var child in elements) {
+ var ige = child as ProjectItemGroupElement;
+ if (ige != null) {
+ foreach (var p in ige.Items) {
+ if (!EvaluateCondition (ige.Condition) || !EvaluateCondition (p.Condition))
+ continue;
+ Func<string,ProjectItemInstance> creator = s => new ProjectItemInstance (this, p.ItemType, p.Metadata.Select (m => new KeyValuePair<string,string> (m.Name, m.Value)).ToList (), s);
+ foreach (var item in GetAllItems (p.Include, p.Exclude, creator, s => new ProjectTaskItem (p, s), it => string.Equals (it, p.ItemType, StringComparison.OrdinalIgnoreCase), (t, s) => t.RecursiveDir = s)) {
+ raw_items.Add (item);
+ all_evaluated_items.Add (item);
+ }
+ }
+ }
+ var def = child as ProjectItemDefinitionGroupElement;
+ if (def != null) {
+ foreach (var p in def.ItemDefinitions) {
+ if (EvaluateCondition (p.Condition)) {
+ ProjectItemDefinitionInstance existing;
+ if (!item_definitions.TryGetValue (p.ItemType, out existing))
+ item_definitions.Add (p.ItemType, (existing = new ProjectItemDefinitionInstance (p)));
+ existing.AddItems (p);
+ }
+ }
+ }
+ }
+ all_evaluated_items.Sort ((p1, p2) => string.Compare (p1.ItemType, p2.ItemType, StringComparison.OrdinalIgnoreCase));
+ }
+
+ void EvaluateTasks (IEnumerable<ProjectElement> elements)
+ {
+ foreach (var child in elements) {
+ var te = child as ProjectTargetElement;
+ if (te != null)
+ this.targets.Add (te.Name, new ProjectTargetInstance (te));
+ }
+ }
+
+ IEnumerable<ProjectElement> Import (ProjectImportElement import)
+ {
+ string dir = projects.GetEvaluationTimeThisFileDirectory (() => FullPath);
+ string path = WindowsCompatibilityExtensions.NormalizeFilePath (ExpandString (import.Project));
+ path = Path.IsPathRooted (path) ? path : dir != null ? Path.Combine (dir, path) : Path.GetFullPath (path);
+ if (projects.OngoingImports.Contains (path))
+ throw new InvalidProjectFileException (import.Location, null, string.Format ("Circular imports was detected: {0} is already on \"importing\" stack", path));
+ projects.OngoingImports.Push (path);
+ try {
+ using (var reader = XmlReader.Create (path)) {
+ var root = ProjectRootElement.Create (reader, projects);
+ if (DefaultTargets.Count == 0)
+ DefaultTargets.AddRange (GetDefaultTargets (root));
+ raw_imports.Add (new ResolvedImport (import, root, true));
+ return this.EvaluatePropertiesAndImports (root.Children).ToArray ();
+ }
+ } finally {
+ projects.OngoingImports.Pop ();
+ }
+ }
+
+ internal IEnumerable<ProjectItemInstance> AllEvaluatedItems {
+ get { return all_evaluated_items; }
+ }
+
public List<string> DefaultTargets { get; private set; }
public string Directory {
- get { throw new NotImplementedException (); }
+ get { return directory; }
}
public string FullPath {
- get { throw new NotImplementedException (); }
+ get { return full_path; }
}
public IDictionary<string, string> GlobalProperties {
#endif
public IDictionary<string, ProjectItemDefinitionInstance> ItemDefinitions {
- get { throw new NotImplementedException (); }
+ get { return item_definitions; }
}
public ICollection<ProjectItemInstance> Items {
- get { throw new NotImplementedException (); }
+ get { return all_evaluated_items; }
}
public ICollection<string> ItemTypes {
- get { throw new NotImplementedException (); }
+ get { return all_evaluated_items.Select (i => i.ItemType).Distinct ().ToArray (); }
}
#if NET_4_5
public ElementLocation ProjectFileLocation {
- get { throw new NotImplementedException (); }
+ get { return location; }
}
#endif
public ICollection<ProjectPropertyInstance> Properties {
- get { throw new NotImplementedException (); }
+ get { return properties; }
}
public IDictionary<string, ProjectTargetInstance> Targets {
- get { throw new NotImplementedException (); }
+ get { return targets; }
}
public string ToolsVersion {
- get { throw new NotImplementedException (); }
+ get { return tools_version; }
}
public ProjectItemInstance AddItem (string itemType, string evaluatedInclude)
public ProjectItemInstance AddItem (string itemType, string evaluatedInclude, IEnumerable<KeyValuePair<string, string>> metadata)
{
- throw new NotImplementedException ();
+ var item = new ProjectItemInstance (this, itemType, metadata, evaluatedInclude);
+ raw_items.Add (item);
+ all_evaluated_items.Add (item);
+ return item;
}
public bool Build ()
public bool Build (IEnumerable<ILogger> loggers, IEnumerable<ForwardingLoggerRecord> remoteLoggers)
{
- return Build ((string []) null, loggers, remoteLoggers);
+ return Build (DefaultTargets.ToArray (), loggers, remoteLoggers);
}
public bool Build (string target, IEnumerable<ILogger> loggers)
public bool Build (string[] targets, IEnumerable<ILogger> loggers, out IDictionary<string, TargetResult> targetOutputs)
{
- return Build (targets, loggers, new ForwardingLoggerRecord [0], out targetOutputs);
+ return Build (targets, loggers, new ForwardingLoggerRecord [0], out targetOutputs);
}
public bool Build (string[] targets, IEnumerable<ILogger> loggers, IEnumerable<ForwardingLoggerRecord> remoteLoggers, out IDictionary<string, TargetResult> targetOutputs)
{
- throw new NotImplementedException ();
+ var manager = new BuildManager ();
+ var parameters = new BuildParameters (projects) {
+ ForwardingLoggers = remoteLoggers,
+ Loggers = loggers,
+ };
+ var requestData = new BuildRequestData (this, targets);
+ var result = manager.Build (parameters, requestData);
+ targetOutputs = result.ResultsByTarget;
+ return result.OverallResult == BuildResultCode.Success;
}
public ProjectInstance DeepCopy ()
public bool EvaluateCondition (string condition)
{
- throw new NotImplementedException ();
+ return string.IsNullOrWhiteSpace (condition) || new ExpressionEvaluator (this, null).EvaluateAsBoolean (condition);
}
public string ExpandString (string unexpandedValue)
{
- throw new NotImplementedException ();
+ return ExpandString (unexpandedValue, null);
+ }
+
+ string ExpandString (string unexpandedValue, string replacementForMissingStuff)
+ {
+ return new ExpressionEvaluator (this, replacementForMissingStuff).Evaluate (unexpandedValue);
}
public ICollection<ProjectItemInstance> GetItems (string itemType)
{
- throw new NotImplementedException ();
+ return new CollectionFromEnumerable<ProjectItemInstance> (Items.Where (p => p.ItemType.Equals (itemType, StringComparison.OrdinalIgnoreCase)));
}
public IEnumerable<ProjectItemInstance> GetItemsByItemTypeAndEvaluatedInclude (string itemType, string evaluatedInclude)
public ProjectPropertyInstance GetProperty (string name)
{
- throw new NotImplementedException ();
+ return properties.FirstOrDefault (p => p.Name.Equals (name, StringComparison.OrdinalIgnoreCase));
}
public string GetPropertyValue (string name)
{
- throw new NotImplementedException ();
+ var prop = GetProperty (name);
+ return prop != null ? prop.EvaluatedValue : string.Empty;
}
public bool RemoveItem (ProjectItemInstance item)
{
- throw new NotImplementedException ();
+ // yeah, this raw_items should vanish...
+ raw_items.Remove (item);
+ return all_evaluated_items.Remove (item);
}
public bool RemoveProperty (string name)
{
- throw new NotImplementedException ();
+ var removed = properties.FirstOrDefault (p => p.Name.Equals (name, StringComparison.OrdinalIgnoreCase));
+ if (removed == null)
+ return false;
+ properties.Remove (removed);
+ return true;
}
public ProjectPropertyInstance SetProperty (string name, string evaluatedValue)
{
- throw new NotImplementedException ();
+ var p = new ProjectPropertyInstance (name, false, evaluatedValue);
+ properties.Add (p);
+ return p;
}
public ProjectRootElement ToProjectRootElement ()
public static string GetEvaluatedItemIncludeEscaped (ProjectItemDefinitionInstance item)
{
+ // ?? ItemDefinition does not have Include attribute. What's the point here?
throw new NotImplementedException ();
}
public static string GetEvaluatedItemIncludeEscaped (ProjectItemInstance item)
{
- throw new NotImplementedException ();
+ return ProjectCollection.Escape (item.EvaluatedInclude);
}
public static string GetMetadataValueEscaped (ProjectMetadataInstance metadatum)
{
- throw new NotImplementedException ();
+ return ProjectCollection.Escape (metadatum.EvaluatedValue);
}
public static string GetMetadataValueEscaped (ProjectItemDefinitionInstance item, string name)
{
- throw new NotImplementedException ();
+ var md = item.Metadata.FirstOrDefault (m => m.Name.Equals (name, StringComparison.OrdinalIgnoreCase));
+ return md != null ? ProjectCollection.Escape (md.EvaluatedValue) : null;
}
public static string GetMetadataValueEscaped (ProjectItemInstance item, string name)
{
- throw new NotImplementedException ();
+ var md = item.Metadata.FirstOrDefault (m => m.Name.Equals (name, StringComparison.OrdinalIgnoreCase));
+ return md != null ? ProjectCollection.Escape (md.EvaluatedValue) : null;
}
public static string GetPropertyValueEscaped (ProjectPropertyInstance property)
{
- throw new NotImplementedException ();
+ // WTF happens here.
+ //return ProjectCollection.Escape (property.EvaluatedValue);
+ return property.EvaluatedValue;
+ }
+
+ internal BuildTaskDatabase TaskDatabase { get; private set; }
+
+ internal string GetFullPath (string pathRelativeToProject)
+ {
+ if (Path.IsPathRooted (pathRelativeToProject))
+ return pathRelativeToProject;
+ return Path.GetFullPath (Path.Combine (Directory, pathRelativeToProject));
}
}
}
// Author:
// Atsushi Enomoto (atsushi@veritas-vos-liberabit.com)
//
-// Copyright (C) 2012 Xamarin Inc.
+// Copyright (C) 2012,2013 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
using Microsoft.Build.Framework;
using System;
using System.Collections.Generic;
+using Microsoft.Build.Construction;
+using System.Linq;
namespace Microsoft.Build.Execution
{
public class ProjectItemDefinitionInstance
{
- internal ProjectItemDefinitionInstance ()
+ internal ProjectItemDefinitionInstance (ProjectItemDefinitionElement xml)
{
+ ItemType = xml.ItemType;
+ AddItems (xml);
}
- public string ItemType {
- get { throw new NotImplementedException (); }
- }
+ List<ProjectMetadataInstance> metadata = new List<ProjectMetadataInstance> ();
+
+ public string ItemType { get; private set; }
public ICollection<ProjectMetadataInstance> Metadata {
- get { throw new NotImplementedException (); }
+ get { return metadata; }
}
public int MetadataCount {
- get { throw new NotImplementedException (); }
+ get { return metadata.Count; }
}
public IEnumerable<string> MetadataNames {
- get { throw new NotImplementedException (); }
+ get { return metadata.Select (m => m.Name).ToArray (); }
+ }
+
+ internal void AddItems (ProjectItemDefinitionElement xml)
+ {
+ foreach (var item in xml.Metadata) {
+ var existing = metadata.FirstOrDefault (i => i.Name == item.Name);
+ if (existing != null)
+ metadata.Remove (existing);
+ metadata.Add (new ProjectMetadataInstance (item.Name, item.Value));
+ }
}
}
}
--- /dev/null
+//
+// ProjectItemGroupTaskInstance.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// (C) 2013 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Build.Construction;
+
+namespace Microsoft.Build.Execution
+{
+ public sealed class ProjectItemGroupTaskInstance : ProjectTargetInstanceChild
+ {
+ internal ProjectItemGroupTaskInstance (ProjectItemGroupElement xml)
+ {
+ condition = xml.Condition;
+ condition_location = xml.ConditionLocation;
+ //this.FullPath = fullPath;
+ location = xml.Location;
+
+ Items = xml.Items.Select (item => new ProjectItemGroupTaskItemInstance (item)).ToArray ();
+ }
+
+ readonly string condition;
+ readonly ElementLocation condition_location, location;
+
+ public override string Condition {
+ get { return condition; }
+ }
+
+ #if NET_4_5
+ public
+ #else
+ internal
+ #endif
+ override ElementLocation ConditionLocation {
+ get { return condition_location; }
+ }
+
+ #if NET_4_5
+ public
+ #else
+ internal
+ #endif
+ override ElementLocation Location {
+ get { return location; }
+ }
+
+ #if NET_4_5
+ public
+ #else
+ internal
+ #endif
+ ElementLocation ExecuteTargetsLocation { get; private set; }
+
+ public ICollection<ProjectItemGroupTaskItemInstance> Items { get; private set; }
+ }
+}
+
--- /dev/null
+//
+// ProjectItemGroupTaskItemInstance.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// (C) 2013 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using Microsoft.Build.Construction;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Microsoft.Build.Execution
+{
+ public class ProjectItemGroupTaskItemInstance
+ {
+ internal ProjectItemGroupTaskItemInstance (ProjectItemElement xml)
+ {
+ Condition = xml.Condition;
+ Exclude = xml.Exclude;
+ Include = xml.Include;
+ ItemType = xml.ItemType;
+ Metadata = xml.Metadata.Select (m => new ProjectItemGroupTaskMetadataInstance (m)).ToArray ();
+ Remove = xml.Remove;
+ #if NET_4_5
+ KeepDuplicates = xml.KeepDuplicates;
+ KeepMetadata = xml.KeepMetadata;
+ RemoveMetadata = xml.RemoveMetadata;
+
+ ConditionLocation = xml.ConditionLocation;
+ ExcludeLocation = xml.ExcludeLocation;
+ IncludeLocation = xml.IncludeLocation;
+ Location = xml.Location;
+ KeepDuplicatesLocation = xml.KeepDuplicatesLocation;
+ RemoveLocation = xml.RemoveLocation;
+ RemoveMetadataLocation = xml.RemoveMetadataLocation;
+ #endif
+ }
+
+ public string Condition { get; private set; }
+
+ public string Exclude { get; private set; }
+
+ public string Include { get; private set; }
+
+ public string ItemType { get; private set; }
+
+ public string KeepDuplicates { get; private set; }
+
+ public string KeepMetadata { get; private set; }
+
+ public ICollection<ProjectItemGroupTaskMetadataInstance> Metadata { get; private set; }
+
+ public string Remove { get; private set; }
+
+ public string RemoveMetadata { get; private set; }
+ #if NET_4_5
+ public ElementLocation ConditionLocation { get; private set; }
+
+ public ElementLocation ExcludeLocation { get; private set; }
+
+ public ElementLocation IncludeLocation { get; private set; }
+
+ public ElementLocation KeepDuplicatesLocation { get; private set; }
+
+ public ElementLocation KeepMetadataLocation { get; private set; }
+
+ public ElementLocation Location { get; private set; }
+
+ public ElementLocation RemoveLocation { get; private set; }
+
+ public ElementLocation RemoveMetadataLocation { get; private set; }
+ #endif
+ }
+}
+
--- /dev/null
+//
+// ProjectItemGroupTaskMetadataInstance.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// (C) 2013 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using Microsoft.Build.Construction;
+
+namespace Microsoft.Build.Execution
+{
+ public sealed class ProjectItemGroupTaskMetadataInstance
+ {
+ internal ProjectItemGroupTaskMetadataInstance (ProjectMetadataElement xml)
+ {
+ Condition = xml.Condition;
+ Name = xml.Name;
+ Value = xml.Value;
+ #if NET_4_5
+ ConditionLocation = xml.ConditionLocation;
+ Location = xml.Location;
+ #endif
+ }
+ public string Condition { get; private set; }
+
+ public string Name { get; private set; }
+
+ public string Value { get; private set; }
+ #if NET_4_5
+ public ElementLocation ConditionLocation { get; private set; }
+
+ public ElementLocation Location { get; private set; }
+ #endif
+ }
+}
+
//
// Author:
// Rolf Bjarne Kvinge (rolf@xamarin.com)
+// Atsushi Enomoto (atsushi@xamarin.com)
//
-// Copyright (C) 2011 Xamarin Inc.
+// Copyright (C) 2011,2013 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-using Microsoft.Build.Framework;
using System;
using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Evaluation;
+using System.Collections;
+using Microsoft.Build.Construction;
+using System.Globalization;
+using System.IO;
namespace Microsoft.Build.Execution
{
- public class ProjectItemInstance
+ public class ProjectItemInstance
: ITaskItem2
- {
- private ProjectItemInstance ()
- {
- throw new NotImplementedException ();
- }
-
- public ProjectMetadataInstance GetMetadata (string name)
- {
- throw new NotImplementedException ();
- }
-
- public string GetMetadataValue (string name)
- {
- throw new NotImplementedException ();
- }
-
- public bool HasMetadata (string name)
- {
- throw new NotImplementedException ();
- }
-
- public void RemoveMetadata (string metadataName)
- {
- throw new NotImplementedException ();
- }
-
- public void SetMetadata (IEnumerable<KeyValuePair<string, string>> metadataDictionary)
- {
- throw new NotImplementedException ();
- }
-
- public ProjectMetadataInstance SetMetadata (string name, string evaluatedValue)
- {
- throw new NotImplementedException ();
- }
-
- public int DirectMetadataCount {
- get { throw new NotImplementedException (); }
- }
-
- public string EvaluatedInclude {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
- }
-
- public string ItemType {
- get { throw new NotImplementedException (); }
- }
-
- public IEnumerable<ProjectMetadataInstance> Metadata {
- get { throw new NotImplementedException (); }
- }
-
- public int MetadataCount {
- get { throw new NotImplementedException (); }
- }
-
- public ICollection<string> MetadataNames {
- get { throw new NotImplementedException (); }
- }
-
- public ProjectInstance Project {
- get { throw new NotImplementedException (); }
- }
-
- #region ITaskItem2 implementation
- string ITaskItem2.GetMetadataValueEscaped (string metadataName)
- {
- throw new NotImplementedException ();
- }
-
- void ITaskItem2.SetMetadataValueLiteral (string metadataName, string metadataValue)
- {
- throw new NotImplementedException ();
- }
-
- System.Collections.IDictionary ITaskItem2.CloneCustomMetadataEscaped ()
- {
- throw new NotImplementedException ();
- }
-
- string ITaskItem2.EvaluatedIncludeEscaped {
- get {
- throw new NotImplementedException ();
- }
- set {
- throw new NotImplementedException ();
- }
- }
- #endregion
-
- #region ITaskItem implementation
- System.Collections.IDictionary ITaskItem.CloneCustomMetadata ()
- {
- throw new NotImplementedException ();
- }
-
- void ITaskItem.CopyMetadataTo (ITaskItem destinationItem)
- {
- throw new NotImplementedException ();
- }
-
- string ITaskItem.GetMetadata (string metadataName)
- {
- throw new NotImplementedException ();
- }
-
- void ITaskItem.RemoveMetadata (string metadataName)
- {
- throw new NotImplementedException ();
- }
-
- void ITaskItem.SetMetadata (string metadataName, string metadataValue)
- {
- throw new NotImplementedException ();
- }
-
- string ITaskItem.ItemSpec {
- get {
- throw new NotImplementedException ();
- }
- set {
- throw new NotImplementedException ();
- }
- }
-
- int ITaskItem.MetadataCount {
- get {
- throw new NotImplementedException ();
- }
- }
-
- System.Collections.ICollection ITaskItem.MetadataNames {
- get {
- throw new NotImplementedException ();
- }
- }
- #endregion
- }
+ {
+ internal ProjectItemInstance (ProjectInstance project, string itemType, IEnumerable<KeyValuePair<string,string>> metadata, string evaluatedInclude)
+ {
+ this.project = project;
+ this.evaluated_include = evaluatedInclude;
+ this.item_type = itemType;
+ this.metadata = new List<ProjectMetadataInstance> ();
+ SetMetadata (metadata);
+ }
+
+ readonly ProjectInstance project;
+ readonly string item_type;
+ string evaluated_include;
+ readonly List<ProjectMetadataInstance> metadata;
+
+ public ProjectMetadataInstance GetMetadata (string name)
+ {
+ if (name == null)
+ throw new ArgumentNullException ("name");
+ // This does not return any Well Known metadata
+ return Metadata.FirstOrDefault (m => m.Name.Equals (name, StringComparison.OrdinalIgnoreCase));
+ }
+
+ public string GetMetadataValue (string name)
+ {
+ if (name == null)
+ throw new ArgumentNullException ("name");
+ var wk = ProjectCollection.GetWellKnownMetadata (name, EvaluatedInclude, project.GetFullPath, RecursiveDir);
+ if (wk != null)
+ return wk;
+ var m = GetMetadata (name);
+ return m != null ? m.EvaluatedValue : null;
+ }
+
+ public bool HasMetadata (string name)
+ {
+ return GetMetadata (name) != null;
+ }
+
+ public void RemoveMetadata (string metadataName)
+ {
+ var m = GetMetadata (metadataName);
+ if (m != null)
+ metadata.Remove (m);
+ }
+
+ public void SetMetadata (IEnumerable<KeyValuePair<string, string>> metadataDictionary)
+ {
+ foreach (var p in metadataDictionary)
+ SetMetadata (p.Key, p.Value);
+ }
+
+ public ProjectMetadataInstance SetMetadata (string name, string evaluatedValue)
+ {
+ var m = metadata.FirstOrDefault (_ => _.Name.Equals (name, StringComparison.OrdinalIgnoreCase));
+ if (m != null)
+ metadata.Remove (m);
+ m = new ProjectMetadataInstance (name, evaluatedValue);
+ metadata.Add (m);
+ return m;
+ }
+
+ public int DirectMetadataCount {
+ get { throw new NotImplementedException (); }
+ }
+
+ public string EvaluatedInclude {
+ get { return evaluated_include; }
+ set {
+ if (value == null)
+ throw new ArgumentNullException ("value");
+ evaluated_include = value;
+ }
+ }
+
+ public string ItemType {
+ get { return item_type; }
+ }
+
+ public IEnumerable<ProjectMetadataInstance> Metadata {
+ get { return metadata; }
+ }
+
+ public int MetadataCount {
+ get { return metadata.Count; }
+ }
+
+ public ICollection<string> MetadataNames {
+ get { return metadata.Select (m => m.Name).ToArray (); }
+ }
+
+ public ProjectInstance Project {
+ get { return project; }
+ }
+
+ internal string RecursiveDir { get; set; }
+
+ #region ITaskItem2 implementation
+
+ string ITaskItem2.GetMetadataValueEscaped (string metadataName)
+ {
+ return ProjectCollection.Escape (GetMetadataValue (metadataName));
+ }
+
+ void ITaskItem2.SetMetadataValueLiteral (string metadataName, string metadataValue)
+ {
+ SetMetadata (metadataName, metadataValue);
+ }
+
+ System.Collections.IDictionary ITaskItem2.CloneCustomMetadataEscaped ()
+ {
+ var dic = ((ITaskItem) this).CloneCustomMetadata ();
+ foreach (DictionaryEntry p in dic)
+ dic [p.Key] = ProjectCollection.Escape ((string) p.Value);
+ return dic;
+ }
+
+ string ITaskItem2.EvaluatedIncludeEscaped {
+ get { return ProjectCollection.Escape (EvaluatedInclude); }
+ set { EvaluatedInclude = ProjectCollection.Unescape (value); }
+ }
+
+ #endregion
+
+ #region ITaskItem implementation
+
+ IDictionary ITaskItem.CloneCustomMetadata ()
+ {
+ var dic = new Hashtable ();
+ foreach (var md in Metadata)
+ dic [md.Name] = md.EvaluatedValue;
+ return dic;
+ }
+
+ void ITaskItem.CopyMetadataTo (ITaskItem destinationItem)
+ {
+ if (destinationItem == null)
+ throw new ArgumentNullException ("destinationItem");
+ foreach (var md in Metadata)
+ destinationItem.SetMetadata (md.Name, md.EvaluatedValue);
+ }
+
+ string ITaskItem.GetMetadata (string metadataName)
+ {
+ return GetMetadataValue (metadataName);
+ }
+
+ void ITaskItem.RemoveMetadata (string metadataName)
+ {
+ RemoveMetadata (metadataName);
+ }
+
+ void ITaskItem.SetMetadata (string metadataName, string metadataValue)
+ {
+ SetMetadata (metadataName, ProjectCollection.Unescape (metadataValue));
+ }
+
+ string ITaskItem.ItemSpec {
+ get { return EvaluatedInclude; }
+ set { EvaluatedInclude = value; }
+ }
+
+ int ITaskItem.MetadataCount {
+ get { return MetadataCount; }
+ }
+
+ ICollection ITaskItem.MetadataNames {
+ get { return MetadataNames.ToArray (); }
+ }
+
+ #endregion
+ }
}
//
using System;
+using Microsoft.Build.Construction;
namespace Microsoft.Build.Execution
{
- public class ProjectMetadataInstance
- {
- private ProjectMetadataInstance ()
- {
- throw new NotImplementedException ();
- }
- }
+ public class ProjectMetadataInstance
+ {
+ internal ProjectMetadataInstance (string name, string value)
+ {
+ Name = name;
+ EvaluatedValue = value;
+ }
+
+ public string EvaluatedValue { get; private set; }
+ public string Name { get; private set; }
+
+ public ProjectMetadataInstance DeepClone ()
+ {
+ return new ProjectMetadataInstance (Name, EvaluatedValue);
+ }
+
+ public override string ToString ()
+ {
+ return string.Format ("{0}={1}", Name, EvaluatedValue);
+ }
+ }
}
-
--- /dev/null
+//
+// ProjectOnErrorInstance.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// (C) 2013 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using Microsoft.Build.Construction;
+
+namespace Microsoft.Build.Execution
+{
+ public class ProjectOnErrorInstance : ProjectTargetInstanceChild
+ {
+ internal ProjectOnErrorInstance (ProjectOnErrorElement xml)
+ {
+ condition = xml.Condition;
+ ExecuteTargets = xml.ExecuteTargetsAttribute;
+ //this.FullPath = fullPath;
+ #if NET_4_5
+ condition_location = xml.ConditionLocation;
+ ExecuteTargetsLocation = xml.ExecuteTargetsAttributeLocation;
+ location = xml.Location;
+ #endif
+ }
+
+ readonly string condition;
+
+ public override string Condition {
+ get { return condition; }
+ }
+
+ public string ExecuteTargets { get; private set; }
+
+ readonly ElementLocation condition_location, location;
+
+ #if NET_4_5
+ public
+ #else
+ internal
+ #endif
+ override ElementLocation ConditionLocation {
+ get { return condition_location; }
+ }
+
+ #if NET_4_5
+ public
+ #else
+ internal
+ #endif
+ ElementLocation ExecuteTargetsLocation { get; private set; }
+
+ #if NET_4_5
+ public
+ #else
+ internal
+ #endif
+ override ElementLocation Location {
+ get { return location; }
+ }
+ }
+}
+
--- /dev/null
+//
+// ProjectPropertyGroupTaskInstance.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// (C) 2013 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Build.Construction;
+
+namespace Microsoft.Build.Execution
+{
+ public sealed class ProjectPropertyGroupTaskInstance : ProjectTargetInstanceChild
+ {
+ internal ProjectPropertyGroupTaskInstance (ProjectPropertyGroupElement xml)
+ {
+ condition = xml.Condition;
+ condition_location = xml.ConditionLocation;
+ //this.FullPath = fullPath;
+ location = xml.Location;
+
+ Properties = xml.Properties.Select (prop => new ProjectPropertyGroupTaskPropertyInstance (prop)).ToArray ();
+ }
+
+ readonly string condition;
+ readonly ElementLocation condition_location, location;
+
+ public override string Condition {
+ get { return condition; }
+ }
+
+ #if NET_4_5
+ public
+ #else
+ internal
+ #endif
+ override ElementLocation ConditionLocation {
+ get { return condition_location; }
+ }
+
+ #if NET_4_5
+ public
+ #else
+ internal
+ #endif
+ override ElementLocation Location {
+ get { return location; }
+ }
+
+ #if NET_4_5
+ public
+ #else
+ internal
+ #endif
+ ElementLocation ExecuteTargetsLocation { get; private set; }
+
+ public ICollection<ProjectPropertyGroupTaskPropertyInstance> Properties { get; private set; }
+ }
+}
+
--- /dev/null
+//
+// ProjectPropertyGroupTaskPropertyInstance.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// (C) 2013 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Build.Construction;
+
+namespace Microsoft.Build.Execution
+{
+ public class ProjectPropertyGroupTaskPropertyInstance
+ {
+ internal ProjectPropertyGroupTaskPropertyInstance (ProjectPropertyElement xml)
+ {
+ Condition = xml.Condition;
+ Name = xml.Name;
+ Value = xml.Value;
+ #if NET_4_5
+ ConditionLocation = xml.ConditionLocation;
+ Location = xml.Location;
+ #endif
+ }
+
+ public string Condition { get; private set; }
+
+ public string Name { get; private set; }
+
+ public string Value { get; private set; }
+
+ #if NET_4_5
+ public ElementLocation ConditionLocation { get; private set; }
+
+ public ElementLocation Location { get; private set; }
+ #endif
+ }
+}
+
//
// Author:
// Rolf Bjarne Kvinge (rolf@xamarin.com)
+// Atsushi Enomoto (atsushi@xamarin.com)
//
-// Copyright (C) 2011 Xamarin Inc.
+// Copyright (C) 2011,2013 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
namespace Microsoft.Build.Execution
{
- public class ProjectPropertyInstance
- {
- private ProjectPropertyInstance ()
- {
- throw new NotImplementedException ();
- }
- }
-}
+ public class ProjectPropertyInstance
+ {
+ internal ProjectPropertyInstance (string name, bool isImmutable, string evaluatedValue, Func<string> evaluatedValueGetter = null)
+ {
+ Name = name;
+ IsImmutable = isImmutable;
+ evaluated_value_getter = evaluatedValueGetter ?? (() => evaluatedValue);
+ }
+
+ Func<string> evaluated_value_getter;
+ public string EvaluatedValue {
+ get { return evaluated_value_getter (); }
+ set {
+ if (IsImmutable)
+ throw new InvalidOperationException ();
+ evaluated_value_getter = () => value;
+ }
+ }
+ public virtual bool IsImmutable { get; private set; }
+
+ public string Name { get; private set; }
+
+ public override string ToString ()
+ {
+ return string.Format ("{0}={1}", Name, EvaluatedValue);
+ }
+ }
+}
+//
// ProjectTargetInstance.cs
//
// Author:
// Rolf Bjarne Kvinge (rolf@xamarin.com)
+// Atsushi Enomoto (atsshi@xamarin.com)
//
-// Copyright (C) 2011 Xamarin Inc.
+// Copyright (C) 2011,2013 Xamarin Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
+
using System;
+using Microsoft.Build.Construction;
+using System.Collections.Generic;
+using System.Linq;
namespace Microsoft.Build.Execution
{
- public sealed class ProjectTargetInstance
- {
- private ProjectTargetInstance ()
- {
- throw new NotImplementedException ();
- }
- }
+ public sealed class ProjectTargetInstance
+ {
+ internal ProjectTargetInstance (ProjectTargetElement xml)
+ {
+ FullPath = xml.ContainingProject.FullPath;
+ Children = xml.Children.Select<ProjectElement,ProjectTargetInstanceChild> (c => {
+ if (c is ProjectOnErrorElement)
+ return new ProjectOnErrorInstance ((ProjectOnErrorElement) c);
+ if (c is ProjectItemGroupElement)
+ return new ProjectItemGroupTaskInstance ((ProjectItemGroupElement) c);
+ if (c is ProjectPropertyGroupElement)
+ return new ProjectPropertyGroupTaskInstance ((ProjectPropertyGroupElement) c);
+ if (c is ProjectTaskElement)
+ return new ProjectTaskInstance ((ProjectTaskElement) c);
+ throw new NotSupportedException ();
+ }).ToArray ();
+ Condition = xml.Condition;
+ DependsOnTargets = xml.DependsOnTargets;
+ //FullPath = fullPath;
+ Inputs = xml.Inputs;
+ KeepDuplicateOutputs = xml.KeepDuplicateOutputs;
+ Name = xml.Name;
+ OnErrorChildren = xml.OnErrors.Select (c => new ProjectOnErrorInstance (c)).ToArray ();
+ Outputs = xml.Outputs;
+ Returns = xml.Returns;
+ Tasks = xml.Tasks.Select (t => new ProjectTaskInstance (t)).ToArray ();
+ AfterTargetsLocation = xml.AfterTargetsLocation;
+ BeforeTargetsLocation = xml.BeforeTargetsLocation;
+ ConditionLocation = xml.ConditionLocation;
+ DependsOnTargetsLocation = xml.DependsOnTargetsLocation;
+ InputsLocation = xml.InputsLocation;
+ KeepDuplicateOutputsLocation = xml.KeepDuplicateOutputsLocation;
+ Location = xml.Location;
+ OutputsLocation = xml.OutputsLocation;
+ ReturnsLocation = xml.ReturnsLocation;
+ }
+
+ public IList<ProjectTargetInstanceChild> Children { get; private set; }
+ public string Condition { get; private set; }
+ public string DependsOnTargets { get; private set; }
+ public string FullPath { get; private set; }
+ public string Inputs { get; private set; }
+ public string KeepDuplicateOutputs { get; private set; }
+ public string Name { get; private set; }
+ public IList<ProjectOnErrorInstance> OnErrorChildren { get; private set; }
+ public string Outputs { get; private set; }
+ public string Returns { get; private set; }
+ public ICollection<ProjectTaskInstance> Tasks { get; private set; }
+#if NET_4_5
+ public ElementLocation AfterTargetsLocation { get; private set; }
+ public ElementLocation BeforeTargetsLocation { get; private set; }
+ public ElementLocation ConditionLocation { get; private set; }
+ public ElementLocation DependsOnTargetsLocation { get; private set; }
+ public ElementLocation InputsLocation { get; private set; }
+ public ElementLocation KeepDuplicateOutputsLocation { get; private set; }
+ public ElementLocation Location { get; private set; }
+ public ElementLocation OutputsLocation { get; private set; }
+ public ElementLocation ReturnsLocation { get; private set; }
+#else
+ internal ElementLocation AfterTargetsLocation { get; private set; }
+ internal ElementLocation BeforeTargetsLocation { get; private set; }
+ internal ElementLocation ConditionLocation { get; private set; }
+ internal ElementLocation DependsOnTargetsLocation { get; private set; }
+ internal ElementLocation InputsLocation { get; private set; }
+ internal ElementLocation KeepDuplicateOutputsLocation { get; private set; }
+ internal ElementLocation Location { get; private set; }
+ internal ElementLocation OutputsLocation { get; private set; }
+ internal ElementLocation ReturnsLocation { get; private set; }
+#endif
+ }
}
--- /dev/null
+//
+// ProjectTargetInstanceChild.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// (C) 2013 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using Microsoft.Build.Construction;
+
+namespace Microsoft.Build.Execution
+{
+ public abstract class ProjectTargetInstanceChild
+ {
+ public abstract string Condition { get; }
+ public string FullPath { get; internal set; }
+ #if NET_4_5
+ public
+ #else
+ internal
+ #endif
+ abstract ElementLocation ConditionLocation { get; }
+
+ #if NET_4_5
+ public
+ #else
+ internal
+ #endif
+ abstract ElementLocation Location { get; }
+ }
+}
+
--- /dev/null
+//
+// ProjectOnErrorInstance.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// (C) 2013 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections.Generic;
+using Microsoft.Build.Construction;
+using System.Linq;
+
+namespace Microsoft.Build.Execution
+{
+ public sealed class ProjectTaskInstance : ProjectTargetInstanceChild
+ {
+ internal ProjectTaskInstance (ProjectTaskElement xml)
+ {
+ condition = xml.Condition;
+ ContinueOnError = xml.ContinueOnError;
+ Name = xml.Name;
+ Outputs = xml.Outputs.Select (o => {
+ if (o.IsOutputItem)
+ return (ProjectTaskInstanceChild) new ProjectTaskOutputItemInstance ((ProjectOutputElement) o);
+ if (o.IsOutputProperty)
+ return new ProjectTaskOutputPropertyInstance ((ProjectOutputElement) o);
+ throw new NotSupportedException ();
+ }).ToArray ();
+ Parameters = new Dictionary<string,string> (xml.Parameters);
+ #if NET_4_5
+ MSBuildArchitecture = xml.MSBuildArchitecture;
+ MSBuildRuntime = xml.MSBuildRuntime;
+
+ condition_location = xml.ConditionLocation;
+ ContinueOnErrorLocation = xml.ContinueOnErrorLocation;
+ location = xml.Location;
+ MSBuildArchitectureLocation = xml.MSBuildArchitectureLocation;
+ MSBuildRuntimeLocation = xml.MSBuildRuntimeLocation;
+ #endif
+ }
+
+ string condition;
+ public override string Condition {
+ get { return condition; }
+ }
+
+ ElementLocation condition_location, location;
+
+ #if NET_4_5
+ public
+ #else
+ internal
+ #endif
+ override ElementLocation ConditionLocation {
+ get { return condition_location; }
+ }
+
+ #if NET_4_5
+ public
+ #else
+ internal
+ #endif
+ override ElementLocation Location {
+ get { return location; }
+ }
+
+ public string ContinueOnError { get; private set; }
+
+ #if NET_4_5
+ public ElementLocation ContinueOnErrorLocation { get; private set; }
+
+ public string MSBuildArchitecture { get; private set; }
+
+ public ElementLocation MSBuildArchitectureLocation { get; private set; }
+
+ public string MSBuildRuntime { get; private set; }
+
+ public ElementLocation MSBuildRuntimeLocation { get; private set; }
+ #endif
+
+ public string Name { get; private set; }
+
+ public IList<ProjectTaskInstanceChild> Outputs { get; private set; }
+
+ public IDictionary<string, string> Parameters { get; private set; }
+ }
+}
+
--- /dev/null
+using System;
+using Microsoft.Build.Construction;
+
+namespace Microsoft.Build.Execution
+{
+ public abstract class ProjectTaskInstanceChild
+ {
+ public abstract string Condition { get; }
+ #if NET_4_5
+ public abstract ElementLocation ConditionLocation { get; }
+ public abstract ElementLocation Location { get; }
+ public abstract ElementLocation TaskParameterLocation { get; }
+ #endif
+ }
+}
+
--- /dev/null
+using System;
+using Microsoft.Build.Construction;
+
+namespace Microsoft.Build.Execution
+{
+ public class ProjectTaskOutputItemInstance : ProjectTaskInstanceChild
+ {
+ internal ProjectTaskOutputItemInstance (ProjectOutputElement xml)
+ {
+ condition = xml.Condition;
+ ItemType = xml.ItemType;
+ TaskParameter = xml.TaskParameter;
+ #if NET_4_5
+ condition_location = xml.ConditionLocation;
+ location = xml.Location;
+ task_parameter_location = xml.TaskParameterLocation;
+ #endif
+ }
+
+ public string ItemType { get; private set; }
+ public string TaskParameter { get; private set; }
+
+ readonly string condition;
+ public override string Condition {
+ get { return condition; }
+ }
+ #if NET_4_5
+ readonly ElementLocation condition_location, location, task_parameter_location;
+ public ElementLocation ItemTypeLocation { get; private set; }
+ public override ElementLocation ConditionLocation {
+ get { return condition_location; }
+ }
+ public override ElementLocation Location {
+ get { return location; }
+ }
+ public override ElementLocation TaskParameterLocation {
+ get { return task_parameter_location; }
+ }
+ #endif
+ }
+}
+
--- /dev/null
+using System;
+using Microsoft.Build.Construction;
+
+namespace Microsoft.Build.Execution
+{
+ public class ProjectTaskOutputPropertyInstance : ProjectTaskInstanceChild
+ {
+ internal ProjectTaskOutputPropertyInstance (ProjectOutputElement xml)
+ {
+ condition = xml.Condition;
+ PropertyName = xml.PropertyName;
+ TaskParameter = xml.TaskParameter;
+ #if NET_4_5
+ condition_location = xml.ConditionLocation;
+ location = xml.Location;
+ task_parameter_location = xml.TaskParameterLocation;
+ #endif
+ }
+
+ public string PropertyName { get; private set; }
+ public string TaskParameter { get; private set; }
+
+ readonly string condition;
+ public override string Condition {
+ get { return condition; }
+ }
+
+ #if NET_4_5
+ readonly ElementLocation condition_location, location, task_parameter_location;
+ public ElementLocation PropertyNameLocation { get; private set; }
+ public override ElementLocation ConditionLocation {
+ get { return condition_location; }
+ }
+ public override ElementLocation Location {
+ get { return location; }
+ }
+ public override ElementLocation TaskParameterLocation {
+ get { return task_parameter_location; }
+ }
+ #endif
+ }
+}
+
//
using Microsoft.Build.Framework;
-
using System;
+using System.Linq;
+using System.Collections.Generic;
namespace Microsoft.Build.Execution
{
- public class TargetResult : ITargetResult
- {
- internal TargetResult ()
- {
- throw new NotImplementedException ();
- }
+ public class TargetResult : ITargetResult
+ {
+ internal TargetResult ()
+ {
+ }
- public Exception Exception {
- get { throw new NotImplementedException (); }
- }
+ public Exception Exception { get; private set; }
- public ITaskItem[] Items {
- get { throw new NotImplementedException (); }
- }
+ public ITaskItem[] Items { get; private set; }
+ public TargetResultCode ResultCode { get; private set; }
- public TargetResultCode ResultCode {
- get { throw new NotImplementedException (); }
- }
- }
+ internal void Failure (Exception exception)
+ {
+ this.Exception = exception;
+ ResultCode = TargetResultCode.Failure;
+ }
+
+ internal void Skip ()
+ {
+ ResultCode = TargetResultCode.Skipped;
+ }
+
+ internal void Success (IEnumerable<ITaskItem> items)
+ {
+ Items = items.ToArray ();
+ ResultCode = TargetResultCode.Success;
+ }
+ }
}
--- /dev/null
+//
+// BuildEngine4.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using Microsoft.Build.Execution;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Evaluation;
+using System.Linq;
+using System.IO;
+using Microsoft.Build.Exceptions;
+using System.Globalization;
+
+namespace Microsoft.Build.Internal
+{
+ class BuildEngine4
+#if NET_4_5
+ : IBuildEngine4
+#else
+ : IBuildEngine3
+#endif
+ {
+ public BuildEngine4 (BuildSubmission submission)
+ {
+ this.submission = submission;
+ event_source = new Microsoft.Build.BuildEngine.EventSource ();
+ if (submission.BuildManager.OngoingBuildParameters.Loggers != null)
+ foreach (var l in submission.BuildManager.OngoingBuildParameters.Loggers)
+ l.Initialize (event_source);
+ }
+
+ BuildSubmission submission;
+ ProjectInstance project;
+ ProjectTaskInstance current_task;
+ Microsoft.Build.BuildEngine.EventSource event_source;
+
+ public ProjectCollection Projects {
+ get { return submission.BuildManager.OngoingBuildParameters.ProjectCollection; }
+ }
+
+ // FIXME:
+ // While we are not faced to implement those features, there are some modern task execution requirements.
+ //
+ // This will have to be available for "out of process" nodes (see NodeAffinity).
+ // NodeAffinity is set per project file at BuildManager.HostServices.
+ // When NodeAffinity is set to OutOfProc, it should probably launch different build host
+ // that runs separate build tasks. (.NET has MSBuildTaskHost.exe which I guess is about that.)
+ //
+ // Also note that the complete implementation has to support LoadInSeparateAppDomainAttribute
+ // (which is most likely derived from AppDomainIsolatedBuildTask) that marks a task to run
+ // in separate AppDomain.
+ //
+ public void BuildProject (Func<bool> checkCancel, BuildResult result, ProjectInstance project, IEnumerable<string> targetNames, IDictionary<string,string> globalProperties, IDictionary<string,string> targetOutputs, string toolsVersion)
+ {
+ if (toolsVersion == null)
+ throw new ArgumentNullException ("toolsVersion");
+
+ var parameters = submission.BuildManager.OngoingBuildParameters;
+ var toolset = parameters.GetToolset (toolsVersion);
+ if (toolset == null)
+ throw new InvalidOperationException (string.Format ("Toolset version '{0}' was not resolved to valid toolset", toolsVersion));
+ LogMessageEvent (new BuildMessageEventArgs (string.Format ("Using Toolset version {0}.", toolsVersion), null, null, MessageImportance.Low));
+ var buildTaskFactory = new BuildTaskFactory (BuildTaskDatabase.GetDefaultTaskDatabase (toolset), submission.BuildRequest.ProjectInstance.TaskDatabase);
+ BuildProject (new InternalBuildArguments () { CheckCancel = checkCancel, Result = result, Project = project, TargetNames = targetNames, GlobalProperties = globalProperties, TargetOutputs = targetOutputs, ToolsVersion = toolsVersion, BuildTaskFactory = buildTaskFactory });
+ }
+
+ class InternalBuildArguments
+ {
+ public Func<bool> CheckCancel;
+ public BuildResult Result;
+ public ProjectInstance Project;
+ public IEnumerable<string> TargetNames;
+ public IDictionary<string,string> GlobalProperties;
+ public IDictionary<string,string> TargetOutputs;
+ public string ToolsVersion;
+ public BuildTaskFactory BuildTaskFactory;
+
+ public void AddTargetResult (string targetName, TargetResult targetResult)
+ {
+ if (!Result.HasResultsForTarget (targetName))
+ Result.AddResultsForTarget (targetName, targetResult);
+ }
+ }
+
+ void BuildProject (InternalBuildArguments args)
+ {
+ var request = submission.BuildRequest;
+ var parameters = submission.BuildManager.OngoingBuildParameters;
+ this.project = args.Project;
+
+ event_source.FireBuildStarted (this, new BuildStartedEventArgs ("Build Started", null, DateTime.Now));
+
+ try {
+
+ var initialPropertiesFormatted = "Initial Properties:\n" + string.Join (Environment.NewLine, project.Properties.OrderBy (p => p.Name).Select (p => string.Format ("{0} = {1}", p.Name, p.EvaluatedValue)).ToArray ());
+ LogMessageEvent (new BuildMessageEventArgs (initialPropertiesFormatted, null, null, MessageImportance.Low));
+ var initialItemsFormatted = "Initial Items:\n" + string.Join (Environment.NewLine, project.Items.OrderBy (i => i.ItemType).Select (i => string.Format ("{0} : {1}", i.ItemType, i.EvaluatedInclude)).ToArray ());
+ LogMessageEvent (new BuildMessageEventArgs (initialItemsFormatted, null, null, MessageImportance.Low));
+
+ // null targets -> success. empty targets -> success(!)
+ if (request.TargetNames == null)
+ args.Result.OverallResult = BuildResultCode.Success;
+ else {
+ foreach (var targetName in (args.TargetNames ?? request.TargetNames).Where (t => t != null))
+ BuildTargetByName (targetName, args);
+
+ // FIXME: check .NET behavior, whether cancellation always results in failure.
+ args.Result.OverallResult = args.CheckCancel () ? BuildResultCode.Failure : args.Result.ResultsByTarget.Any (p => p.Value.ResultCode == TargetResultCode.Failure) ? BuildResultCode.Failure : BuildResultCode.Success;
+ }
+ } catch (Exception ex) {
+ args.Result.OverallResult = BuildResultCode.Failure;
+ LogErrorEvent (new BuildErrorEventArgs (null, null, project.FullPath, 0, 0, 0, 0, "Unhandled exception occured during a build", null, null));
+ LogMessageEvent (new BuildMessageEventArgs ("Exception details: " + ex, null, null, MessageImportance.Low));
+ throw; // BuildSubmission re-catches this.
+ } finally {
+ event_source.FireBuildFinished (this, new BuildFinishedEventArgs ("Build Finished.", null, args.Result.OverallResult == BuildResultCode.Success, DateTime.Now));
+ }
+ }
+
+ bool BuildTargetByName (string targetName, InternalBuildArguments args)
+ {
+ var request = submission.BuildRequest;
+ var parameters = submission.BuildManager.OngoingBuildParameters;
+ ProjectTargetInstance target;
+ TargetResult dummyResult;
+
+ if (args.Result.ResultsByTarget.TryGetValue (targetName, out dummyResult) && dummyResult.ResultCode == TargetResultCode.Success) {
+ LogMessageEvent (new BuildMessageEventArgs (string.Format ("Target '{0}' was skipped because it was already built successfully.", targetName), null, null, MessageImportance.Low));
+ return true; // do not add result.
+ }
+
+ var targetResult = new TargetResult ();
+
+ // null key is allowed and regarded as blind success(!) (as long as it could retrieve target)
+ if (!request.ProjectInstance.Targets.TryGetValue (targetName, out target))
+ throw new InvalidOperationException (string.Format ("target '{0}' was not found in project '{1}'", targetName, project.FullPath));
+ else if (!args.Project.EvaluateCondition (target.Condition)) {
+ LogMessageEvent (new BuildMessageEventArgs (string.Format ("Target '{0}' was skipped because condition '{1}' was not met.", target.Name, target.Condition), null, null, MessageImportance.Low));
+ targetResult.Skip ();
+ } else {
+ // process DependsOnTargets first.
+ foreach (var dep in project.ExpandString (target.DependsOnTargets).Split (';').Select (s => s.Trim ()).Where (s => !string.IsNullOrEmpty (s))) {
+ if (!BuildTargetByName (dep, args)) {
+ return false;
+ }
+ }
+
+ Func<string,ITaskItem> creator = s => new TargetOutputTaskItem () { ItemSpec = s };
+
+ event_source.FireTargetStarted (this, new TargetStartedEventArgs ("Target Started", null, target.Name, project.FullPath, target.FullPath));
+ try {
+ if (!string.IsNullOrEmpty (target.Inputs) != !string.IsNullOrEmpty (target.Outputs)) {
+ targetResult.Failure (new InvalidProjectFileException (target.Location, null, string.Format ("Target {0} has mismatching Inputs and Outputs specification. When one is specified, another one has to be specified too.", targetName), null, null, null));
+ } else {
+ bool skip = false;
+ if (!string.IsNullOrEmpty (target.Inputs)) {
+ var inputs = args.Project.GetAllItems (target.Inputs, string.Empty, creator, creator, s => true, (t, s) => {
+ });
+ if (!inputs.Any ()) {
+ LogMessageEvent (new BuildMessageEventArgs (string.Format ("Target '{0}' was skipped because there is no input.", target.Name), null, null, MessageImportance.Low));
+ skip = true;
+ } else {
+ var outputs = args.Project.GetAllItems (target.Outputs, string.Empty, creator, creator, s => true, (t, s) => {
+ });
+ var needsUpdates = GetOlderOutputsThanInputs (inputs, outputs).FirstOrDefault ();
+ if (needsUpdates != null)
+ LogMessageEvent (new BuildMessageEventArgs (string.Format ("Target '{0}' needs to be built because new output {1} is needed.", target.Name, needsUpdates.ItemSpec), null, null, MessageImportance.Low));
+ else {
+ LogMessageEvent (new BuildMessageEventArgs (string.Format ("Target '{0}' was skipped because all the outputs are newer than all the inputs.", target.Name), null, null, MessageImportance.Low));
+ skip = true;
+ }
+ }
+ }
+ if (skip) {
+ targetResult.Skip ();
+ } else {
+ if (DoBuildTarget (target, targetResult, args)) {
+ var items = args.Project.GetAllItems (target.Outputs, string.Empty, creator, creator, s => true, (t, s) => {
+ });
+ targetResult.Success (items);
+ }
+ }
+ }
+ } finally {
+ event_source.FireTargetFinished (this, new TargetFinishedEventArgs ("Target Finished", null, targetName, project.FullPath, target.FullPath, targetResult.ResultCode != TargetResultCode.Failure));
+ }
+ }
+ args.AddTargetResult (targetName, targetResult);
+
+ return targetResult.ResultCode != TargetResultCode.Failure;
+ }
+
+ IEnumerable<ITaskItem> GetOlderOutputsThanInputs (IEnumerable<ITaskItem> inputs, IEnumerable<ITaskItem> outputs)
+ {
+ return outputs.Where (o => !File.Exists (o.GetMetadata ("FullPath")) || inputs.Any (i => string.CompareOrdinal (i.GetMetadata ("LastModifiedTime"), o.GetMetadata ("LastModifiedTime")) > 0));
+ }
+
+ bool DoBuildTarget (ProjectTargetInstance target, TargetResult targetResult, InternalBuildArguments args)
+ {
+ var request = submission.BuildRequest;
+
+ // Here we check cancellation (only after TargetStarted event).
+ if (args.CheckCancel ()) {
+ targetResult.Failure (new BuildAbortedException ("Build has canceled"));
+ return false;
+ }
+
+ var propsToRestore = new Dictionary<string,string> ();
+ var itemsToRemove = new List<ProjectItemInstance> ();
+ try {
+ // Evaluate additional target properties
+ foreach (var c in target.Children.OfType<ProjectPropertyGroupTaskInstance> ()) {
+ if (!args.Project.EvaluateCondition (c.Condition))
+ continue;
+ foreach (var p in c.Properties) {
+ if (!args.Project.EvaluateCondition (p.Condition))
+ continue;
+ var value = args.Project.ExpandString (p.Value);
+ propsToRestore.Add (p.Name, project.GetPropertyValue (value));
+ project.SetProperty (p.Name, value);
+ }
+ }
+
+ // Evaluate additional target items
+ foreach (var c in target.Children.OfType<ProjectItemGroupTaskInstance> ()) {
+ if (!args.Project.EvaluateCondition (c.Condition))
+ continue;
+ foreach (var item in c.Items) {
+ if (!args.Project.EvaluateCondition (item.Condition))
+ continue;
+ Func<string,ProjectItemInstance> creator = i => new ProjectItemInstance (project, item.ItemType, item.Metadata.Select (m => new KeyValuePair<string,string> (m.Name, m.Value)), i);
+ foreach (var ti in project.GetAllItems (item.Include, item.Exclude, creator, creator, s => s == item.ItemType, (ti, s) => ti.SetMetadata ("RecurseDir", s)))
+ itemsToRemove.Add (ti);
+ }
+ }
+
+ foreach (var c in target.Children.OfType<ProjectOnErrorInstance> ()) {
+ if (!args.Project.EvaluateCondition (c.Condition))
+ continue;
+ throw new NotImplementedException ();
+ }
+
+ // run tasks
+ foreach (var ti in target.Children.OfType<ProjectTaskInstance> ()) {
+ current_task = ti;
+ if (!args.Project.EvaluateCondition (ti.Condition)) {
+ LogMessageEvent (new BuildMessageEventArgs (string.Format ("Task '{0}' was skipped because condition '{1}' wasn't met.", ti.Name, ti.Condition), null, null, MessageImportance.Low));
+ continue;
+ }
+ if (!RunBuildTask (target, ti, targetResult, args))
+ return false;
+ }
+ } finally {
+ // restore temporary property state to the original state.
+ foreach (var p in propsToRestore) {
+ if (p.Value == string.Empty)
+ project.RemoveProperty (p.Key);
+ else
+ project.SetProperty (p.Key, p.Value);
+ }
+ foreach (var item in itemsToRemove)
+ project.RemoveItem (item);
+ }
+ return true;
+ }
+
+ bool RunBuildTask (ProjectTargetInstance target, ProjectTaskInstance taskInstance, TargetResult targetResult, InternalBuildArguments args)
+ {
+ var request = submission.BuildRequest;
+
+ var host = request.HostServices == null ? null : request.HostServices.GetHostObject (request.ProjectFullPath, target.Name, taskInstance.Name);
+
+ // Create Task instance.
+ var factoryIdentityParameters = new Dictionary<string,string> ();
+ #if NET_4_5
+ factoryIdentityParameters ["MSBuildRuntime"] = taskInstance.MSBuildRuntime;
+ factoryIdentityParameters ["MSBuildArchitecture"] = taskInstance.MSBuildArchitecture;
+ #endif
+ var task = args.BuildTaskFactory.CreateTask (taskInstance.Name, factoryIdentityParameters, this);
+ LogMessageEvent (new BuildMessageEventArgs (string.Format ("Using task {0} from {1}", taskInstance.Name, task.GetType ().AssemblyQualifiedName), null, null, MessageImportance.Low));
+ task.HostObject = host;
+ task.BuildEngine = this;
+
+ // Prepare task parameters.
+ var evaluatedTaskParams = taskInstance.Parameters.Select (p => new KeyValuePair<string,string> (p.Key, project.ExpandString (p.Value)));
+
+ var requiredProps = task.GetType ().GetProperties ()
+ .Where (p => p.CanWrite && p.GetCustomAttributes (typeof (RequiredAttribute), true).Any ());
+ var missings = requiredProps.Where (p => !evaluatedTaskParams.Any (tp => tp.Key.Equals (p.Name, StringComparison.OrdinalIgnoreCase)));
+ if (missings.Any ())
+ throw new InvalidOperationException (string.Format ("Task {0} of type {1} is used without specifying mandatory property: {2}",
+ taskInstance.Name, task.GetType (), string.Join (", ", missings.Select (p => p.Name).ToArray ())));
+
+ foreach (var p in evaluatedTaskParams) {
+ var prop = task.GetType ().GetProperty (p.Key);
+ if (prop == null)
+ throw new InvalidOperationException (string.Format ("Task {0} does not have property {1}", taskInstance.Name, p.Key));
+ if (!prop.CanWrite)
+ throw new InvalidOperationException (string.Format ("Task {0} has property {1} but it is read-only.", taskInstance.Name, p.Key));
+ if (string.IsNullOrEmpty (p.Value) && !requiredProps.Contains (prop))
+ continue;
+ try {
+ var valueInstance = ConvertTo (p.Value, prop.PropertyType);
+ prop.SetValue (task, valueInstance, null);
+ } catch (Exception ex) {
+ throw new InvalidOperationException (string.Format ("Failed to convert '{0}' for property '{1}' of type {2}", p.Value, prop.Name, prop.PropertyType), ex);
+ }
+ }
+
+ // Do execute task.
+ bool taskSuccess = false;
+ event_source.FireTaskStarted (this, new TaskStartedEventArgs ("Task Started", null, project.FullPath, taskInstance.FullPath, taskInstance.Name));
+ try {
+ taskSuccess = task.Execute ();
+
+ if (!taskSuccess) {
+ targetResult.Failure (null);
+ if (!ContinueOnError) {
+ return false;
+ }
+ } else {
+ // Evaluate task output properties and items.
+ foreach (var to in taskInstance.Outputs) {
+ if (!project.EvaluateCondition (to.Condition))
+ continue;
+ var toItem = to as ProjectTaskOutputItemInstance;
+ var toProp = to as ProjectTaskOutputPropertyInstance;
+ string taskParameter = toItem != null ? toItem.TaskParameter : toProp.TaskParameter;
+ var pi = task.GetType ().GetProperty (taskParameter);
+ if (pi == null)
+ throw new InvalidOperationException (string.Format ("Task {0} does not have property {1} specified as TaskParameter", taskInstance.Name, toItem.TaskParameter));
+ if (!pi.CanRead)
+ throw new InvalidOperationException (string.Format ("Task {0} has property {1} specified as TaskParameter, but it is write-only", taskInstance.Name, toItem.TaskParameter));
+ var value = ConvertFrom (pi.GetValue (task, null));
+ if (toItem != null) {
+ LogMessageEvent (new BuildMessageEventArgs (string.Format ("Output Item {0} from TaskParameter {1}: {2}", toItem.ItemType, toItem.TaskParameter, value), null, null, MessageImportance.Low));
+ foreach (var item in value.Split (';'))
+ args.Project.AddItem (toItem.ItemType, item);
+ } else {
+ LogMessageEvent (new BuildMessageEventArgs (string.Format ("Output Property {0} from TaskParameter {1}: {2}", toProp.PropertyName, toProp.TaskParameter, value), null, null, MessageImportance.Low));
+ args.Project.SetProperty (toProp.PropertyName, value);
+ }
+ }
+ }
+ } finally {
+ event_source.FireTaskFinished (this, new TaskFinishedEventArgs ("Task Finished", null, project.FullPath, taskInstance.FullPath, taskInstance.Name, taskSuccess));
+ }
+ return true;
+ }
+
+ object ConvertTo (string source, Type targetType)
+ {
+ if (targetType == typeof(ITaskItem) || targetType.IsSubclassOf (typeof(ITaskItem)))
+ return new TargetOutputTaskItem () { ItemSpec = WindowsCompatibilityExtensions.NormalizeFilePath (source.Trim ()) };
+ if (targetType.IsArray)
+ return new ArrayList (source.Split (';').Select (s => s.Trim ()).Where (s => !string.IsNullOrEmpty (s)).Select (s => ConvertTo (s, targetType.GetElementType ())).ToArray ())
+ .ToArray (targetType.GetElementType ());
+ if (targetType == typeof(bool)) {
+ switch (source != null ? source.ToLower (CultureInfo.InvariantCulture) : string.Empty) {
+ case "true":
+ case "yes":
+ case "on":
+ return true;
+ case "false":
+ case "no":
+ case "off":
+ case "":
+ return false;
+ }
+ }
+ return Convert.ChangeType (source == "" ? null : source, targetType);
+ }
+
+ string ConvertFrom (object source)
+ {
+ if (source == null)
+ return string.Empty;
+ if (source is ITaskItem)
+ return ((ITaskItem) source).ItemSpec;
+ if (source.GetType ().IsArray)
+ return string.Join (";", ((Array) source).Cast<object> ().Select (o => ConvertFrom (o)).ToArray ());
+ else
+ return (string) Convert.ChangeType (source, typeof (string));
+ }
+
+ class TargetOutputTaskItem : ITaskItem2
+ {
+ Hashtable metadata = new Hashtable ();
+
+ #region ITaskItem2 implementation
+ public string GetMetadataValueEscaped (string metadataName)
+ {
+ return ProjectCollection.Escape ((string) metadata [metadataName]);
+ }
+ public void SetMetadataValueLiteral (string metadataName, string metadataValue)
+ {
+ metadata [metadataName] = ProjectCollection.Unescape (metadataValue);
+ }
+ public IDictionary CloneCustomMetadataEscaped ()
+ {
+ var ret = new Hashtable ();
+ foreach (DictionaryEntry e in metadata)
+ ret [e.Key] = ProjectCollection.Escape ((string) e.Value);
+ return ret;
+ }
+ public string EvaluatedIncludeEscaped {
+ get { return ProjectCollection.Escape (ItemSpec); }
+ set { ItemSpec = ProjectCollection.Unescape (value); }
+ }
+ #endregion
+ #region ITaskItem implementation
+ public IDictionary CloneCustomMetadata ()
+ {
+ return new Hashtable (metadata);
+ }
+ public void CopyMetadataTo (ITaskItem destinationItem)
+ {
+ foreach (DictionaryEntry e in metadata)
+ destinationItem.SetMetadata ((string) e.Key, (string) e.Value);
+ }
+ public string GetMetadata (string metadataName)
+ {
+ var wk = ProjectCollection.GetWellKnownMetadata (metadataName, ItemSpec, Path.GetFullPath, null);
+ if (wk != null)
+ return wk;
+ return (string) metadata [metadataName];
+ }
+ public void RemoveMetadata (string metadataName)
+ {
+ metadata.Remove (metadataName);
+ }
+ public void SetMetadata (string metadataName, string metadataValue)
+ {
+ metadata [metadataName] = metadataValue;
+ }
+ public string ItemSpec { get; set; }
+ public int MetadataCount {
+ get { return metadata.Count; }
+ }
+ public ICollection MetadataNames {
+ get { return metadata.Keys; }
+ }
+ #endregion
+ }
+
+#if NET_4_5
+ #region IBuildEngine4 implementation
+
+ // task objects are not in use anyways though...
+
+ class TaskObjectRegistration
+ {
+ public TaskObjectRegistration (object key, object obj, RegisteredTaskObjectLifetime lifetime, bool allowEarlyCollection)
+ {
+ Key = key;
+ Object = obj;
+ Lifetime = lifetime;
+ AllowEarlyCollection = allowEarlyCollection;
+ }
+ public object Key { get; private set; }
+ public object Object { get; private set; }
+ public RegisteredTaskObjectLifetime Lifetime { get; private set; }
+ public bool AllowEarlyCollection { get; private set; }
+ }
+
+ List<TaskObjectRegistration> task_objects = new List<TaskObjectRegistration> ();
+
+ public object GetRegisteredTaskObject (object key, RegisteredTaskObjectLifetime lifetime)
+ {
+ var reg = task_objects.FirstOrDefault (t => t.Key == key && t.Lifetime == lifetime);
+ return reg != null ? reg.Object : null;
+ }
+
+ public void RegisterTaskObject (object key, object obj, RegisteredTaskObjectLifetime lifetime, bool allowEarlyCollection)
+ {
+ task_objects.Add (new TaskObjectRegistration (key, obj, lifetime, allowEarlyCollection));
+ }
+
+ public object UnregisterTaskObject (object key, RegisteredTaskObjectLifetime lifetime)
+ {
+ var reg = task_objects.FirstOrDefault (t => t.Key == key && t.Lifetime == lifetime);
+ if (reg != null)
+ task_objects.Remove (reg);
+ return reg.Object;
+ }
+ #endregion
+#endif
+
+ #region IBuildEngine3 implementation
+
+ public BuildEngineResult BuildProjectFilesInParallel (string[] projectFileNames, string[] targetNames, IDictionary[] globalProperties, IList<string>[] removeGlobalProperties, string[] toolsVersion, bool returnTargetOutputs)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public void Reacquire ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ public void Yield ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ #endregion
+
+ #region IBuildEngine2 implementation
+
+ public bool BuildProjectFile (string projectFileName, string[] targetNames, IDictionary globalProperties, IDictionary targetOutputs, string toolsVersion)
+ {
+ var proj = GetProjectInstance (projectFileName, toolsVersion);
+ var globalPropertiesThatMakeSense = new Dictionary<string,string> ();
+ foreach (DictionaryEntry p in globalProperties)
+ globalPropertiesThatMakeSense [(string) p.Key] = (string) p.Value;
+ var result = new BuildResult ();
+ var outputs = new Dictionary<string, string> ();
+ BuildProject (() => false, result, proj, targetNames, globalPropertiesThatMakeSense, outputs, toolsVersion);
+ foreach (var p in outputs)
+ targetOutputs [p.Key] = p.Value;
+ return result.OverallResult == BuildResultCode.Success;
+ }
+
+ public bool BuildProjectFilesInParallel (string[] projectFileNames, string[] targetNames, IDictionary[] globalProperties, IDictionary[] targetOutputsPerProject, string[] toolsVersion, bool useResultsCache, bool unloadProjectsOnCompletion)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public bool IsRunningMultipleNodes {
+ get {
+ throw new NotImplementedException ();
+ }
+ }
+
+ ProjectInstance GetProjectInstance (string projectFileName, string toolsVersion)
+ {
+ string fullPath = Path.GetFullPath (projectFileName);
+ if (submission.BuildRequest.ProjectFullPath == fullPath)
+ return submission.BuildRequest.ProjectInstance;
+ // FIXME: could also be filtered by global properties
+ // http://msdn.microsoft.com/en-us/library/microsoft.build.evaluation.projectcollection.getloadedprojects.aspx
+ var project = Projects.GetLoadedProjects (projectFileName).FirstOrDefault (p => p.ToolsVersion == toolsVersion);
+ if (project == null)
+ throw new InvalidOperationException (string.Format ("Project '{0}' is not loaded", projectFileName));
+ return submission.BuildManager.GetProjectInstanceForBuild (project);
+ }
+
+ #endregion
+
+ #region IBuildEngine implementation
+
+ public bool BuildProjectFile (string projectFileName, string[] targetNames, IDictionary globalProperties, IDictionary targetOutputs)
+ {
+ return BuildProjectFile (projectFileName, targetNames, globalProperties, targetOutputs, Projects.DefaultToolsVersion);
+ }
+
+ public void LogCustomEvent (CustomBuildEventArgs e)
+ {
+ event_source.FireCustomEventRaised (this, e);
+ }
+
+ public void LogErrorEvent (BuildErrorEventArgs e)
+ {
+ event_source.FireErrorRaised (this, e);
+ }
+
+ public void LogMessageEvent (BuildMessageEventArgs e)
+ {
+ event_source.FireMessageRaised (this, e);
+ }
+
+ public void LogWarningEvent (BuildWarningEventArgs e)
+ {
+ event_source.FireWarningRaised (this, e);
+ }
+
+ public int ColumnNumberOfTaskNode {
+ get { return current_task.Location != null ? current_task.Location.Column : 0; }
+ }
+
+ public bool ContinueOnError {
+ get { return current_task != null && project.EvaluateCondition (current_task.Condition) && EvaluateContinueOnError (current_task.ContinueOnError); }
+ }
+
+ bool EvaluateContinueOnError (string value)
+ {
+ switch (value) {
+ case "WarnAndContinue":
+ case "ErrorAndContinue":
+ return true;
+ case "ErrorAndStop":
+ return false;
+ }
+ // empty means "stop on error", so don't pass empty string to EvaluateCondition().
+ return !string.IsNullOrEmpty (value) && project.EvaluateCondition (value);
+ }
+
+ public int LineNumberOfTaskNode {
+ get { return current_task.Location != null ? current_task.Location.Line : 0; }
+ }
+
+ public string ProjectFileOfTaskNode {
+ get { return current_task.FullPath; }
+ }
+
+ #endregion
+ }
+}
+
--- /dev/null
+//
+// BuildNodeManager.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Build.Execution;
+using Microsoft.Build.Framework;
+using System.Threading.Tasks;
+using System.Threading;
+using System.Collections.Concurrent;
+
+namespace Microsoft.Build.Internal
+{
+ class BuildNodeManager
+ {
+ public BuildNodeManager (BuildManager buildManager)
+ {
+ BuildManager = buildManager;
+ new Thread (RunLoop).Start ();
+ }
+
+ ~BuildNodeManager ()
+ {
+ run_loop = false;
+ queue_wait_handle.Set ();
+ }
+
+ public BuildManager BuildManager { get; private set; }
+
+ List<BuildNode> in_proc_nodes = new List<BuildNode> ();
+ List<BuildNode> out_proc_nodes = new List<BuildNode> ();
+ AutoResetEvent queue_wait_handle = new AutoResetEvent (false);
+ ConcurrentQueue<BuildSubmission> queued_builds = new ConcurrentQueue<BuildSubmission> ();
+ // FIXME: currently it is not in use but it should be stored somewhere for cancellation.
+ Dictionary<BuildSubmission,Task> ongoing_builds = new Dictionary<BuildSubmission, Task> ();
+ bool run_loop = true;
+
+ readonly TaskFactory<BuildResult> task_factory = new TaskFactory<BuildResult> ();
+ internal TaskFactory<BuildResult> ThreadTaskFactory {
+ get { return task_factory; }
+ }
+
+ void RunLoop ()
+ {
+ while (run_loop) {
+ try {
+ if (queued_builds.Count == 0)
+ queue_wait_handle.WaitOne ();
+ if (!run_loop)
+ break;
+ BuildSubmission build;
+ if (!queued_builds.TryDequeue (out build))
+ continue;
+ StartOneBuild (build);
+ } catch (Exception ex) {
+ // FIXME: I guess INodeLogger should be used instead.
+ Console.Error.WriteLine ("Uncaught build node exception occured");
+ Console.Error.WriteLine (ex);
+ }
+ }
+ }
+
+ public void Stop ()
+ {
+ run_loop = false;
+ queue_wait_handle.Set ();
+ }
+
+ public void ResetCaches ()
+ {
+ in_proc_nodes.Clear ();
+ out_proc_nodes.Clear ();
+ }
+
+ public void Enqueue (BuildSubmission build)
+ {
+ queued_builds.Enqueue (build);
+ queue_wait_handle.Set ();
+ }
+
+ void StartOneBuild (BuildSubmission build)
+ {
+ var node = TakeNode (build);
+ // FIXME: Task (non-generic) here causes NotImplementedException in somewhere in Interlocked. It does not make sense.
+ ongoing_builds [build] = task_factory.StartNew (node.ExecuteBuild);
+ //new Thread (() => { node.ExecuteBuild (); }).Start ();
+ }
+
+ void EndOneBuild (BuildNode node)
+ {
+ var task = ongoing_builds [node.Build];
+ ongoing_builds [node.Build] = null;
+ node.Release ();
+ }
+
+ // FIXME: take max nodes into account here, and get throttling working.
+ BuildNode TakeNode (BuildSubmission build)
+ {
+ var host = BuildManager.OngoingBuildParameters.HostServices;
+ NodeAffinity affinity;
+ if (host == null)
+ affinity = NodeAffinity.Any;
+ else
+ affinity = host.GetNodeAffinity (build.BuildRequest.ProjectFullPath);
+ BuildNode n = GetReusableNode (affinity);
+ if (n != null)
+ n.Assign (build);
+ else {
+ n = new BuildNode (this, affinity == NodeAffinity.Any ? NodeAffinity.InProc : affinity);
+ n.Assign (build);
+ if (n.Affinity == NodeAffinity.InProc)
+ in_proc_nodes.Add (n);
+ else
+ out_proc_nodes.Add (n);
+ }
+ return n;
+ }
+
+ BuildNode GetReusableNode (NodeAffinity affinity)
+ {
+ if (!BuildManager.OngoingBuildParameters.EnableNodeReuse)
+ return null;
+
+ if (affinity != NodeAffinity.OutOfProc)
+ foreach (var n in in_proc_nodes)
+ if (n.IsAvailable && (n.Affinity & affinity) != 0)
+ return n;
+ if (affinity != NodeAffinity.InProc)
+ foreach (var n in out_proc_nodes)
+ if (n.IsAvailable && (n.Affinity & affinity) != 0)
+ return n;
+ return null;
+ }
+
+ internal class BuildNode
+ {
+ static Random rnd = new Random ();
+
+ public BuildNode (BuildNodeManager manager, NodeAffinity affinity)
+ {
+ Manager = manager;
+ Affinity = affinity;
+ Id = rnd.Next ();
+ }
+
+ public bool IsAvailable { get; private set; }
+ public int Id { get; private set; }
+ public BuildNodeManager Manager { get; set; }
+ public NodeAffinity Affinity { get; private set; }
+ public BuildSubmission Build { get; private set; }
+
+ public void Assign (BuildSubmission build)
+ {
+ IsAvailable = false;
+ Build = build;
+ }
+
+ public void Release ()
+ {
+ Build = null;
+ IsAvailable = true;
+ }
+
+ public BuildResult ExecuteBuild ()
+ {
+ BuildResult result;
+ try {
+ // FIXME: depending on NodeAffinity, build it through another MSBuild process.
+ if (Affinity == NodeAffinity.OutOfProc)
+ throw new NotImplementedException ();
+ result = Build.InternalExecute ();
+ } catch (Exception ex) {
+ // FIXME: I guess INodeLogger should be used instead.
+ Console.Error.WriteLine ("Uncaught build node exception occured");
+ Console.Error.WriteLine (ex);
+ result = null;
+ } finally {
+ Manager.EndOneBuild (this);
+ }
+ return result;
+ }
+ }
+ }
+}
--- /dev/null
+//
+// BuildTaskFactory.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Build.Framework;
+using System.Reflection;
+using Microsoft.Build.Execution;
+using Microsoft.Build.Evaluation;
+using Microsoft.Build.Construction;
+using System.IO;
+using System.Xml;
+
+namespace Microsoft.Build.Internal
+{
+ class BuildTaskDatabase
+ {
+ const string default_tasks_file = "Microsoft.Common.tasks";
+ static readonly Dictionary<string,BuildTaskDatabase> default_factory = new Dictionary<string, BuildTaskDatabase> ();
+
+ public static BuildTaskDatabase GetDefaultTaskDatabase (Toolset toolset)
+ {
+ if (toolset == null)
+ throw new ArgumentNullException ("toolset");
+ BuildTaskDatabase defaults;
+ if (!default_factory.TryGetValue (toolset.ToolsVersion, out defaults)) {
+ defaults = new BuildTaskDatabase (toolset);
+ }
+ return defaults;
+ }
+
+ // for 'default' tasks.
+ BuildTaskDatabase (Toolset toolset)
+ {
+ ProjectRootElement root;
+ using (var xml = XmlReader.Create (Path.Combine (toolset.ToolsPath, default_tasks_file)))
+ root = ProjectRootElement.Create (xml);
+ LoadUsingTasks (null, root);
+ }
+
+ public BuildTaskDatabase (ProjectInstance projectInstance, ProjectRootElement projectRootElement)
+ {
+ LoadUsingTasks (projectInstance, projectRootElement);
+ }
+
+ internal class TaskDescription
+ {
+ public TaskAssembly TaskAssembly { get; set; }
+ public string Name { get; set; }
+ public Type TaskFactoryType { get; set; }
+ public Type TaskType { get; set; }
+ public IDictionary<string, TaskPropertyInfo> TaskFactoryParameters { get; set; }
+ public string TaskBody { get; set; }
+
+ public bool IsMatch (string name)
+ {
+ int ridx = Name.LastIndexOf ('.');
+ int tidx = name.IndexOf ('.');
+ return string.Equals (Name, name, StringComparison.OrdinalIgnoreCase) ||
+ tidx < 0 && ridx > 0 && string.Equals (Name.Substring (ridx + 1), name, StringComparison.OrdinalIgnoreCase);
+ }
+ }
+
+ internal class TaskAssembly
+ {
+ public string AssemblyName { get; set; }
+ public string AssemblyFile { get; set; }
+ public Assembly LoadedAssembly { get; set; }
+ }
+
+ readonly List<TaskAssembly> assemblies = new List<TaskAssembly> ();
+ readonly List<TaskDescription> task_descs = new List<TaskDescription> ();
+
+ public List<TaskDescription> Tasks {
+ get { return task_descs; }
+ }
+
+ void LoadUsingTasks (ProjectInstance projectInstance, ProjectRootElement project)
+ {
+ Func<string,bool> cond = s => projectInstance != null ? projectInstance.EvaluateCondition (s) : Convert.ToBoolean (s);
+ foreach (var ut in project.UsingTasks) {
+ var ta = assemblies.FirstOrDefault (a => a.AssemblyFile.Equals (ut.AssemblyFile, StringComparison.OrdinalIgnoreCase) || a.AssemblyName.Equals (ut.AssemblyName, StringComparison.OrdinalIgnoreCase));
+ if (ta == null) {
+ ta = new TaskAssembly () { AssemblyName = ut.AssemblyName, AssemblyFile = ut.AssemblyFile };
+ ta.LoadedAssembly = ta.AssemblyName != null ? Assembly.Load (ta.AssemblyName) : Assembly.LoadFile (ta.AssemblyFile);
+ assemblies.Add (ta);
+ }
+ var pg = ut.ParameterGroup == null ? null : ut.ParameterGroup.Parameters.Select (p => new TaskPropertyInfo (p.Name, Type.GetType (p.ParameterType), cond (p.Output), cond (p.Required)))
+ .ToDictionary (p => p.Name);
+ var task = new TaskDescription () {
+ TaskAssembly = ta,
+ Name = ut.TaskName,
+ TaskFactoryType = string.IsNullOrEmpty (ut.TaskFactory) ? null : LoadTypeFrom (ta.LoadedAssembly, ut.TaskName, ut.TaskFactory),
+ TaskType = string.IsNullOrEmpty (ut.TaskFactory) ? LoadTypeFrom (ta.LoadedAssembly, ut.TaskName, ut.TaskName) : null,
+ TaskFactoryParameters = pg,
+ TaskBody = ut.TaskBody != null && cond (ut.TaskBody.Condition) ? ut.TaskBody.Evaluate : null,
+ };
+ task_descs.Add (task);
+ }
+ }
+
+ Type LoadTypeFrom (Assembly a, string taskName, string possiblyShortTypeName)
+ {
+ Type type = a.GetType (possiblyShortTypeName, false, true);
+ if (possiblyShortTypeName.IndexOf ('.') < 0)
+ type = a.GetTypes ().FirstOrDefault (t => t.Name == possiblyShortTypeName);
+ if (type == null)
+ throw new InvalidOperationException (string.Format ("For task '{0}' Specified type '{1}' was not found in assembly '{2}'", taskName, possiblyShortTypeName, a.FullName));
+ return type;
+ }
+ }
+}
+
--- /dev/null
+// BuildTaskFactory.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Linq;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Internal;
+using System.Collections.Generic;
+using Microsoft.Build.Execution;
+
+namespace Microsoft.Build.Internal
+{
+ class BuildTaskFactory
+ {
+ public BuildTaskFactory (BuildTaskDatabase builtInDatabase, BuildTaskDatabase perProjectDatabase)
+ {
+ this.built_in_database = builtInDatabase;
+ this.per_project_database = perProjectDatabase;
+ }
+
+ readonly BuildTaskDatabase built_in_database, per_project_database;
+ readonly List<ITaskFactory> task_factories = new List<ITaskFactory> ();
+
+ public void ResetCaches ()
+ {
+ task_factories.Clear ();
+ }
+
+ public ITask CreateTask (string name, IDictionary<string,string> factoryIdentityParameters, IBuildEngine engine)
+ {
+ Func<BuildTaskDatabase.TaskDescription,bool> fn = t => t.IsMatch (name);
+ var td = per_project_database.Tasks.FirstOrDefault (fn) ?? built_in_database.Tasks.FirstOrDefault (fn);
+ if (td == null)
+ throw new InvalidOperationException (string.Format ("Task '{0}' could not be found", name));
+ if (td.TaskFactoryType != null) {
+ var tf = task_factories.FirstOrDefault (f => f.GetType () == td.TaskFactoryType);
+ if (tf == null) {
+ tf = (ITaskFactory) Activator.CreateInstance (td.TaskFactoryType);
+#if NET_4_5
+ var tf2 = tf as ITaskFactory2;
+ if (tf2 != null)
+ tf2.Initialize (name, factoryIdentityParameters, td.TaskFactoryParameters, td.TaskBody, engine);
+ else
+#endif
+ tf.Initialize (name, td.TaskFactoryParameters, td.TaskBody, engine);
+ task_factories.Add (tf);
+ }
+ return tf.CreateTask (engine);
+ }
+ else
+ return (ITask) Activator.CreateInstance (td.TaskType);
+ }
+ }
+}
+
--- /dev/null
+//
+// ExpressionConstructs.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Microsoft.Build.Internal.Expressions
+{
+
+ class Locatable
+ {
+ public ILocation Location { get; set; }
+ }
+
+ partial class ExpressionList : ILocation, IEnumerable<Expression>
+ {
+ public ExpressionList ()
+ {
+ }
+
+ public ExpressionList (Expression entry)
+ {
+ Add (entry);
+ }
+
+ public int Count {
+ get { return list.Count; }
+ }
+
+ //public int Line {
+ // get { return list.Count == 0 ? 0 : list [0].Line; }
+ //}
+ public int Column {
+ get { return list.Count == 0 ? 0 : list [0].Column; }
+ }
+ public string File {
+ get { return list.Count == 0 ? null : list [0].File; }
+ }
+ public string ToLocationString ()
+ {
+ return list.Count == 0 ? null : list [0].Location.ToLocationString ();
+ }
+
+ public IEnumerator<Expression> GetEnumerator ()
+ {
+ return list.GetEnumerator ();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator ()
+ {
+ return list.GetEnumerator ();
+ }
+
+ List<Expression> list = new List<Expression> ();
+
+ public ExpressionList Add (Expression expr)
+ {
+ list.Add (expr);
+ return this;
+ }
+
+ public ExpressionList Insert (int pos, Expression expr)
+ {
+ list.Insert (pos, expr);
+ return this;
+ }
+ }
+
+ abstract partial class Expression : Locatable, ILocation
+ {
+ //public int Line {
+ // get { return Location.Line; }
+ //}
+ public int Column {
+ get { return Location.Column; }
+ }
+ public string File {
+ get { return Location.File; }
+ }
+ public string ToLocationString ()
+ {
+ return Location.ToLocationString ();
+ }
+ }
+
+ enum Operator
+ {
+ EQ,
+ NE,
+ LT,
+ LE,
+ GT,
+ GE,
+ And,
+ Or
+ }
+
+ partial class BinaryExpression : Expression
+ {
+ public Operator Operator { get; set; }
+ public Expression Left { get; set; }
+ public Expression Right { get; set; }
+ }
+
+ partial class BooleanLiteral : Expression
+ {
+ public bool Value { get; set; }
+ }
+
+ partial class NotExpression : Expression
+ {
+ public Expression Negated { get; set; }
+ }
+
+ partial class PropertyAccessExpression : Expression
+ {
+ public PropertyAccess Access { get; set; }
+ }
+
+ enum PropertyTargetType
+ {
+ Object,
+ Type,
+ }
+
+ class PropertyAccess : Locatable
+ {
+ public NameToken Name { get; set; }
+ public Expression Target { get; set; }
+ public PropertyTargetType TargetType { get; set; }
+ public ExpressionList Arguments { get; set; }
+ }
+
+ partial class ItemAccessExpression : Expression
+ {
+ public ItemApplication Application { get; set; }
+ }
+
+ class ItemApplication : Locatable
+ {
+ public NameToken Name { get; set; }
+ public ExpressionList Expressions { get; set; }
+ }
+
+ partial class MetadataAccessExpression : Expression
+ {
+ public MetadataAccess Access { get; set; }
+ }
+
+ class MetadataAccess : Locatable
+ {
+ public NameToken Metadata { get; set; }
+ public NameToken ItemType { get; set; }
+ }
+
+ partial class StringLiteral : Expression
+ {
+ public NameToken Value { get; set; }
+ }
+
+ partial class RawStringLiteral : Expression
+ {
+ public NameToken Value { get; set; }
+ }
+
+ partial class FunctionCallExpression : Expression
+ {
+ public NameToken Name { get; set; }
+ public ExpressionList Arguments { get; set; }
+ }
+}
+
--- /dev/null
+//
+// ExpressionEvaluator.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Linq;
+using Microsoft.Build.Evaluation;
+using Microsoft.Build.Exceptions;
+using System.Collections.Generic;
+using System.Reflection;
+using Microsoft.Build.Execution;
+using Microsoft.Build.Framework;
+using System.IO;
+
+namespace Microsoft.Build.Internal.Expressions
+{
+ class ExpressionEvaluator
+ {
+ public ExpressionEvaluator (Project project, string replacementForMissingPropertyAndItem)
+ {
+ ReplacementForMissingPropertyAndItem = replacementForMissingPropertyAndItem;
+ Project = project;
+ /*
+ GetItems = (name) => project.GetItems (name).Select (i => new KeyValuePair<string,string> (i.ItemType, i.EvaluatedInclude));
+ GetProperty = (name) => {
+ var prop = project.GetProperty (name);
+ return new KeyValuePair<string,string> (prop != null ? prop.Name : null, prop != null ? prop.EvaluatedValue : null);
+ };
+ */
+ }
+
+ public ExpressionEvaluator (ProjectInstance project, string replacementForMissingPropertyAndItem)
+ {
+ ReplacementForMissingPropertyAndItem = replacementForMissingPropertyAndItem;
+ ProjectInstance = project;
+ /*
+ GetItems = (name) => project.GetItems (name).Select (i => new KeyValuePair<string,string> (i.ItemType, i.EvaluatedInclude));
+ GetProperty = (name) => {
+ var prop = project.GetProperty (name);
+ return new KeyValuePair<string,string> (prop != null ? prop.Name : null, prop != null ? prop.EvaluatedValue : null);
+ };
+ */
+ }
+
+ EvaluationContext CreateContext (string source)
+ {
+ return new EvaluationContext (source, this);
+ }
+
+ public Project Project { get; private set; }
+ public ProjectInstance ProjectInstance { get; set; }
+ //public Func<string,IEnumerable<KeyValuePair<string,string>>> GetItems { get; private set; }
+ //public Func<string,KeyValuePair<string,string>> GetProperty { get; private set; }
+
+ public string ReplacementForMissingPropertyAndItem { get; set; }
+
+ // it is to prevent sequential property value expansion in boolean expression
+ public string Wrapper {
+ get { return ReplacementForMissingPropertyAndItem != null ? "'" : null; }
+ }
+
+ public string Evaluate (string source)
+ {
+ return Evaluate (source, new ExpressionParserManual (source ?? string.Empty, ExpressionValidationType.LaxString).Parse ());
+ }
+
+ string Evaluate (string source, ExpressionList exprList)
+ {
+ if (exprList == null)
+ throw new ArgumentNullException ("exprList");
+ return string.Concat (exprList.Select (e => e.EvaluateAsString (CreateContext (source))));
+ }
+
+ public bool EvaluateAsBoolean (string source)
+ {
+ try {
+ var el = new ExpressionParser ().Parse (source, ExpressionValidationType.StrictBoolean);
+ if (el.Count () != 1)
+ throw new InvalidProjectFileException ("Unexpected number of tokens: " + el.Count ());
+ return el.First ().EvaluateAsBoolean (CreateContext (source));
+ } catch (yyParser.yyException ex) {
+ throw new InvalidProjectFileException (string.Format ("failed to evaluate expression as boolean: '{0}': {1}", source, ex.Message), ex);
+ }
+ }
+ }
+
+ class EvaluationContext
+ {
+ public EvaluationContext (string source, ExpressionEvaluator evaluator)
+ {
+ Source = source;
+ Evaluator = evaluator;
+ }
+
+ public string Source { get; private set; }
+
+ public ExpressionEvaluator Evaluator { get; private set; }
+ public object ContextItem { get; set; }
+
+ Stack<object> evaluating_items = new Stack<object> ();
+ Stack<object> evaluating_props = new Stack<object> ();
+
+ public IEnumerable<object> GetItems (string name)
+ {
+ if (Evaluator.Project != null)
+ return Evaluator.Project.GetItems (name);
+ else
+ return Evaluator.ProjectInstance.GetItems (name);
+ }
+
+ public IEnumerable<object> GetAllItems ()
+ {
+ if (Evaluator.Project != null)
+ return Evaluator.Project.AllEvaluatedItems;
+ else
+ return Evaluator.ProjectInstance.AllEvaluatedItems;
+ }
+
+ public string EvaluateItem (string itemType, object item)
+ {
+ if (evaluating_items.Contains (item))
+ throw new InvalidProjectFileException (string.Format ("Recursive reference to item '{0}' was found", itemType));
+ try {
+ evaluating_items.Push (item);
+ var eval = item as ProjectItem;
+ if (eval != null)
+ return Evaluator.Evaluate (eval.EvaluatedInclude);
+ else
+ return Evaluator.Evaluate (((ProjectItemInstance) item).EvaluatedInclude);
+ } finally {
+ evaluating_items.Pop ();
+ }
+ }
+
+ public string EvaluateProperty (string name)
+ {
+ if (Evaluator.Project != null) {
+ var prop = Evaluator.Project.GetProperty (name);
+ if (prop == null)
+ return null;
+ return EvaluateProperty (prop, prop.Name, prop.EvaluatedValue);
+ } else {
+ var prop = Evaluator.ProjectInstance.GetProperty (name);
+ if (prop == null)
+ return null;
+ return EvaluateProperty (prop, prop.Name, prop.EvaluatedValue);
+ }
+ }
+
+ public string EvaluateProperty (object prop, string name, string value)
+ {
+ if (evaluating_props.Contains (prop))
+ throw new InvalidProjectFileException (string.Format ("Recursive reference to property '{0}' was found", name));
+ try {
+ evaluating_props.Push (prop);
+ // FIXME: needs verification on whether string evaluation is appropriate or not.
+ return Evaluator.Evaluate (value);
+ } finally {
+ evaluating_props.Pop ();
+ }
+ }
+ }
+
+ abstract partial class Expression
+ {
+ public abstract string EvaluateAsString (EvaluationContext context);
+ public abstract bool EvaluateAsBoolean (EvaluationContext context);
+ public abstract object EvaluateAsObject (EvaluationContext context);
+
+ public bool EvaluateStringAsBoolean (EvaluationContext context, string ret)
+ {
+ if (ret != null) {
+ if (ret.Equals ("TRUE", StringComparison.InvariantCultureIgnoreCase))
+ return true;
+ else if (ret.Equals ("FALSE", StringComparison.InvariantCultureIgnoreCase))
+ return false;
+ }
+ throw new InvalidProjectFileException (this.Location, string.Format ("Condition '{0}' is evaluated as '{1}' and cannot be converted to boolean", context.Source, ret));
+ }
+ }
+
+ partial class BinaryExpression : Expression
+ {
+ public override bool EvaluateAsBoolean (EvaluationContext context)
+ {
+ switch (Operator) {
+ case Operator.EQ:
+ return string.Equals (Left.EvaluateAsString (context), Right.EvaluateAsString (context), StringComparison.OrdinalIgnoreCase);
+ case Operator.NE:
+ return !string.Equals (Left.EvaluateAsString (context), Right.EvaluateAsString (context), StringComparison.OrdinalIgnoreCase);
+ case Operator.And:
+ case Operator.Or:
+ // evaluate first, to detect possible syntax error on right expr.
+ var lb = Left.EvaluateAsBoolean (context);
+ var rb = Right.EvaluateAsBoolean (context);
+ return Operator == Operator.And ? (lb && rb) : (lb || rb);
+ }
+ // comparison expressions - evaluate comparable first, then compare values.
+ var left = Left.EvaluateAsObject (context);
+ var right = Right.EvaluateAsObject (context);
+ if (!(left is IComparable && right is IComparable))
+ throw new InvalidProjectFileException ("expression cannot be evaluated as boolean");
+ var result = ((IComparable) left).CompareTo (right);
+ switch (Operator) {
+ case Operator.GE:
+ return result >= 0;
+ case Operator.GT:
+ return result > 0;
+ case Operator.LE:
+ return result <= 0;
+ case Operator.LT:
+ return result < 0;
+ }
+ throw new InvalidOperationException ();
+ }
+
+ public override object EvaluateAsObject (EvaluationContext context)
+ {
+ throw new NotImplementedException ();
+ }
+
+ static readonly Dictionary<Operator,string> strings = new Dictionary<Operator, string> () {
+ {Operator.EQ, " == "},
+ {Operator.NE, " != "},
+ {Operator.LT, " < "},
+ {Operator.LE, " <= "},
+ {Operator.GT, " > "},
+ {Operator.GE, " >= "},
+ {Operator.And, " And "},
+ {Operator.Or, " Or "},
+ };
+
+ public override string EvaluateAsString (EvaluationContext context)
+ {
+ return Left.EvaluateAsString (context) + strings [Operator] + Right.EvaluateAsString (context);
+ }
+ }
+
+ partial class BooleanLiteral : Expression
+ {
+ public override string EvaluateAsString (EvaluationContext context)
+ {
+ return Value ? "True" : "False";
+ }
+
+ public override bool EvaluateAsBoolean (EvaluationContext context)
+ {
+ return Value;
+ }
+
+ public override object EvaluateAsObject (EvaluationContext context)
+ {
+ return Value;
+ }
+ }
+
+ partial class NotExpression : Expression
+ {
+ public override string EvaluateAsString (EvaluationContext context)
+ {
+ // no negation for string
+ return "!" + Negated.EvaluateAsString (context);
+ }
+
+ public override bool EvaluateAsBoolean (EvaluationContext context)
+ {
+ return !Negated.EvaluateAsBoolean (context);
+ }
+
+ public override object EvaluateAsObject (EvaluationContext context)
+ {
+ return EvaluateAsString (context);
+ }
+ }
+
+ partial class PropertyAccessExpression : Expression
+ {
+ public override bool EvaluateAsBoolean (EvaluationContext context)
+ {
+ var ret = EvaluateAsString (context);
+ return EvaluateStringAsBoolean (context, ret);
+ }
+
+ public override string EvaluateAsString (EvaluationContext context)
+ {
+ var ret = EvaluateAsObject (context);
+ // FIXME: this "wrapper" is kind of hack, to prevent sequential property references such as $(X)$(Y).
+ return ret == null ? context.Evaluator.ReplacementForMissingPropertyAndItem : context.Evaluator.Wrapper + ret.ToString () + context.Evaluator.Wrapper;
+ }
+
+ public override object EvaluateAsObject (EvaluationContext context)
+ {
+ try {
+ return DoEvaluateAsObject (context);
+ } catch (TargetInvocationException ex) {
+ throw new InvalidProjectFileException ("Access to property caused an error", ex);
+ }
+ }
+
+ object DoEvaluateAsObject (EvaluationContext context)
+ {
+ if (Access.Target == null) {
+ return context.EvaluateProperty (Access.Name.Name);
+ } else {
+ if (this.Access.TargetType == PropertyTargetType.Object) {
+ var obj = Access.Target.EvaluateAsObject (context);
+ if (obj == null)
+ return null;
+ if (Access.Arguments != null) {
+ var args = Access.Arguments.Select (e => e.EvaluateAsObject (context)).ToArray ();
+ var method = FindMethod (obj.GetType (), Access.Name.Name, args);
+ if (method == null)
+ throw new InvalidProjectFileException (Location, string.Format ("access to undefined method '{0}' of '{1}' at {2}", Access.Name.Name, Access.Target.EvaluateAsString (context), Location));
+ return method.Invoke (obj, AdjustArgsForCall (method, args));
+ } else {
+ var prop = obj.GetType ().GetProperty (Access.Name.Name);
+ if (prop == null)
+ throw new InvalidProjectFileException (Location, string.Format ("access to undefined property '{0}' of '{1}' at {2}", Access.Name.Name, Access.Target.EvaluateAsString (context), Location));
+ return prop.GetValue (obj, null);
+ }
+ } else {
+ var type = Type.GetType (Access.Target.EvaluateAsString (context));
+ if (type == null)
+ throw new InvalidProjectFileException (Location, string.Format ("specified type '{0}' was not found", Access.Target.EvaluateAsString (context)));
+ if (Access.Arguments != null) {
+ var args = Access.Arguments.Select (e => e.EvaluateAsObject (context)).ToArray ();
+ var method = FindMethod (type, Access.Name.Name, args);
+ if (method == null)
+ throw new InvalidProjectFileException (Location, string.Format ("access to undefined static method '{0}' of '{1}' at {2}", Access.Name.Name, Access.Target.EvaluateAsString (context), Location));
+ return method.Invoke (null, AdjustArgsForCall (method, args));
+ } else {
+ var prop = type.GetProperty (Access.Name.Name);
+ if (prop == null)
+ throw new InvalidProjectFileException (Location, string.Format ("access to undefined static property '{0}' of '{1}' at {2}", Access.Name.Name, Access.Target.EvaluateAsString (context), Location));
+ return prop.GetValue (null, null);
+ }
+ }
+ }
+ }
+
+ MethodInfo FindMethod (Type type, string name, object [] args)
+ {
+ var methods = type.GetMethods ().Where (m => {
+ if (m.Name != name)
+ return false;
+ var pl = m.GetParameters ();
+ if (pl.Length == args.Length)
+ return true;
+ // calling String.Format() with either set of arguments is valid:
+ // - three strings (two for varargs)
+ // - two strings (happen to be exact match)
+ // - one string (no varargs)
+ if (pl.Length > 0 && pl.Length - 1 <= args.Length &&
+ pl.Last ().GetCustomAttributesData ().Any (a => a.Constructor.DeclaringType == typeof (ParamArrayAttribute)))
+ return true;
+ return false;
+ });
+ if (methods.Count () == 1)
+ return methods.First ();
+ return args.Any (a => a == null) ?
+ type.GetMethod (name) :
+ type.GetMethod (name, args.Select (o => o.GetType ()).ToArray ());
+ }
+
+ object [] AdjustArgsForCall (MethodInfo m, object[] args)
+ {
+ if (m.GetParameters ().Length == args.Length + 1)
+ return args.Concat (new object[] {Array.CreateInstance (m.GetParameters ().Last ().ParameterType.GetElementType (), 0)}).ToArray ();
+ else
+ return args;
+ }
+ }
+
+ partial class ItemAccessExpression : Expression
+ {
+ public override bool EvaluateAsBoolean (EvaluationContext context)
+ {
+ return EvaluateStringAsBoolean (context, EvaluateAsString (context));
+ }
+
+ public override string EvaluateAsString (EvaluationContext context)
+ {
+ string itemType = Application.Name.Name;
+ var items = context.GetItems (itemType);
+ if (!items.Any ())
+ return context.Evaluator.ReplacementForMissingPropertyAndItem;
+ if (Application.Expressions == null)
+ return string.Join (";", items.Select (item => context.EvaluateItem (itemType, item)));
+ else
+ return string.Join (";", items.Select (item => {
+ context.ContextItem = item;
+ var ret = string.Concat (Application.Expressions.Select (e => e.EvaluateAsString (context)));
+ context.ContextItem = null;
+ return ret;
+ }));
+ }
+
+ public override object EvaluateAsObject (EvaluationContext context)
+ {
+ return EvaluateAsString (context);
+ }
+ }
+
+ partial class MetadataAccessExpression : Expression
+ {
+ public override bool EvaluateAsBoolean (EvaluationContext context)
+ {
+ return EvaluateStringAsBoolean (context, EvaluateAsString (context));
+ }
+
+ public override string EvaluateAsString (EvaluationContext context)
+ {
+ string itemType = this.Access.ItemType != null ? this.Access.ItemType.Name : null;
+ string metadataName = Access.Metadata.Name;
+ IEnumerable<object> items;
+ if (this.Access.ItemType != null)
+ items = context.GetItems (itemType);
+ else if (context.ContextItem != null)
+ items = new Object [] { context.ContextItem };
+ else
+ items = context.GetAllItems ();
+
+ var values = items.Select (i => (i is ProjectItem) ? ((ProjectItem) i).GetMetadataValue (metadataName) : ((ProjectItemInstance) i).GetMetadataValue (metadataName)).Where (s => !string.IsNullOrEmpty (s));
+ return string.Join (";", values);
+ }
+
+ public override object EvaluateAsObject (EvaluationContext context)
+ {
+ return EvaluateAsString (context);
+ }
+ }
+ partial class StringLiteral : Expression
+ {
+ public override bool EvaluateAsBoolean (EvaluationContext context)
+ {
+ var ret = EvaluateAsString (context);
+ return EvaluateStringAsBoolean (context, ret);
+ }
+
+ public override string EvaluateAsString (EvaluationContext context)
+ {
+ return context.Evaluator.Evaluate (this.Value.Name);
+ }
+
+ public override object EvaluateAsObject (EvaluationContext context)
+ {
+ return EvaluateAsString (context);
+ }
+ }
+ partial class RawStringLiteral : Expression
+ {
+ public override string EvaluateAsString (EvaluationContext context)
+ {
+ return Value.Name;
+ }
+
+ public override bool EvaluateAsBoolean (EvaluationContext context)
+ {
+ throw new InvalidProjectFileException ("raw string literal cannot be evaluated as boolean");
+ }
+
+ public override object EvaluateAsObject (EvaluationContext context)
+ {
+ return EvaluateAsString (context);
+ }
+ }
+
+ partial class FunctionCallExpression : Expression
+ {
+ public override string EvaluateAsString (EvaluationContext context)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override bool EvaluateAsBoolean (EvaluationContext context)
+ {
+ if (string.Equals (Name.Name, "Exists", StringComparison.OrdinalIgnoreCase)) {
+ if (Arguments.Count != 1)
+ throw new InvalidProjectFileException (Location, "Function 'Exists' expects 1 argument");
+ string val = Arguments.First ().EvaluateAsString (context);
+ return Directory.Exists (val) || System.IO.File.Exists (val);
+ }
+ if (string.Equals (Name.Name, "HasTrailingSlash", StringComparison.OrdinalIgnoreCase)) {
+ if (Arguments.Count != 1)
+ throw new InvalidProjectFileException (Location, "Function 'HasTrailingSlash' expects 1 argument");
+ string val = Arguments.First ().EvaluateAsString (context);
+ return val.LastOrDefault () == '\\' || val.LastOrDefault () == '/';
+ }
+ throw new InvalidProjectFileException (Location, string.Format ("Unsupported function '{0}'", Name));
+ }
+
+ public override object EvaluateAsObject (EvaluationContext context)
+ {
+ throw new NotImplementedException ();
+ }
+ }
+}
+
--- /dev/null
+//
+// ExpressionParser.jay
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+%{
+
+using System;
+using System.Text;
+using Microsoft.Build.Evaluation;
+using Microsoft.Build.Exceptions;
+using Microsoft.Build.Framework;
+
+/*
+
+Pseudo formal syntax for .NET 4.0 expression:
+
+Condition = Expression
+Include = Expression*
+
+ Expression
+ BooleanLiteral
+ TrueLiteral
+ FalseLiteral
+ BinaryExpression
+ Expression "==" Expression
+ Expression "!=" Expression
+ Expression ">" Expression
+ Expression ">=" Expression
+ Expression "<" Expression
+ Expression "<=" Expression
+ Expression "And" Expression
+ Expression "Or" Expression
+ UnaryExpression
+ "!" Expression
+ PropertyExpression
+ "$(" PropertyApplication ")"
+ ItemExpression
+ "@(" ItemApplication ")"
+ MetadataBatchingExpression
+ "%(" MetadataBatchingApplication ")"
+ StringLiteralOrFunction
+ StringLiteralOrFunctionName ( "(" FunctionArguments ")" )?
+
+.NET error messages are so detailed which is something like "you forgot '(' after '$' ?" - so
+it is likely that the MS tokenizer is hand-written.
+
+*/
+
+namespace Microsoft.Build.Internal.Expressions
+{
+ class ExpressionParser
+ {
+ static readonly int yacc_verbose_flag = Environment.GetEnvironmentVariable ("MONO_MSBUILD_PARSER_DEBUG") == "1" ? 1 : 0;
+
+ object debug_obj = yacc_verbose_flag == 0 ? null : new yydebug.yyDebugSimple ();
+
+ public ExpressionList Parse (string source, ExpressionValidationType validationType)
+ {
+ var tokenizer = new ExpressionTokenizer (source, validationType);
+ return (ExpressionList) yyparse (tokenizer, debug_obj);
+ }
+
+ BinaryExpression Binary (Operator op, object left, object right)
+ {
+ return new BinaryExpression () { Operator = op, Left = (Expression) left, Right = (Expression) right, Location = (ILocation) left };
+ }
+%}
+
+%token TRUE_LITERAL
+%token FALSE_LITERAL
+%token STRING_LITERAL
+%token EQ // ==
+%token NE // !=
+%token GT // >
+%token GE // >=
+%token LT // <
+%token LE // <=
+%token AND // AND
+%token OR // OR
+%token NOT //!
+%token DOT //.
+%token COMMA //,
+%token PROP_OPEN // $(
+%token ITEM_OPEN // @(
+%token METADATA_OPEN // %(
+%token PAREN_OPEN // (
+%token PAREN_CLOSE // )
+%token BRACE_OPEN // [
+%token BRACE_CLOSE // ]
+%token COLON2 // ::
+%token ARROW // ->
+%token NAME
+%token ERROR
+
+%start ExpressionList
+
+%%
+
+ExpressionList
+ : /* empty */
+ { $$ = new ExpressionList (); }
+ | ExpressionList Expression
+ { $$ = ((ExpressionList) $1).Add ((Expression) $2); }
+ ;
+
+Expression
+ : LogicalExpression
+ ;
+
+LogicalExpression
+ : ComparisonExpression
+ | LogicalExpression AND LogicalExpression
+ { $$ = Binary (Operator.And, $1, $3); }
+ | LogicalExpression OR LogicalExpression
+ { $$ = Binary (Operator.Or, $1, $3); }
+ ;
+
+ComparisonExpression
+ : UnaryExpression
+ | UnaryExpression EQ UnaryExpression
+ { $$ = Binary (Operator.EQ, $1, $3); }
+ | UnaryExpression NE UnaryExpression
+ { $$ = Binary (Operator.NE, $1, $3); }
+ | UnaryExpression GT UnaryExpression
+ { $$ = Binary (Operator.GT, $1, $3); }
+ | UnaryExpression GE UnaryExpression
+ { $$ = Binary (Operator.GE, $1, $3); }
+ | UnaryExpression LT UnaryExpression
+ { $$ = Binary (Operator.LT, $1, $3); }
+ | UnaryExpression LE UnaryExpression
+ { $$ = Binary (Operator.LE, $1, $3); }
+ ;
+
+UnaryExpression
+ : PrimaryExpression
+ | NOT UnaryExpression
+ { $$ = new NotExpression () { Negated = (Expression) $2, Location = (ILocation) $1 }; }
+ ;
+
+PrimaryExpression
+ : BooleanLiteral
+ | StringLiteral
+ | UnaryExpression
+ | PropertyAccessExpression
+ | ItemAccessExpression
+ | MetadataAccessExpression
+ | RawStringLiteralOrFunction
+ | ParenthesizedExpression
+ ;
+
+BooleanLiteral
+ : TRUE_LITERAL
+ { $$ = new BooleanLiteral () { Value = true, Location = (ILocation) $1 }; }
+ | FALSE_LITERAL
+ { $$ = new BooleanLiteral () { Value = false, Location = (ILocation) $1 }; }
+ ;
+
+PropertyAccessExpression
+ : PROP_OPEN PropertyAccess PAREN_CLOSE
+ { $$ = new PropertyAccessExpression () { Access = (PropertyAccess) $2, Location = (ILocation) $1 }; }
+ ;
+
+PropertyAccess
+ : NAME
+ { $$ = new PropertyAccess () { Name = (NameToken) $1, TargetType = PropertyTargetType.Object, Location = (NameToken) $1 }; }
+ | Expression DOT NAME
+ { $$ = new PropertyAccess () { Name = (NameToken) $3, Target = (Expression) $1, TargetType = PropertyTargetType.Object, Location = (ILocation) $1 }; }
+ | BRACE_OPEN QualifiedNameExpression BRACE_CLOSE COLON2 NAME
+ { $$ = new PropertyAccess () { Name = (NameToken) $5, Target = (Expression) $2, TargetType = PropertyTargetType.Type, Location = (ILocation) $1 }; }
+ | BRACE_OPEN QualifiedNameExpression BRACE_CLOSE COLON2 NAME PAREN_OPEN FunctionCallArguments PAREN_CLOSE
+ { $$ = new PropertyAccess () { Name = (NameToken) $5, Target = (Expression) $2, TargetType = PropertyTargetType.Type, Arguments = (ExpressionList) $7, Location = (ILocation) $1 }; }
+ ;
+
+QualifiedNameExpression
+ : QualifiedName
+ { $$ = new StringLiteral () { Value = (NameToken) $1, Location = (ILocation) $1 }; }
+ ;
+
+QualifiedName
+ : NAME
+ | QualifiedName DOT NAME
+ { $$ = new NameToken () { Name = ((NameToken) $1).Name + "." + ((NameToken) $3).Name, Column = ((ILocation) $1).Column }; }
+ ;
+
+ItemAccessExpression
+ : ITEM_OPEN ItemApplication PAREN_CLOSE
+ { $$ = new ItemAccessExpression () { Application = (ItemApplication) $2, Location = (ILocation) $1 }; }
+ ;
+
+// looking a bit messy, but gives different location
+ItemApplication
+ : NAME
+ { $$ = new ItemApplication () { Name = (NameToken) $1, Location = (ILocation) $1 }; }
+ | NAME ARROW ExpressionList
+ { $$ = new ItemApplication () { Name = (NameToken) $1, Expressions = (ExpressionList) $3, Location = (ILocation) $1 }; }
+ ;
+
+MetadataAccessExpression
+ : METADATA_OPEN MetadataAccess PAREN_CLOSE
+ { $$ = new MetadataAccessExpression () { Access = (MetadataAccess) $2, Location = (ILocation) $1 }; }
+ ;
+
+// looking a bit messy, but gives different location
+MetadataAccess
+ : NAME
+ { $$ = new MetadataAccess () { Metadata = (NameToken) $1, Location = (ILocation) $1 }; }
+ | NAME DOT NAME
+ { $$ = new MetadataAccess () { ItemType = (NameToken) $1, Metadata = (NameToken) $3, Location = (ILocation) $1 }; }
+ ;
+
+StringLiteral
+ : STRING_LITERAL
+ { $$ = new StringLiteral () { Value = (NameToken) $1, Location = (ILocation) $1 }; }
+ ;
+
+RawStringLiteralOrFunction
+ : NAME
+ { $$ = new RawStringLiteral () { Value = (NameToken) $1, Location = (ILocation) $1 }; }
+ | NAME PAREN_OPEN PAREN_CLOSE
+ { $$ = new FunctionCallExpression () { Name = (NameToken) $1, Arguments = new ExpressionList (), Location = (ILocation) $1 }; }
+ | NAME PAREN_OPEN FunctionCallArguments PAREN_CLOSE
+ { $$ = new FunctionCallExpression () { Name = (NameToken) $1, Arguments = (ExpressionList) $3, Location = (ILocation) $1 }; }
+ ;
+
+FunctionCallArguments
+ : /* empty */
+ { $$ = new ExpressionList (); }
+ | Expression
+ { $$ = new ExpressionList ().Add ((Expression) $1); }
+ | FunctionCallArguments COMMA Expression
+ { $$ = ((ExpressionList) $1).Add ((Expression) $3); }
+ ;
+
+ParenthesizedExpression
+ : PAREN_OPEN Expression PAREN_CLOSE
+ { $$ = (Expression) $2; }
+ ;
+
+%%
+
+ }
--- /dev/null
+//
+// ExpressionParserManual.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Build.Exceptions;
+
+namespace Microsoft.Build.Internal.Expressions
+{
+ class ExpressionParserManual
+ {
+ // FIXME: we are going to not need ExpressionValidationType for this; always LaxString.
+ public ExpressionParserManual (string source, ExpressionValidationType validationType)
+ {
+ if (source == null)
+ throw new ArgumentNullException ("source");
+ this.source = source;
+ validation_type = validationType;
+ }
+
+ string source;
+ ExpressionValidationType validation_type;
+
+ public ExpressionList Parse ()
+ {
+ return Parse (0, source.Length);
+ }
+
+ ExpressionList Parse (int start, int end)
+ {
+ if (string.IsNullOrWhiteSpace (source))
+ return new ExpressionList ();
+
+ var ret = new ExpressionList ();
+ while (start < end) {
+ int bak = start;
+ ret.Add (ParseSingle (ref start, end));
+ SkipSpaces (ref start);
+ if (bak == start)
+ throw new Exception ("Parser failed to progress token position: " + source);
+ }
+ return ret;
+ }
+
+ static readonly char [] token_starters = "$@%(),".ToCharArray ();
+
+ Expression ParseSingle (ref int start, int end)
+ {
+ char token = source [start];
+ switch (token) {
+ case '$':
+ case '@':
+ case '%':
+ if (start == end || start + 1 == source.Length || source [start + 1] != '(') {
+ if (validation_type == ExpressionValidationType.StrictBoolean)
+ throw new InvalidProjectFileException (string.Format ("missing '(' after '{0}' at {1} in \"{2}\"", source [start], start, source));
+ else
+ goto default; // treat as raw literal to the section end
+ }
+ start += 2;
+ int last = FindMatchingCloseParen (start, end);
+ if (last < 0) {
+ if (validation_type == ExpressionValidationType.StrictBoolean)
+ throw new InvalidProjectFileException (string.Format ("expression did not have matching ')' since index {0} in \"{1}\"", start, source));
+ else {
+ start -= 2;
+ goto default; // treat as raw literal to the section end
+ }
+ }
+ Expression ret;
+ if (token == '$')
+ ret = EvaluatePropertyExpression (start, last);
+ else if (token == '%')
+ ret = EvaluateMetadataExpression (start, last);
+ else
+ ret = EvaluateItemExpression (start, last);
+ start = last + 1;
+ return ret;
+
+ // Below (until default) are important only for Condition evaluation
+ case '(':
+ if (validation_type == ExpressionValidationType.LaxString)
+ goto default;
+ start++;
+ last = FindMatchingCloseParen (start, end);
+ if (last < 0) {
+ if (validation_type == ExpressionValidationType.StrictBoolean)
+ throw new InvalidProjectFileException (string.Format ("expression did not have matching ')' since index {0} in \"{1}\"", start, source));
+ else {
+ start--;
+ goto default; // treat as raw literal to the section end
+ }
+ }
+ var contents = Parse (start, last).ToArray ();
+ if (contents.Length > 1)
+ throw new InvalidProjectFileException (string.Format ("unexpected continuous expression within (){0} in \"{1}\"", contents [1].Column > 0 ? " at " + contents [1].Column : null, source));
+ return contents.First ();
+
+ default:
+ int idx = source.IndexOfAny (token_starters, start + 1);
+ string name = idx < 0 ? source.Substring (start, end - start) : source.Substring (start, idx - start);
+ var val = new NameToken () { Name = name };
+ ret = new RawStringLiteral () { Value = val };
+ if (idx >= 0)
+ start = idx;
+ else
+ start = end;
+
+ return ret;
+ }
+ }
+
+ int FindMatchingCloseParen (int start, int end)
+ {
+ int n = 0;
+ for (int i = start; i < end; i++) {
+ if (source [i] == '(')
+ n++;
+ else if (source [i] == ')') {
+ if (n-- == 0)
+ return i;
+ }
+ }
+ return -1; // invalid
+ }
+
+ static readonly string spaces = " \t\r\n";
+
+ void SkipSpaces (ref int start)
+ {
+ while (start < source.Length && spaces.Contains (source [start]))
+ start++;
+ }
+
+ PropertyAccessExpression EvaluatePropertyExpression (int start, int end)
+ {
+ // member access
+ int dotAt = source.LastIndexOf ('.', end, end - start);
+ int colonsAt = source.LastIndexOf ("::", end, end - start, StringComparison.Ordinal);
+ if (dotAt < 0 && colonsAt < 0) {
+ // property access without member specification
+ int parenAt = source.IndexOf ('(', start, end - start);
+ string name = parenAt < 0 ? source.Substring (start, end - start) : source.Substring (start, parenAt - start);
+ var access = new PropertyAccess () {
+ Name = new NameToken () { Name = name },
+ TargetType = PropertyTargetType.Object
+ };
+ if (parenAt > 0) { // method arguments
+ start = parenAt + 1;
+ access.Arguments = ParseFunctionArguments (ref start, end);
+ }
+ return new PropertyAccessExpression () { Access = access };
+ }
+ if (colonsAt < 0 || colonsAt < dotAt) {
+ // property access with member specification
+ int mstart = dotAt + 1;
+ int parenAt = source.IndexOf ('(', mstart, end - mstart);
+ string name = parenAt < 0 ? source.Substring (mstart, end - mstart) : source.Substring (mstart, parenAt - mstart);
+ var access = new PropertyAccess () {
+ Name = new NameToken () { Name = name },
+ TargetType = PropertyTargetType.Object,
+ Target = dotAt < 0 ? null : Parse (start, dotAt).FirstOrDefault ()
+ };
+ if (parenAt > 0) { // method arguments
+ start = parenAt + 1;
+ access.Arguments = ParseFunctionArguments (ref start, end);
+ }
+ return new PropertyAccessExpression () { Access = access };
+ } else {
+ // static type access
+ string type = source.Substring (start, colonsAt - start);
+ if (type.Length < 2 || type [0] != '[' || type [type.Length - 1] != ']')
+ throw new InvalidProjectFileException (string.Format ("Static function call misses appropriate type name surrounded by '[' and ']' at {0} in \"{1}\"", start, source));
+ type = type.Substring (1, type.Length - 2);
+ start = colonsAt + 2;
+ int parenAt = source.IndexOf ('(', start, end - start);
+ string member = parenAt < 0 ? source.Substring (start, end - start) : source.Substring (start, parenAt - start);
+ if (member.Length == 0)
+ throw new InvalidProjectFileException ("Static member name is missing");
+ var access = new PropertyAccess () {
+ Name = new NameToken () { Name = member },
+ TargetType = PropertyTargetType.Type,
+ Target = new StringLiteral () { Value = new NameToken () { Name = type } }
+ };
+ if (parenAt > 0) { // method arguments
+ start = parenAt + 1;
+ access.Arguments = ParseFunctionArguments (ref start, end);
+ }
+ return new PropertyAccessExpression () { Access = access };
+ }
+ }
+
+ ExpressionList ParseFunctionArguments (ref int start, int end)
+ {
+ var args = new ExpressionList ();
+ do {
+ SkipSpaces (ref start);
+ if (start == source.Length)
+ throw new InvalidProjectFileException ("unterminated function call arguments.");
+ if (source [start] == ')')
+ break;
+ else if (args.Any ()) {
+ if (source [start] != ',')
+ throw new InvalidProjectFileException (string.Format ("invalid function call arguments specification. ',' is expected, got '{0}'", source [start]));
+ start++;
+ }
+ args.Add (ParseSingle (ref start, end));
+ } while (true);
+ start++;
+ return args;
+ }
+
+ ItemAccessExpression EvaluateItemExpression (int start, int end)
+ {
+ // using property as context and evaluate
+ int idx = source.IndexOf ("->", start, StringComparison.Ordinal);
+ if (idx > 0) {
+ string name = source.Substring (start, idx - start);
+ return new ItemAccessExpression () {
+ Application = new ItemApplication () {
+ Name = new NameToken () { Name = name },
+ Expressions = Parse (idx, end - idx)
+ }
+ };
+ } else {
+ string name = source.Substring (start, end - start);
+ return new ItemAccessExpression () {
+ Application = new ItemApplication () { Name = new NameToken () { Name = name } }
+ };
+ }
+ }
+
+ MetadataAccessExpression EvaluateMetadataExpression (int start, int end)
+ {
+ int idx = source.IndexOf ('.', start, end - start);
+ string item = idx < 0 ? null : source.Substring (start, idx);
+ string meta = idx < 0 ? source.Substring (start, end - start) : source.Substring (idx + 1, end - idx - 1);
+ var access = new MetadataAccess () {
+ ItemType = item == null ? null : new NameToken () { Column = start, Name = item },
+ Metadata = new NameToken () { Column = idx < 0 ? start : idx + 1, Name = meta }
+ };
+ return new MetadataAccessExpression () { Access = access };
+ }
+ }
+}
+
--- /dev/null
+//
+// ExpressionTokenizer.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Collections.Generic;
+using Microsoft.Build.Evaluation;
+
+namespace Microsoft.Build.Internal.Expressions
+{
+ enum ExpressionValidationType
+ {
+ LaxString,
+ StrictBoolean,
+ }
+
+ enum TokenizerMode
+ {
+ Default,
+ InsideItemOrProperty,
+ }
+
+ class ExpressionTokenizer : yyParser.yyInput
+ {
+ public ExpressionTokenizer (string source, ExpressionValidationType validationType)
+ {
+ this.source = source;
+ current_token_position = -1;
+ validation_type = validationType;
+ modes.Push (TokenizerMode.Default);
+ }
+
+ string source;
+ ExpressionValidationType validation_type;
+
+ int current_token;
+ string error;
+ int pos, current_token_position;
+ object token_value;
+ Stack<TokenizerMode> modes = new Stack<TokenizerMode> ();
+
+ TokenizerMode CurrentTokenizerMode {
+ get { return modes.Peek (); }
+ }
+
+ public bool advance ()
+ {
+ if (pos == source.Length)
+ return false;
+
+ error = null;
+ token_value = null;
+
+ while (pos < source.Length) {
+ if (spaces.IndexOf (source [pos]) >= 0)
+ pos++;
+ else
+ break;
+ }
+ if (pos == source.Length)
+ return false;
+ current_token_position = pos;
+
+ switch (source [pos++]) {
+ case '.':
+ TokenForItemPropertyValue (".", Token.DOT);
+ break;
+ case ',':
+ TokenForItemPropertyValue (",", Token.COMMA);
+ break;
+ case '[':
+ TokenForItemPropertyValue ("[", Token.BRACE_OPEN);
+ break;
+ case ']':
+ TokenForItemPropertyValue ("]", Token.BRACE_CLOSE);
+ break;
+ case '(':
+ modes.Push (TokenizerMode.Default);
+ TokenForItemPropertyValue ("(", Token.PAREN_OPEN);
+ break;
+ case ')':
+ if (modes.Count > 0) {
+ modes.Pop ();
+ current_token = Token.PAREN_CLOSE;
+ } else {
+ token_value = ")";
+ current_token = Token.NAME;
+ }
+ break;
+ case '-':
+ if (pos < source.Length && source [pos] == '>') {
+ current_token = Token.ARROW;
+ pos++;
+ } else
+ ErrorOnStrictBoolean ("-", "'-' is not followed by '>'.");
+ break;
+ case '=':
+ if (pos < source.Length && source [pos] == '=') {
+ current_token = Token.EQ;
+ pos++;
+ } else
+ ErrorOnStrictBoolean ("=", "'=' is not followed by '='.");
+ break;
+ case ':':
+ if (pos < source.Length && source [pos] == ':') {
+ current_token = Token.COLON2;
+ } else
+ ErrorOnStrictBoolean (":", "':' is not followed by ':'.");
+ pos++;
+ break;
+ case '!':
+ if (pos < source.Length && source [pos] == '=') {
+ pos++;
+ current_token = Token.NE;
+ } else
+ TokenForItemPropertyValue ("!", Token.NOT);
+ break;
+ case '>':
+ if (pos < source.Length && source [pos] == '=') {
+ pos++;
+ current_token = Token.GE;
+ } else
+ current_token = Token.GT;
+ break;
+ case '<':
+ if (pos < source.Length && source [pos] == '=') {
+ pos++;
+ current_token = Token.LE;
+ } else
+ current_token = Token.LT;
+ break;
+ case '$':
+ if (pos < source.Length && source [pos] == '(') {
+ modes.Push (TokenizerMode.InsideItemOrProperty);
+ current_token = Token.PROP_OPEN;
+ pos++;
+ } else
+ ErrorOnStrictBoolean ("$", "property reference '$' is not followed by '('.");
+ break;
+ case '@':
+ if (pos < source.Length && source [pos] == '(') {
+ modes.Push (TokenizerMode.InsideItemOrProperty);
+ current_token = Token.ITEM_OPEN;
+ pos++;
+ } else
+ ErrorOnStrictBoolean ("@", "item reference '@' is not followed by '('.");
+ break;
+ case '%':
+ if (pos < source.Length && source [pos] == '(') {
+ modes.Push (TokenizerMode.InsideItemOrProperty);
+ current_token = Token.METADATA_OPEN;
+ pos++;
+ } else
+ ErrorOnStrictBoolean ("%", "metadata reference '%' is not followed by '('.");
+ break;
+ case '"':
+ case '\'':
+ pos = source.IndexOf (source [pos - 1], pos);
+ if (pos < 0) {
+ ErrorOnStrictBoolean ("'", "unterminated string literal");
+ pos = source.Length;
+ }
+ token_value = source.Substring (current_token_position + 1, pos - current_token_position - 1);
+ current_token = Token.STRING_LITERAL;
+ pos++;
+ break;
+ default:
+ pos = source.IndexOfAny (token_starter_chars, pos);
+ if (pos < 0)
+ pos = source.Length;
+ var val = source.Substring (current_token_position, pos - current_token_position);
+ if (val.Equals ("AND", StringComparison.OrdinalIgnoreCase))
+ current_token = Token.AND;
+ else if (val.Equals ("OR", StringComparison.OrdinalIgnoreCase))
+ current_token = Token.OR;
+ else if (val.Equals ("TRUE", StringComparison.OrdinalIgnoreCase))
+ current_token = Token.TRUE_LITERAL;
+ else if (val.Equals ("FALSE", StringComparison.OrdinalIgnoreCase))
+ current_token = Token.FALSE_LITERAL;
+ else if (val.Equals ("YES", StringComparison.OrdinalIgnoreCase))
+ current_token = Token.TRUE_LITERAL;
+ else if (val.Equals ("NO", StringComparison.OrdinalIgnoreCase))
+ current_token = Token.FALSE_LITERAL;
+ else if (val.Equals ("ON", StringComparison.OrdinalIgnoreCase))
+ current_token = Token.TRUE_LITERAL;
+ else if (val.Equals ("OFF", StringComparison.OrdinalIgnoreCase))
+ current_token = Token.FALSE_LITERAL;
+ else {
+ current_token = Token.NAME;
+ token_value = ProjectCollection.Unescape (val);
+ break;
+ }
+ break;
+ }
+ return true;
+ }
+ string spaces = " \t\r\n";
+
+ static readonly char [] token_starter_chars = ".,[]()-=:!><$@%\"' ".ToCharArray ();
+
+ void ReadStringLiteral (string source, char c)
+ {
+ while (pos < source.Length && source [pos] != c)
+ pos++;
+ if (source [pos - 1] != c)
+ ErrorOnStrictBoolean (c.ToString (), string.Format ("missing string literal terminator [{0}]", c));
+ else {
+ current_token = Token.NAME;
+ token_value = source.Substring (current_token_position + 1, pos - current_token_position - 2);
+ token_value = ProjectCollection.Unescape ((string) token_value);
+ }
+ }
+
+ void TokenForItemPropertyValue (string value, int token)
+ {
+ if (true)//CurrentTokenizerMode == TokenizerMode.InsideItemOrProperty)
+ current_token = token;
+ else {
+ current_token = Token.NAME;
+ token_value = value;
+ }
+ }
+
+ void ErrorOnStrictBoolean (string value, string message)
+ {
+ if (validation_type == ExpressionValidationType.StrictBoolean) {
+ current_token = Token.ERROR;
+ error = message;
+ } else {
+ current_token = Token.NAME;
+ token_value = value;
+ }
+ }
+
+ public int token ()
+ {
+ return current_token;
+ }
+
+ public object value ()
+ {
+ if (current_token == Token.NAME || current_token == Token.STRING_LITERAL)
+ return new NameToken () { Name = (string) token_value, Column = current_token_position };
+ else if (error != null)
+ return new ErrorToken () { Message = error, Column = current_token_position };
+ else
+ return new Location () { Column = current_token_position };
+ }
+ }
+
+ class NameToken : Location
+ {
+ public string Name { get; set; }
+
+ public override string ToString ()
+ {
+ return string.Format ("[NameToken: Value={0}]", Name);
+ }
+ }
+
+ class ErrorToken : Location
+ {
+ public string Message { get; set; }
+ }
+
+ interface ILocation
+ {
+ //int Line { get; }
+ int Column { get; }
+ string File { get; }
+
+ string ToLocationString ();
+ }
+
+ class Location : ILocation
+ {
+ //public int Line { get; set; }
+ public int Column { get; set; }
+ public string File { get; set; }
+
+ public string ToLocationString ()
+ {
+ return "at " + Column;
+ }
+ }
+}
--- /dev/null
+//
+// ProjectTaskItem.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Linq;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Construction;
+using Microsoft.Build.Evaluation;
+using System.IO;
+
+namespace Microsoft.Build.Internal
+{
+ class ProjectTaskItem : ITaskItem
+ {
+ ProjectItemElement item;
+ string evaluated_include_part;
+
+ public ProjectTaskItem (ProjectItemElement item, string evaluatedIncludePart)
+ {
+ this.item = item;
+ this.evaluated_include_part = WindowsCompatibilityExtensions.NormalizeFilePath (evaluatedIncludePart);
+ }
+ #region ITaskItem implementation
+ System.Collections.IDictionary ITaskItem.CloneCustomMetadata ()
+ {
+ var ret = new System.Collections.Hashtable ();
+ foreach (var p in item.Metadata)
+ ret [p.Name] = p;
+ return ret;
+ }
+ void ITaskItem.CopyMetadataTo (ITaskItem destinationItem)
+ {
+ throw new NotImplementedException ();
+ }
+ string ITaskItem.GetMetadata (string metadataName)
+ {
+ var wk = ProjectCollection.GetWellKnownMetadata (metadataName, evaluated_include_part, Path.GetFullPath, null);
+ if (wk != null)
+ return wk;
+ var mde = item.Metadata.FirstOrDefault (m => m.Name == metadataName);
+ return mde != null ? mde.Value : null;
+ }
+ void ITaskItem.RemoveMetadata (string metadataName)
+ {
+ throw new NotImplementedException ();
+ }
+ void ITaskItem.SetMetadata (string metadataName, string metadataValue)
+ {
+ throw new NotImplementedException ();
+ }
+ string ITaskItem.ItemSpec {
+ get { return evaluated_include_part; }
+ set { throw new NotImplementedException (); }
+ }
+ int ITaskItem.MetadataCount {
+ get {
+ throw new NotImplementedException ();
+ }
+ }
+ System.Collections.ICollection ITaskItem.MetadataNames {
+ get {
+ throw new NotImplementedException ();
+ }
+ }
+ #endregion
+ }
+}
+
--- /dev/null
+//
+// WindowsCompatibilityExtensions.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// (C) 2013 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.IO;
+
+namespace Microsoft.Build.Internal
+{
+ static class WindowsCompatibilityExtensions
+ {
+ public static string NormalizeFilePath (string path)
+ {
+ return path.Replace ('\\', Path.DirectorySeparatorChar);
+ }
+ }
+}
+
--- /dev/null
+using System;
+using Microsoft.Build.Framework;
+
+namespace Microsoft.Build.Logging
+{
+ public class ConfigurableForwardingLogger : IForwardingLogger
+ {
+ #region INodeLogger implementation
+
+ public void Initialize (IEventSource eventSource, int nodeCount)
+ {
+ Initialize (eventSource);
+ }
+
+ #endregion
+
+ #region ILogger implementation
+
+ public void Initialize (IEventSource eventSource)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public void Shutdown ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ public string Parameters { get; set; }
+
+ public LoggerVerbosity Verbosity { get; set; }
+
+ #endregion
+
+ #region IForwardingLogger implementation
+
+ public IEventRedirector BuildEventRedirector { get; set; }
+
+ public int NodeId { get; set; }
+
+ #endregion
+ }
+}
--- /dev/null
+using System;
+using Microsoft.Build.Framework;
+
+namespace Microsoft.Build.Logging
+{
+ public class DistributedFileLogger : IForwardingLogger
+ {
+ #region INodeLogger implementation
+
+ public void Initialize (IEventSource eventSource, int nodeCount)
+ {
+ throw new NotImplementedException ();
+ }
+
+ #endregion
+
+ #region ILogger implementation
+
+ public void Initialize (IEventSource eventSource)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public void Shutdown ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ public string Parameters { get; set; }
+
+ public LoggerVerbosity Verbosity { get; set; }
+
+ #endregion
+
+ #region IForwardingLogger implementation
+
+ public IEventRedirector BuildEventRedirector { get; set; }
+
+ public int NodeId { get; set; }
+
+ #endregion
+ }
+}
+
//
using System;
+using System.Reflection;
using Microsoft.Build.Framework;
namespace Microsoft.Build.Logging
{
- public class LoggerDescription
- {
- public LoggerDescription (string loggerClassName, string loggerAssemblyName,
- string loggerAssemblyFile, string loggerSwitchParameters,
- LoggerVerbosity verbosity)
- {
- throw new NotImplementedException ();
- }
- }
+ public class LoggerDescription
+ {
+ public LoggerDescription (string loggerClassName, string loggerAssemblyName,
+ string loggerAssemblyFile, string loggerSwitchParameters,
+ LoggerVerbosity verbosity)
+ {
+ if (loggerAssemblyName != null && loggerAssemblyFile != null)
+ throw new InvalidOperationException ("Cannot specify both loggerAssemblyName and loggerAssemblyFile at the same time.");
+ if (loggerAssemblyName == null && loggerAssemblyFile == null)
+ throw new InvalidOperationException ("Either loggerAssemblyName or loggerAssemblyFile must be specified");
+ class_name = loggerClassName;
+ assembly_name = loggerAssemblyName;
+ assembly_file = loggerAssemblyFile;
+ LoggerSwitchParameters = loggerSwitchParameters;
+ Verbosity = verbosity;
+ }
+
+ string class_name, assembly_name, assembly_file;
+
+ public string LoggerSwitchParameters { get; private set; }
+ public LoggerVerbosity Verbosity { get; private set; }
+
+ public ILogger CreateLogger ()
+ {
+ var assembly = assembly_name != null ? AppDomain.CurrentDomain.Load (assembly_name) : Assembly.LoadFile (assembly_file);
+ var type = assembly.GetType (class_name);
+ return (ILogger) Activator.CreateInstance (type, Verbosity);
+ }
+ }
}
Assembly/AssemblyInfo.cs
../../build/common/Consts.cs
../../build/common/MonoTODOAttribute.cs
+../Microsoft.Build.Engine/Microsoft.Build.BuildEngine/DirectoryScanner.cs
+../Microsoft.Build.Engine/Microsoft.Build.BuildEngine/EventSource.cs
+../Microsoft.Build.Engine/Microsoft.Build.BuildEngine/ColorSetter.cs
+../Microsoft.Build.Engine/Microsoft.Build.BuildEngine/ColorResetter.cs
+../Microsoft.Build.Engine/Microsoft.Build.BuildEngine/ConsoleLogger.cs
+../Microsoft.Build.Engine/Microsoft.Build.BuildEngine/FileLogger.cs
+../Microsoft.Build.Engine/Microsoft.Build.BuildEngine/WriteHandler.cs
+../Microsoft.Build.Utilities/Mono.XBuild.Utilities/MSBuildUtils.cs
+../Microsoft.Build.Utilities/Mono.XBuild.Utilities/ReservedNameUtils.cs
+../Microsoft.Build.Utilities/Microsoft.Build.Utilities/TaskItem.cs
+../Microsoft.Build.Utilities/Microsoft.Build.Utilities/ToolLocationHelper.cs
+../Microsoft.Build.Utilities/Microsoft.Build.Utilities/TargetDotNetFrameworkVersion.cs
Microsoft.Build.Construction/ElementLocation.cs
Microsoft.Build.Construction/ProjectChooseElement.cs
Microsoft.Build.Construction/ProjectCommentElement.cs
Microsoft.Build.Construction/ProjectWhenElement.cs
Microsoft.Build.Construction/UsingTaskParameterGroupElement.cs
Microsoft.Build.Evaluation/Project.cs
+Microsoft.Build.Evaluation/ProjectChangedEventArgs.cs
Microsoft.Build.Evaluation/ProjectCollection.cs
+Microsoft.Build.Evaluation/ProjectCollectionChangedEventArgs.cs
+Microsoft.Build.Evaluation/ProjectCollectionChangedState.cs
Microsoft.Build.Evaluation/ProjectItem.cs
Microsoft.Build.Evaluation/ProjectItemDefinition.cs
Microsoft.Build.Evaluation/ProjectLoadSettings.cs
Microsoft.Build.Evaluation/ProjectMetadata.cs
Microsoft.Build.Evaluation/ProjectProperty.cs
+Microsoft.Build.Evaluation/ProjectXmlChangedEventArgs.cs
Microsoft.Build.Evaluation/ResolvedImport.cs
+Microsoft.Build.Evaluation/SubToolset.cs
Microsoft.Build.Evaluation/Toolset.cs
Microsoft.Build.Evaluation/ToolsetDefinitionLocations.cs
+Microsoft.Build.Exceptions/BuildAbortedException.cs
+Microsoft.Build.Exceptions/InternalLoggerException.cs
Microsoft.Build.Exceptions/InvalidProjectFileException.cs
+Microsoft.Build.Exceptions/InvalidToolsetDefinitionException.cs
Microsoft.Build.Execution/BuildManager.cs
Microsoft.Build.Execution/BuildParameters.cs
Microsoft.Build.Execution/BuildRequestData.cs
Microsoft.Build.Execution/BuildResult.cs
Microsoft.Build.Execution/BuildResultCode.cs
Microsoft.Build.Execution/BuildSubmission.cs
+Microsoft.Build.Execution/BuildSubmissionCompleteCallback.cs
Microsoft.Build.Execution/HostServices.cs
Microsoft.Build.Execution/ITargetResult.cs
Microsoft.Build.Execution/NodeAffinity.cs
+Microsoft.Build.Execution/NodeEngineShutdownReason.cs
+Microsoft.Build.Execution/OutOfProcNode.cs
Microsoft.Build.Execution/ProjectInstance.cs
Microsoft.Build.Execution/ProjectItemDefinitionInstance.cs
+Microsoft.Build.Execution/ProjectItemGroupTaskInstance.cs
+Microsoft.Build.Execution/ProjectItemGroupTaskItemInstance.cs
+Microsoft.Build.Execution/ProjectItemGroupTaskMetadataInstance.cs
Microsoft.Build.Execution/ProjectItemInstance.cs
Microsoft.Build.Execution/ProjectMetadataInstance.cs
+Microsoft.Build.Execution/ProjectOnErrorInstance.cs
+Microsoft.Build.Execution/ProjectPropertyGroupTaskInstance.cs
+Microsoft.Build.Execution/ProjectPropertyGroupTaskPropertyInstance.cs
Microsoft.Build.Execution/ProjectPropertyInstance.cs
Microsoft.Build.Execution/ProjectTargetInstance.cs
+Microsoft.Build.Execution/ProjectTaskInstance.cs
+Microsoft.Build.Execution/ProjectTaskInstanceChild.cs
+Microsoft.Build.Execution/ProjectTaskOutputItemInstance.cs
+Microsoft.Build.Execution/ProjectTaskOutputPropertyInstance.cs
+Microsoft.Build.Execution/ProjectTargetInstanceChild.cs
Microsoft.Build.Execution/TargetResult.cs
Microsoft.Build.Execution/TargetResultCode.cs
+Microsoft.Build.Internal/BuildEngine4.cs
+Microsoft.Build.Internal/BuildNodeManager.cs
+Microsoft.Build.Internal/BuildTaskDatabase.cs
+Microsoft.Build.Internal/BuildTaskFactory.cs
Microsoft.Build.Internal/CollectionFromEnumerable.cs
+Microsoft.Build.Internal/ExpressionConstructs.cs
+Microsoft.Build.Internal/ExpressionEvaluator.cs
+Microsoft.Build.Internal/ExpressionParserManual.cs
+Microsoft.Build.Internal/ExpressionTokenizer.cs
Microsoft.Build.Internal/FilteredEnumerable.cs
+Microsoft.Build.Internal/ProjectTaskItem.cs
Microsoft.Build.Internal/ReverseEnumerable.cs
-Microsoft.Build.Logging/ColorResetter.cs
-Microsoft.Build.Logging/ColorSetter.cs
-Microsoft.Build.Logging/ConsoleLogger.cs
-Microsoft.Build.Logging/FileLogger.cs
+Microsoft.Build.Internal/WindowsCompatibilityExtensions.cs
+Microsoft.Build.Logging/ConfigurableForwardingLogger.cs
Microsoft.Build.Logging/ForwardingLoggerRecord.cs
Microsoft.Build.Logging/LoggerDescription.cs
-Microsoft.Build.Logging/WriteHandler.cs
FunctionalTest.cs
+Microsoft.Build.Construction/ProjectItemElementTest.cs
+Microsoft.Build.Construction/ProjectRootElementTest.cs
+Microsoft.Build.Evaluation/ProjectCollectionTest.cs
+Microsoft.Build.Evaluation/ProjectItemDefinitionTest.cs
+Microsoft.Build.Evaluation/ProjectItemTest.cs
+Microsoft.Build.Evaluation/ProjectTest.cs
+Microsoft.Build.Evaluation/ProjectPropertyTest.cs
+Microsoft.Build.Evaluation/ResolvedImportTest.cs
+Microsoft.Build.Evaluation/ToolsetTest.cs
+Microsoft.Build.Execution/BuildParametersTest.cs
+Microsoft.Build.Execution/BuildManagerTest.cs
+Microsoft.Build.Execution/BuildSubmissionTest.cs
+Microsoft.Build.Execution/ProjectInstanceTest.cs
+Microsoft.Build.Execution/ProjectMetadataInstanceTest.cs
+Microsoft.Build.Execution/ProjectTargetInstanceTest.cs
Microsoft.Build.Internal/CollectionFromEnumerableTest.cs
+Microsoft.Build.Internal/ExpressionParserTest.cs
Microsoft.Build.Logging/ConsoleLoggerTest.cs
+Microsoft.Build.Logging/LoggerDescriptionTest.cs
+
--- /dev/null
+using System;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using Microsoft.Build.Construction;
+using NUnit.Framework;
+using Microsoft.Build.Evaluation;
+using Microsoft.Build.Exceptions;
+
+namespace MonoTests.Microsoft.Build.Construction
+{
+ [TestFixture]
+ public class ProjectItemElementTest
+ {
+ [Test]
+ [ExpectedException (typeof (InvalidProjectFileException))]
+ public void EmptyInclude ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <ItemGroup>
+ <Foo Include='' />
+ </ItemGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ ProjectRootElement.Create (xml);
+ }
+
+ [Test]
+ [ExpectedException (typeof (InvalidProjectFileException))]
+ public void MissingInclude ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <ItemGroup>
+ <Foo />
+ </ItemGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ ProjectRootElement.Create (xml);
+ }
+ }
+}
+
--- /dev/null
+using System;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using Microsoft.Build.Construction;
+using NUnit.Framework;
+using Microsoft.Build.Evaluation;
+using Microsoft.Build.Exceptions;
+
+namespace MonoTests.Microsoft.Build.Construction
+{
+ [TestFixture]
+ public class ProjectRootElementTest
+ {
+ const string empty_project_xml = "<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+
+ [Test]
+ [ExpectedException (typeof (UriFormatException))]
+ [Category ("NotWorking")] // URL is constructed for ElementLocation, which we don't support yet.
+ public void CreateExpectsAbsoluteUri ()
+ {
+ var xml = XmlReader.Create (new StringReader (empty_project_xml), null, "foo.xml");
+ ProjectRootElement.Create (xml);
+ }
+
+ [Test]
+ public void CreateAndPaths ()
+ {
+ Assert.IsNull (ProjectRootElement.Create ().FullPath, "#1");
+ var xml = XmlReader.Create (new StringReader (empty_project_xml), null, "file:///foo.xml");
+ // This creator does not fill FullPath...
+ var root = ProjectRootElement.Create (xml);
+ Assert.IsNull (root.FullPath, "#2");
+ Assert.AreEqual (Path.GetDirectoryName (new Uri (GetType ().Assembly.CodeBase).LocalPath), root.DirectoryPath, "#3");
+ }
+
+ [Test]
+ public void FullPathSetter ()
+ {
+ var root = ProjectRootElement.Create ();
+ root.FullPath = "test" + Path.DirectorySeparatorChar + "foo.xml";
+ var full = Path.Combine (Path.GetDirectoryName (new Uri (GetType ().Assembly.CodeBase).LocalPath), "test", "foo.xml");
+ Assert.AreEqual (full, root.FullPath, "#1");
+ Assert.AreEqual (Path.GetDirectoryName (full), root.DirectoryPath, "#1");
+ }
+
+ [Test]
+ [ExpectedException (typeof (ArgumentNullException))]
+ public void FullPathSetNull ()
+ {
+ ProjectRootElement.Create ().FullPath = null;
+ }
+
+ [Test]
+ public void InvalidProject ()
+ {
+ try {
+ ProjectRootElement.Create (XmlReader.Create (new StringReader (" <root/>")));
+ Assert.Fail ("should throw InvalidProjectFileException");
+ } catch (InvalidProjectFileException ex) {
+ #if NET_4_5
+ Assert.AreEqual (1, ex.LineNumber, "#1");
+ // it is very interesting, but unlike XmlReader.LinePosition it returns the position for '<'.
+ Assert.AreEqual (2, ex.ColumnNumber, "#2");
+ #endif
+ }
+ }
+
+ [Test]
+ public void CreateWithXmlLoads ()
+ {
+ string project_xml_1 = "<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'><ItemGroup><None Include='bar.txt' /></ItemGroup></Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml_1), null, "file://localhost/foo.xml");
+ var root = ProjectRootElement.Create (xml);
+ Assert.AreEqual (1, root.Items.Count, "#1");
+ }
+
+ [Test]
+ public void ToolsVersionDefault ()
+ {
+ var g = ProjectCollection.GlobalProjectCollection;
+ var root = ProjectRootElement.Create ();
+ // this will be wrong in the future version, but since .NET 4.5 still expects "4.0" we can't say for sure.
+ Assert.AreEqual ("4.0", root.ToolsVersion, "#1");
+ }
+
+ [Test]
+ public void ToolsVersionIsEmptyWithXml ()
+ {
+ string project_xml_1 = "<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'><ItemGroup><None Include='bar.txt' /></ItemGroup></Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml_1), null, "file://localhost/foo.xml");
+ var root = ProjectRootElement.Create (xml);
+ Assert.AreEqual (string.Empty, root.ToolsVersion, "#1");
+ }
+
+ [Test]
+ public void LoadUnknownChild ()
+ {
+ string project_xml_1 = "<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'><Unknown /></Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml_1), null, "file://localhost/foo.xml");
+ try {
+ ProjectRootElement.Create (xml);
+ Assert.Fail ("should throw InvalidProjectFileException");
+ } catch (InvalidProjectFileException ex) {
+ #if NET_4_5
+ Assert.AreEqual (1, ex.LineNumber, "#1");
+ // unlike unexpected element case which returned the position for '<', it does return the name start char...
+ Assert.AreEqual (70, ex.ColumnNumber, "#2");
+ #endif
+ }
+ }
+
+ [Test]
+ public void LoadUnregisteredItem ()
+ {
+ string project_xml_1 = "<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'><ItemGroup><UnregisteredItem Include='bar.txt' /></ItemGroup></Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml_1), null, "file://localhost/foo.xml");
+ var root = ProjectRootElement.Create (xml);
+ Assert.AreEqual (1, root.Items.Count, "#1");
+ }
+
+ [Test]
+ public void LoadInvalidProjectForBadCondition ()
+ {
+ string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <PropertyGroup>
+ <Foo>What are 'ESCAPE' & ""EVALUATE"" ? $ # % ^</Foo>
+ <!-- Note that this contains invalid Condition expression. Project.ctor() fails to load. -->
+ <Baz Condition=""$(Void)=="">$(FOO)</Baz>
+ </PropertyGroup>
+</Project>";
+ var path = "file://localhost/foo.xml";
+ var reader = XmlReader.Create (new StringReader (xml), null, path);
+ var root = ProjectRootElement.Create (reader);
+ Assert.AreEqual (2, root.Properties.Count, "#1");
+ }
+
+ [Test]
+ [ExpectedException (typeof (InvalidProjectFileException))]
+ public void LoadInvalidProjectGroupInProjectGroup ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' />
+ <PropertyGroup>
+ <Foo>Bar</Foo>
+ <PropertyGroup>
+ <X>x</X>
+ <Y>y</Y>
+ <Z>z</Z>
+ </PropertyGroup>
+ </PropertyGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ ProjectRootElement.Create (xml);
+ }
+
+ [Test]
+ [ExpectedException (typeof (InvalidProjectFileException))]
+ public void LoadInvalidItemGroupInProjectGroup ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' />
+ <PropertyGroup>
+ <Foo>Bar</Foo>
+ <ItemGroup/>
+ </PropertyGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ ProjectRootElement.Create (xml);
+ }
+
+ [Test]
+ public void ChildAndAllChildren ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' />
+ <PropertyGroup>
+ <Foo>Bar</Foo>
+ <Item/>
+ </PropertyGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ Assert.AreEqual (2, root.Children.Count, "#1");
+ // AllChildren expands descendants
+ Assert.AreEqual (4, root.AllChildren.Count (), "#2");
+ }
+
+ [Test]
+ [ExpectedException (typeof (InvalidOperationException))]
+ public void SaveWithoutFullPath ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+ var xml = XmlReader.Create (new StringReader (project_xml), null, "file://localhost/foo.xml");
+ var root = ProjectRootElement.Create (xml);
+ root.Save ();
+ }
+
+ [Test]
+ public void SaveToWriter ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+ var xml = XmlReader.Create (new StringReader (project_xml), null, "file://localhost/foo.xml");
+ var root = ProjectRootElement.Create (xml);
+ var sw = new StringWriter ();
+ root.Save (sw);
+ // CRLF? mmm, k...
+ Assert.AreEqual ("<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n" + project_xml.Replace ('\'', '"'), sw.ToString (), "#1");
+ }
+
+ [Test]
+ [ExpectedException (typeof (InvalidProjectFileException))]
+ public void ImportsMissingProject ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <Import Project='' />
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ ProjectRootElement.Create (xml);
+ }
+ }
+}
--- /dev/null
+//
+// ProjectCollectionTest.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using Microsoft.Build.Construction;
+using Microsoft.Build.Evaluation;
+using NUnit.Framework;
+using Microsoft.Build.Execution;
+
+namespace MonoTests.Microsoft.Build.Evaluation
+{
+ [TestFixture]
+ public class ProjectCollectionTest
+ {
+ [Test]
+ public void GlobalProperties ()
+ {
+ var g = ProjectCollection.GlobalProjectCollection;
+ Assert.AreEqual (0, g.GlobalProperties.Count, "#1");
+ Assert.IsTrue (g.GlobalProperties.IsReadOnly, "#2");
+ }
+
+ [Test]
+ public void DefaultToolsVersion ()
+ {
+ var pc = ProjectCollection.GlobalProjectCollection;
+ Assert.AreEqual (pc.Toolsets.First ().ToolsVersion, pc.DefaultToolsVersion, "#1");
+ }
+
+ [Test]
+ public void Toolsets ()
+ {
+ var pc = ProjectCollection.GlobalProjectCollection;
+ Assert.IsNotNull (pc.Toolsets, "#1-1");
+ Assert.IsTrue (pc.Toolsets.Any (), "#1-2");
+ pc = new ProjectCollection ();
+ Assert.IsNotNull (pc.Toolsets, "#2-1");
+ Assert.IsTrue (pc.Toolsets.Any (), "#2-2");
+ }
+
+ [Test]
+ public void BuildDoesNotIncreaseCollectionContent ()
+ {
+ string empty_project_xml = "<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+ var xml = XmlReader.Create (new StringReader (empty_project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var coll = new ProjectCollection ();
+ var inst = new ProjectInstance (root, null, null, coll);
+ root.FullPath = "ProjectCollectionTest.BuildDoesNotIncreaseCollectionContent.proj";
+ Assert.AreEqual (0, coll.Count, "#1");
+ inst.Build ();
+ Assert.AreEqual (0, coll.Count, "#2");
+ }
+
+ [Test]
+ public void GetLoadedProjectsWithoutFullPath ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ string path = Path.GetFullPath ("foo.xml");
+ var pc = new ProjectCollection ();
+
+ pc.LoadProject (XmlReader.Create (new StringReader (project_xml), null, path));
+ Assert.AreEqual (0, pc.GetLoadedProjects (path).Count, "#1"); // huh?
+ Assert.AreEqual (0, pc.LoadedProjects.Count, "#1.1");
+
+ new Project (root, null, null, pc);
+ Assert.AreEqual (0, pc.GetLoadedProjects (path).Count, "#2"); // huh?
+ }
+
+ [Test]
+ public void GetLoadedProjectsSuccess ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ string path = Path.GetFullPath ("foo.xml");
+ var pc = new ProjectCollection ();
+
+ var proj = new Project (root, null, null, pc);
+ // this order also matters for test; It sets FullPath after Project.ctor(), and should still work.
+ root.FullPath = "foo.xml";
+
+ Assert.AreEqual (1, pc.GetLoadedProjects (path).Count, "#1"); // wow ok...
+ Assert.AreEqual (proj, pc.GetLoadedProjects (path).First (), "#2");
+ }
+
+ [Test]
+ public void GetLoadedProjectsSuccess2 ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+ string path = Path.GetFullPath ("GetLoadedProjectsSuccess2.xml");
+ var pc = new ProjectCollection ();
+
+ using (var fs = File.CreateText (path))
+ fs.Write (project_xml);
+ try {
+ var proj = pc.LoadProject (path);
+
+ Assert.AreEqual (1, pc.GetLoadedProjects (path).Count, "#1"); // ok... LoadProject (with filename) adds it to the collection.
+ Assert.AreEqual (proj, pc.GetLoadedProjects (path).First (), "#2");
+ } finally {
+ File.Delete (path);
+ }
+ }
+
+ [Test]
+ public void GetLoadedProjectsForProjectInstance ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ string path = Path.GetFullPath ("foo.xml");
+ var pc = new ProjectCollection ();
+ root.FullPath = "foo.xml";
+
+ new ProjectInstance (root, null, null, pc);
+ Assert.AreEqual (0, pc.GetLoadedProjects (path).Count, "#1"); // so, ProjectInstance does not actually load Project...
+ }
+ }
+}
+
--- /dev/null
+//
+// ProjectItemDefinitionTest.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using Microsoft.Build.Construction;
+using Microsoft.Build.Evaluation;
+using Microsoft.Build.Execution;
+using NUnit.Framework;
+using System.Collections.Generic;
+
+namespace MonoTests.Microsoft.Build.Evaluation
+{
+ [TestFixture]
+ public class ProjectItemDefinitionTest
+ {
+ [Test]
+ public void Properties ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <ItemDefinitionGroup>
+ <Foo>
+ <prop1>value1</prop1>
+ <prop2>value1</prop2>
+ </Foo>
+ <!-- This one is merged into existing Foo definition above. -->
+ <Foo>
+ <prop1>valueX1</prop1><!-- this one overrides value1. -->
+ <prop3>value3</prop3>
+ </Foo>
+ </ItemDefinitionGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new Project (root);
+ Assert.AreEqual (1, proj.ItemDefinitions.Count, "#1"); // Foo
+ var def = proj.ItemDefinitions ["Foo"];
+ Assert.AreEqual ("Foo", def.ItemType, "#1x");
+ Assert.AreEqual (3, def.MetadataCount, "#2");
+ var md1 = def.Metadata.First (m => m.Name == "prop1");
+ Assert.AreEqual ("Foo", md1.ItemType, "#2x");
+ Assert.AreEqual ("valueX1", md1.UnevaluatedValue, "#3");
+ // FIXME: enable it once we implemented it.
+ //Assert.AreEqual ("valueX1", md1.EvaluatedValue, "#4");
+ Assert.IsNotNull (md1.Predecessor, "#5");
+ Assert.AreEqual ("value1", md1.Predecessor.UnevaluatedValue, "#6");
+ // FIXME: enable it once we implemented it.
+ //Assert.AreEqual ("value1", md1.Predecessor.EvaluatedValue, "#7");
+ }
+
+ [Test]
+ public void Condition ()
+ {
+ string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <ItemDefinitionGroup>
+ <I Condition='{0}'>
+ <DefinedMetadata>X</DefinedMetadata>
+ </I>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <I Include='foo' />
+ </ItemGroup>
+</Project>";
+ var reader = XmlReader.Create (new StringReader (string.Format (xml, "True")));
+ var root = ProjectRootElement.Create (reader);
+ var proj = new Project (root);
+ var i = proj.GetItems ("I").First ();
+ Assert.AreEqual ("X", i.GetMetadataValue ("DefinedMetadata"), "#1");
+
+ reader = XmlReader.Create (new StringReader (string.Format (xml, "False")));
+ root = ProjectRootElement.Create (reader);
+ proj = new Project (root);
+ i = proj.GetItems ("I").First ();
+ Assert.AreEqual (string.Empty, i.GetMetadataValue ("DefinedMetadata"), "#2");
+ }
+ }
+}
+
--- /dev/null
+//
+// ProjectItemTest.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using Microsoft.Build.Construction;
+using Microsoft.Build.Evaluation;
+using Microsoft.Build.Execution;
+using NUnit.Framework;
+using System.Collections.Generic;
+
+namespace MonoTests.Microsoft.Build.Evaluation
+{
+ [TestFixture]
+ public class ProjectItemTest
+ {
+ [Test]
+ public void SetUnevaluatedInclude ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <ItemGroup>
+ <Foo Include='foo/bar.txt' />
+ </ItemGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ Assert.AreEqual (1, root.ItemGroups.Count, "#1");
+ var g = root.ItemGroups.First ();
+ Assert.AreEqual (1, g.Items.Count, "#2");
+ var xitem = g.Items.First ();
+ var proj = new Project (root);
+ var item = proj.ItemsIgnoringCondition.First ();
+ string inc = "foo/bar.txt";
+ Assert.AreEqual (inc, xitem.Include, "#3");
+ Assert.AreEqual (inc, item.UnevaluatedInclude, "#4");
+ string inc2 = "foo/bar.ext.txt";
+ item.UnevaluatedInclude = inc2;
+ Assert.AreEqual (inc2, xitem.Include, "#5");
+ Assert.AreEqual (inc2, item.UnevaluatedInclude, "#6");
+ }
+
+ void SetupTemporaryDirectoriesAndFiles ()
+ {
+ Directory.CreateDirectory ("Test/ProjectItemTestTemporary");
+ Directory.CreateDirectory ("Test/ProjectItemTestTemporary/parent");
+ Directory.CreateDirectory ("Test/ProjectItemTestTemporary/parent/dir1");
+ Directory.CreateDirectory ("Test/ProjectItemTestTemporary/parent/dir2");
+ File.CreateText ("Test/ProjectItemTestTemporary/x.cs").Close ();
+ File.CreateText ("Test/ProjectItemTestTemporary/parent/dir1/a.cs").Close ();
+ File.CreateText ("Test/ProjectItemTestTemporary/parent/dir1/a1.cs").Close ();
+ File.CreateText ("Test/ProjectItemTestTemporary/parent/dir1/b.cs").Close ();
+ File.CreateText ("Test/ProjectItemTestTemporary/parent/dir2/a2.cs").Close ();
+ File.CreateText ("Test/ProjectItemTestTemporary/parent/dir2/a.cs").Close ();
+ File.CreateText ("Test/ProjectItemTestTemporary/parent/dir2/b.cs").Close ();
+ }
+
+ void CleanupTemporaryDirectories ()
+ {
+ Directory.Delete ("Test/ProjectItemTestTemporary", true);
+ }
+
+ [Test]
+ public void WildcardExpansion ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <ItemGroup>
+ <Foo Include='Test/ProjectItemTestTemporary/parent/dir*/a*.cs;Test/ProjectItemTestTemporary/x.cs' />
+ </ItemGroup>
+</Project>";
+ try {
+ SetupTemporaryDirectoriesAndFiles ();
+ WildcardExpansionCommon (project_xml, false);
+ } finally {
+ CleanupTemporaryDirectories ();
+ }
+ }
+
+ [Test]
+ public void WildcardExpansionRecursive ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <ItemGroup>
+ <Foo Include='Test/ProjectItemTestTemporary/parent/**/a*.cs;Test/ProjectItemTestTemporary/x.cs' />
+ </ItemGroup>
+</Project>";
+ try {
+ SetupTemporaryDirectoriesAndFiles ();
+ WildcardExpansionCommon (project_xml, true);
+ } finally {
+ CleanupTemporaryDirectories ();
+ }
+ }
+
+ void WildcardExpansionCommon (string xmlString, bool hasRecursiveDir)
+ {
+ char sep = Path.DirectorySeparatorChar;
+ var xml = XmlReader.Create (new StringReader (xmlString));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new Project (root);
+ var xitem = proj.Xml.Items.First ();
+ // sort is needed because they are only sorted by ItemType.
+ var items = proj.Items.OrderBy (p => p.EvaluatedInclude).ToArray ();
+ Assert.AreEqual (5, items.Length, "#1");
+ Assert.AreEqual (string.Format ("Test/ProjectItemTestTemporary/parent/dir1{0}a.cs", Path.DirectorySeparatorChar), items [0].EvaluatedInclude, "#2");
+ Assert.AreEqual ("a", items [0].GetMetadataValue ("Filename"), "#3");
+ if (hasRecursiveDir)
+ Assert.AreEqual ("dir1" + sep, items [0].GetMetadataValue ("RecursiveDir"), "#3.2");
+ Assert.AreEqual (string.Format ("Test/ProjectItemTestTemporary/parent/dir1{0}a1.cs", Path.DirectorySeparatorChar), items [1].EvaluatedInclude, "#4");
+ Assert.AreEqual ("a1", items [1].GetMetadataValue ("Filename"), "#5");
+ if (hasRecursiveDir)
+ Assert.AreEqual ("dir1" + sep, items [1].GetMetadataValue ("RecursiveDir"), "#5.2");
+ Assert.AreEqual (string.Format ("Test/ProjectItemTestTemporary/parent/dir2{0}a.cs", Path.DirectorySeparatorChar), items [2].EvaluatedInclude, "#6");
+ Assert.AreEqual ("a", items [2].GetMetadataValue ("Filename"), "#7");
+ if (hasRecursiveDir)
+ Assert.AreEqual ("dir2" + sep, items [2].GetMetadataValue ("RecursiveDir"), "#7.2");
+ Assert.AreEqual (string.Format ("Test/ProjectItemTestTemporary/parent/dir2{0}a2.cs", Path.DirectorySeparatorChar), items [3].EvaluatedInclude, "#8");
+ Assert.AreEqual ("a2", items [3].GetMetadataValue ("Filename"), "#9");
+ if (hasRecursiveDir)
+ Assert.AreEqual ("dir2" + sep, items [3].GetMetadataValue ("RecursiveDir"), "#9.2");
+ Assert.AreEqual ("Test/ProjectItemTestTemporary/x.cs", items [4].EvaluatedInclude, "#10");
+ for (int i = 0; i < items.Length; i++)
+ Assert.AreEqual (xitem, items [i].Xml, "#11:" + i);
+ }
+
+ [Test]
+ public void Metadata ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <ItemDefinitionGroup>
+ <Foo>
+ <prop1>value1</prop1>
+ </Foo>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <Foo Include='foo/bar.txt'>
+ <prop1>valueX1</prop1>
+ </Foo>
+ </ItemGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ Assert.AreEqual (1, root.ItemGroups.Count, "#1");
+ var g = root.ItemGroups.First ();
+ Assert.AreEqual (1, g.Items.Count, "#2");
+ var proj = new Project (root);
+ var item = proj.ItemsIgnoringCondition.First ();
+ var meta = item.GetMetadata ("prop1");
+ Assert.IsNotNull (meta, "#3");
+ Assert.AreEqual ("valueX1", meta.UnevaluatedValue, "#4");
+ Assert.IsNotNull (meta.Predecessor, "#5");
+ Assert.AreEqual ("value1", meta.Predecessor.UnevaluatedValue, "#6");
+
+ // Well-known metadata don't show up via GetMetadata(), but does show up via GetMetadataValue().
+ Assert.AreEqual (null, item.GetMetadata ("Filename"), "#7");
+ Assert.AreEqual ("bar", item.GetMetadataValue ("Filename"), "#8");
+ }
+
+ [Test]
+ public void ExpandPropertyThenTrim ()
+ {
+ string test = @"A
+B
+C
+ ";
+ string project_xml = string.Format (@"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <PropertyGroup>
+ <Test>{0}</Test>
+ <Test2>$(TEST)</Test2>
+ </PropertyGroup>
+ <ItemGroup>
+ <X Include='$(TEST)' />
+ <X2 Include='$(TEST)z' />
+ </ItemGroup>
+</Project>", test);
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ root.FullPath = "ProjectItemTest.ExpandPropertyThenTrim.proj";
+ var proj = new ProjectInstance (root);
+ Assert.AreEqual (test, proj.GetPropertyValue ("TEST"), "#1");
+ Assert.AreEqual (test, proj.GetPropertyValue ("TEST2"), "#2");
+ Assert.AreEqual (test.Trim (), proj.GetItems ("X").First ().EvaluatedInclude, "#3");
+ Assert.AreEqual (test + "z", proj.GetItems ("X2").First ().EvaluatedInclude, "#4");
+ }
+ }
+}
+
--- /dev/null
+//
+// ProjectPropertyTest.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using Microsoft.Build.Construction;
+using Microsoft.Build.Evaluation;
+using Microsoft.Build.Execution;
+using NUnit.Framework;
+using System.Collections.Generic;
+
+namespace MonoTests.Microsoft.Build.Evaluation
+{
+ [TestFixture]
+ public class ProjectPropertyTest
+ {
+ [Test]
+ public void SetUnevaluatedValueOverwritesElementValue ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <PropertyGroup>
+ <Foo>Bar</Foo>
+ <Item/>
+ <X>1</X>
+ <X>2</X>
+ <PATH>overriden</PATH>
+ </PropertyGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var pe = root.Properties.First ();
+ Assert.AreEqual ("Bar", pe.Value, "#1");
+ var proj = new Project (root);
+ var prop = proj.Properties.First (p => p.Name == "Foo");
+ Assert.AreEqual ("Bar", prop.UnevaluatedValue, "#2");
+ prop.UnevaluatedValue = "x";
+ Assert.AreEqual ("x", pe.Value, "#3");
+
+ prop = proj.Properties.First (p => p.Name == "X");
+ Assert.AreEqual ("2", prop.UnevaluatedValue, "#4");
+ Assert.IsNotNull (prop.Predecessor, "#5");
+ Assert.AreEqual ("1", prop.Predecessor.UnevaluatedValue, "#6");
+
+ // environment property could also be Predecessor (and removed...maybe.
+ // I could reproduce only NRE = .NET bug with environment property so far.)
+ prop = proj.Properties.First (p => p.Name == "PATH");
+ Assert.AreEqual ("overriden", prop.UnevaluatedValue, "#7");
+ Assert.IsNotNull (prop.Predecessor, "#8");
+ }
+
+ [Test]
+ [ExpectedException (typeof(InvalidOperationException))]
+ public void UpdateGlobalPropertyValue ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var props = new Dictionary<string, string> ();
+ props.Add ("GP", "GV");
+ var root = ProjectRootElement.Create (xml);
+ var proj = new Project (root, props, null);
+ var pe = proj.Properties.First (p => p.IsGlobalProperty);
+ pe.UnevaluatedValue = "UPDATED";
+ }
+
+ [Test]
+ [ExpectedException (typeof (InvalidOperationException))]
+ public void UpdateEnvironmentPropertyValue ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new Project (root);
+ var pe = proj.Properties.First (p => p.IsEnvironmentProperty);
+ pe.UnevaluatedValue = "UPDATED";
+ }
+
+ [Test]
+ public void DeepReferences ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <PropertyGroup>
+ <A>1</A>
+ <B>$(A)+1</B>
+ <C>$(B)+2</C>
+ </PropertyGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ Assert.AreEqual ("1+1+2", new Project (root).GetProperty ("C").EvaluatedValue, "#1");
+ Assert.AreEqual ("1+1+2", new ProjectInstance (root).GetProperty ("C").EvaluatedValue, "#1");
+ }
+
+ [Test]
+ public void PlatformPropertyEmptyByDefault ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new Project (root);
+ Assert.IsNull (proj.GetProperty ("PLATFORM"), "#1");
+ }
+ }
+}
+
--- /dev/null
+//
+// ProjectTest.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using Microsoft.Build.Construction;
+using Microsoft.Build.Evaluation;
+using NUnit.Framework;
+using Microsoft.Build.Exceptions;
+using Microsoft.Build.Logging;
+using Microsoft.Build.Framework;
+
+namespace MonoTests.Microsoft.Build.Evaluation
+{
+ [TestFixture]
+ public class ProjectTest
+ {
+ [Test]
+ public void EscapeDoesWTF ()
+ {
+ string value_xml = "What are 'ESCAPE' & \"EVALUATE\" ? $ # % ^";
+ string value = "What are 'ESCAPE' & \"EVALUATE\" ? $ # % ^";
+ string escaped = "What are %27ESCAPE%27 & \"EVALUATE\" %3f %24 # %25 ^";
+ string xml = string.Format (@"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <PropertyGroup>
+ <Foo>{0}</Foo>
+ <Baz>$(FOO)</Baz>
+ </PropertyGroup>
+</Project>", value_xml);
+ var path = "file://localhost/foo.xml";
+ var reader = XmlReader.Create (new StringReader (xml), null, path);
+ var root = ProjectRootElement.Create (reader);
+ var proj = new Project (root);
+ var prop = proj.Properties.First (p => p.Name == "Foo");
+ Assert.AreEqual (value, prop.UnevaluatedValue, "#1");
+ Assert.AreEqual (value, prop.EvaluatedValue, "#2");
+ // eh?
+ Assert.AreEqual (value, Project.GetPropertyValueEscaped (prop), "#3");
+ prop = proj.Properties.First (p => p.Name == "Baz");
+ Assert.AreEqual ("$(FOO)", prop.UnevaluatedValue, "#4");
+ Assert.AreEqual (value, prop.EvaluatedValue, "#5");
+ // eh?
+ Assert.AreEqual (value, Project.GetPropertyValueEscaped (prop), "#6");
+
+ // OK you are fine.
+ Assert.AreEqual (escaped, ProjectCollection.Escape (value), "#7");
+ }
+
+ [Test]
+ public void FullPath ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+ var xml = XmlReader.Create (new StringReader (project_xml), null, "file://localhost/foo.xml");
+ var root = ProjectRootElement.Create (xml);
+ var proj = new Project (root);
+ proj.FullPath = "ABC";
+ Assert.IsTrue (proj.FullPath.EndsWith (Path.DirectorySeparatorChar + "ABC"), "#1");
+ Assert.AreEqual (root.FullPath, proj.FullPath, "#2");
+ }
+
+ [Test]
+ public void BuildEmptyProject ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+ var xml = XmlReader.Create (new StringReader (project_xml), null, "file://localhost/foo.xml");
+ var root = ProjectRootElement.Create (xml);
+ root.FullPath = "ProjectTest.BuildEmptyProject.proj";
+
+ // This seems to do nothing and still returns true
+ Assert.IsTrue (new Project (root) { FullPath = "ProjectTest.BuildEmptyProject.1.proj" }.Build (), "#1");
+ // This seems to fail to find the appropriate target
+ Assert.IsFalse (new Project (root) { FullPath = "ProjectTest.BuildEmptyProject.2.proj" }.Build ("Build", null), "#2");
+ // Thus, this tries to build all the targets (empty) and no one failed, so returns true(!)
+ Assert.IsTrue (new Project (root) { FullPath = "ProjectTest.BuildEmptyProject.3.proj" }.Build (new string [0], null), "#3");
+ // Actially null "targets" is accepted and returns true(!!)
+ Assert.IsTrue (new Project (root) { FullPath = "ProjectTest.BuildEmptyProject.4.proj" }.Build ((string []) null, null), "#4");
+ // matching seems to be blindly done, null string also results in true(!!)
+ Assert.IsTrue (new Project (root) { FullPath = "ProjectTest.BuildEmptyProject.5.proj" }.Build ((string) null, null), "#5");
+ }
+
+ [Test]
+ [ExpectedException (typeof (InvalidProjectFileException))]
+ public void LoadInvalidProjectForBadCondition ()
+ {
+ string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <PropertyGroup>
+ <Foo>What are 'ESCAPE' & ""EVALUATE"" ? $ # % ^</Foo>
+ <!-- Note that this contains invalid Condition expression, yet ProjectElement.Create() does NOT fail. -->
+ <Baz Condition=""$(Void)=="">$(FOO)</Baz>
+ </PropertyGroup>
+</Project>";
+ var reader = XmlReader.Create (new StringReader (xml));
+ var root = ProjectRootElement.Create (reader);
+ new Project (root);
+ }
+
+ [Test]
+ public void ExpandString ()
+ {
+ string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <PropertyGroup>
+ <Foo>What are 'ESCAPE' & ""EVALUATE"" ? $ # % ^</Foo>
+ <Bar>y</Bar>
+ <Baz Condition=""$(Void)==''"">$(FOO)</Baz>
+ </PropertyGroup>
+</Project>";
+ var reader = XmlReader.Create (new StringReader (xml));
+ var root = ProjectRootElement.Create (reader);
+ var proj = new Project (root);
+ root.FullPath = "ProjectTest.ExpandString.proj";
+ Assert.AreEqual ("xyz", proj.ExpandString ("x$(BAR)z"), "#1");
+ Assert.AreEqual ("x$(BARz", proj.ExpandString ("x$(BARz"), "#2"); // incomplete
+ Assert.AreEqual ("xz", proj.ExpandString ("x@(BAR)z"), "#3"); // not an item
+ }
+
+ [Test]
+ public void BuildCSharpTargetGetFrameworkPaths ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' />
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new Project (root);
+ root.FullPath = "ProjectTest.BuildCSharpTargetGetFrameworkPaths.proj";
+ Assert.IsTrue (proj.Build ("GetFrameworkPaths", new ILogger [] {/*new ConsoleLogger ()*/}));
+ }
+
+ [Test]
+ public void BuildCSharpTargetBuild ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <PropertyGroup>
+ <AssemblyName>Foo</AssemblyName>
+ </PropertyGroup>
+ <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' />
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ root.FullPath = "ProjectTest.BuildCSharpTargetBuild.proj";
+ var proj = new Project (root, null, "4.0");
+ Assert.IsFalse (proj.Build ("Build", new ILogger [] {/*new ConsoleLogger (LoggerVerbosity.Diagnostic)*/})); // missing mandatory properties
+ }
+
+ [Test]
+ public void EvaluateItemConditionThenIgnored ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <PropertyGroup>
+ <P></P>
+ </PropertyGroup>
+ <ItemGroup>
+ <Foo Condition='' Include='x' />
+ <Bar Include='$(P)' />
+ <Baz Include='z' />
+ </ItemGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new Project (root);
+ // note that Foo is ignored BUT Bar is NOT ignored.
+ Assert.AreEqual (2, proj.ItemsIgnoringCondition.Count, "#1");
+ Assert.IsNotNull ("Bar", proj.ItemsIgnoringCondition.First ().ItemType, "#2");
+ Assert.IsNotNull ("Baz", proj.ItemsIgnoringCondition.Last ().ItemType, "#3");
+ }
+
+ [Test]
+ public void EvaluateSamePropertiesInOrder ()
+ {
+ // used in Microsoft.Common.targets
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <PropertyGroup>
+ <BaseIntermediateOutputPath Condition=""'$(BaseIntermediateOutputPath)' == ''"">obj\</BaseIntermediateOutputPath>
+ </PropertyGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new Project (root);
+ Assert.AreEqual ("obj\\", proj.GetPropertyValue ("BaseIntermediateOutputPath"), "#1");
+ }
+
+ [Test]
+ public void DirtyMarking ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new Project (root);
+ Assert.IsFalse (proj.IsDirty, "#1");
+ proj.MarkDirty ();
+ Assert.IsTrue (proj.IsDirty, "#2");
+ }
+
+ [Test]
+ public void DirtyMarking2 ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new Project (root);
+ proj.DisableMarkDirty = true;
+ proj.MarkDirty ();
+ Assert.IsFalse (proj.IsDirty, "#1"); // not rejected, just ignored.
+ proj.DisableMarkDirty = false;
+ Assert.IsFalse (proj.IsDirty, "#2"); // not like status pending
+ proj.MarkDirty ();
+ Assert.IsTrue (proj.IsDirty, "#3");
+ }
+
+ [Test]
+ public void CreateProjectInstance ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <PropertyGroup>
+ <AssemblyName>Foo</AssemblyName>
+ </PropertyGroup>
+ <Import Project='$(MSBuildToolsPath)\Microsoft.CSharp.targets' />
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new Project (root, null, "4.0");
+ var inst = proj.CreateProjectInstance ();
+ Assert.AreEqual ("4.0", inst.ToolsVersion, "#1");
+ }
+ }
+}
+
--- /dev/null
+//
+// ResolvedImportTest.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using Microsoft.Build.Construction;
+using Microsoft.Build.Evaluation;
+using NUnit.Framework;
+using Microsoft.Build.Exceptions;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Execution;
+
+namespace MonoTests.Microsoft.Build.Evaluation
+{
+ [TestFixture]
+ public class ResolvedImportTest
+ {
+ const string temp_file_name = "test_imported.proj";
+
+ [Test]
+ public void SimpleImportAndSemanticValues ()
+ {
+ string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <Import Project='test_imported.proj' />
+</Project>";
+ string imported = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <PropertyGroup>
+ <A>x</A>
+ <B>y</B>
+ </PropertyGroup>
+ <ItemGroup>
+ <X Include=""included.txt"" />
+ </ItemGroup>
+</Project>";
+ using (var ts = File.CreateText (temp_file_name))
+ ts.Write (imported);
+ try {
+ var reader = XmlReader.Create (new StringReader (xml));
+ var root = ProjectRootElement.Create (reader);
+ Assert.AreEqual (temp_file_name, root.Imports.First ().Project, "#1");
+ var proj = new Project (root);
+ var prop = proj.GetProperty ("A");
+ Assert.IsNotNull (prop, "#2");
+ Assert.IsTrue (prop.IsImported, "#3");
+ var item = proj.GetItems ("X").FirstOrDefault ();
+ Assert.IsNotNull (item, "#4");
+ Assert.AreEqual ("included.txt", item.EvaluatedInclude, "#5");
+ } finally {
+ File.Delete (temp_file_name);
+ }
+ }
+
+ string import_overrides_test_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <PropertyGroup>
+ <A>X</A>
+ </PropertyGroup>
+ <Import Condition=""{0}"" Project='test_imported.proj' />
+ <PropertyGroup>
+ <B>Y</B>
+ </PropertyGroup>
+</Project>";
+ string import_overrides_test_imported = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <PropertyGroup>
+ <C Condition='$(A)==x'>c</C>
+ <A>a</A>
+ <B>b</B>
+ </PropertyGroup>
+ <ItemGroup>
+ <X Include=""included.txt"" />
+ </ItemGroup>
+</Project>";
+
+ void ImportAndPropertyOverrides (string label, string condition, string valueA, string valueB, string valueAPredecessor, bool existsC)
+ {
+ using (var ts = File.CreateText (temp_file_name))
+ ts.Write (import_overrides_test_imported);
+ try {
+ string xml = string.Format (import_overrides_test_xml, condition);
+ var reader = XmlReader.Create (new StringReader (xml));
+ var root = ProjectRootElement.Create (reader);
+ var proj = new Project (root);
+ var a = proj.GetProperty ("A");
+ Assert.IsNotNull (a, label + "#2");
+ Assert.AreEqual (valueA, a.EvaluatedValue, label + "#3");
+ if (valueAPredecessor == null)
+ Assert.IsNull (a.Predecessor, label + "#3.1");
+ else {
+ Assert.IsNotNull (a.Predecessor, label + "#3.2");
+ Assert.AreEqual (valueAPredecessor, a.Predecessor.EvaluatedValue, label + "#3.3");
+ }
+ var b = proj.GetProperty ("B");
+ Assert.IsNotNull (b, label + "#4");
+ Assert.AreEqual (valueB, b.EvaluatedValue, label + "#5");
+ var c = proj.GetProperty ("C"); // yes it can be retrieved.
+ if (existsC) {
+ Assert.IsNotNull (c, label + "#6");
+ Assert.AreEqual ("c", c.EvaluatedValue, label + "#7");
+ }
+ else
+ Assert.IsNull (c, label + "#8");
+ } finally {
+ File.Delete (temp_file_name);
+ }
+ }
+
+ [Test]
+ public void ImportAndPropertyOverrides ()
+ {
+ ImportAndPropertyOverrides ("[1]", "'True'", "a", "Y", "X", true);
+ ImportAndPropertyOverrides ("[2]", "$(A)=='X'", "a", "Y", "X", true); // evaluated as true
+ ImportAndPropertyOverrides ("[3]", "$(B)=='Y'", "X", "Y", null, false); // evaluated as false
+ ImportAndPropertyOverrides ("[4]", "$(B)=='b'", "X", "Y", null, false); // of course not evaluated with imported value
+ }
+
+ // FIXME:
+ // Looks like $(MSBuildThisFile) is available only within property value, not via .NET MSBuild API.
+ // Right now our variable is added as a Reserved property, but we will have to hide it.
+ //
+ [Test]
+ public void EvaluateMSBuildThisFileProperty ()
+ {
+ string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <PropertyGroup>
+ <A>$(MSBuildThisFile)</A>
+ </PropertyGroup>
+ <Import Project='test_imported.proj' />
+</Project>";
+ string imported = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <PropertyGroup>
+ <B>$(MSBuildThisFile)</B>
+ </PropertyGroup>
+</Project>";
+ using (var ts = File.CreateText (temp_file_name))
+ ts.Write (imported);
+ try {
+ var reader = XmlReader.Create (new StringReader (xml));
+ var root = ProjectRootElement.Create (reader);
+ var proj = new Project (root);
+ var a = proj.GetProperty ("A");
+ Assert.AreEqual (string.Empty, a.EvaluatedValue, "#1");
+ var b = proj.GetProperty ("B");
+ Assert.AreEqual (temp_file_name, b.EvaluatedValue, "#2");
+
+ var pi = new ProjectInstance (root);
+ var ai = pi.GetProperty ("A");
+ Assert.AreEqual (string.Empty, ai.EvaluatedValue, "#3");
+ var bi = pi.GetProperty ("B");
+ Assert.AreEqual (temp_file_name, bi.EvaluatedValue, "#4");
+ } finally {
+ File.Delete (temp_file_name);
+ }
+ }
+ }
+}
+
--- /dev/null
+//
+// ToolSetTest.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using Microsoft.Build.Evaluation;
+using NUnit.Framework;
+
+namespace MonoTests.Microsoft.Build.Evaluation
+{
+ [TestFixture]
+ public class ToolsetTest
+ {
+ [Test]
+ public void Constructor ()
+ {
+ var ts = new Toolset ("4.3", "c:\\", ProjectCollection.GlobalProjectCollection, null);
+ Assert.IsNotNull (ts.Properties, "#1");
+ Assert.AreEqual (0, ts.Properties.Count, "#2");
+#if NET_4_5
+ Assert.IsNull (ts.DefaultSubToolsetVersion, "#3");
+ Assert.IsNotNull (ts.SubToolsets, "#4");
+ Assert.AreEqual (0, ts.SubToolsets.Count, "#5");
+#endif
+ Assert.AreEqual ("c:\\", ts.ToolsPath, "#6");
+ Assert.AreEqual ("4.3", ts.ToolsVersion, "#7");
+ }
+ }
+}
+
--- /dev/null
+//
+// BuildManagerTest.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.IO;
+using System.Xml;
+using Microsoft.Build.Construction;
+using Microsoft.Build.Evaluation;
+using Microsoft.Build.Execution;
+using NUnit.Framework;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Logging;
+
+namespace MonoTests.Microsoft.Build.Execution
+{
+ [TestFixture]
+ public class BuildManagerTest
+ {
+ Project GetDummyProject ()
+ {
+ string empty_project_xml = "<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+ var path = "file://localhost/foo.xml";
+ var xml = XmlReader.Create (new StringReader (empty_project_xml), null, path);
+ var root = ProjectRootElement.Create (xml);
+ return new Project (root);
+ }
+
+ [Test]
+ [ExpectedException (typeof (ArgumentNullException))]
+ public void GetProjectInstanceForBuildNullFullPath ()
+ {
+ var manager = new BuildManager ();
+ manager.GetProjectInstanceForBuild (GetDummyProject ());
+ }
+
+ [Test]
+ [ExpectedException (typeof (ArgumentException))]
+ public void GetProjectInstanceForBuildEmptyFullPath ()
+ {
+ var proj = GetDummyProject ();
+ proj.FullPath = "";
+ var manager = new BuildManager ();
+ manager.GetProjectInstanceForBuild (proj);
+ }
+
+ [Test]
+ public void GetProjectInstanceForBuild ()
+ {
+ string empty_project_xml = "<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+ var path = "file://localhost/foo.xml";
+ var xml = XmlReader.Create (new StringReader(empty_project_xml), null, path);
+ var root = ProjectRootElement.Create (xml);
+ root.FullPath = path;
+ var proj = new Project (root);
+ var manager = new BuildManager ();
+ var inst = manager.GetProjectInstanceForBuild (proj);
+ Assert.AreEqual (inst, manager.GetProjectInstanceForBuild (proj), "#1");
+ }
+
+ [Test]
+ [ExpectedException (typeof (InvalidOperationException))]
+ public void PendBuildRequestBeforeBeginBuild ()
+ {
+ string empty_project_xml = "<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+ var path = "file://localhost/foo.xml";
+ var xml = XmlReader.Create (new StringReader (empty_project_xml), null, path);
+ var root = ProjectRootElement.Create (xml);
+ var proj = new ProjectInstance (root);
+ new BuildManager ().PendBuildRequest (new BuildRequestData (proj, new string [0]));
+ }
+
+ [Test]
+ [ExpectedException (typeof (InvalidOperationException))]
+ public void ResetCachesDuringBuildIsInvalid ()
+ {
+ // Windows does not have useful sleep or alternative, so skip it
+ bool is_windows = true;
+ switch (Environment.OSVersion.Platform) {
+ case PlatformID.Unix:
+ case PlatformID.MacOSX:
+ is_windows = false;
+ break;
+ }
+ string project_xml = string.Format (@"<Project DefaultTargets='Wait1Sec' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <Target Name='Wait1Sec'>
+ <Exec Command='{0}' />
+ </Target>
+</Project>", is_windows ? "powershell -command \"Start-Sleep -s 1\"" : "/bin/sleep 1");
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new ProjectInstance (root);
+ var bm = new BuildManager ();
+ bm.BeginBuild (new BuildParameters ());
+ var sub = bm.PendBuildRequest (new BuildRequestData (proj, new string [] { "Wait1Sec" }));
+ sub.ExecuteAsync (delegate {}, null);
+ try {
+ bm.ResetCaches ();
+ } finally {
+ bm.EndBuild (); // yes, it should work even after invalid ResetCaches call... at least on .NET it does.
+ }
+ }
+
+ [Test]
+ public void BasicManualParallelBuilds ()
+ {
+ string project_xml = @"<Project DefaultTargets='Wait1Sec' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <Target Name='Wait1Sec'>
+ <!-- Exec Command='ping 10.1.1.1 -n 1 -w 1' /-->
+ <Exec Command='/bin/sleep 1' />
+ </Target>
+</Project>";
+ switch (Environment.OSVersion.Platform) {
+ case PlatformID.MacOSX:
+ case PlatformID.Unix:
+ break;
+ default:
+ return; // ignore, cannot run it
+ }
+
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new ProjectInstance (root);
+ var bm = new BuildManager ();
+ bm.BeginBuild (new BuildParameters () { Loggers = new ILogger [] {new ConsoleLogger (LoggerVerbosity.Diagnostic, TextWriter.Null.WriteLine, null, null)} });
+ DateTime waitDone = DateTime.MinValue;
+ DateTime beforeExec = DateTime.Now;
+ var l = new List<BuildSubmission> ();
+ for (int i = 0; i < 10; i++) {
+ var sub = bm.PendBuildRequest (new BuildRequestData (proj, new string [] { "Wait1Sec" }));
+ l.Add (sub);
+ sub.ExecuteAsync (delegate { waitDone = DateTime.Now; }, null);
+ }
+ bm.EndBuild ();
+ Assert.IsTrue (l.All (s => s.BuildResult.OverallResult == BuildResultCode.Success), "#1");
+ DateTime endBuildDone = DateTime.Now;
+ Assert.IsTrue (endBuildDone - beforeExec >= TimeSpan.FromSeconds (1), "#2");
+ Assert.IsTrue (endBuildDone > waitDone, "#3");
+ }
+
+ [Test]
+ public void BuildCommonResolveAssemblyReferences ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <Import Project='$(MSBuildToolsPath)\Microsoft.Common.targets' />
+ <ItemGroup>
+ <Reference Include='System.Core' />
+ <Reference Include='System.Xml' />
+ </ItemGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ root.FullPath = "BuildManagerTest.BuildCommonResolveAssemblyReferences.proj";
+ var proj = new ProjectInstance (root);
+ var manager = new BuildManager ();
+ var parameters = new BuildParameters () { Loggers = new ILogger [] {new ConsoleLogger (LoggerVerbosity.Diagnostic)} };
+ var request = new BuildRequestData (proj, new string [] {"ResolveAssemblyReferences"});
+ Assert.AreEqual (string.Empty, proj.GetPropertyValue ("TargetFrameworkDirectory"), "#1-1");
+ var result = manager.Build (parameters, request);
+ Assert.AreNotEqual (string.Empty, proj.GetPropertyValue ("TargetFrameworkDirectory"), "#1-2"); // filled during build.
+ Assert.IsTrue (result.ResultsByTarget.ContainsKey ("GetFrameworkPaths"), "#2-1");
+ Assert.IsTrue (result.ResultsByTarget.ContainsKey ("PrepareForBuild"), "#2-2");
+ Assert.IsTrue (result.ResultsByTarget.ContainsKey ("ResolveAssemblyReferences"), "#2-3");
+ var items = proj.GetItems ("ReferencePath");
+ Assert.AreEqual (2, items.Count (), "#3");
+ var syscore = items.FirstOrDefault (i => Path.GetFileName (i.EvaluatedInclude) == "System.Core.dll");
+ var sysxml = items.FirstOrDefault (i => Path.GetFileName (i.EvaluatedInclude) == "System.Xml.dll");
+ Assert.IsNotNull (syscore, "#4-1");
+ Assert.IsNotNull (sysxml, "#4-2");
+ Assert.IsTrue (File.Exists (syscore.EvaluatedInclude), "#5-1");
+ Assert.IsTrue (File.Exists (sysxml.EvaluatedInclude), "#5-1");
+ Assert.AreEqual (BuildResultCode.Success, result.OverallResult, "#6");
+ }
+ }
+}
+
--- /dev/null
+//
+// BuildParametersTest.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using Microsoft.Build.Evaluation;
+using Microsoft.Build.Execution;
+using NUnit.Framework;
+
+namespace MonoTests.Microsoft.Build.Execution
+{
+ [TestFixture]
+ public class BuildParametersTest
+ {
+ [Test]
+ public void GetToolset ()
+ {
+ var bp = new BuildParameters (ProjectCollection.GlobalProjectCollection);
+ Assert.IsNull (bp.GetToolset ("0.1"), "#1");
+ var ts = bp.GetToolset ("2.0");
+ // They are equal
+ Assert.AreEqual (ProjectCollection.GlobalProjectCollection.Toolsets.First (t => t.ToolsVersion == "2.0"), ts, "#2");
+
+ bp = new BuildParameters ();
+ Assert.IsNull (bp.GetToolset ("0.1"), "#1");
+ ts = bp.GetToolset ("2.0");
+ // They are NOT equal, because ProjectCollection seems to be different.
+ Assert.AreNotEqual (ProjectCollection.GlobalProjectCollection.Toolsets.First (t => t.ToolsVersion == "2.0"), ts, "#2");
+ }
+
+ [Test]
+ public void PropertiesDefault ()
+ {
+ var bp = new BuildParameters ();
+ Assert.IsTrue (bp.EnableNodeReuse, "#1");
+ Assert.IsTrue (bp.EnvironmentProperties.Count > 0, "#2");
+ Assert.AreEqual (CultureInfo.CurrentCulture, bp.Culture, "#3");
+ }
+ }
+}
--- /dev/null
+//
+// BuildSubmissionTest.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using Microsoft.Build.Construction;
+using Microsoft.Build.Evaluation;
+using Microsoft.Build.Execution;
+using NUnit.Framework;
+using Microsoft.Build.Logging;
+using Microsoft.Build.Framework;
+using System.Collections.Generic;
+
+namespace MonoTests.Microsoft.Build.Execution
+{
+ [TestFixture]
+ public class BuildSubmissionTest
+ {
+ [Test]
+ public void ResultBeforeExecute ()
+ {
+ string empty_project_xml = "<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+ var path = "file://localhost/foo.xml";
+ var xml = XmlReader.Create (new StringReader (empty_project_xml), null, path);
+ var root = ProjectRootElement.Create (xml);
+ var proj = new ProjectInstance (root);
+ var bm = new BuildManager ();
+ bm.BeginBuild (new BuildParameters ());
+ var sub = bm.PendBuildRequest (new BuildRequestData (proj, new string [0]));
+ Assert.IsNull (sub.BuildResult, "#1");
+ }
+
+ // This checks if the build output for each task is written to the loggers and not directly thrown as a Project loader error.
+ [Test]
+ public void TaskOutputsToLoggers ()
+ {
+ string project_xml = @"<Project DefaultTargets='Foo' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <Import Project='$(MSBuildToolsPath)\Microsoft.Common.targets' />
+ <Target Name='Foo'>
+ <ItemGroup>
+ <Foo Condition='$(X)' Include='foo.txt' />
+ </ItemGroup>
+ </Target>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ root.FullPath = "BuildSubmissionTest.TaskOutputsToLoggers.proj";
+ var proj = new ProjectInstance (root);
+ Assert.AreEqual ("$(X)", root.Targets.First ().ItemGroups.First ().Items.First ().Condition, "#0");
+ var sw = new StringWriter ();
+ Assert.IsFalse (proj.Build (new ILogger [] {new ConsoleLogger (LoggerVerbosity.Diagnostic, sw.WriteLine, null, null)}), "#1");
+ Assert.IsTrue (sw.ToString ().Contains ("$(X)"), "#2");
+ }
+
+ [Test]
+ public void EndBuildWaitsForSubmissionCompletion ()
+ {
+ // Windows does not have useful sleep or alternative, so skip it
+ bool is_windows = true;
+ switch (Environment.OSVersion.Platform) {
+ case PlatformID.Unix:
+ case PlatformID.MacOSX:
+ is_windows = false;
+ break;
+ }
+ string project_xml = string.Format (@"<Project DefaultTargets='Wait1Sec' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <Target Name='Wait1Sec'>
+ <Exec Command='{0}' />
+ </Target>
+</Project>", is_windows ? "powershell -command \"Start-Sleep -s 1\"" : "/bin/sleep 1");
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ root.FullPath = "BuildSubmissionTest.EndBuildWaitsForSubmissionCompletion.proj";
+ var proj = new ProjectInstance (root);
+ var bm = new BuildManager ();
+ bm.BeginBuild (new BuildParameters ());
+ DateTime waitDone = DateTime.MinValue;
+ DateTime beforeExec = DateTime.Now;
+ var sub = bm.PendBuildRequest (new BuildRequestData (proj, new string [] { "Wait1Sec" }));
+ sub.ExecuteAsync (delegate { waitDone = DateTime.Now; }, null);
+ bm.EndBuild ();
+ Assert.IsTrue (sub.BuildResult.OverallResult == BuildResultCode.Success, "#1");
+ DateTime endBuildDone = DateTime.Now;
+ Assert.IsTrue (endBuildDone - beforeExec >= TimeSpan.FromSeconds (1), "#2");
+ Assert.IsTrue (endBuildDone > waitDone, "#3");
+ }
+ }
+}
+
--- /dev/null
+//
+// ProjectInstanceTest.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using Microsoft.Build.Construction;
+using Microsoft.Build.Execution;
+using NUnit.Framework;
+using Microsoft.Build.Evaluation;
+
+namespace MonoTests.Microsoft.Build.Execution
+{
+ [TestFixture]
+ public class ProjectInstanceTest
+ {
+ [Test]
+ public void ItemsAndProperties ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <ItemGroup>
+ <X Condition='false' Include='bar.txt' />
+ <X Include='foo.txt'>
+ <M>m</M>
+ <N>=</N>
+ </X>
+ </ItemGroup>
+ <PropertyGroup>
+ <P Condition='false'>void</P>
+ <P Condition='true'>valid</P>
+ </PropertyGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader(project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new ProjectInstance (root);
+ var item = proj.Items.First ();
+ Assert.AreEqual ("foo.txt", item.EvaluatedInclude, "#1");
+ var prop = proj.Properties.First (p => p.Name=="P");
+ Assert.AreEqual ("valid", prop.EvaluatedValue, "#2");
+ Assert.IsNotNull (proj.GetProperty ("MSBuildProjectDirectory"), "#3");
+ Assert.AreEqual ("2.0", proj.ToolsVersion, "#4");
+ }
+
+ [Test]
+ public void ExplicitToolsVersion ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+ var xml = XmlReader.Create (new StringReader(project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new ProjectInstance (root, null, "4.0", new ProjectCollection ());
+ Assert.AreEqual ("4.0", proj.ToolsVersion, "#1");
+ }
+
+ [Test]
+ public void BuildEmptyProject ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' />";
+ var xml = XmlReader.Create (new StringReader (project_xml), null, "file://localhost/foo.xml");
+ var root = ProjectRootElement.Create (xml);
+ // This seems to do nothing and still returns true
+ root.FullPath = "ProjectInstanceTest.BuildEmptyProject.1.proj";
+ Assert.IsTrue (new ProjectInstance (root).Build (), "#1");
+ // This seems to fail to find the appropriate target
+ root.FullPath = "ProjectInstanceTest.BuildEmptyProject.2.proj";
+ Assert.IsFalse (new ProjectInstance (root).Build ("Build", null), "#2");
+ // Thus, this tries to build all the targets (empty) and no one failed, so returns true(!)
+ root.FullPath = "ProjectInstanceTest.BuildEmptyProject.3.proj";
+ Assert.IsTrue (new ProjectInstance (root).Build (new string [0], null), "#3");
+ // Actially null "targets" is accepted and returns true(!!)
+ root.FullPath = "ProjectInstanceTest.BuildEmptyProject.4.proj";
+ Assert.IsTrue (new ProjectInstance (root).Build ((string []) null, null), "#4");
+ // matching seems to be blindly done, null string also results in true(!!)
+ root.FullPath = "ProjectInstanceTest.BuildEmptyProject.5.proj";
+ Assert.IsTrue (new ProjectInstance (root).Build ((string) null, null), "#5");
+ }
+ }
+}
+
--- /dev/null
+//
+// ProjectMetadataInstanceTest.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using Microsoft.Build.Construction;
+using Microsoft.Build.Execution;
+using NUnit.Framework;
+
+namespace MonoTests.Microsoft.Build.Execution
+{
+ [TestFixture]
+ public class ProjectMetadataInstanceTest
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <ItemGroup>
+ <X Include='foo.txt'>
+ <M>m</M>
+ <N>=</N>
+ </X>
+ </ItemGroup>
+</Project>";
+
+ [Test]
+ public void PropertiesCopiesValues ()
+ {
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ string path = Path.GetFullPath ("foo.xml");
+ var root = ProjectRootElement.Create (xml);
+ var proj = new ProjectInstance (root);
+ var item = proj.Items.First ();
+ var md = item.Metadata.First ();
+ Assert.AreEqual ("m", item.Metadata.First ().EvaluatedValue, "#1");
+ Assert.AreEqual ("m", root.ItemGroups.First ().Items.First ().Metadata.First ().Value, "#2");
+ root.ItemGroups.First ().Items.First ().Metadata.First ().Value = "X";
+ Assert.AreEqual ("m", item.Metadata.First ().EvaluatedValue, "#3");
+ }
+
+ [Test]
+ public void ToStringOverride ()
+ {
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ string path = Path.GetFullPath ("foo.xml");
+ var root = ProjectRootElement.Create (xml);
+ var proj = new ProjectInstance (root);
+ var item = proj.Items.First ();
+ Assert.AreEqual ("M=m", item.Metadata.First ().ToString (), "#1");
+ Assert.AreEqual ("N==", item.Metadata.Last ().ToString (), "#2"); // haha
+ }
+ }
+}
+
--- /dev/null
+//
+// ProjectTargetInstanceTest.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using Microsoft.Build.Construction;
+using Microsoft.Build.Execution;
+using NUnit.Framework;
+using Microsoft.Build.Logging;
+using Microsoft.Build.Framework;
+
+namespace MonoTests.Microsoft.Build.Execution
+{
+ [TestFixture]
+ public class ProjectTargetInstanceTest
+ {
+ [Test]
+ public void DefaultTargetsEmpty ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new ProjectInstance (root);
+ Assert.AreEqual (new string [0], proj.DefaultTargets, "#1");
+ }
+
+ [Test]
+ public void DefaultTargetsFromAttribute ()
+ {
+ string project_xml = @"<Project DefaultTargets='Foo Bar Baz;Foo' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new ProjectInstance (root);
+ string [] expected = {"Foo Bar Baz", "Foo"};
+ Assert.AreEqual (expected, proj.DefaultTargets, "#1");
+ }
+
+ [Test]
+ public void DefaultTargetsFromElements ()
+ {
+ string [] defaultTargetAtts = {string.Empty, "DefaultTargets=''"};
+
+ for (int i = 0; i < defaultTargetAtts.Length; i++) {
+ string project_xml = string.Format (@"<Project {0} xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <Target Name='Foo' />
+ <Target Name='Bar' />
+</Project>", defaultTargetAtts [i]);
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new ProjectInstance (root);
+ string [] expected = {"Foo"}; // Bar is not included
+ Assert.AreEqual (expected, proj.DefaultTargets, "#1-" + i);
+ }
+ }
+
+ [Test]
+ public void MicrosoftCommonTargets ()
+ {
+ string [] defaultTargetAtts = { string.Empty, "DefaultTargets=''" };
+
+ for (int i = 0; i < defaultTargetAtts.Length; i++) {
+ string project_xml = string.Format (@"<Project {0} xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <Import Project='$(MSBuildToolsPath)\Microsoft.Common.targets' />
+</Project>", defaultTargetAtts [i]);
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new ProjectInstance (root);
+ Assert.AreEqual ("Build", proj.DefaultTargets.FirstOrDefault (), "#1-" + i);
+ }
+ }
+
+ [Test]
+ public void DefaultTargetsOverride ()
+ {
+ string project_xml = @"<Project DefaultTargets='Foo' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <Import Project='$(MSBuildToolsPath)\Microsoft.Common.targets' />
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new ProjectInstance (root);
+ Assert.AreEqual ("Foo", proj.DefaultTargets.FirstOrDefault (), "#1");
+ }
+
+ [Test]
+ public void MultipleDefaultTargets ()
+ {
+ bool[] expected = { true, false, true };
+ string [] defaultTargets = {"Foo", "Foo;Bar", "Foo;Bar"};
+ string [] targets = { string.Empty, string.Empty, "<Target Name='Bar' />" };
+ for (int i = 0; i < expected.Length; i++) {
+ string project_xml = string.Format (@"<Project DefaultTargets='{0}' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <Import Project='$(MSBuildToolsPath)\Microsoft.Common.targets' />
+ <Target Name='Foo' />
+ {1}
+</Project>", defaultTargets [i], targets [i]);
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ root.FullPath = string.Format ("ProjectInstanceTest.MultipleDefaultTargets.{0}.proj", i);
+ var proj = new ProjectInstance (root);
+ Assert.AreEqual ("Foo", proj.DefaultTargets.FirstOrDefault (), "#1-" + i);
+ Assert.AreEqual (expected [i], proj.Build (), "#2-" + i);
+ }
+ }
+
+ [Test]
+ public void DependsOnTargets ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <Target Name='Bar' DependsOnTargets='Foo' />
+ <Target Name='Foo'>
+ <Error Text='expected error' />
+ </Target>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ root.FullPath = "ProjectInstanceTest.DependsOnTargets.proj";
+ var proj = new ProjectInstance (root);
+ Assert.AreEqual (2, proj.Targets.Count, "#1");
+ Assert.IsFalse (proj.Build ("Bar", new ILogger [0]), "#2");
+ }
+
+ [Test]
+ public void InputsAndOutputs ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <Target Name='Foo' Inputs='inputsandoutputstest.txt' Outputs='inputsandoutputstest.txt'>
+ <Error Text='error' />
+ </Target>
+</Project>";
+ try {
+ if (!File.Exists ("inputsandoutputstest.txt"))
+ File.CreateText ("inputsandoutputstest.txt").Close ();
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ root.FullPath = "ProjectTargetInstanceTest.InputsAndOutputs.proj";
+ var proj = new ProjectInstance (root);
+ Assert.IsTrue (proj.Build (), "#1"); // if it does not skip Foo, it results in an error.
+ } finally {
+ if (File.Exists ("inputsandoutputstest.txt"))
+ File.Delete ("inputsandoutputstest.txt");
+ }
+ }
+ }
+}
--- /dev/null
+//
+// ExpressionParserTest.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using System.IO;
+using System.Linq;
+using System.Xml;
+using Microsoft.Build.Construction;
+using Microsoft.Build.Evaluation;
+using NUnit.Framework;
+using Microsoft.Build.Execution;
+using Microsoft.Build.Exceptions;
+using System.Collections.Generic;
+
+namespace MonoTests.Microsoft.Build.Internal
+{
+ [TestFixture]
+ public class ExpressionParserTest
+ {
+ string [] invalid_always = {
+ "$(Foo..Bar)",
+ "$([DateTime.Now])", // fullname required
+ "$([System.DateTime.Now])", // member cannot be invoked with '.'
+ };
+ string [] invalid_as_boolean = {
+ "$",
+ "@",
+ "%",
+ "%-1",
+ "$(",
+ "%(",
+ "$)",
+ "%)",
+ "%24",
+ "()",
+ "{}",
+ "A", // must be evaluated as a boolean
+ "1", // ditto (no default conversion to bool)
+ "$ (foo) == ''",
+ "@ (foo) == ''",
+ "$(1)",
+ "$(Foo) == And", // reserved keyword 'and'
+ "$(Foo) == Or", // reserved keyword 'or'
+ "$(Foo) == $(Bar) == $(Baz)", // unexpected '=='
+ "$([System.DateTime]::Now)", // it is DateTime
+ "$([System.String]::Format('Tr'))$([System.String]::Format('ue'))", // only one expression is accepted
+ "$([System.String]::Format(null))", // causing ANE, wrapped by InvalidProjectFileException
+ "yep",
+ "nope",
+ "ONN",
+ "OFFF",
+ };
+ string [] valid = {
+ "'%24' == 0",
+ "true",
+ "fAlSe",
+ "(false)",
+ "A==A",
+ "A ==A",
+ "A== A",
+ "A=='A'",
+ "A==\tA",
+ "\tA== A",
+ "$([System.String]::Format('True'))",
+ "$([System.String]::Format('True', null))",
+ "False And True == True And True",
+ "True or True or False",
+ "(True or True or False)",
+ "True and False",
+ "(True) and (False)",
+ "yes",
+ "nO",
+ "oN",
+ "oFf",
+ };
+ string [] depends = {
+ // valid only if evaluated to boolean
+ "$(foo)",
+ "@(foo)",
+ };
+
+ [Test]
+ public void EvaluateAsBoolean ()
+ {
+ foreach (var expr in invalid_always.Concat (invalid_as_boolean).Concat (valid)) {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <ItemGroup>
+ <Foo Condition=""{0}"" Include='x' />
+ </ItemGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (string.Format (project_xml, expr)));
+ var root = ProjectRootElement.Create (xml);
+ try {
+ new Project (root);
+ if (invalid_as_boolean.Contains (expr) || invalid_always.Contains (expr))
+ Assert.Fail ("Parsing Condition '{0}' should fail", expr);
+ } catch (Exception ex) {
+ if (valid.Contains (expr))
+ throw new Exception (string.Format ("failed to parse '{0}'", expr), ex);
+ else if (ex is InvalidProjectFileException)
+ continue;
+ throw new Exception (string.Format ("unexpected exception to parse '{0}'", expr), ex);
+ }
+ }
+ }
+
+ [Test]
+ public void EvaluateAsString ()
+ {
+ foreach (var expr in invalid_always.Concat (invalid_as_boolean).Concat (valid)) {
+ try {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <ItemGroup>
+ <Foo Include=""{0}"" />
+ </ItemGroup>
+ </Project>";
+ var xml = XmlReader.Create (new StringReader (string.Format (project_xml, expr)));
+ var root = ProjectRootElement.Create (xml);
+ // everything but 'invalid_always' should pass
+ new Project (root);
+ } catch (Exception ex) {
+ if (!invalid_always.Contains (expr))
+ throw new Exception (string.Format ("failed to parse '{0}'", expr), ex);
+ }
+ }
+ }
+
+ [Test]
+ public void EvaluatePropertyReferencesWithProperties ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <ItemGroup>
+ <Foo Condition=""$(foo)"" Include='x' />
+ </ItemGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var props = new Dictionary<string,string> ();
+ props ["foo"] = "true";
+ new Project (root, props, null);
+ }
+
+ [Test]
+ public void EvaluateItemReferences ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <ItemGroup>
+ <Foo Include='false' />
+ <!-- by the time Bar is evaluated, Foo is already evaluated and taken into consideration in expansion -->
+ <Bar Condition=""@(foo)"" Include='x' />
+ </ItemGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ new Project (root);
+ }
+
+ [Test]
+ public void EvaluateReferencesWithoutProperties ()
+ {
+ foreach (var expr in depends) {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <ItemGroup>
+ <Foo Condition=""{0}"" Include='x' />
+ </ItemGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (string.Format (project_xml, expr)));
+ var root = ProjectRootElement.Create (xml);
+ try {
+ new Project (root);
+ Assert.Fail ("Parsing Condition '{0}' should fail", expr);
+ } catch (InvalidProjectFileException) {
+ continue;
+ }
+ }
+ }
+
+ [Test]
+ public void SemicolonHandling ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <PropertyGroup>
+ <Foo Condition=""'A;B'=='A;B'"">'A;B'</Foo>
+ </PropertyGroup>
+ <ItemGroup>
+ <Bar Include='$(Foo)' />
+ </ItemGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new Project (root); // at this state property is parsed without error i.e. Condition evaluates fine.
+ var prop = proj.GetProperty ("Foo");
+ Assert.AreEqual ("'A;B'", prop.EvaluatedValue, "#1");
+ var items = proj.GetItems ("Bar");
+ Assert.AreEqual ("'A", items.First ().EvaluatedInclude, "#2");
+ Assert.AreEqual ("$(Foo)", items.First ().UnevaluatedInclude, "#3");
+ Assert.AreEqual (2, items.Count, "#4");
+ Assert.AreEqual ("B'", items.Last ().EvaluatedInclude, "#5");
+ Assert.AreEqual ("$(Foo)", items.Last ().UnevaluatedInclude, "#6");
+ Assert.IsTrue (items.First ().Xml == items.Last ().Xml, "#7");
+ }
+
+ // the same as above except that ItemGroup goes first (and yet evaluated the same).
+ [Test]
+ public void EvaluationOrderPropertiesPrecedesItems ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <ItemGroup>
+ <Bar Include='$(Foo)' />
+ </ItemGroup>
+ <PropertyGroup>
+ <Foo Condition=""'A;B'=='A;B'"">'A;B'</Foo>
+ </PropertyGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ var proj = new Project (root); // at this state property is parsed without error i.e. Condition evaluates fine.
+ var prop = proj.GetProperty ("Foo");
+ Assert.AreEqual ("'A;B'", prop.EvaluatedValue, "#1");
+ var items = proj.GetItems ("Bar");
+ Assert.AreEqual ("'A", items.First ().EvaluatedInclude, "#2");
+ Assert.AreEqual ("$(Foo)", items.First ().UnevaluatedInclude, "#3");
+ Assert.AreEqual (2, items.Count, "#4");
+ Assert.AreEqual ("B'", items.Last ().EvaluatedInclude, "#5");
+ Assert.AreEqual ("$(Foo)", items.Last ().UnevaluatedInclude, "#6");
+ Assert.IsTrue (items.First ().Xml == items.Last ().Xml, "#7");
+ }
+
+ [Test]
+ [ExpectedException (typeof (InvalidProjectFileException))]
+ public void PropertyReferencesItem ()
+ {
+ string project_xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <ItemGroup>
+ <Bar Include='True' />
+ </ItemGroup>
+ <PropertyGroup>
+ <Foo Condition='@(Bar)'>X</Foo><!-- not allowed -->
+ </PropertyGroup>
+</Project>";
+ var xml = XmlReader.Create (new StringReader (project_xml));
+ var root = ProjectRootElement.Create (xml);
+ new Project (root);
+ }
+
+ [Test]
+ [ExpectedException (typeof (InvalidProjectFileException))]
+ public void SequentialPropertyReferenceNotAllowed ()
+ {
+ string xml = @"<Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
+ <PropertyGroup>
+ <A>x</A>
+ <B>y</B>
+ <C Condition=""$(A)$(B)==''"">z</C>
+ </PropertyGroup>
+</Project>";
+ var reader = XmlReader.Create (new StringReader (xml));
+ var root = ProjectRootElement.Create (reader);
+ new Project (root);
+ }
+ }
+}
+
+//
+// ConsoleLoggerTest.cs
+//
+// Author:
+// Atsushi Enomoto (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
using System;
using System.IO;
[TestFixture]
public class ConsoleLoggerTest
{
+ // Unfortunately, the existing code in MS.Build.Engine.dll has slightly different
+ // format. We'd rather use already complete implementation, just disabled this test.
[Test]
+ [Category ("NotWorking")]
public void BasicLoggerUsage ()
{
string expected = @"file : cat error code: msg
--- /dev/null
+//
+// LoggerDescriptionTest.cs
+//
+// Author:
+// Atsushi Eno (atsushi@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+using System;
+using Microsoft.Build.Logging;
+using Microsoft.Build.Framework;
+using NUnit.Framework;
+
+namespace MonoTests.Microsoft.Build.Logging
+{
+ [TestFixture]
+ public class LoggerDescriptionTest
+ {
+ [Test]
+ public void CreateLogger ()
+ {
+ new LoggerDescription ("Microsoft.Build.Logging.ConsoleLogger",
+ typeof (ConsoleLogger).Assembly.FullName,
+ null,
+ null,
+ LoggerVerbosity.Normal)
+ .CreateLogger();
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<FileList Name=".NET Framework 2.0" TargetFrameworkDirectory="..\..\..\..\..\lib\net_2_0">
+</FileList>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<FileList Name=".NET Framework 3.5" TargetFrameworkDirectory="..\..\..\..\..\lib\net_2_0" IncludeFramework="v3.0">
+</FileList>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<FileList Name=".NET Framework 4" TargetFrameworkDirectory="..\..\..\..\..\lib\net_4_0">
+</FileList>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<FileList Name=".NET Framework 4.5" TargetFrameworkDirectory="..\..\..\..\..\lib\net_4_5">
+</FileList>
Assert.AreEqual ("1+", sres, "The result should have been the input string, since we have a partial input");
}
+ [Test]
+ public void GotoWithUnreachableStatement ()
+ {
+ Evaluator.Run ("using System;");
+
+ string code = "var x = new Action(() => {" +
+ "Console.WriteLine(\"beforeGoto\");" +
+ "goto L;" +
+ "L:" +
+ "Console.WriteLine(\"afterGoto\");" +
+ "});";
+
+ Assert.IsTrue (Evaluator.Run (code), "#1");
+ Assert.IsTrue (Evaluator.Run ("x();"), "#2");
+ }
+
#if NET_4_0
[Test]
public void DynamicStatement ()
#if !PLATFORM_COMPACTFRAMEWORK
[assembly: AllowPartiallyTrustedCallers]
[assembly: ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ #if NET_4_0
+ [assembly: SecurityRules(SecurityRuleSet.Level1)]
+ #else
+ [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
+ #endif
#endif
// Version information for an assembly consists of the following four values:
public long catch_type_id;
}
+ [Flags]
enum ExceptionClauseFlags {
None = 0x0,
Filter = 0x1,
VALUE_TYPE_ID_TYPE = 0xf1
}
+ [Flags]
enum InvokeFlags {
NONE = 0x0,
DISABLE_BREAKPOINTS = 0x1,
UNKNOWN = 4
}
+ [Flags]
enum StackFrameFlags {
NONE = 0,
DEBUGGER_INVOKE = 1,
get; set;
}
+ public int ExitCode {
+ get; set;
+ }
+
public EventInfo (EventType type, int req_id) {
EventType = type;
ReqId = req_id;
* with newer runtimes, and vice versa.
*/
internal const int MAJOR_VERSION = 2;
- internal const int MINOR_VERSION = 25;
+ internal const int MINOR_VERSION = 27;
enum WPSuspendPolicy {
NONE = 0,
IS_INITIALIZED = 18
}
+ [Flags]
enum BindingFlagsExtensions {
BINDING_FLAGS_IGNORE_CASE = 0x70000000,
}
EventType etype = (EventType)kind;
+ long thread_id = r.ReadId ();
if (kind == EventKind.VM_START) {
- long thread_id = r.ReadId ();
events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id };
//EventHandler.VMStart (req_id, thread_id, null);
} else if (kind == EventKind.VM_DEATH) {
+ int exit_code = 0;
+ if (Version.AtLeast (2, 27))
+ exit_code = r.ReadInt ();
//EventHandler.VMDeath (req_id, 0, null);
- events [i] = new EventInfo (etype, req_id) { };
+ events [i] = new EventInfo (etype, req_id) { ExitCode = exit_code };
} else if (kind == EventKind.THREAD_START) {
- long thread_id = r.ReadId ();
events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = thread_id };
//EventHandler.ThreadStart (req_id, thread_id, thread_id);
} else if (kind == EventKind.THREAD_DEATH) {
- long thread_id = r.ReadId ();
events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = thread_id };
//EventHandler.ThreadDeath (req_id, thread_id, thread_id);
} else if (kind == EventKind.ASSEMBLY_LOAD) {
- long thread_id = r.ReadId ();
long id = r.ReadId ();
events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
//EventHandler.AssemblyLoad (req_id, thread_id, id);
} else if (kind == EventKind.ASSEMBLY_UNLOAD) {
- long thread_id = r.ReadId ();
long id = r.ReadId ();
events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
//EventHandler.AssemblyUnload (req_id, thread_id, id);
} else if (kind == EventKind.TYPE_LOAD) {
- long thread_id = r.ReadId ();
long id = r.ReadId ();
events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
//EventHandler.TypeLoad (req_id, thread_id, id);
} else if (kind == EventKind.METHOD_ENTRY) {
- long thread_id = r.ReadId ();
long id = r.ReadId ();
events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
//EventHandler.MethodEntry (req_id, thread_id, id);
} else if (kind == EventKind.METHOD_EXIT) {
- long thread_id = r.ReadId ();
long id = r.ReadId ();
events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
//EventHandler.MethodExit (req_id, thread_id, id);
} else if (kind == EventKind.BREAKPOINT) {
- long thread_id = r.ReadId ();
long id = r.ReadId ();
long loc = r.ReadLong ();
events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id, Location = loc };
//EventHandler.Breakpoint (req_id, thread_id, id, loc);
} else if (kind == EventKind.STEP) {
- long thread_id = r.ReadId ();
long id = r.ReadId ();
long loc = r.ReadLong ();
events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id, Location = loc };
//EventHandler.Step (req_id, thread_id, id, loc);
} else if (kind == EventKind.EXCEPTION) {
- long thread_id = r.ReadId ();
long id = r.ReadId ();
long loc = 0; // FIXME
events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id, Location = loc };
//EventHandler.Exception (req_id, thread_id, id, loc);
} else if (kind == EventKind.APPDOMAIN_CREATE) {
- long thread_id = r.ReadId ();
long id = r.ReadId ();
events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
//EventHandler.AppDomainCreate (req_id, thread_id, id);
} else if (kind == EventKind.APPDOMAIN_UNLOAD) {
- long thread_id = r.ReadId ();
long id = r.ReadId ();
events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id };
//EventHandler.AppDomainUnload (req_id, thread_id, id);
} else if (kind == EventKind.USER_BREAK) {
- long thread_id = r.ReadId ();
long id = 0;
long loc = 0;
events [i] = new EventInfo (etype, req_id) { ThreadId = thread_id, Id = id, Location = loc };
//EventHandler.Exception (req_id, thread_id, id, loc);
} else if (kind == EventKind.USER_LOG) {
- long thread_id = r.ReadId ();
int level = r.ReadInt ();
string category = r.ReadString ();
string message = r.ReadString ();
StaticCtor = 1,
/* Since protocol version 2.20 */
/* Methods which have the [DebuggerHidden] attribute */
+ /* Before protocol version 2.26, this includes [DebuggerStepThrough] as well */
DebuggerHidden = 2,
+ /* Since protocol version 2.26 */
+ /* Methods which have the [DebuggerStepThrough] attribute */
+ DebuggerStepThrough = 4,
}
public sealed class StepEventRequest : EventRequest {
TypeMirror[] ifaces;
Dictionary<TypeMirror, InterfaceMappingMirror> iface_map;
TypeMirror[] type_args;
+ bool cached_base_type;
bool inited;
internal const BindingFlags DefaultBindingFlags =
public TypeMirror BaseType {
get {
- // FIXME: base_type could be null for object/interfaces
- if (base_type == null) {
+ if (!cached_base_type) {
base_type = vm.GetType (GetInfo ().base_type);
+ cached_base_type = true;
}
return base_type;
}
string[] source_files;
string[] source_files_full_path;
- public string[] GetSourceFiles (bool return_full_paths) {
- string[] res = return_full_paths ? source_files_full_path : source_files;
+ public string[] GetSourceFiles (bool returnFullPaths) {
+ string[] res = returnFullPaths ? source_files_full_path : source_files;
if (res == null) {
- res = vm.conn.Type_GetSourceFiles (id, return_full_paths);
- if (return_full_paths)
+ res = vm.conn.Type_GetSourceFiles (id, returnFullPaths);
+ if (returnFullPaths)
source_files_full_path = res;
else
source_files = res;
* used by the reflection-only functionality on .net.
*/
public CustomAttributeDataMirror[] GetCustomAttributes (bool inherit) {
- return GetCAttrs (null, inherit);
+ return GetCustomAttrs (null, inherit);
}
public CustomAttributeDataMirror[] GetCustomAttributes (TypeMirror attributeType, bool inherit) {
if (attributeType == null)
throw new ArgumentNullException ("attributeType");
- return GetCAttrs (attributeType, inherit);
+ return GetCustomAttrs (attributeType, inherit);
}
- CustomAttributeDataMirror[] GetCAttrs (TypeMirror type, bool inherit) {
+ void AppendCustomAttrs (IList<CustomAttributeDataMirror> attrs, TypeMirror type, bool inherit)
+ {
if (cattrs == null && Metadata != null && !Metadata.HasCustomAttributes)
cattrs = new CustomAttributeDataMirror [0];
- // FIXME: Handle inherit
if (cattrs == null) {
CattrInfo[] info = vm.conn.Type_GetCustomAttributes (id, 0, false);
cattrs = CustomAttributeDataMirror.Create (vm, info);
}
- var res = new List<CustomAttributeDataMirror> ();
- foreach (var attr in cattrs)
+
+ foreach (var attr in cattrs) {
if (type == null || attr.Constructor.DeclaringType == type)
- res.Add (attr);
- return res.ToArray ();
+ attrs.Add (attr);
+ }
+
+ if (inherit && BaseType != null)
+ BaseType.AppendCustomAttrs (attrs, type, inherit);
+ }
+
+ CustomAttributeDataMirror[] GetCustomAttrs (TypeMirror type, bool inherit) {
+ var attrs = new List<CustomAttributeDataMirror> ();
+ AppendCustomAttrs (attrs, type, inherit);
+ return attrs.ToArray ();
}
public MethodMirror[] GetMethodsByNameFlags (string name, BindingFlags flags, bool ignoreCase) {
{
public class VMDeathEvent : Event
{
- public VMDeathEvent (VirtualMachine vm, int req_id) : base (EventType.VMDeath, vm, req_id, -1) {
+ int exit_code;
+
+ public VMDeathEvent (VirtualMachine vm, int req_id, int exit_code) : base (EventType.VMDeath, vm, req_id, -1) {
+ this.exit_code = exit_code;
+ }
+
+ // Since protocol version 2.27
+ public int ExitCode {
+ get {
+ vm.CheckProtocolVersion (2, 27);
+ return exit_code;
+ }
}
}
}
public void Detach () {
conn.VM_Dispose ();
conn.Close ();
- notify_vm_event (EventType.VMDisconnect, SuspendPolicy.None, 0, 0, null);
+ notify_vm_event (EventType.VMDisconnect, SuspendPolicy.None, 0, 0, null, 0);
}
[Obsolete ("This method was poorly named; use the Detach() method instead")]
root_domain = GetDomain (root_domain_id);
}
- internal void notify_vm_event (EventType evtype, SuspendPolicy spolicy, int req_id, long thread_id, string vm_uri) {
+ internal void notify_vm_event (EventType evtype, SuspendPolicy spolicy, int req_id, long thread_id, string vm_uri, int exit_code) {
//Console.WriteLine ("Event: " + evtype + "(" + vm_uri + ")");
switch (evtype) {
queue_event_set (new EventSet (this, spolicy, new Event[] { new VMStartEvent (vm, req_id, thread_id) }));
break;
case EventType.VMDeath:
- queue_event_set (new EventSet (this, spolicy, new Event[] { new VMDeathEvent (vm, req_id) }));
+ queue_event_set (new EventSet (this, spolicy, new Event[] { new VMDeathEvent (vm, req_id, exit_code) }));
break;
case EventType.VMDisconnect:
queue_event_set (new EventSet (this, spolicy, new Event[] { new VMDisconnectEvent (vm, req_id) }));
switch (ei.EventType) {
case EventType.VMStart:
- vm.notify_vm_event (EventType.VMStart, suspend_policy, req_id, thread_id, null);
+ vm.notify_vm_event (EventType.VMStart, suspend_policy, req_id, thread_id, null, 0);
break;
case EventType.VMDeath:
- vm.notify_vm_event (EventType.VMDeath, suspend_policy, req_id, thread_id, null);
+ vm.notify_vm_event (EventType.VMDeath, suspend_policy, req_id, thread_id, null, ei.ExitCode);
break;
case EventType.ThreadStart:
l.Add (new ThreadStartEvent (vm, req_id, id));
}
public void VMDisconnect (int req_id, long thread_id, string vm_uri) {
- vm.notify_vm_event (EventType.VMDisconnect, SuspendPolicy.None, req_id, thread_id, vm_uri);
+ vm.notify_vm_event (EventType.VMDisconnect, SuspendPolicy.None, req_id, thread_id, vm_uri, 0);
}
}
ss7 ();
ss_nested ();
ss_regress_654694 ();
+ ss_step_through ();
+ ss_recursive (1);
}
[MethodImplAttribute (MethodImplOptions.NoInlining)]
public static void ss_nested_3 () {
}
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static void ss_step_through () {
+ step_through_1 ();
+ StepThroughClass.step_through_2 ();
+ step_through_3 ();
+ }
+
+ [DebuggerStepThrough]
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static void step_through_1 () {
+ }
+
+ [DebuggerStepThrough]
+ class StepThroughClass {
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static void step_through_2 () {
+ }
+ }
+
+ [DebuggerStepThrough]
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static void step_through_3 () {
+ }
+
+ [MethodImplAttribute (MethodImplOptions.NoInlining)]
+ public static void ss_recursive (int n) {
+ if (n == 10)
+ return;
+ ss_recursive (n + 1);
+ }
+
[MethodImplAttribute (MethodImplOptions.NoInlining)]
public static bool is_even (int i) {
return i % 2 == 0;
e = step_into ();
assert_location (e, "ss_nested_1");
e = step_out ();
- Console.WriteLine ("A: " + e.Thread.GetFrames ()[0].Location);
assert_location (e, "ss_nested");
// Check that step over steps over nested calls
e = step_over ();
assert_location (e, "ss_nested");
e = step_into ();
assert_location (e, "ss_nested_3");
+ req.Disable ();
+
+ // Check DebuggerStepThrough support
+ e = run_until ("ss_step_through");
+ req = create_step (e);
+ req.Filter = StepFilter.DebuggerStepThrough;
+ e = step_into ();
+ // Step through step_through_1 ()
+ e = step_into ();
+ assert_location (e, "ss_step_through");
+ // Step through StepThroughClass.step_through_2 ()
+ e = step_into ();
+ assert_location (e, "ss_step_through");
+ req.Disable ();
+ req.Filter = StepFilter.None;
+ e = step_into ();
+ assert_location (e, "step_through_3");
+ req.Disable ();
+
+ // Check that step-over doesn't stop at inner frames with recursive functions
+ e = run_until ("ss_recursive");
+ req = create_step (e);
+ e = step_over ();
+ e = step_over ();
+ e = step_over ();
+ var f = e.Thread.GetFrames () [0];
+ assert_location (e, "ss_recursive");
+ AssertValue (1, f.GetValue (f.Method.GetLocal ("n")));
+
+ req.Disable ();
}
[Test]
t = frame.Method.GetParameters ()[8].ParameterType;
Assert.AreEqual ("Tests2", t.Name);
var attrs = t.GetCustomAttributes (true);
- Assert.AreEqual (3, attrs.Length);
+ Assert.AreEqual (5, attrs.Length);
foreach (var attr in attrs) {
if (attr.Constructor.DeclaringType.Name == "DebuggerDisplayAttribute") {
Assert.AreEqual (1, attr.ConstructorArguments.Count);
Assert.AreEqual (2, attr.NamedArguments.Count);
Assert.AreEqual ("afield", attr.NamedArguments [0].Field.Name);
Assert.AreEqual ("bfield", attr.NamedArguments [1].Field.Name);
+ } else if (attr.Constructor.DeclaringType.Name == "ClassInterfaceAttribute") {
+ // inherited from System.Object
+ //} else if (attr.Constructor.DeclaringType.Name == "Serializable") {
+ // inherited from System.Object
+ } else if (attr.Constructor.DeclaringType.Name == "ComVisibleAttribute") {
+ // inherited from System.Object
} else {
Assert.Fail (attr.Constructor.DeclaringType.Name);
}
var e = GetNextEvent ();
Assert.IsInstanceOfType (typeof (VMDeathEvent), e);
+ Assert.AreEqual (5, (e as VMDeathEvent).ExitCode);
+
var p = vm.Process;
/* Could be a remote vm with no process */
if (p != null) {
if (i == 0)
return false;
throw new OptionException (string.Format (localizer (
- "Cannot bundle unregistered option '{0}'."), opt), opt);
+ "Cannot use unregistered option '{0}' in bundle '{1}'."), rn, f + n), null);
}
p = this [rn];
switch (p.OptionValueType) {
Assert.AreEqual (libs [1], null);
Utils.AssertException (typeof(OptionException),
- "Cannot bundle unregistered option '-V'.",
+ "Cannot use unregistered option 'V' in bundle '-EVALUENOTSUP'.",
p, v => { v.Parse (_("-EVALUENOTSUP")); });
}
// try to bundle with an option requiring a value
Utils.AssertException (typeof(OptionException),
- "Cannot bundle unregistered option '-z'.",
+ "Cannot use unregistered option 'z' in bundle '-cz'.",
p, v => { v.Parse (_("-cz", "extra")); });
Utils.AssertException (typeof(ArgumentNullException),
Assert.AreEqual (formats ["baz"][0], "e");
Assert.AreEqual (formats ["baz"][1], "f");
}
+
+ [Test]
+ public void ReportInvalidDuplication ()
+ {
+ int verbosity = 0;
+ var p = new OptionSet () {
+ { "v", v => verbosity = v != null ? verbosity + 1 : verbosity },
+ };
+ try {
+ p.Parse (new []{"-v-v-v"});
+ Assert.Fail ("Should not be reached.");
+ } catch (OptionException e) {
+ Assert.AreEqual (null, e.OptionName);
+ Assert.AreEqual ("Cannot use unregistered option '-' in bundle '-v-v-v'.", e.Message);
+ }
+ }
}
}
return modRef;
}
- public ClassRef AddExternClass(string name, TypeAttr attrs, MetaDataElement declRef)
+ public ClassRef AddExternClass(string ns, string name, TypeAttr attrs, MetaDataElement declRef)
{
- return new ExternClassRef (attrs, null, name, declRef, metaData);
+ return new ExternClassRef (attrs, ns, name, declRef, metaData);
}
/// <summary>
[TestFixture]
public class FilterUIHintAttributeTest {
[Test]
- [Description("Simple ctors set expected properties.")]
public void FilterUIHintAttribute_Simple_Ctors_Set_Properties() {
var attr = new FilterUIHintAttribute(null, null);
Assert.IsNull(attr.FilterUIHint);
[TestFixture]
public class UIHintAttributeTest {
[Test]
- [Description("Simple ctors set expected properties.")]
public void UIHintAttribute_Simple_Ctors_Set_Properties() {
var attr = new UIHintAttribute(null, null);
Assert.IsNull(attr.UIHint);
using NUnit.Framework;
using SysConfig = System.Configuration.Configuration;
using System.Runtime.InteropServices;
+using System.Reflection;
namespace MonoTests.System.Configuration {
using Util;
[Test]
public void TestConnectionStringRetrieval ()
{
+ var currentAssembly = Assembly.GetExecutingAssembly().Location;
+ Assert.IsTrue (File.Exists (currentAssembly + ".config"),
+ String.Format ("This test cannot succeed without the .config file being in the same place as the assembly ({0})",
+ currentAssembly));
+
var connStringObj = ConfigurationManager.ConnectionStrings ["test-connstring"];
Assert.IsNotNull (connStringObj);
var connString = connStringObj.ConnectionString;
--- /dev/null
+//
+// DynamicExpressionVisitor.cs
+//
+// Authors:
+// Marek Safar <marek.safar@gmail.com>
+//
+// Copyright 2013 Xamarin Inc (http://www.xamarin.com).
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+//
+
+#if NET_4_5
+
+namespace System.Linq.Expressions
+{
+ public abstract class DynamicExpressionVisitor : ExpressionVisitor
+ {
+ }
+}
+
+#endif
if (ltype == rtype && ultype.IsEnum)
return null;
- if (ltype == rtype && ultype == typeof (bool))
+ if (ltype == rtype && (ultype == typeof (bool) || ultype == typeof (char)))
return null;
if (ltype.IsNullable () && ConstantExpression.IsNull (right) && !ConstantExpression.IsNull (left))
if (list != null)
return list [index];
+#if NET_4_5
+ var readOnlyList = source as IReadOnlyList<TSource>;
+ if (readOnlyList != null)
+ return readOnlyList[index];
+#endif
+
return source.ElementAt (index, Fallback.Throw);
}
if (list != null)
return index < list.Count ? list [index] : default (TSource);
+#if NET_4_5
+ var readOnlyList = source as IReadOnlyList<TSource>;
+ if (readOnlyList != null)
+ return index < readOnlyList.Count ? readOnlyList [index] : default (TSource);
+#endif
+
return source.ElementAt (index, Fallback.Default);
}
foreach (TOuter element in outer) {
TKey outerKey = outerKeySelector (element);
- if (innerKeys.Contains (outerKey))
+ if (outerKey != null && innerKeys.Contains (outerKey))
yield return resultSelector (element, innerKeys [outerKey]);
else
yield return resultSelector (element, Empty<TInner> ());
foreach (TOuter element in outer) {
TKey outerKey = outerKeySelector (element);
- if (innerKeys.Contains (outerKey)) {
+ if (outerKey != null && innerKeys.Contains (outerKey)) {
foreach (TInner innerElement in innerKeys [outerKey])
yield return resultSelector (element, innerElement);
}
static void Fill (Stream stream, byte[] nbuf, int required)
{
- int read, offset = 0;
+ int read = 0, offset = 0;
while (offset < required && (read = stream.Read (nbuf, offset, required - offset)) > 0)
offset += read;
if (read != required)
#endif
}
+ [Test]
+ public void PrimitiveNonNumeric ()
+ {
+ BinaryExpression expr = Expression.Equal (Expression.Constant ('a'), Expression.Constant ('b'));
+ Assert.AreEqual (ExpressionType.Equal, expr.NodeType);
+ Assert.AreEqual (typeof (bool), expr.Type);
+ Assert.IsNull (expr.Method);
+
+ var eq = Expression.Lambda<Func<bool>> (expr).Compile ();
+ Assert.IsFalse (eq ());
+ }
+
[Test]
public void Nullable_LiftToNull_SetToFalse ()
{
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Collections.ObjectModel;
using System.Globalization;
using System.Text;
using System.Threading;
Assert.That (source.ElementAt (2), Is.EqualTo (3));
}
+ [Test]
+ public void ElementAt_ReadOnlyListOptimization_ReturnsValueAtGivenIndex()
+ {
+ var source = new NonEnumerableReadOnlyList<int> (new List<int> (new[] { 1, 2, 3, 4, 5, 6 }));
+ Assert.That(source.ElementAt (2), Is.EqualTo (3));
+ }
+
[Test]
public void ElementAtOrDefault_IntegersWithOutOfRangeIndex_ReturnsDefault ()
{
Assert.That (source.ElementAtOrDefault (2), Is.EqualTo (3));
}
+ [Test]
+ public void ElementAtOrDefault_ReadOnlyListOptimization_ReturnsValueAtGivenIndex()
+ {
+ var source = new NonEnumerableReadOnlyList<int>(new List<int> (new[] { 1, 2, 3, 4, 5, 6 }));
+ Assert.That(source.ElementAtOrDefault (2), Is.EqualTo (3));
+ }
+
[Test]
public void ElementAtOrDefault_BooleansAndNegativeIndex_ReturnsDefault ()
{
}
}
+ [Serializable]
+ internal sealed class NonEnumerableReadOnlyList<T> : ReadOnlyCollection<T>, IEnumerable<T> {
+ public NonEnumerableReadOnlyList () :
+ this (new List<T>()) { }
+
+ public NonEnumerableReadOnlyList (IList<T> collection) :
+ base (collection) { }
+
+ // Re-implement GetEnumerator to be undefined.
+
+ IEnumerator<T> IEnumerable<T>.GetEnumerator ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IEnumerable<T>) this).GetEnumerator();
+ }
+ }
+
internal sealed class Reader<T> : IEnumerable<T>, IEnumerator<T>
{
public event EventHandler Disposed;
AssertAreSame (expected2, dataOuter2.Join (dataInner2, x => x, x => x, (x, y) => x + y, EqualityComparer<string>.Default));
}
+ [Test]
+ public void JoinTestNullKeys ()
+ {
+ var l1 = new [] {
+ new { Name = "name1", Nullable = (int?) null },
+ new { Name = "name2", Nullable = (int?) null }
+ };
+
+ var count = l1.Join (l1, i => i.Nullable, i => i.Nullable, (x, y) => x.Name).Count ();
+ Assert.AreEqual (0, count);
+ }
+
[Test]
public void GroupJoinArgumentNullTest ()
{
AssertAreSame (expected2, dataOuter2.GroupJoin (dataInner2, x => x, x => x, (x, y) => { foreach (var s in y) x += s; return x; }, EqualityComparer<string>.Default));
}
+ [Test]
+ public void GroupJoinWithNullKeys ()
+ {
+ string[] l1 = { null };
+ string[] l2 = { null, null };
+ var res = l1.GroupJoin (l2, x => x, y => y, (a, b) => new { Key = a, Count = b.Count () }).ToArray ();
+ Assert.AreEqual (1, res.Length);
+ Assert.AreEqual (0, res [0].Count);
+ }
+
[Test]
public void OrderByArgumentNullTest ()
{
System.Runtime.CompilerServices/DynamicAttribute.cs
System.Linq.Expressions/ExpressionTransformer.cs
System.Linq.Expressions/Extensions.cs
+System.Linq.Expressions/DynamicExpressionVisitor.cs
#include net_4_0_System.Core.dll.sources
../dlr/Runtime/Microsoft.Scripting.Core/Ast/DynamicExpression.cs
+System.Linq.Expressions/DynamicExpressionVisitor.cs
if (keyInfo || schemaOnly)
epilog = sql2.ToString ();
try {
- Connection.Tds.BeginExecuteProcedure (prolog,
+ ar = Connection.Tds.BeginExecuteProcedure (prolog,
epilog,
CommandText,
!wantResults,
[Test]
public void GetHashCode_UnitDiffers_HashesNotEqual()
{
- Font f1 = new Font("DejaVu Sans", 8.25F, GraphicsUnit.Point);
- Font f2 = new Font("DejaVu Sans", 8.25F, GraphicsUnit.Pixel);
+ Font f1 = new Font("Arial", 8.25F, GraphicsUnit.Point);
+ Font f2 = new Font("Arial", 8.25F, GraphicsUnit.Pixel);
Assert.IsFalse(f1.GetHashCode() == f2.GetHashCode(),
"Hashcodes should differ if _unit member differs");
[Test]
public void GetHashCode_NameDiffers_HashesNotEqual()
{
- Font f1 = new Font("DejaVu Sans", 8.25F, GraphicsUnit.Point);
- Font f2 = new Font("Liberation Sans", 8.25F, GraphicsUnit.Point);
+ Font f1 = new Font("Arial", 8.25F, GraphicsUnit.Point);
+ Font f2 = new Font("Courier New", 8.25F, GraphicsUnit.Point);
Assert.IsFalse(f1.GetHashCode() == f2.GetHashCode(),
"Hashcodes should differ if _name member differs");
[Test]
public void GetHashCode_StyleEqualsGdiCharSet_HashesNotEqual()
{
- Font f1 = new Font("DejaVu Sans", 8.25F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0)));
- Font f2 = new Font("DejaVu Sans", 8.25F, FontStyle.Bold, GraphicsUnit.Point, ((byte)(1)));
+ Font f1 = new Font("Arial", 8.25F, FontStyle.Regular, GraphicsUnit.Point, ((byte)(0)));
+ Font f2 = new Font("Arial", 8.25F, FontStyle.Bold, GraphicsUnit.Point, ((byte)(1)));
Assert.IsFalse(f1.GetHashCode() == f2.GetHashCode(),
"Hashcodes should differ if _style member differs");
if (values == null)
throw new ArgumentNullException ("values");
- if (string.IsNullOrEmpty (name))
- return false;
-
- Parser.Token.Check (name);
-
HeaderInfo headerInfo;
- if (known_headers.TryGetValue (name, out headerInfo) && (headerInfo.HeaderKind & HeaderKind) == 0) {
- if (HeaderKind != HttpHeaderKind.None && ((HeaderKind | headerInfo.HeaderKind) & HttpHeaderKind.Content) != 0)
- return false;
- }
+ if (!TryCheckName (name, out headerInfo))
+ return false;
AddInternal (name, values, null, true);
return true;
return headerInfo;
}
+ bool TryCheckName (string name, out HeaderInfo headerInfo)
+ {
+ if (!Parser.Token.TryCheck (name)) {
+ headerInfo = null;
+ return false;
+ }
+
+ if (known_headers.TryGetValue (name, out headerInfo) && (headerInfo.HeaderKind & HeaderKind) == 0) {
+ if (HeaderKind != HttpHeaderKind.None && ((HeaderKind | headerInfo.HeaderKind) & HttpHeaderKind.Content) != 0)
+ return false;
+ }
+
+ return true;
+ }
+
public void Clear ()
{
connectionclose = null;
public IEnumerable<string> GetValues (string name)
{
+ CheckName (name);
+
IEnumerable<string> values;
if (!TryGetValues (name, out values))
throw new InvalidOperationException ();
public bool TryGetValues (string name, out IEnumerable<string> values)
{
- var header_info = CheckName (name);
+ HeaderInfo headerInfo;
+ if (!TryCheckName (name, out headerInfo)) {
+ values = null;
+ return false;
+ }
HeaderBucket bucket;
if (!headers.TryGetValue (name, out bucket)) {
return false;
}
- values = GetAllHeaderValues (bucket, header_info);
+ values = GetAllHeaderValues (bucket, headerInfo);
return true;
}
if (s == null)
return false;
- if (!Lexer.IsValidToken (s)) {
- if (s.Length == 0)
- return false;
-
- return false;
- }
-
- return true;
+ return Lexer.IsValidToken (s);
}
public static void CheckQuotedString (string s)
}
}
+ [Test]
+ public void TryGetValuesTest ()
+ {
+ IEnumerable<string> headerValues;
+ Assert.IsFalse (headers.TryGetValues (null, out headerValues), "#1");
+ Assert.IsFalse (headers.TryGetValues ("some-name", out headerValues), "#2");
+ }
+
[Test]
public void ToStringTest ()
{
return (((long)high) << 32) | low;
}
- if (high > 0x80000000u)
+ /*
+ We cannot represent negative numbers smaller than long.MinValue.
+ Those values are encoded into what look negative numbers, so negating
+ them produces a positive value, that's why it's safe to check for that
+ condition.
+
+ long.MinValue works fine since it's bigint encoding looks like a negative
+ number, but since long.MinValue == -long.MinValue, we're good.
+ */
+
+ long result = - ((((long)high) << 32) | (long)low);
+ if (result > 0)
throw new OverflowException ();
-
- return - ((((long)high) << 32) | (long)low);
+ return result;
}
[CLSCompliantAttribute (false)]
a = new BigInteger ();
Assert.AreEqual (BigInteger.Zero.GetHashCode (), a.GetHashCode (), "#15");
}
+
+ [Test]
+ public void Bug16526 ()
+ {
+ var x = BigInteger.Pow(2, 63);
+ x *= -1;
+ x -= 1;
+ Assert.AreEqual ("-9223372036854775809", x.ToString (), "#1");
+ try {
+ x = (long)x;
+ Assert.Fail ("#2 Must OVF");
+ } catch (OverflowException) {
+ }
+ }
}
}
//
using System;
-using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Xml;
}
-#if NET_2_0
[Test]
public void TestFromEnum_Null_TypeName ()
{
Assert.IsTrue (ex.Message.IndexOf ("AnInvalidValue") != -1, "#4");
Assert.IsTrue (ex.Message.IndexOf ("SomeType") != -1, "#5");
}
-#endif
[Test]
public void WriteCharacter ()
[Serializable]
public class ToBeSerialized
{
- [DefaultValue ('a')]
+ [global::System.ComponentModel.DefaultValue ('a')]
public char character = '\'';
}
int index;
CyclicDeque<T> bag = GetBag (out index);
bag.PushBottom (item);
+ staging.TryAdd (index, bag);
AddHint (index);
Interlocked.Increment (ref count);
}
if (bag == null || bag.PopBottom (out result) != PopResult.Succeed) {
var self = bag;
+ ret = false;
foreach (var other in staging) {
// Try to retrieve something based on a hint
ret = TryGetHint (out hintIndex) && (bag = container[hintIndex]).PopTop (out result) == PopResult.Succeed;
if (bag == null || !bag.PeekBottom (out result)) {
var self = bag;
+ ret = false;
foreach (var other in staging) {
// Try to retrieve something based on a hint
ret = TryGetHint (out hintIndex) && container[hintIndex].PeekTop (out result);
if (container.TryGetValue (index, out value))
return value;
- var bag = createBag ? container.GetOrAdd (index, new CyclicDeque<T> ()) : null;
- if (bag != null)
- staging.TryAdd (index, bag);
- return bag;
+ return createBag ? container.GetOrAdd (index, new CyclicDeque<T> ()) : null;
}
void TidyBag (int index, CyclicDeque<T> bag)
}
}
}
-#endif
\ No newline at end of file
+#endif
private EventHandlerList event_handlers;
private ISite mySite;
- private object disposedEvent = new object ();
+ static readonly object disposedEvent = new object ();
public Component ()
{
//
using System;
+using System.Reflection;
#if (XML_DEP)
using System.Xml;
#endif
#if (CONFIGURATION_DEP)
protected override void Unmerge (ConfigurationElement sourceElement, ConfigurationElement parentElement, ConfigurationSaveMode saveMode)
{
- throw new NotImplementedException ();
+ if (parentElement != null && sourceElement.GetType() != parentElement.GetType())
+ throw new ConfigurationErrorsException ("Can't unmerge two elements of different type");
+
+ bool isMinimalOrModified = saveMode == ConfigurationSaveMode.Minimal ||
+ saveMode == ConfigurationSaveMode.Modified;
+
+ foreach (PropertyInformation prop in sourceElement.ElementInformation.Properties)
+ {
+ if (prop.ValueOrigin == PropertyValueOrigin.Default)
+ continue;
+
+ PropertyInformation unmergedProp = ElementInformation.Properties [prop.Name];
+
+ object sourceValue = prop.Value;
+ if (parentElement == null || !HasValue (parentElement, prop.Name)) {
+ unmergedProp.Value = sourceValue;
+ continue;
+ }
+
+ if (sourceValue == null)
+ continue;
+
+ object parentValue = GetItem (parentElement, prop.Name);
+ if (!PropertyIsElement (prop)) {
+ if (!object.Equals (sourceValue, parentValue) ||
+ (saveMode == ConfigurationSaveMode.Full) ||
+ (saveMode == ConfigurationSaveMode.Modified && prop.ValueOrigin == PropertyValueOrigin.SetHere))
+ unmergedProp.Value = sourceValue;
+ continue;
+ }
+
+ var sourceElem = (ConfigurationElement) sourceValue;
+ if (isMinimalOrModified && !ElementIsModified (sourceElem))
+ continue;
+ if (parentValue == null) {
+ unmergedProp.Value = sourceValue;
+ continue;
+ }
+
+ var parentElem = (ConfigurationElement) parentValue;
+ ConfigurationElement copy = (ConfigurationElement) unmergedProp.Value;
+ ElementUnmerge (copy, sourceElem, parentElem, saveMode);
+ }
+ }
+
+ bool HasValue (ConfigurationElement element, string propName)
+ {
+ PropertyInformation info = element.ElementInformation.Properties [propName];
+ return info != null && info.ValueOrigin != PropertyValueOrigin.Default;
+ }
+
+ object GetItem (ConfigurationElement element, string property)
+ {
+ PropertyInformation pi = ElementInformation.Properties [property];
+ if (pi == null)
+ throw new InvalidOperationException ("Property '" + property + "' not found in configuration element");
+
+ return pi.Value;
+ }
+
+ bool PropertyIsElement (PropertyInformation prop)
+ {
+ return (typeof(ConfigurationElement).IsAssignableFrom (prop.Type));
+ }
+
+ bool ElementIsModified (ConfigurationElement element)
+ {
+ return (bool) element.GetType ().GetMethod ("IsModified", BindingFlags.NonPublic | BindingFlags.Instance).Invoke (element, new object [0]);
+ }
+
+ void ElementUnmerge (ConfigurationElement target, ConfigurationElement sourceElement, ConfigurationElement parentElement, ConfigurationSaveMode saveMode)
+ {
+ target.GetType ().GetMethod ("Unmerge", BindingFlags.NonPublic | BindingFlags.Instance).Invoke (target, new object [] {sourceElement, parentElement, saveMode});
}
#endif
}
async_output.Close ();
if (async_error != null)
async_error.Close ();
+
+ if (input_stream != null) {
+ input_stream.Close();
+ input_stream = null;
+ }
+
+ if (output_stream != null) {
+ output_stream.Close();
+ output_stream = null;
+ }
+
+ if (error_stream != null) {
+ error_stream.Close();
+ error_stream = null;
+ }
}
}
Process_free_internal(process_handle);
process_handle=IntPtr.Zero;
}
-
- if (input_stream != null) {
- input_stream.Close();
- input_stream = null;
- }
-
- if (output_stream != null) {
- output_stream.Close();
- output_stream = null;
- }
-
- if (error_stream != null) {
- error_stream.Close();
- error_stream = null;
- }
}
}
base.Dispose (disposing);
using System.Configuration;
using System.Globalization;
using System.IO;
+using System.Net;
using System.Net.Cache;
using System.Net.Sockets;
using System.Runtime.Remoting.Messaging;
return result.Response;
}
+
+#if NET_3_5
+ public Stream EndGetRequestStream (IAsyncResult asyncResult, out TransportContext transportContext)
+ {
+ transportContext = null;
+ return EndGetRequestStream (asyncResult);
+ }
+#endif
public override WebResponse GetResponse()
{
redirects++;
Exception e = null;
string uriString = null;
-
switch (code) {
case HttpStatusCode.Ambiguous: // 300
e = new WebException ("Ambiguous redirect.");
break;
case HttpStatusCode.MovedPermanently: // 301
case HttpStatusCode.Redirect: // 302
- case HttpStatusCode.TemporaryRedirect: // 307
- /* MS follows the redirect for POST too
- if (method != "GET" && method != "HEAD") // 10.3
- return false;
- */
-
- contentLength = -1;
- bodyBufferLength = 0;
- bodyBuffer = null;
- if (code != HttpStatusCode.TemporaryRedirect)
+ if (method == "POST")
method = "GET";
- uriString = webResponse.Headers ["Location"];
+ break;
+ case HttpStatusCode.TemporaryRedirect: // 307
break;
case HttpStatusCode.SeeOther: //303
method = "GET";
- uriString = webResponse.Headers ["Location"];
break;
case HttpStatusCode.NotModified: // 304
return false;
if (e != null)
throw e;
+ //contentLength = -1;
+ //bodyBufferLength = 0;
+ //bodyBuffer = null;
+ uriString = webResponse.Headers ["Location"];
+
if (uriString == null)
throw new WebException ("No Location header found for " + (int) code,
WebExceptionStatus.ProtocolError);
if (address == null)
throw new ArgumentNullException ("address");
- RecycleServicePoints ();
+ if ((servicePoints.Count % 4) == 0)
+ RecycleServicePoints ();
var origAddress = new Uri (address.Scheme + "://" + address.Authority);
address = new Uri (address.Scheme + "://" + address.Authority);
ServicePoint sp = null;
+ SPKey key = new SPKey (origAddress, usesProxy ? address : null, useConnect);
lock (servicePoints) {
- SPKey key = new SPKey (origAddress, usesProxy ? address : null, useConnect);
sp = servicePoints [key] as ServicePoint;
if (sp != null)
return sp;
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_4_0
+#if NET_3_5
using System.Security.Authentication.ExtendedProtection;
return (statusCode >= 200 && statusCode != 204 && statusCode != 304);
}
- internal void GetCertificates ()
+ internal void GetCertificates (Stream stream)
{
// here the SSL negotiation have been done
#if SECURITY_DEP && MONOTOUCH
- HttpsClientStream s = (nstream as HttpsClientStream);
+ HttpsClientStream s = (stream as HttpsClientStream);
X509Certificate client = s.SelectedClientCertificate;
X509Certificate server = s.ServerCertificate;
#else
- X509Certificate client = (X509Certificate) piClient.GetValue (nstream, null);
- X509Certificate server = (X509Certificate) piServer.GetValue (nstream, null);
+ X509Certificate client = (X509Certificate) piClient.GetValue (stream, null);
+ X509Certificate server = (X509Certificate) piServer.GetValue (stream, null);
#endif
sPoint.SetCertificates (client, server);
certsAvailable = (server != null);
lock (this) {
if (Data.request != request)
throw new ObjectDisposedException (typeof (NetworkStream).FullName);
- if (nstream == null)
- return false;
s = nstream;
+ if (s == null)
+ return false;
}
try {
s.Write (buffer, offset, size);
// here SSL handshake should have been done
if (ssl && !certsAvailable)
- GetCertificates ();
+ GetCertificates (s);
} catch (Exception e) {
err_msg = e.Message;
WebExceptionStatus wes = WebExceptionStatus.SendFailure;
// if SSL is in use then check for TrustFailure
if (ssl) {
#if SECURITY_DEP && MONOTOUCH
- HttpsClientStream https = (nstream as HttpsClientStream);
+ HttpsClientStream https = (s as HttpsClientStream);
if (https.TrustFailure) {
#else
- if ((bool) piTrustFailure.GetValue (nstream, null)) {
+ if ((bool) piTrustFailure.GetValue (s , null)) {
#endif
wes = WebExceptionStatus.TrustFailure;
msg = "Trust failure";
protected override void Dispose (bool disposing)
{
- Close ();
+ // If we're disposing explicitly, clear all
+ // fields. If not, all fields will have been
+ // nulled by the GC during finalization, so
+ // trying to lock on _lock will blow up.
+ if (disposing)
+ Close ();
+
base.Dispose (disposing);
}
Assert.IsTrue (valid, "Aggregate test");
}
+
+ [Test]
+ public void BasicRemoveEmptyTest ()
+ {
+ int result;
+ Assert.IsTrue(bag.IsEmpty);
+ Assert.IsFalse(bag.TryTake(out result));
+ }
+
+ [Test]
+ public void BasicRemoveTwiceTest()
+ {
+ bag.Add (1);
+ Assert.IsFalse (bag.IsEmpty);
+ Assert.AreEqual (1, bag.Count);
+
+ int result;
+ Assert.IsTrue (bag.TryTake (out result));
+ Assert.AreEqual (1, result);
+ Assert.IsTrue (bag.IsEmpty);
+ Assert.IsFalse (bag.TryTake (out result));
+ Assert.IsFalse (bag.TryTake (out result));
+ }
+
+ [Test]
+ public void AddRemoveAddTest()
+ {
+ bag.Add (1);
+ Assert.IsFalse (bag.IsEmpty);
+ Assert.AreEqual (1, bag.Count);
+
+ int result;
+ Assert.IsTrue (bag.TryTake (out result));
+ Assert.AreEqual (1, result);
+ Assert.IsTrue (bag.IsEmpty);
+
+ bag.Add (1);
+ Assert.IsFalse (bag.IsEmpty);
+ Assert.AreEqual (1, bag.Count);
+
+ Assert.IsTrue (bag.TryTake (out result));
+ Assert.AreEqual (1, result);
+ Assert.IsTrue (bag.IsEmpty);
+ }
[Test]
public void AddStressTest ()
}
}
+ [Test]
+ public void SetSocketOption_MulticastInterfaceIndex_Any ()
+ {
+ IPAddress ip = IPAddress.Parse ("239.255.255.250");
+ int index = 0;
+ using (Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
+ {
+ s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, IPAddress.HostToNetworkOrder(index));
+ s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ip, index));
+ }
+ }
+
+ [Test]
+ public void SetSocketOption_MulticastInterfaceIndex_Loopback ()
+ {
+ IPAddress ip = IPAddress.Parse ("239.255.255.250");
+ int index = 1;
+ using (Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
+ {
+ s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, IPAddress.HostToNetworkOrder(index));
+ s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ip, index));
+ }
+ }
+
+ [Test]
+ public void SetSocketOption_MulticastInterfaceIndex_Invalid ()
+ {
+ IPAddress ip = IPAddress.Parse ("239.255.255.250");
+ int index = 31415;
+ using (Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp))
+ {
+ try
+ {
+ s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, IPAddress.HostToNetworkOrder(index));
+ Assert.Fail ("#1");
+ }
+ catch
+ {}
+ try
+ {
+ s.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(ip, index));
+ Assert.Fail ("#2");
+ }
+ catch
+ {}
+ }
+ }
+
[Test]
public void Shutdown_NoConnect ()
{
System.Collections.Specialized/NotifyCollectionChangedEventArgs.cs
System.Collections.Specialized/NotifyCollectionChangedAction.cs
System.Collections.Specialized/NotifyCollectionChangedEventHandler.cs
+System.ComponentModel.Design.Serialization/ComponentSerializationService.cs
+System.ComponentModel.Design.Serialization/ContextStack.cs
+System.ComponentModel.Design.Serialization/DefaultSerializationProviderAttribute.cs
+System.ComponentModel.Design.Serialization/DesignerLoader.cs
+System.ComponentModel.Design.Serialization/DesignerSerializerAttribute.cs
+System.ComponentModel.Design.Serialization/IDesignerLoaderHost.cs
+System.ComponentModel.Design.Serialization/IDesignerLoaderHost2.cs
+System.ComponentModel.Design.Serialization/IDesignerLoaderService.cs
+System.ComponentModel.Design.Serialization/IDesignerSerializationManager.cs
+System.ComponentModel.Design.Serialization/IDesignerSerializationProvider.cs
+System.ComponentModel.Design.Serialization/IDesignerSerializationService.cs
+System.ComponentModel.Design.Serialization/INameCreationService.cs
System.ComponentModel.Design.Serialization/InstanceDescriptor.cs
+System.ComponentModel.Design.Serialization/MemberRelationship.cs
+System.ComponentModel.Design.Serialization/MemberRelationshipService.cs
+System.ComponentModel.Design.Serialization/ResolveNameEventArgs.cs
+System.ComponentModel.Design.Serialization/ResolveNameEventHandler.cs
+System.ComponentModel.Design.Serialization/RootDesignerSerializerAttribute.cs
+System.ComponentModel.Design.Serialization/SerializationStore.cs
+System.ComponentModel.Design/ActiveDesignerEventArgs.cs
+System.ComponentModel.Design/ActiveDesignerEventHandler.cs
+System.ComponentModel.Design/CheckoutException.cs
System.ComponentModel.Design/CommandID.cs
System.ComponentModel.Design/ComponentChangedEventArgs.cs
System.ComponentModel.Design/ComponentChangedEventHandler.cs
System.ComponentModel.Design/ComponentEventHandler.cs
System.ComponentModel.Design/ComponentRenameEventArgs.cs
System.ComponentModel.Design/ComponentRenameEventHandler.cs
+System.ComponentModel.Design/DesignerCollection.cs
+System.ComponentModel.Design/DesignerEventArgs.cs
+System.ComponentModel.Design/DesignerEventHandler.cs
+System.ComponentModel.Design/DesignerOptionService.cs
System.ComponentModel.Design/DesignerTransaction.cs
System.ComponentModel.Design/DesignerTransactionCloseEventArgs.cs
System.ComponentModel.Design/DesignerTransactionCloseEventHandler.cs
System.ComponentModel.Design/DesignerVerb.cs
System.ComponentModel.Design/DesignerVerbCollection.cs
+System.ComponentModel.Design/HelpContextType.cs
+System.ComponentModel.Design/HelpKeywordAttribute.cs
+System.ComponentModel.Design/HelpKeywordType.cs
System.ComponentModel.Design/IComponentChangeService.cs
+System.ComponentModel.Design/IComponentDiscoveryService.cs
+System.ComponentModel.Design/IComponentInitializer.cs
System.ComponentModel.Design/IDesigner.cs
+System.ComponentModel.Design/IDesignerEventService.cs
+System.ComponentModel.Design/IDesignerFilter.cs
System.ComponentModel.Design/IDesignerHost.cs
+System.ComponentModel.Design/IDesignerHostTransactionState.cs
+System.ComponentModel.Design/IDesignerOptionService.cs
+System.ComponentModel.Design/IDictionaryService.cs
+System.ComponentModel.Design/IEventBindingService.cs
+System.ComponentModel.Design/IExtenderListService.cs
+System.ComponentModel.Design/IExtenderProviderService.cs
+System.ComponentModel.Design/IHelpService.cs
+System.ComponentModel.Design/IInheritanceService.cs
+System.ComponentModel.Design/IMenuCommandService.cs
System.ComponentModel.Design/IReferenceService.cs
+System.ComponentModel.Design/IResourceService.cs
System.ComponentModel.Design/IRootDesigner.cs
+System.ComponentModel.Design/ISelectionService.cs
System.ComponentModel.Design/IServiceContainer.cs
+System.ComponentModel.Design/ITreeDesigner.cs
System.ComponentModel.Design/ITypeDescriptorFilterService.cs
+System.ComponentModel.Design/ITypeDiscoveryService.cs
System.ComponentModel.Design/ITypeResolutionService.cs
System.ComponentModel.Design/MenuCommand.cs
+System.ComponentModel.Design/SelectionTypes.cs
+System.ComponentModel.Design/ServiceContainer.cs
System.ComponentModel.Design/ServiceCreatorCallback.cs
System.ComponentModel.Design/StandardCommands.cs
+System.ComponentModel.Design/StandardToolWindows.cs
+System.ComponentModel.Design/TypeDescriptionProviderService.cs
System.ComponentModel.Design/ViewTechnology.cs
System.ComponentModel/AddingNewEventArgs.cs
System.ComponentModel/AddingNewEventHandler.cs
+System.ComponentModel/AmbientValueAttribute.cs
System.ComponentModel/ArrayConverter.cs
System.ComponentModel/AsyncCompletedEventArgs.cs
System.ComponentModel/AsyncCompletedEventHandler.cs
System.ComponentModel/AsyncOperation.cs
System.ComponentModel/AsyncOperationManager.cs
System.ComponentModel/AttributeCollection.cs
+System.ComponentModel/AttributeProviderAttribute.cs
System.ComponentModel/BackgroundWorker.cs
System.ComponentModel/BaseNumberConverter.cs
System.ComponentModel/BindableAttribute.cs
System.ComponentModel/BrowsableAttribute.cs
System.ComponentModel/ByteConverter.cs
System.ComponentModel/CancelEventArgs.cs
+System.ComponentModel/CancelEventHandler.cs
System.ComponentModel/CategoryAttribute.cs
System.ComponentModel/CharConverter.cs
System.ComponentModel/CollectionChangeAction.cs
System.ComponentModel/CollectionChangeEventArgs.cs
System.ComponentModel/CollectionChangeEventHandler.cs
System.ComponentModel/CollectionConverter.cs
+System.ComponentModel/ComplexBindingPropertiesAttribute.cs
System.ComponentModel/Component.cs
System.ComponentModel/ComponentCollection.cs
System.ComponentModel/ComponentConverter.cs
+System.ComponentModel/ComponentEditor.cs
+System.ComponentModel/ComponentResourceManager.cs
+System.ComponentModel/Container.cs
+System.ComponentModel/ContainerFilterService.cs
System.ComponentModel/CultureInfoConverter.cs
System.ComponentModel/CustomTypeDescriptor.cs
System.ComponentModel/DataErrorsChangedEventArgs.cs
+System.ComponentModel/DataObjectAttribute.cs
+System.ComponentModel/DataObjectFieldAttribute.cs
+System.ComponentModel/DataObjectMethodAttribute.cs
+System.ComponentModel/DataObjectMethodType.cs
System.ComponentModel/DateTimeConverter.cs
+System.ComponentModel/DateTimeOffsetConverter.cs
System.ComponentModel/DecimalConverter.cs
+System.ComponentModel/DefaultBindingPropertyAttribute.cs
System.ComponentModel/DefaultEventAttribute.cs
System.ComponentModel/DefaultPropertyAttribute.cs
System.ComponentModel/DefaultValueAttribute.cs
System.ComponentModel/EventDescriptorCollection.cs
System.ComponentModel/EventHandlerList.cs
System.ComponentModel/ExpandableObjectConverter.cs
+System.ComponentModel/ExtenderProvidedPropertyAttribute.cs
System.ComponentModel/GuidConverter.cs
+System.ComponentModel/HandledEventArgs.cs
+System.ComponentModel/HandledEventHandler.cs
System.ComponentModel/IBindingList.cs
System.ComponentModel/IBindingListView.cs
System.ComponentModel/ICancelAddNew.cs
System.ComponentModel/IChangeTracking.cs
System.ComponentModel/IComNativeDescriptorHandler.cs
System.ComponentModel/IComponent.cs
-System.ComponentModel/IComponent.cs
System.ComponentModel/IContainer.cs
System.ComponentModel/ICustomTypeDescriptor.cs
System.ComponentModel/IDataErrorInfo.cs
-System.ComponentModel/IDataErrorInfo.cs
System.ComponentModel/IEditableObject.cs
System.ComponentModel/IExtenderProvider.cs
+System.ComponentModel/IIntellisenseBuilder.cs
System.ComponentModel/IListSource.cs
+System.ComponentModel/ImmutableObjectAttribute.cs
+System.ComponentModel/INestedContainer.cs
+System.ComponentModel/INestedSite.cs
+System.ComponentModel/InheritanceAttribute.cs
+System.ComponentModel/InheritanceLevel.cs
+System.ComponentModel/InitializationEventAttribute.cs
System.ComponentModel/INotifyDataErrorInfo.cs
System.ComponentModel/INotifyPropertyChanged.cs
System.ComponentModel/INotifyPropertyChanging.cs
+System.ComponentModel/InstallerTypeAttribute.cs
+System.ComponentModel/InstanceCreationEditor.cs
+System.ComponentModel/InvalidAsynchronousStateException.cs
System.ComponentModel/IRaiseItemChangedEvents.cs
System.ComponentModel/IRevertibleChangeTracking.cs
System.ComponentModel/ISite.cs
System.ComponentModel/Int32Converter.cs
System.ComponentModel/Int64Converter.cs
System.ComponentModel/InvalidEnumArgumentException.cs
-System.ComponentModel/InvalidEnumArgumentException.cs
System.ComponentModel/ListBindableAttribute.cs
System.ComponentModel/ListChangedEventArgs.cs
System.ComponentModel/ListChangedEventHandler.cs
System.ComponentModel/ListSortDescription.cs
System.ComponentModel/ListSortDescriptionCollection.cs
System.ComponentModel/ListSortDirection.cs
-System.ComponentModel/ListSortDirection.cs
System.ComponentModel/LocalizableAttribute.cs
+System.ComponentModel/LookupBindingPropertiesAttribute.cs
System.ComponentModel/MarshalByValueComponent.cs
+System.ComponentModel/MaskedTextProvider.cs
+System.ComponentModel/MaskedTextResultHint.cs
System.ComponentModel/MemberDescriptor.cs
System.ComponentModel/MergablePropertyAttribute.cs
System.ComponentModel/MultilineStringConverter.cs
+System.ComponentModel/NestedContainer.cs
System.ComponentModel/NotifyParentPropertyAttribute.cs
System.ComponentModel/NullableConverter.cs
+System.ComponentModel/ParenthesizePropertyNameAttribute.cs
System.ComponentModel/PasswordPropertyTextAttribute.cs
System.ComponentModel/ProgressChangedEventArgs.cs
System.ComponentModel/ProgressChangedEventHandler.cs
System.ComponentModel/PropertyChangingEventArgs.cs
System.ComponentModel/PropertyChangingEventHandler.cs
System.ComponentModel/PropertyDescriptor.cs
-System.ComponentModel/PropertyDescriptor.cs
System.ComponentModel/PropertyDescriptorCollection.cs
-System.ComponentModel/ReadOnlyAttribute.cs
+System.ComponentModel/PropertyTabAttribute.cs
+System.ComponentModel/PropertyTabScope.cs
+System.ComponentModel/ProvidePropertyAttribute.cs
System.ComponentModel/ReadOnlyAttribute.cs
System.ComponentModel/RecommendedAsConfigurableAttribute.cs
System.ComponentModel/ReferenceConverter.cs
-System.ComponentModel/ReferenceConverter.cs
System.ComponentModel/ReflectionEventDescriptor.cs
System.ComponentModel/ReflectionPropertyDescriptor.cs
System.ComponentModel/RefreshEventArgs.cs
System.ComponentModel/RefreshEventHandler.cs
System.ComponentModel/RefreshProperties.cs
System.ComponentModel/RefreshPropertiesAttribute.cs
+System.ComponentModel/RunInstallerAttribute.cs
System.ComponentModel/RunWorkerCompletedEventArgs.cs
System.ComponentModel/RunWorkerCompletedEventHandler.cs
System.ComponentModel/SByteConverter.cs
+System.ComponentModel/SettingsBindableAttribute.cs
System.ComponentModel/SingleConverter.cs
System.ComponentModel/StringConverter.cs
+System.ComponentModel/SyntaxCheck.cs
System.ComponentModel/TimeSpanConverter.cs
System.ComponentModel/ToolboxItemAttribute.cs
System.ComponentModel/ToolboxItemFilterAttribute.cs
System.ComponentModel/TypeConverter.cs
System.ComponentModel/TypeConverterAttribute.cs
System.ComponentModel/TypeDescriptionProvider.cs
+System.ComponentModel/TypeDescriptionProviderAttribute.cs
System.ComponentModel/TypeDescriptor.cs
System.ComponentModel/TypeListConverter.cs
System.ComponentModel/UInt16Converter.cs
System.ComponentModel/UInt32Converter.cs
System.ComponentModel/UInt64Converter.cs
+System.ComponentModel/WarningException.cs
System.ComponentModel/WeakObjectWrapper.cs
System.ComponentModel/WeakObjectWrapperComparer.cs
System.ComponentModel/Win32Exception.cs
public override object ConvertFrom (ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (!(value is string))
- throw new NotSupportedException ("RectConverter only supports converting from strings");
+ throw new NotSupportedException ("PointConverter only supports converting from strings");
return Point.Parse ((string)value);
}
TEST_RESOURCES = $(TEST_RESX_RESOURCES) $(TEST_RESX_RESOURCES_SATELITE)
-satellite_assembly1 = es-ES/$(patsubst %.dll,%.Resources.dll,$(test_lib))
-satellite_assembly2 = nn-NO/$(patsubst %.dll,%.Resources.dll,$(test_lib))
+satellite_assembly1 = es-ES/$(patsubst %.dll,%.resources.dll,$(test_lib))
+satellite_assembly2 = nn-NO/$(patsubst %.dll,%.resources.dll,$(test_lib))
$(test_lib): $(TEST_RESOURCES) $(satellite_assembly1) $(satellite_assembly2)
$(vtsdir)/BinarySerializationOverVersions.cs -out:$@
@cp $(vtsdir)/$(PROFILE)_TestLib/1.0/Address.dll $(vtsdir)/$(PROFILE)_TestLib
-# Need to define MONO_PATH to an absolute dir since the test is ran from a subdir
+# Need to define TEST_MONO_PATH to an absolute dir since the test is ran from a subdir
+TEST_MONO_PATH=$(PWD)/../lib/$(PROFILE)
+
run-test-vts: test-vts
@echo Running vts tests...
PATH="$(TEST_RUNTIME_WRAPPERS_PATH):$(PATH)" $(TEST_RUNTIME) $(RUNTIME_FLAGS) $(TEST_HARNESS) -noshadow \
{
[DebuggerDisplay ("Count={Count}")]
[DebuggerTypeProxy (typeof (CollectionDebuggerView<,>))]
+ [Serializable]
public class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>,
ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>,
IDictionary, ICollection, IEnumerable
AddEnumerable (collection);
} else {
_size = c.Count;
- _items = new T [Math.Max (_size, DefaultCapacity)];
+ _items = new T [_size];
c.CopyTo (_items, 0);
}
}
//
// System.Diagnostics.DebuggerTypeProxyAttribute.cs
//
-// Author:
+// Authors:
// Chris Toshok (toshok@novell.com)
+// Marek Safar (marek.safar@gmail.com)
//
//
proxy_type_name = typeName;
}
- public DebuggerTypeProxyAttribute (Type type) {
- proxy_type_name = type.Name;
+ public DebuggerTypeProxyAttribute (Type type)
+ {
+ if (type == null)
+ throw new ArgumentNullException ("type");
+
+ proxy_type_name = type.AssemblyQualifiedName;
}
public string ProxyTypeName {
{
static volatile CultureInfo invariant_culture_info = new CultureInfo (InvariantCultureId, false, true);
static object shared_table_lock = new object ();
- internal static int BootstrapCultureID;
+ static CultureInfo default_current_culture;
#pragma warning disable 169, 649
bool m_isReadOnly;
// Used by Thread.set_CurrentCulture
internal byte[] cached_serialized_form;
- const int InvariantCultureId = 0x7F;
+ internal const int InvariantCultureId = 0x7F;
const int CalendarTypeBits = 8;
const string MSG_READONLY = "This instance is read only";
internal static CultureInfo ConstructCurrentCulture ()
{
- CultureInfo ci = new CultureInfo ();
- if (!ConstructInternalLocaleFromCurrentLocale (ci))
+ if (default_current_culture != null)
+ return default_current_culture;
+
+ var locale_name = get_current_locale_name ();
+ CultureInfo ci = null;
+ try {
+ ci = CreateSpecificCulture (locale_name);
+ } catch {
+ }
+
+ if (ci == null) {
ci = InvariantCulture;
- BootstrapCultureID = ci.cultureID;
+ } else {
+ ci.m_isReadOnly = true;
+ ci.m_useUserOverride = true;
+ }
+
+ default_current_culture = ci;
return ci;
}
}
}
- public static CultureInfo InstalledUICulture
- {
- get { return GetCultureInfo (BootstrapCultureID); }
+ public static CultureInfo InstalledUICulture {
+ get {
+ return ConstructCurrentCulture ();
+ }
}
public bool IsReadOnly {
constructed = true;
}
- static bool ConstructInternalLocaleFromCurrentLocale (CultureInfo ci)
- {
- if (!construct_internal_locale_from_current_locale (ci))
- return false;
- return true;
- }
-
[MethodImplAttribute (MethodImplOptions.InternalCall)]
private extern bool construct_internal_locale_from_lcid (int lcid);
[MethodImplAttribute (MethodImplOptions.InternalCall)]
private extern bool construct_internal_locale_from_name (string name);
-// [MethodImplAttribute (MethodImplOptions.InternalCall)]
-// private extern static bool construct_internal_locale_from_specific_name (CultureInfo ci, string name);
-
[MethodImplAttribute (MethodImplOptions.InternalCall)]
- private extern static bool construct_internal_locale_from_current_locale (CultureInfo ci);
+ private extern static string get_current_locale_name ();
[MethodImplAttribute (MethodImplOptions.InternalCall)]
private extern static CultureInfo [] internal_get_cultures (bool neutral, bool specific, bool installed);
}
if (!construct_internal_locale_from_name (name.ToLowerInvariant ())) {
-#if NET_4_0
- throw new CultureNotFoundException ("name",
- "Culture name " + name + " is not supported.");
-#else
- throw new ArgumentException ("Culture name " + name +
- " is not supported.", "name");
-#endif
+ throw CreateNotFoundException (name);
}
}
if (name.Length == 0)
return InvariantCulture;
- CultureInfo ci = null;
- try {
- ci = new CultureInfo (name);
- } catch (Exception) {
- // TODO: Use construct_internal_locale_from_name when it's not bound to constructor instead
- // of try-catch
+ var src_name = name;
+ name = name.ToLowerInvariant ();
+ CultureInfo ci = new CultureInfo ();
+
+ if (!ci.construct_internal_locale_from_name (name)) {
int idx = name.IndexOf ('-');
- if (idx > 0) {
- try {
- ci = new CultureInfo (name.Substring (0, idx));
- } catch {
- }
- }
-
- if (ci == null)
- throw;
+ if (idx < 1 || !ci.construct_internal_locale_from_name (name.Substring (0, idx)))
+ throw CreateNotFoundException (src_name);
}
- if (!ci.IsNeutralCulture)
- return ci;
+ if (ci.IsNeutralCulture)
+ ci = CreateSpecificCultureFromNeutral (ci.Name);
- return CreateSpecificCultureFromNeutral (ci.Name);
+ return ci;
}
//
return CreateCalendar (1 << CalendarTypeBits); // return invariant calandar if not found
return (Calendar) Activator.CreateInstance (type);
}
+
+ static Exception CreateNotFoundException (string name)
+ {
+#if NET_4_0
+ return new CultureNotFoundException ("name", "Culture name " + name + " is not supported.");
+#else
+ return new ArgumentException ("Culture name " + name + " is not supported.", "name");
+#endif
+ }
#if NET_4_5
- [MonoTODO]
public static CultureInfo DefaultThreadCurrentCulture {
get {
- throw new NotImplementedException ();
+ return Thread.default_culture;
}
set {
- throw new NotImplementedException ();
+ Thread.default_culture = value;
}
}
- [MonoTODO]
public static CultureInfo DefaultThreadCurrentUICulture {
get {
- throw new NotImplementedException ();
+ return Thread.default_ui_culture;
}
set {
- throw new NotImplementedException ();
+ Thread.default_ui_culture = value;
}
}
#endif
{
static RegionInfo currentRegion;
- // This property is not synchronized with CurrentCulture, so
- // we need to use bootstrap CurrentCulture LCID.
public static RegionInfo CurrentRegion {
get {
if (currentRegion == null) {
- // make sure to fill BootstrapCultureID.
CultureInfo ci = CultureInfo.CurrentCulture;
- // If current culture is invariant then region is not available.
- if (ci != null && CultureInfo.BootstrapCultureID != 0x7F)
- currentRegion = new RegionInfo (CultureInfo.BootstrapCultureID);
- else
+ if (ci != null)
+ return currentRegion = new RegionInfo (ci);
+
#if MONOTOUCH
- currentRegion = CreateFromNSLocale ();
-#else
- currentRegion = null;
+ currentRegion = CreateFromNSLocale ();
#endif
}
return currentRegion;
throw new ArgumentException (String.Format ("Region name {0} is not supported.", name), "name");
}
+ RegionInfo (CultureInfo ci)
+ {
+ if (ci.LCID == CultureInfo.InvariantCultureId) {
+ regionId = 244;
+ iso2Name = "IV";
+ iso3Name = "ivc";
+ win3Name = "IVC";
+ nativeName = englishName = "Invariant Country";
+ currencySymbol = "\u00A4";
+ isoCurrencySymbol ="XDR";
+ currencyEnglishName = currencyNativeName = "International Monetary Fund";
+ return;
+ }
+
+ if (ci.Territory == null)
+ throw new NotImplementedException ("Neutral region info");
+
+ construct_internal_region_from_name (ci.Territory.ToUpperInvariant ());
+ }
+
bool GetByTerritory (CultureInfo ci)
{
if (ci == null)
// then don't capitalize it.
int saved = i;
while (++i < str.Length) {
- if (Char.IsWhiteSpace (str [i]))
+ var ch = str [i];
+ var category = char.GetUnicodeCategory (ch);
+ if (IsSeparator (category))
break;
- t = ToTitleCase (str [i]);
- if (t != str [i]) {
+ t = ToTitleCase (ch);
+ if (t != ch) {
allTitle = false;
break;
}
// where we don't have to modify
// the source word.
while (++i < str.Length) {
- if (Char.IsWhiteSpace (str [i]))
+ var ch = str [i];
+ var category = char.GetUnicodeCategory (ch);
+ if (IsSeparator (category))
break;
- if (ToLower (str [i]) != str [i]) {
+ if (ToLower (ch) != ch) {
capitalize = true;
i = saved;
break;
sb.Append (ToTitleCase (str [i]));
start = i + 1;
while (++i < str.Length) {
- if (Char.IsWhiteSpace (str [i]))
+ var ch = str [i];
+ var category = char.GetUnicodeCategory (ch);
+ if (IsSeparator (category))
break;
- sb.Append (ToLower (str [i]));
+ sb.Append (ToLower (ch));
}
start = i;
}
return sb != null ? sb.ToString () : str;
}
+ static bool IsSeparator (UnicodeCategory category)
+ {
+ switch (category) {
+ case UnicodeCategory.SpaceSeparator:
+ case UnicodeCategory.LineSeparator:
+ case UnicodeCategory.ParagraphSeparator:
+ case UnicodeCategory.Control:
+ case UnicodeCategory.Format:
+ case UnicodeCategory.ConnectorPunctuation:
+ case UnicodeCategory.DashPunctuation:
+ case UnicodeCategory.OpenPunctuation:
+ case UnicodeCategory.ClosePunctuation:
+ case UnicodeCategory.InitialQuotePunctuation:
+ case UnicodeCategory.FinalQuotePunctuation:
+ case UnicodeCategory.OtherPunctuation:
+ return true;
+ }
+
+ return false;
+ }
+
// Only Azeri and Turkish have their own special cases.
// Other than them, all languages have common special case
// (enumerable enough).
{
if (index == null || index.Length == 0) {
/*FIXME we should check if the number of arguments matches the expected one, otherwise the error message will be pretty criptic.*/
-#if !MONOTOUCH
+#if !FULL_AOT_RUNTIME
if (cached_getter == null) {
MethodInfo method = GetGetMethod (true);
if (!DeclaringType.IsValueType && !method.ContainsGenericParameters) { //FIXME find a way to build an invoke delegate for value types.
public void SetException (Exception exception)
{
- if (exception is OperationCanceledException) {
- if (Task.TrySetCanceled ())
- return;
- } else {
- if (Task.TrySetException (new AggregateException (exception)))
- return;
- }
+ if (Task.TrySetException (new AggregateException (exception), exception is OperationCanceledException))
+ return;
throw new InvalidOperationException ("The task has already completed");
}
public void SetException (Exception exception)
{
- if (exception is OperationCanceledException) {
- if (Task.TrySetCanceled ())
- return;
- } else {
- if (Task.TrySetException (new AggregateException (exception)))
- return;
- }
+ if (Task.TrySetException (new AggregateException (exception), exception is OperationCanceledException))
+ return;
throw new InvalidOperationException ("The task has already completed");
}
#if NET_4_5
+using System.Threading;
using System.Threading.Tasks;
using System.Runtime.ExceptionServices;
public void GetResult ()
{
+ if (!task.IsCompleted)
+ task.WaitCore (Timeout.Infinite, CancellationToken.None, true);
+
if (task.Status != TaskStatus.RanToCompletion)
ExceptionDispatchInfo.Capture (TaskAwaiter.HandleUnexpectedTaskResult (task)).Throw ();
}
#if NET_4_5
+using System.Threading;
using System.Threading.Tasks;
using System.Runtime.ExceptionServices;
public TResult GetResult ()
{
+ if (!task.IsCompleted)
+ task.WaitCore (Timeout.Infinite, CancellationToken.None, true);
+
if (task.Status != TaskStatus.RanToCompletion)
ExceptionDispatchInfo.Capture (TaskAwaiter.HandleUnexpectedTaskResult (task)).Throw ();
public void GetResult ()
{
if (!task.IsCompleted)
- task.WaitCore (Timeout.Infinite, CancellationToken.None);
+ task.WaitCore (Timeout.Infinite, CancellationToken.None, true);
if (task.Status != TaskStatus.RanToCompletion)
// Merge current and dispatched stack traces if there is any
{
switch (task.Status) {
case TaskStatus.Canceled:
+ // Use original exception when we have one
+ if (task.ExceptionSlot.Exception != null)
+ goto case TaskStatus.Faulted;
+
return new TaskCanceledException (task);
case TaskStatus.Faulted:
- return task.Exception.InnerException;
+ return task.ExceptionSlot.Exception.InnerException;
default:
- throw new ArgumentException ("Should never be reached");
+ throw new ArgumentException (string.Format ("Unexpected task `{0}' status `{1}'", task.Id, task.Status));
}
}
internal static void HandleOnCompleted (Task task, Action continuation, bool continueOnSourceContext, bool manageContext)
{
- if (continueOnSourceContext && SynchronizationContext.Current != null) {
+ if (continueOnSourceContext && SynchronizationContext.Current != null && SynchronizationContext.Current.GetType () != typeof (SynchronizationContext)) {
task.ContinueWith (new SynchronizationContextContinuation (continuation, SynchronizationContext.Current));
} else {
- task.ContinueWith (new ActionContinuation (continuation));
+ IContinuation cont;
+ Task cont_task;
+ if (continueOnSourceContext && TaskScheduler.Current != TaskScheduler.Default) {
+ cont_task = new Task (TaskActionInvoker.Create (continuation), null, CancellationToken.None, TaskCreationOptions.None, null);
+ cont_task.SetupScheduler (TaskScheduler.Current);
+ cont = new SchedulerAwaitContinuation (cont_task);
+ } else {
+ cont_task = null;
+ cont = new ActionContinuation (continuation);
+ }
+
+ //
+ // This is awaiter continuation. For finished tasks we get false result and need to
+ // queue the continuation otherwise the task would block
+ //
+ if (task.ContinueWith (cont, false))
+ return;
+
+ if (cont_task == null) {
+ cont_task = new Task (TaskActionInvoker.Create (continuation), null, CancellationToken.None, TaskCreationOptions.None, null);
+ cont_task.SetupScheduler (TaskScheduler.Current);
+ }
+
+ cont_task.Schedule ();
}
}
public TResult GetResult ()
{
if (!task.IsCompleted)
- task.WaitCore (Timeout.Infinite, CancellationToken.None);
+ task.WaitCore (Timeout.Infinite, CancellationToken.None, true);
if (task.Status != TaskStatus.RanToCompletion)
ExceptionDispatchInfo.Capture (TaskAwaiter.HandleUnexpectedTaskResult (task)).Throw ();
throw new ArgumentNullException ("continuation");
var ctx = SynchronizationContext.Current;
- if (ctx != null) {
+ if (ctx != null && ctx.GetType () != typeof (SynchronizationContext)) {
ctx.Post (l => ((Action) l) (), continuation);
return;
}
--- /dev/null
+#if NET_4_5
+//
+// DefaultInterfaceAttribute.cs
+//
+// Author:
+// Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [AttributeUsageAttribute(AttributeTargets.Class|AttributeTargets.Interface, AllowMultiple = false, Inherited = false)]
+ public sealed class DefaultInterfaceAttribute : Attribute
+ {
+ public Type DefaultInterface {
+ get;
+ private set;
+ }
+
+ public DefaultInterfaceAttribute (Type defaultInterface)
+ {
+ DefaultInterface = defaultInterface;
+ }
+ }
+}
+#endif
--- /dev/null
+#if NET_4_5
+//
+// DesignerNamespaceResolveEventArgs.cs
+//
+// Author:
+// Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.ObjectModel;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [ComVisibleAttribute(false)]
+ public class DesignerNamespaceResolveEventArgs : EventArgs
+ {
+ public DesignerNamespaceResolveEventArgs (string namespaceName)
+ {
+ NamespaceName = namespaceName;
+ ResolvedAssemblyFiles = new Collection<string> ();
+ }
+
+ public string NamespaceName {
+ get;
+ private set;
+ }
+
+ public Collection<string> ResolvedAssemblyFiles {
+ get;
+ private set;
+ }
+ }
+}
+#endif
--- /dev/null
+#if NET_4_5
+//
+// EventRegistrationToken.cs
+//
+// Author:
+// Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ public struct EventRegistrationToken
+ {
+#pragma warning disable 0649
+ long value;
+#pragma warning restore 0649
+
+ public static bool operator == (EventRegistrationToken left, EventRegistrationToken right)
+ {
+ return left.value == right.value;
+ }
+
+ public static bool operator != (EventRegistrationToken left, EventRegistrationToken right)
+ {
+ return left.value != right.value;
+ }
+
+ public override bool Equals (object obj)
+ {
+ return ((EventRegistrationToken)obj).value == value;
+ }
+
+ public override int GetHashCode ()
+ {
+ return unchecked ((int)value);
+ }
+ }
+}
+#endif
--- /dev/null
+#if NET_4_5
+//
+// EventRegistrationTokenTable.cs
+//
+// Author:
+// Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [MonoTODO]
+ public sealed class EventRegistrationTokenTable<T>
+ where T : class
+ {
+ public EventRegistrationTokenTable ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ public T InvocationList {
+ get { throw new NotImplementedException (); }
+ set { throw new NotImplementedException (); }
+ }
+
+ public EventRegistrationToken AddEventHandler (T handler)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static EventRegistrationTokenTable<T> GetOrCreateEventRegistrationTokenTable(ref EventRegistrationTokenTable<T> refEventTable)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public void RemoveEventHandler (T handler)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public void RemoveEventHandler (EventRegistrationToken token)
+ {
+ throw new NotImplementedException ();
+ }
+ }
+}
+#endif
+
--- /dev/null
+#if NET_4_5
+//
+// IActivationFactory.cs
+//
+// Author:
+// Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [Guid("00000035-0000-0000-C000-000000000046")]
+ public interface IActivationFactory
+ {
+ object ActivateInstance ();
+ }
+}
+#endif
--- /dev/null
+#if NET_4_5
+//
+// InterfaceImplementedInVersionAttribute.cs
+//
+// Author:
+// Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [AttributeUsageAttribute(AttributeTargets.Class|AttributeTargets.Interface, AllowMultiple = false, Inherited = false)]
+ public sealed class InterfaceImplementedInVersionAttribute : Attribute
+ {
+ public InterfaceImplementedInVersionAttribute (Type interfaceType, byte majorVersion, byte minorVersion,
+ byte buildVersion, byte revisionVersion)
+ {
+ InterfaceType = interfaceType;
+ MajorVersion = majorVersion;
+ MinorVersion = minorVersion;
+ BuildVersion = buildVersion;
+ RevisionVersion = revisionVersion;
+ }
+
+ public byte BuildVersion {
+ get;
+ private set;
+ }
+
+ public Type InterfaceType {
+ get;
+ private set;
+ }
+
+ public byte MajorVersion {
+ get;
+ private set;
+ }
+
+ public byte MinorVersion {
+ get;
+ private set;
+ }
+
+ public byte RevisionVersion {
+ get;
+ private set;
+ }
+ }
+}
+#endif
--- /dev/null
+#if NET_4_5
+//
+// NamespaceResolveEventArgs.cs
+//
+// Author:
+// Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Reflection;
+using System.Collections.ObjectModel;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [ComVisibleAttribute(false)]
+ public class NamespaceResolveEventArgs : EventArgs
+ {
+ public NamespaceResolveEventArgs (string namespaceName, Assembly requestingAssembly)
+ {
+ NamespaceName = namespaceName;
+ RequestingAssembly = requestingAssembly;
+ ResolvedAssemblies = new Collection<Assembly> ();
+ }
+
+ public string NamespaceName {
+ get;
+ private set;
+ }
+
+ public Assembly RequestingAssembly {
+ get;
+ private set;
+ }
+
+ public Collection<Assembly> ResolvedAssemblies {
+ get;
+ private set;
+ }
+ }
+}
+#endif
--- /dev/null
+#if NET_4_5
+//
+// ReadOnlyArrayAttribute.cs
+//
+// Author:
+// Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [AttributeUsageAttribute(AttributeTargets.Parameter, Inherited = false, AllowMultiple = false)]
+ public sealed class ReadOnlyArrayAttribute : Attribute
+ {
+ }
+}
+#endif
--- /dev/null
+//
+// ReturnValueNameAttribute.cs
+//
+// Author:
+// Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [AttributeUsageAttribute(AttributeTargets.Delegate|AttributeTargets.ReturnValue, AllowMultiple = false, Inherited = false)]
+ public sealed class ReturnValueNameAttribute : Attribute
+ {
+ public ReturnValueNameAttribute (string name)
+ {
+ Name = name;
+ }
+
+ public string Name {
+ get;
+ private set;
+ }
+ }
+}
--- /dev/null
+#if NET_4_5
+//
+// WindowsRuntimeMarshal.cs
+//
+// Author:
+// Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [MonoTODO]
+ public static class WindowsRuntimeMarshal
+ {
+ public static void AddEventHandler<T> ( Func<T, EventRegistrationToken> addMethod, Action<EventRegistrationToken> removeMethod, T handler)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static void FreeHString (IntPtr ptr)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static IActivationFactory GetActivationFactory (Type type)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static string PtrToStringHString (IntPtr ptr)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static void RemoveAllEventHandlers(Action<EventRegistrationToken> removeMethod)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static void RemoveEventHandler<T> (Action<EventRegistrationToken> removeMethod, T handler)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static IntPtr StringToHString (string s)
+ {
+ throw new NotImplementedException ();
+ }
+ }
+}
+#endif
+
--- /dev/null
+#if NET_4_5
+//
+// WindowsRuntimeMetadata.cs
+//
+// Author:
+// Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [MonoTODO]
+ public static class WindowsRuntimeMetadata
+ {
+ public static IEnumerable<string> ResolveNamespace (string namespaceName, IEnumerable<string> packageGraphFilePaths)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public static IEnumerable<string> ResolveNamespace (string namespaceName, string windowsSdkFilePath, IEnumerable<string> packageGraphFilePaths)
+ {
+ throw new NotImplementedException ();
+ }
+
+#pragma warning disable 0067
+ public static event EventHandler<DesignerNamespaceResolveEventArgs> DesignerNamespaceResolve;
+ public static event EventHandler<NamespaceResolveEventArgs> ReflectionOnlyNamespaceResolve;
+#pragma warning restore 0067
+ }
+}
+#endif
+
--- /dev/null
+#if NET_4_5
+//
+// WriteOnlyArrayAttribute.cs
+//
+// Author:
+// Martin Baulig <martin.baulig@xamarin.com>
+//
+// Copyright (c) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [AttributeUsageAttribute(AttributeTargets.Parameter, Inherited = false, AllowMultiple = false)]
+ public sealed class WriteOnlyArrayAttribute : Attribute
+ {
+ }
+}
+#endif
public sealed class CallContext
{
[ThreadStatic] static Header [] Headers;
+ [ThreadStatic] static Hashtable logicalDatastore;
[ThreadStatic] static Hashtable datastore;
[ThreadStatic] static object hostContext;
public static void FreeNamedDataSlot (string name)
{
Datastore.Remove (name);
+ LogicalDatastore.Remove (name);
}
public static object GetData (string name)
{
- return Datastore [name];
+ if (LogicalDatastore.ContainsKey (name)) {
+ return LogicalDatastore [name];
+ } else {
+ return Datastore [name];
+ }
}
public static void SetData (string name, object data)
{
- Datastore [name] = data;
+ if (data is ILogicalThreadAffinative) {
+ LogicalSetData (name, data);
+ } else {
+ LogicalDatastore.Remove (name);
+ Datastore [name] = data;
+ }
}
-
- [MonoTODO]
+
public static object LogicalGetData (string name)
{
- throw new NotImplementedException ();
+ return LogicalDatastore [name];
}
-
- [MonoTODO]
+
public static void LogicalSetData (string name, object data)
{
- throw new NotImplementedException ();
+ Datastore.Remove (name);
+ LogicalDatastore [name] = data;
}
public static Header[] GetHeaders ()
internal static LogicalCallContext CreateLogicalCallContext (bool createEmpty)
{
LogicalCallContext ctx = null;
- if (datastore != null) {
- foreach (DictionaryEntry entry in datastore)
- if (entry.Value is ILogicalThreadAffinative) {
- if (ctx == null) ctx = new LogicalCallContext ();
- ctx.SetData ((string)entry.Key, entry.Value);
- }
+ if (logicalDatastore != null) {
+ ctx = new LogicalCallContext ();
+ foreach (DictionaryEntry entry in logicalDatastore) {
+ ctx.SetData ((string)entry.Key, entry.Value);
+ }
}
if (ctx == null && createEmpty)
internal static object SetCurrentCallContext (LogicalCallContext ctx)
{
- object oldData = datastore;
+ object oldData = new object[] { datastore, logicalDatastore };
if (ctx != null && ctx.HasInfo)
- datastore = (Hashtable) ctx.Datastore.Clone ();
+ logicalDatastore = (Hashtable) ctx.Datastore.Clone ();
else
- datastore = null;
+ logicalDatastore = null;
return oldData;
}
- internal static void UpdateCurrentCallContext (LogicalCallContext ctx)
+ internal static void UpdateCurrentLogicalCallContext (LogicalCallContext ctx)
{
Hashtable data = ctx.Datastore;
+ if (data == null)
+ return;
+
foreach (DictionaryEntry entry in data)
- SetData ((string)entry.Key, entry.Value);
+ LogicalSetData ((string)entry.Key, entry.Value);
}
internal static void RestoreCallContext (object oldContext)
{
- datastore = (Hashtable) oldContext;
+ object[] contextArray = (object[])oldContext;
+ datastore = (Hashtable)contextArray [0];
+ logicalDatastore = (Hashtable)contextArray [1];
}
private static Hashtable Datastore
return r;
}
}
+
+ private static Hashtable LogicalDatastore
+ {
+ get {
+ Hashtable r = logicalDatastore;
+ if (r == null)
+ return logicalDatastore = new Hashtable ();
+ return r;
+ }
+ }
}
[System.Runtime.InteropServices.ComVisible (true)]
}
if (res_msg.LogicalCallContext != null && res_msg.LogicalCallContext.HasInfo)
- CallContext.UpdateCurrentCallContext (res_msg.LogicalCallContext);
+ CallContext.UpdateCurrentLogicalCallContext (res_msg.LogicalCallContext);
exc = res_msg.Exception;
if (obj is CACD) {
CACD cad = (CACD) obj;
obj = cad.d;
- CallContext.UpdateCurrentCallContext ((LogicalCallContext) cad.c);
+ CallContext.UpdateCurrentLogicalCallContext ((LogicalCallContext) cad.c);
}
return obj;
}
}
Schedule ();
- Wait ();
+ WaitCore (Timeout.Infinite, CancellationToken.None, false);
}
#endregion
ContinueWith (new TaskContinuation (continuation, options));
}
- internal void ContinueWith (IContinuation continuation)
+ internal bool ContinueWith (IContinuation continuation, bool canExecuteInline = true)
{
if (IsCompleted) {
+ if (!canExecuteInline)
+ return false;
+
continuation.Execute ();
- return;
+ return true;
}
continuations.Add (continuation);
// Retry in case completion was achieved but event adding was too late
- if (IsCompleted && continuations.Remove (continuation))
+ if (IsCompleted) {
+ continuations.Remove (continuation);
+ if (!canExecuteInline)
+ return false;
+
continuation.Execute ();
+ }
+
+ return true;
}
internal void RemoveContinuation (IContinuation continuation)
return true;
}
- internal bool TrySetException (AggregateException aggregate)
+ internal bool TrySetException (AggregateException aggregate, bool cancellation)
{
if (IsCompleted)
return false;
return false;
}
-
- HandleGenericException (aggregate);
+
+ if (cancellation) {
+ ExceptionSlot.Exception = aggregate;
+ Thread.MemoryBarrier ();
+
+ CancelReal ();
+ } else {
+ HandleGenericException (aggregate);
+ }
+
return true;
}
if (millisecondsTimeout < -1)
throw new ArgumentOutOfRangeException ("millisecondsTimeout");
- bool result = WaitCore (millisecondsTimeout, cancellationToken);
+ bool result = WaitCore (millisecondsTimeout, cancellationToken, true);
if (IsCanceled)
throw new AggregateException (new TaskCanceledException (this));
return result;
}
- internal bool WaitCore (int millisecondsTimeout, CancellationToken cancellationToken)
+ internal bool WaitCore (int millisecondsTimeout, CancellationToken cancellationToken, bool runInline)
{
if (IsCompleted)
return true;
// If the task is ready to be run and we were supposed to wait on it indefinitely without cancellation, just run it
- if (Status == TaskStatus.WaitingToRun && millisecondsTimeout == Timeout.Infinite && scheduler != null && !cancellationToken.CanBeCanceled)
+ if (runInline && Status == TaskStatus.WaitingToRun && millisecondsTimeout == Timeout.Infinite && scheduler != null && !cancellationToken.CanBeCanceled)
scheduler.RunInline (this, true);
bool result = true;
internal static Task<TResult[]> WhenAllCore<TResult> (IList<Task<TResult>> tasks)
{
+ if (tasks.Count == 0)
+ return FromResult(new TResult[0]);
+
foreach (var t in tasks) {
if (t == null)
throw new ArgumentException ("tasks", "the tasks argument contains a null element");
public AggregateException Exception {
get {
- if (exSlot == null)
+ if (exSlot == null || !IsFaulted)
return null;
exSlot.Observed = true;
return exSlot.Exception;
}
}
- TaskExceptionSlot ExceptionSlot {
+ internal TaskExceptionSlot ExceptionSlot {
get {
if (exSlot != null)
return exSlot;
if (aggregate.InnerExceptions.Count == 0)
throw new ArgumentNullException ("exceptions");
- return source.TrySetException (aggregate);
+ return source.TrySetException (aggregate, false);
}
public bool TrySetResult (TResult result)
}
}
+ class SchedulerAwaitContinuation : IContinuation
+ {
+ readonly Task task;
+
+ public SchedulerAwaitContinuation (Task task)
+ {
+ this.task = task;
+ }
+
+ public void Execute ()
+ {
+ task.RunSynchronouslyCore (task.scheduler);
+ }
+ }
+
class SynchronizationContextContinuation : IContinuation
{
readonly Action action;
}
if (exceptions != null) {
- owner.TrySetException (new AggregateException (exceptions));
+ owner.TrySetException (new AggregateException (exceptions), false);
return;
}
}
if (exceptions != null) {
- owner.TrySetException (new AggregateException (exceptions));
+ owner.TrySetException (new AggregateException (exceptions), false);
return;
}
TaskCreationOptions creationOptions,
TaskScheduler scheduler)
{
- Task<TResult> t = new Task<TResult> (function, state, cancellationToken, creationOptions);
- t.Start (scheduler);
+ var t = new Task<TResult> (function, state, cancellationToken, creationOptions);
+ //
+ // Don't start cancelled task it would throw an exception
+ //
+ if (!t.IsCompleted)
+ t.Start (scheduler);
+
return t;
}
#endregion
if (stopCondition ())
return false;
- if (wait.Count > spinCount)
- handle.WaitOne (Math.Min (Math.Max (millisecondsTimeout - (int)sw.ElapsedMilliseconds, 1), deepSleepTime));
- else
+ if (wait.Count > spinCount) {
+ int timeout = millisecondsTimeout < 0 ? deepSleepTime :
+ Math.Min (Math.Max (millisecondsTimeout - (int)sw.ElapsedMilliseconds, 1), deepSleepTime);
+ handle.WaitOne (timeout);
+ } else
wait.SpinOnce ();
}
} while (true);
IPrincipal principal;
int principal_version;
+ bool current_culture_set;
+ bool current_ui_culture_set;
CultureInfo current_culture;
CultureInfo current_ui_culture;
static NamedDataSlot namedDataSlot;
+ static internal CultureInfo default_culture;
+ static internal CultureInfo default_ui_culture;
+
// can be both a ThreadStart and a ParameterizedThreadStart
private MulticastDelegate threadstart;
//private string thread_name=null;
public CultureInfo CurrentCulture {
get {
CultureInfo culture = current_culture;
- if (culture != null)
+ if (current_culture_set && culture != null)
return culture;
+ if (default_culture != null)
+ return default_culture;
+
current_culture = culture = CultureInfo.ConstructCurrentCulture ();
- NumberFormatter.SetThreadCurrentCulture (culture);
return culture;
}
value.CheckNeutral ();
current_culture = value;
- NumberFormatter.SetThreadCurrentCulture (value);
+ current_culture_set = true;
}
}
public CultureInfo CurrentUICulture {
get {
CultureInfo culture = current_ui_culture;
- if (culture != null)
+ if (current_ui_culture_set && culture != null)
return culture;
+ if (default_ui_culture != null)
+ return default_ui_culture;
+
current_ui_culture = culture = CultureInfo.ConstructCurrentUICulture ();
return culture;
}
if (value == null)
throw new ArgumentNullException ("value");
current_ui_culture = value;
+ current_ui_culture_set = true;
}
}
T IList<T>.this[int index] {
get {
- if (index < 0 || count < index)
+ if (index < 0 || index >= count)
throw new ArgumentOutOfRangeException ("index");
return array[offset + index];
}
set {
- if (index < 0 || count < index)
+ if (index < 0 || index >= count)
throw new ArgumentOutOfRangeException ("index");
array[offset + index] = value;
public override int GetHashCode ()
{
- int result = TypeId.GetHashCode ();
+ int result = GetType ().GetHashCode ();
FieldInfo[] fields = GetType ().GetFields (BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
foreach (FieldInfo field in fields) {
[Serializable]
public struct ConsoleKeyInfo {
internal static ConsoleKeyInfo Empty = new ConsoleKeyInfo ('\0', 0, false, false, false);
- ConsoleKey key;
- char keychar;
- ConsoleModifiers modifiers;
+ ConsoleKey _key;
+ char _keyChar;
+ ConsoleModifiers _mods;
public ConsoleKeyInfo (char keyChar, ConsoleKey key, bool shift, bool alt, bool control)
{
- this.key = key;
- this.keychar = keyChar;
- modifiers = 0;
+ _key = key;
+ _keyChar = keyChar;
+ _mods = 0;
SetModifiers (shift, alt, control);
}
internal ConsoleKeyInfo (ConsoleKeyInfo other)
{
- this.key = other.key;
- this.keychar = other.keychar;
- this.modifiers = other.modifiers;
+ _key = other._key;
+ _keyChar = other._keyChar;
+ _mods = other._mods;
}
internal void SetKey (ConsoleKey key)
{
- this.key = key;
+ _key = key;
}
internal void SetKeyChar (char keyChar)
{
- this.keychar = keyChar;
+ _keyChar = keyChar;
}
internal void SetModifiers (bool shift, bool alt, bool control)
{
- this.modifiers = (shift) ? ConsoleModifiers.Shift : 0;
- this.modifiers |= (alt) ? ConsoleModifiers.Alt : 0;
- this.modifiers |= (control) ? ConsoleModifiers.Control : 0;
+ _mods = (shift) ? ConsoleModifiers.Shift : 0;
+ _mods |= (alt) ? ConsoleModifiers.Alt : 0;
+ _mods |= (control) ? ConsoleModifiers.Control : 0;
}
- public ConsoleKey Key {
- get { return key; }
+ public ConsoleKey Key
+ {
+ get { return _key; }
}
- public char KeyChar {
- get { return keychar; }
+ public char KeyChar
+ {
+ get { return _keyChar; }
}
- public ConsoleModifiers Modifiers {
- get { return modifiers; }
+ public ConsoleModifiers Modifiers
+ {
+ get { return _mods; }
}
-
+
public override bool Equals (object value)
{
if (!(value is ConsoleKeyInfo))
return false;
+
return Equals ((ConsoleKeyInfo) value);
}
-
+
public static bool operator == (ConsoleKeyInfo a, ConsoleKeyInfo b)
{
return a.Equals (b);
}
-
+
public static bool operator != (ConsoleKeyInfo a, ConsoleKeyInfo b)
{
return !a.Equals (b);
}
-
+
public bool Equals (ConsoleKeyInfo obj)
{
- return key == obj.key && obj.keychar == keychar && obj.modifiers == modifiers;
+ return _key == obj._key && _keyChar == obj._keyChar && _mods == obj._mods;
}
-
+
public override int GetHashCode ()
{
- return key.GetHashCode () ^ keychar.GetHashCode () ^ modifiers.GetHashCode ();
+ return _key.GetHashCode () ^ _keyChar.GetHashCode () ^ _mods.GetHashCode ();
}
}
}
-
return source;
if (source.GetType () != value.GetType ())
- throw new ArgumentException ("Delegate type mismatch");
+ throw new ArgumentException (Locale.GetText ("Incompatible Delegate Types. First is {0} second is {1}.", source.GetType ().FullName, value.GetType ().FullName));
return source.RemoveImpl (value);
}
* of icalls, do not require an increment.
*/
#pragma warning disable 169
- private const int mono_corlib_version = 110;
+ private const int mono_corlib_version = 111;
#pragma warning restore 169
[ComVisible (true)]
private void Resize (int len)
{
- char[] newBuf = new char [len];
- Array.Copy (_cbuf, newBuf, _ind);
- _cbuf = newBuf;
+ Array.Resize (ref _cbuf, len);
}
private void Append (char c)
threadNumberFormatter = null;
if (res == null)
return new NumberFormatter (Thread.CurrentThread);
+ res.CurrentCulture = Thread.CurrentThread.CurrentCulture;
return res;
}
threadNumberFormatter = this;
}
- internal static void SetThreadCurrentCulture (CultureInfo culture)
- {
- if (threadNumberFormatter != null)
- threadNumberFormatter.CurrentCulture = culture;
- }
-
public static string NumberToString (string format, sbyte value, IFormatProvider fp)
{
NumberFormatter inst = GetInstance();
if (values == null)
throw new ArgumentNullException ("values");
- var stringList = new List<string> ();
- foreach (var v in values)
- stringList.Add (v.ToString ());
+ var stringList = values as IList<T> ?? new List<T> (values);
+ var strCopy = new string [stringList.Count];
+ int i = 0;
+ foreach (var v in stringList)
+ strCopy [i++] = v.ToString ();
- return JoinUnchecked (separator, stringList.ToArray (), 0, stringList.Count);
+ return JoinUnchecked (separator, strCopy, 0, strCopy.Length);
}
public static bool IsNullOrWhiteSpace (string value)
if (time.Kind == DateTimeKind.Utc)
return TimeSpan.Zero;
- if (IsDaylightSavingTime (time))
+ if (IsDaylightSavingTime (time) && !IsAmbiguousTime (time))
return utcOffsetWithDLS;
return utcOffsetWithOutDLS;
}
+ private bool IsAmbiguousTime (DateTime time)
+ {
+ if (time.Kind == DateTimeKind.Utc)
+ return false;
+
+ DaylightTime changes = GetDaylightChanges (time.Year);
+
+ return time < changes.End && time >= changes.End - changes.Delta;
+ }
+
void IDeserializationCallback.OnDeserialization (object sender)
{
OnDeserialization (null);
}
[Test]
+ // This hangs on windows
+ [Category ("NotWorking")]
public void OpenRemoteBaseKey_MachineName_DoesNotExist ()
{
// access to registry of remote machines is not implemented on unix
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-#if NET_2_0
-
using System;
using System.Collections;
using System.Collections.Generic;
Assert.AreEqual (l1.Count, l1.Capacity);
for (int i = 0; i < l1.Count; i++)
Assert.AreEqual (_list1 [i], l1 [i]);
+
+ var input = new [] { "a", "b", "c" };
+ var l2 = new List<string>(input);
+ Assert.AreEqual (3, l2.Capacity);
}
[Test, ExpectedException (typeof (ArgumentNullException))]
}
}
-#endif
//
-// MonoTests.System.Diagnostics.DebuggerDisplayAttributeTest.cs
+// DebuggerDisplayAttributeTest.cs
//
// Author:
// Rolf Bjarne Kvinge (RKvinge@novell.com)
// (C) 2007
//
-#if NET_2_0
-
using System;
using System.Diagnostics;
using NUnit.Framework;
}
}
}
-
-#endif
\ No newline at end of file
--- /dev/null
+//
+// DecoupledTask.cs
+//
+// Authors:
+// Marek Safar <marek.safar@gmail.com>
+//
+// Copyright 2013 Xamarin Inc (http://www.xamarin.com).
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+//
+
+using System;
+using System.Diagnostics;
+using NUnit.Framework;
+
+namespace MonoTests.System.Diagnostics
+{
+ [TestFixture]
+ public class DebuggerTypeProxyAttributeTest
+ {
+ [Test]
+ public void Constructor_Type ()
+ {
+ var dtp = new DebuggerTypeProxyAttribute (typeof (string));
+ Assert.IsNull (dtp.Target, "#1");
+ Assert.AreEqual (typeof (string).AssemblyQualifiedName, dtp.ProxyTypeName, "#2");
+ }
+
+ [Test]
+ public void Constructor_Type_Invalid ()
+ {
+ try {
+ new DebuggerTypeProxyAttribute (null as Type);
+ Assert.Fail ();
+ } catch (ArgumentNullException) {
+ }
+ }
+ }
+}
/// Tests whether getting file name works.
/// </summary>
[Test]
+ [Category("LLVMNotWorking")]
public void TestGetFileName ()
{
Assert.AreEqual ("dir/someFile",
/// Tests whether getting file line number works.
/// </summary>
[Test]
+ [Category("LLVMNotWorking")]
public void TestGetFileLineNumber ()
{
Assert.AreEqual (13,
}
[Test]
+ [Category ("LLVMNotWorking")]
public void TestGetFileName2 ()
{
Assert.IsNotNull (frame2.GetFileName (), "File name not null");
/// Tests whether getting file line number works.
/// </summary>
[Test]
+ [Category ("LLVMNotWorking")]
public void TestGetFileLineNumber ()
{
Assert.AreEqual (0,
frame1.GetFileLineNumber (),
"Line number (1)");
- Assert.AreEqual (132,
+ Assert.AreEqual (134,
frame2.GetFileLineNumber (),
"Line number (2)");
/// Tests whether getting file name works.
/// </summary>
[Test]
+ [Category ("LLVMNotWorking")]
public void TestGetFileName ()
{
Assert.IsNull (frame1.GetFileName (),
#if ONLY_1_1
[Category ("NotDotNet")] // .NET 1.1 is off by one
#endif
+ [Category ("LLVMNotWorking")]
public void TestGetFileLineNumber ()
{
Assert.AreEqual (0,
frame1.GetFileLineNumber (),
"Line number (1)");
- Assert.AreEqual (260,
+ Assert.AreEqual (264,
frame2.GetFileLineNumber (),
"Line number (2)");
}
// https://bugzilla.xamarin.com/show_bug.cgi?id=3471
new CultureInfo ("en-HK");
}
+
+#if NET_4_5
+ CountdownEvent barrier = new CountdownEvent (3);
+ AutoResetEvent[] evt = new AutoResetEvent [] { new AutoResetEvent (false), new AutoResetEvent (false), new AutoResetEvent (false)};
+
+ CultureInfo[] initial_culture = new CultureInfo[3];
+ CultureInfo[] changed_culture = new CultureInfo[3];
+ CultureInfo[] changed_culture2 = new CultureInfo[3];
+ CultureInfo alternative_culture = new CultureInfo("pt-BR");
+
+ void StepAllPhases (int index)
+ {
+ initial_culture [index] = CultureInfo.CurrentCulture;
+ /*Phase 1 - we witness the original value */
+ barrier.Signal ();
+
+ /*Phase 2 - main thread changes culture */
+ evt [index].WaitOne ();
+
+ /*Phase 3 - we witness the new value */
+ changed_culture [index] = CultureInfo.CurrentCulture;
+ barrier.Signal ();
+
+ /* Phase 4 - main thread changes culture back */
+ evt [index].WaitOne ();
+
+ /*Phase 5 - we witness the new value */
+ changed_culture2 [index] = CultureInfo.CurrentCulture;
+ barrier.Signal ();
+ }
+
+ void ThreadWithoutChange () {
+ StepAllPhases (0);
+ }
+
+ void ThreadWithChange () {
+ Thread.CurrentThread.CurrentCulture = alternative_culture;
+ StepAllPhases (1);
+ }
+
+ void ThreadPoolWithoutChange () {
+ StepAllPhases (2);
+ }
+
+ [Test]
+ public void DefaultThreadCurrentCulture () {
+ var orig_culture = CultureInfo.CurrentCulture;
+ var new_culture = new CultureInfo("fr-FR");
+
+ // The test doesn't work if the current culture is already set
+ if (orig_culture != CultureInfo.InvariantCulture)
+ return;
+
+ /* Phase 0 - warm up */
+ new Thread (ThreadWithoutChange).Start ();
+ new Thread (ThreadWithChange).Start ();
+ Action x = ThreadPoolWithoutChange;
+ x.BeginInvoke (null, null);
+
+ /* Phase 1 - let everyone witness initial values */
+ initial_culture [0] = CultureInfo.CurrentCulture;
+ barrier.Wait ();
+ barrier.Reset ();
+
+ /* Phase 2 - change the default culture*/
+ CultureInfo.DefaultThreadCurrentCulture = new_culture;
+ evt [0].Set ();
+ evt [1].Set ();
+ evt [2].Set ();
+ /* Phase 3 - let everyone witness the new value */
+ changed_culture [0] = CultureInfo.CurrentCulture;
+ barrier.Wait ();
+ barrier.Reset ();
+
+ /* Phase 4 - revert the default culture back to null */
+ CultureInfo.DefaultThreadCurrentCulture = null;
+ evt [0].Set ();
+ evt [1].Set ();
+ evt [2].Set ();
+
+ /* Phase 5 - let everyone witness the new value */
+ changed_culture2 [0] = CultureInfo.CurrentCulture;
+ barrier.Wait ();
+ barrier.Reset ();
+
+ CultureInfo.DefaultThreadCurrentCulture = null;
+
+ Assert.AreEqual (orig_culture, initial_culture [0], "#2");
+ Assert.AreEqual (alternative_culture, initial_culture [1], "#3");
+ Assert.AreEqual (orig_culture, initial_culture [2], "#4");
+
+ Assert.AreEqual (new_culture, changed_culture [0], "#6");
+ Assert.AreEqual (alternative_culture, changed_culture [1], "#7");
+ Assert.AreEqual (new_culture, changed_culture [2], "#8");
+
+ Assert.AreEqual (orig_culture, changed_culture2 [0], "#10");
+ Assert.AreEqual (alternative_culture, changed_culture2 [1], "#11");
+ Assert.AreEqual (orig_culture, changed_culture2 [2], "#12");
+ }
+
+ [Test]
+ public void DefaultThreadCurrentCultureAndNumberFormaters () {
+ string us_str = null;
+ string br_str = null;
+ var thread = new Thread (() => {
+ CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");
+ us_str = 100000.ToString ("C");
+ CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("pt-BR");
+ br_str = 100000.ToString ("C");
+ });
+ thread.Start ();
+ thread.Join ();
+ CultureInfo.DefaultThreadCurrentCulture = null;
+ Assert.AreEqual ("$100,000.00", us_str, "#1");
+ Assert.AreEqual ("R$ 100.000,00", br_str, "#2");
+ }
+#endif
}
}
--- /dev/null
+//
+// NumberFormatInfoTest.cs
+//
+// Authors:
+// Marek Safar (marek.safar@gmail.com)
+//
+// Copyright (C) 2013 Xamarin Inc (http://www.xamarin.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+
+using NUnit.Framework;
+using System;
+using System.Globalization;
+
+namespace MonoTests.System.Globalization
+{
+ [TestFixture]
+ public class NumberFormatInfoTest
+ {
+ [Test]
+ public void CurrencyDecimalDigits ()
+ {
+ CultureInfo c;
+
+ c = CultureInfo.GetCultureInfo ("id-ID");
+ Assert.AreEqual (0, c.NumberFormat.CurrencyDecimalDigits, "#1");
+
+ c = CultureInfo.GetCultureInfo ("is-IS");
+ Assert.AreEqual (0, c.NumberFormat.CurrencyDecimalDigits, "#2");
+
+ c = CultureInfo.InvariantCulture;
+ Assert.AreEqual (2, c.NumberFormat.CurrencyDecimalDigits, "#3");
+
+ }
+ }
+}
+
+
{
TextInfo ti = new CultureInfo ("en-US", false).TextInfo;
- Assert.AreEqual (" The Dog", ti.ToTitleCase (" the dog"));
- Assert.AreEqual (" The Dude", ti.ToTitleCase (" The Dude"));
- Assert.AreEqual ("La Guerra Yla Paz", ti.ToTitleCase ("la Guerra yLa pAz"));
- Assert.AreEqual ("\tTab\tAnd\tPeace", ti.ToTitleCase ("\ttab\taNd\tpeaCE"));
+ Assert.AreEqual (" The Dog", ti.ToTitleCase (" the dog"), "#1");
+ Assert.AreEqual (" The Dude", ti.ToTitleCase (" The Dude"), "#2");
+ Assert.AreEqual ("La Guerra Yla Paz", ti.ToTitleCase ("la Guerra yLa pAz"), "#3");
+ Assert.AreEqual ("\tTab\tAnd\tPeace", ti.ToTitleCase ("\ttab\taNd\tpeaCE"), "#4");
+ Assert.AreEqual ("This_Is\uFE58A\u0095String\u06D4With\uFE33Separators", ti.ToTitleCase ("this_is\uFE58a\u0095string\u06D4with\uFE33separators"), "#5");
}
[Test]
Activator.CreateInstance (t, new object[] { "string"});
}
+ public interface IFace16096 {
+ object Bar ();
+ }
+
+ [Test]
+ public void MemberRef_Caching_16096 () {
+ var outer_class = module.DefineType(
+ "container",
+ TypeAttributes.Class | TypeAttributes.Public,
+ typeof(object));
+
+ var builder = outer_class.DefineNestedType(
+ "bind@32-1",
+ TypeAttributes.Class | TypeAttributes.Public,
+ typeof(object));
+
+ builder.AddInterfaceImplementation (typeof (IFace16096));
+
+ var ctor = builder.DefineDefaultConstructor (MethodAttributes.Public);
+ var field = builder.DefineField ("Field", typeof (object), FieldAttributes.Public);
+ var g_args = builder.DefineGenericParameters("b","a");
+ var method = builder.DefineMethod ("Bar", MethodAttributes.Public | MethodAttributes.Virtual, typeof (object), new Type [0]);
+
+ var il = method.GetILGenerator();
+ il.Emit (OpCodes.Ldarg_0);
+ il.Emit (OpCodes.Ldfld, TypeBuilder.GetField (builder.MakeGenericType (g_args), field));
+ il.Emit (OpCodes.Pop);
+ il.Emit (OpCodes.Newobj, TypeBuilder.GetConstructor (builder.MakeGenericType (g_args), ctor));
+ il.Emit (OpCodes.Ret);
+
+ var type = builder.CreateType ();
+
+ /*Build a gshared instance. */
+ var ginst = type.MakeGenericType (typeof (List<char>), typeof (object));
+ var ins = (IFace16096)Activator.CreateInstance (ginst);
+
+ /* This will trigger the runtime to cache the MEMBER_REF to the .ctor as it won't have a context. */
+ var ins2 = ins.Bar ();
+ Assert.IsNotNull (ins2);
+
+ /* Build an unsharable version. */
+ var ginst2 = type.MakeGenericType (typeof (List<char>), typeof (char));
+ var ins3 = (IFace16096)Activator.CreateInstance (ginst2);
+
+ /* This will trigger the runtime to use the cached version, which is wrong as it's an open type. */
+ var ins4 = ins3.Bar ();
+ Assert.IsNotNull (ins4);
+ }
}
}
using System.Threading.Tasks;
using NUnit.Framework;
using System.Runtime.CompilerServices;
+using System.Collections.Generic;
namespace MonoTests.System.Runtime.CompilerServices
{
[TestFixture]
public class TaskAwaiterTest
{
+ class Scheduler : TaskScheduler
+ {
+ string name;
+
+ public Scheduler (string name)
+ {
+ this.name = name;
+ }
+
+ public int InlineCalls { get; set; }
+ public int QueueCalls { get; set; }
+
+ protected override IEnumerable<Task> GetScheduledTasks ()
+ {
+ throw new NotImplementedException ();
+ }
+
+ protected override void QueueTask (Task task)
+ {
+ ++QueueCalls;
+ ThreadPool.QueueUserWorkItem (o => {
+ TryExecuteTask (task);
+ });
+ }
+
+ protected override bool TryExecuteTaskInline (Task task, bool taskWasPreviouslyQueued)
+ {
+ ++InlineCalls;
+ return false;
+ }
+ }
+
[Test]
public void GetResultFaulted ()
{
awaiter.GetResult ();
Assert.AreEqual (TaskStatus.RanToCompletion, task.Status);
}
+
+ [Test]
+ public void CustomScheduler ()
+ {
+ // some test runners (e.g. Touch.Unit) will execute this on the main thread and that would lock them
+ if (!Thread.CurrentThread.IsBackground)
+ return;
+
+ var a = new Scheduler ("a");
+ var b = new Scheduler ("b");
+
+ var t = TestCS (a, b);
+ Assert.IsTrue (t.Wait (3000), "#0");
+ Assert.AreEqual (0, t.Result, "#1");
+ Assert.AreEqual (1, a.InlineCalls, "#2a");
+ Assert.AreEqual (0, b.InlineCalls, "#2b");
+ Assert.AreEqual (2, a.QueueCalls, "#3a");
+ Assert.AreEqual (1, b.QueueCalls, "#3b");
+ }
+
+ static async Task<int> TestCS (TaskScheduler schedulerA, TaskScheduler schedulerB)
+ {
+ var res = await Task.Factory.StartNew (async () => {
+ if (TaskScheduler.Current != schedulerA)
+ return 1;
+
+ await Task.Factory.StartNew (
+ () => {
+ if (TaskScheduler.Current != schedulerB)
+ return 2;
+
+ return 0;
+ }, CancellationToken.None, TaskCreationOptions.None, schedulerB);
+
+ if (TaskScheduler.Current != schedulerA)
+ return 3;
+
+ return 0;
+ }, CancellationToken.None, TaskCreationOptions.None, schedulerA);
+
+ return res.Result;
+ }
+
+ [Test]
+ public void FinishedTaskOnCompleted ()
+ {
+ var mres = new ManualResetEvent (false);
+ var mres2 = new ManualResetEvent (false);
+
+ var tcs = new TaskCompletionSource<object> ();
+ tcs.SetResult (null);
+ var task = tcs.Task;
+
+ var awaiter = task.GetAwaiter ();
+ Assert.IsTrue (awaiter.IsCompleted, "#1");
+
+ awaiter.OnCompleted(() => {
+ if (mres.WaitOne (1000))
+ mres2.Set ();
+ });
+
+ mres.Set ();
+ // this will only terminate correctly if the test was not executed from the main thread
+ // e.g. Touch.Unit defaults to run tests on the main thread and this will return false
+ Assert.AreEqual (Thread.CurrentThread.IsBackground, mres2.WaitOne (2000), "#2");;
+ }
}
}
[Test]
public void StartNewCancelled ()
{
- var cts = new CancellationTokenSource ();
- cts.Cancel ();
+ var ct = new CancellationToken (true);
- var task = factory.StartNew (() => Assert.Fail ("Should never be called"), cts.Token);
+ var task = factory.StartNew (() => Assert.Fail ("Should never be called"), ct);
try {
task.Start ();
+ Assert.Fail ("#1");
} catch (InvalidOperationException) {
}
Assert.IsTrue (task.IsCanceled, "#2");
+
+ task = factory.StartNew (() => { }, ct);
+ try {
+ task.Wait ();
+ } catch (AggregateException e) {
+ Assert.IsTrue (task.IsCanceled, "#3");
+ Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#4");
+ }
}
}
}
using System.Threading.Tasks;
using NUnit.Framework;
+#if !MOBILE
+using NUnit.Framework.SyntaxHelpers;
+#endif
namespace MonoTests.System.Threading.Tasks
{
Assert.AreEqual ("1", task.Result, "#2");
}
+ [Test]
+ public void StartNewCancelled ()
+ {
+ var ct = new CancellationToken (true);
+ var factory = new TaskFactory<int> ();
+
+ var task = factory.StartNew (() => { Assert.Fail ("Should never be called"); return 1; }, ct);
+ try {
+ task.Start ();
+ Assert.Fail ("#1");
+ } catch (InvalidOperationException) {
+ }
+
+ Assert.IsTrue (task.IsCanceled, "#2");
+
+ task = factory.StartNew (() => 1, ct);
+ try {
+ task.Wait ();
+ } catch (AggregateException e) {
+ Assert.IsTrue (task.IsCanceled, "#3");
+ Assert.That (e.InnerException, Is.TypeOf (typeof (TaskCanceledException)), "#4");
+ }
+ }
}
}
}
}
+ [Test]
+ public void WhenAll_Empty ()
+ {
+ var tasks = new Task[0];
+
+ Task t = Task.WhenAll(tasks);
+
+ Assert.IsTrue(t.Wait(1000), "#1");
+ }
+
[Test]
public void WhenAll_WithNull ()
{
Assert.IsTrue (t.Wait (1000), "#2");
}
+ [Test]
+ public void WhenAllResult_Empty ()
+ {
+ var tasks = new Task<int>[0];
+
+ Task<int[]> t = Task.WhenAll(tasks);
+
+ Assert.IsTrue(t.Wait(1000), "#1");
+ Assert.IsNotNull(t.Result, "#2");
+ Assert.AreEqual(t.Result.Length, 0, "#3");
+ }
+
[Test]
public void WhenAllResult_WithNull ()
{
}
[Test] // bug #81529
+ // Causes a Attempting to unref unused handle 0x2 warning
+ [Category ("NotWorking")]
public void Handle_Valid ()
{
AutoResetEvent are1 = new AutoResetEvent (false);
{
if (ExecutionContext.IsFlowSuppressed ())
ExecutionContext.RestoreFlow ();
+
+ CallContext.FreeNamedDataSlot ("testlc");
+ }
+
+ [Test]
+ [Category("MobileNotWorking")]
+ public void LogicalGetData_SetData()
+ {
+ var value = "a";
+
+ CallContext.SetData ("testlc", value);
+ var capturedValue = CallContext.LogicalGetData ("testlc");
+
+ Assert.IsNull (capturedValue);
+ }
+
+ [Test]
+ [Category("MobileNotWorking")]
+ public void LogicalGetData_SetDataLogicalThreadAffinative()
+ {
+ var value = new CallContextValue ("a");
+
+ CallContext.SetData ("testlc", value);
+ var capturedValue = CallContext.LogicalGetData ("testlc");
+
+ Assert.AreEqual (value, capturedValue);
+ }
+
+ [Test]
+ [Category("MobileNotWorking")]
+ public void GetData_SetLogicalData()
+ {
+ var value = "a";
+
+ CallContext.LogicalSetData ("testlc", value);
+ var capturedValue = CallContext.GetData ("testlc");
+
+ Assert.AreEqual (value, capturedValue);
+ }
+
+ [Test]
+ [Category("MobileNotWorking")]
+ public void CaptureLogicalCallContext()
+ {
+ var value = "Tester";
+ object capturedValue = null;
+
+ CallContext.LogicalSetData ("testlc", value);
+
+ ExecutionContext ec = ExecutionContext.Capture ();
+ Assert.IsNotNull (ec, "Capture");
+ Assert.AreEqual (value, CallContext.LogicalGetData ("testlc"));
+ CallContext.LogicalSetData ("testlc", null);
+
+ ExecutionContext.Run (ec, new ContextCallback (new Action<object> ((data) => {
+ capturedValue = CallContext.LogicalGetData ("testlc");
+ })), null);
+
+ Assert.AreEqual (value, capturedValue);
+ Assert.AreNotEqual (value, CallContext.LogicalGetData ("testlc"));
}
[Test]
}
[Test]
+ [Category("MobileNotWorking")]
public void Capture ()
{
ExecutionContext ec = ExecutionContext.Capture ();
}
[Test]
+ [Category("MobileNotWorking")]
public void Copy ()
{
ExecutionContext ec = ExecutionContext.Capture ();
}
[Test]
+ [Category("MobileNotWorking")]
public void IsFlowSuppressed ()
{
Assert.IsFalse (ExecutionContext.IsFlowSuppressed (), "IsFlowSuppressed-1");
[Test]
[ExpectedException (typeof (InvalidOperationException))]
+ [Category("MobileNotWorking")]
public void RestoreFlow_None ()
{
ExecutionContext.RestoreFlow ();
}
[Test]
+ [Category("MobileNotWorking")]
public void RestoreFlow_SuppressFlow ()
{
Assert.IsFalse (ExecutionContext.IsFlowSuppressed (), "IsFlowSuppressed-1");
[Test]
[ExpectedException (typeof (InvalidOperationException))]
+ [Category("MobileNotWorking")]
public void Run_SuppressFlow ()
{
Assert.IsFalse (ExecutionContext.IsFlowSuppressed ());
}
[Test]
+ [Category("MobileNotWorking")]
public void SuppressFlow ()
{
Assert.IsFalse (ExecutionContext.IsFlowSuppressed (), "IsFlowSuppressed-1");
[Test]
[ExpectedException (typeof (InvalidOperationException))]
+ [Category("MobileNotWorking")]
public void SuppressFlow_Two_Undo ()
{
Assert.IsFalse (ExecutionContext.IsFlowSuppressed (), "IsFlowSuppressed-1");
AppDomain.CurrentDomain.ExecuteAssembly (
assembly.Location);
Assert.Fail ("#1");
-#if NET_2_0
} catch (MissingMethodException ex) {
// Entry point not found in assembly '...'
Assert.AreEqual (typeof (MissingMethodException), ex.GetType (), "#2");
Assert.IsNotNull (ex.Message, "#4");
Assert.IsTrue (ex.Message.IndexOf (assembly.FullName) != -1, "#5");
}
-#else
- } catch (COMException ex) {
- // Unspecified error
- Assert.AreEqual (typeof (COMException), ex.GetType (), "#2");
- Assert.AreEqual (-2147467259, ex.ErrorCode, "#3");
- Assert.IsNull (ex.InnerException, "#4");
- Assert.IsNotNull (ex.Message, "#5");
- }
-#endif
}
[Test] // ExecuteAssembly (String, Evidence)
assembly.Location,
(Evidence) null);
Assert.Fail ("#1");
-#if NET_2_0
} catch (MissingMethodException ex) {
// Entry point not found in assembly '...'
Assert.AreEqual (typeof (MissingMethodException), ex.GetType (), "#2");
Assert.IsNotNull (ex.Message, "#4");
Assert.IsTrue (ex.Message.IndexOf (assembly.FullName) != -1, "#5");
}
-#else
- } catch (COMException ex) {
- // Unspecified error
- Assert.AreEqual (typeof (COMException), ex.GetType (), "#2");
- Assert.AreEqual (-2147467259, ex.ErrorCode, "#3");
- Assert.IsNull (ex.InnerException, "#4");
- Assert.IsNotNull (ex.Message, "#5");
- }
-#endif
}
[Test] // ExecuteAssembly (String, Evidence, String [])
(Evidence) null,
new string [0]);
Assert.Fail ("#1");
-#if NET_2_0
} catch (MissingMethodException ex) {
// Entry point not found in assembly '...'
Assert.AreEqual (typeof (MissingMethodException), ex.GetType (), "#2");
Assert.IsNotNull (ex.Message, "#4");
Assert.IsTrue (ex.Message.IndexOf (assembly.FullName) != -1, "#5");
}
-#else
- } catch (COMException ex) {
- // Unspecified error
- Assert.AreEqual (typeof (COMException), ex.GetType (), "#2");
- Assert.AreEqual (-2147467259, ex.ErrorCode, "#3");
- Assert.IsNull (ex.InnerException, "#4");
- Assert.IsNotNull (ex.Message, "#5");
- }
-#endif
}
[Test] // ExecuteAssembly (String, Evidence, String [], Byte [], AssemblyHashAlgorithm)
(byte []) null,
AssemblyHashAlgorithm.SHA1);
Assert.Fail ("#1");
-#if NET_2_0
} catch (MissingMethodException ex) {
// Entry point not found in assembly '...'
Assert.AreEqual (typeof (MissingMethodException), ex.GetType (), "#2");
Assert.IsNotNull (ex.Message, "#4");
Assert.IsTrue (ex.Message.IndexOf (assembly.FullName) != -1, "#5");
}
-#else
- } catch (COMException ex) {
- // Unspecified error
- Assert.AreEqual (typeof (COMException), ex.GetType (), "#2");
- Assert.AreEqual (-2147467259, ex.ErrorCode, "#3");
- Assert.IsNull (ex.InnerException, "#4");
- Assert.IsNotNull (ex.Message, "#5");
- }
-#endif
}
[Test] // bug #79720
try {
AppDomain.CurrentDomain.Load (aname);
Assert.Fail ("#C9");
-#if NET_2_0
} catch (SecurityException) {
// Invalid assembly public key
}
-#else
- } catch (FileLoadException) {
- }
-#endif
aname = new AssemblyName ();
aname.Name = "bug79522C";
// we have no public way to get the default appdomain
}
+ static bool resolve_called;
+
+ [Test]
+ public void AssemblyResolveParseError ()
+ {
+ AppDomain currentDomain = AppDomain.CurrentDomain;
+ ResolveEventHandler d = ParseErrorResolve;
+ currentDomain.AssemblyResolve += d;
+ try {
+ resolve_called = false;
+ var a = Assembly.Load ("MyDynamicType, 1.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756");
+ Assert.Fail ();
+ } catch (FileNotFoundException) {
+ Assert.IsTrue (resolve_called);
+ }
+ currentDomain.AssemblyResolve -= d;
+ }
+
+ static Assembly ParseErrorResolve (object sender, ResolveEventArgs args)
+ {
+ resolve_called = true;
+ return null;
+ }
+
[Test]
public void ReflectionOnlyGetAssemblies ()
{
s[1] = -3;
Assert.AreEqual (-3, s[1], "#2a");
}
+
+ [Test]
+ [ExpectedException (typeof (ArgumentOutOfRangeException))]
+ public void IList_IndexerErrorTest1 ()
+ {
+ byte[] arr = new byte[4];
+ IList<byte> seg = new ArraySegment<byte> (arr, 1, 2);
+ seg[-1] = 3;
+ }
+
+ [Test]
+ [ExpectedException (typeof (ArgumentOutOfRangeException))]
+ public void IList_IndexerErrorTest2 ()
+ {
+ byte[] arr = new byte[4];
+ IList<byte> seg = new ArraySegment<byte> (arr);
+ seg[4] = 3;
+ }
#endif
}
}
class MyDerivedClassNoAttribute : MyClass
{
}
+
+ internal class AttributeWithTypeId : Attribute
+ {
+ public override object TypeId {
+ get { return this; }
+ }
+ }
}
[TestFixture]
MyOwnCustomAttribute b1 = new MyOwnCustomAttribute (null);
Assert.AreNotEqual (a1.GetHashCode (), b1.GetHashCode (), "non-identical-types");
}
+
+ [Test]
+ public void GetHashCodeWithOverriddenTypeId ()
+ {
+ //check for not throwing stack overflow exception
+ AttributeWithTypeId a = new AttributeWithTypeId ();
+ a.GetHashCode ();
+ }
}
namespace ParamNamespace {
Assert.AreEqual(0L, t1.GetUtcOffset (d5).Ticks, "D14");
}
+ private void NZST(TimeZone t1) {
+ Assert.AreEqual("NZST", t1.StandardName, "E01");
+ Assert.AreEqual("NZDT", t1.DaylightName, "E02");
+
+ DaylightTime d1 = t1.GetDaylightChanges (2013);
+ Assert.AreEqual("09/29/2013 02:00:00", d1.Start.ToString ("G"), "E03");
+ Assert.AreEqual("04/07/2013 03:00:00", d1.End.ToString ("G"), "E04");
+ Assert.AreEqual(36000000000L, d1.Delta.Ticks, "E05");
+
+ DaylightTime d2 = t1.GetDaylightChanges (2001);
+ Assert.AreEqual("10/07/2001 02:00:00", d2.Start.ToString ("G"), "E06");
+ Assert.AreEqual("03/18/2001 03:00:00", d2.End.ToString ("G"), "E07");
+ Assert.AreEqual(36000000000L, d2.Delta.Ticks, "E08");
+
+ DateTime d3 = new DateTime(2013,02,15);
+ Assert.AreEqual(true, t1.IsDaylightSavingTime (d3), "E09");
+ DateTime d4 = new DateTime(2013,04,30);
+ Assert.AreEqual(false, t1.IsDaylightSavingTime (d4), "E10");
+ DateTime d5 = new DateTime(2013,11,03);
+ Assert.AreEqual(true, t1.IsDaylightSavingTime (d5), "E11");
+
+ Assert.AreEqual(36000000000L /*hour*/ * 13L, t1.GetUtcOffset (d3).Ticks, "E12");
+ Assert.AreEqual(36000000000L /*hour*/ * 12L, t1.GetUtcOffset (d4).Ticks, "E13");
+ Assert.AreEqual(36000000000L /*hour*/ * 13L, t1.GetUtcOffset (d5).Ticks, "E14");
+ }
+
[Test]
[Culture ("")]
public void TestCtors ()
case "GMT":
GMT (t1);
break;
+ case "NZST":
+ NZST (t1);
+ break;
default:
NUnit.Framework.Assert.Ignore ("Your time zone (" + t1.StandardName + ") isn't defined in the test case");
break;
Assert.IsTrue (tz.ToLocalTime (dst_start_utc.Add (new TimeSpan (1, 0, 0))) < tz.ToLocalTime (dst_start_utc.Add (new TimeSpan (1, 1, 0))), "0:4:00 < 0:4:01");
}
+ [Test]
+ public void GetUtcOffsetAtDSTBoundary ()
+ {
+ /*
+ * Getting a definitive list of timezones which do or don't observe Daylight
+ * Savings is difficult (can't say America's or USA definitively) and lengthy see
+ *
+ * http://en.wikipedia.org/wiki/Daylight_saving_time_by_country
+ *
+ * as a good starting point for a list.
+ *
+ * The following are SOME of the timezones/regions which do support daylight savings.
+ *
+ * Pacific/Auckland
+ * Pacific/Sydney
+ * USA (EST, CST, MST, PST, AKST) note this does not cover all states or regions
+ * Europe/London (GMT)
+ * CET (member states of the European Union)
+ *
+ * This test should work in all the above timezones
+ */
+
+
+ TimeZone tz = TimeZone.CurrentTimeZone;
+ DaylightTime daylightChanges = tz.GetDaylightChanges(2007);
+ DateTime dst_end = daylightChanges.End;
+
+ if (dst_end == DateTime.MinValue)
+ Assert.Ignore (tz.StandardName + " did not observe daylight saving time during 2007.");
+
+ var standardOffset = tz.GetUtcOffset(daylightChanges.Start.AddMinutes(-1));
+
+ Assert.AreEqual(standardOffset, tz.GetUtcOffset (dst_end));
+ Assert.AreEqual(standardOffset, tz.GetUtcOffset (dst_end.Add (daylightChanges.Delta.Negate ().Add (TimeSpan.FromSeconds(1)))));
+ Assert.AreEqual(standardOffset, tz.GetUtcOffset (dst_end.Add(daylightChanges.Delta.Negate ())));
+ Assert.AreNotEqual(standardOffset, tz.GetUtcOffset (dst_end.Add(daylightChanges.Delta.Negate ().Add (TimeSpan.FromSeconds(-1)))));
+ }
+
+
[Test]
public void StaticProperties ()
{
}
#endif
+ [Test]
+ public void GetTypeParseGenericCorrectly () { //Bug #15124
+ Assert.AreEqual (Type.GetType ("MonoTests.System.Foo`1"), typeof (Foo<>), "#1");
+ Assert.AreEqual (Type.GetType ("MonoTests.System.Foo`1[System.Int32]"), typeof (Foo<int>), "#2");
+ Assert.AreEqual (Type.GetType ("MonoTests.System.Foo`1[[System.Int32]]"), typeof (Foo<int>), "#3");
+ Assert.AreEqual (Type.GetType ("MonoTests.System.Foo`1[System.Int32][]"), typeof (Foo<int>[]), "#4");
+ Assert.AreEqual (Type.GetType ("MonoTests.System.Foo`1[][System.Int32]"), null, "#5");
+ Assert.AreEqual (Type.GetType ("MonoTests.System.Foo`1[System.Int32][,]"), typeof (Foo<int>[,]), "#6");
+ Assert.AreEqual (Type.GetType ("MonoTests.System.Foo`1[]"), typeof (Foo<>).MakeArrayType(), "#7");
+ Assert.AreEqual (Type.GetType ("MonoTests.System.Foo`1[,]"), typeof (Foo<>).MakeArrayType (2), "#8");
+ Assert.AreEqual (Type.GetType ("MonoTests.System.Foo`1[][]"), typeof (Foo<>).MakeArrayType ().MakeArrayType (), "#9");
+ Assert.AreEqual (Type.GetType ("MonoTests.System.Foo`1["), null, "#10");
+ Assert.AreEqual (Type.GetType ("MonoTests.System.Foo`1[["), null, "#11");
+ Assert.AreEqual (Type.GetType ("MonoTests.System.Foo`1[[]"), null, "#12");
+ Assert.AreEqual (Type.GetType ("MonoTests.System.Foo`1[,"), null, "#13");
+ Assert.AreEqual (Type.GetType ("MonoTests.System.Foo`1[*"), null, "#14");
+ Assert.AreEqual (Type.GetType ("MonoTests.System.Foo`1[System.Int32"), null, "#15");
+ }
+
public abstract class Stream : IDisposable
{
public void Dispose ()
System.Runtime.InteropServices.ComTypes/VARFLAGS.cs
System.Runtime.InteropServices.ComTypes/VARKIND.cs
System.Runtime.InteropServices.Expando/IExpando.cs
+System.Runtime.InteropServices.WindowsRuntime/DefaultInterfaceAttribute.cs
+System.Runtime.InteropServices.WindowsRuntime/DesignerNamespaceResolveEventArgs.cs
+System.Runtime.InteropServices.WindowsRuntime/EventRegistrationToken.cs
+System.Runtime.InteropServices.WindowsRuntime/EventRegistrationTokenTable.cs
+System.Runtime.InteropServices.WindowsRuntime/IActivationFactory.cs
+System.Runtime.InteropServices.WindowsRuntime/InterfaceImplementedInVersionAttribute.cs
+System.Runtime.InteropServices.WindowsRuntime/NamespaceResolveEventArgs.cs
+System.Runtime.InteropServices.WindowsRuntime/ReadOnlyArrayAttribute.cs
+System.Runtime.InteropServices.WindowsRuntime/ReturnValueNameAttribute.cs
+System.Runtime.InteropServices.WindowsRuntime/WindowsRuntimeMarshal.cs
+System.Runtime.InteropServices.WindowsRuntime/WindowsRuntimeMetadata.cs
+System.Runtime.InteropServices.WindowsRuntime/WriteOnlyArrayAttribute.cs
System.Runtime.Remoting/ActivatedClientTypeEntry.cs
System.Runtime.Remoting/ActivatedServiceTypeEntry.cs
System.Runtime.Remoting/CustomErrorsModes.cs
System/DecimalTest2.cs
System/DecimalTest.cs
System.Diagnostics/DebuggerDisplayAttributeTest.cs
+System.Diagnostics/DebuggerTypeProxyAttribute.cs
System.Diagnostics/StackFrameTest.cs
System.Diagnostics/StackTraceTest.cs
System.Diagnostics.Contracts/ContractAssertTest.cs
System.Globalization/DaylightTimeTest.cs
System.Globalization/EastAsianLunisolarCalendarTest.cs
System.Globalization/IdnMappingTest.cs
+System.Globalization/NumberFormatInfoTest.cs
System.Globalization/RegionInfoTest.cs
System.Globalization/SortKeyTest.cs
System.Globalization/StringInfoTest.cs
static void ClearUntil (StateInfo s, string required)
{
- string e;
+ string e = null;
while (s.tags.Count > 0 &&
(e = s.tags.Peek ().ToString ()) != required) {
s.output.Append (s.tags.Pop ().ToString ());
}
p {
- text-align: justify;
margin-top: .5em;
margin-bottom: .5em;
}
--- /dev/null
+.assembly extern mscorlib
+{
+}
+
+.assembly extern 'missing'
+{
+ .ver 0:0:0:0
+}
+
+.assembly 'CS0246-29-lib'
+{
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+
+.module 'CS0246-29-lib.dll'
+
+.class extern forwarder A
+{
+ .assembly extern 'missing'
+}
+.class extern B
+{
+ .class extern A
+}
\ No newline at end of file
--- /dev/null
+.assembly extern mscorlib
+{
+}
+
+.assembly extern 'CS0731-2-lib'
+{
+ .ver 0:0:0:0
+}
+
+.assembly 'CS0731-1-lib'
+{
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+
+.module 'CS0731-1-lib.dll'
+
+.class extern forwarder A
+{
+ .assembly extern 'CS0731-2-lib'
+}
--- /dev/null
+.assembly extern mscorlib
+{
+}
+
+.assembly extern 'CS0731-1-lib'
+{
+ .ver 0:0:0:0
+}
+
+.assembly 'CS0731-2-lib'
+{
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+
+.module 'CS0731-2-lib.dll'
+
+.class extern forwarder A
+{
+ .assembly extern 'CS0731-1-lib'
+}
\ No newline at end of file
.module 'CS1070-lib.dll'
-.class extern forwarder E
+.class extern forwarder N.E
{
.assembly extern 'CS1070-lib-missing'
}
TEST_SUPPORT_FILES = \
CS0012-lib.dll CS0012-2-lib.dll CS0012-3-lib.dll CS0012-4-lib.dll CS0012-5-lib.dll CS0012-6-lib.dll CS0012-9-lib.dll CS0012-10-lib.dll CS0012-11-lib.dll CS0012-12-lib.dll CS0012-13-lib.dll CS0012-14-lib.dll CS0012-15-lib.dll CS0012-16-lib.dll CS0012-17-lib.dll CS0012-18-lib.dll CS0012-21-lib.dll CS0029-26-lib.dll \
CS0103-2-lib.dll CS0118-2-lib.dll CS0122-8-lib.dll CS0122-10-lib.dll CS0122-14-lib.dll CS0122-15-lib.dll CS0122-19-lib.dll CS0122-35-lib.dll CS0122-36-lib.dll CS0143-lib.dll CS0144-3-lib.dll CS0165-19-lib.dll \
- CS0205-3-lib.dll CS0229-3-lib.dll CS0229-4-lib.dll CS0266-25-lib.dll \
+ CS0205-3-lib.dll CS0246-29-lib.dll CS0229-3-lib.dll CS0229-4-lib.dll CS0266-25-lib.dll \
CS0315-2-lib.dll \
CS0425-7-lib.dll CS0433-lib.dll CS0433-2-lib.dll \
CS0506-3-lib.dll CS0507-7-lib.dll CS0507-8-lib.dll CS0534-3-lib.dll CS0534-4-lib.dll CS0534-6-lib.dll CS0571-3-lib.dll CS0571-5-lib.dll CS0571-6-lib.dll \
CS0612-2-lib.dll CS0618-2-lib.dll CS0619-8-lib.dll CS0619-17-lib.dll CS0619-32-lib.dll CS0619-33-lib.dll CS0619-36-lib.dll CS0619-42-lib.dll \
CS0619-43-lib.dll CS1546-lib.dll CS0619-51-lib.dll CS1509-module.dll CS1681-2-lib.dll \
- CS0730-lib.dll \
+ CS0730-lib.dll CS0731-1-lib.dll CS0731-2-lib.dll \
CS1070-lib.dll \
CS1540-15-lib.dll CS1540-17-lib.dll CS1542-lib.dll CS1577-lib.dll \
CS1607-3-lib.dll CS1683-lib.dll CS1684-lib.dll CS1685-2-lib.dll \
--- /dev/null
+// CS0035: Operator `++' is ambiguous on an operand of type `MyType'
+// Line: 31
+
+public class MyType
+{
+ public static implicit operator float (MyType v)
+ {
+ return 0;
+ }
+
+ public static implicit operator decimal (MyType v)
+ {
+ return 0;
+ }
+
+ public static implicit operator MyType (float v)
+ {
+ return null;
+ }
+
+ public static implicit operator MyType (decimal v)
+ {
+ return null;
+ }
+}
+
+class Test
+{
+ static void test (MyType x)
+ {
+ x++;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0103: The name `bar' does not exist in the current context
+// Line: 8
+
+public class Test
+{
+ static void Main ()
+ {
+ if (false && bar ()) {
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0104: `X' is an ambiguous reference between `A.X' and `B.X'
+// Line: 25
+
+namespace A
+{
+ class X { }
+}
+
+namespace B
+{
+ class X { }
+}
+
+namespace C
+{
+ using System;
+ using A;
+ using B;
+
+ class Test
+ {
+ static void Main ()
+ {
+ Foo (delegate {
+ X x;
+ });
+ }
+
+ static void Foo (Action a)
+ {
+ }
+ }
+}
--- /dev/null
+// CS0104: `XAttribute' is an ambiguous reference between `A.XAttribute' and `B.XAttribute'
+// Line: 21
+
+using System;
+
+namespace A
+{
+ class XAttribute : Attribute { }
+}
+
+namespace B
+{
+ class XAttribute : Attribute { }
+}
+
+namespace C
+{
+ using A;
+ using B;
+
+ [X]
+ class Test
+ {
+ }
+}
--- /dev/null
+// CS0126: An object of a type convertible to `string' is required for the return statement
+// Line: 7
+
+using System.Threading.Tasks;
+
+class A
+{
+ static async Task<string> Test ()
+ {
+ await CallAsync ();
+ return;
+ }
+
+ static Task<string> CallAsync ()
+ {
+ return null;
+ }
+}
+++ /dev/null
-// CS0161: `T.Main()': not all code paths return a value
-// Line: 6
-// CSC bug: The error is not reported even if it should as in other unreachable cases
-
-class T {
- public static int Main ()
- {
- switch (1) {
- case 1:
- return 0;
- default:
- break;
- }
- }
-}
+++ /dev/null
-// CS0162: Unreachable code detected
-// Line: 10
-// Compiler options: -warnaserror
-
-public class X
-{
- public static void Main ()
- {
- return;
- 1+1;
- }
-}
\ No newline at end of file
--- /dev/null
+// CS0162: Unreachable code detected
+// Line: 14
+// Compiler options: -warnaserror
+
+using System;
+
+class X
+{
+
+ public static void Main ()
+ {
+ goto X;
+ A:
+ bool b = false;
+ if (b) {
+ goto A;
+ }
+ X:
+ return;
+ }
+}
\ No newline at end of file
// Line: 9
// Compiler options: -warnaserror -warn:2
-// this requires a multi-pass algorithm for unreachable code detection
-// punting for now
-
class Foo {
static void Main ()
{
--- /dev/null
+// CS0163: Control cannot fall through from one case label `case 1:' to another
+// Line: 14
+
+using System;
+using System.Collections.Generic;
+
+static class C
+{
+ public static IEnumerable<int> Test (int key)
+ {
+ switch (key) {
+ case 1:
+ yield return 0;
+ case 2:
+ yield return 2;
+ default:
+ throw new ArgumentOutOfRangeException ("symbol:" + key);
+ }
+ }
+}
\ No newline at end of file
-// CS0163: Control cannot fall through from one case label to another
-// Line: 17
-
+// CS0163: Control cannot fall through from one case label `case 3:' to another
+// Line: 21
public class Foo
{
--- /dev/null
+// CS0165: Use of unassigned local variable `x'
+// Line: 17
+
+using System;
+
+class Program
+{
+ static int Main ()
+ {
+ int foo = 9;
+ int x;
+
+ switch (foo) {
+ case 1:
+ x = 1;
+ gotoTarget:
+ {
+ Console.WriteLine (x);
+ }
+ break;
+ default:
+ {
+ if (foo != 0) {
+ goto gotoTarget;
+ }
+
+ break;
+ }
+ }
+
+ return 1;
+ }
+}
+
--- /dev/null
+// CS0165: Use of unassigned local variable `retval'
+// Line: 9
+
+class Test
+{
+ static string DoStuff (string msg)
+ {
+ string retval;
+
+ switch (msg) {
+ case "hello":
+ retval = "goodbye";
+ return retval;
+ case "goodbye":
+ return retval;
+ case "other":
+ retval = "other";
+ case "":
+ return msg;
+ }
+ return "";
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0165: Use of unassigned local variable `a'
+// Line: 14
+
+class X
+{
+ public static void Main ()
+ {
+ int i = 3;
+ switch (i) {
+ case 1:
+ float a = 7.0f;
+ break;
+ default:
+ float b = a + 99.0f;
+ break;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0165: Use of unassigned local variable `trial'
+// Line: 18
+
+using System;
+
+class Test
+{
+ public static void Main (string[] args)
+ {
+ bool trial;
+ string action = "add_trial";
+
+ switch (action) {
+ case "add_trial":
+ trial = true;
+ goto case "add_to_project";
+ case "add_to_project":
+ Console.WriteLine (trial);
+ break;
+ case "test":
+ break;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0165: Use of unassigned local variable `eh'
+// Line: 12
+
+using System;
+
+public class E
+{
+ public static void Main ()
+ {
+ EventHandler eh;
+ eh = delegate {
+ Console.WriteLine (eh);
+ };
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0165: Use of unassigned local variable `a'
+// Line: 13
+
+using System;
+
+class Program
+{
+ public static void Main (string[] args)
+ {
+ int a, b;
+ string s = "";
+ var res = s != null ? a = 1 : b = 2;
+ Console.WriteLine (a);
+ }
+}
--- /dev/null
+// CS0165: Use of unassigned local variable `a'
+// Line: 13
+
+using System;
+
+class Program
+{
+ public static void Main ()
+ {
+ int a;
+ string s = "";
+ var res = s == null || ((a = 1) > 0);
+ Console.WriteLine (a);
+ }
+}
--- /dev/null
+// CS0165: Use of unassigned local variable `j'
+// Line: 10
+
+class Test
+{
+ static void Main ()
+ {
+ int? i;
+ int? j;
+ int? x = (i = 7) ?? j;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0165: Use of unassigned local variable `a'
+// Line: 9
+
+using System;
+
+class Test {
+
+ static void Main () {
+ Action a = () => a();
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0165: Use of unassigned local variable `i'
+// Line: 9
+
+public class MainClass
+{
+ public void Foo ()
+ {
+ int i;
+ i++;
+ }
+}
--- /dev/null
+// CS0165: Use of unassigned local variable `a'
+// Line: 9
+
+class C
+{
+ static void Main ()
+ {
+ int a;
+ Foo (out a, a);
+ }
+
+ static void Foo (out int a, int b)
+ {
+ a = b;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0165: Use of unassigned local variable `a'
+// Line: 13
+
+using System;
+using System.Diagnostics;
+
+class C
+{
+ static int Main ()
+ {
+ int a;
+ Foo (a = 9);
+ return a;
+ }
+
+ [Conditional ("MISSING")]
+ static void Foo (int value)
+ {
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0165: Use of unassigned local variable `a'
+// Line: 14
+
+using System;
+
+class Program
+{
+ public static void Main ()
+ {
+ int a;
+ string s = "";
+
+ if (s != "s" || (a = 4) > 3) {
+ Console.WriteLine (a);
+ }
+ }
+}
--- /dev/null
+// CS0165: Use of unassigned local variable `a'
+// Line: 14
+
+using System;
+
+class Program
+{
+ public static void Main ()
+ {
+ int a;
+ string s = "";
+
+ if (s != "s" && (a = 4) > 3) {
+ return;
+ }
+
+ Console.WriteLine (a);
+ }
+}
--- /dev/null
+// CS0165: Use of unassigned local variable `s'
+// Line: 14
+
+using System;
+
+class Program
+{
+ public static void Main ()
+ {
+ string s;
+ object o = null;
+ while (o != null && string.IsNullOrEmpty (s = (string) o.ToString ())) {
+ }
+
+ Console.WriteLine (s);
+ }
+}
--- /dev/null
+// CS0165: Use of unassigned local variable `s'
+// Line: 14
+
+using System;
+
+class Program
+{
+ public static void Main ()
+ {
+ string s;
+ object o = null;
+ while (o != null || string.IsNullOrEmpty (s = (string) o.ToString ())) {
+ Console.WriteLine (s);
+ }
+ }
+}
--- /dev/null
+// CS0165: Use of unassigned local variable `a'
+// Line: 16
+
+using System;
+
+class Program
+{
+ public static void Main ()
+ {
+ int a;
+ string s = "";
+
+ do {
+ } while (s != "s" && (a = 4) > 3);
+
+ Console.WriteLine (a);
+ }
+}
--- /dev/null
+// CS0165: Use of unassigned local variable `a'
+// Line: 16
+
+using System;
+
+class Program
+{
+ public static void Main ()
+ {
+ int a;
+ string s = "";
+
+ for (int i = 0; s != "s" && (a = 4) > 3; ++i) {
+ }
+
+ Console.WriteLine (a);
+ }
+}
--- /dev/null
+// CS0165: Use of unassigned local variable `a'
+// Line: 14
+
+using System;
+
+class Program
+{
+ public static void Main ()
+ {
+ int a;
+ string s = "";
+
+ if (!(s != "s" && (a = 4) > 3)) {
+ Console.WriteLine (a);
+ }
+ }
+}
--- /dev/null
+// CS0165: Use of unassigned local variable `a'
+// Line: 14
+
+using System;
+
+class Program
+{
+ public static void Main ()
+ {
+ int a;
+ string s = "";
+
+ var res = (s == "" && (a = 4) > 3) ? 1 : a;
+ }
+}
--- /dev/null
+// CS0165: Use of unassigned local variable `a'
+// Line: 14
+
+using System;
+
+class Program
+{
+ public static void Main ()
+ {
+ object a;
+ string s = null;
+
+ var res = s ?? (a = null);
+ Console.WriteLine (a);
+ }
+}
--- /dev/null
+// CS0165: Use of unassigned local variable `g'
+// Line: 10
+
+public class A
+{
+ static bool Test7 ()
+ {
+ int f = 1;
+ int g;
+ return f > 1 && OutCall (out g) || g > 1;
+ }
+
+ static bool OutCall (out int arg)
+ {
+ arg = 1;
+ return false;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0171: Field `S.value' must be fully assigned before control leaves the constructor
+// Line: 10
+
+using System;
+
+struct S
+{
+ string value;
+
+ public S (int arg)
+ {
+ if (arg > 0) {
+ return;
+ }
+
+ throw new ApplicationException ();
+ }
+}
--- /dev/null
+// CS0177: The out parameter `val' must be assigned to before control leaves the current method
+// Line: 12
+
+public class A
+{
+ public bool GetValue (out int val)
+ {
+ val = 0;
+ return true;
+ }
+
+ public void ReallyGetValue (out int val)
+ {
+ if (AlwaysReturnTrue () || GetValue (out val)) {
+ }
+ }
+
+ public bool AlwaysReturnTrue ()
+ {
+ return true;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
+// Line: 9
+
+public class X
+{
+ public static void Main ()
+ {
+ return;
+ 1+1;
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
+// Line: 10
+
+using System;
+
+class X
+{
+ public static void Main ()
+ {
+ new Func<int> (() => 0);
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS0246: The type or namespace name `B' could not be found. Are you missing an assembly reference?
+// Line: 8
+
+class X
+{
+ public static void Main ()
+ {
+ B b;
+ }
+}
\ No newline at end of file
+++ /dev/null
-// CS0411: The type arguments for method `C.Foo<T>(IFoo<T>, IFoo<T>)' cannot be inferred from the usage. Try specifying the type arguments explicitly
-// Line: 17
-
-interface IFoo<in T>
-{
-}
-
-class C
-{
- public static void Foo<T> (IFoo<T> e1, IFoo<T> e2)
- {
- }
-
- public static void Main ()
- {
- IFoo<int> a = null;
- IFoo<object> b = null;
- Foo (a, b);
- }
-}
+++ /dev/null
-// CS0411: The type arguments for method `Hello.World<U>(U, IFoo<U>)' cannot be inferred from the usage. Try specifying the type arguments explicitly
-// Line: 16
-public interface IFoo<T>
-{ }
-
-public class Foo : IFoo<int>, IFoo<string>
-{ }
-
-public class Hello
-{
- public void World<U> (U u, IFoo<U> foo)
- { }
-
- public void Test (Foo foo)
- {
- World ("Canada", foo);
- }
-}
-
-class X
-{
- static void Main ()
- {
- }
-}
+++ /dev/null
-// CS0411: The type arguments for method `C.Foo<T>(T, System.Collections.Generic.Comparer<T>)' cannot be inferred from the usage. Try specifying the type arguments explicitly
-// Line: 20
-
-using System;
-using System.Collections.Generic;
-
-public class C
-{
- static void Foo<T>(T t, Comparer<T> tc)
- {
- }
-
- static int Compare (int a, int b)
- {
- return -1;
- }
-
- public static void Main ()
- {
- Foo (1, Compare);
- }
-}
--- /dev/null
+// CS0429: Unreachable expression code detected
+// Line: 12
+// Compiler options: -warnaserror
+
+public class X
+{
+ static void test (int stop)
+ {
+ int pos = 0;
+ do {
+ break;
+ } while (pos < stop);
+ }
+}
--- /dev/null
+// CS0534: `Foo' does not implement inherited abstract member `SomeAbstract.SomeProperty.get'
+// Line: 13
+
+public class SomeProperty
+{
+}
+
+public abstract class SomeAbstract
+{
+ public abstract SomeProperty SomeProperty { get; }
+}
+
+public class Foo : SomeAbstract
+{
+ public static SomeProperty SomeProperty { get { return null; } }
+}
+
--- /dev/null
+// CS0540: `Foo.ISomeProp.SomeProperty': containing type does not implement interface `ISomeProp'
+// Line: 18
+
+public class SomeProperty
+{
+}
+
+public abstract class SomeAbstract : ISomeProp
+{
+ public abstract SomeProperty SomeProperty { get; }
+}
+
+interface ISomeProp
+{
+ SomeProperty SomeProperty { get; }
+}
+
+public class Foo : SomeAbstract
+{
+ SomeProperty ISomeProp.SomeProperty { get { return null; } }
+
+ public override SomeProperty SomeProperty { get { return null; } }
+
+ public static void Main ()
+ {
+ }
+}
--- /dev/null
+// CS0731: The type forwarder for type `A' in assembly `CS0731-2-lib, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' has circular dependency
+// Line: 9
+// Compiler options: -r:CS0731-1-lib.dll -r:CS0731-2-lib.dll
+
+class Test
+{
+ static void Main ()
+ {
+ new A ();
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS1061: Type `string' does not contain a definition for `Name' and no extension method `Name' of type `string' could be found. Are you missing an assembly reference?
+// Line: 18
+
+using System;
+
+static class X
+{
+ public static void Main ()
+ {
+ }
+
+ static void Foo ()
+ {
+ var fileName = "";
+ string[] all = null;
+
+ all.Each (x => {
+ var name = fileName.Name;
+ });
+ }
+
+ static void Each<T> (this T[] s, Action<T> a)
+ {
+ }
+}
--- /dev/null
+// CS1070: The type `N.E' has been forwarded to an assembly that is not referenced. Consider adding a reference to assembly `CS1070-lib-missing, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
+// Line: 9
+// Compiler options: -r:CS1070-lib.dll
+
+using N;
+
+public class D
+{
+ public void Foo (E e)
+ {
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS1503: Argument `#2' cannot convert `IContravariant<object>' expression to type `ICovariant<string>'
+// Line: 23
+
+interface IContravariant<in T>
+{
+}
+
+interface ICovariant<out T>
+{
+}
+
+class C
+{
+ public static void Test<T> (ICovariant<T> e1, ICovariant<T> e2)
+ {
+ }
+
+ public static void Main ()
+ {
+ ICovariant<string> a_2 = null;
+ IContravariant<object> b_2 = null;
+
+ Test (a_2, b_2);
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS1503: Argument `#2' cannot convert `IFoo<object>' expression to type `IFoo<int>'
+// Line: 18
+
+interface IFoo<in T>
+{
+}
+
+class C
+{
+ public static void Foo<T> (IFoo<T> e1, IFoo<T> e2)
+ {
+ }
+
+ public static void Main ()
+ {
+ IFoo<int> a = null;
+ IFoo<object> b = null;
+ Foo (a, b);
+ }
+}
--- /dev/null
+// CS1503: Argument `#2' cannot convert `method group' expression to type `System.Collections.Generic.Comparer<int>'
+// Line: 20
+
+using System;
+using System.Collections.Generic;
+
+public class C
+{
+ static void Foo<T>(T t, Comparer<T> tc)
+ {
+ }
+
+ static int Compare (int a, int b)
+ {
+ return -1;
+ }
+
+ public static void Main ()
+ {
+ Foo (1, Compare);
+ }
+}
--- /dev/null
+// CS1632: Control cannot leave the body of an anonymous method
+// Line: 12
+
+using System;
+
+class X
+{
+ public static void Main ()
+ {
+ while (true) {
+ Action a = () => {
+ break;
+ };
+ }
+ }
+}
--- /dev/null
+// CS1632: Control cannot leave the body of an anonymous method
+// Line: 14
+
+using System;
+
+class X
+{
+ public static void Main ()
+ {
+ int b = 0;
+ switch (b) {
+ case 1:
+ Action a = () => {
+ break;
+ };
+
+ break;
+ }
+ }
+}
--- /dev/null
+// CS1632: Control cannot leave the body of an anonymous method
+// Line: 14
+
+using System;
+
+class X
+{
+ public static void Main ()
+ {
+ int b = 0;
+ switch (b) {
+ case 1:
+ Action a = () => {
+ goto case 2;
+ };
+
+ break;
+ case 2:
+ break;
+ }
+ }
+}
--- /dev/null
+// CS1654: Cannot assign to members of `f' because it is a `using variable'
+// Line: 22
+
+using System;
+
+struct Foo : IDisposable
+{
+ public int Property {
+ set { }
+ }
+
+ public void Dispose ()
+ {
+ }
+}
+
+class Bar
+{
+ static void Main ()
+ {
+ using (var f = new Foo ()) {
+ f.Property = 0;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+// CS1654: Cannot assign to members of `f' because it is a `using variable'
+// Line: 22
+
+using System;
+
+struct Foo : IDisposable
+{
+ public int this[int arg] {
+ set { }
+ }
+
+ public void Dispose ()
+ {
+ }
+}
+
+class Bar
+{
+ static void Main ()
+ {
+ using (var f = new Foo ()) {
+ f[0] = 1;
+ }
+ }
+}
\ No newline at end of file
# Parser problems
cs0080.cs
-cs0162-7.cs NO ERROR
-cs0165-3.cs
-
# Operators
cs0457-2.cs
cs0457.cs
+
+cs1060.cs NO ERROR
+cs1060-2.cs NO ERROR
+cs1060-3.cs NO ERROR
public class ExternClass
{
- string name;
+ string fullName;
TypeAttr ta;
string assemblyReference;
- public ExternClass (string name, TypeAttr ta, string assemblyReference)
+ public ExternClass (string fullName, TypeAttr ta, string assemblyReference)
{
- this.name = name;
+ this.fullName = fullName;
this.ta = ta;
this.assemblyReference = assemblyReference;
}
public void Resolve (CodeGen code_gen, ExternTable table)
{
var ar = table.GetAssemblyRef (assemblyReference);
- if (ar != null)
- code_gen.PEFile.AddExternClass (name, ta, ar.AssemblyRef);
+ if (ar != null) {
+ string ns = null;
+ string name = fullName;
+
+ int pos = name.LastIndexOf ('.');
+ if (pos > 0) {
+ ns = name.Substring (0, pos);
+ name = name.Substring (pos + 1);
+ }
+
+ code_gen.PEFile.AddExternClass (ns, name, ta, ar.AssemblyRef);
+ }
}
}
}\r
;\r
\r
-expt_attr : /* EMPTY */\r
+expt_attr : { $$ = 0; } /* EMPTY */\r
| expt_attr K_PRIVATE { $$ = (TypeAttr)$1 | TypeAttr.Private; }\r
| expt_attr K_PUBLIC { $$ = (TypeAttr)$1 | TypeAttr.Public; }\r
| expt_attr K_NESTED K_PUBLIC { $$ = (TypeAttr)$1 | TypeAttr.NestedPublic; }\r
hoisted_this.EmitAssign (ec, source, false, false);
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ return false;
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement target)
{
// Nothing to clone
if (!DoResolveParameters (ec))
return null;
-#if !STATIC
- // FIXME: The emitted code isn't very careful about reachability
- // so, ensure we have a 'ret' at the end
- BlockContext bc = ec as BlockContext;
- if (bc != null && bc.CurrentBranching != null && bc.CurrentBranching.CurrentUsageVector.IsUnreachable)
- bc.NeedReturnLabel ();
-#endif
return this;
}
}
var bc = ec as BlockContext;
- if (bc != null)
+
+ if (bc != null) {
aec.AssignmentInfoOffset = bc.AssignmentInfoOffset;
+ aec.EnclosingLoop = bc.EnclosingLoop;
+ aec.EnclosingLoopOrSwitch = bc.EnclosingLoopOrSwitch;
+ aec.Switch = bc.Switch;
+ }
var errors = ec.Report.Errors;
- bool res = Block.Resolve (ec.CurrentBranching, aec, null);
+ bool res = Block.Resolve (aec);
+
+ if (res && errors == ec.Report.Errors) {
+ MarkReachable (new Reachability ());
+
+ if (!CheckReachableExit (ec.Report)) {
+ return null;
+ }
+
+ if (bc != null)
+ bc.AssignmentInfoOffset = aec.AssignmentInfoOffset;
+ }
if (am != null && am.ReturnTypeInference != null) {
am.ReturnTypeInference.FixAllTypes (ec);
return false;
}
+ bool CheckReachableExit (Report report)
+ {
+ if (block.HasReachableClosingBrace && ReturnType.Kind != MemberKind.Void) {
+ // FIXME: Flow-analysis on MoveNext generated code
+ if (!IsIterator) {
+ report.Error (1643, StartLocation,
+ "Not all code paths return a value in anonymous method of type `{0}'", GetSignatureForError ());
+
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ // We are reachable, mark block body reachable too
+ MarkReachable (new Reachability ());
+
+ CheckReachableExit (fc.Report);
+
+ var das = fc.BranchDefiniteAssignment ();
+ var prev_pb = fc.ParametersBlock;
+ fc.ParametersBlock = Block;
+ var da_ontrue = fc.DefiniteAssignmentOnTrue;
+ var da_onfalse = fc.DefiniteAssignmentOnFalse;
+
+ block.FlowAnalysis (fc);
+
+ fc.ParametersBlock = prev_pb;
+ fc.DefiniteAssignment = das;
+ fc.DefiniteAssignmentOnTrue = da_ontrue;
+ fc.DefiniteAssignmentOnFalse = da_onfalse;
+ }
+
+ public override void MarkReachable (Reachability rc)
+ {
+ block.MarkReachable (rc);
+ }
+
public void SetHasThisAccess ()
{
ExplicitBlock b = block;
return this;
}
+ public void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ if (ArgType == AType.Out) {
+ var vr = Expr as VariableReference;
+ if (vr != null) {
+ if (vr.VariableInfo != null)
+ fc.SetVariableAssigned (vr.VariableInfo);
+
+ return;
+ }
+
+ var fe = Expr as FieldExpr;
+ if (fe != null) {
+ fe.SetFieldAssigned (fc);
+ return;
+ }
+
+ return;
+ }
+
+ Expr.FlowAnalysis (fc);
+ }
+
public string GetSignatureForError ()
{
if (Expr.eclass == ExprClass.MethodGroup)
public void Resolve (ResolveContext ec)
{
-// using (ec.With (ResolveContext.Options.DoFlowAnalysis, true)) {
- // Verify that the argument is readable
- if (ArgType != AType.Out)
- Expr = Expr.Resolve (ec);
+ // Verify that the argument is readable
+ if (ArgType != AType.Out)
+ Expr = Expr.Resolve (ec);
- // Verify that the argument is writeable
- if (Expr != null && IsByRef)
- Expr = Expr.ResolveLValue (ec, EmptyExpression.OutAccess);
+ // Verify that the argument is writeable
+ if (Expr != null && IsByRef)
+ Expr = Expr.ResolveLValue (ec, EmptyExpression.OutAccess);
- if (Expr == null)
- Expr = ErrorExpression.Instance;
-// }
+ if (Expr == null)
+ Expr = ErrorExpression.Instance;
}
}
return null;
}
+ public void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ bool has_out = false;
+ foreach (var arg in args) {
+ if (arg.ArgType == Argument.AType.Out) {
+ has_out = true;
+ continue;
+ }
+
+ arg.FlowAnalysis (fc);
+ }
+
+ if (!has_out)
+ return;
+
+ foreach (var arg in args) {
+ if (arg.ArgType != Argument.AType.Out)
+ continue;
+
+ arg.FlowAnalysis (fc);
+ }
+ }
+
public List<Argument>.Enumerator GetEnumerator ()
{
return args.GetEnumerator ();
Emit (ec, true);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ source.FlowAnalysis (fc);
+
+ if (target is ArrayAccess || target is IndexerExpr || target is PropertyExpr)
+ target.FlowAnalysis (fc);
+ }
+
protected override void CloneTo (CloneContext clonectx, Expression t)
{
Assign _target = (Assign) t;
return this;
}
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ base.FlowAnalysis (fc);
+
+ var vr = target as VariableReference;
+ if (vr != null) {
+ if (vr.VariableInfo != null)
+ fc.SetVariableAssigned (vr.VariableInfo);
+
+ return;
+ }
+
+ var fe = target as FieldExpr;
+ if (fe != null) {
+ fe.SetFieldAssigned (fc);
+ return;
+ }
+ }
+
+ public override void MarkReachable (Reachability rc)
+ {
+ var es = source as ExpressionStatement;
+ if (es != null)
+ es.MarkReachable (rc);
+ }
}
public class RuntimeExplicitAssign : Assign
// share same constructor (block) for expression trees resolve but
// they have they own resolve scope
//
- sealed class FieldInitializerContext : ResolveContext
+ sealed class FieldInitializerContext : BlockContext
{
- ExplicitBlock ctor_block;
+ readonly ExplicitBlock ctor_block;
- public FieldInitializerContext (IMemberContext mc, ResolveContext constructorContext)
- : base (mc, Options.FieldInitializerScope | Options.ConstructorScope)
+ public FieldInitializerContext (IMemberContext mc, BlockContext constructorContext)
+ : base (mc, null, constructorContext.ReturnType)
{
+ flags |= Options.FieldInitializerScope | Options.ConstructorScope;
this.ctor_block = constructorContext.CurrentBlock.Explicit;
}
public override ExplicitBlock ConstructorBlock {
- get {
- return ctor_block;
- }
+ get {
+ return ctor_block;
+ }
}
}
((FieldExpr)target).InstanceExpression = new CompilerGeneratedThis (mc.CurrentType, expression.Location);
}
+ public int AssignmentOffset { get; private set; }
+
public override Location StartLocation {
get {
return loc;
}
}
- protected override Expression DoResolve (ResolveContext ec)
+ protected override Expression DoResolve (ResolveContext rc)
{
// Field initializer can be resolved (fail) many times
if (source == null)
return null;
+ var bc = (BlockContext) rc;
if (resolved == null) {
- var ctx = new FieldInitializerContext (mc, ec);
+ var ctx = new FieldInitializerContext (mc, bc);
resolved = base.DoResolve (ctx) as ExpressionStatement;
+ AssignmentOffset = ctx.AssignmentInfoOffset - bc.AssignmentInfoOffset;
}
return resolved;
else
base.EmitStatement (ec);
}
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ source.FlowAnalysis (fc);
+ }
public bool IsDefaultInitializer {
get {
return base.DoResolve (ec);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ target.FlowAnalysis (fc);
+ source.FlowAnalysis (fc);
+ }
+
protected override Expression ResolveConversions (ResolveContext ec)
{
//
return true;
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ expr.FlowAnalysis (fc);
+
+ stmt.RegisterResumePoint ();
+ }
+
protected override Expression DoResolve (ResolveContext rc)
{
+ if (rc.HasSet (ResolveContext.Options.FinallyScope)) {
+ rc.Report.Error (1984, loc, "The `await' operator cannot be used in the body of a finally clause");
+ }
+
if (rc.HasSet (ResolveContext.Options.LockScope)) {
rc.Report.Error (1996, loc,
"The `await' operator cannot be used in the body of a lock statement");
stmt.EmitStatement (ec);
}
+ public override void MarkReachable (Reachability rc)
+ {
+ base.MarkReachable (rc);
+ stmt.MarkReachable (rc);
+ }
+
public override object Accept (StructuralVisitor visitor)
{
return visitor.Visit (this);
public AwaitStatement (Expression expr, Location loc)
: base (expr, loc)
{
+ unwind_protect = true;
}
#region Properties
return false;
}
+ if (bc.HasSet (ResolveContext.Options.CatchScope)) {
+ bc.Report.Error (1985, loc, "The `await' operator cannot be used in the body of a catch clause");
+ }
+
if (!base.Resolve (bc))
return false;
}
}
+ class AsyncInitializerStatement : StatementExpression
+ {
+ public AsyncInitializerStatement (AsyncInitializer expr)
+ : base (expr)
+ {
+ }
+
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ base.DoFlowAnalysis (fc);
+
+ var init = (AsyncInitializer) Expr;
+ var res = !init.Block.HasReachableClosingBrace;
+ var storey = (AsyncTaskStorey) init.Storey;
+
+ if (storey.ReturnType.IsGenericTask)
+ return res;
+
+ return true;
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ if (!rc.IsUnreachable)
+ reachable = true;
+
+ var init = (AsyncInitializer) Expr;
+ rc = init.Block.MarkReachable (rc);
+
+ var storey = (AsyncTaskStorey) init.Storey;
+
+ //
+ // Explicit return is required for Task<T> state machine
+ //
+ if (storey.ReturnType != null && storey.ReturnType.IsGenericTask)
+ return rc;
+
+ return Reachability.CreateUnreachable ();
+ }
+ }
+
public class AsyncInitializer : StateMachineInitializer
{
TypeInferenceContext return_inference;
#endregion
- protected override BlockContext CreateBlockContext (ResolveContext rc)
+ protected override BlockContext CreateBlockContext (BlockContext bc)
{
- var ctx = base.CreateBlockContext (rc);
- var lambda = rc.CurrentAnonymousMethod as LambdaMethod;
+ var ctx = base.CreateBlockContext (bc);
+ var lambda = bc.CurrentAnonymousMethod as LambdaMethod;
if (lambda != null)
return_inference = lambda.ReturnTypeInference;
- ctx.StartFlowBranching (this, rc.CurrentBranching);
+ ctx.Set (ResolveContext.Options.TryScope);
+
return ctx;
}
storey.EmitInitializer (ec);
ec.Emit (OpCodes.Ret);
}
+
+ public override void MarkReachable (Reachability rc)
+ {
+ //
+ // Reachability has been done in AsyncInitializerStatement
+ //
+ }
}
class AsyncTaskStorey : StateMachine
/// </summary>
void ResolveAttributeType (bool comparisonOnly)
{
- SessionReportPrinter resolve_printer = new SessionReportPrinter ();
+ var resolve_printer = new SessionReportPrinter ();
+ SessionReportPrinter secondary_printer = null;
ReportPrinter prev_recorder = Report.SetPrinter (resolve_printer);
bool t1_is_attr = false;
try {
t1 = expression.ResolveAsType (context);
- if (t1 != null)
- t1_is_attr = t1.IsAttribute;
-
resolve_printer.EndSession ();
+ if (t1 != null && resolve_printer.ErrorsCount == 0)
+ t1_is_attr = t1.IsAttribute;
+
if (nameEscaped) {
t2 = null;
} else {
expanded = (ATypeNameExpression) expression.Clone (null);
expanded.Name += "Attribute";
+ secondary_printer = new SessionReportPrinter ();
+ Report.SetPrinter (secondary_printer);
t2 = expanded.ResolveAsType (context);
- if (t2 != null)
+ secondary_printer.EndSession ();
+ if (t2 != null && secondary_printer.ErrorsCount == 0)
t2_is_attr = t2.IsAttribute;
+
+ secondary_printer.EndSession ();
}
} finally {
context.Module.Compiler.Report.SetPrinter (prev_recorder);
resolve_error = true;
- if (t1 != null) {
- resolve_printer.Merge (prev_recorder);
+ if (t1 != null) {
+ if (resolve_printer.IsEmpty) {
+ Report.SymbolRelatedToPreviousError (t1);
+ Report.Error (616, Location, "`{0}': is not an attribute class", t1.GetSignatureForError ());
+ } else {
+ resolve_printer.Merge (prev_recorder);
+ }
- Report.SymbolRelatedToPreviousError (t1);
- Report.Error (616, Location, "`{0}': is not an attribute class", t1.GetSignatureForError ());
return;
}
if (t2 != null) {
- Report.SymbolRelatedToPreviousError (t2);
- Report.Error (616, Location, "`{0}': is not an attribute class", t2.GetSignatureForError ());
+ if (secondary_printer.IsEmpty) {
+ Report.SymbolRelatedToPreviousError (t2);
+ Report.Error (616, Location, "`{0}': is not an attribute class", t2.GetSignatureForError ());
+ } else {
+ secondary_printer.Merge (prev_recorder);
+ }
+
return;
}
}
}
+ bool ITypeDefinition.IsCyclicTypeForwarder {
+ get {
+ return false;
+ }
+ }
+
//
// Returns true for secondary partial containers
//
if (!has_complex_initializer && fi.IsDefaultInitializer)
continue;
+ ec.AssignmentInfoOffset += fi.AssignmentOffset;
ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
}
if (fi.IsDefaultInitializer && ec.Module.Compiler.Settings.Optimize)
continue;
+ ec.AssignmentInfoOffset += fi.AssignmentOffset;
ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
}
}
/// </summary>
public bool VerifyImplements (InterfaceMemberBase mb)
{
- var ifaces = spec.Interfaces;
+ var ifaces = PartialContainer.Interfaces;
if (ifaces != null) {
foreach (TypeSpec t in ifaces){
if (t == mb.InterfaceType)
return true;
+
+ var expanded_base = t.Interfaces;
+ if (expanded_base == null)
+ continue;
+
+ foreach (var bt in expanded_base) {
+ if (bt == mb.InterfaceType)
+ return true;
+ }
}
}
//
// Public function used to locate types.
//
- // Set 'ignore_cs0104' to true if you want to ignore cs0104 errors.
- //
// Returns: Type or null if they type can not be found.
//
public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
e = new TypeExpression (t, Location.Null);
else {
+ var errors = Compiler.Report.Errors;
e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
+
+ // TODO: LookupNamespaceOrType does more than just lookup. The result
+ // cannot be cached or the error reporting won't happen
+ if (errors != Compiler.Report.Errors)
+ return e;
}
}
}
}
- if (!IsInterface && base_member.IsAbstract && !overrides) {
+ if (!IsInterface && base_member.IsAbstract && !overrides && !IsStatic) {
Report.SymbolRelatedToPreviousError (base_member);
Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
GetSignatureForError (), base_member.GetSignatureForError ());
public void Emit (EmitContext ec, MethodSpec method, Arguments Arguments, Location loc)
{
- // Speed up the check by not doing it on not allowed targets
- if (method.ReturnType.Kind == MemberKind.Void && method.IsConditionallyExcluded (ec.MemberContext))
- return;
-
EmitPredefined (ec, method, Arguments, loc);
}
var sn = expr as SimpleName;
const ResolveFlags flags = ResolveFlags.VariableOrValue | ResolveFlags.Type;
- //
- // Resolve the expression with flow analysis turned off, we'll do the definite
- // assignment checks later. This is because we don't know yet what the expression
- // will resolve to - it may resolve to a FieldExpr and in this case we must do the
- // definite assignment check on the actual field and not on the whole struct.
- //
- using (rc.Set (ResolveContext.Options.OmitStructFlowAnalysis)) {
- if (sn != null) {
- expr = sn.LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity);
-
- //
- // Resolve expression which does have type set as we need expression type
- // with disable flow analysis as we don't know whether left side expression
- // is used as variable or type
- //
- if (expr is VariableReference || expr is ConstantExpr || expr is Linq.TransparentMemberAccess) {
- using (rc.With (ResolveContext.Options.DoFlowAnalysis, false)) {
- expr = expr.Resolve (rc);
- }
- } else if (expr is TypeParameterExpr) {
- expr.Error_UnexpectedKind (rc, flags, sn.Location);
- expr = null;
- }
- } else {
- expr = expr.Resolve (rc, flags);
+ if (sn != null) {
+ expr = sn.LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity);
+
+ //
+ // Resolve expression which does have type set as we need expression type
+ // with disable flow analysis as we don't know whether left side expression
+ // is used as variable or type
+ //
+ if (expr is VariableReference || expr is ConstantExpr || expr is Linq.TransparentMemberAccess) {
+ expr = expr.Resolve (rc);
+ } else if (expr is TypeParameterExpr) {
+ expr.Error_UnexpectedKind (rc, flags, sn.Location);
+ expr = null;
}
+ } else {
+ expr = expr.Resolve (rc, flags);
}
if (expr == null)
//
public class BlockContext : ResolveContext
{
- FlowBranching current_flow_branching;
-
readonly TypeSpec return_type;
//
flags |= ResolveContext.Options.BaseInitializer;
}
- public override FlowBranching CurrentBranching {
- get { return current_flow_branching; }
- }
+ public ExceptionStatement CurrentTryBlock { get; set; }
- public TypeSpec ReturnType {
- get { return return_type; }
- }
+ public LoopStatement EnclosingLoop { get; set; }
- public bool IsUnreachable {
- get {
- return HasSet (Options.UnreachableScope);
- }
- set {
- flags = value ? flags | Options.UnreachableScope : flags & ~Options.UnreachableScope;
- }
- }
+ public LoopStatement EnclosingLoopOrSwitch { get; set; }
- public bool UnreachableReported {
- get {
- return HasSet (Options.UnreachableReported);
- }
- set {
- flags = value ? flags | Options.UnreachableReported : flags & ~Options.UnreachableScope;
- }
- }
+ public Switch Switch { get; set; }
- // <summary>
- // Starts a new code branching. This inherits the state of all local
- // variables and parameters from the current branching.
- // </summary>
- public FlowBranching StartFlowBranching (FlowBranching.BranchingType type, Location loc)
- {
- current_flow_branching = FlowBranching.CreateBranching (CurrentBranching, type, null, loc);
- return current_flow_branching;
- }
-
- // <summary>
- // Starts a new code branching for block `block'.
- // </summary>
- public FlowBranching StartFlowBranching (Block block)
- {
- Set (Options.DoFlowAnalysis);
-
- current_flow_branching = FlowBranching.CreateBranching (
- CurrentBranching, FlowBranching.BranchingType.Block, block, block.StartLocation);
- return current_flow_branching;
- }
-
- public FlowBranchingTryCatch StartFlowBranching (TryCatch stmt)
- {
- FlowBranchingTryCatch branching = new FlowBranchingTryCatch (CurrentBranching, stmt);
- current_flow_branching = branching;
- return branching;
- }
-
- public FlowBranchingTryFinally StartFlowBranching (TryFinallyBlock stmt)
- {
- FlowBranchingTryFinally branching = new FlowBranchingTryFinally (CurrentBranching, stmt);
- current_flow_branching = branching;
- return branching;
- }
-
- public FlowBranchingLabeled StartFlowBranching (LabeledStatement stmt)
- {
- FlowBranchingLabeled branching = new FlowBranchingLabeled (CurrentBranching, stmt);
- current_flow_branching = branching;
- return branching;
- }
-
- public FlowBranchingIterator StartFlowBranching (Iterator iterator, FlowBranching parent)
- {
- FlowBranchingIterator branching = new FlowBranchingIterator (parent, iterator);
- current_flow_branching = branching;
- return branching;
- }
-
- public FlowBranchingAsync StartFlowBranching (AsyncInitializer asyncBody, FlowBranching parent)
- {
- var branching = new FlowBranchingAsync (parent, asyncBody);
- current_flow_branching = branching;
- return branching;
- }
-
- public FlowBranchingToplevel StartFlowBranching (ParametersBlock stmt, FlowBranching parent)
- {
- FlowBranchingToplevel branching = new FlowBranchingToplevel (parent, stmt);
- current_flow_branching = branching;
- return branching;
- }
-
- // <summary>
- // Ends a code branching. Merges the state of locals and parameters
- // from all the children of the ending branching.
- // </summary>
- public bool EndFlowBranching ()
- {
- FlowBranching old = current_flow_branching;
- current_flow_branching = current_flow_branching.Parent;
-
- FlowBranching.UsageVector vector = current_flow_branching.MergeChild (old);
- return vector.IsUnreachable;
- }
-
- // <summary>
- // Kills the current code branching. This throws away any changed state
- // information and should only be used in case of an error.
- // </summary>
- // FIXME: this is evil
- public void KillFlowBranching ()
- {
- current_flow_branching = current_flow_branching.Parent;
- }
-
-#if !STATIC
- public void NeedReturnLabel ()
- {
+ public TypeSpec ReturnType {
+ get { return return_type; }
}
-#endif
}
//
LockScope = 1 << 13,
- UnreachableScope = 1 << 14,
-
- UnreachableReported = 1 << 15,
+ TryScope = 1 << 14,
- /// <summary>
- /// Whether control flow analysis is enabled
- /// </summary>
- DoFlowAnalysis = 1 << 20,
-
- /// <summary>
- /// Whether control flow analysis is disabled on structs
- /// (only meaningful when DoFlowAnalysis is set)
- /// </summary>
- OmitStructFlowAnalysis = 1 << 21,
+ TryWithCatchScope = 1 << 15,
///
/// Indicates the current context is in probing mode, no errors are reported.
public readonly IMemberContext MemberContext;
- /// <summary>
- /// If this is non-null, points to the current switch statement
- /// </summary>
- public Switch Switch;
-
public ResolveContext (IMemberContext mc)
{
if (mc == null)
}
}
- public virtual FlowBranching CurrentBranching {
- get { return null; }
- }
-
//
// The current iterator
//
get { return (flags & Options.ConstantCheckState) != 0; }
}
- public bool DoFlowAnalysis {
- get { return (flags & Options.DoFlowAnalysis) != 0; }
- }
-
public bool IsInProbingMode {
get {
return (flags & Options.ProbingMode) != 0;
public bool IsVariableCapturingRequired {
get {
- return !IsInProbingMode && (CurrentBranching == null || !CurrentBranching.CurrentUsageVector.IsUnreachable);
+ return !IsInProbingMode;
}
}
}
}
- public bool OmitStructFlowAnalysis {
- get { return (flags & Options.OmitStructFlowAnalysis) != 0; }
- }
-
public Report Report {
get {
return Module.Compiler.Report;
//
// Capture only if this or any of child blocks contain await
- // or it's a parameter
+ // or it's a parameter or we need to access variable from
+ // different parameter block
//
if (CurrentAnonymousMethod is AsyncInitializer)
- return local.IsParameter || local.Block.Explicit.HasAwait || CurrentBlock.Explicit.HasAwait;
+ return local.IsParameter || local.Block.Explicit.HasAwait || CurrentBlock.Explicit.HasAwait ||
+ local.Block.ParametersBlock != CurrentBlock.ParametersBlock.Original;
return local.Block.ParametersBlock != CurrentBlock.ParametersBlock.Original;
}
#endregion
}
+ public class FlowAnalysisContext
+ {
+ readonly CompilerContext ctx;
+
+ public FlowAnalysisContext (CompilerContext ctx, ParametersBlock parametersBlock, int definiteAssignmentLength)
+ {
+ this.ctx = ctx;
+ this.ParametersBlock = parametersBlock;
+
+ DefiniteAssignment = definiteAssignmentLength == 0 ?
+ DefiniteAssignmentBitSet.Empty :
+ new DefiniteAssignmentBitSet (definiteAssignmentLength);
+ }
+
+ public DefiniteAssignmentBitSet DefiniteAssignment { get; set; }
+
+ public DefiniteAssignmentBitSet DefiniteAssignmentOnTrue { get; set; }
+
+ public DefiniteAssignmentBitSet DefiniteAssignmentOnFalse { get; set; }
+
+ public List<LabeledStatement> LabelStack { get; set; }
+
+ public ParametersBlock ParametersBlock { get; set; }
+
+ public Report Report {
+ get {
+ return ctx.Report;
+ }
+ }
+
+ public DefiniteAssignmentBitSet SwitchInitialDefinitiveAssignment { get; set; }
+
+ public TryFinally TryFinally { get; set; }
+
+ public bool UnreachableReported { get; set; }
+
+ public DefiniteAssignmentBitSet BranchDefiniteAssignment ()
+ {
+ var dat = DefiniteAssignment;
+ if (dat != DefiniteAssignmentBitSet.Empty)
+ DefiniteAssignment = new DefiniteAssignmentBitSet (dat);
+ return dat;
+ }
+
+ public bool IsDefinitelyAssigned (VariableInfo variable)
+ {
+ return variable.IsAssigned (DefiniteAssignment);
+ }
+
+ public bool IsStructFieldDefinitelyAssigned (VariableInfo variable, string name)
+ {
+ return variable.IsStructFieldAssigned (DefiniteAssignment, name);
+ }
+
+ public void SetVariableAssigned (VariableInfo variable, bool generatedAssignment = false)
+ {
+ variable.SetAssigned (DefiniteAssignment, generatedAssignment);
+ }
+
+ public void SetStructFieldAssigned (VariableInfo variable, string name)
+ {
+ variable.SetStructFieldAssigned (DefiniteAssignment, name);
+ }
+ }
+
+
//
// This class is used during the Statement.Clone operation
// to remap objects that have been cloned.
string path;
if (!Path.IsPathRooted (name)) {
- string root = Path.GetDirectoryName (comp_unit.SourceFile.FullPathName);
- path = Path.Combine (root, name);
+ var loc = comp_unit.SourceFile;
+ string root = Path.GetDirectoryName (loc.FullPathName);
+ path = Path.GetFullPath (Path.Combine (root, name));
+ var dir = Path.GetDirectoryName (loc.Name);
+ if (!string.IsNullOrEmpty (dir))
+ name = Path.Combine (dir, name);
} else
path = name;
}
| TRY block FINALLY block
{
- $$ = new TryFinally ((Statement) $2, (Block) $4, GetLocation ($1));
+ $$ = new TryFinally ((Statement) $2, (ExplicitBlock) $4, GetLocation ($1));
lbag.AddStatement ($$, GetLocation ($3));
}
| TRY block catch_clauses FINALLY block
{
- $$ = new TryFinally (new TryCatch ((Block) $2, (List<Catch>) $3, Location.Null, true), (Block) $5, GetLocation ($1));
+ $$ = new TryFinally (new TryCatch ((Block) $2, (List<Catch>) $3, Location.Null, true), (ExplicitBlock) $5, GetLocation ($1));
lbag.AddStatement ($$, GetLocation ($4));
}
| TRY block error
catch_clause
: CATCH block
{
- $$ = new Catch ((Block) $2, GetLocation ($1));
+ $$ = new Catch ((ExplicitBlock) $2, GetLocation ($1));
}
| CATCH open_parens_any type opt_identifier CLOSE_PARENS
{
start_block (GetLocation ($2));
- var c = new Catch (current_block, GetLocation ($1));
+ var c = new Catch ((ExplicitBlock) current_block, GetLocation ($1));
c.TypeExpression = (FullNamedExpression) $3;
if ($4 != null) {
lang_version = settings.Version;
yacc_verbose_flag = settings.VerboseParserFlag;
doc_support = settings.DocumentationFile != null;
- lexer = new Tokenizer (reader, file, session);
+ lexer = new Tokenizer (reader, file, session, report);
oob_stack = new Stack<object> ();
lbag = session.LocationsBag;
use_global_stacks = session.UseJayGlobalArrays;
readonly SeekableStreamReader reader;
readonly CompilationSourceFile source_file;
readonly CompilerContext context;
+ readonly Report Report;
+
SourceFile current_source;
Location hidden_block_start;
}
}
- public Tokenizer (SeekableStreamReader input, CompilationSourceFile file, ParserSession session)
+ public Tokenizer (SeekableStreamReader input, CompilationSourceFile file, ParserSession session, Report report)
{
this.source_file = file;
this.context = file.Compiler;
this.id_builder = session.IDBuilder;
this.number_builder = session.NumberBuilder;
this.ltb = new LocatedTokenBuffer (session.LocatedTokens);
+ this.Report = report;
reader = input;
return null;
}
- Report Report {
- get { return context.Report; }
- }
-
void reset_doc_comment ()
{
xml_comment_buffer.Length = 0;
}
}
- TypeSpec rt = delegate_method.ReturnType;
+ TypeSpec rt = method_group.BestCandidateReturnType;
if (rt.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
rt = ec.BuiltinTypes.Object;
Error_ConversionFailed (ec, delegate_method, ret_expr);
}
- if (delegate_method.IsConditionallyExcluded (ec)) {
+ if (method_group.IsConditionallyExcluded) {
ec.Report.SymbolRelatedToPreviousError (delegate_method);
MethodOrOperator m = delegate_method.MemberDefinition as MethodOrOperator;
if (m != null && m.IsPartialDefinition) {
return CreateExpressionFactoryCall (ec, "Invoke", args);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ InstanceExpr.FlowAnalysis (fc);
+ if (arguments != null)
+ arguments.FlowAnalysis (fc);
+ }
+
protected override Expression DoResolve (ResolveContext ec)
{
TypeSpec del_type = InstanceExpr.Type;
SeekableStreamReader reader = new SeekableStreamReader (input, ctx.Settings.Encoding);
var file = new CompilationSourceFile (module, sourceFile);
- Tokenizer lexer = new Tokenizer (reader, file, session);
+ Tokenizer lexer = new Tokenizer (reader, file, session, ctx.Report);
int token, tokens = 0, errors = 0;
while ((token = lexer.token ()) != Token.EOF){
d.PrepareEmit ();
site.AddTypeContainer (d);
+
+ //
+ // Add new container to inflated site container when the
+ // member cache already exists
+ //
+ if (site.CurrentType is InflatedTypeSpec && index > 0)
+ site.CurrentType.MemberCache.AddMember (d.CurrentType);
+
del_type = new TypeExpression (d.CurrentType, loc);
if (targs_for_instance != null) {
del_type_instance_access = null;
}
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ arguments.FlowAnalysis (fc);
+ }
+
public static MemberAccess GetBinderNamespace (Location loc)
{
return new MemberAccess (new MemberAccess (
stmt.Emit (ec);
}
}
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ invoke.FlowAnalysis (fc);
+ }
}
class DynamicConversion : DynamicExpressionStatement, IDynamicBinder
{
var ctors = MemberCache.FindMembers (type, Constructor.ConstructorName, true);
if (ctors == null) {
- rc.Report.SymbolRelatedToPreviousError (type);
- if (type.IsStruct) {
+ switch (type.Kind) {
+ case MemberKind.Struct:
+ rc.Report.SymbolRelatedToPreviousError (type);
// Report meaningful error for struct as they always have default ctor in C# context
OverloadResolver.Error_ConstructorMismatch (rc, type, args == null ? 0 : args.Count, loc);
- } else {
+ break;
+ case MemberKind.MissingType:
+ case MemberKind.InternalCompilerType:
+ break;
+ default:
+ rc.Report.SymbolRelatedToPreviousError (type);
rc.Report.Error (143, loc, "The class `{0}' has no constructors defined",
type.GetSignatureForError ());
+ break;
}
return null;
ec.Report.Error (1944, loc, "An expression tree cannot contain an unsafe pointer operation");
}
+ public virtual void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ }
+
/// <summary>
/// Returns an expression that can be used to invoke operator true
/// on the expression if it exists.
/// </summary>
public abstract class ExpressionStatement : Expression
{
+ public virtual void MarkReachable (Reachability rc)
+ {
+ }
+
public ExpressionStatement ResolveStatement (BlockContext ec)
{
Expression e = Resolve (ec);
return null;
ExpressionStatement es = e as ExpressionStatement;
- if (es == null)
+ if (es == null || e is AnonymousMethodBody)
Error_InvalidExpressionStatement (ec);
//
child.Emit (ec);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ child.FlowAnalysis (fc);
+ }
+
public override SLE.Expression MakeExpression (BuilderContext ctx)
{
#if STATIC
{
stm.EmitStatement (ec);
}
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ stm.FlowAnalysis (fc);
+ }
}
readonly Expression expr, orig_expr;
expr.EmitBranchable (ec, target, on_true);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ expr.FlowAnalysis (fc);
+ }
+
public override SLE.Expression MakeExpression (BuilderContext ctx)
{
return orig_expr.MakeExpression (ctx);
{
throw new InternalErrorException ("Missing Resolve call");
}
+ }
+
+ public class UnreachableExpression : Expression
+ {
+ public UnreachableExpression (Expression expr)
+ {
+ this.loc = expr.Location;
+ }
+
+ public override Expression CreateExpressionTree (ResolveContext ec)
+ {
+ // TODO: is it ok
+ throw new NotImplementedException ();
+ }
+ protected override Expression DoResolve (ResolveContext rc)
+ {
+ throw new NotSupportedException ();
+ }
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ fc.Report.Warning (429, 4, loc, "Unreachable expression code detected");
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ }
+
+ public override void EmitBranchable (EmitContext ec, Label target, bool on_true)
+ {
+ }
}
//
protected override Expression DoResolve (ResolveContext rc)
{
- var e = SimpleNameResolve (rc, null);
-
- var fe = e as FieldExpr;
- if (fe != null) {
- fe.VerifyAssignedStructField (rc, null);
- }
-
- return e;
+ return SimpleNameResolve (rc, null);
}
public override Expression DoResolveLValue (ResolveContext ec, Expression right_side)
member.GetSignatureForError (), qualifier.GetSignatureForError (), rc.CurrentType.GetSignatureForError ());
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ if (InstanceExpression != null)
+ InstanceExpression.FlowAnalysis (fc);
+ }
+
public bool ResolveInstanceExpression (ResolveContext rc, Expression rhs)
{
if (!ResolveInstanceExpressionCore (rc, rhs))
rc.Report.Error (1648, loc, "Members of readonly field `{0}' cannot be modified (except in a constructor or a variable initializer)",
fexpr.GetSignatureForError ());
}
- } else if (InstanceExpression is PropertyExpr || InstanceExpression is IndexerExpr || InstanceExpression is Invocation) {
+
+ return true;
+ }
+
+ if (InstanceExpression is PropertyExpr || InstanceExpression is IndexerExpr || InstanceExpression is Invocation) {
if (rc.CurrentInitializerVariable != null) {
rc.Report.Error (1918, loc, "Members of value type `{0}' cannot be assigned using a property `{1}' object initializer",
InstanceExpression.Type.GetSignatureForError (), InstanceExpression.GetSignatureForError ());
"Cannot modify a value type return value of `{0}'. Consider storing the value in a temporary variable",
InstanceExpression.GetSignatureForError ());
}
+
+ return true;
+ }
+
+ var lvr = InstanceExpression as LocalVariableReference;
+ if (lvr != null) {
+
+ if (!lvr.local_info.IsReadonly)
+ return true;
+
+ rc.Report.Error (1654, loc, "Cannot assign to members of `{0}' because it is a `{1}'",
+ InstanceExpression.GetSignatureForError (), lvr.local_info.GetReadOnlyContext ());
}
}
DeclaringType.GetSignatureForError (), rc.CurrentType.GetSignatureForError ());
}
- InstanceExpression = new This (loc);
- if (this is FieldExpr && rc.CurrentBlock.ParametersBlock.TopBlock.ThisVariable != null) {
- using (rc.Set (ResolveContext.Options.OmitStructFlowAnalysis)) {
- InstanceExpression = InstanceExpression.Resolve (rc);
- }
- } else {
- InstanceExpression = InstanceExpression.Resolve (rc);
- }
-
+ InstanceExpression = new This (loc).Resolve (rc);
return false;
}
if (me != null) {
me.ResolveInstanceExpressionCore (rc, rhs);
- // Using this check to detect probing instance expression resolve
- if (!rc.OmitStructFlowAnalysis) {
- var fe = me as FieldExpr;
- if (fe != null && fe.IsMarshalByRefAccess (rc)) {
- rc.Report.SymbolRelatedToPreviousError (me.DeclaringType);
- rc.Report.Warning (1690, 1, loc,
- "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class",
- me.GetSignatureForError ());
- }
+ var fe = me as FieldExpr;
+ if (fe != null && fe.IsMarshalByRefAccess (rc)) {
+ rc.Report.SymbolRelatedToPreviousError (me.DeclaringType);
+ rc.Report.Warning (1690, 1, loc,
+ "Cannot call methods, properties, or indexers on `{0}' because it is a value type member of a marshal-by-reference class",
+ me.GetSignatureForError ());
}
return true;
}
- //
- // Run member-access postponed check once we know that
- // the expression is not field expression which is the only
- // expression which can use uninitialized this
- //
- if (InstanceExpression is This && !(this is FieldExpr) && rc.CurrentBlock.ParametersBlock.TopBlock.ThisVariable != null) {
- ((This)InstanceExpression).CheckStructThisDefiniteAssignment (rc);
- }
-
//
// Additional checks for l-value member access
//
/// </summary>
public class MethodGroupExpr : MemberExpr, OverloadResolver.IBaseMembersProvider
{
+ static readonly MemberSpec[] Excluded = new MemberSpec[0];
+
protected IList<MemberSpec> Methods;
MethodSpec best_candidate;
TypeSpec best_candidate_return;
}
}
+ public bool IsConditionallyExcluded {
+ get {
+ return Methods == Excluded;
+ }
+ }
+
public override bool IsInstance {
get {
if (best_candidate != null)
return null;
}
- if (best_candidate.IsConditionallyExcluded (ec))
+ if (IsConditionallyExcluded)
ec.Report.Error (765, loc,
"Partial methods with only a defining declaration or removed conditional methods cannot be used in an expression tree");
ErrorIsInaccesible (ec, best_candidate.GetSignatureForError (), loc);
}
+ // Speed up the check by not doing it on disallowed targets
+ if (best_candidate_return.Kind == MemberKind.Void && best_candidate.IsConditionallyExcluded (ec))
+ Methods = Excluded;
+
return this;
}
if (ms.TypeArguments != null)
constr_ok = new ConstraintChecker (rc.MemberContext).CheckAll (ms.GetGenericMethodDefinition (), ms.TypeArguments, ms.Constraints, loc);
- if (ta_count == 0) {
+ if (ta_count == 0 && ms.TypeArguments == null) {
if (custom_errors != null && custom_errors.TypeInferenceFailed (rc, best_candidate))
return;
// "a.b" is initialized, not whether the whole struct "a" is initialized.
if (lvalue_instance) {
- using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
- bool out_access = rhs == EmptyExpression.OutAccess || rhs == EmptyExpression.LValueMemberOutAccess;
+ bool out_access = rhs == EmptyExpression.OutAccess || rhs == EmptyExpression.LValueMemberOutAccess;
- Expression right_side =
- out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
+ Expression right_side =
+ out_access ? EmptyExpression.LValueMemberOutAccess : EmptyExpression.LValueMemberAccess;
- InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side);
- }
+ InstanceExpression = InstanceExpression.ResolveLValue (ec, right_side);
} else {
- using (ec.With (ResolveContext.Options.DoFlowAnalysis, false)) {
- InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue);
- }
+ InstanceExpression = InstanceExpression.Resolve (ec, ResolveFlags.VariableOrValue);
}
if (InstanceExpression == null)
var fb = spec as FixedFieldSpec;
IVariableReference var = InstanceExpression as IVariableReference;
- if (lvalue_instance && var != null && var.VariableInfo != null) {
- var.VariableInfo.SetStructFieldAssigned (ec, Name);
- }
-
if (fb != null) {
IFixedExpression fe = InstanceExpression as IFixedExpression;
if (!ec.HasSet (ResolveContext.Options.FixedInitializerScope) && (fe == null || !fe.IsFixed)) {
//
if (var != null && var.VariableInfo != null && InstanceExpression.Type.IsStruct) {
variable_info = var.VariableInfo.GetStructFieldInfo (Name);
- if (rhs != null && variable_info != null)
- variable_info.SetStructFieldAssigned (ec, Name);
}
eclass = ExprClass.Variable;
return this;
}
- public void VerifyAssignedStructField (ResolveContext rc, Expression rhs)
+ public void SetFieldAssigned (FlowAnalysisContext fc)
+ {
+ if (!IsInstance)
+ return;
+
+ bool lvalue_instance = spec.DeclaringType.IsStruct;
+ if (lvalue_instance) {
+ var var = InstanceExpression as IVariableReference;
+ if (var != null && var.VariableInfo != null) {
+ fc.SetStructFieldAssigned (var.VariableInfo, Name);
+ }
+ }
+
+ var fe = InstanceExpression as FieldExpr;
+ if (fe != null || lvalue_instance) {
+ if (fe == null)
+ return;
+
+ /*
+ while (fe.InstanceExpression is FieldExpr) {
+ fe = (FieldExpr) fe.InstanceExpression;
+ if (!fe.Spec.DeclaringType.IsStruct)
+ continue;
+
+ if (fe.VariableInfo != null && fc.IsStructFieldDefinitelyAssigned (fe.VariableInfo, fe.Name)) {
+ fc.Report.Warning (1060, 1, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
+ }
+ }
+
+ fe.InstanceExpression.FlowAnalysis (fc);
+ */
+ } else {
+ InstanceExpression.FlowAnalysis (fc);
+ }
+ }
+
+
+ public void VerifyAssignedStructField (FlowAnalysisContext fc)
{
var fe = this;
if (var != null) {
var vi = var.VariableInfo;
- if (vi != null && !vi.IsStructFieldAssigned (rc, fe.Name) && (rhs == null || !fe.type.IsStruct)) {
- if (rhs != null) {
- rc.Report.Warning (1060, 1, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
- } else {
- rc.Report.Error (170, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
- }
-
- return;
+ if (vi != null && !fc.IsStructFieldDefinitelyAssigned (vi, fe.Name) && !fe.type.IsStruct) {
+ fc.Report.Warning (1060, 1, fe.loc, "Use of possibly unassigned field `{0}'", fe.Name);
}
}
rc.Report.Error (1649, loc, "Members of readonly field `{0}' cannot be passed ref or out (except in a constructor)",
GetSignatureForError ());
}
-
return null;
}
return this;
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ var var = InstanceExpression as IVariableReference;
+ if (var != null) {
+ var vi = var.VariableInfo;
+ if (vi != null && !fc.IsStructFieldDefinitelyAssigned (vi, Name)) {
+ fc.Report.Error (170, loc, "Use of possibly unassigned field `{0}'", Name);
+ return;
+ }
+
+ if (TypeSpec.IsValueType (InstanceExpression.Type))
+ return;
+ }
+
+ base.FlowAnalysis (fc);
+ }
+
public override int GetHashCode ()
{
return spec.GetHashCode ();
DoEmit (ec);
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ return false;
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement target)
{
// Nothing
public override VariableInfo VariableInfo {
get { return null; }
}
-
- public override void VerifyDefiniteAssignment (ResolveContext rc)
- {
- }
}
///
BlockContext bc = new BlockContext (method, method.Block, ctx.BuiltinTypes.Void);
try {
- method.Block.Resolve (null, bc, method);
+ method.Block.Resolve (bc, method);
} catch (CompletionResult cr) {
prefix = cr.BaseText;
return cr.Result;
//
InputKind ToplevelOrStatement (SeekableStreamReader seekable)
{
- Tokenizer tokenizer = new Tokenizer (seekable, source_file, new ParserSession ());
+ Tokenizer tokenizer = new Tokenizer (seekable, source_file, new ParserSession (), ctx.Report);
// Prefer contextual block keywords over identifiers
tokenizer.parsing_block++;
call.EmitPredefined (ec, oper, arguments, loc);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ arguments.FlowAnalysis (fc);
+ }
+
public override SLE.Expression MakeExpression (BuilderContext ctx)
{
#if STATIC
Expr.EmitSideEffect (ec);
}
+ public static void Error_Ambiguous (ResolveContext rc, string oper, TypeSpec type, Location loc)
+ {
+ rc.Report.Error (35, loc, "Operator `{0}' is ambiguous on an operand of type `{1}'",
+ oper, type.GetSignatureForError ());
+ }
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ if (Oper == Operator.AddressOf) {
+ var vr = Expr as VariableReference;
+ if (vr != null && vr.VariableInfo != null)
+ fc.SetVariableAssigned (vr.VariableInfo);
+
+ return;
+ }
+
+ Expr.FlowAnalysis (fc);
+
+ if (Oper == Operator.LogicalNot) {
+ var temp = fc.DefiniteAssignmentOnTrue;
+ fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse;
+ fc.DefiniteAssignmentOnFalse = temp;
+ }
+ }
+
//
// Converts operator to System.Linq.Expressions.ExpressionType enum name
//
int result = OverloadResolver.BetterTypeConversion (ec, best_expr.Type, t);
if (result == 0) {
if ((oper_expr is UserOperatorCall || oper_expr is UserCast) && (best_expr is UserOperatorCall || best_expr is UserCast)) {
- ec.Report.Error (35, loc, "Operator `{0}' is ambiguous on an operand of type `{1}'",
- OperName (Oper), expr.Type.GetSignatureForError ());
+ Error_Ambiguous (ec, OperName (Oper), expr.Type, loc);
} else {
Error_OperatorCannotBeApplied (ec, loc, OperName (Oper), expr.Type);
}
source = operation;
} else {
+ Expression best_source = null;
foreach (var t in ec.BuiltinTypes.OperatorsUnaryMutator) {
source = Convert.ImplicitUserConversion (ec, operation, t, loc);
// LAMESPEC: It should error on ambiguous operators but that would make us incompatible
- if (source != null) {
- break;
+ if (source == null)
+ continue;
+
+ if (best_source == null) {
+ best_source = source;
+ continue;
}
+
+ var better = OverloadResolver.BetterTypeConversion (ec, best_source.Type, source.Type);
+ if (better == 1)
+ continue;
+
+ if (better == 2) {
+ best_source = source;
+ continue;
+ }
+
+ Unary.Error_Ambiguous (ec, OperName (mode), type, loc);
+ break;
}
+
+ source = best_source;
}
// ++/-- on enum types
EmitCode (ec, false);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ expr.FlowAnalysis (fc);
+ }
+
//
// Converts operator to System.Linq.Expressions.ExpressionType enum name
//
}
#endif
+ public static string OperName (Mode oper)
+ {
+ return (oper & Mode.IsDecrement) != 0 ? "--" : "++";
+ }
+
protected override void CloneTo (CloneContext clonectx, Expression t)
{
UnaryMutator target = (UnaryMutator) t;
return this;
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ expr.FlowAnalysis (fc);
+ }
+
protected abstract string OperatorName { get; }
protected override void CloneTo (CloneContext clonectx, Expression t)
Error_OperatorCannotBeApplied (ec, left, right, OperName (oper), loc);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ if ((oper & Operator.LogicalMask) == 0) {
+ left.FlowAnalysis (fc);
+ right.FlowAnalysis (fc);
+ return;
+ }
+
+ //
+ // Optimized version when on-true/on-false data are not needed
+ //
+ bool set_on_true_false;
+ if (fc.DefiniteAssignmentOnTrue == null && fc.DefiniteAssignmentOnFalse == null) {
+ fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignment;
+ set_on_true_false = false;
+ } else {
+ set_on_true_false = true;
+ }
+
+ left.FlowAnalysis (fc);
+ var left_fc = fc.DefiniteAssignment;
+ var left_fc_ontrue = fc.DefiniteAssignmentOnTrue;
+ var left_fc_onfalse = fc.DefiniteAssignmentOnFalse;
+
+ fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignment = new DefiniteAssignmentBitSet (
+ oper == Operator.LogicalOr ? left_fc_onfalse : left_fc_ontrue);
+ right.FlowAnalysis (fc);
+ fc.DefiniteAssignment = left_fc;
+
+ if (!set_on_true_false) {
+ fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignmentOnTrue = null;
+ return;
+ }
+
+ if (oper == Operator.LogicalOr) {
+ fc.DefiniteAssignmentOnTrue = new DefiniteAssignmentBitSet (left_fc_ontrue);
+ fc.DefiniteAssignmentOnFalse = left_fc_onfalse | fc.DefiniteAssignmentOnFalse;
+ } else {
+ fc.DefiniteAssignmentOnTrue = left_fc_ontrue | fc.DefiniteAssignmentOnTrue;
+ fc.DefiniteAssignmentOnFalse = new DefiniteAssignmentBitSet (left_fc_onfalse);
+ }
+ }
+
//
// Converts operator to System.Linq.Expressions.ExpressionType enum name
//
}
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ arguments.FlowAnalysis (fc);
+ }
+
public override SLE.Expression MakeExpression (BuilderContext ctx)
{
if (arguments.Count != 2)
protected override Expression DoResolve (ResolveContext ec)
{
expr = expr.Resolve (ec);
-
- //
- // Unreachable code needs different resolve path. For instance for await
- // expression to not generate unreachable resumable statement
- //
- Constant c = expr as Constant;
- if (c != null && ec.CurrentBranching != null) {
- bool unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable;
-
- if (c.IsDefaultValue) {
- ec.CurrentBranching.CurrentUsageVector.IsUnreachable = true;
- true_expr = true_expr.Resolve (ec);
- ec.CurrentBranching.CurrentUsageVector.IsUnreachable = unreachable;
-
- false_expr = false_expr.Resolve (ec);
- } else {
- true_expr = true_expr.Resolve (ec);
-
- ec.CurrentBranching.CurrentUsageVector.IsUnreachable = true;
- false_expr = false_expr.Resolve (ec);
- ec.CurrentBranching.CurrentUsageVector.IsUnreachable = unreachable;
- }
- } else {
- true_expr = true_expr.Resolve (ec);
- false_expr = false_expr.Resolve (ec);
- }
+ true_expr = true_expr.Resolve (ec);
+ false_expr = false_expr.Resolve (ec);
if (true_expr == null || false_expr == null || expr == null)
return null;
true_type.GetSignatureForError (), false_type.GetSignatureForError ());
return null;
}
- }
+ }
+ Constant c = expr as Constant;
if (c != null) {
bool is_false = c.IsDefaultValue;
ec.MarkLabel (end_target);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignment;
+
+ expr.FlowAnalysis (fc);
+ var da_true = fc.DefiniteAssignmentOnTrue;
+ var da_false = fc.DefiniteAssignmentOnFalse;
+
+ fc.DefiniteAssignment = new DefiniteAssignmentBitSet (da_true);
+ true_expr.FlowAnalysis (fc);
+ var true_fc = fc.DefiniteAssignment;
+
+ fc.DefiniteAssignment = new DefiniteAssignmentBitSet (da_false);
+ false_expr.FlowAnalysis (fc);
+
+ fc.DefiniteAssignment &= true_fc;
+ if (fc.DefiniteAssignmentOnTrue != null)
+ fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignment;
+ if (fc.DefiniteAssignmentOnFalse != null)
+ fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignment;
+ }
+
protected override void CloneTo (CloneContext clonectx, Expression t)
{
Conditional target = (Conditional) t;
#region Abstract
public abstract HoistedVariable GetHoistedVariable (AnonymousExpression ae);
public abstract void SetHasAddressTaken ();
- public abstract void VerifyDefiniteAssignment (ResolveContext rc);
public abstract bool IsLockedByStatement { get; set; }
#endregion
- public override void VerifyDefiniteAssignment (ResolveContext rc)
+ public override void FlowAnalysis (FlowAnalysisContext fc)
{
VariableInfo variable_info = VariableInfo;
if (variable_info == null)
return;
- if (variable_info.IsAssigned (rc))
+ if (fc.IsDefinitelyAssigned (variable_info))
return;
- rc.Report.Error (165, loc, "Use of unassigned local variable `{0}'", Name);
- variable_info.SetAssigned (rc);
+ fc.Report.Error (165, loc, "Use of unassigned local variable `{0}'", Name);
+ variable_info.SetAssigned (fc.DefiniteAssignment, true);
}
public override void SetHasAddressTaken ()
{
local_info.SetIsUsed ();
- VerifyDefiniteAssignment (ec);
-
DoResolveBase (ec);
return this;
}
local_info.SetIsUsed ();
if (local_info.IsReadonly && !ec.HasAny (ResolveContext.Options.FieldInitializerScope | ResolveContext.Options.UsingInitializerScope)) {
- int code;
- string msg;
- if (rhs == EmptyExpression.OutAccess) {
- code = 1657; msg = "Cannot pass `{0}' as a ref or out argument because it is a `{1}'";
- } else if (rhs == EmptyExpression.LValueMemberAccess) {
- code = 1654; msg = "Cannot assign to members of `{0}' because it is a `{1}'";
- } else if (rhs == EmptyExpression.LValueMemberOutAccess) {
- code = 1655; msg = "Cannot pass members of `{0}' as ref or out arguments because it is a `{1}'";
- } else if (rhs == EmptyExpression.UnaryAddress) {
- code = 459; msg = "Cannot take the address of {1} `{0}'";
+ if (rhs == EmptyExpression.LValueMemberAccess) {
+ // CS1654 already reported
} else {
- code = 1656; msg = "Cannot assign to `{0}' because it is a `{1}'";
+ int code;
+ string msg;
+ if (rhs == EmptyExpression.OutAccess) {
+ code = 1657; msg = "Cannot pass `{0}' as a ref or out argument because it is a `{1}'";
+ } else if (rhs == EmptyExpression.LValueMemberOutAccess) {
+ code = 1655; msg = "Cannot pass members of `{0}' as ref or out arguments because it is a `{1}'";
+ } else if (rhs == EmptyExpression.UnaryAddress) {
+ code = 459; msg = "Cannot take the address of {1} `{0}'";
+ } else {
+ code = 1656; msg = "Cannot assign to `{0}' because it is a `{1}'";
+ }
+ ec.Report.Error (code, loc, msg, Name, local_info.GetReadOnlyContext ());
}
- ec.Report.Error (code, loc, msg, Name, local_info.GetReadOnlyContext ());
- } else if (VariableInfo != null) {
- VariableInfo.SetAssigned (ec);
}
if (eclass == ExprClass.Unresolved)
Parameter.HasAddressTaken = true;
}
- void SetAssigned (ResolveContext ec)
- {
- if (Parameter.HoistedVariant != null)
- Parameter.HoistedVariant.IsAssigned = true;
-
- if (HasOutModifier && ec.DoFlowAnalysis)
- ec.CurrentBranching.SetAssigned (VariableInfo);
- }
-
bool DoResolveBase (ResolveContext ec)
{
if (eclass != ExprClass.Unresolved)
if (!DoResolveBase (ec))
return null;
- VerifyDefiniteAssignment (ec);
return this;
}
if (!DoResolveBase (ec))
return null;
- SetAssigned (ec);
+ if (Parameter.HoistedVariant != null)
+ Parameter.HoistedVariant.IsAssigned = true;
+
return base.DoResolveLValue (ec, right_side);
}
- public override void VerifyDefiniteAssignment (ResolveContext rc)
+ public override void FlowAnalysis (FlowAnalysisContext fc)
{
VariableInfo variable_info = VariableInfo;
if (variable_info == null)
return;
- if (variable_info.IsAssigned (rc))
+ if (fc.IsDefinitelyAssigned (variable_info))
return;
- rc.Report.Error (269, loc, "Use of unassigned out parameter `{0}'", Name);
- variable_info.SetAssigned (rc);
+ fc.Report.Error (269, loc, "Use of unassigned out parameter `{0}'", Name);
+ fc.SetVariableAssigned (variable_info);
}
}
var emg = MethodGroup as ExtensionMethodGroupExpr;
if (emg != null) {
- return MethodGroupExpr.CreatePredefined (candidate, candidate.DeclaringType, MethodGroup.Location);
+ var mg = MethodGroupExpr.CreatePredefined (candidate, candidate.DeclaringType, MethodGroup.Location);
+ if (candidate.IsGeneric) {
+ var targs = new TypeExpression [candidate.Arity];
+ for (int i = 0; i < targs.Length; ++i) {
+ targs[i] = new TypeExpression (candidate.TypeArguments[i], MethodGroup.Location);
+ }
+
+ mg.SetTypeArguments (null, new TypeArguments (targs));
+ }
+
+ return mg;
}
return MethodGroup;
return mg.OverloadResolve (ec, ref arguments, null, OverloadResolver.Restrictions.None);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ if (mg.IsConditionallyExcluded)
+ return;
+
+ mg.FlowAnalysis (fc);
+
+ if (arguments != null)
+ arguments.FlowAnalysis (fc);
+ }
+
public override string GetSignatureForError ()
{
return mg.GetSignatureForError ();
public override void Emit (EmitContext ec)
{
+ if (mg.IsConditionallyExcluded)
+ return;
+
mg.EmitCall (ec, arguments);
}
ec.Emit (OpCodes.Pop);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ if (arguments != null)
+ arguments.FlowAnalysis (fc);
+ }
+
public void AddressOf (EmitContext ec, AddressOp mode)
{
EmitAddressOf (ec, mode);
{
throw new InternalErrorException ("Missing Resolve call");
}
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ throw new InternalErrorException ("Missing Resolve call");
+ }
public override object Accept (StructuralVisitor visitor)
{
ec.Report.Error (248, loc, "Cannot create an array with a negative size");
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ foreach (var arg in arguments)
+ arg.FlowAnalysis (fc);
+
+ if (array_data != null) {
+ foreach (var ad in array_data)
+ ad.FlowAnalysis (fc);
+ }
+ }
+
bool InitializersContainAwait ()
{
if (array_data == null)
#endregion
- public void CheckStructThisDefiniteAssignment (ResolveContext rc)
+ void CheckStructThisDefiniteAssignment (FlowAnalysisContext fc)
{
//
// It's null for all cases when we don't need to check `this'
if (variable_info == null)
return;
- if (rc.OmitStructFlowAnalysis)
+ if (fc.IsDefinitelyAssigned (variable_info))
return;
- if (!variable_info.IsAssigned (rc)) {
- rc.Report.Error (188, loc,
- "The `this' object cannot be used before all of its fields are assigned to");
- }
+ fc.Report.Error (188, loc, "The `this' object cannot be used before all of its fields are assigned to");
}
protected virtual void Error_ThisNotAvailable (ResolveContext ec)
}
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ CheckStructThisDefiniteAssignment (fc);
+ }
+
public override HoistedVariable GetHoistedVariable (AnonymousExpression ae)
{
if (ae == null)
protected override Expression DoResolve (ResolveContext ec)
{
ResolveBase (ec);
-
- CheckStructThisDefiniteAssignment (ec);
-
return this;
}
if (eclass == ExprClass.Unresolved)
ResolveBase (ec);
- if (variable_info != null)
- variable_info.SetAssigned (ec);
-
if (type.IsClass){
if (right_side == EmptyExpression.UnaryAddress)
ec.Report.Error (459, loc, "Cannot take the address of `this' because it is read-only");
{
// Nothing
}
-
- public override void VerifyDefiniteAssignment (ResolveContext rc)
- {
- }
public override object Accept (StructuralVisitor visitor)
{
protected override Expression DoResolve (ResolveContext rc)
{
- var e = DoResolveName (rc, null);
-
- if (!rc.OmitStructFlowAnalysis) {
- var fe = e as FieldExpr;
- if (fe != null) {
- fe.VerifyAssignedStructField (rc, null);
- }
- }
+ var e = LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess);
+ if (e != null)
+ e = e.Resolve (rc, ResolveFlags.VariableOrValue | ResolveFlags.Type | ResolveFlags.MethodGroup);
return e;
}
public override Expression DoResolveLValue (ResolveContext rc, Expression rhs)
{
- var e = DoResolveName (rc, rhs);
+ var e = LookupNameExpression (rc, MemberLookupRestrictions.None);
- if (!rc.OmitStructFlowAnalysis) {
- var fe = e as FieldExpr;
- if (fe != null && fe.InstanceExpression is FieldExpr) {
- fe = (FieldExpr) fe.InstanceExpression;
- fe.VerifyAssignedStructField (rc, rhs);
- }
- }
-
- return e;
- }
-
- Expression DoResolveName (ResolveContext rc, Expression right_side)
- {
- Expression e = LookupNameExpression (rc, right_side == null ? MemberLookupRestrictions.ReadAccess : MemberLookupRestrictions.None);
- if (e == null)
+ if (e is TypeExpr) {
+ e.Error_UnexpectedKind (rc, ResolveFlags.VariableOrValue, loc);
return null;
-
- if (right_side != null) {
- if (e is TypeExpr) {
- e.Error_UnexpectedKind (rc, ResolveFlags.VariableOrValue, loc);
- return null;
- }
-
- e = e.ResolveLValue (rc, right_side);
- } else {
- e = e.Resolve (rc, ResolveFlags.VariableOrValue | ResolveFlags.Type | ResolveFlags.MethodGroup);
}
+ if (e != null)
+ e = e.ResolveLValue (rc, rhs);
+
return e;
}
var sn = expr as SimpleName;
const ResolveFlags flags = ResolveFlags.VariableOrValue | ResolveFlags.Type;
- //
- // Resolve the expression with flow analysis turned off, we'll do the definite
- // assignment checks later. This is because we don't know yet what the expression
- // will resolve to - it may resolve to a FieldExpr and in this case we must do the
- // definite assignment check on the actual field and not on the whole struct.
- //
- using (rc.Set (ResolveContext.Options.OmitStructFlowAnalysis)) {
- if (sn != null) {
- expr = sn.LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity);
+ if (sn != null) {
+ expr = sn.LookupNameExpression (rc, MemberLookupRestrictions.ReadAccess | MemberLookupRestrictions.ExactArity);
- //
- // Resolve expression which does have type set as we need expression type
- // with disable flow analysis as we don't know whether left side expression
- // is used as variable or type
- //
- if (expr is VariableReference || expr is ConstantExpr || expr is Linq.TransparentMemberAccess) {
- using (rc.With (ResolveContext.Options.DoFlowAnalysis, false)) {
- expr = expr.Resolve (rc);
- }
- } else if (expr is TypeParameterExpr) {
- expr.Error_UnexpectedKind (rc, flags, sn.Location);
- expr = null;
- }
- } else {
- expr = expr.Resolve (rc, flags);
+ //
+ // Resolve expression which does have type set as we need expression type
+ // with disable flow analysis as we don't know whether left side expression
+ // is used as variable or type
+ //
+ if (expr is VariableReference || expr is ConstantExpr || expr is Linq.TransparentMemberAccess) {
+ expr = expr.Resolve (rc);
+ } else if (expr is TypeParameterExpr) {
+ expr.Error_UnexpectedKind (rc, flags, sn.Location);
+ expr = null;
}
+ } else {
+ expr = expr.Resolve (rc, flags);
}
if (expr == null)
if (me != null)
me.ResolveInstanceExpression (rc, null);
- //
- // Run defined assigned checks on expressions resolved with
- // disabled flow-analysis
- //
- if (sn != null) {
- var vr = expr as VariableReference;
- if (vr != null)
- vr.VerifyDefiniteAssignment (rc);
- }
-
Arguments args = new Arguments (1);
args.Add (new Argument (expr));
return new DynamicMemberBinder (Name, args, loc);
emg.SetTypeArguments (rc, targs);
}
- //
- // Run defined assigned checks on expressions resolved with
- // disabled flow-analysis
- //
- if (sn != null && !errorMode) {
- var vr = expr as VariableReference;
- if (vr != null)
- vr.VerifyDefiniteAssignment (rc);
- }
-
// TODO: it should really skip the checks bellow
return emg.Resolve (rc);
}
me.SetTypeArguments (rc, targs);
}
- //
- // Run defined assigned checks on expressions resolved with
- // disabled flow-analysis
- //
- if (sn != null && !(me is FieldExpr && TypeSpec.IsValueType (expr_type))) {
- var vr = expr as VariableReference;
- if (vr != null)
- vr.VerifyDefiniteAssignment (rc);
- }
-
return me;
}
Expr.EmitBranchable (ec, target, on_true);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ Expr.FlowAnalysis (fc);
+ }
+
public override SLE.Expression MakeExpression (BuilderContext ctx)
{
using (ctx.With (BuilderContext.Options.CheckedScope, true)) {
Expr.EmitBranchable (ec, target, on_true);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ Expr.FlowAnalysis (fc);
+ }
+
protected override void CloneTo (CloneContext clonectx, Expression t)
{
UnCheckedExpr target = (UnCheckedExpr) t;
Report.Error (1742, na.Location, "An element access expression cannot use named argument");
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ Expr.FlowAnalysis (fc);
+ Arguments.FlowAnalysis (fc);
+ }
+
public override string GetSignatureForError ()
{
return Expr.GetSignatureForError ();
ec.Report.Warning (251, 2, loc, "Indexing an array with a negative index (array indices always start at zero)");
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ ea.FlowAnalysis (fc);
+ }
+
//
// Load the array arguments into the stack.
//
}
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ // TODO: Check the order
+ base.FlowAnalysis (fc);
+ arguments.FlowAnalysis (fc);
+ }
+
public override string GetSignatureForError ()
{
return best_candidate.GetSignatureForError ();
ec.Emit (OpCodes.Call, method);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ source.FlowAnalysis (fc);
+ }
+
public override string GetSignatureForError ()
{
return TypeManager.CSharpSignature (method);
e.EmitStatement (ec);
}
}
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ foreach (var initializer in initializers)
+ initializer.FlowAnalysis (fc);
+ }
}
//
return instance;
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ base.FlowAnalysis (fc);
+ initializers.FlowAnalysis (fc);
+ }
+
public override object Accept (StructuralVisitor visitor)
{
return visitor.Visit (this);
namespace Mono.CSharp
{
- // <summary>
- // A new instance of this class is created every time a new block is resolved
- // and if there's branching in the block's control flow.
- // </summary>
- public abstract class FlowBranching
- {
- // <summary>
- // The type of a FlowBranching.
- // </summary>
- public enum BranchingType : byte {
- // Normal (conditional or toplevel) block.
- Block,
-
- // Conditional.
- Conditional,
-
- // A loop block.
- Loop,
-
- // The statement embedded inside a loop
- Embedded,
-
- // part of a block headed by a jump target
- Labeled,
-
- // TryCatch block.
- TryCatch,
-
- // TryFinally, Using, Lock, CollectionForeach
- Exception,
-
- // Switch block.
- Switch,
-
- // The toplevel block of a function
- Toplevel,
-
- // An iterator block
- Iterator
- }
-
- // <summary>
- // The type of one sibling of a branching.
- // </summary>
- public enum SiblingType : byte {
- Block,
- Conditional,
- SwitchSection,
- Try,
- Catch,
- Finally
- }
-
- public static FlowBranching CreateBranching (FlowBranching parent, BranchingType type, Block block, Location loc)
- {
- switch (type) {
- case BranchingType.Exception:
- case BranchingType.Labeled:
- case BranchingType.Toplevel:
- case BranchingType.TryCatch:
- throw new InvalidOperationException ();
-
- case BranchingType.Switch:
- return new FlowBranchingBreakable (parent, type, SiblingType.SwitchSection, block, loc);
-
- case BranchingType.Block:
- return new FlowBranchingBlock (parent, type, SiblingType.Block, block, loc);
-
- case BranchingType.Loop:
- return new FlowBranchingBreakable (parent, type, SiblingType.Conditional, block, loc);
-
- case BranchingType.Embedded:
- return new FlowBranchingContinuable (parent, type, SiblingType.Conditional, block, loc);
-
- default:
- return new FlowBranchingBlock (parent, type, SiblingType.Conditional, block, loc);
- }
- }
-
- // <summary>
- // The type of this flow branching.
- // </summary>
- public readonly BranchingType Type;
-
- // <summary>
- // The block this branching is contained in. This may be null if it's not
- // a top-level block and it doesn't declare any local variables.
- // </summary>
- public readonly Block Block;
-
- // <summary>
- // The parent of this branching or null if this is the top-block.
- // </summary>
- public readonly FlowBranching Parent;
-
- // <summary>
- // Start-Location of this flow branching.
- // </summary>
- public readonly Location Location;
-
- static int next_id;
- int id;
-
- // <summary>
- // The vector contains a BitArray with information about which local variables
- // and parameters are already initialized at the current code position.
- // </summary>
- public class UsageVector {
- // <summary>
- // The type of this branching.
- // </summary>
- public readonly SiblingType Type;
-
- // <summary>
- // Start location of this branching.
- // </summary>
- public Location Location;
-
- // <summary>
- // This is only valid for SwitchSection, Try, Catch and Finally.
- // </summary>
- public readonly Block Block;
-
- // <summary>
- // The number of locals in this block.
- // </summary>
- public readonly int CountLocals;
-
- // <summary>
- // If not null, then we inherit our state from this vector and do a
- // copy-on-write. If null, then we're the first sibling in a top-level
- // block and inherit from the empty vector.
- // </summary>
- public readonly UsageVector InheritsFrom;
-
- // <summary>
- // This is used to construct a list of UsageVector's.
- // </summary>
- public UsageVector Next;
-
- //
- // Private.
- //
- MyBitVector locals;
- bool is_unreachable;
-
- static int next_id;
- int id;
-
- //
- // Normally, you should not use any of these constructors.
- //
- public UsageVector (SiblingType type, UsageVector parent, Block block, Location loc, int num_locals)
- {
- this.Type = type;
- this.Block = block;
- this.Location = loc;
- this.InheritsFrom = parent;
- this.CountLocals = num_locals;
-
- locals = num_locals == 0
- ? MyBitVector.Empty
- : new MyBitVector (parent == null ? MyBitVector.Empty : parent.locals, num_locals);
-
- if (parent != null)
- is_unreachable = parent.is_unreachable;
-
- id = ++next_id;
-
- }
-
- public UsageVector (SiblingType type, UsageVector parent, Block block, Location loc)
- : this (type, parent, block, loc, parent.CountLocals)
- { }
-
- private UsageVector (MyBitVector locals, bool is_unreachable, Block block, Location loc)
- {
- this.Type = SiblingType.Block;
- this.Location = loc;
- this.Block = block;
-
- this.is_unreachable = is_unreachable;
-
- this.locals = locals;
-
- id = ++next_id;
-
- }
-
- // <summary>
- // This does a deep copy of the usage vector.
- // </summary>
- public UsageVector Clone ()
- {
- UsageVector retval = new UsageVector (Type, null, Block, Location, CountLocals);
-
- retval.locals = locals.Clone ();
- retval.is_unreachable = is_unreachable;
-
- return retval;
- }
-
- public bool IsAssigned (VariableInfo var, bool ignoreReachability)
- {
- if (!ignoreReachability && !var.IsParameter && IsUnreachable)
- return true;
-
- return var.IsAssigned (locals);
- }
-
- public void SetAssigned (VariableInfo var)
- {
- if (!var.IsParameter && IsUnreachable)
- return;
-
- var.SetAssigned (locals);
- }
-
- public bool IsFieldAssigned (VariableInfo var, string name)
- {
- if (/*!var.IsParameter &&*/ IsUnreachable)
- return true;
-
- return var.IsStructFieldAssigned (locals, name);
- }
-
- public void SetFieldAssigned (VariableInfo var, string name)
- {
- if (/*!var.IsParameter &&*/ IsUnreachable)
- return;
-
- var.SetStructFieldAssigned (locals, name);
- }
-
- public bool IsUnreachable {
- get {
- return is_unreachable;
- }
- set {
- is_unreachable = value;
- }
- }
-
- public void ResetBarrier ()
- {
- is_unreachable = false;
- }
-
- public void Goto ()
- {
- is_unreachable = true;
- }
-
- public static UsageVector MergeSiblings (UsageVector sibling_list, Location loc)
- {
- if (sibling_list.Next == null)
- return sibling_list;
-
- MyBitVector locals = null;
- bool is_unreachable = sibling_list.is_unreachable;
-
- if (!sibling_list.IsUnreachable)
- locals &= sibling_list.locals;
-
- for (UsageVector child = sibling_list.Next; child != null; child = child.Next) {
- is_unreachable &= child.is_unreachable;
-
- if (!child.IsUnreachable)
- locals &= child.locals;
- }
-
- return new UsageVector (locals, is_unreachable, null, loc);
- }
-
- // <summary>
- // Merges a child branching.
- // </summary>
- public UsageVector MergeChild (UsageVector child, bool overwrite)
- {
- Report.Debug (2, " MERGING CHILD EFFECTS", this, child, Type);
-
- bool new_isunr = child.is_unreachable;
-
- //
- // We've now either reached the point after the branching or we will
- // never get there since we always return or always throw an exception.
- //
- // If we can reach the point after the branching, mark all locals and
- // parameters as initialized which have been initialized in all branches
- // we need to look at (see above).
- //
-
- if ((Type == SiblingType.SwitchSection) && !new_isunr) {
- Report.Error (163, Location,
- "Control cannot fall through from one " +
- "case label to another");
- return child;
- }
-
- locals |= child.locals;
-
- // throw away un-necessary information about variables in child blocks
- if (locals.Count != CountLocals)
- locals = new MyBitVector (locals, CountLocals);
-
- if (overwrite)
- is_unreachable = new_isunr;
- else
- is_unreachable |= new_isunr;
-
- return child;
- }
-
- public void MergeOrigins (UsageVector o_vectors)
- {
- Report.Debug (1, " MERGING BREAK ORIGINS", this);
-
- if (o_vectors == null)
- return;
-
- if (IsUnreachable && locals != null)
- locals.SetAll (true);
-
- for (UsageVector vector = o_vectors; vector != null; vector = vector.Next) {
- Report.Debug (1, " MERGING BREAK ORIGIN", vector);
- if (vector.IsUnreachable)
- continue;
- locals &= vector.locals;
- is_unreachable &= vector.is_unreachable;
- }
-
- Report.Debug (1, " MERGING BREAK ORIGINS DONE", this);
- }
-
- //
- // Debugging stuff.
- //
-
- public override string ToString ()
- {
- return String.Format ("Vector ({0},{1},{2}-{3})", Type, id, is_unreachable, locals);
- }
- }
-
- // <summary>
- // Creates a new flow branching which is contained in `parent'.
- // You should only pass non-null for the `block' argument if this block
- // introduces any new variables - in this case, we need to create a new
- // usage vector with a different size than our parent's one.
- // </summary>
- protected FlowBranching (FlowBranching parent, BranchingType type, SiblingType stype,
- Block block, Location loc)
- {
- Parent = parent;
- Block = block;
- Location = loc;
- Type = type;
- id = ++next_id;
-
- UsageVector vector;
- if (Block != null) {
- UsageVector parent_vector = parent != null ? parent.CurrentUsageVector : null;
- vector = new UsageVector (stype, parent_vector, Block, loc, Block.AssignableSlots);
- } else {
- vector = new UsageVector (stype, Parent.CurrentUsageVector, null, loc);
- }
-
- AddSibling (vector);
- }
-
- public abstract UsageVector CurrentUsageVector {
- get;
- }
-
- // <summary>
- // Creates a sibling of the current usage vector.
- // </summary>
- public void CreateSibling (Block block, SiblingType type)
- {
- UsageVector vector = new UsageVector (
- type, Parent.CurrentUsageVector, block, Location);
- AddSibling (vector);
-
- Report.Debug (1, " CREATED SIBLING", CurrentUsageVector);
- }
-
- public void CreateSibling ()
- {
- CreateSibling (null, SiblingType.Conditional);
- }
-
- protected abstract void AddSibling (UsageVector uv);
-
- protected abstract UsageVector Merge ();
-
- public UsageVector MergeChild (FlowBranching child)
- {
- return CurrentUsageVector.MergeChild (child.Merge (), true);
- }
-
- public virtual bool CheckRethrow (Location loc)
- {
- return Parent.CheckRethrow (loc);
- }
-
- public virtual bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc)
- {
- return Parent.AddResumePoint (stmt, current, out pc);
- }
-
- // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...)
- public virtual bool AddBreakOrigin (UsageVector vector, Location loc)
- {
- return Parent.AddBreakOrigin (vector, loc);
- }
-
- // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...)
- public virtual bool AddContinueOrigin (UsageVector vector, Location loc)
- {
- return Parent.AddContinueOrigin (vector, loc);
- }
-
- // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...)
- public virtual bool AddReturnOrigin (UsageVector vector, ExitStatement stmt)
- {
- return Parent.AddReturnOrigin (vector, stmt);
- }
-
- // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...)
- public virtual bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
- {
- return Parent.AddGotoOrigin (vector, goto_stmt);
- }
-
- public bool IsAssigned (VariableInfo vi)
- {
- return CurrentUsageVector.IsAssigned (vi, false);
- }
-
- public bool IsStructFieldAssigned (VariableInfo vi, string field_name)
- {
- return CurrentUsageVector.IsAssigned (vi, false) || CurrentUsageVector.IsFieldAssigned (vi, field_name);
- }
-
- protected static Report Report {
- get { return RootContext.ToplevelTypes.Compiler.Report; }
- }
-
- public void SetAssigned (VariableInfo vi)
- {
- CurrentUsageVector.SetAssigned (vi);
- }
-
- public void SetFieldAssigned (VariableInfo vi, string name)
- {
- CurrentUsageVector.SetFieldAssigned (vi, name);
- }
-
-#if DEBUG
- public override string ToString ()
- {
- StringBuilder sb = new StringBuilder ();
- sb.Append (GetType ());
- sb.Append (" (");
-
- sb.Append (id);
- sb.Append (",");
- sb.Append (Type);
- if (Block != null) {
- sb.Append (" - ");
- sb.Append (Block.ID);
- sb.Append (" - ");
- sb.Append (Block.StartLocation);
- }
- sb.Append (" - ");
- // sb.Append (Siblings.Length);
- // sb.Append (" - ");
- sb.Append (CurrentUsageVector);
- sb.Append (")");
- return sb.ToString ();
- }
-#endif
-
- public string Name {
- get { return String.Format ("{0} ({1}:{2}:{3})", GetType (), id, Type, Location); }
- }
- }
-
- public class FlowBranchingBlock : FlowBranching
- {
- UsageVector sibling_list = null;
-
- public FlowBranchingBlock (FlowBranching parent, BranchingType type,
- SiblingType stype, Block block, Location loc)
- : base (parent, type, stype, block, loc)
- { }
-
- public override UsageVector CurrentUsageVector {
- get { return sibling_list; }
- }
-
- protected override void AddSibling (UsageVector sibling)
- {
- if (sibling_list != null && sibling_list.Type == SiblingType.Block)
- throw new InternalErrorException ("Blocks don't have sibling flow paths");
- sibling.Next = sibling_list;
- sibling_list = sibling;
- }
-
- public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
- {
- LabeledStatement stmt = Block == null ? null : Block.LookupLabel (goto_stmt.Target);
- if (stmt == null)
- return Parent.AddGotoOrigin (vector, goto_stmt);
-
- // forward jump
- goto_stmt.SetResolvedTarget (stmt);
- stmt.AddUsageVector (vector);
- return false;
- }
-
- public static void Error_UnknownLabel (Location loc, string label, Report Report)
- {
- Report.Error(159, loc, "The label `{0}:' could not be found within the scope of the goto statement",
- label);
- }
-
- protected override UsageVector Merge ()
- {
- Report.Debug (2, " MERGING SIBLINGS", Name);
- UsageVector vector = UsageVector.MergeSiblings (sibling_list, Location);
- Report.Debug (2, " MERGING SIBLINGS DONE", Name, vector);
- return vector;
- }
- }
-
- public class FlowBranchingBreakable : FlowBranchingBlock
- {
- UsageVector break_origins;
-
- public FlowBranchingBreakable (FlowBranching parent, BranchingType type, SiblingType stype, Block block, Location loc)
- : base (parent, type, stype, block, loc)
- { }
-
- public override bool AddBreakOrigin (UsageVector vector, Location loc)
- {
- vector = vector.Clone ();
- vector.Next = break_origins;
- break_origins = vector;
- return false;
- }
-
- protected override UsageVector Merge ()
- {
- UsageVector vector = base.Merge ();
- vector.MergeOrigins (break_origins);
- return vector;
- }
- }
-
- public class FlowBranchingContinuable : FlowBranchingBlock
- {
- UsageVector continue_origins;
-
- public FlowBranchingContinuable (FlowBranching parent, BranchingType type, SiblingType stype, Block block, Location loc)
- : base (parent, type, stype, block, loc)
- { }
-
- public override bool AddContinueOrigin (UsageVector vector, Location loc)
- {
- vector = vector.Clone ();
- vector.Next = continue_origins;
- continue_origins = vector;
- return false;
- }
-
- protected override UsageVector Merge ()
- {
- UsageVector vector = base.Merge ();
- vector.MergeOrigins (continue_origins);
- return vector;
- }
- }
-
- public class FlowBranchingLabeled : FlowBranchingBlock
- {
- LabeledStatement stmt;
- UsageVector actual;
-
- public FlowBranchingLabeled (FlowBranching parent, LabeledStatement stmt)
- : base (parent, BranchingType.Labeled, SiblingType.Conditional, null, stmt.loc)
- {
- this.stmt = stmt;
- CurrentUsageVector.MergeOrigins (stmt.JumpOrigins);
- actual = CurrentUsageVector.Clone ();
-
- // stand-in for backward jumps
- CurrentUsageVector.ResetBarrier ();
- }
-
- public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
- {
- if (goto_stmt.Target != stmt.Name)
- return Parent.AddGotoOrigin (vector, goto_stmt);
-
- // backward jump
- goto_stmt.SetResolvedTarget (stmt);
- actual.MergeOrigins (vector.Clone ());
-
- return false;
- }
-
- protected override UsageVector Merge ()
- {
- UsageVector vector = base.Merge ();
-
- if (actual.IsUnreachable)
- Report.Warning (162, 2, stmt.loc, "Unreachable code detected");
-
- actual.MergeChild (vector, false);
- return actual;
- }
- }
-
- public class FlowBranchingIterator : FlowBranchingBlock
- {
- readonly Iterator iterator;
-
- public FlowBranchingIterator (FlowBranching parent, Iterator iterator)
- : base (parent, BranchingType.Iterator, SiblingType.Block, iterator.Block, iterator.Location)
- {
- this.iterator = iterator;
- }
-
- public override bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc)
- {
- pc = iterator.AddResumePoint (current);
- return false;
- }
- }
-
- public class FlowBranchingToplevel : FlowBranchingBlock
- {
- UsageVector return_origins;
-
- public FlowBranchingToplevel (FlowBranching parent, ParametersBlock stmt)
- : base (parent, BranchingType.Toplevel, SiblingType.Conditional, stmt, stmt.loc)
- {
- }
-
- public override bool CheckRethrow (Location loc)
- {
- Report.Error (156, loc, "A throw statement with no arguments is not allowed outside of a catch clause");
- return false;
- }
-
- public override bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc)
- {
- throw new InternalErrorException ("A yield in a non-iterator block");
- }
-
- public override bool AddBreakOrigin (UsageVector vector, Location loc)
- {
- Report.Error (139, loc, "No enclosing loop out of which to break or continue");
- return false;
- }
-
- public override bool AddContinueOrigin (UsageVector vector, Location loc)
- {
- Report.Error (139, loc, "No enclosing loop out of which to break or continue");
- return false;
- }
-
- public override bool AddReturnOrigin (UsageVector vector, ExitStatement stmt)
- {
- vector = vector.Clone ();
- vector.Location = stmt.loc;
- vector.Next = return_origins;
- return_origins = vector;
- return false;
- }
-
- public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
- {
- string name = goto_stmt.Target;
- LabeledStatement s = Block.LookupLabel (name);
- if (s != null)
- throw new InternalErrorException ("Shouldn't get here");
-
- if (Parent == null) {
- Error_UnknownLabel (goto_stmt.loc, name, Report);
- return false;
- }
-
- int errors = Report.Errors;
- Parent.AddGotoOrigin (vector, goto_stmt);
- if (errors == Report.Errors)
- Report.Error (1632, goto_stmt.loc, "Control cannot leave the body of an anonymous method");
- return false;
- }
-
- protected override UsageVector Merge ()
- {
- for (UsageVector origin = return_origins; origin != null; origin = origin.Next)
- Block.ParametersBlock.CheckOutParameters (origin);
-
- UsageVector vector = base.Merge ();
- Block.ParametersBlock.CheckOutParameters (vector);
- // Note: we _do_not_ merge in the return origins
- return vector;
- }
-
- public bool End ()
- {
- return Merge ().IsUnreachable;
- }
- }
-
- public class FlowBranchingTryCatch : FlowBranchingBlock
- {
- readonly TryCatch tc;
-
- public FlowBranchingTryCatch (FlowBranching parent, TryCatch stmt)
- : base (parent, BranchingType.Block, SiblingType.Try, null, stmt.loc)
- {
- this.tc = stmt;
- }
-
- public override bool CheckRethrow (Location loc)
- {
- return CurrentUsageVector.Next != null || Parent.CheckRethrow (loc);
- }
-
- public override bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc)
- {
- int errors = Report.Errors;
- Parent.AddResumePoint (stmt, tc.IsTryCatchFinally ? current : tc, out pc);
- if (errors == Report.Errors) {
- if (stmt is AwaitStatement) {
- if (CurrentUsageVector.Next != null) {
- Report.Error (1985, stmt.loc, "The `await' operator cannot be used in the body of a catch clause");
- } else {
- this.tc.AddResumePoint (current, pc);
- }
- } else {
- if (CurrentUsageVector.Next == null)
- Report.Error (1626, stmt.loc, "Cannot yield a value in the body of a try block with a catch clause");
- else
- Report.Error (1631, stmt.loc, "Cannot yield a value in the body of a catch clause");
- }
- }
-
- return true;
- }
-
- public override bool AddBreakOrigin (UsageVector vector, Location loc)
- {
- Parent.AddBreakOrigin (vector, loc);
- tc.SomeCodeFollows ();
- return true;
- }
-
- public override bool AddContinueOrigin (UsageVector vector, Location loc)
- {
- Parent.AddContinueOrigin (vector, loc);
- tc.SomeCodeFollows ();
- return true;
- }
-
- public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt)
- {
- Parent.AddReturnOrigin (vector, exit_stmt);
- tc.SomeCodeFollows ();
- return true;
- }
-
- public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
- {
- Parent.AddGotoOrigin (vector, goto_stmt);
- return true;
- }
- }
-
- public class FlowBranchingAsync : FlowBranchingBlock
- {
- readonly AsyncInitializer async_init;
-
- public FlowBranchingAsync (FlowBranching parent, AsyncInitializer async_init)
- : base (parent, BranchingType.Block, SiblingType.Try, null, async_init.Location)
- {
- this.async_init = async_init;
- }
-/*
- public override bool CheckRethrow (Location loc)
- {
- return CurrentUsageVector.Next != null || Parent.CheckRethrow (loc);
- }
-*/
- public override bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc)
- {
- pc = async_init.AddResumePoint (current);
- return true;
- }
-
- public override bool AddBreakOrigin (UsageVector vector, Location loc)
- {
- Parent.AddBreakOrigin (vector, loc);
- return true;
- }
-
- public override bool AddContinueOrigin (UsageVector vector, Location loc)
- {
- Parent.AddContinueOrigin (vector, loc);
- return true;
- }
-
- public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt)
- {
- Parent.AddReturnOrigin (vector, exit_stmt);
- return true;
- }
-
- public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
- {
- Parent.AddGotoOrigin (vector, goto_stmt);
- return true;
- }
- }
-
- public class FlowBranchingTryFinally : FlowBranching
- {
- ExceptionStatement stmt;
- UsageVector current_vector;
- UsageVector try_vector;
- UsageVector finally_vector;
-
- abstract class SavedOrigin {
- public readonly SavedOrigin Next;
- public readonly UsageVector Vector;
-
- protected SavedOrigin (SavedOrigin next, UsageVector vector)
- {
- Next = next;
- Vector = vector.Clone ();
- }
-
- protected abstract void DoPropagateFinally (FlowBranching parent);
- public void PropagateFinally (UsageVector finally_vector, FlowBranching parent)
- {
- if (finally_vector != null)
- Vector.MergeChild (finally_vector, false);
- DoPropagateFinally (parent);
- }
- }
-
- class BreakOrigin : SavedOrigin {
- Location Loc;
- public BreakOrigin (SavedOrigin next, UsageVector vector, Location loc)
- : base (next, vector)
- {
- Loc = loc;
- }
-
- protected override void DoPropagateFinally (FlowBranching parent)
- {
- parent.AddBreakOrigin (Vector, Loc);
- }
- }
-
- class ContinueOrigin : SavedOrigin {
- Location Loc;
- public ContinueOrigin (SavedOrigin next, UsageVector vector, Location loc)
- : base (next, vector)
- {
- Loc = loc;
- }
-
- protected override void DoPropagateFinally (FlowBranching parent)
- {
- parent.AddContinueOrigin (Vector, Loc);
- }
- }
-
- class ReturnOrigin : SavedOrigin {
- public ExitStatement Stmt;
-
- public ReturnOrigin (SavedOrigin next, UsageVector vector, ExitStatement stmt)
- : base (next, vector)
- {
- Stmt = stmt;
- }
-
- protected override void DoPropagateFinally (FlowBranching parent)
- {
- parent.AddReturnOrigin (Vector, Stmt);
- }
- }
-
- class GotoOrigin : SavedOrigin {
- public Goto Stmt;
-
- public GotoOrigin (SavedOrigin next, UsageVector vector, Goto stmt)
- : base (next, vector)
- {
- Stmt = stmt;
- }
-
- protected override void DoPropagateFinally (FlowBranching parent)
- {
- parent.AddGotoOrigin (Vector, Stmt);
- }
- }
-
- SavedOrigin saved_origins;
-
- public FlowBranchingTryFinally (FlowBranching parent,
- ExceptionStatement stmt)
- : base (parent, BranchingType.Exception, SiblingType.Try,
- null, stmt.loc)
- {
- this.stmt = stmt;
- }
-
- protected override void AddSibling (UsageVector sibling)
- {
- switch (sibling.Type) {
- case SiblingType.Try:
- try_vector = sibling;
- break;
- case SiblingType.Finally:
- finally_vector = sibling;
- break;
- default:
- throw new InvalidOperationException ();
- }
- current_vector = sibling;
- }
-
- public override UsageVector CurrentUsageVector {
- get { return current_vector; }
- }
-
- public override bool CheckRethrow (Location loc)
- {
- if (!Parent.CheckRethrow (loc))
- return false;
- if (finally_vector == null)
- return true;
- Report.Error (724, loc, "A throw statement with no arguments is not allowed inside of a finally clause nested inside of the innermost catch clause");
- return false;
- }
-
- public override bool AddResumePoint (ResumableStatement stmt, ResumableStatement current, out int pc)
- {
- int errors = Report.Errors;
- Parent.AddResumePoint (stmt, this.stmt, out pc);
- if (errors == Report.Errors) {
- if (finally_vector == null)
- this.stmt.AddResumePoint (current, pc);
- else {
- if (stmt is AwaitStatement) {
- Report.Error (1984, stmt.loc, "The `await' operator cannot be used in the body of a finally clause");
- } else {
- Report.Error (1625, stmt.loc, "Cannot yield in the body of a finally clause");
- }
- }
- }
- return true;
- }
-
- public override bool AddBreakOrigin (UsageVector vector, Location loc)
- {
- if (finally_vector != null) {
- int errors = Report.Errors;
- Parent.AddBreakOrigin (vector, loc);
- if (errors == Report.Errors)
- Report.Error (157, loc, "Control cannot leave the body of a finally clause");
- } else {
- saved_origins = new BreakOrigin (saved_origins, vector, loc);
- }
-
- // either the loop test or a back jump will follow code
- stmt.SomeCodeFollows ();
- return true;
- }
-
- public override bool AddContinueOrigin (UsageVector vector, Location loc)
- {
- if (finally_vector != null) {
- int errors = Report.Errors;
- Parent.AddContinueOrigin (vector, loc);
- if (errors == Report.Errors)
- Report.Error (157, loc, "Control cannot leave the body of a finally clause");
- } else {
- saved_origins = new ContinueOrigin (saved_origins, vector, loc);
- }
-
- // either the loop test or a back jump will follow code
- stmt.SomeCodeFollows ();
- return true;
- }
-
- public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt)
- {
- if (finally_vector != null) {
- int errors = Report.Errors;
- Parent.AddReturnOrigin (vector, exit_stmt);
- if (errors == Report.Errors)
- exit_stmt.Error_FinallyClause (Report);
- } else {
- saved_origins = new ReturnOrigin (saved_origins, vector, exit_stmt);
- }
-
- // sets ec.NeedReturnLabel()
- stmt.SomeCodeFollows ();
- return true;
- }
-
- public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt)
- {
- LabeledStatement s = current_vector.Block == null ? null : current_vector.Block.LookupLabel (goto_stmt.Target);
- if (s != null)
- throw new InternalErrorException ("Shouldn't get here");
-
- if (finally_vector != null) {
- int errors = Report.Errors;
- Parent.AddGotoOrigin (vector, goto_stmt);
- if (errors == Report.Errors)
- Report.Error (157, goto_stmt.loc, "Control cannot leave the body of a finally clause");
- } else {
- saved_origins = new GotoOrigin (saved_origins, vector, goto_stmt);
- }
- return true;
- }
-
- protected override UsageVector Merge ()
- {
- UsageVector vector = try_vector.Clone ();
-
- if (finally_vector != null)
- vector.MergeChild (finally_vector, false);
-
- for (SavedOrigin origin = saved_origins; origin != null; origin = origin.Next)
- origin.PropagateFinally (finally_vector, Parent);
-
- return vector;
- }
- }
-
// <summary>
// This is used by the flow analysis code to keep track of the type of local variables.
//
// A struct's constructor must always assign all fields.
// This method checks whether it actually does so.
// </summary>
- public bool IsFullyInitialized (BlockContext ec, VariableInfo vi, Location loc)
+ public bool IsFullyInitialized (FlowAnalysisContext fc, VariableInfo vi, Location loc)
{
if (struct_info == null)
return true;
bool ok = true;
- FlowBranching branching = ec.CurrentBranching;
for (int i = 0; i < struct_info.Count; i++) {
- var field = struct_info.Fields [i];
+ var field = struct_info.Fields[i];
- if (!branching.IsStructFieldAssigned (vi, field.Name)) {
+ if (!fc.IsStructFieldDefinitelyAssigned (vi, field.Name)) {
if (field.MemberDefinition is Property.BackingField) {
- ec.Report.Error (843, loc,
+ fc.Report.Error (843, loc,
"An automatically implemented property `{0}' must be fully assigned before control leaves the constructor. Consider calling the default struct contructor from a constructor initializer",
field.GetSignatureForError ());
} else {
- ec.Report.Error (171, loc,
+ fc.Report.Error (171, loc,
"Field `{0}' must be fully assigned before control leaves the constructor",
field.GetSignatureForError ());
}
return info;
}
- public bool IsAssigned (ResolveContext ec)
- {
- return !ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (this);
- }
-
- public bool IsAssigned (MyBitVector vector)
+ public bool IsAssigned (DefiniteAssignmentBitSet vector)
{
if (vector == null)
return true;
return false;
}
- vector [Offset] = true;
+ vector.Set (Offset);
return true;
}
public bool IsEverAssigned { get; set; }
- public bool IsStructFieldAssigned (ResolveContext ec, string name)
+ public bool IsFullyInitialized (FlowAnalysisContext fc, Location loc)
{
- return !ec.DoFlowAnalysis || ec.CurrentBranching.IsStructFieldAssigned (this, name);
+ return TypeInfo.IsFullyInitialized (fc, this, loc);
}
- public bool IsFullyInitialized (BlockContext bc, Location loc)
- {
- return TypeInfo.IsFullyInitialized (bc, this, loc);
- }
-
- public bool IsStructFieldAssigned (MyBitVector vector, string field_name)
+ public bool IsStructFieldAssigned (DefiniteAssignmentBitSet vector, string field_name)
{
int field_idx = TypeInfo.GetFieldIndex (field_name);
return vector [Offset + field_idx];
}
- public void SetStructFieldAssigned (ResolveContext ec, string name)
- {
- if (ec.DoFlowAnalysis)
- ec.CurrentBranching.SetFieldAssigned (this, name);
- }
-
- public void SetAssigned (ResolveContext ec)
- {
- if (ec.DoFlowAnalysis)
- ec.CurrentBranching.SetAssigned (this);
- }
-
- public void SetAssigned (MyBitVector vector)
+ public void SetAssigned (DefiniteAssignmentBitSet vector, bool generatedAssignment)
{
if (Length == 1)
- vector[Offset] = true;
+ vector.Set (Offset);
else
- vector.SetRange (Offset, Length);
+ vector.Set (Offset, Length);
- IsEverAssigned = true;
+ if (!generatedAssignment)
+ IsEverAssigned = true;
}
- public void SetStructFieldAssigned (MyBitVector vector, string field_name)
+ public void SetStructFieldAssigned (DefiniteAssignmentBitSet vector, string field_name)
{
- if (vector[Offset])
+ if (vector [Offset])
return;
int field_idx = TypeInfo.GetFieldIndex (field_name);
var complex_field = TypeInfo.GetStructField (field_name);
if (complex_field != null) {
- vector.SetRange (Offset + complex_field.Offset, complex_field.TotalLength);
+ vector.Set (Offset + complex_field.Offset, complex_field.TotalLength);
} else {
- vector[Offset + field_idx] = true;
+ vector.Set (Offset + field_idx);
}
IsEverAssigned = true;
//
- // Each field must be assigned
+ // Each field must be assigned before setting master bit
//
for (int i = Offset + 1; i < TypeInfo.TotalLength + Offset; i++) {
if (!vector[i])
// Set master struct flag to assigned when all tested struct
// fields have been assigned
//
- vector[Offset] = true;
+ vector.Set (Offset);
}
public VariableInfo GetStructFieldInfo (string fieldName)
public override string ToString ()
{
- return String.Format ("VariableInfo ({0}:{1}:{2}:{3}:{4})",
- Name, TypeInfo, Offset, Length, IsParameter);
+ return String.Format ("Name={0} Offset={1} Length={2} {3})", Name, Offset, Length, TypeInfo);
}
}
- // <summary>
- // This is a special bit vector which can inherit from another bit vector doing a
- // copy-on-write strategy. The inherited vector may have a smaller size than the
- // current one.
- // </summary>
- public class MyBitVector {
- public readonly int Count;
- public static readonly MyBitVector Empty = new MyBitVector ();
-
- // Invariant: vector != null => vector.Count == Count
- // Invariant: vector == null || shared == null
- // i.e., at most one of 'vector' and 'shared' can be non-null. They can both be null -- that means all-ones
- // The object in 'shared' cannot be modified, while 'vector' can be freely modified
- System.Collections.BitArray vector, shared;
+ public struct Reachability
+ {
+ readonly bool unreachable;
- MyBitVector ()
+ Reachability (bool unreachable)
{
- shared = new System.Collections.BitArray (0, false);
+ this.unreachable = unreachable;
+ }
+
+ public bool IsUnreachable {
+ get {
+ return unreachable;
+ }
}
- public MyBitVector (MyBitVector InheritsFrom, int Count)
+ public static Reachability CreateUnreachable ()
{
- if (InheritsFrom != null)
- shared = InheritsFrom.MakeShared (Count);
+ return new Reachability (true);
+ }
- this.Count = Count;
+ public static Reachability operator & (Reachability a, Reachability b)
+ {
+ return new Reachability (a.unreachable && b.unreachable);
}
- System.Collections.BitArray MakeShared (int new_count)
+ public static Reachability operator | (Reachability a, Reachability b)
{
- // Post-condition: vector == null
+ return new Reachability (a.unreachable | b.unreachable);
+ }
+ }
- // ensure we don't leak out dirty bits from the BitVector we inherited from
- if (new_count > Count &&
- ((shared != null && shared.Count > Count) ||
- (shared == null && vector == null)))
- initialize_vector ();
+ //
+ // Special version of bit array. Many operations can be simplified because
+ // we are always dealing with arrays of same sizes
+ //
+ public class DefiniteAssignmentBitSet
+ {
+ const uint copy_on_write_flag = 1u << 31;
- if (vector != null) {
- shared = vector;
- vector = null;
- }
+ uint bits;
- return shared;
- }
+ // Used when bits overflows
+ int[] large_bits;
- // <summary>
- // Get/set bit `index' in the bit vector.
- // </summary>
- public bool this [int index] {
- get {
- if (index >= Count)
- // FIXME: Disabled due to missing anonymous method flow analysis
- // throw new ArgumentOutOfRangeException ();
- return true;
-
- if (vector != null)
- return vector [index];
- if (shared == null)
- return true;
- if (index < shared.Count)
- return shared [index];
- return false;
- }
+ public static readonly DefiniteAssignmentBitSet Empty = new DefiniteAssignmentBitSet (0);
- set {
- // Only copy the vector if we're actually modifying it.
- if (this [index] != value) {
- if (vector == null)
- initialize_vector ();
- vector [index] = value;
- }
- }
+ public DefiniteAssignmentBitSet (int length)
+ {
+ if (length > 31)
+ large_bits = new int[(length + 31) / 32];
}
- // <summary>
- // Performs an `or' operation on the bit vector. The `new_vector' may have a
- // different size than the current one.
- // </summary>
- private MyBitVector Or (MyBitVector new_vector)
+ public DefiniteAssignmentBitSet (DefiniteAssignmentBitSet source)
{
- if (Count == 0 || new_vector.Count == 0)
- return this;
-
- var o = new_vector.vector != null ? new_vector.vector : new_vector.shared;
-
- if (o == null) {
- int n = new_vector.Count;
- if (n < Count) {
- for (int i = 0; i < n; ++i)
- this [i] = true;
- } else {
- SetAll (true);
- }
- return this;
+ if (source.large_bits != null) {
+ large_bits = source.large_bits;
+ bits = source.bits | copy_on_write_flag;
+ } else {
+ bits = source.bits & ~copy_on_write_flag;
}
+ }
- if (Count == o.Count) {
- if (vector == null) {
- if (shared == null)
- return this;
- initialize_vector ();
- }
- vector.Or (o);
- return this;
- }
+ public static DefiniteAssignmentBitSet operator & (DefiniteAssignmentBitSet a, DefiniteAssignmentBitSet b)
+ {
+ if (AreEqual (a, b))
+ return a;
- int min = o.Count;
- if (Count < min)
- min = Count;
+ DefiniteAssignmentBitSet res;
+ if (a.large_bits == null) {
+ res = new DefiniteAssignmentBitSet (a);
+ res.bits &= (b.bits & ~copy_on_write_flag);
+ return res;
+ }
- for (int i = 0; i < min; i++) {
- if (o [i])
- this [i] = true;
+ res = new DefiniteAssignmentBitSet (a);
+ res.Clone ();
+ var dest = res.large_bits;
+ var src = b.large_bits;
+ for (int i = 0; i < dest.Length; ++i) {
+ dest[i] &= src[i];
}
- return this;
+ return res;
}
- // <summary>
- // Performs an `and' operation on the bit vector. The `new_vector' may have
- // a different size than the current one.
- // </summary>
- private MyBitVector And (MyBitVector new_vector)
+ public static DefiniteAssignmentBitSet operator | (DefiniteAssignmentBitSet a, DefiniteAssignmentBitSet b)
{
- if (Count == 0)
- return this;
-
- var o = new_vector.vector != null ? new_vector.vector : new_vector.shared;
+ if (AreEqual (a, b))
+ return a;
- if (o == null) {
- for (int i = new_vector.Count; i < Count; ++i)
- this [i] = false;
- return this;
+ DefiniteAssignmentBitSet res;
+ if (a.large_bits == null) {
+ res = new DefiniteAssignmentBitSet (a);
+ res.bits |= b.bits;
+ res.bits &= ~copy_on_write_flag;
+ return res;
}
- if (o.Count == 0) {
- SetAll (false);
- return this;
- }
+ res = new DefiniteAssignmentBitSet (a);
+ res.Clone ();
+ var dest = res.large_bits;
+ var src = b.large_bits;
- if (Count == o.Count) {
- if (vector == null) {
- if (shared == null) {
- shared = new_vector.MakeShared (Count);
- return this;
- }
- initialize_vector ();
- }
- vector.And (o);
- return this;
+ for (int i = 0; i < dest.Length; ++i) {
+ dest[i] |= src[i];
}
- int min = o.Count;
- if (Count < min)
- min = Count;
+ return res;
+ }
- for (int i = 0; i < min; i++) {
- if (! o [i])
- this [i] = false;
- }
+ public static DefiniteAssignmentBitSet And (List<DefiniteAssignmentBitSet> das)
+ {
+ if (das.Count == 0)
+ throw new ArgumentException ("Empty das");
- for (int i = min; i < Count; i++)
- this [i] = false;
+ DefiniteAssignmentBitSet res = das[0];
+ for (int i = 1; i < das.Count; ++i) {
+ res &= das[i];
+ }
- return this;
+ return res;
}
- public static MyBitVector operator & (MyBitVector a, MyBitVector b)
- {
- if (a == b)
- return a;
- if (a == null)
- return b.Clone ();
- if (b == null)
- return a.Clone ();
- if (a.Count > b.Count)
- return a.Clone ().And (b);
- else
- return b.Clone ().And (a);
+ bool CopyOnWrite {
+ get {
+ return (bits & copy_on_write_flag) != 0;
+ }
}
- public static MyBitVector operator | (MyBitVector a, MyBitVector b)
- {
- if (a == b)
- return a;
- if (a == null)
- return new MyBitVector (null, b.Count);
- if (b == null)
- return new MyBitVector (null, a.Count);
- if (a.Count > b.Count)
- return a.Clone ().Or (b);
- else
- return b.Clone ().Or (a);
+ int Length {
+ get {
+ return large_bits == null ? 31 : large_bits.Length * 32;
+ }
}
- public MyBitVector Clone ()
+ public void Set (int index)
{
- return Count == 0 ? Empty : new MyBitVector (this, Count);
+ if (CopyOnWrite && !this[index])
+ Clone ();
+
+ SetBit (index);
}
- public void SetRange (int offset, int length)
+ public void Set (int index, int length)
{
- if (offset > Count || offset + length > Count)
- throw new ArgumentOutOfRangeException ("flow-analysis");
-
- if (shared == null && vector == null)
- return;
+ for (int i = 0; i < length; ++i) {
+ if (CopyOnWrite && !this[index + i])
+ Clone ();
- int i = 0;
- if (shared != null) {
- if (offset + length <= shared.Count) {
- for (; i < length; ++i)
- if (!shared [i+offset])
- break;
- if (i == length)
- return;
- }
- initialize_vector ();
+ SetBit (index + i);
}
- for (; i < length; ++i)
- vector [i+offset] = true;
+ }
+ public bool this[int index] {
+ get {
+ return GetBit (index);
+ }
}
- public void SetAll (bool value)
+ public override string ToString ()
{
- // Don't clobber Empty
- if (Count == 0)
- return;
- shared = value ? null : Empty.MakeShared (Count);
- vector = null;
+ var length = Length;
+ StringBuilder sb = new StringBuilder (length);
+ for (int i = 0; i < length; ++i) {
+ sb.Append (this[i] ? '1' : '0');
+ }
+
+ return sb.ToString ();
}
- void initialize_vector ()
+ void Clone ()
{
- // Post-condition: vector != null
- if (shared == null) {
- vector = new System.Collections.BitArray (Count, true);
- return;
- }
+ large_bits = (int[]) large_bits.Clone ();
+ }
- vector = new System.Collections.BitArray (shared);
- if (Count != vector.Count)
- vector.Length = Count;
- shared = null;
+ bool GetBit (int index)
+ {
+ return large_bits == null ?
+ (bits & (1 << index)) != 0 :
+ (large_bits[index >> 5] & (1 << (index & 31))) != 0;
}
- StringBuilder Dump (StringBuilder sb)
+ void SetBit (int index)
{
- var dump = vector == null ? shared : vector;
- if (dump == null)
- return sb.Append ("/");
- if (dump == shared)
- sb.Append ("=");
- for (int i = 0; i < dump.Count; i++)
- sb.Append (dump [i] ? "1" : "0");
- return sb;
+ if (large_bits == null)
+ bits = (uint) ((int) bits | (1 << index));
+ else
+ large_bits[index >> 5] |= (1 << (index & 31));
}
- public override string ToString ()
+ static bool AreEqual (DefiniteAssignmentBitSet a, DefiniteAssignmentBitSet b)
{
- return Dump (new StringBuilder ("{")).Append ("}").ToString ();
+ if (a.large_bits == null)
+ return (a.bits & ~copy_on_write_flag) == (b.bits & ~copy_on_write_flag);
+
+ for (int i = 0; i < a.large_bits.Length; ++i) {
+ if (a.large_bits[i] != b.large_bits[i])
+ return false;
+ }
+
+ return true;
}
}
}
}
}
+ bool ITypeDefinition.IsCyclicTypeForwarder {
+ get {
+ return false;
+ }
+ }
+
public string Name {
get {
return MemberName.Name;
readonly TypeSpec[] tp_args;
readonly TypeSpec[] fixed_types;
readonly List<BoundInfo>[] bounds;
- bool failed;
// TODO MemberCache: Could it be TypeParameterSpec[] ??
public TypeInferenceContext (TypeSpec[] typeArguments)
if (fixed_types[i] != null)
throw new InternalErrorException ("Type argument has been already fixed");
- if (failed)
- return false;
-
var candidates = bounds [i];
if (candidates == null)
return false;
}
//
- // This should always cause type inference failure
+ // Break when candidate arguments are ambiguous
//
- failed = true;
- return 1;
+ return 0;
}
//
Namespace ns = targetNamespace;
string prev_namespace = null;
foreach (var t in types) {
+ if (!t.__IsTypeForwarder)
+ continue;
+
// IsMissing tells us the type has been forwarded and target assembly is missing
if (!t.__IsMissing)
continue;
}
}
+ bool ITypeDefinition.IsCyclicTypeForwarder {
+ get {
+#if STATIC
+ return ((MetaType) provider).__IsCyclicTypeForwarder;
+#else
+ return false;
+#endif
+ }
+ }
+
public override string Name {
get {
if (name == null) {
if (caller.Kind != MemberKind.MissingType)
report.SymbolRelatedToPreviousError (caller);
- if (t.MemberDefinition.DeclaringAssembly == ctx.Module.DeclaringAssembly) {
+ var definition = t.MemberDefinition;
+ if (definition.DeclaringAssembly == ctx.Module.DeclaringAssembly) {
report.Error (1683, loc,
"Reference to type `{0}' claims it is defined in this assembly, but it is not defined in source or any added modules",
name);
- } else if (t.MemberDefinition.DeclaringAssembly.IsMissing) {
- if (t.MemberDefinition.IsTypeForwarder) {
+ } else if (definition.DeclaringAssembly.IsMissing) {
+ if (definition.IsTypeForwarder) {
report.Error (1070, loc,
"The type `{0}' has been forwarded to an assembly that is not referenced. Consider adding a reference to assembly `{1}'",
- name, t.MemberDefinition.DeclaringAssembly.FullName);
+ name, definition.DeclaringAssembly.FullName);
} else {
report.Error (12, loc,
"The type `{0}' is defined in an assembly that is not referenced. Consider adding a reference to assembly `{1}'",
- name, t.MemberDefinition.DeclaringAssembly.FullName);
+ name, definition.DeclaringAssembly.FullName);
}
+ } else if (definition.IsTypeForwarder) {
+ report.Error (731, loc, "The type forwarder for type `{0}' in assembly `{1}' has circular dependency",
+ name, definition.DeclaringAssembly.FullName);
} else {
report.Error (1684, loc,
"Reference to type `{0}' claims it is defined assembly `{1}', but it could not be found",
}
}
+ bool ITypeDefinition.IsCyclicTypeForwarder {
+ get {
+ return false;
+ }
+ }
+
public string Namespace {
get {
return null;
protected bool unwind_protect;
protected T machine_initializer;
int resume_pc;
+ ExceptionStatement inside_try_block;
protected YieldStatement (Expression expr, Location l)
{
machine_initializer.InjectYield (ec, expr, resume_pc, unwind_protect, resume_point);
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ expr.FlowAnalysis (fc);
+
+ RegisterResumePoint ();
+
+ return false;
+ }
+
public override bool Resolve (BlockContext bc)
{
expr = expr.Resolve (bc);
return false;
machine_initializer = bc.CurrentAnonymousMethod as T;
-
- if (!bc.CurrentBranching.CurrentUsageVector.IsUnreachable)
- unwind_protect = bc.CurrentBranching.AddResumePoint (this, this, out resume_pc);
-
+ inside_try_block = bc.CurrentTryBlock;
return true;
}
+
+ public void RegisterResumePoint ()
+ {
+ if (inside_try_block == null) {
+ resume_pc = machine_initializer.AddResumePoint (this);
+ } else {
+ resume_pc = inside_try_block.AddResumePoint (this, resume_pc, machine_initializer);
+ unwind_protect = true;
+ inside_try_block = null;
+ }
+ }
}
public class Yield : YieldStatement<Iterator>
{
}
- public static bool CheckContext (ResolveContext ec, Location loc)
+ public static bool CheckContext (BlockContext bc, Location loc)
{
- if (!ec.CurrentAnonymousMethod.IsIterator) {
- ec.Report.Error (1621, loc,
+ if (!bc.CurrentAnonymousMethod.IsIterator) {
+ bc.Report.Error (1621, loc,
"The yield statement cannot be used inside anonymous method blocks");
return false;
}
+ if (bc.HasSet (ResolveContext.Options.FinallyScope)) {
+ bc.Report.Error (1625, loc, "Cannot yield in the body of a finally clause");
+ return false;
+ }
+
return true;
}
if (!CheckContext (bc, loc))
return false;
+ if (bc.HasAny (ResolveContext.Options.TryWithCatchScope)) {
+ bc.Report.Error (1626, loc, "Cannot yield a value in the body of a try block with a catch clause");
+ }
+
+ if (bc.HasSet (ResolveContext.Options.CatchScope)) {
+ bc.Report.Error (1631, loc, "Cannot yield a value in the body of a catch clause");
+ }
+
if (!base.Resolve (bc))
return false;
loc = l;
}
- public override void Error_FinallyClause (Report Report)
- {
- Report.Error (1625, loc, "Cannot yield in the body of a finally clause");
+ protected override bool IsLocalExit {
+ get {
+ return false;
+ }
}
protected override void CloneTo (CloneContext clonectx, Statement target)
throw new NotSupportedException ();
}
- protected override bool DoResolve (BlockContext ec)
+ protected override bool DoResolve (BlockContext bc)
{
- iterator = ec.CurrentIterator;
- return Yield.CheckContext (ec, loc);
+ iterator = bc.CurrentIterator;
+ return Yield.CheckContext (bc, loc);
}
protected override void DoEmit (EmitContext ec)
{
iterator.EmitYieldBreak (ec, unwind_protect);
}
+
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ return true;
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ base.MarkReachable (rc);
+ return Reachability.CreateUnreachable ();
+ }
public override object Accept (StructuralVisitor visitor)
{
if (new_storey != null)
new_storey = Convert.ImplicitConversionRequired (ec, new_storey, host_method.MemberType, loc);
- ec.CurrentBranching.CurrentUsageVector.Goto ();
return true;
}
new_storey.Emit (ec);
ec.Emit (OpCodes.Ret);
}
+
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ throw new NotImplementedException ();
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ base.MarkReachable (rc);
+ return Reachability.CreateUnreachable ();
+ }
}
GetEnumeratorMethod (IteratorStorey host, FullNamedExpression returnType, MemberName name)
- : base (host, null, returnType, Modifiers.DEBUGGER_HIDDEN, name)
+ : base (host, null, returnType, Modifiers.DEBUGGER_HIDDEN, name, ToplevelBlock.Flags.CompilerGenerated | ToplevelBlock.Flags.NoFlowAnalysis)
{
}
var m = new GetEnumeratorMethod (host, returnType, name);
var stmt = statement ?? new GetEnumeratorStatement (host, m);
m.block.AddStatement (stmt);
- m.block.IsCompilerGenerated = true;
return m;
}
}
ec.CurrentAnonymousMethod = iterator;
iterator.EmitDispose (ec);
}
+
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ throw new NotImplementedException ();
+ }
}
public DisposeMethod (IteratorStorey host)
: base (host, null, new TypeExpression (host.Compiler.BuiltinTypes.Void, host.Location), Modifiers.PUBLIC | Modifiers.DEBUGGER_HIDDEN,
- new MemberName ("Dispose", host.Location))
+ new MemberName ("Dispose", host.Location), ToplevelBlock.Flags.CompilerGenerated | ToplevelBlock.Flags.NoFlowAnalysis)
{
host.Members.Add (this);
Block.AddStatement (new DisposeMethodStatement (host.Iterator));
- Block.IsCompilerGenerated = true;
}
}
var name = new MemberName ("Current", null, explicit_iface, Location);
- ToplevelBlock get_block = new ToplevelBlock (Compiler, Location) {
- IsCompilerGenerated = true
- };
+ ToplevelBlock get_block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location,
+ Block.Flags.CompilerGenerated | Block.Flags.NoFlowAnalysis);
get_block.AddStatement (new Return (new DynamicFieldExpr (CurrentField, Location), Location));
Property current = new Property (this, type, Modifiers.DEBUGGER_HIDDEN | Modifiers.COMPILER_GENERATED, name, null);
ParametersCompiled.EmptyReadOnlyParameters, null);
Members.Add (reset);
- reset.Block = new ToplevelBlock (Compiler, Location) {
- IsCompilerGenerated = true
- };
+ reset.Block = new ToplevelBlock (Compiler, reset.ParameterInfo, Location,
+ Block.Flags.CompilerGenerated | Block.Flags.NoFlowAnalysis);
TypeSpec ex_type = Module.PredefinedTypes.NotSupportedException.Resolve ();
if (ex_type == null)
{
readonly StateMachineInitializer expr;
- public StateMachineMethod (StateMachine host, StateMachineInitializer expr, FullNamedExpression returnType, Modifiers mod, MemberName name)
+ public StateMachineMethod (StateMachine host, StateMachineInitializer expr, FullNamedExpression returnType,
+ Modifiers mod, MemberName name, ToplevelBlock.Flags blockFlags)
: base (host, returnType, mod | Modifiers.COMPILER_GENERATED,
name, ParametersCompiled.EmptyReadOnlyParameters, null)
{
this.expr = expr;
- Block = new ToplevelBlock (host.Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location.Null);
+ Block = new ToplevelBlock (host.Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location.Null, blockFlags);
}
public override EmitContext CreateEmitContext (ILGenerator ig, SourceMethodBuilder sourceMethod)
// Don't create sequence point
DoEmit (ec);
}
+
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ return state_machine.ReturnType.Kind != MemberKind.Void;
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ base.MarkReachable (rc);
+
+ if (state_machine.ReturnType.Kind != MemberKind.Void)
+ rc = Reachability.CreateUnreachable ();
+
+ return rc;
+ }
}
public readonly TypeDefinition Host;
throw new NotSupportedException ("ET");
}
- protected virtual BlockContext CreateBlockContext (ResolveContext rc)
+ protected virtual BlockContext CreateBlockContext (BlockContext bc)
{
- var ctx = new BlockContext (rc, block, ((BlockContext) rc).ReturnType);
+ var ctx = new BlockContext (bc, block, bc.ReturnType);
ctx.CurrentAnonymousMethod = this;
+
+ ctx.AssignmentInfoOffset = bc.AssignmentInfoOffset;
+ ctx.EnclosingLoop = bc.EnclosingLoop;
+ ctx.EnclosingLoopOrSwitch = bc.EnclosingLoopOrSwitch;
+ ctx.Switch = bc.Switch;
+
return ctx;
}
- protected override Expression DoResolve (ResolveContext ec)
+ protected override Expression DoResolve (ResolveContext rc)
{
- var ctx = CreateBlockContext (ec);
+ var bc = (BlockContext) rc;
+ var ctx = CreateBlockContext (bc);
Block.Resolve (ctx);
- //
- // Explicit return is required for Task<T> state machine
- //
- var task_storey = storey as AsyncTaskStorey;
- if (task_storey == null || (task_storey.ReturnType != null && !task_storey.ReturnType.IsGenericTask))
- ctx.CurrentBranching.CurrentUsageVector.Goto ();
-
- ctx.EndFlowBranching ();
-
- if (!ec.IsInProbingMode) {
- var move_next = new StateMachineMethod (storey, this, new TypeExpression (ReturnType, loc), Modifiers.PUBLIC, new MemberName ("MoveNext", loc));
+ if (!rc.IsInProbingMode) {
+ var move_next = new StateMachineMethod (storey, this, new TypeExpression (ReturnType, loc), Modifiers.PUBLIC, new MemberName ("MoveNext", loc), 0);
move_next.Block.AddStatement (new MoveNextBodyStatement (this));
storey.AddEntryMethod (move_next);
}
+ bc.AssignmentInfoOffset = ctx.AssignmentInfoOffset;
eclass = ExprClass.Value;
return this;
}
throw new NotSupportedException ();
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ throw new NotSupportedException ();
+ }
+
protected override void DoEmit (EmitContext ec)
{
//
Modifiers.COMPILER_GENERATED, new MemberName (CompilerGeneratedContainer.MakeName (null, null, "Finally", finally_hosts_counter++), loc),
ParametersCompiled.EmptyReadOnlyParameters, null);
- method.Block = new ToplevelBlock (method.Compiler, method.ParameterInfo, loc);
- method.Block.IsCompilerGenerated = true;
+ method.Block = new ToplevelBlock (method.Compiler, method.ParameterInfo, loc,
+ ToplevelBlock.Flags.CompilerGenerated | ToplevelBlock.Flags.NoFlowAnalysis);
method.Block.AddStatement (new TryFinallyBlockProxyStatement (this, block));
// Cannot it add to storey because it'd be emitted before nested
ec.MarkLabel (resume_point);
}
- protected override BlockContext CreateBlockContext (ResolveContext rc)
- {
- var bc = base.CreateBlockContext (rc);
- bc.StartFlowBranching (this, rc.CurrentBranching);
- return bc;
- }
-
public static void CreateIterator (IMethodData method, TypeDefinition parent, Modifiers modifiers)
{
bool is_enumerable;
}
public QueryBlock (Block parent, Location start)
- : base (parent, ParametersCompiled.EmptyReadOnlyParameters, start)
+ : base (parent, ParametersCompiled.EmptyReadOnlyParameters, start, Flags.CompilerGenerated)
{
- flags |= Flags.CompilerGenerated;
}
public void AddRangeVariable (RangeVariable variable)
TypeSpec[] targs;
TypeParameterSpec[] constraints;
+ public static readonly MethodSpec Excluded = new MethodSpec (MemberKind.Method, InternalType.FakeInternalType, null, null, ParametersCompiled.EmptyReadOnlyParameters, 0);
+
public MethodSpec (MemberKind kind, TypeSpec declaringType, IMethodDefinition details, TypeSpec returnType,
AParametersCollection parameters, Modifiers modifiers)
: base (kind, declaringType, details, modifiers)
} else {
//
// It is legal to have "this" initializers that take no arguments
- // in structs, they are just no-ops.
+ // in structs
//
// struct D { public D (int a) : this () {}
//
public override void Emit (EmitContext ec)
{
- // It can be null for static initializers
- if (base_ctor == null)
+ //
+ // It can be null for struct initializers or System.Object
+ //
+ if (base_ctor == null) {
+ if (type == ec.BuiltinTypes.Object)
+ return;
+
+ ec.Emit (OpCodes.Ldarg_0);
+ ec.Emit (OpCodes.Initobj, type);
return;
+ }
var call = new CallEmitter ();
call.InstanceExpression = new CompilerGeneratedThis (type, loc);
{
Emit (ec);
}
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ if (argument_list != null)
+ argument_list.FlowAnalysis (fc);
+ }
}
public class ConstructorBaseInitializer : ConstructorInitializer {
}
}
- if (block.Resolve (null, bc, this)) {
+ if (block.Resolve (bc, this)) {
debug_builder = Parent.CreateMethodSymbolEntry ();
EmitContext ec = new EmitContext (this, ConstructorBuilder.GetILGenerator (), bc.ReturnType, debug_builder);
ec.With (EmitContext.Options.ConstructorScope, true);
ToplevelBlock block = method.Block;
if (block != null) {
BlockContext bc = new BlockContext (method, block, method.ReturnType);
- if (block.Resolve (null, bc, method)) {
+ if (block.Resolve (bc, method)) {
debug_builder = member.Parent.CreateMethodSymbolEntry ();
EmitContext ec = method.CreateEmitContext (MethodBuilder.GetILGenerator (), debug_builder);
}
if (best.MemberDefinition.IsImported && ts.MemberDefinition.IsImported) {
+ if (ts.Kind == MemberKind.MissingType)
+ continue;
+
+ if (best.Kind == MemberKind.MissingType) {
+ best = ts;
+ continue;
+ }
+
if (mode == LookupMode.Normal) {
ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (best);
ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (ts);
ctx.Module.Compiler.Report.Error (433, loc, "The imported type `{0}' is defined multiple times", ts.GetSignatureForError ());
}
+
break;
}
return uw != null && expr.Equals (uw.expr);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ expr.FlowAnalysis (fc);
+ }
+
public Expression Original {
get {
return expr;
ec.MarkLabel (end_label);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ expr.FlowAnalysis (fc);
+ }
+
public void AddressOf (EmitContext ec, AddressOp mode)
{
unwrap.AddressOf (ec, mode);
ec.MarkLabel (end_label);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ Binary.FlowAnalysis (fc);
+ }
+
public override SLE.Expression MakeExpression (BuilderContext ctx)
{
return Binary.MakeExpression (ctx, Left, Right);
ec.MarkLabel (end_label);
}
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ left.FlowAnalysis (fc);
+ var left_da = fc.BranchDefiniteAssignment ();
+ right.FlowAnalysis (fc);
+ fc.DefiniteAssignment = left_da;
+ }
+
protected override void CloneTo (CloneContext clonectx, Expression t)
{
NullCoalescingOperator target = (NullCoalescingOperator) t;
public abstract class Statement {
public Location loc;
+ protected bool reachable;
+
+ public bool IsUnreachable {
+ get {
+ return !reachable;
+ }
+ }
/// <summary>
/// Resolves the statement, true means that all sub-statements
return true;
}
- /// <summary>
- /// We already know that the statement is unreachable, but we still
- /// need to resolve it to catch errors.
- /// </summary>
- public virtual bool ResolveUnreachable (BlockContext ec, bool warn)
- {
- //
- // This conflicts with csc's way of doing this, but IMHO it's
- // the right thing to do.
- //
- // If something is unreachable, we still check whether it's
- // correct. This means that you cannot use unassigned variables
- // in unreachable code, for instance.
- //
-
- bool unreachable = false;
- if (warn && !ec.UnreachableReported) {
-
- // TODO: This is wrong, need to form of flow-analysis branch specific flag
- // or multiple unrelared unreachable code won't be reported
- // if (false) { // ok } if (false) { // not reported }
- ec.UnreachableReported = true;
- unreachable = true;
- ec.Report.Warning (162, 2, loc, "Unreachable code detected");
- }
-
- ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
- ec.CurrentBranching.CurrentUsageVector.Goto ();
- bool ok = Resolve (ec);
- ec.KillFlowBranching ();
-
- if (unreachable) {
- ec.UnreachableReported = false;
- }
-
- return ok;
- }
-
/// <summary>
/// Return value indicates whether all code paths emitted return.
/// </summary>
{
return visitor.Visit (this);
}
+
+ //
+ // Return value indicates whether statement has unreachable end
+ //
+ protected abstract bool DoFlowAnalysis (FlowAnalysisContext fc);
+
+ public bool FlowAnalysis (FlowAnalysisContext fc)
+ {
+ if (reachable) {
+ fc.UnreachableReported = false;
+ var res = DoFlowAnalysis (fc);
+ fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse = null;
+ return res;
+ }
+
+ //
+ // Special handling cases
+ //
+ if (this is Block) {
+ return DoFlowAnalysis (fc);
+ }
+
+ if (this is EmptyStatement)
+ return true;
+
+ if (fc.UnreachableReported)
+ return true;
+
+ fc.Report.Warning (162, 2, loc, "Unreachable code detected");
+ fc.UnreachableReported = true;
+ return true;
+ }
+
+ public virtual Reachability MarkReachable (Reachability rc)
+ {
+ if (!rc.IsUnreachable)
+ reachable = true;
+
+ return rc;
+ }
+
+ protected void CheckExitBoundaries (BlockContext bc, Block scope)
+ {
+ if (bc.CurrentBlock.ParametersBlock.Original != scope.ParametersBlock.Original) {
+ bc.Report.Error (1632, loc, "Control cannot leave the body of an anonymous method");
+ return;
+ }
+
+ for (var b = bc.CurrentBlock; b != null && b != scope; b = b.Parent) {
+ if (b.IsFinallyBlock) {
+ Error_FinallyClauseExit (bc);
+ break;
+ }
+ }
+ }
+
+ protected void Error_FinallyClauseExit (BlockContext bc)
+ {
+ bc.Report.Error (157, loc, "Control cannot leave the body of a finally clause");
+ }
}
public sealed class EmptyStatement : Statement
{
this.loc = loc;
}
-
- public override bool Resolve (BlockContext ec)
- {
- return true;
- }
- public override bool ResolveUnreachable (BlockContext ec, bool warn)
+ public override bool Resolve (BlockContext ec)
{
return true;
}
throw new NotSupportedException ();
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ return false;
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement target)
{
// nothing needed.
return visitor.Visit (this);
}
}
-
+
public class If : Statement {
Expression expr;
public Statement TrueStatement;
public Statement FalseStatement;
- bool is_true_ret;
+ bool true_returns, false_returns;
public If (Expression bool_expr, Statement true_statement, Location l)
: this (bool_expr, true_statement, null, l)
public override bool Resolve (BlockContext ec)
{
- bool ok = true;
-
expr = expr.Resolve (ec);
- if (expr == null) {
- ok = false;
- } else {
- //
- // Dead code elimination
- //
- if (expr is Constant) {
- bool take = !((Constant) expr).IsDefaultValue;
- if (take) {
- if (!TrueStatement.Resolve (ec))
- return false;
- if ((FalseStatement != null) &&
- !FalseStatement.ResolveUnreachable (ec, true))
- return false;
- FalseStatement = null;
- } else {
- if (!TrueStatement.ResolveUnreachable (ec, true))
- return false;
- TrueStatement = null;
-
- if ((FalseStatement != null) &&
- !FalseStatement.Resolve (ec))
- return false;
- }
+ var ok = TrueStatement.Resolve (ec);
- return true;
- }
- }
-
- ec.StartFlowBranching (FlowBranching.BranchingType.Conditional, loc);
-
- ok &= TrueStatement.Resolve (ec);
-
- is_true_ret = ec.CurrentBranching.CurrentUsageVector.IsUnreachable;
-
- ec.CurrentBranching.CreateSibling ();
-
- if (FalseStatement != null)
+ if (FalseStatement != null) {
ok &= FalseStatement.Resolve (ec);
-
- ec.EndFlowBranching ();
+ }
return ok;
}
bool branch_emitted = false;
end = ec.DefineLabel ();
- if (!is_true_ret){
+ if (!true_returns){
ec.Emit (OpCodes.Br, end);
branch_emitted = true;
}
}
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignment;
+
+ expr.FlowAnalysis (fc);
+
+ var da_false = new DefiniteAssignmentBitSet (fc.DefiniteAssignmentOnFalse);
+
+ fc.DefiniteAssignment = fc.DefiniteAssignmentOnTrue;
+ fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse = null;
+
+ var res = TrueStatement.FlowAnalysis (fc);
+
+ if (FalseStatement == null) {
+ if (true_returns)
+ fc.DefiniteAssignment = da_false;
+ else
+ fc.DefiniteAssignment &= da_false;
+
+ return false;
+ }
+
+ if (true_returns) {
+ fc.DefiniteAssignment = da_false;
+ return FalseStatement.FlowAnalysis (fc);
+ }
+
+ var da_true = fc.DefiniteAssignment;
+
+ fc.DefiniteAssignment = da_false;
+ res &= FalseStatement.FlowAnalysis (fc);
+
+ if (!TrueStatement.IsUnreachable) {
+ if (false_returns || FalseStatement.IsUnreachable)
+ fc.DefiniteAssignment = da_true;
+ else
+ fc.DefiniteAssignment &= da_true;
+ }
+
+ return res;
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ if (rc.IsUnreachable)
+ return rc;
+
+ base.MarkReachable (rc);
+
+ var c = expr as Constant;
+ if (c != null) {
+ bool take = !c.IsDefaultValue;
+ if (take) {
+ rc = TrueStatement.MarkReachable (rc);
+ } else {
+ if (FalseStatement != null)
+ rc = FalseStatement.MarkReachable (rc);
+ }
+
+ return rc;
+ }
+
+ var true_rc = TrueStatement.MarkReachable (rc);
+ true_returns = true_rc.IsUnreachable;
+
+ if (FalseStatement == null)
+ return rc;
+
+ var false_rc = FalseStatement.MarkReachable (rc);
+ false_returns = false_rc.IsUnreachable;
+
+ return true_rc & false_rc;
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement t)
{
If target = (If) t;
}
}
- public class Do : Statement {
+ public class Do : LoopStatement
+ {
public Expression expr;
- public Statement EmbeddedStatement;
+ bool iterator_reachable, end_reachable;
public Do (Statement statement, BooleanExpression bool_expr, Location doLocation, Location whileLocation)
+ : base (statement)
{
expr = bool_expr;
- EmbeddedStatement = statement;
loc = doLocation;
WhileLocation = whileLocation;
}
get; private set;
}
- public override bool Resolve (BlockContext ec)
+ public override bool Resolve (BlockContext bc)
{
- bool ok = true;
-
- ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
+ var ok = base.Resolve (bc);
- bool was_unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable;
-
- ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc);
- if (!EmbeddedStatement.Resolve (ec))
- ok = false;
- ec.EndFlowBranching ();
-
- if (ec.CurrentBranching.CurrentUsageVector.IsUnreachable && !was_unreachable)
- ec.Report.Warning (162, 2, expr.Location, "Unreachable code detected");
-
- expr = expr.Resolve (ec);
- if (expr == null)
- ok = false;
- else if (expr is Constant){
- bool infinite = !((Constant) expr).IsDefaultValue;
- if (infinite)
- ec.CurrentBranching.CurrentUsageVector.Goto ();
- }
-
- ec.EndFlowBranching ();
+ expr = expr.Resolve (bc);
return ok;
}
ec.LoopEnd = ec.DefineLabel ();
ec.MarkLabel (loop);
- EmbeddedStatement.Emit (ec);
+ Statement.Emit (ec);
ec.MarkLabel (ec.LoopBegin);
// Mark start of while condition
ec.LoopEnd = old_end;
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ var res = Statement.FlowAnalysis (fc);
+
+ fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignment;
+ expr.FlowAnalysis (fc);
+
+ fc.DefiniteAssignment = fc.DefiniteAssignmentOnFalse;
+
+ if (res && !iterator_reachable)
+ return !end_reachable;
+
+ if (!end_reachable) {
+ var c = expr as Constant;
+ if (c != null && !c.IsDefaultValue)
+ return true;
+ }
+
+ return false;
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ base.MarkReachable (rc);
+
+ var body_rc = Statement.MarkReachable (rc);
+
+ if (body_rc.IsUnreachable && !iterator_reachable) {
+ expr = new UnreachableExpression (expr);
+ return end_reachable ? rc : Reachability.CreateUnreachable ();
+ }
+
+ if (!end_reachable) {
+ var c = expr as Constant;
+ if (c != null && !c.IsDefaultValue)
+ return Reachability.CreateUnreachable ();
+ }
+
+ return rc;
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement t)
{
Do target = (Do) t;
- target.EmbeddedStatement = EmbeddedStatement.Clone (clonectx);
+ target.Statement = Statement.Clone (clonectx);
target.expr = expr.Clone (clonectx);
}
{
return visitor.Visit (this);
}
+
+ public override void SetEndReachable ()
+ {
+ end_reachable = true;
+ }
+
+ public override void SetIteratorReachable ()
+ {
+ iterator_reachable = true;
+ }
}
- public class While : Statement {
+ public class While : LoopStatement
+ {
public Expression expr;
- public Statement Statement;
- bool infinite, empty;
+ bool empty, infinite, end_reachable;
+ List<DefiniteAssignmentBitSet> end_reachable_das;
public While (BooleanExpression bool_expr, Statement statement, Location l)
+ : base (statement)
{
this.expr = bool_expr;
- Statement = statement;
loc = l;
}
- public override bool Resolve (BlockContext ec)
+ public override bool Resolve (BlockContext bc)
{
bool ok = true;
- expr = expr.Resolve (ec);
+ expr = expr.Resolve (bc);
if (expr == null)
ok = false;
- //
- // Inform whether we are infinite or not
- //
- if (expr is Constant){
- bool value = !((Constant) expr).IsDefaultValue;
-
- if (value == false){
- if (!Statement.ResolveUnreachable (ec, true))
- return false;
- empty = true;
- return true;
- }
-
- infinite = true;
+ var c = expr as Constant;
+ if (c != null) {
+ empty = c.IsDefaultValue;
+ infinite = !empty;
}
- ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
- if (!infinite)
- ec.CurrentBranching.CreateSibling ();
-
- ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc);
- if (!Statement.Resolve (ec))
- ok = false;
- ec.EndFlowBranching ();
-
- // There's no direct control flow from the end of the embedded statement to the end of the loop
- ec.CurrentBranching.CurrentUsageVector.Goto ();
-
- ec.EndFlowBranching ();
-
+ ok &= base.Resolve (bc);
return ok;
}
ec.LoopEnd = old_end;
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignment;
+
+ expr.FlowAnalysis (fc);
+
+ fc.DefiniteAssignment = fc.DefiniteAssignmentOnTrue;
+ var da_false = new DefiniteAssignmentBitSet (fc.DefiniteAssignmentOnFalse);
+ fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse = null;
+
+ Statement.FlowAnalysis (fc);
+
+ //
+ // Special case infinite while with breaks
+ //
+ if (end_reachable_das != null) {
+ da_false = DefiniteAssignmentBitSet.And (end_reachable_das);
+ end_reachable_das = null;
+ }
+
+ fc.DefiniteAssignment = da_false;
+
+ if (infinite && !end_reachable)
+ return true;
+
+ return false;
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ if (rc.IsUnreachable)
+ return rc;
+
+ base.MarkReachable (rc);
+
+ //
+ // Special case unreachable while body
+ //
+ if (empty) {
+ Statement.MarkReachable (Reachability.CreateUnreachable ());
+ return rc;
+ }
+
+ Statement.MarkReachable (rc);
+
+ //
+ // When infinite while end is unreachable via break anything what follows is unreachable too
+ //
+ if (infinite && !end_reachable)
+ return Reachability.CreateUnreachable ();
+
+ return rc;
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement t)
{
While target = (While) t;
{
return visitor.Visit (this);
}
+
+ public override void AddEndDefiniteAssignment (FlowAnalysisContext fc)
+ {
+ if (!infinite)
+ return;
+
+ if (end_reachable_das == null)
+ end_reachable_das = new List<DefiniteAssignmentBitSet> ();
+
+ end_reachable_das.Add (fc.DefiniteAssignment);
+ }
+
+ public override void SetEndReachable ()
+ {
+ end_reachable = true;
+ }
}
- public class For : Statement
+ public class For : LoopStatement
{
- bool infinite, empty;
+ bool infinite, empty, iterator_reachable, end_reachable;
+ List<DefiniteAssignmentBitSet> end_reachable_das;
public For (Location l)
+ : base (null)
{
loc = l;
}
get; set;
}
- public Statement Statement {
- get; set;
- }
-
- public override bool Resolve (BlockContext ec)
+ public override bool Resolve (BlockContext bc)
{
- bool ok = true;
-
- if (Initializer != null) {
- if (!Initializer.Resolve (ec))
- ok = false;
- }
+ Initializer.Resolve (bc);
if (Condition != null) {
- Condition = Condition.Resolve (ec);
- if (Condition == null)
- ok = false;
- else if (Condition is Constant) {
- bool value = !((Constant) Condition).IsDefaultValue;
-
- if (value == false){
- if (!Statement.ResolveUnreachable (ec, true))
- return false;
- if ((Iterator != null) &&
- !Iterator.ResolveUnreachable (ec, false))
- return false;
+ Condition = Condition.Resolve (bc);
+ var condition_constant = Condition as Constant;
+ if (condition_constant != null) {
+ if (condition_constant.IsDefaultValue) {
empty = true;
- return true;
+ } else {
+ infinite = true;
}
-
- infinite = true;
}
- } else
+ } else {
infinite = true;
+ }
- ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
- if (!infinite)
- ec.CurrentBranching.CreateSibling ();
+ base.Resolve (bc);
- bool was_unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable;
+ Iterator.Resolve (bc);
- ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc);
- if (!Statement.Resolve (ec))
- ok = false;
- ec.EndFlowBranching ();
+ return true;
+ }
- if (Iterator != null){
- if (ec.CurrentBranching.CurrentUsageVector.IsUnreachable) {
- if (!Iterator.ResolveUnreachable (ec, !was_unreachable))
- ok = false;
- } else {
- if (!Iterator.Resolve (ec))
- ok = false;
- }
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ Initializer.FlowAnalysis (fc);
+
+ DefiniteAssignmentBitSet da_false;
+ if (Condition != null) {
+ fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse = fc.DefiniteAssignment;
+
+ Condition.FlowAnalysis (fc);
+ fc.DefiniteAssignment = fc.DefiniteAssignmentOnTrue;
+ da_false = new DefiniteAssignmentBitSet (fc.DefiniteAssignmentOnFalse);
+ fc.DefiniteAssignmentOnTrue = fc.DefiniteAssignmentOnFalse = null;
+ } else {
+ da_false = fc.BranchDefiniteAssignment ();
}
- // There's no direct control flow from the end of the embedded statement to the end of the loop
- ec.CurrentBranching.CurrentUsageVector.Goto ();
+ Statement.FlowAnalysis (fc);
- ec.EndFlowBranching ();
+ Iterator.FlowAnalysis (fc);
- return ok;
+ //
+ // Special case infinite for with breaks
+ //
+ if (end_reachable_das != null) {
+ da_false = DefiniteAssignmentBitSet.And (end_reachable_das);
+ end_reachable_das = null;
+ }
+
+ fc.DefiniteAssignment = da_false;
+
+ if (infinite && !end_reachable)
+ return true;
+
+ return false;
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ base.MarkReachable (rc);
+
+ Initializer.MarkReachable (rc);
+
+ var body_rc = Statement.MarkReachable (rc);
+ if (!body_rc.IsUnreachable || iterator_reachable) {
+ Iterator.MarkReachable (rc);
+ }
+
+ //
+ // When infinite for end is unreachable via break anything what follows is unreachable too
+ //
+ if (infinite && !end_reachable) {
+ return Reachability.CreateUnreachable ();
+ }
+
+ return rc;
}
protected override void DoEmit (EmitContext ec)
{
return visitor.Visit (this);
}
+
+ public override void AddEndDefiniteAssignment (FlowAnalysisContext fc)
+ {
+ if (!infinite)
+ return;
+
+ if (end_reachable_das == null)
+ end_reachable_das = new List<DefiniteAssignmentBitSet> ();
+
+ end_reachable_das.Add (fc.DefiniteAssignment);
+ }
+
+ public override void SetEndReachable ()
+ {
+ end_reachable = true;
+ }
+
+ public override void SetIteratorReachable ()
+ {
+ iterator_reachable = true;
+ }
+ }
+
+ public abstract class LoopStatement : Statement
+ {
+ protected LoopStatement (Statement statement)
+ {
+ Statement = statement;
+ }
+
+ public Statement Statement { get; set; }
+
+ public override bool Resolve (BlockContext bc)
+ {
+ var prev_loop = bc.EnclosingLoop;
+ var prev_los = bc.EnclosingLoopOrSwitch;
+ bc.EnclosingLoopOrSwitch = bc.EnclosingLoop = this;
+ Statement.Resolve (bc);
+ bc.EnclosingLoopOrSwitch = prev_los;
+ bc.EnclosingLoop = prev_loop;
+
+ return true;
+ }
+
+ //
+ // Needed by possibly infinite loops statements (for, while) and switch statment
+ //
+ public virtual void AddEndDefiniteAssignment (FlowAnalysisContext fc)
+ {
+ }
+
+ public virtual void SetEndReachable ()
+ {
+ }
+
+ public virtual void SetIteratorReachable ()
+ {
+ }
}
public class StatementExpression : Statement
expr.EmitStatement (ec);
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ expr.FlowAnalysis (fc);
+ return false;
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ base.MarkReachable (rc);
+ expr.MarkReachable (rc);
+ return rc;
+ }
+
public override bool Resolve (BlockContext ec)
{
expr = expr.ResolveStatement (ec);
throw new NotSupportedException ();
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ return false;
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement target)
{
var t = (StatementErrorExpression) target;
s.Emit (ec);
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ foreach (var s in statements)
+ s.FlowAnalysis (fc);
+
+ return false;
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ base.MarkReachable (rc);
+
+ Reachability res = rc;
+ foreach (var s in statements)
+ res = s.MarkReachable (rc);
+
+ return res;
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement target)
{
StatementList t = (StatementList) target;
}
}
- // A 'return' or a 'yield break'
+ //
+ // For statements which require special handling when inside try or catch block
+ //
public abstract class ExitStatement : Statement
{
protected bool unwind_protect;
- protected abstract bool DoResolve (BlockContext ec);
- public virtual void Error_FinallyClause (Report Report)
+ protected abstract bool DoResolve (BlockContext bc);
+ protected abstract bool IsLocalExit { get; }
+
+ public override bool Resolve (BlockContext bc)
{
- Report.Error (157, loc, "Control cannot leave the body of a finally clause");
+ var res = DoResolve (bc);
+
+ if (!IsLocalExit) {
+ //
+ // We are inside finally scope but is it the scope we are exiting
+ //
+ if (bc.HasSet (ResolveContext.Options.FinallyScope)) {
+
+ for (var b = bc.CurrentBlock; b != null; b = b.Parent) {
+ if (b.IsFinallyBlock) {
+ Error_FinallyClauseExit (bc);
+ break;
+ }
+
+ if (b is ParametersBlock)
+ break;
+ }
+ }
+ }
+
+ unwind_protect = bc.HasAny (ResolveContext.Options.TryScope | ResolveContext.Options.CatchScope);
+ return res;
}
- public sealed override bool Resolve (BlockContext ec)
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
{
- var res = DoResolve (ec);
- unwind_protect = ec.CurrentBranching.AddReturnOrigin (ec.CurrentBranching.CurrentUsageVector, this);
- ec.CurrentBranching.CurrentUsageVector.Goto ();
- return res;
+ if (IsLocalExit)
+ return true;
+
+ if (fc.TryFinally != null) {
+ fc.TryFinally.RegisterForControlExitCheck (new DefiniteAssignmentBitSet (fc.DefiniteAssignment));
+ } else {
+ fc.ParametersBlock.CheckControlExit (fc);
+ }
+
+ return true;
}
}
}
}
+ protected override bool IsLocalExit {
+ get {
+ return false;
+ }
+ }
+
#endregion
protected override bool DoResolve (BlockContext ec)
{
+ var block_return_type = ec.ReturnType;
+
if (expr == null) {
- if (ec.ReturnType.Kind == MemberKind.Void)
+ if (block_return_type.Kind == MemberKind.Void)
return true;
//
expr = EmptyExpression.Null;
return true;
}
+
+ if (storey.ReturnType.IsGenericTask)
+ block_return_type = storey.ReturnType.TypeArguments[0];
}
if (ec.CurrentIterator != null) {
Error_ReturnFromIterator (ec);
- } else if (ec.ReturnType != InternalType.ErrorType) {
+ } else if (block_return_type != InternalType.ErrorType) {
ec.Report.Error (126, loc,
"An object of a type convertible to `{0}' is required for the return statement",
- ec.ReturnType.GetSignatureForError ());
+ block_return_type.GetSignatureForError ());
}
return false;
}
expr = expr.Resolve (ec);
- TypeSpec block_return_type = ec.ReturnType;
AnonymousExpression am = ec.CurrentAnonymousMethod;
if (am == null) {
ec.EmitEpilogue ();
}
- ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, async_body.BodyEnd);
+ ec.Emit (OpCodes.Leave, async_body.BodyEnd);
return;
}
}
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ if (expr != null)
+ expr.FlowAnalysis (fc);
+
+ base.DoFlowAnalysis (fc);
+ return true;
+ }
+
void Error_ReturnFromIterator (ResolveContext rc)
{
rc.Report.Error (1622, loc,
"Cannot return a value from iterators. Use the yield return statement to return a value, or yield break to end the iteration");
}
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ base.MarkReachable (rc);
+ return Reachability.CreateUnreachable ();
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement t)
{
Return target = (Return) t;
}
}
- public class Goto : Statement {
+ public class Goto : ExitStatement
+ {
string target;
LabeledStatement label;
- bool unwind_protect;
+ TryFinally try_finally;
- public override bool Resolve (BlockContext ec)
- {
- unwind_protect = ec.CurrentBranching.AddGotoOrigin (ec.CurrentBranching.CurrentUsageVector, this);
- ec.CurrentBranching.CurrentUsageVector.Goto ();
- return true;
- }
-
public Goto (string label, Location l)
{
loc = l;
get { return target; }
}
- public void SetResolvedTarget (LabeledStatement label)
+ protected override bool IsLocalExit {
+ get {
+ return true;
+ }
+ }
+
+ protected override bool DoResolve (BlockContext bc)
{
- this.label = label;
- label.AddReference ();
+ label = bc.CurrentBlock.LookupLabel (target);
+ if (label == null) {
+ Error_UnknownLabel (bc, target, loc);
+ return false;
+ }
+
+ try_finally = bc.CurrentTryBlock as TryFinally;
+
+ CheckExitBoundaries (bc, label.Block);
+
+ return true;
+ }
+
+ public static void Error_UnknownLabel (BlockContext bc, string label, Location loc)
+ {
+ bc.Report.Error (159, loc, "The label `{0}:' could not be found within the scope of the goto statement",
+ label);
+ }
+
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ if (fc.LabelStack == null) {
+ fc.LabelStack = new List<LabeledStatement> ();
+ } else if (fc.LabelStack.Contains (label)) {
+ return true;
+ }
+
+ fc.LabelStack.Add (label);
+ label.Block.ScanGotoJump (label, fc);
+ fc.LabelStack.Remove (label);
+ return true;
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ if (rc.IsUnreachable)
+ return rc;
+
+ base.MarkReachable (rc);
+
+ if (try_finally != null) {
+ if (try_finally.FinallyBlock.HasReachableClosingBrace) {
+ label.AddGotoReference (rc, false);
+ } else {
+ label.AddGotoReference (rc, true);
+ }
+
+ try_finally = null;
+ } else {
+ label.AddGotoReference (rc, false);
+ }
+
+ return Reachability.CreateUnreachable ();
}
protected override void CloneTo (CloneContext clonectx, Statement target)
{
if (label == null)
throw new InternalErrorException ("goto emitted before target resolved");
+
Label l = label.LabelTarget (ec);
ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, l);
}
string name;
bool defined;
bool referenced;
+ bool finalTarget;
Label label;
Block block;
-
- FlowBranching.UsageVector vectors;
public LabeledStatement (string name, Block block, Location l)
{
get { return name; }
}
- public bool IsDefined {
- get { return defined; }
- }
-
- public bool HasBeenReferenced {
- get { return referenced; }
- }
+ protected override void CloneTo (CloneContext clonectx, Statement target)
+ {
+ var t = (LabeledStatement) target;
- public FlowBranching.UsageVector JumpOrigins {
- get { return vectors; }
+ t.block = clonectx.RemapBlockCopy (block);
}
- public void AddUsageVector (FlowBranching.UsageVector vector)
+ public override bool Resolve (BlockContext bc)
{
- vector = vector.Clone ();
- vector.Next = vectors;
- vectors = vector;
+ return true;
}
- protected override void CloneTo (CloneContext clonectx, Statement target)
+ protected override void DoEmit (EmitContext ec)
{
- // nothing to clone
+ LabelTarget (ec);
+ ec.MarkLabel (label);
+
+ if (finalTarget)
+ ec.Emit (OpCodes.Br_S, label);
}
- public override bool Resolve (BlockContext ec)
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
{
- // this flow-branching will be terminated when the surrounding block ends
- ec.StartFlowBranching (this);
- return true;
+ if (!referenced) {
+ fc.Report.Warning (164, 2, loc, "This label has not been referenced");
+ }
+
+ return false;
}
- protected override void DoEmit (EmitContext ec)
+ public override Reachability MarkReachable (Reachability rc)
{
- if (!HasBeenReferenced)
- ec.Report.Warning (164, 2, loc, "This label has not been referenced");
+ base.MarkReachable (rc);
- LabelTarget (ec);
- ec.MarkLabel (label);
+ if (referenced)
+ rc = new Reachability ();
+
+ return rc;
}
- public void AddReference ()
+ public void AddGotoReference (Reachability rc, bool finalTarget)
{
+ if (referenced)
+ return;
+
referenced = true;
+ MarkReachable (rc);
+
+ //
+ // Label is final target when goto jumps out of try block with
+ // finally clause. In that case we need leave with target but in C#
+ // terms the label is unreachable. Using finalTarget we emit
+ // explicit label not just marker
+ //
+ if (finalTarget) {
+ this.finalTarget = true;
+ return;
+ }
+
+ block.ScanGotoJump (this);
}
-
+
public override object Accept (StructuralVisitor visitor)
{
return visitor.Visit (this);
/// <summary>
/// `goto default' statement
/// </summary>
- public class GotoDefault : Statement {
-
+ public class GotoDefault : SwitchGoto
+ {
public GotoDefault (Location l)
+ : base (l)
{
- loc = l;
- }
-
- protected override void CloneTo (CloneContext clonectx, Statement target)
- {
- // nothing to clone
}
- public override bool Resolve (BlockContext ec)
+ public override bool Resolve (BlockContext bc)
{
- ec.CurrentBranching.CurrentUsageVector.Goto ();
-
- if (ec.Switch == null) {
- ec.Report.Error (153, loc, "A goto case is only valid inside a switch statement");
+ if (bc.Switch == null) {
+ Error_GotoCaseRequiresSwitchBlock (bc);
return false;
}
- ec.Switch.RegisterGotoCase (null, null);
+ bc.Switch.RegisterGotoCase (null, null);
+ base.Resolve (bc);
return true;
}
protected override void DoEmit (EmitContext ec)
{
- ec.Emit (OpCodes.Br, ec.Switch.DefaultLabel.GetILLabel (ec));
+ ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.Switch.DefaultLabel.GetILLabel (ec));
}
-
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ if (!rc.IsUnreachable) {
+ var label = switch_statement.DefaultLabel;
+ if (label.IsUnreachable) {
+ label.MarkReachable (rc);
+ switch_statement.Block.ScanGotoJump (label);
+ }
+ }
+
+ return base.MarkReachable (rc);
+ }
+
public override object Accept (StructuralVisitor visitor)
{
return visitor.Visit (this);
/// <summary>
/// `goto case' statement
/// </summary>
- public class GotoCase : Statement {
+ public class GotoCase : SwitchGoto
+ {
Expression expr;
public GotoCase (Expression e, Location l)
+ : base (l)
{
expr = e;
- loc = l;
}
public Expression Expr {
get {
- return this.expr;
+ return expr;
}
}
public SwitchLabel Label { get; set; }
-
+
public override bool Resolve (BlockContext ec)
{
- if (ec.Switch == null){
- ec.Report.Error (153, loc, "A goto case is only valid inside a switch statement");
+ if (ec.Switch == null) {
+ Error_GotoCaseRequiresSwitchBlock (ec);
return false;
}
- ec.CurrentBranching.CurrentUsageVector.Goto ();
-
Constant c = expr.ResolveLabelConstant (ec);
if (c == null) {
return false;
}
ec.Switch.RegisterGotoCase (this, res);
+ base.Resolve (ec);
+ expr = res;
+
return true;
}
protected override void DoEmit (EmitContext ec)
{
- ec.Emit (OpCodes.Br, Label.GetILLabel (ec));
+ ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, Label.GetILLabel (ec));
}
protected override void CloneTo (CloneContext clonectx, Statement t)
target.expr = expr.Clone (clonectx);
}
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ if (!rc.IsUnreachable) {
+ var label = switch_statement.FindLabel ((Constant) expr);
+ if (label.IsUnreachable) {
+ label.MarkReachable (rc);
+ switch_statement.Block.ScanGotoJump (label);
+ }
+ }
+
+ return base.MarkReachable (rc);
+ }
public override object Accept (StructuralVisitor visitor)
{
return visitor.Visit (this);
}
}
+
+ public abstract class SwitchGoto : Statement
+ {
+ protected bool unwind_protect;
+ protected Switch switch_statement;
+
+ protected SwitchGoto (Location loc)
+ {
+ this.loc = loc;
+ }
+
+ protected override void CloneTo (CloneContext clonectx, Statement target)
+ {
+ // Nothing to clone
+ }
+
+ public override bool Resolve (BlockContext bc)
+ {
+ CheckExitBoundaries (bc, bc.Switch.Block);
+
+ unwind_protect = bc.HasAny (ResolveContext.Options.TryScope | ResolveContext.Options.CatchScope);
+ switch_statement = bc.Switch;
+
+ return true;
+ }
+
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ return true;
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ base.MarkReachable (rc);
+ return Reachability.CreateUnreachable ();
+ }
+
+ protected void Error_GotoCaseRequiresSwitchBlock (BlockContext bc)
+ {
+ bc.Report.Error (153, loc, "A goto case is only valid inside a switch statement");
+ }
+ }
public class Throw : Statement {
Expression expr;
public override bool Resolve (BlockContext ec)
{
if (expr == null) {
- ec.CurrentBranching.CurrentUsageVector.Goto ();
- return ec.CurrentBranching.CheckRethrow (loc);
+ if (!ec.HasSet (ResolveContext.Options.CatchScope)) {
+ ec.Report.Error (156, loc, "A throw statement with no arguments is not allowed outside of a catch clause");
+ } else if (ec.HasSet (ResolveContext.Options.FinallyScope)) {
+ for (var b = ec.CurrentBlock; b != null && !b.IsCatchBlock; b = b.Parent) {
+ if (b.IsFinallyBlock) {
+ ec.Report.Error (724, loc,
+ "A throw statement with no arguments is not allowed inside of a finally clause nested inside of the innermost catch clause");
+ break;
+ }
+ }
+ }
+
+ return true;
}
expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
- ec.CurrentBranching.CurrentUsageVector.Goto ();
if (expr == null)
return false;
}
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ if (expr != null)
+ expr.FlowAnalysis (fc);
+
+ return true;
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ base.MarkReachable (rc);
+ return Reachability.CreateUnreachable ();
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement t)
{
Throw target = (Throw) t;
}
}
- public class Break : Statement {
-
+ public class Break : LocalExitStatement
+ {
public Break (Location l)
+ : base (l)
{
- loc = l;
}
-
- bool unwind_protect;
-
- public override bool Resolve (BlockContext ec)
+
+ public override object Accept (StructuralVisitor visitor)
{
- unwind_protect = ec.CurrentBranching.AddBreakOrigin (ec.CurrentBranching.CurrentUsageVector, loc);
- ec.CurrentBranching.CurrentUsageVector.Goto ();
- return true;
+ return visitor.Visit (this);
}
protected override void DoEmit (EmitContext ec)
ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopEnd);
}
- protected override void CloneTo (CloneContext clonectx, Statement t)
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
{
- // nothing needed
+ enclosing_loop.AddEndDefiniteAssignment (fc);
+ return true;
}
-
- public override object Accept (StructuralVisitor visitor)
+
+ protected override bool DoResolve (BlockContext bc)
{
- return visitor.Visit (this);
+ enclosing_loop = bc.EnclosingLoopOrSwitch;
+ return base.DoResolve (bc);
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ base.MarkReachable (rc);
+
+ if (!rc.IsUnreachable)
+ enclosing_loop.SetEndReachable ();
+
+ return Reachability.CreateUnreachable ();
}
}
- public class Continue : Statement {
-
+ public class Continue : LocalExitStatement
+ {
public Continue (Location l)
+ : base (l)
{
- loc = l;
}
- bool unwind_protect;
-
- public override bool Resolve (BlockContext ec)
+ public override object Accept (StructuralVisitor visitor)
{
- unwind_protect = ec.CurrentBranching.AddContinueOrigin (ec.CurrentBranching.CurrentUsageVector, loc);
- ec.CurrentBranching.CurrentUsageVector.Goto ();
- return true;
+ return visitor.Visit (this);
}
+
protected override void DoEmit (EmitContext ec)
{
ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopBegin);
}
+ protected override bool DoResolve (BlockContext bc)
+ {
+ enclosing_loop = bc.EnclosingLoop;
+ return base.DoResolve (bc);
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ base.MarkReachable (rc);
+
+ if (!rc.IsUnreachable)
+ enclosing_loop.SetIteratorReachable ();
+
+ return Reachability.CreateUnreachable ();
+ }
+ }
+
+ public abstract class LocalExitStatement : ExitStatement
+ {
+ protected LoopStatement enclosing_loop;
+
+ protected LocalExitStatement (Location loc)
+ {
+ this.loc = loc;
+ }
+
+ protected override bool IsLocalExit {
+ get {
+ return true;
+ }
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement t)
{
// nothing needed.
}
-
- public override object Accept (StructuralVisitor visitor)
+
+ protected override bool DoResolve (BlockContext bc)
{
- return visitor.Visit (this);
+ if (enclosing_loop == null) {
+ bc.Report.Error (139, loc, "No enclosing loop out of which to break or continue");
+ return false;
+ }
+
+ var block = enclosing_loop.Statement as Block;
+
+ // Don't need to do extra checks for simple statements loops
+ if (block != null) {
+ CheckExitBoundaries (bc, block);
+ }
+
+ return true;
}
}
}
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ if (Initializer != null)
+ Initializer.FlowAnalysis (fc);
+
+ if (declarators != null) {
+ foreach (var d in declarators) {
+ if (d.Initializer != null)
+ d.Initializer.FlowAnalysis (fc);
+ }
+ }
+
+ return false;
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ var init = initializer as ExpressionStatement;
+ if (init != null)
+ init.MarkReachable (rc);
+
+ return base.MarkReachable (rc);
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement target)
{
BlockVariable t = (BlockVariable) target;
//
// The information about a user-perceived local variable
//
- public class LocalVariable : INamedBlockVariable, ILocalVariable
+ public sealed class LocalVariable : INamedBlockVariable, ILocalVariable
{
[Flags]
public enum Flags
ForeachVariable = 1 << 5,
FixedVariable = 1 << 6,
UsingVariable = 1 << 7,
-// DefinitelyAssigned = 1 << 8,
- IsLocked = 1 << 9,
+ IsLocked = 1 << 8,
ReadonlyMask = ForeachVariable | FixedVariable | UsingVariable
}
throw new InternalErrorException ("Variable is not readonly");
}
- public bool IsThisAssigned (BlockContext ec, Block block)
+ public bool IsThisAssigned (FlowAnalysisContext fc, Block block)
{
if (VariableInfo == null)
throw new Exception ();
- if (!ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (VariableInfo))
+ if (IsAssigned (fc))
return true;
- return VariableInfo.IsFullyInitialized (ec, block.StartLocation);
+ return VariableInfo.IsFullyInitialized (fc, block.StartLocation);
}
- public bool IsAssigned (BlockContext ec)
+ public bool IsAssigned (FlowAnalysisContext fc)
{
- if (VariableInfo == null)
- throw new Exception ();
-
- return !ec.DoFlowAnalysis || ec.CurrentBranching.IsAssigned (VariableInfo);
+ return fc.IsDefinitelyAssigned (VariableInfo);
}
public void PrepareAssignmentAnalysis (BlockContext bc)
public enum Flags
{
Unchecked = 1,
- HasRet = 8,
+ ReachableEnd = 8,
Unsafe = 16,
HasCapturedVariable = 64,
HasCapturedThis = 1 << 7,
Resolved = 1 << 11,
YieldBlock = 1 << 12,
AwaitBlock = 1 << 13,
- Iterator = 1 << 14
+ FinallyBlock = 1 << 14,
+ CatchBlock = 1 << 15,
+ Iterator = 1 << 20,
+ NoFlowAnalysis = 1 << 21
}
public Block Parent;
#region Properties
- public bool HasUnreachableClosingBrace {
- get {
- return (flags & Flags.HasRet) != 0;
- }
- set {
- flags = value ? flags | Flags.HasRet : flags & ~Flags.HasRet;
- }
- }
-
public Block Original {
get {
return original;
set { flags = value ? flags | Flags.CompilerGenerated : flags & ~Flags.CompilerGenerated; }
}
+
+ public bool IsCatchBlock {
+ get {
+ return (flags & Flags.CatchBlock) != 0;
+ }
+ }
+
+ public bool IsFinallyBlock {
+ get {
+ return (flags & Flags.FinallyBlock) != 0;
+ }
+ }
+
public bool Unchecked {
get { return (flags & Flags.Unchecked) != 0; }
set { flags = value ? flags | Flags.Unchecked : flags & ~Flags.Unchecked; }
statements.Add (s);
}
- public int AssignableSlots {
- get {
- // FIXME: HACK, we don't know the block available variables count now, so set this high enough
- return 4096;
-// return assignable_slots;
- }
+ public LabeledStatement LookupLabel (string name)
+ {
+ return ParametersBlock.GetLabel (name, this);
}
- public LabeledStatement LookupLabel (string name)
+ public override Reachability MarkReachable (Reachability rc)
{
- return ParametersBlock.TopBlock.GetLabel (name, this);
+ if (rc.IsUnreachable)
+ return rc;
+
+ base.MarkReachable (rc);
+
+ if (scope_initializers != null) {
+ foreach (var si in scope_initializers)
+ si.MarkReachable (rc);
+ }
+
+ foreach (var s in statements) {
+ rc = s.MarkReachable (rc);
+ if (rc.IsUnreachable) {
+ if ((flags & Flags.ReachableEnd) != 0)
+ return new Reachability ();
+
+ return rc;
+ }
+ }
+
+ flags |= Flags.ReachableEnd;
+
+ return rc;
}
- public override bool Resolve (BlockContext ec)
+ public override bool Resolve (BlockContext bc)
{
if ((flags & Flags.Resolved) != 0)
return true;
- Block prev_block = ec.CurrentBlock;
- bool ok = true;
- bool unreachable = ec.IsUnreachable;
- bool prev_unreachable = unreachable;
-
- ec.CurrentBlock = this;
- ec.StartFlowBranching (this);
+ Block prev_block = bc.CurrentBlock;
+ bc.CurrentBlock = this;
//
// Compiler generated scope statements
//
if (scope_initializers != null) {
for (resolving_init_idx = 0; resolving_init_idx < scope_initializers.Count; ++resolving_init_idx) {
- scope_initializers[resolving_init_idx.Value].Resolve (ec);
+ scope_initializers[resolving_init_idx.Value].Resolve (bc);
}
resolving_init_idx = null;
}
- //
- // This flag is used to notate nested statements as unreachable from the beginning of this block.
- // For the purposes of this resolution, it doesn't matter that the whole block is unreachable
- // from the beginning of the function. The outer Resolve() that detected the unreachability is
- // responsible for handling the situation.
- //
+ bool ok = true;
int statement_count = statements.Count;
for (int ix = 0; ix < statement_count; ix++){
Statement s = statements [ix];
- //
- // Warn if we detect unreachable code.
- //
- if (unreachable) {
- if (s is EmptyStatement)
- continue;
-
- if (!ec.UnreachableReported && !(s is LabeledStatement) && !(s is SwitchLabel)) {
- ec.Report.Warning (162, 2, s.loc, "Unreachable code detected");
- ec.UnreachableReported = true;
- }
- }
-
- //
- // Note that we're not using ResolveUnreachable() for unreachable
- // statements here. ResolveUnreachable() creates a temporary
- // flow branching and kills it afterwards. This leads to problems
- // if you have two unreachable statements where the first one
- // assigns a variable and the second one tries to access it.
- //
-
- if (!s.Resolve (ec)) {
+ if (!s.Resolve (bc)) {
ok = false;
- if (!ec.IsInProbingMode)
+ if (!bc.IsInProbingMode)
statements [ix] = new EmptyStatement (s.loc);
continue;
}
+ }
- if (unreachable && !(s is LabeledStatement) && !(s is SwitchLabel) && !(s is Block))
- statements [ix] = new EmptyStatement (s.loc);
+ bc.CurrentBlock = prev_block;
- unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable;
- if (unreachable) {
- ec.IsUnreachable = true;
- } else if (ec.IsUnreachable)
- ec.IsUnreachable = false;
- }
+ flags |= Flags.Resolved;
+ return ok;
+ }
- if (unreachable != prev_unreachable) {
- ec.IsUnreachable = prev_unreachable;
- ec.UnreachableReported = false;
+ protected override void DoEmit (EmitContext ec)
+ {
+ for (int ix = 0; ix < statements.Count; ix++){
+ statements [ix].Emit (ec);
}
+ }
- while (ec.CurrentBranching is FlowBranchingLabeled)
- ec.EndFlowBranching ();
-
- bool flow_unreachable = ec.EndFlowBranching ();
+ public override void Emit (EmitContext ec)
+ {
+ if (scope_initializers != null)
+ EmitScopeInitializers (ec);
- ec.CurrentBlock = prev_block;
+ DoEmit (ec);
+ }
- if (flow_unreachable)
- flags |= Flags.HasRet;
+ protected void EmitScopeInitializers (EmitContext ec)
+ {
+ foreach (Statement s in scope_initializers)
+ s.Emit (ec);
+ }
- // If we're a non-static `struct' constructor which doesn't have an
- // initializer, then we must initialize all of the struct's fields.
- if (this == ParametersBlock.TopBlock && !ParametersBlock.TopBlock.IsThisAssigned (ec) && !flow_unreachable)
- ok = false;
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ if (scope_initializers != null) {
+ foreach (var si in scope_initializers)
+ si.FlowAnalysis (fc);
+ }
- flags |= Flags.Resolved;
- return ok;
+ return DoFlowAnalysis (fc, 0);
}
- public override bool ResolveUnreachable (BlockContext ec, bool warn)
+ bool DoFlowAnalysis (FlowAnalysisContext fc, int startIndex)
{
- bool unreachable = false;
- if (warn && !ec.UnreachableReported) {
- ec.UnreachableReported = true;
- unreachable = true;
- ec.Report.Warning (162, 2, loc, "Unreachable code detected");
- }
+ bool end_unreachable = !reachable;
+ for (; startIndex < statements.Count; ++startIndex) {
+ var s = statements[startIndex];
- var fb = ec.StartFlowBranching (FlowBranching.BranchingType.Block, loc);
- fb.CurrentUsageVector.IsUnreachable = true;
- bool ok = Resolve (ec);
- ec.KillFlowBranching ();
+ end_unreachable = s.FlowAnalysis (fc);
+ if (s.IsUnreachable) {
+ statements[startIndex] = new EmptyStatement (s.loc);
+ continue;
+ }
- if (unreachable)
- ec.UnreachableReported = false;
+ //
+ // Statement end reachability is needed mostly due to goto support. Consider
+ //
+ // if (cond) {
+ // goto X;
+ // } else {
+ // goto Y;
+ // }
+ // X:
+ //
+ // X label is reachable only via goto not as another statement after if. We need
+ // this for flow-analysis only to carry variable info correctly.
+ //
+ if (end_unreachable) {
+ for (++startIndex; startIndex < statements.Count; ++startIndex) {
+ s = statements[startIndex];
+ if (s is SwitchLabel) {
+ s.FlowAnalysis (fc);
+ break;
+ }
- return ok;
- }
-
- protected override void DoEmit (EmitContext ec)
- {
- for (int ix = 0; ix < statements.Count; ix++){
- statements [ix].Emit (ec);
+ if (s.IsUnreachable) {
+ s.FlowAnalysis (fc);
+ statements[startIndex] = new EmptyStatement (s.loc);
+ }
+ }
+ }
}
+
+ //
+ // The condition should be true unless there is forward jumping goto
+ //
+ // if (this is ExplicitBlock && end_unreachable != Explicit.HasReachableClosingBrace)
+ // Debug.Fail ();
+
+ return !Explicit.HasReachableClosingBrace;
}
- public override void Emit (EmitContext ec)
+ public void ScanGotoJump (Statement label)
{
- if (scope_initializers != null)
- EmitScopeInitializers (ec);
+ int i;
+ for (i = 0; i < statements.Count; ++i) {
+ if (statements[i] == label)
+ break;
+ }
- DoEmit (ec);
+ var rc = new Reachability ();
+ for (++i; i < statements.Count; ++i) {
+ var s = statements[i];
+ rc = s.MarkReachable (rc);
+ if (rc.IsUnreachable)
+ return;
+ }
+
+ flags |= Flags.ReachableEnd;
}
- protected void EmitScopeInitializers (EmitContext ec)
+ public void ScanGotoJump (Statement label, FlowAnalysisContext fc)
{
- foreach (Statement s in scope_initializers)
- s.Emit (ec);
+ int i;
+ for (i = 0; i < statements.Count; ++i) {
+ if (statements[i] == label)
+ break;
+ }
+
+ DoFlowAnalysis (fc, ++i);
}
#if DEBUG
public override string ToString ()
{
- return String.Format ("{0} ({1}:{2})", GetType (), ID, StartLocation);
+ return String.Format ("{0}: ID={1} Clone={2} Location={3}", GetType (), ID, clone_id != 0, StartLocation);
}
#endif
{
Block target = (Block) t;
#if DEBUG
- target.clone_id = clone_id_counter++;
+ target.clone_id = ++clone_id_counter;
#endif
clonectx.AddBlockMap (this, target);
}
}
+ public bool HasReachableClosingBrace {
+ get {
+ return (flags & Flags.ReachableEnd) != 0;
+ }
+ set {
+ flags = value ? flags | Flags.ReachableEnd : flags & ~Flags.ReachableEnd;
+ }
+ }
+
public bool HasYield {
get {
return (flags & Flags.YieldBlock) != 0;
if (Parent != null)
ec.EndScope ();
- if (ec.EmitAccurateDebugInfo && !HasUnreachableClosingBrace && !IsCompilerGenerated && ec.Mark (EndLocation)) {
+ if (ec.EmitAccurateDebugInfo && HasReachableClosingBrace && !(this is ParametersBlock) &&
+ !IsCompilerGenerated && ec.Mark (EndLocation)) {
ec.Emit (OpCodes.Nop);
}
}
}
}
+ public void SetCatchBlock ()
+ {
+ flags |= Flags.CatchBlock;
+ }
+
+ public void SetFinallyBlock ()
+ {
+ flags |= Flags.FinallyBlock;
+ }
+
public void WrapIntoDestructor (TryFinally tf, ExplicitBlock tryBlock)
{
tryBlock.statements = statements;
protected ParametersCompiled parameters;
protected ParameterInfo[] parameter_info;
- bool resolved;
- protected bool unreachable;
+ protected bool resolved;
protected ToplevelBlock top_block;
protected StateMachine state_machine;
+ protected Dictionary<string, object> labels;
- public ParametersBlock (Block parent, ParametersCompiled parameters, Location start)
+ public ParametersBlock (Block parent, ParametersCompiled parameters, Location start, Flags flags = 0)
: base (parent, 0, start, start)
{
if (parameters == null)
this.parameters = parameters;
ParametersBlock = this;
- flags |= (parent.ParametersBlock.flags & (Flags.YieldBlock | Flags.AwaitBlock));
+ this.flags |= flags | (parent.ParametersBlock.flags & (Flags.YieldBlock | Flags.AwaitBlock));
this.top_block = parent.ParametersBlock.top_block;
ProcessParameters ();
this.scope_initializers = source.scope_initializers;
this.resolved = true;
- this.unreachable = source.unreachable;
+ this.reachable = source.reachable;
this.am_storey = source.am_storey;
this.state_machine = source.state_machine;
+ this.flags = source.flags & Flags.ReachableEnd;
ParametersBlock = this;
#endregion
- // <summary>
- // Check whether all `out' parameters have been assigned.
- // </summary>
- public void CheckOutParameters (FlowBranching.UsageVector vector)
+ //
+ // Checks whether all `out' parameters have been assigned.
+ //
+ public void CheckControlExit (FlowAnalysisContext fc)
{
- if (vector.IsUnreachable)
- return;
-
- int n = parameter_info == null ? 0 : parameter_info.Length;
+ CheckControlExit (fc, fc.DefiniteAssignment);
+ }
- for (int i = 0; i < n; i++) {
- VariableInfo var = parameter_info[i].VariableInfo;
+ public virtual void CheckControlExit (FlowAnalysisContext fc, DefiniteAssignmentBitSet dat)
+ {
+ if (parameter_info == null)
+ return;
- if (var == null)
+ foreach (var p in parameter_info) {
+ if (p.VariableInfo == null)
continue;
- if (vector.IsAssigned (var, false))
+ if (p.VariableInfo.IsAssigned (dat))
continue;
- var p = parameter_info[i].Parameter;
- TopBlock.Report.Error (177, p.Location,
+ fc.Report.Error (177, p.Location,
"The out parameter `{0}' must be assigned to before control leaves the current method",
- p.Name);
+ p.Parameter.Name);
+ }
+ }
+
+ protected override void CloneTo (CloneContext clonectx, Statement t)
+ {
+ base.CloneTo (clonectx, t);
+
+ var target = (ParametersBlock) t;
+
+ //
+ // Clone label statements as well as they contain block reference
+ //
+ var pb = this;
+ while (true) {
+ if (pb.labels != null) {
+ target.labels = new Dictionary<string, object> ();
+
+ foreach (var entry in pb.labels) {
+ var list = entry.Value as List<LabeledStatement>;
+
+ if (list != null) {
+ var list_clone = new List<LabeledStatement> ();
+ foreach (var lentry in list) {
+ list_clone.Add (RemapLabeledStatement (lentry, lentry.Block, clonectx.RemapBlockCopy (lentry.Block)));
+ }
+
+ target.labels.Add (entry.Key, list_clone);
+ } else {
+ var labeled = (LabeledStatement) entry.Value;
+ target.labels.Add (entry.Key, RemapLabeledStatement (labeled, labeled.Block, clonectx.RemapBlockCopy (labeled.Block)));
+ }
+ }
+
+ break;
+ }
+
+ if (pb.Parent == null)
+ break;
+
+ pb = pb.Parent.ParametersBlock;
}
}
base.Emit (ec);
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ var res = base.DoFlowAnalysis (fc);
+
+ if (HasReachableClosingBrace)
+ CheckControlExit (fc);
+
+ return res;
+ }
+
+ public LabeledStatement GetLabel (string name, Block block)
+ {
+ //
+ // Cloned parameters blocks can have their own cloned version of top-level labels
+ //
+ if (labels == null) {
+ if (Parent != null)
+ return Parent.ParametersBlock.GetLabel (name, block);
+
+ return null;
+ }
+
+ object value;
+ if (!labels.TryGetValue (name, out value)) {
+ return null;
+ }
+
+ var label = value as LabeledStatement;
+ Block b = block;
+ if (label != null) {
+ do {
+ if (label.Block == b)
+ return label;
+ b = b.Parent;
+ } while (b != null);
+ } else {
+ List<LabeledStatement> list = (List<LabeledStatement>) value;
+ for (int i = 0; i < list.Count; ++i) {
+ label = list[i];
+ if (label.Block == b)
+ return label;
+ }
+ }
+
+ return null;
+ }
+
public ParameterInfo GetParameterInfo (Parameter p)
{
for (int i = 0; i < parameters.Count; ++i) {
}
}
- public bool Resolve (FlowBranching parent, BlockContext rc, IMethodData md)
+ static LabeledStatement RemapLabeledStatement (LabeledStatement stmt, Block src, Block dst)
+ {
+ var src_stmts = src.Statements;
+ for (int i = 0; i < src_stmts.Count; ++i) {
+ if (src_stmts[i] == stmt)
+ return (LabeledStatement) dst.Statements[i];
+ }
+
+ throw new InternalErrorException ("Should never be reached");
+ }
+
+ public override bool Resolve (BlockContext bc)
{
+ // TODO: if ((flags & Flags.Resolved) != 0)
+
if (resolved)
return true;
resolved = true;
- if (rc.HasSet (ResolveContext.Options.ExpressionTreeConversion))
+ if (bc.HasSet (ResolveContext.Options.ExpressionTreeConversion))
flags |= Flags.IsExpressionTree;
try {
- PrepareAssignmentAnalysis (rc);
-
- using (rc.With (ResolveContext.Options.DoFlowAnalysis, true)) {
- FlowBranchingToplevel top_level = rc.StartFlowBranching (this, parent);
+ PrepareAssignmentAnalysis (bc);
- if (!Resolve (rc))
- return false;
+ if (!base.Resolve (bc))
+ return false;
- unreachable = top_level.End ();
- }
} catch (Exception e) {
- if (e is CompletionResult || rc.Report.IsDisabled || e is FatalException || rc.Report.Printer is NullReportPrinter)
+ if (e is CompletionResult || bc.Report.IsDisabled || e is FatalException || bc.Report.Printer is NullReportPrinter)
throw;
- if (rc.CurrentBlock != null) {
- rc.Report.Error (584, rc.CurrentBlock.StartLocation, "Internal compiler error: {0}", e.Message);
+ if (bc.CurrentBlock != null) {
+ bc.Report.Error (584, bc.CurrentBlock.StartLocation, "Internal compiler error: {0}", e.Message);
} else {
- rc.Report.Error (587, "Internal compiler error: {0}", e.Message);
+ bc.Report.Error (587, "Internal compiler error: {0}", e.Message);
}
- if (rc.Module.Compiler.Settings.DebugFlags > 0)
+ if (bc.Module.Compiler.Settings.DebugFlags > 0)
throw;
}
- if (rc.ReturnType.Kind != MemberKind.Void && !unreachable) {
- if (rc.CurrentAnonymousMethod == null) {
- // FIXME: Missing FlowAnalysis for generated iterator MoveNext method
- if (md is StateMachineMethod) {
- unreachable = true;
- } else {
- rc.Report.Error (161, md.Location, "`{0}': not all code paths return a value", md.GetSignatureForError ());
- return false;
- }
- } else {
- //
- // If an asynchronous body of F is either an expression classified as nothing, or a
- // statement block where no return statements have expressions, the inferred return type is Task
- //
- if (IsAsync) {
- var am = rc.CurrentAnonymousMethod as AnonymousMethodBody;
- if (am != null && am.ReturnTypeInference != null && !am.ReturnTypeInference.HasBounds (0)) {
- am.ReturnTypeInference = null;
- am.ReturnType = rc.Module.PredefinedTypes.Task.TypeSpec;
- return true;
- }
- }
-
- rc.Report.Error (1643, rc.CurrentAnonymousMethod.Location, "Not all code paths return a value in anonymous method of type `{0}'",
- rc.CurrentAnonymousMethod.GetSignatureForError ());
- return false;
+ //
+ // If an asynchronous body of F is either an expression classified as nothing, or a
+ // statement block where no return statements have expressions, the inferred return type is Task
+ //
+ if (IsAsync) {
+ var am = bc.CurrentAnonymousMethod as AnonymousMethodBody;
+ if (am != null && am.ReturnTypeInference != null && !am.ReturnTypeInference.HasBounds (0)) {
+ am.ReturnTypeInference = null;
+ am.ReturnType = bc.Module.PredefinedTypes.Task.TypeSpec;
+ return true;
}
}
state_machine = stateMachine;
iterator.SetStateMachine (stateMachine);
- var tlb = new ToplevelBlock (host.Compiler, Parameters, Location.Null);
+ var tlb = new ToplevelBlock (host.Compiler, Parameters, Location.Null, Flags.CompilerGenerated);
tlb.Original = this;
- tlb.IsCompilerGenerated = true;
tlb.state_machine = stateMachine;
tlb.AddStatement (new Return (iterator, iterator.Location));
return tlb;
state_machine = stateMachine;
initializer.SetStateMachine (stateMachine);
+ const Flags flags = Flags.CompilerGenerated;
+
var b = this is ToplevelBlock ?
- new ToplevelBlock (host.Compiler, Parameters, Location.Null) :
- new ParametersBlock (Parent, parameters, Location.Null) {
- IsAsync = true,
- };
+ new ToplevelBlock (host.Compiler, Parameters, Location.Null, flags) :
+ new ParametersBlock (Parent, parameters, Location.Null, flags | Flags.HasAsyncModifier);
b.Original = this;
- b.IsCompilerGenerated = true;
b.state_machine = stateMachine;
- b.AddStatement (new StatementExpression (initializer));
+ b.AddStatement (new AsyncInitializerStatement (initializer));
return b;
}
}
LocalVariable this_variable;
CompilerContext compiler;
Dictionary<string, object> names;
- Dictionary<string, object> labels;
List<ExplicitBlock> this_references;
{
}
- public ToplevelBlock (CompilerContext ctx, ParametersCompiled parameters, Location start)
+ public ToplevelBlock (CompilerContext ctx, ParametersCompiled parameters, Location start, Flags flags = 0)
: base (parameters, start)
{
this.compiler = ctx;
+ this.flags = flags;
top_block = this;
- flags |= Flags.HasRet;
ProcessParameters ();
}
{
this.compiler = source.TopBlock.compiler;
top_block = this;
- flags |= Flags.HasRet;
}
public bool IsIterator {
return false;
}
- public LabeledStatement GetLabel (string name, Block block)
- {
- if (labels == null)
- return null;
-
- object value;
- if (!labels.TryGetValue (name, out value)) {
- return null;
- }
-
- var label = value as LabeledStatement;
- Block b = block;
- if (label != null) {
- if (label.Block == b.Original)
- return label;
- } else {
- List<LabeledStatement> list = (List<LabeledStatement>) value;
- for (int i = 0; i < list.Count; ++i) {
- label = list[i];
- if (label.Block == b.Original)
- return label;
- }
- }
-
- return null;
- }
-
// <summary>
// This is used by non-static `struct' constructors which do not have an
// initializer - in this case, the constructor must initialize all of the
this_variable.PrepareAssignmentAnalysis (bc);
}
- public bool IsThisAssigned (BlockContext ec)
+ public override void CheckControlExit (FlowAnalysisContext fc, DefiniteAssignmentBitSet dat)
{
- return this_variable == null || this_variable.IsThisAssigned (ec, this);
+ //
+ // If we're a non-static struct constructor which doesn't have an
+ // initializer, then we must initialize all of the struct's fields.
+ //
+ if (this_variable != null)
+ this_variable.IsThisAssigned (fc, this);
+
+ base.CheckControlExit (fc, dat);
}
public override void Emit (EmitContext ec)
// As a workaround, we're always creating a return label in
// this case.
//
- if (ec.HasReturnLabel || !unreachable) {
+ if (ec.HasReturnLabel || HasReachableClosingBrace) {
if (ec.HasReturnLabel)
ec.MarkLabel (ec.ReturnLabel);
throw new InternalErrorException (e, StartLocation);
}
}
+
+ public bool Resolve (BlockContext bc, IMethodData md)
+ {
+ if (resolved)
+ return true;
+
+ var errors = bc.Report.Errors;
+
+ base.Resolve (bc);
+
+ if (bc.Report.Errors > errors)
+ return false;
+
+ MarkReachable (new Reachability ());
+
+ if (HasReachableClosingBrace && bc.ReturnType.Kind != MemberKind.Void) {
+ // TODO: var md = bc.CurrentMemberDefinition;
+ bc.Report.Error (161, md.Location, "`{0}': not all code paths return a value", md.GetSignatureForError ());
+ }
+
+ if ((flags & Flags.NoFlowAnalysis) != 0)
+ return true;
+
+ var fc = new FlowAnalysisContext (bc.Module.Compiler, this, bc.AssignmentInfoOffset);
+ try {
+ FlowAnalysis (fc);
+ } catch (Exception e) {
+ throw new InternalErrorException (e, StartLocation);
+ }
+
+ return true;
+ }
}
public class SwitchLabel : Statement
{
- Expression label;
Constant converted;
+ Expression label;
Label? il_label;
return converted;
}
set {
- converted = value;
+ converted = value;
}
}
ec.MarkLabel (GetILLabel (ec));
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ if (!SectionStart)
+ return false;
+
+ fc.DefiniteAssignment = new DefiniteAssignmentBitSet (fc.SwitchInitialDefinitiveAssignment);
+ return false;
+ }
+
public override bool Resolve (BlockContext bc)
{
if (ResolveAndReduce (bc))
bc.Switch.RegisterLabel (bc, this);
- bc.CurrentBranching.CurrentUsageVector.ResetBarrier ();
-
- return base.Resolve (bc);
+ return true;
}
//
// Resolves the expression, reduces it to a literal if possible
// and then converts it to the requested type.
//
- bool ResolveAndReduce (ResolveContext rc)
+ bool ResolveAndReduce (BlockContext rc)
{
if (IsDefault)
return true;
public void Error_AlreadyOccurs (ResolveContext ec, SwitchLabel collision_with)
{
- string label;
- if (converted == null)
- label = "default";
- else
- label = converted.GetValueAsLiteral ();
-
ec.Report.SymbolRelatedToPreviousError (collision_with.loc, null);
- ec.Report.Error (152, loc, "The label `case {0}:' already occurs in this switch statement", label);
+ ec.Report.Error (152, loc, "The label `{0}' already occurs in this switch statement", GetSignatureForError ());
}
protected override void CloneTo (CloneContext clonectx, Statement target)
{
return visitor.Visit (this);
}
+
+ public string GetSignatureForError ()
+ {
+ string label;
+ if (converted == null)
+ label = "default";
+ else
+ label = converted.GetValueAsLiteral ();
+
+ return string.Format ("case {0}:", label);
+ }
}
- public class Switch : Statement
+ public class Switch : LoopStatement
{
// structure used to hold blocks of keys while calculating table switch
sealed class LabelsRange : IComparable<LabelsRange>
throw new NotImplementedException ();
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ return false;
+ }
+
protected override void DoEmit (EmitContext ec)
{
body.EmitDispatch (ec);
}
}
+ class MissingBreak : Statement
+ {
+ SwitchLabel label;
+
+ public MissingBreak (SwitchLabel sl)
+ {
+ this.label = sl;
+ this.loc = sl.loc;
+ }
+
+ protected override void DoEmit (EmitContext ec)
+ {
+ }
+
+ protected override void CloneTo (CloneContext clonectx, Statement target)
+ {
+ }
+
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ fc.Report.Error (163, loc, "Control cannot fall through from one case label `{0}' to another",
+ label.GetSignatureForError ());
+
+ return true;
+ }
+ }
+
public Expression Expr;
//
List<SwitchLabel> case_labels;
List<Tuple<GotoCase, Constant>> goto_cases;
+ List<DefiniteAssignmentBitSet> end_reachable_das;
/// <summary>
/// The governing switch type
ExpressionStatement string_dictionary;
FieldExpr switch_cache_field;
ExplicitBlock block;
+ bool end_reachable;
//
// Nullable Types support
Nullable.Unwrap unwrap;
public Switch (Expression e, ExplicitBlock block, Location l)
+ : base (block)
{
Expr = e;
this.block = block;
loc = l;
}
+ public SwitchLabel ActiveLabel { get; set; }
+
public ExplicitBlock Block {
get {
return block;
}
}
+ public List<SwitchLabel> RegisteredLabels {
+ get {
+ return case_labels;
+ }
+ }
+
//
// Determines the governing type for a switch. The returned
// expression might be the expression from the switch, or an
};
}
- public void RegisterLabel (ResolveContext rc, SwitchLabel sl)
+ public void RegisterLabel (BlockContext rc, SwitchLabel sl)
{
case_labels.Add (sl);
}
}
- SwitchLabel FindLabel (Constant value)
+ public SwitchLabel FindLabel (Constant value)
{
SwitchLabel sl = null;
return sl;
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ Expr.FlowAnalysis (fc);
+
+ var prev_switch = fc.SwitchInitialDefinitiveAssignment;
+ var InitialDefinitiveAssignment = fc.DefiniteAssignment;
+ fc.SwitchInitialDefinitiveAssignment = InitialDefinitiveAssignment;
+
+ block.FlowAnalysis (fc);
+
+ fc.SwitchInitialDefinitiveAssignment = prev_switch;
+
+ if (end_reachable_das != null) {
+ var sections_das = DefiniteAssignmentBitSet.And (end_reachable_das);
+ InitialDefinitiveAssignment |= sections_das;
+ end_reachable_das = null;
+ }
+
+ fc.DefiniteAssignment = InitialDefinitiveAssignment;
+
+ return case_default != null && !end_reachable;
+ }
+
public override bool Resolve (BlockContext ec)
{
Expr = Expr.Resolve (ec);
Switch old_switch = ec.Switch;
ec.Switch = this;
- ec.Switch.SwitchType = SwitchType;
+ var parent_los = ec.EnclosingLoopOrSwitch;
+ ec.EnclosingLoopOrSwitch = this;
- ec.StartFlowBranching (FlowBranching.BranchingType.Switch, loc);
-
- ec.CurrentBranching.CurrentUsageVector.Goto ();
-
- var ok = block.Resolve (ec);
-
- if (case_default == null)
- ec.CurrentBranching.CreateSibling (null, FlowBranching.SiblingType.SwitchSection);
-
- if (ec.IsUnreachable)
- ec.KillFlowBranching ();
- else
- ec.EndFlowBranching ();
+ var ok = Statement.Resolve (ec);
+ ec.EnclosingLoopOrSwitch = parent_los;
ec.Switch = old_switch;
//
// Check if all goto cases are valid. Needs to be done after switch
- // is resolved becuase goto can jump forward in the scope.
+ // is resolved because goto can jump forward in the scope.
//
if (goto_cases != null) {
foreach (var gc in goto_cases) {
if (gc.Item1 == null) {
if (DefaultLabel == null) {
- FlowBranchingBlock.Error_UnknownLabel (loc, "default", ec.Report);
+ Goto.Error_UnknownLabel (ec, "default", loc);
}
continue;
var sl = FindLabel (gc.Item2);
if (sl == null) {
- FlowBranchingBlock.Error_UnknownLabel (loc, "case " + gc.Item2.GetValueAsLiteral (), ec.Report);
+ Goto.Error_UnknownLabel (ec, "case " + gc.Item2.GetValueAsLiteral (), loc);
} else {
gc.Item1.Label = sl;
}
}
}
- if (constant != null) {
- ResolveUnreachableSections (ec, constant);
- }
-
if (!ok)
return false;
return true;
}
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ if (rc.IsUnreachable)
+ return rc;
+
+ base.MarkReachable (rc);
+
+ if (block.Statements.Count == 0)
+ return rc;
+
+ SwitchLabel constant_label = null;
+ var constant = new_expr as Constant;
+
+ if (constant != null) {
+ constant_label = FindLabel (constant) ?? case_default;
+ if (constant_label == null) {
+ block.Statements.RemoveAt (0);
+ return rc;
+ }
+ }
+
+ var section_rc = new Reachability ();
+ SwitchLabel prev_label = null;
+
+ for (int i = 0; i < block.Statements.Count; ++i) {
+ var s = block.Statements[i];
+ var sl = s as SwitchLabel;
+
+ if (sl != null && sl.SectionStart) {
+ //
+ // Section is marked already via constant switch or goto case
+ //
+ if (!sl.IsUnreachable) {
+ section_rc = new Reachability ();
+ continue;
+ }
+
+ if (section_rc.IsUnreachable) {
+ section_rc = new Reachability ();
+ } else {
+ if (prev_label != null) {
+ sl.SectionStart = false;
+ s = new MissingBreak (prev_label);
+ s.MarkReachable (rc);
+ block.Statements.Insert (i - 1, s);
+ ++i;
+ }
+ }
+
+ prev_label = sl;
+
+ if (constant_label != null && constant_label != sl)
+ section_rc = Reachability.CreateUnreachable ();
+ }
+
+ section_rc = s.MarkReachable (section_rc);
+ }
+
+ if (!section_rc.IsUnreachable && prev_label != null) {
+ prev_label.SectionStart = false;
+ var s = new MissingBreak (prev_label);
+ s.MarkReachable (rc);
+ block.Statements.Add (s);
+ }
+
+ //
+ // Reachability can affect parent only when all possible paths are handled but
+ // we still need to run reachability check on switch body to check for fall-through
+ //
+ if (case_default == null && constant_label == null)
+ return rc;
+
+ //
+ // We have at least one local exit from the switch
+ //
+ if (end_reachable)
+ return rc;
+
+ return Reachability.CreateUnreachable ();
+ }
+
public void RegisterGotoCase (GotoCase gotoCase, Constant value)
{
if (goto_cases == null)
string_dictionary = new SimpleAssign (switch_cache_field, initializer.Resolve (ec));
}
- void ResolveUnreachableSections (BlockContext bc, Constant value)
- {
- var constant_label = FindLabel (value) ?? case_default;
-
- bool found = false;
- bool unreachable_reported = false;
- for (int i = 0; i < block.Statements.Count; ++i) {
- var s = block.Statements[i];
-
- if (s is SwitchLabel) {
- if (unreachable_reported) {
- found = unreachable_reported = false;
- }
-
- found |= s == constant_label;
- continue;
- }
-
- if (found) {
- unreachable_reported = true;
- continue;
- }
-
- if (!unreachable_reported) {
- unreachable_reported = true;
- if (!bc.IsUnreachable) {
- bc.Report.Warning (162, 2, s.loc, "Unreachable code detected");
- }
- }
-
- block.Statements[i] = new EmptyStatement (s.loc);
- }
- }
-
void DoEmitStringSwitch (EmitContext ec)
{
Label l_initialized = ec.DefineLabel ();
{
if (value == null) {
//
- // Constant switch, we already done the work
+ // Constant switch, we've already done the work if there is only 1 label
+ // referenced
//
+ int reachable = 0;
+ foreach (var sl in case_labels) {
+ if (sl.IsUnreachable)
+ continue;
+
+ if (reachable++ > 0) {
+ var constant = (Constant) new_expr;
+ var constant_label = FindLabel (constant) ?? case_default;
+
+ ec.Emit (OpCodes.Br, constant_label.GetILLabel (ec));
+ break;
+ }
+ }
+
return;
}
protected override void DoEmit (EmitContext ec)
{
- // Workaround broken flow-analysis
- block.HasUnreachableClosingBrace = true;
-
//
// Setup the codegen context
//
Switch target = (Switch) t;
target.Expr = Expr.Clone (clonectx);
- target.block = (ExplicitBlock) block.Clone (clonectx);
+ target.Statement = target.block = (ExplicitBlock) block.Clone (clonectx);
}
public override object Accept (StructuralVisitor visitor)
{
return visitor.Visit (this);
}
+
+ public override void AddEndDefiniteAssignment (FlowAnalysisContext fc)
+ {
+ if (case_default == null)
+ return;
+
+ if (end_reachable_das == null)
+ end_reachable_das = new List<DefiniteAssignmentBitSet> ();
+
+ end_reachable_das.Add (fc.DefiniteAssignment);
+ }
+
+ public override void SetEndReachable ()
+ {
+ end_reachable = true;
+ }
}
- // A place where execution can restart in an iterator
+ // A place where execution can restart in a state machine
public abstract class ResumableStatement : Statement
{
bool prepared;
ec.EndExceptionBlock ();
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ var res = stmt.FlowAnalysis (fc);
+ parent = null;
+ return res;
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ base.MarkReachable (rc);
+ return Statement.MarkReachable (rc);
+ }
+
public override bool Resolve (BlockContext bc)
{
+ bool ok;
+
+ parent = bc.CurrentTryBlock;
+ bc.CurrentTryBlock = this;
+
+ using (bc.Set (ResolveContext.Options.TryScope)) {
+ ok = stmt.Resolve (bc);
+ }
+
+ bc.CurrentTryBlock = parent;
+
//
// Finally block inside iterator is called from MoveNext and
// Dispose methods that means we need to lift the block into
}
}
- return base.Resolve (bc);
+ return base.Resolve (bc) && ok;
}
}
//
public abstract class ExceptionStatement : ResumableStatement
{
-#if !STATIC
- bool code_follows;
-#endif
protected List<ResumableStatement> resume_points;
protected int first_resume_pc;
+ protected ExceptionStatement parent;
protected ExceptionStatement (Location loc)
{
}
}
- public void SomeCodeFollows ()
+ public virtual int AddResumePoint (ResumableStatement stmt, int pc, StateMachineInitializer stateMachine)
{
-#if !STATIC
- code_follows = true;
-#endif
- }
+ if (parent != null) {
+ // TODO: MOVE to virtual TryCatch
+ var tc = this as TryCatch;
+ var s = tc != null && tc.IsTryCatchFinally ? stmt : this;
- public override bool Resolve (BlockContext ec)
- {
-#if !STATIC
- // System.Reflection.Emit automatically emits a 'leave' at the end of a try clause
- // So, ensure there's some IL code after this statement.
- if (!code_follows && resume_points == null && ec.CurrentBranching.CurrentUsageVector.IsUnreachable)
- ec.NeedReturnLabel ();
-#endif
- return true;
- }
+ pc = parent.AddResumePoint (s, pc, stateMachine);
+ } else {
+ pc = stateMachine.AddResumePoint (this);
+ }
- public void AddResumePoint (ResumableStatement stmt, int pc)
- {
if (resume_points == null) {
resume_points = new List<ResumableStatement> ();
first_resume_pc = pc;
throw new InternalErrorException ("missed an intervening AddResumePoint?");
resume_points.Add (stmt);
+ return pc;
}
-
}
public class Lock : TryFinallyBlock
}
using (ec.Set (ResolveContext.Options.LockScope)) {
- ec.StartFlowBranching (this);
- Statement.Resolve (ec);
- ec.EndFlowBranching ();
+ base.Resolve (ec);
}
if (lv != null) {
lv.IsLockedByStatement = locked;
}
- base.Resolve (ec);
-
return true;
}
Block.Emit (ec);
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ return Block.FlowAnalysis (fc);
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ base.MarkReachable (rc);
+ return Block.MarkReachable (rc);
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement t)
{
Unchecked target = (Unchecked) t;
Block.Emit (ec);
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ return Block.FlowAnalysis (fc);
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ base.MarkReachable (rc);
+ return Block.MarkReachable (rc);
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement t)
{
Checked target = (Checked) t;
Block.Emit (ec);
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ return Block.FlowAnalysis (fc);
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ base.MarkReachable (rc);
+ return Block.MarkReachable (rc);
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement t)
{
Unsafe target = (Unsafe) t;
}
public abstract void EmitExit (EmitContext ec);
+
+ public override void FlowAnalysis (FlowAnalysisContext fc)
+ {
+ expr.FlowAnalysis (fc);
+ }
}
class ExpressionEmitter : Emitter {
#endregion
- public override bool Resolve (BlockContext ec)
+ public override bool Resolve (BlockContext bc)
{
- using (ec.Set (ResolveContext.Options.FixedInitializerScope)) {
- if (!decl.Resolve (ec))
+ using (bc.Set (ResolveContext.Options.FixedInitializerScope)) {
+ if (!decl.Resolve (bc))
return false;
}
- ec.StartFlowBranching (FlowBranching.BranchingType.Conditional, loc);
- bool ok = statement.Resolve (ec);
- bool flow_unreachable = ec.EndFlowBranching ();
- has_ret = flow_unreachable;
+ return statement.Resolve (bc);
+ }
- return ok;
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ decl.FlowAnalysis (fc);
+ return statement.FlowAnalysis (fc);
}
protected override void DoEmit (EmitContext ec)
}
}
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ base.MarkReachable (rc);
+
+ decl.MarkReachable (rc);
+
+ rc = statement.MarkReachable (rc);
+
+ // TODO: What if there is local exit?
+ has_ret = rc.IsUnreachable;
+ return rc;
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement t)
{
Fixed target = (Fixed) t;
public class Catch : Statement
{
- Block block;
+ ExplicitBlock block;
LocalVariable li;
FullNamedExpression type_expr;
CompilerAssign assign;
TypeSpec type;
- public Catch (Block block, Location loc)
+ public Catch (ExplicitBlock block, Location loc)
{
this.block = block;
this.loc = loc;
#region Properties
- public Block Block {
+ public ExplicitBlock Block {
get {
return block;
}
public override bool Resolve (BlockContext ec)
{
- using (ec.With (ResolveContext.Options.CatchScope, true)) {
+ using (ec.Set (ResolveContext.Options.CatchScope)) {
if (type_expr != null) {
type = type_expr.ResolveAsType (ec);
if (type == null)
}
}
+ Block.SetCatchBlock ();
return Block.Resolve (ec);
}
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ if (li != null) {
+ fc.SetVariableAssigned (li.VariableInfo, true);
+ }
+
+ return block.FlowAnalysis (fc);
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ base.MarkReachable (rc);
+
+ return block.MarkReachable (rc);
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement t)
{
Catch target = (Catch) t;
if (type_expr != null)
target.type_expr = (FullNamedExpression) type_expr.Clone (clonectx);
- target.block = clonectx.LookupBlock (block);
+ target.block = (ExplicitBlock) clonectx.LookupBlock (block);
}
}
public class TryFinally : TryFinallyBlock
{
- Block fini;
+ ExplicitBlock fini;
+ List<DefiniteAssignmentBitSet> try_exit_dat;
- public TryFinally (Statement stmt, Block fini, Location loc)
+ public TryFinally (Statement stmt, ExplicitBlock fini, Location loc)
: base (stmt, loc)
{
this.fini = fini;
}
- public Block Finallyblock {
+ public ExplicitBlock FinallyBlock {
get {
return fini;
}
}
- public override bool Resolve (BlockContext ec)
+ public void RegisterForControlExitCheck (DefiniteAssignmentBitSet vector)
{
- bool ok = true;
+ if (try_exit_dat == null)
+ try_exit_dat = new List<DefiniteAssignmentBitSet> ();
- ec.StartFlowBranching (this);
-
- if (!stmt.Resolve (ec))
- ok = false;
+ try_exit_dat.Add (vector);
+ }
- if (ok)
- ec.CurrentBranching.CreateSibling (fini, FlowBranching.SiblingType.Finally);
+ public override bool Resolve (BlockContext bc)
+ {
+ bool ok = base.Resolve (bc);
- using (ec.With (ResolveContext.Options.FinallyScope, true)) {
- if (!fini.Resolve (ec))
- ok = false;
+ fini.SetFinallyBlock ();
+ using (bc.Set (ResolveContext.Options.FinallyScope)) {
+ ok &= fini.Resolve (bc);
}
- ec.EndFlowBranching ();
-
- ok &= base.Resolve (ec);
-
return ok;
}
fini.Emit (ec);
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ var da = fc.BranchDefiniteAssignment ();
+
+ var tf = fc.TryFinally;
+ fc.TryFinally = this;
+
+ var res_stmt = Statement.FlowAnalysis (fc);
+
+ fc.TryFinally = tf;
+
+ var try_da = fc.DefiniteAssignment;
+ fc.DefiniteAssignment = da;
+
+ var res_fin = fini.FlowAnalysis (fc);
+
+ if (try_exit_dat != null) {
+ //
+ // try block has global exit but we need to run definite assignment check
+ // for parameter block out parameter after finally block because it's always
+ // executed before exit
+ //
+ foreach (var try_da_part in try_exit_dat)
+ fc.ParametersBlock.CheckControlExit (fc, fc.DefiniteAssignment | try_da_part);
+
+ try_exit_dat = null;
+ }
+
+ fc.DefiniteAssignment |= try_da;
+ return res_stmt | res_fin;
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ //
+ // Mark finally block first for any exit statement in try block
+ // to know whether the code which follows finally is reachable
+ //
+ return fini.MarkReachable (rc) | base.MarkReachable (rc);
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement t)
{
TryFinally target = (TryFinally) t;
target.stmt = stmt.Clone (clonectx);
if (fini != null)
- target.fini = clonectx.LookupBlock (fini);
+ target.fini = (ExplicitBlock) clonectx.LookupBlock (fini);
}
public override object Accept (StructuralVisitor visitor)
}
}
- public override bool Resolve (BlockContext ec)
+ public override bool Resolve (BlockContext bc)
{
- bool ok = true;
+ bool ok;
- ec.StartFlowBranching (this);
+ using (bc.Set (ResolveContext.Options.TryScope)) {
+ parent = bc.CurrentTryBlock;
- if (!Block.Resolve (ec))
- ok = false;
+ if (IsTryCatchFinally) {
+ ok = Block.Resolve (bc);
+ } else {
+ using (bc.Set (ResolveContext.Options.TryWithCatchScope)) {
+ bc.CurrentTryBlock = this;
+ ok = Block.Resolve (bc);
+ bc.CurrentTryBlock = parent;
+ }
+ }
+ }
for (int i = 0; i < clauses.Count; ++i) {
var c = clauses[i];
- ec.CurrentBranching.CreateSibling (c.Block, FlowBranching.SiblingType.Catch);
- if (!c.Resolve (ec)) {
- ok = false;
- continue;
- }
+ ok &= c.Resolve (bc);
TypeSpec resolved_type = c.CatchType;
for (int ii = 0; ii < clauses.Count; ++ii) {
if (resolved_type.BuiltinType != BuiltinTypeSpec.Type.Exception)
continue;
- if (!ec.Module.DeclaringAssembly.WrapNonExceptionThrows)
+ if (!bc.Module.DeclaringAssembly.WrapNonExceptionThrows)
continue;
- if (!ec.Module.PredefinedAttributes.RuntimeCompatibility.IsDefined)
+ if (!bc.Module.PredefinedAttributes.RuntimeCompatibility.IsDefined)
continue;
- ec.Report.Warning (1058, 1, c.loc,
+ bc.Report.Warning (1058, 1, c.loc,
"A previous catch clause already catches all exceptions. All non-exceptions thrown will be wrapped in a `System.Runtime.CompilerServices.RuntimeWrappedException'");
continue;
continue;
if (resolved_type == ct || TypeSpec.IsBaseClass (resolved_type, ct, true)) {
- ec.Report.Error (160, c.loc,
+ bc.Report.Error (160, c.loc,
"A previous catch clause already catches all exceptions of this or a super type `{0}'",
ct.GetSignatureForError ());
ok = false;
}
}
- ec.EndFlowBranching ();
-
- return base.Resolve (ec) && ok;
+ return base.Resolve (bc) && ok;
}
protected sealed override void DoEmit (EmitContext ec)
ec.EndExceptionBlock ();
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ var start_fc = fc.BranchDefiniteAssignment ();
+ var res = Block.FlowAnalysis (fc);
+
+ DefiniteAssignmentBitSet try_fc = res ? null : fc.DefiniteAssignment;
+
+ foreach (var c in clauses) {
+ fc.DefiniteAssignment = new DefiniteAssignmentBitSet (start_fc);
+ if (!c.FlowAnalysis (fc)) {
+ if (try_fc == null)
+ try_fc = fc.DefiniteAssignment;
+ else
+ try_fc &= fc.DefiniteAssignment;
+
+ res = false;
+ }
+ }
+
+ fc.DefiniteAssignment = try_fc ?? start_fc;
+ parent = null;
+ return res;
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ if (rc.IsUnreachable)
+ return rc;
+
+ base.MarkReachable (rc);
+
+ var tc_rc = Block.MarkReachable (rc);
+
+ foreach (var c in clauses)
+ tc_rc &= c.MarkReachable (rc);
+
+ return tc_rc;
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement t)
{
TryCatch target = (TryCatch) t;
decl.EmitDispose (ec);
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ decl.FlowAnalysis (fc);
+ return stmt.FlowAnalysis (fc);
+ }
+
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ decl.MarkReachable (rc);
+ return base.MarkReachable (rc);
+ }
+
public override bool Resolve (BlockContext ec)
{
VariableReference vr;
}
}
- ec.StartFlowBranching (this);
-
- stmt.Resolve (ec);
-
- ec.EndFlowBranching ();
+ base.Resolve (ec);
if (vr != null)
vr.IsLockedByStatement = vr_locked;
- base.Resolve (ec);
-
return true;
}
/// <summary>
/// Implementation of the foreach C# statement
/// </summary>
- public class Foreach : Statement
+ public class Foreach : LoopStatement
{
abstract class IteratorStatement : Statement
{
base.Emit (ec);
}
+
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ throw new NotImplementedException ();
+ }
}
sealed class ArrayForeach : IteratorStatement
for_each.body.AddScopeStatement (new StatementExpression (new CompilerAssign (variable_ref, access, Location.Null), for_each.type.Location));
- bool ok = true;
-
- ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
- ec.CurrentBranching.CreateSibling ();
-
- ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc);
- if (!for_each.body.Resolve (ec))
- ok = false;
- ec.EndFlowBranching ();
-
- // There's no direct control flow from the end of the embedded statement to the end of the loop
- ec.CurrentBranching.CurrentUsageVector.Goto ();
-
- ec.EndFlowBranching ();
-
- return ok;
+ return for_each.body.Resolve (ec);
}
protected override void DoEmit (EmitContext ec)
Expression type;
LocalVariable variable;
Expression expr;
- Statement statement;
Block body;
public Foreach (Expression type, LocalVariable var, Expression expr, Statement stmt, Block body, Location l)
+ : base (stmt)
{
this.type = type;
this.variable = var;
this.expr = expr;
- this.statement = stmt;
this.body = body;
loc = l;
}
get { return expr; }
}
- public Statement Statement {
- get { return statement; }
- }
-
public Expression TypeExpression {
get { return type; }
}
get { return variable; }
}
+ public override Reachability MarkReachable (Reachability rc)
+ {
+ base.MarkReachable (rc);
+
+ body.MarkReachable (rc);
+
+ return rc;
+ }
+
public override bool Resolve (BlockContext ec)
{
expr = expr.Resolve (ec);
return false;
}
- body.AddStatement (statement);
+ body.AddStatement (Statement);
if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.String) {
- statement = new ArrayForeach (this, 1);
+ Statement = new ArrayForeach (this, 1);
} else if (expr.Type is ArrayContainer) {
- statement = new ArrayForeach (this, ((ArrayContainer) expr.Type).Rank);
+ Statement = new ArrayForeach (this, ((ArrayContainer) expr.Type).Rank);
} else {
if (expr.eclass == ExprClass.MethodGroup || expr is AnonymousMethodExpression) {
ec.Report.Error (446, expr.Location, "Foreach statement cannot operate on a `{0}'",
return false;
}
- statement = new CollectionForeach (this, variable, expr);
+ Statement = new CollectionForeach (this, variable, expr);
}
- return statement.Resolve (ec);
+ base.Resolve (ec);
+ return true;
}
protected override void DoEmit (EmitContext ec)
ec.LoopBegin = ec.DefineLabel ();
ec.LoopEnd = ec.DefineLabel ();
- if (!(statement is Block))
+ if (!(Statement is Block))
ec.BeginCompilerScope ();
variable.CreateBuilder (ec);
- statement.Emit (ec);
+ Statement.Emit (ec);
- if (!(statement is Block))
+ if (!(Statement is Block))
ec.EndScope ();
ec.LoopBegin = old_begin;
ec.LoopEnd = old_end;
}
+ protected override bool DoFlowAnalysis (FlowAnalysisContext fc)
+ {
+ expr.FlowAnalysis (fc);
+
+ var da = fc.BranchDefiniteAssignment ();
+ body.FlowAnalysis (fc);
+ fc.DefiniteAssignment = da;
+ return false;
+ }
+
protected override void CloneTo (CloneContext clonectx, Statement t)
{
Foreach target = (Foreach) t;
target.type = type.Clone (clonectx);
target.expr = expr.Clone (clonectx);
target.body = (Block) body.Clone (clonectx);
- target.statement = statement.Clone (clonectx);
+ target.Statement = Statement.Clone (clonectx);
}
public override object Accept (StructuralVisitor visitor)
bool IsPartial { get; }
bool IsComImport { get; }
bool IsTypeForwarder { get; }
+ bool IsCyclicTypeForwarder { get; }
int TypeParametersCount { get; }
TypeParameterSpec[] TypeParameters { get; }
}
}
+ bool ITypeDefinition.IsCyclicTypeForwarder {
+ get {
+ return false;
+ }
+ }
+
public override string Name {
get {
return name;
}
}
+ bool ITypeDefinition.IsCyclicTypeForwarder {
+ get {
+ return false;
+ }
+ }
+
public override string Name {
get {
throw new NotSupportedException ();
--- /dev/null
+using System;
+
+class X
+{
+ public static void Main ()
+ {
+ new C<int> ().Test ();
+ }
+}
+
+class C<T>
+{
+ public void Test ()
+ {
+ dynamic d = null;
+
+ int v;
+ int.TryParse (d, out v);
+
+ int.TryParse (d, out v);
+ }
+}
\ No newline at end of file
--- /dev/null
+class A { }
+class B { }
+
+interface ICharlie<T> { }
+
+class Delta : ICharlie<A>, ICharlie<B>
+{
+ static void Test<U> (ICharlie<U> icu, U u)
+ {
+ }
+
+ public void World<U> (U u, IFoo<U> foo)
+ {
+ }
+
+ public void Test (Foo foo)
+ {
+ World ("Canada", foo);
+ }
+
+ static void Main ()
+ {
+ Test (new Delta (), new A ());
+ Test (new Delta (), new B ());
+ }
+}
+
+public interface IFoo<T>
+{
+}
+
+public class Foo : IFoo<int>, IFoo<string>
+{
+}
return service;
}
+
+ public void test41 ()
+ {
+ int y, x = 3;
+ int z;
+ while (true) {
+ if (x > 3) {
+ y = 3;
+ goto end;
+ } else {
+ z = 3;
+ }
+
+ break;
+ end:
+ z = y;
+ }
+
+ Console.WriteLine (z);
+ }
+
+ public void test42 (int arg)
+ {
+ bool x;
+ for (; ; ) {
+ x = false;
+ if (arg > 0) {
+ x = true;
+ switch (arg) {
+ case 1:
+ case 2:
+ continue;
+ default:
+ break;
+ }
+ break;
+ } else {
+ x = false;
+ break;
+ }
+ }
+
+ Console.WriteLine (x);
+ }
}
+using System;
+
class Foo {
public static int Main ()
{
f ();
return 1;
} catch {
- return 0;
}
+
+ try {
+ f2 ();
+ return 2;
+ } catch (ApplicationException) {
+ }
+
+ return 0;
}
+
static void f ()
{
try {
skip:
;
}
+
+ static void f2 ()
+ {
+ try {
+ goto FinallyExit;
+ } finally {
+ throw new ApplicationException ();
+ }
+ FinallyExit:
+ Console.WriteLine ("Too late");
+ }
}
public class TestCase
{
public static int Main ()
+ {
+ if (Test1 () != 0)
+ return 1;
+
+ if (Test2 () != 0)
+ return 2;
+
+ return 0;
+ }
+
+ static int Test1 ()
{
int i = 0;
{
return 0;
}
+
+ static int Test2 ()
+ {
+ int i = 0;
+
+ while (true) {
+ {
+ goto A;
+ A:
+ i += 3;
+ break;
+ }
+ }
+
+ if (i != 3)
+ return 1;
+
+ return 0;
+ }
+
+ static int Test3 ()
+ {
+ int i = 0;
+
+ do {
+ {
+ goto A;
+ A:
+ i += 3;
+ goto X;
+ X:
+ break;
+ }
+#pragma warning disable 162, 429
+ } while (i > 0);
+#pragma warning restore 162, 429
+
+ if (i != 3)
+ return 1;
+
+ return 0;
+ }
}
--- /dev/null
+using System;
+
+class X
+{
+ public static void Main ()
+ {
+ int x = 1;
+ switch (x) {
+ case 1:
+ try {
+ goto case 6;
+ } catch {
+ }
+ break;
+ case 6:
+ try {
+ goto default;
+ } catch {
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+
+class X
+{
+ public static void Main ()
+ {
+ int a;
+ goto X;
+ A:
+ Console.WriteLine (a);
+ goto Y;
+ X:
+ a = 1;
+ goto A;
+ Y:
+ return;
+ }
+}
\ No newline at end of file
--- /dev/null
+.assembly extern mscorlib
+{
+}
+
+.assembly extern 'test-875-lib-missing'
+{
+}
+
+.assembly 'test-875-2-lib'
+{
+ .hash algorithm 0x00008004
+ .ver 0:0:0:0
+}
+
+.module 'test-875-2-lib'
+
+.class extern forwarder N.Lib
+{
+ .assembly extern 'test-875-lib-missing'
+}
+
--- /dev/null
+// Compiler options: -t:library
+
+namespace N
+{
+ public class Lib
+ {
+ }
+}
--- /dev/null
+// Compiler options: -r:test-875-lib.dll -r:test-875-2-lib.dll
+
+using N;
+
+public class Test: Lib
+{
+ public static void Main ()
+ {
+ new Test ();
+ }
+}
--- /dev/null
+using System;
+
+class T
+{
+ public static int Main ()
+ {
+ Test1 ();
+ Test2 ();
+ Test3 (0, 1);
+ Test4 ();
+ Test5 ();
+
+ switch (1) {
+ case 1:
+ return 0;
+ default:
+ break;
+ }
+ }
+
+ static void Test1 ()
+ {
+ int g = 9;
+ A:
+ switch (g) {
+ case 4:
+ return;
+ case 5:
+ goto A;
+ }
+
+ switch (g) {
+ case 9:
+ break;
+ }
+
+ return;
+ }
+
+ static void Test2 ()
+ {
+ int a,b;
+ int g = 9;
+ if (g > 0) {
+ a = 1;
+ goto X;
+ } else {
+ b = 2;
+ goto Y;
+ }
+
+ X:
+ Console.WriteLine (a);
+ return;
+ Y:
+ Console.WriteLine (b);
+ return;
+ }
+
+ static uint Test3 (int self, uint data)
+ {
+ uint rid;
+ switch (self) {
+ case 0:
+ rid = 2;
+ switch (data & 3) {
+ case 0:
+ goto ret;
+ default:
+ goto exit;
+ }
+ default:
+ goto exit;
+ }
+ ret:
+ return rid;
+ exit:
+ return 0;
+ }
+
+ static void Test4 ()
+ {
+ bool v;
+ try {
+ throw new NotImplementedException ();
+ } catch (System.Exception) {
+ v = false;
+ }
+
+ Console.WriteLine (v);
+ }
+
+ static void Test5 ()
+ {
+ int i = 8;
+ switch (10) {
+ case 5:
+ if (i != 10)
+ throw new ApplicationException ();
+
+ Console.WriteLine (5);
+ break;
+ case 10:
+ i = 10;
+ Console.WriteLine (10);
+ goto default;
+ default:
+ Console.WriteLine ("default");
+ goto case 5;
+ }
+ }
+}
--- /dev/null
+using System;
+
+struct S
+{
+ string value;
+
+ public S (int arg)
+ {
+ throw new ApplicationException ();
+ }
+}
+
+public class A
+{
+ public static void Main ()
+ {
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+
+public class Tests
+{
+ public static int Main ()
+ {
+ return 0;
+ }
+
+ void Test1 ()
+ {
+ int a;
+ if (true) {
+ a = 0;
+ } else {
+ a = 1;
+ }
+
+ Console.WriteLine (a);
+ }
+
+ void Test2 ()
+ {
+ int a;
+ if (false) {
+ a = 0;
+ } else {
+ a = 1;
+ }
+
+ Console.WriteLine (a);
+ }
+}
+
--- /dev/null
+struct AStruct
+{
+ public object foo;
+
+ public AStruct (int i)
+ : this ()
+ {
+ }
+}
+
+public class Tests
+{
+ public static int Main ()
+ {
+ for (int i = 0; i < 100; ++i) {
+ AStruct a;
+
+ a = new AStruct (5);
+ if (a.foo != null)
+ return 1;
+
+ a.foo = i + 1;
+ }
+
+ System.Console.WriteLine ("ok");
+ return 0;
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+
+public class A
+{
+ public static void Main ()
+ {
+ }
+
+ static void Test1 ()
+ {
+ int a;
+ bool r = false;
+
+ if (r && (a = 1) > 0 && r) {
+ System.Console.WriteLine (a);
+ }
+ }
+
+ static void Test2 ()
+ {
+ int a;
+ var res = (a = 1) > 0 || Call (a);
+ }
+
+ static void Test3 ()
+ {
+ int a;
+ if ((a = 1) > 0 || Call (a))
+ return;
+ }
+
+ static void Test4 ()
+ {
+ int version1;
+ bool r = false;
+ if (r || !OutCall (out version1) || version1 == 0 || version1 == -1)
+ {
+ throw new ArgumentException();
+ }
+ }
+
+ static void Test5 ()
+ {
+ bool r = false;
+ int t1;
+ if (Foo (r ? Call (1) : Call (4), OutCall (out t1)))
+ Console.WriteLine (t1);
+ }
+
+ static void Test6 ()
+ {
+ int b = 0;
+ var res = b != 0 && b.ToString () != null;
+ }
+
+ static bool Test7 ()
+ {
+ int f = 1;
+ int g;
+ return f > 1 && OutCall (out g) && g > 1;
+ }
+
+ static bool OutCall (out int arg)
+ {
+ arg = 1;
+ return false;
+ }
+
+ static bool Call (int arg)
+ {
+ return false;
+ }
+
+ static bool Foo (params object[] arg)
+ {
+ return false;
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+
+namespace A
+{
+ class XAttribute : Attribute { }
+}
+
+namespace B
+{
+ class XAttribute : Attribute { }
+}
+
+namespace C
+{
+ using A;
+ using B;
+ using X = A.XAttribute;
+
+ [X]
+ class Test
+ {
+ public static void Main ()
+ {
+ }
+ }
+}
--- /dev/null
+using System;
+
+public class MyUInt32
+{
+ public uint x;
+
+ public MyUInt32 (uint x)
+ {
+ this.x = x;
+ }
+
+ public static implicit operator uint (MyUInt32 v)
+ {
+ return v.x;
+ }
+
+ public static implicit operator long (MyUInt32 v)
+ {
+ throw new ApplicationException ();
+ }
+
+ public static implicit operator MyUInt32 (uint v)
+ {
+ return new MyUInt32 (v);
+ }
+
+ public static implicit operator MyUInt32 (long v)
+ {
+ throw new ApplicationException ();
+ }
+}
+
+class Test
+{
+ static MyUInt32 test1 (MyUInt32 x)
+ {
+ x = x + 1;
+ return x;
+ }
+
+ static MyUInt32 test2 (MyUInt32 x)
+ {
+ x++;
+ return x;
+ }
+
+ static MyUInt32 test3 (MyUInt32 x)
+ {
+ ++x;
+ return x;
+ }
+
+ public static int Main ()
+ {
+ var m = new MyUInt32 (2);
+ m = test1 (m);
+ if (m.x != 3)
+ return 1;
+
+ m = new MyUInt32 (2);
+ m = test2 (m);
+ if (m.x != 3)
+ return 2;
+
+ m = new MyUInt32 (3);
+ m = test3 (m);
+ if (m.x != 4)
+ return 3;
+
+ return 0;
+ }
+}
\ No newline at end of file
{
public void M ()
{
- Console.WriteLine ("called");
}
}
--- /dev/null
+using System;
+
+class Y
+{
+}
+
+class X
+{
+ public event Action<int, string> E;
+
+ void Foo ()
+ {
+ var nc = new Y ();
+
+ E += async (arg1, arg2) => {
+ nc = null;
+ };
+
+ E (1, "h");
+ }
+
+ public static void Main ()
+ {
+ var x = new X ();
+ x.Foo ();
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+class Test
+{
+ public static int Main ()
+ {
+ int res;
+ res = TestMethod (new TaskCanceledException ()).Result;
+ if (res != 0)
+ return 10 * res;
+
+ res = TestMethod (new OperationCanceledException ("my message")).Result;
+ if (res != 0)
+ return 20 * res;
+
+ return 0;
+ }
+
+ async static Task<int> TestMethod (Exception ex)
+ {
+ try {
+ await Foo (ex);
+ } catch (OperationCanceledException e) {
+ if (e == ex)
+ return 0;
+
+ return 1;
+ }
+
+ return 2;
+ }
+
+
+ async static Task Foo (Exception e)
+ {
+ await Task.Delay (1);
+ throw e;
+ }
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0"?>
+<doc>
+ <assembly>
+ <name>test-xml-068</name>
+ </assembly>
+ <members>
+ <member name="M:X.Test">
+ <summary>
+ Test summary
+ </summary>
+ <see cref="!:#sometext" />
+ </member>
+ </members>
+</doc>
--- /dev/null
+// Compiler options: -doc:xml-068.xml
+
+class X
+{
+ /// <summary>
+ /// Test summary
+ /// </summary>
+ /// <see cref="#sometext"/>
+ static void Test ()
+ {
+ }
+
+ public static void Main ()
+ {
+ }
+}
\ No newline at end of file
<size>26</size>\r
</method>\r
<method name="Void .ctor(Int32)" attrs="6278">\r
- <size>9</size>\r
+ <size>16</size>\r
</method>\r
</type>\r
<type name="MyTypeExplicit">\r
</method>\r
</type>\r
</test>\r
+ <test name="dtest-059.cs">\r
+ <type name="X">\r
+ <method name="Void Main()" attrs="150">\r
+ <size>12</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ <type name="C`1[T]">\r
+ <method name="Void Test()" attrs="134">\r
+ <size>238</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ <type name="C`1+<Test>c__DynamicSite0+Container0[T]">\r
+ <method name="Void Invoke(System.Runtime.CompilerServices.CallSite, System.Type, System.Object, Int32 ByRef)" attrs="454">\r
+ <size>0</size>\r
+ </method>\r
+ <method name="Void .ctor(Object, IntPtr)" attrs="6278">\r
+ <size>0</size>\r
+ </method>\r
+ </type>\r
+ <type name="C`1+<Test>c__DynamicSite0+Container1[T]">\r
+ <method name="Void Invoke(System.Runtime.CompilerServices.CallSite, System.Type, System.Object, Int32 ByRef)" attrs="454">\r
+ <size>0</size>\r
+ </method>\r
+ <method name="Void .ctor(Object, IntPtr)" attrs="6278">\r
+ <size>0</size>\r
+ </method>\r
+ </type>\r
+ </test>\r
<test name="dtest-anontype-01.cs">\r
<type name="C">\r
<method name="Void Main()" attrs="150">\r
</method>\r
</type>\r
</test>\r
+ <test name="gtest-600.cs">\r
+ <type name="A">\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ <type name="B">\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ <type name="Delta">\r
+ <method name="Void Test[U](ICharlie`1[U], U)" attrs="145">\r
+ <size>2</size>\r
+ </method>\r
+ <method name="Void World[U](U, IFoo`1[U])" attrs="134">\r
+ <size>2</size>\r
+ </method>\r
+ <method name="Void Test(Foo)" attrs="134">\r
+ <size>14</size>\r
+ </method>\r
+ <method name="Void Main()" attrs="145">\r
+ <size>32</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ <type name="Foo">\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ </test>\r
<test name="gtest-anontype-01.cs">\r
<type name="Test">\r
<method name="Int32 Main()" attrs="150">\r
<size>8</size>\r
</method>\r
<method name="Void .ctor(Object)" attrs="6278">\r
- <size>9</size>\r
+ <size>16</size>\r
</method>\r
</type>\r
<type name="C">\r
<size>26</size>\r
</method>\r
<method name="Void .ctor(Int32)" attrs="6278">\r
- <size>9</size>\r
+ <size>16</size>\r
</method>\r
</type>\r
<type name="MyTypeExplicit">\r
<size>10</size>\r
</method>\r
<method name="Int32 test40(Int32)" attrs="145">\r
- <size>27</size>\r
+ <size>20</size>\r
</method>\r
<method name="Void .ctor()" attrs="6278">\r
<size>7</size>\r
</method>\r
+ <method name="Void test41()" attrs="134">\r
+ <size>44</size>\r
+ </method>\r
+ <method name="Void test42(Int32)" attrs="134">\r
+ <size>73</size>\r
+ </method>\r
</type>\r
</test>\r
<test name="test-155.cs">\r
<test name="test-519.cs">\r
<type name="Foo">\r
<method name="Int32 Main()" attrs="150">\r
- <size>25</size>\r
+ <size>52</size>\r
</method>\r
<method name="Void f()" attrs="145">\r
- <size>21</size>\r
+ <size>23</size>\r
</method>\r
<method name="Void .ctor()" attrs="6278">\r
<size>7</size>\r
</method>\r
+ <method name="Void f2()" attrs="145">\r
+ <size>16</size>\r
+ </method>\r
</type>\r
</test>\r
<test name="test-52.cs">\r
<test name="test-545.cs">\r
<type name="Dingus">\r
<method name="Void .ctor(Int32)" attrs="6278">\r
- <size>2</size>\r
+ <size>9</size>\r
</method>\r
</type>\r
<type name="X">\r
<test name="test-579.cs">\r
<type name="TestCase">\r
<method name="Int32 Main()" attrs="150">\r
- <size>49</size>\r
+ <size>44</size>\r
</method>\r
<method name="Void .ctor()" attrs="6278">\r
<size>7</size>\r
</method>\r
+ <method name="Int32 Test1()" attrs="145">\r
+ <size>49</size>\r
+ </method>\r
+ <method name="Int32 Test2()" attrs="145">\r
+ <size>48</size>\r
+ </method>\r
+ <method name="Int32 Test3()" attrs="145">\r
+ <size>47</size>\r
+ </method>\r
</type>\r
</test>\r
<test name="test-58.cs">\r
<test name="test-634.cs">\r
<type name="Test">\r
<method name="Void TestFunc()" attrs="150">\r
- <size>7</size>\r
+ <size>13</size>\r
</method>\r
<method name="Void Main(System.String[])" attrs="150">\r
<size>7</size>\r
<size>0</size>\r
</method>\r
</type>\r
+ <type name="Test+<TestFunc>c__AnonStorey0">\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
</test>\r
<test name="test-635.cs">\r
<type name="ShortCircuitFold">\r
</method>\r
</type>\r
</test>\r
+ <test name="test-872.cs">\r
+ <type name="X">\r
+ <method name="Void Main()" attrs="150">\r
+ <size>66</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ </test>\r
<test name="test-873.cs">\r
<type name="Program">\r
<method name="Int32 Main()" attrs="145">\r
</method>\r
</type>\r
</test>\r
+ <test name="test-874.cs">\r
+ <type name="X">\r
+ <method name="Void Main()" attrs="150">\r
+ <size>30</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ </test>\r
+ <test name="test-875.cs">\r
+ <type name="Test">\r
+ <method name="Void Main()" attrs="150">\r
+ <size>8</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ </test>\r
+ <test name="test-876.cs">\r
+ <type name="T">\r
+ <method name="Int32 Main()" attrs="150">\r
+ <size>39</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ <method name="Void Test1()" attrs="145">\r
+ <size>57</size>\r
+ </method>\r
+ <method name="Void Test2()" attrs="145">\r
+ <size>50</size>\r
+ </method>\r
+ <method name="UInt32 Test3(Int32, UInt32)" attrs="145">\r
+ <size>60</size>\r
+ </method>\r
+ <method name="Void Test4()" attrs="145">\r
+ <size>25</size>\r
+ </method>\r
+ <method name="Void Test5()" attrs="145">\r
+ <size>65</size>\r
+ </method>\r
+ </type>\r
+ </test>\r
+ <test name="test-877.cs">\r
+ <type name="S">\r
+ <method name="Void .ctor(Int32)" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ <type name="A">\r
+ <method name="Void Main()" attrs="150">\r
+ <size>2</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ </test>\r
+ <test name="test-878.cs">\r
+ <type name="Tests">\r
+ <method name="Int32 Main()" attrs="150">\r
+ <size>10</size>\r
+ </method>\r
+ <method name="Void Test1()" attrs="129">\r
+ <size>12</size>\r
+ </method>\r
+ <method name="Void Test2()" attrs="129">\r
+ <size>12</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ </test>\r
+ <test name="test-879.cs">\r
+ <type name="AStruct">\r
+ <method name="Void .ctor(Int32)" attrs="6278">\r
+ <size>9</size>\r
+ </method>\r
+ </type>\r
+ <type name="Tests">\r
+ <method name="Int32 Main()" attrs="150">\r
+ <size>83</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ </test>\r
<test name="test-88.cs">\r
<type name="X">\r
<method name="Void f(System.String)" attrs="145">\r
</method>\r
</type>\r
</test>\r
+ <test name="test-880.cs">\r
+ <type name="A">\r
+ <method name="Void Main()" attrs="150">\r
+ <size>2</size>\r
+ </method>\r
+ <method name="Void Test1()" attrs="145">\r
+ <size>33</size>\r
+ </method>\r
+ <method name="Void Test2()" attrs="145">\r
+ <size>21</size>\r
+ </method>\r
+ <method name="Void Test3()" attrs="145">\r
+ <size>27</size>\r
+ </method>\r
+ <method name="Void Test4()" attrs="145">\r
+ <size>42</size>\r
+ </method>\r
+ <method name="Void Test5()" attrs="145">\r
+ <size>72</size>\r
+ </method>\r
+ <method name="Void Test6()" attrs="145">\r
+ <size>33</size>\r
+ </method>\r
+ <method name="Boolean Test7()" attrs="145">\r
+ <size>37</size>\r
+ </method>\r
+ <method name="Boolean OutCall(Int32 ByRef)" attrs="145">\r
+ <size>13</size>\r
+ </method>\r
+ <method name="Boolean Call(Int32)" attrs="145">\r
+ <size>10</size>\r
+ </method>\r
+ <method name="Boolean Foo(System.Object[])" attrs="145">\r
+ <size>10</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ </test>\r
+ <test name="test-881.cs">\r
+ <type name="A.XAttribute">\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ <type name="B.XAttribute">\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ <type name="C.Test">\r
+ <method name="Void Main()" attrs="150">\r
+ <size>2</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ </test>\r
+ <test name="test-882.cs">\r
+ <type name="MyUInt32">\r
+ <method name="UInt32 op_Implicit(MyUInt32)" attrs="2198">\r
+ <size>15</size>\r
+ </method>\r
+ <method name="Int64 op_Implicit(MyUInt32)" attrs="2198">\r
+ <size>7</size>\r
+ </method>\r
+ <method name="MyUInt32 op_Implicit(UInt32)" attrs="2198">\r
+ <size>15</size>\r
+ </method>\r
+ <method name="MyUInt32 op_Implicit(Int64)" attrs="2198">\r
+ <size>7</size>\r
+ </method>\r
+ <method name="Void .ctor(UInt32)" attrs="6278">\r
+ <size>15</size>\r
+ </method>\r
+ </type>\r
+ <type name="Test">\r
+ <method name="MyUInt32 test1(MyUInt32)" attrs="145">\r
+ <size>25</size>\r
+ </method>\r
+ <method name="MyUInt32 test2(MyUInt32)" attrs="145">\r
+ <size>25</size>\r
+ </method>\r
+ <method name="MyUInt32 test3(MyUInt32)" attrs="145">\r
+ <size>25</size>\r
+ </method>\r
+ <method name="Int32 Main()" attrs="150">\r
+ <size>109</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ </test>\r
<test name="test-89.cs">\r
<type name="X">\r
<method name="X F(Int32)" attrs="145">\r
</type>\r
<type name="Program+<Main>c__AnonStorey1+<Main>c__async0">\r
<method name="Void MoveNext()" attrs="486">\r
- <size>226</size>\r
+ <size>225</size>\r
</method>\r
</type>\r
<type name="Program+<Main>c__AnonStorey1+<Main>c__async2">\r
<method name="Void MoveNext()" attrs="486">\r
- <size>226</size>\r
+ <size>225</size>\r
</method>\r
</type>\r
<type name="Program+<Main>c__AnonStorey1+<Main>c__async3">\r
</type>\r
<type name="AsyncTypeInference+<Main>c__async8">\r
<method name="Void MoveNext()" attrs="486">\r
- <size>157</size>\r
+ <size>156</size>\r
</method>\r
</type>\r
<type name="AsyncTypeInference+<Main>c__asyncB">\r
<method name="Void MoveNext()" attrs="486">\r
- <size>38</size>\r
+ <size>37</size>\r
</method>\r
</type>\r
<type name="AsyncTypeInference+<Main>c__async2">\r
<size>9</size>\r
</method>\r
<method name="Void .ctor(Int32, String)" attrs="6278">\r
- <size>9</size>\r
+ <size>16</size>\r
</method>\r
</type>\r
<type name="Tester">\r
</type>\r
<type name="Program+C">\r
<method name="Void M()" attrs="134">\r
- <size>12</size>\r
+ <size>2</size>\r
</method>\r
<method name="Void .ctor()" attrs="6278">\r
<size>7</size>\r
</type>\r
<type name="Program+<Main>c__async1">\r
<method name="Void MoveNext()" attrs="486">\r
- <size>197</size>\r
+ <size>196</size>\r
</method>\r
<method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">\r
<size>13</size>\r
</type>\r
<type name="C+<Foo>c__async3">\r
<method name="Void MoveNext()" attrs="486">\r
- <size>169</size>\r
+ <size>168</size>\r
</method>\r
<method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">\r
<size>13</size>\r
</type>\r
<type name="C+<Foo>c__async0+<Foo>c__AnonStorey4+<Foo>c__async3">\r
<method name="Void MoveNext()" attrs="486">\r
- <size>185</size>\r
+ <size>184</size>\r
</method>\r
<method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">\r
<size>13</size>\r
</type>\r
<type name="C+<Foo>c__async0+<Foo>c__AnonStorey4+<Foo>c__async3">\r
<method name="Void MoveNext()" attrs="486">\r
- <size>214</size>\r
+ <size>213</size>\r
</method>\r
<method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">\r
<size>13</size>\r
</type>\r
<type name="C+<Test>c__async0">\r
<method name="Void MoveNext()" attrs="486">\r
- <size>61</size>\r
+ <size>60</size>\r
</method>\r
<method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">\r
<size>13</size>\r
</method>\r
</type>\r
</test>\r
+ <test name="test-async-53.cs">\r
+ <type name="Y">\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ <type name="X">\r
+ <method name="Void add_E(System.Action`2[System.Int32,System.String])" attrs="2182">\r
+ <size>42</size>\r
+ </method>\r
+ <method name="Void remove_E(System.Action`2[System.Int32,System.String])" attrs="2182">\r
+ <size>42</size>\r
+ </method>\r
+ <method name="Void Foo()" attrs="129">\r
+ <size>54</size>\r
+ </method>\r
+ <method name="Void Main()" attrs="150">\r
+ <size>14</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ <type name="X+<Foo>c__AnonStorey1">\r
+ <method name="Void <>m__0(Int32, System.String)" attrs="131">\r
+ <size>35</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ <type name="X+<Foo>c__AnonStorey1+<Foo>c__async0">\r
+ <method name="Void MoveNext()" attrs="486">\r
+ <size>43</size>\r
+ </method>\r
+ <method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">\r
+ <size>13</size>\r
+ </method>\r
+ </type>\r
+ </test>\r
+ <test name="test-async-54.cs">\r
+ <type name="Test">\r
+ <method name="Int32 Main()" attrs="150">\r
+ <size>79</size>\r
+ </method>\r
+ <method name="System.Threading.Tasks.Task`1[System.Int32] TestMethod(System.Exception)" attrs="145">\r
+ <size>41</size>\r
+ </method>\r
+ <method name="System.Threading.Tasks.Task Foo(System.Exception)" attrs="145">\r
+ <size>41</size>\r
+ </method>\r
+ <method name="Void .ctor()" attrs="6278">\r
+ <size>7</size>\r
+ </method>\r
+ </type>\r
+ <type name="Test+<TestMethod>c__async0">\r
+ <method name="Void MoveNext()" attrs="486">\r
+ <size>226</size>\r
+ </method>\r
+ <method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">\r
+ <size>13</size>\r
+ </method>\r
+ </type>\r
+ <type name="Test+<Foo>c__async1">\r
+ <method name="Void MoveNext()" attrs="486">\r
+ <size>159</size>\r
+ </method>\r
+ <method name="Void SetStateMachine(IAsyncStateMachine)" attrs="486">\r
+ <size>13</size>\r
+ </method>\r
+ </type>\r
+ </test>\r
<test name="test-cls-00.cs">\r
<type name="CLSCLass_6">\r
<method name="Void add_Disposed(Delegate)" attrs="2182">\r
public static VariableDefinition GetVariable (MethodBody body, int index)
{
- return body.Variables [index];
+ // bug 15727 - newer cecil does the same (in MethodDefinition.GetVariable)
+ var variables = body.Variables;
+ if (index < 0 || index >= variables.Count)
+ return null;
+ return variables [index];
}
void ReadCilBody (MethodBody body, BinaryReader br)
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>10.0.0</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{7B3D8F99-304A-4C2E-BAC5-7D1A29747B01}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <RootNamespace>cilstrip</RootNamespace>
+ <AssemblyName>cil-strip</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug</OutputPath>
+ <DefineConstants>DEBUG;</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ <Commandlineparameters>/Users/sebastienpouliot/Dropbox/iCatalogXniOS.exe /Users/sebastienpouliot/Dropbox/iCatalogXniOS-out.exe</Commandlineparameters>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>full</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <Externalconsole>true</Externalconsole>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <ItemGroup>
+ <Folder Include="cil-strip\" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="AssemblyStripper.cs">
+ <Link>cil-strip\AssemblyStripper.cs</Link>
+ </Compile>
+ <Compile Include="cilstrip.cs">
+ <Link>cil-strip\cilstrip.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\AggressiveReflectionReader.cs">
+ <Link>cil-strip\Mono.Cecil\AggressiveReflectionReader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ArrayDimension.cs">
+ <Link>cil-strip\Mono.Cecil\ArrayDimension.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ArrayDimensionCollection.cs">
+ <Link>cil-strip\Mono.Cecil\ArrayDimensionCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ArrayType.cs">
+ <Link>cil-strip\Mono.Cecil\ArrayType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\AssemblyDefinition.cs">
+ <Link>cil-strip\Mono.Cecil\AssemblyDefinition.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\AssemblyFactory.cs">
+ <Link>cil-strip\Mono.Cecil\AssemblyFactory.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\AssemblyFlags.cs">
+ <Link>cil-strip\Mono.Cecil\AssemblyFlags.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\AssemblyHashAlgorithm.cs">
+ <Link>cil-strip\Mono.Cecil\AssemblyHashAlgorithm.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\AssemblyInfo.cs">
+ <Link>cil-strip\Mono.Cecil\AssemblyInfo.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\AssemblyKind.cs">
+ <Link>cil-strip\Mono.Cecil\AssemblyKind.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\AssemblyLinkedResource.cs">
+ <Link>cil-strip\Mono.Cecil\AssemblyLinkedResource.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\AssemblyNameDefinition.cs">
+ <Link>cil-strip\Mono.Cecil\AssemblyNameDefinition.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\AssemblyNameReference.cs">
+ <Link>cil-strip\Mono.Cecil\AssemblyNameReference.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\AssemblyNameReferenceCollection.cs">
+ <Link>cil-strip\Mono.Cecil\AssemblyNameReferenceCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\BaseAssemblyResolver.cs">
+ <Link>cil-strip\Mono.Cecil\BaseAssemblyResolver.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\BaseReflectionReader.cs">
+ <Link>cil-strip\Mono.Cecil\BaseReflectionReader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\BaseReflectionVisitor.cs">
+ <Link>cil-strip\Mono.Cecil\BaseReflectionVisitor.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\BaseStructureVisitor.cs">
+ <Link>cil-strip\Mono.Cecil\BaseStructureVisitor.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\CallSite.cs">
+ <Link>cil-strip\Mono.Cecil\CallSite.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\CompactFrameworkCompatibility.cs">
+ <Link>cil-strip\Mono.Cecil\CompactFrameworkCompatibility.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\Constants.cs">
+ <Link>cil-strip\Mono.Cecil\Constants.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ConstraintCollection.cs">
+ <Link>cil-strip\Mono.Cecil\ConstraintCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ConstructorCollection.cs">
+ <Link>cil-strip\Mono.Cecil\ConstructorCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\CustomAttribute.cs">
+ <Link>cil-strip\Mono.Cecil\CustomAttribute.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\CustomAttributeCollection.cs">
+ <Link>cil-strip\Mono.Cecil\CustomAttributeCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\DefaultAssemblyResolver.cs">
+ <Link>cil-strip\Mono.Cecil\DefaultAssemblyResolver.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\DefaultImporter.cs">
+ <Link>cil-strip\Mono.Cecil\DefaultImporter.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\EmbeddedResource.cs">
+ <Link>cil-strip\Mono.Cecil\EmbeddedResource.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\EventAttributes.cs">
+ <Link>cil-strip\Mono.Cecil\EventAttributes.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\EventDefinition.cs">
+ <Link>cil-strip\Mono.Cecil\EventDefinition.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\EventDefinitionCollection.cs">
+ <Link>cil-strip\Mono.Cecil\EventDefinitionCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\EventReference.cs">
+ <Link>cil-strip\Mono.Cecil\EventReference.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ExternTypeCollection.cs">
+ <Link>cil-strip\Mono.Cecil\ExternTypeCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\FieldAttributes.cs">
+ <Link>cil-strip\Mono.Cecil\FieldAttributes.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\FieldDefinition.cs">
+ <Link>cil-strip\Mono.Cecil\FieldDefinition.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\FieldDefinitionCollection.cs">
+ <Link>cil-strip\Mono.Cecil\FieldDefinitionCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\FieldReference.cs">
+ <Link>cil-strip\Mono.Cecil\FieldReference.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\FileAttributes.cs">
+ <Link>cil-strip\Mono.Cecil\FileAttributes.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\FunctionPointerType.cs">
+ <Link>cil-strip\Mono.Cecil\FunctionPointerType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\GenericArgumentCollection.cs">
+ <Link>cil-strip\Mono.Cecil\GenericArgumentCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\GenericContext.cs">
+ <Link>cil-strip\Mono.Cecil\GenericContext.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\GenericInstanceMethod.cs">
+ <Link>cil-strip\Mono.Cecil\GenericInstanceMethod.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\GenericInstanceType.cs">
+ <Link>cil-strip\Mono.Cecil\GenericInstanceType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\GenericParameter.cs">
+ <Link>cil-strip\Mono.Cecil\GenericParameter.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\GenericParameterAttributes.cs">
+ <Link>cil-strip\Mono.Cecil\GenericParameterAttributes.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\GenericParameterCollection.cs">
+ <Link>cil-strip\Mono.Cecil\GenericParameterCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\HashCodeProvider.cs">
+ <Link>cil-strip\Mono.Cecil\HashCodeProvider.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\IAnnotationProvider.cs">
+ <Link>cil-strip\Mono.Cecil\IAnnotationProvider.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\IAssemblyResolver.cs">
+ <Link>cil-strip\Mono.Cecil\IAssemblyResolver.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ICustomAttributeProvider.cs">
+ <Link>cil-strip\Mono.Cecil\ICustomAttributeProvider.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\IDetailReader.cs">
+ <Link>cil-strip\Mono.Cecil\IDetailReader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\IGenericInstance.cs">
+ <Link>cil-strip\Mono.Cecil\IGenericInstance.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\IGenericParameterProvider.cs">
+ <Link>cil-strip\Mono.Cecil\IGenericParameterProvider.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\IHasConstant.cs">
+ <Link>cil-strip\Mono.Cecil\IHasConstant.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\IHasMarshalSpec.cs">
+ <Link>cil-strip\Mono.Cecil\IHasMarshalSpec.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\IHasSecurity.cs">
+ <Link>cil-strip\Mono.Cecil\IHasSecurity.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\IImporter.cs">
+ <Link>cil-strip\Mono.Cecil\IImporter.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\IMemberDefinition.cs">
+ <Link>cil-strip\Mono.Cecil\IMemberDefinition.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\IMemberReference.cs">
+ <Link>cil-strip\Mono.Cecil\IMemberReference.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\IMetadataScope.cs">
+ <Link>cil-strip\Mono.Cecil\IMetadataScope.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\IMetadataTokenProvider.cs">
+ <Link>cil-strip\Mono.Cecil\IMetadataTokenProvider.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\IMethodSignature.cs">
+ <Link>cil-strip\Mono.Cecil\IMethodSignature.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\IReflectionStructureVisitable.cs">
+ <Link>cil-strip\Mono.Cecil\IReflectionStructureVisitable.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\IReflectionStructureVisitor.cs">
+ <Link>cil-strip\Mono.Cecil\IReflectionStructureVisitor.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\IReflectionVisitable.cs">
+ <Link>cil-strip\Mono.Cecil\IReflectionVisitable.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\IReflectionVisitor.cs">
+ <Link>cil-strip\Mono.Cecil\IReflectionVisitor.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\IRequireResolving.cs">
+ <Link>cil-strip\Mono.Cecil\IRequireResolving.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ImportContext.cs">
+ <Link>cil-strip\Mono.Cecil\ImportContext.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\InterfaceCollection.cs">
+ <Link>cil-strip\Mono.Cecil\InterfaceCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\LinkedResource.cs">
+ <Link>cil-strip\Mono.Cecil\LinkedResource.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ManifestResourceAttributes.cs">
+ <Link>cil-strip\Mono.Cecil\ManifestResourceAttributes.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\MarshalSpec.cs">
+ <Link>cil-strip\Mono.Cecil\MarshalSpec.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\MemberReference.cs">
+ <Link>cil-strip\Mono.Cecil\MemberReference.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\MemberReferenceCollection.cs">
+ <Link>cil-strip\Mono.Cecil\MemberReferenceCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\MetadataResolver.cs">
+ <Link>cil-strip\Mono.Cecil\MetadataResolver.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\MethodAttributes.cs">
+ <Link>cil-strip\Mono.Cecil\MethodAttributes.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\MethodCallingConvention.cs">
+ <Link>cil-strip\Mono.Cecil\MethodCallingConvention.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\MethodDefinition.cs">
+ <Link>cil-strip\Mono.Cecil\MethodDefinition.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\MethodDefinitionCollection.cs">
+ <Link>cil-strip\Mono.Cecil\MethodDefinitionCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\MethodImplAttributes.cs">
+ <Link>cil-strip\Mono.Cecil\MethodImplAttributes.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\MethodReference.cs">
+ <Link>cil-strip\Mono.Cecil\MethodReference.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\MethodReturnType.cs">
+ <Link>cil-strip\Mono.Cecil\MethodReturnType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\MethodSemanticsAttributes.cs">
+ <Link>cil-strip\Mono.Cecil\MethodSemanticsAttributes.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\MethodSpecification.cs">
+ <Link>cil-strip\Mono.Cecil\MethodSpecification.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\Modifiers.cs">
+ <Link>cil-strip\Mono.Cecil\Modifiers.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ModuleDefinition.cs">
+ <Link>cil-strip\Mono.Cecil\ModuleDefinition.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ModuleDefinitionCollection.cs">
+ <Link>cil-strip\Mono.Cecil\ModuleDefinitionCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ModuleReference.cs">
+ <Link>cil-strip\Mono.Cecil\ModuleReference.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ModuleReferenceCollection.cs">
+ <Link>cil-strip\Mono.Cecil\ModuleReferenceCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\NameObjectCollectionBase.cs">
+ <Link>cil-strip\Mono.Cecil\NameObjectCollectionBase.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\NativeType.cs">
+ <Link>cil-strip\Mono.Cecil\NativeType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\NestedTypeCollection.cs">
+ <Link>cil-strip\Mono.Cecil\NestedTypeCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\NullReferenceImporter.cs">
+ <Link>cil-strip\Mono.Cecil\NullReferenceImporter.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\OverrideCollection.cs">
+ <Link>cil-strip\Mono.Cecil\OverrideCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\PInvokeAttributes.cs">
+ <Link>cil-strip\Mono.Cecil\PInvokeAttributes.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\PInvokeInfo.cs">
+ <Link>cil-strip\Mono.Cecil\PInvokeInfo.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ParameterAttributes.cs">
+ <Link>cil-strip\Mono.Cecil\ParameterAttributes.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ParameterDefinition.cs">
+ <Link>cil-strip\Mono.Cecil\ParameterDefinition.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ParameterDefinitionCollection.cs">
+ <Link>cil-strip\Mono.Cecil\ParameterDefinitionCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ParameterReference.cs">
+ <Link>cil-strip\Mono.Cecil\ParameterReference.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\PinnedType.cs">
+ <Link>cil-strip\Mono.Cecil\PinnedType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\PointerType.cs">
+ <Link>cil-strip\Mono.Cecil\PointerType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\PropertyAttributes.cs">
+ <Link>cil-strip\Mono.Cecil\PropertyAttributes.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\PropertyDefinition.cs">
+ <Link>cil-strip\Mono.Cecil\PropertyDefinition.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\PropertyDefinitionCollection.cs">
+ <Link>cil-strip\Mono.Cecil\PropertyDefinitionCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\PropertyReference.cs">
+ <Link>cil-strip\Mono.Cecil\PropertyReference.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ReferenceType.cs">
+ <Link>cil-strip\Mono.Cecil\ReferenceType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ReflectionController.cs">
+ <Link>cil-strip\Mono.Cecil\ReflectionController.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ReflectionException.cs">
+ <Link>cil-strip\Mono.Cecil\ReflectionException.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ReflectionHelper.cs">
+ <Link>cil-strip\Mono.Cecil\ReflectionHelper.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ReflectionReader.cs">
+ <Link>cil-strip\Mono.Cecil\ReflectionReader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ReflectionWriter.cs">
+ <Link>cil-strip\Mono.Cecil\ReflectionWriter.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\Resource.cs">
+ <Link>cil-strip\Mono.Cecil\Resource.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\ResourceCollection.cs">
+ <Link>cil-strip\Mono.Cecil\ResourceCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\SecurityAction.cs">
+ <Link>cil-strip\Mono.Cecil\SecurityAction.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\SecurityDeclaration.cs">
+ <Link>cil-strip\Mono.Cecil\SecurityDeclaration.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\SecurityDeclarationCollection.cs">
+ <Link>cil-strip\Mono.Cecil\SecurityDeclarationCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\SecurityDeclarationReader.cs">
+ <Link>cil-strip\Mono.Cecil\SecurityDeclarationReader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\SentinelType.cs">
+ <Link>cil-strip\Mono.Cecil\SentinelType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\StructureReader.cs">
+ <Link>cil-strip\Mono.Cecil\StructureReader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\StructureWriter.cs">
+ <Link>cil-strip\Mono.Cecil\StructureWriter.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\TableComparers.cs">
+ <Link>cil-strip\Mono.Cecil\TableComparers.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\TargetRuntime.cs">
+ <Link>cil-strip\Mono.Cecil\TargetRuntime.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\TypeAttributes.cs">
+ <Link>cil-strip\Mono.Cecil\TypeAttributes.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\TypeDefinition.cs">
+ <Link>cil-strip\Mono.Cecil\TypeDefinition.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\TypeDefinitionCollection.cs">
+ <Link>cil-strip\Mono.Cecil\TypeDefinitionCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\TypeReference.cs">
+ <Link>cil-strip\Mono.Cecil\TypeReference.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\TypeReferenceCollection.cs">
+ <Link>cil-strip\Mono.Cecil\TypeReferenceCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\TypeSpecification.cs">
+ <Link>cil-strip\Mono.Cecil\TypeSpecification.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil\VariantType.cs">
+ <Link>cil-strip\Mono.Cecil\VariantType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\BaseImageVisitor.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\BaseImageVisitor.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\CLIHeader.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\CLIHeader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\CopyImageVisitor.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\CopyImageVisitor.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\DOSHeader.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\DOSHeader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\DataDirectory.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\DataDirectory.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\DebugHeader.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\DebugHeader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\DebugStoreType.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\DebugStoreType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\ExportTable.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\ExportTable.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\IBinaryVisitable.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\IBinaryVisitable.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\IBinaryVisitor.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\IBinaryVisitor.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\IHeader.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\IHeader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\Image.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\Image.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\ImageCharacteristics.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\ImageCharacteristics.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\ImageFormatException.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\ImageFormatException.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\ImageInitializer.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\ImageInitializer.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\ImageReader.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\ImageReader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\ImageWriter.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\ImageWriter.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\Imports.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\Imports.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\MemoryBinaryWriter.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\MemoryBinaryWriter.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\PEFileHeader.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\PEFileHeader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\PEOptionalHeader.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\PEOptionalHeader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\RVA.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\RVA.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\ResourceDataEntry.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\ResourceDataEntry.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\ResourceDirectoryEntry.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\ResourceDirectoryEntry.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\ResourceDirectoryString.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\ResourceDirectoryString.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\ResourceDirectoryTable.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\ResourceDirectoryTable.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\ResourceNode.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\ResourceNode.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\ResourceReader.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\ResourceReader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\ResourceWriter.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\ResourceWriter.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\RuntimeImage.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\RuntimeImage.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\Section.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\Section.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\SectionCharacteristics.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\SectionCharacteristics.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\SectionCollection.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\SectionCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Binary\SubSystem.cs">
+ <Link>cil-strip\Mono.Cecil.Binary\SubSystem.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\BaseCodeVisitor.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\BaseCodeVisitor.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\CilWorker.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\CilWorker.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\Code.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\Code.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\CodeReader.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\CodeReader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\CodeWriter.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\CodeWriter.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\Document.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\Document.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\DocumentHashAlgorithm.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\DocumentHashAlgorithm.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\DocumentLanguage.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\DocumentLanguage.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\DocumentLanguageVendor.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\DocumentLanguageVendor.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\DocumentType.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\DocumentType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\ExceptionHandler.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\ExceptionHandler.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\ExceptionHandlerCollection.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\ExceptionHandlerCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\ExceptionHandlerType.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\ExceptionHandlerType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\FlowControl.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\FlowControl.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\GuidAttribute.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\GuidAttribute.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\ICodeVisitable.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\ICodeVisitable.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\ICodeVisitor.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\ICodeVisitor.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\IScopeProvider.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\IScopeProvider.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\ISymbolReader.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\ISymbolReader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\ISymbolStoreFactory.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\ISymbolStoreFactory.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\ISymbolWriter.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\ISymbolWriter.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\IVariableDefinitionProvider.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\IVariableDefinitionProvider.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\Instruction.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\Instruction.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\InstructionCollection.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\InstructionCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\MethodBody.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\MethodBody.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\MethodDataSection.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\MethodDataSection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\MethodHeader.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\MethodHeader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\OpCode.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\OpCode.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\OpCodeNames.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\OpCodeNames.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\OpCodeType.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\OpCodeType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\OpCodes.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\OpCodes.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\OperandType.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\OperandType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\Scope.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\Scope.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\ScopeCollection.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\ScopeCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\SequencePoint.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\SequencePoint.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\StackBehaviour.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\StackBehaviour.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\SymbolStoreHelper.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\SymbolStoreHelper.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\VariableDefinition.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\VariableDefinition.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\VariableDefinitionCollection.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\VariableDefinitionCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Cil\VariableReference.cs">
+ <Link>cil-strip\Mono.Cecil.Cil\VariableReference.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\Assembly.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\Assembly.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\AssemblyOS.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\AssemblyOS.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\AssemblyProcessor.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\AssemblyProcessor.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\AssemblyRef.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\AssemblyRef.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\AssemblyRefOS.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\AssemblyRefOS.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\AssemblyRefProcessor.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\AssemblyRefProcessor.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\BaseMetadataVisitor.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\BaseMetadataVisitor.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\BlobHeap.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\BlobHeap.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\ClassLayout.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\ClassLayout.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\CodedIndex.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\CodedIndex.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\Constant.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\Constant.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\CultureUtils.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\CultureUtils.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\CustomAttribute.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\CustomAttribute.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\DeclSecurity.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\DeclSecurity.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\ElementType.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\ElementType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\Event.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\Event.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\EventMap.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\EventMap.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\EventPtr.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\EventPtr.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\ExportedType.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\ExportedType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\Field.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\Field.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\FieldLayout.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\FieldLayout.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\FieldMarshal.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\FieldMarshal.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\FieldPtr.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\FieldPtr.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\FieldRVA.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\FieldRVA.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\File.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\File.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\GenericParam.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\GenericParam.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\GenericParamConstraint.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\GenericParamConstraint.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\GuidHeap.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\GuidHeap.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\IMetadataRow.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\IMetadataRow.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\IMetadataTable.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\IMetadataTable.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\IMetadataVisitable.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\IMetadataVisitable.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\IMetadataVisitor.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\IMetadataVisitor.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\ImplMap.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\ImplMap.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\InterfaceImpl.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\InterfaceImpl.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\ManifestResource.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\ManifestResource.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\MemberRef.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\MemberRef.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\MetadataFormatException.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\MetadataFormatException.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\MetadataHeap.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\MetadataHeap.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\MetadataInitializer.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\MetadataInitializer.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\MetadataReader.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\MetadataReader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\MetadataRoot.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\MetadataRoot.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\MetadataRowReader.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\MetadataRowReader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\MetadataRowWriter.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\MetadataRowWriter.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\MetadataStream.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\MetadataStream.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\MetadataStreamCollection.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\MetadataStreamCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\MetadataTableReader.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\MetadataTableReader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\MetadataTableWriter.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\MetadataTableWriter.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\MetadataToken.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\MetadataToken.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\MetadataWriter.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\MetadataWriter.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\Method.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\Method.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\MethodImpl.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\MethodImpl.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\MethodPtr.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\MethodPtr.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\MethodSemantics.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\MethodSemantics.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\MethodSpec.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\MethodSpec.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\Module.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\Module.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\ModuleRef.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\ModuleRef.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\NestedClass.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\NestedClass.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\Param.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\Param.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\ParamPtr.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\ParamPtr.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\Property.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\Property.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\PropertyMap.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\PropertyMap.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\PropertyPtr.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\PropertyPtr.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\RowCollection.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\RowCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\StandAloneSig.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\StandAloneSig.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\StringsHeap.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\StringsHeap.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\TableCollection.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\TableCollection.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\TablesHeap.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\TablesHeap.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\TokenType.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\TokenType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\TypeDef.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\TypeDef.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\TypeRef.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\TypeRef.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\TypeSpec.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\TypeSpec.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\UserStringsHeap.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\UserStringsHeap.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Metadata\Utilities.cs">
+ <Link>cil-strip\Mono.Cecil.Metadata\Utilities.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\Array.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\Array.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\ArrayShape.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\ArrayShape.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\BaseSignatureVisitor.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\BaseSignatureVisitor.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\Class.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\Class.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\Constraint.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\Constraint.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\CustomAttrib.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\CustomAttrib.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\CustomMod.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\CustomMod.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\FieldSig.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\FieldSig.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\FnPtr.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\FnPtr.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\GenericArg.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\GenericArg.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\GenericInst.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\GenericInst.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\GenericInstSignature.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\GenericInstSignature.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\ISignatureVisitable.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\ISignatureVisitable.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\ISignatureVisitor.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\ISignatureVisitor.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\InputOutputItem.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\InputOutputItem.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\LocalVarSig.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\LocalVarSig.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\MVar.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\MVar.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\MarshalSig.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\MarshalSig.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\MethodDefSig.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\MethodDefSig.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\MethodRefSig.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\MethodRefSig.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\MethodSig.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\MethodSig.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\MethodSpec.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\MethodSpec.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\Param.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\Param.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\PropertySig.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\PropertySig.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\Ptr.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\Ptr.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\RetType.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\RetType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\SigType.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\SigType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\Signature.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\Signature.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\SignatureReader.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\SignatureReader.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\SignatureWriter.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\SignatureWriter.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\SzArray.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\SzArray.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\TypeSpec.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\TypeSpec.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\ValueType.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\ValueType.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Cecil.Signatures\Var.cs">
+ <Link>cil-strip\Mono.Cecil.Signatures\Var.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Xml\SecurityParser.cs">
+ <Link>cil-strip\Mono.Xml\SecurityParser.cs</Link>
+ </Compile>
+ <Compile Include="Mono.Xml\SmallXmlParser.cs">
+ <Link>cil-strip\Mono.Xml\SmallXmlParser.cs</Link>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="Mono.Xml\ChangeLog">
+ <Link>cil-strip\Mono.Xml\ChangeLog</Link>
+ </None>
+ </ItemGroup>
+</Project>
\ No newline at end of file
<method name="InternalArray__IndexOf" />
<method name="InternalArray__get_Item" />
<method name="InternalArray__set_Item" />
+ <method name="InternalArray__IReadOnlyList_get_Item" />
+ <method name="InternalArray__IReadOnlyCollection_get_Count" />
</type>
<type fullname="System.ArrayTypeMismatchException" />
<type fullname="System.Attribute" />
MarkCustomAttribute (ca);
}
- void MarkCustomAttribute (CustomAttribute ca)
+ protected virtual void MarkCustomAttribute (CustomAttribute ca)
{
MarkMethod (ca.Constructor);
MarkCustomAttributes (module);
}
- void MarkField (FieldReference reference)
+ protected void MarkField (FieldReference reference)
{
// if (IgnoreScope (reference.DeclaringType.Scope))
// return;
protected virtual void MarkSerializable (TypeDefinition type)
{
- if (!type.HasMethods)
- return;
-
- MarkMethodsIf (type.Methods, IsDefaultConstructorPredicate);
+ MarkDefaultConstructor (type);
MarkMethodsIf (type.Methods, IsSpecialSerializationConstructorPredicate);
}
return method.IsConstructor && !method.IsStatic;
}
+ protected void MarkDefaultConstructor (TypeDefinition type)
+ {
+ if ((type == null) || !type.HasMethods)
+ return;
+
+ MarkMethodsIf (type.Methods, IsDefaultConstructorPredicate);
+ }
+
static MethodPredicate IsStaticConstructorPredicate = new MethodPredicate (IsStaticConstructor);
static bool IsStaticConstructor (MethodDefinition method)
return null;
}
- void MarkProperty (PropertyDefinition prop)
+ protected void MarkProperty (PropertyDefinition prop)
{
MarkCustomAttributes (prop);
}
- void MarkEvent (EventDefinition evt)
+ protected void MarkEvent (EventDefinition evt)
{
MarkCustomAttributes (evt);
MarkMethodIfNotNull (evt.AddMethod);
void SweepReferences (AssemblyDefinition assembly, AssemblyDefinition target)
{
+ if (assembly == target)
+ return;
+
var references = assembly.MainModule.AssemblyReferences;
for (int i = 0; i < references.Count; i++) {
var reference = references [i];
return;
resolvedTypeReferences.Add (assembly);
+ var hash = new Dictionary<TypeReference,IMetadataScope> ();
+
foreach (TypeReference tr in assembly.MainModule.GetTypeReferences ()) {
+ if (hash.ContainsKey (tr))
+ continue;
var td = tr.Resolve ();
+ IMetadataScope scope = tr.Scope;
// at this stage reference might include things that can't be resolved
- tr.Scope = td == null ? null : assembly.MainModule.Import (td).Scope;
+ // and if it is (resolved) it needs to be kept only if marked (#16213)
+ if ((td != null) && Annotations.IsMarked (td))
+ scope = assembly.MainModule.Import (td).Scope;
+ hash.Add (tr, scope);
+ }
+
+ // Resolve everything first before updating scopes.
+ // If we set the scope to null, then calling Resolve() on any of its
+ // nested types would crash.
+
+ foreach (var e in hash) {
+ e.Key.Scope = e.Value;
}
}
<exception cref="T:System.ArgumentNullException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.FormatException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.IndexOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentNullException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.FormatException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.IndexOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentNullException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.FormatException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.IndexOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentNullException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.FormatException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.IndexOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentNullException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.FormatException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.IndexOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentNullException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.FormatException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.IndexOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentNullException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.FormatException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.IndexOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentNullException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.FormatException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.IndexOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentNullException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.FormatException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.IndexOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentNullException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.FormatException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.IndexOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentNullException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.FormatException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.IndexOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentNullException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.FormatException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.IndexOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentNullException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.FormatException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.IndexOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentNullException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.FormatException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.IndexOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentNullException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.FormatException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.IndexOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentNullException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.FormatException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.IndexOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentNullException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.FormatException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.IndexOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentNullException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.FormatException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.IndexOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentNullException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.FormatException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.IndexOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentNullException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.ArgumentOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.FormatException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
<exception cref="T:System.IndexOutOfRangeException">To be added; from:
<see cref="M:System.Delegate.Combine(System.Delegate,System.Delegate)" />,
<see cref="M:System.Delegate.CombineImpl(System.Delegate)" />,
+ <see cref="M:System.Delegate.Remove(System.Delegate,System.Delegate)" />,
<see cref="M:System.String.FormatHelper(System.Text.StringBuilder,System.IFormatProvider,System.String,System.Object[])" />,
<see cref="M:System.String.get_Chars(System.Int32)" />,
<see cref="M:System.String.InternalSetChar(System.Int32,System.Char)" />,
Error ("Cannot find assembly `" + assembly + "'" );
Console.WriteLine ("Log: \n" + total_log);
} catch (IKVM.Reflection.BadImageFormatException f) {
+ if (skip_scan)
+ throw;
Error ("Cannot load assembly (bad file format) " + f.Message);
} catch (FileLoadException f){
Error ("Cannot load assembly " + f.Message);
assembly = options.AssemblyReference;
if (options.ShowAll){
- ShowAll (assembly, options.FilterObsolete, options.ShowPrivate);
+ ShowAll (assembly, options.ShowPrivate, options.FilterObsolete);
return;
} else {
if (options.Type == null) {
public abstract SubStepTargets Targets { get; }
- void ISubStep.Initialize (LinkContext context)
+ public virtual void Initialize (LinkContext context)
{
this.context = context;
}
using System;
-using System.Collections.Generic;
-using System.Linq;
using Mono.Linker;
using Mono.Linker.Steps;
public class RemoveResources : IStep {
- I18nAssemblies assemblies;
+ readonly I18nAssemblies assemblies;
public RemoveResources (I18nAssemblies assemblies)
{
this.assemblies = assemblies;
}
- public void Process (LinkContext context)
+ public virtual void Process (LinkContext context)
{
AssemblyDefinition assembly;
if (!context.TryGetLinkedAssembly ("mscorlib", out assembly))
return;
+ // skip this if we're not linking mscorlib, e.g. --linkskip=mscorlib
+ if (context.Annotations.GetAction (assembly) != AssemblyAction.Link)
+ return;
+
var resources = assembly.MainModule.Resources;
for (int i = 0; i < resources.Count; i++) {
<Import Project="$(MSBuildProjectFullPath).user" Condition="Exists('$(MSBuildProjectFullPath).user')"/>
<PropertyGroup>
+ <OutputType Condition="'$(OutputType)' == ''">Exe</OutputType>
<TargetExt Condition="'$(OutputType)' == 'Winexe'">.exe</TargetExt>
<TargetExt Condition="'$(OutputType)' == 'Exe'">.exe</TargetExt>
<TargetExt Condition="'$(OutputType)' == 'Library'">.dll</TargetExt>
</PropertyGroup>
<PropertyGroup>
- <AssemblyName Condition="'$(AssemblyName)' == ''">$(RootNamespace)</AssemblyName>
+ <AssemblyName Condition="'$(AssemblyName)' == ''">$(MSBuildProjectName)</AssemblyName>
<OutputPath Condition="'$(OutputPath)' != '' and !HasTrailingSlash('$(OutputPath)')">$(OutputPath)\</OutputPath>
<OutputPath Condition=" '$(Platform)'=='' and '$(Configuration)'=='' and '$(OutputPath)'=='' ">bin\Debug\</OutputPath>
<WarningLevel Condition="'$(WarningLevel)' == ''" >2</WarningLevel>
<Import Project="$(MSBuildProjectFullPath).user" Condition="Exists('$(MSBuildProjectFullPath).user')"/>
<PropertyGroup>
+ <OutputType Condition="'$(OutputType)' == ''">Exe</OutputType>
<TargetExt Condition="'$(OutputType)' == 'Winexe'">.exe</TargetExt>
<TargetExt Condition="'$(OutputType)' == 'Exe'">.exe</TargetExt>
<TargetExt Condition="'$(OutputType)' == 'Library'">.dll</TargetExt>
</PropertyGroup>
<PropertyGroup>
- <AssemblyName Condition="'$(AssemblyName)' == ''">$(RootNamespace)</AssemblyName>
+ <AssemblyName Condition="'$(AssemblyName)' == ''">$(MSBuildProjectName)</AssemblyName>
<OutputPath Condition="'$(OutputPath)' != '' and !HasTrailingSlash('$(OutputPath)')">$(OutputPath)\</OutputPath>
<OutputPath Condition=" '$(Platform)'=='' and '$(Configuration)'=='' and '$(OutputPath)'=='' ">bin\Debug\</OutputPath>
<WarningLevel Condition="'$(WarningLevel)' == ''" >2</WarningLevel>
<Import Project="$(MSBuildProjectFullPath).user" Condition="Exists('$(MSBuildProjectFullPath).user')"/>
<PropertyGroup>
+ <OutputType Condition="'$(OutputType)' == ''">Exe</OutputType>
<TargetExt Condition="'$(OutputType)' == 'Winexe'">.exe</TargetExt>
<TargetExt Condition="'$(OutputType)' == 'Exe'">.exe</TargetExt>
<TargetExt Condition="'$(OutputType)' == 'Library'">.dll</TargetExt>
</PropertyGroup>
<PropertyGroup>
- <AssemblyName Condition="'$(AssemblyName)' == ''">$(RootNamespace)</AssemblyName>
+ <AssemblyName Condition="'$(AssemblyName)' == ''">$(MSBuildProjectName)</AssemblyName>
<OutputPath Condition="'$(OutputPath)' != '' and !HasTrailingSlash('$(OutputPath)')">$(OutputPath)\</OutputPath>
<OutputPath Condition=" '$(Platform)'=='' and '$(Configuration)'=='' and '$(OutputPath)'=='' ">bin\Debug\</OutputPath>
<WarningLevel Condition="'$(WarningLevel)' == ''" >2</WarningLevel>
%files -f mcs.lang
%defattr(-, root, root)
-%doc AUTHORS COPYING.LIB ChangeLog NEWS README
+%doc AUTHORS COPYING.LIB ChangeLog NEWS README.md
%config %_sysconfdir/mono/2.0/machine.config
%config %_sysconfdir/mono/2.0/settings.map
%config %_sysconfdir/mono/4.0/machine.config
#define amd64_sse_cvtsi2sd_reg_reg(inst,dreg,reg) amd64_sse_cvtsi2sd_reg_reg_size ((inst), (dreg), (reg), 8)
+#define amd64_sse_cvtsi2ss_reg_reg_size(inst,dreg,reg,size) emit_sse_reg_reg_size ((inst), (dreg), (reg), 0xf3, 0x0f, 0x2a, (size))
+
+#define amd64_sse_cvtsi2ss_reg_reg(inst,dreg,reg) amd64_sse_cvtsi2ss_reg_reg_size ((inst), (dreg), (reg), 8)
+
#define amd64_sse_cvtsd2ss_reg_reg(inst,dreg,reg) emit_sse_reg_reg ((inst), (dreg), (reg), 0xf2, 0x0f, 0x5a)
#define amd64_sse_cvtss2sd_reg_reg(inst,dreg,reg) emit_sse_reg_reg ((inst), (dreg), (reg), 0xf3, 0x0f, 0x5a)
/* misc and coprocessor ops */
#define mips_move(c,dest,src) mips_addu(c,dest,src,mips_zero)
#define mips_dmove(c,dest,src) mips_daddu(c,dest,src,mips_zero)
-#define mips_nop(c) mips_sll(c,0,0,0)
+#define mips_nop(c) mips_or(c,mips_at,mips_at,0)
#define mips_break(c,code) mips_emit32(c, ((code)<<6)|13)
#define mips_mfhi(c,dest) mips_format_r(c,0,0,0,dest,0,16)
#define mips_mflo(c,dest) mips_format_r(c,0,0,0,dest,0,18)
} else { \
x86_codegen_pre(&(inst), 6); \
*(inst)++ = (unsigned char)0x69; \
- x86_reg_emit ((inst), (reg), (mem)); \
+ x86_mem_emit ((inst), (reg), (mem)); \
x86_imm_emit32 ((inst), (imm)); \
} \
} while (0)
slide = _dyld_get_image_vmaddr_slide (i);
name = _dyld_get_image_name (i);
- hdr = _dyld_get_image_header (i);
#if SIZEOF_VOID_P == 8
+ hdr = (const struct mach_header_64*)_dyld_get_image_header (i);
sec = getsectbynamefromheader_64 (hdr, SEG_DATA, SECT_DATA);
#else
+ hdr = _dyld_get_image_header (i);
sec = getsectbynamefromheader (hdr, SEG_DATA, SECT_DATA);
#endif
size_t size;
struct kinfo_proc2 *pi;
#elif defined(PLATFORM_MACOSX)
+#if !(!defined (__mono_ppc__) && defined (TARGET_OSX))
size_t size;
struct kinfo_proc *pi;
int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid };
+#endif
#else
FILE *fp;
gchar *filename = NULL;
gpointer handle = GUINT_TO_POINTER (fd);
int ret;
const void *tmp_val;
+ int bufsize = 0;
struct timeval tv;
if (startup_count == 0) {
* buffer sizes "to allow space for bookkeeping
* overhead."
*/
- int bufsize = *((int *) optval);
+ bufsize = *((int *) optval);
bufsize /= 2;
tmp_val = &bufsize;
filewatcher.c \
filewatcher.h \
gc-internal.h \
+ gc-memfuncs.c \
icall.c \
icall-def.h \
image.c \
sgen-stw.c \
sgen-fin-weak-hash.c \
sgen-layout-stats.c \
- sgen-layout-stats.h
+ sgen-layout-stats.h \
+ sgen-qsort.c
libmonoruntime_la_SOURCES = $(common_sources) $(gc_dependent_sources) $(boehm_sources)
libmonoruntime_la_CFLAGS = $(BOEHM_DEFINES)
Makefile.am: Makefile.am.in
cp $< $@
endif
+
+if !HOST_WIN32
+
+test_sgen_qsort_SOURCES = test-sgen-qsort.c
+test_sgen_qsort_CFLAGS = $(SGEN_DEFINES)
+test_sgen_qsort_LDADD = libmonoruntimesgen.la ../io-layer/libwapi.la ../utils/libmonoutils.la \
+ $(LIBGC_LIBS) $(GLIB_LIBS) -lm $(LIBICONV)
+if PLATFORM_DARWIN
+test_sgen_qsort_LDFLAGS=-framework CoreFoundation
+endif
+
+test_gc_memfuncs_SOURCES = test-gc-memfuncs.c
+test_gc_memfuncs_CFLAGS = $(SGEN_DEFINES)
+test_gc_memfuncs_LDADD = libmonoruntimesgen.la ../io-layer/libwapi.la ../utils/libmonoutils.la \
+ $(LIBGC_LIBS) $(GLIB_LIBS) -lm $(LIBICONV)
+if PLATFORM_DARWIN
+test_gc_memfuncs_LDFLAGS=-framework CoreFoundation
+endif
+
+noinst_PROGRAMS = test-sgen-qsort test-gc-memfuncs
+
+TESTS = test-sgen-qsort test-gc-memfuncs
+
+endif !HOST_WIN32
* Changes which are already detected at runtime, like the addition
* of icalls, do not require an increment.
*/
-#define MONO_CORLIB_VERSION 110
+#define MONO_CORLIB_VERSION 111
typedef struct
{
shadow_location = get_shadow_assembly_location_base (data, &error);
if (!mono_error_ok (&error))
mono_error_raise_exception (&error);
- mono_debugger_event_create_appdomain (data, shadow_location);
g_free (shadow_location);
#endif
if (!parsed) {
/* This is a parse error... */
- return NULL;
+ if (!refOnly)
+ refass = mono_try_assembly_resolve (domain, assRef, refOnly);
+ return refass;
}
ass = mono_assembly_load_full_nosearch (&aname, NULL, &status, refOnly);
} while (InterlockedCompareExchange (&data->refcount, count, count - 1) != count);
}
-static void
-deregister_reflection_info_roots_nspace_table (gpointer key, gpointer value, gpointer image)
-{
- guint32 index = GPOINTER_TO_UINT (value);
- MonoClass *class = mono_class_get (image, MONO_TOKEN_TYPE_DEF | index);
-
- g_assert (class);
-
- mono_class_free_ref_info (class);
-}
-
-static void
-deregister_reflection_info_roots_name_space (gpointer key, gpointer value, gpointer user_data)
-{
- g_hash_table_foreach (value, deregister_reflection_info_roots_nspace_table, user_data);
-}
-
static void
deregister_reflection_info_roots_from_list (MonoImage *image)
{
list = list->next;
}
- g_slist_free (image->reflection_info_unregister_classes);
image->reflection_info_unregister_classes = NULL;
}
{
GSList *list;
- mono_loader_lock ();
mono_domain_assemblies_lock (domain);
for (list = domain->domain_assemblies; list; list = list->next) {
MonoAssembly *assembly = list->data;
MonoImage *image = assembly->image;
int i;
- /*No need to take the image lock here since dynamic images are appdomain bound and at this point the mutator is gone.*/
- if (image->dynamic && image->name_cache)
- g_hash_table_foreach (image->name_cache, deregister_reflection_info_roots_name_space, image);
- deregister_reflection_info_roots_from_list (image);
+
+ /*
+ * No need to take the image lock here since dynamic images are appdomain bound and
+ * at this point the mutator is gone. Taking the image lock here would mean
+ * promoting it from a simple lock to a complex lock, which we better avoid if
+ * possible.
+ */
+ if (image->dynamic)
+ deregister_reflection_info_roots_from_list (image);
+
for (i = 0; i < image->module_count; ++i) {
MonoImage *module = image->modules [i];
- if (module) {
- if (module->dynamic && module->name_cache) {
- g_hash_table_foreach (module->name_cache,
- deregister_reflection_info_roots_name_space, module);
- }
+ if (module && module->dynamic)
deregister_reflection_info_roots_from_list (module);
- }
}
}
mono_domain_assemblies_unlock (domain);
- mono_loader_unlock ();
}
static guint32 WINAPI
}
}
- mono_debugger_event_unload_appdomain (domain);
-
mono_domain_set (domain, FALSE);
/* Notify OnDomainUnload listeners */
method = mono_class_get_method_from_name (domain->domain->mbr.obj.vtable->klass, "DoDomainUnload", -1);
#include <mono/metadata/cil-coff.h>
#include <mono/utils/mono-io-portability.h>
#include <mono/utils/atomic.h>
+#include <mono/utils/mono-mutex.h>
#ifndef HOST_WIN32
#include <sys/types.h>
/* If defined, points to the bundled assembly information */
const MonoBundledAssembly **bundles;
+static mono_mutex_t assembly_binding_mutex;
+
/* Loaded assembly binding info */
static GSList *loaded_assembly_bindings = NULL;
check_extra_gac_path_env ();
InitializeCriticalSection (&assemblies_mutex);
+ mono_mutex_init (&assembly_binding_mutex);
+}
+
+static void
+mono_assembly_binding_lock (void)
+{
+ mono_locks_mutex_acquire (&assembly_binding_mutex, AssemblyBindingLock);
+}
+
+static void
+mono_assembly_binding_unlock (void)
+{
+ mono_locks_mutex_release (&assembly_binding_mutex, AssemblyBindingLock);
}
gboolean
return dest_name;
}
-/* LOCKING: Assumes that we are already locked */
+/* LOCKING: assembly_binding lock must be held */
static MonoAssemblyBindingInfo*
search_binding_loaded (MonoAssemblyName *aname)
{
return aname;
domain = mono_domain_get ();
- mono_loader_lock ();
+
+ mono_assembly_binding_lock ();
info = search_binding_loaded (aname);
+ mono_assembly_binding_unlock ();
+
if (!info) {
mono_domain_lock (domain);
info = get_per_domain_assembly_binding_info (domain, aname);
mono_domain_unlock (domain);
}
- mono_loader_unlock ();
if (info) {
if (!check_policy_versions (info, aname))
return aname;
g_free (domain_config_file_name);
g_free (domain_config_file_path);
}
- mono_domain_unlock (domain);
- mono_loader_lock ();
- mono_domain_lock (domain);
info2 = get_per_domain_assembly_binding_info (domain, aname);
if (info2) {
}
mono_domain_unlock (domain);
- mono_loader_unlock ();
}
if (!info) {
g_strlcpy ((char *)info->public_key_token, (const char *)aname->public_key_token, MONO_PUBLIC_KEY_TOKEN_LENGTH);
}
- mono_loader_lock ();
+ mono_assembly_binding_lock ();
info2 = search_binding_loaded (aname);
if (info2) {
/* This binding was added by another thread
} else
loaded_assembly_bindings = g_slist_prepend (loaded_assembly_bindings, info);
- mono_loader_unlock ();
+ mono_assembly_binding_unlock ();
if (!info->is_valid || !check_policy_versions (info, aname))
return aname;
GSList *l;
DeleteCriticalSection (&assemblies_mutex);
+ mono_mutex_destroy (&assembly_binding_mutex);
for (l = loaded_assembly_bindings; l; l = l->next) {
MonoAssemblyBindingInfo *info = l->data;
free_assembly_preload_hooks ();
}
-/*LOCKING assumes loader lock is held*/
+/*LOCKING takes the assembly_binding lock*/
void
mono_assembly_cleanup_domain_bindings (guint32 domain_id)
{
- GSList **iter = &loaded_assembly_bindings;
+ GSList **iter;
+ mono_assembly_binding_lock ();
+ iter = &loaded_assembly_bindings;
while (*iter) {
GSList *l = *iter;
MonoAssemblyBindingInfo *info = l->data;
iter = &l->next;
}
}
+ mono_assembly_binding_unlock ();
}
/*
#include <mono/utils/mono-threads.h>
#include <mono/utils/dtrace.h>
#include <mono/utils/gc_wrapper.h>
+#include <mono/utils/mono-mutex.h>
#if HAVE_BOEHM_GC
#define MIN_BOEHM_MAX_HEAP_SIZE (MIN_BOEHM_MAX_HEAP_SIZE_IN_MB << 20)
static gboolean gc_initialized = FALSE;
+static mono_mutex_t mono_gc_lock;
static void*
boehm_thread_register (MonoThreadInfo* info, void *baseptr);
#endif
mono_threads_init (&cb, sizeof (MonoThreadInfo));
+ mono_mutex_init (&mono_gc_lock);
mono_gc_enable_events ();
gc_initialized = TRUE;
mono_tls_key_set_offset (TLS_KEY_BOEHM_GC_THREAD, offset);
- mono_loader_lock ();
res = alloc_method_cache [atype];
- if (!res)
- res = alloc_method_cache [atype] = create_allocator (atype, TLS_KEY_BOEHM_GC_THREAD);
- mono_loader_unlock ();
+ if (res)
+ return res;
+
+ res = create_allocator (atype, TLS_KEY_BOEHM_GC_THREAD);
+ mono_mutex_lock (&mono_gc_lock);
+ if (alloc_method_cache [atype]) {
+ mono_free_method (res);
+ res = alloc_method_cache [atype];
+ } else {
+ mono_memory_barrier ();
+ alloc_method_cache [atype] = res;
+ }
+ mono_mutex_unlock (&mono_gc_lock);
return res;
}
void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
-void (*mono_debugger_class_loaded_methods_func) (MonoClass *klass) = NULL;
/*
class->methods = methods;
- if (mono_debugger_class_loaded_methods_func)
- mono_debugger_class_loaded_methods_func (class);
-
mono_loader_unlock ();
}
* We collect the types needed to build the
* instantiations in interfaces at intervals of 3/5, because 3/5 are
* the generic interfaces needed to implement.
+ *
+ * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
+ * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
*/
- nifaces = generic_ireadonlylist_class ? 5 : 3;
if (eclass->valuetype) {
+ nifaces = generic_ireadonlylist_class ? 5 : 3;
fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
/* IList, ICollection, IEnumerable, IReadOnlyList`1 */
int idepth = eclass->idepth;
if (!internal_enumerator)
idepth--;
+ nifaces = generic_ireadonlylist_class ? 2 : 3;
// FIXME: This doesn't seem to work/required for generic params
if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (eclass->image->dynamic && !eclass->wastypebuilder)))
interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
- interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
- if (generic_ireadonlylist_class) {
- interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
- interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
+
+ if (eclass->valuetype) {
+ interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
+ if (generic_ireadonlylist_class) {
+ interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
+ interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
+ }
+ } else {
+ if (!generic_ireadonlylist_class)
+ interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
}
}
if (internal_enumerator) {
if (class->vtable)
return;
- if (mono_debug_using_mono_debugger ())
- /* The debugger currently depends on this */
- mono_class_setup_methods (class);
-
if (MONO_CLASS_IS_INTERFACE (class)) {
/* This sets method->slot for all methods if this is an interface */
mono_class_setup_methods (class);
* - supertypes: array of classes: each element has a class in the hierarchy
* starting from @class up to System.Object
*
- * LOCKING: this assumes the loader lock is held
+ * LOCKING: This function is atomic, in case of contention we waste memory.
*/
void
mono_class_setup_supertypes (MonoClass *class)
int ms;
MonoClass **supertypes;
- if (class->supertypes)
+ mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
+ if (supertypes)
return;
if (class->parent && !class->parent->supertypes)
MonoMethod** method;
if (!iter)
return NULL;
- if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass) || mono_debug_using_mono_debugger ()) {
+ if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
if (!*iter) {
mono_class_setup_methods (klass);
/*
cominterop_setup_marshal_context (&m, adjust_method);
m.mb = mb;
mono_marshal_emit_managed_wrapper (mb, sig_adjusted, mspecs, &m, adjust_method, 0);
- mono_loader_lock ();
mono_cominterop_lock ();
wrapper_method = mono_mb_create_method (mb, m.csig, m.csig->param_count + 16);
mono_cominterop_unlock ();
- mono_loader_unlock ();
vtable [vtable_index--] = mono_compile_method (wrapper_method);
mono_mb_emit_byte (mb, CEE_RET);
- mono_loader_lock ();
mono_cominterop_lock ();
res = mono_mb_create_method (mb, sig_native, sig_native->param_count + 16);
mono_cominterop_unlock ();
- mono_loader_unlock ();
mono_mb_free (mb);
static const NumberFormatEntry number_format_entries [] = {
- {35403, 35406, 35403, 35406, 35403, 35406, 35409, 35419, 35422, 35436, 35439, 35449, 2601, 35458, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35465, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35485, 35494, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35502, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35502, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35506, 35471, 35473, 35477, 35510, 35522, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35534, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35537, 35548, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35559, 35573, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35586, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35481, 35471, 35607, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35481, 35471, 35473, 35477, 35616, 35624, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35632, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 2, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35636, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35534, 35471, 35639, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 0, 35477, 35588, 35644, 2601, 35458, 9, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35502, 35471, 35654, 35477, 35439, 35449, 2601, 35458, 1, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35670, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35674, 35684, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 0, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35693, 35471, 35473, 35477, 35697, 35716, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35735, 35471, 35473, 35477, 35588, 35644, 2601, 35458, 9, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35738, 763, 35738, 763, 35738, 0, 35471, 35473, 35477, 35742, 35751, 2601, 35458, 2, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 0, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35760, 35471, 35768, 35477, 35784, 35812, 2601, 35458, 5, 1, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35839, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 2, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35481, 35471, 0, 35477, 35510, 35522, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35842, 35471, 0, 35477, 35439, 35449, 2601, 35458, 5, 1, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35534, 35471, 35846, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35853, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35857, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35860, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 3, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35865, 35471, 0, 35477, 35439, 35449, 2601, 35458, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35868, 35471, 35872, 35477, 35439, 35449, 2601, 35458, 5, 1, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 0, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35888, 35902, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35481, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35915, 35471, 35918, 35477, 35932, 35944, 2601, 35458, 9, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35955, 35471, 35846, 35477, 35958, 35969, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35460, 35460, 35460, 35460, 35460, 0, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, 0}, {3, 0}, {3, 0}},
- {35403, 35406, 35403, 35406, 35403, 35406, 35979, 35419, 0, 35436, 35439, 35449, 2601, 35458, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35983, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35987, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 0, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35993, 36003, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 0, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 10511, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 2, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 10511, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 2, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 10511, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 2, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 10511, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 2, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 0, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35534, 35471, 35846, 35477, 35439, 35449, 2601, 35458, 12, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36012, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {763, 35460, 763, 35460, 763, 35460, 35481, 35471, 0, 35477, 35439, 35449, 2601, 35458, 1, 0, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35481, 35471, 35846, 35477, 35439, 35449, 2601, 35458, 12, 2, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35481, 35471, 0, 35477, 35439, 35449, 2601, 35458, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36016, 35471, 0, 35477, 35439, 35449, 2601, 35458, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 0, 35471, 0, 35477, 35439, 35449, 2601, 35458, 1, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 36019, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36026, 35471, 0, 35477, 35439, 35449, 2601, 35458, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 0, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36030, 35471, 36037, 35477, 35439, 35449, 2601, 35458, 12, 2, 2, 2, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {35460, 35460, 35460, 35460, 35460, 35460, 0, 35471, 0, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36012, 35471, 36063, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {763, 35460, 763, 35460, 763, 35460, 36012, 35471, 0, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {763, 35460, 763, 35460, 763, 35460, 36012, 35471, 36095, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36012, 35471, 0, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36012, 35471, 36121, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {763, 35460, 763, 35460, 763, 35460, 36012, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 12, 2, 2, 2, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36012, 35471, 0, 35477, 35439, 35449, 2601, 35458, 12, 1, 1, 1, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36012, 35471, 36152, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {35460, 35462, 35460, 35462, 35460, 35462, 0, 35471, 0, 35477, 35439, 35449, 2601, 35458, 5, 1, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36162, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 2, 0, 1, 1, 1, 2, 2, 2, {3, 0}, {3, 0}, {3, 0}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36167, 35471, 0, 35477, 35439, 35449, 2601, 35458, 1, 0, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 36170, 35471, 0, 35477, 35439, 35449, 2601, 35458, 5, 1, 1, 1, 2, 2, 2, 2, {3, -1}, {3, 0}, {3, 0}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36174, 35471, 0, 35477, 35439, 35449, 2601, 35458, 4, 1, 0, 0, 0, 2, 2, 2, {3, 0}, {3, 0}, {3, 0}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36012, 35471, 0, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36178, 35471, 0, 35477, 35439, 35449, 2601, 35458, 14, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, 2}, {3, 2}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36186, 35471, 0, 35477, 35439, 35449, 2601, 35458, 1, 0, 1, 1, 1, 2, 1, 1, {3, 0}, {3, 0}, {3, 0}},
- {35460, 35462, 35460, 35462, 35460, 35462, 0, 35471, 0, 35477, 35616, 35624, 2601, 35458, 8, 3, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36193, 35471, 0, 35477, 35439, 35449, 2601, 35458, 1, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, 2}, {3, 2}},
- {35403, 35406, 35403, 35406, 35403, 35406, 36206, 35419, 0, 35477, 35439, 35449, 2601, 35458, 3, 0, 4, 2, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36209, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 0, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36213, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 10511, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 2, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35534, 35471, 35846, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, 0}, {3, 0}, {3, 0}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36213, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36162, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, 0}, {3, 0}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35481, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35460, 35460, 35460, 35460, 35460, 35481, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35738, 763, 35738, 763, 35738, 0, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35460, 35460, 35460, 35460, 35460, 0, 35471, 0, 35477, 35439, 35449, 2601, 35458, 5, 1, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 36217, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36167, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35403, 35406, 35403, 35406, 35403, 35406, 35409, 35419, 35422, 35436, 35439, 35449, 2601, 35458, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35465, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35485, 35494, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36220, 35471, 36224, 35477, 35439, 35449, 2601, 35458, 1, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35506, 35471, 35473, 35477, 35510, 35522, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35534, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35537, 35548, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35559, 35573, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35586, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35481, 35471, 35607, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35481, 35471, 35473, 35477, 35616, 35624, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35632, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 2, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35636, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35534, 35471, 35639, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 0, 35477, 35588, 35644, 2601, 35458, 9, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35502, 35471, 35654, 35477, 35439, 35449, 2601, 35458, 1, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35670, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35674, 35684, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35534, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35693, 35471, 35473, 35477, 35697, 35716, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35735, 35471, 35473, 35477, 35588, 35644, 2601, 35458, 9, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35738, 763, 35738, 763, 35738, 0, 35471, 35473, 35477, 35742, 35751, 2601, 35458, 2, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 0, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35760, 35471, 35768, 35477, 35784, 35812, 2601, 35458, 5, 1, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35839, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 2, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35481, 35471, 0, 35477, 35510, 35522, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35842, 35471, 0, 35477, 35439, 35449, 2601, 35458, 5, 1, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35534, 35471, 35846, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35853, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35857, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35860, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 3, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35865, 35471, 0, 35477, 35439, 35449, 2601, 35458, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35868, 35471, 35872, 35477, 35439, 35449, 2601, 35458, 5, 1, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 0, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35888, 35902, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35481, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35915, 35471, 35918, 35477, 35932, 35944, 2601, 35458, 9, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35955, 35471, 35846, 35477, 35958, 35969, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36019, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, 0}, {3, 0}, {3, 0}},
- {35403, 35406, 35403, 35406, 35403, 35406, 35979, 35419, 0, 35436, 35439, 35449, 2601, 35458, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35983, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35987, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 36234, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35993, 36003, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 0, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 10511, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 2, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 10511, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 2, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 10511, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 2, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 10511, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 2, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 0, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35534, 35471, 35846, 35477, 35439, 35449, 2601, 35458, 12, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36012, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {763, 35460, 763, 35460, 763, 35460, 35481, 35471, 0, 35477, 35439, 35449, 2601, 35458, 1, 0, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 0, 35471, 35846, 35477, 35439, 35449, 2601, 35458, 12, 2, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36016, 35471, 0, 35477, 35439, 35449, 2601, 35458, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 36019, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36026, 35471, 0, 35477, 35439, 35449, 2601, 35458, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 36239, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36012, 35471, 36037, 35477, 35439, 35449, 2601, 35458, 12, 2, 2, 2, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36012, 35471, 36063, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {763, 35460, 763, 35460, 763, 35460, 36012, 35471, 0, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {763, 35460, 763, 35460, 763, 35460, 36012, 35471, 36095, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36012, 35471, 0, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36012, 35471, 36121, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {763, 35460, 763, 35460, 763, 35460, 36012, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 12, 2, 2, 2, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36012, 35471, 0, 35477, 35439, 35449, 2601, 35458, 12, 1, 1, 1, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36012, 35471, 36152, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {763, 35460, 763, 35460, 763, 35460, 36162, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 2, 0, 1, 1, 1, 2, 2, 2, {3, 0}, {3, 0}, {3, 0}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36167, 35471, 0, 35477, 35439, 35449, 2601, 35458, 1, 0, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 36170, 35471, 0, 35477, 35439, 35449, 2601, 35458, 5, 1, 1, 1, 2, 2, 2, 2, {3, -1}, {3, 0}, {3, 0}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36174, 35471, 0, 35477, 35439, 35449, 2601, 35458, 4, 1, 0, 0, 0, 2, 2, 2, {3, 0}, {3, 0}, {3, 0}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36012, 35471, 0, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36178, 35471, 0, 35477, 35439, 35449, 2601, 35458, 14, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, 2}, {3, 2}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36186, 35471, 0, 35477, 35439, 35449, 2601, 35458, 1, 0, 1, 1, 1, 2, 1, 1, {3, 0}, {3, 0}, {3, 0}},
- {763, 35460, 763, 35460, 763, 35460, 36193, 35471, 0, 35477, 35439, 35449, 2601, 35458, 1, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, 2}, {3, 2}},
- {35403, 35406, 35403, 35406, 35403, 35406, 36206, 35419, 0, 35477, 35439, 35449, 2601, 35458, 3, 0, 4, 2, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36209, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36213, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36213, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 10511, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 2, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35534, 35471, 35846, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, 0}, {3, 0}, {3, 0}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36213, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36162, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, 0}, {3, 0}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35481, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35460, 35460, 35460, 35460, 35460, 35481, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35460, 35460, 35460, 35460, 35460, 0, 35471, 0, 35477, 35439, 35449, 2601, 35458, 5, 1, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 36217, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36167, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35403, 35406, 35403, 35406, 35403, 35406, 36245, 35419, 35422, 35436, 35439, 35449, 2601, 35458, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35502, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 36255, 763, 36255, 763, 36255, 0, 35471, 35473, 35477, 35537, 35548, 2601, 35458, 2, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36167, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35586, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35616, 35624, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 36255, 763, 36255, 763, 36255, 0, 35471, 0, 35477, 35588, 35644, 2601, 35458, 2, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35674, 35684, 2601, 35458, 12, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35534, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35481, 35471, 35473, 35477, 35588, 35644, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35481, 35471, 35846, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 36257, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35481, 35471, 0, 35477, 35439, 35449, 2601, 35458, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35586, 35471, 0, 35477, 35439, 35449, 2601, 35458, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 36265, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36272, 35471, 36037, 35477, 35439, 35449, 2601, 35458, 12, 2, 2, 2, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {35460, 35462, 35460, 35462, 35460, 35462, 36162, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 0, 1, 1, 1, 2, 2, 2, {3, 0}, {3, 0}, {3, 0}},
- {35403, 35406, 35403, 35406, 35403, 35406, 36276, 35419, 35422, 35436, 35439, 35449, 2601, 35458, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35586, 35471, 36224, 35477, 35439, 35449, 2601, 35458, 0, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35537, 35548, 2601, 35458, 9, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35586, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35586, 35471, 35473, 35477, 35616, 35624, 2601, 35458, 15, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35481, 35471, 35846, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35403, 35406, 35403, 35406, 35403, 35406, 36286, 35419, 35422, 35436, 35439, 35449, 2601, 35458, 3, 0, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 0, 35471, 0, 35477, 35439, 35449, 2601, 35458, 0, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35537, 35548, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35586, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 7774, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 36255, 763, 36255, 763, 36255, 0, 35471, 35473, 35477, 35616, 35624, 2601, 35458, 2, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35403, 35406, 35403, 35406, 35403, 35406, 36296, 35419, 35422, 35436, 35439, 35449, 2601, 35458, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 0, 35471, 36224, 35477, 35439, 35449, 2601, 35458, 0, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 36255, 763, 36255, 763, 36255, 0, 35471, 35473, 35477, 35537, 35548, 2601, 35458, 2, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35586, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 36306, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35616, 35624, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35403, 35406, 35403, 35406, 35403, 35406, 36310, 35419, 35422, 35436, 35439, 35449, 2601, 35458, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35481, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36320, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 14, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35481, 35471, 35473, 35477, 35616, 35624, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 36324, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35403, 35406, 35403, 35406, 35403, 35406, 36327, 35419, 35422, 35436, 35439, 35449, 2601, 35458, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 10511, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 2, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35586, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 36337, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35403, 35406, 35403, 35406, 35403, 35406, 36343, 35419, 35422, 35436, 35439, 35449, 2601, 35458, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35586, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 36353, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35403, 35406, 35403, 35406, 35403, 35406, 36359, 35419, 35422, 35436, 35439, 35449, 2601, 35458, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35586, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 14, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 36369, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35403, 35406, 35403, 35406, 35403, 35406, 36374, 35419, 35422, 35436, 35439, 35449, 2601, 35458, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35586, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36384, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 36388, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35403, 35406, 35403, 35406, 35403, 35406, 36396, 35419, 35422, 35436, 35439, 35449, 2601, 35458, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35586, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35586, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 2, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35403, 35406, 35403, 35406, 35403, 35406, 36406, 35419, 35422, 35436, 35439, 35449, 2601, 35458, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35586, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35586, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 14, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35481, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35403, 35406, 35403, 35406, 35403, 35406, 36416, 35419, 35422, 35436, 35439, 35449, 2601, 35458, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36209, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35586, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 9, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35403, 35406, 35403, 35406, 35403, 35406, 36426, 35419, 35422, 35436, 35439, 35449, 2601, 35458, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 35586, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 14, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35403, 35406, 35403, 35406, 35403, 35406, 36436, 35419, 35422, 35436, 35439, 35449, 2601, 35458, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 36446, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 14, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35403, 35406, 35403, 35406, 35403, 35406, 36450, 35419, 35422, 35436, 35439, 35449, 2601, 35458, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36012, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
- {35460, 763, 35460, 763, 35460, 763, 36460, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 14, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36463, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35586, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 0, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 2471, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36467, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 14, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35586, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 14, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 35586, 35471, 35473, 35477, 35588, 35598, 2601, 35458, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, 0}, {3, 0}},
- {35460, 763, 35460, 763, 35460, 763, 36470, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 36478, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 36257, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36483, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35534, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 0, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 36234, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 36265, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 0, 35471, 0, 35477, 35439, 35449, 2601, 35458, 5, 1, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36486, 35471, 36224, 35477, 35439, 35449, 2601, 35458, 0, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36486, 35471, 36224, 35477, 35439, 35449, 2601, 35458, 0, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 35534, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 763, 35460, 763, 35460, 763, 36478, 35471, 35473, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35460, 35460, 35460, 35460, 35460, 36019, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, 0}, {3, 0}, {3, 0}},
- {35460, 35462, 35460, 35462, 35460, 35462, 36239, 35471, 0, 35477, 35439, 35449, 2601, 35458, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {35460, 35462, 35460, 35462, 35460, 35462, 36162, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 0, 1, 1, 1, 2, 2, 2, {3, 0}, {3, 0}, {3, 0}},
- {35460, 35462, 35460, 35462, 35460, 35462, 0, 35471, 0, 35477, 35616, 35624, 2601, 35458, 8, 3, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
- {763, 35460, 763, 35460, 763, 35460, 36213, 35471, 0, 35477, 35439, 35449, 2601, 35458, 2, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}}
+ {763, 35403, 35405, 35408, 35405, 35408, 35411, 35421, 35424, 35438, 35441, 35451, 2601, 35460, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35465, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35485, 35494, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35502, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35502, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35506, 35471, 35473, 35477, 35510, 35522, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35534, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35537, 35548, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35559, 35573, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35586, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 8, 3, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35481, 35471, 35607, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35481, 35471, 35473, 35477, 35616, 35624, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35632, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 2, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35636, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35534, 35471, 35639, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 0, 35477, 35588, 35644, 2601, 35460, 9, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35502, 35471, 35654, 35477, 35441, 35451, 2601, 35460, 1, 0, 1, 1, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35670, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 1, 0, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35674, 35684, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 0, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35693, 35471, 35473, 35477, 35697, 35716, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35735, 35471, 35473, 35477, 35588, 35644, 2601, 35460, 9, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35738, 763, 35740, 763, 35740, 0, 35471, 35473, 35477, 35744, 35753, 2601, 35460, 2, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 0, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35762, 35471, 35770, 35477, 35786, 35814, 2601, 35460, 5, 1, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35841, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 2, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35481, 35471, 0, 35477, 35510, 35522, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35844, 35471, 0, 35477, 35441, 35451, 2601, 35460, 5, 1, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 35462, 35403, 35462, 35534, 35471, 35848, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35855, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35859, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35862, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 3, 0, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35867, 35471, 0, 35477, 35441, 35451, 2601, 35460, 0, 0, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35870, 35471, 35874, 35477, 35441, 35451, 2601, 35460, 5, 1, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 0, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35890, 35904, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35462, 35403, 35462, 35403, 35462, 35481, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35917, 35471, 35920, 35477, 35934, 35946, 2601, 35460, 9, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 763, 35403, 763, 35403, 35957, 35471, 35848, 35477, 35960, 35971, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35981, 35462, 35403, 35403, 35403, 35403, 0, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, 0}, {3, 0}, {3, 0}},
+ {239, 35403, 35405, 35408, 35405, 35408, 35983, 35421, 0, 35438, 35441, 35451, 2601, 35460, 3, 2, 0, 0, 3, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35987, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 763, 35403, 763, 35991, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 763, 35403, 763, 0, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35997, 36007, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 0, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35462, 35403, 35462, 10511, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 2, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35462, 35403, 35462, 10511, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 2, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35462, 35403, 35462, 10511, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 2, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35462, 35403, 35462, 10511, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 2, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 763, 35403, 763, 0, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35534, 35471, 35848, 35477, 35441, 35451, 2601, 35460, 12, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36016, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 763, 35403, 763, 35403, 35481, 35471, 0, 35477, 35441, 35451, 2601, 35460, 1, 0, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35481, 35471, 35848, 35477, 35441, 35451, 2601, 35460, 12, 2, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35481, 35471, 0, 35477, 35441, 35451, 2601, 35460, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36020, 35471, 0, 35477, 35441, 35451, 2601, 35460, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {2601, 35462, 35403, 35462, 35403, 35462, 0, 35471, 0, 35477, 35441, 35451, 2601, 35460, 1, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {2601, 35462, 35403, 35462, 35403, 35462, 36023, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36030, 35471, 0, 35477, 35441, 35451, 2601, 35460, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 0, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36034, 35471, 36041, 35477, 35441, 35451, 2601, 35460, 12, 2, 2, 2, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 35403, 35403, 35403, 35403, 0, 35471, 0, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36016, 35471, 36067, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 763, 35403, 763, 35403, 36016, 35471, 0, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 763, 35403, 763, 35403, 36016, 35471, 36099, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36016, 35471, 0, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36016, 35471, 36125, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 763, 35403, 763, 35403, 36016, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 12, 2, 2, 2, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36016, 35471, 0, 35477, 35441, 35451, 2601, 35460, 12, 1, 1, 1, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36016, 35471, 36156, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 0, 35471, 0, 35477, 35441, 35451, 2601, 35460, 5, 1, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36166, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 2, 0, 1, 1, 1, 2, 2, 2, {3, 0}, {3, 0}, {3, 0}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36171, 35471, 0, 35477, 35441, 35451, 2601, 35460, 1, 0, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 763, 35403, 763, 36174, 35471, 0, 35477, 35441, 35451, 2601, 35460, 5, 1, 1, 1, 2, 2, 2, 2, {3, -1}, {3, 0}, {3, 0}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36178, 35471, 0, 35477, 35441, 35451, 2601, 35460, 4, 1, 0, 0, 0, 0, 2, 2, {3, 0}, {3, 0}, {3, 0}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36016, 35471, 0, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36182, 35471, 0, 35477, 35441, 35451, 2601, 35460, 14, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, 2}, {3, 2}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36190, 35471, 0, 35477, 35441, 35451, 2601, 35460, 1, 0, 1, 1, 1, 2, 1, 1, {3, 0}, {3, 0}, {3, 0}},
+ {763, 35403, 35403, 35462, 35403, 35462, 0, 35471, 0, 35477, 35616, 35624, 2601, 35460, 8, 3, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36197, 35471, 0, 35477, 35441, 35451, 2601, 35460, 1, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, 2}, {3, 2}},
+ {35405, 35408, 35405, 35408, 35405, 35408, 36210, 35421, 0, 35477, 35441, 35451, 2601, 35460, 3, 0, 4, 2, 3, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36213, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 0, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36217, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35462, 35403, 35462, 10511, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 2, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35534, 35471, 35848, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, 0}, {3, 0}, {3, 0}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36217, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36166, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, 0}, {3, 0}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35481, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35403, 35403, 35403, 35481, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 763, 35740, 763, 35740, 0, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35403, 35403, 35403, 0, 35471, 0, 35477, 35441, 35451, 2601, 35460, 5, 1, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 763, 35403, 763, 36221, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 2, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36171, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35405, 35408, 35405, 35408, 35411, 35421, 35424, 35438, 35441, 35451, 2601, 35460, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35465, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35485, 35494, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36224, 35471, 36228, 35477, 35441, 35451, 2601, 35460, 1, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35506, 35471, 35473, 35477, 35510, 35522, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35534, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35537, 35548, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35559, 35573, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35586, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35481, 35471, 35607, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35481, 35471, 35473, 35477, 35616, 35624, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35632, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 2, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35636, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35534, 35471, 35639, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 0, 35477, 35588, 35644, 2601, 35460, 9, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35502, 35471, 35654, 35477, 35441, 35451, 2601, 35460, 1, 0, 1, 1, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35670, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 1, 0, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35674, 35684, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35534, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35693, 35471, 35473, 35477, 35697, 35716, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35735, 35471, 35473, 35477, 35588, 35644, 2601, 35460, 9, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35738, 763, 35740, 763, 35740, 0, 35471, 35473, 35477, 35744, 35753, 2601, 35460, 2, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 0, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35762, 35471, 35770, 35477, 35786, 35814, 2601, 35460, 5, 1, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35841, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 2, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35481, 35471, 0, 35477, 35510, 35522, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35844, 35471, 0, 35477, 35441, 35451, 2601, 35460, 5, 1, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 35462, 35403, 35462, 35534, 35471, 35848, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35855, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35859, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35862, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 3, 0, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35867, 35471, 0, 35477, 35441, 35451, 2601, 35460, 0, 0, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35870, 35471, 35874, 35477, 35441, 35451, 2601, 35460, 5, 1, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 0, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35890, 35904, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35462, 35403, 35462, 35403, 35462, 35481, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35917, 35471, 35920, 35477, 35934, 35946, 2601, 35460, 9, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 763, 35403, 763, 35403, 35957, 35471, 35848, 35477, 35960, 35971, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35981, 35462, 35403, 35403, 35403, 35403, 36023, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, 0}, {3, 0}, {3, 0}},
+ {239, 35403, 35405, 35408, 35405, 35408, 35983, 35421, 0, 35438, 35441, 35451, 2601, 35460, 3, 2, 0, 0, 3, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35987, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 763, 35403, 763, 35991, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 763, 35403, 763, 36238, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35997, 36007, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 0, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35462, 35403, 35462, 10511, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 2, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35462, 35403, 35462, 10511, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 2, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35462, 35403, 35462, 10511, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 2, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35462, 35403, 35462, 10511, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 2, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 763, 35403, 763, 0, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35534, 35471, 35848, 35477, 35441, 35451, 2601, 35460, 12, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36016, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 763, 35403, 763, 35403, 35481, 35471, 0, 35477, 35441, 35451, 2601, 35460, 1, 0, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 0, 35471, 35848, 35477, 35441, 35451, 2601, 35460, 12, 2, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36020, 35471, 0, 35477, 35441, 35451, 2601, 35460, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {2601, 35462, 35403, 35462, 35403, 35462, 36023, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36030, 35471, 0, 35477, 35441, 35451, 2601, 35460, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 36243, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36016, 35471, 36041, 35477, 35441, 35451, 2601, 35460, 12, 2, 2, 2, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36016, 35471, 36067, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 763, 35403, 763, 35403, 36016, 35471, 0, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 763, 35403, 763, 35403, 36016, 35471, 36099, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36016, 35471, 0, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36016, 35471, 36125, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 763, 35403, 763, 35403, 36016, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 12, 2, 2, 2, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36016, 35471, 0, 35477, 35441, 35451, 2601, 35460, 12, 1, 1, 1, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36016, 35471, 36156, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 763, 35403, 763, 35403, 36166, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 2, 0, 1, 1, 1, 2, 2, 2, {3, 0}, {3, 0}, {3, 0}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36171, 35471, 0, 35477, 35441, 35451, 2601, 35460, 1, 0, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 763, 35403, 763, 36174, 35471, 0, 35477, 35441, 35451, 2601, 35460, 5, 1, 1, 1, 2, 2, 2, 2, {3, -1}, {3, 0}, {3, 0}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36178, 35471, 0, 35477, 35441, 35451, 2601, 35460, 4, 1, 0, 0, 0, 0, 2, 2, {3, 0}, {3, 0}, {3, 0}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36016, 35471, 0, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36182, 35471, 0, 35477, 35441, 35451, 2601, 35460, 14, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, 2}, {3, 2}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36190, 35471, 0, 35477, 35441, 35451, 2601, 35460, 1, 0, 1, 1, 1, 2, 1, 1, {3, 0}, {3, 0}, {3, 0}},
+ {763, 35403, 763, 35403, 763, 35403, 36197, 35471, 0, 35477, 35441, 35451, 2601, 35460, 1, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, 2}, {3, 2}},
+ {35405, 35408, 35405, 35408, 35405, 35408, 36210, 35421, 0, 35477, 35441, 35451, 2601, 35460, 3, 0, 4, 2, 3, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36213, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36217, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36217, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35462, 35403, 35462, 10511, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 2, 2, 2, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35534, 35471, 35848, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, 0}, {3, 0}, {3, 0}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36217, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36166, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, 0}, {3, 0}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35481, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35403, 35403, 35403, 35481, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35403, 35403, 35403, 0, 35471, 0, 35477, 35441, 35451, 2601, 35460, 5, 1, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 763, 35403, 763, 36221, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 2, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36171, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35405, 35408, 35405, 35408, 36249, 35421, 35424, 35438, 35441, 35451, 2601, 35460, 3, 2, 0, 0, 3, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35502, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35738, 763, 35738, 763, 35738, 0, 35471, 35473, 35477, 35537, 35548, 2601, 35460, 2, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36171, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35586, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35616, 35624, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35738, 763, 35738, 763, 35738, 0, 35471, 0, 35477, 35588, 35644, 2601, 35460, 2, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35674, 35684, 2601, 35460, 12, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35534, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 35462, 35403, 35462, 35481, 35471, 35473, 35477, 35588, 35644, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35481, 35471, 35848, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 763, 35403, 763, 36259, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35481, 35471, 0, 35477, 35441, 35451, 2601, 35460, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35586, 35471, 0, 35477, 35441, 35451, 2601, 35460, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 36267, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35403, 35403, 35403, 36274, 35471, 36041, 35477, 35441, 35451, 2601, 35460, 12, 2, 2, 2, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {763, 35403, 35403, 35462, 35403, 35462, 36166, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 0, 1, 1, 1, 2, 2, 2, {3, 0}, {3, 0}, {3, 0}},
+ {763, 35403, 35405, 35408, 35405, 35408, 36278, 35421, 35424, 35438, 35441, 35451, 2601, 35460, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35586, 35471, 36228, 35477, 35441, 35451, 2601, 35460, 0, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35537, 35548, 2601, 35460, 9, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35586, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35586, 35471, 35473, 35477, 35616, 35624, 2601, 35460, 15, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35481, 35471, 35848, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35405, 35408, 35405, 35408, 36288, 35421, 35424, 35438, 35441, 35451, 2601, 35460, 3, 0, 0, 0, 3, 3, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 0, 35471, 0, 35477, 35441, 35451, 2601, 35460, 0, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35537, 35548, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35586, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 7774, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35738, 763, 35738, 763, 35738, 0, 35471, 35473, 35477, 35616, 35624, 2601, 35460, 2, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35405, 35408, 35405, 35408, 36298, 35421, 35424, 35438, 35441, 35451, 2601, 35460, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 0, 35471, 36228, 35477, 35441, 35451, 2601, 35460, 0, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35738, 763, 35738, 763, 35738, 0, 35471, 35473, 35477, 35537, 35548, 2601, 35460, 2, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35586, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 36308, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 0, 0, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35616, 35624, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35405, 35408, 35405, 35408, 36312, 35421, 35424, 35438, 35441, 35451, 2601, 35460, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35481, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36322, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 14, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35481, 35471, 35473, 35477, 35616, 35624, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 36326, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35405, 35408, 35405, 35408, 36329, 35421, 35424, 35438, 35441, 35451, 2601, 35460, 3, 2, 0, 0, 3, 3, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 10511, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 2, 2, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35586, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 36339, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35405, 35408, 35405, 35408, 36345, 35421, 35424, 35438, 35441, 35451, 2601, 35460, 3, 2, 0, 0, 3, 3, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35586, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 1, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 36355, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35405, 35408, 35405, 35408, 36361, 35421, 35424, 35438, 35441, 35451, 2601, 35460, 3, 2, 0, 0, 3, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35586, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 14, 2, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 36371, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35405, 35408, 35405, 35408, 36376, 35421, 35424, 35438, 35441, 35451, 2601, 35460, 3, 2, 0, 0, 3, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35586, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36386, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 36390, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35405, 35408, 35405, 35408, 36398, 35421, 35424, 35438, 35441, 35451, 2601, 35460, 3, 2, 0, 0, 3, 3, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35586, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35586, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 2, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35405, 35408, 35405, 35408, 36408, 35421, 35424, 35438, 35441, 35451, 2601, 35460, 3, 2, 0, 0, 3, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35586, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35586, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 14, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35481, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35405, 35408, 35405, 35408, 36418, 35421, 35424, 35438, 35441, 35451, 2601, 35460, 3, 2, 0, 0, 3, 3, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36213, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35586, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 9, 2, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35405, 35408, 35405, 35408, 36428, 35421, 35424, 35438, 35441, 35451, 2601, 35460, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 35586, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 14, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35405, 35408, 35405, 35408, 36438, 35421, 35424, 35438, 35441, 35451, 2601, 35460, 3, 2, 0, 0, 3, 3, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 36448, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 14, 2, 0, 0, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35405, 35408, 35405, 35408, 36452, 35421, 35424, 35438, 35441, 35451, 2601, 35460, 3, 2, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36016, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, 2}, {3, 2}, {3, 2}},
+ {35403, 763, 35403, 763, 35403, 763, 36462, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 14, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36465, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35586, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 0, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 2471, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36469, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 14, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35586, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 14, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 35586, 35471, 35473, 35477, 35588, 35598, 2601, 35460, 0, 0, 0, 0, 1, 2, 2, 2, {3, -1}, {3, 0}, {3, 0}},
+ {35403, 763, 35403, 763, 35403, 763, 36472, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 36480, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 763, 35403, 763, 36259, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36485, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35534, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 0, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 763, 35403, 763, 36238, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 36267, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 0, 35471, 0, 35477, 35441, 35451, 2601, 35460, 5, 1, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36488, 35471, 36228, 35477, 35441, 35451, 2601, 35460, 0, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36488, 35471, 36228, 35477, 35441, 35451, 2601, 35460, 0, 0, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 35534, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 12, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35403, 763, 35403, 763, 35403, 763, 36480, 35471, 35473, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {35981, 35462, 35403, 35403, 35403, 35403, 36023, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 2, 2, 2, {3, 0}, {3, 0}, {3, 0}},
+ {35403, 35462, 35403, 35462, 35403, 35462, 36243, 35471, 0, 35477, 35441, 35451, 2601, 35460, 8, 3, 1, 1, 1, 0, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 35403, 35462, 35403, 35462, 36166, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 0, 1, 1, 1, 2, 2, 2, {3, 0}, {3, 0}, {3, 0}},
+ {763, 35403, 35403, 35462, 35403, 35462, 0, 35471, 0, 35477, 35616, 35624, 2601, 35460, 8, 3, 0, 0, 3, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}},
+ {763, 35403, 763, 35403, 763, 35403, 36217, 35471, 0, 35477, 35441, 35451, 2601, 35460, 2, 2, 0, 0, 1, 2, 2, 2, {3, -1}, {3, -1}, {3, -1}}
};
static const CultureInfoEntry culture_entries [] = {
- {0x0001, 0x007F, 768, -1, 36490, 36493, 36500, 36515, 36519, 36490, 0, {0, 0, 36523, 0}, 0, 0, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x0002, 0x007F, 257, -1, 36551, 36554, 36564, 36583, 36587, 36551, 0, {36591, 0, 0, 0}, 1, 1, { 1251, 21025, 10007, 866, 0, ';' }},
- {0x0003, 0x007F, 257, -1, 36633, 36636, 36644, 36652, 36656, 36633, 0, {36660, 0, 0, 0}, 2, 2, { 1252, 500, 10000, 850, 0, ';' }},
- {0x0004, 0x0004, 257, -1, 36680, 36687, 36715, 36722, 36726, 36730, 0, {36733, 0, 0, 0}, 3, 3, { 936, 500, 10008, 936, 0, ',' }},
- {0x0004, 0x7804, 257, -1, 36740, 36748, 36715, 36722, 36726, 36730, 0, {36733, 0, 0, 0}, 4, 4, { 936, 500, 10008, 936, 0, ',' }},
- {0x0005, 0x007F, 257, -1, 36769, 36772, 36778, 36788, 36792, 36769, 0, {36796, 0, 0, 0}, 5, 5, { 1250, 500, 10029, 852, 0, ';' }},
- {0x0006, 0x007F, 257, -1, 36822, 36825, 36832, 36838, 36842, 36822, 0, {36846, 0, 0, 0}, 6, 6, { 1252, 20277, 10000, 850, 0, ';' }},
- {0x0007, 0x007F, 257, -1, 36867, 36870, 36877, 36885, 36889, 36867, 0, {36893, 0, 0, 0}, 7, 7, { 1252, 20273, 10000, 850, 0, ';' }},
- {0x0008, 0x007F, 257, -1, 36918, 36921, 36927, 36944, 36948, 36918, 0, {36952, 0, 0, 0}, 8, 8, { 1253, 20273, 10006, 737, 0, ';' }},
- {0x0009, 0x007F, 257, -1, 36994, 36997, 36997, 37005, 37009, 36994, 0, {37013, 0, 0, 0}, 9, 9, { 1252, 37, 10000, 437, 0, ',' }},
- {0x000A, 0x007F, 257, -1, 37032, 37035, 37043, 37052, 37056, 37032, 0, {37060, 0, 0, 0}, 10, 10, { 1252, 20284, 10000, 850, 0, ';' }},
- {0x000B, 0x007F, 257, -1, 37082, 37085, 37093, 37099, 37103, 37082, 0, {37107, 0, 0, 0}, 11, 11, { 1252, 20278, 10000, 850, 0, ';' }},
- {0x000C, 0x007F, 257, -1, 37132, 37135, 37142, 37152, 37156, 37132, 0, {37160, 0, 0, 0}, 12, 12, { 1252, 20297, 10000, 850, 0, ';' }},
- {0x000D, 0x007F, 257, -1, 37182, 37185, 37192, 37203, 37207, 37182, 0, {37211, 0, 0, 0}, 13, 13, { 1255, 500, 10005, 862, 1, ',' }},
- {0x000E, 0x007F, 257, -1, 37244, 37247, 37257, 37264, 37268, 37244, 0, {37272, 0, 0, 0}, 14, 14, { 1250, 500, 10029, 852, 0, ';' }},
- {0x000F, 0x007F, 257, -1, 37288, 37291, 37301, 37311, 37315, 37288, 0, {37319, 0, 0, 0}, 15, 15, { 1252, 20871, 10079, 850, 0, ';' }},
- {0x0010, 0x007F, 257, -1, 37339, 37342, 37350, 37359, 37363, 37339, 0, {37060, 0, 0, 0}, 16, 16, { 1252, 20280, 10000, 850, 0, ';' }},
- {0x0011, 0x007F, 257, -1, 37367, 37370, 37379, 37389, 37393, 37367, 0, {37397, 0, 0, 0}, 17, 17, { 932, 20290, 10001, 932, 0, ',' }},
- {0x0012, 0x007F, 257, -1, 37424, 37427, 37434, 37444, 37448, 37424, 0, {37452, 0, 0, 0}, 18, 18, { 949, 20833, 10003, 949, 0, ',' }},
- {0x0013, 0x007F, 257, -1, 37462, 37465, 37471, 37482, 37486, 37462, 0, {37490, 0, 0, 0}, 19, 19, { 1252, 500, 10000, 850, 0, ';' }},
- {0x0014, 0x007F, 257, -1, 37512, 37515, 37525, 37531, 37535, 37539, 0, {36846, 0, 0, 0}, 20, 20, { 1252, 20277, 10000, 850, 0, ';' }},
- {0x0015, 0x007F, 257, -1, 37542, 37545, 37552, 37559, 37563, 37542, 0, {37567, 0, 0, 0}, 21, 21, { 1250, 20880, 10029, 852, 0, ';' }},
- {0x0016, 0x007F, 257, -1, 37591, 37594, 37605, 37616, 37620, 37591, 0, {37624, 0, 0, 0}, 22, 22, { 1252, 500, 10000, 850, 0, ';' }},
- {0x0017, 0x007F, 257, -1, 37647, 37650, 37658, 37668, 37672, 37647, 0, {37676, 0, 0, 0}, 23, 23, { 1252, 20273, 10000, 850, 0, ';' }},
- {0x0018, 0x007F, 257, -1, 37696, 37699, 37708, 37717, 37721, 37696, 0, {37725, 0, 0, 0}, 24, 24, { 1250, 20880, 10029, 852, 0, ';' }},
- {0x0019, 0x007F, 257, -1, 37744, 37747, 37755, 37770, 37774, 37744, 0, {37778, 0, 0, 0}, 25, 25, { 1251, 20880, 10007, 866, 0, ';' }},
- {0x001A, 0x007F, 257, -1, 37824, 37827, 37836, 37845, 37849, 37824, 0, {37853, 0, 0, 0}, 26, 26, { 1250, 500, 10082, 852, 0, ';' }},
- {0x001B, 0x007F, 257, -1, 37876, 37879, 37886, 37898, 37902, 37876, 0, {37906, 0, 0, 0}, 27, 27, { 1250, 20880, 10029, 852, 0, ';' }},
- {0x001C, 0x007F, 257, -1, 37930, 37933, 37942, 37948, 37952, 37930, 0, {0, 0, 0, 0}, 28, 28, { 1250, 20880, 10029, 852, 0, ';' }},
- {0x001D, 0x007F, 257, -1, 37956, 37959, 37967, 37975, 37979, 37956, 0, {36846, 0, 0, 0}, 29, 29, { 1252, 20278, 10000, 850, 0, ';' }},
- {0x001E, 0x007F, 512, -1, 37983, 37986, 37991, 38001, 38005, 37983, 0, {0, 38009, 0, 0}, 30, 30, { 874, 20838, 10021, 874, 0, ',' }},
- {0x001F, 0x007F, 257, -1, 38040, 38043, 38051, 38060, 38064, 38040, 0, {38068, 0, 0, 0}, 31, 31, { 1254, 20905, 10081, 857, 0, ';' }},
- {0x0020, 0x007F, 257, -1, 38082, 38085, 38090, 38099, 38103, 38082, 0, {38107, 0, 0, 0}, 32, 32, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x0021, 0x007F, 257, -1, 38137, 38140, 38151, 38168, 38172, 38137, 0, {38176, 0, 0, 0}, 33, 33, { 1252, 500, 10000, 850, 0, ';' }},
- {0x0022, 0x007F, 257, -1, 38195, 38198, 38208, 38229, 38233, 38195, 0, {38237, 0, 0, 0}, 34, 34, { 1251, 500, 10017, 866, 0, ';' }},
- {0x0023, 0x007F, 257, -1, 38283, 38286, 38297, 38318, 38322, 38283, 0, {38326, 0, 0, 0}, 35, 35, { 1251, 500, 10007, 866, 0, ';' }},
- {0x0024, 0x007F, 257, -1, 38368, 38371, 38381, 38395, 38399, 38368, 0, {38403, 0, 0, 0}, 36, 36, { 1250, 20880, 10029, 852, 0, ';' }},
- {0x0025, 0x007F, 257, -1, 38425, 38428, 38437, 38443, 38447, 38425, 0, {38451, 0, 0, 0}, 37, 37, { 1257, 500, 10029, 775, 0, ';' }},
- {0x0026, 0x007F, 257, -1, 38471, 38474, 38482, 38492, 38496, 38471, 0, {38500, 0, 0, 0}, 38, 38, { 1257, 500, 10029, 775, 0, ';' }},
- {0x0027, 0x007F, 257, -1, 38519, 38522, 38533, 38543, 38547, 38519, 0, {38551, 0, 0, 0}, 39, 39, { 1257, 500, 10029, 775, 0, ';' }},
- {0x0028, 0x007F, 257, -1, 38574, 38577, 0, 38583, 38587, 38574, 0, {0, 0, 0, 0}, 40, 40, { 1251, 20880, 10007, 866, 0, ';' }},
- {0x0029, 0x007F, 257, -1, 38591, 38594, 38602, 38613, 38617, 38591, 0, {38621, 0, 0, 0}, 41, 41, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x002A, 0x007F, 257, -1, 38645, 38648, 38659, 38674, 4121, 38645, 0, {38678, 0, 0, 0}, 42, 42, { 1258, 500, 10000, 1258, 0, ',' }},
- {0x002B, 0x007F, 257, -1, 38693, 38696, 38705, 38720, 38724, 38693, 0, {0, 0, 0, 0}, 43, 43, { 0, 500, 2, 1, 0, ',' }},
- {0x002C, 0x007F, 257, -1, 14519, 38728, 38740, 38754, 38758, 14519, 0, {38762, 0, 0, 0}, 44, 44, { 1254, 20905, 10081, 857, 0, ';' }},
- {0x002D, 0x007F, 257, -1, 38780, 38783, 38790, 38798, 38802, 38780, 0, {38806, 0, 0, 0}, 45, 45, { 1252, 500, 10000, 850, 0, ';' }},
- {0x002F, 0x007F, 257, -1, 38826, 38829, 38840, 38861, 38865, 38826, 0, {38869, 0, 0, 0}, 46, 46, { 1251, 500, 10007, 866, 0, ';' }},
- {0x0032, 0x007F, 257, -1, 38913, 38916, 38923, 38932, 38936, 38913, 0, {0, 0, 0, 0}, 47, 47, { 1252, 500, 10000, 850, 0, ',' }},
- {0x0034, 0x007F, 257, -1, 38940, 38943, 38949, 38958, 38962, 38940, 0, {0, 0, 0, 0}, 48, 48, { 1252, 500, 10000, 850, 0, ',' }},
- {0x0035, 0x007F, 257, -1, 38966, 38969, 38974, 38982, 38986, 38966, 0, {38990, 0, 0, 0}, 49, 49, { 1252, 500, 10000, 850, 0, ',' }},
- {0x0036, 0x007F, 257, -1, 39011, 39014, 39014, 39024, 39028, 39011, 0, {39032, 0, 0, 0}, 50, 50, { 1252, 500, 10000, 850, 0, ',' }},
- {0x0037, 0x007F, 257, -1, 39052, 39055, 39064, 39086, 39090, 39052, 0, {39094, 0, 0, 0}, 51, 51, { 0, 500, 2, 1, 0, ';' }},
- {0x0038, 0x007F, 257, -1, 39159, 39162, 39170, 39180, 39184, 39159, 0, {0, 0, 0, 0}, 52, 52, { 1252, 20277, 10079, 850, 0, ';' }},
- {0x0039, 0x007F, 257, -1, 39188, 39191, 39197, 39216, 39220, 39188, 0, {39224, 0, 0, 0}, 53, 53, { 0, 500, 2, 1, 0, ',' }},
- {0x003A, 0x007F, 257, -1, 39265, 39268, 39276, 39282, 39286, 39265, 0, {39290, 0, 0, 0}, 54, 54, { 0, 500, 2, 1, 0, ',' }},
- {0x003B, 0x007F, 257, -1, 39311, 39314, 39328, 39345, 39349, 39311, 0, {0, 0, 0, 0}, 55, 55, { 1252, 20277, 10000, 850, 0, ';' }},
- {0x003C, 0x007F, 257, -1, 39353, 39356, 39362, 39370, 39374, 39353, 0, {39378, 0, 0, 0}, 56, 56, { 1252, 500, 10000, 850, 0, ',' }},
- {0x003E, 0x007F, 257, -1, 39399, 39402, 39408, 39422, 39426, 39399, 0, {39430, 0, 0, 0}, 57, 57, { 1252, 500, 10000, 850, 0, ';' }},
- {0x003F, 0x007F, 257, -1, 39447, 39450, 39457, 39477, 39481, 39447, 0, {39485, 0, 0, 0}, 58, 58, { 0, 500, 2, 1, 0, ';' }},
- {0x0040, 0x007F, 257, -1, 39527, 39530, 39538, 39551, 39555, 39527, 0, {0, 0, 0, 0}, 59, 59, { 1251, 20880, 10007, 866, 0, ';' }},
- {0x0041, 0x007F, 257, -1, 39559, 39562, 39570, 39580, 39584, 39559, 0, {39588, 0, 0, 0}, 60, 60, { 1252, 500, 10000, 437, 0, ',' }},
- {0x0043, 0x007F, 257, -1, 39609, 39612, 39618, 39629, 39633, 39609, 0, {0, 0, 0, 0}, 61, 61, { 1254, 500, 10029, 857, 0, ';' }},
- {0x0045, 0x007F, 257, -1, 39637, 39640, 39648, 39664, 39668, 39637, 0, {39672, 0, 0, 0}, 62, 62, { 0, 500, 2, 1, 0, ',' }},
- {0x0046, 0x007F, 257, -1, 39737, 39740, 39748, 39767, 39771, 39737, 0, {0, 0, 0, 0}, 63, 63, { 0, 500, 2, 1, 0, ',' }},
- {0x0047, 0x007F, 257, -1, 39775, 39778, 39787, 39809, 39813, 39775, 0, {39817, 0, 0, 0}, 64, 64, { 0, 500, 2, 1, 0, ',' }},
- {0x0048, 0x007F, 257, -1, 14525, 39873, 39879, 39895, 39899, 14525, 0, {0, 0, 0, 0}, 65, 65, { 0, 500, 2, 1, 0, ',' }},
- {0x0049, 0x007F, 257, -1, 39903, 39906, 39912, 39928, 39932, 39903, 0, {39936, 0, 0, 0}, 66, 66, { 0, 500, 2, 1, 0, ',' }},
- {0x004A, 0x007F, 257, -1, 40001, 40004, 40011, 40030, 40034, 40001, 0, {40038, 0, 0, 0}, 67, 67, { 0, 500, 2, 1, 0, ',' }},
- {0x004B, 0x007F, 257, -1, 35839, 40103, 40111, 40127, 40131, 35839, 0, {40135, 0, 0, 0}, 68, 68, { 0, 500, 2, 1, 0, ',' }},
- {0x004C, 0x007F, 257, -1, 40206, 40209, 40219, 40238, 40242, 40206, 0, {40246, 0, 0, 0}, 69, 69, { 0, 500, 2, 1, 0, ',' }},
- {0x004D, 0x007F, 257, -1, 14516, 40296, 40305, 40327, 40331, 14516, 0, {40335, 0, 0, 0}, 70, 70, { 0, 500, 2, 1, 0, ',' }},
- {0x004E, 0x007F, 257, -1, 40388, 40391, 40399, 40415, 2565, 40388, 0, {40419, 0, 0, 0}, 71, 71, { 0, 500, 2, 1, 0, ',' }},
- {0x0050, 0x007F, 257, -1, 40481, 40484, 40494, 40507, 40511, 40481, 0, {0, 0, 0, 0}, 72, 72, { 1251, 20880, 10007, 866, 0, ';' }},
- {0x0051, 0x007F, 257, -1, 40515, 40518, 40526, 40551, 40555, 40515, 0, {0, 0, 0, 0}, 73, 73, { 0, 500, 2, 1, 0, ',' }},
- {0x0052, 0x007F, 257, -1, 40559, 40562, 40568, 40576, 40580, 40559, 0, {0, 0, 0, 0}, 74, 74, { 1252, 20285, 10000, 850, 0, ',' }},
- {0x0053, 0x007F, 257, -1, 40584, 40587, 40593, 40621, 40625, 40584, 0, {0, 0, 0, 0}, 75, 75, { 0, 500, 2, 1, 0, ',' }},
- {0x0054, 0x007F, 257, -1, 40629, 40632, 40636, 40646, 40650, 40629, 0, {0, 0, 0, 0}, 76, 76, { 0, 500, 2, 1, 0, ',' }},
- {0x0056, 0x007F, 257, -1, 40654, 40657, 40666, 40673, 40677, 40654, 0, {37060, 0, 0, 0}, 77, 77, { 1252, 500, 10000, 850, 0, ';' }},
- {0x0057, 0x007F, 257, -1, 40681, 40685, 40693, 40712, 40681, 40681, 0, {0, 0, 0, 0}, 78, 78, { 0, 500, 2, 1, 0, ',' }},
- {0x005B, 0x007F, 257, -1, 40716, 40719, 40727, 40743, 40747, 40716, 0, {40751, 0, 0, 0}, 79, 79, { 0, 500, 2, 1, 0, ',' }},
- {0x005E, 0x007F, 257, -1, 7865, 40773, 40781, 40794, 40798, 7865, 0, {40802, 0, 0, 0}, 80, 80, { 0, 500, 2, 1, 0, ';' }},
- {0x005F, 0x007F, 257, -1, 40847, 40851, 40877, 40887, 40847, 40847, 0, {0, 0, 0, 0}, 81, 81, { 1252, 20297, 10000, 850, 0, ';' }},
- {0x0061, 0x007F, 257, -1, 2059, 40891, 40898, 40917, 40921, 2059, 0, {40925, 0, 0, 0}, 82, 82, { 0, 500, 2, 1, 0, ',' }},
- {0x0063, 0x007F, 1024, -1, 40975, 40978, 40985, 40994, 40998, 40975, 0, {0, 0, 0, 0}, 83, 83, { 0, 500, 2, 1, 1, ';' }},
- {0x0064, 0x007F, 257, -1, 41002, 41006, 41006, 41015, 41002, 41002, 0, {41019, 0, 0, 0}, 84, 84, { 1252, 500, 10000, 437, 0, ',' }},
- {0x0068, 0x007F, 257, -1, 41042, 41045, 41045, 41051, 41055, 41042, 0, {0, 0, 0, 0}, 85, 85, { 1252, 37, 10000, 437, 0, ',' }},
- {0x006A, 0x007F, 257, -1, 41059, 41062, 41069, 41084, 41088, 41059, 0, {0, 0, 0, 0}, 86, 86, { 1252, 37, 10000, 437, 0, ',' }},
- {0x006C, 0x007F, 257, -1, 41092, 41096, 41111, 41128, 41092, 41092, 0, {0, 0, 0, 0}, 87, 87, { 1252, 500, 10000, 850, 0, ',' }},
- {0x006F, 0x007F, 257, -1, 41132, 41135, 41147, 41159, 41163, 41132, 0, {0, 0, 0, 0}, 88, 88, { 1252, 20277, 10000, 850, 0, ';' }},
- {0x0070, 0x007F, 257, -1, 14510, 41167, 41167, 41172, 41176, 14510, 0, {0, 0, 0, 0}, 89, 89, { 1252, 37, 10000, 437, 0, ',' }},
- {0x0078, 0x007F, 257, -1, 41180, 41183, 41194, 41204, 41208, 41180, 0, {41212, 0, 0, 0}, 90, 90, { 0, 500, 2, 1, 0, ',' }},
- {0x007E, 0x007F, 257, -1, 41225, 41228, 41235, 41245, 41249, 41225, 0, {41253, 0, 0, 0}, 91, 91, { 1252, 20297, 10000, 850, 0, ';' }},
- {0x0082, 0x007F, 257, -1, 41273, 41276, 41284, 41292, 41296, 41273, 0, {0, 0, 0, 0}, 92, 92, { 1252, 20297, 10000, 850, 0, ';' }},
- {0x0084, 0x007F, 257, -1, 41300, 41304, 41317, 41336, 41300, 41300, 0, {41340, 0, 0, 0}, 93, 93, { 1252, 20297, 10000, 850, 0, ';' }},
- {0x0085, 0x007F, 257, -1, 41365, 41369, 41375, 41393, 41365, 41365, 0, {0, 0, 0, 0}, 94, 94, { 1251, 20880, 10007, 866, 0, ';' }},
- {0x0087, 0x007F, 257, -1, 41397, 41400, 41400, 41412, 41416, 41397, 0, {0, 0, 0, 0}, 95, 95, { 1252, 37, 10000, 437, 0, ';' }},
- {0x0091, 0x007F, 257, -1, 41420, 41423, 41439, 41449, 41453, 41420, 0, {41457, 0, 0, 0}, 96, 96, { 1252, 20285, 10000, 850, 0, ',' }},
- {0x0401, 0x0001, 768, 98, 41482, 41488, 41510, 36515, 36519, 36490, 13258, {0, 0, 36523, 0}, 97, 97, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x0402, 0x0002, 257, 11, 41574, 41580, 41601, 36583, 36587, 36551, 41639, {36591, 0, 0, 0}, 98, 98, { 1251, 21025, 10007, 866, 0, ';' }},
- {0x0403, 0x0003, 257, 32, 41642, 41648, 41664, 36652, 36656, 36633, 41682, {36660, 0, 0, 0}, 99, 99, { 1252, 500, 10000, 850, 0, ';' }},
- {0x0404, 0x7C04, 257, 110, 41685, 41691, 41713, 41729, 36726, 36730, 41733, {41736, 0, 0, 0}, 100, 100, { 950, 500, 10002, 950, 0, ',' }},
- {0x0405, 0x0005, 257, 24, 41743, 41749, 41772, 36788, 36792, 36769, 41802, {36796, 0, 0, 0}, 101, 101, { 1250, 500, 10029, 852, 0, ';' }},
- {0x0406, 0x0006, 257, 26, 41805, 41811, 41828, 36838, 36842, 36822, 41844, {36846, 0, 0, 0}, 102, 102, { 1252, 20277, 10000, 850, 0, ';' }},
- {0x0407, 0x0007, 257, 25, 41847, 41853, 41870, 36885, 36889, 36867, 41892, {36893, 0, 0, 0}, 103, 103, { 1252, 20273, 10000, 850, 0, ';' }},
- {0x0408, 0x0008, 257, 40, 41895, 41901, 41916, 36944, 36948, 36918, 41948, {36952, 0, 0, 0}, 104, 104, { 1253, 20273, 10006, 737, 0, ';' }},
- {0x0409, 0x0009, 257, 112, 41951, 41957, 41957, 37005, 37009, 36994, 41981, {37013, 0, 0, 0}, 105, 105, { 1252, 37, 10000, 437, 0, ',' }},
- {0x040B, 0x000B, 257, 34, 41984, 41990, 42008, 37099, 37103, 37082, 42022, {37107, 0, 0, 0}, 106, 106, { 1252, 20278, 10000, 850, 0, ';' }},
- {0x040C, 0x000C, 257, 36, 42025, 42031, 42047, 37152, 37156, 37132, 42066, {37160, 0, 0, 0}, 107, 107, { 1252, 20297, 10000, 850, 0, ';' }},
- {0x040D, 0x000D, 257, 48, 42069, 42075, 42091, 37203, 37207, 37182, 42115, {37211, 0, 0, 0}, 108, 108, { 1255, 500, 10005, 862, 1, ',' }},
- {0x040E, 0x000E, 257, 45, 42118, 42124, 42144, 37264, 37268, 37244, 42167, {37272, 0, 0, 0}, 109, 109, { 1250, 500, 10029, 852, 0, ';' }},
- {0x040F, 0x000F, 257, 52, 42170, 42176, 42196, 37311, 37315, 37288, 42216, {37319, 0, 0, 0}, 110, 110, { 1252, 20871, 10079, 850, 0, ';' }},
- {0x0410, 0x0010, 257, 53, 42219, 42225, 42241, 37359, 37363, 37339, 42259, {37060, 0, 0, 0}, 111, 111, { 1252, 20280, 10000, 850, 0, ';' }},
- {0x0411, 0x0011, 257, 56, 42262, 42268, 42285, 37389, 37393, 37367, 42304, {37397, 0, 0, 0}, 112, 112, { 932, 20290, 10001, 932, 0, ',' }},
- {0x0412, 0x0012, 257, 60, 42307, 42313, 42334, 37444, 37448, 37424, 42359, {37452, 0, 0, 0}, 113, 113, { 949, 20833, 10003, 949, 0, ',' }},
- {0x0413, 0x0013, 257, 80, 42362, 42368, 42388, 37482, 37486, 37462, 42411, {37490, 0, 0, 0}, 114, 114, { 1252, 500, 10000, 850, 0, ';' }},
- {0x0414, 0x7C14, 257, 81, 42414, 42420, 42447, 37531, 37535, 37539, 42469, {36846, 0, 0, 0}, 115, 115, { 1252, 20277, 10000, 850, 0, ';' }},
- {0x0415, 0x0015, 257, 89, 42472, 42478, 42494, 37559, 37563, 37542, 42510, {37567, 0, 0, 0}, 116, 116, { 1250, 20880, 10029, 852, 0, ';' }},
- {0x0416, 0x0016, 257, 15, 42513, 42519, 42539, 37616, 37620, 37591, 42559, {37624, 0, 0, 0}, 117, 117, { 1252, 500, 10000, 850, 0, ';' }},
- {0x0417, 0x0017, 257, 19, 42562, 42568, 42590, 37668, 37672, 37647, 13261, {37676, 0, 0, 0}, 118, 118, { 1252, 20273, 10000, 850, 0, ';' }},
- {0x0418, 0x0018, 257, 94, 42609, 42615, 42634, 37717, 37721, 37696, 42654, {37725, 0, 0, 0}, 119, 119, { 1250, 20880, 10029, 852, 0, ';' }},
- {0x0419, 0x0019, 257, 96, 42657, 42663, 42680, 37770, 37774, 37744, 42710, {37778, 0, 0, 0}, 120, 120, { 1251, 20880, 10007, 866, 0, ';' }},
- {0x041A, 0x001A, 257, 44, 42713, 42719, 42738, 37845, 37849, 37824, 42758, {37853, 0, 0, 0}, 121, 121, { 1250, 500, 10082, 852, 0, ';' }},
- {0x041B, 0x001B, 257, 102, 42761, 42767, 42785, 37898, 37902, 37876, 42820, {37906, 0, 0, 0}, 122, 122, { 1250, 20880, 10029, 852, 0, ';' }},
- {0x041C, 0x001C, 257, 2, 42823, 42829, 42848, 37948, 37952, 37930, 42867, {0, 0, 0, 0}, 123, 123, { 1250, 20880, 10029, 852, 0, ';' }},
- {0x041D, 0x001D, 257, 99, 42870, 42876, 42893, 37975, 37979, 37956, 42911, {36846, 0, 0, 0}, 124, 124, { 1252, 20278, 10000, 850, 0, ';' }},
- {0x041E, 0x001E, 512, 105, 42914, 42920, 42936, 38001, 38005, 37983, 42958, {0, 38009, 0, 0}, 125, 125, { 874, 20838, 10021, 874, 0, ',' }},
- {0x041F, 0x001F, 257, 108, 42961, 42967, 42984, 38060, 38064, 38040, 43004, {38068, 0, 0, 0}, 126, 126, { 1254, 20905, 10081, 857, 0, ';' }},
- {0x0420, 0x0020, 257, 88, 43007, 43013, 43029, 38099, 38103, 38082, 43055, {38107, 0, 0, 0}, 127, 127, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x0421, 0x0021, 257, 46, 43058, 43064, 43087, 38168, 38172, 38137, 43116, {38176, 0, 0, 0}, 128, 128, { 1252, 500, 10000, 850, 0, ';' }},
- {0x0422, 0x0022, 257, 111, 43119, 43125, 43145, 38229, 38233, 38195, 43183, {38237, 0, 0, 0}, 129, 129, { 1251, 500, 10017, 866, 0, ';' }},
- {0x0423, 0x0023, 257, 16, 43186, 43192, 43213, 38318, 38322, 38283, 43253, {38326, 0, 0, 0}, 130, 130, { 1251, 500, 10007, 866, 0, ';' }},
- {0x0424, 0x0024, 257, 101, 43256, 43262, 43283, 38395, 38399, 38368, 43309, {38403, 0, 0, 0}, 131, 131, { 1250, 20880, 10029, 852, 0, ';' }},
- {0x0425, 0x0025, 257, 30, 43312, 43318, 43337, 38443, 38447, 38425, 43351, {38451, 0, 0, 0}, 132, 132, { 1257, 500, 10029, 775, 0, ';' }},
- {0x0426, 0x0026, 257, 68, 43354, 43360, 43377, 38492, 38496, 38471, 43397, {38500, 0, 0, 0}, 133, 133, { 1257, 500, 10029, 775, 0, ';' }},
- {0x0427, 0x0027, 257, 66, 43400, 43406, 43429, 38543, 38547, 38519, 43449, {38551, 0, 0, 0}, 134, 134, { 1257, 500, 10029, 775, 0, ';' }},
- {0x0428, 0x7C28, 257, 106, 43452, 43463, 0, 38583, 38587, 38574, 43492, {0, 0, 0, 0}, 135, 135, { 1251, 20880, 10007, 866, 0, ';' }},
- {0x0429, 0x0029, 257, 51, 43495, 43501, 43516, 38613, 38617, 38591, 43540, {38621, 0, 0, 0}, 136, 136, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x042A, 0x002A, 257, 116, 43543, 43549, 43570, 38674, 4121, 38645, 43598, {38678, 0, 0, 0}, 137, 137, { 1258, 500, 10000, 1258, 0, ',' }},
- {0x042B, 0x002B, 257, 3, 43601, 43607, 43626, 38720, 38724, 38693, 3781, {0, 0, 0, 0}, 138, 138, { 0, 500, 2, 1, 0, ',' }},
- {0x042C, 0x782C, 257, 7, 43691, 43702, 43734, 38754, 38758, 14519, 43762, {38762, 0, 0, 0}, 139, 139, { 1254, 20905, 10081, 857, 0, ';' }},
- {0x042D, 0x002D, 257, 32, 43765, 43771, 43786, 38798, 38802, 38780, 41682, {38806, 0, 0, 0}, 140, 140, { 1252, 500, 10000, 850, 0, ';' }},
- {0x042F, 0x002F, 257, 73, 43805, 43811, 43834, 38861, 38865, 38826, 43878, {38869, 0, 0, 0}, 141, 141, { 1251, 500, 10007, 866, 0, ';' }},
- {0x0432, 0x0032, 257, 118, 43881, 43887, 38923, 38932, 38936, 38913, 43909, {0, 0, 0, 0}, 142, 142, { 1252, 500, 10000, 850, 0, ',' }},
- {0x0434, 0x0034, 257, 118, 43912, 43918, 38949, 38958, 38962, 38940, 43909, {0, 0, 0, 0}, 143, 143, { 1252, 500, 10000, 850, 0, ',' }},
- {0x0435, 0x0035, 257, 118, 43939, 43945, 43965, 38982, 38986, 38966, 43909, {38990, 0, 0, 0}, 144, 144, { 1252, 500, 10000, 850, 0, ',' }},
- {0x0436, 0x0036, 257, 118, 43993, 43999, 44024, 39024, 39028, 39011, 43909, {39032, 0, 0, 0}, 145, 145, { 1252, 500, 10000, 850, 0, ',' }},
- {0x0437, 0x0037, 257, 38, 44048, 44054, 44073, 39086, 39090, 39052, 44128, {39094, 0, 0, 0}, 146, 146, { 0, 500, 2, 1, 0, ';' }},
- {0x0438, 0x0038, 257, 35, 44131, 44137, 44161, 39180, 39184, 39159, 44182, {0, 0, 0, 0}, 147, 147, { 1252, 20277, 10079, 850, 0, ';' }},
- {0x0439, 0x0039, 257, 49, 44185, 44191, 44205, 39216, 39220, 39188, 44239, {39224, 0, 0, 0}, 148, 148, { 0, 500, 2, 1, 0, ',' }},
- {0x043A, 0x003A, 257, 75, 44242, 44248, 44264, 39282, 39286, 39265, 44278, {39290, 0, 0, 0}, 149, 149, { 0, 500, 2, 1, 0, ',' }},
- {0x043B, 0x003B, 257, 81, 44281, 44287, 44310, 39345, 39349, 39311, 42469, {0, 0, 0, 0}, 150, 150, { 1252, 20277, 10000, 850, 0, ';' }},
- {0x043E, 0x003E, 257, 77, 44335, 44341, 44358, 39422, 39426, 39399, 44383, {39430, 0, 0, 0}, 151, 151, { 1252, 500, 10000, 850, 0, ';' }},
- {0x0440, 0x0040, 257, 58, 44386, 44392, 44413, 39551, 39555, 39527, 44449, {0, 0, 0, 0}, 152, 152, { 1251, 20880, 10007, 866, 0, ';' }},
- {0x0441, 0x0041, 257, 57, 44452, 44458, 44474, 39580, 39584, 39559, 44492, {39588, 0, 0, 0}, 153, 153, { 1252, 500, 10000, 437, 0, ',' }},
- {0x0443, 0x7C43, 257, 114, 44495, 44506, 44532, 39629, 39633, 39609, 44566, {0, 0, 0, 0}, 154, 154, { 1254, 500, 10029, 857, 0, ';' }},
- {0x0445, 0x0045, 257, 49, 44569, 44575, 44591, 39664, 39668, 39637, 44239, {39672, 0, 0, 0}, 155, 155, { 0, 500, 2, 1, 0, ',' }},
- {0x0447, 0x0047, 257, 49, 44622, 44628, 44645, 39809, 39813, 39775, 44239, {39817, 0, 0, 0}, 156, 156, { 0, 500, 2, 1, 0, ',' }},
- {0x0448, 0x0048, 257, 49, 44682, 44688, 44702, 39895, 39899, 14525, 44239, {0, 0, 0, 0}, 157, 157, { 0, 500, 2, 1, 0, ',' }},
- {0x0449, 0x0049, 257, 49, 44733, 44739, 44753, 39928, 39932, 39903, 44239, {39936, 0, 0, 0}, 158, 158, { 0, 500, 2, 1, 0, ',' }},
- {0x044A, 0x004A, 257, 49, 44793, 44799, 44814, 40030, 40034, 40001, 44239, {40038, 0, 0, 0}, 159, 159, { 0, 500, 2, 1, 0, ',' }},
- {0x044B, 0x004B, 257, 49, 44861, 44867, 44883, 40127, 40131, 35839, 44239, {40135, 0, 0, 0}, 160, 160, { 0, 500, 2, 1, 0, ',' }},
- {0x044C, 0x004C, 257, 49, 44914, 44920, 44938, 40238, 40242, 40206, 44239, {40246, 0, 0, 0}, 161, 161, { 0, 500, 2, 1, 0, ',' }},
- {0x044D, 0x004D, 257, 49, 44978, 44984, 45001, 40327, 40331, 14516, 44239, {40335, 0, 0, 0}, 162, 162, { 0, 500, 2, 1, 0, ',' }},
- {0x044E, 0x004E, 257, 49, 45038, 45044, 45060, 40415, 2565, 40388, 44239, {40419, 0, 0, 0}, 163, 163, { 0, 500, 2, 1, 0, ',' }},
- {0x0451, 0x0051, 257, 21, 45091, 45097, 45113, 40551, 40555, 40515, 13340, {0, 0, 0, 0}, 164, 164, { 0, 500, 2, 1, 0, ',' }},
- {0x0452, 0x0052, 257, 37, 45159, 45165, 45188, 40576, 40580, 40559, 45211, {0, 0, 0, 0}, 165, 165, { 1252, 20285, 10000, 850, 0, ',' }},
- {0x0453, 0x0053, 257, 59, 45214, 45220, 45237, 40621, 40625, 40584, 45289, {0, 0, 0, 0}, 166, 166, { 0, 500, 2, 1, 0, ',' }},
- {0x0454, 0x0054, 257, 62, 45292, 45298, 45309, 40646, 40650, 40629, 45331, {0, 0, 0, 0}, 167, 167, { 0, 500, 2, 1, 0, ',' }},
- {0x0456, 0x0056, 257, 32, 45334, 45340, 45357, 40673, 40677, 40654, 41682, {37060, 0, 0, 0}, 168, 168, { 1252, 500, 10000, 850, 0, ';' }},
- {0x0457, 0x0057, 257, 49, 45374, 45381, 45397, 40712, 40681, 40681, 44239, {0, 0, 0, 0}, 169, 169, { 0, 500, 2, 1, 0, ',' }},
- {0x045B, 0x005B, 257, 65, 45431, 45437, 45457, 40743, 40747, 40716, 45507, {40751, 0, 0, 0}, 170, 170, { 0, 500, 2, 1, 0, ',' }},
- {0x045E, 0x005E, 257, 33, 45510, 45516, 45535, 40794, 40798, 7865, 45566, {40802, 0, 0, 0}, 171, 171, { 0, 500, 2, 1, 0, ';' }},
- {0x0461, 0x0061, 257, 82, 45569, 45575, 45590, 40917, 40921, 2059, 45627, {40925, 0, 0, 0}, 172, 172, { 0, 500, 2, 1, 0, ',' }},
- {0x0463, 0x0063, 1024, 1, 45630, 45636, 45657, 40994, 40998, 40975, 45687, {0, 0, 0, 0}, 173, 173, { 0, 500, 2, 1, 1, ';' }},
- {0x0464, 0x0064, 257, 87, 45690, 45697, 45720, 41015, 41002, 41002, 45741, {41019, 0, 0, 0}, 174, 174, { 1252, 500, 10000, 437, 0, ',' }},
- {0x0468, 0x7C68, 257, 78, 45744, 45755, 45778, 41051, 41055, 41042, 45795, {0, 0, 0, 0}, 175, 175, { 1252, 37, 10000, 437, 0, ',' }},
- {0x046A, 0x006A, 257, 78, 45798, 45804, 45821, 41084, 41088, 41059, 45795, {0, 0, 0, 0}, 176, 176, { 1252, 37, 10000, 437, 0, ',' }},
- {0x046C, 0x006C, 257, 118, 45867, 45874, 41111, 41128, 41092, 41092, 43909, {0, 0, 0, 0}, 177, 177, { 1252, 500, 10000, 850, 0, ',' }},
- {0x046F, 0x006F, 257, 39, 45904, 45910, 45934, 41159, 41163, 41132, 45965, {0, 0, 0, 0}, 178, 178, { 1252, 20277, 10000, 850, 0, ';' }},
- {0x0470, 0x0070, 257, 78, 45968, 45974, 45974, 41172, 41176, 14510, 45795, {0, 0, 0, 0}, 179, 179, { 1252, 37, 10000, 437, 0, ',' }},
- {0x0478, 0x0078, 257, 21, 45989, 45995, 46014, 41204, 41208, 41180, 13340, {41212, 0, 0, 0}, 180, 180, { 0, 500, 2, 1, 0, ',' }},
- {0x047E, 0x007E, 257, 36, 46033, 46039, 46055, 41245, 41249, 41225, 42066, {41253, 0, 0, 0}, 181, 181, { 1252, 20297, 10000, 850, 0, ';' }},
- {0x0482, 0x0082, 257, 36, 46074, 46080, 46097, 41292, 41296, 41273, 42066, {0, 0, 0, 0}, 182, 182, { 1252, 20297, 10000, 850, 0, ';' }},
- {0x0485, 0x0085, 257, 96, 46115, 46122, 41375, 41393, 41365, 41365, 42710, {0, 0, 0, 0}, 183, 183, { 1251, 20880, 10007, 866, 0, ';' }},
- {0x0487, 0x0087, 257, 97, 46137, 46143, 46143, 41412, 41416, 41397, 46164, {0, 0, 0, 0}, 184, 184, { 1252, 37, 10000, 437, 0, ';' }},
- {0x0491, 0x0091, 257, 37, 46167, 46173, 46206, 41449, 41453, 41420, 45211, {41457, 0, 0, 0}, 185, 185, { 1252, 20285, 10000, 850, 0, ',' }},
- {0x0801, 0x0001, 257, 50, 46242, 46248, 46262, 46292, 36519, 36490, 46296, {36523, 0, 0, 0}, 186, 186, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x0804, 0x0004, 257, 21, 46299, 36748, 46305, 36722, 36726, 36730, 13340, {36733, 0, 0, 0}, 187, 187, { 936, 500, 10008, 936, 0, ',' }},
- {0x0807, 0x0007, 257, 19, 46321, 46327, 46348, 46366, 36889, 36867, 13261, {36893, 0, 0, 0}, 188, 188, { 1252, 20273, 10000, 850, 0, ';' }},
- {0x0809, 0x0009, 257, 37, 46370, 46376, 46376, 46401, 37009, 36994, 45211, {37013, 0, 0, 0}, 189, 189, { 1252, 20285, 10000, 850, 0, ',' }},
- {0x080A, 0x000A, 257, 76, 46405, 46411, 46428, 46447, 37056, 37032, 46451, {37060, 0, 0, 0}, 190, 190, { 1252, 20284, 10000, 850, 0, ',' }},
- {0x080C, 0x000C, 257, 10, 46454, 46460, 46477, 46498, 37156, 37132, 46502, {37160, 0, 0, 0}, 191, 191, { 1252, 20297, 10000, 850, 0, ';' }},
- {0x0810, 0x0010, 257, 19, 46505, 46511, 46533, 46553, 37363, 37339, 13261, {37060, 0, 0, 0}, 192, 192, { 1252, 500, 10000, 850, 0, ';' }},
- {0x0813, 0x0013, 257, 10, 46557, 46563, 46579, 46600, 37486, 37462, 46502, {37490, 0, 0, 0}, 193, 193, { 1252, 500, 10000, 850, 0, ';' }},
- {0x0814, 0x7814, 257, 81, 46604, 46610, 46637, 46653, 46657, 46661, 42469, {36846, 0, 0, 0}, 194, 194, { 1252, 20277, 10000, 850, 0, ';' }},
- {0x0816, 0x0016, 257, 91, 46664, 46670, 46692, 46714, 37620, 37591, 46718, {37624, 0, 0, 0}, 195, 195, { 1252, 500, 10000, 850, 0, ';' }},
- {0x081D, 0x001D, 257, 34, 46721, 46727, 46745, 46763, 37979, 37956, 42022, {36846, 0, 0, 0}, 196, 196, { 1252, 20278, 10000, 850, 0, ';' }},
- {0x082C, 0x742C, 257, 7, 46767, 46778, 43734, 46813, 38758, 14519, 43762, {38762, 0, 0, 0}, 197, 197, { 1251, 20880, 10007, 866, 0, ';' }},
- {0x083C, 0x003C, 257, 47, 46817, 46823, 46839, 39370, 39374, 39353, 46855, {39378, 0, 0, 0}, 198, 198, { 1252, 500, 10000, 850, 0, ',' }},
- {0x083E, 0x003E, 257, 13, 46858, 46864, 46879, 46902, 39426, 39399, 46906, {39430, 0, 0, 0}, 199, 199, { 1252, 500, 10000, 850, 0, ';' }},
- {0x0843, 0x7843, 257, 114, 46909, 46920, 44532, 39629, 39633, 39609, 44566, {0, 0, 0, 0}, 200, 200, { 1251, 20880, 10007, 866, 0, ';' }},
- {0x0845, 0x0045, 257, 9, 46949, 46955, 46976, 47019, 39668, 39637, 47023, {39672, 0, 0, 0}, 201, 201, { 0, 500, 2, 1, 0, ',' }},
- {0x0850, 0x7C50, 257, 21, 47026, 47037, 40494, 47066, 40511, 40481, 13340, {0, 0, 0, 0}, 202, 202, { 0, 500, 2, 1, 0, ',' }},
- {0x0C01, 0x0001, 257, 31, 47070, 47076, 47091, 47115, 36519, 36490, 47119, {36523, 0, 0, 0}, 203, 203, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x0C04, 0x7C04, 257, 42, 47122, 47128, 47171, 47208, 36726, 36730, 47212, {41736, 0, 0, 0}, 204, 204, { 950, 500, 10002, 950, 0, ',' }},
- {0x0C07, 0x0007, 257, 5, 47215, 47221, 47238, 47260, 36889, 36867, 47264, {36893, 0, 0, 0}, 205, 205, { 1252, 20273, 10000, 850, 0, ';' }},
- {0x0C09, 0x0009, 257, 6, 47267, 47273, 47273, 47293, 37009, 36994, 47297, {37013, 0, 0, 0}, 206, 206, { 1252, 500, 10000, 850, 0, ',' }},
- {0x0C0A, 0x000A, 257, 32, 47300, 47306, 47322, 47341, 37056, 37032, 41682, {37060, 0, 0, 0}, 207, 207, { 1252, 20284, 10000, 850, 0, ';' }},
- {0x0C0C, 0x000C, 257, 18, 47345, 47351, 47367, 47386, 37156, 37132, 47390, {37160, 0, 0, 0}, 208, 208, { 1252, 20297, 10000, 850, 0, ';' }},
- {0x0C3B, 0x003B, 257, 34, 47393, 47399, 47423, 47449, 47453, 39311, 42022, {0, 0, 0, 0}, 209, 209, { 1252, 20278, 10000, 850, 0, ';' }},
- {0x1001, 0x0001, 257, 69, 47457, 47463, 47478, 47506, 36519, 36490, 47510, {36523, 0, 0, 0}, 210, 210, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x1004, 0x0004, 257, 100, 47513, 47519, 47551, 47570, 36726, 36730, 47574, {36733, 0, 0, 0}, 211, 211, { 936, 500, 10008, 936, 0, ',' }},
- {0x1007, 0x0007, 257, 67, 47577, 47583, 47603, 47623, 36889, 36867, 47627, {36893, 0, 0, 0}, 212, 212, { 1252, 20273, 10000, 850, 0, ';' }},
- {0x1009, 0x0009, 257, 18, 47630, 47636, 47636, 47653, 37009, 36994, 47390, {37013, 0, 0, 0}, 213, 213, { 1252, 37, 10000, 850, 0, ',' }},
- {0x100A, 0x000A, 257, 41, 47657, 47663, 47683, 47704, 37056, 37032, 47708, {37060, 0, 0, 0}, 214, 214, { 1252, 20284, 10000, 850, 0, ',' }},
- {0x100C, 0x000C, 257, 19, 47711, 47717, 47738, 47757, 37156, 37132, 13261, {37160, 0, 0, 0}, 215, 215, { 1252, 20297, 10000, 850, 0, ';' }},
- {0x1401, 0x0001, 257, 28, 47761, 47767, 47784, 47816, 36519, 36490, 47820, {36523, 0, 0, 0}, 216, 216, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x1404, 0x7C04, 257, 74, 47823, 47829, 47868, 47905, 36726, 36730, 47909, {41736, 0, 0, 0}, 217, 217, { 950, 500, 10002, 950, 0, ',' }},
- {0x1407, 0x0007, 257, 64, 47912, 47918, 47941, 47965, 36889, 36867, 47969, {36893, 0, 0, 0}, 218, 218, { 1252, 20273, 10000, 850, 0, ';' }},
- {0x1409, 0x0009, 257, 83, 47972, 47978, 47978, 48000, 37009, 36994, 48004, {37013, 0, 0, 0}, 219, 219, { 1252, 500, 10000, 850, 0, ',' }},
- {0x140A, 0x000A, 257, 23, 48007, 48013, 48034, 48056, 37056, 37032, 48060, {37060, 0, 0, 0}, 220, 220, { 1252, 20284, 10000, 850, 0, ',' }},
- {0x140C, 0x000C, 257, 67, 48063, 48069, 48089, 48112, 37156, 37132, 47627, {37160, 0, 0, 0}, 221, 221, { 1252, 20297, 10000, 850, 0, ';' }},
- {0x1801, 0x0001, 257, 70, 48116, 48122, 48139, 48169, 36519, 36490, 48173, {36523, 0, 0, 0}, 222, 222, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x1809, 0x0009, 257, 47, 48176, 48182, 48182, 48200, 37009, 36994, 46855, {37013, 0, 0, 0}, 223, 223, { 1252, 500, 10000, 850, 0, ',' }},
- {0x180A, 0x000A, 257, 85, 48204, 48210, 48227, 48246, 37056, 37032, 48250, {37060, 0, 0, 0}, 224, 224, { 1252, 20284, 10000, 850, 0, ',' }},
- {0x180C, 0x000C, 257, 71, 48253, 48259, 48275, 48294, 37156, 37132, 48298, {37160, 0, 0, 0}, 225, 225, { 1252, 20297, 10000, 850, 0, ';' }},
- {0x181A, 0x701A, 257, 8, 48301, 48312, 48352, 48404, 48408, 48412, 48415, {48418, 0, 0, 0}, 226, 226, { 1250, 870, 10082, 852, 0, ';' }},
- {0x1C01, 0x0001, 257, 107, 48441, 48447, 48464, 48490, 36519, 36490, 48494, {36523, 0, 0, 0}, 227, 227, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x1C09, 0x0009, 257, 118, 48497, 48503, 48503, 48526, 37009, 36994, 43909, {37013, 0, 0, 0}, 228, 228, { 1252, 500, 10000, 437, 0, ',' }},
- {0x1C0A, 0x000A, 257, 27, 48530, 48536, 48565, 48598, 37056, 37032, 48602, {37060, 0, 0, 0}, 229, 229, { 1252, 20284, 10000, 850, 0, ',' }},
- {0x1C1A, 0x6C1A, 257, 8, 48605, 48616, 48352, 48659, 48663, 48412, 48415, {38869, 0, 0, 0}, 230, 230, { 1251, 21025, 10007, 855, 0, ';' }},
- {0x2001, 0x0001, 257, 84, 48667, 48673, 48687, 48715, 36519, 36490, 48719, {36523, 0, 0, 0}, 231, 231, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x2009, 0x0009, 257, 54, 48722, 48728, 48728, 48746, 37009, 36994, 48750, {37013, 0, 0, 0}, 232, 232, { 1252, 500, 10000, 850, 0, ',' }},
- {0x200A, 0x000A, 257, 115, 48753, 48759, 48779, 48800, 37056, 37032, 48804, {37060, 0, 0, 0}, 233, 233, { 1252, 20284, 10000, 850, 0, ',' }},
- {0x2401, 0x0001, 257, 117, 48807, 48813, 48828, 48856, 36519, 36490, 48860, {36523, 0, 0, 0}, 234, 234, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x240A, 0x000A, 257, 22, 48863, 48869, 48888, 48908, 37056, 37032, 48912, {37060, 0, 0, 0}, 235, 235, { 1252, 20284, 10000, 850, 0, ',' }},
- {0x241A, 0x701A, 257, 95, 48915, 48926, 48950, 48978, 9243, 48412, 48982, {48418, 0, 0, 0}, 236, 236, { 1250, 500, 10029, 852, 0, ';' }},
- {0x2801, 0x0001, 257, 104, 48985, 48991, 49006, 49034, 36519, 36490, 49038, {36523, 0, 0, 0}, 237, 237, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x2809, 0x0009, 257, 17, 49041, 49047, 49047, 49064, 37009, 36994, 49068, {37013, 0, 0, 0}, 238, 238, { 1252, 500, 10000, 850, 0, ';' }},
- {0x280A, 0x000A, 257, 86, 49071, 49077, 49092, 49109, 37056, 37032, 49113, {37060, 0, 0, 0}, 239, 239, { 1252, 20284, 10000, 850, 0, ',' }},
- {0x281A, 0x6C1A, 257, 95, 49116, 49127, 48950, 49154, 9243, 48412, 48982, {38869, 0, 0, 0}, 240, 240, { 1251, 21025, 10007, 855, 0, ';' }},
- {0x2C01, 0x0001, 257, 55, 49158, 49164, 49180, 49210, 36519, 36490, 49214, {36523, 0, 0, 0}, 241, 241, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x2C09, 0x0009, 257, 109, 49217, 49223, 49223, 49253, 37009, 36994, 49257, {37013, 0, 0, 0}, 242, 242, { 1252, 500, 10000, 850, 0, ';' }},
- {0x2C0A, 0x000A, 257, 4, 49260, 49266, 49286, 49307, 37056, 37032, 49311, {37060, 0, 0, 0}, 243, 243, { 1252, 20284, 10000, 850, 0, ',' }},
- {0x2C1A, 0x701A, 257, 72, 49314, 49325, 49353, 49386, 9243, 48412, 49390, {48418, 0, 0, 0}, 244, 244, { 1250, 500, 10029, 852, 0, ';' }},
- {0x3001, 0x0001, 257, 63, 49393, 49399, 49416, 49444, 36519, 36490, 49448, {36523, 0, 0, 0}, 245, 245, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x3009, 0x0009, 257, 119, 49451, 49457, 49457, 49476, 37009, 36994, 49480, {37013, 0, 0, 0}, 246, 246, { 1252, 500, 10000, 437, 0, ',' }},
- {0x300A, 0x000A, 257, 29, 49483, 49489, 49507, 49526, 37056, 37032, 49530, {37060, 0, 0, 0}, 247, 247, { 1252, 20284, 10000, 850, 0, ',' }},
- {0x301A, 0x6C1A, 257, 72, 49533, 49544, 49353, 49575, 9243, 48412, 49390, {38869, 0, 0, 0}, 248, 248, { 1251, 21025, 10007, 855, 0, ';' }},
- {0x3401, 0x0001, 257, 61, 49579, 49585, 49601, 49631, 36519, 36490, 49635, {36523, 0, 0, 0}, 249, 249, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x3409, 0x0009, 257, 87, 49638, 49644, 49644, 49666, 37009, 36994, 45741, {37013, 0, 0, 0}, 250, 250, { 1252, 500, 10000, 437, 0, ',' }},
- {0x340A, 0x000A, 257, 20, 49670, 49676, 49692, 49709, 37056, 37032, 49713, {37060, 0, 0, 0}, 251, 251, { 1252, 20284, 10000, 850, 0, ',' }},
- {0x3801, 0x0001, 257, 0, 49716, 49722, 49752, 49816, 36519, 36490, 49820, {36523, 0, 0, 0}, 252, 252, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x380A, 0x000A, 257, 113, 49823, 49829, 49847, 49866, 37056, 37032, 49870, {37060, 0, 0, 0}, 253, 253, { 1252, 20284, 10000, 850, 0, ',' }},
- {0x3C01, 0x0001, 257, 12, 49873, 49879, 49896, 49928, 36519, 36490, 49932, {36523, 0, 0, 0}, 254, 254, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x3C0A, 0x000A, 257, 92, 49935, 49941, 49960, 49980, 37056, 37032, 49984, {37060, 0, 0, 0}, 255, 255, { 1252, 20284, 10000, 850, 0, ',' }},
- {0x4001, 0x0001, 257, 93, 49987, 49993, 50008, 50032, 36519, 36490, 50036, {36523, 0, 0, 0}, 256, 256, { 1256, 20420, 10004, 720, 1, ';' }},
- {0x4009, 0x0009, 257, 49, 50039, 50045, 50045, 50061, 37009, 36994, 44239, {37013, 0, 0, 0}, 257, 257, { 1252, 37, 10000, 437, 0, ',' }},
- {0x400A, 0x000A, 257, 14, 50065, 50071, 50089, 50108, 37056, 37032, 50112, {37060, 0, 0, 0}, 258, 258, { 1252, 20284, 10000, 850, 0, ',' }},
- {0x440A, 0x000A, 257, 103, 50115, 50121, 50143, 50166, 37056, 37032, 50170, {37060, 0, 0, 0}, 259, 259, { 1252, 20284, 10000, 850, 0, ',' }},
- {0x4809, 0x0009, 257, 100, 50173, 50179, 50179, 50199, 37009, 36994, 47574, {37013, 0, 0, 0}, 260, 260, { 1252, 37, 10000, 437, 0, ',' }},
- {0x480A, 0x000A, 257, 43, 50203, 50209, 50228, 50248, 37056, 37032, 50252, {37060, 0, 0, 0}, 261, 261, { 1252, 20284, 10000, 850, 0, ',' }},
- {0x4C0A, 0x000A, 257, 79, 50255, 50261, 50281, 50302, 37056, 37032, 50306, {37060, 0, 0, 0}, 262, 262, { 1252, 20284, 10000, 850, 0, ',' }},
- {0x500A, 0x000A, 257, 90, 50309, 50315, 50337, 50360, 37056, 37032, 50364, {37060, 0, 0, 0}, 263, 263, { 1252, 20284, 10000, 850, 0, ',' }},
- {0x540A, 0x000A, 257, 112, 50367, 50373, 50397, 50423, 37056, 37032, 41981, {37060, 0, 0, 0}, 264, 264, { 1252, 20284, 10000, 850, 0, ',' }},
- {0x6C1A, 0x7C1A, 257, -1, 50427, 50435, 50454, 49154, 9243, 48412, 0, {38869, 0, 0, 0}, 265, 265, { 1251, 21025, 10007, 855, 0, ';' }},
- {0x701A, 0x7C1A, 257, -1, 50467, 50475, 50454, 48978, 9243, 48412, 0, {48418, 0, 0, 0}, 266, 266, { 1250, 500, 10029, 852, 0, ';' }},
- {0x742C, 0x002C, 257, -1, 50491, 50499, 38740, 46813, 38758, 14519, 0, {38762, 0, 0, 0}, 267, 267, { 1251, 20880, 10007, 866, 0, ';' }},
- {0x7804, 0x007F, 257, -1, 36730, 36748, 36715, 36722, 36726, 36730, 0, {36733, 0, 0, 0}, 268, 268, { 936, 500, 10008, 936, 0, ',' }},
- {0x7814, 0x0014, 257, -1, 46661, 50522, 50540, 46653, 46657, 46661, 0, {36846, 0, 0, 0}, 269, 269, { 1252, 20277, 10000, 850, 0, ';' }},
- {0x781A, 0x007F, 257, -1, 50548, 50551, 50559, 50568, 50572, 50548, 0, {48418, 0, 0, 0}, 270, 270, { 1250, 870, 10082, 852, 0, ';' }},
- {0x782C, 0x002C, 257, -1, 50576, 50584, 38740, 38754, 38758, 14519, 0, {38762, 0, 0, 0}, 271, 271, { 1254, 20905, 10081, 857, 0, ';' }},
- {0x7843, 0x0043, 257, -1, 50604, 50612, 39618, 39629, 39633, 39609, 0, {0, 0, 0, 0}, 272, 272, { 1251, 20880, 10007, 866, 0, ';' }},
- {0x7850, 0x0050, 257, -1, 50629, 50637, 40494, 50658, 40511, 40481, 0, {0, 0, 0, 0}, 273, 273, { 1251, 20880, 10007, 866, 0, ';' }},
- {0x7C04, 0x7804, 257, -1, 50662, 41691, 36715, 41729, 36726, 36730, 0, {41736, 0, 0, 0}, 274, 274, { 950, 500, 10002, 950, 0, ',' }},
- {0x7C04, 0x7C04, 257, -1, 50670, 50677, 36715, 41729, 36726, 36730, 0, {41736, 0, 0, 0}, 275, 275, { 950, 500, 10002, 950, 0, ',' }},
- {0x7C14, 0x0014, 257, -1, 37539, 50706, 50724, 37531, 37535, 37539, 0, {36846, 0, 0, 0}, 276, 276, { 1252, 20277, 10000, 850, 0, ';' }},
- {0x7C1A, 0x007F, 257, -1, 48412, 50738, 50454, 50746, 9243, 48412, 0, {38869, 0, 0, 0}, 277, 277, { 1250, 500, 10029, 852, 0, ';' }},
- {0x7C28, 0x0028, 257, -1, 50750, 50758, 0, 38583, 38587, 38574, 0, {0, 0, 0, 0}, 278, 278, { 1251, 20880, 10007, 866, 0, ';' }},
- {0x7C43, 0x0043, 257, -1, 50775, 50783, 39618, 39629, 39633, 39609, 0, {0, 0, 0, 0}, 279, 279, { 1254, 500, 10029, 857, 0, ';' }},
- {0x7C50, 0x0050, 257, -1, 50797, 50805, 40494, 47066, 40511, 40481, 0, {0, 0, 0, 0}, 280, 280, { 0, 500, 2, 1, 0, ',' }},
- {0x7C5F, 0x005F, 257, -1, 50827, 50836, 40877, 40887, 40847, 40847, 0, {0, 0, 0, 0}, 281, 281, { 1252, 20297, 10000, 850, 0, ';' }},
- {0x7C68, 0x0068, 257, -1, 50870, 50878, 41045, 41051, 41055, 41042, 0, {0, 0, 0, 0}, 282, 282, { 1252, 37, 10000, 437, 0, ',' }}
+ {0x0001, 0x007F, 768, -1, 36492, 36495, 36502, 36517, 36521, 36492, 0, {0, 0, 36525, 0}, 0, 0, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x0002, 0x007F, 257, -1, 36553, 36556, 36566, 36585, 36589, 36553, 0, {36593, 0, 0, 0}, 1, 1, { 1251, 21025, 10007, 866, 0, ';' }},
+ {0x0003, 0x007F, 257, -1, 36635, 36638, 36646, 36654, 36658, 36635, 0, {36662, 0, 0, 0}, 2, 2, { 1252, 500, 10000, 850, 0, ';' }},
+ {0x0004, 0x0004, 257, -1, 36682, 36689, 36717, 36724, 36728, 36732, 0, {36735, 0, 0, 0}, 3, 3, { 936, 500, 10008, 936, 0, ',' }},
+ {0x0004, 0x7804, 257, -1, 36742, 36750, 36717, 36724, 36728, 36732, 0, {36735, 0, 0, 0}, 4, 4, { 936, 500, 10008, 936, 0, ',' }},
+ {0x0005, 0x007F, 257, -1, 36771, 36774, 36780, 36790, 36794, 36771, 0, {36798, 0, 0, 0}, 5, 5, { 1250, 500, 10029, 852, 0, ';' }},
+ {0x0006, 0x007F, 257, -1, 36824, 36827, 36834, 36840, 36844, 36824, 0, {36848, 0, 0, 0}, 6, 6, { 1252, 20277, 10000, 850, 0, ';' }},
+ {0x0007, 0x007F, 257, -1, 36869, 36872, 36879, 36887, 36891, 36869, 0, {36895, 0, 0, 0}, 7, 7, { 1252, 20273, 10000, 850, 0, ';' }},
+ {0x0008, 0x007F, 257, -1, 36920, 36923, 36929, 36946, 36950, 36920, 0, {36954, 0, 0, 0}, 8, 8, { 1253, 20273, 10006, 737, 0, ';' }},
+ {0x0009, 0x007F, 257, -1, 36996, 36999, 36999, 37007, 37011, 36996, 0, {37015, 0, 0, 0}, 9, 9, { 1252, 37, 10000, 437, 0, ',' }},
+ {0x000A, 0x007F, 257, -1, 37034, 37037, 37045, 37054, 37058, 37034, 0, {37062, 0, 0, 0}, 10, 10, { 1252, 20284, 10000, 850, 0, ';' }},
+ {0x000B, 0x007F, 257, -1, 37084, 37087, 37095, 37101, 37105, 37084, 0, {37109, 0, 0, 0}, 11, 11, { 1252, 20278, 10000, 850, 0, ';' }},
+ {0x000C, 0x007F, 257, -1, 37134, 37137, 37144, 37154, 37158, 37134, 0, {37162, 0, 0, 0}, 12, 12, { 1252, 20297, 10000, 850, 0, ';' }},
+ {0x000D, 0x007F, 257, -1, 37184, 37187, 37194, 37205, 37209, 37184, 0, {37213, 0, 0, 0}, 13, 13, { 1255, 500, 10005, 862, 1, ',' }},
+ {0x000E, 0x007F, 257, -1, 37246, 37249, 37259, 37266, 37270, 37246, 0, {37274, 0, 0, 0}, 14, 14, { 1250, 500, 10029, 852, 0, ';' }},
+ {0x000F, 0x007F, 257, -1, 37290, 37293, 37303, 37313, 37317, 37290, 0, {37321, 0, 0, 0}, 15, 15, { 1252, 20871, 10079, 850, 0, ';' }},
+ {0x0010, 0x007F, 257, -1, 37341, 37344, 37352, 37361, 37365, 37341, 0, {37062, 0, 0, 0}, 16, 16, { 1252, 20280, 10000, 850, 0, ';' }},
+ {0x0011, 0x007F, 257, -1, 37369, 37372, 37381, 37391, 37395, 37369, 0, {37399, 0, 0, 0}, 17, 17, { 932, 20290, 10001, 932, 0, ',' }},
+ {0x0012, 0x007F, 257, -1, 37426, 37429, 37436, 37446, 37450, 37426, 0, {37454, 0, 0, 0}, 18, 18, { 949, 20833, 10003, 949, 0, ',' }},
+ {0x0013, 0x007F, 257, -1, 37464, 37467, 37473, 37484, 37488, 37464, 0, {37492, 0, 0, 0}, 19, 19, { 1252, 500, 10000, 850, 0, ';' }},
+ {0x0014, 0x007F, 257, -1, 37514, 37517, 37527, 37533, 37537, 37541, 0, {36848, 0, 0, 0}, 20, 20, { 1252, 20277, 10000, 850, 0, ';' }},
+ {0x0015, 0x007F, 257, -1, 37544, 37547, 37554, 37561, 37565, 37544, 0, {37569, 0, 0, 0}, 21, 21, { 1250, 20880, 10029, 852, 0, ';' }},
+ {0x0016, 0x007F, 257, -1, 37593, 37596, 37607, 37618, 37622, 37593, 0, {37626, 0, 0, 0}, 22, 22, { 1252, 500, 10000, 850, 0, ';' }},
+ {0x0017, 0x007F, 257, -1, 37649, 37652, 37660, 37670, 37674, 37649, 0, {37678, 0, 0, 0}, 23, 23, { 1252, 20273, 10000, 850, 0, ';' }},
+ {0x0018, 0x007F, 257, -1, 37698, 37701, 37710, 37719, 37723, 37698, 0, {37727, 0, 0, 0}, 24, 24, { 1250, 20880, 10029, 852, 0, ';' }},
+ {0x0019, 0x007F, 257, -1, 37746, 37749, 37757, 37772, 37776, 37746, 0, {37780, 0, 0, 0}, 25, 25, { 1251, 20880, 10007, 866, 0, ';' }},
+ {0x001A, 0x007F, 257, -1, 37826, 37829, 37838, 37847, 37851, 37826, 0, {37855, 0, 0, 0}, 26, 26, { 1250, 500, 10082, 852, 0, ';' }},
+ {0x001B, 0x007F, 257, -1, 37878, 37881, 37888, 37900, 37904, 37878, 0, {37908, 0, 0, 0}, 27, 27, { 1250, 20880, 10029, 852, 0, ';' }},
+ {0x001C, 0x007F, 257, -1, 37932, 37935, 37944, 37950, 37954, 37932, 0, {0, 0, 0, 0}, 28, 28, { 1250, 20880, 10029, 852, 0, ';' }},
+ {0x001D, 0x007F, 257, -1, 37958, 37961, 37969, 37977, 37981, 37958, 0, {36848, 0, 0, 0}, 29, 29, { 1252, 20278, 10000, 850, 0, ';' }},
+ {0x001E, 0x007F, 512, -1, 37985, 37988, 37993, 38003, 38007, 37985, 0, {0, 38011, 0, 0}, 30, 30, { 874, 20838, 10021, 874, 0, ',' }},
+ {0x001F, 0x007F, 257, -1, 38042, 38045, 38053, 38062, 38066, 38042, 0, {38070, 0, 0, 0}, 31, 31, { 1254, 20905, 10081, 857, 0, ';' }},
+ {0x0020, 0x007F, 257, -1, 38084, 38087, 38092, 38101, 38105, 38084, 0, {38109, 0, 0, 0}, 32, 32, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x0021, 0x007F, 257, -1, 38139, 38142, 38153, 38170, 38174, 38139, 0, {38178, 0, 0, 0}, 33, 33, { 1252, 500, 10000, 850, 0, ';' }},
+ {0x0022, 0x007F, 257, -1, 38197, 38200, 38210, 38231, 38235, 38197, 0, {38239, 0, 0, 0}, 34, 34, { 1251, 500, 10017, 866, 0, ';' }},
+ {0x0023, 0x007F, 257, -1, 38285, 38288, 38299, 38320, 38324, 38285, 0, {38328, 0, 0, 0}, 35, 35, { 1251, 500, 10007, 866, 0, ';' }},
+ {0x0024, 0x007F, 257, -1, 38370, 38373, 38383, 38397, 38401, 38370, 0, {38405, 0, 0, 0}, 36, 36, { 1250, 20880, 10029, 852, 0, ';' }},
+ {0x0025, 0x007F, 257, -1, 38427, 38430, 38439, 38445, 38449, 38427, 0, {38453, 0, 0, 0}, 37, 37, { 1257, 500, 10029, 775, 0, ';' }},
+ {0x0026, 0x007F, 257, -1, 38473, 38476, 38484, 38494, 38498, 38473, 0, {38502, 0, 0, 0}, 38, 38, { 1257, 500, 10029, 775, 0, ';' }},
+ {0x0027, 0x007F, 257, -1, 38521, 38524, 38535, 38545, 38549, 38521, 0, {38553, 0, 0, 0}, 39, 39, { 1257, 500, 10029, 775, 0, ';' }},
+ {0x0028, 0x007F, 257, -1, 38576, 38579, 0, 38585, 38589, 38576, 0, {0, 0, 0, 0}, 40, 40, { 1251, 20880, 10007, 866, 0, ';' }},
+ {0x0029, 0x007F, 257, -1, 38593, 38596, 38604, 38615, 38619, 38593, 0, {38623, 0, 0, 0}, 41, 41, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x002A, 0x007F, 257, -1, 38647, 38650, 38661, 38676, 4121, 38647, 0, {38680, 0, 0, 0}, 42, 42, { 1258, 500, 10000, 1258, 0, ',' }},
+ {0x002B, 0x007F, 257, -1, 38695, 38698, 38707, 38722, 38726, 38695, 0, {0, 0, 0, 0}, 43, 43, { 0, 500, 2, 1, 0, ',' }},
+ {0x002C, 0x007F, 257, -1, 14519, 38730, 38742, 38756, 38760, 14519, 0, {38764, 0, 0, 0}, 44, 44, { 1254, 20905, 10081, 857, 0, ';' }},
+ {0x002D, 0x007F, 257, -1, 38782, 38785, 38792, 38800, 38804, 38782, 0, {38808, 0, 0, 0}, 45, 45, { 1252, 500, 10000, 850, 0, ';' }},
+ {0x002F, 0x007F, 257, -1, 38828, 38831, 38842, 38863, 38867, 38828, 0, {38871, 0, 0, 0}, 46, 46, { 1251, 500, 10007, 866, 0, ';' }},
+ {0x0032, 0x007F, 257, -1, 38915, 38918, 38925, 38934, 38938, 38915, 0, {0, 0, 0, 0}, 47, 47, { 1252, 500, 10000, 850, 0, ',' }},
+ {0x0034, 0x007F, 257, -1, 38942, 38945, 38951, 38960, 38964, 38942, 0, {0, 0, 0, 0}, 48, 48, { 1252, 500, 10000, 850, 0, ',' }},
+ {0x0035, 0x007F, 257, -1, 38968, 38971, 38976, 38984, 38988, 38968, 0, {38992, 0, 0, 0}, 49, 49, { 1252, 500, 10000, 850, 0, ',' }},
+ {0x0036, 0x007F, 257, -1, 39013, 39016, 39016, 39026, 39030, 39013, 0, {39034, 0, 0, 0}, 50, 50, { 1252, 500, 10000, 850, 0, ',' }},
+ {0x0037, 0x007F, 257, -1, 39054, 39057, 39066, 39088, 39092, 39054, 0, {39096, 0, 0, 0}, 51, 51, { 0, 500, 2, 1, 0, ';' }},
+ {0x0038, 0x007F, 257, -1, 39161, 39164, 39172, 39182, 39186, 39161, 0, {0, 0, 0, 0}, 52, 52, { 1252, 20277, 10079, 850, 0, ';' }},
+ {0x0039, 0x007F, 257, -1, 39190, 39193, 39199, 39218, 39222, 39190, 0, {39226, 0, 0, 0}, 53, 53, { 0, 500, 2, 1, 0, ',' }},
+ {0x003A, 0x007F, 257, -1, 39267, 39270, 39278, 39284, 39288, 39267, 0, {39292, 0, 0, 0}, 54, 54, { 0, 500, 2, 1, 0, ',' }},
+ {0x003B, 0x007F, 257, -1, 39313, 39316, 39330, 39347, 39351, 39313, 0, {0, 0, 0, 0}, 55, 55, { 1252, 20277, 10000, 850, 0, ';' }},
+ {0x003C, 0x007F, 257, -1, 39355, 39358, 39364, 39372, 39376, 39355, 0, {39380, 0, 0, 0}, 56, 56, { 1252, 500, 10000, 850, 0, ',' }},
+ {0x003E, 0x007F, 257, -1, 39401, 39404, 39410, 39424, 39428, 39401, 0, {39432, 0, 0, 0}, 57, 57, { 1252, 500, 10000, 850, 0, ';' }},
+ {0x003F, 0x007F, 257, -1, 39449, 39452, 39459, 39479, 39483, 39449, 0, {39487, 0, 0, 0}, 58, 58, { 0, 500, 2, 1, 0, ';' }},
+ {0x0040, 0x007F, 257, -1, 39529, 39532, 39540, 39553, 39557, 39529, 0, {0, 0, 0, 0}, 59, 59, { 1251, 20880, 10007, 866, 0, ';' }},
+ {0x0041, 0x007F, 257, -1, 39561, 39564, 39572, 39582, 39586, 39561, 0, {39590, 0, 0, 0}, 60, 60, { 1252, 500, 10000, 437, 0, ',' }},
+ {0x0043, 0x007F, 257, -1, 39611, 39614, 39620, 39631, 39635, 39611, 0, {0, 0, 0, 0}, 61, 61, { 1254, 500, 10029, 857, 0, ';' }},
+ {0x0045, 0x007F, 257, -1, 39639, 39642, 39650, 39666, 39670, 39639, 0, {39674, 0, 0, 0}, 62, 62, { 0, 500, 2, 1, 0, ',' }},
+ {0x0046, 0x007F, 257, -1, 39739, 39742, 39750, 39769, 39773, 39739, 0, {0, 0, 0, 0}, 63, 63, { 0, 500, 2, 1, 0, ',' }},
+ {0x0047, 0x007F, 257, -1, 39777, 39780, 39789, 39811, 39815, 39777, 0, {39819, 0, 0, 0}, 64, 64, { 0, 500, 2, 1, 0, ',' }},
+ {0x0048, 0x007F, 257, -1, 14525, 39875, 39881, 39897, 39901, 14525, 0, {0, 0, 0, 0}, 65, 65, { 0, 500, 2, 1, 0, ',' }},
+ {0x0049, 0x007F, 257, -1, 39905, 39908, 39914, 39930, 39934, 39905, 0, {39938, 0, 0, 0}, 66, 66, { 0, 500, 2, 1, 0, ',' }},
+ {0x004A, 0x007F, 257, -1, 40003, 40006, 40013, 40032, 40036, 40003, 0, {40040, 0, 0, 0}, 67, 67, { 0, 500, 2, 1, 0, ',' }},
+ {0x004B, 0x007F, 257, -1, 35841, 40105, 40113, 40129, 40133, 35841, 0, {40137, 0, 0, 0}, 68, 68, { 0, 500, 2, 1, 0, ',' }},
+ {0x004C, 0x007F, 257, -1, 40208, 40211, 40221, 40240, 40244, 40208, 0, {40248, 0, 0, 0}, 69, 69, { 0, 500, 2, 1, 0, ',' }},
+ {0x004D, 0x007F, 257, -1, 14516, 40298, 40307, 40329, 40333, 14516, 0, {40337, 0, 0, 0}, 70, 70, { 0, 500, 2, 1, 0, ',' }},
+ {0x004E, 0x007F, 257, -1, 40390, 40393, 40401, 40417, 2565, 40390, 0, {40421, 0, 0, 0}, 71, 71, { 0, 500, 2, 1, 0, ',' }},
+ {0x0050, 0x007F, 257, -1, 40483, 40486, 40496, 40509, 40513, 40483, 0, {0, 0, 0, 0}, 72, 72, { 1251, 20880, 10007, 866, 0, ';' }},
+ {0x0051, 0x007F, 257, -1, 40517, 40520, 40528, 40553, 40557, 40517, 0, {0, 0, 0, 0}, 73, 73, { 0, 500, 2, 1, 0, ',' }},
+ {0x0052, 0x007F, 257, -1, 40561, 40564, 40570, 40578, 40582, 40561, 0, {0, 0, 0, 0}, 74, 74, { 1252, 20285, 10000, 850, 0, ',' }},
+ {0x0053, 0x007F, 257, -1, 40586, 40589, 40595, 40623, 40627, 40586, 0, {0, 0, 0, 0}, 75, 75, { 0, 500, 2, 1, 0, ',' }},
+ {0x0054, 0x007F, 257, -1, 40631, 40634, 40638, 40648, 40652, 40631, 0, {0, 0, 0, 0}, 76, 76, { 0, 500, 2, 1, 0, ',' }},
+ {0x0056, 0x007F, 257, -1, 40656, 40659, 40668, 40675, 40679, 40656, 0, {37062, 0, 0, 0}, 77, 77, { 1252, 500, 10000, 850, 0, ';' }},
+ {0x0057, 0x007F, 257, -1, 40683, 40687, 40695, 40714, 40683, 40683, 0, {0, 0, 0, 0}, 78, 78, { 0, 500, 2, 1, 0, ',' }},
+ {0x005B, 0x007F, 257, -1, 40718, 40721, 40729, 40745, 40749, 40718, 0, {40753, 0, 0, 0}, 79, 79, { 0, 500, 2, 1, 0, ',' }},
+ {0x005E, 0x007F, 257, -1, 7865, 40775, 40783, 40796, 40800, 7865, 0, {40804, 0, 0, 0}, 80, 80, { 0, 500, 2, 1, 0, ';' }},
+ {0x005F, 0x007F, 257, -1, 40849, 40853, 40879, 40889, 40849, 40849, 0, {0, 0, 0, 0}, 81, 81, { 1252, 20297, 10000, 850, 0, ';' }},
+ {0x0061, 0x007F, 257, -1, 2059, 40893, 40900, 40919, 40923, 2059, 0, {40927, 0, 0, 0}, 82, 82, { 0, 500, 2, 1, 0, ',' }},
+ {0x0063, 0x007F, 1024, -1, 40977, 40980, 40987, 40996, 41000, 40977, 0, {0, 0, 0, 0}, 83, 83, { 0, 500, 2, 1, 1, ';' }},
+ {0x0064, 0x007F, 257, -1, 41004, 41008, 41008, 41017, 41004, 41004, 0, {41021, 0, 0, 0}, 84, 84, { 1252, 500, 10000, 437, 0, ',' }},
+ {0x0068, 0x007F, 257, -1, 41044, 41047, 41047, 41053, 41057, 41044, 0, {0, 0, 0, 0}, 85, 85, { 1252, 37, 10000, 437, 0, ',' }},
+ {0x006A, 0x007F, 257, -1, 41061, 41064, 41071, 41086, 41090, 41061, 0, {0, 0, 0, 0}, 86, 86, { 1252, 37, 10000, 437, 0, ',' }},
+ {0x006C, 0x007F, 257, -1, 41094, 41098, 41113, 41130, 41094, 41094, 0, {0, 0, 0, 0}, 87, 87, { 1252, 500, 10000, 850, 0, ',' }},
+ {0x006F, 0x007F, 257, -1, 41134, 41137, 41149, 41161, 41165, 41134, 0, {0, 0, 0, 0}, 88, 88, { 1252, 20277, 10000, 850, 0, ';' }},
+ {0x0070, 0x007F, 257, -1, 14510, 41169, 41169, 41174, 41178, 14510, 0, {0, 0, 0, 0}, 89, 89, { 1252, 37, 10000, 437, 0, ',' }},
+ {0x0078, 0x007F, 257, -1, 41182, 41185, 41196, 41206, 41210, 41182, 0, {41214, 0, 0, 0}, 90, 90, { 0, 500, 2, 1, 0, ',' }},
+ {0x007E, 0x007F, 257, -1, 41227, 41230, 41237, 41247, 41251, 41227, 0, {41255, 0, 0, 0}, 91, 91, { 1252, 20297, 10000, 850, 0, ';' }},
+ {0x0082, 0x007F, 257, -1, 41275, 41278, 41286, 41294, 41298, 41275, 0, {0, 0, 0, 0}, 92, 92, { 1252, 20297, 10000, 850, 0, ';' }},
+ {0x0084, 0x007F, 257, -1, 41302, 41306, 41319, 41338, 41302, 41302, 0, {41342, 0, 0, 0}, 93, 93, { 1252, 20297, 10000, 850, 0, ';' }},
+ {0x0085, 0x007F, 257, -1, 41367, 41371, 41377, 41395, 41367, 41367, 0, {0, 0, 0, 0}, 94, 94, { 1251, 20880, 10007, 866, 0, ';' }},
+ {0x0087, 0x007F, 257, -1, 41399, 41402, 41402, 41414, 41418, 41399, 0, {0, 0, 0, 0}, 95, 95, { 1252, 37, 10000, 437, 0, ';' }},
+ {0x0091, 0x007F, 257, -1, 41422, 41425, 41441, 41451, 41455, 41422, 0, {41459, 0, 0, 0}, 96, 96, { 1252, 20285, 10000, 850, 0, ',' }},
+ {0x0401, 0x0001, 768, 98, 41484, 41490, 41512, 36517, 36521, 36492, 13258, {0, 0, 36525, 0}, 97, 97, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x0402, 0x0002, 257, 11, 41576, 41582, 41603, 36585, 36589, 36553, 41641, {36593, 0, 0, 0}, 98, 98, { 1251, 21025, 10007, 866, 0, ';' }},
+ {0x0403, 0x0003, 257, 32, 41644, 41650, 41666, 36654, 36658, 36635, 41684, {36662, 0, 0, 0}, 99, 99, { 1252, 500, 10000, 850, 0, ';' }},
+ {0x0404, 0x7C04, 257, 110, 41687, 41693, 41715, 41731, 36728, 36732, 41735, {41738, 0, 0, 0}, 100, 100, { 950, 500, 10002, 950, 0, ',' }},
+ {0x0405, 0x0005, 257, 24, 41745, 41751, 41774, 36790, 36794, 36771, 41804, {36798, 0, 0, 0}, 101, 101, { 1250, 500, 10029, 852, 0, ';' }},
+ {0x0406, 0x0006, 257, 26, 41807, 41813, 41830, 36840, 36844, 36824, 41846, {36848, 0, 0, 0}, 102, 102, { 1252, 20277, 10000, 850, 0, ';' }},
+ {0x0407, 0x0007, 257, 25, 41849, 41855, 41872, 36887, 36891, 36869, 41894, {36895, 0, 0, 0}, 103, 103, { 1252, 20273, 10000, 850, 0, ';' }},
+ {0x0408, 0x0008, 257, 40, 41897, 41903, 41918, 36946, 36950, 36920, 41950, {36954, 0, 0, 0}, 104, 104, { 1253, 20273, 10006, 737, 0, ';' }},
+ {0x0409, 0x0009, 257, 112, 41953, 41959, 41959, 37007, 37011, 36996, 41983, {37015, 0, 0, 0}, 105, 105, { 1252, 37, 10000, 437, 0, ',' }},
+ {0x040B, 0x000B, 257, 34, 41986, 41992, 42010, 37101, 37105, 37084, 42024, {37109, 0, 0, 0}, 106, 106, { 1252, 20278, 10000, 850, 0, ';' }},
+ {0x040C, 0x000C, 257, 36, 42027, 42033, 42049, 37154, 37158, 37134, 42068, {37162, 0, 0, 0}, 107, 107, { 1252, 20297, 10000, 850, 0, ';' }},
+ {0x040D, 0x000D, 257, 48, 42071, 42077, 42093, 37205, 37209, 37184, 42117, {37213, 0, 0, 0}, 108, 108, { 1255, 500, 10005, 862, 1, ',' }},
+ {0x040E, 0x000E, 257, 45, 42120, 42126, 42146, 37266, 37270, 37246, 42169, {37274, 0, 0, 0}, 109, 109, { 1250, 500, 10029, 852, 0, ';' }},
+ {0x040F, 0x000F, 257, 52, 42172, 42178, 42198, 37313, 37317, 37290, 42218, {37321, 0, 0, 0}, 110, 110, { 1252, 20871, 10079, 850, 0, ';' }},
+ {0x0410, 0x0010, 257, 53, 42221, 42227, 42243, 37361, 37365, 37341, 42261, {37062, 0, 0, 0}, 111, 111, { 1252, 20280, 10000, 850, 0, ';' }},
+ {0x0411, 0x0011, 257, 56, 42264, 42270, 42287, 37391, 37395, 37369, 42306, {37399, 0, 0, 0}, 112, 112, { 932, 20290, 10001, 932, 0, ',' }},
+ {0x0412, 0x0012, 257, 60, 42309, 42315, 42336, 37446, 37450, 37426, 42361, {37454, 0, 0, 0}, 113, 113, { 949, 20833, 10003, 949, 0, ',' }},
+ {0x0413, 0x0013, 257, 80, 42364, 42370, 42390, 37484, 37488, 37464, 42413, {37492, 0, 0, 0}, 114, 114, { 1252, 500, 10000, 850, 0, ';' }},
+ {0x0414, 0x7C14, 257, 81, 42416, 42422, 42449, 37533, 37537, 37541, 42471, {36848, 0, 0, 0}, 115, 115, { 1252, 20277, 10000, 850, 0, ';' }},
+ {0x0415, 0x0015, 257, 89, 42474, 42480, 42496, 37561, 37565, 37544, 42512, {37569, 0, 0, 0}, 116, 116, { 1250, 20880, 10029, 852, 0, ';' }},
+ {0x0416, 0x0016, 257, 15, 42515, 42521, 42541, 37618, 37622, 37593, 42561, {37626, 0, 0, 0}, 117, 117, { 1252, 500, 10000, 850, 0, ';' }},
+ {0x0417, 0x0017, 257, 19, 42564, 42570, 42592, 37670, 37674, 37649, 13261, {37678, 0, 0, 0}, 118, 118, { 1252, 20273, 10000, 850, 0, ';' }},
+ {0x0418, 0x0018, 257, 94, 42611, 42617, 42636, 37719, 37723, 37698, 42656, {37727, 0, 0, 0}, 119, 119, { 1250, 20880, 10029, 852, 0, ';' }},
+ {0x0419, 0x0019, 257, 96, 42659, 42665, 42682, 37772, 37776, 37746, 42712, {37780, 0, 0, 0}, 120, 120, { 1251, 20880, 10007, 866, 0, ';' }},
+ {0x041A, 0x001A, 257, 44, 42715, 42721, 42740, 37847, 37851, 37826, 42760, {37855, 0, 0, 0}, 121, 121, { 1250, 500, 10082, 852, 0, ';' }},
+ {0x041B, 0x001B, 257, 102, 42763, 42769, 42787, 37900, 37904, 37878, 42822, {37908, 0, 0, 0}, 122, 122, { 1250, 20880, 10029, 852, 0, ';' }},
+ {0x041C, 0x001C, 257, 2, 42825, 42831, 42850, 37950, 37954, 37932, 42869, {0, 0, 0, 0}, 123, 123, { 1250, 20880, 10029, 852, 0, ';' }},
+ {0x041D, 0x001D, 257, 99, 42872, 42878, 42895, 37977, 37981, 37958, 42913, {36848, 0, 0, 0}, 124, 124, { 1252, 20278, 10000, 850, 0, ';' }},
+ {0x041E, 0x001E, 512, 105, 42916, 42922, 42938, 38003, 38007, 37985, 42960, {0, 38011, 0, 0}, 125, 125, { 874, 20838, 10021, 874, 0, ',' }},
+ {0x041F, 0x001F, 257, 108, 42963, 42969, 42986, 38062, 38066, 38042, 43006, {38070, 0, 0, 0}, 126, 126, { 1254, 20905, 10081, 857, 0, ';' }},
+ {0x0420, 0x0020, 257, 88, 43009, 43015, 43031, 38101, 38105, 38084, 43057, {38109, 0, 0, 0}, 127, 127, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x0421, 0x0021, 257, 46, 43060, 43066, 43089, 38170, 38174, 38139, 43118, {38178, 0, 0, 0}, 128, 128, { 1252, 500, 10000, 850, 0, ';' }},
+ {0x0422, 0x0022, 257, 111, 43121, 43127, 43147, 38231, 38235, 38197, 43185, {38239, 0, 0, 0}, 129, 129, { 1251, 500, 10017, 866, 0, ';' }},
+ {0x0423, 0x0023, 257, 16, 43188, 43194, 43215, 38320, 38324, 38285, 43255, {38328, 0, 0, 0}, 130, 130, { 1251, 500, 10007, 866, 0, ';' }},
+ {0x0424, 0x0024, 257, 101, 43258, 43264, 43285, 38397, 38401, 38370, 43311, {38405, 0, 0, 0}, 131, 131, { 1250, 20880, 10029, 852, 0, ';' }},
+ {0x0425, 0x0025, 257, 30, 43314, 43320, 43339, 38445, 38449, 38427, 43353, {38453, 0, 0, 0}, 132, 132, { 1257, 500, 10029, 775, 0, ';' }},
+ {0x0426, 0x0026, 257, 68, 43356, 43362, 43379, 38494, 38498, 38473, 43399, {38502, 0, 0, 0}, 133, 133, { 1257, 500, 10029, 775, 0, ';' }},
+ {0x0427, 0x0027, 257, 66, 43402, 43408, 43431, 38545, 38549, 38521, 43451, {38553, 0, 0, 0}, 134, 134, { 1257, 500, 10029, 775, 0, ';' }},
+ {0x0428, 0x7C28, 257, 106, 43454, 43465, 0, 38585, 38589, 38576, 43494, {0, 0, 0, 0}, 135, 135, { 1251, 20880, 10007, 866, 0, ';' }},
+ {0x0429, 0x0029, 257, 51, 43497, 43503, 43518, 38615, 38619, 38593, 43542, {38623, 0, 0, 0}, 136, 136, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x042A, 0x002A, 257, 116, 43545, 43551, 43572, 38676, 4121, 38647, 43600, {38680, 0, 0, 0}, 137, 137, { 1258, 500, 10000, 1258, 0, ',' }},
+ {0x042B, 0x002B, 257, 3, 43603, 43609, 43628, 38722, 38726, 38695, 3781, {0, 0, 0, 0}, 138, 138, { 0, 500, 2, 1, 0, ',' }},
+ {0x042C, 0x782C, 257, 7, 43693, 43704, 43736, 38756, 38760, 14519, 43764, {38764, 0, 0, 0}, 139, 139, { 1254, 20905, 10081, 857, 0, ';' }},
+ {0x042D, 0x002D, 257, 32, 43767, 43773, 43788, 38800, 38804, 38782, 41684, {38808, 0, 0, 0}, 140, 140, { 1252, 500, 10000, 850, 0, ';' }},
+ {0x042F, 0x002F, 257, 73, 43807, 43813, 43836, 38863, 38867, 38828, 43880, {38871, 0, 0, 0}, 141, 141, { 1251, 500, 10007, 866, 0, ';' }},
+ {0x0432, 0x0032, 257, 118, 43883, 43889, 38925, 38934, 38938, 38915, 43911, {0, 0, 0, 0}, 142, 142, { 1252, 500, 10000, 850, 0, ',' }},
+ {0x0434, 0x0034, 257, 118, 43914, 43920, 38951, 38960, 38964, 38942, 43911, {0, 0, 0, 0}, 143, 143, { 1252, 500, 10000, 850, 0, ',' }},
+ {0x0435, 0x0035, 257, 118, 43941, 43947, 43967, 38984, 38988, 38968, 43911, {38992, 0, 0, 0}, 144, 144, { 1252, 500, 10000, 850, 0, ',' }},
+ {0x0436, 0x0036, 257, 118, 43995, 44001, 44026, 39026, 39030, 39013, 43911, {39034, 0, 0, 0}, 145, 145, { 1252, 500, 10000, 850, 0, ',' }},
+ {0x0437, 0x0037, 257, 38, 44050, 44056, 44075, 39088, 39092, 39054, 44130, {39096, 0, 0, 0}, 146, 146, { 0, 500, 2, 1, 0, ';' }},
+ {0x0438, 0x0038, 257, 35, 44133, 44139, 44163, 39182, 39186, 39161, 44184, {0, 0, 0, 0}, 147, 147, { 1252, 20277, 10079, 850, 0, ';' }},
+ {0x0439, 0x0039, 257, 49, 44187, 44193, 44207, 39218, 39222, 39190, 44241, {39226, 0, 0, 0}, 148, 148, { 0, 500, 2, 1, 0, ',' }},
+ {0x043A, 0x003A, 257, 75, 44244, 44250, 44266, 39284, 39288, 39267, 44280, {39292, 0, 0, 0}, 149, 149, { 0, 500, 2, 1, 0, ',' }},
+ {0x043B, 0x003B, 257, 81, 44283, 44289, 44312, 39347, 39351, 39313, 42471, {0, 0, 0, 0}, 150, 150, { 1252, 20277, 10000, 850, 0, ';' }},
+ {0x043E, 0x003E, 257, 77, 44337, 44343, 44360, 39424, 39428, 39401, 44385, {39432, 0, 0, 0}, 151, 151, { 1252, 500, 10000, 850, 0, ';' }},
+ {0x0440, 0x0040, 257, 58, 44388, 44394, 44415, 39553, 39557, 39529, 44451, {0, 0, 0, 0}, 152, 152, { 1251, 20880, 10007, 866, 0, ';' }},
+ {0x0441, 0x0041, 257, 57, 44454, 44460, 44476, 39582, 39586, 39561, 44494, {39590, 0, 0, 0}, 153, 153, { 1252, 500, 10000, 437, 0, ',' }},
+ {0x0443, 0x7C43, 257, 114, 44497, 44508, 44534, 39631, 39635, 39611, 44568, {0, 0, 0, 0}, 154, 154, { 1254, 500, 10029, 857, 0, ';' }},
+ {0x0445, 0x0045, 257, 49, 44571, 44577, 44593, 39666, 39670, 39639, 44241, {39674, 0, 0, 0}, 155, 155, { 0, 500, 2, 1, 0, ',' }},
+ {0x0447, 0x0047, 257, 49, 44624, 44630, 44647, 39811, 39815, 39777, 44241, {39819, 0, 0, 0}, 156, 156, { 0, 500, 2, 1, 0, ',' }},
+ {0x0448, 0x0048, 257, 49, 44684, 44690, 44704, 39897, 39901, 14525, 44241, {0, 0, 0, 0}, 157, 157, { 0, 500, 2, 1, 0, ',' }},
+ {0x0449, 0x0049, 257, 49, 44735, 44741, 44755, 39930, 39934, 39905, 44241, {39938, 0, 0, 0}, 158, 158, { 0, 500, 2, 1, 0, ',' }},
+ {0x044A, 0x004A, 257, 49, 44795, 44801, 44816, 40032, 40036, 40003, 44241, {40040, 0, 0, 0}, 159, 159, { 0, 500, 2, 1, 0, ',' }},
+ {0x044B, 0x004B, 257, 49, 44863, 44869, 44885, 40129, 40133, 35841, 44241, {40137, 0, 0, 0}, 160, 160, { 0, 500, 2, 1, 0, ',' }},
+ {0x044C, 0x004C, 257, 49, 44916, 44922, 44940, 40240, 40244, 40208, 44241, {40248, 0, 0, 0}, 161, 161, { 0, 500, 2, 1, 0, ',' }},
+ {0x044D, 0x004D, 257, 49, 44980, 44986, 45003, 40329, 40333, 14516, 44241, {40337, 0, 0, 0}, 162, 162, { 0, 500, 2, 1, 0, ',' }},
+ {0x044E, 0x004E, 257, 49, 45040, 45046, 45062, 40417, 2565, 40390, 44241, {40421, 0, 0, 0}, 163, 163, { 0, 500, 2, 1, 0, ',' }},
+ {0x0451, 0x0051, 257, 21, 45093, 45099, 45115, 40553, 40557, 40517, 13340, {0, 0, 0, 0}, 164, 164, { 0, 500, 2, 1, 0, ',' }},
+ {0x0452, 0x0052, 257, 37, 45161, 45167, 45190, 40578, 40582, 40561, 45213, {0, 0, 0, 0}, 165, 165, { 1252, 20285, 10000, 850, 0, ',' }},
+ {0x0453, 0x0053, 257, 59, 45216, 45222, 45239, 40623, 40627, 40586, 45291, {0, 0, 0, 0}, 166, 166, { 0, 500, 2, 1, 0, ',' }},
+ {0x0454, 0x0054, 257, 62, 45294, 45300, 45311, 40648, 40652, 40631, 45333, {0, 0, 0, 0}, 167, 167, { 0, 500, 2, 1, 0, ',' }},
+ {0x0456, 0x0056, 257, 32, 45336, 45342, 45359, 40675, 40679, 40656, 41684, {37062, 0, 0, 0}, 168, 168, { 1252, 500, 10000, 850, 0, ';' }},
+ {0x0457, 0x0057, 257, 49, 45376, 45383, 45399, 40714, 40683, 40683, 44241, {0, 0, 0, 0}, 169, 169, { 0, 500, 2, 1, 0, ',' }},
+ {0x045B, 0x005B, 257, 65, 45433, 45439, 45459, 40745, 40749, 40718, 45509, {40753, 0, 0, 0}, 170, 170, { 0, 500, 2, 1, 0, ',' }},
+ {0x045E, 0x005E, 257, 33, 45512, 45518, 45537, 40796, 40800, 7865, 45568, {40804, 0, 0, 0}, 171, 171, { 0, 500, 2, 1, 0, ';' }},
+ {0x0461, 0x0061, 257, 82, 45571, 45577, 45592, 40919, 40923, 2059, 45629, {40927, 0, 0, 0}, 172, 172, { 0, 500, 2, 1, 0, ',' }},
+ {0x0463, 0x0063, 1024, 1, 45632, 45638, 45659, 40996, 41000, 40977, 45689, {0, 0, 0, 0}, 173, 173, { 0, 500, 2, 1, 1, ';' }},
+ {0x0464, 0x0064, 257, 87, 45692, 45699, 45722, 41017, 41004, 41004, 45743, {41021, 0, 0, 0}, 174, 174, { 1252, 500, 10000, 437, 0, ',' }},
+ {0x0468, 0x7C68, 257, 78, 45746, 45757, 45780, 41053, 41057, 41044, 45797, {0, 0, 0, 0}, 175, 175, { 1252, 37, 10000, 437, 0, ',' }},
+ {0x046A, 0x006A, 257, 78, 45800, 45806, 45823, 41086, 41090, 41061, 45797, {0, 0, 0, 0}, 176, 176, { 1252, 37, 10000, 437, 0, ',' }},
+ {0x046C, 0x006C, 257, 118, 45869, 45876, 41113, 41130, 41094, 41094, 43911, {0, 0, 0, 0}, 177, 177, { 1252, 500, 10000, 850, 0, ',' }},
+ {0x046F, 0x006F, 257, 39, 45906, 45912, 45936, 41161, 41165, 41134, 45967, {0, 0, 0, 0}, 178, 178, { 1252, 20277, 10000, 850, 0, ';' }},
+ {0x0470, 0x0070, 257, 78, 45970, 45976, 45976, 41174, 41178, 14510, 45797, {0, 0, 0, 0}, 179, 179, { 1252, 37, 10000, 437, 0, ',' }},
+ {0x0478, 0x0078, 257, 21, 45991, 45997, 46016, 41206, 41210, 41182, 13340, {41214, 0, 0, 0}, 180, 180, { 0, 500, 2, 1, 0, ',' }},
+ {0x047E, 0x007E, 257, 36, 46035, 46041, 46057, 41247, 41251, 41227, 42068, {41255, 0, 0, 0}, 181, 181, { 1252, 20297, 10000, 850, 0, ';' }},
+ {0x0482, 0x0082, 257, 36, 46076, 46082, 46099, 41294, 41298, 41275, 42068, {0, 0, 0, 0}, 182, 182, { 1252, 20297, 10000, 850, 0, ';' }},
+ {0x0485, 0x0085, 257, 96, 46117, 46124, 41377, 41395, 41367, 41367, 42712, {0, 0, 0, 0}, 183, 183, { 1251, 20880, 10007, 866, 0, ';' }},
+ {0x0487, 0x0087, 257, 97, 46139, 46145, 46145, 41414, 41418, 41399, 46166, {0, 0, 0, 0}, 184, 184, { 1252, 37, 10000, 437, 0, ';' }},
+ {0x0491, 0x0091, 257, 37, 46169, 46175, 46208, 41451, 41455, 41422, 45213, {41459, 0, 0, 0}, 185, 185, { 1252, 20285, 10000, 850, 0, ',' }},
+ {0x0801, 0x0001, 257, 50, 46244, 46250, 46264, 46294, 36521, 36492, 46298, {36525, 0, 0, 0}, 186, 186, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x0804, 0x0004, 257, 21, 46301, 36750, 46307, 36724, 36728, 36732, 13340, {36735, 0, 0, 0}, 187, 187, { 936, 500, 10008, 936, 0, ',' }},
+ {0x0807, 0x0007, 257, 19, 46323, 46329, 46350, 46368, 36891, 36869, 13261, {36895, 0, 0, 0}, 188, 188, { 1252, 20273, 10000, 850, 0, ';' }},
+ {0x0809, 0x0009, 257, 37, 46372, 46378, 46378, 46403, 37011, 36996, 45213, {37015, 0, 0, 0}, 189, 189, { 1252, 20285, 10000, 850, 0, ',' }},
+ {0x080A, 0x000A, 257, 76, 46407, 46413, 46430, 46449, 37058, 37034, 46453, {37062, 0, 0, 0}, 190, 190, { 1252, 20284, 10000, 850, 0, ',' }},
+ {0x080C, 0x000C, 257, 10, 46456, 46462, 46479, 46500, 37158, 37134, 46504, {37162, 0, 0, 0}, 191, 191, { 1252, 20297, 10000, 850, 0, ';' }},
+ {0x0810, 0x0010, 257, 19, 46507, 46513, 46535, 46555, 37365, 37341, 13261, {37062, 0, 0, 0}, 192, 192, { 1252, 500, 10000, 850, 0, ';' }},
+ {0x0813, 0x0013, 257, 10, 46559, 46565, 46581, 46602, 37488, 37464, 46504, {37492, 0, 0, 0}, 193, 193, { 1252, 500, 10000, 850, 0, ';' }},
+ {0x0814, 0x7814, 257, 81, 46606, 46612, 46639, 46655, 46659, 46663, 42471, {36848, 0, 0, 0}, 194, 194, { 1252, 20277, 10000, 850, 0, ';' }},
+ {0x0816, 0x0016, 257, 91, 46666, 46672, 46694, 46716, 37622, 37593, 46720, {37626, 0, 0, 0}, 195, 195, { 1252, 500, 10000, 850, 0, ';' }},
+ {0x081D, 0x001D, 257, 34, 46723, 46729, 46747, 46765, 37981, 37958, 42024, {36848, 0, 0, 0}, 196, 196, { 1252, 20278, 10000, 850, 0, ';' }},
+ {0x082C, 0x742C, 257, 7, 46769, 46780, 43736, 46815, 38760, 14519, 43764, {38764, 0, 0, 0}, 197, 197, { 1251, 20880, 10007, 866, 0, ';' }},
+ {0x083C, 0x003C, 257, 47, 46819, 46825, 46841, 39372, 39376, 39355, 46857, {39380, 0, 0, 0}, 198, 198, { 1252, 500, 10000, 850, 0, ',' }},
+ {0x083E, 0x003E, 257, 13, 46860, 46866, 46881, 46904, 39428, 39401, 46908, {39432, 0, 0, 0}, 199, 199, { 1252, 500, 10000, 850, 0, ';' }},
+ {0x0843, 0x7843, 257, 114, 46911, 46922, 44534, 39631, 39635, 39611, 44568, {0, 0, 0, 0}, 200, 200, { 1251, 20880, 10007, 866, 0, ';' }},
+ {0x0845, 0x0045, 257, 9, 46951, 46957, 46978, 47021, 39670, 39639, 47025, {39674, 0, 0, 0}, 201, 201, { 0, 500, 2, 1, 0, ',' }},
+ {0x0850, 0x7C50, 257, 21, 47028, 47039, 40496, 47068, 40513, 40483, 13340, {0, 0, 0, 0}, 202, 202, { 0, 500, 2, 1, 0, ',' }},
+ {0x0C01, 0x0001, 257, 31, 47072, 47078, 47093, 47117, 36521, 36492, 47121, {36525, 0, 0, 0}, 203, 203, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x0C04, 0x7C04, 257, 42, 47124, 47130, 47173, 47210, 36728, 36732, 47214, {41738, 0, 0, 0}, 204, 204, { 950, 500, 10002, 950, 0, ',' }},
+ {0x0C07, 0x0007, 257, 5, 47217, 47223, 47240, 47262, 36891, 36869, 47266, {36895, 0, 0, 0}, 205, 205, { 1252, 20273, 10000, 850, 0, ';' }},
+ {0x0C09, 0x0009, 257, 6, 47269, 47275, 47275, 47295, 37011, 36996, 47299, {37015, 0, 0, 0}, 206, 206, { 1252, 500, 10000, 850, 0, ',' }},
+ {0x0C0A, 0x000A, 257, 32, 47302, 47308, 47324, 47343, 37058, 37034, 41684, {37062, 0, 0, 0}, 207, 207, { 1252, 20284, 10000, 850, 0, ';' }},
+ {0x0C0C, 0x000C, 257, 18, 47347, 47353, 47369, 47388, 37158, 37134, 47392, {37162, 0, 0, 0}, 208, 208, { 1252, 20297, 10000, 850, 0, ';' }},
+ {0x0C3B, 0x003B, 257, 34, 47395, 47401, 47425, 47451, 47455, 39313, 42024, {0, 0, 0, 0}, 209, 209, { 1252, 20278, 10000, 850, 0, ';' }},
+ {0x1001, 0x0001, 257, 69, 47459, 47465, 47480, 47508, 36521, 36492, 47512, {36525, 0, 0, 0}, 210, 210, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x1004, 0x0004, 257, 100, 47515, 47521, 47553, 47572, 36728, 36732, 47576, {36735, 0, 0, 0}, 211, 211, { 936, 500, 10008, 936, 0, ',' }},
+ {0x1007, 0x0007, 257, 67, 47579, 47585, 47605, 47625, 36891, 36869, 47629, {36895, 0, 0, 0}, 212, 212, { 1252, 20273, 10000, 850, 0, ';' }},
+ {0x1009, 0x0009, 257, 18, 47632, 47638, 47638, 47655, 37011, 36996, 47392, {37015, 0, 0, 0}, 213, 213, { 1252, 37, 10000, 850, 0, ',' }},
+ {0x100A, 0x000A, 257, 41, 47659, 47665, 47685, 47706, 37058, 37034, 47710, {37062, 0, 0, 0}, 214, 214, { 1252, 20284, 10000, 850, 0, ',' }},
+ {0x100C, 0x000C, 257, 19, 47713, 47719, 47740, 47759, 37158, 37134, 13261, {37162, 0, 0, 0}, 215, 215, { 1252, 20297, 10000, 850, 0, ';' }},
+ {0x1401, 0x0001, 257, 28, 47763, 47769, 47786, 47818, 36521, 36492, 47822, {36525, 0, 0, 0}, 216, 216, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x1404, 0x7C04, 257, 74, 47825, 47831, 47870, 47907, 36728, 36732, 47911, {41738, 0, 0, 0}, 217, 217, { 950, 500, 10002, 950, 0, ',' }},
+ {0x1407, 0x0007, 257, 64, 47914, 47920, 47943, 47967, 36891, 36869, 47971, {36895, 0, 0, 0}, 218, 218, { 1252, 20273, 10000, 850, 0, ';' }},
+ {0x1409, 0x0009, 257, 83, 47974, 47980, 47980, 48002, 37011, 36996, 48006, {37015, 0, 0, 0}, 219, 219, { 1252, 500, 10000, 850, 0, ',' }},
+ {0x140A, 0x000A, 257, 23, 48009, 48015, 48036, 48058, 37058, 37034, 48062, {37062, 0, 0, 0}, 220, 220, { 1252, 20284, 10000, 850, 0, ',' }},
+ {0x140C, 0x000C, 257, 67, 48065, 48071, 48091, 48114, 37158, 37134, 47629, {37162, 0, 0, 0}, 221, 221, { 1252, 20297, 10000, 850, 0, ';' }},
+ {0x1801, 0x0001, 257, 70, 48118, 48124, 48141, 48171, 36521, 36492, 48175, {36525, 0, 0, 0}, 222, 222, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x1809, 0x0009, 257, 47, 48178, 48184, 48184, 48202, 37011, 36996, 46857, {37015, 0, 0, 0}, 223, 223, { 1252, 500, 10000, 850, 0, ',' }},
+ {0x180A, 0x000A, 257, 85, 48206, 48212, 48229, 48248, 37058, 37034, 48252, {37062, 0, 0, 0}, 224, 224, { 1252, 20284, 10000, 850, 0, ',' }},
+ {0x180C, 0x000C, 257, 71, 48255, 48261, 48277, 48296, 37158, 37134, 48300, {37162, 0, 0, 0}, 225, 225, { 1252, 20297, 10000, 850, 0, ';' }},
+ {0x181A, 0x701A, 257, 8, 48303, 48314, 48354, 48406, 48410, 48414, 48417, {48420, 0, 0, 0}, 226, 226, { 1250, 870, 10082, 852, 0, ';' }},
+ {0x1C01, 0x0001, 257, 107, 48443, 48449, 48466, 48492, 36521, 36492, 48496, {36525, 0, 0, 0}, 227, 227, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x1C09, 0x0009, 257, 118, 48499, 48505, 48505, 48528, 37011, 36996, 43911, {37015, 0, 0, 0}, 228, 228, { 1252, 500, 10000, 437, 0, ',' }},
+ {0x1C0A, 0x000A, 257, 27, 48532, 48538, 48567, 48600, 37058, 37034, 48604, {37062, 0, 0, 0}, 229, 229, { 1252, 20284, 10000, 850, 0, ',' }},
+ {0x1C1A, 0x6C1A, 257, 8, 48607, 48618, 48354, 48661, 48665, 48414, 48417, {38871, 0, 0, 0}, 230, 230, { 1251, 21025, 10007, 855, 0, ';' }},
+ {0x2001, 0x0001, 257, 84, 48669, 48675, 48689, 48717, 36521, 36492, 48721, {36525, 0, 0, 0}, 231, 231, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x2009, 0x0009, 257, 54, 48724, 48730, 48730, 48748, 37011, 36996, 48752, {37015, 0, 0, 0}, 232, 232, { 1252, 500, 10000, 850, 0, ',' }},
+ {0x200A, 0x000A, 257, 115, 48755, 48761, 48781, 48802, 37058, 37034, 48806, {37062, 0, 0, 0}, 233, 233, { 1252, 20284, 10000, 850, 0, ',' }},
+ {0x2401, 0x0001, 257, 117, 48809, 48815, 48830, 48858, 36521, 36492, 48862, {36525, 0, 0, 0}, 234, 234, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x240A, 0x000A, 257, 22, 48865, 48871, 48890, 48910, 37058, 37034, 48914, {37062, 0, 0, 0}, 235, 235, { 1252, 20284, 10000, 850, 0, ',' }},
+ {0x241A, 0x701A, 257, 95, 48917, 48928, 48952, 48980, 9243, 48414, 48984, {48420, 0, 0, 0}, 236, 236, { 1250, 500, 10029, 852, 0, ';' }},
+ {0x2801, 0x0001, 257, 104, 48987, 48993, 49008, 49036, 36521, 36492, 49040, {36525, 0, 0, 0}, 237, 237, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x2809, 0x0009, 257, 17, 49043, 49049, 49049, 49066, 37011, 36996, 49070, {37015, 0, 0, 0}, 238, 238, { 1252, 500, 10000, 850, 0, ';' }},
+ {0x280A, 0x000A, 257, 86, 49073, 49079, 49094, 49111, 37058, 37034, 49115, {37062, 0, 0, 0}, 239, 239, { 1252, 20284, 10000, 850, 0, ',' }},
+ {0x281A, 0x6C1A, 257, 95, 49118, 49129, 48952, 49156, 9243, 48414, 48984, {38871, 0, 0, 0}, 240, 240, { 1251, 21025, 10007, 855, 0, ';' }},
+ {0x2C01, 0x0001, 257, 55, 49160, 49166, 49182, 49212, 36521, 36492, 49216, {36525, 0, 0, 0}, 241, 241, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x2C09, 0x0009, 257, 109, 49219, 49225, 49225, 49255, 37011, 36996, 49259, {37015, 0, 0, 0}, 242, 242, { 1252, 500, 10000, 850, 0, ';' }},
+ {0x2C0A, 0x000A, 257, 4, 49262, 49268, 49288, 49309, 37058, 37034, 49313, {37062, 0, 0, 0}, 243, 243, { 1252, 20284, 10000, 850, 0, ',' }},
+ {0x2C1A, 0x701A, 257, 72, 49316, 49327, 49355, 49388, 9243, 48414, 49392, {48420, 0, 0, 0}, 244, 244, { 1250, 500, 10029, 852, 0, ';' }},
+ {0x3001, 0x0001, 257, 63, 49395, 49401, 49418, 49446, 36521, 36492, 49450, {36525, 0, 0, 0}, 245, 245, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x3009, 0x0009, 257, 119, 49453, 49459, 49459, 49478, 37011, 36996, 49482, {37015, 0, 0, 0}, 246, 246, { 1252, 500, 10000, 437, 0, ',' }},
+ {0x300A, 0x000A, 257, 29, 49485, 49491, 49509, 49528, 37058, 37034, 49532, {37062, 0, 0, 0}, 247, 247, { 1252, 20284, 10000, 850, 0, ',' }},
+ {0x301A, 0x6C1A, 257, 72, 49535, 49546, 49355, 49577, 9243, 48414, 49392, {38871, 0, 0, 0}, 248, 248, { 1251, 21025, 10007, 855, 0, ';' }},
+ {0x3401, 0x0001, 257, 61, 49581, 49587, 49603, 49633, 36521, 36492, 49637, {36525, 0, 0, 0}, 249, 249, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x3409, 0x0009, 257, 87, 49640, 49646, 49646, 49668, 37011, 36996, 45743, {37015, 0, 0, 0}, 250, 250, { 1252, 500, 10000, 437, 0, ',' }},
+ {0x340A, 0x000A, 257, 20, 49672, 49678, 49694, 49711, 37058, 37034, 49715, {37062, 0, 0, 0}, 251, 251, { 1252, 20284, 10000, 850, 0, ',' }},
+ {0x3801, 0x0001, 257, 0, 49718, 49724, 49754, 49818, 36521, 36492, 49822, {36525, 0, 0, 0}, 252, 252, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x380A, 0x000A, 257, 113, 49825, 49831, 49849, 49868, 37058, 37034, 49872, {37062, 0, 0, 0}, 253, 253, { 1252, 20284, 10000, 850, 0, ',' }},
+ {0x3C01, 0x0001, 257, 12, 49875, 49881, 49898, 49930, 36521, 36492, 49934, {36525, 0, 0, 0}, 254, 254, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x3C0A, 0x000A, 257, 92, 49937, 49943, 49962, 49982, 37058, 37034, 49986, {37062, 0, 0, 0}, 255, 255, { 1252, 20284, 10000, 850, 0, ',' }},
+ {0x4001, 0x0001, 257, 93, 49989, 49995, 50010, 50034, 36521, 36492, 50038, {36525, 0, 0, 0}, 256, 256, { 1256, 20420, 10004, 720, 1, ';' }},
+ {0x4009, 0x0009, 257, 49, 50041, 50047, 50047, 50063, 37011, 36996, 44241, {37015, 0, 0, 0}, 257, 257, { 1252, 37, 10000, 437, 0, ',' }},
+ {0x400A, 0x000A, 257, 14, 50067, 50073, 50091, 50110, 37058, 37034, 50114, {37062, 0, 0, 0}, 258, 258, { 1252, 20284, 10000, 850, 0, ',' }},
+ {0x440A, 0x000A, 257, 103, 50117, 50123, 50145, 50168, 37058, 37034, 50172, {37062, 0, 0, 0}, 259, 259, { 1252, 20284, 10000, 850, 0, ',' }},
+ {0x4809, 0x0009, 257, 100, 50175, 50181, 50181, 50201, 37011, 36996, 47576, {37015, 0, 0, 0}, 260, 260, { 1252, 37, 10000, 437, 0, ',' }},
+ {0x480A, 0x000A, 257, 43, 50205, 50211, 50230, 50250, 37058, 37034, 50254, {37062, 0, 0, 0}, 261, 261, { 1252, 20284, 10000, 850, 0, ',' }},
+ {0x4C0A, 0x000A, 257, 79, 50257, 50263, 50283, 50304, 37058, 37034, 50308, {37062, 0, 0, 0}, 262, 262, { 1252, 20284, 10000, 850, 0, ',' }},
+ {0x500A, 0x000A, 257, 90, 50311, 50317, 50339, 50362, 37058, 37034, 50366, {37062, 0, 0, 0}, 263, 263, { 1252, 20284, 10000, 850, 0, ',' }},
+ {0x540A, 0x000A, 257, 112, 50369, 50375, 50399, 50425, 37058, 37034, 41983, {37062, 0, 0, 0}, 264, 264, { 1252, 20284, 10000, 850, 0, ',' }},
+ {0x6C1A, 0x7C1A, 257, -1, 50429, 50437, 50456, 49156, 9243, 48414, 0, {38871, 0, 0, 0}, 265, 265, { 1251, 21025, 10007, 855, 0, ';' }},
+ {0x701A, 0x7C1A, 257, -1, 50469, 50477, 50456, 48980, 9243, 48414, 0, {48420, 0, 0, 0}, 266, 266, { 1250, 500, 10029, 852, 0, ';' }},
+ {0x742C, 0x002C, 257, -1, 50493, 50501, 38742, 46815, 38760, 14519, 0, {38764, 0, 0, 0}, 267, 267, { 1251, 20880, 10007, 866, 0, ';' }},
+ {0x7804, 0x007F, 257, -1, 36732, 36750, 36717, 36724, 36728, 36732, 0, {36735, 0, 0, 0}, 268, 268, { 936, 500, 10008, 936, 0, ',' }},
+ {0x7814, 0x0014, 257, -1, 46663, 50524, 50542, 46655, 46659, 46663, 0, {36848, 0, 0, 0}, 269, 269, { 1252, 20277, 10000, 850, 0, ';' }},
+ {0x781A, 0x007F, 257, -1, 50550, 50553, 50561, 50570, 50574, 50550, 0, {48420, 0, 0, 0}, 270, 270, { 1250, 870, 10082, 852, 0, ';' }},
+ {0x782C, 0x002C, 257, -1, 50578, 50586, 38742, 38756, 38760, 14519, 0, {38764, 0, 0, 0}, 271, 271, { 1254, 20905, 10081, 857, 0, ';' }},
+ {0x7843, 0x0043, 257, -1, 50606, 50614, 39620, 39631, 39635, 39611, 0, {0, 0, 0, 0}, 272, 272, { 1251, 20880, 10007, 866, 0, ';' }},
+ {0x7850, 0x0050, 257, -1, 50631, 50639, 40496, 50660, 40513, 40483, 0, {0, 0, 0, 0}, 273, 273, { 1251, 20880, 10007, 866, 0, ';' }},
+ {0x7C04, 0x7804, 257, -1, 50664, 41693, 36717, 41731, 36728, 36732, 0, {41738, 0, 0, 0}, 274, 274, { 950, 500, 10002, 950, 0, ',' }},
+ {0x7C04, 0x7C04, 257, -1, 50672, 50679, 36717, 41731, 36728, 36732, 0, {41738, 0, 0, 0}, 275, 275, { 950, 500, 10002, 950, 0, ',' }},
+ {0x7C14, 0x0014, 257, -1, 37541, 50708, 50726, 37533, 37537, 37541, 0, {36848, 0, 0, 0}, 276, 276, { 1252, 20277, 10000, 850, 0, ';' }},
+ {0x7C1A, 0x007F, 257, -1, 48414, 50740, 50456, 50748, 9243, 48414, 0, {38871, 0, 0, 0}, 277, 277, { 1250, 500, 10029, 852, 0, ';' }},
+ {0x7C28, 0x0028, 257, -1, 50752, 50760, 0, 38585, 38589, 38576, 0, {0, 0, 0, 0}, 278, 278, { 1251, 20880, 10007, 866, 0, ';' }},
+ {0x7C43, 0x0043, 257, -1, 50777, 50785, 39620, 39631, 39635, 39611, 0, {0, 0, 0, 0}, 279, 279, { 1254, 500, 10029, 857, 0, ';' }},
+ {0x7C50, 0x0050, 257, -1, 50799, 50807, 40496, 47068, 40513, 40483, 0, {0, 0, 0, 0}, 280, 280, { 0, 500, 2, 1, 0, ',' }},
+ {0x7C5F, 0x005F, 257, -1, 50829, 50838, 40879, 40889, 40849, 40849, 0, {0, 0, 0, 0}, 281, 281, { 1252, 20297, 10000, 850, 0, ';' }},
+ {0x7C68, 0x0068, 257, -1, 50872, 50880, 41047, 41053, 41057, 41044, 0, {0, 0, 0, 0}, 282, 282, { 1252, 37, 10000, 437, 0, ',' }}
};
static const CultureInfoNameEntry culture_name_entries [] = {
- {39011, 50}, /* af */
- {50892, 145}, /* af-za */
+ {39013, 50}, /* af */
+ {50894, 145}, /* af-za */
{7865, 80}, /* am */
- {50898, 171}, /* am-et */
- {36490, 0}, /* ar */
- {50904, 252}, /* ar-ae */
- {50910, 254}, /* ar-bh */
- {50916, 216}, /* ar-dz */
- {50922, 203}, /* ar-eg */
- {50928, 186}, /* ar-iq */
- {50934, 241}, /* ar-jo */
- {50940, 249}, /* ar-kw */
- {50946, 245}, /* ar-lb */
- {50952, 210}, /* ar-ly */
- {50958, 222}, /* ar-ma */
- {50964, 231}, /* ar-om */
- {50970, 256}, /* ar-qa */
- {50976, 97}, /* ar-sa */
- {50982, 237}, /* ar-sy */
- {50988, 227}, /* ar-tn */
- {50994, 234}, /* ar-ye */
+ {50900, 171}, /* am-et */
+ {36492, 0}, /* ar */
+ {50906, 252}, /* ar-ae */
+ {50912, 254}, /* ar-bh */
+ {50918, 216}, /* ar-dz */
+ {50924, 203}, /* ar-eg */
+ {50930, 186}, /* ar-iq */
+ {50936, 241}, /* ar-jo */
+ {50942, 249}, /* ar-kw */
+ {50948, 245}, /* ar-lb */
+ {50954, 210}, /* ar-ly */
+ {50960, 222}, /* ar-ma */
+ {50966, 231}, /* ar-om */
+ {50972, 256}, /* ar-qa */
+ {50978, 97}, /* ar-sa */
+ {50984, 237}, /* ar-sy */
+ {50990, 227}, /* ar-tn */
+ {50996, 234}, /* ar-ye */
{14516, 70}, /* as */
- {51000, 162}, /* as-in */
+ {51002, 162}, /* as-in */
{14519, 44}, /* az */
- {51006, 267}, /* az-cyrl */
- {51014, 197}, /* az-cyrl-az */
- {51025, 271}, /* az-latn */
- {51033, 139}, /* az-latn-az */
- {38283, 35}, /* be */
- {51044, 130}, /* be-by */
- {36551, 1}, /* bg */
- {51050, 98}, /* bg-bg */
- {39637, 62}, /* bn */
- {51056, 201}, /* bn-bd */
- {51062, 155}, /* bn-in */
- {40515, 73}, /* bo */
- {51068, 164}, /* bo-cn */
- {41225, 91}, /* br */
- {51074, 181}, /* br-fr */
- {50548, 270}, /* bs */
- {36633, 2}, /* ca */
- {51080, 99}, /* ca-es */
- {36769, 5}, /* cs */
- {51086, 101}, /* cs-cz */
- {40559, 74}, /* cy */
- {51092, 165}, /* cy-gb */
- {36822, 6}, /* da */
- {51098, 102}, /* da-dk */
- {36867, 7}, /* de */
- {51104, 205}, /* de-at */
- {51110, 188}, /* de-ch */
- {51116, 103}, /* de-de */
- {51122, 218}, /* de-li */
- {51128, 212}, /* de-lu */
- {36918, 8}, /* el */
- {51134, 104}, /* el-gr */
- {36994, 9}, /* en */
- {51140, 206}, /* en-au */
- {51146, 238}, /* en-bz */
- {51152, 213}, /* en-ca */
- {51158, 189}, /* en-gb */
- {51164, 223}, /* en-ie */
- {51170, 257}, /* en-in */
- {51176, 232}, /* en-jm */
- {51182, 219}, /* en-nz */
- {51188, 250}, /* en-ph */
- {51194, 260}, /* en-sg */
- {51200, 242}, /* en-tt */
- {51206, 105}, /* en-us */
- {51212, 228}, /* en-za */
- {51218, 246}, /* en-zw */
- {37032, 10}, /* es */
- {51224, 243}, /* es-ar */
- {51230, 258}, /* es-bo */
- {51236, 251}, /* es-cl */
- {51242, 235}, /* es-co */
- {51248, 220}, /* es-cr */
- {51254, 229}, /* es-do */
- {51260, 247}, /* es-ec */
- {51266, 207}, /* es-es */
- {51272, 214}, /* es-gt */
- {51278, 261}, /* es-hn */
- {51284, 190}, /* es-mx */
- {51290, 262}, /* es-ni */
- {51296, 224}, /* es-pa */
- {51302, 239}, /* es-pe */
- {51308, 263}, /* es-pr */
- {51314, 255}, /* es-py */
- {51320, 259}, /* es-sv */
- {51326, 264}, /* es-us */
- {51332, 253}, /* es-uy */
- {51338, 233}, /* es-ve */
- {38425, 37}, /* et */
- {51344, 132}, /* et-ee */
- {38780, 45}, /* eu */
- {51350, 140}, /* eu-es */
- {38591, 41}, /* fa */
- {51356, 136}, /* fa-ir */
- {37082, 11}, /* fi */
- {51362, 106}, /* fi-fi */
- {41002, 84}, /* fil */
- {51368, 174}, /* fil-ph */
- {39159, 52}, /* fo */
- {51375, 147}, /* fo-fo */
- {37132, 12}, /* fr */
- {51381, 191}, /* fr-be */
- {51387, 208}, /* fr-ca */
- {51393, 215}, /* fr-ch */
- {51399, 107}, /* fr-fr */
- {51405, 221}, /* fr-lu */
- {51411, 225}, /* fr-mc */
- {39353, 56}, /* ga */
- {51417, 198}, /* ga-ie */
- {41420, 96}, /* gd */
- {51423, 185}, /* gd-gb */
- {40654, 77}, /* gl */
- {51429, 168}, /* gl-es */
- {41300, 93}, /* gsw */
- {39775, 64}, /* gu */
- {51435, 156}, /* gu-in */
- {41042, 85}, /* ha */
- {51441, 282}, /* ha-latn */
- {51449, 175}, /* ha-latn-ng */
- {37182, 13}, /* he */
- {51460, 108}, /* he-il */
- {39188, 53}, /* hi */
- {51466, 148}, /* hi-in */
- {37824, 26}, /* hr */
- {51472, 121}, /* hr-hr */
- {37244, 14}, /* hu */
- {51478, 109}, /* hu-hu */
- {38693, 43}, /* hy */
- {51484, 138}, /* hy-am */
- {38137, 33}, /* id */
- {51490, 128}, /* id-id */
+ {51008, 267}, /* az-cyrl */
+ {51016, 197}, /* az-cyrl-az */
+ {51027, 271}, /* az-latn */
+ {51035, 139}, /* az-latn-az */
+ {38285, 35}, /* be */
+ {51046, 130}, /* be-by */
+ {36553, 1}, /* bg */
+ {51052, 98}, /* bg-bg */
+ {39639, 62}, /* bn */
+ {51058, 201}, /* bn-bd */
+ {51064, 155}, /* bn-in */
+ {40517, 73}, /* bo */
+ {51070, 164}, /* bo-cn */
+ {41227, 91}, /* br */
+ {51076, 181}, /* br-fr */
+ {50550, 270}, /* bs */
+ {36635, 2}, /* ca */
+ {51082, 99}, /* ca-es */
+ {36771, 5}, /* cs */
+ {51088, 101}, /* cs-cz */
+ {40561, 74}, /* cy */
+ {51094, 165}, /* cy-gb */
+ {36824, 6}, /* da */
+ {51100, 102}, /* da-dk */
+ {36869, 7}, /* de */
+ {51106, 205}, /* de-at */
+ {51112, 188}, /* de-ch */
+ {51118, 103}, /* de-de */
+ {51124, 218}, /* de-li */
+ {51130, 212}, /* de-lu */
+ {36920, 8}, /* el */
+ {51136, 104}, /* el-gr */
+ {36996, 9}, /* en */
+ {51142, 206}, /* en-au */
+ {51148, 238}, /* en-bz */
+ {51154, 213}, /* en-ca */
+ {51160, 189}, /* en-gb */
+ {51166, 223}, /* en-ie */
+ {51172, 257}, /* en-in */
+ {51178, 232}, /* en-jm */
+ {51184, 219}, /* en-nz */
+ {51190, 250}, /* en-ph */
+ {51196, 260}, /* en-sg */
+ {51202, 242}, /* en-tt */
+ {51208, 105}, /* en-us */
+ {51214, 228}, /* en-za */
+ {51220, 246}, /* en-zw */
+ {37034, 10}, /* es */
+ {51226, 243}, /* es-ar */
+ {51232, 258}, /* es-bo */
+ {51238, 251}, /* es-cl */
+ {51244, 235}, /* es-co */
+ {51250, 220}, /* es-cr */
+ {51256, 229}, /* es-do */
+ {51262, 247}, /* es-ec */
+ {51268, 207}, /* es-es */
+ {51274, 214}, /* es-gt */
+ {51280, 261}, /* es-hn */
+ {51286, 190}, /* es-mx */
+ {51292, 262}, /* es-ni */
+ {51298, 224}, /* es-pa */
+ {51304, 239}, /* es-pe */
+ {51310, 263}, /* es-pr */
+ {51316, 255}, /* es-py */
+ {51322, 259}, /* es-sv */
+ {51328, 264}, /* es-us */
+ {51334, 253}, /* es-uy */
+ {51340, 233}, /* es-ve */
+ {38427, 37}, /* et */
+ {51346, 132}, /* et-ee */
+ {38782, 45}, /* eu */
+ {51352, 140}, /* eu-es */
+ {38593, 41}, /* fa */
+ {51358, 136}, /* fa-ir */
+ {37084, 11}, /* fi */
+ {51364, 106}, /* fi-fi */
+ {41004, 84}, /* fil */
+ {51370, 174}, /* fil-ph */
+ {39161, 52}, /* fo */
+ {51377, 147}, /* fo-fo */
+ {37134, 12}, /* fr */
+ {51383, 191}, /* fr-be */
+ {51389, 208}, /* fr-ca */
+ {51395, 215}, /* fr-ch */
+ {51401, 107}, /* fr-fr */
+ {51407, 221}, /* fr-lu */
+ {51413, 225}, /* fr-mc */
+ {39355, 56}, /* ga */
+ {51419, 198}, /* ga-ie */
+ {41422, 96}, /* gd */
+ {51425, 185}, /* gd-gb */
+ {40656, 77}, /* gl */
+ {51431, 168}, /* gl-es */
+ {41302, 93}, /* gsw */
+ {39777, 64}, /* gu */
+ {51437, 156}, /* gu-in */
+ {41044, 85}, /* ha */
+ {51443, 282}, /* ha-latn */
+ {51451, 175}, /* ha-latn-ng */
+ {37184, 13}, /* he */
+ {51462, 108}, /* he-il */
+ {39190, 53}, /* hi */
+ {51468, 148}, /* hi-in */
+ {37826, 26}, /* hr */
+ {51474, 121}, /* hr-hr */
+ {37246, 14}, /* hu */
+ {51480, 109}, /* hu-hu */
+ {38695, 43}, /* hy */
+ {51486, 138}, /* hy-am */
+ {38139, 33}, /* id */
+ {51492, 128}, /* id-id */
{14510, 89}, /* ig */
- {51496, 179}, /* ig-ng */
- {41180, 90}, /* ii */
- {51502, 180}, /* ii-cn */
- {37288, 15}, /* is */
- {51508, 110}, /* is-is */
- {37339, 16}, /* it */
- {51514, 192}, /* it-ch */
- {51520, 111}, /* it-it */
- {37367, 17}, /* ja */
- {51526, 112}, /* ja-jp */
- {39052, 51}, /* ka */
- {51532, 146}, /* ka-ge */
- {39447, 58}, /* kk */
- {41132, 88}, /* kl */
- {51538, 178}, /* kl-gl */
- {40584, 75}, /* km */
- {51544, 166}, /* km-kh */
- {35839, 68}, /* kn */
- {51550, 160}, /* kn-in */
- {37424, 18}, /* ko */
- {51556, 113}, /* ko-kr */
- {40681, 78}, /* kok */
- {51562, 169}, /* kok-in */
- {39527, 59}, /* ky */
- {51569, 152}, /* ky-kg */
- {40629, 76}, /* lo */
- {51575, 167}, /* lo-la */
- {38519, 39}, /* lt */
- {51581, 134}, /* lt-lt */
- {38471, 38}, /* lv */
- {51587, 133}, /* lv-lv */
- {38826, 46}, /* mk */
- {51593, 141}, /* mk-mk */
- {40206, 69}, /* ml */
- {51599, 161}, /* ml-in */
- {40481, 72}, /* mn */
- {51605, 273}, /* mn-cyrl */
- {51613, 280}, /* mn-mong */
- {51621, 202}, /* mn-mong-cn */
- {40388, 71}, /* mr */
- {51632, 163}, /* mr-in */
- {39399, 57}, /* ms */
- {51638, 199}, /* ms-bn */
- {51644, 151}, /* ms-my */
- {39265, 54}, /* mt */
- {51650, 149}, /* mt-mt */
- {37539, 276}, /* nb */
- {51656, 115}, /* nb-no */
+ {51498, 179}, /* ig-ng */
+ {41182, 90}, /* ii */
+ {51504, 180}, /* ii-cn */
+ {37290, 15}, /* is */
+ {51510, 110}, /* is-is */
+ {37341, 16}, /* it */
+ {51516, 192}, /* it-ch */
+ {51522, 111}, /* it-it */
+ {37369, 17}, /* ja */
+ {51528, 112}, /* ja-jp */
+ {39054, 51}, /* ka */
+ {51534, 146}, /* ka-ge */
+ {39449, 58}, /* kk */
+ {41134, 88}, /* kl */
+ {51540, 178}, /* kl-gl */
+ {40586, 75}, /* km */
+ {51546, 166}, /* km-kh */
+ {35841, 68}, /* kn */
+ {51552, 160}, /* kn-in */
+ {37426, 18}, /* ko */
+ {51558, 113}, /* ko-kr */
+ {40683, 78}, /* kok */
+ {51564, 169}, /* kok-in */
+ {39529, 59}, /* ky */
+ {51571, 152}, /* ky-kg */
+ {40631, 76}, /* lo */
+ {51577, 167}, /* lo-la */
+ {38521, 39}, /* lt */
+ {51583, 134}, /* lt-lt */
+ {38473, 38}, /* lv */
+ {51589, 133}, /* lv-lv */
+ {38828, 46}, /* mk */
+ {51595, 141}, /* mk-mk */
+ {40208, 69}, /* ml */
+ {51601, 161}, /* ml-in */
+ {40483, 72}, /* mn */
+ {51607, 273}, /* mn-cyrl */
+ {51615, 280}, /* mn-mong */
+ {51623, 202}, /* mn-mong-cn */
+ {40390, 71}, /* mr */
+ {51634, 163}, /* mr-in */
+ {39401, 57}, /* ms */
+ {51640, 199}, /* ms-bn */
+ {51646, 151}, /* ms-my */
+ {39267, 54}, /* mt */
+ {51652, 149}, /* mt-mt */
+ {37541, 276}, /* nb */
+ {51658, 115}, /* nb-no */
{2059, 82}, /* ne */
- {51662, 172}, /* ne-np */
- {37462, 19}, /* nl */
- {51668, 193}, /* nl-be */
- {51674, 114}, /* nl-nl */
- {46661, 269}, /* nn */
- {51680, 194}, /* nn-no */
- {37512, 20}, /* no */
- {41092, 87}, /* nso */
- {51686, 177}, /* nso-za */
- {41273, 92}, /* oc */
- {51693, 182}, /* oc-fr */
+ {51664, 172}, /* ne-np */
+ {37464, 19}, /* nl */
+ {51670, 193}, /* nl-be */
+ {51676, 114}, /* nl-nl */
+ {46663, 269}, /* nn */
+ {51682, 194}, /* nn-no */
+ {37514, 20}, /* no */
+ {41094, 87}, /* nso */
+ {51688, 177}, /* nso-za */
+ {41275, 92}, /* oc */
+ {51695, 182}, /* oc-fr */
{14525, 65}, /* or */
- {51699, 157}, /* or-in */
- {39737, 63}, /* pa */
- {37542, 21}, /* pl */
- {51705, 116}, /* pl-pl */
- {40975, 83}, /* ps */
- {51711, 173}, /* ps-af */
- {37591, 22}, /* pt */
- {51717, 117}, /* pt-br */
- {51723, 195}, /* pt-pt */
- {37647, 23}, /* rm */
- {51729, 118}, /* rm-ch */
- {37696, 24}, /* ro */
- {51735, 119}, /* ro-ro */
- {37744, 25}, /* ru */
- {51741, 120}, /* ru-ru */
- {41397, 95}, /* rw */
- {51747, 184}, /* rw-rw */
- {41365, 94}, /* sah */
- {51753, 183}, /* sah-ru */
- {39311, 55}, /* se */
- {51760, 209}, /* se-fi */
- {51766, 150}, /* se-no */
- {40716, 79}, /* si */
- {51772, 170}, /* si-lk */
- {37876, 27}, /* sk */
- {51778, 122}, /* sk-sk */
- {38368, 36}, /* sl */
- {51784, 131}, /* sl-si */
- {37930, 28}, /* sq */
- {51790, 123}, /* sq-al */
- {48412, 277}, /* sr */
- {51796, 265}, /* sr-cyrl */
- {51804, 230}, /* sr-cyrl-ba */
- {51815, 248}, /* sr-cyrl-me */
- {51826, 240}, /* sr-cyrl-rs */
- {51837, 266}, /* sr-latn */
- {51845, 226}, /* sr-latn-ba */
- {51856, 244}, /* sr-latn-me */
- {51867, 236}, /* sr-latn-rs */
- {37956, 29}, /* sv */
- {51878, 196}, /* sv-fi */
- {51884, 124}, /* sv-se */
- {39559, 60}, /* sw */
- {51890, 153}, /* sw-ke */
- {39903, 66}, /* ta */
- {51896, 158}, /* ta-in */
- {40001, 67}, /* te */
- {51902, 159}, /* te-in */
- {38574, 40}, /* tg */
- {51908, 278}, /* tg-cyrl */
- {51916, 135}, /* tg-cyrl-tj */
- {37983, 30}, /* th */
- {51927, 125}, /* th-th */
- {38913, 47}, /* tn */
- {51933, 142}, /* tn-za */
- {38040, 31}, /* tr */
- {51939, 126}, /* tr-tr */
- {40847, 81}, /* tzm */
- {51945, 281}, /* tzm-latn */
- {38195, 34}, /* uk */
- {51954, 129}, /* uk-ua */
- {38082, 32}, /* ur */
- {51960, 127}, /* ur-pk */
- {39609, 61}, /* uz */
- {51966, 272}, /* uz-cyrl */
- {51974, 200}, /* uz-cyrl-uz */
- {51985, 279}, /* uz-latn */
- {51993, 154}, /* uz-latn-uz */
- {38645, 42}, /* vi */
- {52004, 137}, /* vi-vn */
- {38940, 48}, /* xh */
- {52010, 143}, /* xh-za */
- {41059, 86}, /* yo */
- {52016, 176}, /* yo-ng */
- {36730, 268}, /* zh */
- {52022, 3}, /* zh-chs */
- {52029, 275}, /* zh-cht */
- {52036, 187}, /* zh-cn */
- {52042, 4}, /* zh-hans */
- {52050, 274}, /* zh-hant */
- {52058, 204}, /* zh-hk */
- {52064, 217}, /* zh-mo */
- {52070, 211}, /* zh-sg */
- {52076, 100}, /* zh-tw */
- {38966, 49}, /* zu */
- {52082, 144} /* zu-za */
+ {51701, 157}, /* or-in */
+ {39739, 63}, /* pa */
+ {37544, 21}, /* pl */
+ {51707, 116}, /* pl-pl */
+ {40977, 83}, /* ps */
+ {51713, 173}, /* ps-af */
+ {37593, 22}, /* pt */
+ {51719, 117}, /* pt-br */
+ {51725, 195}, /* pt-pt */
+ {37649, 23}, /* rm */
+ {51731, 118}, /* rm-ch */
+ {37698, 24}, /* ro */
+ {51737, 119}, /* ro-ro */
+ {37746, 25}, /* ru */
+ {51743, 120}, /* ru-ru */
+ {41399, 95}, /* rw */
+ {51749, 184}, /* rw-rw */
+ {41367, 94}, /* sah */
+ {51755, 183}, /* sah-ru */
+ {39313, 55}, /* se */
+ {51762, 209}, /* se-fi */
+ {51768, 150}, /* se-no */
+ {40718, 79}, /* si */
+ {51774, 170}, /* si-lk */
+ {37878, 27}, /* sk */
+ {51780, 122}, /* sk-sk */
+ {38370, 36}, /* sl */
+ {51786, 131}, /* sl-si */
+ {37932, 28}, /* sq */
+ {51792, 123}, /* sq-al */
+ {48414, 277}, /* sr */
+ {51798, 265}, /* sr-cyrl */
+ {51806, 230}, /* sr-cyrl-ba */
+ {51817, 248}, /* sr-cyrl-me */
+ {51828, 240}, /* sr-cyrl-rs */
+ {51839, 266}, /* sr-latn */
+ {51847, 226}, /* sr-latn-ba */
+ {51858, 244}, /* sr-latn-me */
+ {51869, 236}, /* sr-latn-rs */
+ {37958, 29}, /* sv */
+ {51880, 196}, /* sv-fi */
+ {51886, 124}, /* sv-se */
+ {39561, 60}, /* sw */
+ {51892, 153}, /* sw-ke */
+ {39905, 66}, /* ta */
+ {51898, 158}, /* ta-in */
+ {40003, 67}, /* te */
+ {51904, 159}, /* te-in */
+ {38576, 40}, /* tg */
+ {51910, 278}, /* tg-cyrl */
+ {51918, 135}, /* tg-cyrl-tj */
+ {37985, 30}, /* th */
+ {51929, 125}, /* th-th */
+ {38915, 47}, /* tn */
+ {51935, 142}, /* tn-za */
+ {38042, 31}, /* tr */
+ {51941, 126}, /* tr-tr */
+ {40849, 81}, /* tzm */
+ {51947, 281}, /* tzm-latn */
+ {38197, 34}, /* uk */
+ {51956, 129}, /* uk-ua */
+ {38084, 32}, /* ur */
+ {51962, 127}, /* ur-pk */
+ {39611, 61}, /* uz */
+ {51968, 272}, /* uz-cyrl */
+ {51976, 200}, /* uz-cyrl-uz */
+ {51987, 279}, /* uz-latn */
+ {51995, 154}, /* uz-latn-uz */
+ {38647, 42}, /* vi */
+ {52006, 137}, /* vi-vn */
+ {38942, 48}, /* xh */
+ {52012, 143}, /* xh-za */
+ {41061, 86}, /* yo */
+ {52018, 176}, /* yo-ng */
+ {36732, 268}, /* zh */
+ {52024, 3}, /* zh-chs */
+ {52031, 275}, /* zh-cht */
+ {52038, 187}, /* zh-cn */
+ {52044, 4}, /* zh-hans */
+ {52052, 274}, /* zh-hant */
+ {52060, 204}, /* zh-hk */
+ {52066, 217}, /* zh-mo */
+ {52072, 211}, /* zh-sg */
+ {52078, 100}, /* zh-tw */
+ {38968, 49}, /* zu */
+ {52084, 144} /* zu-za */
};
static const RegionInfoEntry region_entries [] = {
- { 224,49820,47115,47115,52088,52109,36426,52156,52160,52188},
- { 3,45687,52212,52212,52216,52228,36206,52247,52251,52266},
- { 6,42867,52279,52279,52283,52291,35842,52302,52306,0},
- { 7,3781,48169,48169,52319,52327,35987,52375,52379,0},
- { 11,49311,47816,47816,52393,52393,35586,49034,52403,52418},
- { 14,47264,52433,52433,52437,52445,35481,52457,52461,52461},
- { 12,47297,52466,52466,52470,52470,35586,52480,52484,52484},
- { 5,43762,38754,38754,52502,52513,36234,52525,52529,52547},
- { 25,48415,52567,52567,52571,52594,36324,52631,52635,52671},
- { 23,47023,52714,52714,52718,52729,36272,52754,52758,52775},
- { 21,46502,38318,38318,52816,52824,35481,52457,52461,52833},
- { 35,41639,36583,36583,52838,52847,35465,52864,52868,52882},
- { 17,49932,52908,52908,52912,52920,36436,52935,52939,52954},
- { 37,46906,52978,52978,52982,52982,35586,52989,52993,53007},
- { 26,50112,53020,53020,53024,53024,36460,40551,53032,53051},
- { 32,42559,53061,53061,53065,53072,35735,53079,53083,53098},
- { 29,43253,53114,53114,53118,53126,0,53143,53147,53164},
- { 24,49068,53196,53196,53200,53200,35586,53207,53211,53211},
- { 39,47390,53225,53225,53229,53229,35586,53236,53240,53256},
- { 223,13261,53272,53272,53276,53288,0,53295,53299,53311},
- { 46,49713,53325,53325,53329,53329,35586,53335,53339,53352},
- { 45,13340,53365,53365,53369,53375,36162,53394,53398,53411},
- { 51,48912,53430,53430,53434,53434,35586,53443,53447,53462},
- { 54,48060,53478,53478,53482,53482,36306,53493,53497,53516},
- { 75,41802,53537,53537,53541,53556,35506,53574,53578,53600},
- { 94,41892,36885,36885,53615,53623,35481,52457,52461,52461},
- { 61,41844,53635,53635,53639,53647,35534,53655,53659,53672},
- { 65,48602,53684,53684,53688,53707,35586,53729,53733,53748},
- { 4,47820,53764,53764,53768,53776,36296,53791,53795,53810},
- { 66,49530,53834,53834,53838,53838,35586,53846,53850,53860},
- { 70,43351,50423,50423,53882,53890,35481,52457,52461,52833},
- { 67,47119,53896,53896,53900,53906,36276,53913,53917,53932},
- { 217,41682,37052,37052,53950,53956,35481,52457,52461,52833},
- { 73,45566,53964,53964,53968,53977,36186,53993,53997,54012},
- { 77,42022,37099,37099,54038,54046,35481,52457,52461,52833},
- { 81,44182,54052,54052,54056,54070,35534,53655,53659,54079},
- { 84,42066,37152,37152,54092,54092,35481,52457,52461,52833},
- { 242,45211,54099,54099,54103,54118,36167,54131,54135,54158},
- { 88,44128,54180,54180,54184,54192,0,54223,54227,54241},
- { 93,45965,54276,54276,54280,54290,35534,53655,53659,54307},
- { 98,41948,54325,54325,54329,54336,35481,52457,52461,54349},
- { 99,47708,54358,54358,54362,54362,7774,54372,54376,54395},
- { 104,47212,54416,54416,54420,54440,35586,54468,54472,54489},
- { 106,50252,54496,54496,54500,54500,2471,54509,54513,54530},
- { 108,42758,37845,37845,54549,54557,35839,54566,54570,54584},
- { 109,42167,37264,37264,54589,54597,35636,54611,54615,54632},
- { 111,43116,54646,54646,54650,54650,35865,54660,54664,54682},
- { 68,46855,54699,54699,54703,54711,35481,52457,52461,52461},
- { 117,42115,54717,54717,54721,54728,35632,54739,54743,54762},
- { 113,44239,38168,38168,54769,54775,36012,54788,54792,54805},
- { 121,46296,54840,54840,54844,54849,36245,54862,54866,54878},
- { 116,43540,54900,54900,54904,54909,35979,54920,54924,54937},
- { 110,42216,37311,37311,54957,54965,35534,54973,54977,54994},
- { 118,42259,37359,37359,55010,55016,35481,52457,52461,52461},
- { 124,48750,55023,55023,55027,55027,35586,55035,55039,55039},
- { 126,49214,55055,55055,55059,55066,36396,55079,55083,55099},
- { 122,42304,37389,37389,55121,55127,35502,55134,55138,55151},
- { 129,44492,55161,55161,55165,55165,36026,55171,55175,55191},
- { 130,44449,55209,55209,55213,55224,36019,55245,55249,0},
- { 40,45289,40621,40621,55264,55273,36170,55295,55299,55314},
- { 134,42359,37444,37444,55319,55331,35670,55344,55348,55365},
- { 136,49635,55382,55382,55386,55393,36416,55406,55410,55424},
- { 138,45331,40646,40646,55446,40636,36174,55451,55455,55467},
- { 139,49448,55477,55477,55481,55489,36406,55500,55504,55519},
- { 145,47969,55541,55541,55545,55545,0,53295,53299,55559},
- { 42,45507,55577,55577,55581,55591,36178,55623,55627,55644},
- { 141,43449,55679,55679,55683,55693,35955,55701,55705,55722},
- { 147,47627,55728,55728,55732,55743,35481,52457,52461,52461},
- { 140,43397,55753,55753,55757,55764,35915,55772,55776,55789},
- { 148,47510,55803,55803,55807,55813,36286,55824,55828,55841},
- { 159,48173,40415,40415,55861,55869,36310,55882,55886,55902},
- { 158,48298,55922,55922,55926,55926,35481,52457,52461,52833},
- { 270,49390,55933,55933,55937,55948,35481,52457,52461,55966},
- { 19618,43878,55971,55971,55975,55985,0,55971,56006,56023},
- { 151,47909,56055,56055,56059,56075,0,56103,56107,56123},
- { 163,44278,39282,39282,56133,56133,35481,52457,52461,56139},
- { 166,46451,56144,56144,56148,56155,35586,56163,56167,56180},
- { 167,44383,56194,56194,56198,56198,36016,56207,56211,56229},
- { 175,45795,56246,56246,56250,56258,36213,56267,56271,56286},
- { 182,50306,56292,56292,56296,56296,36467,56306,56310,56330},
- { 176,42411,37482,37482,56353,56365,35481,52457,52461,52461},
- { 177,42469,37531,37531,56375,56382,35534,56388,56392,56408},
- { 178,45627,56422,56422,56426,56432,36193,56448,56452,0},
- { 183,48004,56467,56467,56471,56471,35586,56483,56487,56487},
- { 164,48719,56506,56506,56510,56515,36343,56526,56530,56541},
- { 192,48250,39767,39767,56561,56568,36320,56576,56580,56598},
- { 187,49113,56615,56615,56619,56624,36384,56630,56634,56653},
- { 201,45741,56671,56671,56675,56687,36209,56697,56701,56701},
- { 190,43055,56717,56717,56721,56730,35860,56745,56749,56765},
- { 191,42510,56793,56793,56797,56804,35693,56811,56815,56828},
- { 202,50364,56842,56842,56846,56846,35586,53846,53850,53860},
- { 193,46718,56858,56858,56862,56862,35481,52457,52461,52461},
- { 185,49984,56871,56871,56875,56875,36446,56884,56888,56907},
- { 197,50036,56926,56926,56930,56936,36450,56943,56947,56959},
- { 200,42654,56977,56977,56981,56989,0,56998,57002,57015},
- { 271,48982,50746,50746,57029,57036,36369,57049,57053,57067},
- { 203,42710,37770,37770,57080,57087,35760,57100,57104,57118},
- { 204,46164,57150,57150,57154,57154,36217,57161,57165,0},
- { 205,13258,57179,57179,57183,57196,35409,57243,57247,57259},
- { 221,42911,57279,57279,57283,57290,35534,57298,57302,57316},
- { 215,47574,57329,57329,57333,57343,0,57353,57357,57374},
- { 212,43309,57387,57387,57391,57400,35481,52457,52461,57410},
- { 143,42820,57415,57415,57419,57428,35481,52457,52461,52461},
- { 72,50170,38395,38395,57449,57449,36463,53846,53850,53860},
- { 222,49038,57461,57461,57465,57471,36374,57482,57486,57499},
- { 227,42958,38001,38001,57519,37991,35853,57528,57532,57542},
- { 228,43492,57561,57561,57565,0,36019,57576,57580,57599},
- { 234,48494,57612,57612,57616,57624,36327,57633,57637,57652},
- { 235,43004,57673,57673,57677,57684,35857,57693,57697,57710},
- { 225,49257,57724,57724,57728,57728,35586,57748,57752,57752},
- { 237,41733,57779,57779,57783,57790,36220,57797,57801,57819},
- { 241,43183,38229,38229,57829,57837,35868,57852,57856,57874},
- { 244,41981,57908,57908,57912,57912,35586,53846,53850,53850},
- { 246,49870,57926,57926,57930,57930,35586,57938,57942,57957},
- { 247,44566,39629,39629,57971,57982,36239,58003,58007,58022},
- { 249,48804,58041,58041,58045,58045,36353,58055,58059,58079},
- { 251,43598,58099,58099,58103,58111,35983,58122,58126,58142},
- { 261,48860,58150,58150,58154,58160,36359,58171,58175,58187},
- { 209,43909,58205,58205,58209,0,10511,58222,58226,0},
- { 264,49480,58245,58245,58249,58249,35586,53846,53850,53850}
+ { 224,49822,47117,47117,52090,52111,36428,52158,52162,52190},
+ { 3,45689,52214,52214,52218,52230,36210,52249,52253,52268},
+ { 6,42869,52281,52281,52285,52293,35844,52304,52308,0},
+ { 7,3781,48171,48171,52321,52329,35991,52377,52381,0},
+ { 11,49313,47818,47818,52395,52395,35586,49036,52405,52420},
+ { 14,47266,52435,52435,52439,52447,35481,52459,52463,52463},
+ { 12,47299,52468,52468,52472,52472,35586,52482,52486,52486},
+ { 5,43764,38756,38756,52504,52515,36238,52527,52531,52549},
+ { 25,48417,52569,52569,52573,52596,36326,52633,52637,52673},
+ { 23,47025,52716,52716,52720,52731,36274,52756,52760,52777},
+ { 21,46504,38320,38320,52818,52826,35481,52459,52463,52835},
+ { 35,41641,36585,36585,52840,52849,35465,52866,52870,52884},
+ { 17,49934,52910,52910,52914,52922,36438,52937,52941,52956},
+ { 37,46908,52980,52980,52984,52984,35586,52991,52995,53009},
+ { 26,50114,53022,53022,53026,53026,36462,40553,53034,53053},
+ { 32,42561,53063,53063,53067,53074,35735,53081,53085,53100},
+ { 29,43255,53116,53116,53120,53128,0,53145,53149,53166},
+ { 24,49070,53198,53198,53202,53202,35586,53209,53213,53213},
+ { 39,47392,53227,53227,53231,53231,35586,53238,53242,53258},
+ { 223,13261,53274,53274,53278,53290,0,53297,53301,53313},
+ { 46,49715,53327,53327,53331,53331,35586,53337,53341,53354},
+ { 45,13340,53367,53367,53371,53377,36166,53396,53400,53413},
+ { 51,48914,53432,53432,53436,53436,35586,53445,53449,53464},
+ { 54,48062,53480,53480,53484,53484,36308,53495,53499,53518},
+ { 75,41804,53539,53539,53543,53558,35506,53576,53580,53602},
+ { 94,41894,36887,36887,53617,53625,35481,52459,52463,52463},
+ { 61,41846,53637,53637,53641,53649,35534,53657,53661,53674},
+ { 65,48604,53686,53686,53690,53709,35586,53731,53735,53750},
+ { 4,47822,53766,53766,53770,53778,36298,53793,53797,53812},
+ { 66,49532,53836,53836,53840,53840,35586,53848,53852,53862},
+ { 70,43353,50425,50425,53884,53892,35481,52459,52463,52835},
+ { 67,47121,53898,53898,53902,53908,36278,53915,53919,53934},
+ { 217,41684,37054,37054,53952,53958,35481,52459,52463,52835},
+ { 73,45568,53966,53966,53970,53979,36190,53995,53999,54014},
+ { 77,42024,37101,37101,54040,54048,35481,52459,52463,52835},
+ { 81,44184,54054,54054,54058,54072,35534,53657,53661,54081},
+ { 84,42068,37154,37154,54094,54094,35481,52459,52463,52835},
+ { 242,45213,54101,54101,54105,54120,36171,54133,54137,54160},
+ { 88,44130,54182,54182,54186,54194,0,54225,54229,54243},
+ { 93,45967,54278,54278,54282,54292,35534,53657,53661,54309},
+ { 98,41950,54327,54327,54331,54338,35481,52459,52463,54351},
+ { 99,47710,54360,54360,54364,54364,7774,54374,54378,54397},
+ { 104,47214,54418,54418,54422,54442,35586,54470,54474,54491},
+ { 106,50254,54498,54498,54502,54502,2471,54511,54515,54532},
+ { 108,42760,37847,37847,54551,54559,35841,54568,54572,54586},
+ { 109,42169,37266,37266,54591,54599,35636,54613,54617,54634},
+ { 111,43118,54648,54648,54652,54652,35867,54662,54666,54684},
+ { 68,46857,54701,54701,54705,54713,35481,52459,52463,52463},
+ { 117,42117,54719,54719,54723,54730,35632,54741,54745,54764},
+ { 113,44241,38170,38170,54771,54777,36016,54790,54794,54807},
+ { 121,46298,54842,54842,54846,54851,36249,54864,54868,54880},
+ { 116,43542,54902,54902,54906,54911,35983,54922,54926,54939},
+ { 110,42218,37313,37313,54959,54967,35534,54975,54979,54996},
+ { 118,42261,37361,37361,55012,55018,35481,52459,52463,52463},
+ { 124,48752,55025,55025,55029,55029,35586,55037,55041,55041},
+ { 126,49216,55057,55057,55061,55068,36398,55081,55085,55101},
+ { 122,42306,37391,37391,55123,55129,35502,55136,55140,55153},
+ { 129,44494,55163,55163,55167,55167,36030,55173,55177,55193},
+ { 130,44451,55211,55211,55215,55226,36023,55247,55251,0},
+ { 40,45291,40623,40623,55266,55275,36174,55297,55301,55316},
+ { 134,42361,37446,37446,55321,55333,35670,55346,55350,55367},
+ { 136,49637,55384,55384,55388,55395,36418,55408,55412,55426},
+ { 138,45333,40648,40648,55448,40638,36178,55453,55457,55469},
+ { 139,49450,55479,55479,55483,55491,36408,55502,55506,55521},
+ { 145,47971,55543,55543,55547,55547,0,53297,53301,55561},
+ { 42,45509,55579,55579,55583,55593,36182,55625,55629,55646},
+ { 141,43451,55681,55681,55685,55695,35957,55703,55707,55724},
+ { 147,47629,55730,55730,55734,55745,35481,52459,52463,52463},
+ { 140,43399,55755,55755,55759,55766,35917,55774,55778,55791},
+ { 148,47512,55805,55805,55809,55815,36288,55826,55830,55843},
+ { 159,48175,40417,40417,55863,55871,36312,55884,55888,55904},
+ { 158,48300,55924,55924,55928,55928,35481,52459,52463,52835},
+ { 270,49392,55935,55935,55939,55950,35481,52459,52463,55968},
+ { 19618,43880,55973,55973,55977,55987,0,55973,56008,56025},
+ { 151,47911,56057,56057,56061,56077,0,56105,56109,56125},
+ { 163,44280,39284,39284,56135,56135,35481,52459,52463,56141},
+ { 166,46453,56146,56146,56150,56157,35586,56165,56169,56182},
+ { 167,44385,56196,56196,56200,56200,36020,56209,56213,56231},
+ { 175,45797,56248,56248,56252,56260,36217,56269,56273,56288},
+ { 182,50308,56294,56294,56298,56298,36469,56308,56312,56332},
+ { 176,42413,37484,37484,56355,56367,35481,52459,52463,52463},
+ { 177,42471,37533,37533,56377,56384,35534,56390,56394,56410},
+ { 178,45629,56424,56424,56428,56434,36197,56450,56454,0},
+ { 183,48006,56469,56469,56473,56473,35586,56485,56489,56489},
+ { 164,48721,56508,56508,56512,56517,36345,56528,56532,56543},
+ { 192,48252,39769,39769,56563,56570,36322,56578,56582,56600},
+ { 187,49115,56617,56617,56621,56626,36386,56632,56636,56655},
+ { 201,45743,56673,56673,56677,56689,36213,56699,56703,56703},
+ { 190,43057,56719,56719,56723,56732,35862,56747,56751,56767},
+ { 191,42512,56795,56795,56799,56806,35693,56813,56817,56830},
+ { 202,50366,56844,56844,56848,56848,35586,53848,53852,53862},
+ { 193,46720,56860,56860,56864,56864,35481,52459,52463,52463},
+ { 185,49986,56873,56873,56877,56877,36448,56886,56890,56909},
+ { 197,50038,56928,56928,56932,56938,36452,56945,56949,56961},
+ { 200,42656,56979,56979,56983,56991,0,57000,57004,57017},
+ { 271,48984,50748,50748,57031,57038,36371,57051,57055,57069},
+ { 203,42712,37772,37772,57082,57089,35762,57102,57106,57120},
+ { 204,46166,57152,57152,57156,57156,36221,57163,57167,0},
+ { 205,13258,57181,57181,57185,57198,35411,57245,57249,57261},
+ { 221,42913,57281,57281,57285,57292,35534,57300,57304,57318},
+ { 215,47576,57331,57331,57335,57345,0,57355,57359,57376},
+ { 212,43311,57389,57389,57393,57402,35481,52459,52463,57412},
+ { 143,42822,57417,57417,57421,57430,35481,52459,52463,52463},
+ { 72,50172,38397,38397,57451,57451,36465,53848,53852,53862},
+ { 222,49040,57463,57463,57467,57473,36376,57484,57488,57501},
+ { 227,42960,38003,38003,57521,37993,35855,57530,57534,57544},
+ { 228,43494,57563,57563,57567,0,36023,57578,57582,57601},
+ { 234,48496,57614,57614,57618,57626,36329,57635,57639,57654},
+ { 235,43006,57675,57675,57679,57686,35859,57695,57699,57712},
+ { 225,49259,57726,57726,57730,57730,35586,57750,57754,57754},
+ { 237,41735,57781,57781,57785,57792,36224,57799,57803,57821},
+ { 241,43185,38231,38231,57831,57839,35870,57854,57858,57876},
+ { 244,41983,57910,57910,57914,57914,35586,53848,53852,53852},
+ { 246,49872,57928,57928,57932,57932,35586,57940,57944,57959},
+ { 247,44568,39631,39631,57973,57984,36243,58005,58009,58024},
+ { 249,48806,58043,58043,58047,58047,36355,58057,58061,58081},
+ { 251,43600,58101,58101,58105,58113,35987,58124,58128,58144},
+ { 261,48862,58152,58152,58156,58162,36361,58173,58177,58189},
+ { 209,43911,58207,58207,58211,0,10511,58224,58228,0},
+ { 264,49482,58247,58247,58251,58251,35586,53848,53852,53852}
};
static const RegionInfoNameEntry region_name_entries [] = {
- {49820, 0}, /* AE */
- {45687, 1}, /* AF */
- {42867, 2}, /* AL */
+ {49822, 0}, /* AE */
+ {45689, 1}, /* AF */
+ {42869, 2}, /* AL */
{3781, 3}, /* AM */
- {49311, 4}, /* AR */
- {47264, 5}, /* AT */
- {47297, 6}, /* AU */
- {43762, 7}, /* AZ */
- {48415, 8}, /* BA */
- {47023, 9}, /* BD */
- {46502, 10}, /* BE */
- {41639, 11}, /* BG */
- {49932, 12}, /* BH */
- {46906, 13}, /* BN */
- {50112, 14}, /* BO */
- {42559, 15}, /* BR */
- {43253, 16}, /* BY */
- {49068, 17}, /* BZ */
- {47390, 18}, /* CA */
+ {49313, 4}, /* AR */
+ {47266, 5}, /* AT */
+ {47299, 6}, /* AU */
+ {43764, 7}, /* AZ */
+ {48417, 8}, /* BA */
+ {47025, 9}, /* BD */
+ {46504, 10}, /* BE */
+ {41641, 11}, /* BG */
+ {49934, 12}, /* BH */
+ {46908, 13}, /* BN */
+ {50114, 14}, /* BO */
+ {42561, 15}, /* BR */
+ {43255, 16}, /* BY */
+ {49070, 17}, /* BZ */
+ {47392, 18}, /* CA */
{13261, 19}, /* CH */
- {49713, 20}, /* CL */
+ {49715, 20}, /* CL */
{13340, 21}, /* CN */
- {48912, 22}, /* CO */
- {48060, 23}, /* CR */
- {41802, 24}, /* CZ */
- {41892, 25}, /* DE */
- {41844, 26}, /* DK */
- {48602, 27}, /* DO */
- {47820, 28}, /* DZ */
- {49530, 29}, /* EC */
- {43351, 30}, /* EE */
- {47119, 31}, /* EG */
- {41682, 32}, /* ES */
- {45566, 33}, /* ET */
- {42022, 34}, /* FI */
- {44182, 35}, /* FO */
- {42066, 36}, /* FR */
- {45211, 37}, /* GB */
- {44128, 38}, /* GE */
- {45965, 39}, /* GL */
- {41948, 40}, /* GR */
- {47708, 41}, /* GT */
- {47212, 42}, /* HK */
- {50252, 43}, /* HN */
- {42758, 44}, /* HR */
- {42167, 45}, /* HU */
- {43116, 46}, /* ID */
- {46855, 47}, /* IE */
- {42115, 48}, /* IL */
- {44239, 49}, /* IN */
- {46296, 50}, /* IQ */
- {43540, 51}, /* IR */
- {42216, 52}, /* IS */
- {42259, 53}, /* IT */
- {48750, 54}, /* JM */
- {49214, 55}, /* JO */
- {42304, 56}, /* JP */
- {44492, 57}, /* KE */
- {44449, 58}, /* KG */
- {45289, 59}, /* KH */
- {42359, 60}, /* KR */
- {49635, 61}, /* KW */
- {45331, 62}, /* LA */
- {49448, 63}, /* LB */
- {47969, 64}, /* LI */
- {45507, 65}, /* LK */
- {43449, 66}, /* LT */
- {47627, 67}, /* LU */
- {43397, 68}, /* LV */
- {47510, 69}, /* LY */
- {48173, 70}, /* MA */
- {48298, 71}, /* MC */
- {49390, 72}, /* ME */
- {43878, 73}, /* MK */
- {47909, 74}, /* MO */
- {44278, 75}, /* MT */
- {46451, 76}, /* MX */
- {44383, 77}, /* MY */
- {45795, 78}, /* NG */
- {50306, 79}, /* NI */
- {42411, 80}, /* NL */
- {42469, 81}, /* NO */
- {45627, 82}, /* NP */
- {48004, 83}, /* NZ */
- {48719, 84}, /* OM */
- {48250, 85}, /* PA */
- {49113, 86}, /* PE */
- {45741, 87}, /* PH */
- {43055, 88}, /* PK */
- {42510, 89}, /* PL */
- {50364, 90}, /* PR */
- {46718, 91}, /* PT */
- {49984, 92}, /* PY */
- {50036, 93}, /* QA */
- {42654, 94}, /* RO */
- {48982, 95}, /* RS */
- {42710, 96}, /* RU */
- {46164, 97}, /* RW */
+ {48914, 22}, /* CO */
+ {48062, 23}, /* CR */
+ {41804, 24}, /* CZ */
+ {41894, 25}, /* DE */
+ {41846, 26}, /* DK */
+ {48604, 27}, /* DO */
+ {47822, 28}, /* DZ */
+ {49532, 29}, /* EC */
+ {43353, 30}, /* EE */
+ {47121, 31}, /* EG */
+ {41684, 32}, /* ES */
+ {45568, 33}, /* ET */
+ {42024, 34}, /* FI */
+ {44184, 35}, /* FO */
+ {42068, 36}, /* FR */
+ {45213, 37}, /* GB */
+ {44130, 38}, /* GE */
+ {45967, 39}, /* GL */
+ {41950, 40}, /* GR */
+ {47710, 41}, /* GT */
+ {47214, 42}, /* HK */
+ {50254, 43}, /* HN */
+ {42760, 44}, /* HR */
+ {42169, 45}, /* HU */
+ {43118, 46}, /* ID */
+ {46857, 47}, /* IE */
+ {42117, 48}, /* IL */
+ {44241, 49}, /* IN */
+ {46298, 50}, /* IQ */
+ {43542, 51}, /* IR */
+ {42218, 52}, /* IS */
+ {42261, 53}, /* IT */
+ {48752, 54}, /* JM */
+ {49216, 55}, /* JO */
+ {42306, 56}, /* JP */
+ {44494, 57}, /* KE */
+ {44451, 58}, /* KG */
+ {45291, 59}, /* KH */
+ {42361, 60}, /* KR */
+ {49637, 61}, /* KW */
+ {45333, 62}, /* LA */
+ {49450, 63}, /* LB */
+ {47971, 64}, /* LI */
+ {45509, 65}, /* LK */
+ {43451, 66}, /* LT */
+ {47629, 67}, /* LU */
+ {43399, 68}, /* LV */
+ {47512, 69}, /* LY */
+ {48175, 70}, /* MA */
+ {48300, 71}, /* MC */
+ {49392, 72}, /* ME */
+ {43880, 73}, /* MK */
+ {47911, 74}, /* MO */
+ {44280, 75}, /* MT */
+ {46453, 76}, /* MX */
+ {44385, 77}, /* MY */
+ {45797, 78}, /* NG */
+ {50308, 79}, /* NI */
+ {42413, 80}, /* NL */
+ {42471, 81}, /* NO */
+ {45629, 82}, /* NP */
+ {48006, 83}, /* NZ */
+ {48721, 84}, /* OM */
+ {48252, 85}, /* PA */
+ {49115, 86}, /* PE */
+ {45743, 87}, /* PH */
+ {43057, 88}, /* PK */
+ {42512, 89}, /* PL */
+ {50366, 90}, /* PR */
+ {46720, 91}, /* PT */
+ {49986, 92}, /* PY */
+ {50038, 93}, /* QA */
+ {42656, 94}, /* RO */
+ {48984, 95}, /* RS */
+ {42712, 96}, /* RU */
+ {46166, 97}, /* RW */
{13258, 98}, /* SA */
- {42911, 99}, /* SE */
- {47574, 100}, /* SG */
- {43309, 101}, /* SI */
- {42820, 102}, /* SK */
- {50170, 103}, /* SV */
- {49038, 104}, /* SY */
- {42958, 105}, /* TH */
- {43492, 106}, /* TJ */
- {48494, 107}, /* TN */
- {43004, 108}, /* TR */
- {49257, 109}, /* TT */
- {41733, 110}, /* TW */
- {43183, 111}, /* UA */
- {41981, 112}, /* US */
- {49870, 113}, /* UY */
- {44566, 114}, /* UZ */
- {48804, 115}, /* VE */
- {43598, 116}, /* VN */
- {48860, 117}, /* YE */
- {43909, 118}, /* ZA */
- {49480, 119} /* ZW */
+ {42913, 99}, /* SE */
+ {47576, 100}, /* SG */
+ {43311, 101}, /* SI */
+ {42822, 102}, /* SK */
+ {50172, 103}, /* SV */
+ {49040, 104}, /* SY */
+ {42960, 105}, /* TH */
+ {43494, 106}, /* TJ */
+ {48496, 107}, /* TN */
+ {43006, 108}, /* TR */
+ {49259, 109}, /* TT */
+ {41735, 110}, /* TW */
+ {43185, 111}, /* UA */
+ {41983, 112}, /* US */
+ {49872, 113}, /* UY */
+ {44568, 114}, /* UZ */
+ {48806, 115}, /* VE */
+ {43600, 116}, /* VN */
+ {48862, 117}, /* YE */
+ {43911, 118}, /* ZA */
+ {49482, 119} /* ZW */
};
"\xd9\x83\xd8\xa7\xd9\x86\xd9\x88\xd9\x86 \xd8\xa7\xd9\x84\xd8\xa3\xd9\x88\xd9\x84\0"
"\xd1\x81\xd1\x80\xd0\xb5\0"
"dddd, d MMMM, yyyy\0"
+ ",\0"
"\xd9\xab\0"
"\xd9\xac\0"
"\xd8\xb1.\xd8\xb3.\xe2\x80\x8f\0"
"-Infinity\0"
"Infinity\0"
"+\0"
- ",\0"
"\xc2\xa0\0"
"\xd0\xbb\xd0\xb2.\0"
"%\0"
"-niesko\xc5\x84\x63zono\xc5\x9b\xc4\x87\0"
"+niesko\xc5\x84\x63zono\xc5\x9b\xc4\x87\0"
"R$\0"
+ "'\0"
"\xe2\x80\x99\0"
"-infinit\0"
"+infinit\0"
"Lt\0"
"-begalyb\xc4\x97\0"
"begalyb\xc4\x97\0"
+ ";\0"
"\xef\xb7\xbc\0"
"\xe2\x82\xab\0"
"\xd5\xa4\xd6\x80.\0"
"man.\0"
"so\xca\xbcm\0"
"\xd8\xaf.\xd8\xb9.\xe2\x80\x8f\0"
- "'\0"
"\xd0\xbc\xd0\xb0\xd0\xbd.\0"
"\xd1\x81\xd1\x9e\xd0\xbc\0"
"\xe0\xa7\xb3\0"
gboolean dbg_hidden:1;
/* Whenever this jit info was loaded in async context */
gboolean async:1;
+ gboolean dbg_step_through_inited:1;
+ gboolean dbg_step_through:1;
/* FIXME: Embed this after the structure later*/
gpointer gc_info; /* Currently only used by SGen */
--- /dev/null
+/*
+ * test-sgen-qsort.c: Our own bzero/memmove.
+ *
+ * Copyright (C) 2013 Xamarin Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License 2.0 as published by the Free Software Foundation;
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License 2.0 along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * SGen cannot deal with invalid pointers on the heap or in registered roots. Sometimes we
+ * need to copy or zero out memory in code that might be interrupted by collections. To
+ * guarantee that those operations will not result in invalid pointers, we must do it
+ * word-atomically.
+ *
+ * libc's bzero() and memcpy()/memmove() functions do not guarantee word-atomicity, even in
+ * cases where one would assume so. For instance, some implementations (like Darwin's on
+ * x86) have variants of memcpy() using vector instructions. Those may copy bytewise for
+ * the region preceding the first vector-aligned address. That region could be
+ * word-aligned, but it would still be copied byte-wise.
+ *
+ * All our memory writes here are to "volatile" locations. This is so that C compilers
+ * don't "optimize" our code back to calls to bzero()/memmove(). LLVM, specifically, will
+ * do that.
+ */
+
+#include <config.h>
+
+#include "metadata/gc-internal.h"
+
+#define ptr_mask ((sizeof (void*) - 1))
+#define _toi(ptr) ((size_t)ptr)
+#define unaligned_bytes(ptr) (_toi(ptr) & ptr_mask)
+#define align_down(ptr) ((void*)(_toi(ptr) & ~ptr_mask))
+#define align_up(ptr) ((void*) ((_toi(ptr) + ptr_mask) & ~ptr_mask))
+#if SIZEOF_VOID_P == 4
+#define bytes_to_words(n) ((size_t)(n) >> 2)
+#elif SIZEOF_VOID_P == 8
+#define bytes_to_words(n) ((size_t)(n) >> 3)
+#else
+#error We only support 32 and 64 bit architectures.
+#endif
+
+#define BZERO_WORDS(dest,words) do { \
+ void * volatile *__d = (void* volatile*)(dest); \
+ int __n = (words); \
+ int __i; \
+ for (__i = 0; __i < __n; ++__i) \
+ __d [__i] = NULL; \
+ } while (0)
+
+/**
+ * mono_gc_bzero:
+ * @dest: address to start to clear
+ * @size: size of the region to clear
+ *
+ * Zero @size bytes starting at @dest.
+ *
+ * Use this to zero memory that can hold managed pointers.
+ *
+ * FIXME borrow faster code from some BSD libc or bionic
+ */
+void
+mono_gc_bzero (void *dest, size_t size)
+{
+ volatile char *d = (char*)dest;
+ size_t tail_bytes, word_bytes;
+
+ /*
+ If we're copying less than a word, just use memset.
+
+ We cannot bail out early if both are aligned because some implementations
+ use byte copying for sizes smaller than 16. OSX, on this case.
+ */
+ if (size < sizeof(void*)) {
+ memset (dest, 0, size);
+ return;
+ }
+
+ /*align to word boundary */
+ while (unaligned_bytes (d) && size) {
+ *d++ = 0;
+ --size;
+ }
+
+ /* copy all words with memmove */
+ word_bytes = (size_t)align_down (size);
+ switch (word_bytes) {
+ case sizeof (void*) * 1:
+ BZERO_WORDS (d, 1);
+ break;
+ case sizeof (void*) * 2:
+ BZERO_WORDS (d, 2);
+ break;
+ case sizeof (void*) * 3:
+ BZERO_WORDS (d, 3);
+ break;
+ case sizeof (void*) * 4:
+ BZERO_WORDS (d, 4);
+ break;
+ default:
+ BZERO_WORDS (d, bytes_to_words (word_bytes));
+ }
+
+ tail_bytes = unaligned_bytes (size);
+ if (tail_bytes) {
+ d += word_bytes;
+ do {
+ *d++ = 0;
+ } while (--tail_bytes);
+ }
+}
+
+#define MEMMOVE_WORDS_UPWARD(dest,src,words) do { \
+ void * volatile *__d = (void* volatile*)(dest); \
+ void **__s = (void**)(src); \
+ int __n = (int)(words); \
+ int __i; \
+ for (__i = 0; __i < __n; ++__i) \
+ __d [__i] = __s [__i]; \
+ } while (0)
+
+#define MEMMOVE_WORDS_DOWNWARD(dest,src,words) do { \
+ void * volatile *__d = (void* volatile*)(dest); \
+ void **__s = (void**)(src); \
+ int __n = (int)(words); \
+ int __i; \
+ for (__i = __n - 1; __i >= 0; --__i) \
+ __d [__i] = __s [__i]; \
+ } while (0)
+
+/**
+ * mono_gc_memmove:
+ * @dest: destination of the move
+ * @src: source
+ * @size: size of the block to move
+ *
+ * Move @size bytes from @src to @dest.
+ * size MUST be a multiple of sizeof (gpointer)
+ *
+ */
+void
+mono_gc_memmove (void *dest, const void *src, size_t size)
+{
+ /*
+ If we're copying less than a word we don't need to worry about word tearing
+ so we bailout to memmove early.
+ */
+ if (size < sizeof(void*)) {
+ memmove (dest, src, size);
+ return;
+ }
+
+ /*
+ * A bit of explanation on why we align only dest before doing word copies.
+ * Pointers to managed objects must always be stored in word aligned addresses, so
+ * even if dest is misaligned, src will be by the same amount - this ensure proper atomicity of reads.
+ *
+ * We don't need to case when source and destination have different alignments since we only do word stores
+ * using memmove, which must handle it.
+ */
+ if (dest > src && ((size_t)((char*)dest - (char*)src) < size)) { /*backward copy*/
+ volatile char *p = (char*)dest + size;
+ char *s = (char*)src + size;
+ char *start = (char*)dest;
+ char *align_end = MAX((char*)dest, (char*)align_down (p));
+ char *word_start;
+ size_t bytes_to_memmove;
+
+ while (p > align_end)
+ *--p = *--s;
+
+ word_start = align_up (start);
+ bytes_to_memmove = p - word_start;
+ p -= bytes_to_memmove;
+ s -= bytes_to_memmove;
+ MEMMOVE_WORDS_DOWNWARD (p, s, bytes_to_words (bytes_to_memmove));
+
+ while (p > start)
+ *--p = *--s;
+ } else {
+ volatile char *d = (char*)dest;
+ const char *s = (const char*)src;
+ size_t tail_bytes;
+
+ /*align to word boundary */
+ while (unaligned_bytes (d)) {
+ *d++ = *s++;
+ --size;
+ }
+
+ /* copy all words with memmove */
+ MEMMOVE_WORDS_UPWARD (d, s, bytes_to_words (align_down (size)));
+
+ tail_bytes = unaligned_bytes (size);
+ if (tail_bytes) {
+ d += (size_t)align_down (size);
+ s += (size_t)align_down (size);
+ do {
+ *d++ = *s++;
+ } while (--tail_bytes);
+ }
+ }
+}
{
queue->should_be_deleted = TRUE;
}
-
-#define ptr_mask ((sizeof (void*) - 1))
-#define _toi(ptr) ((size_t)ptr)
-#define unaligned_bytes(ptr) (_toi(ptr) & ptr_mask)
-#define align_down(ptr) ((void*)(_toi(ptr) & ~ptr_mask))
-#define align_up(ptr) ((void*) ((_toi(ptr) + ptr_mask) & ~ptr_mask))
-
-#define BZERO_WORDS(dest,words) do { \
- int __i; \
- for (__i = 0; __i < (words); ++__i) \
- ((void **)(dest))[__i] = 0; \
-} while (0)
-
-/**
- * mono_gc_bzero:
- * @dest: address to start to clear
- * @size: size of the region to clear
- *
- * Zero @size bytes starting at @dest.
- *
- * Use this to zero memory that can hold managed pointers.
- *
- * FIXME borrow faster code from some BSD libc or bionic
- */
-void
-mono_gc_bzero (void *dest, size_t size)
-{
- char *d = (char*)dest;
- size_t tail_bytes, word_bytes;
-
- /*
- If we're copying less than a word, just use memset.
-
- We cannot bail out early if both are aligned because some implementations
- use byte copying for sizes smaller than 16. OSX, on this case.
- */
- if (size < sizeof(void*)) {
- memset (dest, 0, size);
- return;
- }
-
- /*align to word boundary */
- while (unaligned_bytes (d) && size) {
- *d++ = 0;
- --size;
- }
-
- /* copy all words with memmove */
- word_bytes = (size_t)align_down (size);
- switch (word_bytes) {
- case sizeof (void*) * 1:
- BZERO_WORDS (d, 1);
- break;
- case sizeof (void*) * 2:
- BZERO_WORDS (d, 2);
- break;
- case sizeof (void*) * 3:
- BZERO_WORDS (d, 3);
- break;
- case sizeof (void*) * 4:
- BZERO_WORDS (d, 4);
- break;
- default:
- memset (d, 0, word_bytes);
- }
-
- tail_bytes = unaligned_bytes (size);
- if (tail_bytes) {
- d += word_bytes;
- do {
- *d++ = 0;
- } while (--tail_bytes);
- }
-}
-
-/**
- * mono_gc_memmove:
- * @dest: destination of the move
- * @src: source
- * @size: size of the block to move
- *
- * Move @size bytes from @src to @dest.
- * size MUST be a multiple of sizeof (gpointer)
- *
- */
-void
-mono_gc_memmove (void *dest, const void *src, size_t size)
-{
- /*
- If we're copying less than a word we don't need to worry about word tearing
- so we bailout to memmove early.
-
- If both dest is aligned and size is a multiple of word size, we can go straigh
- to memmove.
-
- */
- if (size < sizeof(void*) || !((_toi (dest) | (size)) & sizeof (void*))) {
- memmove (dest, src, size);
- return;
- }
-
- /*
- * A bit of explanation on why we align only dest before doing word copies.
- * Pointers to managed objects must always be stored in word aligned addresses, so
- * even if dest is misaligned, src will be by the same amount - this ensure proper atomicity of reads.
- *
- * We don't need to case when source and destination have different alignments since we only do word stores
- * using memmove, which must handle it.
- */
- if (dest > src && ((size_t)((char*)dest - (char*)src) < size)) { /*backward copy*/
- char *p = (char*)dest + size;
- char *s = (char*)src + size;
- char *start = (char*)dest;
- char *align_end = MAX((char*)dest, (char*)align_down (p));
- char *word_start;
- size_t bytes_to_memmove;
-
- while (p > align_end)
- *--p = *--s;
-
- word_start = align_up (start);
- bytes_to_memmove = p - word_start;
- p -= bytes_to_memmove;
- s -= bytes_to_memmove;
- memmove (p, s, bytes_to_memmove);
-
- while (p > start)
- *--p = *--s;
- } else {
- char *d = (char*)dest;
- const char *s = (const char*)src;
- size_t tail_bytes;
-
- /*align to word boundary */
- while (unaligned_bytes (d)) {
- *d++ = *s++;
- --size;
- }
-
- /* copy all words with memmove */
- memmove (d, s, (size_t)align_down (size));
-
- tail_bytes = unaligned_bytes (size);
- if (tail_bytes) {
- d += (size_t)align_down (size);
- s += (size_t)align_down (size);
- do {
- *d++ = *s++;
- } while (--tail_bytes);
- }
- }
-}
-
-
ICALL_TYPE(CULINF, "System.Globalization.CultureInfo", CULINF_2)
ICALL(CULINF_2, "construct_datetime_format", ves_icall_System_Globalization_CultureInfo_construct_datetime_format)
-ICALL(CULINF_4, "construct_internal_locale_from_current_locale", ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_current_locale)
ICALL(CULINF_5, "construct_internal_locale_from_lcid", ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_lcid)
ICALL(CULINF_6, "construct_internal_locale_from_name", ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_name)
-ICALL(CULINF_7, "construct_internal_locale_from_specific_name", ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_specific_name)
ICALL(CULINF_8, "construct_number_format", ves_icall_System_Globalization_CultureInfo_construct_number_format)
+ICALL(CULINF_7, "get_current_locale_name", ves_icall_System_Globalization_CultureInfo_get_current_locale_name)
ICALL(CULINF_9, "internal_get_cultures", ves_icall_System_Globalization_CultureInfo_internal_get_cultures)
//ICALL(CULINF_10, "internal_is_lcid_neutral", ves_icall_System_Globalization_CultureInfo_internal_is_lcid_neutral)
#include <mono/utils/mono-io-portability.h>
#include <mono/utils/mono-digest.h>
#include <mono/utils/bsearch.h>
+#include <mono/utils/mono-mutex.h>
#if defined (HOST_WIN32)
#include <windows.h>
mono_class_init_or_throw (klass);
mono_class_init_or_throw (klassc);
} else if (!klass->supertypes || !klassc->supertypes) {
- mono_loader_lock ();
mono_class_setup_supertypes (klass);
mono_class_setup_supertypes (klassc);
- mono_loader_unlock ();
}
if (type->type->byref)
* FIXME: Why is this stuff needed at all ? Why can't the code below work for
* the dynamic case as well ?
*/
- mono_loader_lock ();
+ mono_image_lock ((MonoImage*)image);
res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
- mono_loader_unlock ();
+ mono_image_unlock ((MonoImage*)image);
if (res)
return res;
struct tm start, tt;
time_t t;
- long int gmtoff;
- int is_daylight = 0, day;
+ long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
+ int day, transitioned;
char tzone [64];
+ gmtoff_st = gmtoff_ds = transitioned = 0;
+
MONO_ARCH_SAVE_REGS;
MONO_CHECK_ARG_NULL (data);
gmtoff = gmt_offset (&start, t);
/* For each day of the year, calculate the tm_gmtoff. */
- for (day = 0; day < 365; day++) {
+ for (day = 0; day < 365 && transitioned < 2; day++) {
t += 3600*24;
tt = *localtime (&t);
+ gmtoff_after = gmt_offset(&tt, t);
+
/* Daylight saving starts or ends here. */
- if (gmt_offset (&tt, t) != gmtoff) {
+ if (gmtoff_after != gmtoff) {
struct tm tt1;
time_t t1;
strftime (tzone, sizeof (tzone), "%Z", &tt);
/* Write data, if we're already in daylight saving, we're done. */
- if (is_daylight) {
- mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
- mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
- return 1;
+ if (tt.tm_isdst) {
+ mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
+ mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
+ if (gmtoff_ds == 0) {
+ gmtoff_st = gmtoff;
+ gmtoff_ds = gmtoff_after;
+ }
+ transitioned++;
} else {
- struct tm end;
time_t te;
+ te = mktime (&tt);
- memset (&end, 0, sizeof (end));
- end.tm_year = year-1900 + 1;
- end.tm_mday = 1;
-
- te = mktime (&end);
-
- mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
- mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
- mono_array_set ((*data), gint64, 1, ((gint64)te + EPOCH_ADJUST) * 10000000L);
- is_daylight = 1;
+ mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
+ if (gmtoff_ds == 0) {
+ gmtoff_st = gmtoff_after;
+ gmtoff_ds = gmtoff;
+ }
+ transitioned++;
}
/* This is only set once when we enter daylight saving. */
- mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
- mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
-
+ if (tt1.tm_isdst) {
+ mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
+ mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
+ }
gmtoff = gmt_offset (&tt, t);
}
}
- if (!is_daylight) {
+ if (transitioned < 2) {
strftime (tzone, sizeof (tzone), "%Z", &tt);
mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
{
MONO_ARCH_SAVE_REGS;
+ mono_environment_exitcode_set (result);
+
/* FIXME: There are some cleanup hangs that should be worked out, but
* if the program is going to exit, everything will be cleaned up when
* NaCl exits anyway.
ICALL_EXPORT MonoBoolean
ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
{
- return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
+ return mono_is_debugger_attached ();
}
ICALL_EXPORT MonoBoolean
#endif /* DISABLE_ICALL_TABLES */
+static mono_mutex_t icall_mutex;
static GHashTable *icall_hash = NULL;
static GHashTable *jit_icall_hash_name = NULL;
static GHashTable *jit_icall_hash_addr = NULL;
#endif
icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ mono_mutex_init (&icall_mutex);
+}
+
+static void
+mono_icall_lock (void)
+{
+ mono_locks_mutex_acquire (&icall_mutex, IcallLock);
+}
+
+static void
+mono_icall_unlock (void)
+{
+ mono_locks_mutex_release (&icall_mutex, IcallLock);
}
void
g_hash_table_destroy (icall_hash);
g_hash_table_destroy (jit_icall_hash_name);
g_hash_table_destroy (jit_icall_hash_addr);
+ mono_mutex_destroy (&icall_mutex);
}
void
mono_add_internal_call (const char *name, gconstpointer method)
{
- mono_loader_lock ();
+ mono_icall_lock ();
g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
- mono_loader_unlock ();
+ mono_icall_unlock ();
}
#ifndef DISABLE_ICALL_TABLES
sigstart [siglen + 2] = 0;
g_free (tmpsig);
- mono_loader_lock ();
+ mono_icall_lock ();
res = g_hash_table_lookup (icall_hash, mname);
if (res) {
- mono_loader_unlock ();
+ mono_icall_unlock ();;
return res;
}
/* try without signature */
*sigstart = 0;
res = g_hash_table_lookup (icall_hash, mname);
if (res) {
- mono_loader_unlock ();
+ mono_icall_unlock ();
return res;
}
#ifdef DISABLE_ICALL_TABLES
- mono_loader_unlock ();
+ mono_icall_unlock ();
/* Fail only when the result is actually used */
/* mono_marshal_get_native_wrapper () depends on this */
if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
#else
/* it wasn't found in the static call tables */
if (!imap) {
- mono_loader_unlock ();
+ mono_icall_unlock ();
return NULL;
}
res = find_method_icall (imap, sigstart - mlen);
if (res) {
- mono_loader_unlock ();
+ mono_icall_unlock ();
return res;
}
/* try _with_ signature */
*sigstart = '(';
res = find_method_icall (imap, sigstart - mlen);
if (res) {
- mono_loader_unlock ();
+ mono_icall_unlock ();
return res;
}
g_print ("If you see other errors or faults after this message they are probably related\n");
g_print ("and you need to fix your mono install first.\n");
- mono_loader_unlock ();
+ mono_icall_unlock ();
return NULL;
#endif
return &klass->byval_arg;
}
+/**
+ * LOCKING: Take the corlib image lock.
+ */
MonoMethodSignature*
mono_create_icall_signature (const char *sigstr)
{
gchar **parts;
int i, len;
gchar **tmp;
- MonoMethodSignature *res;
+ MonoMethodSignature *res, *res2;
+ MonoImage *corlib = mono_defaults.corlib;
- mono_loader_lock ();
- res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
- if (res) {
- mono_loader_unlock ();
+ mono_image_lock (corlib);
+ res = g_hash_table_lookup (corlib->helper_signatures, sigstr);
+ mono_image_unlock (corlib);
+
+ if (res)
return res;
- }
parts = g_strsplit (sigstr, " ", 256);
tmp ++;
}
- res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
+ res = mono_metadata_signature_alloc (corlib, len - 1);
res->pinvoke = 1;
#ifdef HOST_WIN32
g_strfreev (parts);
- g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
-
- mono_loader_unlock ();
+ mono_image_lock (corlib);
+ res2 = g_hash_table_lookup (corlib->helper_signatures, sigstr);
+ if (res2)
+ res = res2; /*Value is allocated in the image pool*/
+ else
+ g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
+ mono_image_unlock (corlib);
return res;
}
MonoJitICallInfo *info;
g_assert (jit_icall_hash_name);
- mono_loader_lock ();
+ mono_icall_lock ();
info = g_hash_table_lookup (jit_icall_hash_name, name);
- mono_loader_unlock ();
+ mono_icall_unlock ();
return info;
}
MonoJitICallInfo *info;
g_assert (jit_icall_hash_addr);
- mono_loader_lock ();
+ mono_icall_lock ();
info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
- mono_loader_unlock ();
+ mono_icall_unlock ();
return info;
}
* mono_get_jit_icall_info:
*
* Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
- * caller should access it while holding the loader lock.
+ * caller should access it while holding the icall lock.
*/
GHashTable*
mono_get_jit_icall_info (void)
MonoJitICallInfo *info;
const char *res = NULL;
- mono_loader_lock ();
+ mono_icall_lock ();
info = g_hash_table_lookup (jit_icall_hash_name, name);
if (info)
res = info->c_symbol;
- mono_loader_unlock ();
+ mono_icall_unlock ();
return res;
}
void
mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
{
- mono_loader_lock ();
+ mono_icall_lock ();
g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
- mono_loader_unlock ();
+ mono_icall_unlock ();
}
MonoJitICallInfo *
g_assert (func);
g_assert (name);
- mono_loader_lock ();
+ mono_icall_lock ();
if (!jit_icall_hash_name) {
jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
- mono_loader_unlock ();
+ mono_icall_unlock ();
return info;
}
MonoImage *image2;
GHashTable *loaded_images;
int i;
- GSList *free_list;
g_return_val_if_fail (image != NULL, FALSE);
mono_image_invoke_unload_hook (image);
- free_list = mono_metadata_clean_for_image (image);
+ mono_metadata_clean_for_image (image);
/*
* The caches inside a MonoImage might refer to metadata which is stored in referenced
free_hash (image->pinvoke_scope_filenames);
/* The ownership of signatures is not well defined */
- //g_hash_table_foreach (image->memberref_signatures, free_mr_signatures, NULL);
g_hash_table_destroy (image->memberref_signatures);
- //g_hash_table_foreach (image->helper_signatures, free_mr_signatures, NULL);
g_hash_table_destroy (image->helper_signatures);
g_hash_table_destroy (image->method_signatures);
if (image->property_hash)
mono_property_hash_destroy (image->property_hash);
- g_slist_free (image->reflection_info_unregister_classes);
- image->reflection_info_unregister_classes = free_list;
+ /*
+ reflection_info_unregister_classes is only required by dynamic images, which will not be properly
+ cleared during shutdown as we don't perform regular appdomain unload for the root one.
+ */
+ g_assert (!image->reflection_info_unregister_classes || mono_runtime_is_shutting_down ());
+ image->reflection_info_unregister_classes = NULL;
if (image->interface_bitset) {
mono_unload_interface_ids (image->interface_bitset);
mono_image_close_finish (MonoImage *image)
{
int i;
- GSList *l;
-
- for (l = image->reflection_info_unregister_classes; l; l = l->next)
- g_free (l->data);
- g_slist_free (image->reflection_info_unregister_classes);
- image->reflection_info_unregister_classes = NULL;
if (image->references && !image->dynamic) {
for (i = 0; i < image->nreferences; i++) {
mono_property_hash_remove_object (image->property_hash, subject);
mono_image_unlock (image);
}
+
+void
+mono_image_append_class_to_reflection_info_set (MonoClass *class)
+{
+ MonoImage *image = class->image;
+ g_assert (image->dynamic);
+ mono_image_lock (image);
+ image->reflection_info_unregister_classes = g_slist_prepend_mempool (image->mempool, image->reflection_info_unregister_classes, class);
+ mono_image_unlock (image);
+}
static void
set_loader_error (MonoLoaderError *error)
{
+ mono_loader_clear_error ();
mono_native_tls_set_value (loader_error_thread_id, error);
}
mono_get_method_full (MonoImage *image, guint32 token, MonoClass *klass,
MonoGenericContext *context)
{
- MonoMethod *result;
+ MonoMethod *result = NULL;
gboolean used_context = FALSE;
/* We do everything inside the lock to prevent creation races */
if (!image->method_cache)
image->method_cache = g_hash_table_new (NULL, NULL);
result = g_hash_table_lookup (image->method_cache, GINT_TO_POINTER (mono_metadata_token_index (token)));
- } else {
+ } else if (!image->dynamic) {
if (!image->methodref_cache)
image->methodref_cache = g_hash_table_new (NULL, NULL);
result = g_hash_table_lookup (image->methodref_cache, GINT_TO_POINTER (token));
if (result)
return result;
+
result = mono_get_method_from_token (image, token, klass, context, &used_context);
if (!result)
return NULL;
mono_image_lock (image);
if (!used_context && !result->is_inflated) {
- MonoMethod *result2;
+ MonoMethod *result2 = NULL;
+
if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
result2 = g_hash_table_lookup (image->method_cache, GINT_TO_POINTER (mono_metadata_token_index (token)));
- else
+ else if (!image->dynamic)
result2 = g_hash_table_lookup (image->methodref_cache, GINT_TO_POINTER (token));
if (result2) {
if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
g_hash_table_insert (image->method_cache, GINT_TO_POINTER (mono_metadata_token_index (token)), result);
- else
+ else if (!image->dynamic)
g_hash_table_insert (image->methodref_cache, GINT_TO_POINTER (token), result);
}
return TRUE;
}
-static gboolean
-construct_culture_from_specific_name (MonoCultureInfo *ci, gchar *name)
-{
- const CultureInfoEntry *entry;
- const CultureInfoNameEntry *ne;
-
- MONO_ARCH_SAVE_REGS;
-
- ne = mono_binary_search (name, culture_name_entries, NUM_CULTURE_ENTRIES,
- sizeof (CultureInfoNameEntry), culture_name_locator);
-
- if (ne == NULL)
- return FALSE;
-
- entry = &culture_entries [ne->culture_entry_index];
-
- if (entry)
- return construct_culture (ci, entry);
- else
- return FALSE;
-}
-
static const CultureInfoEntry*
culture_info_entry_from_lcid (int lcid)
{
p = strchr (locale, '@');
if (p != NULL)
*p = 0;
+ p = strchr (locale, '_');
+ if (p != NULL)
+ *p = '-';
ret = g_ascii_strdown (locale, -1);
g_free (locale);
return ret;
}
-MonoBoolean
-ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_current_locale (MonoCultureInfo *ci)
+MonoString*
+ves_icall_System_Globalization_CultureInfo_get_current_locale_name (void)
{
gchar *locale;
- gboolean ret;
+ MonoString* ret;
+ MonoDomain *domain;
MONO_ARCH_SAVE_REGS;
locale = get_current_locale_name ();
if (locale == NULL)
- return FALSE;
+ return NULL;
- ret = construct_culture_from_specific_name (ci, locale);
+ domain = mono_domain_get ();
+ ret = mono_string_new (domain, locale);
g_free (locale);
- ci->is_read_only = TRUE;
- ci->use_user_override = TRUE;
return ret;
}
return construct_culture (this, &culture_entries [ne->culture_entry_index]);
}
-
+/*
MonoBoolean
ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_specific_name (MonoCultureInfo *ci,
MonoString *name)
return ret;
}
-
+*/
MonoBoolean
ves_icall_System_Globalization_RegionInfo_construct_internal_region_from_lcid (MonoRegionInfo *this,
gint lcid)
} MonoCompareOptions;
extern void ves_icall_System_Globalization_CultureInfo_construct_internal_locale (MonoCultureInfo *this, MonoString *locale) MONO_INTERNAL;
-extern MonoBoolean ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_current_locale (MonoCultureInfo *ci) MONO_INTERNAL;
+extern MonoString* ves_icall_System_Globalization_CultureInfo_get_current_locale_name (void) MONO_INTERNAL;
extern MonoBoolean ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_lcid (MonoCultureInfo *this, gint lcid) MONO_INTERNAL;
extern MonoBoolean ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_name (MonoCultureInfo *this, MonoString *name) MONO_INTERNAL;
-extern MonoBoolean ves_icall_System_Globalization_CultureInfo_construct_internal_locale_from_specific_name (MonoCultureInfo *ci, MonoString *name) MONO_INTERNAL;
extern MonoArray *ves_icall_System_Globalization_CultureInfo_internal_get_cultures (MonoBoolean neutral, MonoBoolean specific, MonoBoolean installed) MONO_INTERNAL;
extern void ves_icall_System_Globalization_CultureInfo_construct_datetime_format (MonoCultureInfo *this) MONO_INTERNAL;
extern void ves_icall_System_Globalization_CultureInfo_construct_number_format (MonoCultureInfo *this) MONO_INTERNAL;
#include "lock-tracer.h"
+
/*
* This is a very simple lock trace implementation. It can be used to verify that the runtime is
* correctly following all locking rules.
#ifdef LOCK_TRACER
+#ifdef TARGET_OSX
+#include <dlfcn.h>
+#endif
+
static FILE *trace_file;
static CRITICAL_SECTION tracer_lock;
+static size_t base_address;
typedef enum {
RECORD_MUST_NOT_HOLD_ANY,
void
mono_locks_tracer_init (void)
{
+ Dl_info info;
+ int res;
char *name;
InitializeCriticalSection (&tracer_lock);
if (!g_getenv ("MONO_ENABLE_LOCK_TRACER"))
name = g_strdup_printf ("locks.%d", getpid ());
trace_file = fopen (name, "w+");
g_free (name);
+
+#ifdef TARGET_OSX
+ res = dladdr ((void*)&mono_locks_tracer_init, &info);
+ /* The 0x1000 offset was found by empirically trying it. */
+ if (res)
+ base_address = (size_t)info.dli_fbase - 0x1000;
+#endif
}
static void
add_record (RecordType record_kind, RuntimeLocks kind, gpointer lock)
{
+ int i = 0;
gpointer frames[10];
char *msg;
if (!trace_file)
memset (frames, 0, sizeof (gpointer));
mono_backtrace (frames, 6);
+ for (i = 0; i < 6; ++i)
+ frames [i] = (gpointer)((size_t)frames[i] - base_address);
/*We only dump 5 frames, which should be more than enough to most analysis.*/
msg = g_strdup_printf ("%x,%d,%d,%p,%p,%p,%p,%p,%p\n", (guint32)GetCurrentThreadId (), record_kind, kind, lock, frames [1], frames [2], frames [3], frames [4], frames [5]);
DomainLock,
DomainAssembliesLock,
DomainJitCodeHashLock,
+ IcallLock,
+ AssemblyBindingLock,
+ MarshalLock
} RuntimeLocks;
#ifdef LOCK_TRACER
LeaveCriticalSection (LOCK); \
} while (0)
+#define mono_locks_mutex_acquire(LOCK, NAME) do { \
+ mono_mutex_lock (LOCK); \
+ mono_locks_lock_acquired (NAME, LOCK); \
+} while (0)
+
+#define mono_locks_mutex_release(LOCK, NAME) do { \
+ mono_locks_lock_released (NAME, LOCK); \
+ mono_mutex_unlock (LOCK); \
+} while (0)
G_END_DECLS
#endif /* __MONO_METADATA_LOCK_TRACER_H__ */
/*
* This mutex protects the various marshalling related caches in MonoImage
* and a few other data structures static to this file.
- * Note that when this lock is held it is not possible to take other runtime
- * locks like the loader lock.
+ *
+ * The marshal lock is a non-recursive complex lock that sits below the domain lock in the
+ * runtime locking latice. Which means it can take simple locks suck as the image lock.
*/
-#define mono_marshal_lock() EnterCriticalSection (&marshal_mutex)
-#define mono_marshal_unlock() LeaveCriticalSection (&marshal_mutex)
+#define mono_marshal_lock() mono_locks_acquire (&marshal_mutex, MarshalLock)
+#define mono_marshal_unlock() mono_locks_release (&marshal_mutex, MarshalLock)
static CRITICAL_SECTION marshal_mutex;
static gboolean marshal_mutex_initialized;
mono_mb_emit_byte (mb, CEE_RET);
#endif /* DISABLE_JIT */
- mono_loader_lock ();
+ mono_marshal_lock ();
/* double-checked locking */
if (!method) {
method = mono_mb_create_method (mb, csig, 16);
info = mono_wrapper_info_create (method, WRAPPER_SUBTYPE_RUNTIME_INVOKE_DYNAMIC);
mono_marshal_set_wrapper_info (method, info);
}
- mono_loader_unlock ();
+ mono_marshal_unlock ();
mono_mb_free (mb);
clause->flags = MONO_EXCEPTION_CLAUSE_FINALLY;
#endif
- mono_loader_lock ();
+ mono_marshal_lock ();
if (!enter_method) {
MonoMethodDesc *desc;
mono_method_desc_free (desc);
}
- mono_loader_unlock ();
+ mono_marshal_unlock ();
#ifndef DISABLE_JIT
/* Push this or the type object */
if (!klass->inited)
mono_class_init (klass);
- mono_loader_lock ();
-
- if (klass->marshal_info) {
- mono_loader_unlock ();
+ if (klass->marshal_info)
return klass->marshal_info;
- }
/*
* This function can recursively call itself, so we keep the list of classes which are
loads_list = g_slist_remove (loads_list, klass);
mono_native_tls_set_value (load_type_info_tls_id, loads_list);
- /*We do double-checking locking on marshal_info */
- mono_memory_barrier ();
-
- klass->marshal_info = info;
-
- mono_loader_unlock ();
+ mono_marshal_lock ();
+ if (!klass->marshal_info) {
+ /*We do double-checking locking on marshal_info */
+ mono_memory_barrier ();
+ klass->marshal_info = info;
+ }
+ mono_marshal_unlock ();
return klass->marshal_info;
}
void
mono_remove_image_unload_hook (MonoImageUnloadFunc func, gpointer user_data) MONO_INTERNAL;
+void
+mono_image_append_class_to_reflection_info_set (MonoClass *class) MONO_INTERNAL;
+
gpointer
mono_image_set_alloc (MonoImageSet *set, guint size) MONO_INTERNAL;
MonoType*
mono_metadata_get_shared_type (MonoType *type) MONO_INTERNAL;
-GSList*
+void
mono_metadata_clean_for_image (MonoImage *image) MONO_INTERNAL;
void
}
}
-GSList*
+void
mono_metadata_clean_for_image (MonoImage *image)
{
CleanForImageUserData ginst_data, gclass_data;
- GSList *l, *set_list, *free_list = NULL;
+ GSList *l, *set_list;
//check_image_sets (image);
g_slist_free (set_list);
mono_loader_unlock ();
-
- return free_list;
}
static void
* Create a MonoMethod from this method builder.
* Returns: the newly created method.
*
- * LOCKING: Takes the loader lock.
*/
MonoMethod *
mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
image = mb->method->klass->image;
- mono_loader_lock (); /*FIXME I think this lock can go.*/
#ifndef DISABLE_JIT
if (mb->dynamic) {
method = mb->method;
}
#endif
- mono_loader_unlock ();
return method;
}
static guint32 debugger_lock_level = 0;
static CRITICAL_SECTION debugger_lock_mutex;
-static gboolean mono_debugger_use_debugger = FALSE;
-static MonoObject *last_exception = NULL;
-volatile gint32 _mono_debugger_interruption_request = 0;
-
-void (*mono_debugger_event_handler) (MonoDebuggerEvent event, guint64 data, guint64 arg) = NULL;
typedef struct
{
MonoDebugMethodAddressList *address_list;
} MethodBreakpointInfo;
-typedef struct {
- MonoImage *image;
- guint64 index;
- guint32 token;
- gchar *name_space;
- gchar *name;
-} ClassInitCallback;
-
-typedef struct {
- guint32 id;
- guint32 shadow_path_len;
- gchar *shadow_path;
- MonoDomain *domain;
- MonoAppDomainSetup *setup;
-} AppDomainSetupInfo;
-
-static GPtrArray *class_init_callbacks = NULL;
-
static int initialized = 0;
void
}
void
-mono_debugger_initialize (gboolean use_debugger)
+mono_debugger_initialize ()
{
- MONO_GC_REGISTER_ROOT_SINGLE (last_exception);
-
- g_assert (!mono_debugger_use_debugger);
-
InitializeCriticalSection (&debugger_lock_mutex);
- mono_debugger_use_debugger = use_debugger;
initialized = 1;
}
-void
-mono_debugger_event (MonoDebuggerEvent event, guint64 data, guint64 arg)
-{
- if (mono_debugger_event_handler)
- (* mono_debugger_event_handler) (event, data, arg);
-}
-
-void
-mono_debugger_event_create_appdomain (MonoDomain *domain, gchar *shadow_path)
-{
- AppDomainSetupInfo info;
-
- info.id = mono_domain_get_id (domain);
- info.shadow_path_len = shadow_path ? strlen (shadow_path) : 0;
- info.shadow_path = shadow_path;
-
- info.domain = domain;
- info.setup = domain->setup;
-
- mono_debugger_event (MONO_DEBUGGER_EVENT_CREATE_APPDOMAIN, (guint64) (gsize) &info, 0);
-}
-
-void
-mono_debugger_event_unload_appdomain (MonoDomain *domain)
-{
- mono_debugger_event (MONO_DEBUGGER_EVENT_UNLOAD_APPDOMAIN,
- (guint64) (gsize) domain, (guint64) mono_domain_get_id (domain));
-}
-
-void
-mono_debugger_cleanup (void)
-{
- mono_debugger_event (MONO_DEBUGGER_EVENT_FINALIZE_MANAGED_CODE, 0, 0);
- mono_debugger_event_handler = NULL;
-}
-
-void
-mono_debugger_check_interruption (void)
-{
- if (!_mono_debugger_interruption_request)
- return;
-
- mono_debugger_lock ();
- mono_debugger_event (MONO_DEBUGGER_EVENT_INTERRUPTION_REQUEST, 0, 0);
- mono_debugger_unlock ();
-}
-
/*
* Debugger breakpoint interface.
*
return 0;
}
-
-void
-mono_debugger_check_breakpoints (MonoMethod *method, MonoDebugMethodAddress *debug_info)
-{
- int i;
-
- if (method->is_inflated)
- method = ((MonoMethodInflated *) method)->declaring;
-
- if (method_breakpoints) {
- for (i = 0; i < method_breakpoints->len; i++) {
- MethodBreakpointInfo *info = g_ptr_array_index (method_breakpoints, i);
-
- if (method != info->method)
- continue;
-
- mono_debugger_event (MONO_DEBUGGER_EVENT_JIT_BREAKPOINT,
- (guint64) (gsize) debug_info, info->index);
- }
- }
-
- if (class_init_callbacks) {
- for (i = 0; i < class_init_callbacks->len; i++) {
- ClassInitCallback *info = g_ptr_array_index (class_init_callbacks, i);
-
- if ((method->token != info->token) || (method->klass->image != info->image))
- continue;
-
- mono_debugger_event (MONO_DEBUGGER_EVENT_JIT_BREAKPOINT,
- (guint64) (gsize) debug_info, info->index);
- }
- }
-}
-
-MonoClass *
-mono_debugger_register_class_init_callback (MonoImage *image, const gchar *full_name,
- guint32 method_token, guint32 index)
-{
- ClassInitCallback *info;
- MonoClass *klass;
- gchar *name_space, *name, *pos;
-
- name = g_strdup (full_name);
-
- pos = strrchr (name, '.');
- if (pos) {
- name_space = name;
- *pos = 0;
- name = pos + 1;
- } else {
- name_space = NULL;
- }
-
- mono_loader_lock ();
-
- klass = mono_class_from_name (image, name_space ? name_space : "", name);
-
- info = g_new0 (ClassInitCallback, 1);
- info->image = image;
- info->index = index;
- info->token = method_token;
- info->name_space = name_space;
- info->name = name;
-
- if (!class_init_callbacks)
- class_init_callbacks = g_ptr_array_new ();
-
- g_ptr_array_add (class_init_callbacks, info);
- mono_loader_unlock ();
- return klass;
-}
-
-void
-mono_debugger_remove_class_init_callback (int index)
-{
- int i;
-
- if (!class_init_callbacks)
- return;
-
- for (i = 0; i < class_init_callbacks->len; i++) {
- ClassInitCallback *info = g_ptr_array_index (class_init_callbacks, i);
-
- if (info->index != index)
- continue;
-
- g_ptr_array_remove (class_init_callbacks, info);
- if (info->name_space)
- g_free (info->name_space);
- else
- g_free (info->name);
- g_free (info);
- }
-}
-
-void
-mono_debugger_class_initialized (MonoClass *klass)
-{
- int i;
-
- if (!class_init_callbacks)
- return;
-
- again:
- for (i = 0; i < class_init_callbacks->len; i++) {
- ClassInitCallback *info = g_ptr_array_index (class_init_callbacks, i);
-
- if (info->name_space && strcmp (info->name_space, klass->name_space))
- continue;
- if (strcmp (info->name, klass->name))
- continue;
-
- mono_debugger_event (MONO_DEBUGGER_EVENT_CLASS_INITIALIZED,
- (guint64) (gsize) klass, info->index);
-
- if (info->token) {
- int j;
-
- for (j = 0; j < klass->method.count; j++) {
- if (klass->methods [j]->token != info->token)
- continue;
-
- mono_debugger_insert_method_breakpoint (klass->methods [j], info->index);
- }
- }
-
- g_ptr_array_remove (class_init_callbacks, info);
- if (info->name_space)
- g_free (info->name_space);
- else
- g_free (info->name);
- g_free (info);
- goto again;
- }
-}
#ifndef __MONO_DEBUG_DEBUGGER_H__
#define __MONO_DEBUG_DEBUGGER_H__
-#include <glib.h>
#include <mono/metadata/debug-helpers.h>
#include <mono/metadata/debug-mono-symfile.h>
-#include <mono/utils/mono-codeman.h>
-#include <mono/io-layer/io-layer.h>
+#include <mono/utils/mono-compiler.h>
-typedef enum {
- MONO_DEBUGGER_EVENT_INITIALIZE_MANAGED_CODE = 1,
- MONO_DEBUGGER_EVENT_INITIALIZE_CORLIB,
- MONO_DEBUGGER_EVENT_JIT_BREAKPOINT,
- MONO_DEBUGGER_EVENT_INITIALIZE_THREAD_MANAGER,
- MONO_DEBUGGER_EVENT_ACQUIRE_GLOBAL_THREAD_LOCK,
- MONO_DEBUGGER_EVENT_RELEASE_GLOBAL_THREAD_LOCK,
- MONO_DEBUGGER_EVENT_WRAPPER_MAIN,
- MONO_DEBUGGER_EVENT_MAIN_EXITED,
- MONO_DEBUGGER_EVENT_UNHANDLED_EXCEPTION,
- MONO_DEBUGGER_EVENT_THROW_EXCEPTION,
- MONO_DEBUGGER_EVENT_HANDLE_EXCEPTION,
- MONO_DEBUGGER_EVENT_THREAD_CREATED,
- MONO_DEBUGGER_EVENT_THREAD_CLEANUP,
- MONO_DEBUGGER_EVENT_GC_THREAD_CREATED,
- MONO_DEBUGGER_EVENT_GC_THREAD_EXITED,
- MONO_DEBUGGER_EVENT_REACHED_MAIN,
- MONO_DEBUGGER_EVENT_FINALIZE_MANAGED_CODE,
- MONO_DEBUGGER_EVENT_LOAD_MODULE,
- MONO_DEBUGGER_EVENT_UNLOAD_MODULE,
- MONO_DEBUGGER_EVENT_DOMAIN_CREATE,
- MONO_DEBUGGER_EVENT_DOMAIN_UNLOAD,
- MONO_DEBUGGER_EVENT_CLASS_INITIALIZED,
- MONO_DEBUGGER_EVENT_INTERRUPTION_REQUEST,
- MONO_DEBUGGER_EVENT_CREATE_APPDOMAIN,
- MONO_DEBUGGER_EVENT_UNLOAD_APPDOMAIN,
- /* Obsolete, only for backwards compatibility with older debugger versions */
- MONO_DEBUGGER_EVENT_OLD_TRAMPOLINE = 256,
+void mono_debugger_initialize (void) MONO_INTERNAL;
- MONO_DEBUGGER_EVENT_TRAMPOLINE = 512
-} MonoDebuggerEvent;
+void mono_debugger_lock (void) MONO_INTERNAL;
+void mono_debugger_unlock (void) MONO_INTERNAL;
-extern volatile gint32 _mono_debugger_interruption_request;
+gchar *
+mono_debugger_check_runtime_version (const char *filename) MONO_INTERNAL;
-extern void (*mono_debugger_event_handler) (MonoDebuggerEvent event, guint64 data, guint64 arg);
+MonoDebugMethodAddressList *
+mono_debugger_insert_method_breakpoint (MonoMethod *method, guint64 idx) MONO_INTERNAL;
-MONO_API void mono_debugger_initialize (gboolean use_debugger);
-MONO_API void mono_debugger_cleanup (void);
-
-MONO_API void mono_debugger_lock (void);
-MONO_API void mono_debugger_unlock (void);
-MONO_API void mono_debugger_event (MonoDebuggerEvent event, guint64 data, guint64 arg);
-
-MONO_API gchar *
-mono_debugger_check_runtime_version (const char *filename);
-
-MONO_API void
-mono_debugger_class_initialized (MonoClass *klass);
-
-MONO_API void
-mono_debugger_check_interruption (void);
-
-MONO_API void
-mono_debugger_event_create_appdomain (MonoDomain *domain, gchar *shadow_path);
-
-MONO_API void
-mono_debugger_event_unload_appdomain (MonoDomain *domain);
-
-MONO_API MonoDebugMethodAddressList *
-mono_debugger_insert_method_breakpoint (MonoMethod *method, guint64 idx);
-
-MONO_API int
-mono_debugger_remove_method_breakpoint (guint64 index);
-
-MONO_API void
-mono_debugger_check_breakpoints (MonoMethod *method, MonoDebugMethodAddress *debug_info);
-
-MONO_API MonoClass *
-mono_debugger_register_class_init_callback (MonoImage *image, const gchar *full_name,
- guint32 token, guint32 index);
-
-MONO_API void
-mono_debugger_remove_class_init_callback (int index);
+int
+mono_debugger_remove_method_breakpoint (guint64 index) MONO_INTERNAL;
#endif /* __MONO_DEBUG_DEBUGGER_H__ */
guint32 size;
} MonoDebugDelegateTrampolineEntry;
-MonoSymbolTable *mono_symbol_table = NULL;
-MonoDebugFormat mono_debug_format = MONO_DEBUG_FORMAT_NONE;
-gint32 mono_debug_debugger_version = 5;
-gint32 _mono_debug_using_mono_debugger = 0;
+static MonoSymbolTable *mono_symbol_table = NULL;
+static MonoDebugFormat mono_debug_format = MONO_DEBUG_FORMAT_NONE;
+static gint32 mono_debug_debugger_version = 5;
static gboolean mono_debug_initialized = FALSE;
static GHashTable *mono_debug_handles = NULL;
void _mono_debug_init_corlib (MonoDomain *domain);
extern void (*mono_debugger_class_init_func) (MonoClass *klass);
-extern void (*mono_debugger_class_loaded_methods_func) (MonoClass *klass);
static MonoDebugDataTable *
create_data_table (MonoDomain *domain)
mono_debug_init (MonoDebugFormat format)
{
g_assert (!mono_debug_initialized);
+ if (format == MONO_DEBUG_FORMAT_DEBUGGER)
+ g_error ("The mdb debugger is no longer supported.");
- if (_mono_debug_using_mono_debugger)
- format = MONO_DEBUG_FORMAT_DEBUGGER;
mono_debug_initialized = TRUE;
mono_debug_format = format;
*/
mono_gc_base_init ();
- mono_debugger_initialize (_mono_debug_using_mono_debugger);
+ mono_debugger_initialize ();
mono_debugger_lock ();
data_table_hash = g_hash_table_new_full (
NULL, NULL, NULL, (GDestroyNotify) free_data_table);
+ /* FIXME this is a disgusting hack. Kill it */
mono_debugger_class_init_func = mono_debug_add_type;
- mono_debugger_class_loaded_methods_func = mono_debugger_class_initialized;
mono_install_assembly_load_hook (mono_debug_add_assembly, NULL);
mono_symbol_table->global_data_table = create_data_table (NULL);
/*
* INTERNAL USE ONLY !
+ * FIXME this can have a decent name and exist in an internal header
*/
void
_mono_debug_init_corlib (MonoDomain *domain)
return;
mono_symbol_table->corlib = mono_debug_open_image (mono_defaults.corlib, NULL, 0);
- mono_debugger_event (MONO_DEBUGGER_EVENT_INITIALIZE_CORLIB,
- (guint64) (gsize) mono_symbol_table->corlib, 0);
}
void
mono_debug_open_image (image, raw_contents, size);
}
-
-gboolean
-mono_debug_using_mono_debugger (void)
-{
- return _mono_debug_using_mono_debugger;
-}
-
void
mono_debug_cleanup (void)
{
table = create_data_table (domain);
- mono_debugger_event (MONO_DEBUGGER_EVENT_DOMAIN_CREATE, (guint64) (gsize) table,
- mono_domain_get_id (domain));
-
mono_debugger_unlock ();
}
return;
}
- mono_debugger_event (MONO_DEBUGGER_EVENT_DOMAIN_UNLOAD, (guint64) (gsize) table,
- mono_domain_get_id (domain));
-
g_hash_table_remove (data_table_hash, domain);
mono_debugger_unlock ();
return;
}
- mono_debugger_event (MONO_DEBUGGER_EVENT_UNLOAD_MODULE, (guint64) (gsize) handle,
- handle->index);
-
mono_debug_list_remove (&mono_symbol_table->symbol_files, handle);
g_hash_table_remove (mono_debug_handles, image);
handle->type_table = create_data_table (NULL);
handle->symfile = mono_debug_open_mono_symbols (
- handle, raw_contents, size, _mono_debug_using_mono_debugger);
+ handle, raw_contents, size, FALSE);
mono_debug_list_add (&mono_symbol_table->symbol_files, handle);
g_hash_table_insert (mono_debug_handles, image, handle);
- if (mono_symbol_table->corlib)
- mono_debugger_event (MONO_DEBUGGER_EVENT_LOAD_MODULE,
- (guint64) (gsize) handle, 0);
-
mono_debugger_unlock ();
return handle;
return NULL;
}
+
+/**
+ * mono_debug_enabled:
+ *
+ * Returns true is debug information is enabled. This doesn't relate if a debugger is present or not.
+ */
+mono_bool
+mono_debug_enabled (void)
+{
+ return mono_debug_format != MONO_DEBUG_FORMAT_NONE;
+}
typedef enum {
MONO_DEBUG_FORMAT_NONE,
MONO_DEBUG_FORMAT_MONO,
+ /* Deprecated, the mdb debugger is not longer supported. */
MONO_DEBUG_FORMAT_DEBUGGER
} MonoDebugFormat;
uint32_t il_offset;
};
+MONO_API mono_bool mono_debug_enabled (void);
+
/*
* These bits of the MonoDebugLocalInfo's "index" field are flags specifying
* where the variable is actually stored.
#define MONO_DEBUGGER_MINOR_VERSION 6
#define MONO_DEBUGGER_MAGIC 0x7aff65af4253d427ULL
-extern MonoSymbolTable *mono_symbol_table;
-extern MonoDebugFormat mono_debug_format;
-extern int32_t mono_debug_debugger_version;
-extern int32_t _mono_debug_using_mono_debugger;
-
MONO_API void mono_debug_list_add (MonoDebugList **list, const void* data);
MONO_API void mono_debug_list_remove (MonoDebugList **list, const void* data);
MONO_API void mono_debug_domain_unload (MonoDomain *domain);
MONO_API void mono_debug_domain_create (MonoDomain *domain);
-MONO_API mono_bool mono_debug_using_mono_debugger (void);
-
MONO_API MonoDebugMethodAddress *
mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain);
bitmap = default_bitmap;
} else if (mono_type_is_struct (field->type)) {
fclass = mono_class_from_mono_type (field->type);
- bitmap = compute_class_bitmap (fclass, default_bitmap, sizeof (default_bitmap) * 8, - (sizeof (MonoObject) / sizeof (gpointer)), &max_set, FALSE);
+ bitmap = compute_class_bitmap (fclass, default_bitmap, sizeof (default_bitmap) * 8, - (int)(sizeof (MonoObject) / sizeof (gpointer)), &max_set, FALSE);
numbits = max_set + 1;
} else {
default_bitmap [0] = 0;
}
mono_thread_init_apartment_state ();
- mono_debugger_event (MONO_DEBUGGER_EVENT_REACHED_MAIN, 0, 0);
-
/* FIXME: check signature of method */
if (mono_method_signature (method)->ret->type == MONO_TYPE_I4) {
MonoObject *res;
}
}
- mono_debugger_event (MONO_DEBUGGER_EVENT_MAIN_EXITED, (guint64) (gsize) rval, 0);
-
return rval;
}
_mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
MonoTypeNameParse *info)
{
- char *start, *p, *w, *temp, *last_point, *startn;
+ char *start, *p, *w, *last_point, *startn;
int in_modifiers = 0;
- int isbyref = 0, rank, arity = 0, i;
+ int isbyref = 0, rank = 0;
start = p = w = name;
case ']':
in_modifiers = 1;
break;
- case '`':
- ++p;
- i = strtol (p, &temp, 10);
- arity += i;
- if (p == temp)
- return 0;
- p = temp-1;
- break;
default:
break;
}
*p++ = 0;
break;
case '[':
- if (arity != 0) {
- *p++ = 0;
+ //Decide if it's an array of a generic argument list
+ *p++ = 0;
+
+ if (!*p) //XXX test
+ return 0;
+ if (*p == ',' || *p == '*' || *p == ']') { //array
+ rank = 1;
+ while (*p) {
+ if (*p == ']')
+ break;
+ if (*p == ',')
+ rank++;
+ else if (*p == '*') /* '*' means unknown lower bound */
+ info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
+ else
+ return 0;
+ ++p;
+ }
+ if (*p++ != ']')
+ return 0;
+ info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
+ } else {
+ if (rank) /* generic args after array spec*/ //XXX test
+ return 0;
info->type_arguments = g_ptr_array_new ();
- for (i = 0; i < arity; i++) {
+ while (*p) {
MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
gboolean fqname = FALSE;
} else if (fqname && (*p == ']')) {
*p++ = 0;
}
-
- if (i + 1 < arity) {
- if (*p != ',')
- return 0;
- } else {
- if (*p != ']')
- return 0;
+ if (*p == ']') {
+ *p++ = 0;
+ break;
+ } else if (!*p) {
+ return 0;
}
*p++ = 0;
}
-
- arity = 0;
- break;
- }
- rank = 1;
- *p++ = 0;
- while (*p) {
- if (*p == ']')
- break;
- if (*p == ',')
- rank++;
- else if (*p == '*') /* '*' means unknown lower bound */
- info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
- else
- return 0;
- ++p;
}
- if (*p++ != ']')
- return 0;
- info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
break;
case ']':
if (is_recursed)
/* Put into cache so mono_class_get () will find it.
Skip nested types as those should not be available on the global scope. */
- if (!tb->nesting_type) {
+ if (!tb->nesting_type)
mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
- } else {
- klass->image->reflection_info_unregister_classes =
- g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
- }
+
+ /*
+ We must register all types as we cannot rely on the name_cache hashtable since we find the class
+ by performing a mono_class_get which does the full resolution.
+
+ Working around this semantics would require us to write a lot of code for no clear advantage.
+ */
+ mono_image_append_class_to_reflection_info_set (klass);
} else {
g_assert (mono_class_get_ref_info (klass) == tb);
}
* This table maps metadata structures representing inflated methods/fields
* to the reflection objects representing their generic definitions.
*/
- mono_loader_lock ();
+ mono_image_lock ((MonoImage*)image);
mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
- mono_loader_unlock ();
+ mono_image_unlock ((MonoImage*)image);
}
if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
if (method->is_generic && method->klass->image->dynamic) {
MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
- mono_loader_lock ();
+ mono_image_lock ((MonoImage*)image);
mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
- mono_loader_unlock ();
+ mono_image_unlock ((MonoImage*)image);
}
return (MonoMethod *) imethod;
}
gparam->type.type = &pklass->byval_arg;
mono_class_set_ref_info (pklass, gparam);
- mono_image_lock (image);
- image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
- mono_image_unlock (image);
+ mono_image_append_class_to_reflection_info_set (pklass);
}
MonoArray *
if (!mono_runtime_has_tls_get ())
return NULL;
- mono_loader_lock ();
res = alloc_method_cache [atype];
- if (!res)
- res = alloc_method_cache [atype] = create_allocator (atype);
- mono_loader_unlock ();
+ if (res)
+ return res;
+
+ res = create_allocator (atype);
+ LOCK_GC;
+ if (alloc_method_cache [atype]) {
+ mono_free_method (res);
+ res = alloc_method_cache [atype];
+ } else {
+ mono_memory_barrier ();
+ alloc_method_cache [atype] = res;
+ }
+ UNLOCK_GC;
+
return res;
#else
return NULL;
#define ARCH_COPY_SIGCTX_REGS(a,ctx) do { \
int __i; \
for (__i = 0; __i < 32; ++__i) \
- ((a)[__i]) = UCONTEXT_REG_Rn((ctx), __i); \
+ ((a)[__i]) = (gpointer) UCONTEXT_REG_Rn((ctx), __i); \
} while (0)
#elif defined(TARGET_ARM)
/* sort array according to decreasing finishing time */
- qsort (all_entries, hash_table.num_entries, sizeof (HashEntry*), compare_hash_entries);
+ sgen_qsort (all_entries, hash_table.num_entries, sizeof (HashEntry*), compare_hash_entries);
SGEN_TV_GETTIME (btv);
step_3 = SGEN_TV_ELAPSED (atv, btv);
bridge_processing_in_progress = FALSE;
}
+void
+sgen_bridge_describe_pointer (MonoObject *obj)
+{
+ HashEntry *entry;
+ int i;
+
+ for (i = 0; i < registered_bridges.size; ++i) {
+ if (obj == DYN_ARRAY_PTR_REF (®istered_bridges, i)) {
+ printf ("Pointer is a registered bridge object.\n");
+ break;
+ }
+ }
+
+ entry = sgen_hash_table_lookup (&hash_table, obj);
+ if (!entry)
+ return;
+
+ printf ("Bridge hash table entry %p:\n", entry);
+ printf (" is bridge: %d\n", (int)entry->is_bridge);
+ printf (" is visited: %d\n", (int)entry->is_visited);
+}
+
static const char *bridge_class;
static gboolean
if (!start)
return;
ptr = start;
+ vtable = (MonoVTable*)LOAD_VTABLE (ptr);
} else {
if (sgen_ptr_is_in_los (ptr, &start)) {
if (ptr == start)
printf ("Pointer is at offset 0x%x of object %p in LOS space.\n", (int)(ptr - start), start);
ptr = start;
mono_sgen_los_describe_pointer (ptr);
+ vtable = (MonoVTable*)LOAD_VTABLE (ptr);
} else if (major_collector.ptr_is_in_non_pinned_space (ptr, &start)) {
if (ptr == start)
printf ("Pointer is the start of object %p in oldspace.\n", start);
printf ("Pointer inside oldspace.\n");
if (start)
ptr = start;
- major_collector.describe_pointer (ptr);
+ vtable = major_collector.describe_pointer (ptr);
} else if (major_collector.obj_is_from_pinned_alloc (ptr)) {
+ // FIXME: Handle pointers to the inside of objects
printf ("Pointer is inside a pinned chunk.\n");
+ vtable = (MonoVTable*)LOAD_VTABLE (ptr);
} else {
printf ("Pointer unknown.\n");
return;
goto restart;
}
- // FIXME: Handle pointers to the inside of objects
- vtable = (MonoVTable*)LOAD_VTABLE (ptr);
-
printf ("VTable: %p\n", vtable);
if (vtable == NULL) {
printf ("VTable is invalid (empty).\n");
- return;
+ goto bridge;
}
if (sgen_ptr_in_nursery (vtable)) {
printf ("VTable is invalid (points inside nursery).\n");
- return;
+ goto bridge;
}
printf ("Class: %s\n", vtable->klass->name);
printf ("Descriptor type: %d (%s)\n", type, descriptor_types [type]);
size = sgen_safe_object_get_size ((MonoObject*)ptr);
- printf ("Size: %td\n", size);
+ printf ("Size: %d\n", (int)size);
+
+ bridge:
+ sgen_bridge_describe_pointer ((MonoObject*)ptr);
}
void
#define SGEN_VTABLE_HAS_REFERENCES(vt) (sgen_gc_descr_has_references ((mword)((MonoVTable*)(vt))->gc_descr))
#define SGEN_CLASS_HAS_REFERENCES(c) (sgen_gc_descr_has_references ((mword)(c)->gc_descr))
+#define SGEN_OBJECT_HAS_REFERENCES(o) (SGEN_VTABLE_HAS_REFERENCES (SGEN_LOAD_VTABLE ((o))))
/* helper macros to scan and traverse objects, macros because we resue them in many functions */
#define OBJ_RUN_LEN_SIZE(size,desc,obj) do { \
* ######################################################################
*/
LOCK_DECLARE (gc_mutex);
+gboolean sgen_try_free_some_memory;
#define SCAN_START_SIZE SGEN_SCAN_START_SIZE
continue;
}
sgen_los_pin_object (bigobj->data);
- /* FIXME: only enqueue if object has references */
- GRAY_OBJECT_ENQUEUE (WORKERS_DISTRIBUTE_GRAY_QUEUE, bigobj->data);
+ if (SGEN_OBJECT_HAS_REFERENCES (bigobj->data))
+ GRAY_OBJECT_ENQUEUE (WORKERS_DISTRIBUTE_GRAY_QUEUE, bigobj->data);
if (G_UNLIKELY (do_pin_stats))
sgen_pin_stats_register_object ((char*) bigobj->data, safe_object_get_size ((MonoObject*) bigobj->data));
SGEN_LOG (6, "Marked large object %p (%s) size: %lu from roots", bigobj->data, safe_name (bigobj->data), (unsigned long)sgen_los_object_size (bigobj));
static void
wait_for_workers_to_finish (void)
+{
+ while (!sgen_workers_all_done ())
+ g_usleep (200);
+}
+
+static void
+join_workers (void)
{
if (concurrent_collection_in_progress || major_collector.is_parallel) {
gray_queue_redirect (&gray_queue);
TV_GETTIME (btv);
if (concurrent_collection_in_progress || major_collector.is_parallel)
- wait_for_workers_to_finish ();
+ join_workers ();
if (concurrent_collection_in_progress) {
current_object_ops = major_collector.major_concurrent_ops;
major_copy_or_mark_from_roots (NULL, TRUE, scan_mod_union);
- wait_for_workers_to_finish ();
+ join_workers ();
g_assert (sgen_gray_object_queue_is_empty (&gray_queue));
g_assert (sgen_gray_object_queue_is_empty (&gray_queue));
- major_collector.update_cardtable_mod_union ();
- sgen_los_update_cardtable_mod_union ();
-
if (!force_finish && !sgen_workers_all_done ()) {
+ major_collector.update_cardtable_mod_union ();
+ sgen_los_update_cardtable_mod_union ();
+
MONO_GC_CONCURRENT_UPDATE_END (GENERATION_OLD, major_collector.get_and_reset_num_major_objects_marked ());
return FALSE;
}
- if (mod_union_consistency_check)
- sgen_check_mod_union_consistency ();
+ /*
+ * The major collector can add global remsets which are processed in the finishing
+ * nursery collection, below. That implies that the workers must have finished
+ * marking before the nursery collection is allowed to run, otherwise we might miss
+ * some remsets.
+ */
+ wait_for_workers_to_finish ();
+
+ major_collector.update_cardtable_mod_union ();
+ sgen_los_update_cardtable_mod_union ();
collect_nursery (&unpin_queue, TRUE);
+ if (mod_union_consistency_check)
+ sgen_check_mod_union_consistency ();
+
current_collection_generation = GENERATION_OLD;
major_finish_collection ("finishing", -1, TRUE);
binary_protocol_thread_register ((gpointer)mono_thread_info_get_tid (info));
+ // FIXME: Unift with mono_thread_get_stack_bounds ()
/* try to get it with attributes first */
#if (defined(HAVE_PTHREAD_GETATTR_NP) || defined(HAVE_PTHREAD_ATTR_GET_NP)) && defined(HAVE_PTHREAD_ATTR_GETSTACK)
{
pthread_attr_destroy (&attr);
}
#elif defined(HAVE_PTHREAD_GET_STACKSIZE_NP) && defined(HAVE_PTHREAD_GET_STACKADDR_NP)
- info->stack_end = (char*)pthread_get_stackaddr_np (pthread_self ());
- info->stack_start_limit = (char*)info->stack_end - pthread_get_stacksize_np (pthread_self ());
+ {
+ size_t stsize = 0;
+ guint8 *staddr = NULL;
+
+ mono_thread_get_stack_bounds (&staddr, &stsize);
+ info->stack_start_limit = staddr;
+ info->stack_end = staddr + stsize;
+ }
#else
{
/* FIXME: we assume the stack grows down */
}
static void
-sgen_thread_unregister (SgenThreadInfo *p)
+sgen_thread_detach (SgenThreadInfo *p)
{
/* If a delegate is passed to native code and invoked on a thread we dont
* know about, the jit will register it with mono_jit_thread_attach, but
*/
if (mono_domain_get ())
mono_thread_detach (mono_thread_current ());
+}
+static void
+sgen_thread_unregister (SgenThreadInfo *p)
+{
binary_protocol_thread_unregister ((gpointer)mono_thread_info_get_tid (p));
SGEN_LOG (3, "unregister thread %p (%p)", p, (gpointer)mono_thread_info_get_tid (p));
gc_debug_file = stderr;
cb.thread_register = sgen_thread_register;
+ cb.thread_detach = sgen_thread_detach;
cb.thread_unregister = sgen_thread_unregister;
cb.thread_attach = sgen_thread_attach;
cb.mono_method_is_critical = (gpointer)is_critical_method;
res = mono_mb_create_method (mb, sig, 16);
mono_mb_free (mb);
- mono_loader_lock ();
+ LOCK_GC;
if (write_barrier_method) {
/* Already created */
mono_free_method (res);
mono_memory_barrier ();
write_barrier_method = res;
}
- mono_loader_unlock ();
+ UNLOCK_GC;
return write_barrier_method;
}
void
sgen_gc_unlock (void)
{
- UNLOCK_GC;
+ gboolean try_free = sgen_try_free_some_memory;
+ sgen_try_free_some_memory = FALSE;
+ mono_mutex_unlock (&gc_mutex);
+ MONO_GC_UNLOCKED ();
+ if (try_free)
+ mono_thread_hazardous_try_free_some ();
}
void
MONO_GC_LOCKED (); \
} while (0)
#define TRYLOCK_GC (mono_mutex_trylock (&gc_mutex) == 0)
-#define UNLOCK_GC do { \
- mono_mutex_unlock (&gc_mutex); \
- MONO_GC_UNLOCKED (); \
- } while (0)
+#define UNLOCK_GC do { sgen_gc_unlock (); } while (0)
extern LOCK_DECLARE (sgen_interruption_mutex);
extern char *sgen_nursery_start MONO_INTERNAL;
extern char *sgen_nursery_end MONO_INTERNAL;
-static MONO_ALWAYS_INLINE gboolean
+static inline MONO_ALWAYS_INLINE gboolean
sgen_ptr_in_nursery (void *p)
{
return SGEN_PTR_IN_NURSERY ((p), DEFAULT_NURSERY_BITS, sgen_nursery_start, sgen_nursery_end);
}
-static MONO_ALWAYS_INLINE char*
+static inline MONO_ALWAYS_INLINE char*
sgen_get_nursery_start (void)
{
return sgen_nursery_start;
}
-static MONO_ALWAYS_INLINE char*
+static inline MONO_ALWAYS_INLINE char*
sgen_get_nursery_end (void)
{
return sgen_nursery_end;
void (*init_worker_thread) (void *data);
void (*reset_worker_data) (void *data);
gboolean (*is_valid_object) (char *object);
- gboolean (*describe_pointer) (char *pointer);
+ MonoVTable* (*describe_pointer) (char *pointer);
guint8* (*get_cardtable_mod_union_for_object) (char *object);
long long (*get_and_reset_num_major_objects_marked) (void);
};
gboolean sgen_is_bridge_class (MonoClass *class) MONO_INTERNAL;
void sgen_mark_bridge_object (MonoObject *obj) MONO_INTERNAL;
void sgen_bridge_register_finalized_object (MonoObject *object) MONO_INTERNAL;
+void sgen_bridge_describe_pointer (MonoObject *object) MONO_INTERNAL;
void sgen_scan_togglerefs (char *start, char *end, ScanCopyContext ctx) MONO_INTERNAL;
void sgen_process_togglerefs (void) MONO_INTERNAL;
extern int default_nursery_size;
extern guint32 tlab_size;
extern NurseryClearPolicy nursery_clear_policy;
+extern gboolean sgen_try_free_some_memory;
extern LOCK_DECLARE (gc_mutex);
gboolean sgen_parse_environment_string_extract_number (const char *str, glong *out) MONO_INTERNAL;
void sgen_env_var_error (const char *env_var, const char *fallback, const char *description_format, ...) MONO_INTERNAL;
+/* Utilities */
+
+void sgen_qsort (void *base, size_t nel, size_t width, int (*compar) (const void*, const void*)) MONO_INTERNAL;
+
#endif /* HAVE_SGEN_GC */
#endif /* __MONO_SGENGC_H__ */
vtable = (MonoVTable*)SGEN_LOAD_VTABLE (obj->data);
if (obj->data == ptr) {
- SGEN_LOG (0, "%s (size %td pin %d)\n", los_kind, size, pinned ? 1 : 0);
+ SGEN_LOG (0, "%s (size %d pin %d)\n", los_kind, (int)size, pinned ? 1 : 0);
} else {
- SGEN_LOG (0, "%s (interior-ptr offset %td size %td pin %d)",
- los_kind, ptr - obj->data, size, pinned ? 1 : 0);
+ SGEN_LOG (0, "%s (interior-ptr offset %td size %d pin %d)",
+ los_kind, ptr - obj->data, (int)size, pinned ? 1 : 0);
}
return TRUE;
info->pinned = pinned;
info->has_references = has_references;
info->has_pinned = pinned;
- info->is_to_space = (sgen_get_current_collection_generation () == GENERATION_OLD); /*FIXME WHY??? */
+ /*
+ * Blocks that are to-space are not evacuated from. During an major collection
+ * blocks are allocated for two reasons: evacuating objects from the nursery and
+ * evacuating them from major blocks marked for evacuation. In both cases we don't
+ * want further evacuation.
+ */
+ info->is_to_space = (sgen_get_current_collection_generation () == GENERATION_OLD);
info->swept = 1;
#ifndef FIXED_HEAP
info->block = ms_get_empty_block ();
}
-static gboolean
+static MonoVTable*
major_describe_pointer (char *ptr)
{
MSBlockInfo *block;
SGEN_LOG (0, " marked %d)\n", marked ? 1 : 0);
- return TRUE;
+ return vtable;
} END_FOREACH_BLOCK;
- return FALSE;
+ return NULL;
}
static void
MS_CALC_MARK_BIT (word, bit, obj);
SGEN_ASSERT (9, !MS_MARK_BIT (block, word, bit), "object %p already marked", obj);
MS_PAR_SET_MARK_BIT (was_marked, block, word, bit);
+ binary_protocol_mark (obj, vt, sgen_safe_object_get_size ((MonoObject*)obj));
}
} else {
/*
#endif
sgen_los_pin_object (obj);
- /* FIXME: only enqueue if object has references */
- GRAY_OBJECT_ENQUEUE (queue, obj);
+ if (SGEN_OBJECT_HAS_REFERENCES (obj))
+ GRAY_OBJECT_ENQUEUE (queue, obj);
INC_NUM_MAJOR_OBJECTS_MARKED ();
}
}
#endif
sgen_los_pin_object (obj);
- /* FIXME: only enqueue if object has references */
- GRAY_OBJECT_ENQUEUE (queue, obj);
+ if (SGEN_OBJECT_HAS_REFERENCES (obj))
+ GRAY_OBJECT_ENQUEUE (queue, obj);
}
}
}
sweep_block (MSBlockInfo *block, gboolean during_major_collection)
{
int count;
+ void *reversed = NULL;
if (!during_major_collection)
g_assert (!sgen_concurrent_collection_in_progress ());
/* reset mark bits */
memset (block->mark_words, 0, sizeof (mword) * MS_NUM_MARK_WORDS);
- /*
- * FIXME: reverse free list so that it's in address
- * order
- */
+ /* Reverse free list so that it's in address order */
+ reversed = NULL;
+ while (block->free_list) {
+ void *next = *(void**)block->free_list;
+ *(void**)block->free_list = reversed;
+ reversed = block->free_list;
+ block->free_list = next;
+ }
+ block->free_list = reversed;
block->swept = 1;
}
empty_block_arr [i++] = block;
SGEN_ASSERT (0, i == num_empty_blocks, "empty block count wrong");
- qsort (empty_block_arr, num_empty_blocks, sizeof (void*), compare_pointers);
+ sgen_qsort (empty_block_arr, num_empty_blocks, sizeof (void*), compare_pointers);
/*
* We iterate over the free blocks, trying to find MS_BLOCK_ALLOC_NUM
if (debug_print_allowance) {
mword old_major = last_collection_old_num_major_sections * major_collector.section_size;
- SGEN_LOG (1, "Before collection: %td bytes (%td major, %td LOS)",
- old_major + last_collection_old_los_memory_usage, old_major, last_collection_old_los_memory_usage);
- SGEN_LOG (1, "After collection: %td bytes (%td major, %td LOS)",
- new_heap_size, new_major, last_collection_los_memory_usage);
- SGEN_LOG (1, "Allowance: %td bytes", minor_collection_allowance);
+ SGEN_LOG (1, "Before collection: %ld bytes (%ld major, %ld LOS)",
+ (long)(old_major + last_collection_old_los_memory_usage), (long)old_major, (long)last_collection_old_los_memory_usage);
+ SGEN_LOG (1, "After collection: %ld bytes (%ld major, %ld LOS)",
+ (long)new_heap_size, (long)new_major, (long)last_collection_los_memory_usage);
+ SGEN_LOG (1, "Allowance: %ld bytes", (long)minor_collection_allowance);
}
if (major_collector.have_computed_minor_collection_allowance)
dump_alloc_records (void)
{
int i;
- qsort (alloc_records, next_record, sizeof (AllocRecord), comp_alloc_record);
+ sgen_qsort (alloc_records, next_record, sizeof (AllocRecord), comp_alloc_record);
printf ("------------------------------------DUMP RECORDS----------------------------\n");
for (i = 0; i < next_record; ++i) {
int max_hole = 0;
AllocRecord *prev = NULL;
- qsort (alloc_records, next_record, sizeof (AllocRecord), comp_alloc_record);
+ sgen_qsort (alloc_records, next_record, sizeof (AllocRecord), comp_alloc_record);
printf ("------------------------------------DUMP RECORDS- %d %d---------------------------\n", next_record, alloc_count);
for (i = 0; i < next_record; ++i) {
AllocRecord *rec = alloc_records + i;
if (mono_gc_get_gc_callbacks ()->thread_suspend_func)
mono_gc_get_gc_callbacks ()->thread_suspend_func (info->runtime_data, &ctx, NULL);
- SGEN_LOG (2, "thread %p stopped at %p stack_start=%p", (void*)info->info.native_handle, info->stopped_ip, info->stack_start);
+ SGEN_LOG (2, "thread %p stopped at %p stack_start=%p", (void*)(gsize)info->info.native_handle, info->stopped_ip, info->stack_start);
binary_protocol_thread_suspend ((gpointer)mono_thread_info_get_tid (info), info->stopped_ip);
CloseHandle (handle);
- info->stopped_ip = (gpointer)context.Eip;
- info->stack_start = (char*)context.Esp - REDZONE_SIZE;
-
#ifdef USE_MONO_CTX
memset (&info->ctx, 0, sizeof (MonoContext));
+#ifdef TARGET_AMD64
+ info->ctx.rip = context.Rip;
+ info->ctx.rax = context.Rax;
+ info->ctx.rcx = context.Rcx;
+ info->ctx.rdx = context.Rdx;
+ info->ctx.rbx = context.Rbx;
+ info->ctx.rsp = context.Rsp;
+ info->ctx.rbp = context.Rbp;
+ info->ctx.rsi = context.Rsi;
+ info->ctx.rdi = context.Rdi;
+ info->ctx.r8 = context.R8;
+ info->ctx.r9 = context.R9;
+ info->ctx.r10 = context.R10;
+ info->ctx.r11 = context.R11;
+ info->ctx.r12 = context.R12;
+ info->ctx.r13 = context.R13;
+ info->ctx.r14 = context.R14;
+ info->ctx.r15 = context.R15;
+ info->stopped_ip = info->ctx.rip;
+ info->stack_start = (char*)info->ctx.rsp - REDZONE_SIZE;
+#else
info->ctx.edi = context.Edi;
info->ctx.esi = context.Esi;
info->ctx.ebx = context.Ebx;
info->ctx.eax = context.Eax;
info->ctx.ebp = context.Ebp;
info->ctx.esp = context.Esp;
+ info->stopped_ip = (gpointer)context.Eip;
+ info->stack_start = (char*)context.Esp - REDZONE_SIZE;
+#endif
+
#else
info->regs [0] = context.Edi;
info->regs [1] = context.Esi;
info->regs [5] = context.Eax;
info->regs [6] = context.Ebp;
info->regs [7] = context.Esp;
+ info->stopped_ip = (gpointer)context.Eip;
+ info->stack_start = (char*)context.Esp - REDZONE_SIZE;
#endif
/* Notify the JIT */
#include "sgen-protocol.h"
#include "sgen-memory-governor.h"
#include "utils/mono-mmap.h"
+#include "utils/mono-threads.h"
#ifdef SGEN_BINARY_PROTOCOL
if (!binary_protocol_file)
return;
+ if (sgen_is_worker_thread (mono_native_thread_id_get ()))
+ type |= 0x80;
+
lock_recursive ();
retry:
--- /dev/null
+/*
+ * sgen-qsort.c: Quicksort.
+ *
+ * Copyright (C) 2013 Xamarin Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License 2.0 as published by the Free Software Foundation;
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License 2.0 along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "config.h"
+
+#ifdef HAVE_SGEN_GC
+
+#include "metadata/sgen-gc.h"
+
+#define ELEM(i) (((unsigned char*)base) + ((i) * width))
+#define SWAP(i,j) do { \
+ size_t __i = (i), __j = (j); \
+ if (__i != __j) { \
+ memcpy (swap_tmp, ELEM (__i), width); \
+ memcpy (ELEM (__i), ELEM (__j), width); \
+ memcpy (ELEM (__j), swap_tmp, width); \
+ } \
+ } while (0)
+
+static size_t
+partition (void *base, size_t nel, size_t width, int (*compar) (const void*, const void*), unsigned char *pivot_tmp, unsigned char *swap_tmp)
+{
+ size_t pivot_idx = nel >> 1;
+ size_t s, i;
+
+ memcpy (pivot_tmp, ELEM (pivot_idx), width);
+ SWAP (pivot_idx, nel - 1);
+ s = 0;
+ for (i = 0; i < nel - 1; ++i) {
+ if (compar (ELEM (i), pivot_tmp) <= 0) {
+ SWAP (i, s);
+ ++s;
+ }
+ }
+ SWAP (s, nel - 1);
+ return s;
+}
+
+static void
+qsort_rec (void *base, size_t nel, size_t width, int (*compar) (const void*, const void*), unsigned char *pivot_tmp, unsigned char *swap_tmp)
+{
+ size_t pivot_idx;
+
+ if (nel <= 1)
+ return;
+
+ pivot_idx = partition (base, nel, width, compar, pivot_tmp, swap_tmp);
+ qsort_rec (base, pivot_idx, width, compar, pivot_tmp, swap_tmp);
+ if (pivot_idx < nel)
+ qsort_rec (ELEM (pivot_idx + 1), nel - pivot_idx - 1, width, compar, pivot_tmp, swap_tmp);
+}
+
+void
+sgen_qsort (void *base, size_t nel, size_t width, int (*compar) (const void*, const void*))
+{
+ unsigned char pivot_tmp [width];
+ unsigned char swap_tmp [width];
+
+ qsort_rec (base, nel, width, compar, pivot_tmp, swap_tmp);
+}
+
+#endif
*/
release_gc_locks ();
- mono_thread_hazardous_try_free_some ();
+ sgen_try_free_some_memory = TRUE;
sgen_bridge_processing_finish (generation);
if(address) {
mreq.imr_address = ipaddress_to_struct_in_addr (address);
}
+
+ field = mono_class_get_field_from_name(obj_val->vtable->klass, "iface_index");
+ mreq.imr_ifindex = *(gint32 *)(((char *)obj_val)+field->offset);
#else
if(address) {
mreq.imr_interface = ipaddress_to_struct_in_addr (address);
}
#endif /* HAVE_STRUCT_IP_MREQN */
-
+
ret = _wapi_setsockopt (sock, system_level,
system_name, &mreq,
sizeof (mreq));
linger.l_linger = 0;
ret = _wapi_setsockopt (sock, system_level, system_name, &linger, sizeof (linger));
break;
+ case SocketOptionName_MulticastInterface:
+#ifndef HOST_WIN32
+#ifdef HAVE_STRUCT_IP_MREQN
+ int_val = GUINT32_FROM_BE (int_val);
+ if ((int_val & 0xff000000) == 0) {
+ /* int_val is interface index */
+ struct ip_mreqn mreq = {{0}};
+ mreq.imr_ifindex = int_val;
+ ret = _wapi_setsockopt (sock, system_level, system_name, (char *) &mreq, sizeof (mreq));
+ break;
+ }
+ int_val = GUINT32_TO_BE (int_val);
+#endif /* HAVE_STRUCT_IP_MREQN */
+#endif /* HOST_WIN32 */
+ /* int_val is in_addr */
+ ret = _wapi_setsockopt (sock, system_level, system_name, (char *) &int_val, sizeof (int_val));
+ break;
case SocketOptionName_DontFragment:
#ifdef HAVE_IP_MTU_DISCOVER
/* Fiddle with the value slightly if we're
--- /dev/null
+/*
+ * test-sgen-qsort.c: Unit test for our own bzero/memmove.
+ *
+ * Copyright (C) 2013 Xamarin Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License 2.0 as published by the Free Software Foundation;
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License 2.0 along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "config.h"
+
+#include "metadata/gc-internal.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <assert.h>
+
+#define POOL_SIZE 2048
+#define START_OFFSET 128
+
+#define BZERO_OFFSETS 64
+#define BZERO_SIZES 256
+
+#define MEMMOVE_SRC_OFFSETS 32
+#define MEMMOVE_DEST_OFFSETS 32
+#define MEMMOVE_SIZES 256
+#define MEMMOVE_NONOVERLAP_START 1024
+
+int
+main (void)
+{
+ unsigned char *random_mem = malloc (POOL_SIZE);
+ unsigned char *reference = malloc (POOL_SIZE);
+ unsigned char *playground = malloc (POOL_SIZE);
+ long *long_random_mem;
+ int i, offset, size, src_offset, dest_offset;
+
+ srandom (time (NULL));
+
+ /* init random memory */
+ long_random_mem = (long*)random_mem;
+ for (i = 0; i < POOL_SIZE / sizeof (long); ++i)
+ long_random_mem [i] = random ();
+
+ /* test bzero */
+ for (offset = 0; offset <= BZERO_OFFSETS; ++offset) {
+ for (size = 0; size <= BZERO_SIZES; ++size) {
+ memcpy (reference, random_mem, POOL_SIZE);
+ memcpy (playground, random_mem, POOL_SIZE);
+
+ bzero (reference + START_OFFSET + offset, size);
+ mono_gc_bzero (playground + START_OFFSET + offset, size);
+
+ assert (!memcmp (reference, playground, POOL_SIZE));
+ }
+ }
+
+ /* test memmove */
+ for (src_offset = -MEMMOVE_SRC_OFFSETS; src_offset <= MEMMOVE_SRC_OFFSETS; ++src_offset) {
+ for (dest_offset = -MEMMOVE_DEST_OFFSETS; dest_offset <= MEMMOVE_DEST_OFFSETS; ++dest_offset) {
+ for (size = 0; size <= MEMMOVE_SIZES; ++size) {
+ /* overlapping */
+ memcpy (reference, random_mem, POOL_SIZE);
+ memcpy (playground, random_mem, POOL_SIZE);
+
+ memmove (reference + START_OFFSET + dest_offset, reference + START_OFFSET + src_offset, size);
+ mono_gc_memmove (playground + START_OFFSET + dest_offset, playground + START_OFFSET + src_offset, size);
+
+ assert (!memcmp (reference, playground, POOL_SIZE));
+
+ /* non-overlapping with dest < src */
+ memcpy (reference, random_mem, POOL_SIZE);
+ memcpy (playground, random_mem, POOL_SIZE);
+
+ memmove (reference + START_OFFSET + dest_offset, reference + MEMMOVE_NONOVERLAP_START + src_offset, size);
+ mono_gc_memmove (playground + START_OFFSET + dest_offset, playground + MEMMOVE_NONOVERLAP_START + src_offset, size);
+
+ assert (!memcmp (reference, playground, POOL_SIZE));
+
+ /* non-overlapping with dest > src */
+ memcpy (reference, random_mem, POOL_SIZE);
+ memcpy (playground, random_mem, POOL_SIZE);
+
+ memmove (reference + MEMMOVE_NONOVERLAP_START + dest_offset, reference + START_OFFSET + src_offset, size);
+ mono_gc_memmove (playground + MEMMOVE_NONOVERLAP_START + dest_offset, playground + START_OFFSET + src_offset, size);
+
+ assert (!memcmp (reference, playground, POOL_SIZE));
+ }
+ }
+ }
+
+ return 0;
+}
--- /dev/null
+/*
+ * test-sgen-qsort.c: Unit test for quicksort.
+ *
+ * Copyright (C) 2013 Xamarin Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License 2.0 as published by the Free Software Foundation;
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License 2.0 along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "config.h"
+
+#include "metadata/sgen-gc.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <assert.h>
+
+static int
+compare_ints (const void *pa, const void *pb)
+{
+ int a = *(const int*)pa;
+ int b = *(const int*)pb;
+ if (a < b)
+ return -1;
+ if (a == b)
+ return 0;
+ return 1;
+}
+
+typedef struct {
+ int key;
+ int val;
+} teststruct_t;
+
+static int
+compare_teststructs (const void *pa, const void *pb)
+{
+ int a = ((const teststruct_t*)pa)->key;
+ int b = ((const teststruct_t*)pb)->key;
+ if (a < b)
+ return -1;
+ if (a == b)
+ return 0;
+ return 1;
+}
+
+static void
+compare_sorts (void *base, size_t nel, size_t width, int (*compar) (const void*, const void*))
+{
+ size_t len = nel * width;
+ void *b1 = malloc (len);
+ void *b2 = malloc (len);
+
+ memcpy (b1, base, len);
+ memcpy (b2, base, len);
+
+ qsort (b1, nel, width, compar);
+ sgen_qsort (b2, nel, width, compar);
+
+ assert (!memcmp (b1, b2, len));
+
+ free (b1);
+ free (b2);
+}
+
+int
+main (void)
+{
+ int i;
+ for (i = 0; i < 4000; ++i) {
+ int a [i];
+ int j;
+
+ for (j = 0; j < i; ++j)
+ a [j] = i - j - 1;
+ compare_sorts (a, i, sizeof (int), compare_ints);
+ }
+
+ srandom (time (NULL));
+ for (i = 0; i < 2000; ++i) {
+ teststruct_t a [200];
+ int j;
+ for (j = 0; j < 200; ++j) {
+ a [j].key = random ();
+ a [j].val = random ();
+ }
+
+ compare_sorts (a, 200, sizeof (teststruct_t), compare_teststructs);
+ }
+
+ return 0;
+}
mono_thread_create_internal (domain, func, arg, FALSE, FALSE, 0);
}
-#if defined(HOST_WIN32) && defined(__GNUC__)
+#if defined(HOST_WIN32) && HAVE_DECL___READFSDWORD==0
static __inline__ __attribute__((always_inline))
-/* This is not defined by gcc */
unsigned long long
__readfsdword (unsigned long offset)
{
*staddr = (guint8*)pthread_get_stackaddr_np (pthread_self());
*stsize = pthread_get_stacksize_np (pthread_self());
+
+#ifdef TARGET_OSX
+ /*
+ * Mavericks reports stack sizes as 512kb:
+ * http://permalink.gmane.org/gmane.comp.java.openjdk.hotspot.devel/11590
+ * https://bugs.openjdk.java.net/browse/JDK-8020753
+ */
+ if (*stsize == 512 * 1024)
+ *stsize = 2048 * mono_pagesize ();
+#endif
+
/* staddr points to the start of the stack, not the end */
*staddr -= *stsize;
gint64 ves_icall_System_Threading_Interlocked_Increment_Long (gint64 *location)
{
+#if SIZEOF_VOID_P == 4
+ if (G_UNLIKELY ((size_t)location & 0x7)) {
+ gint64 ret;
+ mono_interlocked_lock ();
+ (*location)++;
+ ret = *location;
+ mono_interlocked_unlock ();
+ return ret;
+ }
+#endif
return InterlockedIncrement64 (location);
}
gint64 ves_icall_System_Threading_Interlocked_Decrement_Long (gint64 * location)
{
+#if SIZEOF_VOID_P == 4
+ if (G_UNLIKELY ((size_t)location & 0x7)) {
+ gint64 ret;
+ mono_interlocked_lock ();
+ (*location)--;
+ ret = *location;
+ mono_interlocked_unlock ();
+ return ret;
+ }
+#endif
return InterlockedDecrement64 (location);
}
gint64
ves_icall_System_Threading_Interlocked_Exchange_Long (gint64 *location, gint64 value)
{
+#if SIZEOF_VOID_P == 4
+ if (G_UNLIKELY ((size_t)location & 0x7)) {
+ gint64 ret;
+ mono_interlocked_lock ();
+ ret = *location;
+ *location = value;
+ mono_interlocked_unlock ();
+ return ret;
+ }
+#endif
return InterlockedExchange64 (location, value);
}
ves_icall_System_Threading_Interlocked_CompareExchange_Long (gint64 *location, gint64 value, gint64 comparand)
{
#if SIZEOF_VOID_P == 4
- if ((size_t)location & 0x7) {
+ if (G_UNLIKELY ((size_t)location & 0x7)) {
gint64 old;
mono_interlocked_lock ();
old = *location;
gint64
ves_icall_System_Threading_Interlocked_Add_Long (gint64 *location, gint64 value)
{
+#if SIZEOF_VOID_P == 4
+ if (G_UNLIKELY ((size_t)location & 0x7)) {
+ gint64 ret;
+ mono_interlocked_lock ();
+ *location += value;
+ ret = *location;
+ mono_interlocked_unlock ();
+ return ret;
+ }
+#endif
return InterlockedAdd64 (location, value);
}
gint64
ves_icall_System_Threading_Interlocked_Read_Long (gint64 *location)
{
+#if SIZEOF_VOID_P == 4
+ if (G_UNLIKELY ((size_t)location & 0x7)) {
+ gint64 ret;
+ mono_interlocked_lock ();
+ ret = *location;
+ mono_interlocked_unlock ();
+ return ret;
+ }
+#endif
return InterlockedRead64 (location);
}
MonoInternalThread *thread = mono_thread_internal_current ();
gboolean throw = FALSE;
- mono_debugger_check_interruption ();
-
ensure_synch_cs_set (thread);
EnterCriticalSection (thread->synch_cs);
gint64
ves_icall_System_Threading_Volatile_Read8 (void *ptr)
{
+#if SIZEOF_VOID_P == 4
+ if (G_UNLIKELY ((size_t)ptr & 0x7)) {
+ gint64 val;
+ mono_interlocked_lock ();
+ val = *(gint64*)ptr;
+ mono_interlocked_unlock ();
+ return val;
+ }
+#endif
return InterlockedRead64 (ptr);
}
{
LongDoubleUnion u;
+#if SIZEOF_VOID_P == 4
+ if (G_UNLIKELY ((size_t)ptr & 0x7)) {
+ double val;
+ mono_interlocked_lock ();
+ val = *(double*)ptr;
+ mono_interlocked_unlock ();
+ return val;
+ }
+#endif
+
u.ival = InterlockedRead64 (ptr);
return u.fval;
void
ves_icall_System_Threading_Volatile_Write8 (void *ptr, gint64 value)
{
+#if SIZEOF_VOID_P == 4
+ if (G_UNLIKELY ((size_t)ptr & 0x7)) {
+ mono_interlocked_lock ();
+ *(gint64*)ptr = value;
+ mono_interlocked_unlock ();
+ return;
+ }
+#endif
+
InterlockedWrite64 (ptr, value);
}
{
LongDoubleUnion u;
+#if SIZEOF_VOID_P == 4
+ if (G_UNLIKELY ((size_t)ptr & 0x7)) {
+ mono_interlocked_lock ();
+ *(double*)ptr = value;
+ mono_interlocked_unlock ();
+ return;
+ }
+#endif
+
u.fval = value;
InterlockedWrite64 (ptr, u.ival);
if (thread == NULL)
return;
- mono_debugger_check_interruption ();
-
if (thread->interruption_requested && (bypass_abort_protection || !is_running_protected_wrapper ())) {
MonoException* exc = mono_thread_execute_interruption (thread);
if (exc) mono_raise_exception (exc);
/Makefile.in
/Makefile.am
/*.o
+/*.g.c
/*.so
/*.exe
/*.dll
if PLATFORM_DARWIN
libmono_llvm_la_LDFLAGS=-Wl,-undefined -Wl,suppress -Wl,-flat_namespace
else
-libmono_llvm_la_LIBADD += $(top_builddir)/mono/mini/libmono-$(API_VER).la $(libs)
+libmono_llvm_la_LIBADD += $(top_builddir)/mono/mini/libmonoboehm-$(API_VER).la $(libs)
endif
endif
local-propagation.c \
driver.c \
debug-mini.c \
- debug-mini.h \
linear-scan.c \
aot-compiler.c \
aot-runtime.c \
mini-gc.c \
debugger-agent.h \
debugger-agent.c \
- debug-debugger.c \
- debug-debugger.h \
xdebug.c \
mini-llvm.h \
- mini-llvm-cpp.h
+ mini-llvm-cpp.h \
+ alias-analysis.c
test_sources = \
basic-calls.cs \
endif
if X86
-if MONO_DEBUGGER_SUPPORTED
-if PLATFORM_DARWIN
-mdb_x86 = mdb-debug-info32-darwin.s
-else
-mdb_x86 = mdb-debug-info32.s
-endif
-else
-mdb_x86 =
-endif
-arch_sources = $(x86_sources) $(mdb_x86)
+arch_sources = $(x86_sources)
arch_built=cpu-x86.h
arch_define=__i386__
endif
if AMD64
-if MONO_DEBUGGER_SUPPORTED
-arch_sources = $(amd64_sources) mdb-debug-info64.s
-else
arch_sources = $(amd64_sources)
-endif
arch_built=cpu-amd64.h
arch_define=__x86_64__
endif
if (REPORT_ABC_REMOVAL) {
printf ("ARRAY-ACCESS: removed bounds check on array %d with index %d\n",
array_variable, index_variable);
- NULLIFY_INS (ins);
}
+ NULLIFY_INS (ins);
} else {
if (TRACE_ABC_REMOVAL) {
if (index_context->ranges.zero.lower >= 0) {
--- /dev/null
+/*
+ * alias-analysis.c: Implement simple alias analysis for local variables.
+ *
+ * Author:
+ * Rodrigo Kumpera (kumpera@gmail.com)
+ *
+ * (C) 2013 Xamarin
+ */
+
+#include <config.h>
+#include <stdio.h>
+
+#include "mini.h"
+#include "ir-emit.h"
+#include "glib.h"
+
+static gboolean
+is_int_stack_size (int type)
+{
+#if SIZEOF_VOID_P == 4
+ return type == STACK_I4 || type == STACK_MP;
+#else
+ return type == STACK_I4;
+#endif
+}
+
+static gboolean
+is_long_stack_size (int type)
+{
+#if SIZEOF_VOID_P == 8
+ return type == STACK_I8 || type == STACK_MP;
+#else
+ return type == STACK_I8;
+#endif
+}
+
+
+static gboolean
+lower_load (MonoCompile *cfg, MonoInst *load, MonoInst *ldaddr)
+{
+ MonoInst *var = ldaddr->inst_p0;
+ MonoType *type = &var->klass->byval_arg;
+ int replaced_op = mono_type_to_load_membase (cfg, type);
+
+ if (load->opcode == OP_LOADV_MEMBASE && load->klass != var->klass) {
+ if (cfg->verbose_level > 2)
+ printf ("Incompatible load_vtype classes %s x %s\n", load->klass->name, var->klass->name);
+ return FALSE;
+ }
+
+ if (replaced_op != load->opcode) {
+ if (cfg->verbose_level > 2)
+ printf ("Incompatible load type: expected %s but got %s\n",
+ mono_inst_name (replaced_op),
+ mono_inst_name (load->opcode));
+ return FALSE;
+ } else {
+ if (cfg->verbose_level > 2) { printf ("mem2reg replacing: "); mono_print_ins (load); }
+ }
+
+ load->opcode = mono_type_to_regmove (cfg, type);
+ type_to_eval_stack_type (cfg, type, load);
+ load->sreg1 = var->dreg;
+ mono_jit_stats.loads_eliminated++;
+ return TRUE;
+}
+
+static gboolean
+lower_store (MonoCompile *cfg, MonoInst *store, MonoInst *ldaddr)
+{
+ MonoInst *var = ldaddr->inst_p0;
+ MonoType *type = &var->klass->byval_arg;
+ int replaced_op = mono_type_to_store_membase (cfg, type);
+
+ if (store->opcode == OP_STOREV_MEMBASE && store->klass != var->klass) {
+ if (cfg->verbose_level > 2)
+ printf ("Incompatible store_vtype classes %s x %s\n", store->klass->name, store->klass->name);
+ return FALSE;
+ }
+
+
+ if (replaced_op != store->opcode) {
+ if (cfg->verbose_level > 2)
+ printf ("Incompatible store_reg type: expected %s but got %s\n",
+ mono_inst_name (replaced_op),
+ mono_inst_name (store->opcode));
+ return FALSE;
+ } else {
+ if (cfg->verbose_level > 2) { printf ("mem2reg replacing: "); mono_print_ins (store); }
+ }
+
+ store->opcode = mono_type_to_regmove (cfg, type);
+ type_to_eval_stack_type (cfg, type, store);
+ store->dreg = var->dreg;
+ mono_jit_stats.stores_eliminated++;
+ return TRUE;
+}
+
+static gboolean
+lower_store_imm (MonoCompile *cfg, MonoInst *store, MonoInst *ldaddr)
+{
+ MonoInst *var = ldaddr->inst_p0;
+ MonoType *type = &var->klass->byval_arg;
+ int store_op = mono_type_to_store_membase (cfg, type);
+ if (store_op == OP_STOREV_MEMBASE || store_op == OP_STOREX_MEMBASE)
+ return FALSE;
+
+ switch (store->opcode) {
+#if SIZEOF_VOID_P == 4
+ case OP_STORE_MEMBASE_IMM:
+#endif
+ case OP_STOREI4_MEMBASE_IMM:
+ if (!is_int_stack_size (var->type)) {
+ if (cfg->verbose_level > 2) printf ("Incompatible variable of size != 4\n");
+ return FALSE;
+ }
+ if (cfg->verbose_level > 2) { printf ("mem2reg replacing: "); mono_print_ins (store); }
+ store->opcode = OP_ICONST;
+ store->type = STACK_I4;
+ store->dreg = var->dreg;
+ store->inst_c0 = store->inst_imm;
+ break;
+
+#if SIZEOF_VOID_P == 8
+ case OP_STORE_MEMBASE_IMM:
+#endif
+ case OP_STOREI8_MEMBASE_IMM:
+ if (!is_long_stack_size (var->type)) {
+ if (cfg->verbose_level > 2) printf ("Incompatible variable of size != 8\n");
+ return FALSE;
+ }
+ if (cfg->verbose_level > 2) { printf ("mem2reg replacing: "); mono_print_ins (store); }
+ store->opcode = OP_I8CONST;
+ store->type = STACK_I8;
+ store->dreg = var->dreg;
+ store->inst_l = store->inst_imm;
+ break;
+ default:
+ return FALSE;
+ }
+ mono_jit_stats.stores_eliminated++;
+ return TRUE;
+}
+
+static gboolean
+lower_memory_access (MonoCompile *cfg)
+{
+ MonoBasicBlock *bb;
+ MonoInst *ins, *tmp;
+ gboolean needs_dce = FALSE;
+ GHashTable *addr_loads = g_hash_table_new (NULL, NULL);
+ //FIXME optimize
+ for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
+ g_hash_table_remove_all (addr_loads);
+
+ for (ins = bb->code; ins; ins = ins->next) {
+ switch (ins->opcode) {
+ case OP_LDADDR:
+ g_hash_table_insert (addr_loads, GINT_TO_POINTER (ins->dreg), ins);
+ if (cfg->verbose_level > 2) { printf ("New address: "); mono_print_ins (ins); }
+ break;
+ case OP_MOVE:
+ tmp = (MonoInst*)g_hash_table_lookup (addr_loads, GINT_TO_POINTER (ins->sreg1));
+ /*
+ Forward propagate known aliases
+ ldaddr R10 <- R8
+ mov R11 <- R10
+ */
+ if (tmp) {
+ g_hash_table_insert (addr_loads, GINT_TO_POINTER (ins->dreg), tmp);
+ if (cfg->verbose_level > 2) { printf ("New alias: "); mono_print_ins (ins); }
+ } else {
+ /*
+ Source value is not a know address, kill the variable.
+ */
+ if (g_hash_table_remove (addr_loads, GINT_TO_POINTER (ins->dreg))) {
+ if (cfg->verbose_level > 2) { printf ("Killed alias: "); mono_print_ins (ins); }
+ }
+ }
+ break;
+
+ case OP_LOADV_MEMBASE:
+ case OP_LOAD_MEMBASE:
+ case OP_LOADU1_MEMBASE:
+ case OP_LOADI2_MEMBASE:
+ case OP_LOADU2_MEMBASE:
+ case OP_LOADI4_MEMBASE:
+ case OP_LOADU4_MEMBASE:
+ case OP_LOADI1_MEMBASE:
+ case OP_LOADI8_MEMBASE:
+ case OP_LOADR4_MEMBASE:
+ case OP_LOADR8_MEMBASE:
+ if (ins->inst_offset != 0)
+ continue;
+ tmp = g_hash_table_lookup (addr_loads, GINT_TO_POINTER (ins->sreg1));
+ if (tmp) {
+ if (cfg->verbose_level > 2) { printf ("Found candidate load:"); mono_print_ins (ins); }
+ needs_dce |= lower_load (cfg, ins, tmp);
+ }
+ break;
+
+ case OP_STORE_MEMBASE_REG:
+ case OP_STOREI1_MEMBASE_REG:
+ case OP_STOREI2_MEMBASE_REG:
+ case OP_STOREI4_MEMBASE_REG:
+ case OP_STOREI8_MEMBASE_REG:
+ case OP_STORER4_MEMBASE_REG:
+ case OP_STORER8_MEMBASE_REG:
+ case OP_STOREV_MEMBASE:
+ if (ins->inst_offset != 0)
+ continue;
+ tmp = g_hash_table_lookup (addr_loads, GINT_TO_POINTER (ins->dreg));
+ if (tmp) {
+ if (cfg->verbose_level > 2) { printf ("Found candidate store:"); mono_print_ins (ins); }
+ needs_dce |= lower_store (cfg, ins, tmp);
+ }
+ break;
+
+ case OP_STORE_MEMBASE_IMM:
+ case OP_STOREI4_MEMBASE_IMM:
+ case OP_STOREI8_MEMBASE_IMM:
+ if (ins->inst_offset != 0)
+ continue;
+ tmp = g_hash_table_lookup (addr_loads, GINT_TO_POINTER (ins->dreg));
+ if (tmp) {
+ if (cfg->verbose_level > 2) { printf ("Found candidate store-imm:"); mono_print_ins (ins); }
+ needs_dce |= lower_store_imm (cfg, ins, tmp);
+ }
+ break;
+ }
+ }
+ }
+ g_hash_table_destroy (addr_loads);
+ return needs_dce;
+}
+
+static gboolean
+recompute_aliased_variables (MonoCompile *cfg)
+{
+ int i;
+ MonoBasicBlock *bb;
+ MonoInst *ins;
+ int kills = 0;
+ int adds = 0;
+
+ for (i = 0; i < cfg->num_varinfo; i++) {
+ MonoInst *var = cfg->varinfo [i];
+ if (var->flags & MONO_INST_INDIRECT) {
+ if (cfg->verbose_level > 2) {
+ printf ("Killing :"); mono_print_ins (var);
+ }
+ ++kills;
+ }
+ var->flags &= ~MONO_INST_INDIRECT;
+ }
+
+ if (!kills)
+ return FALSE;
+
+ for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
+ for (ins = bb->code; ins; ins = ins->next) {
+ if (ins->opcode == OP_LDADDR) {
+ MonoInst *var;
+
+ if (cfg->verbose_level > 2) { printf ("Found op :"); mono_print_ins (ins); }
+
+ var = (MonoInst*)ins->inst_p0;
+ if (!(var->flags & MONO_INST_INDIRECT)) {
+ if (cfg->verbose_level) { printf ("Restoring :"); mono_print_ins (var); }
+ ++adds;
+ }
+ var->flags |= MONO_INST_INDIRECT;
+ }
+ }
+ }
+
+ mono_jit_stats.alias_found += kills;
+ mono_jit_stats.alias_removed += kills - adds;
+ if (kills > adds) {
+ if (cfg->verbose_level > 2) {
+ printf ("Method: %s\n", mono_method_full_name (cfg->method, 1));
+ printf ("Kills %d Adds %d\n", kills, adds);
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
+FIXME:
+ Don't DCE on the whole CFG, only the BBs that have changed.
+
+TODO:
+ SRVT of small types can fix cases of mismatch for fields of a different type than the component.
+ Handle aliasing of byrefs in call conventions.
+*/
+void
+mono_local_alias_analysis (MonoCompile *cfg)
+{
+ if (!cfg->has_indirection)
+ return;
+
+ if (cfg->verbose_level > 2)
+ mono_print_code (cfg, "BEFORE ALIAS_ANALYSIS");
+
+ /*
+ Remove indirection and memory access of known variables.
+ */
+ if (!lower_memory_access (cfg))
+ goto done;
+
+ /*
+ By replacing indirect access with direct operations, some LDADDR ops become dead. Kill them.
+ */
+ if (cfg->opt & MONO_OPT_DEADCE)
+ mono_local_deadce (cfg);
+
+ /*
+ Some variables no longer need to be flagged as indirect, find them.
+ */
+ if (!recompute_aliased_variables (cfg))
+ goto done;
+
+ /*
+ A lot of simplification just took place, we recompute local variables and do DCE to
+ really profit from the previous gains
+ */
+ mono_handle_global_vregs (cfg);
+ if (cfg->opt & MONO_OPT_DEADCE)
+ mono_local_deadce (cfg);
+
+done:
+ if (cfg->verbose_level > 2)
+ mono_print_code (cfg, "AFTER ALIAS_ANALYSIS");
+}
GHashTable *method_depth;
MonoCompile **cfgs;
int cfgs_size;
- GHashTable *patch_to_plt_entry;
+ GHashTable **patch_to_plt_entry;
GHashTable *plt_offset_to_entry;
GHashTable *patch_to_got_offset;
GHashTable **patch_to_got_offset_by_type;
guint32 final_got_size;
/* Number of GOT entries reserved for trampolines */
guint32 num_trampoline_got_entries;
+ guint32 tramp_page_size;
guint32 num_trampolines [MONO_AOT_TRAMP_NUM];
guint32 trampoline_got_offset_base [MONO_AOT_TRAMP_NUM];
guint32 trampoline_size [MONO_AOT_TRAMP_NUM];
+ guint32 tramp_page_code_offsets [MONO_AOT_TRAMP_NUM];
MonoAotOptions aot_opts;
guint32 nmethods;
MonoImageWriter *w;
MonoDwarfWriter *dwarf;
FILE *fp;
+ char *tmpbasename;
char *tmpfname;
GSList *cie_program;
GHashTable *unwind_info_offsets;
char *got_symbol_base;
char *got_symbol;
char *plt_symbol;
+ char *methods_symbol;
GHashTable *method_label_hash;
const char *temp_prefix;
const char *user_symbol_prefix;
acfg->llvm_label_prefix = "";
acfg->user_symbol_prefix = "";
-#if defined(TARGET_AMD64) && defined(TARGET_MACH)
- /* osx contains an old as which doesn't support avx opcodes */
- g_string_append (acfg->llc_args, "-mattr=-avx");
-#endif
-
#if defined(TARGET_AMD64)
g_string_append (acfg->llc_args, " -march=x86-64");
#endif
* calling code.
*/
static void
-arch_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean external, int *call_size)
+arch_emit_direct_call (MonoAotCompile *acfg, const char *target, gboolean external, MonoJumpInfo *ji, int *call_size)
{
#if defined(TARGET_X86) || defined(TARGET_AMD64)
/* Need to make sure this is exactly 5 bytes long */
if (!acfg->aot_opts.use_trampolines_page)
return;
+ acfg->tramp_page_size = mono_pagesize ();
+
sprintf (symbol, "%sspecific_trampolines_page", acfg->user_symbol_prefix);
emit_alignment (acfg, mono_pagesize ());
emit_global (acfg, symbol, TRUE);
if (!is_plt_patch (patch_info))
return NULL;
- res = g_hash_table_lookup (acfg->patch_to_plt_entry, patch_info);
+ if (!acfg->patch_to_plt_entry [patch_info->type])
+ acfg->patch_to_plt_entry [patch_info->type] = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
+ res = g_hash_table_lookup (acfg->patch_to_plt_entry [patch_info->type], patch_info);
// FIXME: This breaks the calculation of final_got_size
if (!acfg->llvm && patch_info->type == MONO_PATCH_INFO_METHOD && (patch_info->data.method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)) {
else
res->llvm_symbol = g_strdup_printf ("%s_llvm", res->symbol);
- g_hash_table_insert (acfg->patch_to_plt_entry, new_ji, res);
+ g_hash_table_insert (acfg->patch_to_plt_entry [new_ji->type], new_ji, res);
g_hash_table_insert (acfg->plt_offset_to_entry, GUINT_TO_POINTER (res->plt_offset), res);
#endif
/* JIT icall wrappers */
- /* FIXME: locking */
+ /* FIXME: locking - this is "safe" as full-AOT threads don't mutate the icall hash*/
g_hash_table_foreach (mono_get_jit_icall_info (), add_jit_icall_wrapper, acfg);
}
if (direct_call) {
int call_size;
- arch_emit_direct_call (acfg, direct_call_target, external_call, &call_size);
+ arch_emit_direct_call (acfg, direct_call_target, external_call, patch_info, &call_size);
i += call_size - 1;
} else {
int code_size;
case MONO_PATCH_INFO_METHOD_JUMP:
case MONO_PATCH_INFO_ICALL_ADDR:
case MONO_PATCH_INFO_METHOD_RGCTX:
+ case MONO_PATCH_INFO_METHOD_CODE_SLOT:
encode_method_ref (acfg, patch_info->data.method, p, &p);
break;
case MONO_PATCH_INFO_INTERNAL_METHOD:
seq_points = cfg->seq_point_info;
- buf_size = header->num_clauses * 256 + debug_info_size + 2048 + (seq_points ? (seq_points->len * 64) : 0) + cfg->gc_map_size;
+ buf_size = header->num_clauses * 256 + debug_info_size + 2048 + (seq_points ? (seq_points->len * 128) : 0) + cfg->gc_map_size;
p = buf = g_malloc (buf_size);
-#ifdef MONO_ARCH_HAVE_XP_UNWIND
use_unwind_ops = cfg->unwind_ops != NULL;
-#endif
flags = (jinfo->has_generic_jit_info ? 1 : 0) | (use_unwind_ops ? 2 : 0) | (header->num_clauses ? 4 : 0) | (seq_points ? 8 : 0) | (cfg->compile_llvm ? 16 : 0) | (jinfo->has_try_block_holes ? 32 : 0) | (cfg->gc_map ? 64 : 0) | (jinfo->has_arch_eh_info ? 128 : 0);
MonoJumpInfo *ji;
GSList *unwind_ops;
+ g_assert (info);
+
name = info->name;
code = info->code;
code_size = info->code_size;
}
emit_label (acfg, end_symbol);
+ emit_int32 (acfg, 0);
}
arch_emit_specific_trampoline_pages (acfg);
{
switch (patch_info->type) {
case MONO_PATCH_INFO_METHOD:
- case MONO_PATCH_INFO_METHODCONST: {
+ case MONO_PATCH_INFO_METHODCONST:
+ case MONO_PATCH_INFO_METHOD_CODE_SLOT: {
MonoMethod *method = patch_info->data.method;
return can_encode_method (acfg, method);
}
- tempbc = g_strdup_printf ("%s.bc", acfg->tmpfname);
+ tempbc = g_strdup_printf ("%s.bc", acfg->tmpbasename);
mono_llvm_emit_aot_module (tempbc, acfg->final_got_size);
g_free (tempbc);
* - 'prune-eh' and 'functionattrs' depend on 'basiccg'.
* The opt list below was produced by taking the output of:
* llvm-as < /dev/null | opt -O2 -disable-output -debug-pass=Arguments
- * then removing tailcallelim + the global opts, and adding a second gvn.
+ * then removing tailcallelim + the global opts.
+ * strip-dead-prototypes deletes unused intrinsics definitions.
*/
opts = g_strdup ("-instcombine -simplifycfg");
- opts = g_strdup ("-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -domfrontier -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -iv-users -indvars -loop-deletion -loop-simplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -simplifycfg -preverify -domtree -verify");
+ //opts = g_strdup ("-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -domfrontier -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -iv-users -indvars -loop-deletion -loop-simplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -simplifycfg -preverify -domtree -verify");
+ opts = g_strdup ("-targetlibinfo -no-aa -basicaa -notti -instcombine -simplifycfg -sroa -domtree -early-cse -lazy-value-info -correlated-propagation -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -indvars -loop-idiom -loop-deletion -loop-unroll -memdep -gvn -memdep -memcpyopt -sccp -instcombine -lazy-value-info -correlated-propagation -domtree -memdep -dse -adce -simplifycfg -instcombine -strip-dead-prototypes -preverify -domtree -verify");
#if 1
- command = g_strdup_printf ("%sopt -f %s -o \"%s.opt.bc\" \"%s.bc\"", acfg->aot_opts.llvm_path, opts, acfg->tmpfname, acfg->tmpfname);
+ command = g_strdup_printf ("%sopt -f %s -o \"%s.opt.bc\" \"%s.bc\"", acfg->aot_opts.llvm_path, opts, acfg->tmpbasename, acfg->tmpbasename);
printf ("Executing opt: %s\n", command);
if (system (command) != 0) {
exit (1);
#endif
unlink (acfg->tmpfname);
- command = g_strdup_printf ("%sllc %s -disable-gnu-eh-frame -enable-mono-eh-frame -o \"%s\" \"%s.opt.bc\"", acfg->aot_opts.llvm_path, acfg->llc_args->str, acfg->tmpfname, acfg->tmpfname);
+ command = g_strdup_printf ("%sllc %s -disable-gnu-eh-frame -enable-mono-eh-frame -o \"%s\" \"%s.opt.bc\"", acfg->aot_opts.llvm_path, acfg->llc_args->str, acfg->tmpfname, acfg->tmpbasename);
printf ("Executing llc: %s\n", command);
{
int oindex, i, prev_index;
char symbol [256];
- char end_symbol [256];
#if defined(TARGET_POWERPC64)
sprintf (symbol, ".Lgot_addr");
* code_offsets array. It is also used to compute the memory ranges occupied by
* AOT code, so it must be equal to the address of the first emitted method.
*/
- sprintf (symbol, "methods");
emit_section_change (acfg, ".text", 0);
emit_alignment (acfg, 8);
if (acfg->llvm) {
for (i = 0; i < acfg->nmethods; ++i) {
if (acfg->cfgs [i] && acfg->cfgs [i]->compile_llvm) {
- fprintf (acfg->fp, "\n.set methods, %s\n", acfg->cfgs [i]->asm_symbol);
+ acfg->methods_symbol = g_strdup (acfg->cfgs [i]->asm_symbol);
break;
}
}
- if (i == acfg->nmethods)
- /* No LLVM compiled methods */
- emit_label (acfg, symbol);
- } else {
+ }
+ if (!acfg->methods_symbol) {
+ sprintf (symbol, "methods");
emit_label (acfg, symbol);
+ acfg->methods_symbol = g_strdup (symbol);
}
/*
acfg->stats.offsets_size += acfg->nmethods * 4;
- sprintf (end_symbol, "methods");
for (i = 0; i < acfg->nmethods; ++i) {
if (acfg->cfgs [i]) {
- emit_symbol_diff (acfg, acfg->cfgs [i]->asm_symbol, end_symbol, 0);
+ emit_symbol_diff (acfg, acfg->cfgs [i]->asm_symbol, acfg->methods_symbol, 0);
} else {
emit_int32 (acfg, 0xffffffff);
}
acfg->stats.offsets_size += acfg->nmethods * 4;
- sprintf (end_symbol, "methods");
for (i = 0; i < acfg->nmethods; ++i) {
if (acfg->cfgs [i]) {
- emit_symbol_diff (acfg, acfg->cfgs [i]->asm_symbol, end_symbol, 0);
+ emit_symbol_diff (acfg, acfg->cfgs [i]->asm_symbol, acfg->methods_symbol, 0);
} else {
emit_int32 (acfg, 0xffffffff);
}
emit_alignment (acfg, 8);
emit_label (acfg, symbol);
- sprintf (end_symbol, "methods");
prev_index = -1;
for (i = 0; i < acfg->nmethods; ++i) {
MonoCompile *cfg;
else
fprintf (acfg->fp, "\n\tbl %s\n", symbol);
} else {
- emit_symbol_diff (acfg, symbol, end_symbol, 0);
+ emit_symbol_diff (acfg, symbol, acfg->methods_symbol, 0);
}
/* Make sure the table is sorted by index */
g_assert (index > prev_index);
}
sprintf (symbol, "unbox_trampolines_end");
emit_label (acfg, symbol);
+ emit_int32 (acfg, 0);
}
static void
* various problems (i.e. arm/thumb).
*/
emit_pointer (acfg, acfg->got_symbol);
- emit_pointer (acfg, "methods");
+ emit_pointer (acfg, acfg->methods_symbol);
if (acfg->llvm) {
/*
* Emit a reference to the mono_eh_frame table created by our modified LLVM compiler.
emit_int32 (acfg, __alignof__ (gint64));
#endif
emit_int32 (acfg, MONO_TRAMPOLINE_NUM);
+ emit_int32 (acfg, acfg->tramp_page_size);
+ for (i = 0; i < MONO_AOT_TRAMP_NUM; ++i)
+ emit_int32 (acfg, acfg->tramp_page_code_offsets [i]);
if (acfg->aot_opts.static_link) {
char *p;
#else
#define AS_NAME "nacl-as"
#endif
+#elif defined(TARGET_OSX)
+#define AS_NAME "clang -c -x assembler"
#else
#define AS_NAME "as"
#endif
#define LD_OPTIONS ""
#endif
-#define EH_LD_OPTIONS ""
+#if defined(sparc)
+#define LD_NAME "ld -shared -G"
+#elif defined(__ppc__) && defined(TARGET_MACH)
+#define LD_NAME "gcc -dynamiclib"
+#elif defined(TARGET_AMD64) && defined(TARGET_MACH)
+#define LD_NAME "clang --shared"
+#elif defined(HOST_WIN32)
+#define LD_NAME "gcc -shared --dll"
+#elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
+#define LD_NAME "clang -m32 -dynamiclib"
+#endif
if (acfg->aot_opts.asm_only) {
printf ("Output file: '%s'.\n", acfg->tmpfname);
tmp_outfile_name = g_strdup_printf ("%s.tmp", outfile_name);
-#if defined(sparc)
- command = g_strdup_printf ("ld -shared -G -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
-#elif defined(__ppc__) && defined(TARGET_MACH)
- command = g_strdup_printf ("gcc -dynamiclib -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
-#elif defined(TARGET_AMD64) && defined(TARGET_MACH)
- command = g_strdup_printf ("gcc --shared -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
-#elif defined(HOST_WIN32)
- command = g_strdup_printf ("gcc -shared --dll -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
-#elif defined(TARGET_X86) && defined(TARGET_MACH) && !defined(__native_client_codegen__)
- command = g_strdup_printf ("gcc -m32 -dynamiclib -o %s %s.o", tmp_outfile_name, acfg->tmpfname);
+#ifdef LD_NAME
+ command = g_strdup_printf ("%s -o %s %s.o", LD_NAME, tmp_outfile_name, acfg->tmpfname);
#else
- command = g_strdup_printf ("%sld %s %s -shared -o %s %s.o", tool_prefix, EH_LD_OPTIONS, LD_OPTIONS, tmp_outfile_name, acfg->tmpfname);
+ command = g_strdup_printf ("%sld %s -shared -o %s %s.o", tool_prefix, LD_OPTIONS, tmp_outfile_name, acfg->tmpfname);
#endif
printf ("Executing the native linker: %s\n", command);
if (system (command) != 0) {
#if defined(TARGET_MACH)
command = g_strdup_printf ("dsymutil %s", outfile_name);
- printf ("Generating debug symbols: %s\n", command);
+ printf ("Executing dsymutil: %s\n", command);
if (system (command) != 0) {
return 1;
}
acfg->method_indexes = g_hash_table_new (NULL, NULL);
acfg->method_depth = g_hash_table_new (NULL, NULL);
acfg->plt_offset_to_entry = g_hash_table_new (NULL, NULL);
- acfg->patch_to_plt_entry = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
+ acfg->patch_to_plt_entry = g_new0 (GHashTable*, MONO_PATCH_INFO_NUM);
acfg->patch_to_got_offset = g_hash_table_new (mono_patch_info_hash, mono_patch_info_equal);
acfg->patch_to_got_offset_by_type = g_new0 (GHashTable*, MONO_PATCH_INFO_NUM);
for (i = 0; i < MONO_PATCH_INFO_NUM; ++i)
g_hash_table_destroy (acfg->method_indexes);
g_hash_table_destroy (acfg->method_depth);
g_hash_table_destroy (acfg->plt_offset_to_entry);
- g_hash_table_destroy (acfg->patch_to_plt_entry);
+ for (i = 0; i < MONO_PATCH_INFO_NUM; ++i) {
+ if (acfg->patch_to_plt_entry [i])
+ g_hash_table_destroy (acfg->patch_to_plt_entry [i]);
+ }
+ g_free (acfg->patch_to_plt_entry);
g_hash_table_destroy (acfg->patch_to_got_offset);
g_hash_table_destroy (acfg->method_to_cfg);
g_hash_table_destroy (acfg->token_info_hash);
acfg->aot_opts.nrgctx_fetch_trampolines = 128;
acfg->aot_opts.ngsharedvt_arg_trampolines = 128;
acfg->aot_opts.llvm_path = g_strdup ("");
-#if MONOTOUCH
+#ifdef MONOTOUCH
acfg->aot_opts.use_trampolines_page = TRUE;
#endif
opt->mdb_optimizations = TRUE;
opt->gen_seq_points = TRUE;
- if (mono_debug_format == MONO_DEBUG_FORMAT_NONE) {
+ if (!mono_debug_enabled ()) {
fprintf (stderr, "The soft-debug AOT option requires the --debug option.\n");
return 1;
}
#ifdef ENABLE_LLVM
if (acfg->llvm) {
if (acfg->aot_opts.asm_only) {
- if (acfg->aot_opts.outfile)
+ if (acfg->aot_opts.outfile) {
acfg->tmpfname = g_strdup_printf ("%s", acfg->aot_opts.outfile);
- else
- acfg->tmpfname = g_strdup_printf ("%s.s", acfg->image->name);
+ acfg->tmpbasename = g_strdup (acfg->tmpfname);
+ } else {
+ acfg->tmpbasename = g_strdup_printf ("%s", acfg->image->name);
+ acfg->tmpfname = g_strdup_printf ("%s.s", acfg->tmpbasename);
+ }
} else {
- acfg->tmpfname = g_strdup ("temp.s");
+ acfg->tmpbasename = g_strdup_printf ("%s", "temp");
+ acfg->tmpfname = g_strdup_printf ("%s.s", acfg->tmpbasename);
}
emit_llvm_file (acfg);
}
if (!acfg->aot_opts.nodebug || acfg->aot_opts.dwarf_debug) {
- if (acfg->aot_opts.dwarf_debug && mono_debug_format == MONO_DEBUG_FORMAT_NONE) {
+ if (acfg->aot_opts.dwarf_debug && !mono_debug_enabled ()) {
fprintf (stderr, "The dwarf AOT option requires the --debug option.\n");
return 1;
}
guint8 *plt_end;
guint8 *blob;
gint32 *code_offsets;
-#ifdef MONOTOUCH
gpointer *method_addresses;
-#endif
/* This contains <offset, index> pairs sorted by offset */
/* This is needed because LLVM emitted methods can be in any order */
gint32 *sorted_code_offsets;
sofile = mono_dl_open (aot_name, MONO_DL_LAZY, &err);
if (!sofile) {
- mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT failed to load AOT module %s: %s\n", aot_name, err);
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT module '%s' not found: %s\n", aot_name, err);
g_free (err);
}
}
}
amodule->code_offsets = info->code_offsets;
-#ifdef MONOTOUCH
amodule->method_addresses = info->method_addresses;
-#endif
amodule->code = info->methods;
#ifdef TARGET_ARM
/* Mask out thumb interop bit */
amodule->code_offsets = g_malloc0 (amodule->info.nmethods * sizeof (gint32));
for (i = 0; i < amodule->info.nmethods; ++i) {
/* method_addresses () contains a table of branches, since the ios linker can update those correctly */
- void *addr = get_arm_bl_target ((guint32*)(amodule->method_addresses + i));
+ void *addr = get_arm_bl_target ((guint32*)amodule->method_addresses + i);
if (addr == amodule->method_addresses)
amodule->code_offsets [i] = 0xffffffff;
len = old_table[0].method_index;
else
len = 1;
- new_table = alloc0_jit_info_data (domain, (len * 1) * sizeof (JitInfoMap), async);
+ new_table = alloc0_jit_info_data (domain, (len + 1) * sizeof (JitInfoMap), async);
if (old_table)
memcpy (new_table, old_table, len * sizeof (JitInfoMap));
new_table [0].method_index = len + 1;
case MONO_PATCH_INFO_METHOD:
case MONO_PATCH_INFO_METHOD_JUMP:
case MONO_PATCH_INFO_ICALL_ADDR:
- case MONO_PATCH_INFO_METHOD_RGCTX: {
+ case MONO_PATCH_INFO_METHOD_RGCTX:
+ case MONO_PATCH_INFO_METHOD_CODE_SLOT: {
MethodRef ref;
gboolean res;
vm_address_t addr, taddr;
kern_return_t ret;
vm_prot_t prot, max_prot;
- int psize;
+ int psize, specific_trampoline_size;
unsigned char *code;
+ specific_trampoline_size = 2 * sizeof (gpointer);
+
mono_aot_page_lock ();
page = trampoline_pages [tramp_type];
if (page && page->trampolines < page->trampolines_end) {
code = page->trampolines;
- page->trampolines += 8;
+ page->trampolines += specific_trampoline_size;
mono_aot_page_unlock ();
return code;
}
amodule = image->aot_module;
g_assert (amodule);
+ g_assert (amodule->info.tramp_page_size == psize);
+
if (tramp_type == MONO_AOT_TRAMP_SPECIFIC)
tpage = load_function (amodule, "specific_trampolines_page");
else if (tramp_type == MONO_AOT_TRAMP_STATIC_RGCTX)
/* some other thread already allocated, so use that to avoid wasting memory */
if (page && page->trampolines < page->trampolines_end) {
code = page->trampolines;
- page->trampolines += 8;
+ page->trampolines += specific_trampoline_size;
mono_aot_page_unlock ();
vm_deallocate (mach_task_self (), addr, psize);
vm_deallocate (mach_task_self (), taddr, psize);
*out_amodule = amodule;
#ifdef MONOTOUCH
-#define MONOTOUCH_TRAMPOLINES_ERROR ". See http://docs.xamarin.com/ios/troubleshooting for instruction on how to fix this condition"
+#define MONOTOUCH_TRAMPOLINES_ERROR ". See http://docs.xamarin.com/ios/troubleshooting for instructions on how to fix this condition."
#else
#define MONOTOUCH_TRAMPOLINES_ERROR ""
#endif
return 5;
return 0;
}
+
+ static int llvm_ldlen_licm (int[] arr) {
+ int sum = 0;
+ // The ldlen should be moved out of the loop
+ for (int i = 0; i < arr.Length; ++i)
+ sum += arr [i];
+ return sum;
+ }
+
+ public static int test_10_llvm_ldlen_licm () {
+ int[] arr = new int [10];
+ for (int i = 0; i < 10; ++i)
+ arr [i] = 1;
+ return llvm_ldlen_licm (arr);
+ }
}
return f == PositiveInfinity ? 0 : 1;
}
- /*
- Disabled until they can be fixed to run on amd64
-
static double VALUE = 0.19975845134874831D;
public static int test_0_float_conversion_reduces_double_precision () {
return 1;
return 0;
}
- */
+
+ public static int test_0_int8_to_float_convertion ()
+ {
+ double d = (double)(float)(long)INT_VAL;
+
+ if (d != 323315616)
+ return 1;
+ return 0;
+ }
}
#
break: len:2
-jmp: len:120
tailcall: len:120 clob:c
br: len:6
label: len:0
long_conv_to_i2: dest:i src1:i len:4
long_conv_to_i4: dest:i src1:i len:3
long_conv_to_i8: dest:i src1:i len:3
-long_conv_to_r4: dest:f src1:i len:9
+long_conv_to_r4: dest:f src1:i len:15
long_conv_to_r8: dest:f src1:i len:9
long_conv_to_u4: dest:i src1:i len:3
long_conv_to_u8: dest:i src1:i len:3
float_cgt_un: dest:i src1:f src2:f len:48
float_clt: dest:i src1:f src2:f len:35
float_clt_un: dest:i src1:f src2:f len:42
+float_cneq: dest:i src1:f src2:f len:42
+float_cge: dest:i src1:f src2:f len:35
+float_cle: dest:i src1:f src2:f len:35
float_ceq_membase: dest:i src1:f src2:b len:35
float_cgt_membase: dest:i src1:f src2:b len:35
float_cgt_un_membase: dest:i src1:f src2:b len:48
amd64_set_xmmreg_r8: dest:f src1:f len:14 clob:m
amd64_save_sp_to_lmf: len:16
tls_get: dest:i len:16
-tls_get_reg: dest:i src1:i len:20
+tls_get_reg: dest:i src1:i len:32
+tls_set: src1:i len:16
+tls_set_reg: src1:i src2:i len:32
atomic_add_i4: src1:b src2:i dest:i len:32
atomic_add_new_i4: src1:b src2:i dest:i len:32
atomic_exchange_i4: src1:b src2:i dest:a len:32
int_neg: dest:i src1:i clob:1 len:4
int_not: dest:i src1:i clob:1 len:4
-int_conv_to_r4: dest:f src1:i len:9
+int_conv_to_r4: dest:f src1:i len:15
int_conv_to_r8: dest:f src1:i len:9
int_ceq: dest:c len:8
int_cgt: dest:c len:8
int_cgt_un: dest:c len:8
int_clt: dest:c len:8
int_clt_un: dest:c len:8
+
+int_cneq: dest:c len:8
+int_cge: dest:c len:8
+int_cle: dest:c len:8
+int_cge_un: dest:c len:8
+int_cle_un: dest:c len:8
+
int_beq: len:8
int_bne_un: len:8
int_blt: len:8
amd64_xor_membase_reg: src1:b src2:i len:13
amd64_mul_membase_reg: src1:b src2:i len:15
-float_conv_to_r4: dest:f src1:f
+float_conv_to_r4: dest:f src1:f len:17
vcall2: len:64 clob:c
vcall2_reg: src1:i len:64 clob:c
switch: src1:i len:40
seq_point: len:24
-callvirt: dest:v clob:c len:20
int_conv_to_r_un: dest:f src1:i len:32
throw: src1:i len:24
rethrow: src1:i len:24
# See the code in mini-x86.c for more details on how the specifiers are used.
#
break: len:1
-jmp: len:32 clob:c
call: dest:a clob:c len:17
tailcall: len:120 clob:c
br: len:5
float_cgt_un: dest:y src1:f src2:f len:37
float_clt: dest:y src1:f src2:f len:25
float_clt_un: dest:y src1:f src2:f len:32
+float_cneq: dest:y src1:f src2:f len:25
+float_cge: dest:y src1:f src2:f len:37
+float_cle: dest:y src1:f src2:f len:37
float_conv_to_u: dest:i src1:f len:36
call_handler: len:11 clob:c
aot_const: dest:i len:5
sext_i2: dest:i src1:y len:3
tls_get: dest:i len:20
tls_get_reg: dest:i src1:i len:20
+tls_set: src1:i len:20
+tls_set_reg: src1:i src2:i len:20
atomic_add_i4: src1:b src2:i dest:i len:16
atomic_add_new_i4: src1:b src2:i dest:i len:16
atomic_exchange_i4: src1:b src2:i dest:a len:24
int_clt: dest:y len:6
int_clt_un: dest:y len:6
+int_cneq: dest:y len:6
+int_cge: dest:y len:6
+int_cle: dest:y len:6
+int_cge_un: dest:y len:6
+int_cle_un: dest:y len:6
+
cond_exc_ieq: len:6
cond_exc_ine_un: len:6
cond_exc_ilt: len:6
+++ /dev/null
-/*
- * debug-debugger.c: Hard debugger support (mdb)
- *
- * Author:
- *
- * Copyright 2006-2010 Novell, Inc.
- */
-#if MONO_DEBUGGER_SUPPORTED
-
-#include <config.h>
-#include <mono/io-layer/io-layer.h>
-#include <mono/metadata/threads.h>
-#include <mono/metadata/assembly.h>
-#include <mono/metadata/mono-debug.h>
-#include <mono/metadata/mono-config.h>
-#define _IN_THE_MONO_DEBUGGER
-#include "debug-debugger.h"
-#include "debug-mini.h"
-#include <libgc/include/libgc-mono-debugger.h>
-#include "mini.h"
-#include <unistd.h>
-#include <locale.h>
-#include <string.h>
-
-/*
- * This file is only compiled on platforms where the debugger is supported - see the conditional
- * definition of `debugger_sources' in Makefile.am.
- *
- * configure.in checks whether we're using the included libgc and disables the debugger if not.
- */
-
-#if !defined(USE_INCLUDED_LIBGC)
-#error "Inconsistency detected: #defined MONO_DEBUGGER_SUPPORTED without USE_INCLUDED_GC - fix configure.in!"
-#endif
-
-static guint64 debugger_compile_method (guint64 method_arg);
-static guint64 debugger_get_virtual_method (guint64 class_arg, guint64 method_arg);
-static guint64 debugger_get_boxed_object (guint64 klass_arg, guint64 val_arg);
-static guint64 debugger_class_get_static_field_data (guint64 klass);
-
-static guint64 debugger_run_finally (guint64 argument1, guint64 argument2);
-static void debugger_initialize (void);
-static guint64 debugger_init_code_buffer (void);
-
-static void debugger_event_handler (MonoDebuggerEvent event, guint64 data, guint64 arg);
-
-static guint64 debugger_create_string (G_GNUC_UNUSED guint64 dummy, G_GNUC_UNUSED guint64 dummy2,
- G_GNUC_UNUSED guint64 dummy3, const gchar *string_argument);
-static gint64 debugger_lookup_class (guint64 image_argument, G_GNUC_UNUSED guint64 dummy,
- G_GNUC_UNUSED guint64 dummy2, gchar *full_name);
-static guint64 debugger_insert_method_breakpoint (guint64 method_argument, guint64 index);
-static guint64 debugger_insert_source_breakpoint (guint64 image_argument, guint64 token,
- guint64 index, const gchar *class_name);
-static void debugger_remove_breakpoint (guint64 index, G_GNUC_UNUSED guint64 dummy);
-static guint64 debugger_register_class_init_callback (guint64 image_argument, guint64 token,
- guint64 index, const gchar *class_name);
-static void debugger_remove_class_init_callback (guint64 index, G_GNUC_UNUSED guint64 dummy);
-static guint64 debugger_get_method_signature (guint64 argument1, G_GNUC_UNUSED guint64 argument2);
-
-static guint64 debugger_abort_runtime_invoke (G_GNUC_UNUSED guint64 dummy1, G_GNUC_UNUSED guint64 dummy2);
-
-#define EXECUTABLE_CODE_BUFFER_SIZE 4096
-static guint8 *debugger_executable_code_buffer = NULL;
-
-static GCThreadFunctions debugger_thread_vtable;
-
-static guint32 debugger_thread_abort_signal = 0;
-
-static MonoDebuggerMetadataInfo debugger_metadata_info = {
- sizeof (MonoDebuggerMetadataInfo),
- sizeof (MonoDefaults),
- &mono_defaults,
- MONO_SIZEOF_TYPE,
- sizeof (MonoArrayType),
- sizeof (MonoClass),
- sizeof (MonoInternalThread),
- G_STRUCT_OFFSET (MonoInternalThread, tid),
- G_STRUCT_OFFSET (MonoInternalThread, stack_ptr),
- G_STRUCT_OFFSET (MonoInternalThread, end_stack),
- G_STRUCT_OFFSET (MonoClass, image),
- G_STRUCT_OFFSET (MonoClass, instance_size),
- G_STRUCT_OFFSET (MonoClass, parent),
- G_STRUCT_OFFSET (MonoClass, type_token),
- G_STRUCT_OFFSET (MonoClass, fields),
- G_STRUCT_OFFSET (MonoClass, methods),
- G_STRUCT_OFFSET (MonoClass, method.count),
- G_STRUCT_OFFSET (MonoClass, this_arg),
- G_STRUCT_OFFSET (MonoClass, byval_arg),
- G_STRUCT_OFFSET (MonoClass, generic_class),
- G_STRUCT_OFFSET (MonoClass, generic_container),
- G_STRUCT_OFFSET (MonoClass, vtable),
- sizeof (MonoClassField),
- G_STRUCT_OFFSET (MonoClassField, type),
- G_STRUCT_OFFSET (MonoClassField, offset),
- G_STRUCT_OFFSET (MonoDefaults, corlib),
- G_STRUCT_OFFSET (MonoDefaults, object_class),
- G_STRUCT_OFFSET (MonoDefaults, byte_class),
- G_STRUCT_OFFSET (MonoDefaults, void_class),
- G_STRUCT_OFFSET (MonoDefaults, boolean_class),
- G_STRUCT_OFFSET (MonoDefaults, sbyte_class),
- G_STRUCT_OFFSET (MonoDefaults, int16_class),
- G_STRUCT_OFFSET (MonoDefaults, uint16_class),
- G_STRUCT_OFFSET (MonoDefaults, int32_class),
- G_STRUCT_OFFSET (MonoDefaults, uint32_class),
- G_STRUCT_OFFSET (MonoDefaults, int_class),
- G_STRUCT_OFFSET (MonoDefaults, uint_class),
- G_STRUCT_OFFSET (MonoDefaults, int64_class),
- G_STRUCT_OFFSET (MonoDefaults, uint64_class),
- G_STRUCT_OFFSET (MonoDefaults, single_class),
- G_STRUCT_OFFSET (MonoDefaults, double_class),
- G_STRUCT_OFFSET (MonoDefaults, char_class),
- G_STRUCT_OFFSET (MonoDefaults, string_class),
- G_STRUCT_OFFSET (MonoDefaults, enum_class),
- G_STRUCT_OFFSET (MonoDefaults, array_class),
- G_STRUCT_OFFSET (MonoDefaults, delegate_class),
- G_STRUCT_OFFSET (MonoDefaults, exception_class),
- G_STRUCT_OFFSET (MonoMethod, klass),
- G_STRUCT_OFFSET (MonoMethod, token),
- G_STRUCT_OFFSET (MonoMethod, name) + sizeof (void *),
- G_STRUCT_OFFSET (MonoMethodInflated, declaring),
- G_STRUCT_OFFSET (MonoVTable, klass),
- G_STRUCT_OFFSET (MonoVTable, vtable)
-};
-
-extern void MONO_DEBUGGER__notification_function (guint64 command, guint64 data, guint64 data2);
-
-/*
- * This is a global data symbol which is read by the debugger.
- */
-MonoDebuggerInfo MONO_DEBUGGER__debugger_info = {
- MONO_DEBUGGER_MAGIC,
- MONO_DEBUGGER_MAJOR_VERSION,
- MONO_DEBUGGER_MINOR_VERSION,
- 0, /* runtime_flags */
- sizeof (MonoDebuggerInfo),
- sizeof (MonoSymbolTable),
- MONO_TRAMPOLINE_NUM,
- mono_trampoline_code,
- &MONO_DEBUGGER__notification_function,
- &mono_symbol_table,
- &debugger_metadata_info,
- &mono_debug_debugger_version,
-
- &debugger_compile_method,
- &debugger_get_virtual_method,
- &debugger_get_boxed_object,
- &mono_debugger_runtime_invoke,
- &debugger_class_get_static_field_data,
- &debugger_run_finally,
- &debugger_initialize,
-
- &debugger_create_string,
- &debugger_lookup_class,
-
- &debugger_insert_method_breakpoint,
- &debugger_insert_source_breakpoint,
- &debugger_remove_breakpoint,
-
- &debugger_register_class_init_callback,
- &debugger_remove_class_init_callback,
-
- &mono_debugger_thread_table,
-
- &debugger_executable_code_buffer,
- mono_breakpoint_info,
- mono_breakpoint_info_index,
-
- EXECUTABLE_CODE_BUFFER_SIZE,
- MONO_BREAKPOINT_ARRAY_SIZE,
-
- debugger_get_method_signature,
- debugger_init_code_buffer,
-
- &gc_thread_vtable,
- &debugger_thread_vtable,
-
- &mono_debugger_event_handler,
- debugger_event_handler,
-
- &_mono_debug_using_mono_debugger,
- (gint32*)&_mono_debugger_interruption_request,
-
- &debugger_abort_runtime_invoke,
-
- &debugger_thread_abort_signal
-};
-
-static guint64
-debugger_abort_runtime_invoke (G_GNUC_UNUSED guint64 dummy1, G_GNUC_UNUSED guint64 dummy2)
-{
- return mono_debugger_abort_runtime_invoke ();
-}
-
-static guint64
-debugger_compile_method (guint64 method_arg)
-{
- MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gsize) method_arg);
- gpointer addr;
-
- mono_debugger_lock ();
- addr = mono_compile_method (method);
- mono_debugger_unlock ();
-
- return (guint64) (gsize) addr;
-}
-
-static guint64
-debugger_get_virtual_method (guint64 object_arg, guint64 method_arg)
-{
- MonoObject *object = (MonoObject *) GUINT_TO_POINTER ((gsize) object_arg);
- MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gsize) method_arg);
-
- if (mono_class_is_valuetype (mono_method_get_class (method)))
- return method_arg;
-
- return (guint64) (gsize) mono_object_get_virtual_method (object, method);
-}
-
-static guint64
-debugger_get_boxed_object (guint64 klass_arg, guint64 val_arg)
-{
- static MonoObject *last_boxed_object = NULL;
- MonoClass *klass = (MonoClass *) GUINT_TO_POINTER ((gsize) klass_arg);
- gpointer val = (gpointer) GUINT_TO_POINTER ((gsize) val_arg);
- MonoObject *boxed;
-
- if (!mono_class_is_valuetype (klass))
- return val_arg;
-
- boxed = mono_value_box (mono_domain_get (), klass, val);
- last_boxed_object = boxed; // Protect the object from being garbage collected
-
- return (guint64) (gsize) boxed;
-}
-
-static guint64
-debugger_create_string (G_GNUC_UNUSED guint64 dummy, G_GNUC_UNUSED guint64 dummy2,
- G_GNUC_UNUSED guint64 dummy3, const gchar *string_argument)
-{
- return (guint64) (gsize) mono_string_new_wrapper (string_argument);
-}
-
-static gint64
-debugger_lookup_class (guint64 image_argument, G_GNUC_UNUSED guint64 dummy,
- G_GNUC_UNUSED guint64 dummy2, gchar *full_name)
-{
- MonoImage *image = (MonoImage *) GUINT_TO_POINTER ((gsize) image_argument);
- gchar *name_space, *name, *pos;
- MonoClass *klass;
-
- pos = strrchr (full_name, '.');
- if (pos) {
- name_space = full_name;
- *pos = 0;
- name = pos + 1;
- } else {
- name = full_name;
- name_space = NULL;
- }
-
- klass = mono_class_from_name (image, name_space ? name_space : "", name);
- if (!klass)
- return -1;
-
- mono_class_init (klass);
- mono_class_setup_methods (klass);
- return (gint64) (gssize) klass;
-}
-
-static guint64
-debugger_run_finally (guint64 context_argument, G_GNUC_UNUSED guint64 dummy)
-{
- mono_debugger_run_finally (GUINT_TO_POINTER ((gsize)context_argument));
- return 0;
-}
-
-static guint64
-debugger_class_get_static_field_data (guint64 value)
-{
- MonoClass *klass = GUINT_TO_POINTER ((gsize) value);
- MonoVTable *vtable = mono_class_vtable (mono_domain_get (), klass);
- return (guint64) (gsize) mono_vtable_get_static_field_data (vtable);
-}
-
-static guint64
-debugger_insert_method_breakpoint (guint64 method_argument, guint64 index)
-{
- MonoMethod *method = GUINT_TO_POINTER ((gsize) method_argument);
- MonoDebugMethodAddressList *info;
-
- mono_debugger_lock ();
-
- if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
- const char *name = method->name;
- MonoMethod *nm = NULL;
-
- if (method->klass->parent == mono_defaults.multicastdelegate_class) {
- if (*name == 'I' && (strcmp (name, "Invoke") == 0))
- nm = mono_marshal_get_delegate_invoke (method, NULL);
- else if (*name == 'B' && (strcmp (name, "BeginInvoke") == 0))
- nm = mono_marshal_get_delegate_begin_invoke (method);
- else if (*name == 'E' && (strcmp (name, "EndInvoke") == 0))
- nm = mono_marshal_get_delegate_end_invoke (method);
- }
-
- if (!nm) {
- mono_debugger_unlock ();
- return 0;
- }
-
- method = nm;
- }
-
- info = mono_debugger_insert_method_breakpoint (method, index);
-
- mono_debugger_unlock ();
- return (guint64) (gsize) info;
-}
-
-static guint64
-debugger_insert_source_breakpoint (guint64 image_argument, guint64 token, guint64 index,
- const gchar *class_name)
-{
- MonoImage *image = GUINT_TO_POINTER ((gsize) image_argument);
- MonoDebugMethodAddressList *info;
- MonoClass *klass;
- int i;
-
- mono_debugger_lock ();
-
- klass = mono_debugger_register_class_init_callback (image, class_name, token, index);
- if (!klass || !klass->inited || !klass->methods) {
- mono_debugger_unlock ();
- return 0;
- }
-
- for (i = 0; i < klass->method.count; i++) {
- MonoMethod *method = klass->methods [i];
-
- if (method->token != token)
- continue;
-
- if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
- const char *name = method->name;
- MonoMethod *nm = NULL;
-
- if (method->klass->parent == mono_defaults.multicastdelegate_class) {
- if (*name == 'I' && (strcmp (name, "Invoke") == 0))
- nm = mono_marshal_get_delegate_invoke (method, NULL);
- else if (*name == 'B' && (strcmp (name, "BeginInvoke") == 0))
- nm = mono_marshal_get_delegate_begin_invoke (method);
- else if (*name == 'E' && (strcmp (name, "EndInvoke") == 0))
- nm = mono_marshal_get_delegate_end_invoke (method);
- }
-
- if (!nm) {
- mono_debugger_unlock ();
- return 0;
- }
-
- method = nm;
- }
-
- info = mono_debug_lookup_method_addresses (method);
- mono_debugger_unlock ();
- return (guint64) (gsize) info;
- }
-
- mono_debugger_unlock ();
- return 0;
-}
-
-static void
-debugger_remove_breakpoint (guint64 index, G_GNUC_UNUSED guint64 dummy)
-{
- mono_debugger_lock ();
- mono_debugger_remove_method_breakpoint (index);
- mono_debugger_remove_class_init_callback (index);
- mono_debugger_unlock ();
-}
-
-static guint64
-debugger_register_class_init_callback (guint64 image_argument, guint64 token, guint64 index,
- const gchar *class_name)
-{
- MonoImage *image = GUINT_TO_POINTER ((gsize) image_argument);
- MonoClass *klass;
-
- mono_debugger_lock ();
- klass = mono_debugger_register_class_init_callback (image, class_name, token, index);
- mono_debugger_unlock ();
- return (guint64) (gsize) klass;
-}
-
-static void
-debugger_remove_class_init_callback (guint64 index, G_GNUC_UNUSED guint64 dummy)
-{
- mono_debugger_lock ();
- mono_debugger_remove_class_init_callback (index);
- mono_debugger_unlock ();
-}
-
-static guint64
-debugger_get_method_signature (guint64 method_arg, G_GNUC_UNUSED guint64 dummy)
-{
- MonoMethod *method = (MonoMethod *) GUINT_TO_POINTER ((gsize) method_arg);
- MonoMethodSignature *sig;
-
- sig = mono_method_signature (method);
- return (guint64) (gsize) sig;
-}
-
-static void
-debugger_event_handler (MonoDebuggerEvent event, guint64 data, guint64 arg)
-{
- MONO_DEBUGGER__notification_function (event, data, arg);
-}
-
-static void
-debugger_gc_thread_created (pthread_t thread, void *stack_ptr)
-{
- mono_debugger_event (MONO_DEBUGGER_EVENT_GC_THREAD_CREATED,
- (guint64) (gsize) stack_ptr, thread);
-}
-
-static void
-debugger_gc_thread_exited (pthread_t thread, void *stack_ptr)
-{
- mono_debugger_event (MONO_DEBUGGER_EVENT_GC_THREAD_EXITED,
- (guint64) (gsize) stack_ptr, thread);
-}
-
-static void
-debugger_gc_stop_world (void)
-{
- mono_debugger_event (MONO_DEBUGGER_EVENT_ACQUIRE_GLOBAL_THREAD_LOCK, 0, 0);
-}
-
-static void
-debugger_gc_start_world (void)
-{
- mono_debugger_event (MONO_DEBUGGER_EVENT_RELEASE_GLOBAL_THREAD_LOCK, 0, 0);
-}
-
-static GCThreadFunctions debugger_thread_vtable = {
- NULL,
-
- debugger_gc_thread_created,
- debugger_gc_thread_exited,
-
- debugger_gc_stop_world,
- debugger_gc_start_world
-};
-
-static void
-debugger_init_threads (void)
-{
- gc_thread_vtable = &debugger_thread_vtable;
-}
-
-#if 0
-
-static void
-debugger_finalize_threads (void)
-{
- gc_thread_vtable = NULL;
-}
-
-#endif
-
-static guint64
-debugger_init_code_buffer (void)
-{
- if (!debugger_executable_code_buffer)
- debugger_executable_code_buffer = mono_global_codeman_reserve (EXECUTABLE_CODE_BUFFER_SIZE);
- return (guint64) (gsize) debugger_executable_code_buffer;
-}
-
-extern MonoDebuggerInfo *MONO_DEBUGGER__debugger_info_ptr;
-extern long MONO_DEBUGGER__using_debugger;
-
-static void
-debugger_initialize (void)
-{
-}
-
-/**
- * Check whether we're running inside the debugger.
- *
- * There seems to be a bug in some versions of glibc which causes _dl_debug_state() being called with
- * RT_CONSISTENT before relocations are done.
- *
- * If that happens, the debugger cannot read the `MONO_DEBUGGER__debugger_info' structure at the time
- * the `libmono.so' library is loaded.
- *
- * As a workaround, the `mdb_debug_info' now also contains a global variable called
- * `MONO_DEBUGGER__using_debugger' which may we set to 1 by the debugger to tell us that we're running
- * inside the debugger.
- *
- * mini_init() checks this and calls mini_debugger_init() if necessary.
- *
- */
-
-gboolean
-mini_debug_running_inside_mdb (void)
-{
- return MONO_DEBUGGER__using_debugger || mono_debug_using_mono_debugger ();
-}
-
-void
-mini_debugger_init (void)
-{
- if (mono_debugger_event_handler) {
- g_warning (G_STRLOC ": duplicate call to mono_debugger_init()!");
- return;
- }
-
- debugger_executable_code_buffer = mono_global_codeman_reserve (EXECUTABLE_CODE_BUFFER_SIZE);
- mono_debugger_event_handler = debugger_event_handler;
-
- debugger_thread_abort_signal = mono_thread_get_abort_signal ();
-
- /*
- * Use an indirect call so gcc can't optimize it away.
- */
- MONO_DEBUGGER__debugger_info.initialize ();
-
- debugger_init_threads ();
-
- /*
- * Initialize the thread manager.
- *
- * NOTE: We only reference the `MONO_DEBUGGER__debugger_info_ptr' here to prevent the
- * linker from removing the .mdb_debug_info section.
- */
-
- mono_debugger_event (MONO_DEBUGGER_EVENT_INITIALIZE_THREAD_MANAGER,
- (guint64) (gssize) MONO_DEBUGGER__debugger_info_ptr, 0);
-}
-
-void
-mini_debugger_set_attach_ok (void)
-{
- debugger_thread_abort_signal = mono_thread_get_abort_signal ();
- MONO_DEBUGGER__debugger_info.runtime_flags |= DEBUGGER_RUNTIME_FLAGS_ATTACH_OK;
-}
-
-typedef struct
-{
- MonoDomain *domain;
- const char *file;
-} DebuggerThreadArgs;
-
-typedef struct
-{
- MonoDomain *domain;
- MonoMethod *method;
- int argc;
- char **argv;
-} MainThreadArgs;
-
-static guint32
-main_thread_handler (gpointer user_data)
-{
- MainThreadArgs *main_args = (MainThreadArgs *) user_data;
-
- return mono_runtime_run_main (main_args->method, main_args->argc, main_args->argv, NULL);
-}
-
-int
-mini_debugger_main (MonoDomain *domain, MonoAssembly *assembly, int argc, char **argv)
-{
- MainThreadArgs main_args;
- MonoImage *image;
- MonoMethod *main_method;
-
- /*
- * Get and compile the main function.
- */
-
- image = mono_assembly_get_image (assembly);
- main_method = mono_get_method (image, mono_image_get_entry_point (image), NULL);
-
- /*
- * Initialize managed code.
- */
- mono_debugger_event (MONO_DEBUGGER_EVENT_INITIALIZE_MANAGED_CODE,
- (guint64) (gssize) main_method, 0);
-
- /*
- * Start the main thread and wait until it's ready.
- */
-
- main_args.domain = domain;
- main_args.method = main_method;
- main_args.argc = argc;
- main_args.argv = argv;
-
-#if RUN_IN_SUBTHREAD
- mono_thread_create (domain, main_thread_handler, &main_args);
-#else
- main_thread_handler (&main_args);
-#endif
-
- mono_thread_manage ();
-
- /*
- * This will never return.
- */
- mono_debugger_event (MONO_DEBUGGER_EVENT_WRAPPER_MAIN, 0, 0);
-
- return 0;
-}
-#endif /* MONO_DEBUGGER_SUPPORTED */
+++ /dev/null
-/*
- * This is a private header file for the debugger.
- */
-
-#ifndef __DEBUG_DEBUGGER_H__
-#define __DEBUG_DEBUGGER_H__
-
-#if !defined _IN_THE_MONO_DEBUGGER
-#error "<debug-debugger.h> is a private header file only intended to be used by the debugger."
-#endif
-
-#include <mono/metadata/class-internals.h>
-#include <mono/metadata/mono-debug-debugger.h>
-#include <libgc/include/libgc-mono-debugger.h>
-#include "debug-mini.h"
-
-typedef struct _MonoDebuggerInfo MonoDebuggerInfo;
-typedef struct _MonoDebuggerMetadataInfo MonoDebuggerMetadataInfo;
-
-/*
- * Address of the x86 trampoline code. This is used by the debugger to check
- * whether a method is a trampoline.
- */
-extern guint8 *mono_trampoline_code [];
-
-typedef enum {
- DEBUGGER_RUNTIME_FLAGS_NONE = 0,
- DEBUGGER_RUNTIME_FLAGS_ATTACH_OK = 1
-} MonoDebuggerRuntimeFlags;
-
-/*
- * There's a global data symbol called `MONO_DEBUGGER__debugger_info' which
- * contains pointers to global variables and functions which must be accessed
- * by the debugger.
- */
-struct _MonoDebuggerInfo {
- guint64 magic;
- guint32 major_version;
- guint32 minor_version;
- guint32 runtime_flags;
- guint32 total_size;
- guint32 symbol_table_size;
- guint32 mono_trampoline_num;
- guint8 **mono_trampoline_code;
- gpointer notification_function;
- MonoSymbolTable **symbol_table;
- MonoDebuggerMetadataInfo *metadata_info;
- gint32 *debugger_version;
-
- guint64 (*compile_method) (guint64 method_argument);
- guint64 (*get_virtual_method) (guint64 object_argument, guint64 method_argument);
- guint64 (*get_boxed_object_method) (guint64 klass_argument, guint64 val_argument);
- MonoInvokeFunc runtime_invoke;
- guint64 (*class_get_static_field_data) (guint64 klass);
- guint64 (*run_finally) (guint64 argument1, guint64 argument2);
- void (*initialize) (void);
-
- guint64 (*create_string) (G_GNUC_UNUSED guint64 dummy1, G_GNUC_UNUSED guint64 dummy2,
- G_GNUC_UNUSED guint64 dummy3, const gchar *string_argument);
- gint64 (*lookup_class) (guint64 image_argument, G_GNUC_UNUSED guint64 dummy,
- G_GNUC_UNUSED guint64 dummy2, gchar *full_name);
-
- guint64 (*insert_method_breakpoint) (guint64 method_argument, guint64 index);
- guint64 (*insert_source_breakpoint) (guint64 image_argument, guint64 token,
- guint64 index, const gchar *class_name);
- void (*remove_breakpoint) (guint64 index, G_GNUC_UNUSED guint64 dummy);
-
- guint64 (*rgister_class_init_callback) (guint64 image_argument, guint64 token,
- guint64 index, const gchar *class_name);
- void (*remove_class_init_callback) (guint64 index, G_GNUC_UNUSED guint64 dummy);
-
- MonoDebuggerThreadInfo **thread_table;
-
- guint8 **executable_code_buffer;
- MonoBreakpointInfo *mono_breakpoint_info;
- gssize *mono_breakpoint_info_index;
-
- guint32 executable_code_buffer_size;
- guint32 breakpoint_array_size;
-
- guint64 (*get_method_signature) (guint64 method_argument, G_GNUC_UNUSED guint64 dummy);
- guint64 (*init_code_buffer) (void);
-
- /*
- * These are only needed when attaching.
- */
- GCThreadFunctions **thread_vtable_ptr;
- GCThreadFunctions *debugger_thread_vtable;
- void (**event_handler_ptr) (MonoDebuggerEvent event, guint64 data, guint64 arg);
- void (*debugger_event_handler) (MonoDebuggerEvent event, guint64 data, guint64 arg);
- gint32 *using_mono_debugger;
- gint32 *interruption_request;
-
- guint64 (*abort_runtime_invoke) (G_GNUC_UNUSED guint64 dummy1, G_GNUC_UNUSED guint64 dummy2);
-
- guint32 *thread_abort_signal;
-};
-
-struct _MonoDebuggerMetadataInfo {
- int size;
- int mono_defaults_size;
- MonoDefaults *mono_defaults;
- int type_size;
- int array_type_size;
- int klass_size;
- int thread_size;
- int thread_tid_offset;
- int thread_stack_ptr_offset;
- int thread_end_stack_offset;
- int klass_image_offset;
- int klass_instance_size_offset;
- int klass_parent_offset;
- int klass_token_offset;
- int klass_field_offset;
- int klass_methods_offset;
- int klass_method_count_offset;
- int klass_this_arg_offset;
- int klass_byval_arg_offset;
- int klass_generic_class_offset;
- int klass_generic_container_offset;
- int klass_vtable_offset;
- int field_info_size;
- int field_info_type_offset;
- int field_info_offset_offset;
- int mono_defaults_corlib_offset;
- int mono_defaults_object_offset;
- int mono_defaults_byte_offset;
- int mono_defaults_void_offset;
- int mono_defaults_boolean_offset;
- int mono_defaults_sbyte_offset;
- int mono_defaults_int16_offset;
- int mono_defaults_uint16_offset;
- int mono_defaults_int32_offset;
- int mono_defaults_uint32_offset;
- int mono_defaults_int_offset;
- int mono_defaults_uint_offset;
- int mono_defaults_int64_offset;
- int mono_defaults_uint64_offset;
- int mono_defaults_single_offset;
- int mono_defaults_double_offset;
- int mono_defaults_char_offset;
- int mono_defaults_string_offset;
- int mono_defaults_enum_offset;
- int mono_defaults_array_offset;
- int mono_defaults_delegate_offset;
- int mono_defaults_exception_offset;
- int mono_method_klass_offset;
- int mono_method_token_offset;
- int mono_method_flags_offset;
- int mono_method_inflated_offset;
- int mono_vtable_klass_offset;
- int mono_vtable_vtable_offset;
-};
-
-#endif
#define _IN_THE_MONO_DEBUGGER
#include <mono/metadata/mono-debug-debugger.h>
-#include "debug-mini.h"
#include <mono/utils/valgrind.h>
-#ifdef MONO_DEBUGGER_SUPPORTED
-#include <libgc/include/libgc-mono-debugger.h>
-#endif
-
typedef struct {
guint32 index;
MonoMethodDesc *desc;
guint32 breakpoint_id;
} MiniDebugMethodInfo;
-typedef struct {
- MonoObject *last_exception;
- guint32 stopped_on_exception : 1;
- guint32 stopped_on_unhandled : 1;
-} MonoDebuggerExceptionState;
-
-typedef enum {
- MONO_DEBUGGER_THREAD_FLAGS_NONE = 0,
- MONO_DEBUGGER_THREAD_FLAGS_INTERNAL = 1,
- MONO_DEBUGGER_THREAD_FLAGS_THREADPOOL = 2
-} MonoDebuggerThreadFlags;
-
-typedef enum {
- MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_NONE = 0,
- MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_IN_RUNTIME_INVOKE = 1,
- MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED = 2
-} MonoDebuggerInternalThreadFlags;
-
-struct _MonoDebuggerThreadInfo {
- guint64 tid;
- guint64 lmf_addr;
- guint64 end_stack;
-
- guint64 extended_notifications;
-
- /* Next pointer. */
- MonoDebuggerThreadInfo *next;
-
- /*
- * The stack bounds are only used when reading a core file.
- */
- guint64 stack_start;
- guint64 signal_stack_start;
- guint32 stack_size;
- guint32 signal_stack_size;
-
- guint32 thread_flags;
-
- /*
- * The debugger doesn't access anything beyond this point.
- */
- MonoDebuggerExceptionState exception_state;
-
- guint32 internal_flags;
-
- MonoJitTlsData *jit_tls;
- MonoInternalThread *thread;
-};
-
-typedef struct {
- gpointer stack_pointer;
- MonoObject *exception_obj;
- guint32 stop;
- guint32 stop_unhandled;
-} MonoDebuggerExceptionInfo;
-
-MonoDebuggerThreadInfo *mono_debugger_thread_table = NULL;
-
static inline void
record_line_number (MiniDebugMethodInfo *info, guint32 address, guint32 offset)
{
{
MiniDebugMethodInfo *info;
- if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
+ if (!mono_debug_enabled ())
return;
info = g_new0 (MiniDebugMethodInfo, 1);
mono_debug_add_vg_method (method, jit);
- mono_debugger_check_breakpoints (method, debug_info);
-
mono_debug_free_method_jit_info (jit);
mono_debug_free_method (cfg);
}
{
MonoDebugMethodJitInfo *jit;
- if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
+ if (!mono_debug_enabled ())
return;
if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
mono_debug_free_method_jit_info (jit);
}
-void
-mono_debug_add_icall_wrapper (MonoMethod *method, MonoJitICallInfo* callinfo)
-{
- if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
- return;
-
- // mono_debug_add_wrapper (method, callinfo->wrapper, callinfo->func);
-}
-
static void
print_var_info (MonoDebugVarInfo *info, int idx, const char *name, const char *type)
{
static GPtrArray *breakpoints = NULL;
-int
+static int
mono_debugger_insert_breakpoint_full (MonoMethodDesc *desc)
{
static int last_breakpoint_id = 0;
return info->index;
}
-int
-mono_debugger_remove_breakpoint (int breakpoint_id)
-{
- int i;
-
- if (!breakpoints)
- return 0;
-
- for (i = 0; i < breakpoints->len; i++) {
- MiniDebugBreakpointInfo *info = g_ptr_array_index (breakpoints, i);
-
- if (info->index != breakpoint_id)
- continue;
-
- mono_method_desc_free (info->desc);
- g_ptr_array_remove (breakpoints, info);
- g_free (info);
- return 1;
- }
-
- return 0;
-}
-
+/*FIXME This is part of the public API by accident, remove it from there when possible. */
int
mono_debugger_insert_breakpoint (const gchar *method_name, gboolean include_namespace)
{
return mono_debugger_insert_breakpoint_full (desc);
}
+/*FIXME This is part of the public API by accident, remove it from there when possible. */
int
mono_debugger_method_has_breakpoint (MonoMethod *method)
{
return 0;
}
-
-void
-mono_debugger_breakpoint_callback (MonoMethod *method, guint32 index)
-{
- mono_debugger_event (MONO_DEBUGGER_EVENT_JIT_BREAKPOINT, (guint64) (gsize) method, index);
-}
-
-void
-mono_debugger_thread_created (gsize tid, MonoThread *thread, MonoJitTlsData *jit_tls, gpointer func)
-{
-#ifdef MONO_DEBUGGER_SUPPORTED
- size_t stsize = 0;
- guint8 *staddr = NULL;
- MonoDebuggerThreadInfo *info;
-
- if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
- return;
-
- mono_debugger_lock ();
-
- mono_thread_get_stack_bounds (&staddr, &stsize);
-
- info = g_new0 (MonoDebuggerThreadInfo, 1);
- info->tid = tid;
- info->thread = thread->internal_thread;
- info->stack_start = (guint64) (gsize) staddr;
- info->signal_stack_start = (guint64) (gsize) jit_tls->signal_stack;
- info->stack_size = stsize;
- info->signal_stack_size = jit_tls->signal_stack_size;
- info->end_stack = (guint64) (gsize) GC_mono_debugger_get_stack_ptr ();
- info->lmf_addr = (guint64) (gsize) mono_get_lmf_addr ();
- info->jit_tls = jit_tls;
-
- if (func)
- info->thread_flags = MONO_DEBUGGER_THREAD_FLAGS_INTERNAL;
- if (thread->internal_thread->threadpool_thread)
- info->thread_flags |= MONO_DEBUGGER_THREAD_FLAGS_THREADPOOL;
-
- info->next = mono_debugger_thread_table;
- mono_debugger_thread_table = info;
-
- mono_debugger_event (MONO_DEBUGGER_EVENT_THREAD_CREATED,
- tid, (guint64) (gsize) info);
-
- mono_debugger_unlock ();
-#endif /* MONO_DEBUGGER_SUPPORTED */
-}
-
-void
-mono_debugger_thread_cleanup (MonoJitTlsData *jit_tls)
-{
-#ifdef MONO_DEBUGGER_SUPPORTED
- MonoDebuggerThreadInfo **ptr;
-
- if (mono_debug_format == MONO_DEBUG_FORMAT_NONE)
- return;
-
- mono_debugger_lock ();
-
- for (ptr = &mono_debugger_thread_table; *ptr; ptr = &(*ptr)->next) {
- MonoDebuggerThreadInfo *info = *ptr;
-
- if (info->jit_tls != jit_tls)
- continue;
-
- mono_debugger_event (MONO_DEBUGGER_EVENT_THREAD_CLEANUP,
- info->tid, (guint64) (gsize) info);
-
- *ptr = info->next;
- g_free (info);
- break;
- }
-
- mono_debugger_unlock ();
-#endif
-}
-
-void
-mono_debugger_extended_notification (MonoDebuggerEvent event, guint64 data, guint64 arg)
-{
-#ifdef MONO_DEBUGGER_SUPPORTED
- MonoDebuggerThreadInfo **ptr;
- MonoInternalThread *thread = mono_thread_internal_current ();
-
- if (!mono_debug_using_mono_debugger ())
- return;
-
- mono_debugger_lock ();
-
- for (ptr = &mono_debugger_thread_table; *ptr; ptr = &(*ptr)->next) {
- MonoDebuggerThreadInfo *info = *ptr;
-
- if (info->thread != thread)
- continue;
-
- if ((info->extended_notifications & (int) event) == 0)
- continue;
-
- mono_debugger_event (event, data, arg);
- }
-
- mono_debugger_unlock ();
-#endif
-}
-
-void
-mono_debugger_trampoline_compiled (const guint8 *trampoline, MonoMethod *method, const guint8 *code)
-{
-#ifdef MONO_DEBUGGER_SUPPORTED
- struct {
- const guint8 * trampoline;
- MonoMethod *method;
- const guint8 *code;
- } info = { trampoline, method, code };
-
- mono_debugger_extended_notification (MONO_DEBUGGER_EVENT_OLD_TRAMPOLINE,
- (guint64) (gsize) method, (guint64) (gsize) code);
- mono_debugger_extended_notification (MONO_DEBUGGER_EVENT_TRAMPOLINE,
- (guint64) (gsize) &info, 0);
-#endif
-}
-
-#if MONO_DEBUGGER_SUPPORTED
-static MonoDebuggerThreadInfo *
-find_debugger_thread_info (MonoInternalThread *thread)
-{
- MonoDebuggerThreadInfo **ptr;
-
- for (ptr = &mono_debugger_thread_table; *ptr; ptr = &(*ptr)->next) {
- MonoDebuggerThreadInfo *info = *ptr;
-
- if (info->thread == thread)
- return info;
- }
-
- return NULL;
-}
-#endif
-
-MonoDebuggerExceptionAction
-_mono_debugger_throw_exception (gpointer addr, gpointer stack, MonoObject *exc)
-{
-#ifdef MONO_DEBUGGER_SUPPORTED
- MonoDebuggerExceptionInfo exc_info;
- MonoDebuggerThreadInfo *thread_info;
-
- if (!mono_debug_using_mono_debugger ())
- return MONO_DEBUGGER_EXCEPTION_ACTION_NONE;
-
- mono_debugger_lock ();
-
- thread_info = find_debugger_thread_info (mono_thread_internal_current ());
- if (!thread_info) {
- mono_debugger_unlock ();
- return MONO_DEBUGGER_EXCEPTION_ACTION_NONE;
- }
-
- if ((thread_info->internal_flags & MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED) != 0) {
- mono_debugger_unlock ();
- return MONO_DEBUGGER_EXCEPTION_ACTION_NONE;
- }
-
- if (thread_info->exception_state.stopped_on_exception ||
- thread_info->exception_state.stopped_on_unhandled) {
- thread_info->exception_state.stopped_on_exception = 0;
- mono_debugger_unlock ();
- return MONO_DEBUGGER_EXCEPTION_ACTION_NONE;
- }
-
- /* Protect the exception object from being garbage collected. */
-
- thread_info->exception_state.stopped_on_unhandled = 0;
- thread_info->exception_state.stopped_on_exception = 1;
- thread_info->exception_state.last_exception = exc;
-
- /*
- * Backwards compatibility:
- *
- * Older debugger versions only know `exc_info.stop' and older runtime versions check
- * `exc_info.stop != 0'.
- *
- * The debugger must check for `mono_debug_debugger_version >= 5' before accessing the
- * `stop_unhandled' field.
- */
-
- exc_info.stack_pointer = stack;
- exc_info.exception_obj = exc;
- exc_info.stop = 0;
- exc_info.stop_unhandled = 0;
-
- mono_debugger_event (MONO_DEBUGGER_EVENT_THROW_EXCEPTION, (guint64) (gsize) &exc_info,
- (guint64) (gsize) addr);
-
- if (!exc_info.stop) {
- thread_info->exception_state.stopped_on_exception = 0;
- thread_info->exception_state.last_exception = NULL;
- }
-
- mono_debugger_unlock ();
-
- if (exc_info.stop)
- return MONO_DEBUGGER_EXCEPTION_ACTION_STOP;
- else if (exc_info.stop_unhandled)
- return MONO_DEBUGGER_EXCEPTION_ACTION_STOP_UNHANDLED;
-#endif
-
- return MONO_DEBUGGER_EXCEPTION_ACTION_NONE;
-}
-
-gboolean
-_mono_debugger_unhandled_exception (gpointer addr, gpointer stack, MonoObject *exc)
-{
-#ifdef MONO_DEBUGGER_SUPPORTED
- MonoDebuggerThreadInfo *thread_info;
-
- if (!mono_debug_using_mono_debugger ())
- return FALSE;
-
- if (exc) {
- const gchar *name = mono_class_get_name (mono_object_get_class (exc));
- if (!strcmp (name, "ThreadAbortException"))
- return FALSE;
- }
-
- mono_debugger_lock ();
-
- thread_info = find_debugger_thread_info (mono_thread_internal_current ());
- if (!thread_info) {
- mono_debugger_unlock ();
- return FALSE;
- }
-
- if ((thread_info->internal_flags & MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED) != 0) {
- mono_debugger_unlock ();
- return FALSE;
- }
-
- if (thread_info->exception_state.stopped_on_unhandled) {
- thread_info->exception_state.stopped_on_unhandled = 0;
- mono_debugger_unlock ();
- return FALSE;
- }
-
- thread_info->exception_state.stopped_on_unhandled = 1;
- thread_info->exception_state.last_exception = exc;
-
- mono_debugger_event (MONO_DEBUGGER_EVENT_UNHANDLED_EXCEPTION,
- (guint64) (gsize) exc, (guint64) (gsize) addr);
-
- return TRUE;
-#else
- return FALSE;
-#endif
-}
-
-/*
- * mono_debugger_call_exception_handler:
- *
- * Called from mono_handle_exception_internal() to tell the debugger that we're about
- * to invoke an exception handler.
- *
- * The debugger may choose to set a breakpoint at @addr. This is used if the user is
- * single-stepping from a `try' into a `catch' block, for instance.
- */
-
-void
-mono_debugger_call_exception_handler (gpointer addr, gpointer stack, MonoObject *exc)
-{
-#ifdef MONO_DEBUGGER_SUPPORTED
- MonoDebuggerThreadInfo *thread_info;
- MonoDebuggerExceptionInfo exc_info;
-
- if (!mono_debug_using_mono_debugger ())
- return;
-
- mono_debugger_lock ();
-
- thread_info = find_debugger_thread_info (mono_thread_internal_current ());
- if (!thread_info) {
- mono_debugger_unlock ();
- return;
- }
-
- if ((thread_info->internal_flags & MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED) != 0) {
- mono_debugger_unlock ();
- return;
- }
-
- // Prevent the object from being finalized.
- thread_info->exception_state.last_exception = exc;
-
- exc_info.stack_pointer = stack;
- exc_info.exception_obj = exc;
- exc_info.stop = 0;
- exc_info.stop_unhandled = 0;
-
- mono_debugger_event (MONO_DEBUGGER_EVENT_HANDLE_EXCEPTION, (guint64) (gsize) &exc_info,
- (guint64) (gsize) addr);
-
- mono_debugger_unlock ();
-#endif
-}
-
-#ifdef MONO_DEBUGGER_SUPPORTED
-
-static gchar *
-get_exception_message (MonoObject *exc)
-{
- char *message = NULL;
- MonoString *str;
- MonoMethod *method;
- MonoClass *klass;
- gint i;
-
- if (mono_object_isinst (exc, mono_defaults.exception_class)) {
- klass = exc->vtable->klass;
- method = NULL;
- while (klass && method == NULL) {
- for (i = 0; i < klass->method.count; ++i) {
- method = klass->methods [i];
- if (!strcmp ("ToString", method->name) &&
- mono_method_signature (method)->param_count == 0 &&
- method->flags & METHOD_ATTRIBUTE_VIRTUAL &&
- method->flags & METHOD_ATTRIBUTE_PUBLIC) {
- break;
- }
- method = NULL;
- }
-
- if (method == NULL)
- klass = klass->parent;
- }
-
- g_assert (method);
-
- str = (MonoString *) mono_runtime_invoke (method, exc, NULL, NULL);
- if (str)
- message = mono_string_to_utf8 (str);
- }
-
- return message;
-}
-
-MonoObject *
-mono_debugger_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc)
-{
- MonoDebuggerThreadInfo *thread_info;
- MonoDebuggerExceptionState saved_exception_state;
- MonoObject *retval;
- gchar *message;
-
- mono_debugger_lock ();
-
- thread_info = find_debugger_thread_info (mono_thread_internal_current ());
- if (!thread_info) {
- mono_debugger_unlock ();
- return NULL;
- }
-
- saved_exception_state = thread_info->exception_state;
-
- thread_info->exception_state.last_exception = NULL;
- thread_info->exception_state.stopped_on_unhandled = 0;
- thread_info->exception_state.stopped_on_exception = 0;
-
- thread_info->internal_flags |= MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_IN_RUNTIME_INVOKE;
-
- mono_debugger_unlock ();
-
- if (!strcmp (method->name, ".ctor")) {
- retval = obj = mono_object_new (mono_domain_get (), method->klass);
-
- mono_runtime_invoke (method, obj, params, exc);
- } else
- retval = mono_runtime_invoke (method, obj, params, exc);
-
- mono_debugger_lock ();
-
- thread_info->exception_state = saved_exception_state;
- thread_info->internal_flags &= ~MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_IN_RUNTIME_INVOKE;
-
- if ((thread_info->internal_flags & MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED) != 0) {
- thread_info->internal_flags &= ~MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED;
- mono_thread_internal_reset_abort (thread_info->thread);
-
- mono_debugger_unlock ();
-
- *exc = NULL;
- return NULL;
- }
-
- mono_debugger_unlock ();
-
- if (!exc || (*exc == NULL))
- return retval;
-
- retval = *exc;
- message = get_exception_message (*exc);
- if (message) {
- *exc = (MonoObject *) mono_string_new_wrapper (message);
- g_free (message);
- }
-
- return retval;
-}
-
-gboolean
-mono_debugger_abort_runtime_invoke ()
-{
- MonoInternalThread *thread = mono_thread_internal_current ();
- MonoDebuggerThreadInfo *thread_info;
-
- mono_debugger_lock ();
-
- thread_info = find_debugger_thread_info (thread);
- if (!thread_info) {
- mono_debugger_unlock ();
- return FALSE;
- }
-
- if ((thread_info->internal_flags & MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_IN_RUNTIME_INVOKE) == 0) {
- mono_debugger_unlock ();
- return FALSE;
- }
-
- if ((thread_info->internal_flags & MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED) != 0) {
- mono_debugger_unlock ();
- return TRUE;
- }
-
- thread_info->internal_flags |= MONO_DEBUGGER_INTERNAL_THREAD_FLAGS_ABORT_REQUESTED;
- ves_icall_System_Threading_Thread_Abort (thread_info->thread, NULL);
-
- mono_debugger_unlock ();
- return TRUE;
-}
-
-#endif
+++ /dev/null
-#ifndef __DEBUG_MINI_H__
-#define __DEBUG_MINI_H__
-
-#include <mono/metadata/class-internals.h>
-#include <mono/metadata/mono-debug-debugger.h>
-
-#include "mini.h"
-
-typedef struct _MonoDebuggerThreadInfo MonoDebuggerThreadInfo;
-extern MonoDebuggerThreadInfo *mono_debugger_thread_table;
-
-MONO_API void
-mono_debugger_thread_created (gsize tid, MonoThread *thread, MonoJitTlsData *jit_tls, gpointer func);
-
-MONO_API void
-mono_debugger_thread_cleanup (MonoJitTlsData *jit_tls);
-
-MONO_API void
-mono_debugger_extended_notification (MonoDebuggerEvent event, guint64 data, guint64 arg);
-
-MONO_API void
-mono_debugger_trampoline_compiled (const guint8 *trampoline, MonoMethod *method, const guint8 *code);
-
-MONO_API void
-mono_debugger_call_exception_handler (gpointer addr, gpointer stack, MonoObject *exc);
-
-MONO_API gboolean
-mono_debugger_handle_exception (MonoContext *ctx, MonoObject *obj);
-
-MONO_API MonoObject *
-mono_debugger_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc);
-
-MONO_API gboolean
-mono_debugger_abort_runtime_invoke (void);
-
-/*
- * Internal exception API.
- */
-
-typedef enum {
- MONO_DEBUGGER_EXCEPTION_ACTION_NONE = 0,
- MONO_DEBUGGER_EXCEPTION_ACTION_STOP = 1,
- MONO_DEBUGGER_EXCEPTION_ACTION_STOP_UNHANDLED = 2
-} MonoDebuggerExceptionAction;
-
-MonoDebuggerExceptionAction
-_mono_debugger_throw_exception (gpointer addr, gpointer stack, MonoObject *exc);
-
-gboolean
-_mono_debugger_unhandled_exception (gpointer addr, gpointer stack, MonoObject *exc);
-
-/*
- * This is the old breakpoint interface.
- * It isn't used by the debugger anymore, but still when using the `--break' command
- * line argument.
- */
-
-int mono_debugger_insert_breakpoint_full (MonoMethodDesc *desc);
-int mono_debugger_remove_breakpoint (int breakpoint_id);
-void mono_debugger_breakpoint_callback (MonoMethod *method, guint32 idx);
-
-#endif
#include <mono/metadata/mono-debug-debugger.h>
#include <mono/metadata/debug-mono-symfile.h>
#include <mono/metadata/gc-internal.h>
+#include <mono/metadata/environment.h>
#include <mono/metadata/threads-types.h>
#include <mono/metadata/socket-io.h>
#include <mono/metadata/assembly.h>
gboolean embedding;
gboolean defer;
int keepalive;
+ gboolean setpgid;
} AgentConfig;
typedef struct
#define HEADER_LENGTH 11
#define MAJOR_VERSION 2
-#define MINOR_VERSION 25
+#define MINOR_VERSION 27
typedef enum {
CMD_SET_VM = 1,
typedef enum {
STEP_FILTER_NONE = 0,
STEP_FILTER_STATIC_CTOR = 1,
- STEP_FILTER_DEBUGGER_HIDDEN = 2
+ STEP_FILTER_DEBUGGER_HIDDEN = 2,
+ STEP_FILTER_DEBUGGER_STEP_THROUGH = 4
} StepFilter;
typedef enum {
gboolean global;
/* The list of breakpoints used to implement step-over */
GSList *bps;
+ /* The number of frames at the start of a step-over */
+ int nframes;
} SingleStepReq;
/*
fprintf (stderr, " timeout=<n>\t\t\tTimeout for connecting in milliseconds.\n");
fprintf (stderr, " server=y/n\t\t\tWhether to listen for a client connection.\n");
fprintf (stderr, " keepalive=<n>\t\t\tSend keepalive events every n milliseconds.\n");
+ fprintf (stderr, " setpgid=y/n\t\t\tWhether to call setpid(0, 0) after startup.\n");
fprintf (stderr, " help\t\t\t\tPrint this help.\n");
}
agent_config.embedding = atoi (arg + 10) == 1;
} else if (strncmp (arg, "keepalive=", 10) == 0) {
agent_config.keepalive = atoi (arg + 10);
+ } else if (strncmp (arg, "setpgid=", 8) == 0) {
+ agent_config.setpgid = parse_flag ("setpgid", arg + 8);
} else {
print_usage ();
exit (1);
*/
mini_get_debug_options ()->load_aot_jit_info_eagerly = TRUE;
+#ifdef HAVE_SETPGID
+ if (agent_config.setpgid)
+ setpgid (0, 0);
+#endif
+
if (!agent_config.onuncaught && !agent_config.onthrow)
finish_agent_init (TRUE);
}
if (ji->dbg_hidden)
filtered = TRUE;
}
+ if ((mod->data.filter & STEP_FILTER_DEBUGGER_STEP_THROUGH) && ji) {
+ MonoCustomAttrInfo *ainfo;
+ static MonoClass *klass;
+
+ if (!klass) {
+ klass = mono_class_from_name (mono_defaults.corlib, "System.Diagnostics", "DebuggerStepThroughAttribute");
+ g_assert (klass);
+ }
+ if (!ji->dbg_step_through_inited) {
+ ainfo = mono_custom_attrs_from_method (jinfo_get_method (ji));
+ if (ainfo) {
+ if (mono_custom_attrs_has_attr (ainfo, klass))
+ ji->dbg_step_through = TRUE;
+ mono_custom_attrs_free (ainfo);
+ }
+ ainfo = mono_custom_attrs_from_class (jinfo_get_method (ji)->klass);
+ if (ainfo) {
+ if (mono_custom_attrs_has_attr (ainfo, klass))
+ ji->dbg_step_through = TRUE;
+ mono_custom_attrs_free (ainfo);
+ }
+ ji->dbg_step_through_inited = TRUE;
+ }
+ if (ji->dbg_step_through)
+ filtered = TRUE;
+ }
}
}
buffer_add_domainid (&buf, mono_get_root_domain ());
break;
case EVENT_KIND_VM_DEATH:
+ if (CHECK_PROTOCOL_VERSION (2, 27))
+ buffer_add_int (&buf, mono_environment_exitcode_get ());
break;
case EVENT_KIND_EXCEPTION: {
EventInfo *ei = arg;
* Return FALSE if single stepping needs to continue.
*/
static gboolean
-ss_update (SingleStepReq *req, MonoJitInfo *ji, SeqPoint *sp)
+ss_update (SingleStepReq *req, MonoJitInfo *ji, SeqPoint *sp, DebuggerTlsData *tls, MonoContext *ctx)
{
MonoDebugMethodInfo *minfo;
MonoDebugSourceLocation *loc = NULL;
return FALSE;
}
+ if (req->depth == STEP_DEPTH_OVER && hit) {
+ if (!tls->context.valid)
+ mono_thread_state_init_from_monoctx (&tls->context, ctx);
+ compute_frame_info (tls->thread, tls);
+ if (req->nframes && tls->frame_count && tls->frame_count > req->nframes) {
+ /* Hit the breakpoint in a recursive call */
+ DEBUG (1, fprintf (log_file, "[%p] Breakpoint at lower frame while stepping over, continuing single stepping.\n", (gpointer)GetCurrentThreadId ()));
+ return FALSE;
+ }
+ }
+
if (req->size != STEP_SIZE_LINE)
return TRUE;
SingleStepReq *ss_req = req->info;
gboolean hit;
- hit = ss_update (ss_req, ji, sp);
+ if (mono_thread_internal_current () != ss_req->thread)
+ continue;
+
+ hit = ss_update (ss_req, ji, sp, tls, ctx);
if (hit)
g_ptr_array_add (ss_reqs, req);
return;
il_offset = sp->il_offset;
- if (!ss_update (ss_req, ji, sp))
+ if (!ss_update (ss_req, ji, sp, tls, ctx))
return;
/* Start single stepping again from the current sequence point */
}
if (ss_req->depth == STEP_DEPTH_OVER) {
+ if (ss_req->nframes == 0)
+ ss_req->nframes = tls->frame_count;
/* Need to stop in catch clauses as well */
for (i = 0; i < tls->frame_count; ++i) {
StackFrame *frame = tls->frames [i];
/* Setup our lmf */
memset (&ext, 0, sizeof (ext));
-#ifdef TARGET_AMD64
- ext.lmf.previous_lmf = *(lmf_addr);
- /* Mark that this is a MonoLMFExt */
- ext.lmf.previous_lmf = (gpointer)(((gssize)ext.lmf.previous_lmf) | 2);
- ext.lmf.rsp = (gssize)&ext;
-#elif defined(TARGET_X86)
- ext.lmf.previous_lmf = (gsize)*(lmf_addr);
- /* Mark that this is a MonoLMFExt */
- ext.lmf.previous_lmf = (gsize)(gpointer)(((gssize)ext.lmf.previous_lmf) | 2);
- ext.lmf.ebp = (gssize)&ext;
-#elif defined(TARGET_ARM)
- ext.lmf.previous_lmf = *(lmf_addr);
- /* Mark that this is a MonoLMFExt */
- ext.lmf.previous_lmf = (gpointer)(((gssize)ext.lmf.previous_lmf) | 2);
- ext.lmf.sp = (gssize)&ext;
-#elif defined(TARGET_POWERPC)
- ext.lmf.previous_lmf = *(lmf_addr);
- /* Mark that this is a MonoLMFExt */
- ext.lmf.previous_lmf = (gpointer)(((gssize)ext.lmf.previous_lmf) | 2);
- ext.lmf.ebp = (gssize)&ext;
-#elif defined(TARGET_S390X)
- ext.lmf.previous_lmf = *(lmf_addr);
- /* Mark that this is a MonoLMFExt */
- ext.lmf.previous_lmf = (gpointer)(((gssize)ext.lmf.previous_lmf) | 2);
- ext.lmf.ebp = (gssize)&ext;
-#elif defined(TARGET_MIPS)
- ext.lmf.previous_lmf = *(lmf_addr);
- /* Mark that this is a MonoLMFExt */
- ext.lmf.previous_lmf = (gpointer)(((gssize)ext.lmf.previous_lmf) | 2);
- ext.lmf.iregs [mips_sp] = (gssize)&ext;
-#else
- g_assert_not_reached ();
-#endif
+ mono_arch_init_lmf_ext (&ext, *lmf_addr);
ext.debugger_invoke = TRUE;
memcpy (&ext.ctx, &invoke->ctx, sizeof (MonoContext));
if (!mono_runtime_try_shutdown ())
break;
+ mono_environment_exitcode_set (exit_code);
+
/* Suspend all managed threads since the runtime is going away */
DEBUG(1, fprintf (log_file, "Suspending all threads...\n"));
mono_thread_suspend_all_other_threads ();
if (CHECK_PROTOCOL_VERSION (2, 16))
filter = decode_int (p, &p, end);
req->modifiers [i].data.filter = filter;
+ if (!CHECK_PROTOCOL_VERSION (2, 26) && (req->modifiers [i].data.filter & STEP_FILTER_DEBUGGER_HIDDEN))
+ /* Treat STEP_THOUGH the same as HIDDEN */
+ req->modifiers [i].data.filter |= STEP_FILTER_DEBUGGER_STEP_THROUGH;
} else if (mod == MOD_KIND_THREAD_ONLY) {
int id = decode_id (p, &p, end);
}
}
+void
+mono_decompose_vtype_opts_llvm (MonoCompile *cfg)
+{
+ MonoBasicBlock *bb, *first_bb;
+
+ /* Decompose only the OP_STOREV_MEMBASE opcodes, which need write barriers */
+
+ cfg->cbb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock));
+ first_bb = cfg->cbb;
+
+ for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
+ MonoInst *ins;
+ MonoInst *prev = NULL;
+ MonoInst *src_var, *src, *dest;
+ gboolean restart;
+ int dreg;
+
+ if (cfg->verbose_level > 2) mono_print_bb (bb, "BEFORE LOWER-VTYPE-OPTS(LLVM) ");
+
+ cfg->cbb->code = cfg->cbb->last_ins = NULL;
+ restart = TRUE;
+
+ while (restart) {
+ restart = FALSE;
+
+ for (ins = bb->code; ins; ins = ins->next) {
+ switch (ins->opcode) {
+ case OP_STOREV_MEMBASE: {
+ src_var = get_vreg_to_inst (cfg, ins->sreg1);
+
+ if (!src_var) {
+ g_assert (ins->klass);
+ src_var = mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, ins->sreg1);
+ }
+
+ EMIT_NEW_VARLOADA_VREG ((cfg), (src), ins->sreg1, &ins->klass->byval_arg);
+
+ dreg = alloc_preg (cfg);
+ EMIT_NEW_BIALU_IMM (cfg, dest, OP_ADD_IMM, dreg, ins->inst_destbasereg, ins->inst_offset);
+ mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
+ break;
+ }
+ default:
+ break;
+ }
+
+ g_assert (cfg->cbb == first_bb);
+
+ if (cfg->cbb->code || (cfg->cbb != first_bb)) {
+ /* Replace the original instruction with the new code sequence */
+
+ mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb);
+ first_bb->code = first_bb->last_ins = NULL;
+ first_bb->in_count = first_bb->out_count = 0;
+ cfg->cbb = first_bb;
+ }
+ else
+ prev = ins;
+ }
+ }
+
+ if (cfg->verbose_level > 2) mono_print_bb (bb, "AFTER LOWER-VTYPE-OPTS(LLVM) ");
+ }
+}
+
inline static MonoInst *
mono_get_domainvar (MonoCompile *cfg)
{
switch (ins->opcode) {
case OP_LDLEN:
NEW_LOAD_MEMBASE_FLAGS (cfg, dest, OP_LOADI4_MEMBASE, ins->dreg, ins->sreg1,
- G_STRUCT_OFFSET (MonoArray, max_length), ins->flags | MONO_INST_CONSTANT_LOAD);
+ G_STRUCT_OFFSET (MonoArray, max_length), ins->flags | MONO_INST_INVARIANT_LOAD);
MONO_ADD_INS (cfg->cbb, dest);
break;
case OP_BOUNDS_CHECK:
break;
case OP_STRLEN:
MONO_EMIT_NEW_LOAD_MEMBASE_OP_FLAGS (cfg, OP_LOADI4_MEMBASE, ins->dreg,
- ins->sreg1, G_STRUCT_OFFSET (MonoString, length), ins->flags | MONO_INST_CONSTANT_LOAD);
+ ins->sreg1, G_STRUCT_OFFSET (MonoString, length), ins->flags | MONO_INST_INVARIANT_LOAD);
break;
default:
break;
MONO_OPT_CMOV | \
MONO_OPT_GSHARED | \
MONO_OPT_SIMD | \
+ MONO_OPT_ALIAS_ANALYSIS | \
MONO_OPT_AOT)
#define EXCLUDED_FROM_ALL (MONO_OPT_SHARED | MONO_OPT_PRECOMP | MONO_OPT_UNSAFE | MONO_OPT_GSHAREDVT)
MONO_OPT_BRANCH,
MONO_OPT_CFOLD,
MONO_OPT_FCMOV,
+ MONO_OPT_ALIAS_ANALYSIS,
#ifdef MONO_ARCH_SIMD_INTRINSICS
MONO_OPT_SIMD,
MONO_OPT_SSE2,
MONO_OPT_SIMD | MONO_OPT_SSE2,
#endif
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_INTRINS,
+ MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_INTRINS | MONO_OPT_ALIAS_ANALYSIS,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_CFOLD,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE,
+ MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_ALIAS_ANALYSIS,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_TAILC,
MONO_OPT_BRANCH | MONO_OPT_PEEPHOLE | MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP | MONO_OPT_DEADCE | MONO_OPT_LOOP | MONO_OPT_INLINE | MONO_OPT_INTRINS | MONO_OPT_SSA,
#ifdef MONO_BIG_ARRAYS
"bigarrays "
#endif
-#ifdef MONO_DEBUGGER_SUPPORTED
- "debugger "
-#endif
#if defined(MONO_ARCH_SOFT_DEBUG_SUPPORTED) && !defined(DISABLE_SOFT_DEBUG)
"softdebug "
#endif
#endif
#endif
- if ((action == DO_EXEC) && mono_debug_using_mono_debugger ())
- action = DO_DEBUGGER;
-
if (mono_compile_aot || action == DO_EXEC || action == DO_DEBUGGER) {
g_set_prgname (argv[i]);
}
if (action == DO_DEBUGGER) {
enable_debugging = TRUE;
-
-#ifdef MONO_DEBUGGER_SUPPORTED
- mono_debug_init (MONO_DEBUG_FORMAT_DEBUGGER);
-#else
- g_print ("The Mono Debugger is not supported on this platform.\n");
+ g_print ("The Mono Debugger is no longer supported.\n");
return 1;
-#endif
} else if (enable_debugging)
mono_debug_init (MONO_DEBUG_FORMAT_MONO);
-#ifdef MONO_DEBUGGER_SUPPORTED
- if (enable_debugging) {
- if ((opt & MONO_OPT_GSHARED) == 0)
- mini_debugger_set_attach_ok ();
- }
-#endif
-
#ifdef HOST_WIN32
if (mixed_mode)
mono_load_coree (argv [i]);
mini_cleanup (domain);
return 0;
} else if (action == DO_DEBUGGER) {
-#ifdef MONO_DEBUGGER_SUPPORTED
- const char *error;
-
- error = mono_check_corlib_version ();
- if (error) {
- fprintf (stderr, "Corlib not in sync with this runtime: %s\n", error);
- fprintf (stderr, "Download a newer corlib or a newer runtime at http://www.go-mono.com/daily.\n");
- exit (1);
- }
-
- mini_debugger_main (domain, assembly, argc - i, argv + i);
- mini_cleanup (domain);
- return 0;
-#else
return 1;
-#endif
}
desc = mono_method_desc_new (mname, 0);
if (!desc) {
static int tramp_subprogram_attr [] = {
DW_AT_name , DW_FORM_string,
-#ifndef TARGET_IOS
- DW_AT_description , DW_FORM_string,
-#endif
DW_AT_low_pc , DW_FORM_addr,
DW_AT_high_pc , DW_FORM_addr,
};
emit_pointer_value (w, 0);
emit_pointer_value (w, 0);
/* offset into .debug_line section */
- emit_symbol_diff (w, ".Ldebug_line_start", ".Ldebug_line_section_start", 0);
+ if (w->emit_line)
+ emit_symbol_diff (w, ".Ldebug_line_start", ".Ldebug_line_section_start", 0);
+ else
+ emit_pointer_value (w, 0);
/* Base types */
for (i = 0; i < G_N_ELEMENTS (basic_types); ++i) {
emit_section_change (w, ".debug_loc", 0);
emit_label (w, ".Ldebug_loc_start");
- /* debug_line section */
- /*
- * We emit some info even if emit_line is FALSE, as the
- * apple linker seems to require a .debug_line section.
- */
- if (!w->collect_line_info)
- emit_line_number_info_begin (w);
-
emit_cie (w);
}
#include "mini.h"
#include "mini-amd64.h"
#include "tasklets.h"
-#include "debug-mini.h"
#define ALIGN_TO(val,align) (((val) + ((align) - 1)) & ~((align) - 1))
static MonoW32ExceptionHandler segv_handler;
LPTOP_LEVEL_EXCEPTION_FILTER mono_old_win_toplevel_exception_filter;
-guint64 mono_win_vectored_exception_handle;
+void *mono_win_vectored_exception_handle;
extern gboolean mono_win_chained_exception_needs_run;
#define W32_SEH_HANDLE_EX(_ex) \
if (_ex##_handler) _ex##_handler(0, ep, sctx)
-LONG CALLBACK seh_unhandled_exception_filter(EXCEPTION_POINTERS* ep)
+static LONG CALLBACK seh_unhandled_exception_filter(EXCEPTION_POINTERS* ep)
{
#ifndef MONO_CROSS_COMPILE
if (mono_old_win_toplevel_exception_filter) {
* Unhandled Exception Filter
* Top-level per-process exception handler.
*/
-LONG CALLBACK seh_vectored_exception_handler(EXCEPTION_POINTERS* ep)
+static LONG CALLBACK seh_vectored_exception_handler(EXCEPTION_POINTERS* ep)
{
EXCEPTION_RECORD* er;
CONTEXT* ctx;
void win32_seh_cleanup()
{
- if (mono_old_win_toplevel_exception_filter) SetUnhandledExceptionFilter(mono_old_win_toplevel_exception_filter);
-
guint32 ret = 0;
+ if (mono_old_win_toplevel_exception_filter) SetUnhandledExceptionFilter(mono_old_win_toplevel_exception_filter);
+
ret = RemoveVectoredExceptionHandler (mono_win_vectored_exception_handle);
g_assert (ret);
}
mono_ex->stack_trace = NULL;
}
- if (mono_debug_using_mono_debugger ()) {
- guint8 buf [16];
-
- mono_breakpoint_clean_code (NULL, (gpointer)rip, 8, buf, sizeof (buf));
-
- if (buf [3] == 0xe8) {
- MonoContext ctx_cp = ctx;
- ctx_cp.rip = rip - 5;
-
- if (mono_debugger_handle_exception (&ctx_cp, exc)) {
- mono_restore_context (&ctx_cp);
- g_assert_not_reached ();
- }
- }
- }
-
/* adjust eip so that it point into the call instruction */
ctx.rip -= 1;
frame->unwind_info = unwind_info;
frame->unwind_info_len = unwind_info_len;
+
+ /*
+ printf ("%s %p %p\n", ji->d.method->name, ji->code_start, ip);
+ mono_print_unwind_info (unwind_info, unwind_info_len);
+ */
regs [AMD64_RAX] = new_ctx->rax;
regs [AMD64_RBX] = new_ctx->rbx;
if (*lmf && ((*lmf) != jit_tls->first_lmf) && (MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->rsp)) {
/* remove any unused lmf */
- *lmf = (gpointer)(((guint64)(*lmf)->previous_lmf) & ~3);
+ *lmf = (gpointer)(((guint64)(*lmf)->previous_lmf) & ~7);
}
#ifndef MONO_AMD64_NO_PUSHES
memcpy (new_ctx, &ext->ctx, sizeof (MonoContext));
- *lmf = (gpointer)(((guint64)(*lmf)->previous_lmf) & ~3);
+ *lmf = (gpointer)(((guint64)(*lmf)->previous_lmf) & ~7);
frame->type = FRAME_TYPE_DEBUGGER_INVOKE;
new_ctx->rbp = (*lmf)->rbp;
new_ctx->rsp = (*lmf)->rsp;
- new_ctx->rbx = (*lmf)->rbx;
- new_ctx->r12 = (*lmf)->r12;
- new_ctx->r13 = (*lmf)->r13;
- new_ctx->r14 = (*lmf)->r14;
- new_ctx->r15 = (*lmf)->r15;
+ if (((guint64)(*lmf)->previous_lmf) & 4) {
+ MonoLMFTramp *ext = (MonoLMFTramp*)(*lmf);
+
+ /* Trampoline frame */
+ new_ctx->rbx = ext->regs [AMD64_RBX];
+ new_ctx->r12 = ext->regs [AMD64_R12];
+ new_ctx->r13 = ext->regs [AMD64_R13];
+ new_ctx->r14 = ext->regs [AMD64_R14];
+ new_ctx->r15 = ext->regs [AMD64_R15];
#ifdef TARGET_WIN32
- new_ctx->rdi = (*lmf)->rdi;
- new_ctx->rsi = (*lmf)->rsi;
+ new_ctx->rdi = ext->regs [AMD64_RDI];
+ new_ctx->rsi = ext->regs [AMD64_RSI];
#endif
+ } else {
+ /*
+ * The registers saved in the LMF will be restored using the normal unwind info,
+ * when the wrapper frame is processed.
+ */
+ new_ctx->rbx = 0;
+ new_ctx->r12 = 0;
+ new_ctx->r13 = 0;
+ new_ctx->r14 = 0;
+ new_ctx->r15 = 0;
+#ifdef TARGET_WIN32
+ new_ctx->rdi = 0;
+ new_ctx->rsi = 0;
+#endif
+ }
- *lmf = (gpointer)(((guint64)(*lmf)->previous_lmf) & ~3);
+ *lmf = (gpointer)(((guint64)(*lmf)->previous_lmf) & ~7);
return TRUE;
}
memcpy (&ctx, &jit_tls->ex_ctx, sizeof (MonoContext));
- if (mono_debugger_handle_exception (&ctx, (MonoObject *)obj))
- return;
-
mono_handle_exception (&ctx, obj);
mono_restore_context (&ctx);
/* The stack should be unaligned */
if ((sp % 16) == 0)
sp -= 8;
+#ifdef __linux__
+ /* Preserve the call chain to prevent crashes in the libgcc unwinder (#15969) */
+ *(guint64*)sp = ctx->rip;
+#endif
ctx->rsp = sp;
ctx->rip = (guint64)async_cb;
}
mono_arch_sigctx_to_monoctx (sigctx, &mctx);
- if (mono_debugger_handle_exception (&mctx, (MonoObject *)obj))
- return TRUE;
-
mono_handle_exception (&mctx, obj);
mono_arch_monoctx_to_sigctx (&mctx, sigctx);
mono_arch_sigctx_to_monoctx (sigctx, &mctx);
- if (mono_debugger_handle_exception (&mctx, (MonoObject *)obj)) {
- if (stack_ovf)
- prepare_for_guard_pages (&mctx);
- mono_restore_context (&mctx);
- }
-
mono_handle_exception (&mctx, obj);
if (stack_ovf)
prepare_for_guard_pages (&mctx);
(sizeof (UNWIND_CODE) * (MONO_MAX_UNWIND_CODES - unwindinfo->unwindInfo.CountOfCodes));
}
-PRUNTIME_FUNCTION
+static PRUNTIME_FUNCTION
MONO_GET_RUNTIME_FUNCTION_CALLBACK ( DWORD64 ControlPc, IN PVOID Context )
{
MonoJitInfo *ji;
ctx_reg = ARMREG_R0;
-#if defined(ARM_FPU_VFP)
- ARM_ADD_REG_IMM8 (code, ARMREG_IP, ctx_reg, G_STRUCT_OFFSET (MonoContext, fregs));
- ARM_FLDMD (code, ARM_VFP_D0, 16, ARMREG_IP);
-#endif
+ if (!mono_arch_is_soft_float ()) {
+ ARM_ADD_REG_IMM8 (code, ARMREG_IP, ctx_reg, G_STRUCT_OFFSET (MonoContext, fregs));
+ ARM_FLDMD (code, ARM_VFP_D0, 16, ARMREG_IP);
+ }
/* move pc to PC */
ARM_LDR_IMM (code, ARMREG_IP, ctx_reg, G_STRUCT_OFFSET (MonoContext, pc));
mono_add_unwind_op_offset (unwind_ops, code, start, ARMREG_LR, - sizeof (mgreg_t));
/* Save fp regs */
- ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, sizeof (double) * 16);
- cfa_offset += sizeof (double) * 16;
- mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, cfa_offset);
-#if defined(ARM_FPU_VFP)
- ARM_FSTMD (code, ARM_VFP_D0, 16, ARMREG_SP);
-#endif
+ if (!mono_arch_is_soft_float ()) {
+ ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, sizeof (double) * 16);
+ cfa_offset += sizeof (double) * 16;
+ mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, cfa_offset);
+ ARM_FSTMD (code, ARM_VFP_D0, 16, ARMREG_SP);
+ }
/* Param area */
ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, 8);
if (ji != NULL) {
int i;
- gssize regs [MONO_MAX_IREGS + 1];
+ gssize regs [MONO_MAX_IREGS + 1 + 8];
guint8 *cfa;
guint32 unwind_info_len;
guint8 *unwind_info;
else
unwind_info = mono_get_cached_unwind_info (ji->used_regs, &unwind_info_len);
+ /*
+ printf ("%s %p %p\n", ji->d.method->name, ji->code_start, ip);
+ mono_print_unwind_info (unwind_info, unwind_info_len);
+ */
+
for (i = 0; i < 16; ++i)
regs [i] = new_ctx->regs [i];
+#ifdef TARGET_IOS
+ /* On IOS, d8..d15 are callee saved. They are mapped to 8..15 in unwind.c */
+ for (i = 0; i < 8; ++i)
+ regs [MONO_MAX_IREGS + i] = new_ctx->fregs [8 + i];
+#endif
mono_unwind_frame (unwind_info, unwind_info_len, ji->code_start,
(guint8*)ji->code_start + ji->code_size,
- ip, regs, MONO_MAX_IREGS,
+ ip, regs, MONO_MAX_IREGS + 8,
save_locations, MONO_MAX_IREGS, &cfa);
for (i = 0; i < 16; ++i)
new_ctx->regs [i] = regs [i];
new_ctx->pc = regs [ARMREG_LR];
new_ctx->regs [ARMREG_SP] = (gsize)cfa;
+#ifdef TARGET_IOS
+ for (i = 0; i < 8; ++i)
+ new_ctx->fregs [8 + i] = regs [MONO_MAX_IREGS + i];
+#endif
if (*lmf && (MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->sp)) {
/* remove any unused lmf */
#include "mini.h"
#include "mini-x86.h"
#include "tasklets.h"
-#include "debug-mini.h"
static gpointer signal_exception_trampoline;
mono_ex->stack_trace = NULL;
}
- if (mono_debug_using_mono_debugger ()) {
- guint8 buf [16], *code;
-
- mono_breakpoint_clean_code (NULL, (gpointer)eip, 8, buf, sizeof (buf));
- code = buf + 8;
-
- if (buf [3] == 0xe8) {
- MonoContext ctx_cp = ctx;
- ctx_cp.eip = eip - 5;
-
- if (mono_debugger_handle_exception (&ctx_cp, exc)) {
- mono_restore_context (&ctx_cp);
- g_assert_not_reached ();
- }
- }
- }
-
/* adjust eip so that it point into the call instruction */
ctx.eip -= 1;
/* Adjust IP */
new_ctx->eip --;
- if (*lmf && (MONO_CONTEXT_GET_BP (ctx) >= (gpointer)(*lmf)->ebp)) {
- /* remove any unused lmf */
- *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~3);
+ if (*lmf && ((*lmf) != jit_tls->first_lmf)) {
+ gboolean is_tramp = ((guint32)((*lmf)->previous_lmf) & 1);
+ gpointer lmf_esp;
+
+ if (is_tramp)
+ /* lmf->esp is only set in trampoline frames */
+ lmf_esp = (gpointer)(*lmf)->esp;
+ else
+ /* In non-trampoline frames, ebp is the frame pointer */
+ lmf_esp = (gpointer)(*lmf)->ebp;
+ if (MONO_CONTEXT_GET_SP (ctx) >= lmf_esp)
+ /* remove any unused lmf */
+ *lmf = (gpointer)(((gsize)(*lmf)->previous_lmf) & ~3);
}
/* Pop arguments off the stack */
memcpy (&ctx, &jit_tls->ex_ctx, sizeof (MonoContext));
- if (mono_debugger_handle_exception (&ctx, (MonoObject *)obj))
- return;
-
mono_handle_exception (&ctx, obj);
mono_restore_context (&ctx);
mono_arch_sigctx_to_monoctx (sigctx, &mctx);
- if (mono_debugger_handle_exception (&mctx, (MonoObject *)obj))
- return TRUE;
-
mono_handle_exception (&mctx, obj);
mono_arch_monoctx_to_sigctx (&mctx, sigctx);
mctx = *ctx;
- if (mono_debugger_handle_exception (&mctx, (MonoObject *)obj)) {
- if (stack_ovf)
- prepare_for_guard_pages (&mctx);
- mono_restore_context (&mctx);
- }
-
mono_handle_exception (&mctx, obj);
if (stack_ovf)
prepare_for_guard_pages (&mctx);
* the IL code looks.
*/
-class Tests {
-
+#if MOBILE
+class ExceptionTests
+#else
+class Tests
+#endif
+{
+
+#if !MOBILE
public static int Main (string[] args) {
return TestDriver.RunTests (typeof (Tests), args);
}
+#endif
public static int test_0_catch () {
Exception x = new Exception ();
}
public static int test_0_nonvirt_nullref_at_clause_start () {
- Tests t = null;
+ ExceptionTests t = null;
try {
t.amethod ();
} catch (NullReferenceException) {
public static int test_0_lmf_filter () {
try {
// The invoke calls a runtime-invoke wrapper which has a filter clause
+#if MOBILE
+ typeof (ExceptionTests).GetMethod ("lmf_filter").Invoke (null, new object [] { });
+#else
typeof (Tests).GetMethod ("lmf_filter").Invoke (null, new object [] { });
+#endif
} catch (TargetInvocationException) {
}
return 0;
}
}
+#if !MOBILE
+class ExceptionTests : Tests
+{
+}
+#endif
\ No newline at end of file
mono_print_label (fp, tree->inst_newa_len);
break;
case OP_CALL:
- case OP_CALLVIRT:
+ case OP_CALL_MEMBASE:
case OP_FCALL:
- case OP_FCALLVIRT:
+ case OP_FCALL_MEMBASE:
case OP_LCALL:
- case OP_LCALLVIRT:
+ case OP_LCALL_MEMBASE:
case OP_VCALL:
- case OP_VCALLVIRT:
+ case OP_VCALL_MEMBASE:
case OP_VOIDCALL:
- case OP_VOIDCALLVIRT: {
+ case OP_VOIDCALL_MEMBASE: {
MonoCallInst *call = (MonoCallInst*)tree;
if (call->method) {
if (mono_method_signature (call->method)->hasthis && tree->inst_left) {
IL_000a: ret
}
- // Check that localloc can't be inlined
+ // Check that localloc cannot be inlined
.method static public int32 test_0_localloc_inline () cil managed {
.maxstack 16
.locals init (
ret
}
+ .method public static int32 test_1234_fconv_u () cil managed {
+ .maxstack 16
+
+ ldc.r8 1234.0
+ conv.u
+ conv.i4
+ ret
+ }
+
.method public static int32 test_0_get_type_from_handle_on_bblock_boundary () cil managed
{
.maxstack 16
#define USE_ELF_WRITER 1
#endif
-#if defined(USE_ELF_WRITER)
+#if defined(TARGET_X86) && defined(__APPLE__)
+#define USE_MACH_WRITER
+#endif
+
+#if defined(USE_ELF_WRITER) || defined(USE_MACH_WRITER)
#define USE_BIN_WRITER 1
#endif
acfg->cur_section->cur_offset += num;
}
+static void
+bin_writer_fwrite (MonoImageWriter *acfg, void *val, size_t size, size_t nmemb)
+{
+ if (acfg->fp)
+ fwrite (val, size, nmemb, acfg->fp);
+ else {
+ g_assert (acfg->out_buf_pos + (size * nmemb) <= acfg->out_buf_size);
+ memcpy (acfg->out_buf + acfg->out_buf_pos, val, size * nmemb);
+ acfg->out_buf_pos += (size * nmemb);
+ }
+}
+
+static void
+bin_writer_fseek (MonoImageWriter *acfg, int offset)
+{
+ if (acfg->fp)
+ fseek (acfg->fp, offset, SEEK_SET);
+ else
+ acfg->out_buf_pos = offset;
+}
+
+#ifdef USE_MACH_WRITER
+
+/*
+ * This is a minimal implementation designed to support xdebug on 32 bit osx
+ * FIXME: 64 bit support
+ */
+
+#include <mach-o/loader.h>
+
+static gsize
+get_label_addr (MonoImageWriter *acfg, const char *name)
+{
+ int offset;
+ BinLabel *lab;
+ BinSection *section;
+ gsize value;
+
+ lab = g_hash_table_lookup (acfg->labels, name);
+ if (!lab)
+ g_error ("Undefined label: '%s'.\n", name);
+ section = lab->section;
+ offset = lab->offset;
+ if (section->parent) {
+ value = section->parent->virt_offset + section->cur_offset + offset;
+ } else {
+ value = section->virt_offset + offset;
+ }
+ return value;
+}
+
+
+static void
+resolve_reloc (MonoImageWriter *acfg, BinReloc *reloc, guint8 **out_data, gsize *out_vaddr, gsize *out_start_val, gsize *out_end_val)
+{
+ guint8 *data;
+ gssize end_val, start_val;
+ gsize vaddr;
+
+ end_val = get_label_addr (acfg, reloc->val1);
+ if (reloc->val2) {
+ start_val = get_label_addr (acfg, reloc->val2);
+ } else if (reloc->val2_section) {
+ start_val = reloc->val2_offset;
+ if (reloc->val2_section->parent)
+ start_val += reloc->val2_section->parent->virt_offset + reloc->val2_section->cur_offset;
+ else
+ start_val += reloc->val2_section->virt_offset;
+ } else {
+ start_val = 0;
+ }
+ end_val = end_val - start_val + reloc->offset;
+ if (reloc->section->parent) {
+ data = reloc->section->parent->data;
+ data += reloc->section->cur_offset;
+ data += reloc->section_offset;
+ vaddr = reloc->section->parent->virt_offset;
+ vaddr += reloc->section->cur_offset;
+ vaddr += reloc->section_offset;
+ } else {
+ data = reloc->section->data;
+ data += reloc->section_offset;
+ vaddr = reloc->section->virt_offset;
+ vaddr += reloc->section_offset;
+ }
+
+ *out_start_val = start_val;
+ *out_end_val = end_val;
+ *out_data = data;
+ *out_vaddr = vaddr;
+}
+
+static void
+resolve_relocations (MonoImageWriter *acfg)
+{
+ BinReloc *reloc;
+ guint8 *data;
+ gsize end_val, start_val;
+ gsize vaddr;
+
+ /* Only resolve static relocations */
+ for (reloc = acfg->relocations; reloc; reloc = reloc->next) {
+ resolve_reloc (acfg, reloc, &data, &vaddr, &start_val, &end_val);
+ data [0] = end_val;
+ data [1] = end_val >> 8;
+ data [2] = end_val >> 16;
+ data [3] = end_val >> 24;
+ }
+}
+
+static int
+bin_writer_emit_writeout (MonoImageWriter *acfg)
+{
+ BinSection *s;
+ int sindex, file_size, nsections, file_offset, vmaddr;
+ struct mach_header header;
+ struct segment_command segment;
+ struct section *sections;
+
+ /* Assing vm addresses to sections */
+ nsections = 0;
+ vmaddr = 0;
+ for (s = acfg->sections; s; s = s->next) {
+ s->virt_offset = vmaddr;
+ vmaddr += s->cur_offset;
+ nsections ++;
+ }
+
+ resolve_relocations (acfg);
+
+ file_offset = 0;
+
+ memset (&header, 0, sizeof (header));
+ header.magic = MH_MAGIC;
+ header.cputype = CPU_TYPE_X86;
+ header.cpusubtype = CPU_SUBTYPE_X86_ALL;
+ header.filetype = MH_OBJECT;
+ header.ncmds = 0;
+ header.sizeofcmds = 0;
+ header.flags = 0;
+
+ file_offset += sizeof (header);
+
+ memset (&segment, 0, sizeof (segment));
+ segment.cmd = LC_SEGMENT;
+ segment.cmdsize = sizeof (segment);
+ segment.maxprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
+ segment.initprot = VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE;
+
+ file_offset += sizeof (segment);
+ file_offset += nsections * sizeof (struct section);
+
+ sections = g_new0 (struct section, nsections);
+ sindex = 0;
+ for (s = acfg->sections; s; s = s->next) {
+ s->file_offset = file_offset;
+
+ /* .debug_line -> __debug_line */
+ sprintf (sections [sindex].sectname, "__%s", s->name + 1);
+ sprintf (sections [sindex].segname, "%s", "__DWARF");
+ sections [sindex].addr = s->virt_offset;
+ sections [sindex].size = s->cur_offset;
+ sections [sindex].offset = s->file_offset;
+
+ file_offset += s->cur_offset;
+
+ segment.nsects ++;
+ segment.cmdsize += sizeof (struct section);
+
+ sindex ++;
+ }
+
+ header.ncmds ++;
+ header.sizeofcmds += segment.cmdsize;
+
+ /* Emit data */
+ file_size = file_offset;
+
+ if (!acfg->fp) {
+ acfg->out_buf_size = file_size;
+ acfg->out_buf = g_malloc (acfg->out_buf_size);
+ }
+
+ bin_writer_fwrite (acfg, &header, sizeof (header), 1);
+ bin_writer_fwrite (acfg, &segment, sizeof (segment), 1);
+ bin_writer_fwrite (acfg, sections, sizeof (struct section), nsections);
+ for (s = acfg->sections; s; s = s->next) {
+ if (!acfg->fp)
+ g_assert (acfg->out_buf_pos == s->file_offset);
+ bin_writer_fwrite (acfg, s->data, s->cur_offset, 1);
+ }
+
+ if (acfg->fp)
+ fclose (acfg->fp);
+
+ return 0;
+}
+
+#endif
+
#ifdef USE_ELF_WRITER
enum {
#endif /* USE_ELF_RELA */
-static void
-bin_writer_fwrite (MonoImageWriter *acfg, void *val, size_t size, size_t nmemb)
-{
- if (acfg->fp)
- fwrite (val, size, nmemb, acfg->fp);
- else {
- g_assert (acfg->out_buf_pos + (size * nmemb) <= acfg->out_buf_size);
- memcpy (acfg->out_buf + acfg->out_buf_pos, val, size * nmemb);
- acfg->out_buf_pos += (size * nmemb);
- }
-}
-
-static void
-bin_writer_fseek (MonoImageWriter *acfg, int offset)
-{
- if (acfg->fp)
- fseek (acfg->fp, offset, SEEK_SET);
- else
- acfg->out_buf_pos = offset;
-}
-
static int normal_sections [] = { SECT_DATA, SECT_DEBUG_FRAME, SECT_DEBUG_INFO, SECT_DEBUG_ABBREV, SECT_DEBUG_LINE, SECT_DEBUG_LOC };
static int
(dest)->type = STACK_MP; \
(dest)->klass = (var)->klass; \
(dest)->dreg = alloc_dreg ((cfg), STACK_MP); \
+ (cfg)->has_indirection = TRUE; \
if (G_UNLIKELY (cfg->gsharedvt) && mini_is_gsharedvt_variable_type ((cfg), (var)->inst_vtype)) { handle_gsharedvt_ldaddr ((cfg)); } \
if (SIZEOF_REGISTER == 4 && DECOMPOSE_INTO_REGPAIR ((var)->type)) { MonoInst *var1 = get_vreg_to_inst (cfg, (var)->dreg + 1); MonoInst *var2 = get_vreg_to_inst (cfg, (var)->dreg + 2); g_assert (var1); g_assert (var2); var1->flags |= MONO_INST_INDIRECT; var2->flags |= MONO_INST_INDIRECT; } \
} while (0)
/* Loads/Stores which can fault are handled correctly by the LLVM mono branch */
#define MONO_EMIT_NEW_IMPLICIT_EXCEPTION_LOAD_STORE(cfg) do { \
- if (COMPILE_LLVM (cfg) && !IS_LLVM_MONO_BRANCH) \
- MONO_EMIT_NEW_IMPLICIT_EXCEPTION ((cfg)); \
} while (0)
/* Emit an explicit null check which doesn't depend on SIGSEGV signal handling */
int __ins_flags = ins_flags; \
if (__ins_flags & MONO_INST_FAULT) { \
MONO_EMIT_NULL_CHECK ((cfg), (base)); \
- if (cfg->explicit_null_checks) \
- __ins_flags &= ~MONO_INST_FAULT; \
} \
NEW_LOAD_MEMBASE ((cfg), (dest), (op), (dr), (base), (offset)); \
(dest)->flags = (__ins_flags); \
int __ins_flags = ins_flags; \
if (__ins_flags & MONO_INST_FAULT) { \
MONO_EMIT_NULL_CHECK ((cfg), (base)); \
- if (cfg->explicit_null_checks) \
- __ins_flags &= ~MONO_INST_FAULT; \
} \
NEW_LOAD_MEMBASE ((cfg), (inst), (op), (dr), (base), (offset)); \
inst->flags = (__ins_flags); \
#define MONO_EMIT_NEW_LOAD_MEMBASE_FAULT(cfg,dr,base,offset) MONO_EMIT_NEW_LOAD_MEMBASE_OP_FAULT ((cfg), (OP_LOAD_MEMBASE), (dr), (base), (offset))
+#define NEW_LOAD_MEMBASE_INVARIANT(cfg,dest,op,dr,base,offset) NEW_LOAD_MEMBASE_FLAGS ((cfg), (dest), (op), (dr), (base), (offset), MONO_INST_INVARIANT_LOAD)
+
+#define MONO_EMIT_NEW_LOAD_MEMBASE_OP_INVARIANT(cfg,op,dr,base,offset) MONO_EMIT_NEW_LOAD_MEMBASE_OP_FLAGS ((cfg), (op), (dr), (base), (offset), MONO_INST_INVARIANT_LOAD)
+
+#define MONO_EMIT_NEW_LOAD_MEMBASE_INVARIANT(cfg,dr,base,offset) MONO_EMIT_NEW_LOAD_MEMBASE_OP_INVARIANT ((cfg), (OP_LOAD_MEMBASE), (dr), (base), (offset))
+
/*Object Model related macros*/
/* Default bounds check implementation for most architectures + llvm */
if (fault) \
MONO_EMIT_NEW_LOAD_MEMBASE_OP_FAULT (cfg, OP_LOADI4_MEMBASE, _length_reg, array_reg, offset); \
else \
- MONO_EMIT_NEW_LOAD_MEMBASE_OP_FLAGS (cfg, OP_LOADI4_MEMBASE, _length_reg, array_reg, offset, MONO_INST_CONSTANT_LOAD); \
+ MONO_EMIT_NEW_LOAD_MEMBASE_OP_FLAGS (cfg, OP_LOADI4_MEMBASE, _length_reg, array_reg, offset, MONO_INST_INVARIANT_LOAD); \
MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, _length_reg, index_reg); \
MONO_EMIT_NEW_COND_EXC (cfg, LE_UN, "IndexOutOfRangeException"); \
} while (0)
MonoMethodVar *vars = cfg->vars;
guint32 abs_pos = (bb->dfn << 16);
- for (inst_num = 0, ins = bb->code; ins; ins = ins->next, inst_num += 2) {
+ /* Start inst_num from > 0, so last_use.abs_pos is only 0 for dead variables */
+ for (inst_num = 2, ins = bb->code; ins; ins = ins->next, inst_num += 2) {
const char *spec = INS_INFO (ins->opcode);
int num_sregs, i;
int sregs [MONO_MAX_SRC_REGS];
+++ /dev/null
-.text
-.globl _MONO_DEBUGGER__debugger_info
-.globl _MONO_DEBUGGER__notification_function
-_MONO_DEBUGGER__notification_function:
- int3
- ret
-.section .mdb_debug_info, "aw"
-.globl _MONO_DEBUGGER__debugger_info_ptr
-.globl _MONO_DEBUGGER__using_debugger
-_MONO_DEBUGGER__debugger_info_ptr:
- .long _MONO_DEBUGGER__debugger_info
-_MONO_DEBUGGER__using_debugger:
- .long 0
- .long 0
+++ /dev/null
- .text
-.global MONO_DEBUGGER__debugger_info
-.global MONO_DEBUGGER__notification_function
-MONO_DEBUGGER__notification_function:
- int3
- ret
-.section .mdb_debug_info, "aw", @progbits
-.global MONO_DEBUGGER__debugger_info_ptr
-.global MONO_DEBUGGER__using_debugger
-MONO_DEBUGGER__debugger_info_ptr:
- .long MONO_DEBUGGER__debugger_info
-MONO_DEBUGGER__using_debugger:
- .quad 0
+++ /dev/null
-.text
-.global MONO_DEBUGGER__debugger_info
-.global MONO_DEBUGGER__notification_function
-MONO_DEBUGGER__notification_function:
- int3
- ret
-.section .mdb_debug_info, "aw", @progbits
-.global MONO_DEBUGGER__debugger_info_ptr
-.global MONO_DEBUGGER__using_debugger
-MONO_DEBUGGER__debugger_info_ptr:
- .quad MONO_DEBUGGER__debugger_info
-MONO_DEBUGGER__using_debugger:
- .quad 0
-.section .note.GNU-stack, "", @progbits
-.previous
if (type->byref)
return OP_MOVE;
+ type = mini_type_get_underlying_type (NULL, type);
handle_enum:
switch (type->type) {
case MONO_TYPE_I1:
var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
/* prevent it from being register allocated */
- var->flags |= MONO_INST_INDIRECT;
+ var->flags |= MONO_INST_VOLATILE;
g_hash_table_insert (cfg->spvars, GINT_TO_POINTER (region), var);
}
var = mono_compile_create_var (cfg, &mono_defaults.object_class->byval_arg, OP_LOCAL);
/* prevent it from being register allocated */
- var->flags |= MONO_INST_INDIRECT;
+ var->flags |= MONO_INST_VOLATILE;
g_hash_table_insert (cfg->exvars, GINT_TO_POINTER (offset), var);
{
MonoClass *klass;
+ type = mini_type_get_underlying_type (NULL, type);
inst->klass = klass = mono_class_from_mono_type (type);
if (type->byref) {
inst->type = STACK_MP;
if (!cfg->rgctx_var) {
cfg->rgctx_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
/* force the var to be stack allocated */
- cfg->rgctx_var->flags |= MONO_INST_INDIRECT;
+ cfg->rgctx_var->flags |= MONO_INST_VOLATILE;
}
return cfg->rgctx_var;
}
}
+static void
+emit_tls_set (MonoCompile *cfg, int sreg1, int tls_key)
+{
+ MonoInst *ins, *c;
+
+ if (cfg->compile_aot) {
+ EMIT_NEW_TLS_OFFSETCONST (cfg, c, tls_key);
+ MONO_INST_NEW (cfg, ins, OP_TLS_SET_REG);
+ ins->sreg1 = sreg1;
+ ins->sreg2 = c->dreg;
+ MONO_ADD_INS (cfg->cbb, ins);
+ } else {
+ MONO_INST_NEW (cfg, ins, OP_TLS_SET);
+ ins->sreg1 = sreg1;
+ ins->inst_offset = mini_get_tls_offset (tls_key);
+ MONO_ADD_INS (cfg->cbb, ins);
+ }
+}
+
+/*
+ * emit_push_lmf:
+ *
+ * Emit IR to push the current LMF onto the LMF stack.
+ */
+static void
+emit_push_lmf (MonoCompile *cfg)
+{
+ /*
+ * Emit IR to push the LMF:
+ * lmf_addr = <lmf_addr from tls>
+ * lmf->lmf_addr = lmf_addr
+ * lmf->prev_lmf = *lmf_addr
+ * *lmf_addr = lmf
+ */
+ int lmf_reg, prev_lmf_reg;
+ MonoInst *ins, *lmf_ins;
+
+ if (!cfg->lmf_ir)
+ return;
+
+ if (cfg->lmf_ir_mono_lmf && mini_tls_get_supported (cfg, TLS_KEY_LMF)) {
+ /* Load current lmf */
+ lmf_ins = mono_get_lmf_intrinsic (cfg);
+ g_assert (lmf_ins);
+ MONO_ADD_INS (cfg->cbb, lmf_ins);
+ EMIT_NEW_VARLOADA (cfg, ins, cfg->lmf_var, NULL);
+ lmf_reg = ins->dreg;
+ /* Save previous_lmf */
+ EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_reg, G_STRUCT_OFFSET (MonoLMF, previous_lmf), lmf_ins->dreg);
+ /* Set new LMF */
+ emit_tls_set (cfg, lmf_reg, TLS_KEY_LMF);
+ } else {
+ /*
+ * Store lmf_addr in a variable, so it can be allocated to a global register.
+ */
+ if (!cfg->lmf_addr_var)
+ cfg->lmf_addr_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+
+ lmf_ins = mono_get_lmf_addr_intrinsic (cfg);
+ if (lmf_ins)
+ MONO_ADD_INS (cfg->cbb, lmf_ins);
+ else
+ lmf_ins = mono_emit_jit_icall (cfg, mono_get_lmf_addr, NULL);
+ lmf_ins->dreg = cfg->lmf_addr_var->dreg;
+
+ EMIT_NEW_VARLOADA (cfg, ins, cfg->lmf_var, NULL);
+ lmf_reg = ins->dreg;
+
+ prev_lmf_reg = alloc_preg (cfg);
+ /* Save previous_lmf */
+ EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, prev_lmf_reg, cfg->lmf_addr_var->dreg, 0);
+ EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_reg, G_STRUCT_OFFSET (MonoLMF, previous_lmf), prev_lmf_reg);
+ /* Set new lmf */
+ EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, cfg->lmf_addr_var->dreg, 0, lmf_reg);
+ }
+}
+
+/*
+ * emit_pop_lmf:
+ *
+ * Emit IR to pop the current LMF from the LMF stack.
+ */
+static void
+emit_pop_lmf (MonoCompile *cfg)
+{
+ int lmf_reg, lmf_addr_reg, prev_lmf_reg;
+ MonoInst *ins;
+
+ if (!cfg->lmf_ir)
+ return;
+
+ EMIT_NEW_VARLOADA (cfg, ins, cfg->lmf_var, NULL);
+ lmf_reg = ins->dreg;
+
+ if (cfg->lmf_ir_mono_lmf && mini_tls_get_supported (cfg, TLS_KEY_LMF)) {
+ /* Load previous_lmf */
+ prev_lmf_reg = alloc_preg (cfg);
+ EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, prev_lmf_reg, lmf_reg, G_STRUCT_OFFSET (MonoLMF, previous_lmf));
+ /* Set new LMF */
+ emit_tls_set (cfg, prev_lmf_reg, TLS_KEY_LMF);
+ } else {
+ /*
+ * Emit IR to pop the LMF:
+ * *(lmf->lmf_addr) = lmf->prev_lmf
+ */
+ /* This could be called before emit_push_lmf () */
+ if (!cfg->lmf_addr_var)
+ cfg->lmf_addr_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+ lmf_addr_reg = cfg->lmf_addr_var->dreg;
+
+ prev_lmf_reg = alloc_preg (cfg);
+ EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, prev_lmf_reg, lmf_reg, G_STRUCT_OFFSET (MonoLMF, previous_lmf));
+ EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_addr_reg, 0, prev_lmf_reg);
+ }
+}
+
static int
ret_type_to_call_opcode (MonoType *type, int calli, int virt, MonoGenericSharingContext *gsctx)
{
if (type->byref)
- return calli? OP_CALL_REG: virt? OP_CALLVIRT: OP_CALL;
+ return calli? OP_CALL_REG: virt? OP_CALL_MEMBASE: OP_CALL;
handle_enum:
type = mini_get_basic_type_from_generic (gsctx, type);
switch (type->type) {
case MONO_TYPE_VOID:
- return calli? OP_VOIDCALL_REG: virt? OP_VOIDCALLVIRT: OP_VOIDCALL;
+ return calli? OP_VOIDCALL_REG: virt? OP_VOIDCALL_MEMBASE: OP_VOIDCALL;
case MONO_TYPE_I1:
case MONO_TYPE_U1:
case MONO_TYPE_BOOLEAN:
case MONO_TYPE_CHAR:
case MONO_TYPE_I4:
case MONO_TYPE_U4:
- return calli? OP_CALL_REG: virt? OP_CALLVIRT: OP_CALL;
+ return calli? OP_CALL_REG: virt? OP_CALL_MEMBASE: OP_CALL;
case MONO_TYPE_I:
case MONO_TYPE_U:
case MONO_TYPE_PTR:
case MONO_TYPE_FNPTR:
- return calli? OP_CALL_REG: virt? OP_CALLVIRT: OP_CALL;
+ return calli? OP_CALL_REG: virt? OP_CALL_MEMBASE: OP_CALL;
case MONO_TYPE_CLASS:
case MONO_TYPE_STRING:
case MONO_TYPE_OBJECT:
case MONO_TYPE_SZARRAY:
case MONO_TYPE_ARRAY:
- return calli? OP_CALL_REG: virt? OP_CALLVIRT: OP_CALL;
+ return calli? OP_CALL_REG: virt? OP_CALL_MEMBASE: OP_CALL;
case MONO_TYPE_I8:
case MONO_TYPE_U8:
- return calli? OP_LCALL_REG: virt? OP_LCALLVIRT: OP_LCALL;
+ return calli? OP_LCALL_REG: virt? OP_LCALL_MEMBASE: OP_LCALL;
case MONO_TYPE_R4:
case MONO_TYPE_R8:
- return calli? OP_FCALL_REG: virt? OP_FCALLVIRT: OP_FCALL;
+ return calli? OP_FCALL_REG: virt? OP_FCALL_MEMBASE: OP_FCALL;
case MONO_TYPE_VALUETYPE:
if (type->data.klass->enumtype) {
type = mono_class_enum_basetype (type->data.klass);
goto handle_enum;
} else
- return calli? OP_VCALL_REG: virt? OP_VCALLVIRT: OP_VCALL;
+ return calli? OP_VCALL_REG: virt? OP_VCALL_MEMBASE: OP_VCALL;
case MONO_TYPE_TYPEDBYREF:
- return calli? OP_VCALL_REG: virt? OP_VCALLVIRT: OP_VCALL;
+ return calli? OP_VCALL_REG: virt? OP_VCALL_MEMBASE: OP_VCALL;
case MONO_TYPE_GENERICINST:
type = &type->data.generic_class->container_class->byval_arg;
goto handle_enum;
case MONO_TYPE_VAR:
case MONO_TYPE_MVAR:
/* gsharedvt */
- return calli? OP_VCALL_REG: virt? OP_VCALLVIRT: OP_VCALL;
+ return calli? OP_VCALL_REG: virt? OP_VCALL_MEMBASE: OP_VCALL;
default:
g_error ("unknown type 0x%02x in ret_type_to_call_opcode", type->type);
}
MonoType *simple_type;
MonoClass *klass;
+ target = mini_type_get_underlying_type (NULL, target);
if (target->byref) {
/* FIXME: check that the pointed to types match */
if (arg->type == STACK_MP)
callvirt_to_call (int opcode)
{
switch (opcode) {
- case OP_CALLVIRT:
+ case OP_CALL_MEMBASE:
return OP_CALL;
- case OP_VOIDCALLVIRT:
+ case OP_VOIDCALL_MEMBASE:
return OP_VOIDCALL;
- case OP_FCALLVIRT:
+ case OP_FCALL_MEMBASE:
return OP_FCALL;
- case OP_VCALLVIRT:
+ case OP_VCALL_MEMBASE:
return OP_VCALL;
- case OP_LCALLVIRT:
+ case OP_LCALL_MEMBASE:
return OP_LCALL;
default:
g_assert_not_reached ();
return -1;
}
-static int
-callvirt_to_call_membase (int opcode)
-{
- switch (opcode) {
- case OP_CALLVIRT:
- return OP_CALL_MEMBASE;
- case OP_VOIDCALLVIRT:
- return OP_VOIDCALL_MEMBASE;
- case OP_FCALLVIRT:
- return OP_FCALL_MEMBASE;
- case OP_LCALLVIRT:
- return OP_LCALL_MEMBASE;
- case OP_VCALLVIRT:
- return OP_VCALL_MEMBASE;
- default:
- g_assert_not_reached ();
- }
-
- return -1;
-}
-
#ifdef MONO_ARCH_HAVE_IMT
/* Either METHOD or IMT_ARG needs to be set */
static void
mono_emit_call_args (MonoCompile *cfg, MonoMethodSignature *sig,
MonoInst **args, int calli, int virtual, int tail, int rgctx, int unbox_trampoline)
{
+ MonoType *sig_ret;
MonoCallInst *call;
#ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
int i;
call->args = args;
call->signature = sig;
call->rgctx_reg = rgctx;
+ sig_ret = mini_type_get_underlying_type (NULL, sig->ret);
- type_to_eval_stack_type ((cfg), sig->ret, &call->inst);
+ type_to_eval_stack_type ((cfg), sig_ret, &call->inst);
if (tail) {
- if (mini_type_is_vtype (cfg, sig->ret)) {
+ if (mini_type_is_vtype (cfg, sig_ret)) {
call->vret_var = cfg->vret_addr;
//g_assert_not_reached ();
}
- } else if (mini_type_is_vtype (cfg, sig->ret)) {
- MonoInst *temp = mono_compile_create_var (cfg, sig->ret, OP_LOCAL);
+ } else if (mini_type_is_vtype (cfg, sig_ret)) {
+ MonoInst *temp = mono_compile_create_var (cfg, sig_ret, OP_LOCAL);
MonoInst *loada;
temp->backend.is_pinvoke = sig->pinvoke;
call->inst.dreg = temp->dreg;
call->vret_var = loada;
- } else if (!MONO_TYPE_IS_VOID (sig->ret))
+ } else if (!MONO_TYPE_IS_VOID (sig_ret))
call->inst.dreg = alloc_dreg (cfg, call->inst.type);
#ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
MONO_EMIT_NULL_CHECK (cfg, this_reg);
/* Make a call to delegate->invoke_impl */
- call->inst.opcode = callvirt_to_call_membase (call->inst.opcode);
call->inst.inst_basereg = this_reg;
call->inst.inst_offset = G_STRUCT_OFFSET (MonoDelegate, invoke_impl);
MONO_ADD_INS (cfg->cbb, (MonoInst*)call);
call->inst.opcode = callvirt_to_call (call->inst.opcode);
} else {
- call->inst.opcode = callvirt_to_call_membase (call->inst.opcode);
-
vtable_reg = alloc_preg (cfg);
MONO_EMIT_NEW_LOAD_MEMBASE_FAULT (cfg, vtable_reg, this_reg, G_STRUCT_OFFSET (MonoObject, vtable));
if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
has_card_table_wb = TRUE;
#endif
- if (has_card_table_wb && !cfg->compile_aot && card_table && nursery_shift_bits > 0) {
+ if (has_card_table_wb && !cfg->compile_aot && card_table && nursery_shift_bits > 0 && !COMPILE_LLVM (cfg)) {
MonoInst *wbarrier;
MONO_INST_NEW (cfg, wbarrier, OP_CARD_TABLE_WBARRIER);
* in mono_delegate_trampoline (), we allocate a per-domain memory slot to
* store it, and we fill it after the method has been compiled.
*/
- if (!cfg->compile_aot && !method->dynamic && !(cfg->opt & MONO_OPT_SHARED)) {
+ if (!method->dynamic && !(cfg->opt & MONO_OPT_SHARED)) {
MonoInst *code_slot_ins;
if (context_used) {
}
mono_domain_unlock (domain);
- EMIT_NEW_PCONST (cfg, code_slot_ins, code_slot);
+ if (cfg->compile_aot)
+ EMIT_NEW_AOTCONST (cfg, code_slot_ins, MONO_PATCH_INFO_METHOD_CODE_SLOT, method);
+ else
+ EMIT_NEW_PCONST (cfg, code_slot_ins, code_slot);
}
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, G_STRUCT_OFFSET (MonoDelegate, method_code), code_slot_ins->dreg);
}
* inside the inlined code
*/
if (!(cfg->opt & MONO_OPT_SHARED)) {
- if (method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) {
+ /* The AggressiveInlining hint is a good excuse to force that cctor to run. */
+ if (method->iflags & METHOD_IMPL_ATTRIBUTE_AGGRESSIVE_INLINING) {
+ vtable = mono_class_vtable (cfg->domain, method->klass);
+ if (!vtable)
+ return FALSE;
+ mono_runtime_class_init (vtable);
+ } else if (method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) {
if (cfg->run_cctors && method->klass->has_cctor) {
/*FIXME it would easier and lazier to just use mono_class_try_get_vtable */
if (!method->klass->runtime_info)
case MONO_BREAK_POLICY_NEVER:
return FALSE;
case MONO_BREAK_POLICY_ON_DBG:
- return mono_debug_using_mono_debugger ();
+ g_warning ("mdb no longer supported");
+ return FALSE;
default:
g_warning ("Incorrect value returned from break policy callback");
return FALSE;
#endif
static void
-emit_init_rvar (MonoCompile *cfg, MonoInst *rvar, MonoType *rtype)
+emit_init_rvar (MonoCompile *cfg, int dreg, MonoType *rtype)
{
static double r8_0 = 0.0;
MonoInst *ins;
-
- switch (rvar->type) {
- case STACK_I4:
- MONO_EMIT_NEW_ICONST (cfg, rvar->dreg, 0);
- break;
- case STACK_I8:
- MONO_EMIT_NEW_I8CONST (cfg, rvar->dreg, 0);
- break;
- case STACK_PTR:
- case STACK_MP:
- case STACK_OBJ:
- MONO_EMIT_NEW_PCONST (cfg, rvar->dreg, 0);
- break;
- case STACK_R8:
+ int t;
+
+ rtype = mini_type_get_underlying_type (NULL, rtype);
+ t = rtype->type;
+
+ if (rtype->byref) {
+ MONO_EMIT_NEW_PCONST (cfg, dreg, NULL);
+ } else if (t >= MONO_TYPE_BOOLEAN && t <= MONO_TYPE_U4) {
+ MONO_EMIT_NEW_ICONST (cfg, dreg, 0);
+ } else if (t == MONO_TYPE_I8 || t == MONO_TYPE_U8) {
+ MONO_EMIT_NEW_I8CONST (cfg, dreg, 0);
+ } else if (t == MONO_TYPE_R4 || t == MONO_TYPE_R8) {
MONO_INST_NEW (cfg, ins, OP_R8CONST);
ins->type = STACK_R8;
ins->inst_p0 = (void*)&r8_0;
- ins->dreg = rvar->dreg;
+ ins->dreg = dreg;
MONO_ADD_INS (cfg->cbb, ins);
- break;
- case STACK_VTYPE:
- MONO_EMIT_NEW_VZERO (cfg, rvar->dreg, mono_class_from_mono_type (rtype));
- break;
- default:
- g_assert_not_reached ();
+ } else if ((t == MONO_TYPE_VALUETYPE) || (t == MONO_TYPE_TYPEDBYREF) ||
+ ((t == MONO_TYPE_GENERICINST) && mono_type_generic_inst_is_valuetype (rtype))) {
+ MONO_EMIT_NEW_VZERO (cfg, dreg, mono_class_from_mono_type (rtype));
+ } else if (((t == MONO_TYPE_VAR) || (t == MONO_TYPE_MVAR)) && mini_type_var_is_vt (cfg, rtype)) {
+ MONO_EMIT_NEW_VZERO (cfg, dreg, mono_class_from_mono_type (rtype));
+ } else {
+ MONO_EMIT_NEW_PCONST (cfg, dreg, NULL);
+ }
+}
+
+static void
+emit_init_local (MonoCompile *cfg, int local, MonoType *type)
+{
+ MonoInst *var = cfg->locals [local];
+ if (COMPILE_SOFT_FLOAT (cfg)) {
+ MonoInst *store;
+ int reg = alloc_dreg (cfg, var->type);
+ emit_init_rvar (cfg, reg, type);
+ EMIT_NEW_LOCSTORE (cfg, store, local, cfg->cbb->last_ins);
+ } else {
+ emit_init_rvar (cfg, var->dreg, type);
}
}
if (bb->last_ins && bb->last_ins->opcode == OP_NOT_REACHED) {
cfg->cbb = bb;
- emit_init_rvar (cfg, rvar, fsig->ret);
+ emit_init_rvar (cfg, rvar->dreg, fsig->ret);
}
}
}
* set, so set it to a dummy value.
*/
if (!ret_var_set)
- emit_init_rvar (cfg, rvar, fsig->ret);
+ emit_init_rvar (cfg, rvar->dreg, fsig->ret);
EMIT_NEW_TEMPLOAD (cfg, ins, rvar->inst_c0);
*sp++ = ins;
case MONO_TYPE_R4:
size = 4; break;
case MONO_TYPE_R8:
-#ifdef ARM_FPU_FPA
- return NULL; /* stupid ARM FP swapped format */
-#endif
case MONO_TYPE_I8:
case MONO_TYPE_U8:
size = 8; break;
{
int local, token;
MonoClass *klass;
+ MonoType *type;
if (size == 1) {
local = ip [1];
}
if (ip + 6 < end && (ip [0] == CEE_PREFIX1) && (ip [1] == CEE_INITOBJ) && ip_in_bb (cfg, cfg->cbb, ip + 1)) {
- gboolean skip = FALSE;
-
/* From the INITOBJ case */
token = read32 (ip + 2);
klass = mini_get_class (cfg->current_method, token, cfg->generic_context);
CHECK_TYPELOAD (klass);
- if (mini_type_is_reference (cfg, &klass->byval_arg)) {
- MONO_EMIT_NEW_PCONST (cfg, cfg->locals [local]->dreg, NULL);
- } else if (MONO_TYPE_ISSTRUCT (&klass->byval_arg)) {
- MONO_EMIT_NEW_VZERO (cfg, cfg->locals [local]->dreg, klass);
- } else {
- skip = TRUE;
- }
-
- if (!skip)
- return ip + 6;
+ type = mini_type_get_underlying_type (NULL, &klass->byval_arg);
+ emit_init_local (cfg, local, type);
+ return ip + 6;
}
load_error:
return NULL;
}
static gboolean
-is_supported_tail_call (MonoCompile *cfg, MonoMethod *method, MonoMethod *cmethod, MonoMethodSignature *fsig)
+is_supported_tail_call (MonoCompile *cfg, MonoMethod *method, MonoMethod *cmethod, MonoMethodSignature *fsig, int call_opcode)
{
gboolean supported_tail_call;
int i;
-#ifdef MONO_ARCH_USE_OP_TAIL_CALL
- supported_tail_call = MONO_ARCH_USE_OP_TAIL_CALL (mono_method_signature (method), mono_method_signature (cmethod));
+#ifdef MONO_ARCH_HAVE_OP_TAIL_CALL
+ supported_tail_call = mono_arch_tail_call_supported (mono_method_signature (method), mono_method_signature (cmethod));
#else
supported_tail_call = mono_metadata_signature_equal (mono_method_signature (method), mono_method_signature (cmethod)) && !MONO_TYPE_ISSTRUCT (mono_method_signature (cmethod)->ret);
#endif
supported_tail_call = FALSE;
if (cmethod->wrapper_type && cmethod->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD)
supported_tail_call = FALSE;
+ if (call_opcode != CEE_CALL)
+ supported_tail_call = FALSE;
/* Debugging support */
#if 0
MonoClass *klass;
MonoClass *constrained_call = NULL;
unsigned char *ip, *end, *target, *err_pos;
- static double r8_0 = 0.0;
MonoMethodSignature *sig;
MonoGenericContext *generic_context = NULL;
MonoGenericContainer *generic_container = NULL;
dont_verify_stloc = TRUE;
}
- if (mono_debug_using_mono_debugger ())
- cfg->keep_cil_nops = TRUE;
-
if (sig->is_inflated)
generic_context = mono_method_get_context (method);
else if (generic_container)
tblock->real_offset = clause->handler_offset;
tblock->flags |= BB_EXCEPTION_HANDLER;
- link_bblock (cfg, try_bb, tblock);
+ /*
+ * Linking the try block with the EH block hinders inlining as we won't be able to
+ * merge the bblocks from inlining and produce an artificial hole for no good reason.
+ */
+ if (COMPILE_LLVM (cfg))
+ link_bblock (cfg, try_bb, tblock);
if (*(ip + clause->handler_offset) == CEE_POP)
tblock->flags |= BB_EXCEPTION_DEAD_OBJ;
if (cfg->method == method) {
breakpoint_id = mono_debugger_method_has_breakpoint (method);
- if (breakpoint_id && (mono_debug_format != MONO_DEBUG_FORMAT_DEBUGGER)) {
+ if (breakpoint_id) {
MONO_INST_NEW (cfg, ins, OP_BREAK);
MONO_ADD_INS (bblock, ins);
}
var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
/* prevent it from being register allocated */
- //var->flags |= MONO_INST_INDIRECT;
+ //var->flags |= MONO_INST_VOLATILE;
cfg->gsharedvt_info_var = var;
ins = emit_get_rgctx_gsharedvt_method (cfg, mini_method_check_context_used (cfg, method), method, info);
/* Allocate locals */
locals_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
/* prevent it from being register allocated */
- //locals_var->flags |= MONO_INST_INDIRECT;
+ //locals_var->flags |= MONO_INST_VOLATILE;
cfg->gsharedvt_locals_var = locals_var;
dreg = alloc_ireg (cfg);
/* FIXME: Is there a better way to do this?
We need the variable live for the duration
of the whole method. */
- cfg->args [0]->flags |= MONO_INST_INDIRECT;
+ cfg->args [0]->flags |= MONO_INST_VOLATILE;
}
}
if (mono_security_cas_enabled ())
CHECK_CFG_EXCEPTION;
-#ifdef MONO_ARCH_USE_OP_TAIL_CALL
- {
+ if (ARCH_HAVE_OP_TAIL_CALL) {
MonoMethodSignature *fsig = mono_method_signature (cmethod);
int i, n;
mono_arch_emit_call (cfg, call);
MONO_ADD_INS (bblock, (MonoInst*)call);
- }
-#else
- for (i = 0; i < num_args; ++i)
- /* Prevent arguments from being optimized away */
- arg_array [i]->flags |= MONO_INST_VOLATILE;
+ } else {
+ for (i = 0; i < num_args; ++i)
+ /* Prevent arguments from being optimized away */
+ arg_array [i]->flags |= MONO_INST_VOLATILE;
- MONO_INST_NEW_CALL (cfg, call, OP_JMP);
- ins = (MonoInst*)call;
- ins->inst_p0 = cmethod;
- MONO_ADD_INS (bblock, ins);
-#endif
+ MONO_INST_NEW_CALL (cfg, call, OP_JMP);
+ ins = (MonoInst*)call;
+ ins->inst_p0 = cmethod;
+ MONO_ADD_INS (bblock, ins);
+ }
ip += 5;
start_new_bblock = 1;
/*
* Making generic calls out of gsharedvt methods.
*/
- if (cmethod && cfg->gsharedvt && mini_is_gsharedvt_signature (cfg, fsig)) {
+ if (cmethod && cfg->gsharedvt && mini_is_gsharedvt_variable_signature (fsig)) {
MonoRgctxInfoType info_type;
if (virtual) {
/* FIXME: runtime generic context pointer for jumps? */
/* FIXME: handle this for generic sharing eventually */
if (cmethod && (ins_flag & MONO_INST_TAILCALL) &&
- !vtable_arg && !cfg->generic_sharing_context && is_supported_tail_call (cfg, method, cmethod, fsig))
+ !vtable_arg && !cfg->generic_sharing_context && is_supported_tail_call (cfg, method, cmethod, fsig, call_opcode))
supported_tail_call = TRUE;
- if (supported_tail_call) {
- if (call_opcode != CEE_CALL)
- supported_tail_call = FALSE;
- }
if (supported_tail_call) {
MonoCallInst *call;
//printf ("HIT: %s -> %s\n", mono_method_full_name (cfg->method, TRUE), mono_method_full_name (cmethod, TRUE));
- if (ARCH_USE_OP_TAIL_CALL) {
+ if (ARCH_HAVE_OP_TAIL_CALL) {
/* Handle tail calls similarly to normal calls */
tail_call = TRUE;
} else {
cfg->ret_var_set = TRUE;
}
} else {
+ if (cfg->lmf_var && cfg->cbb->in_count)
+ emit_pop_lmf (cfg);
+
if (cfg->ret) {
- MonoType *ret_type = mono_method_signature (method)->ret;
+ MonoType *ret_type = mini_type_get_underlying_type (NULL, mono_method_signature (method)->ret);
if (seq_points && !sym_seq_points) {
/*
if (cmethod->klass->valuetype) {
iargs [0] = mono_compile_create_var (cfg, &cmethod->klass->byval_arg, OP_LOCAL);
- MONO_EMIT_NEW_VZERO (cfg, iargs [0]->dreg, cmethod->klass);
+ emit_init_rvar (cfg, iargs [0]->dreg, &cmethod->klass->byval_arg);
EMIT_NEW_TEMPLOADA (cfg, *sp, iargs [0]->inst_c0);
alloc = NULL;
gboolean is_special_static;
MonoType *ftype;
MonoInst *store_val = NULL;
+ MonoInst *thread_ins;
op = *ip;
is_instance = (op == CEE_LDFLD || op == CEE_LDFLDA || op == CEE_STFLD);
is_special_static = mono_class_field_is_special_static (field);
+ if (is_special_static && ((gsize)addr & 0x80000000) == 0)
+ thread_ins = mono_get_thread_intrinsic (cfg);
+ else
+ thread_ins = NULL;
+
/* Generate IR to compute the field address */
- if (is_special_static && ((gsize)addr & 0x80000000) == 0 && mono_get_thread_intrinsic (cfg) && !(cfg->opt & MONO_OPT_SHARED) && !context_used) {
+ if (is_special_static && ((gsize)addr & 0x80000000) == 0 && thread_ins && !(cfg->opt & MONO_OPT_SHARED) && !context_used) {
/*
* Fast access to TLS data
* Inline version of get_thread_static_data () in
*/
guint32 offset;
int idx, static_data_reg, array_reg, dreg;
- MonoInst *thread_ins;
GSHAREDVT_FAILURE (op);
// offset &= 0x7fffffff;
// idx = (offset >> 24) - 1;
// return ((char*) thread->static_data [idx]) + (offset & 0xffffff);
-
- thread_ins = mono_get_thread_intrinsic (cfg);
MONO_ADD_INS (cfg->cbb, thread_ins);
static_data_reg = alloc_ireg (cfg);
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, static_data_reg, thread_ins->dreg, G_STRUCT_OFFSET (MonoInternalThread, static_data));
if (!cfg->dyn_call_var) {
cfg->dyn_call_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
/* prevent it from being register allocated */
- cfg->dyn_call_var->flags |= MONO_INST_INDIRECT;
+ cfg->dyn_call_var->flags |= MONO_INST_VOLATILE;
}
/* Has to use a call inst since it local regalloc expects it */
ins->sreg2 = sp [1]->dreg;
MONO_ADD_INS (bblock, ins);
-#ifdef MONO_ARCH_DYN_CALL_PARAM_AREA
cfg->param_area = MAX (cfg->param_area, MONO_ARCH_DYN_CALL_PARAM_AREA);
-#endif
ip += 2;
inline_costs += 10 * num_calls++;
cfg->cbb = init_localsbb;
- if (! (get_domain = mono_arch_get_domain_intrinsic (cfg))) {
+ if ((get_domain = mono_get_domain_intrinsic (cfg))) {
+ MONO_ADD_INS (cfg->cbb, get_domain);
+ } else {
get_domain = mono_emit_jit_icall (cfg, mono_domain_get, NULL);
}
- else {
- get_domain->dreg = alloc_preg (cfg);
- MONO_ADD_INS (cfg->cbb, get_domain);
- }
NEW_TEMPSTORE (cfg, store, cfg->domainvar->inst_c0, get_domain);
MONO_ADD_INS (cfg->cbb, store);
}
mono_emit_load_got_addr (cfg);
if (init_locals) {
- MonoInst *store;
-
cfg->cbb = init_localsbb;
cfg->ip = NULL;
for (i = 0; i < header->num_locals; ++i) {
- MonoType *ptype = header->locals [i];
- int t = ptype->type;
- dreg = cfg->locals [i]->dreg;
-
- if (t == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype)
- t = mono_class_enum_basetype (ptype->data.klass)->type;
- if (ptype->byref) {
- MONO_EMIT_NEW_PCONST (cfg, dreg, NULL);
- } else if (t >= MONO_TYPE_BOOLEAN && t <= MONO_TYPE_U4) {
- MONO_EMIT_NEW_ICONST (cfg, cfg->locals [i]->dreg, 0);
- } else if (t == MONO_TYPE_I8 || t == MONO_TYPE_U8) {
- MONO_EMIT_NEW_I8CONST (cfg, cfg->locals [i]->dreg, 0);
- } else if (t == MONO_TYPE_R4 || t == MONO_TYPE_R8) {
- MONO_INST_NEW (cfg, ins, OP_R8CONST);
- ins->type = STACK_R8;
- ins->inst_p0 = (void*)&r8_0;
- ins->dreg = alloc_dreg (cfg, STACK_R8);
- MONO_ADD_INS (init_localsbb, ins);
- EMIT_NEW_LOCSTORE (cfg, store, i, ins);
- } else if ((t == MONO_TYPE_VALUETYPE) || (t == MONO_TYPE_TYPEDBYREF) ||
- ((t == MONO_TYPE_GENERICINST) && mono_type_generic_inst_is_valuetype (ptype))) {
- MONO_EMIT_NEW_VZERO (cfg, dreg, mono_class_from_mono_type (ptype));
- } else if (((t == MONO_TYPE_VAR) || (t == MONO_TYPE_MVAR)) && mini_type_var_is_vt (cfg, ptype)) {
- MONO_EMIT_NEW_VZERO (cfg, dreg, mono_class_from_mono_type (ptype));
- } else {
- MONO_EMIT_NEW_PCONST (cfg, dreg, NULL);
- }
+ emit_init_local (cfg, i, header->locals [i]);
}
}
}
}
+ if (cfg->lmf_var && cfg->method == method) {
+ cfg->cbb = init_localsbb;
+ emit_push_lmf (cfg);
+ }
+
if (seq_points) {
MonoBasicBlock *bb;
/* Arguments are implicitly global */
/* Putting R4 vars into registers doesn't work currently */
/* The gsharedvt vars are implicitly referenced by ldaddr opcodes, but those opcodes are only generated later */
- if ((var->opcode != OP_ARG) && (var != cfg->ret) && !(var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) && (vreg_to_bb [var->dreg] != -1) && (var->klass->byval_arg.type != MONO_TYPE_R4) && !cfg->disable_vreg_to_lvreg && var != cfg->gsharedvt_info_var && var != cfg->gsharedvt_locals_var) {
+ if ((var->opcode != OP_ARG) && (var != cfg->ret) && !(var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) && (vreg_to_bb [var->dreg] != -1) && (var->klass->byval_arg.type != MONO_TYPE_R4) && !cfg->disable_vreg_to_lvreg && var != cfg->gsharedvt_info_var && var != cfg->gsharedvt_locals_var && var != cfg->lmf_addr_var) {
/*
* Make that the variable's liveness interval doesn't contain a call, since
* that would cause the lvreg to be spilled, making the whole optimization
#include "debugger-agent.h"
#include "mini-gc.h"
-static gint lmf_tls_offset = -1;
-static gint lmf_addr_tls_offset = -1;
-static gint appdomain_tls_offset = -1;
+#ifdef HOST_WIN32
+static gint jit_tls_offset = -1;
+#endif
#ifdef MONO_XEN_OPT
static gboolean optimize_for_xen = TRUE;
case MONO_TYPE_VALUETYPE: {
guint32 tmp_gr = 0, tmp_fr = 0, tmp_stacksize = 0;
- add_valuetype (gsctx, sig, &cinfo->ret, sig->ret, TRUE, &tmp_gr, &tmp_fr, &tmp_stacksize);
+ add_valuetype (gsctx, sig, &cinfo->ret, ret_type, TRUE, &tmp_gr, &tmp_fr, &tmp_stacksize);
if (cinfo->ret.storage == ArgOnStack) {
cinfo->vtype_retaddr = TRUE;
/* The caller passes the address where the value is stored */
case MONO_TYPE_VOID:
break;
default:
- g_error ("Can't handle as return value 0x%x", sig->ret->type);
+ g_error ("Can't handle as return value 0x%x", ret_type->type);
}
}
}
gboolean
-mono_amd64_tail_call_supported (MonoMethodSignature *caller_sig, MonoMethodSignature *callee_sig)
+mono_arch_tail_call_supported (MonoMethodSignature *caller_sig, MonoMethodSignature *callee_sig)
{
CallInfo *c1, *c2;
gboolean res;
+ MonoType *callee_ret;
c1 = get_call_info (NULL, NULL, caller_sig);
c2 = get_call_info (NULL, NULL, callee_sig);
res = c1->stack_usage >= c2->stack_usage;
- if (callee_sig->ret && MONO_TYPE_ISSTRUCT (callee_sig->ret) && c2->ret.storage != ArgValuetypeInReg)
+ callee_ret = mini_type_get_underlying_type (NULL, callee_sig->ret);
+ if (callee_ret && MONO_TYPE_ISSTRUCT (callee_ret) && c2->ret.storage != ArgValuetypeInReg)
/* An address on the callee's stack is passed as the first argument */
res = FALSE;
void
mono_arch_fill_argument_info (MonoCompile *cfg)
{
+ MonoType *sig_ret;
MonoMethodSignature *sig;
MonoMethodHeader *header;
MonoInst *ins;
sig = mono_method_signature (cfg->method);
cinfo = cfg->arch.cinfo;
+ sig_ret = mini_type_get_underlying_type (NULL, sig->ret);
/*
* Contrary to mono_arch_allocate_vars (), the information should describe
* accessed during the execution of the method. The later makes no sense for the
* global register allocator, since a variable can be in more than one location.
*/
- if (sig->ret->type != MONO_TYPE_VOID) {
+ if (sig_ret->type != MONO_TYPE_VOID) {
switch (cinfo->ret.storage) {
case ArgInIReg:
case ArgInFloatSSEReg:
case ArgInDoubleSSEReg:
- if ((MONO_TYPE_ISSTRUCT (sig->ret) && !mono_class_from_mono_type (sig->ret)->enumtype) || ((sig->ret->type == MONO_TYPE_TYPEDBYREF) && cinfo->vtype_retaddr)) {
+ if ((MONO_TYPE_ISSTRUCT (sig_ret) && !mono_class_from_mono_type (sig_ret)->enumtype) || ((sig_ret->type == MONO_TYPE_TYPEDBYREF) && cinfo->vtype_retaddr)) {
cfg->vret_addr->opcode = OP_REGVAR;
cfg->vret_addr->inst_c0 = cinfo->ret.reg;
}
void
mono_arch_allocate_vars (MonoCompile *cfg)
{
+ MonoType *sig_ret;
MonoMethodSignature *sig;
MonoMethodHeader *header;
MonoInst *ins;
sig = mono_method_signature (cfg->method);
cinfo = cfg->arch.cinfo;
+ sig_ret = mini_type_get_underlying_type (NULL, sig->ret);
mono_arch_compute_omit_fp (cfg);
if (AMD64_IS_CALLEE_SAVED_REG (i) && (cfg->used_int_regs & (1 << i))) {
offset += sizeof(mgreg_t);
}
+ if (!cfg->arch.omit_fp)
+ cfg->arch.reg_save_area_offset = -offset;
}
- if (sig->ret->type != MONO_TYPE_VOID) {
+ if (sig_ret->type != MONO_TYPE_VOID) {
switch (cinfo->ret.storage) {
case ArgInIReg:
case ArgInFloatSSEReg:
case ArgInDoubleSSEReg:
- if ((MONO_TYPE_ISSTRUCT (sig->ret) && !mono_class_from_mono_type (sig->ret)->enumtype) || ((sig->ret->type == MONO_TYPE_TYPEDBYREF) && cinfo->vtype_retaddr)) {
+ if ((MONO_TYPE_ISSTRUCT (sig_ret) && !mono_class_from_mono_type (sig_ret)->enumtype) || ((sig_ret->type == MONO_TYPE_TYPEDBYREF) && cinfo->vtype_retaddr)) {
if (cfg->globalra) {
cfg->vret_addr->opcode = OP_REGVAR;
cfg->vret_addr->inst_c0 = cinfo->ret.reg;
{
MonoMethodSignature *sig;
CallInfo *cinfo;
+ MonoType *sig_ret;
sig = mono_method_signature (cfg->method);
if (cinfo->ret.storage == ArgValuetypeInReg)
cfg->ret_var_is_local = TRUE;
- if ((cinfo->ret.storage != ArgValuetypeInReg) && MONO_TYPE_ISSTRUCT (sig->ret)) {
+ sig_ret = mini_type_get_underlying_type (NULL, sig->ret);
+ if ((cinfo->ret.storage != ArgValuetypeInReg) && MONO_TYPE_ISSTRUCT (sig_ret)) {
cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
if (G_UNLIKELY (cfg->verbose_level > 1)) {
printf ("vret_addr = ");
cfg->arch.no_pushes = TRUE;
#endif
+ if (cfg->method->save_lmf)
+ cfg->create_lmf_var = TRUE;
+
+#if !defined(HOST_WIN32)
if (cfg->method->save_lmf) {
- MonoInst *lmf_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
- lmf_var->flags |= MONO_INST_VOLATILE;
- lmf_var->flags |= MONO_INST_LMF;
- cfg->arch.lmf_var = lmf_var;
+ cfg->lmf_ir = TRUE;
+ if (mono_get_lmf_tls_offset () != -1 && !optimize_for_xen)
+ cfg->lmf_ir_mono_lmf = TRUE;
}
+#endif
#ifndef MONO_AMD64_NO_PUSHES
cfg->arch_eh_jit_info = 1;
ArgInfo *ainfo;
int j;
LLVMCallInfo *linfo;
- MonoType *t;
+ MonoType *t, *sig_ret;
n = sig->param_count + sig->hasthis;
+ sig_ret = mini_type_get_underlying_type (NULL, sig->ret);
cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig);
linfo->ret.pair_storage [j] = arg_storage_to_llvm_arg_storage (cfg, cinfo->ret.pair_storage [j]);
}
- if (MONO_TYPE_ISSTRUCT (sig->ret) && cinfo->ret.storage == ArgInIReg) {
+ if (MONO_TYPE_ISSTRUCT (sig_ret) && cinfo->ret.storage == ArgInIReg) {
/* Vtype returned using a hidden argument */
linfo->ret.storage = LLVMArgVtypeRetAddr;
linfo->vret_arg_index = cinfo->vret_arg_index;
{
MonoInst *arg, *in;
MonoMethodSignature *sig;
+ MonoType *sig_ret;
int i, n, stack_size;
CallInfo *cinfo;
ArgInfo *ainfo;
cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig);
+ sig_ret = sig->ret;
+
if (COMPILE_LLVM (cfg)) {
/* We shouldn't be called in the llvm case */
cfg->disable_llvm = TRUE;
if (!sig->pinvoke && (sig->call_convention == MONO_CALL_VARARG) && (n == sig->sentinelpos))
emit_sig_cookie (cfg, call, cinfo);
- if (sig->ret && MONO_TYPE_ISSTRUCT (sig->ret)) {
+ sig_ret = mini_type_get_underlying_type (NULL, sig->ret);
+ if (sig_ret && MONO_TYPE_ISSTRUCT (sig_ret)) {
MonoInst *vtarg;
if (cinfo->ret.storage == ArgValuetypeInReg) {
}
#ifdef HOST_WIN32
- if (call->inst.opcode != OP_JMP && OP_TAILCALL != call->inst.opcode) {
+ if (call->inst.opcode != OP_TAILCALL) {
MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SUB_IMM, X86_ESP, X86_ESP, 0x20);
}
#endif
g_assert (!cfg->arch.no_pushes);
MONO_INST_NEW (cfg, load, OP_LDADDR);
+ cfg->has_indirection = TRUE;
load->inst_p0 = vtaddr;
vtaddr->flags |= MONO_INST_INDIRECT;
load->type = STACK_MP;
MonoMethodSignature *sig = dinfo->sig;
guint8 *ret = ((DynCallArgs*)buf)->ret;
mgreg_t res = ((DynCallArgs*)buf)->res;
+ MonoType *sig_ret = mono_type_get_underlying_type (sig->ret);
- switch (mono_type_get_underlying_type (sig->ret)->type) {
+ switch (sig_ret->type) {
case MONO_TYPE_VOID:
*(gpointer*)ret = NULL;
break;
*(guint64*)ret = res;
break;
case MONO_TYPE_GENERICINST:
- if (MONO_TYPE_IS_REFERENCE (sig->ret)) {
+ if (MONO_TYPE_IS_REFERENCE (sig_ret)) {
*(gpointer*)ret = GREG_TO_PTR(res);
break;
} else {
#endif
}
+int
+mono_amd64_get_tls_gs_offset (void)
+{
+#ifdef TARGET_OSX
+ return tls_gs_offset;
+#else
+ g_assert_not_reached ();
+ return -1;
+#endif
+}
+
/*
* mono_amd64_emit_tls_get:
* @code: buffer to store code to
return code;
}
+static guint8*
+emit_tls_get_reg (guint8* code, int dreg, int offset_reg)
+{
+ /* offset_reg contains a value translated by mono_arch_translate_tls_offset () */
+#ifdef TARGET_OSX
+ if (dreg != offset_reg)
+ amd64_mov_reg_reg (code, dreg, offset_reg, sizeof (mgreg_t));
+ amd64_prefix (code, X86_GS_PREFIX);
+ amd64_mov_reg_membase (code, dreg, dreg, 0, sizeof (mgreg_t));
+#elif defined(__linux__)
+ int tmpreg = -1;
+
+ if (dreg == offset_reg) {
+ /* Use a temporary reg by saving it to the redzone */
+ tmpreg = dreg == AMD64_RAX ? AMD64_RCX : AMD64_RAX;
+ amd64_mov_membase_reg (code, AMD64_RSP, -8, tmpreg, 8);
+ amd64_mov_reg_reg (code, tmpreg, offset_reg, sizeof (gpointer));
+ offset_reg = tmpreg;
+ }
+ x86_prefix (code, X86_FS_PREFIX);
+ amd64_mov_reg_mem (code, dreg, 0, 8);
+ amd64_mov_reg_memindex (code, dreg, dreg, 0, offset_reg, 0, 8);
+ if (tmpreg != -1)
+ amd64_mov_reg_membase (code, tmpreg, AMD64_RSP, -8, 8);
+#else
+ g_assert_not_reached ();
+#endif
+ return code;
+}
+
+static guint8*
+amd64_emit_tls_set (guint8 *code, int sreg, int tls_offset)
+{
+#ifdef HOST_WIN32
+ g_assert_not_reached ();
+#elif defined(__APPLE__)
+ x86_prefix (code, X86_GS_PREFIX);
+ amd64_mov_mem_reg (code, tls_gs_offset + (tls_offset * 8), sreg, 8);
+#else
+ g_assert (!optimize_for_xen);
+ x86_prefix (code, X86_FS_PREFIX);
+ amd64_mov_mem_reg (code, tls_offset, sreg, 8);
+#endif
+ return code;
+}
+
+static guint8*
+amd64_emit_tls_set_reg (guint8 *code, int sreg, int offset_reg)
+{
+ /* offset_reg contains a value translated by mono_arch_translate_tls_offset () */
+#ifdef HOST_WIN32
+ g_assert_not_reached ();
+#elif defined(__APPLE__)
+ x86_prefix (code, X86_GS_PREFIX);
+ amd64_mov_membase_reg (code, offset_reg, 0, sreg, 8);
+#else
+ x86_prefix (code, X86_FS_PREFIX);
+ amd64_mov_membase_reg (code, offset_reg, 0, sreg, 8);
+#endif
+ return code;
+}
+
+ /*
+ * mono_arch_translate_tls_offset:
+ *
+ * Translate the TLS offset OFFSET computed by MONO_THREAD_VAR_OFFSET () into a format usable by OP_TLS_GET_REG/OP_TLS_SET_REG.
+ */
+int
+mono_arch_translate_tls_offset (int offset)
+{
+#ifdef __APPLE__
+ return tls_gs_offset + (offset * 8);
+#else
+ return offset;
+#endif
+}
+
/*
* emit_setup_lmf:
*
/* These can't contain refs */
mini_gc_set_slot_type_from_fp (cfg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
+#ifdef HOST_WIN32
mini_gc_set_slot_type_from_fp (cfg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
- mini_gc_set_slot_type_from_fp (cfg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
+#endif
mini_gc_set_slot_type_from_fp (cfg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, rip), SLOT_NOREF);
mini_gc_set_slot_type_from_fp (cfg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, rsp), SLOT_NOREF);
return code;
}
+#ifdef HOST_WIN32
/*
- * emit_save_lmf:
+ * emit_push_lmf:
*
* Emit code to push an LMF structure on the LMF stack.
*/
static guint8*
-emit_save_lmf (MonoCompile *cfg, guint8 *code, gint32 lmf_offset, gboolean *args_clobbered)
+emit_push_lmf (MonoCompile *cfg, guint8 *code, gint32 lmf_offset, gboolean *args_clobbered)
{
- if ((lmf_tls_offset != -1) && !optimize_for_xen) {
- /*
- * Optimized version which uses the mono_lmf TLS variable instead of
- * indirection through the mono_lmf_addr TLS variable.
- */
- /* %rax = previous_lmf */
- x86_prefix (code, X86_FS_PREFIX);
- amd64_mov_reg_mem (code, AMD64_RAX, lmf_tls_offset, 8);
-
- /* Save previous_lmf */
- amd64_mov_membase_reg (code, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), AMD64_RAX, 8);
- /* Set new lmf */
- if (lmf_offset == 0) {
- x86_prefix (code, X86_FS_PREFIX);
- amd64_mov_mem_reg (code, lmf_tls_offset, cfg->frame_reg, 8);
- } else {
- amd64_lea_membase (code, AMD64_R11, cfg->frame_reg, lmf_offset);
- x86_prefix (code, X86_FS_PREFIX);
- amd64_mov_mem_reg (code, lmf_tls_offset, AMD64_R11, 8);
- }
+ if (jit_tls_offset != -1) {
+ code = mono_amd64_emit_tls_get (code, AMD64_RAX, jit_tls_offset);
+ amd64_alu_reg_imm (code, X86_ADD, AMD64_RAX, G_STRUCT_OFFSET (MonoJitTlsData, lmf));
} else {
- if (lmf_addr_tls_offset != -1) {
- /* Load lmf quicky using the FS register */
- code = mono_amd64_emit_tls_get (code, AMD64_RAX, lmf_addr_tls_offset);
-#ifdef HOST_WIN32
- /* The TLS key actually contains a pointer to the MonoJitTlsData structure */
- /* FIXME: Add a separate key for LMF to avoid this */
- amd64_alu_reg_imm (code, X86_ADD, AMD64_RAX, G_STRUCT_OFFSET (MonoJitTlsData, lmf));
-#endif
- }
- else {
- /*
- * The call might clobber argument registers, but they are already
- * saved to the stack/global regs.
- */
- if (args_clobbered)
- *args_clobbered = TRUE;
- code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD,
- (gpointer)"mono_get_lmf_addr", TRUE);
- }
-
- /* Save lmf_addr */
- amd64_mov_membase_reg (code, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, lmf_addr), AMD64_RAX, sizeof(gpointer));
- /* Save previous_lmf */
- amd64_mov_reg_membase (code, AMD64_R11, AMD64_RAX, 0, sizeof(gpointer));
- amd64_mov_membase_reg (code, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), AMD64_R11, sizeof(gpointer));
- /* Set new lmf */
- amd64_lea_membase (code, AMD64_R11, cfg->frame_reg, lmf_offset);
- amd64_mov_membase_reg (code, AMD64_RAX, 0, AMD64_R11, sizeof(gpointer));
+ /*
+ * The call might clobber argument registers, but they are already
+ * saved to the stack/global regs.
+ */
+ if (args_clobbered)
+ *args_clobbered = TRUE;
+ code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD,
+ (gpointer)"mono_get_lmf_addr", TRUE);
}
+ /* Save lmf_addr */
+ amd64_mov_membase_reg (code, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, lmf_addr), AMD64_RAX, sizeof(gpointer));
+ /* Save previous_lmf */
+ amd64_mov_reg_membase (code, AMD64_R11, AMD64_RAX, 0, sizeof(gpointer));
+ amd64_mov_membase_reg (code, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), AMD64_R11, sizeof(gpointer));
+ /* Set new lmf */
+ amd64_lea_membase (code, AMD64_R11, cfg->frame_reg, lmf_offset);
+ amd64_mov_membase_reg (code, AMD64_RAX, 0, AMD64_R11, sizeof(gpointer));
+
return code;
}
+#endif
+#ifdef HOST_WIN32
/*
- * emit_save_lmf:
+ * emit_pop_lmf:
*
* Emit code to pop an LMF structure from the LMF stack.
*/
static guint8*
-emit_restore_lmf (MonoCompile *cfg, guint8 *code, gint32 lmf_offset)
+emit_pop_lmf (MonoCompile *cfg, guint8 *code, gint32 lmf_offset)
{
- if ((lmf_tls_offset != -1) && !optimize_for_xen) {
- /*
- * Optimized version which uses the mono_lmf TLS variable instead of indirection
- * through the mono_lmf_addr TLS variable.
- */
- /* reg = previous_lmf */
- amd64_mov_reg_membase (code, AMD64_R11, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), sizeof(gpointer));
- x86_prefix (code, X86_FS_PREFIX);
- amd64_mov_mem_reg (code, lmf_tls_offset, AMD64_R11, 8);
- } else {
- /* Restore previous lmf */
- amd64_mov_reg_membase (code, AMD64_RCX, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), sizeof(gpointer));
- amd64_mov_reg_membase (code, AMD64_R11, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, lmf_addr), sizeof(gpointer));
- amd64_mov_membase_reg (code, AMD64_R11, 0, AMD64_RCX, sizeof(gpointer));
- }
+ /* Restore previous lmf */
+ amd64_mov_reg_membase (code, AMD64_RCX, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), sizeof(gpointer));
+ amd64_mov_reg_membase (code, AMD64_R11, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, lmf_addr), sizeof(gpointer));
+ amd64_mov_membase_reg (code, AMD64_R11, 0, AMD64_RCX, sizeof(gpointer));
return code;
}
+#endif
#define REAL_PRINT_REG(text,reg) \
mono_assert (reg >= 0); \
}
case OP_TAILCALL: {
MonoCallInst *call = (MonoCallInst*)ins;
- int pos = 0, i;
+ int i, save_area_offset;
/* FIXME: no tracing support... */
if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
g_assert (!cfg->method->save_lmf);
- if (cfg->arch.omit_fp) {
- guint32 save_offset = 0;
- /* Pop callee-saved registers */
- for (i = 0; i < AMD64_NREG; ++i)
- if (AMD64_IS_CALLEE_SAVED_REG (i) && (cfg->used_int_regs & (1 << i))) {
- amd64_mov_reg_membase (code, i, AMD64_RSP, save_offset, 8);
- save_offset += 8;
- }
- amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, cfg->arch.stack_alloc_size);
+ /* Restore callee saved registers */
+ save_area_offset = cfg->arch.reg_save_area_offset;
+ for (i = 0; i < AMD64_NREG; ++i)
+ if (AMD64_IS_CALLEE_SAVED_REG (i) && (cfg->used_int_regs & (1 << i))) {
+ amd64_mov_reg_membase (code, i, cfg->frame_reg, save_area_offset, 8);
+ save_area_offset += 8;
+ }
+ if (cfg->arch.omit_fp) {
+ if (cfg->arch.stack_alloc_size)
+ amd64_alu_reg_imm (code, X86_ADD, AMD64_RSP, cfg->arch.stack_alloc_size);
// FIXME:
if (call->stack_usage)
NOT_IMPLEMENTED;
- }
- else {
- for (i = 0; i < AMD64_NREG; ++i)
- if (AMD64_IS_CALLEE_SAVED_REG (i) && (cfg->used_int_regs & (1 << i)))
- pos -= sizeof(mgreg_t);
-
- /* Restore callee-saved registers */
- for (i = AMD64_NREG - 1; i > 0; --i) {
- if (AMD64_IS_CALLEE_SAVED_REG (i) && (cfg->used_int_regs & (1 << i))) {
- amd64_mov_reg_membase (code, i, AMD64_RBP, pos, sizeof(mgreg_t));
- pos += sizeof(mgreg_t);
- }
- }
-
+ } else {
/* Copy arguments on the stack to our argument area */
for (i = 0; i < call->stack_usage; i += sizeof(mgreg_t)) {
amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RSP, i, sizeof(mgreg_t));
amd64_mov_membase_reg (code, AMD64_RBP, 16 + i, AMD64_RAX, sizeof(mgreg_t));
}
-
- if (pos)
- amd64_lea_membase (code, AMD64_RSP, AMD64_RBP, pos);
amd64_leave (code);
}
break;
}
case OP_AMD64_SAVE_SP_TO_LMF: {
- MonoInst *lmf_var = cfg->arch.lmf_var;
- amd64_mov_membase_reg (code, cfg->frame_reg, lmf_var->inst_offset + G_STRUCT_OFFSET (MonoLMF, rsp), AMD64_RSP, 8);
+ MonoInst *lmf_var = cfg->lmf_var;
+ amd64_mov_membase_reg (code, lmf_var->inst_basereg, lmf_var->inst_offset + G_STRUCT_OFFSET (MonoLMF, rsp), AMD64_RSP, 8);
break;
}
case OP_X86_PUSH:
case OP_BR_REG:
amd64_jump_reg (code, ins->sreg1);
break;
+ case OP_ICNEQ:
+ case OP_ICGE:
+ case OP_ICLE:
+ case OP_ICGE_UN:
+ case OP_ICLE_UN:
+
case OP_CEQ:
case OP_LCEQ:
case OP_ICEQ:
amd64_sse_movss_reg_membase (code, ins->dreg, ins->inst_basereg, ins->inst_offset);
amd64_sse_cvtss2sd_reg_reg (code, ins->dreg, ins->dreg);
break;
- case OP_ICONV_TO_R4: /* FIXME: change precision */
+ case OP_ICONV_TO_R4:
+ amd64_sse_cvtsi2ss_reg_reg_size (code, ins->dreg, ins->sreg1, 4);
+ amd64_sse_cvtss2sd_reg_reg (code, ins->dreg, ins->dreg);
+ break;
case OP_ICONV_TO_R8:
amd64_sse_cvtsi2sd_reg_reg_size (code, ins->dreg, ins->sreg1, 4);
break;
- case OP_LCONV_TO_R4: /* FIXME: change precision */
+ case OP_LCONV_TO_R4:
+ amd64_sse_cvtsi2ss_reg_reg (code, ins->dreg, ins->sreg1);
+ amd64_sse_cvtss2sd_reg_reg (code, ins->dreg, ins->dreg);
+ break;
case OP_LCONV_TO_R8:
amd64_sse_cvtsi2sd_reg_reg (code, ins->dreg, ins->sreg1);
break;
case OP_FCONV_TO_R4:
- /* FIXME: nothing to do ?? */
+ amd64_sse_cvtsd2ss_reg_reg (code, ins->dreg, ins->sreg1);
+ amd64_sse_cvtss2sd_reg_reg (code, ins->dreg, ins->dreg);
break;
case OP_FCONV_TO_I1:
code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, TRUE);
*/
amd64_sse_comisd_reg_reg (code, ins->sreg2, ins->sreg1);
break;
+ case OP_FCNEQ:
case OP_FCEQ: {
/* zeroing the register at the start results in
* shorter and faster code (we can also remove the widening op)
amd64_sse_comisd_reg_reg (code, ins->sreg1, ins->sreg2);
unordered_check = code;
x86_branch8 (code, X86_CC_P, 0, FALSE);
- amd64_set_reg (code, X86_CC_EQ, ins->dreg, FALSE);
- amd64_patch (unordered_check, code);
+
+ if (ins->opcode == OP_FCEQ) {
+ amd64_set_reg (code, X86_CC_EQ, ins->dreg, FALSE);
+ amd64_patch (unordered_check, code);
+ } else {
+ guchar *jump_to_end;
+ amd64_set_reg (code, X86_CC_NE, ins->dreg, FALSE);
+ jump_to_end = code;
+ x86_jump8 (code, 0);
+ amd64_patch (unordered_check, code);
+ amd64_inc_reg (code, ins->dreg);
+ amd64_patch (jump_to_end, code);
+ }
break;
}
case OP_FCLT:
amd64_set_reg (code, X86_CC_GT, ins->dreg, FALSE);
}
break;
+ case OP_FCLE: {
+ guchar *unordered_check;
+ amd64_alu_reg_reg (code, X86_XOR, ins->dreg, ins->dreg);
+ amd64_sse_comisd_reg_reg (code, ins->sreg2, ins->sreg1);
+ unordered_check = code;
+ x86_branch8 (code, X86_CC_P, 0, FALSE);
+ amd64_set_reg (code, X86_CC_NB, ins->dreg, FALSE);
+ amd64_patch (unordered_check, code);
+ break;
+ }
case OP_FCGT:
case OP_FCGT_UN: {
/* zeroing the register at the start results in
}
break;
}
+ case OP_FCGE: {
+ guchar *unordered_check;
+ amd64_alu_reg_reg (code, X86_XOR, ins->dreg, ins->dreg);
+ amd64_sse_comisd_reg_reg (code, ins->sreg2, ins->sreg1);
+ unordered_check = code;
+ x86_branch8 (code, X86_CC_P, 0, FALSE);
+ amd64_set_reg (code, X86_CC_NA, ins->dreg, FALSE);
+ amd64_patch (unordered_check, code);
+ break;
+ }
+
case OP_FCLT_MEMBASE:
case OP_FCGT_MEMBASE:
case OP_FCLT_UN_MEMBASE:
break;
}
case OP_TLS_GET_REG:
-#ifdef TARGET_OSX
- // FIXME: tls_gs_offset can change too, do these when calculating the tls offset
- if (ins->dreg != ins->sreg1)
- amd64_mov_reg_reg (code, ins->dreg, ins->sreg1, sizeof (gpointer));
- amd64_shift_reg_imm (code, X86_SHL, ins->dreg, 3);
- if (tls_gs_offset)
- amd64_alu_reg_imm (code, X86_ADD, ins->dreg, tls_gs_offset);
- x86_prefix (code, X86_GS_PREFIX);
- amd64_mov_reg_membase (code, ins->dreg, ins->dreg, 0, sizeof (gpointer));
-#else
- g_assert_not_reached ();
-#endif
+ code = emit_tls_get_reg (code, ins->dreg, ins->sreg1);
+ break;
+ case OP_TLS_SET: {
+ code = amd64_emit_tls_set (code, ins->sreg1, ins->inst_offset);
break;
+ }
+ case OP_TLS_SET_REG: {
+ code = amd64_emit_tls_set_reg (code, ins->sreg1, ins->sreg2);
+ break;
+ }
case OP_MEMORY_BARRIER: {
switch (ins->backend.memory_barrier_kind) {
case StoreLoadBarrier:
int alloc_size, pos, i, cfa_offset, quad, max_epilog_size;
guint8 *code;
CallInfo *cinfo;
- MonoInst *lmf_var = cfg->arch.lmf_var;
+ MonoInst *lmf_var = cfg->lmf_var;
gboolean args_clobbered = FALSE;
gboolean trace = FALSE;
#ifdef __native_client_codegen__
#endif
}
- /* Save callee saved registers */
- if (!cfg->arch.omit_fp && !method->save_lmf) {
- int offset = cfa_offset;
-
- for (i = 0; i < AMD64_NREG; ++i)
- if (AMD64_IS_CALLEE_SAVED_REG (i) && (cfg->used_int_regs & (1 << i))) {
- amd64_push_reg (code, i);
- pos += 8; /* AMD64 push inst is always 8 bytes, no way to change it */
- offset += 8;
- mono_emit_unwind_op_offset (cfg, code, i, - offset);
- async_exc_point (code);
-
- /* These are handled automatically by the stack marking code */
- mini_gc_set_slot_type_from_cfa (cfg, - offset, SLOT_NOREF);
- }
- }
-
/* The param area is always at offset 0 from sp */
/* This needs to be allocated here, since it has to come after the spill area */
if (cfg->arch.no_pushes && cfg->param_area) {
}
/* Save callee saved registers */
- if (cfg->arch.omit_fp && !method->save_lmf) {
- gint32 save_area_offset = cfg->arch.reg_save_area_offset;
+ if (!method->save_lmf) {
+ gint32 save_area_offset;
+
+ if (cfg->arch.omit_fp) {
+ save_area_offset = cfg->arch.reg_save_area_offset;
+ /* Save caller saved registers after sp is adjusted */
+ /* The registers are saved at the bottom of the frame */
+ /* FIXME: Optimize this so the regs are saved at the end of the frame in increasing order */
+ } else {
+ /* The registers are saved just below the saved rbp */
+ save_area_offset = cfg->arch.reg_save_area_offset;
+ }
- /* Save caller saved registers after sp is adjusted */
- /* The registers are saved at the bottom of the frame */
- /* FIXME: Optimize this so the regs are saved at the end of the frame in increasing order */
for (i = 0; i < AMD64_NREG; ++i)
if (AMD64_IS_CALLEE_SAVED_REG (i) && (cfg->used_int_regs & (1 << i))) {
- amd64_mov_membase_reg (code, AMD64_RSP, save_area_offset, i, 8);
- mono_emit_unwind_op_offset (cfg, code, i, - (cfa_offset - save_area_offset));
+ amd64_mov_membase_reg (code, cfg->frame_reg, save_area_offset, i, 8);
- /* These are handled automatically by the stack marking code */
- mini_gc_set_slot_type_from_cfa (cfg, - (cfa_offset - save_area_offset), SLOT_NOREF);
+ if (cfg->arch.omit_fp) {
+ mono_emit_unwind_op_offset (cfg, code, i, - (cfa_offset - save_area_offset));
+ /* These are handled automatically by the stack marking code */
+ mini_gc_set_slot_type_from_cfa (cfg, - (cfa_offset - save_area_offset), SLOT_NOREF);
+ } else {
+ mono_emit_unwind_op_offset (cfg, code, i, - (-save_area_offset + (2 * 8)));
+ // FIXME: GC
+ }
save_area_offset += 8;
async_exc_point (code);
}
}
+#ifdef HOST_WIN32
if (method->save_lmf) {
- code = emit_save_lmf (cfg, code, lmf_var->inst_offset, &args_clobbered);
+ code = emit_push_lmf (cfg, code, lmf_var->inst_offset, &args_clobbered);
}
+#else
+ args_clobbered = TRUE;
+#endif
if (trace) {
args_clobbered = TRUE;
guint8 *code;
int max_epilog_size;
CallInfo *cinfo;
- gint32 lmf_offset = cfg->arch.lmf_var ? ((MonoInst*)cfg->arch.lmf_var)->inst_offset : -1;
+ gint32 lmf_offset = cfg->lmf_var ? ((MonoInst*)cfg->lmf_var)->inst_offset : -1;
max_epilog_size = get_max_epilog_size (cfg);
if (mono_jit_trace_calls != NULL && mono_trace_eval (method))
code = mono_arch_instrument_epilog (cfg, mono_trace_leave_method, code, TRUE);
- /* the code restoring the registers must be kept in sync with OP_JMP */
+ /* the code restoring the registers must be kept in sync with OP_TAILCALL */
pos = 0;
if (method->save_lmf) {
+#ifdef HOST_WIN32
+ code = emit_pop_lmf (cfg, code, lmf_offset);
+#endif
+
/* check if we need to restore protection of the stack after a stack overflow */
if (mono_get_jit_tls_offset () != -1) {
guint8 *patch;
/* FIXME: maybe save the jit tls in the prolog */
}
- code = emit_restore_lmf (cfg, code, lmf_offset);
-
/* Restore caller saved regs */
if (cfg->used_int_regs & (1 << AMD64_RBP)) {
amd64_mov_reg_membase (code, AMD64_RBP, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, rbp), 8);
}
#endif
} else {
+ gint32 save_area_offset = cfg->arch.reg_save_area_offset;
- if (cfg->arch.omit_fp) {
- gint32 save_area_offset = cfg->arch.reg_save_area_offset;
-
- for (i = 0; i < AMD64_NREG; ++i)
- if (AMD64_IS_CALLEE_SAVED_REG (i) && (cfg->used_int_regs & (1 << i))) {
- amd64_mov_reg_membase (code, i, AMD64_RSP, save_area_offset, 8);
- save_area_offset += 8;
- }
- }
- else {
- for (i = 0; i < AMD64_NREG; ++i)
- if (AMD64_IS_CALLEE_SAVED_REG (i) && (cfg->used_int_regs & (1 << i)))
- pos -= sizeof(mgreg_t);
-
- if (pos) {
- if (pos == - sizeof(mgreg_t)) {
- /* Only one register, so avoid lea */
- for (i = AMD64_NREG - 1; i > 0; --i)
- if (AMD64_IS_CALLEE_SAVED_REG (i) && (cfg->used_int_regs & (1 << i))) {
- amd64_mov_reg_membase (code, i, AMD64_RBP, pos, 8);
- }
- }
- else {
- amd64_lea_membase (code, AMD64_RSP, AMD64_RBP, pos);
-
- /* Pop registers in reverse order */
- for (i = AMD64_NREG - 1; i > 0; --i)
- if (AMD64_IS_CALLEE_SAVED_REG (i) && (cfg->used_int_regs & (1 << i))) {
- amd64_pop_reg (code, i);
- }
- }
+ for (i = 0; i < AMD64_NREG; ++i)
+ if (AMD64_IS_CALLEE_SAVED_REG (i) && (cfg->used_int_regs & (1 << i))) {
+ amd64_mov_reg_membase (code, i, cfg->frame_reg, save_area_offset, 8);
+ save_area_offset += 8;
}
- }
}
/* Load returned vtypes into registers if needed */
return NULL;
/* FIXME: Support more cases */
- if (MONO_TYPE_ISSTRUCT (sig->ret))
+ if (MONO_TYPE_ISSTRUCT (mini_type_get_underlying_type (NULL, sig->ret)))
return NULL;
if (has_target) {
* We need to init this multiple times, since when we are first called, the key might not
* be initialized yet.
*/
- appdomain_tls_offset = mono_domain_get_tls_key ();
- lmf_tls_offset = mono_get_jit_tls_key ();
- lmf_addr_tls_offset = mono_get_jit_tls_key ();
+ jit_tls_offset = mono_get_jit_tls_key ();
/* Only 64 tls entries can be accessed using inline code */
- if (appdomain_tls_offset >= 64)
- appdomain_tls_offset = -1;
- if (lmf_tls_offset >= 64)
- lmf_tls_offset = -1;
- if (lmf_addr_tls_offset >= 64)
- lmf_addr_tls_offset = -1;
+ if (jit_tls_offset >= 64)
+ jit_tls_offset = -1;
#else
#ifdef MONO_XEN_OPT
optimize_for_xen = access ("/proc/xen", F_OK) == 0;
#endif
- appdomain_tls_offset = mono_domain_get_tls_offset ();
- lmf_tls_offset = mono_get_lmf_tls_offset ();
- lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset ();
#endif
}
return 0;
}
-MonoInst* mono_arch_get_domain_intrinsic (MonoCompile* cfg)
-{
- MonoInst* ins;
-
- if (appdomain_tls_offset == -1)
- return NULL;
-
- MONO_INST_NEW (cfg, ins, OP_TLS_GET);
- ins->inst_offset = appdomain_tls_offset;
- return ins;
-}
-
#define _CTX_REG(ctx,fld,i) ((&ctx->fld)[i])
mgreg_t
case AMD64_RBP: return ctx->rbp;
case AMD64_RSP: return ctx->rsp;
default:
- if (reg < 8)
- return _CTX_REG (ctx, rax, reg);
- else if (reg >= 12)
- return _CTX_REG (ctx, r12, reg - 12);
- else
- g_assert_not_reached ();
+ return _CTX_REG (ctx, rax, reg);
}
}
ctx->rsp = val;
break;
default:
- if (reg < 8)
- _CTX_REG (ctx, rax, reg) = val;
- else if (reg >= 12)
- _CTX_REG (ctx, r12, reg - 12) = val;
- else
- g_assert_not_reached ();
+ _CTX_REG (ctx, rax, reg) = val;
}
}
return info;
}
+void
+mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
+{
+ ext->lmf.previous_lmf = prev_lmf;
+ /* Mark that this is a MonoLMFExt */
+ ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
+ ext->lmf.rsp = (gssize)ext;
+}
+
#endif
guint64 eip;
};
-typedef void (* MonoW32ExceptionHandler) (int _dummy, EXCEPTION_RECORD *info, void *context);
+typedef void (* MonoW32ExceptionHandler) (int _dummy, EXCEPTION_POINTERS *info, void *context);
void win32_seh_init(void);
void win32_seh_cleanup(void);
void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler);
struct MonoLMF {
/*
- * If the lowest bit is set to 1, then this LMF has the rip field set. Otherwise,
+ * If the lowest bit is set, then this LMF has the rip field set. Otherwise,
* the rip field is not set, and the rsp field points to the stack location where
* the caller ip is saved.
- * If the second lowest bit is set to 1, then this is a MonoLMFExt structure, and
+ * If the second lowest bit is set, then this is a MonoLMFExt structure, and
* the other fields are not valid.
+ * If the third lowest bit is set, then this is a MonoLMFTramp structure.
*/
gpointer previous_lmf;
+#ifdef HOST_WIN32
gpointer lmf_addr;
- /* This is only set in trampoline LMF frames */
- MonoMethod *method;
+#endif
#if defined(__default_codegen__) || defined(HOST_WIN32)
guint64 rip;
#elif defined(__native_client_codegen__)
#endif
};
+/* LMF structure used by the JIT trampolines */
+typedef struct {
+ struct MonoLMF lmf;
+ guint64 *regs;
+ gpointer lmf_addr;
+} MonoLMFTramp;
+
typedef struct MonoCompileArch {
gint32 localloc_offset;
gint32 reg_save_area_offset;
#define MONO_ARCH_HAVE_IS_INT_OVERFLOW 1
#define MONO_ARCH_ENABLE_REGALLOC_IN_EH_BLOCKS 1
-#if !defined(__APPLE__)
#define MONO_ARCH_ENABLE_MONO_LMF_VAR 1
-#endif
#define MONO_ARCH_HAVE_INVALIDATE_METHOD 1
#define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE 1
#define MONO_ARCH_HAVE_ATOMIC_ADD 1
#define MONO_ARCH_HAVE_CONTEXT_SET_INT_REG 1
#define MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK 1
#define MONO_ARCH_HAVE_CREATE_LLVM_NATIVE_THUNK 1
+#define MONO_ARCH_HAVE_OP_TAIL_CALL 1
+#define MONO_ARCH_HAVE_TRANSLATE_TLS_OFFSET 1
-#ifdef TARGET_OSX
+#if defined(TARGET_OSX) || defined(__linux__)
#define MONO_ARCH_HAVE_TLS_GET_REG 1
#endif
-gboolean
-mono_amd64_tail_call_supported (MonoMethodSignature *caller_sig, MonoMethodSignature *callee_sig) MONO_INTERNAL;
-
-#define MONO_ARCH_USE_OP_TAIL_CALL(caller_sig, callee_sig) mono_amd64_tail_call_supported (caller_sig, callee_sig)
-
/* Used for optimization, not complete */
#define MONO_ARCH_IS_OP_MEMBASE(opcode) ((opcode) == OP_X86_PUSH_MEMBASE)
GSList*
mono_amd64_get_exception_trampolines (gboolean aot) MONO_INTERNAL;
+int
+mono_amd64_get_tls_gs_offset (void) MONO_INTERNAL;
+
typedef struct {
guint8 *address;
guint8 saved_byte;
#error "ARM_FPU_NONE is defined while one of ARM_FPU_VFP/ARM_FPU_VFP_HARD is defined"
#endif
-#if defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
+/*
+ * IS_SOFT_FLOAT: Is full software floating point used?
+ * IS_HARD_FLOAT: Is full hardware floating point used?
+ * IS_VFP: Is hardware floating point with software ABI used?
+ *
+ * These are not necessarily constants, e.g. IS_SOFT_FLOAT and
+ * IS_VFP may delegate to mono_arch_is_soft_float ().
+ */
+
+#if defined(ARM_FPU_VFP_HARD)
+#define IS_SOFT_FLOAT (FALSE)
+#define IS_HARD_FLOAT (TRUE)
+#define IS_VFP (TRUE)
+#elif defined(ARM_FPU_NONE)
#define IS_SOFT_FLOAT (mono_arch_is_soft_float ())
+#define IS_HARD_FLOAT (FALSE)
#define IS_VFP (!mono_arch_is_soft_float ())
#else
#define IS_SOFT_FLOAT (FALSE)
+#define IS_HARD_FLOAT (FALSE)
#define IS_VFP (TRUE)
#endif
*/
static MonoArmFPU arm_fpu;
+static int vfp_scratch1 = ARM_VFP_F28;
+static int vfp_scratch2 = ARM_VFP_F30;
+
static int i8_align;
static volatile int ss_trigger_var = 0;
#define ADD_LR_PC_4 ((ARMCOND_AL << ARMCOND_SHIFT) | (1 << 25) | (1 << 23) | (ARMREG_PC << 16) | (ARMREG_LR << 12) | 4)
#define MOV_LR_PC ((ARMCOND_AL << ARMCOND_SHIFT) | (1 << 24) | (0xa << 20) | (ARMREG_LR << 12) | ARMREG_PC)
-#define DEBUG_IMT 0
+//#define DEBUG_IMT 0
/* A variant of ARM_LDR_IMM which can handle large offsets */
#define ARM_LDR_IMM_GENERAL(code, dreg, basereg, offset, scratch_reg) do { \
}
#endif
-
static guint8*
emit_move_return_value (MonoCompile *cfg, MonoInst *ins, guint8 *code)
{
case OP_FCALL_MEMBASE:
if (IS_VFP) {
if (((MonoCallInst*)ins)->signature->ret->type == MONO_TYPE_R4) {
- ARM_FMSR (code, ins->dreg, ARMREG_R0);
- ARM_CVTS (code, ins->dreg, ins->dreg);
+ if (IS_HARD_FLOAT) {
+ ARM_CVTS (code, ins->dreg, ARM_VFP_F0);
+ } else {
+ ARM_FMSR (code, ins->dreg, ARMREG_R0);
+ ARM_CVTS (code, ins->dreg, ins->dreg);
+ }
} else {
- ARM_FMDRR (code, ARMREG_R0, ARMREG_R1, ins->dreg);
+ if (IS_HARD_FLOAT) {
+ ARM_CPYD (code, ins->dreg, ARM_VFP_D0);
+ } else {
+ ARM_FMDRR (code, ARMREG_R0, ARMREG_R1, ins->dreg);
+ }
}
}
break;
return code;
}
+typedef struct {
+ gint32 vreg;
+ gint32 hreg;
+} FloatArgData;
+
+static guint8 *
+emit_float_args (MonoCompile *cfg, MonoCallInst *inst, guint8 *code, int *max_len, guint *offset)
+{
+ GSList *list;
+
+ for (list = inst->float_args; list; list = list->next) {
+ FloatArgData *fad = list->data;
+ MonoInst *var = get_vreg_to_inst (cfg, fad->vreg);
+
+ *max_len += 4;
+
+ if (*offset + *max_len > cfg->code_size) {
+ cfg->code_size += *max_len;
+ cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
+
+ code = cfg->native_code + *offset;
+ }
+
+ ARM_FLDS (code, fad->hreg, var->inst_basereg, var->inst_offset);
+
+ *offset = code - cfg->native_code;
+ }
+
+ return code;
+}
+
/*
* emit_save_lmf:
*
}
#endif
+gboolean
+mono_arm_is_hard_float (void)
+{
+ return arm_fpu == MONO_ARM_FPU_VFP_HARD;
+}
+
static gboolean
is_regsize_var (MonoGenericSharingContext *gsctx, MonoType *t) {
if (t->byref)
(*gr) ++;
}
+static void inline
+add_float (guint *fpr, guint *stack_size, ArgInfo *ainfo, gboolean is_double, gint *float_spare)
+{
+ /*
+ * If we're calling a function like this:
+ *
+ * void foo(float a, double b, float c)
+ *
+ * We pass a in s0 and b in d1. That leaves us
+ * with s1 being unused. The armhf ABI recognizes
+ * this and requires register assignment to then
+ * use that for the next single-precision arg,
+ * i.e. c in this example. So float_spare either
+ * tells us which reg to use for the next single-
+ * precision arg, or it's -1, meaning use *fpr.
+ *
+ * Note that even though most of the JIT speaks
+ * double-precision, fpr represents single-
+ * precision registers.
+ *
+ * See parts 5.5 and 6.1.2 of the AAPCS for how
+ * this all works.
+ */
+
+ if (*fpr < ARM_VFP_F16 || (!is_double && *float_spare >= 0)) {
+ ainfo->storage = RegTypeFP;
+
+ if (is_double) {
+ /*
+ * If we're passing a double-precision value
+ * and *fpr is odd (e.g. it's s1, s3, ...)
+ * we need to use the next even register. So
+ * we mark the current *fpr as a spare that
+ * can be used for the next single-precision
+ * value.
+ */
+ if (*fpr % 2) {
+ *float_spare = *fpr;
+ (*fpr)++;
+ }
+
+ /*
+ * At this point, we have an even register
+ * so we assign that and move along.
+ */
+ ainfo->reg = *fpr;
+ *fpr += 2;
+ } else if (*float_spare >= 0) {
+ /*
+ * We're passing a single-precision value
+ * and it looks like a spare single-
+ * precision register is available. Let's
+ * use it.
+ */
+
+ ainfo->reg = *float_spare;
+ *float_spare = -1;
+ } else {
+ /*
+ * If we hit this branch, we're passing a
+ * single-precision value and we can simply
+ * use the next available register.
+ */
+
+ ainfo->reg = *fpr;
+ (*fpr)++;
+ }
+ } else {
+ /*
+ * We've exhausted available floating point
+ * regs, so pass the rest on the stack.
+ */
+
+ if (is_double) {
+ *stack_size += 7;
+ *stack_size &= ~7;
+ }
+
+ ainfo->offset = *stack_size;
+ ainfo->reg = ARMREG_SP;
+ ainfo->storage = RegTypeBase;
+
+ *stack_size += 8;
+ }
+}
+
static CallInfo*
get_call_info (MonoGenericSharingContext *gsctx, MonoMemPool *mp, MonoMethodSignature *sig)
{
- guint i, gr, pstart;
+ guint i, gr, fpr, pstart;
+ gint float_spare;
int n = sig->hasthis + sig->param_count;
MonoType *simpletype;
guint32 stack_size = 0;
cinfo->nargs = n;
gr = ARMREG_R0;
+ fpr = ARM_VFP_F0;
+ float_spare = -1;
t = mini_type_get_underlying_type (gsctx, sig->ret);
if (MONO_TYPE_ISSTRUCT (t)) {
/* Prevent implicit arguments and sig_cookie from
being passed in registers */
gr = ARMREG_R3 + 1;
+ fpr = ARM_VFP_F16;
/* Emit the signature cookie just before the implicit arguments */
add_general (&gr, &stack_size, &cinfo->sig_cookie, TRUE);
}
case MONO_TYPE_STRING:
case MONO_TYPE_SZARRAY:
case MONO_TYPE_ARRAY:
- case MONO_TYPE_R4:
cinfo->args [n].size = sizeof (gpointer);
add_general (&gr, &stack_size, ainfo, TRUE);
n++;
}
case MONO_TYPE_U8:
case MONO_TYPE_I8:
- case MONO_TYPE_R8:
ainfo->size = 8;
add_general (&gr, &stack_size, ainfo, FALSE);
n++;
break;
+ case MONO_TYPE_R4:
+ ainfo->size = 4;
+
+ if (IS_HARD_FLOAT)
+ add_float (&fpr, &stack_size, ainfo, FALSE, &float_spare);
+ else
+ add_general (&gr, &stack_size, ainfo, TRUE);
+
+ n++;
+ break;
+ case MONO_TYPE_R8:
+ ainfo->size = 8;
+
+ if (IS_HARD_FLOAT)
+ add_float (&fpr, &stack_size, ainfo, TRUE, &float_spare);
+ else
+ add_general (&gr, &stack_size, ainfo, FALSE);
+
+ n++;
+ break;
case MONO_TYPE_VAR:
case MONO_TYPE_MVAR:
/* gsharedvt arguments are passed by ref */
/* Prevent implicit arguments and sig_cookie from
being passed in registers */
gr = ARMREG_R3 + 1;
+ fpr = ARM_VFP_F16;
/* Emit the signature cookie just before the implicit arguments */
add_general (&gr, &stack_size, &cinfo->sig_cookie, TRUE);
}
case MONO_TYPE_R4:
case MONO_TYPE_R8:
cinfo->ret.storage = RegTypeFP;
- cinfo->ret.reg = ARMREG_R0;
- /* FIXME: cinfo->ret.reg = ???;
- cinfo->ret.storage = RegTypeFP;*/
+
+ if (IS_HARD_FLOAT) {
+ cinfo->ret.reg = ARM_VFP_F0;
+ } else {
+ cinfo->ret.reg = ARMREG_R0;
+ }
+
break;
case MONO_TYPE_GENERICINST:
if (!mono_type_generic_inst_is_valuetype (simpletype)) {
}
break;
case RegTypeFP: {
- /* FIXME: */
- NOT_IMPLEMENTED;
-#if 0
- arg->backend.reg3 = ainfo->reg;
- /* FP args are passed in int regs */
- call->used_iregs |= 1 << ainfo->reg;
+ int fdreg = mono_alloc_freg (cfg);
+
if (ainfo->size == 8) {
- arg->opcode = OP_OUTARG_R8;
- call->used_iregs |= 1 << (ainfo->reg + 1);
+ MONO_INST_NEW (cfg, ins, OP_FMOVE);
+ ins->sreg1 = in->dreg;
+ ins->dreg = fdreg;
+ MONO_ADD_INS (cfg->cbb, ins);
+
+ mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, ainfo->reg, TRUE);
} else {
- arg->opcode = OP_OUTARG_R4;
+ FloatArgData *fad;
+
+ /*
+ * Mono's register allocator doesn't speak single-precision registers that
+ * overlap double-precision registers (i.e. armhf). So we have to work around
+ * the register allocator and load the value from memory manually.
+ *
+ * So we create a variable for the float argument and an instruction to store
+ * the argument into the variable. We then store the list of these arguments
+ * in cfg->float_args. This list is then used by emit_float_args later to
+ * pass the arguments in the various call opcodes.
+ *
+ * This is not very nice, and we should really try to fix the allocator.
+ */
+
+ MonoInst *float_arg = mono_compile_create_var (cfg, &mono_defaults.single_class->byval_arg, OP_LOCAL);
+
+ /* Make sure the instruction isn't seen as pointless and removed.
+ */
+ float_arg->flags |= MONO_INST_VOLATILE;
+
+ MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, float_arg->dreg, in->dreg);
+
+ /* We use the dreg to look up the instruction later. The hreg is used to
+ * emit the instruction that loads the value into the FP reg.
+ */
+ fad = mono_mempool_alloc0 (cfg->mempool, sizeof (FloatArgData));
+ fad->vreg = float_arg->dreg;
+ fad->hreg = ainfo->reg;
+
+ call->float_args = g_slist_append_mempool (cfg->mempool, call->float_args, fad);
}
-#endif
+
+ call->used_iregs |= 1 << ainfo->reg;
cfg->flags |= MONO_CFG_HAS_FPOUT;
break;
}
}
break;
case MONO_ARM_FPU_VFP:
+ case MONO_ARM_FPU_VFP_HARD:
if (ret->type == MONO_TYPE_R8 || ret->type == MONO_TYPE_R4) {
MonoInst *ins;
/* sreg is a float, dreg is an integer reg */
if (IS_VFP) {
if (is_signed)
- ARM_TOSIZD (code, ARM_VFP_F0, sreg);
+ ARM_TOSIZD (code, vfp_scratch1, sreg);
else
- ARM_TOUIZD (code, ARM_VFP_F0, sreg);
- ARM_FMRS (code, dreg, ARM_VFP_F0);
+ ARM_TOUIZD (code, vfp_scratch1, sreg);
+ ARM_FMRS (code, dreg, vfp_scratch1);
}
if (!is_signed) {
if (size == 1)
case OP_VOIDCALL:
case OP_CALL:
call = (MonoCallInst*)ins;
+
+ if (IS_HARD_FLOAT)
+ code = emit_float_args (cfg, call, code, &max_len, &offset);
+
if (ins->flags & MONO_INST_HAS_METHOD)
mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_METHOD, call->method);
else
case OP_VCALL2_REG:
case OP_VOIDCALL_REG:
case OP_CALL_REG:
+ if (IS_HARD_FLOAT)
+ code = emit_float_args (cfg, (MonoCallInst *)ins, code, &max_len, &offset);
+
code = emit_call_reg (code, ins->sreg1);
ins->flags |= MONO_INST_GC_CALLSITE;
ins->backend.pc_offset = code - cfg->native_code;
g_assert (ins->sreg1 != ARMREG_LR);
call = (MonoCallInst*)ins;
+
+ if (IS_HARD_FLOAT)
+ code = emit_float_args (cfg, call, code, &max_len, &offset);
+
if (call->dynamic_imt_arg || call->method->klass->flags & TYPE_ATTRIBUTE_INTERFACE)
imt_arg = TRUE;
if (!arm_is_imm12 (ins->inst_offset))
break;
case OP_STORER4_MEMBASE_REG:
g_assert (arm_is_fpimm8 (ins->inst_offset));
- ARM_CVTD (code, ARM_VFP_F0, ins->sreg1);
- ARM_FSTS (code, ARM_VFP_F0, ins->inst_destbasereg, ins->inst_offset);
+ ARM_CVTD (code, vfp_scratch1, ins->sreg1);
+ ARM_FSTS (code, vfp_scratch1, ins->inst_destbasereg, ins->inst_offset);
break;
case OP_LOADR4_MEMBASE:
g_assert (arm_is_fpimm8 (ins->inst_offset));
- ARM_FLDS (code, ARM_VFP_F0, ins->inst_basereg, ins->inst_offset);
- ARM_CVTS (code, ins->dreg, ARM_VFP_F0);
+ ARM_FLDS (code, vfp_scratch1, ins->inst_basereg, ins->inst_offset);
+ ARM_CVTS (code, ins->dreg, vfp_scratch1);
break;
case OP_ICONV_TO_R_UN: {
g_assert_not_reached ();
break;
}
case OP_ICONV_TO_R4:
- ARM_FMSR (code, ARM_VFP_F0, ins->sreg1);
- ARM_FSITOS (code, ARM_VFP_F0, ARM_VFP_F0);
- ARM_CVTS (code, ins->dreg, ARM_VFP_F0);
+ ARM_FMSR (code, vfp_scratch1, ins->sreg1);
+ ARM_FSITOS (code, vfp_scratch1, vfp_scratch1);
+ ARM_CVTS (code, ins->dreg, vfp_scratch1);
break;
case OP_ICONV_TO_R8:
- ARM_FMSR (code, ARM_VFP_F0, ins->sreg1);
- ARM_FSITOD (code, ins->dreg, ARM_VFP_F0);
+ ARM_FMSR (code, vfp_scratch1, ins->sreg1);
+ ARM_FSITOD (code, ins->dreg, vfp_scratch1);
break;
case OP_SETFRET:
if (mono_method_signature (cfg->method)->ret->type == MONO_TYPE_R4) {
ARM_CVTD (code, ARM_VFP_F0, ins->sreg1);
- ARM_FMRS (code, ARMREG_R0, ARM_VFP_F0);
+
+ if (!IS_HARD_FLOAT) {
+ ARM_FMRS (code, ARMREG_R0, ARM_VFP_F0);
+ }
} else {
- ARM_FMRRD (code, ARMREG_R0, ARMREG_R1, ins->sreg1);
+ if (IS_HARD_FLOAT) {
+ ARM_CPYD (code, ARM_VFP_D0, ins->sreg1);
+ } else {
+ ARM_FMRRD (code, ARMREG_R0, ARMREG_R1, ins->sreg1);
+ }
}
break;
case OP_FCONV_TO_I1:
jte [0] = GUINT_TO_POINTER (0xffffffff);
jte [1] = GUINT_TO_POINTER (0x7fefffff);
code = mono_arm_load_jumptable_entry_addr (code, jte, ARMREG_IP);
- ARM_FLDD (code, ARM_VFP_D0, ARMREG_IP, 0);
+ ARM_FLDD (code, vfp_scratch1, ARMREG_IP, 0);
}
#else
- ARM_ABSD (code, ARM_VFP_D1, ins->sreg1);
- ARM_FLDD (code, ARM_VFP_D0, ARMREG_PC, 0);
+ ARM_ABSD (code, vfp_scratch2, ins->sreg1);
+ ARM_FLDD (code, vfp_scratch1, ARMREG_PC, 0);
ARM_B (code, 1);
*(guint32*)code = 0xffffffff;
code += 4;
*(guint32*)code = 0x7fefffff;
code += 4;
#endif
- ARM_CMPD (code, ARM_VFP_D1, ARM_VFP_D0);
+ ARM_CMPD (code, vfp_scratch2, vfp_scratch1);
ARM_FMSTAT (code);
EMIT_COND_SYSTEM_EXCEPTION_FLAGS (ARMCOND_GT, "ArithmeticException");
ARM_CMPD (code, ins->sreg1, ins->sreg1);
break;
}
} else if (ainfo->storage == RegTypeFP) {
- g_assert_not_reached ();
+ code = mono_arm_emit_load_imm (code, ARMREG_IP, inst->inst_offset);
+ ARM_ADD_REG_REG (code, ARMREG_IP, ARMREG_IP, inst->inst_basereg);
+
+ if (ainfo->size == 8)
+ ARM_FSTD (code, ainfo->reg, ARMREG_IP, 0);
+ else
+ ARM_FSTS (code, ainfo->reg, ARMREG_IP, 0);
} else if (ainfo->storage == RegTypeStructByVal) {
int doffset = inst->inst_offset;
int soffset = 0;
#ifndef DISABLE_JIT
-MonoInst*
-mono_arch_get_domain_intrinsic (MonoCompile* cfg)
-{
- return mono_get_domain_intrinsic (cfg);
-}
-
#endif
guint32
return (MonoVTable*) regs [MONO_ARCH_RGCTX_REG];
}
-#define ENABLE_WRONG_METHOD_CHECK 0
+/* #define ENABLE_WRONG_METHOD_CHECK 1 */
#define BASE_SIZE (6 * 4)
#define BSEARCH_ENTRY_SIZE (4 * 4)
#define CMP_SIZE (3 * 4)
#define BRANCH_SIZE (1 * 4)
#define CALL_SIZE (2 * 4)
-#define WMC_SIZE (5 * 4)
+#define WMC_SIZE (8 * 4)
#define DISTANCE(A, B) (((gint32)(B)) - ((gint32)(A)))
#ifdef USE_JUMP_TABLES
}
#endif
+#ifdef ENABLE_WRONG_METHOD_CHECK
+static void
+mini_dump_bad_imt (int input_imt, int compared_imt, int pc)
+{
+ g_print ("BAD IMT comparing %x with expected %x at ip %x", input_imt, compared_imt, pc);
+ g_assert (0);
+}
+#endif
+
gpointer
mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count,
gpointer fail_tramp)
arminstr_t *vtable_target = NULL;
int extra_space = 0;
#endif
+#ifdef ENABLE_WRONG_METHOD_CHECK
+ char * cond;
+#endif
size = BASE_SIZE;
#ifdef USE_JUMP_TABLES
item->chunk_size += CMP_SIZE;
item->chunk_size += BRANCH_SIZE;
} else {
-#if ENABLE_WRONG_METHOD_CHECK
+#ifdef ENABLE_WRONG_METHOD_CHECK
item->chunk_size += WMC_SIZE;
#endif
}
code = mono_domain_code_reserve (domain, size);
start = code;
-#if DEBUG_IMT
- printf ("building IMT thunk for class %s %s entries %d code size %d code at %p end %p vtable %p\n", vtable->klass->name_space, vtable->klass->name, count, size, start, ((guint8*)start) + size, vtable);
+#ifdef DEBUG_IMT
+ g_print ("Building IMT thunk for class %s %s entries %d code size %d code at %p end %p vtable %p fail_tramp %p\n", vtable->klass->name_space, vtable->klass->name, count, size, start, ((guint8*)start) + size, vtable, fail_tramp);
for (i = 0; i < count; ++i) {
MonoIMTCheckItem *item = imt_entries [i];
- printf ("method %d (%p) %s vtable slot %p is_equals %d chunk size %d\n", i, item->key, item->key->name, &vtable->vtable [item->value.vtable_slot], item->is_equals, item->chunk_size);
+ g_print ("method %d (%p) %s vtable slot %p is_equals %d chunk size %d\n", i, item->key, ((MonoMethod*)item->key)->name, &vtable->vtable [item->value.vtable_slot], item->is_equals, item->chunk_size);
}
#endif
#endif
} else {
/*Enable the commented code to assert on wrong method*/
-#if ENABLE_WRONG_METHOD_CHECK
+#ifdef ENABLE_WRONG_METHOD_CHECK
#ifdef USE_JUMP_TABLES
imt_method_jti = IMT_METHOD_JTI (i);
code = load_element_with_regbase_cond (code, ARMREG_R1, ARMREG_R2, imt_method_jti, ARMCOND_AL);
ARM_LDR_IMM (code, ARMREG_R1, ARMREG_PC, 0);
#endif
ARM_CMP_REG_REG (code, ARMREG_R0, ARMREG_R1);
- ARM_B_COND (code, ARMCOND_NE, 1);
-
+ cond = code;
+ ARM_B_COND (code, ARMCOND_EQ, 0);
+
+/* Define this if your system is so bad that gdb is failing. */
+#ifdef BROKEN_DEV_ENV
+ ARM_MOV_REG_REG (code, ARMREG_R2, ARMREG_PC);
+ ARM_BL (code, 0);
+ arm_patch (code - 1, mini_dump_bad_imt);
+#else
ARM_DBRK (code);
+#endif
+ arm_patch (cond, code);
#endif
}
#ifdef USE_JUMP_TABLES
code = load_element_with_regbase_cond (code, ARMREG_R1, ARMREG_R2, IMT_METHOD_JTI (i), ARMCOND_AL);
ARM_CMP_REG_REG (code, ARMREG_R0, ARMREG_R1);
- code = load_element_with_regbase_cond (code, ARMREG_R1, ARMREG_R2, JUMP_CODE_JTI (i), ARMCOND_GE);
- ARM_BX_COND (code, ARMCOND_GE, ARMREG_R1);
+ code = load_element_with_regbase_cond (code, ARMREG_R1, ARMREG_R2, JUMP_CODE_JTI (i), ARMCOND_HS);
+ ARM_BX_COND (code, ARMCOND_HS, ARMREG_R1);
item->jmp_code = GUINT_TO_POINTER (JUMP_CODE_JTI (i));
#else
ARM_LDR_IMM (code, ARMREG_R1, ARMREG_PC, 0);
ARM_CMP_REG_REG (code, ARMREG_R0, ARMREG_R1);
item->jmp_code = (guint8*)code;
- ARM_B_COND (code, ARMCOND_GE, 0);
+ ARM_B_COND (code, ARMCOND_HS, 0);
++extra_space;
#endif
}
}
}
-#if DEBUG_IMT
+#ifdef DEBUG_IMT
{
char *buff = g_strdup_printf ("thunk_for_class_%s_%s_entries_%d", vtable->klass->name_space, vtable->klass->name, count);
mono_disassemble_code (NULL, (guint8*)start, size, buff);
return info;
}
+void
+mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
+{
+ ext->lmf.previous_lmf = prev_lmf;
+ /* Mark that this is a MonoLMFExt */
+ ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
+ ext->lmf.sp = (gssize)ext;
+}
+
/*
* mono_arch_set_target:
*
#define MONO_ARCH_SOFT_FLOAT_FALLBACK 1
#endif
-#ifdef ARM_FPU_VFP_HARD
-#error "hardfp-abi not yet supported."
-#endif
-
#if defined(__ARM_EABI__)
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
#define ARM_ARCHITECTURE "armel"
#endif
#define MONO_MAX_IREGS 16
-#define MONO_MAX_FREGS 16
+#define MONO_MAX_FREGS 32
#define MONO_SAVED_GREGS 10 /* r4-r11, ip, lr */
-#define MONO_SAVED_FREGS 8
/* r4-r11, ip, lr: registers saved in the LMF */
#define MONO_ARM_REGSAVE_MASK 0x5ff0
#define MONO_ARCH_CALLEE_REGS ((1<<ARMREG_R0) | (1<<ARMREG_R1) | (1<<ARMREG_R2) | (1<<ARMREG_R3) | (1<<ARMREG_IP))
#define MONO_ARCH_CALLEE_SAVED_REGS ((1<<ARMREG_V1) | (1<<ARMREG_V2) | (1<<ARMREG_V3) | (1<<ARMREG_V4) | (1<<ARMREG_V5) | (1<<ARMREG_V6) | (1<<ARMREG_V7))
-/* Every double precision vfp register, d0/d1 is reserved for a scratch reg */
-#define MONO_ARCH_CALLEE_FREGS 0x55555550
-#define MONO_ARCH_CALLEE_SAVED_FREGS 0
+/*
+ * TODO: Make use of VFP v3 registers d16-d31.
+ */
+
+/*
+ * TODO: We can't use registers d8-d15 in hard float mode because the
+ * register allocator doesn't allocate floating point registers globally.
+ */
+
+#if defined(ARM_FPU_VFP_HARD)
+#define MONO_SAVED_FREGS 16
+/*
+ * d8-d15 must be preserved across function calls. We use d14-d15 as
+ * scratch registers in the JIT. The rest have no meaning tied to them.
+ */
+#define MONO_ARCH_CALLEE_FREGS 0x00005555
+#define MONO_ARCH_CALLEE_SAVED_FREGS 0x55550000
+#else
+#define MONO_SAVED_FREGS 0
+/*
+ * No registers need to be preserved across function calls. We use d14-d15
+ * as scratch registers in the JIT. The rest have no meaning tied to them.
+ */
+#define MONO_ARCH_CALLEE_FREGS 0x05555555
+#define MONO_ARCH_CALLEE_SAVED_FREGS 0x00000000
+#endif
#define MONO_ARCH_USE_FPSTACK FALSE
#define MONO_ARCH_FPSTACK_SIZE 0
mgreg_t sp;
mgreg_t ip;
mgreg_t fp;
+ /* Currently only used in trampolines on armhf to hold d0-d15. We don't really
+ * need to put d0-d7 in the LMF, but it simplifies the trampoline code.
+ */
+ double fregs [16];
/* all but sp and pc: matches the PUSH instruction layout in the trampolines
* 0-4 should be considered undefined (execpt in the magic tramp)
* sp is saved at IP.
mono_arm_load_jumptable_entry (guint8 *code, gpointer *jte, ARMReg reg) MONO_INTERNAL;
#endif
+gboolean
+mono_arm_is_hard_float (void) MONO_INTERNAL;
+
#endif /* __MONO_MINI_ARM_H__ */
else
printf (" %s", mono_inst_name (ins->opcode));
if (spec == MONO_ARCH_CPU_SPEC) {
+ gboolean dest_base = FALSE;
+ switch (ins->opcode) {
+ case OP_STOREV_MEMBASE:
+ dest_base = TRUE;
+ break;
+ default:
+ break;
+ }
+
/* This is a lowered opcode */
- if (ins->dreg != -1)
- printf (" R%d <-", ins->dreg);
+ if (ins->dreg != -1) {
+ if (dest_base)
+ printf (" [R%d + 0x%lx] <-", ins->dreg, (long)ins->inst_offset);
+ else
+ printf (" R%d <-", ins->dreg);
+ }
if (ins->sreg1 != -1)
printf (" R%d", ins->sreg1);
if (ins->sreg2 != -1)
case OP_CALL_MEMBASE:
case OP_CALL_REG:
case OP_FCALL:
- case OP_FCALLVIRT:
case OP_LCALL:
- case OP_LCALLVIRT:
case OP_VCALL:
- case OP_VCALLVIRT:
case OP_VCALL_REG:
case OP_VCALL_MEMBASE:
case OP_VCALL2:
case OP_VCALL2_MEMBASE:
case OP_VOIDCALL:
case OP_VOIDCALL_MEMBASE:
- case OP_VOIDCALLVIRT:
case OP_TAILCALL: {
MonoCallInst *call = (MonoCallInst*)ins;
GSList *list;
case OP_CMOV_IEQ:
case OP_CMOV_LEQ:
return CMP_EQ;
+ case OP_FCNEQ:
+ case OP_ICNEQ:
case OP_IBNE_UN:
case OP_LBNE_UN:
case OP_FBNE_UN:
case OP_CMOV_INE_UN:
case OP_CMOV_LNE_UN:
return CMP_NE;
+ case OP_FCLE:
+ case OP_ICLE:
case OP_IBLE:
case OP_LBLE:
case OP_FBLE:
case OP_CMOV_ILE:
case OP_CMOV_LLE:
return CMP_LE;
+ case OP_FCGE:
+ case OP_ICGE:
case OP_IBGE:
case OP_LBGE:
case OP_FBGE:
case OP_CMOV_LGT:
return CMP_GT;
+ case OP_ICLE_UN:
case OP_IBLE_UN:
case OP_LBLE_UN:
case OP_FBLE_UN:
case OP_CMOV_ILE_UN:
case OP_CMOV_LLE_UN:
return CMP_LE_UN;
+
+ case OP_ICGE_UN:
case OP_IBGE_UN:
case OP_LBGE_UN:
case OP_FBGE_UN:
#include <mono/utils/mono-logger-internal.h>
#include "mini.h"
-#include "debug-mini.h"
#include "trace.h"
#include "debugger-agent.h"
MonoJitInfo *ji = NULL;
MonoContext ctx, new_ctx;
MonoDebugSourceLocation *location;
- MonoMethod *jmethod, *actual_method;
+ MonoMethod *jmethod = NULL, *actual_method;
StackFrameInfo frame;
gboolean res;
#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->exceptions_filters++;
#endif
- mono_debugger_call_exception_handler (ei->data.filter, MONO_CONTEXT_GET_SP (ctx), ex_obj);
-
/*
Here's the thing, if this is a filter clause done by a wrapper like runtime invoke, we don't want to
trim the stackframe since if it returns FALSE we lose information.
MonoContext initial_ctx;
MonoMethod *method;
int frame_count = 0;
- gint32 filter_idx, first_filter_idx;
+ gint32 filter_idx, first_filter_idx = 0;
int i;
MonoObject *ex_obj;
MonoObject *non_exception = NULL;
jit_tls->orig_ex_ctx_set = TRUE;
mono_profiler_exception_clause_handler (method, ei->flags, i);
jit_tls->orig_ex_ctx_set = FALSE;
- mono_debugger_call_exception_handler (ei->handler_start, MONO_CONTEXT_GET_SP (ctx), ex_obj);
MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
*(mono_get_lmf_addr ()) = lmf;
#ifndef DISABLE_PERFCOUNTERS
jit_tls->orig_ex_ctx_set = TRUE;
mono_profiler_exception_clause_handler (method, ei->flags, i);
jit_tls->orig_ex_ctx_set = FALSE;
- mono_debugger_call_exception_handler (ei->handler_start, MONO_CONTEXT_GET_SP (ctx), ex_obj);
call_filter (ctx, ei->handler_start);
}
if (is_address_protected (ji, ei, MONO_CONTEXT_GET_IP (ctx)) &&
jit_tls->orig_ex_ctx_set = TRUE;
mono_profiler_exception_clause_handler (method, ei->flags, i);
jit_tls->orig_ex_ctx_set = FALSE;
- mono_debugger_call_exception_handler (ei->handler_start, MONO_CONTEXT_GET_SP (ctx), ex_obj);
#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->exceptions_finallys++;
#endif
g_assert_not_reached ();
}
-/*
- * mono_debugger_handle_exception:
- *
- * Notify the debugger about exceptions. Returns TRUE if the debugger wants us to stop
- * at the exception and FALSE to resume with the normal exception handling.
- *
- * The arch code is responsible to setup @ctx in a way that MONO_CONTEXT_GET_IP () and
- * MONO_CONTEXT_GET_SP () point to the throw instruction; ie. before executing the
- * `callq throw' instruction.
- */
-gboolean
-mono_debugger_handle_exception (MonoContext *ctx, MonoObject *obj)
-{
- MonoDebuggerExceptionAction action;
-
- if (!mono_debug_using_mono_debugger ())
- return FALSE;
-
- if (!obj) {
- MonoException *ex = mono_get_exception_null_reference ();
- MONO_OBJECT_SETREF (ex, message, mono_string_new (mono_domain_get (), "Object reference not set to an instance of an object"));
- obj = (MonoObject *)ex;
- }
-
- action = _mono_debugger_throw_exception (MONO_CONTEXT_GET_IP (ctx), MONO_CONTEXT_GET_SP (ctx), obj);
-
- if (action == MONO_DEBUGGER_EXCEPTION_ACTION_STOP) {
- /*
- * The debugger wants us to stop on the `throw' instruction.
- * By the time we get here, it already inserted a breakpoint there.
- */
- return TRUE;
- } else if (action == MONO_DEBUGGER_EXCEPTION_ACTION_STOP_UNHANDLED) {
- MonoContext ctx_cp = *ctx;
- MonoJitInfo *ji = NULL;
- gboolean ret;
-
- /*
- * The debugger wants us to stop only if this exception is user-unhandled.
- */
-
- ret = mono_handle_exception_internal_first_pass (&ctx_cp, obj, NULL, &ji, NULL, NULL);
- if (ret && (ji != NULL) && (jinfo_get_method (ji)->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE)) {
- /*
- * The exception is handled in a runtime-invoke wrapper, that means that it's unhandled
- * inside the method being invoked, so we handle it like a user-unhandled exception.
- */
- ret = FALSE;
- }
-
- if (!ret) {
- /*
- * The exception is user-unhandled - tell the debugger to stop.
- */
- return _mono_debugger_unhandled_exception (MONO_CONTEXT_GET_IP (ctx), MONO_CONTEXT_GET_SP (ctx), obj);
- }
-
- /*
- * The exception is catched somewhere - resume with the normal exception handling and don't
- * stop in the debugger.
- */
- }
-
- return FALSE;
-}
-
/**
* mono_debugger_run_finally:
* @start_ctx: saved processor state
int count;
} PrintOverflowUserData;
+#ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
static gboolean
print_overflow_stack_frame (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
{
return FALSE;
}
+#endif
void
mono_handle_hard_stack_ovf (MonoJitTlsData *jit_tls, MonoJitInfo *ji, void *ctx, guint8* fault_addr)
{
+#ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
PrintOverflowUserData ud;
MonoContext mctx;
+#endif
/* we don't do much now, but we can warn the user with a useful message */
mono_runtime_printf_err ("Stack overflow: IP: %p, fault addr: %p", mono_arch_ip_from_context (ctx), fault_addr);
if (mini_get_debug_options ()->suspend_on_sigsegv) {
mono_runtime_printf_err ("Received SIGSEGV, suspending...");
+#ifdef HOST_WIN32
while (1)
;
+#else
+ while (1) {
+ sleep (0);
+ }
+#endif
}
/* To prevent infinite loops when the stack walk causes a crash */
/* Try to get more meaningful information using gdb */
#if !defined(HOST_WIN32) && defined(HAVE_SYS_SYSCALL_H) && defined(SYS_fork)
- if (!mini_get_debug_options ()->no_gdb_backtrace && !mono_debug_using_mono_debugger ()) {
+ if (!mini_get_debug_options ()->no_gdb_backtrace) {
/* From g_spawn_command_line_sync () in eglib */
pid_t pid;
int status;
return 0;
}
-MonoInst*
-mono_arch_get_domain_intrinsic (MonoCompile* cfg)
-{
- return mono_get_domain_intrinsic (cfg);
-}
-
mgreg_t
mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
{
virtual void deallocateExceptionTable(void*) {
}
- virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
- unsigned SectionID) {
+ virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
+ StringRef SectionName) {
// FIXME:
assert(0);
return NULL;
}
- virtual uint8_t* allocateDataSection(uintptr_t, unsigned int, unsigned int, bool) {
+ virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
+ StringRef SectionName, bool IsReadOnly) {
// FIXME:
assert(0);
return NULL;
return false;
}
+ virtual bool finalizeMemory(std::string *ErrMsg = 0) {
+ // FIXME:
+ assert(0);
+ return false;
+ }
+
virtual void* getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure) {
void *res;
char *err;
* install a profiler hook and reset the code model here.
* This should be inside an ifdef, but we can't include our config.h either,
* since its definitions conflict with LLVM's config.h.
- *
+ * The LLVM mono branch contains a workaround.
*/
- //#if defined(TARGET_X86) || defined(TARGET_AMD64)
-#ifndef LLVM_MONO_BRANCH
- /* The LLVM mono branch contains a workaround, so this is not needed */
- if (Details.MF->getTarget ().getCodeModel () == CodeModel::Large) {
- Details.MF->getTarget ().setCodeModel (CodeModel::Default);
- }
-#endif
- //#endif
-
emitted_cb (wrap (&F), Code, (char*)Code + Size);
}
};
void
mono_llvm_optimize_method (LLVMValueRef method)
{
- verifyFunction (*(unwrap<Function> (method)));
+ /*
+ * The verifier does some checks on the whole module, leading to quadratic behavior.
+ */
+ //verifyFunction (*(unwrap<Function> (method)));
fpm->run (*unwrap<Function> (method));
}
(void) llvm::createBasicAliasAnalysisPass();
(void) llvm::createLibCallAliasAnalysisPass(0);
(void) llvm::createScalarEvolutionAliasAnalysisPass();
- (void) llvm::createBlockPlacementPass();
+ //(void) llvm::createBlockPlacementPass();
(void) llvm::createBreakCriticalEdgesPass();
(void) llvm::createCFGSimplificationPass();
/*
(void) llvm::createReassociatePass();
(void) llvm::createSCCPPass();
(void) llvm::createScalarReplAggregatesPass();
- (void) llvm::createSimplifyLibCallsPass();
+ //(void) llvm::createSimplifyLibCallsPass();
/*
(void) llvm::createSingleLoopExtractorPass();
(void) llvm::createStripSymbolsPass();
mono_mm->alloc_cb = alloc_cb;
mono_mm->dlsym_cb = dlsym_cb;
- //JITExceptionHandling = true;
- // PrettyStackTrace installs signal handlers which trip up libgc
- DisablePrettyStackTrace = true;
-
/*
* The Default code model doesn't seem to work on amd64,
* test_0_fields_with_big_offsets (among others) crashes, because LLVM tries to call
#endif
g_assert (EE);
-#if 0
- ExecutionEngine *EE = ExecutionEngine::createJIT (unwrap (MP), &Error, mono_mm, CodeGenOpt::Default, true, Reloc::Default, CodeModel::Large);
- if (!EE) {
- errs () << "Unable to create LLVM ExecutionEngine: " << Error << "\n";
- g_assert_not_reached ();
- }
-#endif
-
EE->InstallExceptionTableRegister (exception_cb);
mono_event_listener = new MonoJITEventListener (emitted_cb);
EE->RegisterJITEventListener (mono_event_listener);
PassRegistry &Registry = *PassRegistry::getPassRegistry();
initializeCore(Registry);
initializeScalarOpts(Registry);
- //initializeIPO(Registry);
initializeAnalysis(Registry);
initializeIPA(Registry);
initializeTransformUtils(Registry);
initializeInstCombine(Registry);
- //initializeInstrumentation(Registry);
initializeTarget(Registry);
llvm::cl::ParseEnvironmentOptions("mono", "MONO_LLVM", "");
}
} else {
/* Use the same passes used by 'opt' by default, without the ipo passes */
- const char *opts = "-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -domtree -domfrontier -scalarrepl -simplify-libcalls -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -domfrontier -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -iv-users -indvars -loop-deletion -loop-simplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -gvn -simplifycfg -preverify -domtree -verify";
+ const char *opts = "-simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -domtree -domfrontier -scalarrepl -instcombine -simplifycfg -instcombine -simplifycfg -reassociate -domtree -loops -loop-simplify -domfrontier -loop-simplify -lcssa -loop-rotate -licm -lcssa -loop-unswitch -instcombine -scalar-evolution -loop-simplify -lcssa -iv-users -indvars -loop-deletion -loop-simplify -lcssa -loop-unroll -instcombine -memdep -gvn -memdep -memcpyopt -sccp -instcombine -domtree -memdep -dse -adce -gvn -simplifycfg";
char **args;
int i;
LLVMValueRef got_var;
const char *got_symbol;
GHashTable *plt_entries;
+ char **bb_names;
+ GPtrArray *used;
+ LLVMTypeRef ptr_type;
} MonoLLVMModule;
/*
#define IS_TARGET_X86 0
#endif
+#ifdef TARGET_AMD64
+#define IS_TARGET_AMD64 1
+#else
+#define IS_TARGET_AMD64 0
+#endif
+
#define LLVM_FAILURE(ctx, reason) do { \
TRACE_FAILURE (reason); \
(ctx)->cfg->exception_message = g_strdup (reason); \
return sizeof (gpointer) == 8 ? LLVMInt64Type () : LLVMInt32Type ();
}
+static LLVMTypeRef
+ObjRefType (void)
+{
+ return sizeof (gpointer) == 8 ? LLVMPointerType (LLVMInt64Type (), 0) : LLVMPointerType (LLVMInt32Type (), 0);
+}
+
+static LLVMTypeRef
+ThisType (void)
+{
+ return sizeof (gpointer) == 8 ? LLVMPointerType (LLVMInt64Type (), 0) : LLVMPointerType (LLVMInt32Type (), 0);
+}
+
/*
* get_vtype_size:
*
case MONO_TYPE_SZARRAY:
case MONO_TYPE_STRING:
case MONO_TYPE_PTR:
- return IntPtrType ();
+ return ObjRefType ();
case MONO_TYPE_VAR:
case MONO_TYPE_MVAR:
/* Because of generic sharing */
- return IntPtrType ();
+ return ObjRefType ();
case MONO_TYPE_GENERICINST:
if (!mono_type_generic_inst_is_valuetype (t))
- return IntPtrType ();
+ return ObjRefType ();
/* Fall through */
case MONO_TYPE_VALUETYPE:
case MONO_TYPE_TYPEDBYREF: {
static LLVMBasicBlockRef
get_bb (EmitContext *ctx, MonoBasicBlock *bb)
{
- char bb_name [128];
+ char bb_name_buf [128];
+ char *bb_name;
if (ctx->bblocks [bb->block_num].bblock == NULL) {
if (bb->flags & BB_EXCEPTION_HANDLER) {
int clause_index = (mono_get_block_region_notry (ctx->cfg, bb->region) >> 8) - 1;
- sprintf (bb_name, "EH_CLAUSE%d_BB%d", clause_index, bb->block_num);
+ sprintf (bb_name_buf, "EH_CLAUSE%d_BB%d", clause_index, bb->block_num);
+ bb_name = bb_name_buf;
+ } else if (bb->block_num < 256) {
+ if (!ctx->lmodule->bb_names)
+ ctx->lmodule->bb_names = g_new0 (char*, 256);
+ if (!ctx->lmodule->bb_names [bb->block_num]) {
+ char *n;
+
+ n = g_strdup_printf ("BB%d", bb->block_num);
+ mono_memory_barrier ();
+ ctx->lmodule->bb_names [bb->block_num] = n;
+ }
+ bb_name = ctx->lmodule->bb_names [bb->block_num];
} else {
- sprintf (bb_name, "BB%d", bb->block_num);
+ sprintf (bb_name_buf, "BB%d", bb->block_num);
+ bb_name = bb_name_buf;
}
ctx->bblocks [bb->block_num].bblock = LLVMAppendBasicBlock (ctx->lmethod, bb_name);
if (cinfo && cinfo->rgctx_arg) {
if (sinfo)
sinfo->rgctx_arg_pindex = pindex;
- param_types [pindex] = IntPtrType ();
+ param_types [pindex] = ctx->lmodule->ptr_type;
pindex ++;
}
if (cinfo && cinfo->imt_arg) {
if (sinfo)
sinfo->imt_arg_pindex = pindex;
- param_types [pindex] = IntPtrType ();
+ param_types [pindex] = ctx->lmodule->ptr_type;
pindex ++;
}
if (vretaddr) {
if (sig->hasthis) {
if (sinfo)
sinfo->this_arg_pindex = pindex;
- param_types [pindex ++] = IntPtrType ();
+ param_types [pindex ++] = ThisType ();
}
if (vretaddr && vret_arg_pindex == pindex)
param_types [pindex ++] = IntPtrType ();
{
LLVMValueRef md_arg;
int md_kind;
-
+
md_kind = LLVMGetMDKindID (flag_name, strlen (flag_name));
md_arg = LLVMMDString ("mono", 4);
LLVMSetMetadata (v, md_kind, LLVMMDNode (&md_arg, 1));
}
+static void
+set_invariant_load_flag (LLVMValueRef v)
+{
+ LLVMValueRef md_arg;
+ int md_kind;
+ const char *flag_name;
+
+ // FIXME: Cache this
+ flag_name = "invariant.load";
+ md_kind = LLVMGetMDKindID (flag_name, strlen (flag_name));
+ md_arg = LLVMMDString ("<index>", strlen ("<index>"));
+ LLVMSetMetadata (v, md_kind, LLVMMDNode (&md_arg, 1));
+}
+
/*
* emit_call:
*
throw_sig->ret = &mono_get_void_class ()->byval_arg;
throw_sig->params [0] = &mono_get_int32_class ()->byval_arg;
icall_name = "llvm_throw_corlib_exception_abs_trampoline";
- throw_sig->params [1] = &mono_get_intptr_class ()->byval_arg;
+ /* This will become i8* */
+ throw_sig->params [1] = &mono_get_byte_class ()->this_arg;
sig = sig_to_llvm_sig (ctx, throw_sig);
if (ctx->cfg->compile_aot) {
/*
* Differences between the LLVM/non-LLVM throw corlib exception trampoline:
* - On x86, LLVM generated code doesn't push the arguments
- * - When using the LLVM mono branch, the trampoline takes the throw address as an
- * arguments, not a pc offset.
+ * - The trampoline takes the throw address as an arguments, not a pc offset.
*/
LLVMAddGlobalMapping (ee, callee, resolve_patch (ctx->cfg, MONO_PATCH_INFO_INTERNAL_METHOD, icall_name));
}
ctx->lmodule->throw_corlib_exception = callee;
}
- if (IS_TARGET_X86)
+ if (IS_TARGET_X86 || IS_TARGET_AMD64)
args [0] = LLVMConstInt (LLVMInt32Type (), exc_class->type_token - MONO_TOKEN_TYPE_DEF, FALSE);
else
args [0] = LLVMConstInt (LLVMInt32Type (), exc_class->type_token, FALSE);
* The LLVM mono branch contains changes so a block address can be passed as an
* argument to a call.
*/
- args [1] = LLVMBuildPtrToInt (builder, LLVMBlockAddress (ctx->lmethod, ex_bb), IntPtrType (), "");
+ args [1] = LLVMBlockAddress (ctx->lmethod, ex_bb);
emit_call (ctx, bb, &builder, ctx->lmodule->throw_corlib_exception, args, 2);
LLVMBuildUnreachable (builder);
* Put the global into the 'llvm.used' array to prevent it from being optimized away.
*/
static void
-mark_as_used (LLVMModuleRef module, LLVMValueRef global)
+mark_as_used (MonoLLVMModule *lmodule, LLVMValueRef global)
{
+ if (!lmodule->used)
+ lmodule->used = g_ptr_array_sized_new (16);
+ g_ptr_array_add (lmodule->used, global);
+}
+
+static void
+emit_llvm_used (MonoLLVMModule *lmodule)
+{
+ LLVMModuleRef module = lmodule->module;
LLVMTypeRef used_type;
- LLVMValueRef used, used_elem;
+ LLVMValueRef used, *used_elem;
+ int i;
- used_type = LLVMArrayType (LLVMPointerType (LLVMInt8Type (), 0), 1);
+ if (!lmodule->used)
+ return;
+
+ used_type = LLVMArrayType (LLVMPointerType (LLVMInt8Type (), 0), lmodule->used->len);
used = LLVMAddGlobal (module, used_type, "llvm.used");
- used_elem = LLVMConstBitCast (global, LLVMPointerType (LLVMInt8Type (), 0));
- LLVMSetInitializer (used, LLVMConstArray (LLVMPointerType (LLVMInt8Type (), 0), &used_elem, 1));
+ used_elem = g_new0 (LLVMValueRef, lmodule->used->len);
+ for (i = 0; i < lmodule->used->len; ++i)
+ used_elem [i] = LLVMConstBitCast (g_ptr_array_index (lmodule->used, i), LLVMPointerType (LLVMInt8Type (), 0));
+ LLVMSetInitializer (used, LLVMConstArray (LLVMPointerType (LLVMInt8Type (), 0), used_elem, lmodule->used->len));
LLVMSetLinkage (used, LLVMAppendingLinkage);
LLVMSetSection (used, "llvm.metadata");
}
* with the "mono.this" custom metadata to tell llvm that it needs to save its
* location into the LSDA.
*/
- this_alloc = mono_llvm_build_alloca (builder, IntPtrType (), LLVMConstInt (LLVMInt32Type (), 1, FALSE), 0, "");
+ this_alloc = mono_llvm_build_alloca (builder, ThisType (), LLVMConstInt (LLVMInt32Type (), 1, FALSE), 0, "");
/* This volatile store will keep the alloca alive */
mono_llvm_build_store (builder, ctx->values [cfg->args [0]->dreg], this_alloc, TRUE);
g_assert (ctx->addresses [cfg->rgctx_var->dreg]);
rgctx_alloc = ctx->addresses [cfg->rgctx_var->dreg];
/* This volatile store will keep the alloca alive */
- store = mono_llvm_build_store (builder, ctx->rgctx_arg, rgctx_alloc, TRUE);
+ store = mono_llvm_build_store (builder, convert (ctx, ctx->rgctx_arg, IntPtrType ()), rgctx_alloc, TRUE);
set_metadata_flag (rgctx_alloc, "mono.this");
}
if (call->rgctx_arg_reg) {
g_assert (values [call->rgctx_arg_reg]);
g_assert (sinfo.rgctx_arg_pindex < nargs);
- args [sinfo.rgctx_arg_pindex] = values [call->rgctx_arg_reg];
+ args [sinfo.rgctx_arg_pindex] = convert (ctx, values [call->rgctx_arg_reg], ctx->lmodule->ptr_type);
}
if (call->imt_arg_reg) {
g_assert (values [call->imt_arg_reg]);
g_assert (sinfo.imt_arg_pindex < nargs);
- args [sinfo.imt_arg_pindex] = values [call->imt_arg_reg];
+ args [sinfo.imt_arg_pindex] = convert (ctx, values [call->imt_arg_reg], ctx->lmodule->ptr_type);
}
if (vretaddr) {
} else {
g_assert (args [pindex]);
if (i == 0 && sig->hasthis)
- args [pindex] = convert (ctx, args [pindex], IntPtrType ());
+ args [pindex] = convert (ctx, args [pindex], ThisType ());
else
args [pindex] = convert (ctx, args [pindex], type_to_llvm_arg_type (ctx, sig->params [i - sig->hasthis]));
}
lcall = emit_call (ctx, bb, &builder, callee, args, LLVMCountParamTypes (llvm_sig));
-#ifdef LLVM_MONO_BRANCH
/*
* Modify cconv and parameter attributes to pass rgctx/imt correctly.
*/
LLVMAddInstrAttribute (lcall, 1 + sinfo.rgctx_arg_pindex, LLVMInRegAttribute);
if (call->imt_arg_reg)
LLVMAddInstrAttribute (lcall, 1 + sinfo.imt_arg_pindex, LLVMInRegAttribute);
-#endif
/* Add byval attributes if needed */
for (i = 0; i < sig->param_count; ++i) {
/* We use COMPARE+SETcc/Bcc, llvm uses SETcc+br cond */
if (ins->opcode == OP_FCOMPARE)
cmp = LLVMBuildFCmp (builder, fpcond_to_llvm_cond [rel], convert (ctx, lhs, LLVMDoubleType ()), convert (ctx, rhs, LLVMDoubleType ()), "");
- else if (ins->opcode == OP_COMPARE_IMM)
- cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], convert (ctx, lhs, IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), "");
- else if (ins->opcode == OP_LCOMPARE_IMM) {
+ else if (ins->opcode == OP_COMPARE_IMM) {
+ if (LLVMGetTypeKind (LLVMTypeOf (lhs)) == LLVMPointerTypeKind && ins->inst_imm == 0)
+ cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], lhs, LLVMConstNull (LLVMTypeOf (lhs)), "");
+ else
+ cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], convert (ctx, lhs, IntPtrType ()), LLVMConstInt (IntPtrType (), ins->inst_imm, FALSE), "");
+ } else if (ins->opcode == OP_LCOMPARE_IMM) {
if (SIZEOF_REGISTER == 4 && COMPILE_LLVM (cfg)) {
/* The immediate is encoded in two fields */
guint64 l = ((guint64)(guint32)ins->inst_offset << 32) | ((guint32)ins->inst_imm);
cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], convert (ctx, lhs, LLVMInt64Type ()), LLVMConstInt (LLVMInt64Type (), ins->inst_imm, FALSE), "");
}
}
- else if (ins->opcode == OP_COMPARE)
- cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], convert (ctx, lhs, IntPtrType ()), convert (ctx, rhs, IntPtrType ()), "");
- else
+ else if (ins->opcode == OP_COMPARE) {
+ if (LLVMGetTypeKind (LLVMTypeOf (lhs)) == LLVMPointerTypeKind && LLVMTypeOf (lhs) == LLVMTypeOf (rhs))
+ cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], lhs, rhs, "");
+ else
+ cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], convert (ctx, lhs, IntPtrType ()), convert (ctx, rhs, IntPtrType ()), "");
+ } else
cmp = LLVMBuildICmp (builder, cond_to_llvm_cond [rel], lhs, rhs, "");
if (MONO_IS_COND_BRANCH_OP (ins->next)) {
case OP_AND_IMM:
case OP_MUL_IMM:
case OP_SHL_IMM:
- case OP_SHR_IMM: {
+ case OP_SHR_IMM:
+ case OP_SHR_UN_IMM: {
LLVMValueRef imm;
if (spec [MONO_INST_SRC1] == 'l') {
values [ins->dreg] = LLVMBuildLShr (builder, lhs, imm, dname);
break;
case OP_LSHR_UN_IMM:
+ case OP_SHR_UN_IMM:
values [ins->dreg] = LLVMBuildLShr (builder, lhs, imm, dname);
break;
default:
values [ins->dreg] = emit_load (ctx, bb, &builder, size, addr, dname, is_volatile);
- if (!is_volatile && (ins->flags & MONO_INST_CONSTANT_LOAD)) {
+ if (!is_volatile && (ins->flags & MONO_INST_INVARIANT_LOAD)) {
/*
* These will signal LLVM that these loads do not alias any stores, and
* they can't fail, allowing them to be hoisted out of loops.
*/
- set_metadata_flag (values [ins->dreg], "mono.noalias");
+ set_invariant_load_flag (values [ins->dreg]);
set_metadata_flag (values [ins->dreg], "mono.nofail.load");
}
indexes [1] = LLVMConstInt (LLVMInt32Type (), (gssize)got_offset, FALSE);
got_entry_addr = LLVMBuildGEP (builder, ctx->lmodule->got_var, indexes, 2, "");
- // FIXME: This doesn't work right now, because it must be
- // paired with an invariant.end, and even then, its only in effect
- // inside its basic block
-#if 0
- {
- LLVMValueRef args [3];
- LLVMValueRef ptr, val;
-
- ptr = LLVMBuildBitCast (builder, got_entry_addr, LLVMPointerType (LLVMInt8Type (), 0), "ptr");
-
- args [0] = LLVMConstInt (LLVMInt64Type (), sizeof (gpointer), FALSE);
- args [1] = ptr;
- val = LLVMBuildCall (builder, LLVMGetNamedFunction (module, "llvm.invariant.start"), args, 2, "");
- }
-#endif
-
values [ins->dreg] = LLVMBuildLoad (builder, got_entry_addr, dname);
+ set_invariant_load_flag (values [ins->dreg]);
break;
}
case OP_NOT_REACHED:
values [ins->dreg] = LLVMBuildSelect (builder, v, lhs, rhs, dname);
break;
}
- case OP_ATOMIC_EXCHANGE_I4: {
- LLVMValueRef args [2];
-
- g_assert (ins->inst_offset == 0);
-
- args [0] = convert (ctx, lhs, LLVMPointerType (LLVMInt32Type (), 0));
- args [1] = rhs;
-
- values [ins->dreg] = mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_XCHG, args [0], args [1]);
- break;
- }
+ case OP_ATOMIC_EXCHANGE_I4:
case OP_ATOMIC_EXCHANGE_I8: {
LLVMValueRef args [2];
+ LLVMTypeRef t;
+
+ if (ins->opcode == OP_ATOMIC_EXCHANGE_I4)
+ t = LLVMInt32Type ();
+ else
+ t = LLVMInt64Type ();
g_assert (ins->inst_offset == 0);
- args [0] = convert (ctx, lhs, LLVMPointerType (LLVMInt64Type (), 0));
- args [1] = convert (ctx, rhs, LLVMInt64Type ());
- values [ins->dreg] = mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_XCHG, args [0], args [1]);
- break;
- }
- case OP_ATOMIC_ADD_NEW_I4: {
- LLVMValueRef args [2];
-
- g_assert (ins->inst_offset == 0);
+ args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
+ args [1] = convert (ctx, rhs, t);
- args [0] = convert (ctx, lhs, LLVMPointerType (LLVMInt32Type (), 0));
- args [1] = rhs;
- values [ins->dreg] = LLVMBuildAdd (builder, mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_ADD, args [0], args [1]), args [1], dname);
+ values [ins->dreg] = mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_XCHG, args [0], args [1]);
break;
}
+ case OP_ATOMIC_ADD_NEW_I4:
case OP_ATOMIC_ADD_NEW_I8: {
LLVMValueRef args [2];
+ LLVMTypeRef t;
+
+ if (ins->opcode == OP_ATOMIC_ADD_NEW_I4)
+ t = LLVMInt32Type ();
+ else
+ t = LLVMInt64Type ();
g_assert (ins->inst_offset == 0);
- args [0] = convert (ctx, lhs, LLVMPointerType (LLVMInt64Type (), 0));
- args [1] = convert (ctx, rhs, LLVMInt64Type ());
+ args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
+ args [1] = convert (ctx, rhs, t);
values [ins->dreg] = LLVMBuildAdd (builder, mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_ADD, args [0], args [1]), args [1], dname);
break;
}
LLVMValueRef args [3];
LLVMTypeRef t;
- if (ins->opcode == OP_ATOMIC_CAS_I4) {
+ if (ins->opcode == OP_ATOMIC_CAS_I4)
t = LLVMInt32Type ();
- } else {
+ else
t = LLVMInt64Type ();
- }
args [0] = convert (ctx, lhs, LLVMPointerType (t, 0));
/* comparand */
// 256 == GS segment register
LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
#endif
-
// FIXME: XEN
values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, LLVMConstInt (IntPtrType (), ins->inst_offset, TRUE), ptrtype, ""), "");
+#elif defined(TARGET_AMD64) && defined(TARGET_OSX)
+ /* See mono_amd64_emit_tls_get () */
+ int offset = mono_amd64_get_tls_gs_offset () + (ins->inst_offset * 8);
+
+ // 256 == GS segment register
+ LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
+ values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, LLVMConstInt (IntPtrType (), offset, TRUE), ptrtype, ""), "");
#else
LLVM_FAILURE (ctx, "opcode tls-get");
#endif
break;
}
+ case OP_TLS_GET_REG: {
+#if defined(TARGET_AMD64) && defined(TARGET_OSX)
+ /* See emit_tls_get_reg () */
+ // 256 == GS segment register
+ LLVMTypeRef ptrtype = LLVMPointerType (IntPtrType (), 256);
+ values [ins->dreg] = LLVMBuildLoad (builder, LLVMBuildIntToPtr (builder, convert (ctx, lhs, LLVMInt32Type ()), ptrtype, ""), "");
+#else
+ LLVM_FAILURE (ctx, "opcode tls-get");
+#endif
+ break;
+ }
/*
* Overflow opcodes.
switch (ins->opcode) {
case OP_STOREV_MEMBASE:
- if (cfg->gen_write_barriers && klass->has_references && ins->inst_destbasereg != cfg->frame_reg) {
- /* FIXME: Emit write barriers like in mini_emit_stobj () */
- LLVM_FAILURE (ctx, "storev_membase + write barriers");
+ if (cfg->gen_write_barriers && klass->has_references && ins->inst_destbasereg != cfg->frame_reg &&
+ LLVMGetInstructionOpcode (values [ins->inst_destbasereg]) != LLVMAlloca) {
+ /* Decomposed earlier */
+ g_assert_not_reached ();
break;
}
if (!addresses [ins->sreg1]) {
#if 1
for (i = 0; i < header->num_clauses; ++i) {
clause = &header->clauses [i];
-
+
if (i > 0 && clause->try_offset <= header->clauses [i - 1].handler_offset + header->clauses [i - 1].handler_len) {
/*
* FIXME: Some tests still fail with nested clauses.
ctx->addresses = g_new0 (LLVMValueRef, cfg->next_vreg);
ctx->vreg_types = g_new0 (LLVMTypeRef, cfg->next_vreg);
ctx->vreg_cli_types = g_new0 (MonoType*, cfg->next_vreg);
- phi_values = g_ptr_array_new ();
+ phi_values = g_ptr_array_sized_new (256);
/*
* This signals whenever the vreg was defined by a phi node with no input vars
* (i.e. all its input bblocks end with NOT_REACHABLE).
/* Whenever the bblock is unreachable */
ctx->unreachable = g_new0 (gboolean, cfg->max_block_num);
- bblock_list = g_ptr_array_new ();
+ bblock_list = g_ptr_array_sized_new (256);
ctx->values = values;
ctx->region_to_handler = g_hash_table_new (NULL, NULL);
method = LLVMAddFunction (module, method_name, method_type);
ctx->lmethod = method;
-#ifdef LLVM_MONO_BRANCH
LLVMSetFunctionCallConv (method, LLVMMono1CallConv);
-#endif
LLVMSetLinkage (method, LLVMPrivateLinkage);
LLVMAddFunctionAttr (method, LLVMUWTable);
if (cfg->verbose_level > 1)
mono_llvm_dump_value (method);
- mark_as_used (module, method);
+ if (cfg->compile_aot)
+ mark_as_used (ctx->lmodule, method);
if (cfg->compile_aot) {
LLVMValueRef md_args [16];
* with it.
*/
cfg->encoded_unwind_ops = mono_unwind_decode_fde ((guint8*)data, &cfg->encoded_unwind_ops_len, NULL, &ei, &ei_len, &type_info, &this_reg, &this_offset);
+ if (cfg->verbose_level > 1)
+ mono_print_unwind_info (cfg->encoded_unwind_ops, cfg->encoded_unwind_ops_len);
/* Count nested clauses */
nested_len = 0;
LLVMAddFunction (module, "llvm.umul.with.overflow.i64", LLVMFunctionType (LLVMStructType (ovf_res_i64, 2, FALSE), ovf_params_i64, 2, FALSE));
}
- {
- LLVMTypeRef struct_ptr = LLVMPointerType (LLVMStructType (NULL, 0, FALSE), 0);
- LLVMTypeRef invariant_start_params [] = { LLVMInt64Type (), LLVMPointerType (LLVMInt8Type (), 0) };
- LLVMTypeRef invariant_end_params [] = { struct_ptr, LLVMInt64Type (), LLVMPointerType (LLVMInt8Type (), 0) };
-
- LLVMAddFunction (module, "llvm.invariant.start", LLVMFunctionType (struct_ptr, invariant_start_params, 2, FALSE));
-
- LLVMAddFunction (module, "llvm.invariant.end", LLVMFunctionType (LLVMVoidType (), invariant_end_params, 3, FALSE));
- }
-
/* EH intrinsics */
{
LLVMTypeRef arg_types [2];
}
/* SSE intrinsics */
+#if defined(TARGET_X86) || defined(TARGET_AMD64)
{
LLVMTypeRef ret_type, arg_types [16];
}
AddFunc (module, "llvm.x86.sse2.pause", LLVMVoidType (), NULL, 0);
+#endif
/* Load/Store intrinsics */
{
}
}
+static void
+add_types (MonoLLVMModule *lmodule)
+{
+ lmodule->ptr_type = LLVMPointerType (sizeof (gpointer) == 8 ? LLVMInt64Type () : LLVMInt32Type (), 0);
+}
+
void
mono_llvm_init (void)
{
ee = mono_llvm_create_ee (LLVMCreateModuleProviderForExistingModule (jit_module.module), alloc_cb, emitted_cb, exception_cb, dlsym_cb);
add_intrinsics (jit_module.module);
+ add_types (&jit_module);
jit_module.llvm_types = g_hash_table_new (NULL, NULL);
aot_module.got_symbol = got_symbol;
add_intrinsics (aot_module.module);
+ add_types (&aot_module);
/* Add GOT */
/*
* its size is known in mono_llvm_emit_aot_module ().
*/
{
- LLVMTypeRef got_type = LLVMArrayType (IntPtrType (), 0);
+ LLVMTypeRef got_type = LLVMArrayType (aot_module.ptr_type, 0);
aot_module.got_var = LLVMAddGlobal (aot_module.module, got_type, "mono_dummy_got");
LLVMSetInitializer (aot_module.got_var, LLVMConstNull (got_type));
* Create the real got variable and replace all uses of the dummy variable with
* the real one.
*/
- got_type = LLVMArrayType (IntPtrType (), got_size);
+ got_type = LLVMArrayType (aot_module.ptr_type, got_size);
real_got = LLVMAddGlobal (aot_module.module, got_type, aot_module.got_symbol);
LLVMSetInitializer (real_got, LLVMConstNull (got_type));
LLVMSetLinkage (real_got, LLVMInternalLinkage);
mono_llvm_replace_uses_of (aot_module.got_var, real_got);
- mark_as_used (aot_module.module, real_got);
+ mark_as_used (&aot_module, real_got);
/* Delete the dummy got so it doesn't become a global */
LLVMDeleteGlobal (aot_module.got_var);
+ emit_llvm_used (&aot_module);
+
#if 0
{
char *verifier_err;
static int tls_mode = TLS_MODE_DETECT;
static int lmf_pthread_key = -1;
static int monothread_key = -1;
-static int monodomain_key = -1;
/* Whenever the host is little-endian */
static int little_endian;
}
#endif
}
- if (monodomain_key == -1) {
- ptk = mono_domain_get_tls_key ();
- if (ptk < 1024)
- monodomain_key = ptk;
- }
if (lmf_pthread_key == -1) {
ptk = mono_jit_tls_id;
if (ptk < 1024) {
return 0;
}
-MonoInst* mono_arch_get_domain_intrinsic (MonoCompile* cfg)
-{
- MonoInst* ins;
-
- setup_tls_access ();
- if (monodomain_key == -1)
- return NULL;
-
- MONO_INST_NEW (cfg, ins, OP_TLS_GET);
- ins->inst_offset = monodomain_key;
- return ins;
-}
-
mgreg_t
mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
{
return NULL;
}
+void
+mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
+{
+ ext->lmf.previous_lmf = prev_lmf;
+ /* Mark that this is a MonoLMFExt */
+ ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
+ ext->lmf.iregs [mips_sp] = (gssize)ext;
+}
+
#endif /* MONO_ARCH_SOFT_DEBUG_SUPPORTED */
MINI_OP(OP_IMPLICIT_EXCEPTION, "implicit_exception", NONE, NONE, NONE)
MINI_OP(OP_VOIDCALL, "voidcall", NONE, NONE, NONE)
-MINI_OP(OP_VOIDCALLVIRT, "voidcallvirt", NONE, NONE, NONE)
MINI_OP(OP_VOIDCALL_REG, "voidcall_reg", NONE, IREG, NONE)
MINI_OP(OP_VOIDCALL_MEMBASE, "voidcall_membase", NONE, IREG, NONE)
MINI_OP(OP_CALL, "call", IREG, NONE, NONE)
MINI_OP(OP_CALL_REG, "call_reg", IREG, IREG, NONE)
MINI_OP(OP_CALL_MEMBASE, "call_membase", IREG, IREG, NONE)
-MINI_OP(OP_CALLVIRT, "callvirt", IREG, NONE, NONE)
MINI_OP(OP_FCALL, "fcall", FREG, NONE, NONE)
-MINI_OP(OP_FCALLVIRT, "fcallvirt", FREG, NONE, NONE)
MINI_OP(OP_FCALL_REG, "fcall_reg", FREG, IREG, NONE)
MINI_OP(OP_FCALL_MEMBASE, "fcall_membase", FREG, IREG, NONE)
MINI_OP(OP_LCALL, "lcall", LREG, NONE, NONE)
-MINI_OP(OP_LCALLVIRT, "lcallvirt", LREG, NONE, NONE)
MINI_OP(OP_LCALL_REG, "lcall_reg", LREG, IREG, NONE)
MINI_OP(OP_LCALL_MEMBASE, "lcall_membase", LREG, IREG, NONE)
MINI_OP(OP_VCALL, "vcall", VREG, NONE, NONE)
-MINI_OP(OP_VCALLVIRT, "vcallvirt", VREG, NONE, NONE)
MINI_OP(OP_VCALL_REG, "vcall_reg", VREG, IREG, NONE)
MINI_OP(OP_VCALL_MEMBASE, "vcall_membase", VREG, IREG, NONE)
/* Represents the decomposed vcall which doesn't return a vtype no more */
MINI_OP(OP_ICLT, "int_clt", IREG, NONE, NONE)
MINI_OP(OP_ICLT_UN,"int_clt_un", IREG, NONE, NONE)
+MINI_OP(OP_ICNEQ, "int_cneq", IREG, NONE, NONE)
+MINI_OP(OP_ICGE, "int_cge", IREG, NONE, NONE)
+MINI_OP(OP_ICLE, "int_cle", IREG, NONE, NONE)
+MINI_OP(OP_ICGE_UN,"int_cge_un", IREG, NONE, NONE)
+MINI_OP(OP_ICLE_UN,"int_cle_un", IREG, NONE, NONE)
+
MINI_OP(OP_IBEQ, "int_beq", NONE, NONE, NONE)
MINI_OP(OP_IBGE, "int_bge", NONE, NONE, NONE)
MINI_OP(OP_IBGT, "int_bgt", NONE, NONE, NONE)
MINI_OP(OP_FCLT, "float_clt", IREG, FREG, FREG)
MINI_OP(OP_FCLT_UN,"float_clt_un", IREG, FREG, FREG)
+MINI_OP(OP_FCNEQ, "float_cneq", IREG, FREG, FREG)
+MINI_OP(OP_FCGE, "float_cge", IREG, FREG, FREG)
+MINI_OP(OP_FCLE, "float_cle", IREG, FREG, FREG)
+
MINI_OP(OP_FCEQ_MEMBASE, "float_ceq_membase", IREG, FREG, IREG)
MINI_OP(OP_FCGT_MEMBASE, "float_cgt_membase", IREG, FREG, IREG)
MINI_OP(OP_FCGT_UN_MEMBASE,"float_cgt_un_membase", IREG, FREG, IREG)
/* arch-dep tls access */
MINI_OP(OP_TLS_GET, "tls_get", IREG, NONE, NONE)
-MINI_OP(OP_TLS_GET_REG, "tls_get_reg", IREG, IREG, NONE)
+MINI_OP(OP_TLS_GET_REG, "tls_get_reg", IREG, IREG, NONE)
+/* inst_offset contains the TLS offset */
+MINI_OP(OP_TLS_SET, "tls_set", NONE, IREG, NONE)
+MINI_OP(OP_TLS_SET_REG, "tls_set_reg", NONE, IREG, IREG)
MINI_OP(OP_LOAD_GOTADDR, "load_gotaddr", IREG, NONE, NONE)
MINI_OP(OP_DUMMY_USE, "dummy_use", NONE, IREG, NONE)
int mono_exc_esp_offset = 0;
static int tls_mode = TLS_MODE_DETECT;
static int lmf_pthread_key = -1;
-static int monodomain_key = -1;
/*
* The code generated for sequence points reads from this location, which is
}
gboolean
-mono_ppc_tail_call_supported (MonoMethodSignature *caller_sig, MonoMethodSignature *callee_sig)
+mono_arch_tail_call_supported (MonoMethodSignature *caller_sig, MonoMethodSignature *callee_sig)
{
CallInfo *c1, *c2;
gboolean res;
case MONO_PATCH_INFO_ABS:
case MONO_PATCH_INFO_CLASS_INIT:
case MONO_PATCH_INFO_RGCTX_FETCH:
+ case MONO_PATCH_INFO_JIT_ICALL_ADDR:
is_fd = TRUE;
break;
#endif
static void
setup_tls_access (void)
{
- guint32 ptk;
-
#if defined(__linux__) && defined(_CS_GNU_LIBPTHREAD_VERSION)
size_t conf_size = 0;
char confbuf[128];
ppc_blr (code);
if (*ins == cmplwi_1023) {
int found_lwz_284 = 0;
+ guint32 ptk;
for (ptk = 0; ptk < 20; ++ptk) {
++ins;
if (!*ins || *ins == blr_ins)
tls_mode = TLS_MODE_FAILED;
if (tls_mode == TLS_MODE_FAILED)
return;
- if ((monodomain_key == -1) && (tls_mode == TLS_MODE_NPTL)) {
- monodomain_key = mono_domain_get_tls_offset();
- }
- /* if not TLS_MODE_NPTL or local dynamic (as indicated by
- mono_domain_get_tls_offset returning -1) then use keyed access. */
- if (monodomain_key == -1) {
- ptk = mono_domain_get_tls_key ();
- if (ptk < 1024)
- monodomain_key = ptk;
- }
-
if ((lmf_pthread_key == -1) && (tls_mode == TLS_MODE_NPTL)) {
lmf_pthread_key = mono_get_lmf_addr_tls_offset();
}
/* if not TLS_MODE_NPTL or local dynamic (as indicated by
mono_get_lmf_addr_tls_offset returning -1) then use keyed access. */
if (lmf_pthread_key == -1) {
- ptk = mono_jit_tls_id;
+ guint32 ptk = mono_jit_tls_id;
if (ptk < 1024) {
/*g_print ("MonoLMF at: %d\n", ptk);*/
/*if (!try_offset_access (mono_get_lmf_addr (), ptk)) {
return 0;
}
-MonoInst* mono_arch_get_domain_intrinsic (MonoCompile* cfg)
-{
- MonoInst* ins;
-
- setup_tls_access ();
- if (monodomain_key == -1)
- return NULL;
-
- MONO_INST_NEW (cfg, ins, OP_TLS_GET);
- ins->inst_offset = monodomain_key;
- return ins;
-}
-
mgreg_t
mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
{
return NULL;
}
+void
+mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
+{
+ ext->lmf.previous_lmf = prev_lmf;
+ /* Mark that this is a MonoLMFExt */
+ ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
+ ext->lmf.ebp = (gssize)ext;
+}
+
#endif
#define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
#endif
#define MONO_ARCH_THIS_AS_FIRST_ARG 1
+#define MONO_ARCH_HAVE_OP_TAIL_CALL 1
#define PPC_NUM_REG_ARGS (PPC_LAST_ARG_REG-PPC_FIRST_ARG_REG+1)
#define PPC_NUM_REG_FPARGS (PPC_LAST_FPARG_REG-PPC_FIRST_FPARG_REG+1)
gboolean
mono_ppc_tail_call_supported (MonoMethodSignature *caller_sig, MonoMethodSignature *callee_sig) MONO_INTERNAL;
-#define MONO_ARCH_USE_OP_TAIL_CALL(caller_sig, callee_sig) mono_ppc_tail_call_supported (caller_sig, callee_sig)
-
void
mono_ppc_patch (guchar *code, const guchar *target) MONO_INTERNAL;
mono_method_signature (method)->ret->type);
}
- ip = ((gint64) __builtin_return_address (0));
+ ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
printf (" ip: %p\n", (gpointer) ip);
}
/*========================= End of Function ========================*/
-/*------------------------------------------------------------------*/
-/* */
-/* Name - mono_arch_get_domain_intrinsic */
-/* */
-/* Function - */
-/* */
-/* Returns - */
-/* */
-/*------------------------------------------------------------------*/
-
-MonoInst *
-mono_arch_get_domain_intrinsic (MonoCompile* cfg)
-{
- MonoInst *ins;
-
- if (appdomain_tls_offset == -1)
- return NULL;
-
- MONO_INST_NEW (cfg, ins, OP_TLS_GET);
- ins->inst_offset = appdomain_tls_offset;
- return (ins);
-}
-
-/*========================= End of Function ========================*/
-
/*------------------------------------------------------------------*/
/* */
/* Name - mono_arch_flush_register_windows */
return NULL;
}
+/*------------------------------------------------------------------*/
+/* */
+/* Name - mono_arch_init_lmf_ext. */
+/* */
+/* Function - */
+/* */
+/*------------------------------------------------------------------*/
+
+void
+mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
+{
+ ext->lmf.previous_lmf = prev_lmf;
+ /* Mark that this is a MonoLMFExt */
+ ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
+ ext->lmf.ebp = (gssize)ext;
+}
+
/*========================= End of Function ========================*/
#endif
return 0;
}
-MonoInst* mono_arch_get_domain_intrinsic (MonoCompile* cfg)
-{
- return NULL;
-}
-
mgreg_t
mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
{
#include <mono/utils/mono-membar.h>
#include "mini.h"
-#include "debug-mini.h"
/*
* Address of the trampoline code. This is used by the debugger to check
addr = compiled_method = mono_compile_method (m);
g_assert (addr);
- mono_debugger_trampoline_compiled (code, m, addr);
-
if (generic_virtual || variant_iface) {
if (vt->klass->valuetype) /*FIXME is this required variant iface?*/
need_unbox_tramp = TRUE;
addr = mono_compile_method (m);
g_assert (addr);
- mono_debugger_trampoline_compiled (NULL, m, addr);
-
return addr;
}
#endif
delegate->method_ptr = addr;
if (enable_caching && delegate->method_code)
*delegate->method_code = delegate->method_ptr;
- mono_debugger_trampoline_compiled (NULL, method, delegate->method_ptr);
}
} else {
if (need_rgctx_tramp)
code = mono_compile_method (m);
code = mini_add_method_trampoline (NULL, m, code, mono_method_needs_static_rgctx_invoke (m, FALSE), FALSE);
delegate->invoke_impl = mono_get_addr_from_ftnptr (code);
- mono_debugger_trampoline_compiled (NULL, m, delegate->invoke_impl);
return code;
}
GSList* mono_unwind_get_cie_program (void) MONO_INTERNAL;
+void mono_print_unwind_info (guint8 *unwind_info, int unwind_info_len) MONO_INTERNAL;
+
#endif
#include "mini-gc.h"
/* On windows, these hold the key returned by TlsAlloc () */
-static gint lmf_tls_offset = -1;
#ifdef TARGET_WIN32
static gint jit_tls_offset = -1;
#else
static gint lmf_addr_tls_offset = -1;
#endif
-static gint appdomain_tls_offset = -1;
#ifdef MONO_XEN_OPT
static gboolean optimize_for_xen = TRUE;
#define optimize_for_xen 0
#endif
-#ifdef TARGET_WIN32
-static gboolean is_win32 = TRUE;
-#else
-static gboolean is_win32 = FALSE;
-#endif
-
/* This mutex protects architecture specific caches */
#define mono_mini_arch_lock() EnterCriticalSection (&mini_arch_mutex)
#define mono_mini_arch_unlock() LeaveCriticalSection (&mini_arch_mutex)
MonoBreakpointInfo
mono_breakpoint_info [MONO_BREAKPOINT_ARRAY_SIZE];
+static guint8*
+emit_load_aotconst (guint8 *start, guint8 *code, MonoCompile *cfg, MonoJumpInfo **ji, int dreg, int tramp_type, gconstpointer target);
#ifdef __native_client_codegen__
ainfo->pair_storage [0] = ainfo->pair_storage [1] = ArgNone;
/* Special case structs with only a float member */
- if ((info->native_size == 8) && (info->num_fields == 1) && (info->fields [0].field->type->type == MONO_TYPE_R8)) {
- ainfo->storage = ArgValuetypeInReg;
- ainfo->pair_storage [0] = ArgOnDoubleFpStack;
- return;
+ if (info->num_fields == 1) {
+ int ftype = mini_type_get_underlying_type (NULL, info->fields [0].field->type)->type;
+ if ((info->native_size == 8) && (ftype == MONO_TYPE_R8)) {
+ ainfo->storage = ArgValuetypeInReg;
+ ainfo->pair_storage [0] = ArgOnDoubleFpStack;
+ return;
+ }
+ if ((info->native_size == 4) && (ftype == MONO_TYPE_R4)) {
+ ainfo->storage = ArgValuetypeInReg;
+ ainfo->pair_storage [0] = ArgOnFloatFpStack;
+ return;
+ }
}
- if ((info->native_size == 4) && (info->num_fields == 1) && (info->fields [0].field->type->type == MONO_TYPE_R4)) {
- ainfo->storage = ArgValuetypeInReg;
- ainfo->pair_storage [0] = ArgOnFloatFpStack;
- return;
- }
if ((info->native_size == 1) || (info->native_size == 2) || (info->native_size == 4) || (info->native_size == 8)) {
ainfo->storage = ArgValuetypeInReg;
ainfo->pair_storage [0] = ArgInIReg;
case MONO_TYPE_TYPEDBYREF: {
guint32 tmp_gr = 0, tmp_fr = 0, tmp_stacksize = 0;
- add_valuetype (gsctx, sig, &cinfo->ret, sig->ret, TRUE, &tmp_gr, NULL, &tmp_fr, &tmp_stacksize);
+ add_valuetype (gsctx, sig, &cinfo->ret, ret_type, TRUE, &tmp_gr, NULL, &tmp_fr, &tmp_stacksize);
if (cinfo->ret.storage == ArgOnStack) {
cinfo->vtype_retaddr = TRUE;
/* The caller passes the address where the value is stored */
cinfo->ret.storage = ArgNone;
break;
default:
- g_error ("Can't handle as return value 0x%x", sig->ret->type);
+ g_error ("Can't handle as return value 0x%x", ret_type->type);
}
}
}
gboolean
-mono_x86_tail_call_supported (MonoMethodSignature *caller_sig, MonoMethodSignature *callee_sig)
+mono_arch_tail_call_supported (MonoMethodSignature *caller_sig, MonoMethodSignature *callee_sig)
{
+ MonoType *callee_ret;
CallInfo *c1, *c2;
gboolean res;
c1 = get_call_info (NULL, NULL, caller_sig);
c2 = get_call_info (NULL, NULL, callee_sig);
+ /*
+ * Tail calls with more callee stack usage than the caller cannot be supported, since
+ * the extra stack space would be left on the stack after the tail call.
+ */
res = c1->stack_usage >= c2->stack_usage;
- if (callee_sig->ret && MONO_TYPE_ISSTRUCT (callee_sig->ret) && c2->ret.storage != ArgValuetypeInReg)
+ callee_ret = mini_type_get_underlying_type (NULL, callee_sig->ret);
+ if (callee_ret && MONO_TYPE_ISSTRUCT (callee_ret) && c2->ret.storage != ArgValuetypeInReg)
/* An address on the callee's stack is passed as the first argument */
res = FALSE;
/* Reserve space to save LMF and caller saved registers */
if (cfg->method->save_lmf) {
- offset += sizeof (MonoLMF);
+ /* The LMF var is allocated normally */
} else {
if (cfg->used_int_regs & (1 << X86_EBX)) {
offset += 4;
void
mono_arch_create_vars (MonoCompile *cfg)
{
+ MonoType *sig_ret;
MonoMethodSignature *sig;
CallInfo *cinfo;
sig = mono_method_signature (cfg->method);
cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig);
+ sig_ret = mini_type_get_underlying_type (NULL, sig->ret);
if (cinfo->ret.storage == ArgValuetypeInReg)
cfg->ret_var_is_local = TRUE;
- if ((cinfo->ret.storage != ArgValuetypeInReg) && (MONO_TYPE_ISSTRUCT (sig->ret) || mini_is_gsharedvt_variable_type (cfg, sig->ret))) {
+ if ((cinfo->ret.storage != ArgValuetypeInReg) && (MONO_TYPE_ISSTRUCT (sig_ret) || mini_is_gsharedvt_variable_type (cfg, sig_ret))) {
cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
}
+ if (cfg->method->save_lmf) {
+ cfg->create_lmf_var = TRUE;
+#ifndef HOST_WIN32
+ if (!optimize_for_xen) {
+ cfg->lmf_ir = TRUE;
+ cfg->lmf_ir_mono_lmf = TRUE;
+ }
+#endif
+ }
+
cfg->arch_eh_jit_info = 1;
}
CallInfo *cinfo;
ArgInfo *ainfo;
LLVMCallInfo *linfo;
- MonoType *t;
+ MonoType *t, *sig_ret;
n = sig->param_count + sig->hasthis;
cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig);
+ sig_ret = sig->ret;
linfo = mono_mempool_alloc0 (cfg->mempool, sizeof (LLVMCallInfo) + (sizeof (LLVMArgInfo) * n));
*/
}
- if (mini_type_is_vtype (cfg, sig->ret) && cinfo->ret.storage == ArgInIReg) {
+ if (mini_type_is_vtype (cfg, sig_ret) && cinfo->ret.storage == ArgInIReg) {
/* Vtype returned using a hidden argument */
linfo->ret.storage = LLVMArgVtypeRetAddr;
linfo->vret_arg_index = cinfo->vret_arg_index;
}
- if (mini_type_is_vtype (cfg, sig->ret) && cinfo->ret.storage != ArgInIReg) {
+ if (mini_type_is_vtype (cfg, sig_ret) && cinfo->ret.storage != ArgInIReg) {
// FIXME:
cfg->exception_message = g_strdup ("vtype ret in call");
cfg->disable_llvm = TRUE;
void
mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
{
+ MonoType *sig_ret;
MonoInst *arg, *in;
MonoMethodSignature *sig;
int i, j, n;
sig = call->signature;
n = sig->param_count + sig->hasthis;
+ sig_ret = mini_type_get_underlying_type (NULL, sig->ret);
cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig);
}
}
- if (sig->ret && MONO_TYPE_ISSTRUCT (sig->ret)) {
+ if (sig_ret && MONO_TYPE_ISSTRUCT (sig_ret)) {
if (cinfo->ret.storage == ArgValuetypeInReg) {
/*
* Tell the JIT to use a more efficient calling convention: call using
arg->opcode = OP_OUTARG_VT;
arg->sreg1 = in->dreg;
arg->klass = in->klass;
+ arg->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
+ memcpy (arg->inst_p1, ainfo, sizeof (ArgInfo));
sp_offset += 4;
MONO_ADD_INS (cfg->cbb, arg);
} else if ((i >= sig->hasthis) && (MONO_TYPE_ISSTRUCT(t))) {
}
}
- if (sig->ret && (MONO_TYPE_ISSTRUCT (sig->ret) || cinfo->vtype_retaddr)) {
+ if (sig_ret && (MONO_TYPE_ISSTRUCT (sig_ret) || cinfo->vtype_retaddr)) {
MonoInst *vtarg;
if (cinfo->ret.storage == ArgValuetypeInReg) {
return code;
}
+static guint8*
+emit_tls_get_reg (guint8* code, int dreg, int offset_reg)
+{
+ /* offset_reg contains a value translated by mono_arch_translate_tls_offset () */
+#if defined(__APPLE__) || defined(__linux__)
+ if (dreg != offset_reg)
+ x86_mov_reg_reg (code, dreg, offset_reg, sizeof (mgreg_t));
+ x86_prefix (code, X86_GS_PREFIX);
+ x86_mov_reg_membase (code, dreg, dreg, 0, sizeof (mgreg_t));
+#else
+ g_assert_not_reached ();
+#endif
+ return code;
+}
+
+static guint8*
+emit_tls_set_reg (guint8* code, int sreg, int offset_reg)
+{
+ /* offset_reg contains a value translated by mono_arch_translate_tls_offset () */
+#ifdef HOST_WIN32
+ g_assert_not_reached ();
+#elif defined(__APPLE__) || defined(__linux__)
+ x86_prefix (code, X86_GS_PREFIX);
+ x86_mov_membase_reg (code, offset_reg, 0, sreg, sizeof (mgreg_t));
+#else
+ g_assert_not_reached ();
+#endif
+ return code;
+}
+
+ /*
+ * mono_arch_translate_tls_offset:
+ *
+ * Translate the TLS offset OFFSET computed by MONO_THREAD_VAR_OFFSET () into a format usable by OP_TLS_GET_REG/OP_TLS_SET_REG.
+ */
+int
+mono_arch_translate_tls_offset (int offset)
+{
+#ifdef __APPLE__
+ return tls_gs_offset + (offset * 4);
+#else
+ return offset;
+#endif
+}
+
/*
- * emit_load_volatile_arguments:
+ * emit_setup_lmf:
*
- * Load volatile arguments from the stack to the original input registers.
- * Required before a tail call.
+ * Emit code to initialize an LMF structure at LMF_OFFSET.
*/
static guint8*
-emit_load_volatile_arguments (MonoCompile *cfg, guint8 *code)
+emit_setup_lmf (MonoCompile *cfg, guint8 *code, gint32 lmf_offset, int cfa_offset)
{
- MonoMethod *method = cfg->method;
- MonoMethodSignature *sig;
- MonoInst *inst;
- CallInfo *cinfo;
- guint32 i;
+ /* save all caller saved regs */
+ x86_mov_membase_reg (code, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, ebx), X86_EBX, sizeof (mgreg_t));
+ mono_emit_unwind_op_offset (cfg, code, X86_EBX, - cfa_offset + lmf_offset + G_STRUCT_OFFSET (MonoLMF, ebx));
+ x86_mov_membase_reg (code, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, edi), X86_EDI, sizeof (mgreg_t));
+ mono_emit_unwind_op_offset (cfg, code, X86_EDI, - cfa_offset + lmf_offset + G_STRUCT_OFFSET (MonoLMF, edi));
+ x86_mov_membase_reg (code, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, esi), X86_ESI, sizeof (mgreg_t));
+ mono_emit_unwind_op_offset (cfg, code, X86_ESI, - cfa_offset + lmf_offset + G_STRUCT_OFFSET (MonoLMF, esi));
+ x86_mov_membase_reg (code, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, ebp), X86_EBP, sizeof (mgreg_t));
+
+ /* save the current IP */
+ if (cfg->compile_aot) {
+ /* This pushes the current ip */
+ x86_call_imm (code, 0);
+ x86_pop_reg (code, X86_EAX);
+ } else {
+ mono_add_patch_info (cfg, code + 1 - cfg->native_code, MONO_PATCH_INFO_IP, NULL);
+ x86_mov_reg_imm (code, X86_EAX, 0);
+ }
+ x86_mov_membase_reg (code, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, eip), X86_EAX, sizeof (mgreg_t));
+
+ mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset + lmf_offset + G_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
+ mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset + lmf_offset + G_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
+ mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset + lmf_offset + G_STRUCT_OFFSET (MonoLMF, esi), SLOT_NOREF);
+ mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset + lmf_offset + G_STRUCT_OFFSET (MonoLMF, edi), SLOT_NOREF);
+ mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset + lmf_offset + G_STRUCT_OFFSET (MonoLMF, ebx), SLOT_NOREF);
+ mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset + lmf_offset + G_STRUCT_OFFSET (MonoLMF, esp), SLOT_NOREF);
+ mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset + lmf_offset + G_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
+ mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset + lmf_offset + G_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
+ mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset + lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
- /* FIXME: Generate intermediate code instead */
+ return code;
+}
- sig = mono_method_signature (method);
+/*
+ * emit_push_lmf:
+ *
+ * Emit code to push an LMF structure on the LMF stack.
+ */
+static guint8*
+emit_push_lmf (MonoCompile *cfg, guint8 *code, gint32 lmf_offset)
+{
+ /* get the address of lmf for the current thread */
+ /*
+ * This is performance critical so we try to use some tricks to make
+ * it fast.
+ */
+ gboolean have_fastpath = FALSE;
- cinfo = get_call_info (cfg->generic_sharing_context, cfg->mempool, sig);
-
- /* This is the opposite of the code in emit_prolog */
+#ifdef TARGET_WIN32
+ if (jit_tls_offset != -1) {
+ code = mono_x86_emit_tls_get (code, X86_EAX, jit_tls_offset);
+ x86_alu_reg_imm (code, X86_ADD, X86_EAX, G_STRUCT_OFFSET (MonoJitTlsData, lmf));
+ have_fastpath = TRUE;
+ }
+#else
+ if (!cfg->compile_aot && lmf_addr_tls_offset != -1) {
+ code = mono_x86_emit_tls_get (code, X86_EAX, lmf_addr_tls_offset);
+ have_fastpath = TRUE;
+ }
+#endif
+ if (!have_fastpath) {
+ if (cfg->compile_aot)
+ code = mono_arch_emit_load_got_addr (cfg->native_code, code, cfg, NULL);
+ code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_get_lmf_addr");
+ }
- for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
- ArgInfo *ainfo = cinfo->args + i;
- MonoType *arg_type;
- inst = cfg->args [i];
+ /* save lmf_addr */
+ x86_mov_membase_reg (code, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, lmf_addr), X86_EAX, sizeof (mgreg_t));
+ /* save previous_lmf */
+ x86_mov_reg_membase (code, X86_ECX, X86_EAX, 0, sizeof (mgreg_t));
+ x86_mov_membase_reg (code, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), X86_ECX, sizeof (mgreg_t));
+ /* set new LMF */
+ x86_lea_membase (code, X86_ECX, cfg->frame_reg, lmf_offset);
+ x86_mov_membase_reg (code, X86_EAX, 0, X86_ECX, sizeof (mgreg_t));
- if (sig->hasthis && (i == 0))
- arg_type = &mono_defaults.object_class->byval_arg;
- else
- arg_type = sig->params [i - sig->hasthis];
+ return code;
+}
- /*
- * On x86, the arguments are either in their original stack locations, or in
- * global regs.
- */
- if (inst->opcode == OP_REGVAR) {
- g_assert (ainfo->storage == ArgOnStack);
-
- x86_mov_membase_reg (code, X86_EBP, inst->inst_offset, inst->dreg, 4);
- }
+/*
+ * emit_pop_lmf:
+ *
+ * Emit code to pop an LMF structure from the LMF stack.
+ * Preserves the return registers.
+ */
+static guint8*
+emit_pop_lmf (MonoCompile *cfg, guint8 *code, gint32 lmf_offset)
+{
+ MonoMethodSignature *sig = mono_method_signature (cfg->method);
+ int prev_lmf_reg;
+
+ /* Find a spare register */
+ switch (mini_type_get_underlying_type (cfg->generic_sharing_context, sig->ret)->type) {
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+ prev_lmf_reg = X86_EDI;
+ cfg->used_int_regs |= (1 << X86_EDI);
+ break;
+ default:
+ prev_lmf_reg = X86_EDX;
+ break;
}
+ /* reg = previous_lmf */
+ x86_mov_reg_membase (code, prev_lmf_reg, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), 4);
+
+ /* ecx = lmf */
+ x86_mov_reg_membase (code, X86_ECX, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, lmf_addr), 4);
+
+ /* *(lmf) = previous_lmf */
+ x86_mov_membase_reg (code, X86_ECX, 0, prev_lmf_reg, 4);
+
return code;
}
case OP_MOVE:
x86_mov_reg_reg (code, ins->dreg, ins->sreg1, 4);
break;
- case OP_JMP: {
- /*
- * Note: this 'frame destruction' logic is useful for tail calls, too.
- * Keep in sync with the code in emit_epilog.
- */
- int pos = 0;
-
- /* FIXME: no tracing support... */
- if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
- code = mono_arch_instrument_epilog (cfg, mono_profiler_method_leave, code, FALSE);
- /* reset offset to make max_len work */
- offset = code - cfg->native_code;
-
- g_assert (!cfg->method->save_lmf);
-
- code = emit_load_volatile_arguments (cfg, code);
-
- if (cfg->used_int_regs & (1 << X86_EBX))
- pos -= 4;
- if (cfg->used_int_regs & (1 << X86_EDI))
- pos -= 4;
- if (cfg->used_int_regs & (1 << X86_ESI))
- pos -= 4;
- if (pos)
- x86_lea_membase (code, X86_ESP, X86_EBP, pos);
-
- if (cfg->used_int_regs & (1 << X86_ESI))
- x86_pop_reg (code, X86_ESI);
- if (cfg->used_int_regs & (1 << X86_EDI))
- x86_pop_reg (code, X86_EDI);
- if (cfg->used_int_regs & (1 << X86_EBX))
- x86_pop_reg (code, X86_EBX);
-
- /* restore ESP/EBP */
- x86_leave (code);
- offset = code - cfg->native_code;
- mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_METHOD_JUMP, ins->inst_p0);
- x86_jump32 (code, 0);
-
- cfg->disable_aot = TRUE;
- break;
- }
case OP_TAILCALL: {
MonoCallInst *call = (MonoCallInst*)ins;
int pos = 0, i;
g_assert (!cfg->method->save_lmf);
- //code = emit_load_volatile_arguments (cfg, code);
-
/* restore callee saved registers */
for (i = 0; i < X86_NREG; ++i)
if (X86_IS_CALLEE_SAVED_REG (i) && cfg->used_int_regs & (1 << i))
case OP_BR_REG:
x86_jump_reg (code, ins->sreg1);
break;
+ case OP_ICNEQ:
+ case OP_ICGE:
+ case OP_ICLE:
+ case OP_ICGE_UN:
+ case OP_ICLE_UN:
+
case OP_CEQ:
case OP_CLT:
case OP_CLT_UN:
x86_alu_reg_imm (code, X86_AND, X86_EAX, X86_FP_CC_MASK);
break;
case OP_FCEQ:
+ case OP_FCNEQ:
if (cfg->opt & MONO_OPT_FCMOV) {
/* zeroing the register at the start results in
* shorter and faster code (we can also remove the widening op)
x86_fstp (code, 0);
unordered_check = code;
x86_branch8 (code, X86_CC_P, 0, FALSE);
- x86_set_reg (code, X86_CC_EQ, ins->dreg, FALSE);
- x86_patch (unordered_check, code);
+ if (ins->opcode == OP_FCEQ) {
+ x86_set_reg (code, X86_CC_EQ, ins->dreg, FALSE);
+ x86_patch (unordered_check, code);
+ } else {
+ guchar *jump_to_end;
+ x86_set_reg (code, X86_CC_NE, ins->dreg, FALSE);
+ jump_to_end = code;
+ x86_jump8 (code, 0);
+ x86_patch (unordered_check, code);
+ x86_inc_reg (code, ins->dreg);
+ x86_patch (jump_to_end, code);
+ }
+
break;
}
if (ins->dreg != X86_EAX)
EMIT_FPCOMPARE(code);
x86_alu_reg_imm (code, X86_AND, X86_EAX, X86_FP_CC_MASK);
x86_alu_reg_imm (code, X86_CMP, X86_EAX, 0x4000);
- x86_set_reg (code, X86_CC_EQ, ins->dreg, TRUE);
+ x86_set_reg (code, ins->opcode == OP_FCEQ ? X86_CC_EQ : X86_CC_NE, ins->dreg, TRUE);
x86_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
if (ins->dreg != X86_EAX)
if (ins->dreg != X86_EAX)
x86_pop_reg (code, X86_EAX);
break;
+ case OP_FCLE: {
+ guchar *unordered_check;
+ guchar *jump_to_end;
+ if (cfg->opt & MONO_OPT_FCMOV) {
+ /* zeroing the register at the start results in
+ * shorter and faster code (we can also remove the widening op)
+ */
+ x86_alu_reg_reg (code, X86_XOR, ins->dreg, ins->dreg);
+ x86_fcomip (code, 1);
+ x86_fstp (code, 0);
+ unordered_check = code;
+ x86_branch8 (code, X86_CC_P, 0, FALSE);
+ x86_set_reg (code, X86_CC_NB, ins->dreg, FALSE);
+ x86_patch (unordered_check, code);
+ break;
+ }
+ if (ins->dreg != X86_EAX)
+ x86_push_reg (code, X86_EAX);
+
+ EMIT_FPCOMPARE(code);
+ x86_alu_reg_imm (code, X86_AND, X86_EAX, X86_FP_CC_MASK);
+ x86_alu_reg_imm (code, X86_CMP, X86_EAX, 0x4500);
+ unordered_check = code;
+ x86_branch8 (code, X86_CC_EQ, 0, FALSE);
+
+ x86_alu_reg_imm (code, X86_CMP, X86_EAX, X86_FP_C0);
+ x86_set_reg (code, X86_CC_NE, ins->dreg, TRUE);
+ x86_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
+ jump_to_end = code;
+ x86_jump8 (code, 0);
+ x86_patch (unordered_check, code);
+ x86_alu_reg_reg (code, X86_XOR, ins->dreg, ins->dreg);
+ x86_patch (jump_to_end, code);
+
+ if (ins->dreg != X86_EAX)
+ x86_pop_reg (code, X86_EAX);
+ break;
+ }
case OP_FCGT:
case OP_FCGT_UN:
if (cfg->opt & MONO_OPT_FCMOV) {
if (ins->dreg != X86_EAX)
x86_pop_reg (code, X86_EAX);
break;
+ case OP_FCGE: {
+ guchar *unordered_check;
+ guchar *jump_to_end;
+ if (cfg->opt & MONO_OPT_FCMOV) {
+ /* zeroing the register at the start results in
+ * shorter and faster code (we can also remove the widening op)
+ */
+ x86_alu_reg_reg (code, X86_XOR, ins->dreg, ins->dreg);
+ x86_fcomip (code, 1);
+ x86_fstp (code, 0);
+ unordered_check = code;
+ x86_branch8 (code, X86_CC_P, 0, FALSE);
+ x86_set_reg (code, X86_CC_NA, ins->dreg, FALSE);
+ x86_patch (unordered_check, code);
+ break;
+ }
+ if (ins->dreg != X86_EAX)
+ x86_push_reg (code, X86_EAX);
+
+ EMIT_FPCOMPARE(code);
+ x86_alu_reg_imm (code, X86_AND, X86_EAX, X86_FP_CC_MASK);
+ x86_alu_reg_imm (code, X86_CMP, X86_EAX, 0x4500);
+ unordered_check = code;
+ x86_branch8 (code, X86_CC_EQ, 0, FALSE);
+
+ x86_alu_reg_imm (code, X86_CMP, X86_EAX, X86_FP_C0);
+ x86_set_reg (code, X86_CC_GE, ins->dreg, TRUE);
+ x86_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
+ jump_to_end = code;
+ x86_jump8 (code, 0);
+ x86_patch (unordered_check, code);
+ x86_alu_reg_reg (code, X86_XOR, ins->dreg, ins->dreg);
+ x86_patch (jump_to_end, code);
+
+ if (ins->dreg != X86_EAX)
+ x86_pop_reg (code, X86_EAX);
+ break;
+ }
case OP_FBEQ:
if (cfg->opt & MONO_OPT_FCMOV) {
guchar *jump = code;
break;
}
case OP_TLS_GET_REG: {
-#ifdef __APPLE__
- // FIXME: tls_gs_offset can change too, do these when calculating the tls offset
- if (ins->dreg != ins->sreg1)
- x86_mov_reg_reg (code, ins->dreg, ins->sreg1, sizeof (gpointer));
- x86_shift_reg_imm (code, X86_SHL, ins->dreg, 2);
- if (tls_gs_offset)
- x86_alu_reg_imm (code, X86_ADD, ins->dreg, tls_gs_offset);
- x86_prefix (code, X86_GS_PREFIX);
- x86_mov_reg_membase (code, ins->dreg, ins->dreg, 0, sizeof (gpointer));
-#else
- g_assert_not_reached ();
-#endif
+ code = emit_tls_get_reg (code, ins->dreg, ins->sreg1);
+ break;
+ }
+ case OP_TLS_SET: {
+ code = mono_x86_emit_tls_set (code, ins->sreg1, ins->inst_offset);
+ break;
+ }
+ case OP_TLS_SET_REG: {
+ code = emit_tls_set_reg (code, ins->sreg1, ins->sreg2);
break;
}
case OP_MEMORY_BARRIER: {
case OP_CARD_TABLE_WBARRIER: {
int ptr = ins->sreg1;
int value = ins->sreg2;
- guchar *br;
+ guchar *br = NULL;
int nursery_shift, card_table_shift;
gpointer card_table_mask;
size_t nursery_size;
alloc_size = cfg->stack_offset;
pos = 0;
- if (method->save_lmf) {
- pos += sizeof (MonoLMF);
-
- /* save the current IP */
- if (cfg->compile_aot) {
- /* This pushes the current ip */
- x86_call_imm (code, 0);
- } else {
- mono_add_patch_info (cfg, code + 1 - cfg->native_code, MONO_PATCH_INFO_IP, NULL);
- x86_push_imm_template (code);
- }
- cfa_offset += sizeof (gpointer);
- mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset, SLOT_NOREF);
-
- /* save all caller saved regs */
- x86_push_reg (code, X86_EBP);
- cfa_offset += sizeof (gpointer);
- mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset, SLOT_NOREF);
- x86_push_reg (code, X86_ESI);
- cfa_offset += sizeof (gpointer);
- mono_emit_unwind_op_offset (cfg, code, X86_ESI, - cfa_offset);
- mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset, SLOT_NOREF);
- x86_push_reg (code, X86_EDI);
- cfa_offset += sizeof (gpointer);
- mono_emit_unwind_op_offset (cfg, code, X86_EDI, - cfa_offset);
- mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset, SLOT_NOREF);
- x86_push_reg (code, X86_EBX);
- cfa_offset += sizeof (gpointer);
- mono_emit_unwind_op_offset (cfg, code, X86_EBX, - cfa_offset);
- mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset, SLOT_NOREF);
-
- if ((lmf_tls_offset != -1) && !is_win32 && !optimize_for_xen) {
- /*
- * Optimized version which uses the mono_lmf TLS variable instead of indirection
- * through the mono_lmf_addr TLS variable.
- */
- /* %eax = previous_lmf */
- code = mono_x86_emit_tls_get (code, X86_EAX, lmf_tls_offset);
- /* skip esp + method_info + lmf */
- x86_alu_reg_imm (code, X86_SUB, X86_ESP, 12);
- cfa_offset += 12;
- mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset, SLOT_NOREF);
- mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset + 4, SLOT_NOREF);
- mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset + 8, SLOT_NOREF);
- /* push previous_lmf */
- x86_push_reg (code, X86_EAX);
- cfa_offset += 4;
- mini_gc_set_slot_type_from_cfa (cfg, -cfa_offset, SLOT_NOREF);
- /* new lmf = ESP */
- code = mono_x86_emit_tls_set (code, X86_ESP, lmf_tls_offset);
- } else {
- /* get the address of lmf for the current thread */
- /*
- * This is performance critical so we try to use some tricks to make
- * it fast.
- */
- gboolean have_fastpath = FALSE;
-
-#ifdef TARGET_WIN32
- if (jit_tls_offset != -1) {
- code = mono_x86_emit_tls_get (code, X86_EAX, jit_tls_offset);
- x86_alu_reg_imm (code, X86_ADD, X86_EAX, G_STRUCT_OFFSET (MonoJitTlsData, lmf));
- have_fastpath = TRUE;
- }
-#else
- if (lmf_addr_tls_offset != -1) {
- code = mono_x86_emit_tls_get (code, X86_EAX, lmf_addr_tls_offset);
- have_fastpath = TRUE;
- }
-#endif
- if (!have_fastpath) {
- if (cfg->compile_aot)
- code = mono_arch_emit_load_got_addr (cfg->native_code, code, cfg, NULL);
- code = emit_call (cfg, code, MONO_PATCH_INFO_INTERNAL_METHOD, (gpointer)"mono_get_lmf_addr");
- }
-
- /* Skip esp + method info */
- x86_alu_reg_imm (code, X86_SUB, X86_ESP, 8);
-
- /* push lmf */
- x86_push_reg (code, X86_EAX);
- /* push *lfm (previous_lmf) */
- x86_push_membase (code, X86_EAX, 0);
- /* *(lmf) = ESP */
- x86_mov_membase_reg (code, X86_EAX, 0, X86_ESP, 4);
- }
- } else {
-
+ if (!method->save_lmf) {
if (cfg->used_int_regs & (1 << X86_EBX)) {
x86_push_reg (code, X86_EBX);
pos += 4;
x86_mov_membase_reg (code, X86_EBP, cfg->rgctx_var->inst_offset, MONO_ARCH_RGCTX_REG, 4);
}
+ if (method->save_lmf) {
+ code = emit_setup_lmf (cfg, code, cfg->lmf_var->inst_offset, cfa_offset);
+ if (!cfg->lmf_ir)
+ code = emit_push_lmf (cfg, code, cfg->lmf_var->inst_offset);
+ }
+
if (mono_jit_trace_calls != NULL && mono_trace_eval (method))
code = mono_arch_instrument_prolog (cfg, mono_trace_enter_method, code, TRUE);
{
MonoMethod *method = cfg->method;
MonoMethodSignature *sig = mono_method_signature (method);
- int quad, pos;
+ int i, quad, pos;
guint32 stack_to_pop;
guint8 *code;
int max_epilog_size = 16;
if (mono_jit_trace_calls != NULL && mono_trace_eval (method))
code = mono_arch_instrument_epilog (cfg, mono_trace_leave_method, code, TRUE);
- /* the code restoring the registers must be kept in sync with OP_JMP */
+ /* the code restoring the registers must be kept in sync with OP_TAILCALL */
pos = 0;
if (method->save_lmf) {
- gint32 prev_lmf_reg;
- gint32 lmf_offset = -sizeof (MonoLMF);
+ gint32 lmf_offset = cfg->lmf_var->inst_offset;
+ guint8 *patch;
+ gboolean supported = FALSE;
+
+ if (cfg->compile_aot) {
+#if defined(__APPLE__) || defined(__linux__)
+ supported = TRUE;
+#endif
+ } else if (mono_get_jit_tls_offset () != -1) {
+ supported = TRUE;
+ }
/* check if we need to restore protection of the stack after a stack overflow */
- if (mono_get_jit_tls_offset () != -1) {
- guint8 *patch;
- code = mono_x86_emit_tls_get (code, X86_ECX, mono_get_jit_tls_offset ());
+ if (supported) {
+ if (cfg->compile_aot) {
+ code = emit_load_aotconst (NULL, code, cfg, NULL, X86_ECX, MONO_PATCH_INFO_TLS_OFFSET, GINT_TO_POINTER (TLS_KEY_JIT_TLS));
+
+ code = emit_tls_get_reg (code, X86_ECX, X86_ECX);
+ } else {
+ code = mono_x86_emit_tls_get (code, X86_ECX, mono_get_jit_tls_offset ());
+ }
+
/* we load the value in a separate instruction: this mechanism may be
* used later as a safer way to do thread interruption
*/
} else {
/* FIXME: maybe save the jit tls in the prolog */
}
- if ((lmf_tls_offset != -1) && !is_win32 && !optimize_for_xen) {
- /*
- * Optimized version which uses the mono_lmf TLS variable instead of indirection
- * through the mono_lmf_addr TLS variable.
- */
- /* reg = previous_lmf */
- x86_mov_reg_membase (code, X86_ECX, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), 4);
-
- /* lmf = previous_lmf */
- code = mono_x86_emit_tls_set (code, X86_ECX, lmf_tls_offset);
- } else {
- /* Find a spare register */
- switch (mini_type_get_underlying_type (cfg->generic_sharing_context, sig->ret)->type) {
- case MONO_TYPE_I8:
- case MONO_TYPE_U8:
- prev_lmf_reg = X86_EDI;
- cfg->used_int_regs |= (1 << X86_EDI);
- break;
- default:
- prev_lmf_reg = X86_EDX;
- break;
- }
-
- /* reg = previous_lmf */
- x86_mov_reg_membase (code, prev_lmf_reg, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), 4);
- /* ecx = lmf */
- x86_mov_reg_membase (code, X86_ECX, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, lmf_addr), 4);
-
- /* *(lmf) = previous_lmf */
- x86_mov_membase_reg (code, X86_ECX, 0, prev_lmf_reg, 4);
- }
+ if (!cfg->lmf_ir)
+ code = emit_pop_lmf (cfg, code, lmf_offset);
/* restore caller saved regs */
if (cfg->used_int_regs & (1 << X86_EBX)) {
- x86_mov_reg_membase (code, X86_EBX, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, ebx), 4);
+ x86_mov_reg_membase (code, X86_EBX, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, ebx), 4);
}
if (cfg->used_int_regs & (1 << X86_EDI)) {
- x86_mov_reg_membase (code, X86_EDI, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, edi), 4);
+ x86_mov_reg_membase (code, X86_EDI, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, edi), 4);
}
if (cfg->used_int_regs & (1 << X86_ESI)) {
- x86_mov_reg_membase (code, X86_ESI, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, esi), 4);
+ x86_mov_reg_membase (code, X86_ESI, cfg->frame_reg, lmf_offset + G_STRUCT_OFFSET (MonoLMF, esi), 4);
}
/* EBP is restored by LEAVE */
} else {
- if (cfg->used_int_regs & (1 << X86_EBX)) {
- pos -= 4;
- }
- if (cfg->used_int_regs & (1 << X86_EDI)) {
- pos -= 4;
+ for (i = 0; i < X86_NREG; ++i) {
+ if ((cfg->used_int_regs & X86_CALLER_REGS & (1 << i)) && (i != X86_EBP)) {
+ pos -= 4;
+ }
}
- if (cfg->used_int_regs & (1 << X86_ESI)) {
- pos -= 4;
+
+ if (pos) {
+ g_assert (need_stack_frame);
+ x86_lea_membase (code, X86_ESP, X86_EBP, pos);
}
if (pos) {
* We need to init this multiple times, since when we are first called, the key might not
* be initialized yet.
*/
- appdomain_tls_offset = mono_domain_get_tls_key ();
jit_tls_offset = mono_get_jit_tls_key ();
/* Only 64 tls entries can be accessed using inline code */
- if (appdomain_tls_offset >= 64)
- appdomain_tls_offset = -1;
if (jit_tls_offset >= 64)
jit_tls_offset = -1;
#else
#if MONO_XEN_OPT
optimize_for_xen = access ("/proc/xen", F_OK) == 0;
#endif
- appdomain_tls_offset = mono_domain_get_tls_offset ();
- lmf_tls_offset = mono_get_lmf_tls_offset ();
lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset ();
#endif
}
return 0;
}
-MonoInst* mono_arch_get_domain_intrinsic (MonoCompile* cfg)
-{
- MonoInst* ins;
-
- return NULL;
-
- if (appdomain_tls_offset == -1)
- return NULL;
-
- MONO_INST_NEW (cfg, ins, OP_TLS_GET);
- ins->inst_offset = appdomain_tls_offset;
- return ins;
-}
-
guint32
mono_arch_get_patch_offset (guint8 *code)
{
return code;
}
+static guint8*
+emit_load_aotconst (guint8 *start, guint8 *code, MonoCompile *cfg, MonoJumpInfo **ji, int dreg, int tramp_type, gconstpointer target)
+{
+ if (cfg)
+ mono_add_patch_info (cfg, code - cfg->native_code, tramp_type, target);
+ else
+ g_assert_not_reached ();
+ x86_mov_reg_membase (code, dreg, MONO_ARCH_GOT_REG, 0xf0f0f0f0, 4);
+ return code;
+}
+
/*
- * mono_ppc_emit_load_aotconst:
+ * mono_arch_emit_load_aotconst:
*
* Emit code to load the contents of the GOT slot identified by TRAMP_TYPE and
* TARGET from the mscorlib GOT in full-aot code.
return NULL;
}
+void
+mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
+{
+ ext->lmf.previous_lmf = (gsize)prev_lmf;
+ /* Mark that this is a MonoLMFExt */
+ ext->lmf.previous_lmf = (gsize)(gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
+ ext->lmf.ebp = (gssize)ext;
+}
+
#endif
#if defined(MONOTOUCH) || defined(MONO_EXTENSIONS)
#define MONO_ARCH_HAVE_CONTEXT_SET_INT_REG 1
#define MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK 1
#define MONO_ARCH_GSHAREDVT_SUPPORTED 1
-
-#ifdef TARGET_OSX
+#define MONO_ARCH_HAVE_OP_TAIL_CALL 1
+#define MONO_ARCH_HAVE_TRANSLATE_TLS_OFFSET 1
#define MONO_ARCH_HAVE_TLS_GET_REG 1
-#endif
-
-gboolean
-mono_x86_tail_call_supported (MonoMethodSignature *caller_sig, MonoMethodSignature *callee_sig) MONO_INTERNAL;
-
-#define MONO_ARCH_USE_OP_TAIL_CALL(caller_sig, callee_sig) mono_x86_tail_call_supported (caller_sig, callee_sig)
/* Used for optimization, not complete */
#define MONO_ARCH_IS_OP_MEMBASE(opcode) ((opcode) == OP_X86_PUSH_MEMBASE)
#include <mono/metadata/mempool-internals.h>
#include <mono/metadata/attach.h>
#include <mono/metadata/runtime.h>
+#include <mono/metadata/mono-debug-debugger.h>
#include <mono/utils/mono-math.h>
#include <mono/utils/mono-compiler.h>
#include <mono/utils/mono-counters.h>
#include "jit-icalls.h"
-#include "debug-mini.h"
#include "mini-gc.h"
#include "debugger-agent.h"
-/* this macro is used for a runtime check done in mini_init () */
-#ifdef MONO_ARCH_EMULATE_MUL_DIV
-#define EMUL_MUL_DIV 1
-#else
-#define EMUL_MUL_DIV 0
-#endif
-
static gpointer mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoException **ex);
MONO_FAST_TLS_DECLARE(mono_jit_tls);
#endif
-#ifndef MONO_ARCH_MONITOR_ENTER_ADJUSTMENT
-#define MONO_ARCH_MONITOR_ENTER_ADJUSTMENT 1
-#endif
-
MonoTraceSpec *mono_jit_trace_calls = NULL;
gboolean mono_compile_aot = FALSE;
/* If this is set, no code is generated dynamically, everything is taken from AOT files */
gboolean mono_aot_only = FALSE;
/* Whenever to use IMT */
-#ifdef MONO_ARCH_HAVE_IMT
-gboolean mono_use_imt = TRUE;
-#else
-gboolean mono_use_imt = FALSE;
-#endif
+gboolean mono_use_imt = ARCH_HAVE_IMT;
MonoMethodDesc *mono_inject_async_exc_method = NULL;
int mono_inject_async_exc_pos;
MonoMethodDesc *mono_break_at_bb_method = NULL;
if (type->byref)
return OP_STORE_MEMBASE_REG;
+ type = mini_type_get_underlying_type (NULL, type);
+
handle_enum:
switch (type->type) {
case MONO_TYPE_I1:
if (type->byref)
return OP_LOAD_MEMBASE;
- type = mono_type_get_underlying_type (type);
+ type = mini_type_get_underlying_type (NULL, type);
switch (type->type) {
case MONO_TYPE_I1:
guint
mini_type_to_stind (MonoCompile* cfg, MonoType *type)
{
+ type = mini_type_get_underlying_type (NULL, type);
+
if (cfg->generic_sharing_context && !type->byref) {
if (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) {
if (mini_type_var_is_vt (cfg, type))
int num = cfg->num_varinfo;
gboolean regpair;
+ type = mini_type_get_underlying_type (NULL, type);
+
if ((num + 1) >= cfg->varinfo_count) {
int orig_count = cfg->varinfo_count;
cfg->varinfo_count = cfg->varinfo_count ? (cfg->varinfo_count * 2) : 64;
mono_compile_create_var (MonoCompile *cfg, MonoType *type, int opcode)
{
int dreg;
+ type = mini_type_get_underlying_type (NULL, type);
if (mono_type_is_long (type))
dreg = mono_alloc_dreg (cfg, STACK_I8);
res = mono_metadata_signature_alloc (mono_defaults.corlib, arity + 1);
res->pinvoke = 1;
-#ifdef MONO_ARCH_VARARG_ICALLS
- /* Only set this only some archs since not all backends can handle varargs+pinvoke */
- res->call_convention = MONO_CALL_VARARG;
-#endif
+ if (ARCH_VARARG_ICALLS)
+ /* Only set this only some archs since not all backends can handle varargs+pinvoke */
+ res->call_convention = MONO_CALL_VARARG;
#ifdef TARGET_WIN32
res->call_convention = MONO_CALL_C;
MonoInternalThread *thread;
void *jit_tls = setup_jit_tls_data (stack_start, mono_thread_abort);
thread = mono_thread_internal_current ();
- mono_debugger_thread_created (tid, thread->root_domain_thread, jit_tls, func);
if (thread)
thread->jit_data = jit_tls;
MonoInternalThread *thread;
void *jit_tls = setup_jit_tls_data (stack_start, mono_thread_abort_dummy);
thread = mono_thread_internal_current ();
- mono_debugger_thread_created (tid, thread->root_domain_thread, (MonoJitTlsData *) jit_tls, NULL);
if (thread)
thread->jit_data = jit_tls;
if (mono_profiler_get_events () & MONO_PROFILE_STATISTICAL)
MonoJitTlsData *jit_tls = thread->jit_data;
if (jit_tls) {
- mono_debugger_thread_cleanup (jit_tls);
-
/* We can't clean up tls information if we are on another thread, it will clean up the wrong stuff
* It would be nice to issue a warning when this happens outside of the shutdown sequence. but it's
* not a trivial thing.
g_assert (offset != -1);
break;
}
+
return offset;
}
return ins;
}
+gboolean
+mini_tls_get_supported (MonoCompile *cfg, MonoTlsKey key)
+{
+ if (!MONO_ARCH_HAVE_TLS_GET)
+ return FALSE;
+
+ if (cfg->compile_aot)
+ return ARCH_HAVE_TLS_GET_REG;
+ else
+ return mini_get_tls_offset (key) != -1;
+}
+
MonoInst*
mono_create_tls_get (MonoCompile *cfg, MonoTlsKey key)
{
return mono_create_tls_get (cfg, TLS_KEY_LMF);
}
+MonoInst*
+mono_get_lmf_addr_intrinsic (MonoCompile* cfg)
+{
+ return mono_create_tls_get (cfg, TLS_KEY_LMF_ADDR);
+}
+
#endif /* !DISABLE_JIT */
void
case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
case MONO_PATCH_INFO_SIGNATURE:
case MONO_PATCH_INFO_TLS_OFFSET:
+ case MONO_PATCH_INFO_METHOD_CODE_SLOT:
return (ji->type << 8) | (gssize)ji->data.target;
case MONO_PATCH_INFO_GSHAREDVT_CALL:
return (ji->type << 8) | (gssize)ji->data.gsharedvt->method;
}
#endif
break;
+ case MONO_PATCH_INFO_METHOD_CODE_SLOT: {
+ gpointer code_slot;
+
+ mono_domain_lock (domain);
+ if (!domain_jit_info (domain)->method_code_hash)
+ domain_jit_info (domain)->method_code_hash = g_hash_table_new (NULL, NULL);
+ code_slot = g_hash_table_lookup (domain_jit_info (domain)->method_code_hash, patch_info->data.method);
+ if (!code_slot) {
+ code_slot = mono_domain_alloc0 (domain, sizeof (gpointer));
+ g_hash_table_insert (domain_jit_info (domain)->method_code_hash, patch_info->data.method, code_slot);
+ }
+ mono_domain_unlock (domain);
+ target = code_slot;
+ break;
+ }
case MONO_PATCH_INFO_SWITCH: {
gpointer *jump_table;
int i;
target = (gpointer) (size_t) mono_jit_tls_id;
break;
}
- case MONO_PATCH_INFO_TLS_OFFSET:
- target = GINT_TO_POINTER (mini_get_tls_offset (GPOINTER_TO_INT (patch_info->data.target)));
+ case MONO_PATCH_INFO_TLS_OFFSET: {
+ int offset;
+
+ offset = mini_get_tls_offset (GPOINTER_TO_INT (patch_info->data.target));
+#ifdef MONO_ARCH_HAVE_TRANSLATE_TLS_OFFSET
+ offset = mono_arch_translate_tls_offset (offset);
+#endif
+ target = GINT_TO_POINTER (offset);
break;
+ }
case MONO_PATCH_INFO_OBJC_SELECTOR_REF: {
target = NULL;
break;
g_print ("locals done\n");
mono_arch_create_vars (cfg);
+
+ if (cfg->method->save_lmf && cfg->create_lmf_var) {
+ MonoInst *lmf_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
+ lmf_var->flags |= MONO_INST_VOLATILE;
+ lmf_var->flags |= MONO_INST_LMF;
+ cfg->lmf_var = lmf_var;
+ }
}
void
* Its possible to generate dwarf unwind info for xdebug etc, but not actually
* using it during runtime, hence the define.
*/
-#ifdef MONO_ARCH_HAVE_XP_UNWIND
if (cfg->encoded_unwind_ops) {
jinfo->used_regs = mono_cache_unwind_info (cfg->encoded_unwind_ops, cfg->encoded_unwind_ops_len);
g_free (cfg->encoded_unwind_ops);
jinfo->used_regs = mono_cache_unwind_info (unwind_info, info_len);
g_free (unwind_info);
}
-#endif
return jinfo;
}
#endif
/* The debugger has no liveness information, so avoid sharing registers/stack slots */
- if (mono_debug_using_mono_debugger () || debug_options.mdb_optimizations) {
+ if (debug_options.mdb_optimizations) {
cfg->disable_reuse_registers = TRUE;
cfg->disable_reuse_stack_slots = TRUE;
/*
mono_handle_global_vregs (cfg);
if (cfg->opt & MONO_OPT_DEADCE)
mono_local_deadce (cfg);
+ if (cfg->opt & MONO_OPT_ALIAS_ANALYSIS)
+ mono_local_alias_analysis (cfg);
/* Disable this for LLVM to make the IR easier to handle */
if (!COMPILE_LLVM (cfg))
mono_if_conversion (cfg);
#endif
if (cfg->comp_done & MONO_COMP_SSA && COMPILE_LLVM (cfg)) {
+ mono_ssa_loop_invariant_code_motion (cfg);
/* This removes MONO_INST_FAULT flags too so perform it unconditionally */
if (cfg->opt & MONO_OPT_ABCREM)
mono_perform_abc_removal (cfg);
if (COMPILE_SOFT_FLOAT (cfg))
mono_decompose_soft_float (cfg);
#endif
- if (!COMPILE_LLVM (cfg))
+ if (COMPILE_LLVM (cfg))
+ mono_decompose_vtype_opts_llvm (cfg);
+ else
mono_decompose_vtype_opts (cfg);
if (cfg->flags & MONO_CFG_HAS_ARRAY_ACCESS)
mono_decompose_array_access_opts (cfg);
if (jinfo)
mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK);
return code;
-
- //if (mono_debug_format != MONO_DEBUG_FORMAT_NONE)
- //mono_debug_add_wrapper (method, nm);
} else if ((method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
const char *name = method->name;
char *full_name, *msg;
if (!callinfo->wrapper) {
callinfo->wrapper = p;
mono_register_jit_icall_wrapper (callinfo, p);
- mono_debug_add_icall_wrapper (method, callinfo);
}
mono_jit_unlock ();
mono_loader_unlock ();
*/
#ifdef MONO_ARCH_DYN_CALL_SUPPORTED
if (mono_aot_only || debug_options.dyn_runtime_invoke) {
+ MonoType *ret_type;
MonoMethodSignature *sig = mono_method_signature (method);
gboolean supported = TRUE;
int i;
if (supported)
info->dyn_call_info = mono_arch_dyn_call_prepare (sig);
+ ret_type = mini_type_get_underlying_type (NULL, sig->ret);
if (info->dyn_call_info) {
- switch (sig->ret->type) {
+ switch (ret_type->type) {
case MONO_TYPE_VOID:
break;
case MONO_TYPE_I1:
case MONO_TYPE_CHAR:
case MONO_TYPE_R4:
case MONO_TYPE_R8:
- info->ret_box_class = mono_class_from_mono_type (sig->ret);
+ info->ret_box_class = mono_class_from_mono_type (ret_type);
break;
case MONO_TYPE_PTR:
info->ret_box_class = mono_defaults.int_class;
case MONO_TYPE_OBJECT:
break;
case MONO_TYPE_GENERICINST:
- if (!MONO_TYPE_IS_REFERENCE (sig->ret))
- info->ret_box_class = mono_class_from_mono_type (sig->ret);
+ if (!MONO_TYPE_IS_REFERENCE (ret_type))
+ info->ret_box_class = mono_class_from_mono_type (ret_type);
break;
case MONO_TYPE_VALUETYPE:
- info->ret_box_class = mono_class_from_mono_type (sig->ret);
+ info->ret_box_class = mono_class_from_mono_type (ret_type);
break;
default:
g_assert_not_reached ();
if (sig->hasthis)
args [pindex ++] = &obj;
for (i = 0; i < sig->param_count; ++i) {
- MonoType *t = sig->params [i];
+ MonoType *t = mini_type_get_underlying_type (NULL, sig->params [i]);
if (t->byref) {
args [pindex ++] = ¶ms [i];
mono_counters_register ("Method cache lookups", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_lookups);
mono_counters_register ("Compiled CIL code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.cil_code_size);
mono_counters_register ("Native code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.native_code_size);
+ mono_counters_register ("Aliases found", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.alias_found);
+ mono_counters_register ("Aliases eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.alias_removed);
+ mono_counters_register ("Aliased loads eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.loads_eliminated);
+ mono_counters_register ("Aliased stores eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.stores_eliminated);
}
static void runtime_invoke_info_free (gpointer value);
InitializeCriticalSection (&jit_mutex);
-#ifdef MONO_DEBUGGER_SUPPORTED
- if (mini_debug_running_inside_mdb ())
- mini_debugger_init ();
-#endif
-
#ifdef MONO_HAVE_FAST_TLS
MONO_FAST_TLS_INIT (mono_jit_tls);
MONO_FAST_TLS_INIT (mono_lmf_addr);
#endif
#if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
- if (EMUL_MUL_DIV || mono_arch_is_soft_float ()) {
+ if (ARCH_EMULATE_MUL_DIV || mono_arch_is_soft_float ()) {
register_opcode_emulation (OP_FDIV, "__emul_fdiv", "double double double", mono_fdiv, "mono_fdiv", FALSE);
}
#endif
#if SIZEOF_REGISTER == 4
register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "uint32 double", mono_fconv_u4, "mono_fconv_u4", TRUE);
+#else
+ register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "ulong double", mono_fconv_u8, "mono_fconv_u8", TRUE);
#endif
/* other jit icalls */
mono_domain_free (domain, TRUE);
#endif
- mono_debugger_cleanup ();
-
#ifdef ENABLE_LLVM
if (mono_use_llvm)
mono_llvm_cleanup ();
#define LLVM_CHECK_VERSION(major,minor) 0
#endif
-/*
- * Whenever we are using mono's LLVM branch.
- * This can be used in if statements, code which references new definitions from the branch
- * still needs an #ifdef LLVM_MONO_BRANCH.
- */
-#ifdef LLVM_MONO_BRANCH
-#define IS_LLVM_MONO_BRANCH 1
-#else
-#define IS_LLVM_MONO_BRANCH 0
-#endif
-
#define NOT_IMPLEMENTED do { g_assert_not_reached (); } while (0)
/* for 32 bit systems */
#endif
/* Version number of the AOT file format */
-#define MONO_AOT_FILE_VERSION 95
+#define MONO_AOT_FILE_VERSION 97
//TODO: This is x86/amd64 specific.
#define mono_simd_shuffle_mask(a,b,c,d) ((a) | ((b) << 2) | ((c) << 4) | ((d) << 6))
/* These are used for sanity checking object layout problems when cross-compiling */
guint32 double_align, long_align, generic_tramp_num;
+ /* The page size used by trampoline pages */
+ guint32 tramp_page_size;
+ /* The offset where the trampolines begin on a trampoline page */
+ guint32 tramp_page_code_offsets [MONO_AOT_TRAMP_NUM];
} MonoAotFileInfo;
/* Per-domain information maintained by the JIT */
/* FIXME: Add more instructions */
/* INEG sets the condition codes, and the OP_LNEG decomposition depends on this on x86 */
-#define MONO_INS_HAS_NO_SIDE_EFFECT(ins) (MONO_IS_MOVE (ins) || (ins->opcode == OP_ICONST) || (ins->opcode == OP_I8CONST) || MONO_IS_ZERO (ins) || (ins->opcode == OP_ADD_IMM) || (ins->opcode == OP_R8CONST) || (ins->opcode == OP_LADD_IMM) || (ins->opcode == OP_ISUB_IMM) || (ins->opcode == OP_IADD_IMM) || (ins->opcode == OP_LNEG) || (ins->opcode == OP_ISUB) || (ins->opcode == OP_CMOV_IGE) || (ins->opcode == OP_ISHL_IMM) || (ins->opcode == OP_ISHR_IMM) || (ins->opcode == OP_ISHR_UN_IMM) || (ins->opcode == OP_IAND_IMM) || (ins->opcode == OP_ICONV_TO_U1) || (ins->opcode == OP_ICONV_TO_I1) || (ins->opcode == OP_SEXT_I4) || (ins->opcode == OP_LCONV_TO_U1) || (ins->opcode == OP_ICONV_TO_U2) || (ins->opcode == OP_ICONV_TO_I2) || (ins->opcode == OP_LCONV_TO_I2) || (ins->opcode == OP_LDADDR))
+#define MONO_INS_HAS_NO_SIDE_EFFECT(ins) (MONO_IS_MOVE (ins) || (ins->opcode == OP_ICONST) || (ins->opcode == OP_I8CONST) || MONO_IS_ZERO (ins) || (ins->opcode == OP_ADD_IMM) || (ins->opcode == OP_R8CONST) || (ins->opcode == OP_LADD_IMM) || (ins->opcode == OP_ISUB_IMM) || (ins->opcode == OP_IADD_IMM) || (ins->opcode == OP_LNEG) || (ins->opcode == OP_ISUB) || (ins->opcode == OP_CMOV_IGE) || (ins->opcode == OP_ISHL_IMM) || (ins->opcode == OP_ISHR_IMM) || (ins->opcode == OP_ISHR_UN_IMM) || (ins->opcode == OP_IAND_IMM) || (ins->opcode == OP_ICONV_TO_U1) || (ins->opcode == OP_ICONV_TO_I1) || (ins->opcode == OP_SEXT_I4) || (ins->opcode == OP_LCONV_TO_U1) || (ins->opcode == OP_ICONV_TO_U2) || (ins->opcode == OP_ICONV_TO_I2) || (ins->opcode == OP_LCONV_TO_I2) || (ins->opcode == OP_LDADDR) || (ins->opcode == OP_PHI) || (ins->opcode == OP_NOP) || (ins->opcode == OP_ZEXT_I4) || (ins->opcode == OP_NOT_NULL))
#define MONO_METHOD_IS_FINAL(m) (((m)->flags & METHOD_ATTRIBUTE_FINAL) || ((m)->klass && ((m)->klass->flags & TYPE_ATTRIBUTE_SEALED)))
LLVMCallInfo *cinfo;
int rgctx_arg_reg, imt_arg_reg;
#endif
+#ifdef TARGET_ARM
+ /* See the comment in mini-arm.c!mono_arch_emit_call for RegTypeFP. */
+ GSList *float_args;
+#endif
};
struct MonoCallArgParm {
*/
MONO_INST_LMF = 32,
/* On loads, the source address points to a constant value */
- MONO_INST_CONSTANT_LOAD = 64,
+ MONO_INST_INVARIANT_LOAD = 64,
/* On variables, the variable needs GC tracking */
MONO_INST_GC_TRACK = 128,
/*
/* For native-to-managed wrappers, the saved old domain */
MonoInst *orig_domain_var;
+ MonoInst *lmf_var;
+ MonoInst *lmf_addr_var;
+
unsigned char *cil_start;
#ifdef __native_client_codegen__
/* this alloc is not aligned, native_code */
guint disable_vreg_to_lvreg : 1;
guint disable_deadce_vars : 1;
guint disable_out_of_line_bblocks : 1;
+ guint create_lmf_var : 1;
+ /*
+ * When this is set, the code to push/pop the LMF from the LMF stack is generated as IR
+ * instead of being generated in emit_prolog ()/emit_epilog ().
+ */
+ guint lmf_ir : 1;
+ /*
+ * Whenever to use the mono_lmf TLS variable instead of indirection through the
+ * mono_lmf_addr TLS variable.
+ */
+ guint lmf_ir_mono_lmf : 1;
guint gen_write_barriers : 1;
guint init_ref_vars : 1;
guint extend_live_ranges : 1;
guint compute_gc_maps : 1;
guint soft_breakpoints : 1;
guint arch_eh_jit_info : 1;
+ guint has_indirection : 1;
gpointer debug_info;
guint32 lmf_offset;
guint16 *intvars;
gint32 cas_linkdemand;
gint32 cas_demand_generation;
gint32 generic_virtual_invocations;
+ gint32 alias_found;
+ gint32 alias_removed;
+ gint32 loads_eliminated;
+ gint32 stores_eliminated;
int methods_with_llvm;
int methods_without_llvm;
char *max_ratio_method;
gint32 mono_get_lmf_tls_offset (void) MONO_INTERNAL;
gint32 mono_get_lmf_addr_tls_offset (void) MONO_INTERNAL;
int mini_get_tls_offset (MonoTlsKey key) MONO_INTERNAL;
+gboolean mini_tls_get_supported (MonoCompile *cfg, MonoTlsKey key) MONO_INTERNAL;
MonoInst* mono_create_tls_get (MonoCompile *cfg, MonoTlsKey key) MONO_INTERNAL;
MonoInst* mono_get_jit_tls_intrinsic (MonoCompile *cfg) MONO_INTERNAL;
MonoInst* mono_get_domain_intrinsic (MonoCompile* cfg) MONO_INTERNAL;
MonoInst* mono_get_thread_intrinsic (MonoCompile* cfg) MONO_INTERNAL;
MonoInst* mono_get_lmf_intrinsic (MonoCompile* cfg) MONO_INTERNAL;
+MonoInst* mono_get_lmf_addr_intrinsic (MonoCompile* cfg) MONO_INTERNAL;
GList *mono_varlist_insert_sorted (MonoCompile *cfg, GList *list, MonoMethodVar *mv, int sort_type) MONO_INTERNAL;
GList *mono_varlist_sort (MonoCompile *cfg, GList *list, int sort_type) MONO_INTERNAL;
void mono_analyze_liveness (MonoCompile *cfg) MONO_INTERNAL;
MonoInst *mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins) MONO_INTERNAL;
void mono_decompose_long_opts (MonoCompile *cfg) MONO_INTERNAL;
void mono_decompose_vtype_opts (MonoCompile *cfg) MONO_INTERNAL;
+void mono_decompose_vtype_opts_llvm (MonoCompile *cfg) MONO_INTERNAL;
void mono_decompose_array_access_opts (MonoCompile *cfg) MONO_INTERNAL;
void mono_decompose_soft_float (MonoCompile *cfg) MONO_INTERNAL;
void mono_handle_global_vregs (MonoCompile *cfg) MONO_INTERNAL;
gpointer mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) MONO_INTERNAL;
gpointer mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_sig, MonoMethodSignature *gsharedvt_sig, MonoGenericSharingContext *gsctx, gboolean gsharedvt_in, gint32 vcall_offset, gboolean calli) MONO_INTERNAL;
gboolean mono_arch_opcode_needs_emulation (MonoCompile *cfg, int opcode) MONO_INTERNAL;
+gboolean mono_arch_tail_call_supported (MonoMethodSignature *caller_sig, MonoMethodSignature *callee_sig) MONO_INTERNAL;
+int mono_arch_translate_tls_offset (int offset) MONO_INTERNAL;
#ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
gboolean mono_arch_is_soft_float (void) MONO_INTERNAL;
void mono_arch_skip_single_step (MonoContext *ctx) MONO_INTERNAL;
gpointer mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code) MONO_INTERNAL;
void mono_arch_setup_resume_sighandler_ctx (MonoContext *ctx, gpointer func) MONO_INTERNAL;
+void mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf) MONO_INTERNAL;
#endif
#ifdef USE_JUMP_TABLES
void mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val) MONO_INTERNAL;
void mono_arch_flush_register_windows (void) MONO_INTERNAL;
gboolean mono_arch_is_inst_imm (gint64 imm) MONO_INTERNAL;
-MonoInst* mono_arch_get_domain_intrinsic (MonoCompile* cfg) MONO_INTERNAL;
gboolean mono_arch_is_int_overflow (void *sigctx, void *info) MONO_INTERNAL;
void mono_arch_invalidate_method (MonoJitInfo *ji, void *func, gpointer func_arg) MONO_INTERNAL;
guint32 mono_arch_get_patch_offset (guint8 *code) MONO_INTERNAL;
void mono_ssa_deadce (MonoCompile *cfg) MONO_INTERNAL;
void mono_ssa_strength_reduction (MonoCompile *cfg) MONO_INTERNAL;
void mono_free_loop_info (MonoCompile *cfg) MONO_INTERNAL;
+void mono_ssa_loop_invariant_code_motion (MonoCompile *cfg) MONO_INTERNAL;
void mono_ssa_compute2 (MonoCompile *cfg);
void mono_ssa_remove2 (MonoCompile *cfg);
void mono_debug_add_aot_method (MonoDomain *domain,
MonoMethod *method, guint8 *code_start,
guint8 *debug_info, guint32 debug_info_len) MONO_INTERNAL;
-void mono_debug_add_icall_wrapper (MonoMethod *method, MonoJitICallInfo* info) MONO_INTERNAL;
MONO_API void mono_debug_print_vars (gpointer ip, gboolean only_arguments);
MONO_API void mono_debugger_run_finally (MonoContext *start_ctx);
MONO_API gboolean mono_breakpoint_clean_code (guint8 *method_start, guint8 *code, int offset, guint8 *buf, int size);
-#ifdef MONO_DEBUGGER_SUPPORTED
-
-/* Mono Debugger support */
-void mini_debugger_init (void);
-int mini_debugger_main (MonoDomain *domain, MonoAssembly *assembly, int argc, char **argv);
-gboolean mini_debug_running_inside_mdb (void);
-void mini_debugger_set_attach_ok (void);
-
-#endif
-
/* Tracing */
MonoTraceSpec *mono_trace_parse_options (const char *options) MONO_INTERNAL;
void mono_trace_set_assembly (MonoAssembly *assembly) MONO_INTERNAL;
mono_local_cprop (MonoCompile *cfg);
extern void
mono_local_deadce (MonoCompile *cfg);
+void
+mono_local_alias_analysis (MonoCompile *cfg) MONO_INTERNAL;
/* CAS - stack walk */
MonoSecurityFrame* ves_icall_System_Security_SecurityFrame_GetSecurityFrame (gint32 skip) MONO_INTERNAL;
#define ARCH_HAVE_DELEGATE_TRAMPOLINES 0
#endif
-#ifdef MONO_ARCH_USE_OP_TAIL_CALL
-#define ARCH_USE_OP_TAIL_CALL 1
+#ifdef MONO_ARCH_HAVE_OP_TAIL_CALL
+#define ARCH_HAVE_OP_TAIL_CALL 1
#else
-#define ARCH_USE_OP_TAIL_CALL 0
+#define ARCH_HAVE_OP_TAIL_CALL 0
#endif
#ifndef MONO_ARCH_HAVE_TLS_GET
#define ARCH_HAVE_TLS_GET_REG 0
#endif
+#ifdef MONO_ARCH_EMULATE_MUL_DIV
+#define ARCH_EMULATE_MUL_DIV 1
+#else
+#define ARCH_EMULATE_MUL_DIV 0
+#endif
+
+#ifndef MONO_ARCH_MONITOR_ENTER_ADJUSTMENT
+#define MONO_ARCH_MONITOR_ENTER_ADJUSTMENT 1
+#endif
+
+#ifndef MONO_ARCH_DYN_CALL_PARAM_AREA
+#define MONO_ARCH_DYN_CALL_PARAM_AREA 0
+#endif
+
+#ifdef MONO_ARCH_HAVE_IMT
+#define ARCH_HAVE_IMT 1
+#else
+#define ARCH_HAVE_IMT 0
+#endif
+
+#ifdef MONO_ARCH_VARARG_ICALLS
+#define ARCH_VARARG_ICALLS 1
+#else
+#define ARCH_VARARG_ICALLS 0
+#endif
+
#endif /* __MONO_MINI_H__ */
OPTFLAG(GSHAREDVT,24, "gsharedvt", "Generic sharing for valuetypes")
OPTFLAG(SIMD ,26, "simd", "Simd intrinsics")
OPTFLAG(UNSAFE ,27, "unsafe", "Remove bound checks and perform other dangerous changes")
+OPTFLAG(ALIAS_ANALYSIS ,28, "alias-analysis", "Alias analysis of locals")
PATCH_INFO(JIT_TLS_ID, "jit_tls_id")
PATCH_INFO(TLS_OFFSET, "tls_offset")
PATCH_INFO(OBJC_SELECTOR_REF, "objc_selector_ref")
+PATCH_INFO(METHOD_CODE_SLOT, "method_code_slot")
PATCH_INFO(NONE, "none")
-
-
-
}
#endif
+void
+mono_ssa_loop_invariant_code_motion (MonoCompile *cfg)
+{
+ MonoBasicBlock *bb, *h, *idom;
+ MonoInst *ins, *n, *tins;
+ int i;
+
+ g_assert (cfg->comp_done & MONO_COMP_SSA);
+ if (!(cfg->comp_done & MONO_COMP_LOOPS) || !(cfg->comp_done & MONO_COMP_SSA_DEF_USE))
+ return;
+
+ for (bb = cfg->bb_entry->next_bb; bb; bb = bb->next_bb) {
+ GList *lp = bb->loop_blocks;
+
+ if (!lp)
+ continue;
+ h = (MonoBasicBlock *)lp->data;
+ if (bb != h)
+ continue;
+ MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
+ gboolean is_class_init = FALSE;
+
+ /*
+ * Try to move instructions out of loop headers into the preceeding bblock.
+ */
+ if (ins->opcode == OP_VOIDCALL) {
+ MonoCallInst *call = (MonoCallInst*)ins;
+
+ if (call->fptr_is_patch) {
+ MonoJumpInfo *ji = (MonoJumpInfo*)call->fptr;
+
+ if (ji->type == MONO_PATCH_INFO_CLASS_INIT)
+ is_class_init = TRUE;
+ }
+ }
+ if (ins->opcode == OP_LDLEN || ins->opcode == OP_STRLEN || ins->opcode == OP_CHECK_THIS || ins->opcode == OP_AOTCONST || is_class_init) {
+ gboolean skip;
+ int sreg;
+
+ idom = h->idom;
+ /*
+ * h->nesting is needed to work around:
+ * http://llvm.org/bugs/show_bug.cgi?id=17868
+ */
+ if (!(idom && idom->last_ins && idom->last_ins->opcode == OP_BR && idom->last_ins->inst_target_bb == h && h->nesting == 1)) {
+ continue;
+ }
+
+ /*
+ * Make sure there are no instructions with side effects before ins.
+ */
+ skip = FALSE;
+ MONO_BB_FOR_EACH_INS (bb, tins) {
+ if (tins == ins)
+ break;
+ if (!MONO_INS_HAS_NO_SIDE_EFFECT (tins)) {
+ skip = TRUE;
+ break;
+ }
+ }
+ if (skip) {
+ /*
+ printf ("%s\n", mono_method_full_name (cfg->method, TRUE));
+ mono_print_ins (tins);
+ */
+ continue;
+ }
+
+ /* Make sure we don't move the instruction before the def of its sreg */
+ if (ins->opcode == OP_LDLEN || ins->opcode == OP_STRLEN || ins->opcode == OP_CHECK_THIS)
+ sreg = ins->sreg1;
+ else
+ sreg = -1;
+ if (sreg != -1) {
+ MonoInst *tins;
+
+ skip = FALSE;
+ for (tins = ins->prev; tins; tins = tins->prev) {
+ const char *spec = INS_INFO (tins->opcode);
+
+ if (tins->opcode == OP_MOVE && tins->dreg == sreg) {
+ sreg = tins->sreg1;
+ } if (spec [MONO_INST_DEST] != ' ' && tins->dreg == sreg) {
+ skip = TRUE;
+ break;
+ }
+ }
+ if (skip)
+ continue;
+ ins->sreg1 = sreg;
+ }
+
+ if (cfg->verbose_level > 1) {
+ printf ("licm in BB%d on ", bb->block_num);
+ mono_print_ins (ins);
+ }
+ //{ static int count = 0; count ++; printf ("%d\n", count); }
+ MONO_REMOVE_INS (bb, ins);
+ mono_bblock_insert_before_ins (idom, idom->last_ins, ins);
+ if (ins->opcode == OP_LDLEN || ins->opcode == OP_STRLEN)
+ idom->has_array_access = TRUE;
+ }
+ }
+ }
+
+ cfg->comp_done &= ~MONO_COMP_SSA_DEF_USE;
+ for (i = 0; i < cfg->num_varinfo; i++) {
+ MonoMethodVar *info = MONO_VARINFO (cfg, i);
+ info->def = NULL;
+ info->uses = NULL;
+ }
+}
+
#endif /* DISABLE_JIT */
}
cont->lmf = lmf;
- cont->return_ip = __builtin_return_address (0);
+ cont->return_ip = __builtin_extract_return_addr (__builtin_return_address (0));
cont->return_sp = __builtin_frame_address (0);
num_bytes = (char*)cont->top_sp - (char*)cont->return_sp;
# define fprintf(__ignore, ...) g_log ("mono-gc", G_LOG_LEVEL_MESSAGE, __VA_ARGS__)
#endif
+#define RETURN_ADDRESS(N) (__builtin_extract_return_addr (__builtin_return_address (N)))
+
static MonoTraceSpec trace_spec;
gboolean
g_free (fname);
if (!ebp) {
- printf (") ip: %p\n", __builtin_return_address (1));
+ printf (") ip: %p\n", RETURN_ADDRESS (1));
return;
}
if (method->is_inflated) {
/* FIXME: Might be better to pass the ji itself */
- MonoJitInfo *ji = mini_jit_info_table_find (mono_domain_get (), __builtin_return_address (0), NULL);
+ MonoJitInfo *ji = mini_jit_info_table_find (mono_domain_get (), RETURN_ADDRESS (0), NULL);
if (ji) {
gsctx = mono_jit_info_get_generic_sharing_context (ji);
if (gsctx && (gsctx->var_is_vt || gsctx->mvar_is_vt)) {
if (method->is_inflated) {
/* FIXME: Might be better to pass the ji itself */
- MonoJitInfo *ji = mini_jit_info_table_find (mono_domain_get (), __builtin_return_address (0), NULL);
+ MonoJitInfo *ji = mini_jit_info_table_find (mono_domain_get (), RETURN_ADDRESS (0), NULL);
if (ji) {
gsctx = mono_jit_info_get_generic_sharing_context (ji);
if (gsctx && (gsctx->var_is_vt || gsctx->mvar_is_vt)) {
printf ("(unknown return type %x)", mono_method_signature (method)->ret->type);
}
- //printf (" ip: %p\n", __builtin_return_address (1));
+ //printf (" ip: %p\n", RETURN_ADDRESS (1));
printf ("\n");
fflush (stdout);
}
code = buf = mono_global_codeman_reserve (kMaxCodeSize);
- framesize = kMaxCodeSize + sizeof (MonoLMF);
+ framesize = kMaxCodeSize + sizeof (MonoLMFTramp);
framesize = (framesize + (MONO_ARCH_FRAME_ALIGNMENT - 1)) & ~ (MONO_ARCH_FRAME_ALIGNMENT - 1);
orig_rsp_to_rbp_offset = 0;
/* Save LMF begin */
- offset += sizeof (MonoLMF);
+ offset += sizeof (MonoLMFTramp);
lmf_offset = - offset;
/* Save ip */
amd64_mov_reg_reg (code, AMD64_R11, AMD64_RSP, sizeof(mgreg_t));
amd64_alu_reg_imm (code, X86_ADD, AMD64_R11, framesize + 16);
amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, rsp), AMD64_R11, sizeof(mgreg_t));
- /* Save method */
- if (tramp_type == MONO_TRAMPOLINE_JIT || tramp_type == MONO_TRAMPOLINE_JUMP) {
- amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, arg_offset, sizeof(gpointer));
- amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, method), AMD64_R11, sizeof(gpointer));
- } else {
- amd64_mov_membase_imm (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, method), 0, sizeof(gpointer));
- }
- /* Save callee saved regs */
-#ifdef TARGET_WIN32
- amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, rdi), AMD64_RDI, sizeof(mgreg_t));
- amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, rsi), AMD64_RSI, sizeof(mgreg_t));
-#endif
- amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, rbx), AMD64_RBX, sizeof(mgreg_t));
- amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, r12), AMD64_R12, sizeof(mgreg_t));
- amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, r13), AMD64_R13, sizeof(mgreg_t));
- amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, r14), AMD64_R14, sizeof(mgreg_t));
- amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, r15), AMD64_R15, sizeof(mgreg_t));
+ /* Save pointer to registers */
+ amd64_lea_membase (code, AMD64_R11, AMD64_RBP, saved_regs_offset);
+ amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMFTramp, regs), AMD64_R11, sizeof(mgreg_t));
if (aot) {
code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_get_lmf_addr");
amd64_call_reg (code, AMD64_R11);
/* Save lmf_addr */
- amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, lmf_addr), AMD64_RAX, sizeof(gpointer));
+ amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMFTramp, lmf_addr), AMD64_RAX, sizeof(gpointer));
/* Save previous_lmf */
- /* Set the lowest bit to 1 to signal that this LMF has the ip field set */
+ /* Set the lowest bit to signal that this LMF has the ip field set */
+ /* Set the third lowest bit to signal that this is a MonoLMFTramp structure */
amd64_mov_reg_membase (code, AMD64_R11, AMD64_RAX, 0, sizeof(gpointer));
- amd64_alu_reg_imm_size (code, X86_ADD, AMD64_R11, 1, sizeof(gpointer));
+ amd64_alu_reg_imm_size (code, X86_ADD, AMD64_R11, 0x5, sizeof(gpointer));
amd64_mov_membase_reg (code, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), AMD64_R11, sizeof(gpointer));
/* Set new lmf */
amd64_lea_membase (code, AMD64_R11, AMD64_RBP, lmf_offset);
amd64_mov_reg_membase (code, AMD64_RAX, AMD64_RBP, res_offset, sizeof(mgreg_t));
/* Restore LMF */
-
amd64_mov_reg_membase (code, AMD64_RCX, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, previous_lmf), sizeof(gpointer));
- amd64_alu_reg_imm_size (code, X86_SUB, AMD64_RCX, 1, sizeof(gpointer));
- amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, lmf_addr), sizeof(gpointer));
+ amd64_alu_reg_imm_size (code, X86_SUB, AMD64_RCX, 0x5, sizeof(gpointer));
+ amd64_mov_reg_membase (code, AMD64_R11, AMD64_RBP, lmf_offset + G_STRUCT_OFFSET (MonoLMFTramp, lmf_addr), sizeof(gpointer));
amd64_mov_membase_reg (code, AMD64_R11, 0, AMD64_RCX, sizeof(gpointer));
/*
#include <mono/metadata/marshal.h>
#include <mono/metadata/tabledefs.h>
#include <mono/arch/arm/arm-codegen.h>
+#include <mono/arch/arm/arm-vfp-codegen.h>
#include "mini.h"
#include "mini-arm.h"
return code;
}
-/* Stack size for trampoline function
+/* Stack size for trampoline function
*/
#define STACK ALIGN_TO (sizeof (MonoLMF), 8)
gpointer *constants;
#endif
- int cfa_offset, lmf_offset, regsave_size, lr_offset;
+ int cfa_offset, regsave_size, lr_offset;
GSList *unwind_ops = NULL;
MonoJumpInfo *ji = NULL;
int buf_len;
/* Now we'll create in 'buf' the ARM trampoline code. This
is the trampoline code common to all methods */
- buf_len = 212;
+ buf_len = 272;
+
+ /* Add space for saving/restoring VFP regs. */
+ if (mono_arm_is_hard_float ())
+ buf_len += 8 * 2;
+
code = buf = mono_global_codeman_reserve (buf_len);
/*
* saved as sp + LR_OFFSET by the push in the specific trampoline
*/
- /* The offset of lmf inside the stack frame */
- lmf_offset = STACK - sizeof (MonoLMF);
/* The size of the area already allocated by the push in the specific trampoline */
regsave_size = 14 * sizeof (mgreg_t);
/* The offset where lr was saved inside the regsave area */
* The pointer to the struct is put in r1.
* the iregs array is already allocated on the stack by push.
*/
- ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, STACK - regsave_size);
+ code = mono_arm_emit_load_imm (code, ARMREG_R2, STACK - regsave_size);
+ ARM_SUB_REG_REG (code, ARMREG_SP, ARMREG_SP, ARMREG_R2);
cfa_offset += STACK - regsave_size;
mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset);
/* V1 == lmf */
- ARM_ADD_REG_IMM8 (code, ARMREG_V1, ARMREG_SP, STACK - sizeof (MonoLMF));
+ code = mono_arm_emit_load_imm (code, ARMREG_R2, STACK - sizeof (MonoLMF));
+ ARM_ADD_REG_REG (code, ARMREG_V1, ARMREG_SP, ARMREG_R2);
/*
* The stack now looks like:
ARM_STR_IMM (code, ARMREG_R2, ARMREG_V1, G_STRUCT_OFFSET (MonoLMF, method));
}
/* save caller SP */
- ARM_ADD_REG_IMM8 (code, ARMREG_R2, ARMREG_SP, cfa_offset);
+ code = mono_arm_emit_load_imm (code, ARMREG_R2, cfa_offset);
+ ARM_ADD_REG_REG (code, ARMREG_R2, ARMREG_SP, ARMREG_R2);
ARM_STR_IMM (code, ARMREG_R2, ARMREG_V1, G_STRUCT_OFFSET (MonoLMF, sp));
/* save caller FP */
ARM_LDR_IMM (code, ARMREG_R2, ARMREG_V1, (G_STRUCT_OFFSET (MonoLMF, iregs) + ARMREG_FP*4));
}
ARM_STR_IMM (code, ARMREG_R2, ARMREG_V1, G_STRUCT_OFFSET (MonoLMF, ip));
+ /* Save VFP registers. */
+ if (mono_arm_is_hard_float ()) {
+ /*
+ * Strictly speaking, we don't have to save d0-d7 in the LMF, but
+ * it's easier than attempting to store them on the stack since
+ * this trampoline code is pretty messy.
+ */
+ ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_V1, G_STRUCT_OFFSET (MonoLMF, fregs));
+ ARM_FSTMD (code, ARM_VFP_D0, 8, ARMREG_R0);
+ }
+
/*
* Now we're ready to call xxx_trampoline ().
*/
/* Arg 1: the saved registers */
- ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_V1, G_STRUCT_OFFSET (MonoLMF, iregs));
+ ARM_ADD_REG_IMM (code, ARMREG_R0, ARMREG_V1, G_STRUCT_OFFSET (MonoLMF, iregs), 0);
/* Arg 2: code (next address to the instruction that called us) */
if (tramp_type == MONO_TRAMPOLINE_JUMP) {
/* *(lmf_addr) = previous_lmf */
ARM_STR_IMM (code, ARMREG_IP, ARMREG_LR, G_STRUCT_OFFSET (MonoLMF, previous_lmf));
+ /* Restore VFP registers. */
+ if (mono_arm_is_hard_float ()) {
+ ARM_ADD_REG_IMM8 (code, ARMREG_R0, ARMREG_V1, G_STRUCT_OFFSET (MonoLMF, fregs));
+ ARM_FLDMD (code, ARM_VFP_D0, 8, ARMREG_R0);
+ }
+
/* Non-standard function epilogue. Instead of doing a proper
* return, we just jump to the compiled code.
*/
#include "mini.h"
#include "mini-ppc.h"
+#if 0
/* Same as mono_create_ftnptr, but doesn't require a domain */
static gpointer
mono_ppc_create_ftnptr (guint8 *code)
return code;
#endif
}
+#endif
/*
* Return the instruction to jump from code to target, 0 if not
/*========================= End of Function ========================*/
+/*------------------------------------------------------------------*/
+/* */
+/* Name - mono_arch_get_nullified_class_init */
+/* */
+/* Function - Nullify a PLT entry call. */
+/* */
+/*------------------------------------------------------------------*/
+
+gpointer
+mono_arch_get_nullified_class_init_trampoline (MonoTrampInfo **info)
+{
+ guint8 *buf, *code;
+
+ code = buf = mono_global_codeman_reserve (16);
+
+ s390_br (code, s390_r14);
+
+ if (info)
+ *info = mono_tramp_info_create ("nullified_class_init_trampoline",
+ buf, code - buf, NULL, NULL);
+
+ return (buf);
+}
+
+/*========================= End of Function ========================*/
+
/*------------------------------------------------------------------*/
/* */
/* Name - mono_arch_nullify_plt_entry */
guint8 info [MONO_ZERO_LEN_ARRAY];
} MonoUnwindInfo;
+#define ALIGN_TO(val,align) ((((size_t)val) + ((align) - 1)) & ~((align) - 1))
+
static CRITICAL_SECTION unwind_mutex;
static MonoUnwindInfo **cached_info;
#define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (AMD64_RIP))
#elif defined(TARGET_ARM)
// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0040a/IHI0040A_aadwarf.pdf
-static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
-#define NUM_REGS 16
+/* Assign d8..d15 to hregs 16..24 */
+static int map_hw_reg_to_dwarf_reg [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 264, 265, 266, 267, 268, 269, 270, 271 };
+#define NUM_REGS 272
#define DWARF_DATA_ALIGN (-4)
#define DWARF_PC_REG (mono_hw_reg_to_dwarf_reg (ARMREG_LR))
#elif defined (TARGET_X86)
return res;
}
+void
+mono_print_unwind_info (guint8 *unwind_info, int unwind_info_len)
+{
+ guint8 *p;
+ int pos, reg, offset, cfa_reg, cfa_offset;
+
+ p = unwind_info;
+ pos = 0;
+ while (p < unwind_info + unwind_info_len) {
+ int op = *p & 0xc0;
+
+ switch (op) {
+ case DW_CFA_advance_loc:
+ pos += *p & 0x3f;
+ p ++;
+ break;
+ case DW_CFA_offset:
+ reg = *p & 0x3f;
+ p ++;
+ offset = decode_uleb128 (p, &p) * DWARF_DATA_ALIGN;
+ if (reg == DWARF_PC_REG)
+ printf ("CFA: [%x] offset: %s at cfa-0x%x\n", pos, "pc", -offset);
+ else
+ printf ("CFA: [%x] offset: %s at cfa-0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (reg)), -offset);
+ break;
+ case 0: {
+ int ext_op = *p;
+ p ++;
+ switch (ext_op) {
+ case DW_CFA_def_cfa:
+ cfa_reg = decode_uleb128 (p, &p);
+ cfa_offset = decode_uleb128 (p, &p);
+ printf ("CFA: [%x] def_cfa: %s+0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (cfa_reg)), cfa_offset);
+ break;
+ case DW_CFA_def_cfa_offset:
+ cfa_offset = decode_uleb128 (p, &p);
+ printf ("CFA: [%x] def_cfa_offset: 0x%x\n", pos, cfa_offset);
+ break;
+ case DW_CFA_def_cfa_register:
+ cfa_reg = decode_uleb128 (p, &p);
+ printf ("CFA: [%x] def_cfa_reg: %s\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (cfa_reg)));
+ break;
+ case DW_CFA_offset_extended_sf:
+ reg = decode_uleb128 (p, &p);
+ offset = decode_sleb128 (p, &p) * DWARF_DATA_ALIGN;
+ printf ("CFA: [%x] offset_extended_sf: %s at cfa-0x%x\n", pos, mono_arch_regname (mono_dwarf_reg_to_hw_reg (reg)), -offset);
+ break;
+ case DW_CFA_advance_loc4:
+ pos += read32 (p);
+ p += 4;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+ break;
+ }
+ default:
+ g_assert_not_reached ();
+ }
+ }
+}
+
/*
* mono_unwind_ops_encode:
*
#endif
static G_GNUC_UNUSED void
-print_dwarf_state (int cfa_reg, int cfa_offset, int ip, int nregs, Loc *locations)
+print_dwarf_state (int cfa_reg, int cfa_offset, int ip, int nregs, Loc *locations, guint8 *reg_saved)
{
int i;
printf ("\t%x: cfa=r%d+%d ", ip, cfa_reg, cfa_offset);
for (i = 0; i < nregs; ++i)
- if (locations [i].loc_type == LOC_OFFSET)
+ if (reg_saved [i] && locations [i].loc_type == LOC_OFFSET)
printf ("r%d@%d(cfa) ", i, locations [i].offset);
printf ("\n");
}
guint8 **out_cfa)
{
Loc locations [NUM_REGS];
- int i, pos, reg, cfa_reg, cfa_offset;
+ guint8 reg_saved [NUM_REGS];
+ int i, pos, reg, cfa_reg, cfa_offset, offset;
guint8 *p;
guint8 *cfa_val;
- for (i = 0; i < NUM_REGS; ++i)
- locations [i].loc_type = LOC_SAME;
+ memset (reg_saved, 0, sizeof (reg_saved));
p = unwind_info;
pos = 0;
case DW_CFA_offset:
reg = *p & 0x3f;
p ++;
+ reg_saved [reg] = TRUE;
locations [reg].loc_type = LOC_OFFSET;
locations [reg].offset = decode_uleb128 (p, &p) * DWARF_DATA_ALIGN;
break;
break;
case DW_CFA_offset_extended_sf:
reg = decode_uleb128 (p, &p);
+ offset = decode_sleb128 (p, &p);
+ g_assert (reg < NUM_REGS);
+ reg_saved [reg] = TRUE;
locations [reg].loc_type = LOC_OFFSET;
- locations [reg].offset = decode_sleb128 (p, &p) * DWARF_DATA_ALIGN;
+ locations [reg].offset = offset * DWARF_DATA_ALIGN;
+ break;
+ case DW_CFA_offset_extended:
+ reg = decode_uleb128 (p, &p);
+ offset = decode_uleb128 (p, &p);
+ g_assert (reg < NUM_REGS);
+ reg_saved [reg] = TRUE;
+ locations [reg].loc_type = LOC_OFFSET;
+ locations [reg].offset = offset * DWARF_DATA_ALIGN;
break;
case DW_CFA_advance_loc4:
pos += read32 (p);
cfa_val = (guint8*)regs [mono_dwarf_reg_to_hw_reg (cfa_reg)] + cfa_offset;
for (i = 0; i < NUM_REGS; ++i) {
- if (locations [i].loc_type == LOC_OFFSET) {
+ if (reg_saved [i] && locations [i].loc_type == LOC_OFFSET) {
int hreg = mono_dwarf_reg_to_hw_reg (i);
g_assert (hreg < nregs);
regs [hreg] = *(mgreg_t*)(cfa_val + locations [i].offset);
/*
* decode_lsda:
*
- * Decode the Language Specific Data Area generated by LLVM.
+ * Decode the Mono specific Language Specific Data Area generated by LLVM.
*/
static void
decode_lsda (guint8 *lsda, guint8 *code, MonoJitExceptionInfo **ex_info, guint32 *ex_info_len, gpointer **type_info, int *this_reg, int *this_offset)
{
- gint32 ttype_offset, call_site_length;
- gint32 ttype_encoding, call_site_encoding;
- guint8 *ttype, *action_table, *call_site, *p;
- int i, ncall_sites;
+ guint8 *p;
+ int i, ncall_sites, this_encoding;
+ guint32 mono_magic, version;
- /*
- * LLVM generates a c++ style LSDA, which can be decoded by looking at
- * eh_personality.cc in gcc.
- */
p = lsda;
- if (*p == DW_EH_PE_udata4) {
- /* This is the modified LSDA generated by the LLVM mono branch */
- guint32 mono_magic, version;
+ /* This is the modified LSDA generated by the LLVM mono branch */
+ mono_magic = decode_uleb128 (p, &p);
+ g_assert (mono_magic == 0x4d4fef4f);
+ version = decode_uleb128 (p, &p);
+ g_assert (version == 1);
+ this_encoding = *p;
+ p ++;
+ if (this_encoding == DW_EH_PE_udata4) {
gint32 op, reg, offset;
- p ++;
- mono_magic = decode_uleb128 (p, &p);
- g_assert (mono_magic == 0x4d4fef4f);
- version = decode_uleb128 (p, &p);
- g_assert (version == 1);
-
/* 'this' location */
op = *p;
g_assert (op == DW_OP_bregx);
*this_reg = mono_dwarf_reg_to_hw_reg (reg);
*this_offset = offset;
} else {
- /* Read @LPStart */
- g_assert (*p == DW_EH_PE_omit);
- p ++;
+ g_assert (this_encoding == DW_EH_PE_omit);
*this_reg = -1;
*this_offset = -1;
}
-
- /* Read @TType */
- ttype_encoding = *p;
- p ++;
- ttype_offset = decode_uleb128 (p, &p);
- ttype = p + ttype_offset;
-
- /* Read call-site table */
- call_site_encoding = *p;
- g_assert (call_site_encoding == DW_EH_PE_udata4);
- p ++;
- call_site_length = decode_uleb128 (p, &p);
- call_site = p;
- p += call_site_length;
- action_table = p;
-
- /* Calculate the size of our table */
- ncall_sites = 0;
- p = call_site;
- while (p < action_table) {
- int block_start_offset, block_size, landing_pad, action_offset;
-
- block_start_offset = read32 (p);
- p += sizeof (gint32);
- block_size = read32 (p);
- p += sizeof (gint32);
- landing_pad = read32 (p);
- p += sizeof (gint32);
- action_offset = decode_uleb128 (p, &p);
-
- /* landing_pad == 0 means the region has no landing pad */
- if (landing_pad)
- ncall_sites ++;
- }
+ ncall_sites = decode_uleb128 (p, &p);
+ p = (guint8*)ALIGN_TO ((mgreg_t)p, 4);
if (ex_info) {
*ex_info = g_malloc0 (ncall_sites * sizeof (MonoJitExceptionInfo));
*ex_info_len = ncall_sites;
}
-
if (type_info)
*type_info = g_malloc0 (ncall_sites * sizeof (gpointer));
- p = call_site;
- i = 0;
- while (p < action_table) {
- int block_start_offset, block_size, landing_pad, action_offset, type_offset;
- guint8 *action, *tinfo;
+ for (i = 0; i < ncall_sites; ++i) {
+ int block_start_offset, block_size, landing_pad;
+ guint8 *tinfo;
block_start_offset = read32 (p);
p += sizeof (gint32);
p += sizeof (gint32);
landing_pad = read32 (p);
p += sizeof (gint32);
- action_offset = decode_uleb128 (p, &p);
-
- if (!action_offset)
- continue;
-
- action = action_table + action_offset - 1;
-
- type_offset = decode_sleb128 (action, &action);
-
- if (landing_pad) {
- //printf ("BLOCK: %p-%p %p, %d\n", code + block_start_offset, code + block_start_offset + block_size, code + landing_pad, action_offset);
-
- g_assert (ttype_offset);
-
- if (ttype_encoding == DW_EH_PE_absptr) {
- guint8 *ttype_entry = (ttype - (type_offset * sizeof (gpointer)));
- tinfo = *(gpointer*)ttype_entry;
- } else if (ttype_encoding == (DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4)) {
- guint8 *ttype_entry = (ttype - (type_offset * 4));
- gint32 offset = *(gint32*)ttype_entry;
- guint8 *stub = ttype_entry + offset;
- tinfo = *(gpointer*)stub;
- } else if (ttype_encoding == (DW_EH_PE_pcrel | DW_EH_PE_sdata4)) {
- guint8 *ttype_entry = (ttype - (type_offset * 4));
- gint32 offset = *(gint32*)ttype_entry;
- tinfo = ttype_entry + offset;
- } else if (ttype_encoding == DW_EH_PE_udata4) {
- /* Embedded directly */
- guint8 *ttype_entry = (ttype - (type_offset * 4));
- tinfo = ttype_entry;
- } else {
- g_assert_not_reached ();
- }
+ tinfo = p;
+ p += sizeof (gint32);
- if (ex_info) {
- if (*type_info)
- (*type_info) [i] = tinfo;
- (*ex_info)[i].try_start = code + block_start_offset;
- (*ex_info)[i].try_end = code + block_start_offset + block_size;
- (*ex_info)[i].handler_start = code + landing_pad;
+ g_assert (landing_pad);
+ g_assert (((size_t)tinfo % 4) == 0);
+ //printf ("X: %p %d\n", landing_pad, *(int*)tinfo);
- }
- i ++;
+ if (ex_info) {
+ if (*type_info)
+ (*type_info) [i] = tinfo;
+ (*ex_info)[i].try_start = code + block_start_offset;
+ (*ex_info)[i].try_end = code + block_start_offset + block_size;
+ (*ex_info)[i].handler_start = code + landing_pad;
}
}
}
runtime_lib=../interpreter/libmint.la
endif
+if DISABLE_EXECUTABLES
+bin_PROGRAMS =
+else
if DISABLE_LIBRARIES
+bin_PROGRAMS =
else
+if SUPPORT_BOEHM
bin_PROGRAMS = monograph
endif
+endif
+endif
AM_CPPFLAGS = \
-I$(top_srcdir) \
using System.Threading;
public class FinalizerException {
+
~FinalizerException () {
throw new Exception ();
}
+ static IntPtr aptr;
+
/*
* We allocate the exception object deep down the stack so
* that it doesn't get pinned.
public static unsafe void MakeException (int depth) {
// Avoid tail calls
int* values = stackalloc int [20];
+ aptr = new IntPtr (values);
if (depth <= 0) {
new FinalizerException ();
return;
mono-hwcap.h \
mono-hwcap.c \
bsearch.h \
- bsearch.c
+ bsearch.c \
+ mono-signal-handler.h
arch_sources =
#include "utils/mono-compiler.h"
#include "mach-support.h"
+/* _mcontext.h now defines __darwin_mcontext32, not __darwin_mcontext, starting with Xcode 5.1 */
+#ifdef _STRUCT_MCONTEXT32
+ #define __darwin_mcontext __darwin_mcontext32
+#endif
+
/* Known offsets used for TLS storage*/
gboolean mono_hwcap_arm_is_v7 = FALSE;
gboolean mono_hwcap_arm_is_v7s = FALSE;
gboolean mono_hwcap_arm_has_vfp = FALSE;
+gboolean mono_hwcap_arm_has_vfp3 = FALSE;
+gboolean mono_hwcap_arm_has_vfp3_d16 = FALSE;
gboolean mono_hwcap_arm_has_thumb = FALSE;
gboolean mono_hwcap_arm_has_thumb2 = FALSE;
if (hwcap & 0x00000040)
mono_hwcap_arm_has_vfp = TRUE;
+ /* HWCAP_ARM_VFPv3 */
+ if (hwcap & 0x00002000)
+ mono_hwcap_arm_has_vfp3 = TRUE;
+
+ /* HWCAP_ARM_VFPv3D16 */
+ if (hwcap & 0x00004000)
+ mono_hwcap_arm_has_vfp3_d16 = TRUE;
+
/* TODO: Find a way to detect Thumb 2. */
}
if (strstr (line, "vfp"))
mono_hwcap_arm_has_vfp = TRUE;
+ if (strstr (line, "vfpv3"))
+ mono_hwcap_arm_has_vfp3 = TRUE;
+
+ if (strstr (line, "vfpv3-d16"))
+ mono_hwcap_arm_has_vfp3_d16 = TRUE;
+
continue;
}
}
g_fprintf (f, "mono_hwcap_arm_is_v7 = %i\n", mono_hwcap_arm_is_v7);
g_fprintf (f, "mono_hwcap_arm_is_v7s = %i\n", mono_hwcap_arm_is_v7s);
g_fprintf (f, "mono_hwcap_arm_has_vfp = %i\n", mono_hwcap_arm_has_vfp);
+ g_fprintf (f, "mono_hwcap_arm_has_vfp3 = %i\n", mono_hwcap_arm_has_vfp3);
+ g_fprintf (f, "mono_hwcap_arm_has_vfp3_d16 = %i\n", mono_hwcap_arm_has_vfp3_d16);
g_fprintf (f, "mono_hwcap_arm_has_thumb = %i\n", mono_hwcap_arm_has_thumb);
g_fprintf (f, "mono_hwcap_arm_has_thumb2 = %i\n", mono_hwcap_arm_has_thumb2);
}
extern gboolean mono_hwcap_arm_is_v7;
extern gboolean mono_hwcap_arm_is_v7s;
extern gboolean mono_hwcap_arm_has_vfp;
+extern gboolean mono_hwcap_arm_has_vfp3;
+extern gboolean mono_hwcap_arm_has_vfp3_d16;
extern gboolean mono_hwcap_arm_has_thumb;
extern gboolean mono_hwcap_arm_has_thumb2;
char buf [256];
char *s;
int hz = get_user_hz ();
- guint64 user_ticks, nice_ticks, system_ticks, idle_ticks, iowait_ticks, irq_ticks, sirq_ticks;
+ guint64 user_ticks = 0, nice_ticks = 0, system_ticks = 0, idle_ticks = 0, iowait_ticks, irq_ticks = 0, sirq_ticks = 0;
FILE *f = fopen ("/proc/stat", "r");
if (!f)
return;
mono_native_tls_set_value (small_id_key, GUINT_TO_POINTER (info->small_id + 1));
info->thread_state = STATE_SHUTTING_DOWN;
+
+ /*
+ First perform the callback that requires no locks.
+ This callback has the potential of taking other locks, so we do it before.
+ After it completes, the thread remains functional.
+ */
+ if (threads_callbacks.thread_detach)
+ threads_callbacks.thread_detach (info);
+
mono_thread_info_suspend_lock ();
+
+ /*
+ Now perform the callback that must be done under locks.
+ This will render the thread useless and non-suspendable, so it must
+ be done while holding the suspend lock to give no other thread chance
+ to suspend it.
+ */
if (threads_callbacks.thread_unregister)
threads_callbacks.thread_unregister (info);
mono_threads_unregister_current_thread (info);
typedef struct {
void* (*thread_register)(THREAD_INFO_TYPE *info, void *baseaddr);
/*
- This callback is called after @info is removed from the thread list.
+ This callback is called with @info still on the thread list.
+ This call is made while holding the suspend lock, so don't do callbacks.
SMR remains functional as its small_id has not been reclaimed.
*/
void (*thread_unregister)(THREAD_INFO_TYPE *info);
+ /*
+ This callback is called right before thread_unregister. This is called
+ without any locks held so it's the place for complicated cleanup.
+
+ The thread must remain operational between this call and thread_unregister.
+ It must be possible to successfully suspend it after thread_unregister completes.
+ */
+ void (*thread_detach)(THREAD_INFO_TYPE *info);
void (*thread_attach)(THREAD_INFO_TYPE *info);
gboolean (*mono_method_is_critical) (void *method);
#ifndef HOST_WIN32
* Copyright 2013 Xamarin, Inc (http://www.xamarin.com)
*/
+#include <config.h>
+
#include "mono-tls.h"
static int tls_offsets [TLS_KEY_NUM];
</ItemGroup>\r
<Import Project="mono.props" />\r
<ItemGroup>\r
+ <ClCompile Include="..\mono\mini\alias-analysis.c" />\r
<ClCompile Include="..\mono\mini\exceptions-amd64.c">\r
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>\r
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug_SGen|Win32'">true</ExcludedFromBuild>\r
<ClCompile Include="..\mono\mini\local-propagation.c" />\r
<ClCompile Include="..\mono\mini\driver.c" />\r
<ClCompile Include="..\mono\mini\debug-mini.c" />\r
- <ClInclude Include="..\mono\mini\debug-mini.h" />\r
<ClCompile Include="..\mono\mini\linear-scan.c" />\r
<ClCompile Include="..\mono\mini\aot-compiler.c" />\r
<ClCompile Include="..\mono\mini\aot-runtime.c" />\r
<ClCompile Include="..\mono\mini\mini-gc.c" />\r
<ClInclude Include="..\mono\mini\debugger-agent.h " />\r
<ClCompile Include="..\mono\mini\debugger-agent.c" />\r
- <ClCompile Include="..\mono\mini\debug-debugger.c" />\r
- <ClInclude Include="..\mono\mini\debug-debugger.h" />\r
<ClCompile Include="..\mono\mini\xdebug.c" />\r
<ClInclude Include="..\mono\mini\mini-llvm.h" />\r
<ClInclude Include="..\mono\mini\mini-llvm-cpp.h" />\r
<ClCompile Include="..\mono\metadata\exception.c" />\r
<ClCompile Include="..\mono\metadata\file-io.c" />\r
<ClCompile Include="..\mono\metadata\filewatcher.c" />\r
+ <ClCompile Include="..\mono\metadata\gc-memfuncs.c" />\r
<ClCompile Include="..\mono\metadata\gc.c" />\r
<ClCompile Include="..\mono\metadata\icall.c" />\r
<ClCompile Include="..\mono\metadata\image.c" />\r
<ClCompile Include="..\mono\utils\mono-threads-windows.c" />\r
<ClCompile Include="..\mono\utils\mono-threads.c" />\r
<ClCompile Include="..\mono\utils\mono-time.c" />\r
+ <ClCompile Include="..\mono\utils\mono-tls.c" />\r
<ClCompile Include="..\mono\utils\mono-uri.c" />\r
<ClCompile Include="..\mono\utils\mono-value-hash.c" />\r
<ClCompile Include="..\mono\utils\monobitset.c" />\r
public bool HasMissingLocale { get; set; }
+ public bool IsNeutral {
+ get {
+ return Territory == null;
+ }
+ }
+
public string OriginalName { get; set; }
public CultureInfoEntry Parent { get; set; }
ci.DateTimeFormatEntry.CalendarWeekRule = (int) rule;
}
- string fraction_value;
- if (currency_fractions.TryGetValue (ci.Territory, out fraction_value)) {
- ci.NumberFormatEntry.CurrencyDecimalDigits = fraction_value;
- }
-
RegionInfoEntry region = regions.Where (l => l.Name == ci.Territory).FirstOrDefault ();
if (region == null) {
region = new RegionInfoEntry () {
regions.Add (region);
}
+ string fraction_value;
+ if (currency_fractions.TryGetValue (region.ISOCurrencySymbol, out fraction_value)) {
+ ci.NumberFormatEntry.CurrencyDecimalDigits = fraction_value;
+ }
+
ci.RegionInfoEntry = region;
}
case "zh-Hant":
nfe.CurrencySymbol = "HK$";
break;
-
+
default:
var all_currencies = new List<string> ();
GetAllChildrenValues (ci, all_currencies, l => l.NumberFormatEntry.CurrencySymbol);
if (!ci.HasMissingLocale)
Console.WriteLine ("No currency decimal digits data for `{0}'", ci.Name);
+ nfe.CurrencyDecimalDigits = "2";
+ } else if (ci.IsNeutral) {
nfe.CurrencyDecimalDigits = "2";
} else {
// .NET has weird concept of territory data available for neutral cultures (e.g. en, es, pt)
el = node.SelectSingleNode ("decimal");
if (el != null) {
ni.NumberDecimalSeparator =
- ni.PercentDecimalSeparator =
- ni.CurrencyDecimalSeparator = el.InnerText;
+ ni.PercentDecimalSeparator = el.InnerText;
}
el = node.SelectSingleNode ("plusSign");
};
static readonly Dictionary<int, string[]> Numbers = new Dictionary<int, string[]> {
- { 0x0001, new [] { "3", "2", "3", "0", "0" } },
- { 0x0002, new [] { "8", "3", "1", "0", "0" } },
- { 0x0003, new [] { "8", "3", "1", "0", "0" } },
- { 0x0004, new [] { "2", "0", "1", "1", "1" } },
- { 0x0005, new [] { "8", "3", "1", "1", "1" } },
- { 0x0006, new [] { "12", "2", "1", "0", "0" } },
- { 0x0007, new [] { "8", "3", "1", "1", "1" } },
- { 0x0008, new [] { "8", "3", "1", "1", "1" } },
- { 0x0009, new [] { "0", "0", "1", "0", "0" } },
- { 0x000a, new [] { "8", "3", "1", "0", "0" } },
- { 0x000b, new [] { "8", "3", "1", "0", "0" } },
- { 0x000c, new [] { "8", "3", "1", "0", "0" } },
- { 0x000d, new [] { "2", "2", "1", "1", "1" } },
- { 0x000e, new [] { "8", "3", "1", "0", "0" } },
- { 0x000f, new [] { "8", "3", "1", "1", "1" } },
- { 0x0010, new [] { "9", "2", "1", "1", "1" } },
- { 0x0011, new [] { "1", "0", "1", "1", "1" } },
- { 0x0012, new [] { "1", "0", "1", "0", "0" } },
- { 0x0013, new [] { "12", "2", "1", "0", "0" } },
- { 0x0014, new [] { "12", "2", "1", "0", "0" } },
- { 0x0015, new [] { "8", "3", "1", "1", "1" } },
- { 0x0016, new [] { "9", "2", "1", "1", "1" } },
- { 0x0017, new [] { "2", "2", "1", "1", "1" } },
- { 0x0018, new [] { "8", "3", "1", "1", "1" } },
- { 0x0019, new [] { "5", "1", "1", "1", "1" } },
- { 0x001a, new [] { "8", "3", "2", "1", "1" } },
- { 0x001b, new [] { "8", "3", "1", "1", "1" } },
- { 0x001c, new [] { "5", "1", "1", "0", "0" } },
- { 0x001d, new [] { "8", "3", "1", "0", "0" } },
- { 0x001e, new [] { "1", "0", "1", "0", "0" } },
- { 0x001f, new [] { "8", "3", "1", "2", "2" } },
- { 0x0020, new [] { "3", "0", "1", "0", "0" } },
- { 0x0021, new [] { "0", "0", "1", "0", "0" } },
- { 0x0022, new [] { "5", "1", "1", "1", "1" } },
- { 0x0023, new [] { "8", "3", "1", "0", "0" } },
- { 0x0024, new [] { "8", "3", "1", "1", "1" } },
- { 0x0025, new [] { "8", "3", "1", "1", "1" } },
- { 0x0026, new [] { "9", "2", "1", "1", "1" } },
- { 0x0027, new [] { "8", "3", "1", "1", "1" } },
- { 0x0028, new [] { "8", "3", "1", "1", "1" } },
- { 0x0029, new [] { "3", "2", "3", "0", "0" } },
- { 0x002a, new [] { "8", "3", "1", "0", "0" } },
- { 0x002b, new [] { "8", "3", "1", "0", "0" } },
- { 0x002c, new [] { "8", "3", "1", "1", "1" } },
- { 0x002d, new [] { "8", "3", "1", "0", "0" } },
- { 0x002e, new [] { "8", "3", "1", "0", "0" } },
- { 0x002f, new [] { "8", "3", "1", "0", "0" } },
- { 0x0032, new [] { "2", "2", "1", "2", "2" } },
- { 0x0034, new [] { "2", "2", "1", "2", "2" } },
- { 0x0035, new [] { "2", "2", "1", "2", "2" } },
- { 0x0036, new [] { "2", "2", "1", "1", "1" } },
- { 0x0037, new [] { "8", "3", "1", "0", "0" } },
- { 0x0038, new [] { "12", "2", "1", "1", "1" } },
- { 0x0039, new [] { "12", "2", "1", "0", "0" } },
- { 0x003a, new [] { "1", "0", "1", "2", "2" } },
- { 0x003b, new [] { "12", "2", "1", "2", "2" } },
- { 0x003c, new [] { "1", "0", "1", "0", "0" } },
- { 0x003e, new [] { "0", "0", "1", "0", "0" } },
- { 0x003f, new [] { "1", "0", "1", "1", "1" } },
- { 0x0040, new [] { "8", "3", "1", "1", "1" } },
- { 0x0041, new [] { "0", "0", "1", "0", "0" } },
- { 0x0042, new [] { "5", "1", "1", "1", "1" } },
- { 0x0043, new [] { "8", "3", "1", "1", "1" } },
- { 0x0044, new [] { "8", "3", "1", "1", "1" } },
- { 0x0045, new [] { "12", "2", "1", "2", "2" } },
- { 0x0046, new [] { "12", "2", "1", "0", "0" } },
- { 0x0047, new [] { "12", "2", "1", "0", "0" } },
- { 0x0048, new [] { "12", "2", "1", "0", "0" } },
- { 0x0049, new [] { "12", "2", "1", "0", "0" } },
- { 0x004a, new [] { "12", "2", "1", "0", "0" } },
- { 0x004b, new [] { "12", "2", "1", "0", "0" } },
- { 0x004c, new [] { "12", "2", "1", "2", "2" } },
- { 0x004d, new [] { "12", "1", "1", "1", "1" } },
- { 0x004e, new [] { "12", "2", "1", "0", "0" } },
- { 0x004f, new [] { "12", "2", "1", "0", "0" } },
- { 0x0050, new [] { "5", "1", "1", "0", "0" } },
- { 0x0051, new [] { "2", "0", "1", "1", "1" } },
- { 0x0052, new [] { "1", "0", "1", "2", "2" } },
- { 0x0053, new [] { "5", "1", "2", "1", "1" } },
- { 0x0054, new [] { "4", "1", "0", "0", "0" } },
- { 0x0056, new [] { "8", "3", "1", "0", "0" } },
- { 0x0057, new [] { "12", "2", "1", "0", "0" } },
- { 0x005a, new [] { "3", "2", "1", "0", "0" } },
- { 0x005b, new [] { "14", "2", "1", "0", "0" } },
- { 0x005d, new [] { "0", "0", "1", "0", "0" } },
- { 0x005e, new [] { "1", "0", "1", "1", "1" } },
- { 0x005f, new [] { "8", "3", "3", "0", "0" } },
- { 0x0061, new [] { "1", "0", "1", "1", "1" } },
- { 0x0062, new [] { "12", "2", "1", "0", "0" } },
- { 0x0063, new [] { "3", "0", "3", "4", "2" } },
- { 0x0064, new [] { "0", "0", "1", "0", "0" } },
- { 0x0065, new [] { "10", "3", "1", "0", "0" } },
- { 0x0068, new [] { "2", "2", "1", "0", "0" } },
- { 0x006a, new [] { "2", "2", "1", "0", "0" } },
- { 0x006b, new [] { "14", "2", "1", "2", "2" } },
- { 0x006c, new [] { "2", "2", "1", "2", "2" } },
- { 0x006d, new [] { "8", "3", "1", "1", "1" } },
- { 0x006e, new [] { "8", "3", "1", "0", "0" } },
- { 0x006f, new [] { "12", "2", "1", "0", "0" } },
- { 0x0070, new [] { "2", "2", "1", "0", "0" } },
- { 0x0078, new [] { "2", "0", "1", "1", "1" } },
- { 0x007a, new [] { "9", "2", "1", "0", "0" } },
- { 0x007c, new [] { "0", "0", "1", "0", "0" } },
- { 0x007e, new [] { "8", "3", "1", "0", "0" } },
- { 0x007f, new [] { "0", "0", "1", "0", "0" } },
- { 0x0080, new [] { "2", "0", "1", "1", "1" } },
- { 0x0081, new [] { "1", "0", "1", "2", "2" } },
- { 0x0082, new [] { "8", "3", "1", "0", "0" } },
- { 0x0083, new [] { "8", "3", "1", "0", "0" } },
- { 0x0084, new [] { "8", "3", "1", "0", "0" } },
- { 0x0085, new [] { "5", "1", "1", "1", "1" } },
- { 0x0086, new [] { "0", "0", "1", "0", "0" } },
- { 0x0087, new [] { "2", "2", "1", "0", "0" } },
- { 0x0088, new [] { "8", "3", "1", "0", "0" } },
- { 0x008c, new [] { "3", "0", "3", "4", "2" } },
- { 0x0091, new [] { "1", "0", "1", "0", "0" } },
- { 0x0401, new [] { "3", "2", "3", "0", "0" } },
- { 0x0402, new [] { "8", "3", "1", "0", "0" } },
- { 0x0403, new [] { "8", "3", "1", "0", "0" } },
- { 0x0404, new [] { "1", "0", "1", "1", "1" } },
- { 0x0405, new [] { "8", "3", "1", "1", "1" } },
- { 0x0406, new [] { "12", "2", "1", "0", "0" } },
- { 0x0407, new [] { "8", "3", "1", "1", "1" } },
- { 0x0408, new [] { "8", "3", "1", "1", "1" } },
- { 0x0409, new [] { "0", "0", "1", "0", "0" } },
- { 0x040b, new [] { "8", "3", "1", "0", "0" } },
- { 0x040c, new [] { "8", "3", "1", "0", "0" } },
- { 0x040d, new [] { "2", "2", "1", "1", "1" } },
- { 0x040e, new [] { "8", "3", "1", "0", "0" } },
- { 0x040f, new [] { "8", "3", "1", "1", "1" } },
- { 0x0410, new [] { "9", "2", "1", "1", "1" } },
- { 0x0411, new [] { "1", "0", "1", "1", "1" } },
- { 0x0412, new [] { "1", "0", "1", "0", "0" } },
- { 0x0413, new [] { "12", "2", "1", "0", "0" } },
- { 0x0414, new [] { "12", "2", "1", "0", "0" } },
- { 0x0415, new [] { "8", "3", "1", "1", "1" } },
- { 0x0416, new [] { "9", "2", "1", "1", "1" } },
- { 0x0417, new [] { "2", "2", "1", "1", "1" } },
- { 0x0418, new [] { "8", "3", "1", "1", "1" } },
- { 0x0419, new [] { "5", "1", "1", "1", "1" } },
- { 0x041a, new [] { "8", "3", "2", "1", "1" } },
- { 0x041b, new [] { "8", "3", "1", "1", "1" } },
- { 0x041c, new [] { "5", "1", "1", "0", "0" } },
- { 0x041d, new [] { "8", "3", "1", "0", "0" } },
- { 0x041e, new [] { "1", "0", "1", "0", "0" } },
- { 0x041f, new [] { "8", "3", "1", "2", "2" } },
- { 0x0420, new [] { "3", "0", "1", "0", "0" } },
- { 0x0421, new [] { "0", "0", "1", "0", "0" } },
- { 0x0422, new [] { "5", "1", "1", "1", "1" } },
- { 0x0423, new [] { "8", "3", "1", "0", "0" } },
- { 0x0424, new [] { "8", "3", "1", "1", "1" } },
- { 0x0425, new [] { "8", "3", "1", "1", "1" } },
- { 0x0426, new [] { "9", "2", "1", "1", "1" } },
- { 0x0427, new [] { "8", "3", "1", "1", "1" } },
- { 0x0428, new [] { "8", "3", "1", "1", "1" } },
- { 0x0429, new [] { "3", "2", "3", "0", "0" } },
- { 0x042a, new [] { "8", "3", "1", "0", "0" } },
- { 0x042b, new [] { "8", "3", "1", "0", "0" } },
- { 0x042c, new [] { "8", "3", "1", "1", "1" } },
- { 0x042d, new [] { "8", "3", "1", "0", "0" } },
- { 0x042e, new [] { "8", "3", "1", "0", "0" } },
- { 0x042f, new [] { "8", "3", "1", "0", "0" } },
- { 0x0432, new [] { "2", "2", "1", "2", "2" } },
- { 0x0434, new [] { "2", "2", "1", "2", "2" } },
- { 0x0435, new [] { "2", "2", "1", "2", "2" } },
- { 0x0436, new [] { "2", "2", "1", "1", "1" } },
- { 0x0437, new [] { "8", "3", "1", "0", "0" } },
- { 0x0438, new [] { "12", "2", "1", "1", "1" } },
- { 0x0439, new [] { "12", "2", "1", "0", "0" } },
- { 0x043a, new [] { "1", "0", "1", "2", "2" } },
- { 0x043b, new [] { "12", "2", "1", "2", "2" } },
- { 0x043e, new [] { "0", "0", "1", "0", "0" } },
- { 0x043f, new [] { "1", "0", "1", "1", "1" } },
- { 0x0440, new [] { "8", "3", "1", "1", "1" } },
- { 0x0441, new [] { "0", "0", "1", "0", "0" } },
- { 0x0442, new [] { "5", "1", "1", "1", "1" } },
- { 0x0443, new [] { "8", "3", "1", "1", "1" } },
- { 0x0444, new [] { "8", "3", "1", "1", "1" } },
- { 0x0445, new [] { "12", "2", "1", "2", "2" } },
- { 0x0446, new [] { "12", "2", "1", "0", "0" } },
- { 0x0447, new [] { "12", "2", "1", "0", "0" } },
- { 0x0448, new [] { "12", "2", "1", "0", "0" } },
- { 0x0449, new [] { "12", "2", "1", "0", "0" } },
- { 0x044a, new [] { "12", "2", "1", "0", "0" } },
- { 0x044b, new [] { "12", "2", "1", "0", "0" } },
- { 0x044c, new [] { "12", "2", "1", "2", "2" } },
- { 0x044d, new [] { "12", "1", "1", "1", "1" } },
- { 0x044e, new [] { "12", "2", "1", "0", "0" } },
- { 0x044f, new [] { "12", "2", "1", "0", "0" } },
- { 0x0450, new [] { "5", "1", "1", "0", "0" } },
- { 0x0451, new [] { "2", "0", "1", "1", "1" } },
- { 0x0452, new [] { "1", "0", "1", "2", "2" } },
- { 0x0453, new [] { "5", "1", "2", "1", "1" } },
- { 0x0454, new [] { "4", "1", "0", "0", "0" } },
- { 0x0456, new [] { "8", "3", "1", "0", "0" } },
- { 0x0457, new [] { "12", "2", "1", "0", "0" } },
- { 0x045a, new [] { "3", "2", "1", "0", "0" } },
- { 0x045b, new [] { "14", "2", "1", "0", "0" } },
- { 0x045d, new [] { "0", "0", "1", "1", "1" } },
- { 0x045e, new [] { "1", "0", "1", "1", "1" } },
- { 0x0461, new [] { "1", "0", "1", "1", "1" } },
- { 0x0462, new [] { "12", "2", "1", "0", "0" } },
- { 0x0463, new [] { "3", "0", "3", "4", "2" } },
- { 0x0464, new [] { "0", "0", "1", "0", "0" } },
- { 0x0465, new [] { "10", "3", "1", "0", "0" } },
- { 0x0468, new [] { "2", "2", "1", "0", "0" } },
- { 0x046a, new [] { "2", "2", "1", "0", "0" } },
- { 0x046b, new [] { "14", "2", "1", "2", "2" } },
- { 0x046c, new [] { "2", "2", "1", "2", "2" } },
- { 0x046d, new [] { "8", "3", "1", "1", "1" } },
- { 0x046e, new [] { "8", "3", "1", "0", "0" } },
- { 0x046f, new [] { "12", "2", "1", "0", "0" } },
- { 0x0470, new [] { "2", "2", "1", "0", "0" } },
- { 0x0478, new [] { "2", "0", "1", "1", "1" } },
- { 0x047a, new [] { "9", "2", "1", "0", "0" } },
- { 0x047c, new [] { "0", "0", "1", "0", "0" } },
- { 0x047e, new [] { "8", "3", "1", "0", "0" } },
- { 0x0480, new [] { "2", "0", "1", "1", "1" } },
- { 0x0481, new [] { "1", "0", "1", "2", "2" } },
- { 0x0482, new [] { "8", "3", "1", "0", "0" } },
- { 0x0483, new [] { "8", "3", "1", "0", "0" } },
- { 0x0484, new [] { "8", "3", "1", "0", "0" } },
- { 0x0485, new [] { "5", "1", "1", "1", "1" } },
- { 0x0486, new [] { "0", "0", "1", "0", "0" } },
- { 0x0487, new [] { "2", "2", "1", "0", "0" } },
- { 0x0488, new [] { "8", "3", "1", "0", "0" } },
- { 0x048c, new [] { "3", "0", "3", "4", "2" } },
- { 0x0491, new [] { "1", "0", "1", "0", "0" } },
- { 0x0801, new [] { "3", "2", "3", "0", "0" } },
- { 0x0804, new [] { "2", "0", "1", "1", "1" } },
- { 0x0807, new [] { "2", "2", "1", "1", "1" } },
- { 0x0809, new [] { "1", "0", "1", "0", "0" } },
- { 0x080a, new [] { "1", "0", "1", "0", "0" } },
- { 0x080c, new [] { "12", "2", "1", "0", "0" } },
- { 0x0810, new [] { "2", "2", "1", "1", "1" } },
- { 0x0813, new [] { "12", "2", "1", "1", "1" } },
- { 0x0814, new [] { "12", "2", "1", "0", "0" } },
- { 0x0816, new [] { "8", "3", "1", "1", "1" } },
- { 0x081a, new [] { "8", "3", "1", "1", "1" } },
- { 0x081d, new [] { "8", "3", "1", "0", "0" } },
- { 0x082c, new [] { "8", "3", "1", "1", "1" } },
- { 0x082e, new [] { "8", "3", "1", "0", "0" } },
- { 0x083b, new [] { "8", "3", "1", "0", "0" } },
- { 0x083c, new [] { "1", "0", "1", "0", "0" } },
- { 0x083e, new [] { "0", "0", "1", "0", "0" } },
- { 0x0843, new [] { "8", "3", "1", "1", "1" } },
- { 0x0845, new [] { "12", "2", "1", "2", "2" } },
- { 0x0850, new [] { "2", "0", "1", "1", "1" } },
- { 0x085d, new [] { "0", "0", "1", "0", "0" } },
- { 0x085f, new [] { "8", "3", "3", "0", "0" } },
- { 0x086b, new [] { "14", "2", "1", "2", "2" } },
- { 0x0c01, new [] { "3", "2", "3", "0", "0" } },
- { 0x0c04, new [] { "0", "0", "1", "1", "1" } },
- { 0x0c07, new [] { "9", "2", "1", "1", "1" } },
- { 0x0c09, new [] { "1", "0", "1", "0", "0" } },
- { 0x0c0a, new [] { "8", "3", "1", "0", "0" } },
- { 0x0c0c, new [] { "15", "3", "1", "0", "0" } },
- { 0x0c1a, new [] { "8", "3", "1", "1", "1" } },
- { 0x0c3b, new [] { "8", "3", "1", "0", "0" } },
- { 0x0c6b, new [] { "12", "2", "1", "2", "2" } },
- { 0x1001, new [] { "3", "0", "3", "0", "0" } },
- { 0x1004, new [] { "0", "0", "1", "1", "1" } },
- { 0x1007, new [] { "8", "3", "1", "1", "1" } },
- { 0x1009, new [] { "1", "0", "1", "0", "0" } },
- { 0x100a, new [] { "0", "0", "1", "0", "0" } },
- { 0x100c, new [] { "2", "2", "1", "0", "0" } },
- { 0x101a, new [] { "8", "3", "2", "0", "0" } },
- { 0x103b, new [] { "12", "2", "1", "2", "2" } },
- { 0x1401, new [] { "3", "2", "3", "0", "0" } },
- { 0x1404, new [] { "0", "0", "1", "1", "1" } },
- { 0x1407, new [] { "2", "2", "1", "1", "1" } },
- { 0x1409, new [] { "1", "0", "1", "0", "0" } },
- { 0x140a, new [] { "0", "0", "1", "0", "0" } },
- { 0x140c, new [] { "8", "3", "1", "0", "0" } },
- { 0x141a, new [] { "8", "3", "1", "0", "0" } },
- { 0x143b, new [] { "8", "3", "1", "0", "0" } },
- { 0x1801, new [] { "3", "2", "3", "0", "0" } },
- { 0x1809, new [] { "1", "0", "1", "0", "0" } },
- { 0x180a, new [] { "14", "2", "1", "0", "0" } },
- { 0x180c, new [] { "8", "3", "1", "0", "0" } },
- { 0x181a, new [] { "8", "3", "1", "0", "0" } },
- { 0x183b, new [] { "12", "2", "1", "2", "2" } },
- { 0x1c01, new [] { "3", "2", "3", "0", "0" } },
- { 0x1c09, new [] { "2", "2", "1", "1", "1" } },
- { 0x1c0a, new [] { "0", "0", "1", "0", "0" } },
- { 0x1c1a, new [] { "8", "3", "1", "0", "0" } },
- { 0x1c3b, new [] { "8", "3", "1", "0", "0" } },
- { 0x2001, new [] { "3", "2", "3", "0", "0" } },
- { 0x2009, new [] { "1", "0", "1", "0", "0" } },
- { 0x200a, new [] { "12", "2", "1", "0", "0" } },
- { 0x201a, new [] { "8", "3", "1", "0", "0" } },
- { 0x203b, new [] { "8", "3", "1", "0", "0" } },
- { 0x2401, new [] { "3", "2", "3", "0", "0" } },
- { 0x2409, new [] { "1", "0", "1", "0", "0" } },
- { 0x240a, new [] { "14", "2", "1", "0", "0" } },
- { 0x241a, new [] { "8", "3", "1", "1", "1" } },
- { 0x243b, new [] { "8", "3", "1", "0", "0" } },
- { 0x2801, new [] { "3", "2", "3", "0", "0" } },
- { 0x2809, new [] { "0", "0", "1", "0", "0" } },
- { 0x280a, new [] { "12", "2", "1", "0", "0" } },
- { 0x281a, new [] { "8", "3", "1", "1", "1" } },
- { 0x2c01, new [] { "3", "2", "3", "0", "0" } },
- { 0x2c09, new [] { "0", "0", "1", "0", "0" } },
- { 0x2c0a, new [] { "2", "2", "1", "0", "0" } },
- { 0x2c1a, new [] { "8", "3", "1", "1", "1" } },
- { 0x3001, new [] { "3", "2", "3", "0", "0" } },
- { 0x3009, new [] { "0", "0", "1", "0", "0" } },
- { 0x300a, new [] { "14", "2", "1", "0", "0" } },
- { 0x301a, new [] { "8", "3", "1", "1", "1" } },
- { 0x3401, new [] { "3", "2", "3", "0", "0" } },
- { 0x3409, new [] { "0", "0", "1", "0", "0" } },
- { 0x340a, new [] { "9", "2", "1", "0", "0" } },
- { 0x3801, new [] { "3", "2", "3", "0", "0" } },
- { 0x380a, new [] { "14", "2", "1", "0", "0" } },
- { 0x3c01, new [] { "3", "2", "3", "0", "0" } },
- { 0x3c0a, new [] { "14", "2", "1", "0", "0" } },
- { 0x4001, new [] { "3", "2", "3", "0", "0" } },
- { 0x4009, new [] { "12", "2", "1", "0", "0" } },
- { 0x400a, new [] { "14", "2", "1", "0", "0" } },
- { 0x4409, new [] { "0", "0", "1", "1", "1" } },
- { 0x440a, new [] { "0", "0", "1", "0", "0" } },
- { 0x4809, new [] { "0", "0", "1", "1", "1" } },
- { 0x480a, new [] { "12", "2", "1", "0", "0" } },
- { 0x4c0a, new [] { "14", "2", "1", "0", "0" } },
- { 0x500a, new [] { "14", "2", "1", "0", "0" } },
- { 0x540a, new [] { "0", "0", "1", "0", "0" } },
- { 0x641a, new [] { "8", "3", "1", "0", "0" } },
- { 0x681a, new [] { "8", "3", "1", "0", "0" } },
- { 0x6c1a, new [] { "8", "3", "1", "1", "1" } },
- { 0x701a, new [] { "8", "3", "1", "1", "1" } },
- { 0x703b, new [] { "8", "3", "1", "0", "0" } },
- { 0x742c, new [] { "8", "3", "1", "1", "1" } },
- { 0x743b, new [] { "8", "3", "1", "0", "0" } },
- { 0x7804, new [] { "2", "0", "1", "1", "1" } },
- { 0x7814, new [] { "12", "2", "1", "0", "0" } },
- { 0x781a, new [] { "8", "3", "1", "0", "0" } },
- { 0x782c, new [] { "8", "3", "1", "1", "1" } },
- { 0x783b, new [] { "8", "3", "1", "0", "0" } },
- { 0x7843, new [] { "8", "3", "1", "1", "1" } },
- { 0x7850, new [] { "5", "1", "1", "0", "0" } },
- { 0x785d, new [] { "0", "0", "1", "1", "1" } },
- { 0x7c04, new [] { "0", "0", "1", "1", "1" } },
- { 0x7c14, new [] { "12", "2", "1", "0", "0" } },
- { 0x7c1a, new [] { "8", "3", "1", "1", "1" } },
- { 0x7c28, new [] { "8", "3", "1", "1", "1" } },
- { 0x7c2e, new [] { "8", "3", "1", "0", "0" } },
- { 0x7c3b, new [] { "8", "3", "1", "0", "0" } },
- { 0x7c43, new [] { "8", "3", "1", "1", "1" } },
- { 0x7c50, new [] { "2", "0", "1", "1", "1" } },
- { 0x7c5d, new [] { "0", "0", "1", "0", "0" } },
- { 0x7c5f, new [] { "8", "3", "3", "0", "0" } },
- { 0x7c68, new [] { "2", "2", "1", "0", "0" } },
+ { 0x0001, new [] { "3", "2", "3", "0", "0", ".", "," } },
+ { 0x0002, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x0003, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x0004, new [] { "2", "0", "1", "1", "1", ".", "," } },
+ { 0x0005, new [] { "8", "3", "1", "1", "1", ",", " " } },
+ { 0x0006, new [] { "12", "2", "1", "0", "0", ",", "." } },
+ { 0x0007, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x0008, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x0009, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x000A, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x000B, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x000C, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x000D, new [] { "2", "2", "1", "1", "1", ".", "," } },
+ { 0x000E, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x000F, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x0010, new [] { "9", "2", "1", "1", "1", ",", "." } },
+ { 0x0011, new [] { "1", "0", "1", "1", "1", ".", "," } },
+ { 0x0012, new [] { "1", "0", "1", "0", "0", ".", "," } },
+ { 0x0013, new [] { "12", "2", "1", "0", "0", ",", "." } },
+ { 0x0014, new [] { "12", "2", "1", "0", "0", ",", " " } },
+ { 0x0015, new [] { "8", "3", "1", "1", "1", ",", " " } },
+ { 0x0016, new [] { "9", "2", "1", "1", "1", ",", "." } },
+ { 0x0017, new [] { "2", "2", "1", "1", "1", ".", "'" } },
+ { 0x0018, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x0019, new [] { "5", "1", "1", "1", "1", ",", " " } },
+ { 0x001A, new [] { "8", "3", "2", "1", "1", ",", "." } },
+ { 0x001B, new [] { "8", "3", "1", "1", "1", ",", " " } },
+ { 0x001C, new [] { "5", "1", "1", "0", "0", ",", "." } },
+ { 0x001D, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x001E, new [] { "1", "0", "1", "0", "0", ".", "," } },
+ { 0x001F, new [] { "8", "3", "1", "2", "2", ",", "." } },
+ { 0x0020, new [] { "3", "0", "1", "0", "0", ".", "," } },
+ { 0x0021, new [] { "0", "0", "1", "0", "0", ",", "." } },
+ { 0x0022, new [] { "5", "1", "1", "1", "1", ",", " " } },
+ { 0x0023, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x0024, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x0025, new [] { "8", "3", "1", "1", "1", ".", " " } },
+ { 0x0026, new [] { "9", "2", "1", "1", "1", ",", " " } },
+ { 0x0027, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x0028, new [] { "8", "3", "1", "1", "1", ";", " " } },
+ { 0x0029, new [] { "3", "2", "3", "0", "0", "/", "," } },
+ { 0x002A, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x002B, new [] { "8", "3", "1", "0", "0", ".", "," } },
+ { 0x002C, new [] { "8", "3", "1", "1", "1", ",", " " } },
+ { 0x002D, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x002E, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x002F, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x0032, new [] { "2", "2", "1", "2", "2", ".", "," } },
+ { 0x0034, new [] { "2", "2", "1", "2", "2", ".", "," } },
+ { 0x0035, new [] { "2", "2", "1", "2", "2", ".", "," } },
+ { 0x0036, new [] { "2", "2", "1", "1", "1", ".", "," } },
+ { 0x0037, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x0038, new [] { "12", "2", "1", "1", "1", ",", "." } },
+ { 0x0039, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x003A, new [] { "1", "0", "1", "2", "2", ".", "," } },
+ { 0x003B, new [] { "12", "2", "1", "2", "2", ",", " " } },
+ { 0x003C, new [] { "1", "0", "1", "0", "0", ".", "," } },
+ { 0x003E, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x003F, new [] { "1", "0", "1", "1", "1", "-", " " } },
+ { 0x0040, new [] { "8", "3", "1", "1", "1", "-", " " } },
+ { 0x0041, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x0042, new [] { "5", "1", "1", "1", "1", ",", " " } },
+ { 0x0043, new [] { "8", "3", "1", "1", "1", ",", " " } },
+ { 0x0044, new [] { "8", "3", "1", "1", "1", ",", " " } },
+ { 0x0045, new [] { "12", "2", "1", "2", "2", ".", "," } },
+ { 0x0046, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x0047, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x0048, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x0049, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x004A, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x004B, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x004C, new [] { "12", "2", "1", "2", "2", ".", "," } },
+ { 0x004D, new [] { "12", "1", "1", "1", "1", ".", "," } },
+ { 0x004E, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x004F, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x0050, new [] { "5", "1", "1", "0", "0", ",", " " } },
+ { 0x0051, new [] { "2", "0", "1", "1", "1", ".", "," } },
+ { 0x0052, new [] { "1", "0", "1", "2", "2", ".", "," } },
+ { 0x0053, new [] { "5", "1", "2", "1", "1", ".", "," } },
+ { 0x0054, new [] { "4", "1", "0", "0", "0", ".", "," } },
+ { 0x0056, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x0057, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x005A, new [] { "3", "2", "1", "0", "0", ".", "," } },
+ { 0x005B, new [] { "14", "2", "1", "0", "0", ".", "," } },
+ { 0x005D, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x005E, new [] { "1", "0", "1", "1", "1", ".", "," } },
+ { 0x005F, new [] { "8", "3", "3", "0", "0", ".", "," } },
+ { 0x0061, new [] { "1", "0", "1", "1", "1", ".", "," } },
+ { 0x0062, new [] { "12", "2", "1", "0", "0", ",", "." } },
+ { 0x0063, new [] { "3", "0", "3", "4", "2", "٫", "٬" } },
+ { 0x0064, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x0065, new [] { "10", "3", "1", "0", "0", ".", "," } },
+ { 0x0068, new [] { "2", "2", "1", "0", "0", ".", "," } },
+ { 0x006A, new [] { "2", "2", "1", "0", "0", ".", "," } },
+ { 0x006B, new [] { "14", "2", "1", "2", "2", ",", "." } },
+ { 0x006C, new [] { "2", "2", "1", "2", "2", ".", "," } },
+ { 0x006D, new [] { "8", "3", "1", "1", "1", ",", " " } },
+ { 0x006E, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x006F, new [] { "12", "2", "1", "0", "0", ",", "." } },
+ { 0x0070, new [] { "2", "2", "1", "0", "0", ".", "," } },
+ { 0x0078, new [] { "2", "0", "1", "1", "1", ".", "," } },
+ { 0x007A, new [] { "9", "2", "1", "0", "0", ",", "." } },
+ { 0x007C, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x007E, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x0080, new [] { "2", "0", "1", "1", "1", ".", "," } },
+ { 0x0081, new [] { "1", "0", "1", "2", "2", ".", "," } },
+ { 0x0082, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x0083, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x0084, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x0085, new [] { "5", "1", "1", "1", "1", ",", " " } },
+ { 0x0086, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x0087, new [] { "2", "2", "1", "0", "0", ",", " " } },
+ { 0x0088, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x008C, new [] { "3", "0", "3", "4", "2", ".", "," } },
+ { 0x0091, new [] { "1", "0", "1", "0", "0", ".", "," } },
+ { 0x0401, new [] { "3", "2", "3", "0", "0", ".", "," } },
+ { 0x0402, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x0403, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x0404, new [] { "1", "0", "1", "1", "1", ".", "," } },
+ { 0x0405, new [] { "8", "3", "1", "1", "1", ",", " " } },
+ { 0x0406, new [] { "12", "2", "1", "0", "0", ",", "." } },
+ { 0x0407, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x0408, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x0409, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x040B, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x040C, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x040D, new [] { "2", "2", "1", "1", "1", ".", "," } },
+ { 0x040E, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x040F, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x0410, new [] { "9", "2", "1", "1", "1", ",", "." } },
+ { 0x0411, new [] { "1", "0", "1", "1", "1", ".", "," } },
+ { 0x0412, new [] { "1", "0", "1", "0", "0", ".", "," } },
+ { 0x0413, new [] { "12", "2", "1", "0", "0", ",", "." } },
+ { 0x0414, new [] { "12", "2", "1", "0", "0", ",", " " } },
+ { 0x0415, new [] { "8", "3", "1", "1", "1", ",", " " } },
+ { 0x0416, new [] { "9", "2", "1", "1", "1", ",", "." } },
+ { 0x0417, new [] { "2", "2", "1", "1", "1", ".", "'" } },
+ { 0x0418, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x0419, new [] { "5", "1", "1", "1", "1", ",", " " } },
+ { 0x041A, new [] { "8", "3", "2", "1", "1", ",", "." } },
+ { 0x041B, new [] { "8", "3", "1", "1", "1", ",", " " } },
+ { 0x041C, new [] { "5", "1", "1", "0", "0", ",", "." } },
+ { 0x041D, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x041E, new [] { "1", "0", "1", "0", "0", ".", "," } },
+ { 0x041F, new [] { "8", "3", "1", "2", "2", ",", "." } },
+ { 0x0420, new [] { "3", "0", "1", "0", "0", ".", "," } },
+ { 0x0421, new [] { "0", "0", "1", "0", "0", ",", "." } },
+ { 0x0422, new [] { "5", "1", "1", "1", "1", ",", " " } },
+ { 0x0423, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x0424, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x0425, new [] { "8", "3", "1", "1", "1", ".", " " } },
+ { 0x0426, new [] { "9", "2", "1", "1", "1", ",", " " } },
+ { 0x0427, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x0428, new [] { "8", "3", "1", "1", "1", ";", " " } },
+ { 0x0429, new [] { "3", "2", "3", "0", "0", "/", "," } },
+ { 0x042A, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x042B, new [] { "8", "3", "1", "0", "0", ".", "," } },
+ { 0x042C, new [] { "8", "3", "1", "1", "1", ",", " " } },
+ { 0x042D, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x042E, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x042F, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x0432, new [] { "2", "2", "1", "2", "2", ".", "," } },
+ { 0x0434, new [] { "2", "2", "1", "2", "2", ".", "," } },
+ { 0x0435, new [] { "2", "2", "1", "2", "2", ".", "," } },
+ { 0x0436, new [] { "2", "2", "1", "1", "1", ".", "," } },
+ { 0x0437, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x0438, new [] { "12", "2", "1", "1", "1", ",", "." } },
+ { 0x0439, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x043A, new [] { "1", "0", "1", "2", "2", ".", "," } },
+ { 0x043B, new [] { "12", "2", "1", "2", "2", ",", " " } },
+ { 0x043E, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x043F, new [] { "1", "0", "1", "1", "1", "-", " " } },
+ { 0x0440, new [] { "8", "3", "1", "1", "1", "-", " " } },
+ { 0x0441, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x0442, new [] { "5", "1", "1", "1", "1", ",", " " } },
+ { 0x0443, new [] { "8", "3", "1", "1", "1", ",", " " } },
+ { 0x0444, new [] { "8", "3", "1", "1", "1", ",", " " } },
+ { 0x0445, new [] { "12", "2", "1", "2", "2", ".", "," } },
+ { 0x0446, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x0447, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x0448, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x0449, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x044A, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x044B, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x044C, new [] { "12", "2", "1", "2", "2", ".", "," } },
+ { 0x044D, new [] { "12", "1", "1", "1", "1", ".", "," } },
+ { 0x044E, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x044F, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x0450, new [] { "5", "1", "1", "0", "0", ",", " " } },
+ { 0x0451, new [] { "2", "0", "1", "1", "1", ".", "," } },
+ { 0x0452, new [] { "1", "0", "1", "2", "2", ".", "," } },
+ { 0x0453, new [] { "5", "1", "2", "1", "1", ".", "," } },
+ { 0x0454, new [] { "4", "1", "0", "0", "0", ".", "," } },
+ { 0x0456, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x0457, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x045A, new [] { "3", "2", "1", "0", "0", ".", "," } },
+ { 0x045B, new [] { "14", "2", "1", "0", "0", ".", "," } },
+ { 0x045D, new [] { "0", "0", "1", "1", "1", ".", "," } },
+ { 0x045E, new [] { "1", "0", "1", "1", "1", ".", "," } },
+ { 0x0461, new [] { "1", "0", "1", "1", "1", ".", "," } },
+ { 0x0462, new [] { "12", "2", "1", "0", "0", ",", "." } },
+ { 0x0463, new [] { "3", "0", "3", "4", "2", "٫", "٬" } },
+ { 0x0464, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x0465, new [] { "10", "3", "1", "0", "0", ".", "," } },
+ { 0x0468, new [] { "2", "2", "1", "0", "0", ".", "," } },
+ { 0x046A, new [] { "2", "2", "1", "0", "0", ".", "," } },
+ { 0x046B, new [] { "14", "2", "1", "2", "2", ",", "." } },
+ { 0x046C, new [] { "2", "2", "1", "2", "2", ".", "," } },
+ { 0x046D, new [] { "8", "3", "1", "1", "1", ",", " " } },
+ { 0x046E, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x046F, new [] { "12", "2", "1", "0", "0", ",", "." } },
+ { 0x0470, new [] { "2", "2", "1", "0", "0", ".", "," } },
+ { 0x0478, new [] { "2", "0", "1", "1", "1", ".", "," } },
+ { 0x047A, new [] { "9", "2", "1", "0", "0", ",", "." } },
+ { 0x047C, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x047E, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x0480, new [] { "2", "0", "1", "1", "1", ".", "," } },
+ { 0x0481, new [] { "1", "0", "1", "2", "2", ".", "," } },
+ { 0x0482, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x0483, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x0484, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x0485, new [] { "5", "1", "1", "1", "1", ",", " " } },
+ { 0x0486, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x0487, new [] { "2", "2", "1", "0", "0", ",", " " } },
+ { 0x0488, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x048C, new [] { "3", "0", "3", "4", "2", ".", "," } },
+ { 0x0491, new [] { "1", "0", "1", "0", "0", ".", "," } },
+ { 0x0801, new [] { "3", "2", "3", "0", "0", ".", "," } },
+ { 0x0804, new [] { "2", "0", "1", "1", "1", ".", "," } },
+ { 0x0807, new [] { "2", "2", "1", "1", "1", ".", "'" } },
+ { 0x0809, new [] { "1", "0", "1", "0", "0", ".", "," } },
+ { 0x080A, new [] { "1", "0", "1", "0", "0", ".", "," } },
+ { 0x080C, new [] { "12", "2", "1", "0", "0", ",", "." } },
+ { 0x0810, new [] { "2", "2", "1", "1", "1", ".", "'" } },
+ { 0x0813, new [] { "12", "2", "1", "1", "1", ",", "." } },
+ { 0x0814, new [] { "12", "2", "1", "0", "0", ",", " " } },
+ { 0x0816, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x081A, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x081D, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x082C, new [] { "8", "3", "1", "1", "1", ",", " " } },
+ { 0x082E, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x083B, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x083C, new [] { "1", "0", "1", "0", "0", ".", "," } },
+ { 0x083E, new [] { "0", "0", "1", "0", "0", ",", "." } },
+ { 0x0843, new [] { "8", "3", "1", "1", "1", ",", " " } },
+ { 0x0845, new [] { "12", "2", "1", "2", "2", ".", "," } },
+ { 0x0850, new [] { "2", "0", "1", "1", "1", ".", "," } },
+ { 0x085D, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x085F, new [] { "8", "3", "3", "0", "0", ".", "," } },
+ { 0x086B, new [] { "14", "2", "1", "2", "2", ",", "." } },
+ { 0x0C01, new [] { "3", "2", "3", "0", "0", ".", "," } },
+ { 0x0C04, new [] { "0", "0", "1", "1", "1", ".", "," } },
+ { 0x0C07, new [] { "9", "2", "1", "1", "1", ",", "." } },
+ { 0x0C09, new [] { "1", "0", "1", "0", "0", ".", "," } },
+ { 0x0C0A, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x0C0C, new [] { "15", "3", "1", "0", "0", ",", " " } },
+ { 0x0C1A, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x0C3B, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x0C6B, new [] { "12", "2", "1", "2", "2", ".", "," } },
+ { 0x1001, new [] { "3", "0", "3", "0", "0", ".", "," } },
+ { 0x1004, new [] { "0", "0", "1", "1", "1", ".", "," } },
+ { 0x1007, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x1009, new [] { "1", "0", "1", "0", "0", ".", "," } },
+ { 0x100A, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x100C, new [] { "2", "2", "1", "0", "0", ".", "'" } },
+ { 0x101A, new [] { "8", "3", "2", "0", "0", ",", "." } },
+ { 0x103B, new [] { "12", "2", "1", "2", "2", ",", " " } },
+ { 0x1401, new [] { "3", "2", "3", "0", "0", ".", "," } },
+ { 0x1404, new [] { "0", "0", "1", "1", "1", ".", "," } },
+ { 0x1407, new [] { "2", "2", "1", "1", "1", ".", "'" } },
+ { 0x1409, new [] { "1", "0", "1", "0", "0", ".", "," } },
+ { 0x140A, new [] { "0", "0", "1", "0", "0", ",", "." } },
+ { 0x140C, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x141A, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x143B, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x1801, new [] { "3", "2", "3", "0", "0", ".", "," } },
+ { 0x1809, new [] { "1", "0", "1", "0", "0", ".", "," } },
+ { 0x180A, new [] { "14", "2", "1", "0", "0", ".", "," } },
+ { 0x180C, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x181A, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x183B, new [] { "12", "2", "1", "2", "2", ",", " " } },
+ { 0x1C01, new [] { "3", "2", "3", "0", "0", ".", "," } },
+ { 0x1C09, new [] { "2", "2", "1", "1", "1", ",", " " } },
+ { 0x1C0A, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x1C1A, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x1C3B, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x2001, new [] { "3", "2", "3", "0", "0", ".", "," } },
+ { 0x2009, new [] { "1", "0", "1", "0", "0", ".", "," } },
+ { 0x200A, new [] { "12", "2", "1", "0", "0", ",", "." } },
+ { 0x201A, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x203B, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x2401, new [] { "3", "2", "3", "0", "0", ".", "," } },
+ { 0x2409, new [] { "1", "0", "1", "0", "0", ".", "," } },
+ { 0x240A, new [] { "14", "2", "1", "0", "0", ",", "." } },
+ { 0x241A, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x243B, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x2801, new [] { "3", "2", "3", "0", "0", ".", "," } },
+ { 0x2809, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x280A, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x281A, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x2C01, new [] { "3", "2", "3", "0", "0", ".", "," } },
+ { 0x2C09, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x2C0A, new [] { "2", "2", "1", "0", "0", ",", "." } },
+ { 0x2C1A, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x3001, new [] { "3", "2", "3", "0", "0", ".", "," } },
+ { 0x3009, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x300A, new [] { "14", "2", "1", "0", "0", ",", "." } },
+ { 0x301A, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x3401, new [] { "3", "2", "3", "0", "0", ".", "," } },
+ { 0x3409, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x340A, new [] { "9", "2", "1", "0", "0", ",", "." } },
+ { 0x3801, new [] { "3", "2", "3", "0", "0", ".", "," } },
+ { 0x380A, new [] { "14", "2", "1", "0", "0", ",", "." } },
+ { 0x3C01, new [] { "3", "2", "3", "0", "0", ".", "," } },
+ { 0x3C0A, new [] { "14", "2", "1", "0", "0", ",", "." } },
+ { 0x4001, new [] { "3", "2", "3", "0", "0", ".", "," } },
+ { 0x4009, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x400A, new [] { "14", "2", "1", "0", "0", ",", "." } },
+ { 0x4409, new [] { "0", "0", "1", "1", "1", ".", "," } },
+ { 0x440A, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x4809, new [] { "0", "0", "1", "1", "1", ".", "," } },
+ { 0x480A, new [] { "12", "2", "1", "0", "0", ".", "," } },
+ { 0x4C0A, new [] { "14", "2", "1", "0", "0", ".", "," } },
+ { 0x500A, new [] { "14", "2", "1", "0", "0", ".", "," } },
+ { 0x540A, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x641A, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x681A, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x6C1A, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x701A, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x703B, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x742C, new [] { "8", "3", "1", "1", "1", ",", " " } },
+ { 0x743B, new [] { "8", "3", "1", "0", "0", ",", " " } },
+ { 0x7804, new [] { "2", "0", "1", "1", "1", ".", "," } },
+ { 0x7814, new [] { "12", "2", "1", "0", "0", ",", " " } },
+ { 0x781A, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x782C, new [] { "8", "3", "1", "1", "1", ",", " " } },
+ { 0x783B, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x7843, new [] { "8", "3", "1", "1", "1", ",", " " } },
+ { 0x7850, new [] { "5", "1", "1", "0", "0", ",", " " } },
+ { 0x785D, new [] { "0", "0", "1", "1", "1", ".", "," } },
+ { 0x7C04, new [] { "0", "0", "1", "1", "1", ".", "," } },
+ { 0x7C14, new [] { "12", "2", "1", "0", "0", ",", " " } },
+ { 0x7C1A, new [] { "8", "3", "1", "1", "1", ",", "." } },
+ { 0x7C28, new [] { "8", "3", "1", "1", "1", ";", " " } },
+ { 0x7C2E, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x7C3B, new [] { "8", "3", "1", "0", "0", ",", "." } },
+ { 0x7C43, new [] { "8", "3", "1", "1", "1", ",", " " } },
+ { 0x7C50, new [] { "2", "0", "1", "1", "1", ".", "," } },
+ { 0x7C5D, new [] { "0", "0", "1", "0", "0", ".", "," } },
+ { 0x7C5F, new [] { "8", "3", "3", "0", "0", ".", "," } },
+ { 0x7C68, new [] { "2", "2", "1", "0", "0", ".", "," } },
};
static readonly Dictionary<int, string> Geo = new Dictionary<int, string> {
nf.NumberNegativePattern = entry_nf[2];
nf.PercentNegativePattern = entry_nf[3];
nf.PercentPositivePattern = entry_nf[4];
+ nf.CurrencyDecimalSeparator = entry_nf[5];
+ nf.CurrencyGroupSeparator = entry_nf[6];
string[][] gsizes;
if (!GroupSizes.TryGetValue (lcid, out gsizes)) {
#define SGEN_PROTOCOL_EOF 255
+#define TYPE(t) ((t) & 0x7f)
+#define WORKER(t) ((t) & 0x80)
+
static int
read_entry (FILE *in, void **data)
{
if (fread (&type, 1, 1, in) != 1)
return SGEN_PROTOCOL_EOF;
- switch (type) {
+ switch (TYPE (type)) {
case SGEN_PROTOCOL_COLLECTION_FORCE: size = sizeof (SGenProtocolCollectionForce); break;
case SGEN_PROTOCOL_COLLECTION_BEGIN: size = sizeof (SGenProtocolCollection); break;
case SGEN_PROTOCOL_COLLECTION_END: size = sizeof (SGenProtocolCollection); break;
return (int)type;
}
+#define WORKER_PREFIX(t) (WORKER ((t)) ? "w" : " ")
+
static void
print_entry (int type, void *data)
{
- switch (type) {
+ switch (TYPE (type)) {
case SGEN_PROTOCOL_COLLECTION_FORCE: {
SGenProtocolCollectionForce *entry = data;
- printf ("collection force generation %d\n", entry->generation);
+ printf ("%s collection force generation %d\n", WORKER_PREFIX (type), entry->generation);
break;
}
case SGEN_PROTOCOL_COLLECTION_BEGIN: {
SGenProtocolCollection *entry = data;
- printf ("collection begin %d generation %d\n", entry->index, entry->generation);
+ printf ("%s collection begin %d generation %d\n", WORKER_PREFIX (type), entry->index, entry->generation);
break;
}
case SGEN_PROTOCOL_COLLECTION_END: {
SGenProtocolCollection *entry = data;
- printf ("collection end %d generation %d\n", entry->index, entry->generation);
+ printf ("%s collection end %d generation %d\n", WORKER_PREFIX (type), entry->index, entry->generation);
break;
}
case SGEN_PROTOCOL_ALLOC: {
SGenProtocolAlloc *entry = data;
- printf ("alloc obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
+ printf ("%s alloc obj %p vtable %p size %d\n", WORKER_PREFIX (type), entry->obj, entry->vtable, entry->size);
break;
}
case SGEN_PROTOCOL_ALLOC_PINNED: {
SGenProtocolAlloc *entry = data;
- printf ("alloc pinned obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
+ printf ("%s alloc pinned obj %p vtable %p size %d\n", WORKER_PREFIX (type), entry->obj, entry->vtable, entry->size);
break;
}
case SGEN_PROTOCOL_ALLOC_DEGRADED: {
SGenProtocolAlloc *entry = data;
- printf ("alloc degraded obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
+ printf ("%s alloc degraded obj %p vtable %p size %d\n", WORKER_PREFIX (type), entry->obj, entry->vtable, entry->size);
break;
}
case SGEN_PROTOCOL_COPY: {
SGenProtocolCopy *entry = data;
- printf ("copy from %p to %p vtable %p size %d\n", entry->from, entry->to, entry->vtable, entry->size);
+ printf ("%s copy from %p to %p vtable %p size %d\n", WORKER_PREFIX (type), entry->from, entry->to, entry->vtable, entry->size);
break;
}
case SGEN_PROTOCOL_PIN: {
SGenProtocolPin *entry = data;
- printf ("pin obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
+ printf ("%s pin obj %p vtable %p size %d\n", WORKER_PREFIX (type), entry->obj, entry->vtable, entry->size);
break;
}
case SGEN_PROTOCOL_MARK: {
SGenProtocolMark *entry = data;
- printf ("mark obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
+ printf ("%s mark obj %p vtable %p size %d\n", WORKER_PREFIX (type), entry->obj, entry->vtable, entry->size);
break;
}
case SGEN_PROTOCOL_SCAN_BEGIN: {
SGenProtocolScanBegin *entry = data;
- printf ("scan_begin obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
+ printf ("%s scan_begin obj %p vtable %p size %d\n", WORKER_PREFIX (type), entry->obj, entry->vtable, entry->size);
break;
}
case SGEN_PROTOCOL_SCAN_VTYPE_BEGIN: {
SGenProtocolScanVTypeBegin *entry = data;
- printf ("scan_vtype_begin obj %p size %d\n", entry->obj, entry->size);
+ printf ("%s scan_vtype_begin obj %p size %d\n", WORKER_PREFIX (type), entry->obj, entry->size);
break;
}
case SGEN_PROTOCOL_WBARRIER: {
SGenProtocolWBarrier *entry = data;
- printf ("wbarrier ptr %p value %p value_vtable %p\n", entry->ptr, entry->value, entry->value_vtable);
+ printf ("%s wbarrier ptr %p value %p value_vtable %p\n", WORKER_PREFIX (type), entry->ptr, entry->value, entry->value_vtable);
break;
}
case SGEN_PROTOCOL_GLOBAL_REMSET: {
SGenProtocolGlobalRemset *entry = data;
- printf ("global_remset ptr %p value %p value_vtable %p\n", entry->ptr, entry->value, entry->value_vtable);
+ printf ("%s global_remset ptr %p value %p value_vtable %p\n", WORKER_PREFIX (type), entry->ptr, entry->value, entry->value_vtable);
break;
}
case SGEN_PROTOCOL_PTR_UPDATE: {
SGenProtocolPtrUpdate *entry = data;
- printf ("ptr_update ptr %p old_value %p new_value %p vtable %p size %d\n",
+ printf ("%s ptr_update ptr %p old_value %p new_value %p vtable %p size %d\n", WORKER_PREFIX (type),
entry->ptr, entry->old_value, entry->new_value, entry->vtable, entry->size);
break;
}
case SGEN_PROTOCOL_CLEANUP: {
SGenProtocolCleanup *entry = data;
- printf ("cleanup ptr %p vtable %p size %d\n", entry->ptr, entry->vtable, entry->size);
+ printf ("%s cleanup ptr %p vtable %p size %d\n", WORKER_PREFIX (type), entry->ptr, entry->vtable, entry->size);
break;
}
case SGEN_PROTOCOL_EMPTY: {
SGenProtocolEmpty *entry = data;
- printf ("empty start %p size %d\n", entry->start, entry->size);
+ printf ("%s empty start %p size %d\n", WORKER_PREFIX (type), entry->start, entry->size);
break;
}
case SGEN_PROTOCOL_THREAD_SUSPEND: {
SGenProtocolThreadSuspend *entry = data;
- printf ("thread_suspend thread %p ip %p\n", entry->thread, entry->stopped_ip);
+ printf ("%s thread_suspend thread %p ip %p\n", WORKER_PREFIX (type), entry->thread, entry->stopped_ip);
break;
}
case SGEN_PROTOCOL_THREAD_RESTART: {
SGenProtocolThreadRestart *entry = data;
- printf ("thread_restart thread %p\n", entry->thread);
+ printf ("%s thread_restart thread %p\n", WORKER_PREFIX (type), entry->thread);
break;
}
case SGEN_PROTOCOL_THREAD_REGISTER: {
SGenProtocolThreadRegister *entry = data;
- printf ("thread_register thread %p\n", entry->thread);
+ printf ("%s thread_register thread %p\n", WORKER_PREFIX (type), entry->thread);
break;
}
case SGEN_PROTOCOL_THREAD_UNREGISTER: {
SGenProtocolThreadUnregister *entry = data;
- printf ("thread_unregister thread %p\n", entry->thread);
+ printf ("%s thread_unregister thread %p\n", WORKER_PREFIX (type), entry->thread);
break;
}
case SGEN_PROTOCOL_MISSING_REMSET: {
SGenProtocolMissingRemset *entry = data;
- printf ("missing_remset obj %p obj_vtable %p offset %d value %p value_vtable %p value_pinned %d\n",
+ printf ("%s missing_remset obj %p obj_vtable %p offset %d value %p value_vtable %p value_pinned %d\n", WORKER_PREFIX (type),
entry->obj, entry->obj_vtable, entry->offset, entry->value, entry->value_vtable, entry->value_pinned);
break;
}
case SGEN_PROTOCOL_CARD_SCAN: {
SGenProtocolCardScan *entry = data;
- printf ("card_scan start %p size %d\n", entry->start, entry->size);
+ printf ("%s card_scan start %p size %d\n", WORKER_PREFIX (type), entry->start, entry->size);
break;
}
case SGEN_PROTOCOL_CEMENT: {
SGenProtocolCement *entry = data;
- printf ("cement obj %p vtable %p size %d\n", entry->obj, entry->vtable, entry->size);
+ printf ("%s cement obj %p vtable %p size %d\n", WORKER_PREFIX (type), entry->obj, entry->vtable, entry->size);
break;
}
case SGEN_PROTOCOL_CEMENT_RESET: {
- printf ("cement_reset\n");
+ printf ("%s cement_reset\n", WORKER_PREFIX (type));
break;
}
case SGEN_PROTOCOL_DISLINK_UPDATE: {
SGenProtocolDislinkUpdate *entry = data;
- printf ("dislink_update link %p obj %p staged %d", entry->link, entry->obj, entry->staged);
+ printf ("%s dislink_update link %p obj %p staged %d", WORKER_PREFIX (type), entry->link, entry->obj, entry->staged);
if (entry->obj)
printf (" track %d\n", entry->track);
else
}
case SGEN_PROTOCOL_DISLINK_UPDATE_STAGED: {
SGenProtocolDislinkUpdateStaged *entry = data;
- printf ("dislink_update_staged link %p obj %p index %d", entry->link, entry->obj, entry->index);
+ printf ("%s dislink_update_staged link %p obj %p index %d", WORKER_PREFIX (type), entry->link, entry->obj, entry->index);
if (entry->obj)
printf (" track %d\n", entry->track);
else
}
case SGEN_PROTOCOL_DISLINK_PROCESS_STAGED: {
SGenProtocolDislinkProcessStaged *entry = data;
- printf ("dislink_process_staged link %p obj %p index %d\n", entry->link, entry->obj, entry->index);
+ printf ("%s dislink_process_staged link %p obj %p index %d\n", WORKER_PREFIX (type), entry->link, entry->obj, entry->index);
break;
}
case SGEN_PROTOCOL_DOMAIN_UNLOAD_BEGIN: {
SGenProtocolDomainUnload *entry = data;
- printf ("dislink_unload_begin domain %p\n", entry->domain);
+ printf ("%s dislink_unload_begin domain %p\n", WORKER_PREFIX (type), entry->domain);
break;
}
case SGEN_PROTOCOL_DOMAIN_UNLOAD_END: {
SGenProtocolDomainUnload *entry = data;
- printf ("dislink_unload_end domain %p\n", entry->domain);
+ printf ("%s dislink_unload_end domain %p\n", WORKER_PREFIX (type), entry->domain);
break;
}
default:
static gboolean
is_match (gpointer ptr, int type, void *data)
{
- switch (type) {
+ switch (TYPE (type)) {
case SGEN_PROTOCOL_COLLECTION_FORCE:
case SGEN_PROTOCOL_COLLECTION_BEGIN:
case SGEN_PROTOCOL_COLLECTION_END:
static gboolean
is_vtable_match (gpointer ptr, int type, void *data)
{
- switch (type) {
+ switch (TYPE (type)) {
case SGEN_PROTOCOL_ALLOC:
case SGEN_PROTOCOL_ALLOC_PINNED:
case SGEN_PROTOCOL_ALLOC_DEGRADED: {
/* Define to 1 if you have the <curses.h> header file. */
/* #undef HAVE_CURSES_H */
+/* Define to 1 if you have the declaration of `InterlockedAdd',
+ and to 0 if you don't. */
+#define HAVE_DECL_INTERLOCKEDADD 1
+
+/* Define to 1 if you have the declaration of `InterlockedAdd64',
+ and to 0 if you don't. */
+#define HAVE_DECL_INTERLOCKEDADD64 1
+
/* Define to 1 if you have the declaration of `InterlockedCompareExchange64',
and to 0 if you don't. */
#define HAVE_DECL_INTERLOCKEDCOMPAREEXCHANGE64 1
+/* Define to 1 if you have the declaration of `InterlockedDecrement64',
+ and to 0 if you don't. */
+#define HAVE_DECL_INTERLOCKEDDECREMENT64 1
+
+/* Define to 1 if you have the declaration of `InterlockedExchange64',
+ and to 0 if you don't. */
+#define HAVE_DECL_INTERLOCKEDEXCHANGE64 1
+
+/* Define to 1 if you have the declaration of `InterlockedIncrement64',
+ and to 0 if you don't. */
+#define HAVE_DECL_INTERLOCKEDINCREMENT64 1
+
+/* Define to 1 if you have the declaration of `__readfsdword',
+ and to 0 if you don't. */
+#define HAVE_DECL___READFSDWORD 1
+
/* Define to 1 if you have the <dirent.h> header file. */
/* #define HAVE_DIRENT_H 1 */
/* Enable the allocation and indexing of arrays greater than Int32.MaxValue */
/* #undef MONO_BIG_ARRAYS */
-/* The Mono Debugger is supported on this platform */
-/* #undef MONO_DEBUGGER_SUPPORTED */
-
/* Sizeof sock_un.sun_path */
/* #undef MONO_SIZEOF_SUNPATH */