From 17c0f0296279d6e16b4044b6603479c816171e6e Mon Sep 17 00:00:00 2001 From: Martin Fouilleul Date: Wed, 12 Apr 2023 16:21:03 +0200 Subject: [PATCH] orca runtime initial commit --- .gitignore | 20 + .gitmodules | 3 + build.sh | 64 + ext/wasm3/.codespellrc | 5 + ext/wasm3/.github/workflows/publish.yml | 180 + ext/wasm3/.github/workflows/tests.yml | 619 +++ ext/wasm3/.gitignore | 13 + ext/wasm3/CMakeLists.txt | 225 + ext/wasm3/LICENSE | 21 + ext/wasm3/README.md | 118 + ext/wasm3/docs/Cookbook.md | 462 +++ ext/wasm3/docs/Demos.md | 17 + ext/wasm3/docs/Development.md | 181 + ext/wasm3/docs/Diagnostics.md | 57 + ext/wasm3/docs/Hardware.md | 60 + ext/wasm3/docs/Installation.md | 26 + ext/wasm3/docs/Interpreter.md | 166 + ext/wasm3/docs/Performance.md | 91 + ext/wasm3/docs/Testing.md | 61 + ext/wasm3/docs/Troubleshooting.md | 26 + ext/wasm3/extra/blynk.png | Bin 0 -> 8696 bytes ext/wasm3/extra/button.png | Bin 0 -> 3999 bytes ext/wasm3/extra/disasm-func.sh | 17 + ext/wasm3/extra/iden3.svg | 202 + ext/wasm3/extra/logo.png | Bin 0 -> 16659 bytes ext/wasm3/extra/scailable.png | Bin 0 -> 8750 bytes ext/wasm3/extra/screenshot-android.png | Bin 0 -> 52445 bytes ext/wasm3/extra/screenshot-ios.png | Bin 0 -> 87612 bytes ext/wasm3/extra/shareup_app.svg | 1 + ext/wasm3/extra/testutils.py | 57 + ext/wasm3/extra/utils.mk | 39 + ext/wasm3/extra/wapm-package/README.md | 105 + ext/wasm3/extra/wapm-package/build/.gitignore | 4 + ext/wasm3/extra/wapm-package/wapm.toml | 25 + ext/wasm3/extra/wasm-symbol.svg | 71 + ext/wasm3/extra/wowcube.png | Bin 0 -> 28449 bytes ext/wasm3/platforms/android/.gitignore | 9 + ext/wasm3/platforms/android/README.md | 26 + ext/wasm3/platforms/android/app/build.gradle | 33 + .../platforms/android/app/proguard-rules.pro | 17 + .../android/app/src/main/AndroidManifest.xml | 20 + .../android/app/src/main/cpp/CMakeLists.txt | 16 + .../platforms/android/app/src/main/cpp/jni.c | 96 + .../platforms/android/app/src/main/cpp/m3 | 1 + .../platforms/android/app/src/main/cpp/main.c | 70 + .../java/com/example/wasm3/MainActivity.java | 52 + .../app/src/main/res/drawable/ic_launcher.png | Bin 0 -> 6259 bytes .../app/src/main/res/layout/activity_main.xml | 34 + .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 1478 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1011 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 1924 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 2806 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 3769 bytes .../app/src/main/res/values-w820dp/dimens.xml | 6 + .../app/src/main/res/values/colors.xml | 6 + .../app/src/main/res/values/dimens.xml | 5 + .../app/src/main/res/values/strings.xml | 3 + .../app/src/main/res/values/styles.xml | 11 + ext/wasm3/platforms/android/build.gradle | 25 + ext/wasm3/platforms/android/gradle.properties | 21 + .../android/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 58694 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + ext/wasm3/platforms/android/gradlew | 183 + ext/wasm3/platforms/android/gradlew.bat | 103 + ext/wasm3/platforms/android/override.txt | 43 + ext/wasm3/platforms/android/settings.gradle | 1 + ext/wasm3/platforms/app/README.md | 1 + ext/wasm3/platforms/app/main.c | 723 ++++ ext/wasm3/platforms/app_fuzz/fuzzer.c | 49 + ext/wasm3/platforms/cosmopolitan/.gitignore | 4 + ext/wasm3/platforms/cosmopolitan/build.sh | 41 + ext/wasm3/platforms/cpp/.gitignore | 2 + ext/wasm3/platforms/cpp/CMakeLists.txt | 25 + ext/wasm3/platforms/cpp/README.md | 98 + ext/wasm3/platforms/cpp/main.cpp | 89 + ext/wasm3/platforms/cpp/wasm/Makefile | 18 + ext/wasm3/platforms/cpp/wasm/test_prog.c | 41 + ext/wasm3/platforms/cpp/wasm/test_prog.wasm.h | 68 + .../platforms/cpp/wasm3_cpp/CMakeLists.txt | 4 + .../cpp/wasm3_cpp/include/wasm3_cpp.h | 412 ++ .../platforms/embedded/arduino/.gitignore | 1 + .../platforms/embedded/arduino/lib/wasm3 | 1 + .../platforms/embedded/arduino/platformio.ini | 137 + .../platforms/embedded/arduino/src/main.cpp | 82 + .../platforms/embedded/bluepill/.gitignore | 1 + .../embedded/bluepill/lib/wasm3/library.json | 7 + .../platforms/embedded/bluepill/lib/wasm3/src | 1 + .../embedded/bluepill/platformio.ini | 10 + .../platforms/embedded/bluepill/src/main.cpp | 75 + .../embedded/esp32-idf-wasi/.gitignore | 3 + .../embedded/esp32-idf-wasi/.old/Makefile | 9 + .../embedded/esp32-idf-wasi/.old/component.mk | 5 + .../embedded/esp32-idf-wasi/CMakeLists.txt | 6 + .../embedded/esp32-idf-wasi/README.md | 24 + .../esp32-idf-wasi/main/CMakeLists.txt | 11 + .../esp32-idf-wasi/main/m3_api_esp_wasi.c | 616 +++ .../esp32-idf-wasi/main/m3_api_esp_wasi.h | 28 + .../embedded/esp32-idf-wasi/main/main.cpp | 76 + .../esp32-idf-wasi/main/wasi_test.wasm.h | 2307 +++++++++++ .../embedded/esp32-idf-wasi/main/wasm3 | 1 + .../esp32-idf-wasi/sdkconfig.defaults | 14 + .../platforms/embedded/esp32-idf/.gitignore | 3 + .../embedded/esp32-idf/.old/Makefile | 9 + .../embedded/esp32-idf/.old/component.mk | 5 + .../embedded/esp32-idf/CMakeLists.txt | 6 + .../platforms/embedded/esp32-idf/README.md | 24 + .../embedded/esp32-idf/main/CMakeLists.txt | 26 + .../embedded/esp32-idf/main/linker.lf | 6 + .../embedded/esp32-idf/main/main.cpp | 70 + .../embedded/esp32-idf/sdkconfig.defaults | 8 + .../platforms/embedded/esp32-pio/.gitignore | 1 + .../embedded/esp32-pio/lib/wasm3/README.md | 3 + .../embedded/esp32-pio/lib/wasm3/library.json | 5 + .../embedded/esp32-pio/lib/wasm3/src | 1 + .../embedded/esp32-pio/platformio.ini | 18 + .../platforms/embedded/esp32-pio/src/main.cpp | 70 + .../embedded/esp32-pio/src/sdkconfig | 962 +++++ .../embedded/esp32-pio/src/sdkconfig.h | 371 ++ .../platforms/embedded/esp8266/.gitignore | 1 + .../platforms/embedded/esp8266/lib/wasm3 | 1 + .../platforms/embedded/esp8266/platformio.ini | 29 + .../platforms/embedded/esp8266/src/main.cpp | 71 + ext/wasm3/platforms/embedded/fomu/.env | 17 + ext/wasm3/platforms/embedded/fomu/.gitignore | 5 + ext/wasm3/platforms/embedded/fomu/Makefile | 121 + ext/wasm3/platforms/embedded/fomu/README.md | 36 + ext/wasm3/platforms/embedded/fomu/gdb_init | 11 + .../platforms/embedded/fomu/include/console.h | 24 + .../platforms/embedded/fomu/include/crc.h | 15 + .../embedded/fomu/include/csr-defs.h | 11 + .../embedded/fomu/include/generated/csr.h | 773 ++++ .../embedded/fomu/include/generated/mem.h | 16 + .../embedded/fomu/include/hw/common.h | 52 + .../embedded/fomu/include/hw/flags.h | 40 + .../platforms/embedded/fomu/include/irq.h | 144 + .../platforms/embedded/fomu/include/printf.h | 124 + .../platforms/embedded/fomu/include/rgb.h | 29 + .../platforms/embedded/fomu/include/spi.h | 93 + .../embedded/fomu/include/spiflash.h | 8 + .../platforms/embedded/fomu/include/system.h | 67 + .../platforms/embedded/fomu/include/time.h | 16 + .../embedded/fomu/include/toboot-api.h | 109 + .../embedded/fomu/include/toboot-internal.h | 49 + .../embedded/fomu/include/usb-desc.h | 91 + .../platforms/embedded/fomu/include/usb.h | 40 + .../platforms/embedded/fomu/include/usbcdc.h | 162 + .../platforms/embedded/fomu/include/usbstd.h | 277 ++ .../embedded/fomu/include/webusb-defs.h | 55 + .../platforms/embedded/fomu/include/xxhash.c | 912 +++++ .../platforms/embedded/fomu/include/xxhash.h | 294 ++ .../platforms/embedded/fomu/ld/linker.ld | 56 + .../embedded/fomu/ld/output_format.ld | 1 + .../platforms/embedded/fomu/ld/regions.ld | 4 + .../embedded/fomu/src/crt0-vexriscv.S | 83 + ext/wasm3/platforms/embedded/fomu/src/ltoa.c | 58 + ext/wasm3/platforms/embedded/fomu/src/main.c | 148 + ext/wasm3/platforms/embedded/fomu/src/rgb.c | 73 + ext/wasm3/platforms/embedded/fomu/src/time.c | 43 + .../platforms/embedded/fomu/src/usb-desc.c | 284 ++ .../platforms/embedded/fomu/src/usb-dev.c | 285 ++ .../platforms/embedded/fomu/src/usb-epfifo.c | 369 ++ ext/wasm3/platforms/embedded/fomu/src/wasm3 | 1 + .../platforms/embedded/hifive1/.gitignore | 1 + .../platforms/embedded/hifive1/README.md | 19 + .../platforms/embedded/hifive1/lib/wasm3 | 1 + .../platforms/embedded/hifive1/platformio.ini | 36 + .../platforms/embedded/hifive1/src/main.c | 62 + .../platforms/embedded/particle/.gitignore | 1 + .../platforms/embedded/particle/README.md | 18 + .../particle/lib/wasm3/library.properties | 6 + .../platforms/embedded/particle/lib/wasm3/src | 1 + .../embedded/particle/project.properties | 1 + .../platforms/embedded/particle/src/main.ino | 81 + .../platforms/embedded/wm_w600/.gitignore | 1 + ext/wasm3/platforms/embedded/wm_w600/Makefile | 120 + .../platforms/embedded/wm_w600/README.md | 28 + ext/wasm3/platforms/embedded/wm_w600/build.sh | 10 + ext/wasm3/platforms/embedded/wm_w600/main.c | 91 + ext/wasm3/platforms/embedded/wm_w600/wasm3 | 1 + ext/wasm3/platforms/emscripten/README.md | 35 + ext/wasm3/platforms/emscripten/main.c | 65 + ext/wasm3/platforms/emscripten_lib/main.c | 57 + .../platforms/emscripten_lib/run_native.js | 28 + .../platforms/emscripten_lib/run_wasm3.js | 129 + ext/wasm3/platforms/ios/.gitignore | 2 + ext/wasm3/platforms/ios/README.md | 17 + .../ios/wasm3.xcodeproj/project.pbxproj | 459 +++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 5 + .../xcschemes/wasm3 Release.xcscheme | 78 + .../xcshareddata/xcschemes/wasm3.xcscheme | 78 + .../platforms/ios/wasm3/AppDelegate.swift | 46 + .../AppIcon.appiconset/Contents.json | 98 + .../wasm3/Base.lproj/LaunchScreen.storyboard | 37 + .../ios/wasm3/Base.lproj/Main.storyboard | 55 + .../platforms/ios/wasm3/Bridging-Header.h | 8 + ext/wasm3/platforms/ios/wasm3/Info.plist | 49 + .../platforms/ios/wasm3/ViewController.swift | 41 + ext/wasm3/platforms/ios/wasm3/icon.png | Bin 0 -> 3769 bytes ext/wasm3/platforms/ios/wasm3/main.c | 117 + ext/wasm3/platforms/openwrt/README.md | 6 + ext/wasm3/platforms/openwrt/build/Makefile | 15 + ext/wasm3/platforms/python/README.md | 5 + ext/wasm3/source/CMakeLists.txt | 55 + ext/wasm3/source/extensions/m3_extensions.c | 112 + ext/wasm3/source/extensions/wasm3_ext.h | 51 + .../source/extra/coremark_minimal.wasm.h | 651 +++ ext/wasm3/source/extra/fib32.wasm.h | 9 + ext/wasm3/source/extra/fib32_tail.wasm.h | 10 + ext/wasm3/source/extra/fib64.wasm.h | 9 + ext/wasm3/source/extra/wasi_core.h | 2764 +++++++++++++ ext/wasm3/source/m3_api_libc.c | 245 ++ ext/wasm3/source/m3_api_libc.h | 20 + ext/wasm3/source/m3_api_meta_wasi.c | 995 +++++ ext/wasm3/source/m3_api_tracer.c | 168 + ext/wasm3/source/m3_api_tracer.h | 19 + ext/wasm3/source/m3_api_uvwasi.c | 1144 ++++++ ext/wasm3/source/m3_api_wasi.c | 873 ++++ ext/wasm3/source/m3_api_wasi.h | 38 + ext/wasm3/source/m3_bind.c | 175 + ext/wasm3/source/m3_bind.h | 20 + ext/wasm3/source/m3_code.c | 231 ++ ext/wasm3/source/m3_code.h | 80 + ext/wasm3/source/m3_compile.c | 2922 +++++++++++++ ext/wasm3/source/m3_compile.h | 206 + ext/wasm3/source/m3_config.h | 154 + ext/wasm3/source/m3_config_platforms.h | 202 + ext/wasm3/source/m3_core.c | 615 +++ ext/wasm3/source/m3_core.h | 311 ++ ext/wasm3/source/m3_env.c | 1225 ++++++ ext/wasm3/source/m3_env.h | 219 + ext/wasm3/source/m3_exception.h | 33 + ext/wasm3/source/m3_exec.c | 8 + ext/wasm3/source/m3_exec.h | 1488 +++++++ ext/wasm3/source/m3_exec_defs.h | 63 + ext/wasm3/source/m3_function.c | 233 ++ ext/wasm3/source/m3_function.h | 102 + ext/wasm3/source/m3_info.c | 561 +++ ext/wasm3/source/m3_info.h | 38 + ext/wasm3/source/m3_math_utils.h | 268 ++ ext/wasm3/source/m3_module.c | 171 + ext/wasm3/source/m3_parse.c | 649 +++ ext/wasm3/source/wasm3.h | 373 ++ ext/wasm3/source/wasm3_defs.h | 282 ++ ext/wasm3/test/internal/m3_test.c | 262 ++ ext/wasm3/test/internal/tailcall/build.sh | 91 + ext/wasm3/test/internal/tailcall/ops.c | 111 + ext/wasm3/test/lang/README.md | 31 + ext/wasm3/test/lang/fib.c | 30 + ext/wasm3/test/lang/fib.js | 8 + ext/wasm3/test/lang/fib.lua | 8 + ext/wasm3/test/lang/fib.min.js | 3 + ext/wasm3/test/lang/fib.py | 7 + ext/wasm3/test/lang/fib.walt | 6 + ext/wasm3/test/lang/fib32.wat | 30 + ext/wasm3/test/lang/fib32_tail.wat | 17 + ext/wasm3/test/lang/fib64.wat | 30 + ext/wasm3/test/run-spec-test.py | 597 +++ ext/wasm3/test/run-wasi-test.py | 216 + ext/wasm3/test/wasi/brotli/README.md | 47 + ext/wasm3/test/wasi/brotli/alice29.txt | 3609 +++++++++++++++++ .../test/wasi/brotli/alice29.txt.compressed | Bin 0 -> 46487 bytes ext/wasm3/test/wasi/brotli/alice29_small.txt | 245 ++ ext/wasm3/test/wasi/c-ray/README.md | 54 + ext/wasm3/test/wasi/c-ray/c-ray-f.c | 583 +++ ext/wasm3/test/wasi/c-ray/scene | 18 + ext/wasm3/test/wasi/c-ray/scene.jpg | Bin 0 -> 111827 bytes ext/wasm3/test/wasi/c-ray/sphfract | 192 + ext/wasm3/test/wasi/c-ray/sphfract.jpg | Bin 0 -> 192770 bytes ext/wasm3/test/wasi/coremark/README.md | 3 + ext/wasm3/test/wasi/mal/.gitattributes | 1 + ext/wasm3/test/wasi/mal/README.md | 21 + ext/wasm3/test/wasi/mal/core.mal | 72 + ext/wasm3/test/wasi/mal/env.mal | 34 + ext/wasm3/test/wasi/mal/mal.mal | 152 + ext/wasm3/test/wasi/mal/test-fib.mal | 8 + ext/wasm3/test/wasi/mandelbrot/README.md | 49 + ext/wasm3/test/wasi/mandelbrot/colors.h | 836 ++++ ext/wasm3/test/wasi/mandelbrot/doubledouble.h | 147 + ext/wasm3/test/wasi/mandelbrot/image.png | Bin 0 -> 485076 bytes ext/wasm3/test/wasi/mandelbrot/mandel.c | 120 + ext/wasm3/test/wasi/mandelbrot/mandel_dd.c | 146 + ext/wasm3/test/wasi/raymarcher/raymarcher.cpp | 164 + ext/wasm3/test/wasi/simple/0.txt | 1 + ext/wasm3/test/wasi/simple/README.md | 23 + ext/wasm3/test/wasi/simple/test.c | 152 + ext/wasm3/test/wasi/simple/wasm_api.h | 10 + ext/wasm3/test/wasi/simple/wasm_api.syms | 1 + ext/wasm3/test/wasi/smallpt/README.md | 48 + ext/wasm3/test/wasi/smallpt/image.jpg | Bin 0 -> 253688 bytes ext/wasm3/test/wasi/smallpt/smallpt-ex.cpp | 130 + ext/wasm3/test/wasi/smallpt/smallpt.cpp | 108 + ext/wasm3/test/wasi/stream/stream.c | 585 +++ ext/wasm3/test/wasi/wasmboy/.gitignore | 1 + ext/wasm3/test/wasi/wasmboy/README.md | 32 + ext/wasm3/test/wasi/wasmboy/image.png | Bin 0 -> 51171 bytes ext/wasm3/test/wasi/wasmsynth/README.md | 24 + ext/wasm3/test/wasi/wasmsynth/image.png | Bin 0 -> 158769 bytes milepost | 1 + samples/pong/build.sh | 13 + samples/pong/icon.png | Bin 0 -> 25276 bytes samples/pong/main.c | 272 ++ scripts/bindgen.py | 127 + scripts/mkapp.py | 149 + sdk/GLES3/gl3.h | 1192 ++++++ sdk/GLES3/gl31.h | 1507 +++++++ sdk/GLES3/gl32.h | 1808 +++++++++ sdk/GLES3/gl3platform.h | 27 + sdk/KHR/khrplatform.h | 292 ++ sdk/keys.h | 140 + sdk/macro_helpers.h | 129 + sdk/typedefs.h | 69 + src/bindgen_core_api.txt | 6 + src/bindgen_gles_api.txt | 44 + src/main.c | 454 +++ src/manual_gles_api.c | 29 + 318 files changed, 50440 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100755 build.sh create mode 100644 ext/wasm3/.codespellrc create mode 100644 ext/wasm3/.github/workflows/publish.yml create mode 100644 ext/wasm3/.github/workflows/tests.yml create mode 100644 ext/wasm3/.gitignore create mode 100755 ext/wasm3/CMakeLists.txt create mode 100644 ext/wasm3/LICENSE create mode 100644 ext/wasm3/README.md create mode 100644 ext/wasm3/docs/Cookbook.md create mode 100644 ext/wasm3/docs/Demos.md create mode 100644 ext/wasm3/docs/Development.md create mode 100644 ext/wasm3/docs/Diagnostics.md create mode 100644 ext/wasm3/docs/Hardware.md create mode 100644 ext/wasm3/docs/Installation.md create mode 100644 ext/wasm3/docs/Interpreter.md create mode 100644 ext/wasm3/docs/Performance.md create mode 100644 ext/wasm3/docs/Testing.md create mode 100644 ext/wasm3/docs/Troubleshooting.md create mode 100644 ext/wasm3/extra/blynk.png create mode 100644 ext/wasm3/extra/button.png create mode 100755 ext/wasm3/extra/disasm-func.sh create mode 100644 ext/wasm3/extra/iden3.svg create mode 100644 ext/wasm3/extra/logo.png create mode 100644 ext/wasm3/extra/scailable.png create mode 100644 ext/wasm3/extra/screenshot-android.png create mode 100644 ext/wasm3/extra/screenshot-ios.png create mode 100644 ext/wasm3/extra/shareup_app.svg create mode 100755 ext/wasm3/extra/testutils.py create mode 100644 ext/wasm3/extra/utils.mk create mode 100644 ext/wasm3/extra/wapm-package/README.md create mode 100644 ext/wasm3/extra/wapm-package/build/.gitignore create mode 100644 ext/wasm3/extra/wapm-package/wapm.toml create mode 100644 ext/wasm3/extra/wasm-symbol.svg create mode 100644 ext/wasm3/extra/wowcube.png create mode 100644 ext/wasm3/platforms/android/.gitignore create mode 100644 ext/wasm3/platforms/android/README.md create mode 100644 ext/wasm3/platforms/android/app/build.gradle create mode 100644 ext/wasm3/platforms/android/app/proguard-rules.pro create mode 100644 ext/wasm3/platforms/android/app/src/main/AndroidManifest.xml create mode 100644 ext/wasm3/platforms/android/app/src/main/cpp/CMakeLists.txt create mode 100644 ext/wasm3/platforms/android/app/src/main/cpp/jni.c create mode 120000 ext/wasm3/platforms/android/app/src/main/cpp/m3 create mode 100644 ext/wasm3/platforms/android/app/src/main/cpp/main.c create mode 100644 ext/wasm3/platforms/android/app/src/main/java/com/example/wasm3/MainActivity.java create mode 100644 ext/wasm3/platforms/android/app/src/main/res/drawable/ic_launcher.png create mode 100644 ext/wasm3/platforms/android/app/src/main/res/layout/activity_main.xml create mode 100644 ext/wasm3/platforms/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 ext/wasm3/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 ext/wasm3/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 ext/wasm3/platforms/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 ext/wasm3/platforms/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 ext/wasm3/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 ext/wasm3/platforms/android/app/src/main/res/values-w820dp/dimens.xml create mode 100644 ext/wasm3/platforms/android/app/src/main/res/values/colors.xml create mode 100644 ext/wasm3/platforms/android/app/src/main/res/values/dimens.xml create mode 100644 ext/wasm3/platforms/android/app/src/main/res/values/strings.xml create mode 100644 ext/wasm3/platforms/android/app/src/main/res/values/styles.xml create mode 100644 ext/wasm3/platforms/android/build.gradle create mode 100644 ext/wasm3/platforms/android/gradle.properties create mode 100644 ext/wasm3/platforms/android/gradle/wrapper/gradle-wrapper.jar create mode 100644 ext/wasm3/platforms/android/gradle/wrapper/gradle-wrapper.properties create mode 100755 ext/wasm3/platforms/android/gradlew create mode 100644 ext/wasm3/platforms/android/gradlew.bat create mode 100644 ext/wasm3/platforms/android/override.txt create mode 100644 ext/wasm3/platforms/android/settings.gradle create mode 100644 ext/wasm3/platforms/app/README.md create mode 100644 ext/wasm3/platforms/app/main.c create mode 100644 ext/wasm3/platforms/app_fuzz/fuzzer.c create mode 100644 ext/wasm3/platforms/cosmopolitan/.gitignore create mode 100755 ext/wasm3/platforms/cosmopolitan/build.sh create mode 100644 ext/wasm3/platforms/cpp/.gitignore create mode 100644 ext/wasm3/platforms/cpp/CMakeLists.txt create mode 100644 ext/wasm3/platforms/cpp/README.md create mode 100644 ext/wasm3/platforms/cpp/main.cpp create mode 100644 ext/wasm3/platforms/cpp/wasm/Makefile create mode 100644 ext/wasm3/platforms/cpp/wasm/test_prog.c create mode 100644 ext/wasm3/platforms/cpp/wasm/test_prog.wasm.h create mode 100644 ext/wasm3/platforms/cpp/wasm3_cpp/CMakeLists.txt create mode 100644 ext/wasm3/platforms/cpp/wasm3_cpp/include/wasm3_cpp.h create mode 100644 ext/wasm3/platforms/embedded/arduino/.gitignore create mode 120000 ext/wasm3/platforms/embedded/arduino/lib/wasm3 create mode 100644 ext/wasm3/platforms/embedded/arduino/platformio.ini create mode 100644 ext/wasm3/platforms/embedded/arduino/src/main.cpp create mode 100644 ext/wasm3/platforms/embedded/bluepill/.gitignore create mode 100644 ext/wasm3/platforms/embedded/bluepill/lib/wasm3/library.json create mode 120000 ext/wasm3/platforms/embedded/bluepill/lib/wasm3/src create mode 100644 ext/wasm3/platforms/embedded/bluepill/platformio.ini create mode 100644 ext/wasm3/platforms/embedded/bluepill/src/main.cpp create mode 100644 ext/wasm3/platforms/embedded/esp32-idf-wasi/.gitignore create mode 100644 ext/wasm3/platforms/embedded/esp32-idf-wasi/.old/Makefile create mode 100644 ext/wasm3/platforms/embedded/esp32-idf-wasi/.old/component.mk create mode 100644 ext/wasm3/platforms/embedded/esp32-idf-wasi/CMakeLists.txt create mode 100644 ext/wasm3/platforms/embedded/esp32-idf-wasi/README.md create mode 100644 ext/wasm3/platforms/embedded/esp32-idf-wasi/main/CMakeLists.txt create mode 100644 ext/wasm3/platforms/embedded/esp32-idf-wasi/main/m3_api_esp_wasi.c create mode 100644 ext/wasm3/platforms/embedded/esp32-idf-wasi/main/m3_api_esp_wasi.h create mode 100644 ext/wasm3/platforms/embedded/esp32-idf-wasi/main/main.cpp create mode 100644 ext/wasm3/platforms/embedded/esp32-idf-wasi/main/wasi_test.wasm.h create mode 120000 ext/wasm3/platforms/embedded/esp32-idf-wasi/main/wasm3 create mode 100644 ext/wasm3/platforms/embedded/esp32-idf-wasi/sdkconfig.defaults create mode 100644 ext/wasm3/platforms/embedded/esp32-idf/.gitignore create mode 100644 ext/wasm3/platforms/embedded/esp32-idf/.old/Makefile create mode 100644 ext/wasm3/platforms/embedded/esp32-idf/.old/component.mk create mode 100644 ext/wasm3/platforms/embedded/esp32-idf/CMakeLists.txt create mode 100644 ext/wasm3/platforms/embedded/esp32-idf/README.md create mode 100644 ext/wasm3/platforms/embedded/esp32-idf/main/CMakeLists.txt create mode 100644 ext/wasm3/platforms/embedded/esp32-idf/main/linker.lf create mode 100644 ext/wasm3/platforms/embedded/esp32-idf/main/main.cpp create mode 100644 ext/wasm3/platforms/embedded/esp32-idf/sdkconfig.defaults create mode 100644 ext/wasm3/platforms/embedded/esp32-pio/.gitignore create mode 100644 ext/wasm3/platforms/embedded/esp32-pio/lib/wasm3/README.md create mode 100644 ext/wasm3/platforms/embedded/esp32-pio/lib/wasm3/library.json create mode 120000 ext/wasm3/platforms/embedded/esp32-pio/lib/wasm3/src create mode 100644 ext/wasm3/platforms/embedded/esp32-pio/platformio.ini create mode 100644 ext/wasm3/platforms/embedded/esp32-pio/src/main.cpp create mode 100644 ext/wasm3/platforms/embedded/esp32-pio/src/sdkconfig create mode 100644 ext/wasm3/platforms/embedded/esp32-pio/src/sdkconfig.h create mode 100644 ext/wasm3/platforms/embedded/esp8266/.gitignore create mode 120000 ext/wasm3/platforms/embedded/esp8266/lib/wasm3 create mode 100644 ext/wasm3/platforms/embedded/esp8266/platformio.ini create mode 100644 ext/wasm3/platforms/embedded/esp8266/src/main.cpp create mode 100644 ext/wasm3/platforms/embedded/fomu/.env create mode 100644 ext/wasm3/platforms/embedded/fomu/.gitignore create mode 100644 ext/wasm3/platforms/embedded/fomu/Makefile create mode 100644 ext/wasm3/platforms/embedded/fomu/README.md create mode 100644 ext/wasm3/platforms/embedded/fomu/gdb_init create mode 100644 ext/wasm3/platforms/embedded/fomu/include/console.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/crc.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/csr-defs.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/generated/csr.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/generated/mem.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/hw/common.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/hw/flags.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/irq.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/printf.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/rgb.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/spi.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/spiflash.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/system.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/time.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/toboot-api.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/toboot-internal.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/usb-desc.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/usb.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/usbcdc.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/usbstd.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/webusb-defs.h create mode 100644 ext/wasm3/platforms/embedded/fomu/include/xxhash.c create mode 100644 ext/wasm3/platforms/embedded/fomu/include/xxhash.h create mode 100644 ext/wasm3/platforms/embedded/fomu/ld/linker.ld create mode 100644 ext/wasm3/platforms/embedded/fomu/ld/output_format.ld create mode 100644 ext/wasm3/platforms/embedded/fomu/ld/regions.ld create mode 100644 ext/wasm3/platforms/embedded/fomu/src/crt0-vexriscv.S create mode 100644 ext/wasm3/platforms/embedded/fomu/src/ltoa.c create mode 100644 ext/wasm3/platforms/embedded/fomu/src/main.c create mode 100644 ext/wasm3/platforms/embedded/fomu/src/rgb.c create mode 100644 ext/wasm3/platforms/embedded/fomu/src/time.c create mode 100644 ext/wasm3/platforms/embedded/fomu/src/usb-desc.c create mode 100644 ext/wasm3/platforms/embedded/fomu/src/usb-dev.c create mode 100644 ext/wasm3/platforms/embedded/fomu/src/usb-epfifo.c create mode 120000 ext/wasm3/platforms/embedded/fomu/src/wasm3 create mode 100644 ext/wasm3/platforms/embedded/hifive1/.gitignore create mode 100644 ext/wasm3/platforms/embedded/hifive1/README.md create mode 120000 ext/wasm3/platforms/embedded/hifive1/lib/wasm3 create mode 100644 ext/wasm3/platforms/embedded/hifive1/platformio.ini create mode 100644 ext/wasm3/platforms/embedded/hifive1/src/main.c create mode 100644 ext/wasm3/platforms/embedded/particle/.gitignore create mode 100644 ext/wasm3/platforms/embedded/particle/README.md create mode 100644 ext/wasm3/platforms/embedded/particle/lib/wasm3/library.properties create mode 120000 ext/wasm3/platforms/embedded/particle/lib/wasm3/src create mode 100644 ext/wasm3/platforms/embedded/particle/project.properties create mode 100644 ext/wasm3/platforms/embedded/particle/src/main.ino create mode 100644 ext/wasm3/platforms/embedded/wm_w600/.gitignore create mode 100644 ext/wasm3/platforms/embedded/wm_w600/Makefile create mode 100644 ext/wasm3/platforms/embedded/wm_w600/README.md create mode 100755 ext/wasm3/platforms/embedded/wm_w600/build.sh create mode 100644 ext/wasm3/platforms/embedded/wm_w600/main.c create mode 120000 ext/wasm3/platforms/embedded/wm_w600/wasm3 create mode 100644 ext/wasm3/platforms/emscripten/README.md create mode 100644 ext/wasm3/platforms/emscripten/main.c create mode 100644 ext/wasm3/platforms/emscripten_lib/main.c create mode 100644 ext/wasm3/platforms/emscripten_lib/run_native.js create mode 100644 ext/wasm3/platforms/emscripten_lib/run_wasm3.js create mode 100644 ext/wasm3/platforms/ios/.gitignore create mode 100644 ext/wasm3/platforms/ios/README.md create mode 100644 ext/wasm3/platforms/ios/wasm3.xcodeproj/project.pbxproj create mode 100644 ext/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ext/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 ext/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 ext/wasm3/platforms/ios/wasm3.xcodeproj/xcshareddata/xcschemes/wasm3 Release.xcscheme create mode 100644 ext/wasm3/platforms/ios/wasm3.xcodeproj/xcshareddata/xcschemes/wasm3.xcscheme create mode 100644 ext/wasm3/platforms/ios/wasm3/AppDelegate.swift create mode 100644 ext/wasm3/platforms/ios/wasm3/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ext/wasm3/platforms/ios/wasm3/Base.lproj/LaunchScreen.storyboard create mode 100644 ext/wasm3/platforms/ios/wasm3/Base.lproj/Main.storyboard create mode 100644 ext/wasm3/platforms/ios/wasm3/Bridging-Header.h create mode 100644 ext/wasm3/platforms/ios/wasm3/Info.plist create mode 100644 ext/wasm3/platforms/ios/wasm3/ViewController.swift create mode 100644 ext/wasm3/platforms/ios/wasm3/icon.png create mode 100644 ext/wasm3/platforms/ios/wasm3/main.c create mode 100644 ext/wasm3/platforms/openwrt/README.md create mode 100644 ext/wasm3/platforms/openwrt/build/Makefile create mode 100644 ext/wasm3/platforms/python/README.md create mode 100644 ext/wasm3/source/CMakeLists.txt create mode 100644 ext/wasm3/source/extensions/m3_extensions.c create mode 100644 ext/wasm3/source/extensions/wasm3_ext.h create mode 100644 ext/wasm3/source/extra/coremark_minimal.wasm.h create mode 100644 ext/wasm3/source/extra/fib32.wasm.h create mode 100644 ext/wasm3/source/extra/fib32_tail.wasm.h create mode 100644 ext/wasm3/source/extra/fib64.wasm.h create mode 100644 ext/wasm3/source/extra/wasi_core.h create mode 100644 ext/wasm3/source/m3_api_libc.c create mode 100644 ext/wasm3/source/m3_api_libc.h create mode 100644 ext/wasm3/source/m3_api_meta_wasi.c create mode 100644 ext/wasm3/source/m3_api_tracer.c create mode 100644 ext/wasm3/source/m3_api_tracer.h create mode 100644 ext/wasm3/source/m3_api_uvwasi.c create mode 100644 ext/wasm3/source/m3_api_wasi.c create mode 100644 ext/wasm3/source/m3_api_wasi.h create mode 100644 ext/wasm3/source/m3_bind.c create mode 100644 ext/wasm3/source/m3_bind.h create mode 100644 ext/wasm3/source/m3_code.c create mode 100644 ext/wasm3/source/m3_code.h create mode 100644 ext/wasm3/source/m3_compile.c create mode 100644 ext/wasm3/source/m3_compile.h create mode 100644 ext/wasm3/source/m3_config.h create mode 100644 ext/wasm3/source/m3_config_platforms.h create mode 100644 ext/wasm3/source/m3_core.c create mode 100644 ext/wasm3/source/m3_core.h create mode 100644 ext/wasm3/source/m3_env.c create mode 100644 ext/wasm3/source/m3_env.h create mode 100644 ext/wasm3/source/m3_exception.h create mode 100644 ext/wasm3/source/m3_exec.c create mode 100644 ext/wasm3/source/m3_exec.h create mode 100644 ext/wasm3/source/m3_exec_defs.h create mode 100644 ext/wasm3/source/m3_function.c create mode 100644 ext/wasm3/source/m3_function.h create mode 100644 ext/wasm3/source/m3_info.c create mode 100644 ext/wasm3/source/m3_info.h create mode 100644 ext/wasm3/source/m3_math_utils.h create mode 100644 ext/wasm3/source/m3_module.c create mode 100644 ext/wasm3/source/m3_parse.c create mode 100644 ext/wasm3/source/wasm3.h create mode 100644 ext/wasm3/source/wasm3_defs.h create mode 100644 ext/wasm3/test/internal/m3_test.c create mode 100755 ext/wasm3/test/internal/tailcall/build.sh create mode 100644 ext/wasm3/test/internal/tailcall/ops.c create mode 100644 ext/wasm3/test/lang/README.md create mode 100644 ext/wasm3/test/lang/fib.c create mode 100755 ext/wasm3/test/lang/fib.js create mode 100755 ext/wasm3/test/lang/fib.lua create mode 100755 ext/wasm3/test/lang/fib.min.js create mode 100755 ext/wasm3/test/lang/fib.py create mode 100644 ext/wasm3/test/lang/fib.walt create mode 100644 ext/wasm3/test/lang/fib32.wat create mode 100644 ext/wasm3/test/lang/fib32_tail.wat create mode 100644 ext/wasm3/test/lang/fib64.wat create mode 100755 ext/wasm3/test/run-spec-test.py create mode 100755 ext/wasm3/test/run-wasi-test.py create mode 100644 ext/wasm3/test/wasi/brotli/README.md create mode 100644 ext/wasm3/test/wasi/brotli/alice29.txt create mode 100644 ext/wasm3/test/wasi/brotli/alice29.txt.compressed create mode 100644 ext/wasm3/test/wasi/brotli/alice29_small.txt create mode 100644 ext/wasm3/test/wasi/c-ray/README.md create mode 100644 ext/wasm3/test/wasi/c-ray/c-ray-f.c create mode 100644 ext/wasm3/test/wasi/c-ray/scene create mode 100644 ext/wasm3/test/wasi/c-ray/scene.jpg create mode 100644 ext/wasm3/test/wasi/c-ray/sphfract create mode 100644 ext/wasm3/test/wasi/c-ray/sphfract.jpg create mode 100644 ext/wasm3/test/wasi/coremark/README.md create mode 100644 ext/wasm3/test/wasi/mal/.gitattributes create mode 100644 ext/wasm3/test/wasi/mal/README.md create mode 100644 ext/wasm3/test/wasi/mal/core.mal create mode 100644 ext/wasm3/test/wasi/mal/env.mal create mode 100644 ext/wasm3/test/wasi/mal/mal.mal create mode 100644 ext/wasm3/test/wasi/mal/test-fib.mal create mode 100644 ext/wasm3/test/wasi/mandelbrot/README.md create mode 100644 ext/wasm3/test/wasi/mandelbrot/colors.h create mode 100644 ext/wasm3/test/wasi/mandelbrot/doubledouble.h create mode 100644 ext/wasm3/test/wasi/mandelbrot/image.png create mode 100644 ext/wasm3/test/wasi/mandelbrot/mandel.c create mode 100644 ext/wasm3/test/wasi/mandelbrot/mandel_dd.c create mode 100644 ext/wasm3/test/wasi/raymarcher/raymarcher.cpp create mode 100644 ext/wasm3/test/wasi/simple/0.txt create mode 100644 ext/wasm3/test/wasi/simple/README.md create mode 100644 ext/wasm3/test/wasi/simple/test.c create mode 100644 ext/wasm3/test/wasi/simple/wasm_api.h create mode 100644 ext/wasm3/test/wasi/simple/wasm_api.syms create mode 100644 ext/wasm3/test/wasi/smallpt/README.md create mode 100644 ext/wasm3/test/wasi/smallpt/image.jpg create mode 100644 ext/wasm3/test/wasi/smallpt/smallpt-ex.cpp create mode 100644 ext/wasm3/test/wasi/smallpt/smallpt.cpp create mode 100644 ext/wasm3/test/wasi/stream/stream.c create mode 100644 ext/wasm3/test/wasi/wasmboy/.gitignore create mode 100644 ext/wasm3/test/wasi/wasmboy/README.md create mode 100644 ext/wasm3/test/wasi/wasmboy/image.png create mode 100644 ext/wasm3/test/wasi/wasmsynth/README.md create mode 100644 ext/wasm3/test/wasi/wasmsynth/image.png create mode 160000 milepost create mode 100755 samples/pong/build.sh create mode 100644 samples/pong/icon.png create mode 100644 samples/pong/main.c create mode 100755 scripts/bindgen.py create mode 100644 scripts/mkapp.py create mode 100644 sdk/GLES3/gl3.h create mode 100644 sdk/GLES3/gl31.h create mode 100644 sdk/GLES3/gl32.h create mode 100644 sdk/GLES3/gl3platform.h create mode 100644 sdk/KHR/khrplatform.h create mode 100644 sdk/keys.h create mode 100644 sdk/macro_helpers.h create mode 100644 sdk/typedefs.h create mode 100644 src/bindgen_core_api.txt create mode 100644 src/bindgen_gles_api.txt create mode 100644 src/main.c create mode 100644 src/manual_gles_api.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..82c5f66 --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +.DS_Store +*.dSYM +bin/* +*.metallib +*.pdb +*.exe +*.ilk +*.vs +*.obj +*.lib +*.dll +*.sln +*.wasm +*.app +*.dylib + +Debug/* + +src/bindgen_core_api.c +src/bindgen_gles_api.c \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..6442133 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "milepost"] + path = milepost + url = ssh://git@git.forkingpaths.dev/martinfouilleul/milepost.git diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..f2d342f --- /dev/null +++ b/build.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +target="$1" + +if [ -z $target ] ; then + target='orca' +fi +target=$(echo $target | tr '[:upper:]' '[:lower:]') + +if [ ! \( -e bin \) ] ; then + mkdir ./bin +fi + +if [ ! \( -e resources \) ] ; then + mkdir ./resources +fi + + +if [ $target = milepost ] ; then + echo "building milepost" + pushd milepost > /dev/null + ./build.sh lib "$2" + popd > /dev/null + +elif [ $target = wasm3 ] ; then + + echo "building wasm3" + mkdir ./bin/obj + for file in ./ext/wasm3/source/*.c ; do + name=$(basename $file) + name=${name/.c/.o} + clang -c -g -Wno-extern-initializer -Dd_m3VerboseErrorMessages -o ./bin/obj/$name -I./ext/wasm3/source $file + done + ar -rcs ./bin/libwasm3.a ./bin/obj/*.o + rm -rf ./bin/obj + +elif [ $target = orca ] ; then + echo "building orca" + + # copies libraries + cp milepost/bin/mtl_renderer.metallib bin/ + cp milepost/bin/libmilepost.dylib bin/ + cp milepost/bin/libGLESv2.dylib bin/ + cp milepost/bin/libEGL.dylib bin/ + + INCLUDES="-Imilepost/src -Imilepost/src/util -Imilepost/src/platform -Iext/wasm3/source -Imilepost/ext/" + LIBS="-Lbin -lmilepost -lwasm3" + FLAGS="-g -DLOG_COMPILE_DEBUG -mmacos-version-min=10.15.4 -maes" + + # generate wasm3 api bindings + ./scripts/bindgen.py core ./src + ./scripts/bindgen.py gles ./src + + # compile orca + clang $FLAGS $INCLUDES $LIBS -o bin/orca src/main.c + + # fix libs imports + install_name_tool -change "./bin/libmilepost.dylib" "@rpath/libmilepost.dylib" bin/orca + install_name_tool -add_rpath "@executable_path/" bin/orca + + +else + echo "unknown build target $target" +fi diff --git a/ext/wasm3/.codespellrc b/ext/wasm3/.codespellrc new file mode 100644 index 0000000..5a26d39 --- /dev/null +++ b/ext/wasm3/.codespellrc @@ -0,0 +1,5 @@ +[codespell] +skip = ./test/wasi/brotli/alice29.txt,./test/.spec-*,./build* +quiet-level = 2 +ignore-words-list = gameboy,iif,strng,woh + diff --git a/ext/wasm3/.github/workflows/publish.yml b/ext/wasm3/.github/workflows/publish.yml new file mode 100644 index 0000000..5b9ba1e --- /dev/null +++ b/ext/wasm3/.github/workflows/publish.yml @@ -0,0 +1,180 @@ +name: publish + +on: + push: + tags: + - "v*.*.*" + +env: + draft: true + +jobs: + wasm3-windows: + runs-on: windows-latest + name: ${{ matrix.config.target }} + timeout-minutes: 10 + + strategy: + fail-fast: false + matrix: + config: + - {target: wasm3-win-x64, platform: "-A x64", toolset: "-T ClangCL" } + - {target: wasm3-win-x86, platform: "-A Win32", toolset: "-T ClangCL" } + - {target: wasm3-strace-win-x64, platform: "-A x64", toolset: "-T ClangCL", cflags: "-DDEBUG -Dd_m3EnableStrace=2 -Dd_m3RecordBacktraces=1" } + + env: + LDFLAGS: -s + steps: + - uses: actions/checkout@v2 + - name: Configure + env: + CFLAGS: ${{ matrix.config.cflags }} + run: | + mkdir build + cd build + cmake ${{ matrix.config.platform }} ${{ matrix.config.toolset }} .. + - name: Build + run: | + cmake --build build --config Release + cp ./build/Release/wasm3.exe ./${{ matrix.config.target }}.exe + - name: Publish + uses: softprops/action-gh-release@v1 + with: + draft: ${{ env.draft }} + files: "*.exe" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + wasm3-linux-x64: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Setup musl + run: | + sudo apt update + sudo apt install musl-tools + - name: Setup cmake + uses: jwlawson/actions-setup-cmake@v1.9 + with: + cmake-version: '3.16.x' + - name: Configure + env: + CC: musl-gcc + LDFLAGS: "-static -s" + run: | + mkdir build + cd build + cmake --version + cmake .. + - name: Build + run: | + cmake --build build --verbose + cp ./build/wasm3 ./wasm3-linux-x64.elf + - name: Publish + uses: softprops/action-gh-release@v1 + with: + draft: ${{ env.draft }} + files: "*.elf" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + wasm3-cosmopolitan: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Build αcτµαlly pδrταblε εxεcµταblε + run: | + cd platforms/cosmopolitan + ./build.sh + cp ./wasm3.com ../../wasm3-cosmopolitan.com + cp ./wasm3.com.dbg ../../wasm3-cosmopolitan.com.dbg + - name: Publish + uses: softprops/action-gh-release@v1 + with: + draft: ${{ env.draft }} + files: | + *.com + *.com.dbg + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + wasm3-wasi: + runs-on: ubuntu-latest + timeout-minutes: 10 + + env: + LDFLAGS: -s + steps: + - uses: actions/checkout@v2 + - name: Install Python dependencies + run: | + python3 -m pip install pip==20.1.1 + python3 -m pip install --upgrade setuptools wheel + pip3 --version + - name: Install Wasienv + env: + WASMER_RELEASE_TAG: "1.0.2" + run: curl https://raw.githubusercontent.com/wasienv/wasienv/master/install.sh | sh + - name: Configure + run: | + source $HOME/.wasienv/wasienv.sh + mkdir build + cd build + wasimake cmake .. + - name: Build + run: | + source $HOME/.wasienv/wasienv.sh + cmake --build build + cp ./build/wasm3.wasm ./wasm3-wasi.wasm + - name: Configure, Build wasm3-strace + env: + CFLAGS: -DDEBUG -Dd_m3EnableStrace=2 -Dd_m3RecordBacktraces=1 + run: | + source $HOME/.wasienv/wasienv.sh + mkdir build-strace + cd build-strace + wasimake cmake .. + cmake --build . + cp ./wasm3.wasm ../wasm3-strace.wasm + - name: Publish + uses: softprops/action-gh-release@v1 + with: + draft: ${{ env.draft }} + files: "*.wasm" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + wasm3-android-coremark: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - uses: seanmiddleditch/gha-setup-ninja@master + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Install NDK + run: | + sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;22.1.7171670" + sudo ${ANDROID_HOME}/tools/bin/sdkmanager --uninstall "cmake;3.18.1" + sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "cmake;3.10.2.4988404" + - name: Build + run: | + cd platforms/android + ./gradlew build + - name: Copy + run: | + cp ./platforms/android/app/build/outputs/apk/debug/app-debug.apk ./wasm3-android-coremark.apk + - name: Publish + uses: softprops/action-gh-release@v1 + with: + draft: ${{ env.draft }} + files: "*.apk" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/ext/wasm3/.github/workflows/tests.yml b/ext/wasm3/.github/workflows/tests.yml new file mode 100644 index 0000000..2935b1d --- /dev/null +++ b/ext/wasm3/.github/workflows/tests.yml @@ -0,0 +1,619 @@ +name: tests + +on: + push: + paths-ignore: ['**.md', '**.svg', '**.png'] + pull_request: + paths-ignore: ['**.md', '**.svg', '**.png'] + +jobs: + linux: + runs-on: ubuntu-latest + name: linux-${{ matrix.config.target }} + timeout-minutes: 10 + + strategy: + fail-fast: false + matrix: + config: + - {target: clang, cc: clang, } + - {target: clang-x86, cc: clang, flags: -DCMAKE_C_FLAGS="-m32", install: "gcc-multilib" } + - {target: gcc, cc: gcc, } + # Builds without uvwasi + - {target: gcc-no-uvwasi, cc: gcc, flags: -DBUILD_WASI=simple } + - {target: clang-no-uvwasi, cc: clang, flags: -DBUILD_WASI=simple } + # Debug builds + - {target: gcc-debug, cc: gcc, flags: -DCMAKE_BUILD_TYPE=Debug } + - {target: clang-no-uvwasi-debug, cc: clang, flags: -DCMAKE_BUILD_TYPE=Debug -DBUILD_WASI=simple } + + # TODO: fails on numeric operations + #- {target: gcc-x86, cc: gcc, flags: "-m32", install: "gcc-multilib" } + + steps: + - uses: actions/checkout@v2 + - name: Install ${{ matrix.config.install }} + if: ${{ matrix.config.install }} + run: | + sudo apt update + sudo apt install ${{ matrix.config.install }} + - name: Configure + env: + CC: ${{ matrix.config.cc }} + CFLAGS: ${{ matrix.config.cflags }} + run: | + mkdir build + cd build + cmake ${{ matrix.config.flags }} .. + - name: Build + run: | + cmake --build build + - name: Test WebAssembly spec + run: cd test && python3 run-spec-test.py + - name: Test previous WebAssembly specs + run: | + cd test + python3 run-spec-test.py --spec=v1.1 + - name: Test WASI apps + run: cd test && python3 run-wasi-test.py + + linux-alpine: + runs-on: ubuntu-latest + container: alpine:3.10 + + steps: + - uses: actions/checkout@v2 + - name: Prepare + run: apk add build-base cmake python3 git --update-cache + - name: Configure + run: | + mkdir build + cd build + cmake .. + - name: Build + run: cmake --build build + - name: Test WebAssembly spec + run: cd test && python3 run-spec-test.py + - name: Test WASI apps + run: cd test && python3 run-wasi-test.py + + macos: + runs-on: macos-latest + name: macos-${{ matrix.config.target }} + timeout-minutes: 10 + + strategy: + fail-fast: false + matrix: + config: + - {target: uvwasi, } + - {target: no-uvwasi, flags: -DBUILD_WASI=simple } + + steps: + - uses: actions/checkout@v2 + - name: Configure + run: | + mkdir build + cd build + cmake ${{ matrix.config.flags }} .. + - name: Build + run: | + cmake --build build + - name: Test WebAssembly spec + run: cd test && python3 run-spec-test.py + - name: Test previous WebAssembly specs + run: | + cd test + python3 run-spec-test.py --spec=v1.1 + - name: Test WASI apps + run: cd test && python3 run-wasi-test.py + + windows: + runs-on: windows-latest + name: windows-${{ matrix.config.target }} + timeout-minutes: 10 + + strategy: + fail-fast: false + matrix: + config: + - {target: clang-x64, platform: "-A x64", toolset: "-T ClangCL" } + - {target: msvc-x64, platform: "-A x64", toolset: "" } + - {target: clang-x86, platform: "-A Win32", toolset: "-T ClangCL" } + - {target: msvc-x86, platform: "-A Win32", toolset: "" } + # Builds without uvwasi + - {target: clang-x64-no-uvwasi, platform: "-A x64", toolset: "-T ClangCL", flags: "-DBUILD_WASI=simple" } + - {target: msvc-x64-no-uvwasi, platform: "-A x64", toolset: "", flags: "-DBUILD_WASI=simple" } + - {target: clang-x86-no-uvwasi, platform: "-A Win32", toolset: "-T ClangCL", flags: "-DBUILD_WASI=simple" } + - {target: msvc-x86-no-uvwasi, platform: "-A Win32", toolset: "", flags: "-DBUILD_WASI=simple" } + + defaults: + run: + shell: cmd + + steps: + - uses: actions/checkout@v2 + - name: Configure + run: | + mkdir build + cd build + cmake ${{ matrix.config.platform }} ${{ matrix.config.toolset }} ${{ matrix.config.flags }} .. + - name: Build + run: | + cmake --build build --config Release + cp ./build/Release/wasm3.exe ./build/ + - name: Test WebAssembly spec + run: | + cd test + python run-spec-test.py + - name: Test previous WebAssembly specs + run: | + cd test + python run-spec-test.py --spec=v1.1 + - name: Test WASI apps + run: | + cd test + python run-wasi-test.py + + cygwin-build: + runs-on: windows-latest + + steps: + - uses: actions/checkout@main + - name: Set up Cygwin + uses: egor-tensin/setup-cygwin@master + with: + platform: x64 + packages: make gcc-g++ cmake + - run: cd $GITHUB_WORKSPACE && cmake -DBUILD_WASI=simple . && make + shell: C:\tools\cygwin\bin\bash.exe --login --norc -eo pipefail -o igncr '{0}' + + wasi: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Install Python dependencies + run: | + python3 -m pip install pip==20.1.1 + python3 -m pip install --upgrade setuptools wheel + pip3 --version + - name: Install Wasienv + env: + WASMER_RELEASE_TAG: "1.0.2" + run: curl https://raw.githubusercontent.com/wasienv/wasienv/master/install.sh | sh + - name: Configure + run: | + source $HOME/.wasienv/wasienv.sh + mkdir build-wasi + cd build-wasi + wasimake cmake .. + - name: Build + run: | + source $HOME/.wasienv/wasienv.sh + cmake --build build-wasi + - name: Test WebAssembly spec (in Wasmer) + run: | + source $HOME/.wasmer/wasmer.sh + cd test + python3 run-spec-test.py --exec "wasmer run --mapdir=/:. ../build-wasi/wasm3.wasm -- --repl" + + - name: Test WASI apps (in Wasmer) + run: | + source $HOME/.wasmer/wasmer.sh + cd test + python3 run-wasi-test.py --exec "wasmer run --mapdir=/:. ../build-wasi/wasm3.wasm --" --fast + + - name: Configure (native) + run: | + mkdir build + cd build + cmake .. + - name: Build (native) + run: | + cmake --build build + - name: Test WebAssembly spec (in Wasm3, self-hosting) + run: | + cd test + cp ../build-wasi/wasm3.wasm ./ + python3 run-spec-test.py --exec "../build/wasm3 --stack-size 2097152 ../build-wasi/wasm3.wasm --repl" + - name: Test WASI apps (in Wasm3, self-hosting) + run: | + cd test + python3 run-wasi-test.py --fast --exec "../build/wasm3 --stack-size 2097152 ../build-wasi/wasm3.wasm" + + ios: + runs-on: macos-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: List Xcode versions + run: ls /Applications | grep Xcode + - name: Select Xcode 12 + run: sudo xcode-select -switch /Applications/Xcode_12.4.app + - name: Build (iPhone 11) + run: | + cd platforms/ios + xcodebuild build -scheme wasm3 -project wasm3.xcodeproj -configuration Release -destination 'platform=iOS Simulator,name=iPhone 11,OS=14.4' + + android: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - uses: seanmiddleditch/gha-setup-ninja@master + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Install NDK + run: | + sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;22.1.7171670" + sudo ${ANDROID_HOME}/tools/bin/sdkmanager --uninstall "cmake;3.18.1" + sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "cmake;3.10.2.4988404" + - name: Build + run: | + cd platforms/android + ./gradlew build + + python: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + path: wasm3 + - name: Checkout pywasm3 + uses: actions/checkout@v2 + with: + repository: wasm3/pywasm3 + path: pywasm3 + - name: Set up Python + uses: actions/setup-python@v2 + - name: Update and Build Python module + run: | + rm -rf ./pywasm3/wasm3 + cp -r wasm3/source ./pywasm3/wasm3 + pip install ./pywasm3 + - name: Install WABT + run: | + sudo apt update + sudo apt install wabt + - name: Test + run: | + pip install pytest + cd ./pywasm3 + pytest + + cosmopolitan: + runs-on: ubuntu-20.04 + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Build αcτµαlly pδrταblε εxεcµταblε + run: | + cd platforms/cosmopolitan + gcc -v + ./build.sh + - name: Prepare tests + run: | + cd test + cp ../platforms/cosmopolitan/wasm3.com ./wasm3-lin.com + cp ../platforms/cosmopolitan/wasm3.com ./wasm3-win.com + sudo sh -c "echo ':APE:M::MZqFpD::/bin/sh:' >/proc/sys/fs/binfmt_misc/register" + - name: Test WebAssembly spec + run: | + cd test + python3 run-spec-test.py --exec "./wasm3-lin.com --repl" + - name: Test WASI apps + run: | + cd test + python3 run-wasi-test.py --fast --exec "./wasm3-lin.com" + - name: Install Wine64 + run: | + sudo apt update + sudo apt install wine64 + wine --version + - name: Test WebAssembly spec (in Wine) + run: | + cd test + python3 run-spec-test.py --exec "wine ./wasm3-win.com --repl" + - name: Test WASI apps (in Wine) + run: | + cd test + python3 run-wasi-test.py --fast --exec "wine ./wasm3-win.com" + + cross-qemu: + runs-on: ubuntu-20.04 + name: cross-qemu-${{ matrix.config.target }} + timeout-minutes: 10 + + strategy: + fail-fast: false + matrix: + config: + #- {target: i386, toolchain: gcc-multilib, cc: clang -m32, qemu: qemu-i386-static } + - {target: arm, toolchain: gcc-arm-linux-gnueabi, cc: arm-linux-gnueabi-gcc, qemu: qemu-arm-static } + - {target: armhf, toolchain: gcc-arm-linux-gnueabihf, cc: arm-linux-gnueabihf-gcc, qemu: qemu-arm-static } + - {target: aarch64, toolchain: gcc-aarch64-linux-gnu, cc: aarch64-linux-gnu-gcc, qemu: qemu-aarch64-static } + - {target: riscv64, toolchain: gcc-riscv64-linux-gnu, cc: riscv64-linux-gnu-gcc, qemu: qemu-riscv64-static } + - {target: ppc, toolchain: gcc-powerpc-linux-gnu, cc: powerpc-linux-gnu-gcc, qemu: qemu-ppc-static } + - {target: ppc64, toolchain: gcc-powerpc64-linux-gnu, cc: powerpc64-linux-gnu-gcc, qemu: qemu-ppc64-static } + #- {target: ppc64le, toolchain: gcc-powerpc64le-linux-gnu, cc: powerpc64le-linux-gnu-gcc, qemu: qemu-ppc64le-static } + - {target: s390x, toolchain: gcc-s390x-linux-gnu, cc: s390x-linux-gnu-gcc, qemu: qemu-s390x-static } + - {target: mips, toolchain: gcc-mips-linux-gnu, cc: mips-linux-gnu-gcc, qemu: qemu-mips-static } + - {target: mips64, toolchain: gcc-mips64-linux-gnuabi64, cc: mips64-linux-gnuabi64-gcc, qemu: qemu-mips64-static } + - {target: mipsel, toolchain: gcc-mipsel-linux-gnu, cc: mipsel-linux-gnu-gcc, qemu: qemu-mipsel-static } + - {target: mips64el,toolchain: gcc-mips64el-linux-gnuabi64, cc: mips64el-linux-gnuabi64-gcc,qemu: qemu-mips64el-static } + - {target: alpha, toolchain: gcc-alpha-linux-gnu, cc: alpha-linux-gnu-gcc, qemu: qemu-alpha-static } + - {target: sparc64, toolchain: gcc-sparc64-linux-gnu, cc: sparc64-linux-gnu-gcc, qemu: qemu-sparc64-static, skip_wasi: true } + + #- {target: i386 (u64 slots), toolchain: gcc-multilib, cc: clang -m32, qemu: qemu-i386-static, cflags: -Dd_m3Use32BitSlots=0 } + - {target: arm (u64 slots), toolchain: gcc-arm-linux-gnueabi, cc: arm-linux-gnueabi-gcc, qemu: qemu-arm-static, cflags: -Dd_m3Use32BitSlots=0 } + - {target: aarch64 (u64 slots), toolchain: gcc-aarch64-linux-gnu, cc: aarch64-linux-gnu-gcc, qemu: qemu-aarch64-static, cflags: -Dd_m3Use32BitSlots=0 } + - {target: ppc (u64 slots), toolchain: gcc-powerpc-linux-gnu, cc: powerpc-linux-gnu-gcc, qemu: qemu-ppc-static, cflags: -Dd_m3Use32BitSlots=0 } + - {target: ppc64 (u64 slots), toolchain: gcc-powerpc64-linux-gnu, cc: powerpc64-linux-gnu-gcc, qemu: qemu-ppc64-static, cflags: -Dd_m3Use32BitSlots=0 } + + steps: + - uses: actions/checkout@v2 + - name: Install QEMU + run: | + sudo apt update + sudo apt install qemu-user-static + - name: Install ${{ matrix.config.toolchain }} + run: | + sudo apt install ${{ matrix.config.toolchain }} + - name: Build + run: | + mkdir build + cd build + ${{ matrix.config.cc }} -DASSERTS -Dd_m3HasWASI ${{ matrix.config.cflags }} \ + -I../source ../source/*.c ../platforms/app/main.c \ + -O3 -g0 -flto -lm -static \ + -o wasm3 + - name: Test WebAssembly spec + run: | + cd test + python3 run-spec-test.py --exec "${{ matrix.config.qemu }} ../build/wasm3 --repl" + - name: Test WASI apps + if: ${{ !matrix.config.skip_wasi }} + run: | + cd test + python3 run-wasi-test.py --fast --exec "${{ matrix.config.qemu }} ../build/wasm3" + + platformio: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + - name: Install PlatformIO + run: | + python -m pip install --upgrade pip + pip install -U platformio + - name: Build AVR ATmega1284 + run: | + cd platforms/embedded/arduino + pio run -e mega1284 + ! nm .pio/build/mega1284/firmware.elf | grep printf + - name: Build ESP8266 + run: | + cd platforms/embedded/esp8266 + pio run + # TODO: + #- name: Build ESP32 + # run: | + # cd platforms/embedded/esp32-pio + # pio run + + platformio-arm: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + - name: Install PlatformIO + run: | + python -m pip install --upgrade pip + pip install -U platformio + - name: Build Arduino MKR1000 + run: | + cd platforms/embedded/arduino + pio run -e mkr1000 + - name: Build Blue Pill (JeeH) + run: | + cd platforms/embedded/bluepill + pio run + - name: Build TinyBLE + run: | + cd platforms/embedded/arduino + pio run -e tinyBLE + - name: Build MXChip AZ3166 + run: | + cd platforms/embedded/arduino + pio run -e az3166 + + platformio-riscv: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + - name: Install PlatformIO + run: | + python -m pip install --upgrade pip + pip install -U platformio + - name: Build HiFive1 + run: | + cd platforms/embedded/hifive1 + pio run + - name: Build Sipeed MAIX + run: | + cd platforms/embedded/arduino + pio run -e maix + + particle: + runs-on: ubuntu-latest + timeout-minutes: 10 + if: "github.event_name == 'push'" + + steps: + - uses: actions/checkout@v2 + - name: Set up Particle CLI + run: sudo npm install -g particle-cli + - name: Log in + env: + PARTICLE_TOKEN: ${{ secrets.PARTICLE_TOKEN }} + run: particle login --token $PARTICLE_TOKEN + - name: Build Photon + run: | + cd platforms/embedded/particle + particle compile --followSymlinks photon + particle compile --followSymlinks argon + + esp32-idf: + runs-on: ubuntu-latest + container: igrr/idf-qemu:release-v4.0-esp-develop-20191228 + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Build for ESP32 (IDF v4.0) + run: | + . $IDF_PATH/export.sh + cd platforms/embedded/esp32-idf + export EXTRA_CFLAGS="-Werror" + idf.py build + shell: bash + - name: Test for ESP32 in QEMU + run: | + cd platforms/embedded/esp32-idf + make-flash-img.sh wasm3 flash_img.bin + qemu-system-xtensa -machine esp32 -nographic -drive file=flash_img.bin,if=mtd,format=raw -no-reboot | tee out.txt + grep "Result: 46368" out.txt + grep "Elapsed: " out.txt + grep "Restarting..." out.txt + test $(($(grep "ets Jun 8 2016" out.txt | wc -l))) -eq 1 + - name: Check that IDF and PIO examples are in sync + run: | + diff -q platforms/embedded/esp32-idf/main/main.cpp platforms/embedded/esp32-pio/src/main.cpp + # TODO: also check that the build flags are in sync + + cpp: + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Configure + run: | + cd platforms/cpp + mkdir build + cd build + cmake .. + - name: Build + run: | + cd platforms/cpp + cmake --build build + - name: Run + run: | + cd platforms/cpp/build + ./wasm3_cpp_example + + as-cpp: + name: maintenance (build as C++) + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Build + run: | + mkdir build + cd build + clang -xc++ -Dd_m3HasWASI \ + -I../source ../source/*.c ../platforms/app/main.c \ + -O3 -g0 -lm \ + -o wasm3 + - name: Test + run: ./build/wasm3 ./test/wasi/simple/test.wasm + + with-logs: + name: maintenance (debug logs) + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Build + run: | + mkdir build + cd build + clang -xc++ -Dd_m3HasWASI -DDEBUG \ + -Dd_m3EnableOpTracing=1 \ + -Dd_m3EnableStrace=1 \ + -Dd_m3LogParse=1 \ + -Dd_m3LogModule=1 \ + -Dd_m3LogCompile=1 \ + -Dd_m3LogWasmStack=1 \ + -Dd_m3LogEmit=1 \ + -Dd_m3LogCodePages=1 \ + -Dd_m3LogRuntime=1 \ + -Dd_m3LogNativeStack=1 \ + -I../source ../source/*.c ../platforms/app/main.c \ + -O3 -g0 -lm \ + -o wasm3 + - name: Test + run: ./build/wasm3 ./test/wasi/simple/test.wasm > /dev/null + + preprocessed-ops: + name: maintenance (preprocess ops) + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + - name: Install sponge + run: | + sudo apt update + sudo apt install moreutils + - name: Build + run: | + make -f extra/utils.mk preprocess + mkdir build + cd build + gcc -Dd_m3HasWASI \ + -I../source ../source/*.c ../platforms/app/main.c \ + -O3 -g0 -lm \ + -o wasm3 + - name: Test + run: ./build/wasm3 ./test/wasi/simple/test.wasm + + spellcheck: + runs-on: ubuntu-latest + steps: + - name: Set up Python + uses: actions/setup-python@v2 + - name: Install codespell + run: | + pip install codespell + - name: Spellcheck + run: | + codespell diff --git a/ext/wasm3/.gitignore b/ext/wasm3/.gitignore new file mode 100644 index 0000000..cc890e1 --- /dev/null +++ b/ext/wasm3/.gitignore @@ -0,0 +1,13 @@ +/build* +/source-* +/.toolchains +test/.spec-* +test/*.log +test/tailcall/*.S +node_modules/ +__pycache__/ +.project +.cproject +.settings +.vscode +.DS_Store diff --git a/ext/wasm3/CMakeLists.txt b/ext/wasm3/CMakeLists.txt new file mode 100755 index 0000000..09a1a93 --- /dev/null +++ b/ext/wasm3/CMakeLists.txt @@ -0,0 +1,225 @@ +cmake_minimum_required(VERSION 3.11) + +# Detect WasiEnv +if(DEFINED ENV{WASI_CC}) + set(WASIENV 1) +endif() + +# Detect MinGW +if(WIN32 AND CMAKE_C_COMPILER_ID MATCHES "GNU") + set(MINGW 1) +endif() + +# Set options + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release" CACHE STRING "set build type to Release") +endif() + +if(WASIENV) + set(BUILD_WASI "metawasi" CACHE STRING "WASI implementation") +elseif(EMSCRIPTEN OR EMSCRIPTEN_LIB) + set(BUILD_WASI "none" CACHE STRING "WASI implementation") +else() + set(BUILD_WASI "uvwasi" CACHE STRING "WASI implementation") +endif() +set_property(CACHE BUILD_WASI PROPERTY STRINGS none simple uvwasi metawasi) + +option(BUILD_NATIVE "Build with machine-specific optimisations" ON) + +set(OUT_FILE "wasm3") + +if(NOT APP_DIR) + set(APP_DIR "platforms/app") +endif() + +# Configure the toolchain + +if(CLANG OR CLANG_SUFFIX) + set(CMAKE_C_COMPILER "clang${CLANG_SUFFIX}") + set(CMAKE_CXX_COMPILER "clang++${CLANG_SUFFIX}") + + if(BUILD_FUZZ) + set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") + set(OUT_FILE "wasm3-fuzzer") + set(APP_DIR "platforms/app_fuzz") + set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "set build type to Debug") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=fuzzer,address") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=fuzzer,address") + endif() +endif() + +if(CLANG_CL) + set(CMAKE_C_COMPILER "clang-cl") + set(CMAKE_CXX_COMPILER "clang-cl") + set(CMAKE_LINKER "lld-link") +endif() + +if(EMSCRIPTEN OR EMSCRIPTEN_LIB) + set(CMAKE_C_COMPILER "emcc") + set(CMAKE_CXX_COMPILER "em++") + + if (EMSCRIPTEN_LIB) + set(APP_DIR "platforms/emscripten_lib") + set(OUT_FILE "wasm3.wasm") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s STANDALONE_WASM") + else() + set(APP_DIR "platforms/emscripten") + set(OUT_FILE "wasm3.html") + endif() +endif() + +if(BUILD_32BIT) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") +endif() + + + +project(wasm3) + +message("----") +message("Generator: ${CMAKE_GENERATOR}") +message("Compiler: ${CMAKE_C_COMPILER_ID}") +message("Build Type: ${CMAKE_BUILD_TYPE}") + + +include(CheckIPOSupported) + +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD_REQUIRED YES) +set(CMAKE_C_EXTENSIONS NO) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED YES) +set(CMAKE_CXX_EXTENSIONS NO) + + +file(GLOB app_srcs "${APP_DIR}/*.c") +add_executable(${OUT_FILE} ${app_srcs}) + +#-fno-optimize-sibling-calls + +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG=1") + +if(EMSCRIPTEN OR EMSCRIPTEN_LIB) + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s GLOBAL_BASE=1024 -s TOTAL_STACK=2MB -s INITIAL_MEMORY=4MB -s ALLOW_MEMORY_GROWTH") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -s EXPORTED_FUNCTIONS=\"[\\\"_malloc\\\",\\\"_free\\\",\\\"_main\\\"]\"") + + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -flto -Wfatal-errors -s ASSERTIONS=0") + set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} --strip-all --gc-sections") + + if(WASM_EXT) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mbulk-memory -mnontrapping-fptoint -msign-ext -mtail-call") + endif() + +elseif(WASIENV) + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dd_m3HasTracer") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -Wfatal-errors -fomit-frame-pointer -fno-stack-check -fno-stack-protector") + + if(WASM_EXT) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mbulk-memory -mnontrapping-fptoint -msign-ext -mtail-call") + endif() + + # TODO: LTO breaks wasm imports currently: + # https://www.mail-archive.com/llvm-bugs@lists.llvm.org/msg36273.html + + #-flto -Wl,--lto-O3 + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,stack-size=8388608") + +elseif(WIN32 AND NOT MINGW) + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dd_m3HasTracer -D_CRT_SECURE_NO_WARNINGS /WX- /diagnostics:column") + + string(REGEX REPLACE "/W[0-4]" "/W0" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + + if (CMAKE_C_COMPILER_ID MATCHES "MSVC") + + if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /d2noftol3") + endif() + + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Oxs /Oy /GS- /Zi /Zo /arch:AVX2") + + # Uncomment this if you want to disassemble the release build, + # for example: dumpbin /DISASM wasm3.exe /out:wasm3.S + #set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG:FULL") + + else() + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /Oxs /Oy /GS- /Qvec -Clang -O3") + endif() + + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:8388608") # stack size + +else() + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dd_m3HasTracer") #-Dd_m3FixedHeap=1048576 + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wparentheses -Wundef -Wpointer-arith -Wstrict-aliasing=2") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=implicit-function-declaration") # -Werror=cast-align + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers") + if (CMAKE_C_COMPILER_ID MATCHES "Clang") + # TODO: Place clang-specific options here + elseif(CMAKE_C_COMPILER_ID MATCHES "Intel") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fp-model precise") + elseif(CMAKE_C_COMPILER_ID MATCHES "GNU") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wjump-misses-init") + endif() + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -save-temps") + + set(CMAKE_C_FLAGS_RELEASE "-O3 -Wfatal-errors -fomit-frame-pointer -fno-stack-check -fno-stack-protector") #-fno-inline + + if(BUILD_NATIVE) + if(APPLE AND CMAKE_C_COMPILER_ID MATCHES "Clang" AND CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "arm64") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -mcpu=native") + else() + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -march=native") + endif() + endif() + + set(CMAKE_EXE_LINKER_FLAGS_DEBUG "-O0") + set(CMAKE_EXE_LINKER_FLAGS_RELEASE "-O3") + + target_link_libraries(${OUT_FILE} m) + +endif() + +target_link_libraries(${OUT_FILE} m3) + +if(BUILD_WASI MATCHES "simple") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dd_m3HasWASI") +elseif(BUILD_WASI MATCHES "metawasi") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dd_m3HasMetaWASI") +elseif(BUILD_WASI MATCHES "uvwasi") + include(FetchContent) + FetchContent_Declare( + uvwasi + GIT_REPOSITORY https://github.com/nodejs/uvwasi.git + GIT_TAG b599542f7ce001e04cdff9db82b05fee96bb3332 + ) + + FetchContent_GetProperties(uvwasi) + if(NOT uvwasi_POPULATED) + FetchContent_Populate(uvwasi) + include_directories("${uvwasi_SOURCE_DIR}/include") + add_subdirectory(${uvwasi_SOURCE_DIR} ${uvwasi_BINARY_DIR} EXCLUDE_FROM_ALL) + endif() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Dd_m3HasUVWASI") + target_link_libraries(${OUT_FILE} uvwasi_a uv_a) +endif() + +check_ipo_supported(RESULT result) +if(result AND NOT WASIENV) # TODO: LTO breaks wasm imports + set_property(TARGET ${OUT_FILE} PROPERTY INTERPROCEDURAL_OPTIMIZATION True) + message("LTO: ON") +else() + message("LTO: OFF") +endif() + +add_subdirectory(source) + +message("Flags: ${CMAKE_C_FLAGS}") +message("Debug flags: ${CMAKE_C_FLAGS_DEBUG}") +message("Release flags: ${CMAKE_C_FLAGS_RELEASE}") + +message("----") diff --git a/ext/wasm3/LICENSE b/ext/wasm3/LICENSE new file mode 100644 index 0000000..e580601 --- /dev/null +++ b/ext/wasm3/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Steven Massey, Volodymyr Shymanskyy + +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. diff --git a/ext/wasm3/README.md b/ext/wasm3/README.md new file mode 100644 index 0000000..f88cc41 --- /dev/null +++ b/ext/wasm3/README.md @@ -0,0 +1,118 @@ +[![SWUbanner](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/banner-direct.svg)](https://vshymanskyy.github.io/StandWithUkraine) + + + +# Wasm3 + +[![WAPM](https://wapm.io/package/vshymanskyy/wasm3/badge.svg)](https://wapm.io/package/vshymanskyy/wasm3) +[![GitHub issues](https://img.shields.io/github/issues-raw/wasm3/wasm3?style=flat-square&label=issues&color=success)](https://github.com/wasm3/wasm3/issues) +[![Tests status](https://img.shields.io/github/workflow/status/wasm3/wasm3/tests/main?style=flat-square&logo=github&label=tests)](https://github.com/wasm3/wasm3/actions) +[![Fuzzing Status](https://img.shields.io/badge/oss--fuzz-fuzzing-success?style=flat-square)](https://bugs.chromium.org/p/oss-fuzz/issues/list?can=1&q=proj:wasm3) +[![GitHub license](https://img.shields.io/badge/license-MIT-blue?style=flat-square)](https://github.com/wasm3/wasm3) + +The fastest WebAssembly interpreter, and the most universal runtime. +Based on [**CoreMark 1.0**](./docs/Performance.md) and [**independent**](https://00f.net/2021/02/22/webassembly-runtimes-benchmarks) benchmarks. Your mileage may vary. + + +[![Twitter](https://img.shields.io/twitter/follow/wasm3_engine?style=flat-square&color=1da1f2&label=twitter&logo=twitter)](https://twitter.com/wasm3_engine) +[![Discord](https://img.shields.io/discord/671415645073702925?style=flat-square&logo=discord&color=7289da&label=discord)](https://discord.gg/qmZjgnd) +[![Telegram](https://img.shields.io/badge/telegram-chat-0088cc?style=flat-square&logo=telegram)](https://t.me/joinchat/DD8s3xVG8Vj_LxRDm52eTQ) + +## Getting Started + +Here's a small [getting started guide](https://wapm.io/package/vshymanskyy/wasm3). Click here to start: + +[![LIVE DEMO](extra/button.png)](https://webassembly.sh/?run-command=wasm3) + + +## Installation + +**Please follow the [installation instructions](./docs/Installation.md).** + +Wasm3 can also be used as a library for: + +[ Python3](https://github.com/wasm3/pywasm3) │ +[ Rust](https://github.com/Veykril/wasm3-rs) │ +[ C/C++](https://github.com/wasm3/wasm3) │ +[ GoLang](https://github.com/matiasinsaurralde/go-wasm3) │ +[ Zig](https://github.com/alichay/zig-wasm3) │ +[ Perl](https://metacpan.org/pod/Wasm::Wasm3) +[ Swift](https://github.com/shareup/wasm-interpreter-apple) │ +[ .Net](https://github.com/tana/Wasm3DotNet) │ +[ Arduino, PlatformIO, Particle](https://github.com/wasm3/wasm3-arduino) │ [QuickJS](https://github.com/saghul/txiki.js) + +## Status + +`wasm3` passes the [WebAssembly spec testsuite](https://github.com/WebAssembly/spec/tree/master/test/core) and is able to run many `WASI` apps. + +Minimum useful system requirements: **~64Kb** for code and **~10Kb** RAM + +`wasm3` runs on a wide range of architectures (`x86`, `x86_64`, `ARM`, `RISC-V`, `PowerPC`, `MIPS`, `Xtensa`, `ARC32`, ...) and [platforms](/platforms): +- Linux, + Windows, + OS X, + FreeBSD, + Android, + iOS +- OpenWrt, Yocto, Buildroot (routers, modems, etc.) +- Raspberry Pi, Orange Pi and other SBCs +- MCUs: Arduino, ESP8266, ESP32, Particle, ... [see full list](./docs/Hardware.md) +- Browsers. Yes, using WebAssembly itself! +- `wasm3` can execute `wasm3` (self-hosting) + +## Features + +| Webassembly [Core Proposals][WasmProps] | Extra | +| --- | --- | +| ☑ Import/Export of Mutable Globals | ☑ Structured execution tracing | +| ☑ Non-trapping float-to-int conversions | ☑ Big-Endian systems support | +| ☑ Sign-extension operators | ☑ Wasm and WASI self-hosting | +| ☑ Multi-value | ☑ Gas metering | +| ☑ Bulk memory operations (partial support) | ☑ Linear memory limit (< 64KiB) | +| ☐ Multiple memories | +| ☐ Reference types | +| ☐ Tail call optimization | +| ☐ Fixed-width SIMD | +| ☐ Exception handling | + +## Motivation + +**Why use a "slow interpreter" versus a "fast JIT"?** + +In many situations, speed is not the main concern. Runtime executable size, memory usage, startup latency can be improved with the interpreter approach. Portability and security are much easier to achieve and maintain. Additionally, development impedance is much lower. A simple library like Wasm3 is easy to compile and integrate into an existing project. (Wasm3 builds in a just few seconds). Finally, on some platforms (i.e. iOS and WebAssembly itself) you can't generate executable code pages in runtime, so JIT is unavailable. + +**Why would you want to run WASM on embedded devices?** + +Wasm3 started as a research project and remains so by many means. Evaluating the engine in different environments is part of the research. Given that we have `Lua`, `JS`, `Python`, `Lisp`, `...` running on MCUs, `WebAssembly` is actually a promising alternative. It provides toolchain decoupling as well as a completely sandboxed, well-defined, predictable environment. Among practical use cases we can list `edge computing`, `scripting`, `plugin systems`, running `IoT rules`, `smart contracts`, etc. + +## Used by + +[](https://wasmcloud.dev/)  +[](https://wowcube.com/)  +[](https://scailable.net/)  +[](https://blynk.io/)  +[](https://www.iden3.io/)  +[](https://github.com/kateinoigakukun/wasmic-ios)  +[](https://github.com/balena-io-playground/balena-wasm3)  +[](https://github.com/deislabs/krustlet-wasm3)  +[](https://shareup.app/blog/introducing-shareup/) + +## Further Resources + +[Demos](./docs/Demos.md) +[Installation instructions](./docs/Installation.md) +[Cookbook](./docs/Cookbook.md) +[Troubleshooting](./docs/Troubleshooting.md) +[Build and Development instructions](./docs/Development.md) +[Supported Hardware](./docs/Hardware.md) +[Testing & Fuzzing](./docs/Testing.md) +[Performance](./docs/Performance.md) +[Interpreter Architecture](./docs/Interpreter.md) +[Logging](./docs/Diagnostics.md) +[Awesome WebAssembly Tools](https://github.com/vshymanskyy/awesome-wasm-tools/blob/main/README.md) + +### License +This project is released under The MIT License (MIT) + + +[WasmProps]: https://github.com/WebAssembly/proposals/blob/master/finished-proposals.md "WebAssembly Finished Proposals" diff --git a/ext/wasm3/docs/Cookbook.md b/ext/wasm3/docs/Cookbook.md new file mode 100644 index 0000000..ba53fa6 --- /dev/null +++ b/ext/wasm3/docs/Cookbook.md @@ -0,0 +1,462 @@ +# WASM module examples + +### Rust WASI app + +Create a new project: +```sh +$ cargo new --bin hello +$ cd hello +$ rustup target add wasm32-wasi +``` + +Build and run: +```sh +$ cargo build --release --target wasm32-wasi + +$ wasm3 ./target/wasm32-wasi/release/hello.wasm +Hello, world! +``` + +### AssemblyScript WASI app + +Create `hello.ts`: +```ts +import "wasi" +import {Console} from "as-wasi" + +Console.log('Hello World!'); +``` + +Create `package.json`: +```json +{ + "scripts": { + "asbuild:debug": "asc hello.ts -b hello.wasm --debug", + "asbuild:optimized": "asc hello.ts -b hello.wasm -O3s --noAssert", + "asbuild:tiny": "asc hello.ts -b hello.wasm -O3z --noAssert --runtime stub --use abort=", + "build": "npm run asbuild:optimized" + }, + "devDependencies": { + "assemblyscript": "*", + "as-wasi": "*" + } +} +``` + +Build and run: +```sh +$ npm install +$ npm run build + +$ wasm3 hello.wasm +Hello World! +``` + +### TinyGo WASI app + +Create `hello.go`: +```go +package main + +import "fmt" + +func main() { + fmt.Printf("Hello, %s!\n", "world") +} +``` + +Build and run: +```sh +$ tinygo build -o hello.wasm -target wasi -no-debug hello.go + +$ wasm3 hello.wasm +Hello, world! +``` + + +### Go WASI app + +Go currently does not provide the WASI interface. +For reference see [this issue](https://github.com/golang/go/issues/31105). + + +### Zig WASI app + +Create `hello.zig`: +```zig +const std = @import("std"); + +pub fn main() !void { + const stdout = std.io.getStdOut().writer(); + try stdout.print("Hello, {s}!\n", .{"world"}); +} +``` + +Build and run: +```sh +$ zig build-exe -O ReleaseSmall -target wasm32-wasi hello.zig + +$ wasm3 hello.wasm +Hello, world! +``` + +### Zig C-code WASI app + +Create `hello.c`: +```c +#include + +int main() { + printf("Hello, %s!\n", "world"); + return 0; +} +``` + +Build and run: +```sh +$ zig build-exe -O ReleaseSmall -target wasm32-wasi hello.c -lc + +$ wasm3 hello.wasm +Hello, world! +``` + +## Zig library + +Create `add.zig`: +```zig +export fn add(a: i32, b: i32) i64 { + return a + b; +} +``` + +Build and run: +```sh +$ zig build-lib add.zig -O ReleaseSmall -target wasm32-freestanding + +$ wasm3 --repl add.wasm +wasm3> add 1 2 +Result: 3 +``` + +### C/C++ WASI app + +The easiest way to start is to use [Wasienv](https://github.com/wasienv/wasienv). + +Create `hello.cpp`: +```cpp +#include + +int main() { + std::cout << "Hello, world!" << std::endl; + return 0; +} +``` + +Or `hello.c`: +```c +#include + +int main() { + printf("Hello, %s!\n", "world"); + return 0; +} +``` + +Build and run: +```sh +$ wasic++ -O3 hello.cpp -o hello.wasm +$ wasicc -O3 hello.c -o hello.wasm + +$ wasm3 hello.wasm +Hello World! +``` + +Useful `clang` options: + +- **-nostdlib** Do not use the standard system startup files or libraries when linking + +- **-Wl,--no-entry** Do not output any entry point + +- **-Wl,--export=\** Force a symbol to be exported, e.g. **-Wl,--export=foo** to export foo function + +- **-Wl,--export-all** Export all symbols (normally combined with --no-gc-sections) + +- **-Wl,--initial-memory=\** Initial size of the linear memory, which must be a multiple of 65536 + +- **-Wl,--max-memory=\** Maximum size of the linear memory, which must be a multiple of 65536 + +- **-z stack-size=\** The auxiliary stack size, which is an area of linear memory, and must be smaller than initial memory size. + +- **-Wl,--strip-all** Strip all symbols + +- **-Wl,--shared-memory** Use shared linear memory + +- **-Wl,--allow-undefined** Allow undefined symbols in linked binary + +- **-Wl,--allow-undefined-file=\** Allow symbols listed in \ to be undefined in linked binary + +- **-pthread** Support POSIX threads in generated code + +Limitations: +- `setjmp/longjmp` and `C++ exceptions` are not available +- no support for `threads` and `atomics` +- no support for `dynamic libraries` + +### Grain WASI app + +Create `hello.gr`: +``` +print("Hello, world!") +``` + +Build and run: +```sh +$ grain compile hello.gr -o hello.wasm + +$ wasm3 hello.wasm +Hello, world! +``` + +### WAT WASI app + +Create `hello.wat`: +```wat +(module + ;; wasi_snapshot_preview1!fd_write(file_descriptor, *iovs, iovs_len, nwritten) -> status_code + (import "wasi_snapshot_preview1" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32))) + + (memory 1) + (export "memory" (memory 0)) + + ;; Put a message to linear memory at offset 32 + (data (i32.const 32) "Hello, world!\n") + + (func $main (export "_start") + ;; Create a new io vector at address 0x4 + (i32.store (i32.const 4) (i32.const 32)) ;; iov.iov_base - pointer to the start of the message + (i32.store (i32.const 8) (i32.const 14)) ;; iov.iov_len - length of the message + + (call $fd_write + (i32.const 1) ;; file_descriptor - 1 for stdout + (i32.const 4) ;; *iovs - pointer to the io vector + (i32.const 1) ;; iovs_len - count of items in io vector + (i32.const 20) ;; nwritten - where to store the number of bytes written + ) + drop ;; discard the WASI status code + ) +) +``` + + +Build and run: +```sh +$ wat2wasm hello.wat -o hello.wasm + +$ wasm3 hello.wasm +Hello, world! +``` + +### WAT library + +Create `swap.wat`: +```wat +(module + (func (export "swap") (param i32 i32) (result i32 i32) + (get_local 1) + (get_local 0) + ) +) +``` + +Build and run: +```sh +$ wat2wasm swap.wat -o swap.wasm + +$ wasm3 --repl swap.wasm +wasm3> :invoke swap 123 456 +Result: 456:i32, 123:i32 +``` + +# Tracing + +Drag'n'drop any of the WASI apps to [`WebAssembly.sh`](https://webassembly.sh/) and run: +```sh +$ wasm3-strace /tmp/hello.wasm +``` + +The execution trace will be produced: +```js +_start () { + __wasilibc_init_preopen () { + malloc (i32: 16) { + dlmalloc (i32: 16) { + sbrk (i32: 0) { + } = 131072 + sbrk (i32: 65536) { +``` +
+ Click to expand! + +```js + } = 131072 + } = 131088 + } = 131088 + calloc (i32: 24, i32: 0) { + dlmalloc (i32: 96) { + } = 131120 + memset (i32: 131120, i32: 65504, i32: 0) { + } = 131120 + } = 131120 + po_map_assertvalid (i32: 131088) { + } + po_map_assertvalid (i32: 131088) { + } + } + wasi_unstable!fd_prestat_get(3, 65528) { } = 0 + malloc (i32: 2) { + dlmalloc (i32: 2) { + } = 131232 + } = 131232 + wasi_unstable!fd_prestat_dir_name(3, 131232, 1) { } = 0 + __wasilibc_register_preopened_fd (i32: 3, i32: 131120) { + po_map_assertvalid (i32: 131088) { + } + po_map_assertvalid (i32: 131088) { + } + strdup (i32: 131232) { + strlen (i32: 131232) { + } = 1 + malloc (i32: 2) { + dlmalloc (i32: 2) { + } = 131248 + } = 131248 + memcpy (i32: 131248, i32: 131233, i32: 131232) { + } = 131248 + } = 131248 + wasi_unstable!fd_fdstat_get(3, 65496) { } = 0 + po_map_assertvalid (i32: 131088) { + } + po_map_assertvalid (i32: 131088) { + } + } = 0 + free (i32: 131232) { + dlfree (i32: 131232) { + } + } + wasi_unstable!fd_prestat_get(4, 65528) { } = 0 + malloc (i32: 2) { + dlmalloc (i32: 2) { + } = 131232 + } = 131232 + wasi_unstable!fd_prestat_dir_name(4, 131232, 1) { } = 0 + __wasilibc_register_preopened_fd (i32: 4, i32: 131120) { + po_map_assertvalid (i32: 131088) { + } + po_map_assertvalid (i32: 131088) { + } + strdup (i32: 131232) { + strlen (i32: 131232) { + } = 1 + malloc (i32: 2) { + dlmalloc (i32: 2) { + } = 131264 + } = 131264 + memcpy (i32: 131264, i32: 131233, i32: 131232) { + } = 131264 + } = 131264 + wasi_unstable!fd_fdstat_get(4, 65496) { } = 0 + po_map_assertvalid (i32: 131088) { + } + po_map_assertvalid (i32: 131088) { + } + } = 0 + free (i32: 131232) { + dlfree (i32: 131232) { + } + } + wasi_unstable!fd_prestat_get(5, 65528) { } = 8 + __wasm_call_ctors () { + } + __original_main () { + printf (i32: 65536, i32: 0) { + vfprintf (i32: 69512, i32: 0, i32: 65536) { + printf_core (i32: 0, i32: -1, i32: 65536, i32: -16, i32: 65480) { + } = 0 + __towrite (i32: 69512) { + } = 0 + printf_core (i32: 69512, i32: 8, i32: 65536, i32: -1, i32: 65480) { + __fwritex (i32: 65536, i32: 0, i32: 7) { + memcpy (i32: 68472, i32: 0, i32: 65536) { + } = 68472 + } = 7 + __fwritex (i32: 65543, i32: 0, i32: 0) { + memcpy (i32: 68479, i32: 0, i32: 65543) { + } = 68479 + } = 0 + pop_arg (i32: 64456, i32: 0, i32: 9) { + } + strnlen (i32: 65548, i32: 0) { + memchr (i32: 65548, i32: 4, i32: 0) { + } = 65553 + } = 5 + __fwritex (i32: 67222, i32: 65553, i32: 0) { + memcpy (i32: 68479, i32: 0, i32: 67222) { + } = 68479 + } = 0 + __fwritex (i32: 65548, i32: 65553, i32: 5) { + memcpy (i32: 68479, i32: 0, i32: 65548) { + } = 68479 + } = 5 + __fwritex (i32: 65545, i32: 0, i32: 2) { + __stdout_write (i32: 69512, i32: 0, i32: 65545) { + __isatty (i32: 1) { + wasi_unstable!fd_fdstat_get(1, 64376) { } = 0 + } = 1 + __stdio_write (i32: 69512, i32: 64368, i32: 65545) { + writev (i32: 1, i32: -16, i32: 64384) { +Hello, world! + wasi_unstable!fd_write(1, 64384, 2, 64380) { } = 0 + } = 14 + } = 2 + } = 2 + memcpy (i32: 68472, i32: -1, i32: 65547) { + } = 68472 + } = 2 + } = 14 + } = 14 + } = 14 + } = 0 + __prepare_for_exit () { + dummy () { + } + __stdio_exit () { + __ofl_lock () { + } = 69504 + } + } +} +``` +
+ +# Gas Metering + +```sh +$ npm install -g wasm-metering + +$ wasm-meter hello.wasm hello-metered.wasm + +$ wasm3 hello-metered.wasm +Warning: Gas is limited to 500000000.0000 +Hello, world! +Gas used: 20.8950 + +$ wasm3 --gas-limit 10 hello-metered.wasm +Warning: Gas is limited to 10.0000 +Gas used: 10.0309 +Error: [trap] Out of gas +``` + +# Other resources + +- [WebAssembly by examples](https://wasmbyexample.dev/home.en-us.html) by Aaron Turner +- [Writing WebAssembly](https://docs.wasmtime.dev/wasm.html) in Wasmtime docs diff --git a/ext/wasm3/docs/Demos.md b/ext/wasm3/docs/Demos.md new file mode 100644 index 0000000..d982c1b --- /dev/null +++ b/ext/wasm3/docs/Demos.md @@ -0,0 +1,17 @@ +# Wasm3 demos + +- **In-browser Wasm3 (with MetaWASI support) on Webassembly.sh** │ [try it](https://webassembly.sh/?run-command=wasm3) +- **PyGame + pywasm3 examples** | [github](https://github.com/wasm3/pywasm3/tree/main/examples) +- **DOOM compiled to WASI, running on pywasm3** | [video](https://twitter.com/wasm3_engine/status/1393588527863144450), [github](https://github.com/wasm3/pywasm3-doom-demo) +- **WebAssembly On Your Nintendo DS** | [blog](https://softwayre.com/blog/2021/09/13/webassembly-on-your-nintendo-ds), [github](https://github.com/moxon6/snake-assemblyscript-ds) +- **Each pixel on this ESP32 board is controlled by a different WebAssembly app** | [video](https://twitter.com/zubr_kabbi/status/1436833749359017985), [github](https://github.com/kabbi/m5-atom-wasms) +- **Wasm3 self-compilation using `clang.wasm`** | [github](https://github.com/wasm3/wasm3-self-compiling) +- **Dino game** + - on PyBadge/Arduino | [video](https://twitter.com/vshymanskyy/status/1345048053041029121), [github](https://github.com/wasm3/wasm3-arduino/tree/main/examples/Wasm_Dino_PyBadge) + - on Raspberry Pi Pico | [github](https://github.com/vshymanskyy/wasm3_dino_rpi_pico) + - on ESP32 TTGO TDisplay | [github](https://github.com/wasm3/wasm3-arduino/tree/main/examples/Wasm_Dino_ESP32_TDisplay) +- **Basic WiFi/Gpio access, updating `wasm` file over-the-air** │ [video](https://twitter.com/alvaroviebrantz/status/1221618910803513344), [github](https://github.com/alvarowolfx/wasm-arduino-wifi) [ESP32 / Web] +- **RGB lamp animation using WebAssembly** │ [video](https://twitter.com/wasm3_engine/status/1222835097289752576), [github](https://github.com/vshymanskyy/Wasm3_RGB_Lamp) [nRF51 / nRF52 / ESP8266 / ESP32] +- **LCD display rendering with AssemblyScript** │ [video](https://twitter.com/h1romas4/status/1228581467850100736), [github](https://github.com/h1romas4/m5stack-wasm3-testing) [M5Stack / ESP32] +- **Conway's Game Of Life with AssemblyScript** │ [video](https://www.youtube.com/watch?v=Hc2sbhGMrig), [github](https://github.com/h1romas4/maixduino-wasm3-testing) [Maixduino / K210] + diff --git a/ext/wasm3/docs/Development.md b/ext/wasm3/docs/Development.md new file mode 100644 index 0000000..3cce0dd --- /dev/null +++ b/ext/wasm3/docs/Development.md @@ -0,0 +1,181 @@ +# Wasm3 development notes + +This project uses CMake. +General build steps look like: +```sh +mkdir -p build +cd build +cmake .. +make -j8 +``` + +Wasm3 is continuously tested with Clang, GCC, MSVC compilers, and on multiple platforms. +It can be easily integrated into any build system, as shown in `platforms`. + +## Build on Linux, OS X + +### Clang + +```sh +mkdir build +cd build +cmake -GNinja -DCLANG_SUFFIX="-12" .. +ninja +``` + +### GCC + +```sh +mkdir build +cd build +cmake -GNinja .. +ninja +``` + +## Build on Windows + +Prerequisites: +- [Build Tools for Visual Studio 2019](https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019) +- [CMake](https://cmake.org/download/) +- [Ninja](https://github.com/ninja-build/ninja/releases) +- [Clang 9](https://releases.llvm.org/download.html#9.0.0) + +Recommended tools: +- [Cmder](https://cmder.net/) +- [Python3](https://www.python.org/downloads/) +- [ptime](http://www.pc-tools.net/win32/ptime/) + +```sh +# Prepare environment (if needed): +"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvars64.bat" +set PATH=C:\Python36-32\;C:\Python36-32\Scripts\;%PATH% +``` + +### Build with MSBuild + +```sh +# Create a build directory as usual, then build a specific configuration +mkdir build +cd build + +# Configure Clang, x64 +cmake -G"Visual Studio 16 2019" -A x64 -T ClangCL .. + +# Configure Clang, x86 +cmake -G"Visual Studio 16 2019" -A Win32 -T ClangCL .. + +# Configure MSVC, x64 +cmake -G"Visual Studio 16 2019" -A x64 .. + +# Configure MSVC, x86 +cmake -G"Visual Studio 16 2019" -A Win32 .. + +# Build +cmake --build . --config Release +cp ./Release/wasm3.exe ./ +``` + +### Build with Ninja + +```sh +set PATH=C:\Program Files\CMake\bin;%PATH% +set PATH=C:\Program Files\LLVM\bin;%PATH% + +# Clang +cmake -GNinja -DCLANG_CL=1 .. +ninja + +# MSVC +cmake -GNinja .. +ninja +``` + +## Build using compiler directly + +This can be useful for cross-compilation, quick builds or when a build system (CMake, Ninja, etc.) is not available. + +### gcc/clang +```sh +gcc -O3 -g0 -s -Isource -Dd_m3HasWASI source/*.c platforms/app/main.c -lm -o wasm3 +``` + +### msvc/clang-cl +```sh +cl source/*.c platforms/app/main.c /Isource /MD /Ox /Oy /Gw /GS- /W0 /Dd_m3HasWASI /Fewasm3.exe /link advapi32.lib +``` + +### mingw-w64 +```sh +x86_64-w64-mingw32-gcc -O3 -g0 -s -Isource -Dd_m3HasWASI source/*.c platforms/app/main.c -lm -lpthread -static -o wasm3.exe +``` + +## Build for microcontrollers + +In `./platforms/` folder you can find projects for different targets. Some of them are using Platformio, so you can follow the regular pio build process. Others have custom instructions in respective `README.md` files. + +## Build with WasiEnv + +```sh +wasimake cmake -GNinja .. +ninja +``` + +If you want to enable experimental WASM features during the build: + +```sh +export CFLAGS="-Xclang -target-feature -Xclang +tail-call" +wasimake cmake -GNinja .. +ninja +``` + +Here's how some options can be used with different tools: + +```log +Clang target-feature option WABT option Chromium --js-flags option +---------------------------------------------------------------------------------------------------------------- ++multivalue --enable-multi-value --experimental-wasm-mv ++tail-call --enable-tail-call --experimental-wasm-return-call ++bulk-memory --enable-bulk-memory --experimental-wasm-bulk-memory ++nontrapping-fptoint --enable-saturating-float-to-int --experimental-wasm-sat-f2i-conversions ++sign-ext --enable-sign-extension --experimental-wasm-se ++simd128, +unimplemented-simd128 --enable-simd --experimental-wasm-simd +``` + +```sh +# List clang options: +llc -march=wasm32 -mattr=help + +# List Chromium options: +chromium-browser --single-process --js-flags="--help" 2>&1 | grep wasm +``` + +## Build with Zig + +Grab the latest nightly Zig toolchain from [ziglang.org/download], and then simply run: + +[ziglang.org/download]: https://ziglang.org/download/ + +```sh +zig build +``` + +This will install `wasm3` compiled for your target architecture in `zig-out/bin/wasm3`. + +In order to build `wasm3` in a mode different than Debug, e.g., in ReleaseFast, pass in +an appropriate flag like so: + +```sh +zig build -Drelease-fast +``` + +If you want to cross-compile to some specific target, pass in the target with a flag like so: + +```sh +zig build -Dtarget=wasm32-wasi +``` + +Or if targeting Apple Silicon (this works from *any* host with Zig): + +```sh +zig build -Dtarget=aarch64-macos +``` diff --git a/ext/wasm3/docs/Diagnostics.md b/ext/wasm3/docs/Diagnostics.md new file mode 100644 index 0000000..5f9b947 --- /dev/null +++ b/ext/wasm3/docs/Diagnostics.md @@ -0,0 +1,57 @@ + +## Logs + +To enable various logs, modify the defines in `m3_config.h`. These are only enabled when compiled in debug mode. + +```C +# define d_m3LogParse 0 // .wasm binary decoding info +# define d_m3LogModule 0 // Wasm module info +# define d_m3LogCompile 0 // wasm -> metacode generation phase +# define d_m3LogWasmStack 0 // dump the wasm stack when pushed or popped +# define d_m3LogEmit 0 // metacode-generation info +# define d_m3LogCodePages 0 // dump metacode pages when released +# define d_m3LogRuntime 0 // higher-level runtime information +# define d_m3LogNativeStack 0 // track the memory usage of the C-stack +``` + + +## Operation Profiling + +To profile the interpreter's operations enable `d_m3EnableOpProfiling` in `m3_config.h`. This profiling option works in either release or debug builds. + +When a runtime is released or `m3_PrintProfilerInfo ()` is called, a table of the executed operations and +their instance counts will be printed to stderr. + +``` + 23199904 op_SetSlot_i32 + 12203917 op_i32_Add_ss + 6682992 op_u32_GreaterThan_sr + 2021555 op_u32_ShiftLeft_sr + 1136577 op_u32_ShiftLeft_ss + 1019725 op_CopySlot_32 + 775431 op_i32_Subtract_ss + 703307 op_i32_Store_i32_rs + 337656 op_i32_Multiply_rs + 146383 op_u32_Or_rs + 99168 op_u64_Or_rs + 50311 op_u32_ShiftRight_rs + 43319 op_u32_ShiftLeft_rs + 21104 op_i64_Load_i64_s + 17450 op_i32_LessThan_sr + 7129 op_If_s + 5574 op_i32_Wrap_i64_r + 1630 op_f64_Load_f64_r + 1116 op_u32_Divide_sr + 903 op_i32_GreaterThan_ss + 390 op_u64_And_rs + 108 op_Select_f64_rss + 77 op_u64_ShiftLeft_sr + 64 op_Select_i32_ssr + 11 op_f64_Store_f64_ss + 10 op_MemGrow + 8 op_f64_GreaterThan_sr + 4 op_u64_LessThan_rs + 1 op_u32_Xor_ss + 1 op_i64_Subtract_ss +``` + diff --git a/ext/wasm3/docs/Hardware.md b/ext/wasm3/docs/Hardware.md new file mode 100644 index 0000000..498224d --- /dev/null +++ b/ext/wasm3/docs/Hardware.md @@ -0,0 +1,60 @@ +# Wasm3 hardware support + +## Recommended devices (ideal for beginners) + +- ESP32-based + - **LilyGO TTGO T7 V1.4** │ [AliExpress](https://www.aliexpress.com/item/32977375539.html) + - **M5Stack Fire** │ [AliExpress](https://www.aliexpress.com/item/32847906756.html) +- nRF52840-based + - **Adafruit CLUE** │ [Adafruit](https://www.adafruit.com/clue) + - **Arduino Nano 33 BLE (or BLE Sense)** │ [Arduino](https://store.arduino.cc/arduino-nano-33-ble) + - **Particle Argon** │ [Particle](https://store.particle.io/collections/bluetooth/products/argon) + - **Adafruit Feather nRF52840** | [Adafruit](https://www.adafruit.com/product/4062) +- Other + - **Raspberry Pi Pico** | [Raspberry Pi](https://www.raspberrypi.org/products/raspberry-pi-pico) + - **Adafruit PyGamer/PyBadge/PyBadge LC** │ [Adafruit](https://www.adafruit.com/product/4242) + - **SparkFun Artemis** | [SparkFun](https://www.sparkfun.com/search/results?term=Artemis) + - **Teensy 4.0** │ [PJRC](https://www.pjrc.com/store/teensy40.html) + - **Wemos W600 PICO** │ [AliExpress](https://www.aliexpress.com/item/4000314757449.html) + +## Compatibility table + +Device | Chipset | Architecture | Clock | Flash | RAM +--- |:---: | --- | -----:| --- | --- +Espressif ESP32 | | Xtensa LX6 ⚠️ | 240MHz | 4 MB | 520KB +Particle Argon, Boron, Xenon | nRF52840 | Cortex-M4F | 64MHz | 1 MB | 256KB +Particle Photon, Electron | STM32F205 | Cortex-M3 | 120Mhz | 1 MB | 128KB +Sparkfun Photon RedBoard | STM32F205 | Cortex-M3 | 120Mhz | 1 MB | 128KB +Air602 | WM W600 | Cortex-M3 | 80MHz | 1 MB | 160KB+128KB +Adafruit PyBadge | ATSAMD51J19 | Cortex-M4F | 120MHz | 512KB | 192KB +Realtek RTL8711 | | Cortex-M3 | 166MHz | 2 MB | 2 MB+512KB +Nordic nRF52840 | | Cortex-M4F | 64MHz | 1 MB | 256KB +Nordic nRF52833 | | Cortex-M4F | 64MHz | 512KB | 128KB +P-Nucleo WB55RG | STM32WB55RG | Cortex-M4F | 64MHz | 1 MB | 256KB +Teensy 4.0 | NXP iMXRT1062 | Cortex-M7 | 600MHz | 2 MB | 1 MB +Teensy 3.5 | MK64FX512 | Cortex-M4F | 120MHz | 512KB | 192KB +MXChip AZ3166 | EMW3166 | Cortex-M4 | 100MHz | 1 MB+2 MB | 256KB +Arduino Due | AT91SAM3X8E | Cortex-M3 | 84MHz | 512KB | 96KB +Sipeed MAIX | Kendryte K210 | RV64IMAFDC | 400MHz | 16 MB | 8 MB +Fomu (soft CPU) | Lattice ICE40UP5K | RV32I | 12MHz | 2 MB | 128KB + +## Limited support + +The following devices can run Wasm3, however they cannot afford to allocate even a single Linear Memory page (64KB). +This means `memoryLimit` should be set to the actual amount of RAM available, and that in turn usually breaks the allocator of the hosted Wasm application (which still assumes the page is 64KB and performs OOB access). + +Device | Chipset | Architecture | Clock | Flash | RAM +--- |:---: | --- | -----:| --- | --- +Espressif ESP8266 | | Xtensa L106 ⚠️ | 160MHz | 4 MB | ~50KB (available) +Teensy 3.1/3.2 | NXP MK20DX256 | Cortex-M4 | 72MHz | 288KB | 64KB +Blue Pill | STM32F103 | Cortex-M3 | 72MHz | 64KB | 20KB +Arduino MKR* | SAMD21 | Cortex-M0+ ⚠️ | 48MHz | 256KB | 32KB +Arduino 101 | Intel Curie | ARC32 | 32MHz | 196KB | 24KB +SiFive HiFive1 | Freedom E310 | RV32IMAC | 320MHz | 16 MB | 16KB +Nordic nRF52832 | | Cortex-M4F | 64MHz | 256/512KB | 32/64KB +Nordic nRF51822 | | Cortex-M0 ⚠️ | 16MHz | 128/256KB | 16/32KB +Wicked Device WildFire | ATmega1284 | 8-bit AVR ⚠️ | 20MHz | 128KB | 16KB + +### Legend: + ⚠️ This architecture/compiler currently fails to perform TCO (Tail Call Optimization/Elimination), which leads to sub-optimal interpreter behaviour (intense native stack usage, lower performance). +There are plans to improve this in future 🦄. diff --git a/ext/wasm3/docs/Installation.md b/ext/wasm3/docs/Installation.md new file mode 100644 index 0000000..651cdf3 --- /dev/null +++ b/ext/wasm3/docs/Installation.md @@ -0,0 +1,26 @@ +# Wasm3 installation + +## Windows +Download `wasm3-win-x64.exe` or `wasm3-win-x86.exe` from the [latest release page](https://github.com/wasm3/wasm3/releases/latest). + +## macOS +Use [Homebrew](https://brew.sh) to build and install automatically: +```sh +brew install wasm3 +``` + +## Cosmopolitan / Actually Portable Executable +[APE](https://justine.lol/cosmopolitan/index.html) is a polyglot format that runs natively on Linux + Mac + Windows + FreeBSD + OpenBSD + NetBSD + BIOS. +Download `wasm3-cosmopolitan.com` from the [latest release page](https://github.com/wasm3/wasm3/releases/latest) + +## OpenWRT +Follow instructions [here](https://github.com/wasm3/wasm3-openwrt-packages). + +## Arduino / PlatformIO / Particle.io library +Find `Wasm3` in the `Library Manager` and install it. + +## Python module +```sh +pip3 install pywasm3 +``` + diff --git a/ext/wasm3/docs/Interpreter.md b/ext/wasm3/docs/Interpreter.md new file mode 100644 index 0000000..67f2688 --- /dev/null +++ b/ext/wasm3/docs/Interpreter.md @@ -0,0 +1,166 @@ +# M3 + +This is a WebAssembly interpreter written in C using a novel, high performance interpreter topology. The interpreter strategy (named M3) was developed prior to this particular Wasm project and is described some below. + +## Purpose + +I don't know. I just woke up one day and started hacking this out after realizing my interpreter was well suited for the Wasm bytecode structure. Some ideas: + +* It could be useful for embedded systems. +* It might be a good start-up, pre-JIT interpreter in a more complex Wasm compiler system. +* It could serve as a Wasm validation library. +* The interpreter topology might be inspiring to others. + + +## Benchmarks + +It's at least fleshed out enough to run some simple benchmarks. + +Tested on a 4 GHz Intel Core i7 iMac (Retina 5K, 27-inch, Late 2014). M3 was compiled with Clang -Os. C benchmarks were compiled with gcc with -O3 + +### Mandelbrot + +C code lifted from: https://github.com/ColinEberhardt/wasm-mandelbrot + +|Interpreter|Execution Time|Relative to GCC| | +|-----------|--------------|---------------|----| +|Life |547 s |133 x | https://github.com/perlin-network/life +|Lua |122 s |30 x | This isn't Lua running some weird Wasm transcoding; a manual Lua conversion of the C benchmark as an additional reference point. +|M3 |17.9 s |4.4 x | (3.7 x on my 2016 MacBook Pro) +|GCC |4.1 s | | + +### CRC32 + +|Interpreter|Execution Time|Relative to GCC| +|-----------|--------------|---------------| +|Life |153 s |254 x | +|M3 |5.1 s |8.5 x | +|GCC |600 ms | | + + +In general, the M3 strategy seems capable of executing code around 4-15X slower than compiled code on a modern x86 processor. (Older CPUs don't fare as well. I suspect branch predictor differences.) I have yet to test on anything ARM. + +## M3: Massey Meta Machine + +Over the years, I've mucked around with creating my own personal programming language. It's called Gestalt. The yet unreleased repository will be here: https://github.com/soundandform/gestalt + +Early on I decided I needed an efficient interpreter to achieve the instant-feedback, live-coding environment I desire. Deep traditional compilation is too slow and totally unnecessary during development. And, most importantly, compilation latency destroys creative flow. + +I briefly considered retooling something extant. The Lua virtual machine, one of the faster interpreters, is too Lua centric. And everything else is too slow. + +I've also always felt that the "spin in a loop around a giant switch statement" thing most interpreters do was clumsy and boring. My intuition said there was something more elegant to be found. + +The structure that emerged I named a "meta machine" since it mirrors the execution of compiled code much more closely than the switch-based virtual machine. + +I set out with a goal of approximating Lua's performance. But this interpreter appears to beat Lua by 3X and more on basic benchmarks -- whatever they're worth! + +### How it works + +This rough information might not be immediately intelligible without referencing the source code. + +#### Reduce bytecode decoding overhead + +* Bytecode/opcodes are translated into more efficient "operations" during a compilation pass, generating pages of meta-machine code + * M3 trades some space for time. Opcodes map to up to 3 different operations depending on the number of source operands and commutative-ness. +* Commonly occurring sequences of operations can can also be optimized into a "fused" operation. This *sometimes* results in improved performance. + * the modern CPU pipeline is a mysterious beast +* In M3/Wasm, the stack machine model is translated into a more direct and efficient "register file" approach. + +#### Tightly Chained Operations + +* M3 operations are C functions with a single, fixed function signature. + + ```C + void * Operation_Whatever (pc_t pc, u64 * sp, u8 * mem, reg_t r0, f64 fp0); + ``` + +* The arguments of the operation are the M3's virtual machine registers + * program counter, stack pointer, etc. +* The return argument is a trap/exception and program flow control signal +* The M3 program code is traversed by each operation calling the next. The operations themselves drive execution forward. There is no outer control structure. + * Because operations end with a call to the next function, the C compiler will tail-call optimize most operations. +* Finally, note that x86/ARM calling conventions pass initial arguments through registers, and the indirect jumps between operations are branch predicted. + +#### The End Result + +Since operations all have a standardized signature and arguments are tail-call passed through to the next, the M3 "virtual" machine registers end up mapping directly to real CPU registers. It's not virtual! Instead, it's a meta machine with very low execution impedance. + +|M3 Register |x86 Register| +|-----------------------------|------------| +|program counter (pc) |rdi | +|stack pointer (sp) |rsi | +|linear memory (mem) |rdx | +|integer register (r0) |rcx | +|floating-point register (fp0)|xmm0 | + + +For example, here's a bitwise-or operation in the M3 compiled on x86. + +```assembly +m3`op_u64_Or_sr: + 0x1000062c0 <+0>: movslq (%rdi), %rax ; load operand stack offset + 0x1000062c3 <+3>: orq (%rsi,%rax,8), %rcx ; or r0 with stack operand + 0x1000062c7 <+7>: movq 0x8(%rdi), %rax ; fetch next operation + 0x1000062cb <+11>: addq $0x10, %rdi ; increment program counter + 0x1000062cf <+15>: jmpq *%rax ; jump to next operation +``` + + +#### Registers and Operational Complexity + +* The conventional Windows calling convention isn't compatible with M3, as-is, since it only passes 4 arguments through registers. Applying the vectorcall calling convention (https://docs.microsoft.com/en-us/cpp/cpp/vectorcall) resolves this problem. + +* It's possible to use more CPU registers. For example, adding an additional floating-point register to the meta-machine did marginally increase performance in prior tests. However, the operation space increases exponentially. With one register, there are up to 3 operations per opcode (e.g. a non-commutative math operation). Adding another register increases the operation count to 10. However, as you can see above, operations tend to be tiny. + +#### Stack Usage + +* Looking at the above assembly code, you'll notice that once an M3 operation is optimized, it doesn't need the regular stack (no mucking with the ebp/esp registers). This is the case for 90% of the opcodes. Branching and call operations do require stack variables. Therefore, execution can't march forward indefinitely; the stack would eventually overflow. + + Therefore, loops unwind the stack. When a loop is continued, the Continue operation returns, unwinding the stack. Its return value is a pointer to the loop opcode it wants to unwind to. The Loop operations checks for its pointer and responds appropriately, either calling back into the loop code or returning the loop pointer back down the call stack. + +* Traps/Exceptions work similarly. A trap pointer is returned from the trap operation which has the effect of unwinding the entire stack. + +* Returning from a Wasm function also unwinds the stack, back to the point of the Call operation. + +* But, because M3 execution leans heavily on the native stack, this does create one runtime usage issue. + + A conventional interpreter can save its state, break out of its processing loop and return program control to the client code. This is not the case in M3 since the C stack might be wound up in a loop for long periods of time. + + With Gestalt, I resolved this problem with fibers (built with Boost Context). M3 execution occurs in a fiber so that control can effortlessly switch to the "main" fiber. No explicit saving of state is necessary since that's the whole purpose of a fiber. + + More simplistically, the interpreter runtime can also periodically call back to the client (in the either the Loop or LoopContinue operation). This is necessary, regardless, to detect hangs and break out of infinite loops. + + +## The M3 strategy for other languages (is rad) + +The Gestalt M3 interpreter works slightly differently than this Wasm version. With Gestalt, blocks of all kind (if/else/try), not just loops, unwind the native stack. (This somewhat degrades raw x86 performance.) + +But, this adds a really beautiful property to the interpreter. The lexical scoping of a block in the language source code maps directly into the interpreter. All opcodes/operations end up having an optional prologue/epilogue structure. This made things like reference-counting objects in Gestalt effortless. Without this property, the compiler itself would have to track scope and insert dererence opcodes intentionally. Instead, the "CreateObject" operation is also the "DestroyObject" operation on the exit/return pathway. + +Here's some pseudocode to make this more concrete: + +``` +return_t Operation_NewObject (registers...) +{ + Object o = runtime->CreateObject (registers...); + + * stack [index] = o; + + return_t r = CallNextOperation (registers...); // executes to the end of the scope/block/curly-brace & returns + + if (o->ReferenceCount () == 0) + runtime->DestroyObject (registers..., o); // calls o's destructor and frees memory + + return r; +} +``` + +Likewise, a "defer" function (like in Go) becomes absolutely effortless to implement. Exceptions (try/catch) as well. + + +## Prior Art + +After the Wasm3 project was posted to Hacker News (https://news.ycombinator.com/item?id=22024758), I finally discovered precedent for this tail-call interpreter design. It has previously been called "threaded code". See the "Continuation-passing style" section: http://www.complang.tuwien.ac.at/forth/threaded-code.html). + +If this style of interpreter was discussed back in the 70's, why hasn't it been more popular? I suspect because there was no benefit until more recently. Older calling conventions only used the stack to pass arguments, older CPUs didn't have branch prediction and compiler tail-call optimization maybe weren't ubiqutous. + diff --git a/ext/wasm3/docs/Performance.md b/ext/wasm3/docs/Performance.md new file mode 100644 index 0000000..4b52a74 --- /dev/null +++ b/ext/wasm3/docs/Performance.md @@ -0,0 +1,91 @@ +# Performance + +## CoreMark 1.0 results + +```log +# Intel i5-8250U x64 (1.6-3.4GHz) + +Node v13.0.1 (interpreter) 28.544923 57.0x +wac (wax) 101.864113 16.0x +wasm-micro-runtime 201.612903 8.1x ▲ slower +wasm3 1627.869119 1.0 +Wasmer 0.13.1 singlepass 4065.591544 2.5x ▼ faster +wasmtime 0.8.0 (--optimize) 6453.505427 4.0x +Wasmer 0.13.1 cranelift 6467.164442 4.0x +Webassembly.sh (Chromium 78) 6914.325225 4.2x +Webassembly.sh (Firefox 70) 7251.153593 4.5x +wasmer-js (Node v13.0.1) 10043.827611 6.2x +Wasmer 0.13.1 llvm 12450.199203 7.6x +WAVM 14946.566026 9.2x +Native (GCC 7.4.0, 32-bit) 18070.112035 11.1x +Native (GCC 7.4.0, 64-bit) 19144.862795 11.8x +``` + +**Note:** Here is more info on [how to run CoreMark benchmark](https://github.com/wasm3/wasm-coremark). + +## Simple recursive Fibonacci calculation test + +```log + fib(40) +----------------------------------------------------------------------------------------- +# Intel i5-8250U x64 (1.6-3.4GHz) +Native C implementation 0.23s +Linux 3.83s +Win 10 5.35s +wasm3 on V8 (Emscripten 1.38, node v13.0.1) 17.98s + +# Raspberry Pi 4 BCM2711B0 armv7l (A72 @ 1.5GHz) +Native C implementation 1.11s +Linux 22.97s + +# Orange Pi Zero Plus2 H5 aarch64 (A53 @ 1GHz) +Native C implementation 2.55s +Linux 50.00s + +# VoCore2 mips32r2 (MT7628AN @ 580MHz) +Native C implementation 6.21s +OpenWRT 2m 38s + +# Xiaomi Mi Router 3G mips32r2 (MT7621AT @ 880MHz) +Native C implementation 8.83s +OpenWRT 3m 20s +``` + +## Wasm3 on MCUs + +```log + fib(24) comments +----------------------------------------------------------------------------------------- +Maix (K210) rv64imafc @ 400MHz 77ms +ESP8266 LX106 @ 160MHz 308ms TCO failed, stack used: 9024 +ESP32 LX6 @ 240MHz 297ms TCO failed, stack used: 10600 +ESP32-s2 (beta) LX6 @ 240MHz 297ms TCO failed +Particle Photon Arm M3 @ 120MHz 536ms +MXChip AZ3166 Arm M4 @ 100MHz ms +WM W600 Arm M3 @ 80MHz 698ms TCO enabled, stack used: 1325 +WM W600 Arm M3 @ 80MHz 826ms TCO disabled, stack used: 8109 +Arduino DUE (SAM3X8E) Arm M3 @ 84MHz 754ms +BleNano2 (nRF52) Arm M4 @ 64MHz 1.19s +Arduino MKR1000 Arm M0+ @ 48MHz 1.93s TCO failed +TinyBLE (nRF51) Arm M0 @ 16MHz 5.69s TCO failed +BluePill Arm M3 @ 72MHz 7.62s +HiFive1 (FE310) rv32imac @ 320MHz 9.10s <- something wrong here? +ATmega1284 avr @ 16MHz 12.99s TCO failed +Fomu rv32i @ 12MHz 25.20s +``` + +## Wasm3 vs other languages + +```log + fib(40) +----------------------------------------------------------------------------------------- +LuaJIT jit 1.15s +Node v10.15 jit 2.97s ▲ faster +Wasm3 interp 3.83s +Lua 5.1 interp 16.65s ▼ slower +Python 2.7 interp 34.08s +Python 3.4 interp 35.67s +Micropython v1.11 interp 85,00s +Espruino 2v04 interp >20m +``` + diff --git a/ext/wasm3/docs/Testing.md b/ext/wasm3/docs/Testing.md new file mode 100644 index 0000000..b38820c --- /dev/null +++ b/ext/wasm3/docs/Testing.md @@ -0,0 +1,61 @@ +# Wasm3 tests + +## Running WebAssembly spec tests + +To run spec tests, you need `python3` + +```sh +# In test directory: +python3 ./run-spec-test.py +``` + +It will automatically download, extract, run the WebAssembly core test suite. + +## Running WASI test + +Wasm3 comes with a set of benchmarks and test programs (prebuilt as `WASI` apps) including `CoreMark`, `C-Ray`, `Brotli`, `mandelbrot`, `smallpt` and `wasm3` itself. + +This test will run all of them and verify the output: + +```sh +# In test directory: +python3 ./run-wasi-test.py +``` + +It can be run against other engines as well: + +```sh +./run-wasi-test.py --exec wasmtime # [PASS] +./run-wasi-test.py --exec "wavm run" # [PASS] +./run-wasi-test.py --exec "wasmer run" # [PASS] +./run-wasi-test.py --exec "wasmer-js run" # [PASS] +./run-wasi-test.py --exec $WAMR/iwasm --timeout=300 # [PASS, but very slow] +./run-wasi-test.py --exec $WAC/wax --timeout=300 # [FAIL, crashes on most tests] +``` + +## Running coverage-guided fuzz testing with libFuzzer + +You need to produce a fuzzer build first (use your version of Clang): + +```sh +# In wasm3 root: +mkdir build-fuzzer +cd build-fuzzer +cmake -GNinja -DCLANG_SUFFIX="-9" .. +cmake -DBUILD_FUZZ:BOOL=TRUE .. +ninja +``` + +```sh +# In test directory: +../build-fuzzer/wasm3-fuzzer -detect_leaks=0 ./fuzz/corpus +``` + +Read [more on libFuzzer](https://llvm.org/docs/LibFuzzer.html) and it's options. + +Note: to catch fuzzer errors in debugger, you need to define: +```sh +export ASAN_OPTIONS=abort_on_error=1 +export UBSAN_OPTIONS=abort_on_error=1 +``` + diff --git a/ext/wasm3/docs/Troubleshooting.md b/ext/wasm3/docs/Troubleshooting.md new file mode 100644 index 0000000..9b95b12 --- /dev/null +++ b/ext/wasm3/docs/Troubleshooting.md @@ -0,0 +1,26 @@ +# Wasm3 troubleshooting + +### `Error: [trap] stack overflow` + +Increase the stack size: +```sh +wasm3 --stack-size 1000000 file.wasm +``` + +### `Error: missing imported function` + +This means that the runtime doesn't provide a specific function, needed for your module execution. +You need to implement the required functions, and re-build Wasm3. +Alternatively, you can use Python to define your environment. Check out [`pywasm3`](https://pypi.org/project/pywasm3/) module. + +**Note:** If this happens with `WASI` functions like `wasi_unstable.*` or `wasi_snapshot_preview1.*`, please report as a bug. + +### `Error: compiling function overran its stack height limit` + +Try increasing `d_m3MaxFunctionStackHeight` in `m3_config.h` and rebuilding Wasm3. + +### `Error: [Fatal] repl_load: unallocated linear memory` + +Your module requires some `Memory`, but doesn't define/export it by itself. +This happens if module is built by `Emscripten`, or it's a library that is intended to be linked to some other modules. +Wasm3 currently doesn't support running such modules directly, but you can remove this limitation when embedding Wasm3 into your own app. diff --git a/ext/wasm3/extra/blynk.png b/ext/wasm3/extra/blynk.png new file mode 100644 index 0000000000000000000000000000000000000000..000fde8f1604dce5468b2b6a49128b04dc349e0f GIT binary patch literal 8696 zcmVZlRI3~~`c5SSS>nCQp#5@U>Fc4JJUMn7JF8P;qzn@zlA zcN2Zzml;4Mz8b<}Vj|IKl8s5$xUxzQqTC!soQvXxA!1NqfVuT_{q~QZp1xIAo$jgX z?qSZCPcz+Br_Om!RoAbdbLu(g2=WY)Qn6$8c}zkG zz2tz1FxTfpqZw{UE(%@57yN(S{N@=!v#-)L%t|3D0ak*T1js1_i*kQrqzB+W2;Kpt zg@P8tG+GJ_f6Iwg)85@E7xd-YMvdlpBrBpcWz$beiKFMy2rU9-5rA1F3vylgOc9YF zfSnL-6w|j+FzTh|g*P6_wOty`@qlNdG;2qFS!XA1Ab2e)a{&5sU0LstkO;R4k4KY0geIkvw}jdeskXPUAeYLqZw+r zCQ4HSD`)i4tS5M3t}B%<2;|RxG3s{LEPEr@wrDg%g+YtboUIR+9O>!&K7r*!xu3`@ zL?kG{iqfKzd$-NKr8C#|Xf*lGphT&1bNwX@@j(I;b6t^qM}R%zliORW>i&>xTQr({ z#>nI#l2RF{|B)Huvs#eUATZGk@!85i{f|iIBosrV849F*b5u2MC_cdU^(3#(wedq0 z5qWaFlwZHOdU02-ZP94*jkH8*W?;>PE_VNx;QU-0KGYG&mSP!kMN`eKALZH>jV7N^ z7NwbiH50nf-AMA&xiV-TAH2KtYtIG&cNDcWQeJ$*ZR{HvBNxc4##D zfbFky<>vZJ%n+Z=wUNUG!zY*OI3~?-C#5LO+4^uvNB6NebR1Il5Ma;f5hG{l$ZySX zCS~)jf9Qx7q%1;U;*p-t@8{YMjV6~^dP-9RD`)h<+^)y6Wgig<`eB@-2k~l#E0&&8 zAI*9#NV$PzK_AWfT-%}1c~(-LOzThtCw%m3?~LWCF1CLT9EP$ z`oh;mqZvL#Mac*)%C#|ekaX=el*sq%qS3gGf8ZTu5s)7@tk=SkDu0nYoINDGqOe9Y zY%l;|5nu2Fn3YRIlsp;IotJ_QdE`;e>c2i3&9J}^0QoiM3$$3)-v(Zs8V_u|+4ci}f5?S=^g2_h7+Hy7d*>O%!w7Nv^7 z%5Ol-ah@7Z91t-+Fb#RNZNbuxbPqqP>7lXRN4kIJSPbPr+rql9d0LlYLS>+SIl<34 zrK9-oZ>wJVKVI124;O%nY;`B45~DD=@kab&psMV2RF$2Mn@^pGe|_f#1P;B|Z&L2X z$u!JL0Paq<$IzW5rg?2U83HJslLPfn75I!F>|U@;SzOI-7LmBrDV+%RdR>pHJ?dOV3jFEUpaq=7g2r%V@*uRy^-D;Kt2lUI-^tk|)7e6G)h%XKOZ zvG;p+X>{{#c;c6?Pv#D^0KOEA8$1hYqU{GD2dO< zN|<82B`*kHr|cszHn-H&KBk)f8gBT(&OrPBC0MJLKhDfWy)^lYU%;{1_mSfTi5W(8 z(?Luvg^JOAFMj+E7MGvxSWeJ16TG4XVH()%T{BL=v94w2A-|Hvp+$V*TYCdLF9JAS z;gAz^ZSzotq@1;7<%FIPPZk3wo5aZm5ri1~#N^)Qg|*GOwlNd@5R`fL&?}{v6uV!d z`y^dYDUI|Iv4}BZf6q~+L-%$cj{52JR~KTd~8eWM7ATh6VE z>o_GTXTID}ZJM~YGSF}}!IJ@iq40h)=ELMoD_TV4CxvB&5AB+MyV{rCWvUuC6d&N; z4WyjxlvV`Kx7O5s+fTsNUts4ZSnPfYr)Ok)8h5s7(Wexjb)sSM+eDNH|F(B^L_MFx zW?Gh-am3IOB>)hEt&tnWHXUV;mv$7R=%p@n{gSbBhgm_)ncn!|4UK&T`B_&|3KjH9TN%;8&dH3UDY>z0ssc+ z(J!#WWNk@;lvyE)LdIy?{Yf8@PatZjChA=7=lzfLYu)wrP;Fu&rIP6VHva`KoBUfWYzSn_)T4mhQw zuzK?LRmvUjzK=pRNN8duR}yV+RWErx6T5r+{DtTYJxySu8|Q)G{MQ2eu683YJEm+| zJ&`7#P+N$E-)gR2_Q%*Q21JTHvyK)Yth}Tc4<@bbGgvI3>V!|>@pG@k+_9%Q=KuKK z9eC;EJ^dmR@wTj*ap~KhHeOyQ7n%9m`jH3N{s`ba-HM3u9~&orquXnnw#~gI2#Dik zaUcwIhd!^GZ%C!-MkDj4n;BXSu*S`EK{1!RnO`C^Ut2%Y4E8-k;smF(BC@t^;qv;# z?S2rhO@ph}hZ5-(jy(`zu}Y(Vc;WboC{i3QGRj|s(@M%PY2-Le8l^Vb;_pA)jqmOL z6Jo-)`#Z1+P(U!eM-rka6ZFcp&;S>&Q+makRh5km&Jm165d>4aj(&U%$y1$@i^$#) zEOLB0=N3}nTgPButz$Y9R{~h8mMJcB?!PrNZo0WGNB}@$-ps(72~9P(e&lxE0ML2# z6A_&n+nUyZ?)RzCp`YL(_u%3F-i-@eF_W4xj)Ff&ouGqyIWBI_KW=%G90O3 zDJ&M=lEu&yH}L#Ar7D;B25Ejn)kqZt(j$4xMlFC)=Ixt*P3`@y~V?yf(g`RHH6rWg@>B--4RRO3rL z4ptIxW^%|nBAo)`#+I68uV%k+V;x}HiV}$8BfZ@h19;jlSr3nV7K~r^KB+WA2H_>y z(gKk!0=y4mCcw`UNMmw)_vh!D(zx<(Lk#_!W66-ChEJ|&PB91@0Q>?JWN~6wL={N@ z_D4!bw&!?i+|x?RaP_HY;qec4Vo&EM1Ktj;yd|Q)2`5?6Qpu604(C5&*PT)$KNXvN(@nrA7;_zeTsoqi6UUhp+cEIFayw8SY^9HwS*8PBd$mLPd5L*~mBffXAo zH`ia1GeZpdse-NJUVpj$yj1(AY*{^#;3T^|MEJBwy5pu&X10}n-(_|~MVc4XHi;;% zcq4GdQz9w72Yc2N&a2`G@OVpg-49jrH3$SUUl{#A+p~oT`2q%&bkhv zzKfiW7r4`(BqBk;_hq$p^F(zWHs`4^6sX+X@Gk@$#|w(!mGbhjH>&3A2hj_lMD>8Q zu$ww|kT+^`$46*8>KG3Eev8nzs0(UwXcm;sk6t+7w-Ed%Lb@~6e zGSG}z+qQ7&+e%4^c27>4Wnt#!1itK)Oa$%zBDpf1cr?EN9#8KV`^Z1}eO$9B4MTq0 z{stau3#c6vqZtMSpF61%ODoUAj4_S_mjM80k2wX4%g@G!_9mtDULaZYXcG!<6Ubkb z)05*UIMeCLR5&TWzO%921fcvY>IMacT-V!cFG>U^R&H5!cFX*wuf=Y^n>2pjSpQl3 zQ-IY%829X+TdV&40pN$QH~W1#RN9nDHYwBf3zG@r zx&6&}ZhtebJ#9Aredc8_6yk~Qm{^S`+FwhaI4)aZ43eAXn*rngmYUi}(m7_eA`NxPW;_uj{QTXPig1ux;Ax(}WDmi&RMMI- zFG#AghpU;qKJ&JN6g=aUuD8b=m}9A`aYL~Xw&T&ngW(&;113X{&e~C5rjphmDT8r1~zRj#U`8g5UXKOxr{#i{AjSauIZ@Llk`_0vhyS%hH?+_sj zxlu%RIwduU>na;pI>t2_U>3jZj)R2;nSF*g{+NOhist7qz%!fI$tC7&eYk+c45jK> z%&e*EDUr-*2+pr$aY!iZZSw~FT}OH^0|1D9C%4b%`dGKTN66dSs_WMJ4crKbV?2V% z(2t!a(#u`*&5IKxlF{5nQ%aqu#RY)gSb@X(78_IKwGwG4BvZo}N zFlXz-84Xw#I8T);Ft41vebtGypXk5aKe|Y5n8$H~A@UEc3zz>G0Crc^Z5M+p91kKU zNLSw)+k6d!A3A1qJdi@GCXX7Av&z(hDED`#7>zg#R`q03-5EJox{xmw03Cy1|ipG^G7ZmVkH8kDP+ANkOK#}3c{bygHe8_uU2crk8#7(*wTbZltM4FdOZd{=> zU8eyNlbl%5*iZ#>MtYZ1(puUm5tC-alr5{TXr8}hV0Dy=K*RYyk-oR8m)VZiHw5cU zqAKM%07n71+rI7?R!uh%V_V|3&DD#$rUdG54grpFS~SfErfgchv3cQ=q&_`AkVm5A z6&AuUckF5S=V=#V_SkaeY@Xep`sudYE8<#^8&Lwj2-A7cB@m95A2=!{D{ADZxhoT$Z@U&thLYI)~n@7$=Sxg{h~2jreK zVl>K&$KdkvX{c1}M~bkw>kwW&_(8%%Z%qB!_8reZ9xudtI1#qaxw)ev&=68v z6$1!Q-o{yR+aQh|?c3(wa=0Q;|7(JdE3jCX%jb8_UVbPyr!M~(QCf6oS4a1y08X+? zN8-}TP4zdmEUbGpcDuiI_L2jYfrcKt_=|kx>l5eU>l5c?t-ST`Z%-q&yNV=`o|f55 z4hWWJt-jepAU!_u*IMoqVMU<6g;ZNZ&N2_;ETwb?)-i;PM9FYznv&y%*Js{#up-cK z2WdJ6l2W*0YT$wAcGukTUSyjQo`{P3oDLq&>^RttweP-?VsADAK)KJg3B&RXG2~9$ zb1lgIQG(Q5k)8bfPFYavmT}*#T4l0yu3criihurMmV3yJUp%{|8%C54s(j zaCeKCB3!SMUwl3IV$0lH)F<{DM)>Hz9fHG-35g3T8yoJ3eC(g|Mq09Nv4pM3XFl#Z zhOfNx^Y9`9E|7UtcMh(Phlt3#27RAzt*Kq*l(wyU=?+8SypW^~rckK~NBGyJo3|ml z>6VJ-g-iAsBLAq8mcWmuzPz#m=ocjl^5aYI?bEBYc>CzbxaQ^cXgZwM{8ZKqa)?RZ zT%SQB?+c87`*Eg~-Jb!5*lfJQSb8qRKzH7sx-h=J`M&a$YkM5&|n}BQ=$YX^vO4-w* zU>%6_6jN{BJ$JbazgovHBEqRJul#1PFVqCUemoaZ{qx3#JN*DqVE9{l%&bk59BXm( zF?x;{4rn^G56`r}j;Gt-z@fhGXv~qL9(h0eWP#y#UzEhS)u4=WHBX;OnsQA1#^C}V z4_-58>E63V2IfK(EXz3S{yB=iHF^80`=#5w3gmg=*dd+(NFRU>2=|i4Zo^|>y%9^&Le!zaX5k=0f0q(!QbAvvy$p=)@7D(Y4 zv5&Gf?%)UdS9l22?*wq};IbPWArh1R`0p{Rd^0L=ajm|LJB+P2#X387qA{>9P48%M z&A**mkg|tKen}~z$W|>#-Vj}JLb%bJB4Tf3B)yNDh+nz8DU+LAlr{kg-b_S)#QsS{h%?xC& zdh<*2$4H)bUXsAtPOEedMGn*_-BakrbJG9JB#RF2fz3ujQ%xdX9pbhPzLOiTwAL)2 zpXv3`#6wal0`)OZ1JOs3UXW?65G`UXQwjXkWJcU7rUG$%6zCoj^Uk7amqIv_nq4X{ zAl^HRD@T%NtdzurF?OaD7WYFMvU@#-9|ZjA3lffuC@p*}*R~(e#EDW#3Dyd5%)8 zG#NqT2d~e(ZOBbcJd}tNrJb|u4goT#aYoieMMYA0L1J|?6LG?nBu*x{14Y@Ysc*jWGP*AA0Hj^z$O(Dxf(X^?& zB}txk)>51lUY0@>Yf5Atx;R0L6{Og0iC&W8xkv+7u7k!kL}Z_j{x58sdyB$~zna02 zBua12TfR#mf6gQ`wT@h-IymYriG>IxL;y&F&^W!4%Ztq~!3#eCf7jY0fM$dDg2Dpe9{{CF|0QF#i&zT1Kt6#_z>5GOBNw(VFKb*B-7?m zq7cQ3Q3?-9;%u>d;$~In3``UW`o*Xl^tso#f(V{6ibhuLs=j?t3ma(Eu@t4_J(WcUK57^ zN<(%;Y2(bA%ldpo+1EhaEAqnz!6Aw~MTaR_jrLnmfGAnXsc zOnmYcm%pklNbS)i2uH*+t2m>iCxVJzl4{dUfIX!}CHH1@zBP`B2l!P~_f)x`U^@sn&^>8P=pzumKCeAF07H`$T9x=vFkleTsBKK)Q z(r6U!D3Vgy*sy`*)vB4M^p*zx#_o?DW|Fus)@zE!25=D3(@}w=g)k!7JBt02N{|NW zC5gzBE!DM)kJlATG@5iUoDzr#$4mM30@>nTvGHP%G@)9w@Tm7Zh3-a@pH@ll>@CH;NtoCz zcB3GvzbWC+jB1-CKndef>^ijV1St(KNkrZ*#)#^snp;20pf(!Kafzd+6rri+){lxY zqIyssQ_@YG*nDDC1QNX_AiiJ7h;x~oU$Nd$Vpu`MfY`7E5$j}b2@+(B79@=(nY0@n zRgD{p53qf`N*|M@w*=UGOfess=wT&&um~qeSGHvB*=L@V)a<{r|Mb>lp3Tk^drS4dohYRKvLw9 z_(ab}lnjyknyYKSqx+CF8fymiJiBsp{Ur?XLAwCU^n@wtL(DOfI?r?~oj9&7rHD9q zN8!wD@{T)vkND(v{n%flv1iahHgmQ+o7=Uw+~y=k5)$Dyfjm)Cg0(wl)gDers|87;QN%S-0+NL(!kK}!qllyD(FiR9 zWf93)mi$<0qlfuqnN&pf>AHMRdd5p%dE8^X*6k(6;Vp$ z0&Mi{-_kU(FW5JQA{7Fu0L@AOlPD-BQ3$6eZ0X+WO5zk7YlL1Q+5x-+F0 zG8#sikYyyw0E~v92$TW>1rQbrP(Z*hKp%l1D7^v%Aq;}(0nj0WLlikAkb?jYkvJq` zeh8wSCfeyY+rRqUu>*JAbyvosq6JB#$qd&;3CK*CA|wh_wi%2N0a}bSn!)0k01QT$ z67fQ)1}i>^Xfe`g+`)6N#7%L^H?$CGH13mC!5HcSrA0`i@t&NEL_P_X79EWy_xvw{ W`|w*QkAvm_0000CPX+4YSkTv$M0)%kJ6VKZco}>Bk(u&;0t=Jw1ykr65QCCA-hESITRZ zQmF|c4WPjUZr%sPOkE zL26Md9R+{ti%1CKLnPr5JsUZ}2(rU1N5N3;3fO%LvXisq!WA(a{#_%{j(aP*QdGE7 z8OfgnXWzZ`-w_oaO=}}GxFBHoP{F-GRI=ivT$Gou5N$<=IqNE@V;SmiR!NG90><)Vf3?x3)DV40aaW-r5TqM|ZHm`qmp`}MsijPEK zc<}HcB#8G=Dhr7`211BZ>Vd&Yu@mh>_f~dmBVfbFY54dGk3awk@LY$2q`c%GZM%_h z?B3m#@)VU5lBmd$;y3aIL&OQUC{cAvr6d25R-e9;2nm>=0*dHEqGyABz`Hv|ZV^Iq z;z6@JR0@yMR}e731p{P*;TFc2ErCTs5*~%Jk<(bY?!uvhiw7YDcx-s;QaqHt*eIOK z2F92R1|ft?hy#O&ib!aQ*l(~-0|a2WsUU=$J*jnW*ZU8_&>+dAqivK@sVk90RW;Di zh?lK0u9;=oFgRckLVO&Eog%|^6f}m*=A}%G;RA-V-SkSb{Xe9T+fbS`YFmrHe9yS; zN!TqbV0vqg3Zx}UHYhK8=60e8A2hAY;ZeN?n9Ok5Bi-uq|eGLm9M&X=xnEhwJUcP|HFJGcYXtS zfrq31Ly=dmG8gxL8$DrbH}O1$Cb0kQ)R_ugd8ccIGe~NB-*N#CZBw$V6Tk4 z_M(pAdYq%Ys+A^(M188_n2?lMoZIdq-2EKg|I=v`rqhVL#Zy43Ql%>*77X_()>qI-S9BC(O|0nN z!WH=O=$6GR&fl_r!?fBd0kaHV7<+4TchBxEbyL@et5oTV$miKAX+4u$vex~vo*^o~ zF*w$-a?R}*)1xD&1_Nf%b$#WUh1<6NGbbBMzf=A2Duf8x^7P27y#cN{f|h-^>cN!= zQM&8dkr%tNZz`_e`|ByIuL7DfHa?Ov9;$wLmH5BZvi|X{(Kk+rYn(Ww79Ag>=TBP4 z_M5x6Wcmk$SBk2*d>N%ZKOgzkJFfo>G;v1&Kxx-=!@p^Fm7wD}tK+LauQz-K*H$59 z(cyE}@gB2%b7tSE=({*Re#1En(!OgbeO}z17)iWglF`bFm}TL3EEYVMrfDV_4OgR| zC_S*<9BYeBMQGtNE!Jfku9JF0tZ^CuK&so=KLYb3suO9bq8iO?#4{UXtG<%h^V_kP zwh|+EK5kiPUYlOI%@}k3H!AfdO?+F^u8!UPWX0;)E>qM{?JT`^mfpNRe(>eg@BVJ3 zBISb{Z*VUw#dUvfvF&!>PgIc;rL?oVJCn)el`9^POA6gC?#=WJ#y(dI)k|Zub+gaB zd}>y!UW)-J-M8JmY&5=3$xjm*k%p#Ttu0s`zx~cwT@o*UbPBpSx^b85_JUPGE|B4B zTys-w(Nts4$fd+&Q*7ZBAQ#AJ4X$?C8>-ar{6XdF>j6>vQG5FJ*Nom1#7yGZD-w6y z8=qZ`7u`4Iq15OvHxqepk9y3>!$ahRNL=^FrbOa5D8M5Rem&pp2%*3I>G5zi=Fqsc zXAfyxkMVT9X%6%qnMl{PrllAI(DTNgeNkdbEjn_>?D&g$xWD52PsL|wc-aHVo!u9Y zU>Bvx)jRT6j-#>8?~)&>@oC5*bVpz(yy<43ykBv2#A z_L3#_ctM+9vC~LVfTY&kj1VDxy|ihW`%3Mzt2G?~HLb0Go&aM)>7(gQ@5Ucpi%^x` zwhVP|og~BaMPeh${tTt2WgR?tFt1FeWr4K+GPBRLX!f4twBzVrGqWa^K&XD6rfrpWzw+la+$uxA0bp5|j3BrtwJb~G zAJwutc3SK1*0lQAqHEHp&j29Y*rI6&$VsE4Kl@^gZ~aNltxOpM{~CMd_h!CpAV&tM zML|bUH4R;!#|>PCamYM88ecwDZ(f2r--Wp=^eO~nJ?1eZ%P>$4s=@#OSpWtceE`LP6KNTc#D~R3q}B_ zMsJ!22;lTiRqOzHADoej%=I=L5seS{1oHjc8lJyJVhE~01Q^r`V&y52$t&W|Rm&nlLR6I?; z8fypuU}%8kJ5B`vKxuEMnQ4nvHtF*k>7rVoHZ8NVuNtI77JvqL2EGczAVYh6I^V&0_|jD*fg=Vzn5I!{(t8?=>`KesB^10N3e_v)D4wjZ1VL0Z@AUF!L-Z zTa_OhK&caN1eYZ<7Poa_kI|b3l+YR%>kAhlMCsA(#(>N^r>#t`TL1{aI%%|rbwqT~ z?CArF@w_ICDID)IN7yzK()qTTrU06@=HB>>?6=Yq4T;-UA_PFr8#}rt$siRJlZ~jp z9Yn*jA-lIq2aS%slp-|$w#58uplPdf50O$Og5-3qc|+wBkHu;+P?K!mm_89Ys-fgS z=cOJewXA*b@!S0Io8xcxQwmVkQt|DllC2H6A_nnl+;B_sv1bz3$AJ>k{bKsi#jwrb zDcbK%<*PD`H;TZ9V4P=U%h;1Ih{s?k-M`&TEss^t*Qx7>R3Qa3O^44~{qGsu-pCvs$eqJq zBQH(z~vr0WZbHLLWwb8zicM91mSS*yRt*uB{}bgmd&6w`Ht z{N|@;0v~uwv`DrrM$bJlBSh6*{oj1)uTO`_c;8ol)H?Tt5E+%Ol)m@;#~LG?EuSys z+6s+R#D0UFaPYL!a}W88QbNAA;fDYeD5XGcDn*UC^e-Sl2mz*)AcO>C^hzZsk-nWwQW$rHsH7qM_ku)I&p(dpkaA%wlMu0JnVI0$NLc>W)EdZ^^ zA)QiGlKRzjR?){B+_`G!ehTv&6Ccusn66bu(O9LDmVal-eVL5frHtWnt)In1M%7A_ zN&aBSHYDlu8<9syN}n9D22;!jYXocrbau*bDCH|3zu{wVQJI!Rzrlj;={_cs3J)cr z;t77d;U9ZMsOZ@cxdp_iswVQvl_rm>r}5`5+>+V{k?S|O_vY-+T_~?|rLxzY1=Oe0 zArA>h5wpQvkqi7B+=F%uBN7Hz4~4M9%Sx8-^Pi%Ww^el1w!; z;&pco`?x6)D^&8>Y0P*)povr(~Jy|g96nkaGM`z;i?@As!3?oCJe(UU$rg#FXr{OsZ zX!FYPx=&{iLYk&IFnI8Ac(C_@*MYZHpi7CE4ans>SV-7?_H}np$v$mRDiQfaq=+ZC zXW;I8wz8cDNL|~6m^cYzObD^J_Dw?ePw&|2_NNk@Zzg!y03HvDkkS!rk;oN8gX;nB zJor7P?_ofMguF<@R`l#7RLT;u;c*%)2|0Q2aT
  • %-|?(#QfkJu60AdrZVC>#}u>;6Q9xWTY{P4>P+ zg}W=|_7#eavJ=aO+oqjEuIY185m6Dj(}2R+2;w>@^YuXo42KH0kgF@@=|_opP@I&G z{2%08Hdru3RIr8Q)rPzzcikV#jy<@9h=!!t-jo8PToeQkHx(epL*y=GI}MODPKB7D z+;Igye>G8n!GfV+C@-;gEP}*`6UYV$c#uTg>`3g4TZoU9vo37>~iE<{9002ovPDHLk FV1jl`p(+3X literal 0 HcmV?d00001 diff --git a/ext/wasm3/extra/disasm-func.sh b/ext/wasm3/extra/disasm-func.sh new file mode 100755 index 0000000..188f3ff --- /dev/null +++ b/ext/wasm3/extra/disasm-func.sh @@ -0,0 +1,17 @@ +# +# Utility to disassemble a specific function. +# Usage: +# ./disasm-func.sh ../build/wasm3 i32_Divide_sr +# + +FILE="$1" +FUNC="$2" + +# get starting address and size of function fact from nm +ADDR=$(nm --print-size --radix=d $FILE | grep $FUNC | cut -d ' ' -f 1,2) +# strip leading 0's to avoid being interpreted by objdump as octal addresses +STARTADDR=$(echo $ADDR | cut -d ' ' -f 1 | sed 's/^0*\(.\)/\1/') +SIZE=$(echo $ADDR | cut -d ' ' -f 2 | sed 's/^0*//') +STOPADDR=$(( $STARTADDR + $SIZE )) + +objdump --disassemble $FILE --start-address=$STARTADDR --stop-address=$STOPADDR -M suffix diff --git a/ext/wasm3/extra/iden3.svg b/ext/wasm3/extra/iden3.svg new file mode 100644 index 0000000..975144f --- /dev/null +++ b/ext/wasm3/extra/iden3.svg @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ext/wasm3/extra/logo.png b/ext/wasm3/extra/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..c1cf38de930420f76d842b835390e0ddf2e17fb8 GIT binary patch literal 16659 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 literal 0 HcmV?d00001 diff --git a/ext/wasm3/extra/scailable.png b/ext/wasm3/extra/scailable.png new file mode 100644 index 0000000000000000000000000000000000000000..eb997b888bb2ed7330ed8db5061d13be438fc8df GIT binary patch literal 8750 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

      ?djOQC2( z!$lv-ftlznj9r>m#qp0|0kGt@vC5aOu9fM|{nJlht^EXcORe@CuxChr-ML=$C%(P} z37MGzDSpFb55>%n^r=ulq1f#V`c^cx(rz?rV3T zZ$%v%28N~Aeu83xh@@|>+vsw)vEBGsB(=GtN*RQAIZc~n$T3Yzr;*ZgO|H+s$%-T4}8`+ikJ-&SXDm3y2^UV15>mOV(^YQcdN4yah^_len zc6!2ivz{a9HXECrl#()G_p12#c>jXeZEeG@I!PcY{`n!zW;^iqolG&g@Vkb-ISP9U z8JT;3G)6L93*M?d|&x9Eg3E@y3*P?u#r&60;PZ21}a6Cm6eIL z^f#`xv$J!$v#nd(bPTAbncM)8+G~R!y?VvNa#TGUx?{wiLWo9X9Uo`aq@SEO@s&=WzN@6mE}C-Podmsv>Op;5Vn^MZ~DF{rhuVF>B146?}EWe5ROl zL+`MOz^5Aqm`EMTad_sH74~+k+J0Z1xR@squSCH(z@XhSA?oJOog3)E=8hl( zr6XpyVB?rECW0+GW-*n_g3?RaADDHK&|C>yWo&HY%pG-U%mFX_lWWzMsBkaQf0oMG_c$!4RaJlf_<`b#HNvV+&CD0TBTO;2la{1ZqNthw z{rmUMck+^w`Axn^R;*LwJgW=^*R&+=p~W?k?Wdl>cVz#i6KLS%;h_e5v|_=ck5Pxs zlSgZNgVGFe944_xf8(3G7GbNwGCBHa2Pa7FLjnlwzuCcx?)=TWce{%k3$&F3oW8Pt zP9G2ZF*7}Jx1!8}0atyXfB?1h2QBVS25lcWXwa$*d!f+$iph~G(AHnSeCgNOU0hrY z5~w>^LcH*<%QP5tO>bA%ySq})hXkAkq0rPUM_#ES`RL3P+qCu15cYLRmc6Rm- z5ccTDIROxAmlkC<&N8>WSV@(@D8;dt{oCqVPmH>EBtJiYLc%tw$fC$Yhi(IoEWhNx zZQIKwJyeF}Rq=Ey(;9gRWD!hh`-5wm|TaZqN?n2d`T z#dk`CsELUe@~{EV3Y_1!v}6pC2ruZTx0a{STPqgaKW^!t7p`hLTkJ`uif87 z&fcHi+uN1vJRMzFPKAtXHmV`>%Wb#*OX!M@|Okto81UP}B#GUNFvj z`}W!Po3)ns#2E$OIej|BG%+MOFGBb=lqayiTu!8-zILTz=n@$}_e?SEpFe+sZUJnk z8olew%gTP|WIy?b@ z<&E*tzc}H^s?cTrmzJIp-23ZyPnZ6kFoX)!rka}MTen`0udQ>qrx33{KT>Hx&~Kp4 zXv79;I`AjVXE0(F9tcH!y-|MMNG$tk{9MqQnVf3;g#ZTV9Kfn6inGq8# zEnZl7Yro(K@XF5F!KCM$@BjMETOf1B*Hl}C0fX#{Klt5*I7|=TKen;4kyQovj_Pd6 z6oGoc^1~*G29;rlz^$(R7p5^pEi!eC`s~@;BU)aVNNg1fEw8BfE4pM=`TN_d0tv#P zl+bYc0ELTl#!gLiR z_6nbvG!c?#*7}z<)zwQK9K@eQg(bkZ(dB}rhtAw^;pd&9zMD3&<6z7HRscl{_OA>z zZfI(XVmqBY`JuU4%&wlJGuLOue{dh*O5j0;33-g<&YE&cO1;oeZdxAIPoJtg-8xay zR0ojIK`j-4`j@>+NXrb*}0T?_q>uDs#1%G&zL+qbUBHx@1|fq}excPART!Go9I z@OjNi8e?&;*4uDvr#BLm_*sF6|4zMpSwe2JU;@xy0PcbIhZig{Xi)#$-|@4zJ{!L) zm;wq#t*o4Y-T~3T8_4z2(o*A?ws*^BX*;*>L z^HpfDvf;KLfF@r$J2@^LGu;kZrc72>S5Qy@1$tCmybQEcQ&!Pv$IE{_A)Vc*D);Uo zsYDP16&@0_3)q;=VQpgrI}I9Mv$!ZLq60XZ$#>@3XMm8vj%O#WzKdGs|^W6xG`1M4Spj>-;dRnK>P*dBBdP43XWVL5XJLkugV3L`P@S_=JS?6E6f=Zgr8B(?%N<8#}su7r&$T7*-o8DpHu%k?Kib-HN6egO4}7o|`n?a`h~;Lzy1!W7H)vbk+*Akt z_iss)b4{$L%nkQ4B}QOrX*T@4Wb4e#%z}=hd-qshAby_r9ZbnczNhA6NdNr3t z^gK0RRWvjr3Y_J{cSEWZZ1C*q(;IIiSWGK}e`ndNi>_E&+47B7ifX;Qy!`xmwWJFB zfBxAB8n86#SAB11Hn^^2Df-syba@k_%o{ce6x~tgil~@T&V6>WYsm>Ym0)_wm_rUclqYm<#CDzt&p7$T-?P=%ec-y%^ zsDW!HmG4=uT9pVamQYq!QqsWzx}Vb;h6%hJ5W+BFnE%+H16o>JXQLPb$wJ;bLQ0Br z1vviDys=7==vnC&#~v}`$OC80ITZh~O%y0YCCS9hZ11adN1|I=?X7HW{n-ECzWHfH z_k1ZFR^obO#Y~v|x{`joD``4uv*@80dEG=_j zd@%P(bgjp|=IaA>Q zP&$43^a3rkKkl+EG#c=9tUR{C_ix`sVmI_3dBsW%%|BE^2k00$j_xR3XiD?s4{dD- z9GopS&q=GINjgQ5@tkjxe(FVqjdS0X#+7lOehm!cb92ZDt$6d)?*T$(;8p4!F#>+w zGUn*r?X%Y_4zv@y`tDmx<#a(85UFfrsUj&r8mLpp1YgoUOFg{3e<2Xb15K+HOHZ9U zZHh|4Nfy4J;OpAaCBZ&E>B-4!(Ae-JPs|O~bqw||yJ?+j;QMx9sIfpGOYaO2?A14D z?{i*MO}6yLsCTft2V|yv?dlpPE`F`=m8(`(Ru;wU7eJkjtlW!_W!J6<8`y1Hyx(VG z$8J720@HIE+B8&<@|&fuM1(cMJEBb)X7I%riy+83oA{NAk&aFvB2T1HwG+h#*?)ZO zlCjhDubM@r#nBbj)d3V?gn)}nzwcPBtrq{WMGc|Z!){rY+%4Gl|m z89W(v8BdVBeXh^zE1r-LH&IGxqy6V;(Hmy8Hec5t@7}UaQ#=5XtkuCztS>&e6j2y|}B^o|lQc^|cKAhh?UQoxm?NJXcazE&F&d0~Z z{4HQ1U(|(N&dJL9&iSjcais2{@{i9h3ABKa^Jv+O%X9C!AYl`Tm-B-AY^Q()=g*-D z+5TK*HzK$66<_1qJjFhwv#mj|{5Pi^oe?AN(?N~LwR3Sr_T&0`|Hbf30|Cz+V|S8kgp zn=>(yVNYMaBQ`b`u4KiE*rURqftRQ=;AjW;?-z<3{4kTg021i;G8z3G2d5=Vb`>?k zc{;wY+5DDbv>&0ufvu#ILE?P3!9~DXCuJxIw_X^V^gtr3mhZ2j?}bt-+W0OIP) zuRYkftW$wGXW2E63N#lADFXurVVY1>jE{-Q;W&u?WUd!IvE*fGKg&7b>i6&0weAtw zI2!9w@Q_CHmYlATcKb2?}x1B^&5g04&EijsrT{Y+6?>s z2M)MDKfNmAWbvH@ox>)X??m&3{Nk94HTLY1umlV?y{=A^Ey&+I5=Aa6=D-tpI+Rvk{YSYTq zzZdPQNgGqM+~eGZy=T<+%@I1YO%(}P{N7$&!{)N*+1n#F1ne0$FR9|apB@V4#&);N zQQQ2&3p7h6i0bQ=`h}FbO^>ngsnmKfd$P`tZ9AYJfoE68UaR%?$^zJf>PKgV3M}`z z@Mn%qDhOi|K;|}3)Rft~@42jdb#o>K)9?N10yO3*WdZIMzq;h55x8}$(U*K-P=#`@ zEd7Ab2ACdNhwf0@4>}C)7JeCx6r;-G$t!8Io2ib8R{5&)Y-Xw7?gA77?LyrQSOTnx zgtVxUi519$T@TpK7c-lz#2^&JV~zv{1yP-WSa`y*rO%LhvKpZ@UcOXkx3yFv*}HP( z3K9yA=s9CXDJrh>^7?=!^1}yasMw$W4jN0-wobI#d&UEn1hqPOifh+? zq|(6|f?@1Rirz)P;c$g_RrF#&Hw)H z{8ZlZ?aLP*jp&a&>*i*(gHVz+VOeQu7)u^|7MT}4_J@WBQ#?1B7sLS)qv|O6V8f{a zLu6h@?N#|dEr7%AEnq^6dRGcoR}%WSAILN~(L{s_UcJcs08m<}N%+RL6pS(P^?2nO1f6KS`>)P%j3Pw?g*a51>?y`e!&y4jl4_tjsOhQc)S-Z^iG&g{@ zPp{3t1Kz@{i(!MhiBzt4!+B@shqhZCk1=|%5J^Iax4csQ@%t9%4PYa+I3&?7I&RjV zH7gta(kC1SoZFV!u^gH2-xIhwi0!qMV``}Se`q&cHgzd;%zc)n%a ziS2!wyz!&O%;jAi_0`p4dKqutxTFky*5+XB?&hXFb0(C0(Nu{?qv<`*pZ8z~v9>Gy zuk$%FrQM*Srk5EA&maF__S)C^jqTEdcbRj|R0lel{byM1un){M0#71onmU_zH%lR} z#Tz0go@uf2sn>V92vU~BmDCLkezj)T_eLGl`Xb9aao&!nqPx4BJ~z%QAJLP)e%{g1 zAD#H=Y?D9T1|4*%oA9bxP&IoB_uYFVrWB|$W5&0f=2L0s&)?{HaqsS3@7k;5@hN_q zAGzv8g@;JpV03ke)>%fBW=N&rE69khZVDNejUnsA2|0eCrrftJvk_8OcmPk*rAaD9 z)`Q~H68%2Lz(Q*&`e37v{ulp-9)<=3q@Ix40Nb}3BbrY?20X<=gcP%>sR=_S7~2Q! zL-TUiwdxPSZ^L&^w!3Jyc(Lr@U4aHlFM)g?TMJ@6fNLu}P6wax+H3mH(_J>hrRQ>t z(1g+_K>3-aREEYDduubjEsGn@4`Ehgh~V(rW~h8i@%)a<>pZ}Z3!EVV`5SMY!Bh#0 zKGia*0$7E_4?6G3S8i!#We#wXvsw^0c*O5nJ}<*wW`-3apreJFPu(|JL6gc#=Ld6O z@a6G}4SHM|g7X|7dLN=Q*I{KiP-0qg|Kbejo`LAbX zvDm~5PguO8OOBqplE$C;YsK>AqI`*oDV6~+FoJ@M&irG9dcp2P4;^JL$SN^6H-|H$ zTQkzu?j#^rcc>IQo1hccIXm^Av?>tSvSu8=8e_+X-*cH_pWeX7-S%eRggCz%Iv%B< zx5Et+A`4%`6Tf{sjswm*HK65hgC7my0^Rvz8*UY_ois}PzWTfEDH%SX%Nv4wUOb)H zfBzYQ$bX9&$m@r+D;oCca8Sbgus0)|@K}}^_oHTY{<+sHR35(&a4V7SIlm}gfJiENCY^uI~ZerqV)Yg?wi74U_Pb0Z&nQ+@_ zB>;&2&d=Y>2lpXI0}$FP&7Md8+=tUyN>Oo&)INSOe^5Z=4ADkw{`sc@n6e=5 zYqryy(?)N6bYf?1z;Ap7x-2+oBq#lrp4M!lQz#K=cgy~54-}wA)5IsMsnNW0j$%*K z2QpQxd+e$eueaF?RSAo9w2~6;d*?|c>`~1*!1;x+Uoh?=%WfN|1L{jr{73pyYHBwh z%omY?=4l4r&o8p4Qj^Dx!%N6E$UU;!)%7j?nS0qOpv+bjn0um8ZegN=Ae=gDR&-f2 z`lP8dXO47`G)}6(3CiIJ$2@wp{E*&DWjr@%w_un;h`P_tSFnLZX!d7s3HLx&bwT0R%fGaCoqtt_!;#Z_0RkOvo* zq`65cATMF&V>q_l6|~`7C|+EALMn*>B`bnTOdqenPEeQV6S3(^XYaNB$UbS zn}avM>I2k#N*eC?R9o{gM-bYdyZ`=mdmu+Vk)1k=uiC3qD*~oQJfU$YDZ%&B-?Qq; z6W>{%&s2G#ykqpq#!H_{i0?+;S z?b*uJ^vl~=Mw6FbK5M1spb=g8nzggFfRDZjU!8aNYu`fHbpg+MpdvTf`Dl21Z7hFFBAIDXF2~?gZWfO5J$F?Kdx7nu2}c^Qcz5 zg_bF6*R7ik_d`iz9U^+#@wxTemfvN!r|v()hh?y8sCUamsu3ttroMX>T~Bs)7kf*v zgu$aRO*_Y}$vmJ3W^x_pu>YIDE0>DYKjS%K*_K@Fhj)BrJDf1-GObG*F6MWeMTzI+~_PamB)%alxebvPW3PVB$v3bf6K=y+Ul$hnHZ z142pwxwh5a-V}3Y?)>>1UR+;?JO|qq5e~IyY3mt;8yZeCz!MX$AgfFz!Sc#)3iE!U z>VxNi`7BoxlLF9C1no3Szb0Qi-KV_OU8(wMR9D~2Pd)S49Rmj~{4YYK=L{X8wVH-~ z0O+p&Da+^>OXb#%4>j)3Q(FD9DqGxEWIelneY32rAx?>Dm2Lt~dXdefctWYg^8&=53F=w#lLvH#I^k_}l(c?DNN+(wpe&BP13;#etGM zYK&Bx?NxsVB$dTE=7^4#778CKYI?+@ao$n$xSt>dYe$MFRNTZVQ+`*8?l?5Bvb@}< zEv2Kqow<0tAy#I9P#m#<0!y1`uf7q(a%%3yo<%D6a=*R_a9s7=UCo{9-e}^;w zNZS=@@bv*NYjky2ZW8|qt3NG{gN6W-oIYFuCr?I^(u-@JBkXs2tzUon(xthQ^$K!XPU_=+Y z+NEVtq;|aZ^*JfVl=n}nt>zpa667;-7;m|V+j$NecF$bVqqKPbm?MTi8iXZHlBz$l%$SxjCY-CQ_HzvFx${QpN=M!3 zP4AYzzi)9Bbu(6#bh+m*UmCpHx6|}BorJN2l$m68Wn~9#R+-7@aU#AeMZ_S7FaL0E zfMkbYnKbF4v!D4G{)*Q!~tf&VU;hXgk5E@QNR8fPG*pN80M=_w8w_ zOsx@Cpt z&*%$1(1O&|z|9OlT5Pdk0ha!GN&TzdD5)MDB_ngcxr0-Y8t~gbuV*H>NW_9}<`(Nz zVo?l(zMfrJ{lG|w0c`yEUH4o#)fs6T+W|3^nPHKMb85WG4Om=lH15xr&dFR5Mtli0 z<%+=#k`LOJ`3O)q&!j3ZKmk1xUL6$->@i#e{y`rRg2aUoFRDZb@6y}&W+&M&+~x2o zb)ox^8S>jHt=NG{L^4e112^Voa|exCQ>UVfLfs)iz3*SA`2gzQd+!aFyurKvL#d+I zIUh)xLj>h7$2>xZmbJfs{i477NA1|WB;BB|Z#VR+%ZbkeXRBOnbcjtaJ^1}OlQU-% zcKmEv+4r;h_ni=a4ju$S+<0#<@?C+MrFZzA!h+X67>~&HSn{26OYLS1z@-EznTL$8 zVHFls+GfSYUGI}3=gpbZ(Efwr(vbtS|Dx5ytS_ydagxc1w2%yY=EpxujX%EOm6M{R z2JU1~xY;e5doH0QNL68~xX!@(cF7zEfoBD&kMn3^=A5_qzy5C*XnBrB-F}q^Xg?4J znQZ~KH5>PDN=l0Dq*u3sGU+Q@{Ag5m{Vn^J#>ZG@)1i67J3IlvB8xf#Z}Fy4@iNe3 zw{rHH@lavH%$e-^(^lsNx|;*H&696(;6r*CIzB1h`j(NOeGY{(c+eoI-|zU$8r&w` z0x88SSN)N=m^hc2lydNlr(TRar%rliq^E1@=$sHZoCR*_trw)olEKU@E$uo(9>k{E z^r|ZZL827{rf4`8T_k00nK&S6YV;z0ceO35xv?>c^My-tayR& zl5zatL5qb839@+Yn*$yUR!#50Ol&i3mi!^wu5;%^?^c4fznoUlvmva)13D1~7fJu2 zd4Ng6?m=CW`{tm8MQ`;a33(kUM6mJY#aZ(7B+}+)2 zTWN;a_;g()#N`DSOq(&|+J^c&ywcEGuJicUJei7$K$Wi}0;hP3zz3XeH;SKD;A(rx zPJjGWQgl!Rvc4@;J9fljGOZ-fn&y6R~>nukLK$N`J_U3-}y&RQ9oA zN(;^wCO94>!7faF36HP!8e5^eX?Zd}C8P#4Q(&%YyWLfXIi24MtMPFS#}C#%s0}`$ zi$Wu^>6bRSH;!+m+ge&CYG|zY^1?Do(~f&QD2NP^1>>Y(x>%Uy6T?zr2#fz6AF%@X z5jm?ME=*wRhIRGRn>}%&C#_B9sVPcA-6MYts2jw365q_^1OG+M5L9?hc!4(-JBY-d zqtVfTQf{vrU*7@a3Tg0J7PaU~b(-yk9`}zLlP5EY0f{hO&{SPckdz-P9Z4J;!kU;5 z{f-?q{Y-=NVe9)BhY87q?Jfj)BG#9 zzM6xBRCow9K}2ClRsCAAF(BS}$&xC;k;NWtZf;IFcaHF=R0?o9bZHkm`p z#?aKKrKZN5IPnF8>*X-%2M0y$9+G|MAo?Iw+}qeEWJXzp!t5=6SX?5D!VOL|T&B?n zES^?uxpu~;J(SJQb+!ecv!h4I6J|wpP_3&Lny=IySGpbx z$TP&+sz;ZhZ`j(ke*TqJ6Hs$-I67Y_N@#ydZ9aX>G#=Z7o zz!)J<4|&WuS=Ri*Q9ZP_AE4qz?_!sX{FW(&Woe7VKmitbR*gOL6FG#|{@Efddzhc(;t;J&zd=NJJA(n z^Z0IP;kE;8`C2jJ;RU2};0JhAF+^%-NSKaO*7Dh?l>;wYscl0mP9hO;YFMuGz}pBX z>x(SU`_bK98-LYNbw3OYUsMp`{VS6y9B%rhlF@Ye)xce*%d)(dkU?{}7xbMI_wwb> z8h7^Ja|yjX?AWD**Z-iByt@FMQHyWK--08L1qILs#&Z6@HC5X;&B~QV*h~L=iCJ_@q4G<(9lr5)MX~?>gJ@U`;e=NGu~NK zdgRE`_QwY-Q%GEEkfTv?PqTfu_R4Ki{H99nGfu1~UFLN}tCgJ{Mih;s#Z2Gx=NF;= zZvFvLv@kTCwYb}6=MY@DbV(x?8@z66O2#=1P=vg`C$c;TG6c%W>I{6)%QZ9S9DcqH zM{7eC?gXaQO;$cA<0!rudeVjHR9=wz84xyh;zU8D=eNU_IX_-PE(=_NA|@o9mALGY zeDJc_Dcbg|bqgRSr~p|j1wRyN)S&96wC-pSdoCv`uzE-VpaDQ$tA#Et?qH_UHYAw z^42$}WHB$Im2O8tf>xPE)bZS3&}Ay!gF^~mKN`0nExx#TLD7M@?hA(+6-!;8hr{TJ zi|#38=%L#vb<>x*;CI#SHsDa@cU^it7A|{qmnogAo=g-KpVm`k{VU6zJ9pv>>bEBn zFH6qhbHjvk@?<1L!>3U;Y4j2+JggQHEh9EyKex~c_p<2+UOr;44%9Jd`vN$tt@s8-TO(e(Z>u)XGJrqco(G#&2 z-h|4bO5mQTZbuL!fFqYi9#DaP(5CcO{T!bMu2)eobYDStM1R9?&cH}Q3+ZK6R#w1; z+qM}XCWx^BKv-`b^(gMwuV08j$ZHZ8oldc8Y3Y8laO$F0rQX`nc*2mQO|#Ab*I^Vb z2pgak^C`yt6xMHgZ{V)T*`0zMO`0W`sMOSqWO zT3X~+NQz`EzeJ0io~O$}3m+3i2_7vkPZ-}>+esi}CMUWm72w9B#CJn;Pn`*+rDTvTmWt3M4mcNNJijALjeOhoyiz%5%Y z+h+)!eTf(ox25~zxSZAACu0x1?dWC_fGn1N?~Z{VYrWGIka~V^qW;k7p;6%AA-W>M z4i=yzJMZ^UTS3|%cjItJA|v*U8Pa|d94oeeorqEv649z2FyGDXoMX;vO}VWcTr6=y7Og%oFu&rI5|9@6siUI|U%ug=?g zQM0|gF5KS#1pSQB&-Y`aXWnMz3o8Wj^2)r1yx^GCY|dE8T2#S}l<3BY>h`B}57 zOG?(#!?XXb(8^_(?BoyO%^e~lhG&Ye zt}Zc?QxRnm^O6WAWW1#JB#-2g%jMw=fxuhfcKrhe)6YCFLchq#3`*od4bv(w;p=OwMu zl%sjGw}1cb26l5$3X-_n11X=K_eJtH9!_eb!L3|0iFEIM4e5(bK0Slo08DsZSvei- z=K1q2>aBw*FB>|U|xm03V4#B)-J%D3uez2%n$`5_O`((*AT$RLALzms^q zJXV2&@AoYNhp%zej2R;o_`-I{l8I3d>kWL2uT-rB8fUEYw|5fdg?KQsaN0>d0n_C-eGLP zK4bk{T}4R+%h90=BALDC?$GU(YMtb2w|uvS>U25ro?J1RiBzYA|6DSN<=Sc{U|oWO zbi)gn`Yp4ORs&yKo-$bG;P9z#LSfyU{4n1lW%<2Bvbuyjm4{gEa6VAs;rC&bqzD73 zM%!bhHMF{lZR;<@lq&@_zta;8>F>)E0X7INk~z?HO+|m&w2iPg6h+QNo#auB#cGo$ zFI==}fbIfCBQ5zuoOMRqetaSRG)`*F-zvi-13E2L@OKy92z8G0{tlni{yK^L<9{QE<(3U;_Umjwt&poIb#M5 z9op0$*f2}{xDrN!57$;;#W6J%iZ1#7<;w}={79A7t|dugIgJx-WU;Frkf)7U`+=KZ zLqb9xJ+iRM>46*x(A|a7hOpGr=XYAC-Xc=>=slr5g=C|XCyiD_G`zpp;)8Jhvu0t0 z-Kbi9nEYiG$%}TRhpt_=EGBm6i9C7sk&cc%ErW;<%Zywx*Q=#&!Y!FFc9SPfa;sRV z0fefjcardUW=NbFaze{i|9?yQL&|P?Td1U;$$LWyST|0 zM*|;+lWxwLdoF0Vs#^SLkU8o<2hWrfR|P|b%znvULuh(4X~ZL2)aqz)NPLg|NOm$& zCJ{i zh1o&)?tyX=t*{L~cubq|zep;rsv%;(ZlX4rZD3&5w+dJ1FUgy^xok+q$s?H|{w|m{ z8H$*=#u@U#n^O9B;mst>QCGL+>a`~?`^$w&ilD^uiP`$CKUy5?R9lP%53lPEh<-dX zCR|-`T1|ReO+Rr_;pM`I=9R5)$8Ump8rrtlm9&>r3uN2{f9Wri z8=JE1CH62}8-JfjUxa$d*fzpgavZVobUGRK>hwv1)MG~cZFLr^o2o7>iHV5;;{m}1 zq}o)gt{}08W&KQ?EOCHC(604&UKSNiFfs~e_5t}4q=Rq(^bK4@GC!KM3XizNEkJfo z#>OGI$fiyeOWtMN|HaDJ*1+g6nCO-#McEv9!aW!dHmK_`HQoRXh9vK$4{^&}mQ?W) zY8b^KS&-o+|D|j)@d4RnuN}B&no`LpmR5j#F;Aw~!^&cR=^6AXl==F%!@Dg~xeFA|~_>0`+#5NXAilWFTgX z7Loh==XtUvA+oS$)6TZ-Sb51_U0_lRGEfRr!4V4b#M8@*c*x5=95Xlq8i$@m{?NM{ z72et;D-yOtz~Ea{eEM5E)x95z4e1JB#Hg$0+V-^)eug|XPNr6__)fIa*)ieA^0ca- z`bv*TTEFI6{4eQb92SHsnI_VOk%bcbH?tZH6~`A@J0?A+1t0QK^+(CJ=Y)7> z4*s-f?bS6bja{ZRK)6?R=@YZI-rc~}ST?LWNgo|A{BBBmV zgx|FJX$VvNRrs<1N+DIML9+(Y8tmM=$gDhLH$D+62+{GOLa5{srBeMVawK^K7r zr$8s^7HH$hdh1oWl)b8O_pMu`;DZ#wlW2CcU%G@!_~{7v&{(sFSX77;gp*&e)f_Yc zuZd%{OZ%R7<<3pz>Vqm~_&`v)^OzyBYp0JTrV z2J`5kv)wm0e>}D2L+YOx=l3vGJ>zuXeuxB{8fCuW<&EJZMhG7-Zg3eaA{0{@R_Ln5 z*v-<<;5P#|>aoVCtR`WR?M@G$@3tJYc~K#3Dwg zrpX^dbaOrTH~FZW_!$U49WDGL6?EbL8u4zZ@OP+$7o4#4VJHU6M%>RH+GYBWgM$N6 zp6_A-I-$bzt;vtiLHW06Q7O6<7-+}Od4Llr)HUT0_p!BDg$0>xUsf?9R=z&Bjb|GG zqY%+cOkLDN9Iz0SgcIEKzAvD3A|vSw+R^c-Nl*IguL7klvlY=W!mNo1nWR-Y-3rV| zO)c&fT!$hoBordV@kSNT)X*X9m2yG`4l4a}oOwO^+*af~P$HTs20P6fcXu3ccmOzB zQ))9=ZLH1&K4?a0TUFIR5Qk2aWoywM$8oMrtp$kL+KU z3=2!kcg@WLBt}5x2>Q~?6I4_hlB1o>7c8J_L=|PM!pK8p4SqmDHO7lC3NcZ9jH-{{ zzD6vQ?FIfD+}9O6WS8mub&1s<13uL-%YPoTVt27CZ=b>r49RJ(V`(|_(62`2zW-$& zGOC6b&@v*65KtnFQ}3RhptCp;8`}e+zf47vu9xHv(?rAvr>j3IZ~c@JP#08`>{r8f zwVk9mdh~SpL&)guGu?*9TZ*MDq^U11?nY+k6#RR0binYDBePJ`(9hE;C0Ze=epCFkg5F2?Tj}ZuQ<>wzVy02SX<4>O4KQC#KstxVmtLa4ULjWS*=(l)<#GXw> z$uYSNQA?c$4IGH=&0ymj5g!G?AtbiM2in~Ui!B*SdkX2!QZkwo_b6>4bpWO4GWBQN zpP4k>Ux@nPrQc}d&{1doNTmb0GHKu|dloR1E# zM-Bnp?XB5I*R196nR@FB;$EgqRy6u;Vgyka;yA0UJbKTi^;K>ck7Sb`S7KshhC64g zk;g@3eyXj&rkq4%8_Eta9d-4%3$`>da){Lutw5q;Po5;+j`+NH%oN@x%oaP7D z|=CQ9xy#b=xHNDRFt_|BxL!O&0!3W7&9+pcmb zX*w9YPt4i??LKkx!K8D{5<7 zTn9mnZZkBRFd>C}Ht= z%xJqy%d`F@|2-`)7ibCvz+;3MQI>gMA5MlM*&A#BEhnW z9Of_{g*i_gwS%G&h!iIrU;at=#EYH+^oodz(n^5r?f~2({Rb0MMCE%P92R3-zx4yZ zCJrCClYvsu9{lt3u-RFFJpP=7sQ zBUWleS?l}0-Fx&o%T~~7(lz?&IpWB-P|e&Ruv}ccNCSy#l+tNw`JED@vcd(Dg&*^f)t7l@t9JJ70qj6UK#wZ`B|E|FmR~}r z0{m(-V2@qeI&W`3^V2!OeLI|o^j|x{jJ)j>l``-+gQQ!x}zPH8Ir`F`?fin2UlI|8f9$3e_I&)Mp~chx1E$Wo6#MA97Qj zh`Sdr1b07mCdo`$J}%09o%Rc~PTu3oL=(ph3}cK$5Kwz)N>ML&j}b=3DM}m1{Abf9 zVR9H0mYg%Km`AQ!02@cA;UbJT3RY6r4E^oCv3-Zk0!vFnP~5<~oEx0=f<#=%CFT~E z?@Ak+=`#n31-`c&O(JE@(NZ_Wwmtrnq9z?NGk(|#ww7vnk-rE;>rWH%rTZ6PNGdVf zwJlFW1O|Y`Gvu*BFw7Km(qlNAk)wx;IKQNz-B@a$E&S((Is-l%S=Qqx8cOUD?k%xP zTXLnEi#=Fcbh4aUFuoYM`-Hwq<khW=D%N&rIz5nAf{-Qk31&rK~Ug`}cq_9tf-J zeCiE{oELWcu+30eyqE-JO!sl?JAr`KX^#dOL-rX~$d>uI%R&`MnFf-09r}$Za{w7; zCi-IUnW46m23(#%i}26O8$>2@U83~hkpw#sMQ9Na;OtDLRF_$Mp@H_sd;R+BlcREC z^bc^>4HTKb$TPE+i3Noq3LRQ^6zM5SYi7thewfg3gS?(kV<&rzCq`q=S*)2iU*d>d z_hmicORBBj5}y;LZdfhfstKD~=1=5Co9($61b+m;{Qzofw8@7TfaD}qs70CYoAbtY zLewb4P$BiA*aoaq=Zu*~HxCY(Y`q;qA^$i5l*ZE812aOGIi>d}*1xRSO?!@RsqfSOE-hqeT5TD<@*&P4$;rmw)S2zLjr+hoE}YtqP|8_Z zFP{4?^FKCQ-~K%Ycr|*;3L@i}O37=$D*E}WQo-%;xwC5qnbO4k?So~4)9vLO@XOXg zCqK!bK>~z-WpmpsMkA&q#U*C67tBb^S3W+Nkv#tXTNv{lH>`jN4qEJ<@lBU?IJ@`J zZ8Z?Ua!KkIz5BV?X*`Fl>(?KbHvJpJkLu+LJ?>DGT*2jY*Os?3p(`do5g$DQ_t1lj#rjk6wchK!y>CT-8;R|g^IT2? zri8jl_aKOh;~onCB3Zq7i5(O9L2SvcAGegYf1}0H1C^| zZ2&0|VC^6Uel6d@23^+=k^o0(Z5=8yAIfd^mkq4^z(68^PFkG9QX!$A2arH|>FwqVz`eM$T8SXhE^RGh54S?ccvVFE$;%Xd(N z>E{>51BJ=|)c`f%##^Id`9~;+`%aJ|ZM#FUYj%oA(xyaP5k?gTqqer@1g>lSR-X+A-#n26&wgcor~-VL(@ z_jpGb2P8i9%eUkb=|{Q+$O`yZAy1hqn50kV(p7?lk?uzSaJB7Xg$LIl=s>VzKo=1c z%lr0ZA?^jk%^#%qs$!=gK|rMmCx#w_qwR!pUK3y}hYn1QuWx>!0WxFqqCGc=9?0st z&Qdol6F#-i@?r7DYc*VCNd>f>pO#0_+OjEK(d2)Y_>C#=WyfU}JNFHB_;d2VihfwExuAb+;R3om zlMuO2{r{4D;2^EwoAYaN@Xrx&ob7?9&rTS;3$AAU+O=Ezes@hBcfPgb|Fi%r?|izZ zwC(MKBM_pgwhx;-aE6fTc$ML=;cwuK_kLTjdf)|STQe{^oXP;VJ#$9L@1dHs`6W9P zJDYBnV6_BcLUW)ZN+*CA@;EZ^+uWNO{Cu?*0~gVQ?{4g9=jq_e!yVaBGxdlWL*qJ4 zIqU`8>}8(JLlWF^SA47BF9D|=5y9IaX%Acivk*s5zln-~{`P**t9Y63tlsslXTOyi zAh!M&seV7la!rGDHbRzV78VC@FJox(|NOH1<4Pn<)JiuN18TVF=xXAcN6N_|*$Y+K zOGcr$w|ZpJXa$9fmoCL8Zu}Ur4e*NImkv@*?E$ntc=GAfc-;CA=Tf!dii)i*EkRh} zI3pkbBT&Hs;|VMyPVFO)eMfsGm=qQ)=&vLN>COEmcYfM9I&SAaVncy24?1ODN~Pd5 z{o{|p?MADEugw=9Y|P5MdoH2N`$MBi3=j)bajxN7LqL+iZt5joS_CoRV**gL^3p|t z)tJ;-B)+e@G9hBt7Q9SjRelo53&ruX3CTLcEEBNcj}*clG8VDgKy9vEuA3euq$VaM z-el~z?UiK|{kQHCGjMmZiTctc*&lBJySVZ;qv?>FcRR$_+q*hNjw(Xbohntv5x&EYASsw(r{~>sWVvl&^?Sc}dA8tTaIM){WXm z=uDnJpNPiPX(DrAOQE>bf(?rP@9!*86*osT3Wd+!KNd)SPrtcz+@;@@rKR;cpU5uh zEftK_W=@6W2EAp|rWK$J7mPnHt5=gRet7G1H$4S;d3@dPg;ZC+dr+z*VKSv$R#1LE z0p}gygw~XKq@eAlq3aBvLE5ecmY7q0kKN+9`-?U66us=br_TK#1jR@9b*0-a!sz0g zhiFE;2j)jOiWZFL`C8V_eY&)9{7uKA7t!)SO`3NTt;NxZ#;2;_O*zUOZpGfI&s0^RSNUh5HcYpP1GFC{*sSw8h>3q0CdJbK}{G zrJaqI0AMmtk~#3RT2RPrk-*1GdQfQRWIMPumNOf9UpseB-2VUyEIcxb_ucNgq#)pe zc*e+%hZEI}V-pbspLYiB?)mL#a5iq-xN_z29<0)H&6-gYHwxV=tlVl6LjxB--6;P5 zh`y)g{hx32|L6aF|Go2ud*rjK8lhOfg|4H5?0goh64+LcS;DK5-T>1E*x@U|>9R z=_3M8H-7wFk}n8{1HkZ18AUQdy65WY)1}}xb9U?iO3QQft!+X2x8Hgs#5byS!q~R2 z;he7%qy;1Zx3=m>7y0v6#VM%!e6U( z0Ff#Ap!v|#0(pW1<$E%nA@3*OQ41z&{i;>dke-;J;Jy;+XrlS^Q1x`52&#t@ z`uz1Pd%3BOCB=^SQe*9OP|jGe$*Edmx+pTIDWXf$mol=H)#`?$b`i- z_J#>-3@ppEMi-GS(&NJzALk-7H4`}eNE!WZTPC=f9a5 zSL^)o-fX)Rv26TW1l_{&*(-?iPT_%?{cD_5FkuNR*%m_x4QhY(Y`(sJ1CCHdMKZpG9Dz8~A;X3#B${zY4+Z5z0wElR;8s(_mdbNT zr@}KEdFb>+YC3yH%E5Im=`E6T@}ZIcYUHc)x*8EY=MmX z2;`lT`g(w}va*sA*#QeR%Mb=E*NQ${@-GHYK(AWP^eN;1>614^+<3P z=}#7iNf@BV`)_X#DTv;#Img4pKamE=IVE(ZHZasZ?L-gXMC-JJ9f4GlEq)mUI=O%# zFc!i~hUQ3uBdxkg_)T@DK8Weakr!Et znj0vNZoeV>rtv@pvYeKCz&PE(2SB-GQzASaOEv%y0U0aYFrVu|yM(cX1r*Rb z6B?+9ERAN1OJP0B0W#8Oiv_mvD=wZtFS4M|p8IGz(InD1e`slWePi|hM=xLDHkb_N ztD!^+2myb2jyTGQ+}^&uOOP70zDz#HzRwH2Kf-6C%tCO%op|a>p4(M4$1hqcQX28t zeluZ5Czvi7D*a^(Xr}-%xt|}}K_GmMw_`b_0|fzbNg)|ST3VVvHow8-+1i^hV3>S~ z+?YRFIbl&WWH|b4Zr|*VDV@{c-uQudVV$?CJZgstk%K+}p+@wm8(~H${=2eA(aB5+ zS_L!DBPA~@OYql!Ze>DMdp4(rTfMEX2Zc8M)iz~R-f(4EI77sxtiNt;U91@a^k#X6 z&V5gT(-|9LrY3JOh5{oOs)p@$^{uUR#{$*9bu0NN_FA;tK40e$H$p2aBR}#eG2NH#|HtALjDnVg*te`g)A#(a3gat*axxVCU>9YUlW+N`hI3ZthftxVg3l}xoFhHSYMsyZNiosrqB%2XZdzACVNW8# z1rg#{rM=c87mzxNJ8|F;4j0zB9C3diNXKuFT!N+2gATg?7X|yknN5T+++>&wrcBky z5|i#PX59;HY*^^Mzp$RdLw(1J_~}#ltP26AE7ZgJh#c;LF}$0M&j_JxMyqnxH8&%a z?|EX0_A?qN=K@5*?nGoCT9KnPG}tJNX3+b}A1=b2*jS7@jQlg63H5LSp*Y!eqJ)@j zLU>-+U-jgqG9KFc;lm>$A!jw%<}s>UkBm0kVH#Jwal?kP5A9F0L}_vk*UBg;%$+j_ zfO{zYG`LLiszUhZ3OBH5BuN;}nJ#$N@spMyKajCX@Wot>?uw{sM0&4r=mOA4tq;tH+<62umS!09gT{D|7`4XB?|XLU7e_w8fOT$ zBE!oo{$=VTo=to!K{h2)B6?(>vT zc@8;F#{E;za`fQ-SCe=7Q~457vU4RKJ(+iNhEU1X6p3dEQUhLO_{_|VCRNPWn7+6C z1I^sWTL-Zo0k?4kAw1;*k5S%773VXnsIV`WU=Tq^1a5hif8p`kOVa~RPXP&j(~ zNCi(-2Vo#)K%%z;0!faMll8+P`QiSis?R%DLK3^W%>0E5CCByy8X?pCf{=#78dFTF zxYvn3mbCD?P*bH@Y>=1ine*n_rbl$WHQ9MzFIOLGzA*R+i0_Jmh zZXM!amg*g}*BYj(%BD_BIxQxnK?lFJw+rhW5wHA*Y%);+);72HI$T2LD8G_TMfjcg zBr@uyvLkvVs&yxFoCD#6<$OLy4IFVt5@#d7t)?1j5osxkhNfZQ8tW5;Itnj&g(aTjD^m@H)nQ zJ7aSRz`opJ>o`>LuuqzrS1w(;A8XG>KO(iU=Kh2e;9Je9sd)MFHtH;7ngoe5O23S~ z+dDKL87*0Fcm)YzVuZboyYV}oD| zl=dp4TPP5;HS7qYf!wo#HlGoRq7@%sSTd0X4GfZOg8xPGf#Hvdq$iPMVg|Cu(RTVY zBn#@kxsw*}bUwE+yZ!h!Oe>u=-M?!9jL1Xb9Wdx6PjEVlSw5RyG%|+3-7X#;Hu0sO ze6t98iR@q%!9$mnz7mu19CC;c88`7#x4~{IZTvYjl~i`LPgk#2rmP7o-8UF-=G?g( z@jpDgO)%+6zV*O?mlj=xoCR0U7bqYz8chIY>OCa@93IU-P42h3xKrqt(3Id;aE%X#Cxh zy~;y$)v7C-oMw&AGrueOOn>#vSm(bV&en^b?U~X%vf|jEy)@43marbJ=P09h@3y}E z^-bfCY*kBXNtBz_`~32)$!qVq*m^EwNvd#! z*6{MXAMF(KPsfbm>w#w+FI(1(%IDvV|u3x`S$z!1fe&q5G z^sTHRZ1+S%iY7lek5>@SbH*I4;WD6F83~V{rqK{~LO>ZyZ@qrMPt~~ab?W4BmaOF+ zp>2sB^e?52XLIwGmAT_Z?Zr_Kxc@m&?jkEcAKNr|PL3;P-i4HLN>&RRp`$~i$eo{m z8GDa~Oz;>6aIPeYv`uV{=qFI+HewKV~gay$ngy zF%F&w53+GdZu6S@)aOw|n)+bH*x6fBQ5CR0NR8x%NrpFB6d>O(n!Jyo^^Q7G@->uH{!AZ6p$s~boG}SEBa(0&ZSE_spnwi~}fh$q{ zj$Lsl3mANT3hd6nkl>&o3_@3(xI>o5%W`+@ER}m^?|5!;3701DzIUbk!_V_BKaYwz z=u%w1Vh0hRuP6xV_As6gNiDg~k~t<7oMreL*rcZ4A)}e zY~kIXbVwwmuC}%o-L?tmf#Y=feC^Hw;Ui-ES#ZWbUBZ&)+S|1+Ce<92YtWVhCrmnX z=KjB8`P!aj?!+LE(RNF#%wDR4X>CoDkA+@hBXxtFTV&T7Ene7o`R27nV^E3gomFl6**_R=zE;Z5c<5Q3l>_0jXt2yZ@aPgJ zr~P^^&iRfGFb|qR$f2VTsODmCF>5UtGB936qo|=1C8?jV&;x-XJ8#GDk zkDZF^^(9e-9X3~ZyC6wLo;_oJ1{jmF(TV^3{(YtP3FeHX$+qsjGpij4U+wWr^GJkr z4yB6;+&Z3ZSnJkV7|j;$L8M^o&6O8@x5lAk07^M#k|Zw- zFE5C|i7CqxUO*=?va22HE28~#m)d>o(>sB_h`r%T`^}QBy4bWq#eoCCd)nDUhAm}f8m4(j6K??d18eOCaEIy*9hVnlRzWQeqzWk_xLQK8Voi7rk)-!wAullia zAPh$UCJGGaOB1?;cwo$}G$G_gIG*JNd`Q!NYW|2@qKD%ieq2D%{9>0zqr9~ffkSO3 zsLFkb)%C^z3-FE@i(EsFXhvo~*2df@i)m8x6UO0dLb}xA( zkD6u3*qCZb?f?#@@Ev4ZZtrAlP23 zXpC@Hmj$hIa{~$3nM~3l?LhiR;@iz@ChF(}oiGPCgGm4K-6bXc{Q0+nNB3aasWaWv z+}iE6%8NQhEe>;-#LK34All=o{4tAXpm+!^>bpe)1I5xMV_d^^J)|DVWYF)wl7Lur!t-!!BTx&3PAr@;nmayP5^$gjh8cK`mK z%3nh@#*w3fLSn2+@O|sz_*l;+|EmQ^-!7Pd*N-9TGo^xJ#CK{2nh4w}q};{Viqx=Y zkRO5w|B#!$a%G(m7ju6^*xPsSNSbB6)+y6%gZc`q;ngyBnXBzgwM-g$DpPci15BrT zu>R2p5|38$R_eaES9&O@z-i5hHGrB3B1ns*Kf^wSxE=dwv$vqcgSU{A=5jxY)>rtY zw{qanAwv>aa(iJKR{foF!}i#){vdYt59H}jVGBm&tS21=RI0c|jF%*Bya7J7+&y?M zl=}5E**qXfd5EF}h686S;+51Af{I)SH%30neEHQdMRm|1kU(v@p47Vl{Y)?Xq~)Sr zL(%+l1eCc-{x!k4bj&zJGQO{#2vJD6{>)7?$+SFqGFOJAYm69Zp_KdeqYcHEdbJkp z3a_=~z>shU+V4>qZBDlj&Bsgp1Lt76iC1*d@gqlW z5LU)YNv%lUd7~+*{*G68#)*EHtT2MkvKt%w-Swk)<|1s7smzBHqlAlZ{{EyO=4E{ZfqrRoVSoToV>g| z5O(kf`~loQu<+P13lcfTe=!9~?FZ7ih&8Si1;RMV8E9V6;mW<}+-dzC7TNtT(qSLN zj(1`1RnHl4uEZB=qu9|!I3W~##*Dp{oQymXK{zpFQBh6rZz>4xB_4-FajW|w)$TKn zU$CgkshoE@WOri|k;FKtk%8H20*m+R1QT)?k zhn!OdPP=#Q@=g6lv?mBcn%i=_v3f>E(S`NU(Oq5J4{O0?0bo<3@pdjGPXNHF2m`UvLFVZF#ZL25K z<)I;^seTOEPTA38dV?bzkA4W1amMlt5GJ)sw|pcwbJm4t?rF%61I@LAXUJQ!LmQ2Q zsbb06KM^Ra#Z7a1ir5I@?wrmSgvju$%>%8(EhZ=CjOqgkJ`)-gDQ~ z2hP|QFqAAMDGGQkH^?1?46i2UL-V2TX%6eC$<$DY4|J8BH28R4=9BWXXpxF`La}x* zUN);4Xf(sO^ih?k;XNE!IO*7@M)WwFfb^ML<1k@l?3<;}#a^PjKq-HT8m^g@K> zEHS4Li~IK=NFWPNos#&bK`mXn9>^P9Ch*h=CVfE;O%^{RMQ$)B5d@>DsROT%^+n({ zzk~&h+HsHybaBr@q$DLbRNbC;#sBg(&vbQ9CS$` zGzYE0j}pExeqH(^HmqLy6nLPpM{4x z_**Cii2Lu*-XT~gjAPAqX%^%GU|h0&&(J~~F43ZS%O*^k)G*2aJKOjOF(5fj@I%Sv zGt>dI#$G+k^Dx?Ho(IsEkbjX;ww`1K$StHUjz3L2-?A!B?2=9d@nPXs9P*Hw(M1l) zPP>_n*kz5fY9&g=IU|n(ZzCE6UkR+pFLlam@EnHR^RUX0f5X@mqHXr~+_{8g?iqCw{+#tD z?oHDA;*3@Q@vhurfKS1W!!4#DPgUQ$Z{Pf@Wq@|>tKJXMAp}TK(R}1lcwXkJ79En& zC{aWs@#?7=WiGo-4cmV5)G0a5sE@C+jezH}v#XtwMK%#HgfnZkP6ZYw0(FcfrSGo_ zkBLD(PczPCh%1JEii(S)y|^9lU1xN6U|~IB4+TyWc#_h*%msTkoVd=+&uJ;Afcz`G?I4Rc*KSehm!;Z5q$|YsfUKL8@otDDKH=v zx&#g9m<*x>{oLwt2vX92TXJZJEB?@SMu2V9db(rjH4#sfC@FIIzy5*?3I25=@tL%Ye0(YGdD9=SgcYsy zu?hC+^G6XAxg&|IRvqXK3=%TYcwiqKpvS4F<59JLyC;)bad9U~o1p0NVV7f49W-P}ADuBfm4-uCEu}}>y47f)g7KQe{1qhnzRL_=`EruC z?S=W(w>ODjTj1Mrt;`i7oY1Dm!*Ui+FE5CvKyCK)#2sDR+PYDDAciZraa_3tz7>*`BZjUgcd=lX$r|CE`5WUUB5h>P z8yK7?xv?YEn|Jivx9vFKXoYxl#KYMH&WS`0s|(u)tPV_+4_&1bmAmaNfTr&GEzI3; zxV_uPZD}7gnRM{{IxJ)21uqW|kozYg0LO~MxIU1i;{9KlNBEuYowtoyW&4*ReYWYe zUCR|CEPy{}zzYAS3q-#5+HI-$qt46lqxVnPUp&hkmosPfT3ZZ;!2S~T@Rya9`!TAv zd7u<#M1M1M{lr1+_CQVX;ZZM#IwL@|-SG z>@&%vr}KHccc)W_g95;#^b1zq?|wOUjSE>5=gtMsx)7Ah()pH(tbB4GYxVNxGT}UK zKDqDL%ka2?+SYSs&kod92aHkPV|j))7n<+M9W_mSl~}i*Jdvu~QChJ)i(u{Re7#Js z@$QW=S1(7{jRm3bFpS}flhOHep@}I<7D)8}Oy^ZE0(GLsju=tz9hQ;s4F%0qb$%gl z8CxI=*GHu_LHhA$KPf80LJ`|CDLRl!!ZjObf7^zv&ER;o$VX(*u?u!b+FZdeKz@`_ z%oBmzCL8GEogQR$f$@)j&*j$FfyG1Mtqnf?Yd+iH(X^0CLDsm)hCZ~elSPB|@=Wfb zw?=Hh9dNIlrd~o#CDd?E{D-C{i@U>YY+5Faztf43!yw$sZQZ)4$rS@2<{viaotfjkopAUW zh>j5Dz!2eXu-L{!nc7cUm2 zy>}u-N;3jMPp}!F^utGwc3jRIk5wRS$FEgnxp2c-Zn3^s_Et45KjYY`>iDm<<<_UZ zf_J7N&D^9l^5|cv_&xoQt{$A;GoY{kfLh|R?WJaO3yY|TT0t|7B!s|W`>lPn7ZREb z*@%dqTZ613XV|ER4)JTjY0&1ev}JeD<0Gx>+k6A;?W=}$wS}_ry6@hpHucKL&ff|P z-Dop~bc~-3-c;E(Si?uoI`O6K#(d2dJ$5wQ-y$7leM{&}jeLS0Y@-HwdVU_iC6&Rv z$c4aPvI3q*=19-ACoN~!E@OaLs5s^g_q4^VBVx^r&xmD6Ed(DQ5)EX4^S70|qzHgA zNt^4pY?<_`3|)Fv#!o`38666oDn5GSeR7t*{?tkP1b7|l`WRzBPwFtQRZie#xzUr{ z@jk?VAAFnn`&d-ecRqBm*dM3me}caWel;t|HVhh+6;mZuK4(wMr4|5m_tw*oMSwS^ zKp^m5^4GM!FCHy!l(zA?i7EDa4-}KY+=xJ!@4~H+#Cd1N~X@I=khn*Dn1={xU4)eOX#-<#I)3m@H9BZ z`-rbT3~0MgpX%0eI+G@C>H6iDuxNjQ6NU@cr~TeO1Cf@n>&Ws9{2NULFBS5OfPhnY zlGod=0iO}^=Qkb zrKSS3q}z85Yd`w!%a`5?3XPuWkl*~!E4t|ksm6S5_m@ie+kvZ=Ba=D` z+G;me5ZO>`!Mh+q&Az|wcQb#Qg@t6HTYLmS3kHz*6bh2CJgk)Xcep3cT7sPCU*=$R z+`${FDC0N~X$Kl6_nPS=kAg1CNZcg>W%@Y_XIZ&?hF=)|kKgk0h@4^tA$S*TNtE@A z5AC4)iT5^3AVf!WQ{aSAJ9X)}Ky!SS=tH77T=r}Liayj^qD*H(>VT0SCK^Pkmo|fJ+l9&DlmWK!XvMrAnXl%IE)C==*=Ppf% z?Kl33plKdE_JHLXx*fXtPEJItW4lV5s1{(MOpm2eqM#X=JHLFVnR8ELF$i}ZK=}{% zK7L=(lhJ%9B`HiyvL3lAr9xZoKV}2tod1tOtCFF0xmKtgcUy{TJph~q8!{+8%&97_o zHRis(o-PwaR?k#*(Z7xH+=E)tPp2HaQX47~FqUPQG|NLwHw_G7!8U8Va96CDKmQqx zY)s6yj^kTE8wuTT9LU`r7SJa8Mu~-{jsv9GC*OM+0_f05FkphC0wYmpFnS`7m^Et_3hg&4CV_HWdaH~T zoJo=TlP9A=v0JeMm2UwFM;v3ROPAAAEM4l~s37DmT)ReCF>H!&_O_{0Gx{PRV%Z7+ zBti?D(WF)Vw+M}u<+N-tn(;>K_P_ zD~54lV%05KYd@aB+Z0~_lCe6{`N7J(8ht{8f<6z^G*FYFw%`P7@)CQ5<;mQ1*6i8U z6j^xwzyA89tO_WJ^bkcL>=tVw`l><;G0rhn4J0oD8!;!s^_AkpFd4>3hz&POIeAxwyaE9zSXC@mY#}`--an#X_l`6^p!?c4Kc{y$a%@I@$9)v2q`( zS#qjoX0~FqvY=+<8e_0rU~8)^mtWh$w++m>vNVB}FDK9JMzSIhpnmV7fH}}_u!Vz9 zSp9wOpi5<2>s!Z0%*u0(aY&L5Q(DPX2)M;1146VO`KaMDu^P4>9PmN)jZ?6t|N6C4 z;TI6_2Z=!;E3uNFSXeDmX%TQS+Gwx=IuBvYQ&)HT5AOnE;PGbaD{!LbAdFa?7pO|; z63Q4dC?SBDiIIB!sWg)T&s z0g#`31Ax+S!S}d~F%)s1$=~ONzm$-$#YCHgPgb?@&R|IgAA_A@ ztQzptc&LJf4Sz`El^1gCo1%M!Nq^Slg*X}Y^3$hqt+=3}yDZQ6zKdGJ#|7-@^+Gwz z)P5k@GM~BV%ope#(Q@VHibw?`rWMy3asMquJ}Y0$KK;{=bE9WP>5KAm4k|7p-F3Lt z&F#NYH}FK1zJA@}t%Wo1>C@{x_xwk$(a{IIvUq3lD4SHvp0pVayGQcExe{5S zF?xm4rc)PY=@rS z#lc}H$^0oUvllLmn1A_Hp6)%8(;T(Y91b(^sBNpu-(w~DO!oc)1UF;VshzwA?63Px zlHO!JJ%BHQb-*8mKAp##+em<4*Qc-@UPimiTunB=vz|5UA*?ScTTE<>ulSMBWdUrL zUnQ>x%ltzGG(;v$CUV;|At;k&gr$(&puHp=dVT-gz%2Pkvji;zvnQK}!MBhELOSs- z&xvnrXuvV_ht59oaQY0^YkrkFhLupndvO@~VnS#wY~c~%Vm;MW3&};s3a&@LiB#dmr}Kevf2od~0Q894QYcBQ zR*ksviO@n}jqcxnV?bm>Xl#(UfhBuELRnoRJ?3A|GXai@6}8oz#Nv*twdThwHH;(M&1dsSDr z9IYHAadPvY20PuJeP~a+AQ?G!30Q<%N(Jj|p$%&?Z#@&HP3R7aJ71Q6!kGL~H3TmV zW-2b7KU0r02>wqvMOv|s!t6=~VM!Q?WW&t5P@rZQ-eJFzt%lO~&Q5Tj^B16lry|VB zH2H)O2I&Kydwv4f+MV8YG4qPxx^MFGe}A5OMFB((hkzJI6gzVlE}RtX4oO3|;Ljco z`?zz9uJX8#_w>@65Kb*__<9ndLsl{x)p^{_&tExkk!A!Pir{A;eBoW& zL;5KyKY_a+?h%WreTj%m@>El&;Ad)j|K78`JabdMR9j#8L-p{r?#nzlb71X!Duo4! zLx$jQB&j0pD>y+X*_OPGv0uHfK-t{bCIqy z?s2XYPhyNFOdh*1oKr2fG~L0CS7!XL7C=CPlWF}Hr`G*Af4V!tK800Hh|lL=Hf0UM zTz%pVJ23Ny?AnDV;Q4b~{X9{Nr&LrDv{3V*iwW#)#qrC~=CycI{=R$=>#J9;&>RvZ zhzzo??t#U~tVn`fUKUbW?FWbs7(fA388W20yu3rWWP7oP)f6Vx@am2duAUoNLsx*C?5gG3I7>G;>RTu^WEo|bha)>H$TIcTm?Nmrm zNf2{-x_#1+Z3K?5aT|VV1OdC*504q;xu*Ib3Wsp2eTXcO9k=B)Nr3qh7Tg|(-}=IG zHUj7#*QJUM8}zTURo{?G_?_!g^`ag<25J6tY;A>38p>^3g5J&$b7x@Z!;cymD0n{^tAteR zWpN%II$`i8zg|e7jlJL2rfoHFnwp}ypG=R}%odqH??T#Q8b|JjNoXGyL!26A|KUNp ztiS~n%c-ah6eR^@^s)48tE5BQxgd@^QGw=eK($EllS&r4?(*+GcZYs@2ngSkp6(C9=Nd`=*|asw{O%er!KO{Ox$r?KeP1b(i^=579}wcO4!U@oEHt z66@I%T)x(MF%|Y0yX{m|I5gmufrB*uK(Lr?5lBq#2DBh$`>DFx@b! zSUeTh$I*#Q&eE|tmiNJ1`}kb_)o?5hMw_&!KdI|~S6fc!jGswl@KBh|G7wzS^3F{wO^YY&gXYXj&{+}IiwRUA~?VT&Pzp*D#_C7E!~PRWfjJe_-I z_5JzOtLlXej}%ar-B>_+sl3^ML_50vTMb*2Qyto~%3b`U%Fv;Acy-Opa(MsQ&`@4< zeWhM>qlOe~eHzRxJ$4%OZR=(X;^*SUkv2CsbFN{J5Qb?VW%IKuyEo5T9QE7R5 zV*}s4YQ}G>aN~I3%wHc(*J}UBc=ygTbB;~%#&`3+9naUc3C*==Pc3(d9v=5nZWVp& zQy|o`nwnNGLllh0pvTqvnDG)xK!Dd&lqh@toOM;q#?H!WRGIK=3XV5_dqd=yZe?EA`N~7({&igC> z2f^9kbuw{>in6lCs8KlGz~u;)PG_t*b0#m<2$2}-4QX(2L^sCq+<4cJ?z`(}<&Ko|Z{Dsut`;aTF z7c*gFaKxEcx^&pt^ z4b8$6)O>yV93=f2cP#-3I$@|S_<>7y$giVfhdaD8lgM^}bKB`he)QeVp&a4qeTEP& z#4aeM{RJqTm_7(MT-f)Cn!(Q9!rBH23G{uuDbF$9F@I*|2aSiYCUh|%VXAu6lQ!K@ z%)~)f;Qe#-Q$;Nl4^HnbFMrQb+b6$GYJP~hBKt_Tz=XgMVLb%rB%JYU`3M8^;|_;I z`ahP2v-p)KJxcW9`*@=lywuExC ziZ{F&k9}c?5n#qlg14SM!`8cIgaP?;dCvw~rEX`(S@~QB9V!zLmyAqCe#Mz;cj>ZP zT2u4KZSubSIX& zu0gM1x&P?jA0y9BH)M||EChMEyqp{$F@q_a`O@0P*i@9%d3gEwWR{tU?L6>#Pac7A z&9J0tSylr>aCCtI9Le@_b(QsXE|!CCfidabd&(`cg3soQaQN2E>C*}FL`Ml&Cb?UW zx*DEwZqJ{@`nbQk`Jnw02m@<0s)C!Ei*qM^iY)(X<8!tc%!iTDaUl7NiM>+QWFErl z&6*{)Abav#njBgnC~~YfOqR?r2fkI~uy>X8tq= zKp19rpUw?IRAL;E*i8;5I%(1N69-Z>IywUslhTZ#N!hRi5k#E~iM3y1(ibv;~ z5;cys*^?)aLT{-k=ol$&n2WHvtS={U`5Rd*$n6n$rg%gV}^+(8Bc^c}CBK1I+CQm%q2a_G>OMJ~-O=>)13Qf3k2QFDE3a|6kM5e=yW z&@+W6VmakNxpzD*Sgm|wcdVvI1w{tL1Np@F_Z>$;&X4z3`4{571MKYVAd7H(14&@U z0`KBHKUJR+HQRidbO&O1W#MV4*_77r&f3lf9&Q!DU)37^mr?##%1D&WevVw_~% ztOaHxb`3$?J#J?ew)CV`B6O&>Z8>^5x*E_il#}+OmAl@|=5h-C@_E~_Cw_{x{@`KTSb3{Y#b(%YoY+2Z zQXSJOK|WboD5mKHZ^9D@-R0N}KG;iE_T=U~M!^-=E1Ch$3i)sU{KJ~dhQ>y+MVJKD z6j{2727XZAI@)&*S27c*>U0r$dfy<^#>nNHpQ`)RiCTr=3t@lZgZ{5+9T9;co8fCA zQ6U``?4Wkj&ixXTOG$BP`6bAb5QBcjsw^V`*vH2cn+@qAA(lrs&t1ohEna=J^D^HP zEUowMySR|(W%=dgIFBFB`NwV6`lXCtwr3!cpB*Ik93;6~PAv>)RgvOsW$ z`qqk?#wnb9UgrVIs};FF&k-`t+cc_;5Ld22Mk>d_XWb?z%n_h zRn-|=Ac53s;Pcq7WJ1$TJB;-3>lm5+e=5qrY+)7u(s6LvSo<`0H zXJLL&rUUJW6w7Oynr#rw?L1l-hbbQayMbaBi^EngcCsjo)n{=8G1MB8aRC?>(GLlkvoj^@|VY(?1m7 z)+o0Ymi`gzI@5R#_z2ebK?k{SM3S3N2v!bYuV78UmxJZ+r}ebH9*s~8uBj&n>Ha-z zU`QVx3~@5{W<<kAYqh27C{=!#3-&4qtQ`9Yyp_^K~ufKhNAiUUX+iPWN(K z+g-|;EY^HDuGntzV$ze#s;ZDlAnle9WzibpT2y`Jn3Hw60IGt1MdPG+Sfy_C9rB6J zUAgj}gtsYYGss^6XBoFhxC~ZPw2;E)IerJbZ$oA=i>ucYRtVoj-b0I#lwzaSgzC z?AKF9?jj5AZnNDqcNx-Nq#I)KD%U0V7r=u4hN4~(@M-tbgz1BO{_KV{i34bTm?;r6 zkXHb$Vs&9Y3a^w3wCK#4eyC+BqDGI$^?XGtlf1G_kQ$dXUJwTCwj^wo1tn`I9tsQl z;ANOnap0Ch&nNi5{^Ma)u;D>Vr03e&ihn&6K^K*solW-7fTVG7NW$eDT>HWg?osN} zy^^!FV`Ei07tZRi!pe`|m`tf$Rr6VpeH-fok8Noa zhzOi-(ziJrXEa?f>IAD*xM7hCgY_|))bsanh%Q?+8+HuBfzeD0|2BS94W03<0@j@FL?R)|FT>s)4-LH7);Dh)0^;ZbVB>*(#vX`tc(>j*0nHoxR z`Mi-Evpz|^`a?io;(H&0CkA?i+9(b~2SMwBp@1BJlX4C#m=MC&yjWTuA!mmoj-vZ7_F-Hz)A#-4~39u@5z$tD{kAj*!Mcb zXVhADOYXAb2mj-o1p-fU{rc~p9asm8S8?ERiA#i52AQMK|1yBuFV^1+yucVb&wNjZ1%2-*R<(b@MO8jbN8#W~s_&Rv*f9 zbg_HFkb5~X5g^Oq&jF*Go-}w4k)N?}VgDN{cxic$d1~T+E;SySWHXvHc84SsRM-{1 z%divR!i8*fBDBr;IM}+<(LwnC)iRXZy(EH|yUWYs;?RizY%@-xH2~dl)(Koq>(!5X zhN-Up6S7pAX^t0r1z`js5D4M{Q4A{>5m*sp9%xQVg&@sOc9MMg@pw`m@I8MNW&p)8 zm*NzAs#TW)!JNXzUtm#IVG&0mCnu~Y#H9=Kwr`(5tO0#Kn%CA3ult1+j_6lYA?{vL z=kZInl>h=GeSLKJWP-pn@ZW$^zPmD; zz!3gIZ&Z@>?isW8%@Fi+GlsH`_O9DGVD{ z13?~cm6fznC9F_z>hs1rB^#q+^D_K>Je1YaWOz}f5vh~9^7~cGzxY+?dW5x}Ox*M& zL;LmHjA02e^@It@EAyplP5hTJ{rS1MJ$6q+1TfjeWZO4s5GchgO?)JKEB$8!d}GNh za~-0p8qg52_~Ory3g6JGBT5|OHHG=N5ci}k059elt!6BOB!rWh=sVob>pE}5j z;|a+>>0ub;T~i?xKsot3ao@cx&v;PwfRh>jdXihXibUr7wKu_$^P(B3CQ_NQvxkiR zt+p#9Bxt20j2Vh2pO>yM2C!MV#UNy&%ZU@Bk+t8TVZOVHmE2b^tMLP`jJ;x*7)g5i zzsxY%a^6xq(VoBaG6Y3xu{mt=_30Fpesvzo0|p4mz{jOSV6=AaqH@1}{hHj7#XiG8 zK%3c!nE;*xMp5|q_<1AekW>wsASjXNu9JX)!>!b8rTxN%O7i*(7_k1vH)MXXu!)>T z^jEYdJZnv_KcW?KUcH)4ZUT`ZsC#z`*DY@XeDL3NWQgTf+G$2G66%-F8yc3jrg*4g zJ8_{s85anzP+4@6N81hh#wl5xL{PGTyb;A^Gg@K>=OuY)SO$0~I6$}&f?hju)>`x# z#il=@@Tb81MTCKBOjrS$Yv?J z;vvuUDuh+$YQC?n92{O#qW<;z!8s(Pr&Qih5N2LZD>i8S4Y1yTG&9rh8xyY+G%X-G zh6^VrvGdR96FAA>jXOIrP?HBW{A#-h!poyazaY2|x9c4^jo^V9> zU=<0Ao(Yxp0bjlc6i0}W2BD-RX7TjYt_1bO$iziV21DdSNo{Cu^UmBBGIMfhJ_j{4 zc5N{QE%VdPMw<;ghxgm{=r|9QL z9Eu6)lXoI>LXlQ@1k?0fEz2-G1WkKgi7Z!=F%Ey^u$~U)g+bOKDe_SRN^lLGKZXwV z{{0TZ5|U=dv}p_yWXeUZEl1VDWLg>gz*$N{f=BXd*{iZL2FdU+dQfDb1mXW@4HYm4 z^ehLb6L<#Q!#hi!5Cwu}v`T_Q{SBuC{|3zwofBO-smVnyJT`=XX+I6*!`w` zL}>nm#Zl+9*v($DHus2Zl=bV3E$cbxX(RZJ&<7umperhpTjTZn-||*BM1(9RvxqN6 z`Np40(?3?B>iWuH7JA5suBRA3x+a;g4ObOzMWaQ#7gi`Nb>i8_A8($Et{ySl9UvPn zqt8z%vfe&D)-ATVY)d2g{`uwCuN}%m#l{Zf27w4x+$OGppmf8S?YtN)C`bJO87^e# zZSJSaLqofiY&Vv$U2reCSM5Auh#5v!Nln{r`RVxr0Sf17L7G9F|NAdOFc!~S5WCiZ zDG>Pb;B7YXX3f>^0S;}SJ}p7%0Lr%Bi!ZYgp1!n+BV3?UtB&UrU_?n|v7O|y1TqFl zsR_4N`~FW)o^UmbGIv~UeJG?;*Vj|xXqHf&Ras77<4D1re_1)`G#K>VyO#QWf%bMP z;;{xk6IOcB+pE7qeom;`Xl0;-3N{D4`*tXnRkVN&*p2Eu;8$6PE+aAhTrzpum|s|} zG3^`Rthoo_E#(5@vjL3&vm+f5C{3<~ghs#3CPb3I;0d^G4=PoSIcnq08g3_|Q)@Cb z51WZ-Bokx?#&T@d1z+Pkd|}3Qz^nU5W>FeQtFj(Bc<9hB0t&02OG#Kz1GjT5VW~mX zK*Eb+o@l-{)3t|zc@6IH+e64n+Oe=n3nAr=5YJ`9Qxm_Pn7lXVcBR|P>w(1a$2@@) zVSZdPw13~eb*-&)<4YrEt>%=g%!)HtW4s?264;Rs1mjI*)%Cl`$pI*IY!n8$M zL%Jft-0Umlr$f@R43W-E!VXZdzlw@rq=6bt{QRo0Q2LrMGEMc!0x?5mB^6wUJI~PT z-@^pewVIJeGyn4aWTm|toVrj%9QV@lsvaqgLTx%7luzK0$BrF4v_r-3Y;o2}7nW{B z>7pJs+5YSHdXqiq8KbOWn7s_EX=MnDxxZ-_2pa$o?;TnO{$}`cT^IE1deO-7`HcGu z0G<(pJnrngjk51x!wejjOcZKsjOFsd3v=FGWpt41-J1|uKyJY26rTjUOm7H`KsEGF zMWxFl&D8)H94+_2;6)d8|7tXw8*AKa{%I<8;?h)>keE@ThYzn4e28_s2fS;$$mfHJ zJvf~p4n9I~9?dSv8|aIfx33%&cqUcv%ptaYAKt%jheg<2ZM3GQ*hQ?>GTVnR#?4g4 z1Pirv%e`7Qzm58o!ys|9^uNbvoXE84ht2ZNXR%`wSdirl-ka}z{qzYXfT9G-#nzgf znhygIRVXUcxY8!fm?8c0b!q8>MT>5+Jk&I<8{$CgZi8Q;h=_v6%&8W(c)IxHw4Ee0 z0BYe;-2QmY`+%%dhn#*T+WRt^l#WBuw7 z0}m0ueuy~vVWdI72_MdGP8OZ!m)%7Fhw_wNID{@h`OoP9Akcs9%gahq;;@pZU_Vxe zmLJ|5020VE2F}9jIBC=K)anzr0TIlvGk4L&fLMNMZ(pbxAw+;~JJ~gim#!gJRUcl(p1n zZ)3KKpnAJe`H>5Nwxh9o#a5rerEe?rJhGBx9vVFtwVb9XxhZJrv}w+kZIbt&H@%rS zr~dJgq7&(>|9EiZ`#P6px18PMs+6|4Z_+Y6DAoAEYqLQVzMj9vt6bkXPI*Ib$%o4- zf98KbKett7V9RUoR=;oE+bo+a?6VX9PCD1^cL%*5MZi8Q=NVf9IaP?gL5VSP z=qPwiKlU-R0OiaX!Gn8eydoZ}Vv0Dp@tyr^@q|#0(d02yoHFuB+!*+*^&3RX)-EAm zp0^X&cR~D|YMOXZYRCZ1H|%rNaFUtuC;ti^7A?3J^_b>;PaUVRdM*3g)VCTkh%unE z%o`kL1<~~o7RH+wWP!T1-JC3Ko;#dKOkU7&W5)DLC|dLQM6!Ez1_vYH4lCUjV^PZV zE{e$?K1)GEX(mctQrhl4m`Ah^&sJ_P!;v_Wb;Hba|Lp=w9vs z(lVZ!H7)Jz-fO%!Cmt#YLQzwBAD<-k%o&Soe_3l=&t%P?l?I>+2q;(Opi#ks7Y&{e zw4Hi~I0*Vpnnt|jt&JZUf>CqdmMPIiBgGC8Wj0_%KuJx_iX{4<@~wKW0rWh^XIh_}IMYjg9Vgf2 z%fsJ^w9Qp8s7k5fdI5_m&YnbRiiGXJCq^Wa{p2$?-yn8t%jA-( z=Do)Q*?e5)x&NW=3k5|e)ZA2rZAz*wg0?5;5_$7eq%%0HMEc>BloSF z@zM8Z^nXb3i^SzuZAL?j^#SiV- zL%6rD%i~Vk!tAa|=>tZyr;8rquPAF`r62GVc;<+9#!IW-`7~q0hL51306~-mVl93l zbOH4GH0>$xw_FH-$YtA;Cr)%4Ei$L70^!Vw=R8Ju$yN%K6iIh}xT0i%UZSv|T1I%- z_@N+W)@57&KQA$Ka*9Vj8l~iMJ97(yiM_Tlw`&$0TWbAFob&QZnQO<=BLz++uBkin zmpKC%As3^R^5{`y`o-BjWMj3p^)V|AU}vWGRWaG*Lu6KKJv98s_W0t*eU+5dXIXI| zPXAb`xBB5Rcv@6Zd%l?I=&1jQ>N@oMb=AToD1fWMf(xg@?d)5&qNgDj#Ans6I_8Kg zJ1=SCP8>nH#4`c7&~dNrN72#O#v*MBvIhUy(tJ)s{!HEtlOJDs_UwaeH=t9ZgF*D& zgfJDSSGPuk6CfSP0YB_lVqgO!Jy&8Kr86yIQKq<+==^NyyG0_QwY}wZOz$y7py!e zz5bCVvw4N>J}Biw8NUybkH$$$|4Y&e2luGiC*M{qA?ov=d-wKDJk3lxFMcKxUyuxh zyw#JVAt9AA&l)#{vW}c|?~DIVet|+aD%KucYWeb*h=@NUW=&iFM{yv^mIW8B0oB1r zrk|T9$66njhVNYK^lorD%bXkEz9mgG)2B7obla;YFQnyB*6+#^2Z+cRz>rK$DvvYR zqz*oUeja3oatKCH=fR1Djox|98YJvlZFhSMQlKq02Vp;wE7DE`sld7eMo-_i4b5_A ztKGHVTe~8RY^*rlPWrAOcEn(?um9{yGJ86HlFL$4rR9tWL3O^J-HFkUqfR63fQV<6 zIO`+b`%=@{*a0n60lqdjnZiT%&bh_D z8IE~D0DGDCi6qu0{eDwjDo#3xNy;Q1tjI@&C$+J3;C!HTpG!=~n8IZk9r2JUJ|n}h zxbib|J%1F1g)TocvvSN=KXR@LemoL%1h2ElY-dL}W25Q&2yzcG^Luv-%oC^prQmEI z5ed~*b39r8OIL^r1SF70K~Q6Od7UVF$19JO0^R@ENt049UHTWrALr89is=OBEKQh$ z=yZbu^9tg!E;H%#HheZb@T7E;iNKzOn(6{$ejo9nU$5Q7hcx@fa;?QZ!w*TXB*rmx z1M>5=pq2@Azbu0zY@^+*msTYT4bvAvnWX>HaPUaIiHbRV zn1e~%r^TKD9^iayN6YN2>?XUZbGIQ5FKq%rYU}*8YJY(e0>LfsZ4XZ8Fg}UHo4k}{ zJFo*2qkmD5lY0r}Ngg1I7qqn>QN~_LN{Tbx=Fh}Vs0EcC4L|XgRbR}tBG;==%X)J& z>{Y@r9`>%qfipWR2)F9k+!DLY_y4t?<3Cf=glr)H1 zM$U~DjQ`Xsp^BWb(fISv)y~dHZn#MpCK!LxT znjTUz_4JzwgoQI>(k;ubzmtW@lpw^);3-<%h!g=ejnjL)hyWtg0ei%aSK>9c z$|;!LrO)L7U=iSeTzZrc`H|;`cuf#fNVH!YX1(NQ2=;3%y=G}>sL6HLrq}nu@*kbD z7c5AYJ@C*Z1>jB<#%P4uWbalMe&$YHri z0>c?KX!^vVNAC6h(_om9X&c6OhPp0cuY#t)5E#vDJ}`%FhRHUF>6AWrl(x_L4(A$^ zNRp5zk+%4=r)_>~f(3B4y}7v~q6K8Yqh9N5DT{-fx~hdH?N^qt5b0ME)U;yZ7m?W4 zYbEd!jlXhsDh3hMiK4QS&VC%n31`a*>HNABwiqKfZ$j0akf|54Y4u`qdeL-UeE#|V z*b{P=&mKSjh-{rPxCTx`#q1`1I}Q##v21!~poKF^=2y);rjaH@#K#1A4Vu!z;E6yE zzw92MfvBte^@hneu^l_R#S4VJMjA4oVQ|ZC`V(|WDnhI%(3FLF`2u-({korLc*7l? zb(fa=yT)MXpx&bQR}4Hm_CrUT1%U?l;vbpI)^Vgzm{w~Xu;H%T^4$t7QoIkB?t|UI zTV@XK>1OjDUTie3cqz3{szmg~%zVHo!2JrC- zh`5BU+E$$Jvz%}D>y|%Gt#mB7?f^W-(?eev0tLgN(~M{`t~VhY7mQerTalxMXB=~T zIA9xbMB64W!f^#aw$*Bt0Nf#nVjs?o!ZW@(vpwr_Ma5R5WLU8$H8uLsL6{8aa^p!O z;3l>QBsVC@+8Fzw;ls|+wxc&1`89T(-39AJ_bsJdf3bza$W52Hz5Pyj zuc^gq4eYl?X7?3%^1KGkuA=x32&boK<}4{&%>W;dh*a;pk_jRZ=*=U{lB8`ZZ-_O| zLR*oUk)cmmL-n`H^C&sr+_m5R;}p*@gMXgiIhn=ZBC$G(;>O@Q9x$rpR m3GkyCslV0g^*?=_p-xrNv~}vLx;cl$y3~tTL|={Cbl?y2Rhzf~ literal 0 HcmV?d00001 diff --git a/ext/wasm3/extra/shareup_app.svg b/ext/wasm3/extra/shareup_app.svg new file mode 100644 index 0000000..875a8b1 --- /dev/null +++ b/ext/wasm3/extra/shareup_app.svg @@ -0,0 +1 @@ +Shareup \ No newline at end of file diff --git a/ext/wasm3/extra/testutils.py b/ext/wasm3/extra/testutils.py new file mode 100755 index 0000000..97eccc6 --- /dev/null +++ b/ext/wasm3/extra/testutils.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 + +# Author: Volodymyr Shymanskyy + +import os +import re, fnmatch +import pathlib + +class ansi: + ENDC = '\033[0m' + HEADER = '\033[94m' + OKGREEN = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + +class dotdict(dict): + def __init__(self, *args, **kwargs): + super(dotdict, self).__init__(*args, **kwargs) + for arg in args: + if isinstance(arg, dict): + for k, v in arg.items(): + self[k] = v + if kwargs: + for k, v in kwargs.items(): + self[k] = v + + __getattr__ = dict.get + __setattr__ = dict.__setitem__ + __delattr__ = dict.__delitem__ + +class Blacklist(): + def __init__(self, patterns): + self._patterns = list(map(fnmatch.translate, patterns)) + self.update() + + def add(self, patterns): + self._patterns += list(map(fnmatch.translate, patterns)) + self.update() + + def update(self): + self._regex = re.compile('|'.join(self._patterns)) + + def __contains__(self, item): + return self._regex.match(item) is not None + +def filename(p): + _, fn = os.path.split(p) + return fn + +def pathname(p): + pn, _ = os.path.split(p) + return pn + +def ensure_path(p): + pathlib.Path(p).mkdir(parents=True, exist_ok=True) diff --git a/ext/wasm3/extra/utils.mk b/ext/wasm3/extra/utils.mk new file mode 100644 index 0000000..f5ce9ea --- /dev/null +++ b/ext/wasm3/extra/utils.mk @@ -0,0 +1,39 @@ +.PHONY: format + +all: + +format: + # Convert tabs to spaces + find ./source -type f -iname '*.[cpp\|c\|h]' -exec bash -c 'expand -t 4 "$$0" | sponge "$$0"' {} \; + # Remove trailing whitespaces + find ./source -type f -iname '*.[cpp\|c\|h]' -exec sed -i 's/ *$$//' {} \; + +preprocess: preprocess_restore + cp ./source/m3_exec.h ./source/m3_exec.h.bak + cp ./source/m3_compile.c ./source/m3_compile.c.bak + awk 'BEGIN {RS=""}{gsub(/\\\n/,"\\\n__NL__ ")}1' ./source/m3_exec.h | sponge ./source/m3_exec.h + cpp -I./source -P ./source/m3_compile.c | sponge ./source/m3_compile.c + awk '{gsub(/__NL__/,"\n")}1' ./source/m3_compile.c | sponge ./source/m3_compile.c + mv ./source/m3_exec.h.bak ./source/m3_exec.h + +preprocess_restore: + -mv source/m3_compile.c.bak source/m3_compile.c + touch source/m3_compile.c + + +test_rv64: + riscv64-linux-gnu-gcc -DDEBUG -Dd_m3HasWASI \ + -I./source ./source/*.c ./platforms/app/main.c \ + -O3 -g0 -flto -lm -static \ + -o wasm3-rv64 + + cd test; python3 run-wasi-test.py --fast --exec "qemu-riscv64-static ../wasm3-rv64" + rm ./wasm3-rv64 + +test_cpp: + clang -xc++ -Dd_m3HasWASI \ + -I./source ./source/*.c ./platforms/app/main.c \ + -O3 -g0 -flto -lm -static \ + -o wasm3-cpp + cd test; python3 run-wasi-test.py --fast --exec "../wasm3-cpp" + rm ./wasm3-cpp diff --git a/ext/wasm3/extra/wapm-package/README.md b/ext/wasm3/extra/wapm-package/README.md new file mode 100644 index 0000000..0174c86 --- /dev/null +++ b/ext/wasm3/extra/wapm-package/README.md @@ -0,0 +1,105 @@ +# Wasm3 + +[Wasm3](https://github.com/wasm3/wasm3) is the fastest WebAssembly interpreter, and the most universal runtime. +It's packaged into a `WebAssembly` package, so you can finally run `WebAssembly` on `WebAssembly` 😆 + +## Running on WebAssembly.sh + +Open [**WebAssembly.sh**](https://webassembly.sh) + +First you need to fetch a wasm file you'd like to run: + +```sh +$ curl https://raw.githubusercontent.com/wasm3/wasm3/main/test/lang/fib32.wasm -o /tmp/fib32.wasm + +$ ls -l /tmp/fib32.wasm +---------- 1 somebody somegroup 62 1970-01-19 05:45 /tmp/fib32.wasm +``` + +Now we can run `wasm3` in interactive mode: + +```sh +$ wasm3 --repl /tmp/fib32.wasm +wasm3> fib 20 +Result: 6765 +wasm3> fib 30 +Result: 832040 +wasm3> ^C +$ +``` + +Or run a specific function directly: + +```sh +$ wasm3 --func fib /tmp/fib32.wasm 30 +Result: 832040 +``` + +`wasm3` also supports `WASI`, so you can run: + +```sh +$ curl https://raw.githubusercontent.com/wasm3/wasm3/main/test/wasi/simple/test.wasm -o /tmp/test.wasm +$ wasm3 /tmp/test.wasm +``` + +or even... run wasm3 inside wasm3: + +```sh +$ curl https://registry-cdn.wapm.io/contents/vshymanskyy/wasm3/0.5.0/build/wasm3-wasi.wasm -o /tmp/wasm3.wasm +$ wasm3 --stack-size 100000 /tmp/wasm3.wasm /tmp/test.wasm +``` + +## Tracing + +You can also get structured traces of arbitrary WASM file execution (and this requires no specific support from the runtime): + +```sh +$ wasm3-strace --repl /tmp/fib32.wasm +wasm3> fib 3 +fib (i32: 3) { + fib (i32: 1) { + } = 1 + fib (i32: 2) { + fib (i32: 0) { + } = 0 + fib (i32: 1) { + } = 1 + } = 1 +} = 2 +Result: 2 +``` + +WASI apps tracing is also supported: + +```sh +$ wasm3-strace /tmp/test.wasm trap +_start () { + __wasm_call_ctors () { + __wasilibc_populate_preopens () { + wasi_snapshot_preview1!fd_prestat_get(3, 65528) { } = 0 + malloc (i32: 2) { + dlmalloc (i32: 2) { + sbrk (i32: 0) { + } = 131072 + } = 70016 + } = 70016 +... + strcmp (i32: 70127, i32: 32) { + } = 0 + test_trap () { + a () { + b () { + c () { + } !trap = [trap] unreachable executed +... +==== wasm backtrace: + 0: 0x000c59 - .unnamed!c + 1: 0x000c5e - .unnamed!b + 2: 0x000c68 - .unnamed!a + 3: 0x000c72 - .unnamed!test_trap + 4: 0x000d2c - .unnamed!main + 5: 0x0037c9 - .unnamed!__main_void + 6: 0x000edb - .unnamed!__original_main + 7: 0x0002f3 - .unnamed!_start +Error: [trap] unreachable executed +``` diff --git a/ext/wasm3/extra/wapm-package/build/.gitignore b/ext/wasm3/extra/wapm-package/build/.gitignore new file mode 100644 index 0000000..86d0cb2 --- /dev/null +++ b/ext/wasm3/extra/wapm-package/build/.gitignore @@ -0,0 +1,4 @@ +# Ignore everything in this directory +* +# Except this file +!.gitignore \ No newline at end of file diff --git a/ext/wasm3/extra/wapm-package/wapm.toml b/ext/wasm3/extra/wapm-package/wapm.toml new file mode 100644 index 0000000..54b6b27 --- /dev/null +++ b/ext/wasm3/extra/wapm-package/wapm.toml @@ -0,0 +1,25 @@ +[package] +name = "vshymanskyy/wasm3" +version = "0.5.0" +description = "🚀 The fastest WebAssembly interpreter. You can finally run WebAssembly on WebAssembly 😆" +readme = "README.md" +repository = "https://github.com/wasm3/wasm3" +homepage = "https://github.com/wasm3/wasm3" + +[[module]] +name = "wasm3" +source = "build/wasm3-wasi.wasm" +abi = "wasi" + +[[module]] +name = "wasm3-strace" +source = "build/wasm3-strace.wasm" +abi = "wasi" + +[[command]] +name = "wasm3" +module = "wasm3" + +[[command]] +name = "wasm3-strace" +module = "wasm3-strace" diff --git a/ext/wasm3/extra/wasm-symbol.svg b/ext/wasm3/extra/wasm-symbol.svg new file mode 100644 index 0000000..1323482 --- /dev/null +++ b/ext/wasm3/extra/wasm-symbol.svg @@ -0,0 +1,71 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/ext/wasm3/extra/wowcube.png b/ext/wasm3/extra/wowcube.png new file mode 100644 index 0000000000000000000000000000000000000000..f6c069c7a23debc19a7598d84da539fa5af55a3a GIT binary patch literal 28449 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 literal 0 HcmV?d00001 diff --git a/ext/wasm3/platforms/android/.gitignore b/ext/wasm3/platforms/android/.gitignore new file mode 100644 index 0000000..11b5322 --- /dev/null +++ b/ext/wasm3/platforms/android/.gitignore @@ -0,0 +1,9 @@ +.gradle +# Build output directies +*/.externalNativeBuild +/target +*/target +/build +*/build +*/.cxx + diff --git a/ext/wasm3/platforms/android/README.md b/ext/wasm3/platforms/android/README.md new file mode 100644 index 0000000..1f408d7 --- /dev/null +++ b/ext/wasm3/platforms/android/README.md @@ -0,0 +1,26 @@ +## Build for Android + +

      + +Install OpenJDK 15, [Android Command Line Tools](https://developer.android.com/studio#cmdline-tools), then: + +```sh +export ANDROID_HOME=/opt/android-sdk/ +export PATH=$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$PATH +``` + +Install NDK: +```sh +sdkmanager --install ndk-bundle platform-tools +``` + +Build: +```sh +./gradlew build +``` + +Install on device: +``` +adb install -r ./app/build/outputs/apk/debug/app-debug.apk +``` + diff --git a/ext/wasm3/platforms/android/app/build.gradle b/ext/wasm3/platforms/android/app/build.gradle new file mode 100644 index 0000000..025c86b --- /dev/null +++ b/ext/wasm3/platforms/android/app/build.gradle @@ -0,0 +1,33 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 29 + ndkVersion '22.1.7171670' + + defaultConfig { + applicationId 'com.example.wasm3' + minSdkVersion 23 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), + 'proguard-rules.pro' + } + } + externalNativeBuild { + cmake { + version '3.10.2+' + path "src/main/cpp/CMakeLists.txt" + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' +} diff --git a/ext/wasm3/platforms/android/app/proguard-rules.pro b/ext/wasm3/platforms/android/app/proguard-rules.pro new file mode 100644 index 0000000..b7420a7 --- /dev/null +++ b/ext/wasm3/platforms/android/app/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /Users/gfan/dev/sdk_current/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/ext/wasm3/platforms/android/app/src/main/AndroidManifest.xml b/ext/wasm3/platforms/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..2081ab0 --- /dev/null +++ b/ext/wasm3/platforms/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + diff --git a/ext/wasm3/platforms/android/app/src/main/cpp/CMakeLists.txt b/ext/wasm3/platforms/android/app/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000..d4d63ec --- /dev/null +++ b/ext/wasm3/platforms/android/app/src/main/cpp/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.4.1) + +add_definitions(-DANDROID -Wno-format-security -O3 + #-fno-optimize-sibling-calls + -flto -fomit-frame-pointer -fno-stack-check -fno-stack-protector) + +file(GLOB M3_SRC FOLLOW_SYMLINKS "m3/*.c" "*.c") + +add_library(wasm3-jni SHARED ${M3_SRC}) + +set_target_properties(wasm3-jni PROPERTIES LINK_FLAGS "-flto -O3") + +# Include libraries needed for wasm3-jni lib +target_link_libraries(wasm3-jni + android + log) diff --git a/ext/wasm3/platforms/android/app/src/main/cpp/jni.c b/ext/wasm3/platforms/android/app/src/main/cpp/jni.c new file mode 100644 index 0000000..115c6a4 --- /dev/null +++ b/ext/wasm3/platforms/android/app/src/main/cpp/jni.c @@ -0,0 +1,96 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include +#include +#include +#include +#include +#include +#include + +extern int main(); + +/* + * JNI init + */ + +JavaVM* javaVM; +JNIEnv* jniEnv; +jclass activityClz; +jobject activityObj; + +JNIEXPORT jint JNICALL +JNI_OnLoad(JavaVM* vm, void* reserved) +{ + if ((*vm)->GetEnv(vm, (void**)&jniEnv, JNI_VERSION_1_6) != JNI_OK) { + return JNI_ERR; // JNI version not supported + } + javaVM = vm; + return JNI_VERSION_1_6; +} + +static int pfd[2]; +static pthread_t pumpThread; +static pthread_t mainThread; + +static void* runOutputPump(void* ctx) +{ + int readSize; + char buff[128]; + + JNIEnv* env; + (*javaVM)->AttachCurrentThread(javaVM, &env, NULL); + + jmethodID outputTextId = (*env)->GetMethodID(env, activityClz, + "outputText", + "(Ljava/lang/String;)V"); + + while ((readSize = read(pfd[0], buff, sizeof(buff) - 1)) > 0) + { + buff[readSize] = '\0'; + + jstring javaMsg = (*env)->NewStringUTF(env, buff); + (*env)->CallVoidMethod(env, activityObj, outputTextId, javaMsg); + (*env)->DeleteLocalRef(env, javaMsg); + } + + return 0; +} + +static void* runMain(void* ctx) +{ + (*javaVM)->AttachCurrentThread(javaVM, &jniEnv, NULL); + main(); + return NULL; +} + +JNIEXPORT void JNICALL +Java_com_example_wasm3_MainActivity_runMain(JNIEnv* env, jobject instance) +{ + setvbuf(stdout, 0, _IOLBF, 0); // stdout: line-buffered + setvbuf(stderr, 0, _IONBF, 0); // stderr: unbuffered + + // create the pipe and redirect stdout and stderr + pipe(pfd); + dup2(pfd[1], 1); + dup2(pfd[1], 2); + + jclass clz = (*env)->GetObjectClass(env, instance); + activityClz = (*env)->NewGlobalRef(env, clz); + activityObj = (*env)->NewGlobalRef(env, instance); + + pthread_attr_t threadAttr; + pthread_attr_init(&threadAttr); + pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED); + + pthread_create( &pumpThread, &threadAttr, runOutputPump, NULL); + + pthread_create( &mainThread, &threadAttr, runMain, NULL); + + pthread_attr_destroy(&threadAttr); +} diff --git a/ext/wasm3/platforms/android/app/src/main/cpp/m3 b/ext/wasm3/platforms/android/app/src/main/cpp/m3 new file mode 120000 index 0000000..f70c2e0 --- /dev/null +++ b/ext/wasm3/platforms/android/app/src/main/cpp/m3 @@ -0,0 +1 @@ +../../../../../../source \ No newline at end of file diff --git a/ext/wasm3/platforms/android/app/src/main/cpp/main.c b/ext/wasm3/platforms/android/app/src/main/cpp/main.c new file mode 100644 index 0000000..a1bb331 --- /dev/null +++ b/ext/wasm3/platforms/android/app/src/main/cpp/main.c @@ -0,0 +1,70 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include +#include +#include + +#include "m3/wasm3.h" +#include "m3/m3_api_libc.h" + +#include "m3/extra/coremark_minimal.wasm.h" + +#define FATAL(msg, ...) { printf("Fatal: " msg "\n", ##__VA_ARGS__); return; } + +void run_wasm() +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)coremark_minimal_wasm; + size_t fsize = coremark_minimal_wasm_len; + + printf("Loading WebAssembly...\n"); + + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 8192, NULL); + if (!runtime) FATAL("m3_NewRuntime failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule: %s", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule: %s", result); + + result = m3_LinkLibC (module); + if (result) FATAL("m3_LinkLibC: %s", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "run"); + if (result) FATAL("m3_FindFunction: %s", result); + + printf("Running CoreMark 1.0...\n"); + + result = m3_CallV (f); + if (result) FATAL("m3_Call: %s", result); + + float value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults: %s", result); + + printf("Result: %0.3f\n", value); +} + +int main() +{ + printf("Wasm3 v" M3_VERSION " on Android (" M3_ARCH ")\n"); + printf("Build " __DATE__ " " __TIME__ "\n"); + + clock_t start = clock(); + run_wasm(); + clock_t end = clock(); + + printf("Elapsed: %ld ms\n", (end - start)*1000 / CLOCKS_PER_SEC); +} diff --git a/ext/wasm3/platforms/android/app/src/main/java/com/example/wasm3/MainActivity.java b/ext/wasm3/platforms/android/app/src/main/java/com/example/wasm3/MainActivity.java new file mode 100644 index 0000000..88e3326 --- /dev/null +++ b/ext/wasm3/platforms/android/app/src/main/java/com/example/wasm3/MainActivity.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.example.wasm3; + +import androidx.annotation.Keep; +import androidx.appcompat.app.AppCompatActivity; +import android.os.Bundle; +import android.widget.TextView; + +public class MainActivity extends AppCompatActivity { + + TextView tv; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_main); + tv = (TextView)findViewById(R.id.console); + + runMain(); + } + + @Keep + private void outputText(final String s) { + runOnUiThread(new Runnable() { + @Override + public void run() { + MainActivity.this.tv.append(s); + } + }); + } + + static { + System.loadLibrary("wasm3-jni"); + } + public native void runMain(); +} + diff --git a/ext/wasm3/platforms/android/app/src/main/res/drawable/ic_launcher.png b/ext/wasm3/platforms/android/app/src/main/res/drawable/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..842fcc88fa9cddf4a23d0ddcb9dfc05a28eff1b9 GIT binary patch literal 6259 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 + + + + + + + + + + + + diff --git a/ext/wasm3/platforms/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/ext/wasm3/platforms/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..c68f603 --- /dev/null +++ b/ext/wasm3/platforms/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/ext/wasm3/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/ext/wasm3/platforms/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..ae9968a03ee40bfd8080caa91bbe4b6e1622d42e GIT binary patch literal 1478 zcmZ9Mc{mh!7{`BuLDNu`OacY~;KO3jM7Co7E?zEn zKVFJ`!xk=YGrSo94cRA;+@WkQL&gyC0K_N)KuHGRfIXtD0T6)%faL}Nst^Ft;L_I1 z7uX99lFdalIKG|zri1Nx!m)Tuo+Sv6ppwAA{@GY|_AnN0X7BU)YcU?@;vn1~pY2X5 z?-W*=m1=khwSJ_I!9DKNk!AK29^4C`XQJ`A))Bm}UZ1Uyi3qcWRjc}9G;+QoU4q(| z83;?6e;ilv9npmBgiFETVXna~?c&_5Sn^e&+31p;;TNl=$A+uZvESMZX#uVsb6$pn zOT|V*zLWAA;@OZq?|1dCrulgRhi#IxRH%K|(3G(Wp&CD==Z^__;Ofj&TRt@v8K`RI z`?;cCd++`vm8a5iNvKi3YhXT1PT3J}=CGY+BPnl}G_ZiUMKU;3!aW$Yed29sk~7Y& zzGT(F+RSf-$g`_Ko$=iSp}>G5Y059dGZLTjkLGZ$`BFJwLzdVpqd@E5v?lSK21;=A zCZP}C)g-oPNHNb59pkcB+0o=Afm9(6k@lIWafjv#Io3Uv{j%b|fNt%5d-T()bd|RX zCJ(z+8oxGIv}3m1mCbG7TM|K?x3jV8CYU00_a*6_tJf|Ko212DaC%Zsi6abpmSLH+ zw|hz--^2NxwD}#M$gU|Si(=@6p$p^w?Ub9lyw@?!6Rnx${Yuk1m(^})m&7?9a5&b) zjH6tye36@?TaC}|R!hg?)YCRBQnYqcP!Cs@2Xq~B=ekIPUSEW2VRgZWi^i+!E=t`^!V8@g!7_0kn0}vpxm+>4gt)`J7 z)%fQ|B@Br2fgW`G<%v&wmh^O|r(YN32^{r(KU}b+SuL7zB50|G(o6?qGequm9vrE9 z)%i5lGn!`?np%#Eb`+yw6vdXGrXg?|G3#dQKAs}YMYC2>C0VDJg>7)T<kgeud}VPxy30&S|k@qp7m&m066WQ zXJA~5AOK#zDPQC0#7p^yw(48fP1uFQZctTSR^(z6j7pK24QI*`A@JrlCGRfC1SLp$ z-9pD&baU}trJiud4t*<=VeGAHK9bc9{Fc@HoF+CQiFx4G3@*s#C4zpdfoRS>R1IO> z`*oAfK@sN$g&rA#G^;DyJ}yuMu@>EzMrAVXW~sU1SW+rNQ&xE$7YVi~-_!#ucM^l` z7|}jLwzfZxB3L8=N?~nngoFniV^f@}A0-8PGh4LL&dSb+&MC$rWu?_o^N;27OiNns zv)%WDykTnOoL=p=0Ul!ftE1x62F~MMHJ|xz<3q&ds*cT0QzO^s6*e1t;M&QWTST)2 zdqUpHkPf>Eve#mbon1`!r2heQ!9lsX;jc$wGmX+jPY=ahCXOAzY9g?ok`HOmmoA-o7cD($U-Qu5n=p+2<22Nd;Drfzvm;Zg#YhgOq9Yphb>69V+nvV@l;~`C57%R9v zcAEX{5aE`N;U4bco+xstCtH9PQVXe$)Ko|6+iRXj>1d;nda6h*6cQQMCcgV0An+Ft dU$5x@14xvn{=Y!dNdb2@0I-$>bgj8t;$OU0he!Yb literal 0 HcmV?d00001 diff --git a/ext/wasm3/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/ext/wasm3/platforms/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..7ed0c12a89ca16ca6c8cca572a4fdb94d34e0d03 GIT binary patch literal 1011 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 K)@-YDsec1${}7%4 literal 0 HcmV?d00001 diff --git a/ext/wasm3/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/ext/wasm3/platforms/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..85c1d0671735930948c7d9ec7d6dd0faee35e11e GIT binary patch literal 3769 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 literal 0 HcmV?d00001 diff --git a/ext/wasm3/platforms/android/app/src/main/res/values-w820dp/dimens.xml b/ext/wasm3/platforms/android/app/src/main/res/values-w820dp/dimens.xml new file mode 100644 index 0000000..63fc816 --- /dev/null +++ b/ext/wasm3/platforms/android/app/src/main/res/values-w820dp/dimens.xml @@ -0,0 +1,6 @@ + + + 64dp + diff --git a/ext/wasm3/platforms/android/app/src/main/res/values/colors.xml b/ext/wasm3/platforms/android/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..932a251 --- /dev/null +++ b/ext/wasm3/platforms/android/app/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #654ff0 + #4b3bb3 + #bfd9cc + diff --git a/ext/wasm3/platforms/android/app/src/main/res/values/dimens.xml b/ext/wasm3/platforms/android/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..47c8224 --- /dev/null +++ b/ext/wasm3/platforms/android/app/src/main/res/values/dimens.xml @@ -0,0 +1,5 @@ + + + 16dp + 16dp + diff --git a/ext/wasm3/platforms/android/app/src/main/res/values/strings.xml b/ext/wasm3/platforms/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..8d2f0bf --- /dev/null +++ b/ext/wasm3/platforms/android/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Wasm3 + diff --git a/ext/wasm3/platforms/android/app/src/main/res/values/styles.xml b/ext/wasm3/platforms/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..5885930 --- /dev/null +++ b/ext/wasm3/platforms/android/app/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/ext/wasm3/platforms/android/build.gradle b/ext/wasm3/platforms/android/build.gradle new file mode 100644 index 0000000..4dc1795 --- /dev/null +++ b/ext/wasm3/platforms/android/build.gradle @@ -0,0 +1,25 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:4.0.0' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/ext/wasm3/platforms/android/gradle.properties b/ext/wasm3/platforms/android/gradle.properties new file mode 100644 index 0000000..8c31d11 --- /dev/null +++ b/ext/wasm3/platforms/android/gradle.properties @@ -0,0 +1,21 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +android.enableJetifier=true +android.useAndroidX=true + diff --git a/ext/wasm3/platforms/android/gradle/wrapper/gradle-wrapper.jar b/ext/wasm3/platforms/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..490fda8577df6c95960ba7077c43220e5bb2c0d9 GIT binary patch literal 58694 zcma&OV~}Oh(k5J8>Mq;1ZQHhO+v>7y+qO>Gc6Hgdjp>5?}0s%q%y~>Cv3(!c&iqe4q$^V<9O+7CU z|6d2bzlQvOI?4#hN{EUmDbvb`-pfo*NK4Vs&cR60P)<+IG%C_BGVL7RP11}?Ovy}9 zNl^cQJPR>SIVjSkXhS0@IVhqGLL)&%E<(L^ymkEXU!M5)A^-c;K>yy`Ihy@nZ}orr zK>gFl%+bKu+T{P~iuCWUZjJ`__9l-1*OFwCg_8CkKtLEEKtOc=d5NH%owJkk-}N#E z7Pd;x29C}qj>HVKM%D&SPSJ`JwhR2oJPU0u3?)GiA|6TndJ+~^eXL<%D)IcZ)QT?t zE7BJP>Ejq;`w$<dd^@|esR(;1Z@9EVR%7cZG`%Xr%6 zLHXY#GmPV!HIO3@j5yf7D{PN5E6tHni4mC;qIq0Fj_fE~F1XBdnzZIRlk<~?V{-Uc zt9ldgjf)@8NoAK$6OR|2is_g&pSrDGlQS);>YwV7C!=#zDSwF}{_1#LA*~RGwALm) zC^N1ir5_}+4!)@;uj92irB5_Ugihk&Uh|VHd924V{MiY7NySDh z|6TZCb1g`c)w{MWlMFM5NK@xF)M33F$ZElj@}kMu$icMyba8UlNQ86~I$sau*1pzZ z4P)NF@3(jN(thO5jwkx(M5HOe)%P1~F!hXMr%Rp$&OY0X{l_froFdbi(jCNHbHj#! z(G`_tuGxu#h@C9HlIQ8BV4>%8eN=MApyiPE0B3dR`bsa1=MM$lp+38RN4~`m>PkE? zARywuzZ#nV|0wt;22|ITkkrt>ahz7`sKXd2!vpFCC4i9VnpNvmqseE%XnxofI*-Mr6tjm7-3$I-v}hr6B($ALZ=#Q4|_2l#i5JyVQCE{hJAnFhZF>vfSZgnw`Vgn zIi{y#1e7`}xydrUAdXQ%e?_V6K(DK89yBJ;6Sf{Viv*GzER9C3Mns=nTFt6`Eu?yu<*Fb}WpP$iO#-y+^H>OQ< zw%DSM@I=@a)183hx!sz(#&cg-6HVfK(UMgo8l2jynx5RWEo8`?+^3x0sEoj9H8%m1 z87?l+w;0=@Dx_J86rA6vesuDQ^nY(n?SUdaY}V)$Tvr%>m9XV>G>6qxKxkH zN6|PyTD(7+fjtb}cgW1rctvZQR!3wX2S|ils!b%(=jj6lLdx#rjQ6XuJE1JhNqzXO zKqFyP8Y1tN91g;ahYsvdGsfyUQz6$HMat!7N1mHzYtN3AcB>par(Q>mP7^`@7@Ox14gD12*4RISSYw-L>xO#HTRgM)eLaOOFuN}_UZymIhu%J?D|k>Y`@ zYxTvA;=QLhu@;%L6;Ir_$g+v3;LSm8e3sB;>pI5QG z{Vl6P-+69G-P$YH-yr^3cFga;`e4NUYzdQy6vd|9${^b#WDUtxoNe;FCcl5J7k*KC z7JS{rQ1%=7o8to#i-`FD3C?X3!60lDq4CqOJ8%iRrg=&2(}Q95QpU_q ziM346!4()C$dHU@LtBmfKr!gZGrZzO{`dm%w_L1DtKvh8UY zTP3-|50~Xjdu9c%Cm!BN^&9r?*Wgd(L@E!}M!#`C&rh&c2fsGJ_f)XcFg~$#3S&Qe z_%R=Gd`59Qicu`W5YXk>vz5!qmn`G>OCg>ZfGGuI5;yQW9Kg*exE+tdArtUQfZ&kO ze{h37fsXuQA2Z(QW|un!G2Xj&Qwsk6FBRWh;mfDsZ-$-!YefG!(+bY#l3gFuj)OHV830Xl*NKp1-L&NPA3a8jx#yEn3>wea~ z9zp8G6apWn$0s)Pa!TJo(?lHBT1U4L>82jifhXlkv^a+p%a{Og8D?k6izWyhv`6prd7Yq5{AqtzA8n{?H|LeQFqn(+fiIbDG zg_E<1t%>753QV!erV^G4^7p1SE7SzIqBwa{%kLHzP{|6_rlM*ae{*y4WO?{%&eQ`| z>&}ZkQ;<)rw;d(Dw*om?J@3<~UrXsvW2*0YOq_-Lfq45PQGUVu?Ws3&6g$q+q{mx4 z$2s@!*|A+74>QNlK!D%R(u22>Jeu}`5dsv9q~VD!>?V86x;Fg4W<^I;;ZEq5z4W5c z#xMX=!iYaaW~O<(q>kvxdjNk15H#p0CSmMaZB$+%v90@w(}o$T7;(B+Zv%msQvjnW z`k7=uf(h=gkivBw?57m%k^SPxZnYu@^F% zKd`b)S#no`JLULZCFuP^y5ViChc;^3Wz#c|ehD+2MHbUuB3IH5+bJ_FChTdARM6Q2 zdyuu9eX{WwRasK!aRXE+0j zbTS8wg@ue{fvJ*=KtlWbrXl8YP88;GXto?_h2t@dY3F?=gX9Frwb8f1n!^xdOFDL7 zbddq6he>%k+5?s}sy?~Ya!=BnwSDWloNT;~UF4|1>rUY!SSl^*F6NRs_DT-rn=t-p z_Ga0p)`@!^cxW_DhPA=0O;88pCT*G9YL29_4fJ(b{| zuR~VCZZCR97e%B(_F5^5Eifes$8!7DCO_4(x)XZDGO%dY9Pkm~-b1-jF#2H4kfl<3 zsBes0sP@Zyon~Q&#<7%gxK{o+vAsIR>gOm$w+{VY8ul7OsSQ>07{|7jB6zyyeu+WU zME>m2s|$xvdsY^K%~nZ^%Y`D7^PCO(&)eV-Qw|2_PnL=Nd=}#4kY)PS=Y62Dzz1e2 z&*)`$OEBuC&M5f`I}A-pEzy^lyEEcd$n1mEgLj}u_b^d!5pg{v+>_FexoDxYj%X_F z5?4eHVXurS%&n2ISv2&Eik?@3ry}0qCwS9}N)`Zc_Q8}^SOViB_AB&o6Eh#bG;NnL zAhP2ZF_la`=dZv6Hs@78DfMjy*KMSExRZfccK=-DPGkqtCK%U1cUXxbTX-I0m~x$3 z&Oc&aIGWtcf|i~=mPvR^u6^&kCj|>axShGlPG}r{DyFp(Fu;SAYJ}9JfF*x0k zA@C(i5ZM*(STcccXkpV$=TznZKQVtec!A24VWu*oS0L(^tkEm2ZIaE4~~?#y9Z4 zlU!AB6?yc(jiB`3+{FC zl|IdP1Fdt#e5DI{W{d8^$EijTU(8FA@8V&_A*tO?!9rI zhoRk`Q*riCozP>F%4pDPmA>R#Zm>_mAHB~Y5$sE4!+|=qK0dhMi4~`<6sFHb=x8Naml}1*8}K_Es3#oh3-7@0W}BJDREnwWmw<{wY9p)3+Mq2CLcX?uAvItguqhk*Po!RoP`kR)!OQy3Ayi zL@ozJ!I_F2!pTC?OBAaOrJmpGX^O(dSR-yu5Wh)f+o5O262f6JOWuXiJS_Jxgl@lS z6A9c*FSHGP4HuwS)6j3~b}t{+B(dqG&)Y}C;wnb!j#S0)CEpARwcF4Q-5J1NVizx7 z(bMG>ipLI1lCq?UH~V#i3HV9|bw%XdZ3Q#c3)GB+{2$zoMAev~Y~(|6Ae z^QU~3v#*S>oV*SKvA0QBA#xmq9=IVdwSO=m=4Krrlw>6t;Szk}sJ+#7=ZtX(gMbrz zNgv}8GoZ&$=ZYiI2d?HnNNGmr)3I);U4ha+6uY%DpeufsPbrea>v!D50Q)k2vM=aF-zUsW*aGLS`^2&YbchmKO=~eX@k9B!r;d{G% zrJU~03(->>utR^5;q!i>dAt)DdR!;<9f{o@y2f}(z(e)jj^*pcd%MN{5{J=K<@T!z zseP#j^E2G31piu$O@3kGQ{9>Qd;$6rr1>t!{2CuT_XWWDRfp7KykI?kXz^{u_T2AZ z-@;kGj8Iy>lOcUyjQqK!1OHkY?0Kz+_`V8$Q-V|8$9jR|%Ng;@c%kF_!rE3w>@FtX zX1w7WkFl%Vg<mE0aAHX==DLjyxlfA}H|LVh;}qcWPd8pSE!_IUJLeGAW#ZJ?W}V7P zpVeo|`)a<#+gd}dH%l)YUA-n_Vq3*FjG1}6mE;@A5ailjH*lJaEJl*51J0)Xecn6X zz zDr~lx5`!ZJ`=>>Xb$}p-!3w;ZHtu zX@xB4PbX!J(Jl((<8K%)inh!-3o2S2sbI4%wu9-4ksI2%e=uS?Wf^Tp%(Xc&wD6lV z*DV()$lAR&##AVg__A=Zlu(o$3KE|N7ZN{X8oJhG+FYyF!(%&R@5lpCP%A|{Q1cdr>x0<+;T`^onat<6tlGfEwRR?ZgMTD-H zjWY?{Fd8=Fa6&d@0+pW9nBt-!muY@I9R>eD5nEDcU~uHUT04gH-zYB>Re+h4EX|IH zp`Ls>YJkwWD3+}DE4rC3kT-xE89^K@HsCt6-d;w*o8xIHua~||4orJ<7@4w_#C6>W z2X$&H38OoW8Y-*i=@j*yn49#_C3?@G2CLiJUDzl(6P&v`lW|=gQ&)DVrrx8Bi8I|$ z7(7`p=^Lvkz`=Cwd<0%_jn&6k_a(+@)G^D04}UylQax*l(bhJ~;SkAR2q*4>ND5nc zq*k9(R}Ijc1J8ab>%Tv{kb-4TouWfA?-r(ns#ghDW^izG3{ts{C7vHc5Mv?G;)|uX zk&Fo*xoN`OG9ZXc>9(`lpHWj~9!hI;2aa_n!Ms1i;BFHx6DS23u^D^e(Esh~H@&f}y z(=+*7I@cUGi`U{tbSUcSLK`S)VzusqEY)E$ZOokTEf2RGchpmTva?Fj! z<7{9Gt=LM|*h&PWv6Q$Td!|H`q-aMIgR&X*;kUHfv^D|AE4OcSZUQ|1imQ!A$W)pJtk z56G;0w?&iaNV@U9;X5?ZW>qP-{h@HJMt;+=PbU7_w`{R_fX>X%vnR&Zy1Q-A=7**t zTve2IO>eEKt(CHjSI7HQ(>L5B5{~lPm91fnR^dEyxsVI-wF@82$~FD@aMT%$`usqNI=ZzH0)u>@_9{U!3CDDC#xA$pYqK4r~9cc_T@$nF1yODjb{=(x^({EuO?djG1Hjb{u zm*mDO(e-o|v2tgXdy87*&xVpO-z_q)f0~-cf!)nb@t_uCict?p-L%v$_mzG`FafIV zPTvXK4l3T8wAde%otZhyiEVVU^5vF zQSR{4him-GCc-(U;tIi;qz1|Az0<4+yh6xFtqB-2%0@ z&=d_5y>5s^NQKAWu@U#IY_*&G73!iPmFkWxxEU7f9<9wnOVvSuOeQ3&&HR<>$!b%J z#8i?CuHx%la$}8}7F5-*m)iU{a7!}-m@#O}ntat&#d4eSrT1%7>Z?A-i^Y!Wi|(we z$PBfV#FtNZG8N-Ot#Y>IW@GtOfzNuAxd1%=it zDRV-dU|LP#v70b5w~fm_gPT6THi zNnEw&|Yc9u5lzTVMAL} zgj|!L&v}W(2*U^u^+-e?Tw#UiCZc2omzhOf{tJX*;i2=i=9!kS&zQN_hKQ|u7_3vo6MU0{U+h~` zckXGO+XK9{1w3Z$U%%Fw`lr7kK8PzU=8%0O8ZkW`aQLFlR4OCb^aQgGCBqu6AymXk zX!p(JDJtR`xB$j48h}&I2FJ*^LFJzJQJ0T>=z{*> zWesZ#%W?fm`?f^B^%o~Jzm|Km5$LP#d7j9a{NCv!j14axHvO<2CpidW=|o4^a|l+- zSQunLj;${`o%xrlcaXzOKp>nU)`m{LuUW!CXzbyvn;MeK#-D{Z4)+>xSC)km=&K%R zsXs3uRkta6-rggb8TyRPnquv1>wDd)C^9iN(5&CEaV9yAt zM+V+%KXhGDc1+N$UNlgofj8+aM*(F7U3=?grj%;Pd+p)U9}P3ZN`}g3`{N`bm;B(n z12q1D7}$``YQC7EOed!n5Dyj4yl~s0lptb+#IEj|!RMbC!khpBx!H-Kul(_&-Z^OS zQTSJA@LK!h^~LG@`D}sMr2VU#6K5Q?wqb7-`ct2(IirhhvXj?(?WhcNjJiPSrwL0} z8LY~0+&7<~&)J!`T>YQgy-rcn_nf+LjKGy+w+`C*L97KMD%0FWRl`y*piJz2=w=pj zxAHHdkk9d1!t#bh8Joi1hTQr#iOmt8v`N--j%JaO`oqV^tdSlzr#3 zw70~p)P8lk<4pH{_x$^i#=~E_ApdX6JpR`h{@<Y;PC#{0uBTe z1Puhl^q=DuaW}Gdak6kV5w);35im0PJ0F)Zur)CI*LXZxZQTh=4dWX}V}7mD#oMAn zbxKB7lai}G8C){LS`hn>?4eZFaEw-JoHI@K3RbP_kR{5eyuwBL_dpWR>#bo!n~DvoXvX`ZK5r|$dBp6%z$H@WZ6Pdp&(zFKGQ z2s6#ReU0WxOLti@WW7auSuyOHvVqjaD?kX;l)J8tj7XM}lmLxLvp5V|CPQrt6ep+t z>7uK|fFYALj>J%ou!I+LR-l9`z3-3+92j2G`ZQPf18rst;qXuDk-J!kLB?0_=O}*XQ5wZMn+?ZaL5MKlZie- z0aZ$*5~FFU*qGs|-}v-t5c_o-ReR@faw^*mjbMK$lzHSheO*VJY)tBVymS^5ol=ea z)W#2z8xCoh1{FGtJA+01Hwg-bx`M$L9Ex-xpy?w-lF8e*xJXS4(I^=k1zFy|V)=ll z#&yez3hRC5?@rPywJo2eOHWezUxZphm#wo`oyA-sP@|^+LV0^nzq|UJEZZM9wqa z5Y}M0Lu@0Qd%+Q=3kCSb6q4J60t_s(V|qRw^LC>UL7I`=EZ zvIO;P2n27=QJ1u;C+X)Si-P#WB#phpY3XOzK(3nEUF7ie$>sBEM3=hq+x<=giJjgS zo;Cr5uINL%4k@)X%+3xvx$Y09(?<6*BFId+399%SC)d# zk;Qp$I}Yiytxm^3rOxjmRZ@ws;VRY?6Bo&oWewe2i9Kqr1zE9AM@6+=Y|L_N^HrlT zAtfnP-P8>AF{f>iYuKV%qL81zOkq3nc!_?K7R3p$fqJ?};QPz6@V8wnGX>3%U%$m2 zdZv|X+%cD<`OLtC<>=ty&o{n-xfXae2~M-euITZY#X@O}bkw#~FMKb5vG?`!j4R_X%$ZSdwW zUA0Gy&Q_mL5zkhAadfCo(yAw1T@}MNo>`3Dwou#CMu#xQKY6Z+9H+P|!nLI;4r9@k zn~I*^*4aA(4y^5tLD+8eX;UJW;>L%RZZUBo(bc{)BDM!>l%t?jm~}eCH?OOF%ak8# z*t$YllfyBeT(9=OcEH(SHw88EOH0L1Ad%-Q`N?nqM)<`&nNrp>iEY_T%M6&U>EAv3 zMsvg1E#a__!V1E|ZuY!oIS2BOo=CCwK1oaCp#1ED_}FGP(~Xp*P5Gu(Pry_U zm{t$qF^G^0JBYrbFzPZkQ;#A63o%iwe;VR?*J^GgWxhdj|tj`^@i@R+vqQWt~^ z-dLl-Ip4D{U<;YiFjr5OUU8X^=i35CYi#j7R! zI*9do!LQrEr^g;nF`us=oR2n9ei?Gf5HRr&(G380EO+L6zJD)+aTh_<9)I^{LjLZ} z{5Jw5vHzucQ*knJ6t}Z6k+!q5a{DB-(bcN*)y?Sfete7Y}R9Lo2M|#nIDsYc({XfB!7_Db0Z99yE8PO6EzLcJGBlHe(7Q{uv zlBy7LR||NEx|QyM9N>>7{Btifb9TAq5pHQpw?LRe+n2FV<(8`=R}8{6YnASBj8x}i zYx*enFXBG6t+tmqHv!u~OC2nNWGK0K3{9zRJ(umqvwQ~VvD;nj;ihior5N$Hf@y0G z$7zrb=CbhyXSy`!vcXK-T}kisTgI$8vjbuCSe7Ev*jOqI&Pt@bOEf>WoQ!A?`UlO5 zSLDKE(-mN4a{PUu$QdGbfiC)pA}phS|A1DE(f<{Dp4kIB_1mKQ5!0fdA-K0h#_ z{qMsj@t^!n0Lq%)h3rJizin0wT_+9K>&u0%?LWm<{e4V8W$zZ1w&-v}y zY<6F2$6Xk>9v{0@K&s(jkU9B=OgZI(LyZSF)*KtvI~a5BKr_FXctaVNLD0NIIokM}S}-mCB^^Sgqo%e{4!Hp)$^S%q@ zU%d&|hkGHUKO2R6V??lfWCWOdWk74WI`xmM5fDh+hy6>+e)rG_w>_P^^G!$hSnRFy z5fMJx^0LAAgO5*2-rsN)qx$MYzi<_A=|xez#rsT9&K*RCblT2FLJvb?Uv3q^@Dg+J zQX_NaZza4dAajS!khuvt_^1dZzOZ@eLg~t02)m2+CSD=}YAaS^Y9S`iR@UcHE%+L0 zOMR~6r?0Xv#X8)cU0tpbe+kQ;ls=ZUIe2NsxqZFJQj87#g@YO%a1*^ zJZ+`ah#*3dVYZdeNNnm8=XOOc<_l-b*uh zJR8{yQJ#-FyZ!7yNxY|?GlLse1ePK!VVPytKmBwlJdG-bgTYW$3T5KinRY#^Cyu@& zd7+|b@-AC67VEHufv=r5(%_#WwEIKjZ<$JD%4!oi1XH65r$LH#nHHab{9}kwrjtf= zD}rEC65~TXt=5bg*UFLw34&*pE_(Cw2EL5Zl2i^!+*Vx+kbkT_&WhOSRB#8RInsh4 z#1MLczJE+GAHR^>8hf#zC{pJfZ>6^uGn6@eIxmZ6g_nHEjMUUfXbTH1ZgT7?La;~e zs3(&$@4FmUVw3n033!1+c9dvs&5g#a;ehO(-Z}aF{HqygqtHf=>raoWK9h7z)|DUJ zlE0#|EkzOcrAqUZF+Wd@4$y>^0eh!m{y@qv6=C zD(){00vE=5FU@Fs_KEpaAU1#$zpPJGyi0!aXI8jWaDeTW=B?*No-vfv=>`L`LDp$C zr4*vgJ5D2Scl{+M;M(#9w_7ep3HY#do?!r0{nHPd3x=;3j^*PQpXv<~Ozd9iWWlY_ zVtFYzhA<4@zzoWV-~in%6$}Hn$N;>o1-pMK+w$LaN1wA95mMI&Q6ayQO9 zTq&j)LJm4xXjRCse?rMnbm%7E#%zk!EQiZwt6gMD=U6A0&qXp%yMa(+C~^(OtJ8dH z%G1mS)K9xV9dlK>%`(o6dKK>DV07o46tBJfVxkIz#%VIv{;|)?#_}Qq(&| zd&;iIJt$|`te=bIHMpF1DJMzXKZp#7Fw5Q0MQe@;_@g$+ELRfh-UWeYy%L*A@SO^J zLlE}MRZt(zOi6yo!);4@-`i~q5OUAsac^;RpULJD(^bTLt9H{0a6nh0<)D6NS7jfB ze{x#X2FLD2deI8!#U@5$i}Wf}MzK&6lSkFy1m2c~J?s=!m}7%3UPXH_+2MnKNY)cI z(bLGQD4ju@^<+%T5O`#77fmRYxbs(7bTrFr=T@hEUIz1t#*ntFLGOz)B`J&3WQa&N zPEYQ;fDRC-nY4KN`8gp*uO@rMqDG6=_hHIX#u{TNpjYRJ9ALCl!f%ew7HeprH_I2L z6;f}G90}1x9QfwY*hxe&*o-^J#qQ6Ry%2rn=9G3*B@86`$Pk1`4Rb~}`P-8^V-x+s zB}Ne8)A3Ex29IIF2G8dGEkK^+^0PK36l3ImaSv1$@e=qklBmy~7>5IxwCD9{RFp%q ziejFT(-C>MdzgQK9#gC?iFYy~bjDcFA^%dwfTyVCk zuralB)EkA)*^8ZQd8T!ofh-tRQ#&mWFo|Y3taDm8(0=KK>xke#KPn8yLCXwq zc*)>?gGKvSK(}m0p4uL8oQ~!xRqzDRo(?wvwk^#Khr&lf9YEPLGwiZjwbu*p+mkWPmhoh0Fb(mhJEKXl+d68b6%U{E994D z3$NC=-avSg7s{si#CmtfGxsijK_oO7^V`s{?x=BsJkUR4=?e@9# z-u?V8GyQp-ANr%JpYO;3gxWS?0}zLmnTgC66NOqtf*p_09~M-|Xk6ss7$w#kdP8`n zH%UdedsMuEeS8Fq0RfN}Wz(IW%D%Tp)9owlGyx#i8YZYsxWimQ>^4ikb-?S+G;HDT zN4q1{0@|^k_h_VFRCBtku@wMa*bIQc%sKe0{X@5LceE`Uqqu7E9i9z-r}N2ypvdX1{P$*-pa$A8*~d0e5AYkh_aF|LHt7qOX>#d3QOp-iEO7Kq;+}w zb)Le}C#pfmSYYGnq$Qi4!R&T{OREvbk_;7 zHP<*B$~Qij1!9Me!@^GJE-icH=set0fF-#u5Z{JmNLny=S*9dbnU@H?OCXAr7nHQH zw?$mVH^W-Y89?MZo5&q{C2*lq}sj&-3@*&EZaAtpxiLU==S@m_PJ6boIC9+8fKz@hUDw==nNm9? z`#!-+AtyCOSDPZA)zYeB|EQ)nBq6!QI66xq*PBI~_;`fHEOor}>5jj^BQ;|-qS5}1 zRezNBpWm1bXrPw3VC_VHd z$B06#uyUhx)%6RkK2r8*_LZ3>-t5tG8Q?LU0Yy+>76dD(m|zCJ>)}9AB>y{*ftDP3 z(u8DDZd(m;TcxW-w$(vq7bL&s#U_bsIm67w{1n|y{k9Ei8Q9*8E^W0Jr@M?kBFJE< zR7Pu}#3rND;*ulO8X%sX>8ei7$^z&ZH45(C#SbEXrr3T~e`uhVobV2-@p5g9Of%!f z6?{|Pt*jW^oV0IV7V76Pd>Pcw5%?;s&<7xelwDKHz(KgGL7GL?IZO%upB+GMgBd3ReR9BS zL_FPE2>LuGcN#%&=eWWe;P=ylS9oIWY)Xu2dhNe6piyHMI#X4BFtk}C9v?B3V+zty zLFqiPB1!E%%mzSFV+n<(Rc*VbvZr)iJHu(HabSA_YxGNzh zN~O(jLq9bX41v{5C8%l%1BRh%NDH7Vx~8nuy;uCeXKo2Do{MzWQyblZsWdk>k0F~t z`~8{PWc86VJ)FDpj!nu))QgHjl7a%ArDrm#3heEHn|;W>xYCocNAqX{J(tD!)~rWu zlRPZ3i5sW;k^^%0SkgV4lypb zqKU2~tqa+!Z<)!?;*50pT&!3xJ7=7^xOO0_FGFw8ZSWlE!BYS2|hqhQT8#x zm2a$OL>CiGV&3;5-sXp>3+g+|p2NdJO>bCRs-qR(EiT&g4v@yhz(N5cU9UibBQ8wM z0gwd4VHEs(Mm@RP(Zi4$LNsH1IhR}R7c9Wd$?_+)r5@aj+!=1-`fU(vr5 z1c+GqAUKulljmu#ig5^SF#{ag10PEzO>6fMjOFM_Le>aUbw>xES_Ow|#~N%FoD{5!xir^;`L1kSb+I^f z?rJ0FZugo~sm)@2rP_8p$_*&{GcA4YyWT=!uriu+ZJ%~_OD4N%!DEtk9SCh+A!w=< z3af%$60rM%vdi%^X2mSb)ae>sk&DI_&+guIC88_Gq|I1_7q#}`9b8X zGj%idjshYiq&AuXp%CXk>zQ3d2Ce9%-?0jr%6-sX3J{*Rgrnj=nJ2`#m`TaW-13kl zS2>w8ehkYEx@ml2JPivxp zIa2l^?)!?Y*=-+jk_t;IMABQ5Uynh&LM^(QB{&VrD7^=pXNowzD9wtMkH_;`H|d0V z*rohM)wDg^EH_&~=1j1*?@~WvMG3lH=m#Btz?6d9$E*V5t~weSf4L%|H?z-^g>Fg` zI_Q+vgHOuz31?mB{v#4(aIP}^+RYU}^%XN}vX_KN=fc{lHc5;0^F2$2A+%}D=gk-) zi1qBh!1%xw*uL=ZzYWm-#W4PV(?-=hNF%1cXpWQ_m=ck1vUdTUs5d@2Jm zV8cXsVsu~*f6=_7@=1 zaV0n2`FeQ{62GMaozYS)v~i10wGoOs+Z8=g$F-6HH1qBbasAkkcZj-}MVz{%xf8`2 z1XJU;&QUY4Hf-I(AG8bX zhu~KqL}TXS6{)DhW=GFkCzMFMSf`Y00e{Gzu2wiS4zB|PczU^tjLhOJUv=i2KuFZHf-&`wi>CU0h_HUxCdaZ`s9J8|7F}9fZXg`UUL}ws7G=*n zImEd-k@tEXU?iKG#2I13*%OX#dXKTUuv1X3{*WEJS41ci+uy=>30LWCv*YfX_A2(M z9lnNAjLIzX=z;g;-=ARa<`z$x)$PYig1|#G;lnOs8-&rB2lT0#e;`EH8qZ_xNvwy7 zo_9>P@SHK(YPu*8r86f==eshYjM3yAPOHDn- zmuW04o02AGMz!S|S32(h560d(IP$;S7LIM(PC7Owwr$&XCbsQNY))+3HYS+ZcHTVq zJm;QsfA`#~_m8fwuI~DFb$@pE-h1t}*HZB7hc-CUM~x6aZ<4v9_Jr-))=El>(rphK z(@wMC$e>^o+cQ(9S+>&JfP;&KM6nff2{RNu;MqE9>L9t^lvzo^*B5>@$TG!gZlh0Z z%us8ys$1~v&&N-gPBvXl5b<#>-@lhAkg_4Ev6#R&r{ObIn=Qki&`wxR_OWj%kU_RW&w#Mxv%x zW|-sJ^jss+;xmxi8?gphNW{^HZ!xF?poe%mgZ>nwlqgvH@TrZ zad5)yJx3T|&$Afl$pkh=7bZAwBdv+tQEP=d3vE#o<&r6h+sTU$64ZZQ0e^Fu9FrnL zN-?**4ta&!+{cP=jt`w)5|dD&CP@-&*BsN#mlbUn!V*(E_gskcQ*%F#Nw#aTkp%x| z8^&g)1d!%Y+`L!Se2s_XzKfonT_BWbn}LQo#YUAx%f7L__h4Xi680GIk)s z8GHm59EYn(@4c&eAO)}0US@((t#0+rNZ680SS<=I^|Y=Yv)b<@n%L20qu7N%V1-k1 z*oxpOj$ZAc>L6T)SZX?Pyr#}Q?B`7ZlBrE1fHHx_Au{q9@ zLxwPOf>*Gtfv6-GYOcT^ZJ7RGEJTVXN=5(;{;{xAV3n`q1Z-USkK626;atcu%dTHU zBewQwrpcZkKoR(iF;fVev&D;m9q)URqvKP*eF9J=A?~0=jn3=_&80vhfBp?6@KUpgyS`kBk(S0@X5Xf%a~?#4Ct5nMB9q~)LP<`G#T-eA z+)6cl1H-2uMP=u<=saDj*;pOggb2(NJO^pW8O<6u^?*eiqn7h)w9{D`TrE1~k?Xuo z(r%NIhw3kcTHS%9nbff>-jK1k^~zr8kypQJ6W+?dkY7YS`Nm z5i;Q23ZpJw(F7|e?)Tm~1bL9IUKx6GC*JpUa_Y00Xs5nyxGmS~b{ zR!(TzwMuC%bB8&O->J82?@C|9V)#i3Aziv7?3Z5}d|0eTTLj*W3?I32?02>Eg=#{> zpAO;KQmA}fx?}j`@@DX-pp6{-YkYY81dkYQ(_B88^-J#rKVh8Wys-;z)LlPu{B)0m zeZr=9{@6=7mrjShh~-=rU}n&B%a7qs1JL_nBa>kJFQ8elV=2!WY1B5t2M5GD5lt|f zSAvTgLUv#8^>CX}cM(i(>(-)dxz;iDvWw5O!)c5)TBoWp3$>3rUI=pH9D1ffeIOUW zDbYx}+)$*+`hT}j226{;=*3(uc*ge(HQpTHM4iD&r<=JVc1(gCy}hK%<(6)^`uY4>Tj6rIHYB zqW5UAzpdS!34#jL;{)Fw{QUgJ~=w`e>PHMsnS1TcIXXHZ&3M~eK5l>Xu zKsoFCd%;X@qk#m-fefH;((&?Y9grF{Al#55A3~L5YF0plJ;G=;Tr^+W-7|6IO;Q+8 z(jAXq$ayf;ZkMZ4(*w?Oh@p8LhC6=8??!%@V(e}%*>fW^Gdn|qZVyvHhcn;7nP7e; z13!D$^-?^#x*6d1)88ft06hVZh%m4w`xR?!cnzuoOj(g9mdE2vbKT@RghJ)XOPj{9 z@)8!#=HRJvG=jDJ77XND;cYsC=CszC!<6GUC=XLuTJ&-QRa~EvJ1rk2+G!*oQJ-rv zDyHVZ{iQN$*5is?dNbqV8|qhc*O15)HGG)f2t9s^Qf|=^iI?0K-Y1iTdr3g=GJp?V z$xZiigo(pndUv;n1xV1r5+5qPf#vQQWw3m&pRT>G&vF( zUfKIQg9%G;R`*OdO#O;nP4o+BElMgmKt<>DmKO1)S$&&!q6#4HnU4||lxfMa-543{ zkyJ+ohEfq{OG3{kZszURE;Rw$%Q;egRKJ%zsVcXx!KIO0*3MFBx83sD=dDVsvc17i zIOZuEaaI~q`@!AR{gEL#Iw}zQpS$K6i&omY2n94@a^sD@tQSO(dA(npgkPs7kGm>;j?$Ia@Q-Xnzz?(tgpkA6VBPNX zE?K%$+e~B{@o>S+P?h6K=XP;caQ=3)I{@ZMNDz)9J2T#5m#h9nXd*33TEH^v7|~i) zeYctF*06eX)*0e{xXaPT!my1$Xq>KPJakJto3xnuT&z zSaL8NwRUFm?&xIMwA~gt4hc3=hAde#vDjQ!I)@;V<9h2YOvi-XzleP!g4blZm|$iV zF%c3G8Cs;FH8|zEczqGSY%F54h`$P_VsmJ6TaXRLc8lSf`Sv%s%6<4+;Wbs-3lya( z=9I>I%97Y~G945O48YaAq6ENPUs%EJvyC! zM4jMgJj}r~@D;cdaQ-j#`5zCRku}42aI<>CgraXuKDr19db~#|@UyM;f-uc!(KDsu z5EA@CsN>^t@oH+0!SALi;ud>`P5mQta+Lh*-#RHJ)Gin%>EaFLSoU`(TG7c|yeFvl zk|Yll%)h-*%WoI6M*j+4xw`OqiDVX{k-^V2{rzCIM9mzNHGP^D={!*P7T)%yDSI5- zkGA4}r3`)#Vl6JFJ3xG)8K;FTtII9o7jNHof_Z_Zc<%@-H4RPpyXudpf)ky zmTH$LFGxaIUGQ;l=>R>?+>ZSCU|@&+Gt@5Bj3w{L{KPpgQ<~)jqx0oNZSv9R&^A42 zzqJr?C#D-n>=9FjM=D=7h_$QO$KQ8*%0%)rI(Npai_JjE9_lBk75BQMI zkk4X5PATWgrub!fb5Hxi8{(Y<(GOO8^HECOA)eanyS{u%leQOkp;1W}_8eH?nPQxW zd#Z+uJfTK>g-TR3WPu~2Ru9A+NkuIICM@PyPmJn(GBZt;xFZNDMbw8`xzl2`(?UC- z#<*=*fo{UOvycb|b&4y0Nm!sHhFMI*Y$Olgh;BG#xBU+yxav82Ejj(ZvQ|64Wwy7I zN=DXx7(V^NTH3YRB4HOu6T5=DW86P`L#Ng!SuT{%&>Cq8>|o8lF^^U%MRU41TT?h& z!uJ$YdbM*2y?#`LJ2)XPoKq`hm$I3R{V5-;@u7!E9tH4sR(`Ab-Qh!|UN-a5fZ?P@2LWRvSv!hOk08;Yy!h&uEI-X}j+&v`X` zkqY%*F@{}DHL*Jgjg2}a54hwEV`63bK4>mL%D^YT|>m1-kX{876BRm&`Y#{$&oz($qWJL}T*tj42k+yu8fa=4b7VUPq()Wb~=L?DU0U-4*Iu^KMZBRByWn-@=_f(4){Or#| zpw}~Ajs6a=z!8_H59lqYlfnS77QY0pHpIz0#)}!EGhypupZeZe@%cv z6Dngnl*SsUy^a`v?>lARi6Yps@%32JpGQvrcd*A8LPLEInBEU2vriGvMqG!jh^=Gj zXvu5zpikqnt*e4&Un_e$2FAB?(yOS0JAzxh@nN?Blqc-)Pv`U}&E5|# z)97-9utpqi*`hR+$;eS)A+KK)CO)V`b?*}z&*+28mDfWI31)sF)tBg6LVlxS z225poL+O|x)5;skkj{rew<}TsDVqFMMLSgd;UK7^clMcObM~IgSq6!eJ($JP!KHPr zBJ&SHi{wLsgMzn1^#kV#_!NO@RG@B5lxBO7WfIAi@o`{_XQg(*{R=@Z(0ij+*i7sK zW5D%_fRN7l6qpytW2K1lUqP&W5jDT!AA9@q<;M!T=CKv*^MP)Er_uLL+Y53>**w7Y zQ!2?^4$wC;Soc!+#~d?Yec;NLdR z{~*hrSQS>UOMBe)1pHe0EsyO@d(IrU4ZiS&jL`wqv6Oqv=HbI^70qu9kn~wGkNL^> z!Pd2)i--+&zp^`#4@*Myg;3r(jt*h@RWgRt70byZr;0Na8n4!bmpuX1&gK=QK!@j< zH2fF7@2s0H0!9%VC-BIp(99@e@<%Ko?BB9uv*xPnZ5dQr z8r7~9cZXv(AZPY^<(X@}GARv&_}mfYA7`vdl=)g2GIyN(<}(b_S_N2--NKp$SgO<3 zRx|EabcjUSB44GaH3Kxmx3SW;E;Eia2Zs5SkbkQ8E%VQqr0J?tQjF~p;nbIXn+D;? zg;t3Jg7A@9U**@aaqs}9;%??Scm{zBIY2ceYAQd*W-hB-!+H&4#yrm*GtT*&#`FXx zGIVm}G<;Pj+h*KQ68S4rcIIGw-mkl039s@O4p9F%TC&&&xRL=N49v2PdBb$MxJoMo zQk8+Sv+F5m{xP1prZvn1=x-Q z&Yox|y&arZrLTm~<%o}VfPV#z+i&{)W5emXhx^g~8>eUe)|Vvwp8-x8d-MOj%@mSk zZ9i{-Hu8m-rfO##y(_Rv;Y@?6%h4Id#6%`7ah+IaQ13o7o>bG&ScMj&KO~QoCmNT6()+oo%B zugV3Da)t>unQq=tbD)FP{JmB~S5QCmb)lq9Fp(*|(UGeXr3kR?k35sKFs{{a*y+h0anA_K@iCi;BR6nFmKHC=@)rMmu=XWS1nVqD*=#${cFJ6<{e=U7!Rbg>Y0b~d#&viX+5m9aNAv=RAMt8=n6a&@t^|2LsKMR7xF z;Cmw>t0<=W2II;doX`p#bcjPV9z&3dhAObzcB9xXMslqr(y!P6+2kG>Eh!rx&ZKmW)Wk~_xh`?neJqVhJk~1eTvRF#ehRwpS>s1{vUx*qf&Jm z$)Wh|lmwYatW@U@*$<14>^|yYwmwFs)C5ke9hG42{gilSU#^ulO`M}`wJ_4*-3 zGb?hfQj_AGQBI?4ghGijqfu>uAYkLK#!^uGUXuctdn8Ae5I7}o+j{9MJiM|sf9Nc{ zuP&Ls@?rMe=IfJo!=iX?9&*4!Yjs5d?0Yx4cIFXrkSHRk17Fc@yM__fyFLLl6O9nT zQqaDXunH;!PpQ7+-&#wJVtJXl8LjIkh)5qmcqhErYrP31w5~#!tS{LYTWGKEtbpE%(hH>qV(!2KMfs#a z?ZzzbDB}(7+NWIiSBQ<_{3>;H;z}uZI;n2PKWJNxM=l;5-^zpu-}+1x|38lS-}6GX z6F=M~bUtHg98X@of>mgCH-&5g6UpXGAla<+g`b&MQANW6D^;zfSzq0mQ)*J%;&tPOYin?J*G7GqmQ=>jvWvOn6E?! z{$(CU7}zChEnl$(>xf`ZdeF2E9Bv=eH&T4HWAOQ!9gBs z{gl^|(78q-ioBS^rR2PEGZLe_4Rl**H(bB?84RHquCEKi8N#29u=Eoh(DV`ZX{+8< z3BIX<`sOFNBziFWS#-X%(e`0C_|Q8;Pw9izjNOF8h|kvmWCmDHM&pANC9MV<wEJ;W{-jXqm!zC+Y@Q1y_lLL zfV^(1{A;L%TWmyI)RPknVUB<4r+d42S(W=%bXd@YB(~d>ABq-E;t)ie6%ouy(Fg`p zuj<=I7^PDs5H+UsG}+GH}zoGt*{yKF&n23C7aW@ z4ydrRtFW-uuAUu@RWe&0c!N4!H;`!n@@t#u zxlGQB4rx(F7#&MKHPy}EI;d+l(G{1KG!ZBE)7)@P!AsUCCCb0IH!P5TW=GoNFcif`NB4en16Cp<7=fhz7^uQAjbJBH>@naf2ueMktmtZ|U|)ICDMN2r`mgMSl=qDwHL;}L-d~El>pf8UJRts_03eTj*hVy6H z5o!>?AcffORZq9!NJNa`-W4wMfe6I{3*rYUhIMA>y|T}KZ56HR5XEs{(|x#SDtP@N z5?12L0W7qfvWl8T-V+u=fkBH8!$}g)7hRs34m7~)^S&Ar zd`Kz7$S2Mz(|5H(Dwn$V7n8K2pqhHQ8!i{G4C~Y6_Ex&Y%EyXdw#Nj}VdG`XCN_1n zFg4;3DGjjUo$%=m@ui%z$JU66QK^qywvLKZpD6ZQ2Ve2VBps8rcvJ6^Cf^#H4?UQ5PW$4;b)55yIY9}@k@48RLtJa>7bofX{EUE7 z?0Cx0PeYbbLAelC-BfqHf_08;{lzC1kwr|a>5{O6*g<~wt6KYPfP5uW0w?VTO!M~Q z6H@n{cONp`{>hVjEIkOV6m^ZP^l;mGz=T&*5&`m84astyZ#XZ6CpH384tt%vSJ zsvYDC5u`D&U_u)1OJ&D2=F*ie-7!%N+V6*qoM6m-zj|}hDZ+@?`mJ10OX3K-`+R0m zNk$^+zBJK7%It=_&sIc}&DT>!LYU{|WPNrp-Nfly8u5&3@(l{!pcPxek3^{L`<9*! zE-0KukkD^^+<&3BNJM$e0=~B$=VQEp@V`L+PsUEL-_%+E_kyR-_mUjr|D1Z2J->y2 zZNHTrzP$=uEKQvy4DG&+4*o5^8Kd?eI>5S#b;NXlSrGVnj3~e^OLe4*Qe7%U#4WiX z)k7h@VHRERR_j{wp8ALHdD6bj&+Dl^?2(MuL9*oTRUI3SQ2jJ4x#!GR~b8F(H6|clt%g_O=v(@*;;5eW{e)CsR{UNDIE{C-1@qe z7NY&S7DeI4?z7tR9LJ$e6za%qLsF(>%M?m1nQQ4htpl?P)yj7_C#Ds5k5F z1h@YlI%a#k9x6}=hs(mkRr-fSrmikEk)Iv6D`S==)-dDVbNK;4F@J7iC(M!K6l<^lm@iXKpYbd7b{_0BDjc9ju~tFH7Qfcgu>A9~3tzmbFnXbS(pWES9955Vbu=iI zX>GH$kbD_?_fRojp{~Mz+%=%RHG!3l(wxQb{zQlW&MTlbr2*9|peUBo#YZ8u!UMPz zJo9lmW3isPrkErmxp&SA4Z4vpe~LLL-w6JUW}f*bf#w6lVyDvUhdK9fX!p#TT3fL+ z7im|;28gcWM)UdfRI;603BWd`d%7#sP0t)qNW*R*WmrD?hg37Zngmu{P;Lm`rlK_> zITGMQH~V(}6l6}TeG5nPEHYI3EHiY}TD%AAQ@%&*Q@w}lLp!VC>E;PCjzgVyNqNmA zYd0t~-pn55?#)1Tc-(xbL07m;Md14bPJOLyoRpLhRx-BtH{Z%<78P>0$olxWy4d9! zncKIDHrWFnBRUUqc`qiz@xrz52u-?2kq~5n$h}&*K?MxJ?xV?vVXvLErROVl7L9s; zedsv`#k1PCWY;`{${N?=R9%uy1P+jKf$&__RLHP zWVH#4;U{}bB4D^B*hm%nhRpQF{4?xW$&|oNp2CUE?Coyj1QI%P|w91%+*lty%ecgZ$I1|mJWq9_c?+4{KElHR%TIU zf+^4^hXY?f0&(|Q5=NG~AhiIVR+(a1gF)Q;L&vH%zPO{yydKt*(f#LehU3CVRIS&* zA1khb+xXe{29|Ggayz;nqv9M8n$JYj?Z!w0Sb}^lq#XQlg~=nkBhYxmlB{huZcL}F zA6sNZgJpJ|laA>P$V#ZhT+&$nvNM2sudEEeUaohc#ab+sC zrj7G)E-#;G-w=I1hTjN@b;lAjX40pR+<>)=n`V_!(JFk*yE zP3nDEs^C9DCSbs8`TV~U17Bmq%9I^$2xWK;N>;W~^^HOu)jQt*LH(-WD@UyR?lk$o z+mZhVgYn<1!ov1;W|rozPKN*0V#Xxdelr-6M$Gf?*Y~BQbHRK-&@B;ni(p_#pe0mg z(1pQKcH#lqe^P^eZVUta>(kWOPSnhH^E-oKtcJzCI^FSuJ zze(PI3_%VP4Fp7k#GyT8c6l?vndL`$$s5Z05+P==upnazJ>&{eIc?MW6fVO34pXfm zmmilQmRYtQ*e*BV>J{aqI%F$j*;=Tdx{msYgM{2Gd`D^TU>~NLKrbqtQDh6KPGcB& zYEY{fj~P1Q zY_vIx8j+W?nOTo{k7|A!vvlK?qYKZnTkm@qV7lWQf#;J@)(qh~m07vHwdQ@701t>}N2> zYt=Q^?p;5oP%enrkvLCarS2rlJ;zjT@1)Ha_28t7T(IMcZi3U?D_dTzMKnR%{b7 zXeWL6f-xfJvhsVNF_?I2^3gmv=2|f7azO~wc+o|=2cR+N_<9sF;vio2z;vtlV7U6o z%q9XNPhjS1Fv)QuRq|0#HVGw&HG!!t0wQo=W>hP)uYZ7o;_qdM=-*`k-Z%4+>VGZ; z{vGL`lv&#q*NFJmy`%{yAIPrAB%*freDk*5cHaNPB~B86YH zIw9gNDz9H+n0&}J-c0V{E(`My-2Nkt0NBY-PjL5r*s48D&j)h7pIpJUb+0ol1F*~` zp1!}vw0*&IA^z*SXZ}pIG9;ySrW01 zpU6d%LB2t@(;)LD!*G(DXK-!R!}Bp1mKS>Uu`^#p z>~WR%dn&;>iuz9Pv3W7EPX~GtnCg$63a-#A$1B7q;ZqH{xws^Pf-V1eO|D zHXE9qC~c)%CS>n>jc?m)ux2hN2UpKIU2hP(X}`Ljjc|CDFH%asVJH&6j5&Rb6aaVeQvSt z6VIX1X(pXAmxL>}wO&QIImzI9LcFhECJ|Mzi1FWhCgS$=^!!D3^vyEEY0HM0>?fsv zz1W(i8*H{v9APY$IW@J9NQ06Y@g$&STTrPC$I1{t0ptDZ=rHjEZnN2BSw{(Pn+6KD zRZ-hjn-KgzRa=ZoUs=W0cAc-}66Rmi)kZgub$G6zPQn>fM&}9X6!J^UsbVFdewj#M zt5erf{g$1$WV`h=0<2Y%iDK|HwH6hSu-8LDPknW`jl$UfmI_z9=GkC(@A$oVsRFl` zMYdksp797E2vzaH-N_%;t@q4}Z;FxZ(y&6&(#;_uzaGV+M%CB= zVNRMN3tj1#%##v%wdYNDfy0)|Q$>JYJ8-6o*K4hcC(;5F=_Mn-l)y@UX$ zt$YU7Q%o3cqwRC6;{vbL1No%d&)=)2$$;SD9a-=PfFh$6P1;*I*d z?C_52JLp$(UF}SCxJXTY+9?uE`@f35}k=i`#4Rk6e@*KDc^(tnQcw(jY^fcG z2hqo(q%7)o0YkX;lCq$o6hgCi3n%i#6vZ7x&_k#aW{QnPk2CWm8yVytzz-Xd_05x& zK3Vo>SFs-R)cf&`{&tL=xJVe`-HvE7&mAL^uj`W z%$d@~HtC6RV)R6}b6PqR$Pa7R8c3d_D4Hqq2NfG(>kTi!rOp%>Lc~n3!5mddW>>pR zt8tmTCxnr(Xk6g2^MqN08AmxcFLP;APA}^V80R_+K#agUx(RR48L2ZQej@XRm?OF3 z&jyIH+L2f<&wdR}X$XB~;2tBIf^AThY(zLA4*i6@9FdbT!Xy~7Ywt-zdi=wCIRuOL z73^T>|0wMU6&500dh%`EqjoMKS;Z+_5iFfnaLNy+B-@vyNWRdcmRaaBUdtQvT_Q17 zTG$aE4SA0iRA}+d@r;k~BwsTn@=r*;LgW8Q~>>Y9oke1Rm(xx!gv){TQFv|25IK_jjLj z_mxH%0-WoyI`)361H|?QVmz7;GfF~EKrTLxMMI`-GF&@Hdq@W!)mBLYniN*qL^iti)BMVHlCJ}6zkOoinJYolUHu!*(WoxKrxmw=1b&YHkFD)8! zM;5~XMl=~kcaLx%$51-XsJ|ZRi6_Vf{D(Kj(u!%R1@wR#`p!%eut#IkZ5eam1QVDF zeNm0!33OmxQ-rjGle>qhyZSvRfes@dC-*e=DD1-j%<$^~4@~AX+5w^Fr{RWL>EbUCcyC%19 z80kOZqZF0@@NNNxjXGN=X>Rfr=1-1OqLD8_LYcQ)$D0 zV4WKz{1eB#jUTU&+IVkxw9Vyx)#iM-{jY_uPY4CEH31MFZZ~+5I%9#6yIyZ(4^4b7 zd{2DvP>-bt9Zlo!MXFM`^@N?@*lM^n=7fmew%Uyz9numNyV{-J;~}``lz9~V9iX8` z1DJAS$ejyK(rPP!r43N(R`R%ay*Te2|MStOXlu&Na7^P-<-+VzRB!bKslVU1OQf;{WQ`}Nd5KDyDEr#7tB zKtpT2-pRh5N~}mdm+@1$<>dYcykdY94tDg4K3xZc?hfwps&VU*3x3>0ejY84MrKTz zQ{<&^lPi{*BCN1_IJ9e@#jCL4n*C;8Tt?+Z>1o$dPh;zywNm4zZ1UtJ&GccwZJcU+H_f@wLdeXfw(8tbE1{K>*X1 ze|9e`K}`)B-$3R$3=j~{{~fvi8H)b}WB$K`vRX}B{oC8@Q;vD8m+>zOv_w97-C}Uj zptN+8q@q-LOlVX|;3^J}OeiCg+1@1BuKe?*R`;8het}DM`|J7FjbK{KPdR!d6w7gD zO|GN!pO4!|Ja2BdXFKwKz}M{Eij2`urapNFP7&kZ!q)E5`811 z_Xf}teCb0lglZkv5g>#=E`*vPgFJd8W}fRPjC0QX=#7PkG2!}>Ei<<9g7{H%jpH%S zJNstSm;lCYoh_D}h>cSujzZYlE0NZj#!l_S$(^EB6S*%@gGHuW z<5$tex}v$HdO|{DmAY=PLn(L+V+MbIN)>nEdB)ISqMDSL{2W?aqO72SCCq${V`~Ze z#PFWr7?X~=08GVa5;MFqMPt$8e*-l$h* zw=_VR1PeIc$LXTeIf3X3_-JoIXLftZMg?JDcnctMTH0aJ`DvU{k}B1JrU(TEqa_F zPLhu~YI`*APCk%*IhBESX!*CLEKTI9vSD9IXLof$a4mLTe?Vowa0cRAGP!J;D)JC( z@n)MB^41Iari`eok4q+2rg;mKqmb)1b@CJ3gf$t{z;o0q4BPVPz_N!Zk0p~iR_&9f ztG4r5U0Fq~2siVlw3h6YEBh_KpiMbas0wAX_B{@z&V@{(7jze4fqf#OP(qSuE|aca zaMu)GD18I+Lq0`_7yC7Vbd44}0`E=pyfUq3poQ-ajw^kZ+BT=gnh{h>him533v+o7 zuI18YU5ZPG>90kTxI(#aFOh~_37&3NK|h?(K7M8_22UIYl$5*-E7X9K++N?J5X3@O z2ym8Yrt5Zekk;S{f3llyqQi)F-ZAq;PkePNF=?`k(ibbbYq)OsFBkC7^H7nb6&bhDx~F#muc#-a(ymv|)2@4)NQw!cgZ|NLJ@N6o#y!T* zi0kdtK#GC8e7m#SA9pSuiE5bOKs^ox%=l6KBL?8Rl;8R~V>7UCaz+Y_hEOZ^fT}$m{$;GJt9$l$m3ax6_ro{OH@r z8LmGIt2C9tM6fNUD<(Y1Q8w(aN2t@VPrjc;dLp9756VNLt9&>pX!L*6kyU=uui9e7 zrQ^&h7Nuk|fa1WH?@{DNg}C&i2BPX$%)+AMi%-ImT2Q_QnRV)3UbO2JW7T-JYoYnU!(}tii1LAN|D(%7cL@IEI0mCT0!t|kd)1KahVC2K z|9L76JA1F#-=|{!eJcN|r2bI={kK#3M*^rokSGIa zWe@gc$gT&!Q!WYqGHNy3PlhBvcjf&X0o_R>a?DGQ`e|uWa)>YuWk(ibM6r_Xpiaq4 zWtcFh6k&ih==f(%+T$`L1EYJ^CeevsviNKGK3iUF&1QI!EZOR4y2d?z{kh!@hfoR4 zR$n!oTq-{w^eSf-ckrX)rp`@DG4(8%e{AtoKlwoHjNIX8hY>P;3y*y_O8XZ8ien=J zQR{%EX3|XA79>Al$+8(rw$Y~9ydiaH!@*{;*H_Weng(B+tJe^@Hh~lm^J?rL_`0$g z%o51AI)M5AP4)R##rWU8U-|zQ>N#rK?x?C*TS+B3tQmUYjh6X32PBq4xJ`|D)tg%M zLwd8z7?Ds5CNhvE8H^bY$XD*~ke$yZo!3P40jio4f0GcqUohXX>C;+gOt>>PizdRd z?{b{G8+tZA!Aj6GmXFD*thAzMDL!h{90}jI=PdjS093DQi3v@l|5~^hKrwR6 zeUbcTjhPDLUg*ao;c>8JN}wB>MOIE^vN22t5147OVW>!BTDvz4xeP$B({i(Po~_BL z9*#5s@;l~%7S3?WkF0}E8>iN+UQZh{-D}3F##`x$+YG@H0vyyD%vY!zsJHcnGrN|& z;j<&E%0i6kwaMT{tjp$m5^V4*+9;13^DDjgaFvvOe3=j2hWU3(PY)kFXvfx#EJF(V zM!l@%;xJuF3pERftbWw~WnR$A&ok4UQ0dISRjNi-j7>!WdGm0^FUmns_uy2DYX1!< zihag3z-a%BI*WE?er9_UTY_Eui-R>cvS1;=N#Bv{mPKKIv5O9iXS- z3|WAAOhFjGB1il&5F9vj6Vm!t99VnZ6v)$mKW$!I)_=41msTtDQ`CAV`azZw#(aSt z5XK052F(2mTOy|hb~KaAM@(Gg9l3=rqXB79Zp!Q>)*)Hhm(8O3s53@BCx_ltYRV=o ztb3!SE4UlbZadeiDcr2NZnT1}MNd0Au}VRHKQ!`nW(2!sPW5ulYI zosR$tFs@ul-q2)^z}}Y;3$Jj4J#kik5ou3xxf)_JL$5C!E%MDFH5fza9unrHXXw5F zHY#AcZSU73&;sy;y;fM_*p0Txd{DmQVYSyT(8Bu@vSLZAPKlVDd&6%bHj%HaV1{=L z91uK99)#H)!*Q6S`Dv))pyUoDkMa0Sllw7Fvb!iKKjbR3>q-@zp>$lcNLt4(&F9yk z!g!~88ulk{z2xgG-3{{il~#8wah-S$PDsv)h$4v?e@iEW{%JRU21>lL%fw8~(DT#^ zywKIPee|O;<3lWQL$hEWAUeA2)~-xA7yV(I(Pe55DMTFD&6fP6bS3JXHE& ze2nS2pMh>pdB%}#XYcS*N|SMQmQ2J&7WZu72OP zj&wXEJHG2^_XZLJUco>yC|q(0L~1fPN+}|}7%$xcp-i$$kXV=D`~$(T`2Y)+8U2yu zvr%Mzd~RzcUfF#X_+uh&RV1fO9P&C;yFTuW5sb%e_xPYEB%AgtaOJ(ztnLEW_Hao2 zZHV-;f-^2epH zxn#@~NOA z11ZBV6tw5T5>Iz^Jb)0%OIlra;qJl^ufG156Ui{A2$qpZ_{^c1^R`+fbi*WT%;He@ zyieltZ{6ivdgz6i=@iEldc;jVS!5E5$rymBrD?v#K?Mr`?ocG-n&lL`@;sMYaM2m6 z)Tt641KSaR_(MIZi0J-0r(53x)8LPvfBwp-{yFxkKiTU)pdB)FGjC~7AfTS_$=v_Y z*Z#MJ`R|V^X!eb+h*>&0yC}OF{rl;vioX)<^+YRtY&IVpwZx%m(G%kbE0AM%G$dMnxO@9U~x`$qY-b?f@fkQ`9pNJeiFRud6ZB~-h_kWX>mCgONAn%y8FDS z1jJ5f3AGpr111cNW(=njoJxN_XIF;t1dO^e0km*ZO?76yVM(*B>Ix?cT=nC+o2XP$ zo!&hK$H9sd8H07(XoY2&7QG(*iL;qrs4U*82`MFg4P0Dzw%rEFXuGLBslk;D|Cf}sL{Bdj9TpChAGEEN*DvCLV(j_N-e zcLNc98=ZJ>3?UluoPSL2QwygpEHOrNp?KEVT77e1i3zzY%Y9lStpis{$m zm(cz{%HDxH)4xj^O$Qy@?AW%`NjkP|cWgVkW81cE+qP}nZ)X0p&N}nVoOeCvGhF+3 z?b@|#SADRMCTILsR4>rrHy4AU0PJ{|)~M^(@q-e3hLdj7_}OdzCb7?6jvhyQy!)3Gv3ELg)6!VjwA<}NC@GK%{NI0 zJT}T#aRk{>TXHs_T?t5eRw>v2ntXC6^p*jkWo`a)WZ0?8&JFWArnx^e@#->FsW0`H zaG;x(iE*;8ugY6Nhw%)c!hpKUyX3jhGA*i6J6@(fUBPL$z{4dz!^d6OL#hN?41I+g z!KjR5!+yZ+z+Y#U0p;s{fV{jmnQyy>%`Eu5GUWo&fsZL97=D~-b_O#00NQ+zO>XS` z6cn1v6jGixMb@=ItgwK*pbiAms3``uBok32wSnIF!(VPSH!Aca2(cTt_k_R zo!iTIMT0nvu%dfM`Tm^UEy_oqiKOy5hANU5*kqB?bbwBoz>e&)X{#5b+bFeY#FB}p zj#JFe|1ix8(itqE%U8Oe9{8p+lmPB#ITX?HhA~WU^`aMeLagZ?{J#$k1(<*Ga=!-# z(r?kozXS&T@4ut}e53yWT>JmB5K8z*I`ZXC(_u$bUyRSI0_sa;;}c3a_~)8{7*#4- z*hR0l-h`v$GUX!Y8S$OAGx`t7Oh5c~5aXowl-+DBh(YT4|& zz2Q~Iz2(b(#FdLc$(X>h-N-=%K&sS{-j3KfIshl~vZ(yd@zZNg`=RANO&IW5GfVZE zs6mU)V!n_RSxggdO;6lhUb4T6hUvzQ$bXz{bZkC4QCxql0E>+~jH^F@J~OC%bQSnw z!dVcM*I_fSE>Yp7Ty9TQ8VjoGh>2rpcziKFwP#ZBOnF7Eb+fb#57*n=S;keHfwc zH49H*3q*cDponQrD`v$M1l5b=n=zY6HiA!3d-3ZhDZ+LzKN9kDW#xrc^yy*`$5>{c zL~=_5`{q}NdlgOp5;!td)>hv&2umQuUJip0G-qJ0O^3tqXGdqmn}Z9DTz4j33Oh6* zRs?8e!2wbIsGfGP{9#WZD|RF{E86KJLEy$vz9KuntCBzNS(>A~j5a$SlK;1USU4_S zB~S;>^=U+8Kqh5?r+Nbfvr>prvVolf25hJ>p9%wx5ew2uyC4l%vXv}jkoT5T@NOml z^@+(g=Fks#f9@XKR3CWI`oEWac$gIO`*&M%ga!iQ{=d%2|J9ZRjEt@AzT>j~_r7Ge zrikzvS+U<-JIh%phK;}dvq;P%#NIq@*-Ro zG795&jLHtK3kt@gsFnVb^geyY&Q#0!O5NK<5l`92U6zg)2z^ixqqM;dD69k{pn5na zjzCXM7%i#qTM&x#D|7;Cs8qI%RB+HS5}ROsznNr@l{c2b$1$=!oSc;%3db4qHN!gG z%>$rEZM~8pIiTEB<|bT*mBLb{tT1uWu6OFJ)KF7(hj^P2rs5QyMx#q_*|BJuoXwJv zyh%!-X{q#YM`heA8Hj!57>5|U9qR_sVak1r z2ZH_d(s!DNqIuDZc5gkw(w^h@n7~LZ82aCz6|aG^n5bXeTCFdW z7m@2Ej5B%8MSD2HAr*BPh~b^9^;NJ~HXJJX7VeGl(#=!DS?r0mNIH^}d}=~&Ui+B^ z_wm)B4@6oIZ9FP|3#qxxW6-_;>b*pN_iexjXi=h}e`(krgGC?N9fbTnyYPYIO6K}B zFA_P-suUrOEb6b`R1i9SkQ*s2Jb7^Y-tOTodB9(}j@~WUg#QJE`jW#~0+;?p-Oyv- zf|?tPS8>)50*6Qh^}EqVu&_nQ+F^C-IvX6tCg-UDYg3UXsv^pjsXxyJD>pVkh$z=?hWh9Cyd8bJRGUUU{A@XK zEFVF%XrUA0yYJ(VcELR{+rh(`Av6SI^lRD?z)AQ$gLvakWpQF`_zp{aqZKUt@U1H2uD*qV*seS(QQ2Dy-oc-O8X zMKUd~h#|T^-6H}`fk?iJx;2kI2$Jj;QIf6%C{vhRVjqTvaHy7Wq*g(r%|c-3w(n|C zr9N;Rs9JfUDeCWJFL}uP;Y0FDf(Wy};!IZ2zFjeU(d+_6MEJlaX*p=3D!D0b>op*k zuYr23N1W0wly8w74c#W1LpXP|?)nWr(3eXs$E(c&PiERe!JWE^z0mm5cg@7F`_!@X za8nQpF$jOM+JDY~nb?BoW=-xIQ22c3TFS?M{R<~rPg$le_1#FXz85*d|IS}UP|x1z z+ey;M%HGW3JB?4_`{vKeW ztvEN4bJui=CcnsQr$FVybke#RDpaIHY{GaczId-A9x@ zD;Gi-lJ9Iau-2o;`eV1*3ztzN3!P`Jxrc)3ocRRAct^jD5E<^lS-Z2}IFL)oUQ<%h z4?B_#BP>07`M}`7ywGkk}UQpFIOvRZx*v_~StXIsHv% zk|F{D@%%dlD`92rZ1oTF`=>D~IOsVT{euA~R8PKHPL!_>)`|SN9}+Q?LbiX7V;y|` zxRlL>%Ik$H(5Pr(Mxx>JnH-I0{je|Ff^ zz-BM|Nl%;W&QA{{-tTu0O+e~5f#GiJBzZraC7MNqDOlr?|LhqN(b;MvwI7GKiU~0K z{eT373oTRU0c$+Rhw4@XlTr&~#ma@bzsx0Wj}{NwfD$q4FH;&|U+$&78LfwdW8CyW z;OP%PLaqA+xw`)8&GY!c(BaeeC9Brzjgx$h5BNTOB+6D5tkg^CsI*KLgPcM%ya0vp zbV@C>a?WQSn!)u=q#cuPB(|i9nbp{($Sdf>!kHiclcaabX4aUu7DhI!LxJ!}0zu6Q zTOuR4jCzAp4HQB~$lx0-I*OxW?+7`C+)yPz2LhTJcEWDtrjrKPGYcx7JOz5>Fq1BbCwdcc~)V(_dWb^W^Cg+d`E znHou4u_BxEZ#{w1)X2Kp1f&31bB$h<4(gDTg@SKrHdbYIH!LCpjoWx$m6H?^Rn_?n zQtIMb-Te>usVOR~oBNm|$%EuM-Al$LI7T(caHlUC_)EwIwb_}nTuQcJOCTkj73b`fRMv9KQcH|un^M#jXkC}A*2{;)>XL4t%9j;TE~jj=;kQxkt|4?2+jG$ zO>MA4Ihwb3fs%0QJ?(xri>|+HFKQwe~VKVDLRp+kcn%p&_N|cAcOg@pMI36hxJ}`pdX&g37 z;cjX3*$bO0ZP)WGjS+*#9BPg-k|%%ld(u(z6#Rs)CdDq3v`;~(3yzuCIThvMSR?)N8k)5*zG&`Z5~4mo5!kDs8X%#wWG=BAOu>f;BBx)i={ZF2%pg&8u9OHu$RwHWi(Zrnb_F!S4}H4Pemup{B?g&x zU#uE<^xzLw!p;7LfV$qJaB~})?F?0goeb3_q^thbL^rZUwm(m}&9u{(G_k#^JTnZ# z?ls#Ol&@v+(`?BLI#?e_JDXMXZ{(A&w5)*9@rU$xbIzoJK{+Kq$9~gGf?d^9H95ge z9~bmk_TQ;pQR=n`mb-!up;6q>rJg5h&~DXGOL10ZCpZElV9+NXAe{ z(U{+>WGl-7n9_cB;esbv`zQd5PGDmtwrS6_?5O|j?f&4!=Swn)P&{DTRm#Q z?lZCaTsQRukADw>9hvymR@=x9j+`A^;gGe7opW<)l3(+nJ@lsz+RXHLf8DN7;}xZk z?qsC(lwIfrLNr`%cX`j&a39Sp*W&E5ABI{ZAa5xsdUx~eii8JeRZF~w%iTbC#CrAF z-f(##d2g%O_TH()d(?*AHm2=rhVJdR;EgIyP9gikuT_JX+bTqZK_f(F?2|1`kjc^R zBzDQ!BZWG%cOfa7HvQaL{Ub@Sf-hnaA$2DxLI5WNxlEM_Y{{$4dSJMYh7u9pnQdxV z4jn2yc%eOWUGmF0IvlC|>3K7RbP86le>*$oQf1o9Hu$U5W?FiyW4x15Ke~2{<~fNTN9&{nZ5ltn)|0&e(%8lU!5}Jn=P4>{Wc_V#@<*& z#iR_5lKis*QVSbHPz*U4gh7_7OW&h{zBrzGiDu1}dlO-OKldzv6xfgM1;iJBv)(xV zL*nOH>}C4e_pM>gMOIgr7fA9zY$T{1XY4SU7$v!*x(F28!b*5-sBQdSve9%p&6M3A zoF)u_&hxDVt(HQi+d30wc#%MI?O*#P7A-(aDiQVoVBc|#+G2bKX3W9;9o8 zD4HbHZV4&TIV&gj0z6v7AXq7b^MENIMn!!BR-tnjn>8c7k|S+hdv8|W%?0CbQ$7B2 z*nZ5BW(Fd9tQJwZVVWzfGE-5!b%f6Gtb7t<-@dIT#=TMz3ERX_;%e*+5i3(E=Fe|ao}{&(4(W{aQ4Aoc)ELdd z5xg&)DFQ19QdauMEM#(&`Aef|XP5yeP7=4gf8P)3_V6z`))+>cj3Zt1W8V+5k z6@?Vs07*I%!{dvD{3k3PvAAMT~6`Iim@M4XaO_%YOCvyx_aZ#OE zEoQCTV=MOnIy3QCDFvy%ko~6YBp3`2U{rdbr*BHVsIz1!_!-at!VxNhO7NC`mw*3v z`Ttu;@xSWcS?XvTO7%Eu&JIN?8S!yGelAjipZZjjL?kL>E`1=KPegVn$cd#Q3 zmrT=BIxi`@g_jH)Xa+_?g2hpyNK%m(2OB8!%k?+{0(O|w)+-aJ*9?afapdUc!Kzrs z{bs76WLj({R!@J8BMHvCo3*s0;2pzhzGX)r8;v!#bHTvh^<3+|+&~E$E|kdCik&Q* zvXm9N43@#(!o=hFvr%fQ&OT-!rqBw$jx?HZJdVPlcdD=K;SDr6uCWgM^>3>bYYyzD zw(m$e)>4rAZ2TKb((Vb1@C$)B zlGwcqUCU-rWbV8uqUIsl`VCcnOj-itFqI_2Vd=!Iq?jNi9x#_YHyx#bWu>p$(+<#3 zm8~w;gB*jg_f08pzm}{qhFqd*D)ma%t4`7=-7rq(#5?lpDE3t^qTn!nJd{~h0E~E- zRQR>Q81&d@rddwej@!YvrbA+RoMKfi;I-d?R$U8^y^k3xwU)Hbm+Y+5OD;`JOia_@ z@eFpvBey;1Twd9l*KHO!*;QK5)5hjZ6$t;DMfiE(0a6m5?s6M|m_vXC)Q4Fs9sn_y zI!or%?trl8Gt;p&}Jf;`yVHP@rsXhgAkueW}cmxLXHXddup{SVk z>^B@F*hxOnbBoJ8BbZ4}yNfh{NlUbMcb;7pL3x^mNLtFPzQXori=YGCNI{)ZAZ2Ki zs3qvR(7N>3nl%-R(nxn9g25ba>ww@!Zk2n&Ba}d16bhv_#ER1_5xYp4v>EZSD=SiN zawHYv%hwEpP%wK16R};MR@m~tu!hMb+v9EDkD&DX5wQI`eh`K1)O`&W>qHzi z!b-DJ&}vPMc~072@*LfJeLTEC`v}F87}68vWOcpLQ|U|l0V(wYixZ*=QHzP%b48F5 zDzkei^(!En6E0%9u}ZGpvth=98Ab7vbAkWtt0*l8ho~bKg&k)N)D{X)Sw;9K%Rymb9ZkXRbICW~F^rHlD@gHfrM)$z@z z$hD#^b4Oa|U>c*}O;;{gCD0tASCj@XM=^K~@*b&A(W9HhBW7}y*>zs`L6&b(Numk+ z?}W2dTTY-k=m`2Mn)4HUL~E6!TYM-44baeHe*R4+@g^O;S2E_999y!?b&i{oCw2p8XKj8~?@*s%WZ!JnBS*(vHBdP{u*jZ;&mPhgW- z$TymUXpLsqmETA3RIEm7PvM~#n2jc{hcz=P?u0)H3}EOmNcTzyZTDabzVJS};Lw~R z^_n%#OhfmE{M47|-{~Pe!$80aEMfivs=~;(cxH+gPUI*ZYK)Fs^CUuPfB%5wwKIf`Er>NFR$wv_^&lqkC2)JPA$tSp%^o25 zAg&XPxP;|y!~aPnY+-Z{-RB5sI)^EdId1W3Ryen*fIbqnZ*#ViWDj((OR4xJM)(;? z@Cf4i$TZxF!ziNG;)MR>mr=gWYsSqO1fHC|%#CXi%S_NF)#i?IVU?g9jGmIR0)3Bq z;tln(pGsuhYpC|QPZ-M*8&b?$?(Qip*nJ?akUU7FF0*UvGnI!R3f3ehEjPhPEH4?iI+hc$O*6CpeI~ z4Sg%6ZtDeiGX3M@Xb0VgXkGxN8nJgs*k=MrN#I7+%!m&e>Y)R!$GXr{Ox1#dMkdI= zlKCh%&BnMT;qlKbqHxO{`^lO_0%GE1Wrg?yydI<3s6he$-Lq$K9S~S3G^v4nX^Z) zB1xZCP}vgY{yApKcg{ysSWd~`b){kFXX{Ue7MRxdIp*Pn%tWiA;G zK}!DfOQSN$&ZWcr5-u-l7x|fv7&wHK*XJt#+uRJnB2FM~@^XCA<8EU7^5gaHgUsjK zVOWSyGNZpfk~vg>rhqFct7@kb;0^O2Xsel9!;mh_$I zaKvjBu*O_)8H>OOS4ydd6g-9Aa_$Ws${Ws6Fz0|USEkulnyRswYM|urnEWUey-5v< zK|YioRQPd{ip*!92N>e3y5>A+Nv3n4toNold<;@)Cpa-}o{A3jKdb?O!_ZABIy-wA ztzaL_l_MAt9Aem+gcuy}HD3IYtK{aB*hzTjXq&0A@uXRXv^;8|0?@Am=!pbiG=C5N zM)McoW~TRnVW3NZq1KJj+xK2C;;K|}6aa~;Hr(bM#K7Rt=}86*!4%lv7!SYq>1?b! zoj=E)44db=!=F?h3B5g#AL`+B*zeH*a^T`<+KZ^BuwjR)kT#^@EDMz<=4WrL{?JQL z(Midu5k`G6nx|MAl2Y&qGSM%%J)+Yw(FWm|z4fu4I z{{3wjNT2C$ql;!i*H5F{3gKU*q?bZrK0;+SlBwYIPElp%gqUQ} zu~PZr#qYvYE(y1#z$@vrcmgY2xRG0o>lUpzY=8Rxlo4QAjRJzT;NnCL<(mUbSdA4= ztVE89jFFMl`L#!Zg%3PXupV$V{iK<4bVwi2|NAg#!f#s}|6Tho-?jh$0}cQ0{CR|dmG3a^sq@LvxXZ)+3$dF}+2P(mIEWS<*7dvo6~{*oVgRl! zQj7D|**X2unoU|<->1K~fm%Nsb}uww1XK5 zPTkQf9B`IX6+xXBtW=vbHP=GNFEGLjjx=4n!T8k>P0Dxgg)8?1odzkeL#&YQ#Ot0b z=PB19V^dl>CF9vFxxuNE`{qHrf083@(u~2?E+QAb|ND4Ak^;V`^p(&%y!)wtA0#DI~1sjPy=Gl=Jk_LKV+s!Y^j?t@%~H!tX2)H zm{hZ!i~RL`v`e690}D)}3FD}V(vmxXyhY%K5Guq{_Mv9?v2lT{bOWg4Zu^7y1ar8n zmAHd)JADf~14}K&Kd>r_R}_x(PBD?%GkD@IDUklYfy|?y1BVdi#9312{)remsr!-H zjW0tu#v*ygyWbLt^s5_5MkpYWOUgiCwk>cCafD`_APTvKBz%WJjzlS-G2A*dS)qkQzz504s~eJE&!(*U_>0mr$HykbwGNoNWwCEjL=c7M*D!Nb`PH zx2NPxryn>XZ%|N7#-LQKLHw1-kG_2=QJ2=JLW=C*nydd_?z&Q5N}%86-u%7SV*Gb- z@Bf(i5)`(qXJx-{k|yJdb?lP{@*FHb*?$CWe>MafB>S6?GqJ~&cUG(*a1pK4j zcf{!2#D*VPQ_jByclkm!s~C_7tTThdil^s=WdwIgp0IA$=lH>9hCTx z5Xr)>@*R|x(DjaQ$DHV74NS`Whn+KWt~fSy84>OBxriMf6kUU4Q-kS1l88`oJ;U37 zBQ0WgFx`l;cSai&{i2YGMjA#*3na}+e^znG8aHDsy4bZf z{#LURLOT3~vp8(Iz0R{4 z(_8XLA)?)amfcWVTsCQ-sSBOwSm)13fLBY`sl!Db%2|ifT=q zA}^pepW;deI;)PQ&|m^3N#3nC$*tDKC&*TfWst8|sxfW&I?b{?nN`JNk9Ca(mhRwR z;e*YDD(uF0O__g-j`;qano_bd|GzAsI+Vubzr}$(&aq;>^uHkxZUTeJ#UKKb;6ZDm zXJ;v)Dg@N3+lUox9T)|rNJr_O>1gvqMG~O-x)ZQ{39k$k* zrcOGGtVyrDyF9^lp_*9wqZg(DHLU6pbt5$?+x}t^@`ZWLSOY9S8qUS0f_DMG--u2U zVVx5|fL}q@Sl3A;632wqbUjvV!&-8wpc7-pG>olAC=&9uR9P+aLa{6Tryv9JHBdyU z`QqpdCu5x$noe5^wes^G-+w6U9@E!NDHQLKi5hO!OIh=Gi{cttNKdQZov`>`$0}qW zwz3-)$gk3`583rGJ_}20tDDcVxc&m|+f<1AbLy?n*OZa;*e5mRaNf1g%?~}~d-9qg z)YnEg7G_l=&u9@fFIBKaalRbC<3=@@*feY>lRsNADQ15TvdRTJZ<)eCYVPqzdL=Ef zN5(>Vd%-(d`|e!KyLWUEG);_E!J-fhAOl=zUcrgVX1&hj`Zz+wvF9Oz%X4gGuONcH z%h?(;os*+5gzz&rd5$4ULvA`P^W&(9fPMjG4QPG?KhaXi@O6O|U0j#gaaIq8)g2TV zw^p{f?V!a@N*#6eiN&o9wm34rAKw#f?N|a+zzc!gN;w?_aaFF$hD3`u9UipKy2=a?eobQF_M*REf$ zj;+{$jx7^GXy!mmwnHMf3B}G*11Dl+ur+U$HV>=|*rWme??d4H)D^+~34-e<&T4fK z9ektGZMEA`+wEVx>}pcQ8=?b3U&4M_&cEw^b7&G~t`IahA*>38X=Dd9PK+d+v5AchxFfgIsaho z3^g-d&4HLt@zfMHx9?onm0BKMiye@&M25!d0|j0nObOP+ni%+TRkv7Sys6+6#71_3 z=3c}|gh*XvU|-!JP`?&KXx|m7=3b=XOQhwATD=v29v@f&3!tGPuaC{Nnek)Hkat;U z8D}L&CC7!O1(_;b_eTUDwOd6z&YPOQpDHX}OEqX&rqBLxbi6Y+6raWRuS~FCMLRMt z&#=5pIeXB!uFvv)dfz7vM;+QgV~i`G1D= z-T1{F=Svc>DCY7thwMnMEmQWBpxlHg7sL~EN*8FEl-J$-QY%K%J<1cYy3$KV zG+EM%8p|KXJPMwGyQmer(9LR9MVP?GkZ=w}PhCJq%Z)LsM&!Gw6`W|6YLt|VXVknn zG+d8xv`&o*XpcrIyO?E>GlQ59W6fo)hgdm&!us+gk&~Z(xzd@ocd|b&VXN{1iqTsr*tppm%|xZev}kgETo?Ip)PrPEKQ`fJY27Z?+iQ zPb+`K9I8RYFXR$~Ml+_RwfhqjPI$G<^2eQukio^mMUAfca=8^`P$}-3av))0#reBX zJO?KRoQN}PfKy6EWE<${E5oA4psTIXI5R3P!`afUEO#@F#cW6?SdJ)pjcBxn{HXms zby#DnxcBA!a)&`0rbZD2SYTN$P0#hKE_J>aS6t>Fk>J=OkHFT(x{~rHi3m`WL<=kn zYqLhsunHC_IFkJ)nD=}RTK!-#DyN3zk?9q}WQ|y1rKvmlPWbjHi7UlXup~E2|PJyPAGVueL7){V%z~!0G zXAH|iVbtT<`S2``Tz}5WNHpQkL-$|7{gJQRQ z{~K-@lS>`6>%9heUPf-y_RL%GwF=+XQ~OK*X5E^AVS9Hz$Yi?j*y$}A5lRJRSrKl( z3QcA!z)W=;sR?}0Mz~&?X z!oKp_GaPNka5j@l=_W8i_Ofa*C=4c}Wn{Tg&f#Kv>KXE-R$KfXiUCcU6VXc% z=8i?pTr4YAqN+|9NHN6(T6PSGByZO+A&`CaMYXfh0S?fVLF)`1*NWI$0?QTU>kd1; zGzWn5_-2B({Gn)x14cpGBq|78lCZr3xPjhMM!`-370O&|EV~3vDVO@igfR9m|9LnF``CmprMnO!UW=7QAFV7bZS z&97u9G63r&&SVh|)l9V;7LLGCY8;X~D^VDNon%jj$@1u7VD2c4OvIF-u>sc%Ihq#3{;M1c1{1p*hfy2MCQDBv0zVR>fl{I|lfOf;-g+=$^M zq0Rs#+yN#^6GhBtw92LZA^WH9cMTdqHT|aKv9`5>skD<(_o8oU-&XLEN{BSkLfhlzuyX9QH{N}qaK6~?EU{Kz zFf*F$WS+nvgybofAOzsSJB2OZAEG_m7vlWn+^D;_jaN7gg(HGtYw~px zw}w`idAI|sf^=i2^*GKT7v~wW-*+2JZJYOB6^uJwuw86RE7aIFD9F(*S)1|L=(x*R zBloIwb9(ht1|YF%8f9femH5?zGAQAwWo zyqo4TV2R=B`U<5m8wAeMHEHpWnOW5wp)I$xr(kkl)R;Oi0isun=y}c-l7LZ7m;lm$ z$q4Iy6Sc&$7dUfcx*n3=`*`*UR zN1JtLOUYS-=7UaFQks;9^B@e^CN+Pz{Jd$gh_F`j>;ZkK-Md1}-@#73aDFjIwBy*d zTlwKK`nqGu3$(>F?Ap8A?q4y9mka`bxGNnAlZNNKWA&(V)8YwF5nmp7j%ul`_QG%4 zaeXBNd7~ytMg3#Xf>6W<>tYbEa%-$6=;P^Sh>aUHZ+e~0RG)Xi3%`rEs8MS8uYqwNdw4SWVkOjZaf` zG5VfUUiPoOG}N6 z<{qp@h!mly6=>7I?*}czyF3Y!CUIt=0}iD^XE&VrDA?Dp@(yuX{qsEJgb&Q}SNvXl zg?HrA?!MH-r4JN!Af3G9!#Qn(6l%OCA`)Ef2g8*M)Z!C4?WMK9NKh2jRTsnTgfut9 zpcZ7xAHd%`iq|80efZ31m3pN9wwBIl#Hqv=X)1r?($L>(#BR+)^)pSgbo+7#q<^S1nr$1&0=q$@M&POX?y?3L&3X z!%^Atu025LgEZ~|-)Cd0=o8K9A{$sT;SHj3M?l{!Er;st5w=T=K2^hJ<$(>&P!j2m zy3~(Qm?r5vh*EGKNLnP31{fhbiIU~c2GX_wqmM}ik7)NF$bEYKH^bK?MD+uJ24Qa=6~Fg-o!gSX*ZYoo{fzTLs$371<;7oLD|PiS3s zz;aIW1HVCV2r*#r`V-0hw_!s4!G4R|L@`u_;)KA?o(p8@$&bkWXV*taO%NC3k? zok=*KA5vswZe|5QOQd*4kD7Db^c|__5C;&|S5MvKdkPtu)vo}DGqDpc097%52V*z( zXp%Esq4?Rzj53SE6hKu;Xc!&LMZPPIj;O-Gnpq&!&u5db7Xi z64ox137#@4w5it68EPn<8RO48KG_2>?+Aa}Qo7fR%&wXJNf2J;Kwm6Opddsyx$gY# zU+b%y*{cBju|sw!wOcY_sMFWX9(C02d(;_YQh1*sH9?j$%`tKJyd(j0PtK#D+KLHI zL;b*n{CZ7IBb}MUGdG3l2vFGJn3TOYJD$Hz2OOy*%!5a{!!0mvok+e+N zaP?Ndm;SO(8-v%yvu#Rr;qFSgZrKJxV^uEnX@L(r4)dZeyh@yRqoi@3M|#Hz`hHN6 zA|8#&oFv8+1F8t(#j1%Ywdn%N2uREt;@bFAF}2zeI2KE&uZr$?-SIwKu<5ThXn_}f z`@RRcJ!3;pKi>mQe)VU5;c)zA@b#dd(J?}$sg0K5L^fIm8%TV4|>Q?qdfMwAh4AM8l8J|tiSF32B4q`!TYj_z!4Lowq99lipY?vlC zJssf0Vy+@In|fg`2sUl$wDGr$XY+4g*%PhDjM^G!Z{H44gwY-ymOqXka)G3ulfWdY ztNvx4oW*}=5^&NGhiS)Vzwb4;K`^*tjj8h$esujKb7&}?V_cU5kQElGgCL<358O^% zcT-EwP>hqb1%_8C_5R4e#7RH zp@tA$bVGG}q@TDR#-_^YT6}Zo5~p_5P%C_pRxwhgkor!;FtNFF#cncoEHm=#?xtY0 z1dHK{(;)5CQJ`0upxdRV?(5PH{JISW%d+@v8FmbTh9n5TXGnM`Cs}{(AbDxaIg&O2 zg<~{fKtj#r91u9PujPqhkFt7tid?IZ={dML<$3sh;A*Hw=VP++12;lVguAyio!na#kaYeX{|8h3_;g*K=UEf zU*{ZR($$Bw*(h;CSO4{alBraU^)52&nxLKUxg=1N5MCBUJ+3a^`9#f?7=4#`&oz?k zoz-#s4C)f8Uk@S*VF!Uc>X}9M`_*gkn0&GI2R*j zUlHUy5b;rLro3?bBLIt%dRd~2lT@kjcfY~OL5ZmTl)ExZyt!)^K#1p>U~rdclk``e z>=zHu6Qp^z%nX2U*RE14f{$U0*Cf)LfBz-c)t%iD%3wxsgHpRPvieqZgEC0IX_Vkd zxh27*KXpXxYD=^PP&EtX{NlX zC%v9)Wz6De((qH}Jqg-g`mwJ!IZ^L?eE2PE9@#9U0T>jD%e^K8-Phz7cZ-bP zU%h91CvGtNYmE{gk=tex+96fK^!I7P7YI3Ma}h)ty%NEN zn}d&kVV1DM4tPht`B!poikUOE396Uy+VE|E*eQuq zoT8M0M&bcREYOX7Q)F5+d!xec;2;H!WO+!r;v#uo402OEt*q%vj)mC@8wg}HO02G( zYG=<5*Vgl3R(5)N@{y+rvBY9CgUHeN`qQLm*3;$@Ez|2z2j3@V_m6j4Kc{5MTf}GG zMS_qp%5n(5$y|Ke#!!7w$4KKAJmhA@sJLcoS}Mv+l^X$2DS9H)ezLP0LfVpNMIPwL2U@Y%%7Q7jPXmGSPlRwa7*y~EkqObIDtyFm)q z-D~m~?At^+db`FvO2uEi2FuK@`RaSN*`T%G!}yA5f-hG1SYtty+Q}}`O^In~cgi>l z=zXVDDNVH?QHtgup3*d46+OEicA^)pIn2`}B}8}{g`msSbzzvq5zHCIjU>OrtmbrG zU26iOxr*A6%_LC(|3nH@ef$16q%glnTl}ob+(w=A9Uk48Pe(F^%ktv(oHC2Ve4|TE zc6J5le1ZqXdLP~+(UY@`Y?r~{B6_Alh8Q{OmhufQSf94*GFtAi(lV<=!6wqxL;jck zOnpR+=HK3Nh}Vv}%LXPzn;0b#^5Afk3y&G)X}NEkE`~TM%tU-P1@^=msCxOyP!IRO zBegW5wZ@10CM!9*_|kF~ZSxrk>r^zyCL|dy9$~*`OX?>1)fL1l(|lW|G!``CEq!N$ zMM)W~G2zDb6wA#)D5OmIMu_&UH_5B%DJ#NKl#R!?QVz>y5jLrK(-JpI6LIGVyD%W9 zg+7;cE40;Rcv9 zkCrUgZ-H}IaC=aY8~7*9+Ny?O=Ep;yso*#-SesEGSa3T&e&DQ`k!p#Zgb<6@KRjgn zG+Z?LoNstww}#+R`Y(?d>>GG^ncorkoKX@REYSTD zQTYHMwNiE~9MM(>u%!3KVR=O=by_thqeFR&Bm;D|lW@>^unOrb^k9yd-=S2LH0S7} z>ae^bwruKEB*7m=)u$5MIo(`)Y+RR5o>9(DDDV623UMVck1##|b`7H%yjK9unoDGkVIKrG*dvN;2S3P_9>ckR6c?7n{s5v!i;dE&<_aDaPA_ zi>Z&SHW^bWYJr-2sb7{WC|0k-a}7>k3)*YgZora(7dVnK7b6?Y7U|>t*u=-aLgC3` zvnz>+QQ_%r^ePEJA5X6^`Ey@^#{dDW(QZr*A_L9Y+QI4?xFXAQ-JDe?&YmeAVN{2b zK0DO+&S-fQWDg`ab0$mQodAEemrA3p{cHbqx{yVqz5Ns6)Rixse^k(i5spvs@22QF zAhsD~>)rC%n(#M+D1!s?DFCBTRfNF~`N7kC8by+1samiHH9dbid%Masz0;p`l^GuF z)taCc0FD9!#^qP3B`G>vZA2db%ma*@6WNWW{*kPq^|f^R%Ee|F-FM69H)u|#Qt{qt zoi{%@b&~<}!vBf99Ef=ih~RNSh2LT6zvdLf+KCi=hu6#d5v7kpppM&Z;F3;`{0FxW z@#nY=LnIjx1?~XD?48~y)>Y&odjWF%6G64~A_3<{rx6>R zqF2ozPyJzzmcF+3AQwJQ@C?KEo|5k3xP%;^ZN*zpQBm5ho(*e)*zn8NzzzG6V?5V0 z2<7tkys|TInay6or7^K(y0ZdwJz|6$blXL}SX7s2es~5{gYwS3d>6k|3V9vz-#G3! zh@|-B?^JP~seJrS$&XAfp`RknZ!pFw@e!a9WgKijDz3K#6@`ifTCWHTa}Tr}n!~;0 zh0~X4_sEKGZZ^}8+X9!T7NazNv{%@nJgpJ8M;Oa zaYo_2Qbk6_j7W15!`+XKC!`+_)IGZ>r6X=buKUkQ*5wXs5}A2D@eYvF0{q(=wm znxEYB{>rdO75{|gy2>`^UB!(y+9acVVRieAMG@Lhf)g>yr+Ccgf8oy1qUO@L$n8@A z;nKV>muW=<*rD@Su=A?nhxTpx>?1>jYOk(ytb|TNwq8q1{;WERaWZi0ov0xFjiIm} z)PkKhn`#2CSuR?p?4)9Vk#`#oL)#q8!B*j3s+x*6kQ~2Pog{K^{k(=xfv{IP9MecW zCB_bMVE;HQS12k5L;tHHjhJ8m%07IN<1N(vQCG+8IilmMo{g$Y5nrPhSx`OH03*55 z;^!ZP!KR|h3~K&8O?uAqKie(}FOYVMt}S-M;FF6%#pX@C<8P!jbk&G&a^_Oj+^2Ys z*1tnnx4eOpd*hgE$xD+(iTw1TaGNs=4*;Pf#P`fd%_%)Jk|eeooma)pR9ka)Ek(PX zq2N$R8sio=D*TQ0BaO+M*8wF-0cR8Bq6vZjr?NAFhjQ!V_)x?Yxmhd9T8#bPWJ^p2 zVbs{=P2C~;GV>Zlkw%u3?OM9&TE|2xMT@t3uSiNEt`MOO*Q>52Wh>pfXJR}YW6XQ{ zJfCN%^ZlJU=RD7Ip3^zMKT-4Q8#0faYOd#r>yK58)sH5XCS>Yj%p1^_p%gSNX4Iai z%;dio52O@`qrWD0>K#6CJvdGFcB%`pA47@W5qIzGe`HRY=O5CK4bZvl6IkJj{#%r? z|A5O4Uo8)Ng;t9f!sRAIsl1a8=TST_Vn(m0i`>XCa0r`>YP-LwxB%^wu8;8+GdQv( zG^usXB?ocI0_)y0MR`T!?Us5ehia8>M~+$sXlUCRovE--QR@;Ys?Ozq9P(Q7ZQ43> zpIo}_{z39UhS{5f8wKSDu+TKfi+#n{O-~4Uk zh*EmSxYYrfwOxCYV}}!zL%2uIc%Oe$XRV@rFeWeka?;Z(XI{}`X?HJGyIgFm@ZX;w zsc2~^A%MTLdqhpoV!jr)}36>dv>Px$jJImpFCzVcs)1b7l%&=qcE;^ zEoSbtk#6sYkpC=iQX(3 z5EUP%LDh0p49U2=$~DIZhi;dDRKwLN8`|PiC-Echa#PXZ|6)S}wWEA@3f!rX>G_!A zphhlmxu@3JVRr3xOWD}*UYv04{*WHt*vT;0@pVLmuu52Mb_Vg9Wg9EUuA2 zl8?Jv5GSU+*{PO$tBpirns`>?!VL-cX@gZO&q)OL%2_8U)8r*4jrGrH`p2zV!T-&| zaf{j)uCI!{A{R9~aJ?$SZ?kk?jfE7FM%1sOCd&S0B(^ckufHtAOetsuspYrqyZ)x8Z8=dG=GG1lcFtKmoxl{>m zAakHGc|f5ZKh>>}F8qu)Y29d2Op+uf?qK|dKPwE!pPkfGl#Sa#?TmJfv}jA5;1`#= zQqplM=!3^!2QZeCx7wu8uWl9!IN85^zrmqGDxsj;TVs=EU)ubiDaD<*@ss- zm%Y-l)9@TN+_0W7Ml5XnEz>_ep>fFIL{5V-n#cCKFhy#0p;!@D!D-=e{(8;*$#2G- z-~F3cHNv>%;D819xg3-F_yHg8bD1W}{1-kQ-da2kMRP?r=@>BD^b5H6=`Lf3y6VPn$`%)-GW}O^kSon7EBP;q9?=n_7O67v9pc>!pQb z)auPuaqG5v3l(E)_GSI_vFY2BtlPgw{(hIMip%d;>9vWnej@q%qMva4iRPI|N7n7w z(!_tL^K*((d428fyiU(eFYzyaICWGnFx_T^a$3(A4p<5kwVtGjOSNa=ey z3;wiIDZDmghb8BsMcSVyT9^W#{YkoGJ9As)0ccff5 zB`U1^TKO@jql!utGX7_6ceT=$mJTWcQ+7_Fk7=jIE7Lu2Ja%~~6K=X$o@5Q7)=`Ao z%Vptz#p~F$l82kO>0*a`LQ8HomkN}$Q0{w8GzfUMX3_$LbiUMT6?eJhshLtmT2m`2 zrK@zuUt8C6$2Zb?u5HM~2xm~H)s1rOJ^3v#{cdG~?xM<+6Lrd(chPMthvmtIcgJoV z-(H!YsUD=t^F)QFU+e|WYBXo`#ht!`&flPI?tga}(nLX13WI~;V?XO(57wx&_pbkw zBgcA$g+wx2w|Xvakrlw=n~x7nWeO7*SwR2(p1`8M*~Ae34SZ&}#$zt|Z%!C%XpOXbpLFv5`sjlu|+#!Pgo9FXG>J~QZn(O%YH zBWQs46dZC)E;!SviJp zefD-koJ?SaKCq_$3t)wALZM_9CQK zGw9iXX^iWLHTQFmME^y==>muB0FYBWAg>aJ#z};63aHSV~ z^&BI1Xx6m%m3k8-P|$7QUIaSpT%uDW?OD?BB+n%~l7+?9t%+Q~hX?=}`?8pcPE~ed z2_t~uEm#W0-QN{N#+ApD+=zZSaBm3ob`3@h+u^Gh4ttNN2s$sX!nzuwp?JOsGoHwj z2@l5>ME8YD3`fUA=$RfY>9hSG4D8@onJ^lTK8T>xz1g7`#v+8NaNr$;IubZHjA0js z2L>_#pi_KLjIjbU(W!eWi-1dyWY}RDad&1C;~9SzVCP+CjBSB%W;hBDGdrDHyErp5 z5X#cSZWs?oRzdJKA&bh!#B=h>1`ELv5fGsjM;8grEB_Ml5nw!Q?T_Fy!`b1Xw-Oi& zJK7`IPZ8{}^QU`YChTvFFb$*GF~83#Ejd(!t%MOOCWZs*(#FDY@nJtyM5ys3r$RH; zGwY5D3&8G^h`_zm90;)SqJ))TM><4FJcR=#j{NChP1sZn(R`H3fhIePF<1&VWkIAq zW^y3K#-asQg8eTLr4LygD9v;SEK4^GSPFI-K%^#fIhF$V7sl;-&O{IvfwyiWBC85G z7MZzT=Na3;D)1g*L}lf9j#XxMO|l*@z#B0U0n~;6Q((CogEzq;QX^ml3_auK-QH(! zYRlFYydetV8<%jvXTLoPZWwqE2_hCzy1W?cwt!a;Ak6maMa=Kjv3M;3Tu%5uArNL? z-SSL!&nS5679sOBE+%t6kqdtVcsdc$>26x21CM6sb)#h-?QyJ literal 0 HcmV?d00001 diff --git a/ext/wasm3/platforms/android/gradle/wrapper/gradle-wrapper.properties b/ext/wasm3/platforms/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..c19e35b --- /dev/null +++ b/ext/wasm3/platforms/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.1-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/ext/wasm3/platforms/android/gradlew b/ext/wasm3/platforms/android/gradlew new file mode 100755 index 0000000..2fe81a7 --- /dev/null +++ b/ext/wasm3/platforms/android/gradlew @@ -0,0 +1,183 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/ext/wasm3/platforms/android/gradlew.bat b/ext/wasm3/platforms/android/gradlew.bat new file mode 100644 index 0000000..62bd9b9 --- /dev/null +++ b/ext/wasm3/platforms/android/gradlew.bat @@ -0,0 +1,103 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/ext/wasm3/platforms/android/override.txt b/ext/wasm3/platforms/android/override.txt new file mode 100644 index 0000000..670531e --- /dev/null +++ b/ext/wasm3/platforms/android/override.txt @@ -0,0 +1,43 @@ + +/* + * Override printf, puts, putchar + */ + +JNIEnv* jniEnv; + +void callOutputText(const char* text) { + JNIEnv *env = jniEnv; + + jstring javaMsg = (*env)->NewStringUTF(env, text); + (*env)->CallVoidMethod(env, activityObj, outputTextId, javaMsg); + (*env)->DeleteLocalRef(env, javaMsg); +} + +int printf(const char * format, ... ) +{ + char buff[256] = {}; + + va_list args; + va_start (args, format); + const int result = vsnprintf(buff, sizeof(buff), format, args); + va_end (args); + + if (result > 0) { + callOutputText(buff); + } + return result; +} + +int puts(const char *s) +{ + callOutputText(s); + callOutputText("\n"); + return strlen(s); +} + +int putchar(int c) +{ + char buff[2] = { c, '\0' }; + callOutputText(buff); + return c; +} diff --git a/ext/wasm3/platforms/android/settings.gradle b/ext/wasm3/platforms/android/settings.gradle new file mode 100644 index 0000000..e7b4def --- /dev/null +++ b/ext/wasm3/platforms/android/settings.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/ext/wasm3/platforms/app/README.md b/ext/wasm3/platforms/app/README.md new file mode 100644 index 0000000..17587ba --- /dev/null +++ b/ext/wasm3/platforms/app/README.md @@ -0,0 +1 @@ +This is the main file for Linux, Windows, Mac OS, OpenWRT builds diff --git a/ext/wasm3/platforms/app/main.c b/ext/wasm3/platforms/app/main.c new file mode 100644 index 0000000..d4af4e4 --- /dev/null +++ b/ext/wasm3/platforms/app/main.c @@ -0,0 +1,723 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include +#include +#include +#include + +#include "wasm3.h" +#include "m3_api_libc.h" + +#if defined(d_m3HasWASI) || defined(d_m3HasMetaWASI) || defined(d_m3HasUVWASI) +#include "m3_api_wasi.h" +#define LINK_WASI +#endif + +#if defined(d_m3HasTracer) +#include "m3_api_tracer.h" +#endif + +// TODO: remove +#include "m3_env.h" + +/* + * NOTE: Gas metering/limit only applies to pre-instrumented modules. + * You can generate a metered version from any wasm file automatically, using + * https://github.com/ewasm/wasm-metering + */ +#define GAS_LIMIT 500000000 +#define GAS_FACTOR 10000LL + +#define MAX_MODULES 16 + +#define FATAL(msg, ...) { fprintf(stderr, "Error: [Fatal] " msg "\n", ##__VA_ARGS__); goto _onfatal; } + + +static IM3Environment env; +static IM3Runtime runtime; + +static u8* wasm_bins[MAX_MODULES]; +static int wasm_bins_qty = 0; + +#if defined(GAS_LIMIT) + +static int64_t initial_gas = GAS_FACTOR * GAS_LIMIT; +static int64_t current_gas = GAS_FACTOR * GAS_LIMIT; +static bool is_gas_metered = false; + +m3ApiRawFunction(metering_usegas) +{ + m3ApiGetArg (int32_t, gas) + + current_gas -= gas; + + if (M3_UNLIKELY(current_gas < 0)) { + m3ApiTrap("[trap] Out of gas"); + } + m3ApiSuccess(); +} + +#endif // GAS_LIMIT + + +M3Result link_all (IM3Module module) +{ + M3Result res; + res = m3_LinkSpecTest (module); + if (res) return res; + + res = m3_LinkLibC (module); + if (res) return res; + +#if defined(LINK_WASI) + res = m3_LinkWASI (module); + if (res) return res; +#endif + +#if defined(d_m3HasTracer) + res = m3_LinkTracer (module); + if (res) return res; +#endif + +#if defined(GAS_LIMIT) + res = m3_LinkRawFunction (module, "metering", "usegas", "v(i)", &metering_usegas); + if (!res) { + fprintf(stderr, "Warning: Gas is limited to %0.4f\n", (double)(current_gas) / GAS_FACTOR); + is_gas_metered = true; + } + if (res == m3Err_functionLookupFailed) { res = NULL; } +#endif + + return res; +} + +const char* modname_from_fn(const char* fn) +{ + const char* sep = "/\\:*?"; + char c; + while ((c = *sep++)) { + const char* off = strrchr(fn, c) + 1; + fn = (fn < off) ? off : fn; + } + return fn; +} + +M3Result repl_load (const char* fn) +{ + M3Result result = m3Err_none; + IM3Module module = NULL; + + u8* wasm = NULL; + u32 fsize = 0; + + FILE* f = fopen (fn, "rb"); + if (!f) { + return "cannot open file"; + } + fseek (f, 0, SEEK_END); + fsize = ftell(f); + fseek (f, 0, SEEK_SET); + + if (fsize < 8) { + result = "file is too small"; + goto on_error; + } else if (fsize > 64*1024*1024) { + result = "file is too big"; + goto on_error; + } + + wasm = (u8*) malloc(fsize); + if (!wasm) { + result = "cannot allocate memory for wasm binary"; + goto on_error; + } + + if (fread (wasm, 1, fsize, f) != fsize) { + result = "cannot read file"; + goto on_error; + } + fclose (f); + f = NULL; + + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) goto on_error; + + result = m3_LoadModule (runtime, module); + if (result) goto on_error; + + m3_SetModuleName(module, modname_from_fn(fn)); + + result = link_all (module); + if (result) goto on_error; + + if (wasm_bins_qty < MAX_MODULES) { + wasm_bins[wasm_bins_qty++] = wasm; + } + + return result; + +on_error: + m3_FreeModule(module); + if (wasm) free(wasm); + if (f) fclose(f); + + return result; +} + +M3Result repl_load_hex (u32 fsize) +{ + M3Result result = m3Err_none; + + if (fsize < 8) { + return "file is too small"; + } else if (fsize > 10*1024*1024) { + return "file too big"; + } + + u8* wasm = (u8*) malloc(fsize); + if (!wasm) { + return "cannot allocate memory for wasm binary"; + } + + { // Load hex data from stdin + u32 wasm_idx = 0; + char hex[3] = { 0, }; + int hex_idx = 0; + while (wasm_idx < fsize) { + int c = fgetc(stdin); + if (!isxdigit(c)) continue; // Skip non-hex chars + hex[hex_idx++] = c; + if (hex_idx == 2) { + int val = strtol(hex, NULL, 16); + wasm[wasm_idx++] = val; + hex_idx = 0; + } + } + if (!fgets(hex, 3, stdin)) // Consume a newline + return "cannot read EOL"; + } + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) return result; + + result = m3_LoadModule (runtime, module); + if (result) return result; + + result = link_all (module); + + return result; +} + +void print_gas_used() +{ +#if defined(GAS_LIMIT) + if (is_gas_metered) { + fprintf(stderr, "Gas used: %0.4f\n", (double)(initial_gas - current_gas) / GAS_FACTOR); + } +#endif +} + +void print_backtrace() +{ + IM3BacktraceInfo info = m3_GetBacktrace(runtime); + if (!info) { + return; + } + + fprintf(stderr, "==== wasm backtrace:"); + + int frameCount = 0; + IM3BacktraceFrame curr = info->frames; + while (curr) + { + fprintf(stderr, "\n %d: 0x%06x - %s!%s", + frameCount, curr->moduleOffset, + m3_GetModuleName (m3_GetFunctionModule(curr->function)), + m3_GetFunctionName (curr->function) + ); + curr = curr->next; + frameCount++; + } + if (info->lastFrame == M3_BACKTRACE_TRUNCATED) { + fprintf(stderr, "\n (truncated)"); + } + fprintf(stderr, "\n"); +} + +M3Result repl_call (const char* name, int argc, const char* argv[]) +{ + IM3Function func; + M3Result result = m3_FindFunction (&func, runtime, name); + if (result) return result; + + if (argc && (!strcmp(name, "main") || !strcmp(name, "_main"))) { + return "passing arguments to libc main() not implemented"; + } + + if (!strcmp(name, "_start")) { +#if defined(LINK_WASI) + // Strip wasm file path + if (argc > 0) { + argv[0] = modname_from_fn(argv[0]); + } + + m3_wasi_context_t* wasi_ctx = m3_GetWasiContext(); + wasi_ctx->argc = argc; + wasi_ctx->argv = argv; + + result = m3_CallArgv(func, 0, NULL); + + print_gas_used(); + + if (result == m3Err_trapExit) { + exit(wasi_ctx->exit_code); + } + + return result; +#else + return "WASI not linked"; +#endif + } + + int arg_count = m3_GetArgCount(func); + int ret_count = m3_GetRetCount(func); + if (argc < arg_count) { + return "not enough arguments"; + } else if (argc > arg_count) { + return "too many arguments"; + } + + result = m3_CallArgv (func, argc, argv); + + print_gas_used(); + + if (result) return result; + + static uint64_t valbuff[128]; + static const void* valptrs[128]; + memset(valbuff, 0, sizeof(valbuff)); + for (int i = 0; i < ret_count; i++) { + valptrs[i] = &valbuff[i]; + } + result = m3_GetResults (func, ret_count, valptrs); + if (result) return result; + + if (ret_count <= 0) { + fprintf (stderr, "Result: \n"); + } + for (int i = 0; i < ret_count; i++) { + switch (m3_GetRetType(func, i)) { + case c_m3Type_i32: fprintf (stderr, "Result: %" PRIi32 "\n", *(i32*)valptrs[i]); break; + case c_m3Type_i64: fprintf (stderr, "Result: %" PRIi64 "\n", *(i64*)valptrs[i]); break; +# if d_m3HasFloat + case c_m3Type_f32: fprintf (stderr, "Result: %" PRIf32 "\n", *(f32*)valptrs[i]); break; + case c_m3Type_f64: fprintf (stderr, "Result: %" PRIf64 "\n", *(f64*)valptrs[i]); break; +# endif + default: return "unknown return type"; + } + } + + return result; +} + +// :invoke is used by spec tests, so it treats floats as raw data +M3Result repl_invoke (const char* name, int argc, const char* argv[]) +{ + IM3Function func; + M3Result result = m3_FindFunction (&func, runtime, name); + if (result) return result; + + int arg_count = m3_GetArgCount(func); + int ret_count = m3_GetRetCount(func); + + if (argc > 128) { + return "arguments limit reached"; + } else if (argc < arg_count) { + return "not enough arguments"; + } else if (argc > arg_count) { + return "too many arguments"; + } + + static uint64_t valbuff[128]; + static const void* valptrs[128]; + memset(valbuff, 0, sizeof(valbuff)); + memset(valptrs, 0, sizeof(valptrs)); + + for (int i = 0; i < argc; i++) { + u64* s = &valbuff[i]; + valptrs[i] = s; + switch (m3_GetArgType(func, i)) { + case c_m3Type_i32: + case c_m3Type_f32: *(u32*)(s) = strtoul(argv[i], NULL, 10); break; + case c_m3Type_i64: + case c_m3Type_f64: *(u64*)(s) = strtoull(argv[i], NULL, 10); break; + default: return "unknown argument type"; + } + } + + result = m3_Call (func, argc, valptrs); + if (result) return result; + + // reuse valbuff for return values + memset(valbuff, 0, sizeof(valbuff)); + for (int i = 0; i < ret_count; i++) { + valptrs[i] = &valbuff[i]; + } + result = m3_GetResults (func, ret_count, valptrs); + if (result) return result; + + fprintf (stderr, "Result: "); + if (ret_count <= 0) { + fprintf (stderr, ""); + } + for (int i = 0; i < ret_count; i++) { + switch (m3_GetRetType(func, i)) { + case c_m3Type_i32: fprintf (stderr, "%" PRIu32 ":i32", *(u32*)valptrs[i]); break; + case c_m3Type_f32: fprintf (stderr, "%" PRIu32 ":f32", *(u32*)valptrs[i]); break; + case c_m3Type_i64: fprintf (stderr, "%" PRIu64 ":i64", *(u64*)valptrs[i]); break; + case c_m3Type_f64: fprintf (stderr, "%" PRIu64 ":f64", *(u64*)valptrs[i]); break; + default: return "unknown return type"; + } + if (i != ret_count-1) { + fprintf (stderr, ", "); + } + } + fprintf (stderr, "\n"); + + return result; +} + +M3Result repl_global_get (const char* name) +{ + IM3Global g = m3_FindGlobal(runtime->modules, name); + + M3TaggedValue tagged; + M3Result err = m3_GetGlobal (g, &tagged); + if (err) return err; + + switch (tagged.type) { + case c_m3Type_i32: fprintf (stderr, "%" PRIu32 ":i32\n", tagged.value.i32); break; + case c_m3Type_i64: fprintf (stderr, "%" PRIu64 ":i64\n", tagged.value.i64); break; + case c_m3Type_f32: fprintf (stderr, "%" PRIf32 ":f32\n", tagged.value.f32); break; + case c_m3Type_f64: fprintf (stderr, "%" PRIf64 ":f64\n", tagged.value.f64); break; + default: return m3Err_invalidTypeId; + } + return m3Err_none; +} + +M3Result repl_global_set (const char* name, const char* value) +{ + IM3Global g = m3_FindGlobal(runtime->modules, name); + + M3TaggedValue tagged = { + .type = m3_GetGlobalType(g) + }; + + switch (tagged.type) { + case c_m3Type_i32: tagged.value.i32 = strtoul(value, NULL, 10); break; + case c_m3Type_i64: tagged.value.i64 = strtoull(value, NULL, 10); break; + case c_m3Type_f32: tagged.value.f32 = strtod(value, NULL); break; + case c_m3Type_f64: tagged.value.f64 = strtod(value, NULL); break; + default: return m3Err_invalidTypeId; + } + + return m3_SetGlobal (g, &tagged); +} + +M3Result repl_compile () +{ + return m3_CompileModule(runtime->modules); +} + +M3Result repl_dump () +{ + uint32_t len; + uint8_t* mem = m3_GetMemory(runtime, &len, 0); + if (mem) { + FILE* f = fopen ("wasm3_dump.bin", "wb"); + if (!f) { + return "cannot open file"; + } + if (fwrite (mem, 1, len, f) != len) { + return "cannot write file"; + } + fclose (f); + } + return m3Err_none; +} + +void repl_free () +{ + if (runtime) { + m3_FreeRuntime (runtime); + runtime = NULL; + } + + for (int i = 0; i < wasm_bins_qty; i++) { + free (wasm_bins[i]); + wasm_bins[i] = NULL; + } +} + +M3Result repl_init (unsigned stack) +{ + repl_free(); + runtime = m3_NewRuntime (env, stack, NULL); + if (runtime == NULL) { + return "m3_NewRuntime failed"; + } + return m3Err_none; +} + +static +void unescape(char* buff) +{ + char* outp = buff; + while (*buff) { + if (*buff == '\\') { + switch (*(buff+1)) { + case '0': *outp++ = '\0'; break; + case 'b': *outp++ = '\b'; break; + case 'n': *outp++ = '\n'; break; + case 'r': *outp++ = '\r'; break; + case 't': *outp++ = '\t'; break; + case 'x': { + char hex[3] = { *(buff+2), *(buff+3), '\0' }; + *outp = strtol(hex, NULL, 16); + buff += 2; outp += 1; + break; + } + // Otherwise just pass the letter + // Also handles '\\' + default: *outp++ = *(buff+1); break; + } + buff += 2; + } else { + *outp++ = *buff++; + } + } + *outp = '\0'; +} + +static +int split_argv(char *str, char** argv) +{ + int result = 0; + char* curr = str; + int len = 0; + for (int i = 0; str[i] != '\0'; i++) { + if (strchr(" \n\r\t", str[i])) { + if (len) { // Found space after non-space + str[i] = '\0'; + //unescape(curr); // TODO: breaks windows build? + argv[result++] = curr; + len = 0; + } + } else { + if (!len) { // Found non-space after space + curr = &str[i]; + } + len++; + } + } + argv[result] = NULL; + return result; +} + +void print_version() { + const char* wasm3_env = getenv("WASM3"); + const char* wasm3_arch = getenv("WASM3_ARCH"); + + printf("Wasm3 v" M3_VERSION "%s on %s\n", + (wasm3_arch || wasm3_env) ? " self-hosting" : "", + wasm3_arch ? wasm3_arch : M3_ARCH); + + printf("Build: " __DATE__ " " __TIME__ ", " M3_COMPILER_VER "\n"); +} + +void print_usage() { + puts("Usage:"); + puts(" wasm3 [options] [args...]"); + puts(" wasm3 --repl [file]"); + puts("Options:"); + puts(" --func function to run default: _start"); + puts(" --stack-size stack size in bytes default: 64KB"); + puts(" --compile disable lazy compilation"); + puts(" --dump-on-trap dump wasm memory"); + puts(" --gas-limit set gas limit"); +} + +#define ARGV_SHIFT() { i_argc--; i_argv++; } +#define ARGV_SET(x) { if (i_argc > 0) { x = i_argv[0]; ARGV_SHIFT(); } } + +int main (int i_argc, const char* i_argv[]) +{ + M3Result result = m3Err_none; + env = m3_NewEnvironment (); + runtime = NULL; + + bool argRepl = false; + bool argDumpOnTrap = false; + bool argCompile = false; + const char* argFile = NULL; + const char* argFunc = "_start"; + unsigned argStackSize = 64*1024; + +// m3_PrintM3Info (); + + ARGV_SHIFT(); // Skip executable name + + while (i_argc > 0) + { + const char* arg = i_argv[0]; + if (arg[0] != '-') break; + + ARGV_SHIFT(); + if (!strcmp("--help", arg) or !strcmp("-h", arg)) { + print_usage(); + return 0; + } else if (!strcmp("--version", arg)) { + print_version(); + return 0; + } else if (!strcmp("--repl", arg)) { + argRepl = true; + } else if (!strcmp("--dump-on-trap", arg)) { + argDumpOnTrap = true; + } else if (!strcmp("--compile", arg)) { + argCompile = true; + } else if (!strcmp("--stack-size", arg)) { + const char* tmp = "65536"; + ARGV_SET(tmp); + argStackSize = atol(tmp); + } else if (!strcmp("--gas-limit", arg)) { + const char* tmp = "0"; + ARGV_SET(tmp); + initial_gas = current_gas = GAS_FACTOR * atol(tmp); + } else if (!strcmp("--dir", arg)) { + const char* argDir; + ARGV_SET(argDir); + (void)argDir; + } else if (!strcmp("--func", arg) or !strcmp("-f", arg)) { + ARGV_SET(argFunc); + } + } + + if ((argRepl and (i_argc > 1)) or // repl supports 0 or 1 args + (not argRepl and (i_argc < 1)) // normal expects at least 1 + ) { + print_usage(); + return 1; + } + + ARGV_SET(argFile); + + result = repl_init(argStackSize); + if (result) FATAL("repl_init: %s", result); + + if (argFile) { + result = repl_load(argFile); + if (result) FATAL("repl_load: %s", result); + + if (argCompile) { + repl_compile(); + } + + if (argFunc and not argRepl) { + if (!strcmp(argFunc, "_start")) { + // When passing args to WASI, include wasm filename as argv[0] + result = repl_call(argFunc, i_argc+1, i_argv-1); + } else { + result = repl_call(argFunc, i_argc, i_argv); + } + + if (result) { + if (argDumpOnTrap) { + repl_dump(); + } + print_backtrace(); + goto _onfatal; + } + } + } + + while (argRepl) + { + char cmd_buff[2048] = { 0, }; + char* argv[32] = { 0, }; + fprintf(stdout, "wasm3> "); + fflush(stdout); + if (!fgets(cmd_buff, sizeof(cmd_buff), stdin)) { + return 0; + } + int argc = split_argv(cmd_buff, argv); + if (argc <= 0) { + continue; + } + result = m3Err_none; + if (!strcmp(":init", argv[0])) { + result = repl_init(argStackSize); + } else if (!strcmp(":version", argv[0])) { + print_version(); + } else if (!strcmp(":exit", argv[0])) { + repl_free(); + return 0; + } else if (!strcmp(":load", argv[0])) { // :load + result = repl_load(argv[1]); + } else if (!strcmp(":load-hex", argv[0])) { // :load-hex \n + result = repl_load_hex(atol(argv[1])); + } else if (!strcmp(":get-global", argv[0])) { + result = repl_global_get(argv[1]); + } else if (!strcmp(":set-global", argv[0])) { + result = repl_global_set(argv[1], argv[2]); + } else if (!strcmp(":dump", argv[0])) { + result = repl_dump(); + } else if (!strcmp(":compile", argv[0])) { + result = repl_compile(); + } else if (!strcmp(":invoke", argv[0])) { + unescape(argv[1]); + result = repl_invoke(argv[1], argc-2, (const char**)(argv+2)); + } else if (argv[0][0] == ':') { + result = "no such command"; + } else { + unescape(argv[0]); + result = repl_call(argv[0], argc-1, (const char**)(argv+1)); + if (result) { + print_backtrace(); + } + } + + if (result == m3Err_trapExit) { + //TODO: fprintf(stderr, M3_ARCH "-wasi: exit(%d)\n", runtime->exit_code); + } else if (result) { + fprintf (stderr, "Error: %s", result); + M3ErrorInfo info; + m3_GetErrorInfo (runtime, &info); + fprintf (stderr, " (%s)\n", info.message); + } + } + +_onfatal: + if (result) { + fprintf (stderr, "Error: %s", result); + if (runtime) + { + M3ErrorInfo info; + m3_GetErrorInfo (runtime, &info); + if (strlen(info.message)) { + fprintf (stderr, " (%s)", info.message); + } + } + fprintf (stderr, "\n"); + } + + m3_FreeRuntime (runtime); + m3_FreeEnvironment (env); + + return result ? 1 : 0; +} diff --git a/ext/wasm3/platforms/app_fuzz/fuzzer.c b/ext/wasm3/platforms/app_fuzz/fuzzer.c new file mode 100644 index 0000000..b97d649 --- /dev/null +++ b/ext/wasm3/platforms/app_fuzz/fuzzer.c @@ -0,0 +1,49 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include +#include + +#include "wasm3.h" + +#define FATAL(...) __builtin_trap() + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + M3Result result = m3Err_none; + + if (size < 8 || size > 256*1024) { + return 0; + } + + IM3Environment env = m3_NewEnvironment (); + if (env) { + IM3Runtime runtime = m3_NewRuntime (env, 128, NULL); + if (runtime) { + IM3Module module = NULL; + result = m3_ParseModule (env, &module, data, size); + if (module) { + result = m3_LoadModule (runtime, module); + if (result == 0) { + IM3Function f = NULL; + result = m3_FindFunction (&f, runtime, "fib"); + /* TODO: + if (f) { + m3_CallV (f, 10); + }*/ + } else { + m3_FreeModule (module); + } + } + + m3_FreeRuntime(runtime); + } + m3_FreeEnvironment(env); + } + + return 0; +} diff --git a/ext/wasm3/platforms/cosmopolitan/.gitignore b/ext/wasm3/platforms/cosmopolitan/.gitignore new file mode 100644 index 0000000..8352c97 --- /dev/null +++ b/ext/wasm3/platforms/cosmopolitan/.gitignore @@ -0,0 +1,4 @@ +cosmopolitan/ +wasm3.com +wasm3.com.dbg + diff --git a/ext/wasm3/platforms/cosmopolitan/build.sh b/ext/wasm3/platforms/cosmopolitan/build.sh new file mode 100755 index 0000000..b84f995 --- /dev/null +++ b/ext/wasm3/platforms/cosmopolitan/build.sh @@ -0,0 +1,41 @@ + +COSMOPOLITAN_VERSION=1.0 +COSMOPOLITAN_URL=https://github.com/jart/cosmopolitan/releases/download/$COSMOPOLITAN_VERSION/cosmopolitan-amalgamation-$COSMOPOLITAN_VERSION.zip + +SOURCE_DIR=../../source + +EXTRA_FLAGS="-Dd_m3PreferStaticAlloc -Dd_m3HasWASI" + +STD=./cosmopolitan/std + +if [ ! -d "./cosmopolitan" ]; then + echo "Downloading Cosmopolitan..." + curl -L -o cosmopolitan.zip $COSMOPOLITAN_URL + unzip cosmopolitan.zip -d cosmopolitan + rm cosmopolitan.zip +fi + +if [ ! -d "$STD/sys" ]; then + # Generate header stubs + mkdir -p $STD/sys + touch $STD/assert.h $STD/limits.h $STD/ctype.h $STD/time.h $STD/errno.h \ + $STD/inttypes.h $STD/fcntl.h $STD/math.h $STD/stdarg.h $STD/stdbool.h \ + $STD/stdint.h $STD/stdio.h $STD/stdlib.h $STD/string.h $STD/stddef.h \ + $STD/sys/types.h $STD/sys/stat.h $STD/unistd.h $STD/sys/uio.h \ + $STD/sys/random.h +fi + +echo "Building Wasm3..." + +# TODO: remove -fno-strict-aliasing + +gcc -g -Os -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone \ + -Wl,--gc-sections -Wl,-z,max-page-size=0x1000 -fuse-ld=bfd \ + -Wl,-T,cosmopolitan/ape.lds -include cosmopolitan/cosmopolitan.h \ + -Wno-format-security -Wfatal-errors -fno-strict-aliasing $EXTRA_FLAGS \ + -fomit-frame-pointer -fno-stack-check -fno-stack-protector \ + -o wasm3.com.dbg -DAPE -I$STD -I$SOURCE_DIR $SOURCE_DIR/*.c ../app/main.c \ + cosmopolitan/crt.o cosmopolitan/ape.o cosmopolitan/cosmopolitan.a + +objcopy -SO binary wasm3.com.dbg wasm3.com + diff --git a/ext/wasm3/platforms/cpp/.gitignore b/ext/wasm3/platforms/cpp/.gitignore new file mode 100644 index 0000000..6be3b8f --- /dev/null +++ b/ext/wasm3/platforms/cpp/.gitignore @@ -0,0 +1,2 @@ +build +cmake-build-debug diff --git a/ext/wasm3/platforms/cpp/CMakeLists.txt b/ext/wasm3/platforms/cpp/CMakeLists.txt new file mode 100644 index 0000000..1230a33 --- /dev/null +++ b/ext/wasm3/platforms/cpp/CMakeLists.txt @@ -0,0 +1,25 @@ +cmake_minimum_required(VERSION 3.9) +project(wasm3_cpp_example) + +set(target ${CMAKE_PROJECT_NAME}) + +add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../../source ${CMAKE_BINARY_DIR}/m3) + +add_executable(${target} main.cpp) +target_link_libraries(${target} PRIVATE m3) + +add_subdirectory(wasm3_cpp) +target_link_libraries(${target} PRIVATE wasm3_cpp) + +target_compile_options(${target} PUBLIC -g) +target_compile_options(m3 PUBLIC -g) + +# Copy the 'wasm' directory into the build directory, so that +# wasm/test_prog.wasm is found even if wasm3_cpp_example is executed +# from the build directory. +add_custom_target(copy_wasm ALL + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_LIST_DIR}/wasm + ${CMAKE_BINARY_DIR}/wasm +) +add_dependencies(${CMAKE_PROJECT_NAME} copy_wasm) diff --git a/ext/wasm3/platforms/cpp/README.md b/ext/wasm3/platforms/cpp/README.md new file mode 100644 index 0000000..7751ff3 --- /dev/null +++ b/ext/wasm3/platforms/cpp/README.md @@ -0,0 +1,98 @@ +## C++ wrapper + +This example shows how to embed WASM3 into a C++ application. It uses a header-only library, `wasm3_cpp.h`, provided in `wasm3_cpp` subdirectory. Like WASM3 itself, this library can be included into CMake projects using `add_subdirectory` function. + +The main code of the example in `main.cpp` initializes WASM3, loads a WebAssembly module, links two external functions to the module, and executes two functions defined in WebAssembly. + +The WebAssembly module source code is inside `wasm` subdirectory. + +### `wasm3_cpp.h` reference + +All the classes are located in `wasm3` namespace. + +#### Class `environment` + +`environment::environment()` — create a new WASM3 environment. Runtimes, modules are owned by an environment. + +`runtime environment::new_runtime(size_t stack_size_bytes)` — create new runtime inside the environment. + +`module environment::parse_module(std::istream &in)` or `module environment::parse_module(const uint8_t *data, size_t size)` — parse a WASM binary module. + +#### Class `runtime` + +`runtime` objects are created using `environment::new_runtime` method, see above. + +`void runtime::load(module &m)` — load a parsed module into the runtime. + +`function runtime::find_function(const char *name)` — find a function defined in one of the loaded modules, by name. Raises a `wasm3::error` exception if the function is not found. + +#### Class `module` + +`module` objects are created by `environment::parse_module`. Parsed modules can be loaded into a `runtime` object. One module can only be loaded into one runtime. + +Before loading a module, you may need to link some external functions to it: + +`template void module::link(const char *mod, const char *function_name, Func *function)` — link a function `function` to module named `mod` under the name `function_name`. To link to any module, use `mod="*"`. + +`function` has to be either a non-member function or a static member function. + +Currently, the following types of arguments can be passed to functions linked this way: + +* int32_t +* int64_t +* float +* double +* const/non-const pointers + +Automatic conversion of other integral types may be implemented in the future. + +If the module doesn't reference an imported function named `func`, an exception is thrown. To link a function "optionally", i.e. without throwing an exception if the function is not imported, use `module::link_optional` instead. + +#### Class `function` + +`function` object can be obtained from a `runtime`, looking up the function by name. Function objects are used to call WebAssembly functions. + +`template Ret function::call(Args...)` — calls a WebAssembly function with or without arguments and a return value.
      +The return value of the function, if not `void`, is automatically converted to the type `Ret`.
      +Note that you always need to specify the matching return type when using this template with a non-void function.
      +Examples: +```cpp +// WASM signature: [] → [] +func.call(); + +// WASM signature: [i32, i32] → [] +func.call(42, 43); // implicit argument types + +// WASM signature: [i32, i64] → [] +func.call(42, 43); // explicit argument types require the return type + +// WASM signature: [] → [i32] +auto result = func.call(); + +// WASM signature: [i32, i32] → [i64] +auto result = func.call(42, 43); // implicit argument types + +// WASM signature: [i32, i64] → [i64] +auto result = func.call(42, 43); // explicit argument types + +``` + +`template Ret function::call_argv(Args...)` — same as above, except that this function takes arguments as C strings (`const char*`). + +### Building and running + +This directory is a CMake project, and can be built as follows: + +```bash +mkdir build +cd build +cmake .. +cmake --build . +``` + +Then run the example: + +```bash +./wasm3_cpp_example +``` + diff --git a/ext/wasm3/platforms/cpp/main.cpp b/ext/wasm3/platforms/cpp/main.cpp new file mode 100644 index 0000000..93b4dcb --- /dev/null +++ b/ext/wasm3/platforms/cpp/main.cpp @@ -0,0 +1,89 @@ +#include +#include +#include + +#include "wasm3_cpp.h" +#include "wasm/test_prog.wasm.h" + +int sum(int a, int b) +{ + return a + b; +} + +void * ext_memcpy (void* dst, const void* arg, int32_t size) +{ + return memcpy(dst, arg, (size_t) size); +} + +int main(void) +{ + std::cout << "Loading WebAssembly..." << std::endl; + + /* Wasm module can be loaded from a file */ + try { + wasm3::environment env; + wasm3::runtime runtime = env.new_runtime(1024); + const char* file_name = "wasm/test_prog.wasm"; + std::ifstream wasm_file(file_name, std::ios::binary | std::ios::in); + if (!wasm_file.is_open()) { + throw std::runtime_error("Failed to open wasm file"); + } + wasm3::module mod = env.parse_module(wasm_file); + runtime.load(mod); + } + catch(std::runtime_error &e) { + std::cerr << "WASM3 error: " << e.what() << std::endl; + return 1; + } + + /* Wasm module can also be loaded from an array */ + try { + wasm3::environment env; + wasm3::runtime runtime = env.new_runtime(1024); + wasm3::module mod = env.parse_module(test_prog_wasm, test_prog_wasm_len); + runtime.load(mod); + + mod.link("*", "sum", sum); + mod.link("*", "ext_memcpy", ext_memcpy); + + { + wasm3::function test_fn = runtime.find_function("test"); + auto res = test_fn.call(20, 10); + std::cout << "result: " << res << std::endl; + } + { + wasm3::function memcpy_test_fn = runtime.find_function("test_memcpy"); + auto res = memcpy_test_fn.call(); + std::cout << "result: 0x" << std::hex << res << std::dec << std::endl; + } + + /** + * Calling functions that modify an internal state, with mixed argument / return types + */ + { + wasm3::function counter_get_fn = runtime.find_function("test_counter_get"); + wasm3::function counter_inc_fn = runtime.find_function("test_counter_inc"); + wasm3::function counter_add_fn = runtime.find_function("test_counter_add"); + + // call with no arguments and a return value + auto value = counter_get_fn.call(); + std::cout << "counter: " << value << std::endl; + + // call with no arguments and no return value + counter_inc_fn.call(); + value = counter_get_fn.call(); + std::cout << "counter after increment: " << value << std::endl; + + // call with one argument and no return value + counter_add_fn.call(42); + value = counter_get_fn.call(); + std::cout << "counter after adding value: " << value << std::endl; + } + } + catch(wasm3::error &e) { + std::cerr << "WASM3 error: " << e.what() << std::endl; + return 1; + } + + return 0; +} diff --git a/ext/wasm3/platforms/cpp/wasm/Makefile b/ext/wasm3/platforms/cpp/wasm/Makefile new file mode 100644 index 0000000..acdf6e1 --- /dev/null +++ b/ext/wasm3/platforms/cpp/wasm/Makefile @@ -0,0 +1,18 @@ +NAME=test_prog +SRC=$(NAME).c +WASM=$(NAME).wasm +HEADER=$(NAME).wasm.h +EMCC_FLAGS=-s STANDALONE_WASM -s ERROR_ON_UNDEFINED_SYMBOLS=0 -O3 + +all: $(HEADER) + +clean: + rm -f $(HEADER) $(WASM) + +.PHONY: all clean + +$(WASM): $(SRC) + emcc $< -o $@ $(EMCC_FLAGS) + +$(HEADER): $(WASM) + xxd -i $< >$@ diff --git a/ext/wasm3/platforms/cpp/wasm/test_prog.c b/ext/wasm3/platforms/cpp/wasm/test_prog.c new file mode 100644 index 0000000..c11c8d9 --- /dev/null +++ b/ext/wasm3/platforms/cpp/wasm/test_prog.c @@ -0,0 +1,41 @@ +#include +#include + +extern int sum(int, int); +extern int ext_memcpy(void*, const void*, size_t); + +int32_t counter = 0; + +#define WASM_EXPORT __attribute__((used)) __attribute__((visibility ("default"))) + +int WASM_EXPORT test(int32_t arg1, int32_t arg2) +{ + int x = arg1 + arg2; + int y = arg1 - arg2; + return sum(x, y) / 2; +} + +int64_t WASM_EXPORT test_memcpy(void) +{ + int64_t x = 0; + int32_t low = 0x01234567; + int32_t high = 0x89abcdef; + ext_memcpy(&x, &low, 4); + ext_memcpy(((uint8_t*)&x) + 4, &high, 4); + return x; +} + +int32_t WASM_EXPORT test_counter_get() +{ + return counter; +} + +void WASM_EXPORT test_counter_inc() +{ + ++counter; +} + +void WASM_EXPORT test_counter_add(int32_t inc_value) +{ + counter += inc_value; +} diff --git a/ext/wasm3/platforms/cpp/wasm/test_prog.wasm.h b/ext/wasm3/platforms/cpp/wasm/test_prog.wasm.h new file mode 100644 index 0000000..d54e08c --- /dev/null +++ b/ext/wasm3/platforms/cpp/wasm/test_prog.wasm.h @@ -0,0 +1,68 @@ +unsigned char test_prog_wasm[] = { + 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x22, 0x07, 0x60, + 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x00, 0x60, 0x00, 0x00, + 0x60, 0x00, 0x01, 0x7f, 0x60, 0x03, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, + 0x00, 0x01, 0x7e, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x02, 0x94, 0x01, 0x06, + 0x03, 0x65, 0x6e, 0x76, 0x03, 0x73, 0x75, 0x6d, 0x00, 0x00, 0x03, 0x65, + 0x6e, 0x76, 0x0a, 0x65, 0x78, 0x74, 0x5f, 0x6d, 0x65, 0x6d, 0x63, 0x70, + 0x79, 0x00, 0x04, 0x16, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x73, 0x6e, 0x61, + 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, 0x65, + 0x77, 0x31, 0x0e, 0x61, 0x72, 0x67, 0x73, 0x5f, 0x73, 0x69, 0x7a, 0x65, + 0x73, 0x5f, 0x67, 0x65, 0x74, 0x00, 0x00, 0x16, 0x77, 0x61, 0x73, 0x69, + 0x5f, 0x73, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, + 0x65, 0x76, 0x69, 0x65, 0x77, 0x31, 0x08, 0x61, 0x72, 0x67, 0x73, 0x5f, + 0x67, 0x65, 0x74, 0x00, 0x00, 0x03, 0x65, 0x6e, 0x76, 0x04, 0x6d, 0x61, + 0x69, 0x6e, 0x00, 0x00, 0x16, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x73, 0x6e, + 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x76, 0x69, + 0x65, 0x77, 0x31, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x5f, 0x65, 0x78, 0x69, + 0x74, 0x00, 0x01, 0x03, 0x0c, 0x0b, 0x02, 0x00, 0x05, 0x03, 0x02, 0x01, + 0x02, 0x03, 0x01, 0x06, 0x03, 0x04, 0x05, 0x01, 0x70, 0x01, 0x02, 0x02, + 0x05, 0x06, 0x01, 0x01, 0x80, 0x02, 0x80, 0x02, 0x06, 0x09, 0x01, 0x7f, + 0x01, 0x41, 0x90, 0x88, 0xc0, 0x02, 0x0b, 0x07, 0xb8, 0x01, 0x0c, 0x06, + 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x04, 0x74, 0x65, 0x73, + 0x74, 0x00, 0x07, 0x0b, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x6d, 0x65, 0x6d, + 0x63, 0x70, 0x79, 0x00, 0x08, 0x10, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x5f, 0x67, 0x65, 0x74, 0x00, 0x09, + 0x10, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, + 0x72, 0x5f, 0x69, 0x6e, 0x63, 0x00, 0x0a, 0x10, 0x74, 0x65, 0x73, 0x74, + 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x5f, 0x61, 0x64, 0x64, + 0x00, 0x0b, 0x19, 0x5f, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x72, 0x65, 0x63, + 0x74, 0x5f, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, + 0x61, 0x62, 0x6c, 0x65, 0x01, 0x00, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x00, 0x0c, 0x10, 0x5f, 0x5f, 0x65, 0x72, 0x72, 0x6e, 0x6f, 0x5f, + 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x10, 0x09, 0x73, + 0x74, 0x61, 0x63, 0x6b, 0x53, 0x61, 0x76, 0x65, 0x00, 0x0d, 0x0c, 0x73, + 0x74, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x00, + 0x0e, 0x0a, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x41, 0x6c, 0x6c, 0x6f, 0x63, + 0x00, 0x0f, 0x09, 0x07, 0x01, 0x00, 0x41, 0x01, 0x0b, 0x01, 0x06, 0x0a, + 0xd1, 0x02, 0x0b, 0x03, 0x00, 0x01, 0x0b, 0x11, 0x00, 0x20, 0x00, 0x20, + 0x01, 0x6a, 0x20, 0x00, 0x20, 0x01, 0x6b, 0x10, 0x00, 0x41, 0x02, 0x6d, + 0x0b, 0x58, 0x02, 0x02, 0x7f, 0x01, 0x7e, 0x23, 0x00, 0x41, 0x10, 0x6b, + 0x22, 0x00, 0x24, 0x00, 0x20, 0x00, 0x42, 0x00, 0x37, 0x03, 0x08, 0x20, + 0x00, 0x41, 0xe7, 0x8a, 0x8d, 0x09, 0x36, 0x02, 0x04, 0x20, 0x00, 0x41, + 0xef, 0x9b, 0xaf, 0xcd, 0x78, 0x36, 0x02, 0x00, 0x20, 0x00, 0x41, 0x08, + 0x6a, 0x22, 0x01, 0x20, 0x00, 0x41, 0x04, 0x6a, 0x41, 0x04, 0x10, 0x01, + 0x1a, 0x20, 0x01, 0x41, 0x04, 0x72, 0x20, 0x00, 0x41, 0x04, 0x10, 0x01, + 0x1a, 0x20, 0x00, 0x29, 0x03, 0x08, 0x21, 0x02, 0x20, 0x00, 0x41, 0x10, + 0x6a, 0x24, 0x00, 0x20, 0x02, 0x0b, 0x08, 0x00, 0x41, 0x80, 0x08, 0x28, + 0x02, 0x00, 0x0b, 0x11, 0x00, 0x41, 0x80, 0x08, 0x41, 0x80, 0x08, 0x28, + 0x02, 0x00, 0x41, 0x01, 0x6a, 0x36, 0x02, 0x00, 0x0b, 0x11, 0x00, 0x41, + 0x80, 0x08, 0x41, 0x80, 0x08, 0x28, 0x02, 0x00, 0x20, 0x00, 0x6a, 0x36, + 0x02, 0x00, 0x0b, 0x8f, 0x01, 0x01, 0x04, 0x7f, 0x02, 0x7f, 0x23, 0x00, + 0x41, 0x10, 0x6b, 0x22, 0x00, 0x24, 0x00, 0x02, 0x40, 0x20, 0x00, 0x22, + 0x01, 0x41, 0x0c, 0x6a, 0x20, 0x00, 0x41, 0x08, 0x6a, 0x10, 0x02, 0x45, + 0x04, 0x40, 0x20, 0x01, 0x28, 0x02, 0x0c, 0x22, 0x02, 0x04, 0x7f, 0x20, + 0x00, 0x20, 0x02, 0x41, 0x02, 0x74, 0x22, 0x03, 0x41, 0x13, 0x6a, 0x41, + 0x70, 0x71, 0x6b, 0x22, 0x00, 0x24, 0x00, 0x20, 0x00, 0x20, 0x01, 0x28, + 0x02, 0x08, 0x41, 0x0f, 0x6a, 0x41, 0x70, 0x71, 0x6b, 0x22, 0x02, 0x24, + 0x00, 0x20, 0x00, 0x20, 0x03, 0x6a, 0x41, 0x00, 0x36, 0x02, 0x00, 0x20, + 0x00, 0x20, 0x02, 0x10, 0x03, 0x0d, 0x02, 0x20, 0x01, 0x28, 0x02, 0x0c, + 0x05, 0x41, 0x00, 0x0b, 0x20, 0x00, 0x10, 0x04, 0x21, 0x00, 0x20, 0x01, + 0x41, 0x10, 0x6a, 0x24, 0x00, 0x20, 0x00, 0x0c, 0x02, 0x0b, 0x41, 0xc7, + 0x00, 0x10, 0x05, 0x00, 0x0b, 0x41, 0xc7, 0x00, 0x10, 0x05, 0x00, 0x0b, + 0x10, 0x05, 0x00, 0x0b, 0x04, 0x00, 0x23, 0x00, 0x0b, 0x06, 0x00, 0x20, + 0x00, 0x24, 0x00, 0x0b, 0x10, 0x00, 0x23, 0x00, 0x20, 0x00, 0x6b, 0x41, + 0x70, 0x71, 0x22, 0x00, 0x24, 0x00, 0x20, 0x00, 0x0b, 0x05, 0x00, 0x41, + 0x84, 0x08, 0x0b +}; +unsigned int test_prog_wasm_len = 771; diff --git a/ext/wasm3/platforms/cpp/wasm3_cpp/CMakeLists.txt b/ext/wasm3/platforms/cpp/wasm3_cpp/CMakeLists.txt new file mode 100644 index 0000000..1cd3216 --- /dev/null +++ b/ext/wasm3/platforms/cpp/wasm3_cpp/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.5) +add_library(wasm3_cpp INTERFACE) +target_include_directories(wasm3_cpp INTERFACE include) +target_compile_features(wasm3_cpp INTERFACE cxx_std_17) diff --git a/ext/wasm3/platforms/cpp/wasm3_cpp/include/wasm3_cpp.h b/ext/wasm3/platforms/cpp/wasm3_cpp/include/wasm3_cpp.h new file mode 100644 index 0000000..c12a127 --- /dev/null +++ b/ext/wasm3/platforms/cpp/wasm3_cpp/include/wasm3_cpp.h @@ -0,0 +1,412 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wasm3.h" + + +namespace wasm3 { + /** @cond */ + namespace detail { + typedef uint64_t *stack_type; + typedef void *mem_type; + template struct first_type { typedef T type; }; + + typedef const void *(*m3_api_raw_fn)(IM3Runtime, uint64_t *, void *); + + template + void arg_from_stack(T &dest, stack_type &_sp, mem_type mem) { + m3ApiGetArg(T, tmp); + dest = tmp; + } + + template + void arg_from_stack(T* &dest, stack_type &_sp, mem_type _mem) { + m3ApiGetArgMem(T*, tmp); + dest = tmp; + }; + + template + void arg_from_stack(const T* &dest, stack_type &_sp, mem_type _mem) { + m3ApiGetArgMem(const T*, tmp); + dest = tmp; + }; + + template + struct m3_sig { + static const char value = c; + }; + template struct m3_type_to_sig; + template<> struct m3_type_to_sig : m3_sig<'i'> {}; + template<> struct m3_type_to_sig : m3_sig<'I'> {}; + template<> struct m3_type_to_sig : m3_sig<'f'> {}; + template<> struct m3_type_to_sig : m3_sig<'F'> {}; + template<> struct m3_type_to_sig : m3_sig<'v'> {}; + template<> struct m3_type_to_sig : m3_sig<'*'> {}; + template<> struct m3_type_to_sig : m3_sig<'*'> {}; + + + template + struct m3_signature { + constexpr static size_t n_args = sizeof...(Args); + constexpr static const char value[n_args + 4] = { + m3_type_to_sig::value, + '(', + m3_type_to_sig::value..., + ')', + 0 + }; + }; + + template + static void get_args_from_stack(stack_type &sp, mem_type mem, std::tuple &tuple) { + std::apply([&](auto &... item) { + (arg_from_stack(item, sp, mem), ...); + }, tuple); + } + + template + struct wrap_helper; + + template + struct wrap_helper { + using Func = Ret(Args...); + static const void *wrap_fn(IM3Runtime rt, IM3ImportContext _ctx, stack_type _sp, mem_type mem) { + std::tuple args; + // The order here matters: m3ApiReturnType should go before calling get_args_from_stack, + // since both modify `_sp`, and the return value on the stack is reserved before the arguments. + m3ApiReturnType(Ret); + get_args_from_stack(_sp, mem, args); + Func* function = reinterpret_cast(_ctx->userdata); + Ret r = std::apply(function, args); + m3ApiReturn(r); + } + }; + + template + struct wrap_helper { + using Func = void(Args...); + static const void *wrap_fn(IM3Runtime rt, IM3ImportContext _ctx, stack_type sp, mem_type mem) { + std::tuple args; + get_args_from_stack(sp, mem, args); + Func* function = reinterpret_cast(_ctx->userdata); + std::apply(function, args); + m3ApiSuccess(); + } + }; + + template + class m3_wrapper; + + template + class m3_wrapper { + public: + static M3Result link(IM3Module io_module, + const char *const i_moduleName, + const char *const i_functionName, + Ret (*function)(Args...)) { + + return m3_LinkRawFunctionEx(io_module, i_moduleName, i_functionName, + m3_signature::value, + &wrap_helper::wrap_fn, + reinterpret_cast(function)); + } + }; + } // namespace detail + /** @endcond */ + + class module; + class runtime; + class function; + + /** + * Exception thrown for wasm3 errors. + * + * Use error:what() to get the reason as a string. + */ + class error : public std::runtime_error { + public: + explicit error(M3Result err) : std::runtime_error(err) {} + }; + + /** @cond */ + namespace detail { + static inline void check_error(M3Result err) { + if (err != m3Err_none) { + throw error(err); + } + } + } // namespace detail + /** @endcond */ + + + /** + * Wrapper for WASM3 environment. + * + * Runtimes, modules are owned by an environment. + */ + class environment { + public: + environment() { + m_env.reset(m3_NewEnvironment(), m3_FreeEnvironment); + if (m_env == nullptr) { + throw std::bad_alloc(); + } + } + + /** + * Create new runtime + * + * @param stack_size_bytes size of the WASM stack for this runtime + * @return runtime object + */ + runtime new_runtime(size_t stack_size_bytes); + + /** + * Parse a WASM module from file + * + * The parsed module is not loaded into any runtime. Use runtime::load to + * load the module after parsing it. + * + * @param in file (WASM binary) + * @return module object + */ + module parse_module(std::istream &in); + + /** + * Parse a WASM module from binary data + * + * @param data pointer to the start of the binary + * @param size size of the binary + * @return module object + */ + module parse_module(const uint8_t *data, size_t size); + + protected: + std::shared_ptr m_env; + }; + + /** + * Wrapper for the runtime, where modules are loaded and executed. + */ + class runtime { + public: + /** + * Load the module into runtime + * @param mod module parsed by environment::parse_module + */ + void load(module &mod); + + /** + * Get a function handle by name + * + * If the function is not found, throws an exception. + * @param name name of a function, c-string + * @return function object + */ + function find_function(const char *name); + + protected: + friend class environment; + + runtime(const std::shared_ptr &env, size_t stack_size_bytes) + : m_env(env) { + m_runtime.reset(m3_NewRuntime(env.get(), stack_size_bytes, nullptr), &m3_FreeRuntime); + if (m_runtime == nullptr) { + throw std::bad_alloc(); + } + } + + /* runtime extends the lifetime of the environment */ + std::shared_ptr m_env; + std::shared_ptr m_runtime; + }; + + /** + * Module object holds a webassembly module + * + * It can be constructed by parsing a WASM binary using environment::parse_module. + * Functions can be linked to the loaded module. + * Once constructed, modules can be loaded into the runtime. + */ + class module { + public: + /** + * Link an external function. + * + * Throws an exception if the module doesn't reference a function with the given name. + * + * @tparam Func Function type (signature) + * @param module Name of the module to link the function to, or "*" to link to any module + * @param function_name Name of the function (as referenced by the module) + * @param function Function to link (a function pointer) + */ + template + void link(const char *module, const char *function_name, Func *function); + + /** + * Same as module::link, but doesn't throw an exception if the function is not referenced. + */ + template + void link_optional(const char *module, const char *function_name, Func *function); + + + protected: + friend class environment; + friend class runtime; + + module(const std::shared_ptr &env, std::istream &in_wasm) { + in_wasm.unsetf(std::ios::skipws); + std::copy(std::istream_iterator(in_wasm), + std::istream_iterator(), + std::back_inserter(m_moduleRawData)); + parse(env.get(), m_moduleRawData.data(), m_moduleRawData.size()); + } + + module(const std::shared_ptr &env, const uint8_t *data, size_t size) : m_env(env) { + m_moduleRawData = std::vector{data, data + size}; + parse(env.get(), m_moduleRawData.data(), m_moduleRawData.size()); + } + + void parse(IM3Environment env, const uint8_t *data, size_t size) { + IM3Module p; + M3Result err = m3_ParseModule(env, &p, data, size); + detail::check_error(err); + m_module.reset(p, [this](IM3Module module) { + if (!m_loaded) { + m3_FreeModule(module); + } + }); + } + + void load_into(IM3Runtime runtime) { + M3Result err = m3_LoadModule(runtime, m_module.get()); + detail::check_error(err); + m_loaded = true; + } + + std::shared_ptr m_env; + std::shared_ptr m_module; + bool m_loaded = false; + std::vector m_moduleRawData {}; + }; + + + /** + * Handle of a function. Can be obtained from runtime::find_function method by name. + */ + class function { + public: + /** + * Call the function with the provided arguments, expressed as strings. + * + * Arguments are passed as strings. WASM3 automatically converts them into the types expected + * by the function being called. + * + * Note that the type of the return value must be explicitly specified as a template argument. + * + * @return the return value of the function. + */ + template + typename detail::first_type::value>::type...>::type + call_argv(Args... args) { + /* std::enable_if above checks that all argument types are convertible const char* */ + const char* argv[] = {args...}; + M3Result res = m3_CallArgv(m_func, sizeof...(args), argv); + detail::check_error(res); + Ret ret; + res = m3_GetResults(m_func, 1, &ret); + detail::check_error(res); + return ret; + } + + template + typename detail::first_type::value>::type...>::type + call_argv(Args... args) { + /* std::enable_if above checks that all argument types are convertible const char* */ + const char* argv[] = {args...}; + M3Result res = m3_CallArgv(m_func, sizeof...(args), argv); + detail::check_error(res); + } + + /** + * Call the function with the provided arguments (int/float types). + * + * Note that the type of the return value must be explicitly specified as a template argument. + * + * @return the return value of the function or void. + */ + template + Ret call(Args... args) { + const void *arg_ptrs[] = { reinterpret_cast(&args)... }; + M3Result res = m3_Call(m_func, sizeof...(args), arg_ptrs); + detail::check_error(res); + + if constexpr (!std::is_void::value) { + Ret ret; + const void* ret_ptrs[] = { &ret }; + res = m3_GetResults(m_func, 1, ret_ptrs); + detail::check_error(res); + return ret; + } + } + + protected: + friend class runtime; + + function(const std::shared_ptr &runtime, const char *name) : m_runtime(runtime) { + M3Result err = m3_FindFunction(&m_func, runtime.get(), name); + detail::check_error(err); + assert(m_func != nullptr); + } + + std::shared_ptr m_runtime; + M3Function *m_func = nullptr; + }; + + inline runtime environment::new_runtime(size_t stack_size_bytes) { + return runtime(m_env, stack_size_bytes); + } + + inline module environment::parse_module(std::istream &in) { + return module(m_env, in); + } + + inline module environment::parse_module(const uint8_t *data, size_t size) { + return module(m_env, data, size); + } + + inline void runtime::load(module &mod) { + mod.load_into(m_runtime.get()); + } + + inline function runtime::find_function(const char *name) { + return function(m_runtime, name); + } + + template + void module::link(const char *module, const char *function_name, Func *function) { + M3Result ret = detail::m3_wrapper::link(m_module.get(), module, function_name, function); + detail::check_error(ret); + } + + template + void module::link_optional(const char *module, const char *function_name, Func *function) { + M3Result ret = detail::m3_wrapper::link(m_module.get(), module, function_name, function); + if (ret == m3Err_functionLookupFailed) { + return; + } + detail::check_error(ret); + } + +} // namespace wasm3 diff --git a/ext/wasm3/platforms/embedded/arduino/.gitignore b/ext/wasm3/platforms/embedded/arduino/.gitignore new file mode 100644 index 0000000..03f4a3c --- /dev/null +++ b/ext/wasm3/platforms/embedded/arduino/.gitignore @@ -0,0 +1 @@ +.pio diff --git a/ext/wasm3/platforms/embedded/arduino/lib/wasm3 b/ext/wasm3/platforms/embedded/arduino/lib/wasm3 new file mode 120000 index 0000000..17056a9 --- /dev/null +++ b/ext/wasm3/platforms/embedded/arduino/lib/wasm3 @@ -0,0 +1 @@ +../../../../source \ No newline at end of file diff --git a/ext/wasm3/platforms/embedded/arduino/platformio.ini b/ext/wasm3/platforms/embedded/arduino/platformio.ini new file mode 100644 index 0000000..dceda85 --- /dev/null +++ b/ext/wasm3/platforms/embedded/arduino/platformio.ini @@ -0,0 +1,137 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[platformio] +default_envs = + mkr1000 + due + mega1284 + tinyBLE + blenano + blenano2 + teensy31 + bluepill-mapple + bluepill + az3166 + maix + #titiva TODO: undefined reference to `_exit' + +[env] +framework = arduino +monitor_speed = 115200 + +src_filter = + +<*> + - + +[env:mkr1000] +platform = atmelsam +board = mkr1000USB + +src_build_flags = + -O3 -Wfatal-errors + -flto + #-fPIC -fomit-frame-pointer -foptimize-sibling-calls + +[env:due] +platform = atmelsam +board = due + +src_build_flags = + -O3 -Wfatal-errors + -flto + +[env:mega1284] +platform = atmelavr +board = wildfirev3 + +src_build_flags = + -Dd_m3CodePageAlignSize=512 + -Os -Wfatal-errors + -flto + +[env:tinyBLE] +platform = nordicnrf51 +board = seeedTinyBLE + +src_build_flags = + -O3 -Wfatal-errors + -flto + +[env:blenano] +platform = nordicnrf51 +board = redBearLabBLENano + +src_build_flags = + -O3 -Wfatal-errors + -flto + +[env:blenano2] +platform = nordicnrf52 +board = redbear_blenano2 + +src_build_flags = + -O3 -Wfatal-errors + -flto + +[env:teensy31] +platform = teensy +board = teensy31 +upload_protocol = teensy-cli + +src_build_flags = + -O3 -Wfatal-errors + -flto + +[env:bluepill-mapple] +platform = ststm32 +board = bluepill_f103c8_128k +board_build.core = maple +upload_protocol = stlink +#upload_protocol = dfu + +src_build_flags = + -Dd_m3FixedHeap=8192 + -Os -Wfatal-errors + -flto + +[env:bluepill] +platform = ststm32 +board = bluepill_f103c8 +upload_protocol = stlink + +src_build_flags = + -Dd_m3FixedHeap=8192 + -Os -Wfatal-errors + -flto + +[env:az3166] +platform = ststm32 +board = mxchip_az3166 + +src_build_flags = + -O3 -Wfatal-errors + -flto + +[env:maix] +platform = kendryte210 +board = sipeed-maix-one-dock + +src_build_flags = + -O3 -Wfatal-errors + -flto + +[env:titiva] +platform = titiva +board = lptm4c1294ncpdt + +src_build_flags = + -DLED_BUILTIN=13 + -O3 -Wfatal-errors diff --git a/ext/wasm3/platforms/embedded/arduino/src/main.cpp b/ext/wasm3/platforms/embedded/arduino/src/main.cpp new file mode 100644 index 0000000..f14d4f6 --- /dev/null +++ b/ext/wasm3/platforms/embedded/arduino/src/main.cpp @@ -0,0 +1,82 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include "Arduino.h" + +#include "wasm3.h" + +#include "extra/fib32.wasm.h" + +#define FATAL(func, msg) { \ + Serial.print("Fatal: " func ": "); \ + Serial.println(msg); return; } + +void run_wasm() +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + size_t fsize = fib32_wasm_len; + + Serial.println("Loading WebAssembly..."); + + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment", "failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + if (!runtime) FATAL("m3_NewRuntime", "failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction", result); + + Serial.println("Running..."); + + result = m3_CallV(f, 24); + if (result) FATAL("m3_Call", result); + + uint32_t value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults: %s", result); + + Serial.print("Result: "); + Serial.println(value); +} + +void setup() +{ + pinMode(LED_BUILTIN, OUTPUT); + + Serial.begin(115200); + delay(10); + while (!Serial) {} + + Serial.println(); + Serial.println("Wasm3 v" M3_VERSION " on Arduino (" M3_ARCH "), build " __DATE__ " " __TIME__); + + digitalWrite(LED_BUILTIN, HIGH); + uint32_t start = millis(); + run_wasm(); + uint32_t end = millis(); + digitalWrite(LED_BUILTIN, LOW); + + Serial.print("Elapsed: "); + Serial.print(end - start); + Serial.println(" ms"); +} + +void loop() +{ + delay(100); +} diff --git a/ext/wasm3/platforms/embedded/bluepill/.gitignore b/ext/wasm3/platforms/embedded/bluepill/.gitignore new file mode 100644 index 0000000..03f4a3c --- /dev/null +++ b/ext/wasm3/platforms/embedded/bluepill/.gitignore @@ -0,0 +1 @@ +.pio diff --git a/ext/wasm3/platforms/embedded/bluepill/lib/wasm3/library.json b/ext/wasm3/platforms/embedded/bluepill/lib/wasm3/library.json new file mode 100644 index 0000000..38cdf08 --- /dev/null +++ b/ext/wasm3/platforms/embedded/bluepill/lib/wasm3/library.json @@ -0,0 +1,7 @@ +{ + "build" : { + "flags": "-Os -fomit-frame-pointer -fno-stack-check -fno-stack-protector -Wfatal-errors -Wno-unused-function -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers", + "srcFilter": ["+<*>", "-"], + "libArchive": false + } +} diff --git a/ext/wasm3/platforms/embedded/bluepill/lib/wasm3/src b/ext/wasm3/platforms/embedded/bluepill/lib/wasm3/src new file mode 120000 index 0000000..e3e41d7 --- /dev/null +++ b/ext/wasm3/platforms/embedded/bluepill/lib/wasm3/src @@ -0,0 +1 @@ +../../../../../source \ No newline at end of file diff --git a/ext/wasm3/platforms/embedded/bluepill/platformio.ini b/ext/wasm3/platforms/embedded/bluepill/platformio.ini new file mode 100644 index 0000000..6b3199b --- /dev/null +++ b/ext/wasm3/platforms/embedded/bluepill/platformio.ini @@ -0,0 +1,10 @@ +[env:bluepill] +platform = ststm32 +board = bluepill_f103c8 +framework = stm32cube +upload_protocol = stlink +lib_deps = jeeh + +build_flags = + -Dd_m3FixedHeap=8192 + -Os -Wfatal-errors diff --git a/ext/wasm3/platforms/embedded/bluepill/src/main.cpp b/ext/wasm3/platforms/embedded/bluepill/src/main.cpp new file mode 100644 index 0000000..120af16 --- /dev/null +++ b/ext/wasm3/platforms/embedded/bluepill/src/main.cpp @@ -0,0 +1,75 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include "wasm3.h" + +#include "extra/fib32.wasm.h" + +#include +#include + +#define FATAL(func, msg) { \ + puts("Fatal: " func ": "); \ + puts(msg); return; } + +void run_wasm() +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + size_t fsize = fib32_wasm_len; + + puts("Loading WebAssembly..."); + + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment", "failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + if (!runtime) FATAL("m3_NewRuntime", "failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction", result); + + puts("Running..."); + + result = m3_CallV (f, 24); + if (result) FATAL("m3_Call", result); + + uint32_t value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults", result); + + char buff[32]; + itoa(value, buff, 10); + + puts("Result: "); + puts(buff); + puts("\n"); +} + +PinC<13> led; + +int main() +{ + enableSysTick(); + led.mode(Pinmode::out); + + puts("Wasm3 v" M3_VERSION " on BluePill, build " __DATE__ " " __TIME__ "\n"); + + led = 0; + run_wasm(); + led = 1; + +} diff --git a/ext/wasm3/platforms/embedded/esp32-idf-wasi/.gitignore b/ext/wasm3/platforms/embedded/esp32-idf-wasi/.gitignore new file mode 100644 index 0000000..d054d84 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf-wasi/.gitignore @@ -0,0 +1,3 @@ +build +sdkconfig +sdkconfig.old diff --git a/ext/wasm3/platforms/embedded/esp32-idf-wasi/.old/Makefile b/ext/wasm3/platforms/embedded/esp32-idf-wasi/.old/Makefile new file mode 100644 index 0000000..2f23716 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf-wasi/.old/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := wasm3 + +include $(IDF_PATH)/make/project.mk + diff --git a/ext/wasm3/platforms/embedded/esp32-idf-wasi/.old/component.mk b/ext/wasm3/platforms/embedded/esp32-idf-wasi/.old/component.mk new file mode 100644 index 0000000..0b9d758 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf-wasi/.old/component.mk @@ -0,0 +1,5 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + diff --git a/ext/wasm3/platforms/embedded/esp32-idf-wasi/CMakeLists.txt b/ext/wasm3/platforms/embedded/esp32-idf-wasi/CMakeLists.txt new file mode 100644 index 0000000..d88e541 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf-wasi/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(wasm3) diff --git a/ext/wasm3/platforms/embedded/esp32-idf-wasi/README.md b/ext/wasm3/platforms/embedded/esp32-idf-wasi/README.md new file mode 100644 index 0000000..eeaeb12 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf-wasi/README.md @@ -0,0 +1,24 @@ +## Build for ESP-IDF, with minimal WASI support + +**Note:** Currently, to run this example you need a PSRAM-enabled ESP32 module (this might be improved in future). + +Download and install ESP-IDF v4.0 + +```sh +export IDF_PATH=/opt/esp32/esp-idf + +# Set tools path if needed: +#export IDF_TOOLS_PATH=/opt/esp32 + +source $IDF_PATH/export.sh + +idf.py menuconfig + +# Select target: +idf.py set-target esp32 # or: esp32s2, esp32c3, esp32s3, linux + +idf.py build + +idf.py -p /dev/ttyUSB0 flash monitor + +``` diff --git a/ext/wasm3/platforms/embedded/esp32-idf-wasi/main/CMakeLists.txt b/ext/wasm3/platforms/embedded/esp32-idf-wasi/main/CMakeLists.txt new file mode 100644 index 0000000..ce8b13f --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf-wasi/main/CMakeLists.txt @@ -0,0 +1,11 @@ +file(GLOB_RECURSE M3_SOURCES "wasm3/*.c") + +set(APP_SOURCES "main.cpp" "m3_api_esp_wasi.c") + +idf_component_register(SRCS ${APP_SOURCES} ${M3_SOURCES} + INCLUDE_DIRS "wasm3") + +target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error -O3 -DESP32 -Dd_m3MaxFunctionStackHeight=256) + +# Disable harmless warnings +target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-unused-function -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers) diff --git a/ext/wasm3/platforms/embedded/esp32-idf-wasi/main/m3_api_esp_wasi.c b/ext/wasm3/platforms/embedded/esp32-idf-wasi/main/m3_api_esp_wasi.c new file mode 100644 index 0000000..c2f35a8 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf-wasi/main/m3_api_esp_wasi.c @@ -0,0 +1,616 @@ +// +// m3_api_esp_wasi.c +// +// Created by Volodymyr Shymanskyy on 01/07/20. +// Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. +// + +#define _POSIX_C_SOURCE 200809L + +#include "m3_api_esp_wasi.h" + +#include "m3_env.h" +#include "m3_exception.h" + +#if defined(ESP32) + +typedef uint32_t __wasi_size_t; +#include "extra/wasi_core.h" + +#include +#include +#include +#include +#include +#include +#include + +static m3_wasi_context_t* wasi_context; + +typedef struct wasi_iovec_t +{ + __wasi_size_t buf; + __wasi_size_t buf_len; +} wasi_iovec_t; + +#define PREOPEN_CNT 3 + +typedef struct Preopen { + int fd; + char* path; +} Preopen; + +Preopen preopen[PREOPEN_CNT] = { + { 0, "" }, + { 1, "" }, + { 2, "" }, +}; + +# define APE_SWITCH_BEG switch (errnum) { +# define APE_SWITCH_END } +# define APE_CASE_RET(e1,e2) case e1: return e2; break; + +static +__wasi_errno_t errno_to_wasi(int errnum) { + APE_SWITCH_BEG + APE_CASE_RET( EPERM , __WASI_ERRNO_PERM ) + APE_CASE_RET( ENOENT , __WASI_ERRNO_NOENT ) + APE_CASE_RET( ESRCH , __WASI_ERRNO_SRCH ) + APE_CASE_RET( EINTR , __WASI_ERRNO_INTR ) + APE_CASE_RET( EIO , __WASI_ERRNO_IO ) + APE_CASE_RET( ENXIO , __WASI_ERRNO_NXIO ) + APE_CASE_RET( E2BIG , __WASI_ERRNO_2BIG ) + APE_CASE_RET( ENOEXEC , __WASI_ERRNO_NOEXEC ) + APE_CASE_RET( EBADF , __WASI_ERRNO_BADF ) + APE_CASE_RET( ECHILD , __WASI_ERRNO_CHILD ) + APE_CASE_RET( EAGAIN , __WASI_ERRNO_AGAIN ) + APE_CASE_RET( ENOMEM , __WASI_ERRNO_NOMEM ) + APE_CASE_RET( EACCES , __WASI_ERRNO_ACCES ) + APE_CASE_RET( EFAULT , __WASI_ERRNO_FAULT ) + APE_CASE_RET( EBUSY , __WASI_ERRNO_BUSY ) + APE_CASE_RET( EEXIST , __WASI_ERRNO_EXIST ) + APE_CASE_RET( EXDEV , __WASI_ERRNO_XDEV ) + APE_CASE_RET( ENODEV , __WASI_ERRNO_NODEV ) + APE_CASE_RET( ENOTDIR , __WASI_ERRNO_NOTDIR ) + APE_CASE_RET( EISDIR , __WASI_ERRNO_ISDIR ) + APE_CASE_RET( EINVAL , __WASI_ERRNO_INVAL ) + APE_CASE_RET( ENFILE , __WASI_ERRNO_NFILE ) + APE_CASE_RET( EMFILE , __WASI_ERRNO_MFILE ) + APE_CASE_RET( ENOTTY , __WASI_ERRNO_NOTTY ) + APE_CASE_RET( ETXTBSY , __WASI_ERRNO_TXTBSY ) + APE_CASE_RET( EFBIG , __WASI_ERRNO_FBIG ) + APE_CASE_RET( ENOSPC , __WASI_ERRNO_NOSPC ) + APE_CASE_RET( ESPIPE , __WASI_ERRNO_SPIPE ) + APE_CASE_RET( EROFS , __WASI_ERRNO_ROFS ) + APE_CASE_RET( EMLINK , __WASI_ERRNO_MLINK ) + APE_CASE_RET( EPIPE , __WASI_ERRNO_PIPE ) + APE_CASE_RET( EDOM , __WASI_ERRNO_DOM ) + APE_CASE_RET( ERANGE , __WASI_ERRNO_RANGE ) + APE_SWITCH_END + return __WASI_ERRNO_INVAL; +} + +static inline +int convert_clockid(__wasi_clockid_t in) { + switch (in) { + case __WASI_CLOCKID_MONOTONIC: return CLOCK_MONOTONIC; + //case __WASI_CLOCKID_PROCESS_CPUTIME_ID: return CLOCK_PROCESS_CPUTIME_ID; + case __WASI_CLOCKID_REALTIME: return CLOCK_REALTIME; + //case __WASI_CLOCKID_THREAD_CPUTIME_ID: return CLOCK_THREAD_CPUTIME_ID; + default: return -1; + } +} + +static inline +__wasi_timestamp_t convert_timespec(const struct timespec *ts) { + if (ts->tv_sec < 0) + return 0; + if ((__wasi_timestamp_t)ts->tv_sec >= UINT64_MAX / 1000000000) + return UINT64_MAX; + return (__wasi_timestamp_t)ts->tv_sec * 1000000000 + ts->tv_nsec; +} + + +/* + * WASI API implementation + */ + +m3ApiRawFunction(m3_wasi_generic_args_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint32_t * , argv) + m3ApiGetArgMem (char * , argv_buf) + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context == NULL) { m3ApiReturn(__WASI_ERRNO_INVAL); } + + m3ApiCheckMem(argv, context->argc * sizeof(uint32_t)); + + for (u32 i = 0; i < context->argc; ++i) + { + m3ApiWriteMem32(&argv[i], m3ApiPtrToOffset(argv_buf)); + + size_t len = strlen (context->argv[i]); + + m3ApiCheckMem(argv_buf, len); + memcpy (argv_buf, context->argv[i], len); + argv_buf += len; + * argv_buf++ = 0; + } + + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_args_sizes_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (__wasi_size_t * , argc) + m3ApiGetArgMem (__wasi_size_t * , argv_buf_size) + + m3ApiCheckMem(argc, sizeof(__wasi_size_t)); + m3ApiCheckMem(argv_buf_size, sizeof(__wasi_size_t)); + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context == NULL) { m3ApiReturn(__WASI_ERRNO_INVAL); } + + __wasi_size_t buf_len = 0; + for (u32 i = 0; i < context->argc; ++i) + { + buf_len += strlen (context->argv[i]) + 1; + } + + m3ApiWriteMem32(argc, context->argc); + m3ApiWriteMem32(argv_buf_size, buf_len); + + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_environ_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint32_t * , env) + m3ApiGetArgMem (char * , env_buf) + + // TODO + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_environ_sizes_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (__wasi_size_t * , env_count) + m3ApiGetArgMem (__wasi_size_t * , env_buf_size) + + m3ApiCheckMem(env_count, sizeof(__wasi_size_t)); + m3ApiCheckMem(env_buf_size, sizeof(__wasi_size_t)); + + // TODO + m3ApiWriteMem32(env_count, 0); + m3ApiWriteMem32(env_buf_size, 0); + + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_fd_prestat_dir_name) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (char * , path) + m3ApiGetArg (__wasi_size_t , path_len) + + m3ApiCheckMem(path, path_len); + + if (fd < 3 || fd >= PREOPEN_CNT) { m3ApiReturn(__WASI_ERRNO_BADF); } + size_t slen = strlen(preopen[fd].path) + 1; + memcpy(path, preopen[fd].path, M3_MIN(slen, path_len)); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_fd_prestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(buf, 8); + + if (fd < 3 || fd >= PREOPEN_CNT) { m3ApiReturn(__WASI_ERRNO_BADF); } + + m3ApiWriteMem32(buf+0, __WASI_PREOPENTYPE_DIR); + m3ApiWriteMem32(buf+4, strlen(preopen[fd].path) + 1); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_fd_fdstat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (__wasi_fdstat_t * , fdstat) + + m3ApiCheckMem(fdstat, sizeof(__wasi_fdstat_t)); + + struct stat fd_stat; + int fl = fcntl(fd, F_GETFL); + if (fl < 0) { m3ApiReturn(errno_to_wasi(errno)); } + fstat(fd, &fd_stat); + int mode = fd_stat.st_mode; + fdstat->fs_filetype = (S_ISBLK(mode) ? __WASI_FILETYPE_BLOCK_DEVICE : 0) | + (S_ISCHR(mode) ? __WASI_FILETYPE_CHARACTER_DEVICE : 0) | + (S_ISDIR(mode) ? __WASI_FILETYPE_DIRECTORY : 0) | + (S_ISREG(mode) ? __WASI_FILETYPE_REGULAR_FILE : 0) | + //(S_ISSOCK(mode) ? __WASI_FILETYPE_SOCKET_STREAM : 0) | + (S_ISLNK(mode) ? __WASI_FILETYPE_SYMBOLIC_LINK : 0); + m3ApiWriteMem16(&fdstat->fs_flags, + ((fl & O_APPEND) ? __WASI_FDFLAGS_APPEND : 0) | + //((fl & O_DSYNC) ? __WASI_FDFLAGS_DSYNC : 0) | + ((fl & O_NONBLOCK) ? __WASI_FDFLAGS_NONBLOCK : 0) | + //((fl & O_RSYNC) ? __WASI_FDFLAGS_RSYNC : 0) | + ((fl & O_SYNC) ? __WASI_FDFLAGS_SYNC : 0)); + + fdstat->fs_rights_base = (uint64_t)-1; // all rights + + // Make descriptors 0,1,2 look like a TTY + if (fd <= 2) { + fdstat->fs_rights_base &= ~(__WASI_RIGHTS_FD_SEEK | __WASI_RIGHTS_FD_TELL); + } + + fdstat->fs_rights_inheriting = (uint64_t)-1; // all rights + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_fd_fdstat_set_flags) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_fdflags_t , flags) + + // TODO + + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_unstable_fd_seek) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_filedelta_t , offset) + m3ApiGetArg (uint32_t , wasi_whence) + m3ApiGetArgMem (__wasi_filesize_t * , result) + + m3ApiCheckMem(result, sizeof(__wasi_filesize_t)); + + int whence; + + switch (wasi_whence) { + case 0: whence = SEEK_CUR; break; + case 1: whence = SEEK_END; break; + case 2: whence = SEEK_SET; break; + default: m3ApiReturn(__WASI_ERRNO_INVAL); + } + + int64_t ret; + ret = lseek(fd, offset, whence); + if (ret < 0) { m3ApiReturn(errno_to_wasi(errno)); } + m3ApiWriteMem64(result, ret); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_snapshot_preview1_fd_seek) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_filedelta_t , offset) + m3ApiGetArg (uint32_t , wasi_whence) + m3ApiGetArgMem (__wasi_filesize_t * , result) + + m3ApiCheckMem(result, sizeof(__wasi_filesize_t)); + + int whence; + + switch (wasi_whence) { + case 0: whence = SEEK_SET; break; + case 1: whence = SEEK_CUR; break; + case 2: whence = SEEK_END; break; + default: m3ApiReturn(__WASI_ERRNO_INVAL); + } + + int64_t ret; + ret = lseek(fd, offset, whence); + if (ret < 0) { m3ApiReturn(errno_to_wasi(errno)); } + m3ApiWriteMem64(result, ret); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + + +m3ApiRawFunction(m3_wasi_generic_path_open) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , dirfd) + m3ApiGetArg (__wasi_lookupflags_t , dirflags) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (__wasi_size_t , path_len) + m3ApiGetArg (__wasi_oflags_t , oflags) + m3ApiGetArg (__wasi_rights_t , fs_rights_base) + m3ApiGetArg (__wasi_rights_t , fs_rights_inheriting) + m3ApiGetArg (__wasi_fdflags_t , fs_flags) + m3ApiGetArgMem (__wasi_fd_t * , fd) + + m3ApiCheckMem(path, path_len); + m3ApiCheckMem(fd, sizeof(__wasi_fd_t)); + + if (path_len >= 512) + m3ApiReturn(__WASI_ERRNO_INVAL); + + // copy path so we can ensure it is NULL terminated + char host_path[path_len+1]; + + memcpy (host_path, path, path_len); + host_path[path_len] = '\0'; // NULL terminator + + // TODO + m3ApiReturn(__WASI_ERRNO_NOSYS); +} + +m3ApiRawFunction(m3_wasi_generic_fd_read) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (__wasi_size_t , iovs_len) + m3ApiGetArgMem (__wasi_size_t * , nread) + + m3ApiCheckMem(wasi_iovs, iovs_len * sizeof(wasi_iovec_t)); + m3ApiCheckMem(nread, sizeof(__wasi_size_t)); + + ssize_t res = 0; + for (__wasi_size_t i = 0; i < iovs_len; i++) { + void* addr = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iovs[i].buf)); + size_t len = m3ApiReadMem32(&wasi_iovs[i].buf_len); + if (len == 0) continue; + + int ret = read (fd, addr, len); + if (ret < 0) m3ApiReturn(errno_to_wasi(errno)); + res += ret; + if ((size_t)ret < len) break; + } + m3ApiWriteMem32(nread, res); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_fd_write) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (__wasi_size_t , iovs_len) + m3ApiGetArgMem (__wasi_size_t * , nwritten) + + m3ApiCheckMem(wasi_iovs, iovs_len * sizeof(wasi_iovec_t)); + m3ApiCheckMem(nwritten, sizeof(__wasi_size_t)); + + ssize_t res = 0; + for (__wasi_size_t i = 0; i < iovs_len; i++) { + void* addr = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iovs[i].buf)); + size_t len = m3ApiReadMem32(&wasi_iovs[i].buf_len); + if (len == 0) continue; + + int ret = write (fd, addr, len); + if (ret < 0) m3ApiReturn(errno_to_wasi(errno)); + res += ret; + if ((size_t)ret < len) break; + } + m3ApiWriteMem32(nwritten, res); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_fd_close) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t, fd) + + int ret = close(fd); + m3ApiReturn(ret == 0 ? __WASI_ERRNO_SUCCESS : ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_datasync) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t, fd) + + // TODO + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_random_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint8_t * , buf) + m3ApiGetArg (__wasi_size_t , buf_len) + + m3ApiCheckMem(buf, buf_len); + + while (1) { + ssize_t retlen = 0; + +#if defined(__wasi__) || defined(__APPLE__) || defined(__ANDROID_API__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__) + size_t reqlen = M3_MIN (buf_len, 256); +# if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) + retlen = SecRandomCopyBytes(kSecRandomDefault, reqlen, buf) < 0 ? -1 : reqlen; +# else + retlen = getentropy(buf, reqlen) < 0 ? -1 : reqlen; +# endif +#elif defined(__FreeBSD__) || defined(__linux__) + retlen = getrandom(buf, buf_len, 0); +#elif defined(_WIN32) + if (RtlGenRandom(buf, buf_len) == TRUE) { + m3ApiReturn(__WASI_ERRNO_SUCCESS); + } +#else + m3ApiReturn(__WASI_ERRNO_NOSYS); +#endif + if (retlen < 0) { + if (errno == EINTR || errno == EAGAIN) { + continue; + } + m3ApiReturn(errno_to_wasi(errno)); + } else if (retlen == buf_len) { + m3ApiReturn(__WASI_ERRNO_SUCCESS); + } else { + buf += retlen; + buf_len -= retlen; + } + } +} + +m3ApiRawFunction(m3_wasi_generic_clock_res_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_clockid_t , wasi_clk_id) + m3ApiGetArgMem (__wasi_timestamp_t * , resolution) + + m3ApiCheckMem(resolution, sizeof(__wasi_timestamp_t)); + + int clk = convert_clockid(wasi_clk_id); + if (clk < 0) m3ApiReturn(__WASI_ERRNO_INVAL); + + struct timespec tp; + if (clock_getres(clk, &tp) != 0) { + m3ApiWriteMem64(resolution, 1000000); + } else { + m3ApiWriteMem64(resolution, convert_timespec(&tp)); + } + + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_clock_time_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_clockid_t , wasi_clk_id) + m3ApiGetArg (__wasi_timestamp_t , precision) + m3ApiGetArgMem (__wasi_timestamp_t * , time) + + m3ApiCheckMem(time, sizeof(__wasi_timestamp_t)); + + int clk = convert_clockid(wasi_clk_id); + if (clk < 0) m3ApiReturn(__WASI_ERRNO_INVAL); + + struct timespec tp; + if (clock_gettime(clk, &tp) != 0) { + m3ApiReturn(errno_to_wasi(errno)); + } + + m3ApiWriteMem64(time, convert_timespec(&tp)); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_proc_exit) +{ + m3ApiGetArg (uint32_t, code) + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context) { + context->exit_code = code; + } + + m3ApiTrap(m3Err_trapExit); +} + + +static +M3Result SuppressLookupFailure(M3Result i_result) +{ + if (i_result == m3Err_functionLookupFailed) + return m3Err_none; + else + return i_result; +} + +m3_wasi_context_t* m3_GetWasiContext() +{ + return wasi_context; +} + + +M3Result m3_LinkEspWASI (IM3Module module) +{ + M3Result result = m3Err_none; + + // TODO: Preopen dirs + + if (!wasi_context) { + wasi_context = (m3_wasi_context_t*)malloc(sizeof(m3_wasi_context_t)); + wasi_context->exit_code = 0; + wasi_context->argc = 0; + wasi_context->argv = 0; + } + + static const char* namespaces[2] = { "wasi_unstable", "wasi_snapshot_preview1" }; + + // fd_seek is incompatible +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_unstable", "fd_seek", "i(iIi*)", &m3_wasi_unstable_fd_seek))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1", "fd_seek", "i(iIi*)", &m3_wasi_snapshot_preview1_fd_seek))); + + for (int i=0; i<2; i++) + { + const char* wasi = namespaces[i]; + +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "args_get", "i(**)", &m3_wasi_generic_args_get, wasi_context))); +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "args_sizes_get", "i(**)", &m3_wasi_generic_args_sizes_get, wasi_context))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_res_get", "i(i*)", &m3_wasi_generic_clock_res_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_time_get", "i(iI*)", &m3_wasi_generic_clock_time_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_get", "i(**)", &m3_wasi_generic_environ_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_sizes_get", "i(**)", &m3_wasi_generic_environ_sizes_get))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_advise", "i(iIIi)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_allocate", "i(iII)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_close", "i(i)", &m3_wasi_generic_fd_close))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_datasync", "i(i)", &m3_wasi_generic_fd_datasync))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_get", "i(i*)", &m3_wasi_generic_fd_fdstat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_flags", "i(ii)", &m3_wasi_generic_fd_fdstat_set_flags))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_rights", "i(iII)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_get", "i(i*)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_size", "i(iI)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_times","i(iIIi)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pread", "i(i*iI*)",))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_get", "i(i*)", &m3_wasi_generic_fd_prestat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_dir_name", "i(i*i)", &m3_wasi_generic_fd_prestat_dir_name))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pwrite", "i(i*iI*)",))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_read", "i(i*i*)", &m3_wasi_generic_fd_read))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_readdir", "i(i*iI*)",))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_renumber", "i(ii)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_sync", "i(i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_tell", "i(i*)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_write", "i(i*i*)", &m3_wasi_generic_fd_write))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_create_directory", "i(i*i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_filestat_get", "i(ii*i*)", &m3_wasi_generic_path_filestat_get))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_filestat_set_times", "i(ii*iIIi)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_link", "i(ii*ii*i)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_open", "i(ii*iiIIi*)", &m3_wasi_generic_path_open))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_readlink", "i(i*i*i*)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_remove_directory", "i(i*i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_rename", "i(i*ii*i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_symlink", "i(*ii*i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_unlink_file", "i(i*i)", ))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "poll_oneoff", "i(**i*)", &m3_wasi_generic_poll_oneoff))); +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "proc_exit", "v(i)", &m3_wasi_generic_proc_exit, wasi_context))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "proc_raise", "i(i)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "random_get", "i(*i)", &m3_wasi_generic_random_get))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sched_yield", "i()", ))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_recv", "i(i*ii**)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_send", "i(i*ii*)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_shutdown", "i(ii)", ))); + } + +_catch: + return result; +} + +#endif // ESP32 + diff --git a/ext/wasm3/platforms/embedded/esp32-idf-wasi/main/m3_api_esp_wasi.h b/ext/wasm3/platforms/embedded/esp32-idf-wasi/main/m3_api_esp_wasi.h new file mode 100644 index 0000000..0d53d64 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf-wasi/main/m3_api_esp_wasi.h @@ -0,0 +1,28 @@ +// +// m3_api_esp_wasi.h +// +// Created by Volodymyr Shymanskyy on 01/07/20. +// Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. +// + +#ifndef m3_api_esp_wasi_h +#define m3_api_esp_wasi_h + +#include "m3_core.h" + +d_m3BeginExternC + +typedef struct m3_wasi_context_t +{ + i32 exit_code; + u32 argc; + ccstr_t * argv; +} m3_wasi_context_t; + + M3Result m3_LinkEspWASI (IM3Module io_module); + +m3_wasi_context_t* m3_GetWasiContext(); + +d_m3EndExternC + +#endif /* m3_api_esp_wasi_h */ diff --git a/ext/wasm3/platforms/embedded/esp32-idf-wasi/main/main.cpp b/ext/wasm3/platforms/embedded/esp32-idf-wasi/main/main.cpp new file mode 100644 index 0000000..b61d7a1 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf-wasi/main/main.cpp @@ -0,0 +1,76 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include "esp_system.h" + +#include +#include +#include + +#include "wasm3.h" +#include "m3_env.h" + +#include "m3_api_esp_wasi.h" +#include "wasi_test.wasm.h" + +#define FATAL(msg, ...) { printf("Fatal: " msg "\n", ##__VA_ARGS__); return; } + +static void run_wasm(void) +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)wasi_test_wasm; + uint32_t fsize = wasi_test_wasm_len; + + printf("Loading WebAssembly...\n"); + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 8*1024, NULL); + if (!runtime) FATAL("m3_NewRuntime failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule: %s", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule: %s", result); + + result = m3_LinkEspWASI (runtime->modules); + if (result) FATAL("m3_LinkEspWASI: %s", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "_start"); + if (result) FATAL("m3_FindFunction: %s", result); + + printf("Running...\n"); + + const char* i_argv[2] = { "test.wasm", NULL }; + + m3_wasi_context_t* wasi_ctx = m3_GetWasiContext(); + wasi_ctx->argc = 1; + wasi_ctx->argv = i_argv; + + result = m3_CallV (f); + + if (result) FATAL("m3_Call: %s", result); +} + +extern "C" void app_main(void) +{ + printf("\nWasm3 v" M3_VERSION " on " CONFIG_IDF_TARGET ", build " __DATE__ " " __TIME__ "\n"); + + clock_t start = clock(); + run_wasm(); + clock_t end = clock(); + + printf("Elapsed: %ld ms\n", (end - start)*1000 / CLOCKS_PER_SEC); + + sleep(3); + printf("Restarting...\n\n\n"); + esp_restart(); +} diff --git a/ext/wasm3/platforms/embedded/esp32-idf-wasi/main/wasi_test.wasm.h b/ext/wasm3/platforms/embedded/esp32-idf-wasi/main/wasi_test.wasm.h new file mode 100644 index 0000000..6dbdab3 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf-wasi/main/wasi_test.wasm.h @@ -0,0 +1,2307 @@ +unsigned char wasi_test_wasm[] = { + 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x0e, 0x60, + 0x03, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x60, + 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x03, 0x7f, 0x7e, 0x7f, 0x01, 0x7e, + 0x60, 0x00, 0x00, 0x60, 0x01, 0x7f, 0x00, 0x60, 0x02, 0x7f, 0x7f, 0x00, + 0x60, 0x03, 0x7f, 0x7f, 0x7f, 0x00, 0x60, 0x04, 0x7f, 0x7f, 0x7f, 0x7f, + 0x01, 0x7f, 0x60, 0x05, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, + 0x09, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, 0x7e, 0x7f, 0x7f, 0x01, 0x7f, + 0x60, 0x03, 0x7f, 0x7e, 0x7f, 0x01, 0x7f, 0x60, 0x04, 0x7f, 0x7e, 0x7f, + 0x7f, 0x01, 0x7f, 0x60, 0x02, 0x7c, 0x7f, 0x01, 0x7c, 0x02, 0xa8, 0x03, + 0x0f, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e, 0x73, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x0e, 0x66, 0x64, 0x5f, 0x70, 0x72, 0x65, 0x73, 0x74, + 0x61, 0x74, 0x5f, 0x67, 0x65, 0x74, 0x00, 0x02, 0x0d, 0x77, 0x61, 0x73, + 0x69, 0x5f, 0x75, 0x6e, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x13, 0x66, + 0x64, 0x5f, 0x70, 0x72, 0x65, 0x73, 0x74, 0x61, 0x74, 0x5f, 0x64, 0x69, + 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x0d, 0x77, 0x61, 0x73, + 0x69, 0x5f, 0x75, 0x6e, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x11, 0x65, + 0x6e, 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x73, + 0x5f, 0x67, 0x65, 0x74, 0x00, 0x02, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, + 0x75, 0x6e, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0b, 0x65, 0x6e, 0x76, + 0x69, 0x72, 0x6f, 0x6e, 0x5f, 0x67, 0x65, 0x74, 0x00, 0x02, 0x0d, 0x77, + 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x0e, 0x61, 0x72, 0x67, 0x73, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x73, 0x5f, + 0x67, 0x65, 0x74, 0x00, 0x02, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x75, + 0x6e, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x08, 0x61, 0x72, 0x67, 0x73, + 0x5f, 0x67, 0x65, 0x74, 0x00, 0x02, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, + 0x75, 0x6e, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0e, 0x63, 0x6c, 0x6f, + 0x63, 0x6b, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x67, 0x65, 0x74, 0x00, + 0x0b, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e, 0x73, 0x74, 0x61, + 0x62, 0x6c, 0x65, 0x09, 0x70, 0x72, 0x6f, 0x63, 0x5f, 0x65, 0x78, 0x69, + 0x74, 0x00, 0x05, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e, 0x73, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x08, 0x66, 0x64, 0x5f, 0x63, 0x6c, 0x6f, + 0x73, 0x65, 0x00, 0x01, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e, + 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x07, 0x66, 0x64, 0x5f, 0x72, 0x65, + 0x61, 0x64, 0x00, 0x08, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e, + 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x0d, 0x66, 0x64, 0x5f, 0x66, 0x64, + 0x73, 0x74, 0x61, 0x74, 0x5f, 0x67, 0x65, 0x74, 0x00, 0x02, 0x0d, 0x77, + 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x09, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x00, 0x0a, + 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e, 0x73, 0x74, 0x61, 0x62, + 0x6c, 0x65, 0x0a, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x5f, 0x67, 0x65, + 0x74, 0x00, 0x02, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e, 0x73, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x07, 0x66, 0x64, 0x5f, 0x73, 0x65, 0x65, + 0x6b, 0x00, 0x0c, 0x0d, 0x77, 0x61, 0x73, 0x69, 0x5f, 0x75, 0x6e, 0x73, + 0x74, 0x61, 0x62, 0x6c, 0x65, 0x08, 0x66, 0x64, 0x5f, 0x77, 0x72, 0x69, + 0x74, 0x65, 0x00, 0x08, 0x03, 0x32, 0x31, 0x04, 0x01, 0x04, 0x05, 0x02, + 0x01, 0x05, 0x01, 0x05, 0x05, 0x01, 0x02, 0x02, 0x01, 0x06, 0x05, 0x04, + 0x02, 0x01, 0x06, 0x01, 0x01, 0x06, 0x09, 0x07, 0x04, 0x02, 0x04, 0x01, + 0x03, 0x03, 0x01, 0x00, 0x04, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x01, 0x00, 0x07, 0x01, 0x02, 0x02, 0x02, 0x0d, 0x04, 0x05, 0x01, 0x70, + 0x01, 0x05, 0x05, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f, + 0x01, 0x41, 0xa0, 0xaa, 0x04, 0x0b, 0x07, 0x19, 0x03, 0x06, 0x6d, 0x65, + 0x6d, 0x6f, 0x72, 0x79, 0x02, 0x00, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x00, 0x0f, 0x03, 0x66, 0x69, 0x62, 0x00, 0x10, 0x09, 0x0a, 0x01, + 0x00, 0x41, 0x01, 0x0b, 0x04, 0x2b, 0x2f, 0x2d, 0x36, 0x0a, 0xd2, 0xbf, + 0x01, 0x31, 0xf7, 0x02, 0x01, 0x04, 0x7f, 0x23, 0x00, 0x41, 0x10, 0x6b, + 0x22, 0x01, 0x24, 0x00, 0x10, 0x1f, 0x41, 0x03, 0x21, 0x00, 0x02, 0x40, + 0x03, 0x40, 0x20, 0x00, 0x20, 0x01, 0x10, 0x00, 0x22, 0x02, 0x41, 0x08, + 0x4b, 0x0d, 0x01, 0x02, 0x40, 0x02, 0x40, 0x20, 0x02, 0x41, 0x01, 0x6b, + 0x0e, 0x08, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x0b, + 0x20, 0x01, 0x2d, 0x00, 0x00, 0x45, 0x04, 0x40, 0x20, 0x01, 0x28, 0x02, + 0x04, 0x41, 0x01, 0x6a, 0x10, 0x14, 0x22, 0x02, 0x45, 0x0d, 0x03, 0x20, + 0x00, 0x20, 0x02, 0x20, 0x01, 0x28, 0x02, 0x04, 0x10, 0x01, 0x04, 0x40, + 0x20, 0x02, 0x10, 0x15, 0x0c, 0x04, 0x0b, 0x20, 0x02, 0x20, 0x01, 0x28, + 0x02, 0x04, 0x6a, 0x41, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x00, 0x20, 0x02, + 0x10, 0x20, 0x20, 0x02, 0x10, 0x15, 0x0d, 0x03, 0x0b, 0x20, 0x00, 0x41, + 0x01, 0x6a, 0x22, 0x02, 0x20, 0x00, 0x49, 0x20, 0x02, 0x21, 0x00, 0x45, + 0x0d, 0x01, 0x0b, 0x0b, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x01, + 0x20, 0x01, 0x41, 0x0c, 0x6a, 0x10, 0x02, 0x0d, 0x00, 0x41, 0xe8, 0x1f, + 0x20, 0x01, 0x28, 0x02, 0x00, 0x41, 0x02, 0x74, 0x41, 0x04, 0x6a, 0x10, + 0x14, 0x36, 0x02, 0x00, 0x20, 0x01, 0x28, 0x02, 0x0c, 0x10, 0x14, 0x22, + 0x00, 0x45, 0x0d, 0x00, 0x41, 0xe8, 0x1f, 0x28, 0x02, 0x00, 0x22, 0x02, + 0x45, 0x0d, 0x00, 0x20, 0x02, 0x20, 0x01, 0x28, 0x02, 0x00, 0x41, 0x02, + 0x74, 0x6a, 0x41, 0x00, 0x36, 0x02, 0x00, 0x41, 0xe8, 0x1f, 0x28, 0x02, + 0x00, 0x20, 0x00, 0x10, 0x03, 0x0d, 0x00, 0x20, 0x01, 0x41, 0x0c, 0x6a, + 0x20, 0x01, 0x10, 0x04, 0x0d, 0x01, 0x20, 0x01, 0x28, 0x02, 0x0c, 0x22, + 0x00, 0x04, 0x40, 0x20, 0x00, 0x41, 0x02, 0x74, 0x41, 0x04, 0x6a, 0x10, + 0x14, 0x21, 0x00, 0x20, 0x01, 0x28, 0x02, 0x00, 0x10, 0x14, 0x21, 0x02, + 0x20, 0x00, 0x45, 0x0d, 0x02, 0x20, 0x02, 0x45, 0x0d, 0x02, 0x20, 0x00, + 0x41, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x02, 0x10, 0x05, 0x0d, + 0x02, 0x0b, 0x41, 0xe8, 0x1b, 0x41, 0x88, 0x08, 0x29, 0x03, 0x00, 0x37, + 0x03, 0x00, 0x41, 0xe0, 0x1b, 0x41, 0x80, 0x08, 0x29, 0x03, 0x00, 0x37, + 0x03, 0x00, 0x20, 0x01, 0x28, 0x02, 0x0c, 0x20, 0x00, 0x10, 0x13, 0x21, + 0x00, 0x10, 0x30, 0x20, 0x00, 0x0d, 0x02, 0x20, 0x01, 0x41, 0x10, 0x6a, + 0x24, 0x00, 0x0f, 0x0b, 0x41, 0xc7, 0x00, 0x10, 0x18, 0x00, 0x0b, 0x41, + 0xc7, 0x00, 0x10, 0x18, 0x00, 0x0b, 0x20, 0x00, 0x10, 0x18, 0x00, 0x0b, + 0x41, 0xc7, 0x00, 0x10, 0x18, 0x00, 0x0b, 0x1c, 0x00, 0x20, 0x00, 0x41, + 0x02, 0x4f, 0x04, 0x40, 0x20, 0x00, 0x41, 0x7f, 0x6a, 0x10, 0x10, 0x20, + 0x00, 0x41, 0x7e, 0x6a, 0x10, 0x10, 0x6a, 0x0f, 0x0b, 0x20, 0x00, 0x0b, + 0xb0, 0x01, 0x02, 0x04, 0x7f, 0x01, 0x7e, 0x23, 0x00, 0x41, 0x40, 0x6a, + 0x22, 0x00, 0x24, 0x00, 0x20, 0x00, 0x41, 0x14, 0x36, 0x02, 0x10, 0x41, + 0xe0, 0x08, 0x20, 0x00, 0x41, 0x10, 0x6a, 0x10, 0x22, 0x41, 0xd8, 0x1b, + 0x28, 0x02, 0x00, 0x10, 0x23, 0x1a, 0x20, 0x00, 0x41, 0x30, 0x6a, 0x10, + 0x17, 0x41, 0x14, 0x10, 0x10, 0x21, 0x03, 0x20, 0x00, 0x41, 0x20, 0x6a, + 0x10, 0x17, 0x20, 0x00, 0x29, 0x03, 0x20, 0x20, 0x00, 0x29, 0x03, 0x30, + 0x7d, 0x21, 0x04, 0x02, 0x7f, 0x20, 0x00, 0x28, 0x02, 0x28, 0x22, 0x01, + 0x20, 0x00, 0x28, 0x02, 0x38, 0x22, 0x02, 0x48, 0x04, 0x40, 0x20, 0x04, + 0x42, 0x7f, 0x7c, 0x21, 0x04, 0x20, 0x01, 0x20, 0x02, 0x6b, 0x41, 0x80, + 0x94, 0xeb, 0xdc, 0x03, 0x6a, 0x0c, 0x01, 0x0b, 0x20, 0x01, 0x20, 0x02, + 0x6b, 0x0b, 0x21, 0x01, 0x20, 0x00, 0x20, 0x03, 0x36, 0x02, 0x00, 0x20, + 0x00, 0x20, 0x04, 0xb9, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x8f, + 0x40, 0xa2, 0x20, 0x01, 0xb7, 0x44, 0x00, 0x00, 0x00, 0x00, 0x80, 0x84, + 0x2e, 0x41, 0xa3, 0xa0, 0x39, 0x03, 0x08, 0x41, 0xeb, 0x08, 0x20, 0x00, + 0x10, 0x22, 0x20, 0x00, 0x41, 0x40, 0x6b, 0x24, 0x00, 0x0b, 0x75, 0x01, + 0x02, 0x7f, 0x23, 0x00, 0x41, 0x20, 0x6b, 0x22, 0x01, 0x24, 0x00, 0x02, + 0x40, 0x20, 0x00, 0x10, 0x1c, 0x22, 0x02, 0x41, 0x00, 0x4e, 0x04, 0x40, + 0x20, 0x01, 0x41, 0x00, 0x3a, 0x00, 0x1f, 0x20, 0x02, 0x20, 0x01, 0x41, + 0x1f, 0x6a, 0x10, 0x1a, 0x41, 0x01, 0x4e, 0x04, 0x40, 0x03, 0x40, 0x20, + 0x01, 0x20, 0x01, 0x2c, 0x00, 0x1f, 0x36, 0x02, 0x00, 0x41, 0xf9, 0x08, + 0x20, 0x01, 0x10, 0x22, 0x20, 0x02, 0x20, 0x01, 0x41, 0x1f, 0x6a, 0x10, + 0x1a, 0x41, 0x00, 0x4a, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x02, 0x10, 0x19, + 0x1a, 0x10, 0x28, 0x0c, 0x01, 0x0b, 0x20, 0x01, 0x20, 0x00, 0x36, 0x02, + 0x10, 0x41, 0xff, 0x08, 0x20, 0x01, 0x41, 0x10, 0x6a, 0x10, 0x22, 0x0b, + 0x20, 0x01, 0x41, 0x20, 0x6a, 0x24, 0x00, 0x0b, 0xdd, 0x02, 0x02, 0x02, + 0x7f, 0x01, 0x7e, 0x23, 0x00, 0x41, 0xd0, 0x00, 0x6b, 0x22, 0x02, 0x24, + 0x00, 0x41, 0x90, 0x08, 0x41, 0x0c, 0x41, 0xd8, 0x1b, 0x28, 0x02, 0x00, + 0x22, 0x03, 0x10, 0x34, 0x1a, 0x41, 0xe0, 0x1b, 0x41, 0x0f, 0x20, 0x03, + 0x10, 0x34, 0x1a, 0x20, 0x02, 0x41, 0xa8, 0x08, 0x36, 0x02, 0x30, 0x41, + 0x9d, 0x08, 0x20, 0x02, 0x41, 0x30, 0x6a, 0x10, 0x22, 0x41, 0xaf, 0x08, + 0x41, 0x00, 0x10, 0x22, 0x20, 0x00, 0x41, 0x01, 0x4e, 0x04, 0x40, 0x20, + 0x01, 0x21, 0x03, 0x03, 0x40, 0x20, 0x02, 0x20, 0x03, 0x28, 0x02, 0x00, + 0x36, 0x02, 0x20, 0x41, 0xb6, 0x08, 0x20, 0x02, 0x41, 0x20, 0x6a, 0x10, + 0x22, 0x20, 0x03, 0x41, 0x04, 0x6a, 0x21, 0x03, 0x20, 0x00, 0x41, 0x7f, + 0x6a, 0x22, 0x00, 0x0d, 0x00, 0x0b, 0x0b, 0x10, 0x28, 0x20, 0x02, 0x41, + 0x40, 0x6b, 0x10, 0x17, 0x20, 0x02, 0x20, 0x02, 0x29, 0x03, 0x40, 0x37, + 0x03, 0x10, 0x20, 0x02, 0x20, 0x02, 0x28, 0x02, 0x48, 0x36, 0x02, 0x18, + 0x41, 0xc9, 0x08, 0x20, 0x02, 0x41, 0x10, 0x6a, 0x10, 0x22, 0x20, 0x02, + 0x41, 0x40, 0x6b, 0x41, 0x04, 0x10, 0x0c, 0x22, 0x00, 0x04, 0x40, 0x41, + 0xe0, 0x1f, 0x20, 0x00, 0x36, 0x02, 0x00, 0x0b, 0x41, 0xa8, 0x28, 0x20, + 0x02, 0x28, 0x02, 0x40, 0x41, 0x7f, 0x6a, 0xad, 0x37, 0x03, 0x00, 0x41, + 0xa8, 0x28, 0x41, 0xa8, 0x28, 0x29, 0x03, 0x00, 0x42, 0xad, 0xfe, 0xd5, + 0xe4, 0xd4, 0x85, 0xfd, 0xa8, 0xd8, 0x00, 0x7e, 0x42, 0x01, 0x7c, 0x22, + 0x04, 0x37, 0x03, 0x00, 0x20, 0x04, 0x42, 0x21, 0x88, 0xa7, 0x21, 0x00, + 0x41, 0xa8, 0x28, 0x41, 0xa8, 0x28, 0x29, 0x03, 0x00, 0x42, 0xad, 0xfe, + 0xd5, 0xe4, 0xd4, 0x85, 0xfd, 0xa8, 0xd8, 0x00, 0x7e, 0x42, 0x01, 0x7c, + 0x22, 0x04, 0x37, 0x03, 0x00, 0x20, 0x04, 0x42, 0x21, 0x88, 0xa7, 0x21, + 0x03, 0x20, 0x02, 0x20, 0x00, 0x41, 0xbb, 0xd1, 0x8b, 0xdd, 0x00, 0x6d, + 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x02, 0x20, 0x03, 0x41, 0xbb, 0xd1, + 0x8b, 0xdd, 0x00, 0x6d, 0x22, 0x03, 0x36, 0x02, 0x04, 0x20, 0x02, 0x20, + 0x00, 0x20, 0x03, 0x6a, 0x36, 0x02, 0x08, 0x41, 0xbb, 0x08, 0x20, 0x02, + 0x10, 0x22, 0x10, 0x11, 0x20, 0x01, 0x28, 0x02, 0x04, 0x10, 0x3b, 0x45, + 0x04, 0x40, 0x20, 0x01, 0x28, 0x02, 0x08, 0x10, 0x12, 0x0b, 0x10, 0x32, + 0x20, 0x02, 0x41, 0xd0, 0x00, 0x6a, 0x24, 0x00, 0x41, 0x00, 0x0b, 0xb9, + 0x2e, 0x01, 0x0b, 0x7f, 0x23, 0x00, 0x41, 0x10, 0x6b, 0x22, 0x0b, 0x24, + 0x00, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, + 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, + 0x00, 0x41, 0xec, 0x01, 0x4d, 0x04, 0x40, 0x41, 0xf0, 0x1b, 0x28, 0x02, + 0x00, 0x22, 0x05, 0x41, 0x10, 0x20, 0x00, 0x41, 0x13, 0x6a, 0x41, 0x70, + 0x71, 0x20, 0x00, 0x41, 0x0b, 0x49, 0x1b, 0x22, 0x06, 0x41, 0x03, 0x76, + 0x22, 0x00, 0x76, 0x22, 0x01, 0x41, 0x03, 0x71, 0x04, 0x40, 0x20, 0x01, + 0x41, 0x01, 0x71, 0x20, 0x00, 0x72, 0x41, 0x01, 0x73, 0x22, 0x02, 0x41, + 0x03, 0x74, 0x22, 0x04, 0x41, 0xa0, 0x1c, 0x6a, 0x28, 0x02, 0x00, 0x22, + 0x01, 0x41, 0x08, 0x6a, 0x21, 0x00, 0x02, 0x40, 0x20, 0x01, 0x28, 0x02, + 0x08, 0x22, 0x03, 0x20, 0x04, 0x41, 0x98, 0x1c, 0x6a, 0x22, 0x04, 0x46, + 0x04, 0x40, 0x41, 0xf0, 0x1b, 0x20, 0x05, 0x41, 0x7e, 0x20, 0x02, 0x77, + 0x71, 0x36, 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x41, 0x80, 0x1c, 0x28, 0x02, + 0x00, 0x1a, 0x20, 0x04, 0x20, 0x03, 0x36, 0x02, 0x08, 0x20, 0x03, 0x20, + 0x04, 0x36, 0x02, 0x0c, 0x0b, 0x20, 0x01, 0x20, 0x02, 0x41, 0x03, 0x74, + 0x22, 0x02, 0x41, 0x03, 0x72, 0x36, 0x02, 0x04, 0x20, 0x01, 0x20, 0x02, + 0x6a, 0x22, 0x01, 0x20, 0x01, 0x28, 0x02, 0x04, 0x41, 0x01, 0x72, 0x36, + 0x02, 0x04, 0x0c, 0x0c, 0x0b, 0x20, 0x06, 0x41, 0xf8, 0x1b, 0x28, 0x02, + 0x00, 0x22, 0x08, 0x4d, 0x0d, 0x01, 0x20, 0x01, 0x04, 0x40, 0x02, 0x40, + 0x41, 0x02, 0x20, 0x00, 0x74, 0x22, 0x02, 0x41, 0x00, 0x20, 0x02, 0x6b, + 0x72, 0x20, 0x01, 0x20, 0x00, 0x74, 0x71, 0x22, 0x00, 0x41, 0x00, 0x20, + 0x00, 0x6b, 0x71, 0x41, 0x7f, 0x6a, 0x22, 0x00, 0x20, 0x00, 0x41, 0x0c, + 0x76, 0x41, 0x10, 0x71, 0x22, 0x00, 0x76, 0x22, 0x01, 0x41, 0x05, 0x76, + 0x41, 0x08, 0x71, 0x22, 0x02, 0x20, 0x00, 0x72, 0x20, 0x01, 0x20, 0x02, + 0x76, 0x22, 0x00, 0x41, 0x02, 0x76, 0x41, 0x04, 0x71, 0x22, 0x01, 0x72, + 0x20, 0x00, 0x20, 0x01, 0x76, 0x22, 0x00, 0x41, 0x01, 0x76, 0x41, 0x02, + 0x71, 0x22, 0x01, 0x72, 0x20, 0x00, 0x20, 0x01, 0x76, 0x22, 0x00, 0x41, + 0x01, 0x76, 0x41, 0x01, 0x71, 0x22, 0x01, 0x72, 0x20, 0x00, 0x20, 0x01, + 0x76, 0x6a, 0x22, 0x02, 0x41, 0x03, 0x74, 0x22, 0x03, 0x41, 0xa0, 0x1c, + 0x6a, 0x28, 0x02, 0x00, 0x22, 0x01, 0x28, 0x02, 0x08, 0x22, 0x00, 0x20, + 0x03, 0x41, 0x98, 0x1c, 0x6a, 0x22, 0x03, 0x46, 0x04, 0x40, 0x41, 0xf0, + 0x1b, 0x20, 0x05, 0x41, 0x7e, 0x20, 0x02, 0x77, 0x71, 0x22, 0x05, 0x36, + 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x41, 0x80, 0x1c, 0x28, 0x02, 0x00, 0x1a, + 0x20, 0x03, 0x20, 0x00, 0x36, 0x02, 0x08, 0x20, 0x00, 0x20, 0x03, 0x36, + 0x02, 0x0c, 0x0b, 0x20, 0x01, 0x41, 0x08, 0x6a, 0x21, 0x00, 0x20, 0x01, + 0x20, 0x06, 0x41, 0x03, 0x72, 0x36, 0x02, 0x04, 0x20, 0x01, 0x20, 0x02, + 0x41, 0x03, 0x74, 0x22, 0x02, 0x6a, 0x20, 0x02, 0x20, 0x06, 0x6b, 0x22, + 0x04, 0x36, 0x02, 0x00, 0x20, 0x01, 0x20, 0x06, 0x6a, 0x22, 0x06, 0x20, + 0x04, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x20, 0x08, 0x04, 0x40, 0x20, + 0x08, 0x41, 0x03, 0x76, 0x22, 0x03, 0x41, 0x03, 0x74, 0x41, 0x98, 0x1c, + 0x6a, 0x21, 0x01, 0x41, 0x84, 0x1c, 0x28, 0x02, 0x00, 0x21, 0x02, 0x02, + 0x7f, 0x20, 0x05, 0x41, 0x01, 0x20, 0x03, 0x74, 0x22, 0x03, 0x71, 0x45, + 0x04, 0x40, 0x41, 0xf0, 0x1b, 0x20, 0x03, 0x20, 0x05, 0x72, 0x36, 0x02, + 0x00, 0x20, 0x01, 0x0c, 0x01, 0x0b, 0x20, 0x01, 0x28, 0x02, 0x08, 0x0b, + 0x22, 0x03, 0x20, 0x02, 0x36, 0x02, 0x0c, 0x20, 0x01, 0x20, 0x02, 0x36, + 0x02, 0x08, 0x20, 0x02, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x20, 0x02, 0x20, + 0x03, 0x36, 0x02, 0x08, 0x0b, 0x41, 0x84, 0x1c, 0x20, 0x06, 0x36, 0x02, + 0x00, 0x41, 0xf8, 0x1b, 0x20, 0x04, 0x36, 0x02, 0x00, 0x0c, 0x0c, 0x0b, + 0x41, 0xf4, 0x1b, 0x28, 0x02, 0x00, 0x22, 0x0a, 0x45, 0x0d, 0x01, 0x20, + 0x0a, 0x41, 0x00, 0x20, 0x0a, 0x6b, 0x71, 0x41, 0x7f, 0x6a, 0x22, 0x00, + 0x20, 0x00, 0x41, 0x0c, 0x76, 0x41, 0x10, 0x71, 0x22, 0x00, 0x76, 0x22, + 0x01, 0x41, 0x05, 0x76, 0x41, 0x08, 0x71, 0x22, 0x02, 0x20, 0x00, 0x72, + 0x20, 0x01, 0x20, 0x02, 0x76, 0x22, 0x00, 0x41, 0x02, 0x76, 0x41, 0x04, + 0x71, 0x22, 0x01, 0x72, 0x20, 0x00, 0x20, 0x01, 0x76, 0x22, 0x00, 0x41, + 0x01, 0x76, 0x41, 0x02, 0x71, 0x22, 0x01, 0x72, 0x20, 0x00, 0x20, 0x01, + 0x76, 0x22, 0x00, 0x41, 0x01, 0x76, 0x41, 0x01, 0x71, 0x22, 0x01, 0x72, + 0x20, 0x00, 0x20, 0x01, 0x76, 0x6a, 0x41, 0x02, 0x74, 0x41, 0xa0, 0x1e, + 0x6a, 0x28, 0x02, 0x00, 0x22, 0x01, 0x28, 0x02, 0x04, 0x41, 0x78, 0x71, + 0x20, 0x06, 0x6b, 0x21, 0x02, 0x20, 0x01, 0x21, 0x04, 0x03, 0x40, 0x02, + 0x40, 0x20, 0x04, 0x28, 0x02, 0x10, 0x22, 0x00, 0x45, 0x04, 0x40, 0x20, + 0x04, 0x41, 0x14, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x01, + 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, 0x41, 0x78, 0x71, 0x20, 0x06, 0x6b, + 0x22, 0x03, 0x20, 0x02, 0x20, 0x03, 0x20, 0x02, 0x49, 0x22, 0x03, 0x1b, + 0x21, 0x02, 0x20, 0x00, 0x20, 0x01, 0x20, 0x03, 0x1b, 0x21, 0x01, 0x20, + 0x00, 0x21, 0x04, 0x0c, 0x01, 0x0b, 0x0b, 0x20, 0x01, 0x28, 0x02, 0x18, + 0x21, 0x09, 0x20, 0x01, 0x20, 0x01, 0x28, 0x02, 0x0c, 0x22, 0x03, 0x47, + 0x04, 0x40, 0x41, 0x80, 0x1c, 0x28, 0x02, 0x00, 0x20, 0x01, 0x28, 0x02, + 0x08, 0x22, 0x00, 0x4d, 0x04, 0x40, 0x20, 0x00, 0x28, 0x02, 0x0c, 0x1a, + 0x0b, 0x20, 0x03, 0x20, 0x00, 0x36, 0x02, 0x08, 0x20, 0x00, 0x20, 0x03, + 0x36, 0x02, 0x0c, 0x0c, 0x0b, 0x0b, 0x20, 0x01, 0x41, 0x14, 0x6a, 0x22, + 0x04, 0x28, 0x02, 0x00, 0x22, 0x00, 0x45, 0x04, 0x40, 0x20, 0x01, 0x28, + 0x02, 0x10, 0x22, 0x00, 0x45, 0x0d, 0x03, 0x20, 0x01, 0x41, 0x10, 0x6a, + 0x21, 0x04, 0x0b, 0x03, 0x40, 0x20, 0x04, 0x21, 0x07, 0x20, 0x00, 0x22, + 0x03, 0x41, 0x14, 0x6a, 0x22, 0x04, 0x28, 0x02, 0x00, 0x22, 0x00, 0x0d, + 0x00, 0x20, 0x03, 0x41, 0x10, 0x6a, 0x21, 0x04, 0x20, 0x03, 0x28, 0x02, + 0x10, 0x22, 0x00, 0x0d, 0x00, 0x0b, 0x20, 0x07, 0x41, 0x00, 0x36, 0x02, + 0x00, 0x0c, 0x0a, 0x0b, 0x41, 0x7f, 0x21, 0x06, 0x20, 0x00, 0x41, 0xbf, + 0x7f, 0x4b, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x13, 0x6a, 0x22, 0x00, 0x41, + 0x70, 0x71, 0x21, 0x06, 0x41, 0xf4, 0x1b, 0x28, 0x02, 0x00, 0x22, 0x08, + 0x45, 0x0d, 0x00, 0x41, 0x00, 0x20, 0x06, 0x6b, 0x21, 0x04, 0x02, 0x40, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x7f, 0x41, 0x00, 0x20, 0x00, 0x41, 0x08, + 0x76, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x1a, 0x41, 0x1f, 0x20, 0x06, 0x41, + 0xff, 0xff, 0xff, 0x07, 0x4b, 0x0d, 0x00, 0x1a, 0x20, 0x00, 0x20, 0x00, + 0x41, 0x80, 0xfe, 0x3f, 0x6a, 0x41, 0x10, 0x76, 0x41, 0x08, 0x71, 0x22, + 0x00, 0x74, 0x22, 0x01, 0x20, 0x01, 0x41, 0x80, 0xe0, 0x1f, 0x6a, 0x41, + 0x10, 0x76, 0x41, 0x04, 0x71, 0x22, 0x01, 0x74, 0x22, 0x02, 0x20, 0x02, + 0x41, 0x80, 0x80, 0x0f, 0x6a, 0x41, 0x10, 0x76, 0x41, 0x02, 0x71, 0x22, + 0x02, 0x74, 0x41, 0x0f, 0x76, 0x20, 0x00, 0x20, 0x01, 0x72, 0x20, 0x02, + 0x72, 0x6b, 0x22, 0x00, 0x41, 0x01, 0x74, 0x20, 0x06, 0x20, 0x00, 0x41, + 0x15, 0x6a, 0x76, 0x41, 0x01, 0x71, 0x72, 0x41, 0x1c, 0x6a, 0x0b, 0x22, + 0x07, 0x41, 0x02, 0x74, 0x41, 0xa0, 0x1e, 0x6a, 0x28, 0x02, 0x00, 0x22, + 0x02, 0x45, 0x04, 0x40, 0x41, 0x00, 0x21, 0x00, 0x0c, 0x01, 0x0b, 0x20, + 0x06, 0x41, 0x00, 0x41, 0x19, 0x20, 0x07, 0x41, 0x01, 0x76, 0x6b, 0x20, + 0x07, 0x41, 0x1f, 0x46, 0x1b, 0x74, 0x21, 0x01, 0x41, 0x00, 0x21, 0x00, + 0x03, 0x40, 0x02, 0x40, 0x20, 0x02, 0x28, 0x02, 0x04, 0x41, 0x78, 0x71, + 0x20, 0x06, 0x6b, 0x22, 0x05, 0x20, 0x04, 0x4f, 0x0d, 0x00, 0x20, 0x02, + 0x21, 0x03, 0x20, 0x05, 0x22, 0x04, 0x0d, 0x00, 0x41, 0x00, 0x21, 0x04, + 0x20, 0x02, 0x21, 0x00, 0x0c, 0x03, 0x0b, 0x20, 0x00, 0x20, 0x02, 0x41, + 0x14, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x05, 0x20, 0x05, 0x20, 0x02, 0x20, + 0x01, 0x41, 0x1d, 0x76, 0x41, 0x04, 0x71, 0x6a, 0x41, 0x10, 0x6a, 0x28, + 0x02, 0x00, 0x22, 0x02, 0x46, 0x1b, 0x20, 0x00, 0x20, 0x05, 0x1b, 0x21, + 0x00, 0x20, 0x01, 0x20, 0x02, 0x41, 0x00, 0x47, 0x74, 0x21, 0x01, 0x20, + 0x02, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x00, 0x20, 0x03, 0x72, 0x45, 0x04, + 0x40, 0x41, 0x02, 0x20, 0x07, 0x74, 0x22, 0x00, 0x41, 0x00, 0x20, 0x00, + 0x6b, 0x72, 0x20, 0x08, 0x71, 0x22, 0x00, 0x45, 0x0d, 0x03, 0x20, 0x00, + 0x41, 0x00, 0x20, 0x00, 0x6b, 0x71, 0x41, 0x7f, 0x6a, 0x22, 0x00, 0x20, + 0x00, 0x41, 0x0c, 0x76, 0x41, 0x10, 0x71, 0x22, 0x00, 0x76, 0x22, 0x01, + 0x41, 0x05, 0x76, 0x41, 0x08, 0x71, 0x22, 0x02, 0x20, 0x00, 0x72, 0x20, + 0x01, 0x20, 0x02, 0x76, 0x22, 0x00, 0x41, 0x02, 0x76, 0x41, 0x04, 0x71, + 0x22, 0x01, 0x72, 0x20, 0x00, 0x20, 0x01, 0x76, 0x22, 0x00, 0x41, 0x01, + 0x76, 0x41, 0x02, 0x71, 0x22, 0x01, 0x72, 0x20, 0x00, 0x20, 0x01, 0x76, + 0x22, 0x00, 0x41, 0x01, 0x76, 0x41, 0x01, 0x71, 0x22, 0x01, 0x72, 0x20, + 0x00, 0x20, 0x01, 0x76, 0x6a, 0x41, 0x02, 0x74, 0x41, 0xa0, 0x1e, 0x6a, + 0x28, 0x02, 0x00, 0x21, 0x00, 0x0b, 0x20, 0x00, 0x45, 0x0d, 0x01, 0x0b, + 0x03, 0x40, 0x20, 0x00, 0x28, 0x02, 0x04, 0x41, 0x78, 0x71, 0x20, 0x06, + 0x6b, 0x22, 0x05, 0x20, 0x04, 0x49, 0x21, 0x01, 0x20, 0x05, 0x20, 0x04, + 0x20, 0x01, 0x1b, 0x21, 0x04, 0x20, 0x00, 0x20, 0x03, 0x20, 0x01, 0x1b, + 0x21, 0x03, 0x20, 0x00, 0x28, 0x02, 0x10, 0x22, 0x02, 0x04, 0x7f, 0x20, + 0x02, 0x05, 0x20, 0x00, 0x41, 0x14, 0x6a, 0x28, 0x02, 0x00, 0x0b, 0x22, + 0x00, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x03, 0x45, 0x0d, 0x00, 0x20, 0x04, + 0x41, 0xf8, 0x1b, 0x28, 0x02, 0x00, 0x20, 0x06, 0x6b, 0x4f, 0x0d, 0x00, + 0x20, 0x03, 0x28, 0x02, 0x18, 0x21, 0x07, 0x20, 0x03, 0x20, 0x03, 0x28, + 0x02, 0x0c, 0x22, 0x01, 0x47, 0x04, 0x40, 0x41, 0x80, 0x1c, 0x28, 0x02, + 0x00, 0x20, 0x03, 0x28, 0x02, 0x08, 0x22, 0x00, 0x4d, 0x04, 0x40, 0x20, + 0x00, 0x28, 0x02, 0x0c, 0x1a, 0x0b, 0x20, 0x01, 0x20, 0x00, 0x36, 0x02, + 0x08, 0x20, 0x00, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x0c, 0x09, 0x0b, 0x20, + 0x03, 0x41, 0x14, 0x6a, 0x22, 0x02, 0x28, 0x02, 0x00, 0x22, 0x00, 0x45, + 0x04, 0x40, 0x20, 0x03, 0x28, 0x02, 0x10, 0x22, 0x00, 0x45, 0x0d, 0x03, + 0x20, 0x03, 0x41, 0x10, 0x6a, 0x21, 0x02, 0x0b, 0x03, 0x40, 0x20, 0x02, + 0x21, 0x05, 0x20, 0x00, 0x22, 0x01, 0x41, 0x14, 0x6a, 0x22, 0x02, 0x28, + 0x02, 0x00, 0x22, 0x00, 0x0d, 0x00, 0x20, 0x01, 0x41, 0x10, 0x6a, 0x21, + 0x02, 0x20, 0x01, 0x28, 0x02, 0x10, 0x22, 0x00, 0x0d, 0x00, 0x0b, 0x20, + 0x05, 0x41, 0x00, 0x36, 0x02, 0x00, 0x0c, 0x08, 0x0b, 0x41, 0xf8, 0x1b, + 0x28, 0x02, 0x00, 0x22, 0x01, 0x20, 0x06, 0x4f, 0x04, 0x40, 0x41, 0x84, + 0x1c, 0x28, 0x02, 0x00, 0x21, 0x00, 0x02, 0x40, 0x20, 0x01, 0x20, 0x06, + 0x6b, 0x22, 0x02, 0x41, 0x10, 0x4f, 0x04, 0x40, 0x20, 0x00, 0x20, 0x06, + 0x6a, 0x22, 0x03, 0x20, 0x02, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x41, + 0xf8, 0x1b, 0x20, 0x02, 0x36, 0x02, 0x00, 0x41, 0x84, 0x1c, 0x20, 0x03, + 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x20, 0x02, 0x36, 0x02, + 0x00, 0x20, 0x00, 0x20, 0x06, 0x41, 0x03, 0x72, 0x36, 0x02, 0x04, 0x0c, + 0x01, 0x0b, 0x20, 0x00, 0x20, 0x01, 0x41, 0x03, 0x72, 0x36, 0x02, 0x04, + 0x20, 0x00, 0x20, 0x01, 0x6a, 0x22, 0x01, 0x20, 0x01, 0x28, 0x02, 0x04, + 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x41, 0x84, 0x1c, 0x41, 0x00, 0x36, + 0x02, 0x00, 0x41, 0xf8, 0x1b, 0x41, 0x00, 0x36, 0x02, 0x00, 0x0b, 0x20, + 0x00, 0x41, 0x08, 0x6a, 0x21, 0x00, 0x0c, 0x0a, 0x0b, 0x41, 0xfc, 0x1b, + 0x28, 0x02, 0x00, 0x22, 0x01, 0x20, 0x06, 0x4b, 0x04, 0x40, 0x41, 0x88, + 0x1c, 0x28, 0x02, 0x00, 0x22, 0x00, 0x20, 0x06, 0x6a, 0x22, 0x02, 0x20, + 0x01, 0x20, 0x06, 0x6b, 0x22, 0x01, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, + 0x41, 0xfc, 0x1b, 0x20, 0x01, 0x36, 0x02, 0x00, 0x41, 0x88, 0x1c, 0x20, + 0x02, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x06, 0x41, 0x03, 0x72, 0x36, + 0x02, 0x04, 0x20, 0x00, 0x41, 0x08, 0x6a, 0x21, 0x00, 0x0c, 0x0a, 0x0b, + 0x41, 0x00, 0x21, 0x00, 0x20, 0x06, 0x41, 0xc7, 0x00, 0x6a, 0x22, 0x04, + 0x02, 0x7f, 0x41, 0xc8, 0x1f, 0x28, 0x02, 0x00, 0x04, 0x40, 0x41, 0xd0, + 0x1f, 0x28, 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x41, 0xd4, 0x1f, 0x42, 0x7f, + 0x37, 0x02, 0x00, 0x41, 0xcc, 0x1f, 0x42, 0x80, 0x80, 0x84, 0x80, 0x80, + 0x80, 0xc0, 0x00, 0x37, 0x02, 0x00, 0x41, 0xc8, 0x1f, 0x20, 0x0b, 0x41, + 0x0c, 0x6a, 0x41, 0x70, 0x71, 0x41, 0xd8, 0xaa, 0xd5, 0xaa, 0x05, 0x73, + 0x36, 0x02, 0x00, 0x41, 0xdc, 0x1f, 0x41, 0x00, 0x36, 0x02, 0x00, 0x41, + 0xac, 0x1f, 0x41, 0x00, 0x36, 0x02, 0x00, 0x41, 0x80, 0x80, 0x04, 0x0b, + 0x22, 0x02, 0x6a, 0x22, 0x05, 0x41, 0x00, 0x20, 0x02, 0x6b, 0x22, 0x07, + 0x71, 0x22, 0x02, 0x20, 0x06, 0x4d, 0x04, 0x40, 0x41, 0xe0, 0x1f, 0x41, + 0x30, 0x36, 0x02, 0x00, 0x0c, 0x0a, 0x0b, 0x02, 0x40, 0x41, 0xa8, 0x1f, + 0x28, 0x02, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x41, 0xa0, 0x1f, 0x28, + 0x02, 0x00, 0x22, 0x03, 0x20, 0x02, 0x6a, 0x22, 0x08, 0x20, 0x03, 0x4b, + 0x41, 0x00, 0x20, 0x08, 0x20, 0x00, 0x4d, 0x1b, 0x0d, 0x00, 0x41, 0x00, + 0x21, 0x00, 0x41, 0xe0, 0x1f, 0x41, 0x30, 0x36, 0x02, 0x00, 0x0c, 0x0a, + 0x0b, 0x41, 0xac, 0x1f, 0x2d, 0x00, 0x00, 0x41, 0x04, 0x71, 0x0d, 0x04, + 0x02, 0x40, 0x02, 0x40, 0x41, 0x88, 0x1c, 0x28, 0x02, 0x00, 0x22, 0x03, + 0x04, 0x40, 0x41, 0xb0, 0x1f, 0x21, 0x00, 0x03, 0x40, 0x20, 0x00, 0x28, + 0x02, 0x00, 0x22, 0x08, 0x20, 0x03, 0x4d, 0x04, 0x40, 0x20, 0x08, 0x20, + 0x00, 0x28, 0x02, 0x04, 0x6a, 0x20, 0x03, 0x4b, 0x0d, 0x03, 0x0b, 0x20, + 0x00, 0x28, 0x02, 0x08, 0x22, 0x00, 0x0d, 0x00, 0x0b, 0x0b, 0x41, 0x00, + 0x10, 0x21, 0x22, 0x01, 0x41, 0x7f, 0x46, 0x0d, 0x05, 0x20, 0x02, 0x21, + 0x05, 0x41, 0xcc, 0x1f, 0x28, 0x02, 0x00, 0x22, 0x00, 0x41, 0x7f, 0x6a, + 0x22, 0x03, 0x20, 0x01, 0x71, 0x04, 0x40, 0x20, 0x02, 0x20, 0x01, 0x6b, + 0x20, 0x01, 0x20, 0x03, 0x6a, 0x41, 0x00, 0x20, 0x00, 0x6b, 0x71, 0x6a, + 0x21, 0x05, 0x0b, 0x20, 0x05, 0x20, 0x06, 0x4d, 0x0d, 0x05, 0x20, 0x05, + 0x41, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x4b, 0x0d, 0x05, 0x41, 0xa8, 0x1f, + 0x28, 0x02, 0x00, 0x22, 0x00, 0x04, 0x40, 0x41, 0xa0, 0x1f, 0x28, 0x02, + 0x00, 0x22, 0x03, 0x20, 0x05, 0x6a, 0x22, 0x07, 0x20, 0x03, 0x4d, 0x0d, + 0x06, 0x20, 0x07, 0x20, 0x00, 0x4b, 0x0d, 0x06, 0x0b, 0x20, 0x05, 0x10, + 0x21, 0x22, 0x00, 0x20, 0x01, 0x47, 0x0d, 0x01, 0x0c, 0x07, 0x0b, 0x20, + 0x05, 0x20, 0x01, 0x6b, 0x20, 0x07, 0x71, 0x22, 0x05, 0x41, 0xfe, 0xff, + 0xff, 0xff, 0x07, 0x4b, 0x0d, 0x04, 0x20, 0x05, 0x10, 0x21, 0x22, 0x01, + 0x20, 0x00, 0x28, 0x02, 0x00, 0x20, 0x00, 0x28, 0x02, 0x04, 0x6a, 0x46, + 0x0d, 0x03, 0x20, 0x01, 0x21, 0x00, 0x0b, 0x20, 0x00, 0x21, 0x01, 0x02, + 0x40, 0x20, 0x06, 0x41, 0xc8, 0x00, 0x6a, 0x20, 0x05, 0x4d, 0x0d, 0x00, + 0x20, 0x05, 0x41, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x4b, 0x0d, 0x00, 0x20, + 0x01, 0x41, 0x7f, 0x46, 0x0d, 0x00, 0x41, 0xd0, 0x1f, 0x28, 0x02, 0x00, + 0x22, 0x00, 0x20, 0x04, 0x20, 0x05, 0x6b, 0x6a, 0x41, 0x00, 0x20, 0x00, + 0x6b, 0x71, 0x22, 0x00, 0x41, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x4b, 0x0d, + 0x06, 0x20, 0x00, 0x10, 0x21, 0x41, 0x7f, 0x47, 0x04, 0x40, 0x20, 0x00, + 0x20, 0x05, 0x6a, 0x21, 0x05, 0x0c, 0x07, 0x0b, 0x41, 0x00, 0x20, 0x05, + 0x6b, 0x10, 0x21, 0x1a, 0x0c, 0x04, 0x0b, 0x20, 0x01, 0x41, 0x7f, 0x47, + 0x0d, 0x05, 0x0c, 0x03, 0x0b, 0x41, 0x00, 0x21, 0x03, 0x0c, 0x07, 0x0b, + 0x41, 0x00, 0x21, 0x01, 0x0c, 0x05, 0x0b, 0x20, 0x01, 0x41, 0x7f, 0x47, + 0x0d, 0x02, 0x0b, 0x41, 0xac, 0x1f, 0x41, 0xac, 0x1f, 0x28, 0x02, 0x00, + 0x41, 0x04, 0x72, 0x36, 0x02, 0x00, 0x0b, 0x20, 0x02, 0x41, 0xfe, 0xff, + 0xff, 0xff, 0x07, 0x4b, 0x0d, 0x01, 0x20, 0x02, 0x10, 0x21, 0x22, 0x01, + 0x41, 0x00, 0x10, 0x21, 0x22, 0x00, 0x4f, 0x0d, 0x01, 0x20, 0x01, 0x41, + 0x7f, 0x46, 0x0d, 0x01, 0x20, 0x00, 0x41, 0x7f, 0x46, 0x0d, 0x01, 0x20, + 0x00, 0x20, 0x01, 0x6b, 0x22, 0x05, 0x20, 0x06, 0x41, 0x38, 0x6a, 0x4d, + 0x0d, 0x01, 0x0b, 0x41, 0xa0, 0x1f, 0x41, 0xa0, 0x1f, 0x28, 0x02, 0x00, + 0x20, 0x05, 0x6a, 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00, 0x41, 0xa4, + 0x1f, 0x28, 0x02, 0x00, 0x4b, 0x04, 0x40, 0x41, 0xa4, 0x1f, 0x20, 0x00, + 0x36, 0x02, 0x00, 0x0b, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x41, 0x88, + 0x1c, 0x28, 0x02, 0x00, 0x22, 0x07, 0x04, 0x40, 0x41, 0xb0, 0x1f, 0x21, + 0x00, 0x03, 0x40, 0x20, 0x01, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x02, + 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, 0x03, 0x6a, 0x46, 0x0d, 0x02, 0x20, + 0x00, 0x28, 0x02, 0x08, 0x22, 0x00, 0x0d, 0x00, 0x0b, 0x0c, 0x02, 0x0b, + 0x41, 0x80, 0x1c, 0x28, 0x02, 0x00, 0x22, 0x00, 0x41, 0x00, 0x20, 0x01, + 0x20, 0x00, 0x4f, 0x1b, 0x45, 0x04, 0x40, 0x41, 0x80, 0x1c, 0x20, 0x01, + 0x36, 0x02, 0x00, 0x0b, 0x41, 0x00, 0x21, 0x00, 0x41, 0xb4, 0x1f, 0x20, + 0x05, 0x36, 0x02, 0x00, 0x41, 0xb0, 0x1f, 0x20, 0x01, 0x36, 0x02, 0x00, + 0x41, 0x90, 0x1c, 0x41, 0x7f, 0x36, 0x02, 0x00, 0x41, 0x94, 0x1c, 0x41, + 0xc8, 0x1f, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x41, 0xbc, 0x1f, 0x41, + 0x00, 0x36, 0x02, 0x00, 0x03, 0x40, 0x20, 0x00, 0x41, 0xa0, 0x1c, 0x6a, + 0x20, 0x00, 0x41, 0x98, 0x1c, 0x6a, 0x22, 0x02, 0x36, 0x02, 0x00, 0x20, + 0x00, 0x41, 0xa4, 0x1c, 0x6a, 0x20, 0x02, 0x36, 0x02, 0x00, 0x20, 0x00, + 0x41, 0x08, 0x6a, 0x22, 0x00, 0x41, 0x80, 0x02, 0x47, 0x0d, 0x00, 0x0b, + 0x20, 0x01, 0x41, 0x78, 0x20, 0x01, 0x6b, 0x41, 0x0f, 0x71, 0x41, 0x00, + 0x20, 0x01, 0x41, 0x08, 0x6a, 0x41, 0x0f, 0x71, 0x1b, 0x22, 0x00, 0x6a, + 0x22, 0x02, 0x20, 0x05, 0x41, 0x48, 0x6a, 0x22, 0x03, 0x20, 0x00, 0x6b, + 0x22, 0x00, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x41, 0x8c, 0x1c, 0x41, + 0xd8, 0x1f, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x41, 0xfc, 0x1b, 0x20, + 0x00, 0x36, 0x02, 0x00, 0x41, 0x88, 0x1c, 0x20, 0x02, 0x36, 0x02, 0x00, + 0x20, 0x01, 0x20, 0x03, 0x6a, 0x41, 0x38, 0x36, 0x02, 0x04, 0x0c, 0x02, + 0x0b, 0x20, 0x00, 0x2d, 0x00, 0x0c, 0x41, 0x08, 0x71, 0x0d, 0x00, 0x20, + 0x01, 0x20, 0x07, 0x4d, 0x0d, 0x00, 0x20, 0x02, 0x20, 0x07, 0x4b, 0x0d, + 0x00, 0x20, 0x07, 0x41, 0x78, 0x20, 0x07, 0x6b, 0x41, 0x0f, 0x71, 0x41, + 0x00, 0x20, 0x07, 0x41, 0x08, 0x6a, 0x41, 0x0f, 0x71, 0x1b, 0x22, 0x01, + 0x6a, 0x22, 0x02, 0x41, 0xfc, 0x1b, 0x28, 0x02, 0x00, 0x20, 0x05, 0x6a, + 0x22, 0x04, 0x20, 0x01, 0x6b, 0x22, 0x01, 0x41, 0x01, 0x72, 0x36, 0x02, + 0x04, 0x20, 0x00, 0x20, 0x03, 0x20, 0x05, 0x6a, 0x36, 0x02, 0x04, 0x41, + 0x8c, 0x1c, 0x41, 0xd8, 0x1f, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x41, + 0xfc, 0x1b, 0x20, 0x01, 0x36, 0x02, 0x00, 0x41, 0x88, 0x1c, 0x20, 0x02, + 0x36, 0x02, 0x00, 0x20, 0x04, 0x20, 0x07, 0x6a, 0x41, 0x38, 0x36, 0x02, + 0x04, 0x0c, 0x01, 0x0b, 0x20, 0x01, 0x41, 0x80, 0x1c, 0x28, 0x02, 0x00, + 0x22, 0x03, 0x49, 0x04, 0x40, 0x41, 0x80, 0x1c, 0x20, 0x01, 0x36, 0x02, + 0x00, 0x20, 0x01, 0x21, 0x03, 0x0b, 0x20, 0x01, 0x20, 0x05, 0x6a, 0x21, + 0x02, 0x41, 0xb0, 0x1f, 0x21, 0x00, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x03, 0x40, 0x20, 0x02, 0x20, 0x00, + 0x28, 0x02, 0x00, 0x47, 0x04, 0x40, 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, + 0x00, 0x0d, 0x01, 0x0c, 0x02, 0x0b, 0x0b, 0x20, 0x00, 0x2d, 0x00, 0x0c, + 0x41, 0x08, 0x71, 0x45, 0x0d, 0x01, 0x0b, 0x41, 0xb0, 0x1f, 0x21, 0x00, + 0x03, 0x40, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x02, 0x20, 0x07, 0x4d, + 0x04, 0x40, 0x20, 0x02, 0x20, 0x00, 0x28, 0x02, 0x04, 0x6a, 0x22, 0x03, + 0x20, 0x07, 0x4b, 0x0d, 0x03, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x08, 0x21, + 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x0b, 0x20, 0x00, 0x20, 0x01, 0x36, 0x02, + 0x00, 0x20, 0x00, 0x20, 0x00, 0x28, 0x02, 0x04, 0x20, 0x05, 0x6a, 0x36, + 0x02, 0x04, 0x20, 0x01, 0x41, 0x78, 0x20, 0x01, 0x6b, 0x41, 0x0f, 0x71, + 0x41, 0x00, 0x20, 0x01, 0x41, 0x08, 0x6a, 0x41, 0x0f, 0x71, 0x1b, 0x6a, + 0x22, 0x08, 0x20, 0x06, 0x41, 0x03, 0x72, 0x36, 0x02, 0x04, 0x20, 0x02, + 0x41, 0x78, 0x20, 0x02, 0x6b, 0x41, 0x0f, 0x71, 0x41, 0x00, 0x20, 0x02, + 0x41, 0x08, 0x6a, 0x41, 0x0f, 0x71, 0x1b, 0x6a, 0x22, 0x01, 0x20, 0x08, + 0x6b, 0x20, 0x06, 0x6b, 0x21, 0x00, 0x20, 0x06, 0x20, 0x08, 0x6a, 0x21, + 0x04, 0x20, 0x01, 0x20, 0x07, 0x46, 0x04, 0x40, 0x41, 0x88, 0x1c, 0x20, + 0x04, 0x36, 0x02, 0x00, 0x41, 0xfc, 0x1b, 0x41, 0xfc, 0x1b, 0x28, 0x02, + 0x00, 0x20, 0x00, 0x6a, 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x04, 0x20, + 0x00, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x0c, 0x03, 0x0b, 0x20, 0x01, + 0x41, 0x84, 0x1c, 0x28, 0x02, 0x00, 0x46, 0x04, 0x40, 0x41, 0x84, 0x1c, + 0x20, 0x04, 0x36, 0x02, 0x00, 0x41, 0xf8, 0x1b, 0x41, 0xf8, 0x1b, 0x28, + 0x02, 0x00, 0x20, 0x00, 0x6a, 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x04, + 0x20, 0x00, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x20, 0x00, 0x20, 0x04, + 0x6a, 0x20, 0x00, 0x36, 0x02, 0x00, 0x0c, 0x03, 0x0b, 0x20, 0x01, 0x28, + 0x02, 0x04, 0x22, 0x06, 0x41, 0x03, 0x71, 0x41, 0x01, 0x46, 0x04, 0x40, + 0x20, 0x06, 0x41, 0x78, 0x71, 0x21, 0x09, 0x02, 0x40, 0x20, 0x06, 0x41, + 0xff, 0x01, 0x4d, 0x04, 0x40, 0x20, 0x01, 0x28, 0x02, 0x08, 0x22, 0x03, + 0x20, 0x06, 0x41, 0x03, 0x76, 0x22, 0x06, 0x41, 0x03, 0x74, 0x41, 0x98, + 0x1c, 0x6a, 0x47, 0x1a, 0x20, 0x03, 0x20, 0x01, 0x28, 0x02, 0x0c, 0x22, + 0x02, 0x46, 0x04, 0x40, 0x41, 0xf0, 0x1b, 0x41, 0xf0, 0x1b, 0x28, 0x02, + 0x00, 0x41, 0x7e, 0x20, 0x06, 0x77, 0x71, 0x36, 0x02, 0x00, 0x0c, 0x02, + 0x0b, 0x20, 0x02, 0x20, 0x03, 0x36, 0x02, 0x08, 0x20, 0x03, 0x20, 0x02, + 0x36, 0x02, 0x0c, 0x0c, 0x01, 0x0b, 0x20, 0x01, 0x28, 0x02, 0x18, 0x21, + 0x07, 0x02, 0x40, 0x20, 0x01, 0x20, 0x01, 0x28, 0x02, 0x0c, 0x22, 0x05, + 0x47, 0x04, 0x40, 0x20, 0x03, 0x20, 0x01, 0x28, 0x02, 0x08, 0x22, 0x02, + 0x4d, 0x04, 0x40, 0x20, 0x02, 0x28, 0x02, 0x0c, 0x1a, 0x0b, 0x20, 0x05, + 0x20, 0x02, 0x36, 0x02, 0x08, 0x20, 0x02, 0x20, 0x05, 0x36, 0x02, 0x0c, + 0x0c, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x01, 0x41, 0x14, 0x6a, 0x22, 0x02, + 0x28, 0x02, 0x00, 0x22, 0x06, 0x0d, 0x00, 0x20, 0x01, 0x41, 0x10, 0x6a, + 0x22, 0x02, 0x28, 0x02, 0x00, 0x22, 0x06, 0x0d, 0x00, 0x41, 0x00, 0x21, + 0x05, 0x0c, 0x01, 0x0b, 0x03, 0x40, 0x20, 0x02, 0x21, 0x03, 0x20, 0x06, + 0x22, 0x05, 0x41, 0x14, 0x6a, 0x22, 0x02, 0x28, 0x02, 0x00, 0x22, 0x06, + 0x0d, 0x00, 0x20, 0x05, 0x41, 0x10, 0x6a, 0x21, 0x02, 0x20, 0x05, 0x28, + 0x02, 0x10, 0x22, 0x06, 0x0d, 0x00, 0x0b, 0x20, 0x03, 0x41, 0x00, 0x36, + 0x02, 0x00, 0x0b, 0x20, 0x07, 0x45, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x01, + 0x20, 0x01, 0x28, 0x02, 0x1c, 0x22, 0x02, 0x41, 0x02, 0x74, 0x41, 0xa0, + 0x1e, 0x6a, 0x22, 0x03, 0x28, 0x02, 0x00, 0x46, 0x04, 0x40, 0x20, 0x03, + 0x20, 0x05, 0x36, 0x02, 0x00, 0x20, 0x05, 0x0d, 0x01, 0x41, 0xf4, 0x1b, + 0x41, 0xf4, 0x1b, 0x28, 0x02, 0x00, 0x41, 0x7e, 0x20, 0x02, 0x77, 0x71, + 0x36, 0x02, 0x00, 0x0c, 0x02, 0x0b, 0x20, 0x07, 0x41, 0x10, 0x41, 0x14, + 0x20, 0x07, 0x28, 0x02, 0x10, 0x20, 0x01, 0x46, 0x1b, 0x6a, 0x20, 0x05, + 0x36, 0x02, 0x00, 0x20, 0x05, 0x45, 0x0d, 0x01, 0x0b, 0x20, 0x05, 0x20, + 0x07, 0x36, 0x02, 0x18, 0x20, 0x01, 0x28, 0x02, 0x10, 0x22, 0x02, 0x04, + 0x40, 0x20, 0x05, 0x20, 0x02, 0x36, 0x02, 0x10, 0x20, 0x02, 0x20, 0x05, + 0x36, 0x02, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x02, 0x14, 0x22, 0x02, 0x45, + 0x0d, 0x00, 0x20, 0x05, 0x41, 0x14, 0x6a, 0x20, 0x02, 0x36, 0x02, 0x00, + 0x20, 0x02, 0x20, 0x05, 0x36, 0x02, 0x18, 0x0b, 0x20, 0x01, 0x20, 0x09, + 0x6a, 0x21, 0x01, 0x20, 0x00, 0x20, 0x09, 0x6a, 0x21, 0x00, 0x0b, 0x20, + 0x01, 0x20, 0x01, 0x28, 0x02, 0x04, 0x41, 0x7e, 0x71, 0x36, 0x02, 0x04, + 0x20, 0x00, 0x20, 0x04, 0x6a, 0x20, 0x00, 0x36, 0x02, 0x00, 0x20, 0x04, + 0x20, 0x00, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x20, 0x00, 0x41, 0xff, + 0x01, 0x4d, 0x04, 0x40, 0x20, 0x00, 0x41, 0x03, 0x76, 0x22, 0x01, 0x41, + 0x03, 0x74, 0x41, 0x98, 0x1c, 0x6a, 0x21, 0x00, 0x02, 0x7f, 0x41, 0xf0, + 0x1b, 0x28, 0x02, 0x00, 0x22, 0x02, 0x41, 0x01, 0x20, 0x01, 0x74, 0x22, + 0x01, 0x71, 0x45, 0x04, 0x40, 0x41, 0xf0, 0x1b, 0x20, 0x01, 0x20, 0x02, + 0x72, 0x36, 0x02, 0x00, 0x20, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x28, + 0x02, 0x08, 0x0b, 0x22, 0x02, 0x20, 0x04, 0x36, 0x02, 0x0c, 0x20, 0x00, + 0x20, 0x04, 0x36, 0x02, 0x08, 0x20, 0x04, 0x20, 0x00, 0x36, 0x02, 0x0c, + 0x20, 0x04, 0x20, 0x02, 0x36, 0x02, 0x08, 0x0c, 0x03, 0x0b, 0x20, 0x04, + 0x02, 0x7f, 0x41, 0x00, 0x20, 0x00, 0x41, 0x08, 0x76, 0x22, 0x01, 0x45, + 0x0d, 0x00, 0x1a, 0x41, 0x1f, 0x20, 0x00, 0x41, 0xff, 0xff, 0xff, 0x07, + 0x4b, 0x0d, 0x00, 0x1a, 0x20, 0x01, 0x20, 0x01, 0x41, 0x80, 0xfe, 0x3f, + 0x6a, 0x41, 0x10, 0x76, 0x41, 0x08, 0x71, 0x22, 0x01, 0x74, 0x22, 0x02, + 0x20, 0x02, 0x41, 0x80, 0xe0, 0x1f, 0x6a, 0x41, 0x10, 0x76, 0x41, 0x04, + 0x71, 0x22, 0x02, 0x74, 0x22, 0x03, 0x20, 0x03, 0x41, 0x80, 0x80, 0x0f, + 0x6a, 0x41, 0x10, 0x76, 0x41, 0x02, 0x71, 0x22, 0x03, 0x74, 0x41, 0x0f, + 0x76, 0x20, 0x01, 0x20, 0x02, 0x72, 0x20, 0x03, 0x72, 0x6b, 0x22, 0x01, + 0x41, 0x01, 0x74, 0x20, 0x00, 0x20, 0x01, 0x41, 0x15, 0x6a, 0x76, 0x41, + 0x01, 0x71, 0x72, 0x41, 0x1c, 0x6a, 0x0b, 0x22, 0x02, 0x36, 0x02, 0x1c, + 0x20, 0x04, 0x42, 0x00, 0x37, 0x02, 0x10, 0x20, 0x02, 0x41, 0x02, 0x74, + 0x41, 0xa0, 0x1e, 0x6a, 0x21, 0x01, 0x41, 0xf4, 0x1b, 0x28, 0x02, 0x00, + 0x22, 0x03, 0x41, 0x01, 0x20, 0x02, 0x74, 0x22, 0x06, 0x71, 0x45, 0x04, + 0x40, 0x20, 0x01, 0x20, 0x04, 0x36, 0x02, 0x00, 0x41, 0xf4, 0x1b, 0x20, + 0x03, 0x20, 0x06, 0x72, 0x36, 0x02, 0x00, 0x20, 0x04, 0x20, 0x01, 0x36, + 0x02, 0x18, 0x20, 0x04, 0x20, 0x04, 0x36, 0x02, 0x08, 0x20, 0x04, 0x20, + 0x04, 0x36, 0x02, 0x0c, 0x0c, 0x03, 0x0b, 0x20, 0x00, 0x41, 0x00, 0x41, + 0x19, 0x20, 0x02, 0x41, 0x01, 0x76, 0x6b, 0x20, 0x02, 0x41, 0x1f, 0x46, + 0x1b, 0x74, 0x21, 0x02, 0x20, 0x01, 0x28, 0x02, 0x00, 0x21, 0x01, 0x03, + 0x40, 0x20, 0x01, 0x22, 0x03, 0x28, 0x02, 0x04, 0x41, 0x78, 0x71, 0x20, + 0x00, 0x46, 0x0d, 0x02, 0x20, 0x02, 0x41, 0x1d, 0x76, 0x21, 0x01, 0x20, + 0x02, 0x41, 0x01, 0x74, 0x21, 0x02, 0x20, 0x03, 0x20, 0x01, 0x41, 0x04, + 0x71, 0x6a, 0x41, 0x10, 0x6a, 0x22, 0x06, 0x28, 0x02, 0x00, 0x22, 0x01, + 0x0d, 0x00, 0x0b, 0x20, 0x06, 0x20, 0x04, 0x36, 0x02, 0x00, 0x20, 0x04, + 0x20, 0x03, 0x36, 0x02, 0x18, 0x20, 0x04, 0x20, 0x04, 0x36, 0x02, 0x0c, + 0x20, 0x04, 0x20, 0x04, 0x36, 0x02, 0x08, 0x0c, 0x02, 0x0b, 0x20, 0x01, + 0x41, 0x78, 0x20, 0x01, 0x6b, 0x41, 0x0f, 0x71, 0x41, 0x00, 0x20, 0x01, + 0x41, 0x08, 0x6a, 0x41, 0x0f, 0x71, 0x1b, 0x22, 0x00, 0x6a, 0x22, 0x04, + 0x20, 0x05, 0x41, 0x48, 0x6a, 0x22, 0x02, 0x20, 0x00, 0x6b, 0x22, 0x00, + 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x20, 0x01, 0x20, 0x02, 0x6a, 0x41, + 0x38, 0x36, 0x02, 0x04, 0x20, 0x07, 0x20, 0x03, 0x41, 0x37, 0x20, 0x03, + 0x6b, 0x41, 0x0f, 0x71, 0x41, 0x00, 0x20, 0x03, 0x41, 0x49, 0x6a, 0x41, + 0x0f, 0x71, 0x1b, 0x6a, 0x41, 0x41, 0x6a, 0x22, 0x02, 0x20, 0x02, 0x20, + 0x07, 0x41, 0x10, 0x6a, 0x49, 0x1b, 0x22, 0x02, 0x41, 0x23, 0x36, 0x02, + 0x04, 0x41, 0x8c, 0x1c, 0x41, 0xd8, 0x1f, 0x28, 0x02, 0x00, 0x36, 0x02, + 0x00, 0x41, 0xfc, 0x1b, 0x20, 0x00, 0x36, 0x02, 0x00, 0x41, 0x88, 0x1c, + 0x20, 0x04, 0x36, 0x02, 0x00, 0x20, 0x02, 0x41, 0x10, 0x6a, 0x41, 0xb8, + 0x1f, 0x29, 0x02, 0x00, 0x37, 0x02, 0x00, 0x20, 0x02, 0x41, 0xb0, 0x1f, + 0x29, 0x02, 0x00, 0x37, 0x02, 0x08, 0x41, 0xb8, 0x1f, 0x20, 0x02, 0x41, + 0x08, 0x6a, 0x36, 0x02, 0x00, 0x41, 0xb4, 0x1f, 0x20, 0x05, 0x36, 0x02, + 0x00, 0x41, 0xb0, 0x1f, 0x20, 0x01, 0x36, 0x02, 0x00, 0x41, 0xbc, 0x1f, + 0x41, 0x00, 0x36, 0x02, 0x00, 0x20, 0x02, 0x41, 0x24, 0x6a, 0x21, 0x00, + 0x03, 0x40, 0x20, 0x00, 0x41, 0x07, 0x36, 0x02, 0x00, 0x20, 0x00, 0x41, + 0x04, 0x6a, 0x22, 0x00, 0x20, 0x03, 0x49, 0x0d, 0x00, 0x0b, 0x20, 0x02, + 0x20, 0x07, 0x46, 0x0d, 0x03, 0x20, 0x02, 0x20, 0x02, 0x28, 0x02, 0x04, + 0x41, 0x7e, 0x71, 0x36, 0x02, 0x04, 0x20, 0x02, 0x20, 0x02, 0x20, 0x07, + 0x6b, 0x22, 0x03, 0x36, 0x02, 0x00, 0x20, 0x07, 0x20, 0x03, 0x41, 0x01, + 0x72, 0x36, 0x02, 0x04, 0x20, 0x03, 0x41, 0xff, 0x01, 0x4d, 0x04, 0x40, + 0x20, 0x03, 0x41, 0x03, 0x76, 0x22, 0x01, 0x41, 0x03, 0x74, 0x41, 0x98, + 0x1c, 0x6a, 0x21, 0x00, 0x02, 0x7f, 0x41, 0xf0, 0x1b, 0x28, 0x02, 0x00, + 0x22, 0x02, 0x41, 0x01, 0x20, 0x01, 0x74, 0x22, 0x01, 0x71, 0x45, 0x04, + 0x40, 0x41, 0xf0, 0x1b, 0x20, 0x01, 0x20, 0x02, 0x72, 0x36, 0x02, 0x00, + 0x20, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x08, 0x0b, 0x22, + 0x04, 0x20, 0x07, 0x36, 0x02, 0x0c, 0x20, 0x00, 0x20, 0x07, 0x36, 0x02, + 0x08, 0x20, 0x07, 0x20, 0x00, 0x36, 0x02, 0x0c, 0x20, 0x07, 0x20, 0x04, + 0x36, 0x02, 0x08, 0x0c, 0x04, 0x0b, 0x20, 0x07, 0x42, 0x00, 0x37, 0x02, + 0x10, 0x20, 0x07, 0x41, 0x1c, 0x6a, 0x02, 0x7f, 0x41, 0x00, 0x20, 0x03, + 0x41, 0x08, 0x76, 0x22, 0x01, 0x45, 0x0d, 0x00, 0x1a, 0x41, 0x1f, 0x20, + 0x03, 0x41, 0xff, 0xff, 0xff, 0x07, 0x4b, 0x0d, 0x00, 0x1a, 0x20, 0x01, + 0x20, 0x01, 0x41, 0x80, 0xfe, 0x3f, 0x6a, 0x41, 0x10, 0x76, 0x41, 0x08, + 0x71, 0x22, 0x00, 0x74, 0x22, 0x01, 0x20, 0x01, 0x41, 0x80, 0xe0, 0x1f, + 0x6a, 0x41, 0x10, 0x76, 0x41, 0x04, 0x71, 0x22, 0x01, 0x74, 0x22, 0x02, + 0x20, 0x02, 0x41, 0x80, 0x80, 0x0f, 0x6a, 0x41, 0x10, 0x76, 0x41, 0x02, + 0x71, 0x22, 0x02, 0x74, 0x41, 0x0f, 0x76, 0x20, 0x00, 0x20, 0x01, 0x72, + 0x20, 0x02, 0x72, 0x6b, 0x22, 0x00, 0x41, 0x01, 0x74, 0x20, 0x03, 0x20, + 0x00, 0x41, 0x15, 0x6a, 0x76, 0x41, 0x01, 0x71, 0x72, 0x41, 0x1c, 0x6a, + 0x0b, 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00, 0x41, 0x02, 0x74, 0x41, + 0xa0, 0x1e, 0x6a, 0x21, 0x01, 0x41, 0xf4, 0x1b, 0x28, 0x02, 0x00, 0x22, + 0x02, 0x41, 0x01, 0x20, 0x00, 0x74, 0x22, 0x04, 0x71, 0x45, 0x04, 0x40, + 0x20, 0x01, 0x20, 0x07, 0x36, 0x02, 0x00, 0x41, 0xf4, 0x1b, 0x20, 0x02, + 0x20, 0x04, 0x72, 0x36, 0x02, 0x00, 0x20, 0x07, 0x41, 0x18, 0x6a, 0x20, + 0x01, 0x36, 0x02, 0x00, 0x20, 0x07, 0x20, 0x07, 0x36, 0x02, 0x08, 0x20, + 0x07, 0x20, 0x07, 0x36, 0x02, 0x0c, 0x0c, 0x04, 0x0b, 0x20, 0x03, 0x41, + 0x00, 0x41, 0x19, 0x20, 0x00, 0x41, 0x01, 0x76, 0x6b, 0x20, 0x00, 0x41, + 0x1f, 0x46, 0x1b, 0x74, 0x21, 0x00, 0x20, 0x01, 0x28, 0x02, 0x00, 0x21, + 0x01, 0x03, 0x40, 0x20, 0x01, 0x22, 0x02, 0x28, 0x02, 0x04, 0x41, 0x78, + 0x71, 0x20, 0x03, 0x46, 0x0d, 0x03, 0x20, 0x00, 0x41, 0x1d, 0x76, 0x21, + 0x01, 0x20, 0x00, 0x41, 0x01, 0x74, 0x21, 0x00, 0x20, 0x02, 0x20, 0x01, + 0x41, 0x04, 0x71, 0x6a, 0x41, 0x10, 0x6a, 0x22, 0x04, 0x28, 0x02, 0x00, + 0x22, 0x01, 0x0d, 0x00, 0x0b, 0x20, 0x04, 0x20, 0x07, 0x36, 0x02, 0x00, + 0x20, 0x07, 0x41, 0x18, 0x6a, 0x20, 0x02, 0x36, 0x02, 0x00, 0x20, 0x07, + 0x20, 0x07, 0x36, 0x02, 0x0c, 0x20, 0x07, 0x20, 0x07, 0x36, 0x02, 0x08, + 0x0c, 0x03, 0x0b, 0x20, 0x03, 0x28, 0x02, 0x08, 0x21, 0x00, 0x20, 0x03, + 0x20, 0x04, 0x36, 0x02, 0x08, 0x20, 0x00, 0x20, 0x04, 0x36, 0x02, 0x0c, + 0x20, 0x04, 0x41, 0x00, 0x36, 0x02, 0x18, 0x20, 0x04, 0x20, 0x00, 0x36, + 0x02, 0x08, 0x20, 0x04, 0x20, 0x03, 0x36, 0x02, 0x0c, 0x0b, 0x20, 0x08, + 0x41, 0x08, 0x6a, 0x21, 0x00, 0x0c, 0x05, 0x0b, 0x20, 0x02, 0x28, 0x02, + 0x08, 0x21, 0x00, 0x20, 0x02, 0x20, 0x07, 0x36, 0x02, 0x08, 0x20, 0x00, + 0x20, 0x07, 0x36, 0x02, 0x0c, 0x20, 0x07, 0x41, 0x18, 0x6a, 0x41, 0x00, + 0x36, 0x02, 0x00, 0x20, 0x07, 0x20, 0x00, 0x36, 0x02, 0x08, 0x20, 0x07, + 0x20, 0x02, 0x36, 0x02, 0x0c, 0x0b, 0x41, 0xfc, 0x1b, 0x28, 0x02, 0x00, + 0x22, 0x01, 0x20, 0x06, 0x4d, 0x0d, 0x00, 0x41, 0x88, 0x1c, 0x28, 0x02, + 0x00, 0x22, 0x00, 0x20, 0x06, 0x6a, 0x22, 0x02, 0x20, 0x01, 0x20, 0x06, + 0x6b, 0x22, 0x01, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x41, 0xfc, 0x1b, + 0x20, 0x01, 0x36, 0x02, 0x00, 0x41, 0x88, 0x1c, 0x20, 0x02, 0x36, 0x02, + 0x00, 0x20, 0x00, 0x20, 0x06, 0x41, 0x03, 0x72, 0x36, 0x02, 0x04, 0x20, + 0x00, 0x41, 0x08, 0x6a, 0x21, 0x00, 0x0c, 0x03, 0x0b, 0x41, 0x00, 0x21, + 0x00, 0x41, 0xe0, 0x1f, 0x41, 0x30, 0x36, 0x02, 0x00, 0x0c, 0x02, 0x0b, + 0x02, 0x40, 0x20, 0x07, 0x45, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x03, 0x28, + 0x02, 0x1c, 0x22, 0x00, 0x41, 0x02, 0x74, 0x41, 0xa0, 0x1e, 0x6a, 0x22, + 0x02, 0x28, 0x02, 0x00, 0x20, 0x03, 0x46, 0x04, 0x40, 0x20, 0x02, 0x20, + 0x01, 0x36, 0x02, 0x00, 0x20, 0x01, 0x0d, 0x01, 0x41, 0xf4, 0x1b, 0x20, + 0x08, 0x41, 0x7e, 0x20, 0x00, 0x77, 0x71, 0x22, 0x08, 0x36, 0x02, 0x00, + 0x0c, 0x02, 0x0b, 0x20, 0x07, 0x41, 0x10, 0x41, 0x14, 0x20, 0x07, 0x28, + 0x02, 0x10, 0x20, 0x03, 0x46, 0x1b, 0x6a, 0x20, 0x01, 0x36, 0x02, 0x00, + 0x20, 0x01, 0x45, 0x0d, 0x01, 0x0b, 0x20, 0x01, 0x20, 0x07, 0x36, 0x02, + 0x18, 0x20, 0x03, 0x28, 0x02, 0x10, 0x22, 0x00, 0x04, 0x40, 0x20, 0x01, + 0x20, 0x00, 0x36, 0x02, 0x10, 0x20, 0x00, 0x20, 0x01, 0x36, 0x02, 0x18, + 0x0b, 0x20, 0x03, 0x41, 0x14, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x00, 0x45, + 0x0d, 0x00, 0x20, 0x01, 0x41, 0x14, 0x6a, 0x20, 0x00, 0x36, 0x02, 0x00, + 0x20, 0x00, 0x20, 0x01, 0x36, 0x02, 0x18, 0x0b, 0x02, 0x40, 0x20, 0x04, + 0x41, 0x0f, 0x4d, 0x04, 0x40, 0x20, 0x03, 0x20, 0x04, 0x20, 0x06, 0x6a, + 0x22, 0x00, 0x41, 0x03, 0x72, 0x36, 0x02, 0x04, 0x20, 0x00, 0x20, 0x03, + 0x6a, 0x22, 0x00, 0x20, 0x00, 0x28, 0x02, 0x04, 0x41, 0x01, 0x72, 0x36, + 0x02, 0x04, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x20, 0x06, 0x6a, 0x22, 0x05, + 0x20, 0x04, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x20, 0x03, 0x20, 0x06, + 0x41, 0x03, 0x72, 0x36, 0x02, 0x04, 0x20, 0x04, 0x20, 0x05, 0x6a, 0x20, + 0x04, 0x36, 0x02, 0x00, 0x20, 0x04, 0x41, 0xff, 0x01, 0x4d, 0x04, 0x40, + 0x20, 0x04, 0x41, 0x03, 0x76, 0x22, 0x01, 0x41, 0x03, 0x74, 0x41, 0x98, + 0x1c, 0x6a, 0x21, 0x00, 0x02, 0x7f, 0x41, 0xf0, 0x1b, 0x28, 0x02, 0x00, + 0x22, 0x02, 0x41, 0x01, 0x20, 0x01, 0x74, 0x22, 0x01, 0x71, 0x45, 0x04, + 0x40, 0x41, 0xf0, 0x1b, 0x20, 0x01, 0x20, 0x02, 0x72, 0x36, 0x02, 0x00, + 0x20, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x08, 0x0b, 0x22, + 0x02, 0x20, 0x05, 0x36, 0x02, 0x0c, 0x20, 0x00, 0x20, 0x05, 0x36, 0x02, + 0x08, 0x20, 0x05, 0x20, 0x00, 0x36, 0x02, 0x0c, 0x20, 0x05, 0x20, 0x02, + 0x36, 0x02, 0x08, 0x0c, 0x01, 0x0b, 0x20, 0x05, 0x02, 0x7f, 0x41, 0x00, + 0x20, 0x04, 0x41, 0x08, 0x76, 0x22, 0x01, 0x45, 0x0d, 0x00, 0x1a, 0x41, + 0x1f, 0x20, 0x04, 0x41, 0xff, 0xff, 0xff, 0x07, 0x4b, 0x0d, 0x00, 0x1a, + 0x20, 0x01, 0x20, 0x01, 0x41, 0x80, 0xfe, 0x3f, 0x6a, 0x41, 0x10, 0x76, + 0x41, 0x08, 0x71, 0x22, 0x00, 0x74, 0x22, 0x01, 0x20, 0x01, 0x41, 0x80, + 0xe0, 0x1f, 0x6a, 0x41, 0x10, 0x76, 0x41, 0x04, 0x71, 0x22, 0x01, 0x74, + 0x22, 0x02, 0x20, 0x02, 0x41, 0x80, 0x80, 0x0f, 0x6a, 0x41, 0x10, 0x76, + 0x41, 0x02, 0x71, 0x22, 0x02, 0x74, 0x41, 0x0f, 0x76, 0x20, 0x00, 0x20, + 0x01, 0x72, 0x20, 0x02, 0x72, 0x6b, 0x22, 0x00, 0x41, 0x01, 0x74, 0x20, + 0x04, 0x20, 0x00, 0x41, 0x15, 0x6a, 0x76, 0x41, 0x01, 0x71, 0x72, 0x41, + 0x1c, 0x6a, 0x0b, 0x22, 0x00, 0x36, 0x02, 0x1c, 0x20, 0x05, 0x42, 0x00, + 0x37, 0x02, 0x10, 0x20, 0x00, 0x41, 0x02, 0x74, 0x41, 0xa0, 0x1e, 0x6a, + 0x21, 0x01, 0x20, 0x08, 0x41, 0x01, 0x20, 0x00, 0x74, 0x22, 0x02, 0x71, + 0x45, 0x04, 0x40, 0x20, 0x01, 0x20, 0x05, 0x36, 0x02, 0x00, 0x41, 0xf4, + 0x1b, 0x20, 0x02, 0x20, 0x08, 0x72, 0x36, 0x02, 0x00, 0x20, 0x05, 0x20, + 0x01, 0x36, 0x02, 0x18, 0x20, 0x05, 0x20, 0x05, 0x36, 0x02, 0x08, 0x20, + 0x05, 0x20, 0x05, 0x36, 0x02, 0x0c, 0x0c, 0x01, 0x0b, 0x20, 0x04, 0x41, + 0x00, 0x41, 0x19, 0x20, 0x00, 0x41, 0x01, 0x76, 0x6b, 0x20, 0x00, 0x41, + 0x1f, 0x46, 0x1b, 0x74, 0x21, 0x00, 0x20, 0x01, 0x28, 0x02, 0x00, 0x21, + 0x06, 0x02, 0x40, 0x03, 0x40, 0x20, 0x06, 0x22, 0x01, 0x28, 0x02, 0x04, + 0x41, 0x78, 0x71, 0x20, 0x04, 0x46, 0x0d, 0x01, 0x20, 0x00, 0x41, 0x1d, + 0x76, 0x21, 0x02, 0x20, 0x00, 0x41, 0x01, 0x74, 0x21, 0x00, 0x20, 0x01, + 0x20, 0x02, 0x41, 0x04, 0x71, 0x6a, 0x41, 0x10, 0x6a, 0x22, 0x02, 0x28, + 0x02, 0x00, 0x22, 0x06, 0x0d, 0x00, 0x0b, 0x20, 0x02, 0x20, 0x05, 0x36, + 0x02, 0x00, 0x20, 0x05, 0x20, 0x01, 0x36, 0x02, 0x18, 0x20, 0x05, 0x20, + 0x05, 0x36, 0x02, 0x0c, 0x20, 0x05, 0x20, 0x05, 0x36, 0x02, 0x08, 0x0c, + 0x01, 0x0b, 0x20, 0x01, 0x28, 0x02, 0x08, 0x21, 0x00, 0x20, 0x01, 0x20, + 0x05, 0x36, 0x02, 0x08, 0x20, 0x00, 0x20, 0x05, 0x36, 0x02, 0x0c, 0x20, + 0x05, 0x41, 0x00, 0x36, 0x02, 0x18, 0x20, 0x05, 0x20, 0x00, 0x36, 0x02, + 0x08, 0x20, 0x05, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x0b, 0x20, 0x03, 0x41, + 0x08, 0x6a, 0x21, 0x00, 0x0c, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x09, 0x45, + 0x0d, 0x00, 0x02, 0x40, 0x20, 0x01, 0x28, 0x02, 0x1c, 0x22, 0x00, 0x41, + 0x02, 0x74, 0x41, 0xa0, 0x1e, 0x6a, 0x22, 0x04, 0x28, 0x02, 0x00, 0x20, + 0x01, 0x46, 0x04, 0x40, 0x20, 0x04, 0x20, 0x03, 0x36, 0x02, 0x00, 0x20, + 0x03, 0x0d, 0x01, 0x41, 0xf4, 0x1b, 0x20, 0x0a, 0x41, 0x7e, 0x20, 0x00, + 0x77, 0x71, 0x36, 0x02, 0x00, 0x0c, 0x02, 0x0b, 0x20, 0x09, 0x41, 0x10, + 0x41, 0x14, 0x20, 0x09, 0x28, 0x02, 0x10, 0x20, 0x01, 0x46, 0x1b, 0x6a, + 0x20, 0x03, 0x36, 0x02, 0x00, 0x20, 0x03, 0x45, 0x0d, 0x01, 0x0b, 0x20, + 0x03, 0x20, 0x09, 0x36, 0x02, 0x18, 0x20, 0x01, 0x28, 0x02, 0x10, 0x22, + 0x00, 0x04, 0x40, 0x20, 0x03, 0x20, 0x00, 0x36, 0x02, 0x10, 0x20, 0x00, + 0x20, 0x03, 0x36, 0x02, 0x18, 0x0b, 0x20, 0x01, 0x41, 0x14, 0x6a, 0x28, + 0x02, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x20, 0x03, 0x41, 0x14, 0x6a, + 0x20, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x03, 0x36, 0x02, 0x18, + 0x0b, 0x02, 0x40, 0x20, 0x02, 0x41, 0x0f, 0x4d, 0x04, 0x40, 0x20, 0x01, + 0x20, 0x02, 0x20, 0x06, 0x6a, 0x22, 0x00, 0x41, 0x03, 0x72, 0x36, 0x02, + 0x04, 0x20, 0x00, 0x20, 0x01, 0x6a, 0x22, 0x00, 0x20, 0x00, 0x28, 0x02, + 0x04, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x0c, 0x01, 0x0b, 0x20, 0x01, + 0x20, 0x06, 0x6a, 0x22, 0x07, 0x20, 0x02, 0x41, 0x01, 0x72, 0x36, 0x02, + 0x04, 0x20, 0x01, 0x20, 0x06, 0x41, 0x03, 0x72, 0x36, 0x02, 0x04, 0x20, + 0x02, 0x20, 0x07, 0x6a, 0x20, 0x02, 0x36, 0x02, 0x00, 0x20, 0x08, 0x04, + 0x40, 0x20, 0x08, 0x41, 0x03, 0x76, 0x22, 0x03, 0x41, 0x03, 0x74, 0x41, + 0x98, 0x1c, 0x6a, 0x21, 0x00, 0x41, 0x84, 0x1c, 0x28, 0x02, 0x00, 0x21, + 0x04, 0x02, 0x7f, 0x41, 0x01, 0x20, 0x03, 0x74, 0x22, 0x03, 0x20, 0x05, + 0x71, 0x45, 0x04, 0x40, 0x41, 0xf0, 0x1b, 0x20, 0x03, 0x20, 0x05, 0x72, + 0x36, 0x02, 0x00, 0x20, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x28, 0x02, + 0x08, 0x0b, 0x22, 0x03, 0x20, 0x04, 0x36, 0x02, 0x0c, 0x20, 0x00, 0x20, + 0x04, 0x36, 0x02, 0x08, 0x20, 0x04, 0x20, 0x00, 0x36, 0x02, 0x0c, 0x20, + 0x04, 0x20, 0x03, 0x36, 0x02, 0x08, 0x0b, 0x41, 0x84, 0x1c, 0x20, 0x07, + 0x36, 0x02, 0x00, 0x41, 0xf8, 0x1b, 0x20, 0x02, 0x36, 0x02, 0x00, 0x0b, + 0x20, 0x01, 0x41, 0x08, 0x6a, 0x21, 0x00, 0x0b, 0x20, 0x0b, 0x41, 0x10, + 0x6a, 0x24, 0x00, 0x20, 0x00, 0x0b, 0x9e, 0x0d, 0x01, 0x07, 0x7f, 0x02, + 0x40, 0x20, 0x00, 0x45, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x78, 0x6a, 0x22, + 0x03, 0x20, 0x00, 0x41, 0x7c, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x01, 0x41, + 0x78, 0x71, 0x22, 0x00, 0x6a, 0x21, 0x05, 0x02, 0x40, 0x20, 0x01, 0x41, + 0x01, 0x71, 0x0d, 0x00, 0x20, 0x01, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x01, + 0x20, 0x03, 0x20, 0x03, 0x28, 0x02, 0x00, 0x22, 0x02, 0x6b, 0x22, 0x03, + 0x41, 0x80, 0x1c, 0x28, 0x02, 0x00, 0x22, 0x04, 0x49, 0x0d, 0x01, 0x20, + 0x00, 0x20, 0x02, 0x6a, 0x21, 0x00, 0x20, 0x03, 0x41, 0x84, 0x1c, 0x28, + 0x02, 0x00, 0x47, 0x04, 0x40, 0x20, 0x02, 0x41, 0xff, 0x01, 0x4d, 0x04, + 0x40, 0x20, 0x03, 0x28, 0x02, 0x08, 0x22, 0x04, 0x20, 0x02, 0x41, 0x03, + 0x76, 0x22, 0x02, 0x41, 0x03, 0x74, 0x41, 0x98, 0x1c, 0x6a, 0x47, 0x1a, + 0x20, 0x04, 0x20, 0x03, 0x28, 0x02, 0x0c, 0x22, 0x01, 0x46, 0x04, 0x40, + 0x41, 0xf0, 0x1b, 0x41, 0xf0, 0x1b, 0x28, 0x02, 0x00, 0x41, 0x7e, 0x20, + 0x02, 0x77, 0x71, 0x36, 0x02, 0x00, 0x0c, 0x03, 0x0b, 0x20, 0x01, 0x20, + 0x04, 0x36, 0x02, 0x08, 0x20, 0x04, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x0c, + 0x02, 0x0b, 0x20, 0x03, 0x28, 0x02, 0x18, 0x21, 0x06, 0x02, 0x40, 0x20, + 0x03, 0x20, 0x03, 0x28, 0x02, 0x0c, 0x22, 0x01, 0x47, 0x04, 0x40, 0x20, + 0x04, 0x20, 0x03, 0x28, 0x02, 0x08, 0x22, 0x02, 0x4d, 0x04, 0x40, 0x20, + 0x02, 0x28, 0x02, 0x0c, 0x1a, 0x0b, 0x20, 0x01, 0x20, 0x02, 0x36, 0x02, + 0x08, 0x20, 0x02, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x0c, 0x01, 0x0b, 0x02, + 0x40, 0x20, 0x03, 0x41, 0x14, 0x6a, 0x22, 0x02, 0x28, 0x02, 0x00, 0x22, + 0x04, 0x0d, 0x00, 0x20, 0x03, 0x41, 0x10, 0x6a, 0x22, 0x02, 0x28, 0x02, + 0x00, 0x22, 0x04, 0x0d, 0x00, 0x41, 0x00, 0x21, 0x01, 0x0c, 0x01, 0x0b, + 0x03, 0x40, 0x20, 0x02, 0x21, 0x07, 0x20, 0x04, 0x22, 0x01, 0x41, 0x14, + 0x6a, 0x22, 0x02, 0x28, 0x02, 0x00, 0x22, 0x04, 0x0d, 0x00, 0x20, 0x01, + 0x41, 0x10, 0x6a, 0x21, 0x02, 0x20, 0x01, 0x28, 0x02, 0x10, 0x22, 0x04, + 0x0d, 0x00, 0x0b, 0x20, 0x07, 0x41, 0x00, 0x36, 0x02, 0x00, 0x0b, 0x20, + 0x06, 0x45, 0x0d, 0x01, 0x02, 0x40, 0x20, 0x03, 0x20, 0x03, 0x28, 0x02, + 0x1c, 0x22, 0x02, 0x41, 0x02, 0x74, 0x41, 0xa0, 0x1e, 0x6a, 0x22, 0x04, + 0x28, 0x02, 0x00, 0x46, 0x04, 0x40, 0x20, 0x04, 0x20, 0x01, 0x36, 0x02, + 0x00, 0x20, 0x01, 0x0d, 0x01, 0x41, 0xf4, 0x1b, 0x41, 0xf4, 0x1b, 0x28, + 0x02, 0x00, 0x41, 0x7e, 0x20, 0x02, 0x77, 0x71, 0x36, 0x02, 0x00, 0x0c, + 0x03, 0x0b, 0x20, 0x06, 0x41, 0x10, 0x41, 0x14, 0x20, 0x06, 0x28, 0x02, + 0x10, 0x20, 0x03, 0x46, 0x1b, 0x6a, 0x20, 0x01, 0x36, 0x02, 0x00, 0x20, + 0x01, 0x45, 0x0d, 0x02, 0x0b, 0x20, 0x01, 0x20, 0x06, 0x36, 0x02, 0x18, + 0x20, 0x03, 0x28, 0x02, 0x10, 0x22, 0x02, 0x04, 0x40, 0x20, 0x01, 0x20, + 0x02, 0x36, 0x02, 0x10, 0x20, 0x02, 0x20, 0x01, 0x36, 0x02, 0x18, 0x0b, + 0x20, 0x03, 0x28, 0x02, 0x14, 0x22, 0x02, 0x45, 0x0d, 0x01, 0x20, 0x01, + 0x41, 0x14, 0x6a, 0x20, 0x02, 0x36, 0x02, 0x00, 0x20, 0x02, 0x20, 0x01, + 0x36, 0x02, 0x18, 0x0c, 0x01, 0x0b, 0x20, 0x05, 0x28, 0x02, 0x04, 0x22, + 0x01, 0x41, 0x03, 0x71, 0x41, 0x03, 0x47, 0x0d, 0x00, 0x20, 0x05, 0x20, + 0x01, 0x41, 0x7e, 0x71, 0x36, 0x02, 0x04, 0x41, 0xf8, 0x1b, 0x20, 0x00, + 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x03, 0x6a, 0x20, 0x00, 0x36, 0x02, + 0x00, 0x20, 0x03, 0x20, 0x00, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x0f, + 0x0b, 0x20, 0x05, 0x20, 0x03, 0x4d, 0x0d, 0x00, 0x20, 0x05, 0x28, 0x02, + 0x04, 0x22, 0x01, 0x41, 0x01, 0x71, 0x45, 0x0d, 0x00, 0x02, 0x40, 0x20, + 0x01, 0x41, 0x02, 0x71, 0x45, 0x04, 0x40, 0x20, 0x05, 0x41, 0x88, 0x1c, + 0x28, 0x02, 0x00, 0x46, 0x04, 0x40, 0x41, 0x88, 0x1c, 0x20, 0x03, 0x36, + 0x02, 0x00, 0x41, 0xfc, 0x1b, 0x41, 0xfc, 0x1b, 0x28, 0x02, 0x00, 0x20, + 0x00, 0x6a, 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x03, 0x20, 0x00, 0x41, + 0x01, 0x72, 0x36, 0x02, 0x04, 0x20, 0x03, 0x41, 0x84, 0x1c, 0x28, 0x02, + 0x00, 0x47, 0x0d, 0x03, 0x41, 0xf8, 0x1b, 0x41, 0x00, 0x36, 0x02, 0x00, + 0x41, 0x84, 0x1c, 0x41, 0x00, 0x36, 0x02, 0x00, 0x0f, 0x0b, 0x20, 0x05, + 0x41, 0x84, 0x1c, 0x28, 0x02, 0x00, 0x46, 0x04, 0x40, 0x41, 0x84, 0x1c, + 0x20, 0x03, 0x36, 0x02, 0x00, 0x41, 0xf8, 0x1b, 0x41, 0xf8, 0x1b, 0x28, + 0x02, 0x00, 0x20, 0x00, 0x6a, 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x03, + 0x20, 0x00, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x20, 0x00, 0x20, 0x03, + 0x6a, 0x20, 0x00, 0x36, 0x02, 0x00, 0x0f, 0x0b, 0x20, 0x01, 0x41, 0x78, + 0x71, 0x20, 0x00, 0x6a, 0x21, 0x00, 0x02, 0x40, 0x20, 0x01, 0x41, 0xff, + 0x01, 0x4d, 0x04, 0x40, 0x20, 0x05, 0x28, 0x02, 0x0c, 0x21, 0x02, 0x20, + 0x05, 0x28, 0x02, 0x08, 0x22, 0x04, 0x20, 0x01, 0x41, 0x03, 0x76, 0x22, + 0x01, 0x41, 0x03, 0x74, 0x41, 0x98, 0x1c, 0x6a, 0x22, 0x07, 0x47, 0x04, + 0x40, 0x41, 0x80, 0x1c, 0x28, 0x02, 0x00, 0x1a, 0x0b, 0x20, 0x02, 0x20, + 0x04, 0x46, 0x04, 0x40, 0x41, 0xf0, 0x1b, 0x41, 0xf0, 0x1b, 0x28, 0x02, + 0x00, 0x41, 0x7e, 0x20, 0x01, 0x77, 0x71, 0x36, 0x02, 0x00, 0x0c, 0x02, + 0x0b, 0x20, 0x02, 0x20, 0x07, 0x47, 0x04, 0x40, 0x41, 0x80, 0x1c, 0x28, + 0x02, 0x00, 0x1a, 0x0b, 0x20, 0x02, 0x20, 0x04, 0x36, 0x02, 0x08, 0x20, + 0x04, 0x20, 0x02, 0x36, 0x02, 0x0c, 0x0c, 0x01, 0x0b, 0x20, 0x05, 0x28, + 0x02, 0x18, 0x21, 0x06, 0x02, 0x40, 0x20, 0x05, 0x20, 0x05, 0x28, 0x02, + 0x0c, 0x22, 0x01, 0x47, 0x04, 0x40, 0x41, 0x80, 0x1c, 0x28, 0x02, 0x00, + 0x20, 0x05, 0x28, 0x02, 0x08, 0x22, 0x02, 0x4d, 0x04, 0x40, 0x20, 0x02, + 0x28, 0x02, 0x0c, 0x1a, 0x0b, 0x20, 0x01, 0x20, 0x02, 0x36, 0x02, 0x08, + 0x20, 0x02, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x0c, 0x01, 0x0b, 0x02, 0x40, + 0x20, 0x05, 0x41, 0x14, 0x6a, 0x22, 0x02, 0x28, 0x02, 0x00, 0x22, 0x04, + 0x0d, 0x00, 0x20, 0x05, 0x41, 0x10, 0x6a, 0x22, 0x02, 0x28, 0x02, 0x00, + 0x22, 0x04, 0x0d, 0x00, 0x41, 0x00, 0x21, 0x01, 0x0c, 0x01, 0x0b, 0x03, + 0x40, 0x20, 0x02, 0x21, 0x07, 0x20, 0x04, 0x22, 0x01, 0x41, 0x14, 0x6a, + 0x22, 0x02, 0x28, 0x02, 0x00, 0x22, 0x04, 0x0d, 0x00, 0x20, 0x01, 0x41, + 0x10, 0x6a, 0x21, 0x02, 0x20, 0x01, 0x28, 0x02, 0x10, 0x22, 0x04, 0x0d, + 0x00, 0x0b, 0x20, 0x07, 0x41, 0x00, 0x36, 0x02, 0x00, 0x0b, 0x20, 0x06, + 0x45, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x05, 0x20, 0x05, 0x28, 0x02, 0x1c, + 0x22, 0x02, 0x41, 0x02, 0x74, 0x41, 0xa0, 0x1e, 0x6a, 0x22, 0x04, 0x28, + 0x02, 0x00, 0x46, 0x04, 0x40, 0x20, 0x04, 0x20, 0x01, 0x36, 0x02, 0x00, + 0x20, 0x01, 0x0d, 0x01, 0x41, 0xf4, 0x1b, 0x41, 0xf4, 0x1b, 0x28, 0x02, + 0x00, 0x41, 0x7e, 0x20, 0x02, 0x77, 0x71, 0x36, 0x02, 0x00, 0x0c, 0x02, + 0x0b, 0x20, 0x06, 0x41, 0x10, 0x41, 0x14, 0x20, 0x06, 0x28, 0x02, 0x10, + 0x20, 0x05, 0x46, 0x1b, 0x6a, 0x20, 0x01, 0x36, 0x02, 0x00, 0x20, 0x01, + 0x45, 0x0d, 0x01, 0x0b, 0x20, 0x01, 0x20, 0x06, 0x36, 0x02, 0x18, 0x20, + 0x05, 0x28, 0x02, 0x10, 0x22, 0x02, 0x04, 0x40, 0x20, 0x01, 0x20, 0x02, + 0x36, 0x02, 0x10, 0x20, 0x02, 0x20, 0x01, 0x36, 0x02, 0x18, 0x0b, 0x20, + 0x05, 0x28, 0x02, 0x14, 0x22, 0x02, 0x45, 0x0d, 0x00, 0x20, 0x01, 0x41, + 0x14, 0x6a, 0x20, 0x02, 0x36, 0x02, 0x00, 0x20, 0x02, 0x20, 0x01, 0x36, + 0x02, 0x18, 0x0b, 0x20, 0x00, 0x20, 0x03, 0x6a, 0x20, 0x00, 0x36, 0x02, + 0x00, 0x20, 0x03, 0x20, 0x00, 0x41, 0x01, 0x72, 0x36, 0x02, 0x04, 0x20, + 0x03, 0x41, 0x84, 0x1c, 0x28, 0x02, 0x00, 0x47, 0x0d, 0x01, 0x41, 0xf8, + 0x1b, 0x20, 0x00, 0x36, 0x02, 0x00, 0x0f, 0x0b, 0x20, 0x05, 0x20, 0x01, + 0x41, 0x7e, 0x71, 0x36, 0x02, 0x04, 0x20, 0x00, 0x20, 0x03, 0x6a, 0x20, + 0x00, 0x36, 0x02, 0x00, 0x20, 0x03, 0x20, 0x00, 0x41, 0x01, 0x72, 0x36, + 0x02, 0x04, 0x0b, 0x20, 0x00, 0x41, 0xff, 0x01, 0x4d, 0x04, 0x40, 0x20, + 0x00, 0x41, 0x03, 0x76, 0x22, 0x01, 0x41, 0x03, 0x74, 0x41, 0x98, 0x1c, + 0x6a, 0x21, 0x00, 0x02, 0x7f, 0x41, 0xf0, 0x1b, 0x28, 0x02, 0x00, 0x22, + 0x02, 0x41, 0x01, 0x20, 0x01, 0x74, 0x22, 0x01, 0x71, 0x45, 0x04, 0x40, + 0x41, 0xf0, 0x1b, 0x20, 0x01, 0x20, 0x02, 0x72, 0x36, 0x02, 0x00, 0x20, + 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x08, 0x0b, 0x22, 0x02, + 0x20, 0x03, 0x36, 0x02, 0x0c, 0x20, 0x00, 0x20, 0x03, 0x36, 0x02, 0x08, + 0x20, 0x03, 0x20, 0x00, 0x36, 0x02, 0x0c, 0x20, 0x03, 0x20, 0x02, 0x36, + 0x02, 0x08, 0x0f, 0x0b, 0x20, 0x03, 0x42, 0x00, 0x37, 0x02, 0x10, 0x20, + 0x03, 0x41, 0x1c, 0x6a, 0x02, 0x7f, 0x41, 0x00, 0x20, 0x00, 0x41, 0x08, + 0x76, 0x22, 0x01, 0x45, 0x0d, 0x00, 0x1a, 0x41, 0x1f, 0x20, 0x00, 0x41, + 0xff, 0xff, 0xff, 0x07, 0x4b, 0x0d, 0x00, 0x1a, 0x20, 0x01, 0x20, 0x01, + 0x41, 0x80, 0xfe, 0x3f, 0x6a, 0x41, 0x10, 0x76, 0x41, 0x08, 0x71, 0x22, + 0x01, 0x74, 0x22, 0x02, 0x20, 0x02, 0x41, 0x80, 0xe0, 0x1f, 0x6a, 0x41, + 0x10, 0x76, 0x41, 0x04, 0x71, 0x22, 0x02, 0x74, 0x22, 0x04, 0x20, 0x04, + 0x41, 0x80, 0x80, 0x0f, 0x6a, 0x41, 0x10, 0x76, 0x41, 0x02, 0x71, 0x22, + 0x04, 0x74, 0x41, 0x0f, 0x76, 0x20, 0x01, 0x20, 0x02, 0x72, 0x20, 0x04, + 0x72, 0x6b, 0x22, 0x01, 0x41, 0x01, 0x74, 0x20, 0x00, 0x20, 0x01, 0x41, + 0x15, 0x6a, 0x76, 0x41, 0x01, 0x71, 0x72, 0x41, 0x1c, 0x6a, 0x0b, 0x22, + 0x02, 0x36, 0x02, 0x00, 0x20, 0x02, 0x41, 0x02, 0x74, 0x41, 0xa0, 0x1e, + 0x6a, 0x21, 0x01, 0x02, 0x40, 0x41, 0xf4, 0x1b, 0x28, 0x02, 0x00, 0x22, + 0x04, 0x41, 0x01, 0x20, 0x02, 0x74, 0x22, 0x07, 0x71, 0x45, 0x04, 0x40, + 0x20, 0x01, 0x20, 0x03, 0x36, 0x02, 0x00, 0x41, 0xf4, 0x1b, 0x20, 0x04, + 0x20, 0x07, 0x72, 0x36, 0x02, 0x00, 0x20, 0x03, 0x41, 0x18, 0x6a, 0x20, + 0x01, 0x36, 0x02, 0x00, 0x20, 0x03, 0x20, 0x03, 0x36, 0x02, 0x08, 0x20, + 0x03, 0x20, 0x03, 0x36, 0x02, 0x0c, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x41, + 0x00, 0x41, 0x19, 0x20, 0x02, 0x41, 0x01, 0x76, 0x6b, 0x20, 0x02, 0x41, + 0x1f, 0x46, 0x1b, 0x74, 0x21, 0x02, 0x20, 0x01, 0x28, 0x02, 0x00, 0x21, + 0x01, 0x02, 0x40, 0x03, 0x40, 0x20, 0x01, 0x22, 0x04, 0x28, 0x02, 0x04, + 0x41, 0x78, 0x71, 0x20, 0x00, 0x46, 0x0d, 0x01, 0x20, 0x02, 0x41, 0x1d, + 0x76, 0x21, 0x01, 0x20, 0x02, 0x41, 0x01, 0x74, 0x21, 0x02, 0x20, 0x04, + 0x20, 0x01, 0x41, 0x04, 0x71, 0x6a, 0x41, 0x10, 0x6a, 0x22, 0x07, 0x28, + 0x02, 0x00, 0x22, 0x01, 0x0d, 0x00, 0x0b, 0x20, 0x07, 0x20, 0x03, 0x36, + 0x02, 0x00, 0x20, 0x03, 0x20, 0x03, 0x36, 0x02, 0x0c, 0x20, 0x03, 0x41, + 0x18, 0x6a, 0x20, 0x04, 0x36, 0x02, 0x00, 0x20, 0x03, 0x20, 0x03, 0x36, + 0x02, 0x08, 0x0c, 0x01, 0x0b, 0x20, 0x04, 0x28, 0x02, 0x08, 0x21, 0x00, + 0x20, 0x04, 0x20, 0x03, 0x36, 0x02, 0x08, 0x20, 0x00, 0x20, 0x03, 0x36, + 0x02, 0x0c, 0x20, 0x03, 0x41, 0x18, 0x6a, 0x41, 0x00, 0x36, 0x02, 0x00, + 0x20, 0x03, 0x20, 0x00, 0x36, 0x02, 0x08, 0x20, 0x03, 0x20, 0x04, 0x36, + 0x02, 0x0c, 0x0b, 0x41, 0x90, 0x1c, 0x41, 0x90, 0x1c, 0x28, 0x02, 0x00, + 0x41, 0x7f, 0x6a, 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00, 0x0d, 0x00, + 0x41, 0xb8, 0x1f, 0x21, 0x03, 0x03, 0x40, 0x20, 0x03, 0x28, 0x02, 0x00, + 0x22, 0x00, 0x41, 0x08, 0x6a, 0x21, 0x03, 0x20, 0x00, 0x0d, 0x00, 0x0b, + 0x41, 0x90, 0x1c, 0x41, 0x7f, 0x36, 0x02, 0x00, 0x0b, 0x0b, 0x4c, 0x01, + 0x01, 0x7f, 0x02, 0x40, 0x02, 0x7f, 0x20, 0x00, 0x41, 0x18, 0x6c, 0x22, + 0x01, 0x20, 0x00, 0x41, 0x18, 0x72, 0x41, 0x80, 0x80, 0x04, 0x49, 0x0d, + 0x00, 0x1a, 0x20, 0x01, 0x41, 0x7f, 0x20, 0x01, 0x41, 0x18, 0x6e, 0x20, + 0x00, 0x46, 0x1b, 0x0b, 0x22, 0x01, 0x10, 0x14, 0x22, 0x00, 0x45, 0x0d, + 0x00, 0x20, 0x00, 0x41, 0x7c, 0x6a, 0x2d, 0x00, 0x00, 0x41, 0x03, 0x71, + 0x45, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x00, 0x20, 0x01, 0x10, 0x3a, 0x0b, + 0x20, 0x00, 0x0b, 0x5d, 0x02, 0x02, 0x7f, 0x02, 0x7e, 0x23, 0x00, 0x41, + 0x10, 0x6b, 0x22, 0x01, 0x24, 0x00, 0x02, 0x40, 0x41, 0xa0, 0x09, 0x28, + 0x02, 0x00, 0x42, 0x01, 0x20, 0x01, 0x41, 0x08, 0x6a, 0x10, 0x06, 0x22, + 0x02, 0x04, 0x40, 0x41, 0xe0, 0x1f, 0x20, 0x02, 0x36, 0x02, 0x00, 0x0c, + 0x01, 0x0b, 0x20, 0x00, 0x20, 0x01, 0x29, 0x03, 0x08, 0x22, 0x03, 0x42, + 0x80, 0x94, 0xeb, 0xdc, 0x03, 0x80, 0x22, 0x04, 0x37, 0x03, 0x00, 0x20, + 0x00, 0x20, 0x03, 0x20, 0x04, 0x42, 0x80, 0x94, 0xeb, 0xdc, 0x03, 0x7e, + 0x7d, 0x3e, 0x02, 0x08, 0x0b, 0x20, 0x01, 0x41, 0x10, 0x6a, 0x24, 0x00, + 0x0b, 0x07, 0x00, 0x20, 0x00, 0x10, 0x07, 0x00, 0x0b, 0x19, 0x00, 0x20, + 0x00, 0x10, 0x08, 0x22, 0x00, 0x45, 0x04, 0x40, 0x41, 0x00, 0x0f, 0x0b, + 0x41, 0xe0, 0x1f, 0x20, 0x00, 0x36, 0x02, 0x00, 0x41, 0x7f, 0x0b, 0x54, + 0x01, 0x01, 0x7f, 0x23, 0x00, 0x41, 0x10, 0x6b, 0x22, 0x02, 0x24, 0x00, + 0x20, 0x02, 0x41, 0x01, 0x36, 0x02, 0x0c, 0x20, 0x02, 0x20, 0x01, 0x36, + 0x02, 0x08, 0x02, 0x7f, 0x20, 0x00, 0x20, 0x02, 0x41, 0x08, 0x6a, 0x41, + 0x01, 0x20, 0x02, 0x41, 0x04, 0x6a, 0x10, 0x09, 0x22, 0x00, 0x04, 0x40, + 0x41, 0xe0, 0x1f, 0x41, 0x08, 0x20, 0x00, 0x20, 0x00, 0x41, 0xcc, 0x00, + 0x46, 0x1b, 0x36, 0x02, 0x00, 0x41, 0x7f, 0x0c, 0x01, 0x0b, 0x20, 0x02, + 0x28, 0x02, 0x04, 0x0b, 0x20, 0x02, 0x41, 0x10, 0x6a, 0x24, 0x00, 0x0b, + 0xaa, 0x01, 0x02, 0x02, 0x7f, 0x01, 0x7e, 0x23, 0x00, 0x41, 0x20, 0x6b, + 0x22, 0x03, 0x24, 0x00, 0x02, 0x40, 0x20, 0x00, 0x20, 0x03, 0x41, 0x08, + 0x6a, 0x10, 0x0a, 0x22, 0x02, 0x04, 0x40, 0x41, 0xe0, 0x1f, 0x20, 0x02, + 0x36, 0x02, 0x00, 0x41, 0x7f, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x20, 0x03, + 0x2d, 0x00, 0x08, 0x41, 0x03, 0x47, 0x04, 0x40, 0x41, 0xe0, 0x1f, 0x41, + 0x36, 0x36, 0x02, 0x00, 0x41, 0x7f, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x20, + 0x03, 0x29, 0x03, 0x18, 0x22, 0x04, 0x42, 0x02, 0x83, 0x42, 0x02, 0x52, + 0x04, 0x40, 0x41, 0xe0, 0x1f, 0x41, 0xcc, 0x00, 0x36, 0x02, 0x00, 0x41, + 0x7f, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x41, 0x7f, 0x21, 0x02, 0x20, 0x00, + 0x41, 0x01, 0x20, 0x01, 0x20, 0x01, 0x10, 0x38, 0x41, 0x00, 0x20, 0x04, + 0x42, 0xbe, 0xfd, 0xff, 0x7d, 0x83, 0x20, 0x04, 0x41, 0x00, 0x20, 0x03, + 0x41, 0x04, 0x6a, 0x10, 0x0b, 0x22, 0x00, 0x04, 0x40, 0x41, 0xe0, 0x1f, + 0x20, 0x00, 0x36, 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x28, 0x02, + 0x04, 0x21, 0x02, 0x0c, 0x00, 0x0b, 0x20, 0x03, 0x41, 0x20, 0x6a, 0x24, + 0x00, 0x20, 0x02, 0x0b, 0x54, 0x01, 0x02, 0x7f, 0x23, 0x00, 0x41, 0x20, + 0x6b, 0x22, 0x01, 0x24, 0x00, 0x20, 0x01, 0x41, 0x10, 0x6a, 0x20, 0x00, + 0x10, 0x1d, 0x41, 0x7f, 0x21, 0x00, 0x02, 0x40, 0x20, 0x01, 0x28, 0x02, + 0x10, 0x22, 0x02, 0x41, 0x7f, 0x46, 0x04, 0x40, 0x41, 0xe0, 0x1f, 0x41, + 0xcc, 0x00, 0x36, 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x01, 0x28, 0x02, + 0x14, 0x21, 0x00, 0x20, 0x01, 0x41, 0x00, 0x36, 0x02, 0x00, 0x20, 0x02, + 0x20, 0x00, 0x10, 0x1b, 0x21, 0x00, 0x0b, 0x20, 0x01, 0x41, 0x20, 0x6a, + 0x24, 0x00, 0x20, 0x00, 0x0b, 0x94, 0x04, 0x01, 0x0e, 0x7f, 0x02, 0x40, + 0x02, 0x40, 0x02, 0x40, 0x41, 0xe4, 0x1f, 0x28, 0x02, 0x00, 0x22, 0x03, + 0x45, 0x0d, 0x00, 0x20, 0x03, 0x10, 0x1e, 0x41, 0xe4, 0x1f, 0x28, 0x02, + 0x00, 0x22, 0x03, 0x10, 0x1e, 0x20, 0x01, 0x45, 0x04, 0x40, 0x41, 0x7f, + 0x21, 0x06, 0x0c, 0x03, 0x0b, 0x20, 0x03, 0x28, 0x02, 0x0c, 0x22, 0x0b, + 0x45, 0x04, 0x40, 0x41, 0x7f, 0x21, 0x06, 0x0c, 0x02, 0x0b, 0x20, 0x03, + 0x28, 0x02, 0x04, 0x21, 0x0c, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x22, 0x09, + 0x41, 0x52, 0x6a, 0x22, 0x0d, 0x41, 0x01, 0x4b, 0x21, 0x0e, 0x41, 0x7f, + 0x21, 0x06, 0x03, 0x40, 0x20, 0x0c, 0x20, 0x0a, 0x41, 0x18, 0x6c, 0x6a, + 0x22, 0x07, 0x28, 0x02, 0x00, 0x22, 0x04, 0x10, 0x38, 0x21, 0x03, 0x02, + 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, + 0x0e, 0x45, 0x04, 0x40, 0x20, 0x0d, 0x41, 0x01, 0x6b, 0x45, 0x0d, 0x01, + 0x20, 0x01, 0x2d, 0x00, 0x01, 0x22, 0x02, 0x45, 0x0d, 0x01, 0x20, 0x02, + 0x41, 0x2f, 0x46, 0x0d, 0x01, 0x0b, 0x20, 0x03, 0x41, 0x02, 0x4f, 0x04, + 0x40, 0x20, 0x04, 0x2d, 0x00, 0x00, 0x22, 0x02, 0x41, 0x2e, 0x47, 0x0d, + 0x03, 0x41, 0x2e, 0x21, 0x02, 0x20, 0x04, 0x2d, 0x00, 0x01, 0x41, 0x2f, + 0x47, 0x0d, 0x03, 0x20, 0x03, 0x41, 0x7e, 0x6a, 0x21, 0x03, 0x20, 0x04, + 0x41, 0x02, 0x6a, 0x21, 0x04, 0x0c, 0x02, 0x0b, 0x20, 0x03, 0x41, 0x01, + 0x47, 0x0d, 0x00, 0x20, 0x04, 0x41, 0x01, 0x6a, 0x20, 0x04, 0x20, 0x04, + 0x2d, 0x00, 0x00, 0x22, 0x03, 0x41, 0x2e, 0x46, 0x1b, 0x21, 0x04, 0x20, + 0x03, 0x41, 0x2e, 0x47, 0x21, 0x03, 0x0c, 0x01, 0x0b, 0x20, 0x04, 0x45, + 0x0d, 0x06, 0x0b, 0x20, 0x09, 0x41, 0x2f, 0x47, 0x04, 0x40, 0x41, 0x00, + 0x21, 0x02, 0x20, 0x03, 0x45, 0x0d, 0x03, 0x0b, 0x20, 0x03, 0x45, 0x04, + 0x40, 0x41, 0x00, 0x21, 0x02, 0x0c, 0x02, 0x0b, 0x20, 0x04, 0x2d, 0x00, + 0x00, 0x21, 0x02, 0x0b, 0x20, 0x09, 0x20, 0x02, 0x41, 0xff, 0x01, 0x71, + 0x47, 0x0d, 0x02, 0x41, 0x01, 0x21, 0x02, 0x03, 0x40, 0x20, 0x02, 0x20, + 0x03, 0x46, 0x04, 0x40, 0x20, 0x03, 0x21, 0x02, 0x0c, 0x02, 0x0b, 0x20, + 0x02, 0x20, 0x04, 0x6a, 0x21, 0x08, 0x20, 0x01, 0x20, 0x02, 0x6a, 0x20, + 0x02, 0x41, 0x01, 0x6a, 0x21, 0x02, 0x2d, 0x00, 0x00, 0x20, 0x08, 0x2d, + 0x00, 0x00, 0x46, 0x0d, 0x00, 0x0b, 0x0c, 0x02, 0x0b, 0x20, 0x04, 0x41, + 0x7f, 0x6a, 0x21, 0x08, 0x20, 0x02, 0x21, 0x03, 0x03, 0x40, 0x20, 0x03, + 0x22, 0x05, 0x04, 0x40, 0x20, 0x05, 0x41, 0x7f, 0x6a, 0x21, 0x03, 0x20, + 0x05, 0x20, 0x08, 0x6a, 0x2d, 0x00, 0x00, 0x41, 0x2f, 0x46, 0x0d, 0x01, + 0x0b, 0x0b, 0x20, 0x01, 0x20, 0x05, 0x6a, 0x2d, 0x00, 0x00, 0x22, 0x03, + 0x41, 0x2f, 0x46, 0x0d, 0x00, 0x20, 0x03, 0x0d, 0x01, 0x0b, 0x20, 0x07, + 0x29, 0x03, 0x08, 0x42, 0x7f, 0x85, 0x42, 0x80, 0xc0, 0x00, 0x83, 0x42, + 0x00, 0x52, 0x0d, 0x00, 0x20, 0x07, 0x29, 0x03, 0x10, 0x42, 0x7f, 0x85, + 0x42, 0x00, 0x83, 0x42, 0x00, 0x52, 0x0d, 0x00, 0x20, 0x07, 0x28, 0x02, + 0x04, 0x21, 0x06, 0x20, 0x02, 0x21, 0x0f, 0x0b, 0x20, 0x0b, 0x20, 0x0a, + 0x41, 0x01, 0x6a, 0x22, 0x0a, 0x47, 0x0d, 0x00, 0x0b, 0x0c, 0x01, 0x0b, + 0x00, 0x0b, 0x20, 0x01, 0x20, 0x0f, 0x6a, 0x21, 0x02, 0x03, 0x40, 0x20, + 0x02, 0x2d, 0x00, 0x00, 0x22, 0x01, 0x41, 0x2f, 0x46, 0x04, 0x40, 0x20, + 0x02, 0x41, 0x01, 0x6a, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x0b, 0x20, 0x01, + 0x0d, 0x00, 0x41, 0xa4, 0x09, 0x21, 0x02, 0x0b, 0x20, 0x00, 0x20, 0x02, + 0x36, 0x02, 0x04, 0x20, 0x00, 0x20, 0x06, 0x36, 0x02, 0x00, 0x0b, 0x63, + 0x01, 0x02, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x00, + 0x41, 0x00, 0x4c, 0x0d, 0x00, 0x20, 0x00, 0x28, 0x02, 0x0c, 0x22, 0x01, + 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, 0x02, 0x4b, 0x0d, 0x00, 0x41, 0x00, + 0x20, 0x02, 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, 0x00, 0x1b, 0x0d, 0x00, + 0x20, 0x01, 0x45, 0x0d, 0x01, 0x03, 0x40, 0x20, 0x00, 0x28, 0x02, 0x00, + 0x45, 0x0d, 0x01, 0x20, 0x00, 0x41, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x41, + 0x7f, 0x4c, 0x0d, 0x01, 0x20, 0x00, 0x41, 0x18, 0x6a, 0x21, 0x00, 0x20, + 0x01, 0x41, 0x7f, 0x6a, 0x22, 0x01, 0x0d, 0x00, 0x0b, 0x0c, 0x01, 0x0b, + 0x00, 0x0b, 0x0b, 0x4a, 0x01, 0x02, 0x7f, 0x02, 0x40, 0x41, 0x10, 0x10, + 0x14, 0x22, 0x00, 0x04, 0x40, 0x20, 0x00, 0x41, 0x04, 0x10, 0x16, 0x22, + 0x01, 0x36, 0x02, 0x04, 0x20, 0x01, 0x0d, 0x01, 0x20, 0x00, 0x10, 0x15, + 0x0b, 0x41, 0xe4, 0x1f, 0x41, 0x00, 0x36, 0x02, 0x00, 0x00, 0x0b, 0x20, + 0x00, 0x42, 0x04, 0x37, 0x02, 0x08, 0x20, 0x00, 0x41, 0x01, 0x36, 0x02, + 0x00, 0x20, 0x00, 0x10, 0x1e, 0x41, 0xe4, 0x1f, 0x20, 0x00, 0x36, 0x02, + 0x00, 0x20, 0x00, 0x10, 0x1e, 0x0b, 0xfd, 0x01, 0x01, 0x05, 0x7f, 0x23, + 0x00, 0x41, 0x20, 0x6b, 0x22, 0x04, 0x24, 0x00, 0x41, 0xe4, 0x1f, 0x28, + 0x02, 0x00, 0x10, 0x1e, 0x41, 0x7f, 0x21, 0x06, 0x02, 0x40, 0x20, 0x01, + 0x45, 0x0d, 0x00, 0x41, 0xe4, 0x1f, 0x28, 0x02, 0x00, 0x22, 0x02, 0x10, + 0x1e, 0x20, 0x00, 0x41, 0x00, 0x48, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x02, + 0x28, 0x02, 0x0c, 0x22, 0x05, 0x20, 0x02, 0x28, 0x02, 0x08, 0x47, 0x04, + 0x40, 0x20, 0x02, 0x28, 0x02, 0x04, 0x21, 0x03, 0x0c, 0x01, 0x0b, 0x20, + 0x05, 0x41, 0x01, 0x74, 0x10, 0x16, 0x22, 0x03, 0x45, 0x0d, 0x01, 0x20, + 0x03, 0x20, 0x02, 0x28, 0x02, 0x04, 0x20, 0x02, 0x28, 0x02, 0x0c, 0x41, + 0x18, 0x6c, 0x10, 0x39, 0x1a, 0x20, 0x02, 0x28, 0x02, 0x04, 0x10, 0x15, + 0x20, 0x02, 0x20, 0x03, 0x36, 0x02, 0x04, 0x20, 0x02, 0x20, 0x02, 0x28, + 0x02, 0x08, 0x41, 0x01, 0x74, 0x36, 0x02, 0x08, 0x20, 0x02, 0x28, 0x02, + 0x0c, 0x21, 0x05, 0x0b, 0x20, 0x02, 0x20, 0x05, 0x41, 0x01, 0x6a, 0x36, + 0x02, 0x0c, 0x20, 0x01, 0x10, 0x37, 0x21, 0x01, 0x20, 0x03, 0x20, 0x05, + 0x41, 0x18, 0x6c, 0x6a, 0x22, 0x03, 0x20, 0x00, 0x36, 0x02, 0x04, 0x20, + 0x03, 0x20, 0x01, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x04, 0x41, 0x08, + 0x6a, 0x10, 0x0a, 0x22, 0x00, 0x04, 0x40, 0x41, 0xe0, 0x1f, 0x20, 0x00, + 0x36, 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x20, 0x04, 0x29, 0x03, + 0x10, 0x37, 0x03, 0x08, 0x20, 0x03, 0x20, 0x04, 0x29, 0x03, 0x18, 0x37, + 0x03, 0x10, 0x20, 0x02, 0x10, 0x1e, 0x20, 0x02, 0x10, 0x1e, 0x41, 0x00, + 0x21, 0x06, 0x41, 0xe4, 0x1f, 0x20, 0x02, 0x36, 0x02, 0x00, 0x0b, 0x20, + 0x04, 0x41, 0x20, 0x6a, 0x24, 0x00, 0x20, 0x06, 0x0b, 0x36, 0x00, 0x02, + 0x40, 0x20, 0x00, 0x41, 0xff, 0xff, 0x03, 0x71, 0x0d, 0x00, 0x20, 0x00, + 0x41, 0x7f, 0x4c, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x10, 0x76, 0x40, 0x00, + 0x22, 0x00, 0x41, 0x7f, 0x46, 0x04, 0x40, 0x41, 0xe0, 0x1f, 0x41, 0x30, + 0x36, 0x02, 0x00, 0x41, 0x7f, 0x0f, 0x0b, 0x20, 0x00, 0x41, 0x10, 0x74, + 0x0f, 0x0b, 0x00, 0x0b, 0x21, 0x01, 0x01, 0x7f, 0x23, 0x00, 0x41, 0x10, + 0x6b, 0x22, 0x02, 0x24, 0x00, 0x20, 0x02, 0x20, 0x01, 0x36, 0x02, 0x0c, + 0x20, 0x00, 0x20, 0x01, 0x10, 0x25, 0x20, 0x02, 0x41, 0x10, 0x6a, 0x24, + 0x00, 0x0b, 0x9e, 0x02, 0x01, 0x03, 0x7f, 0x20, 0x00, 0x45, 0x04, 0x40, + 0x41, 0xa0, 0x29, 0x28, 0x02, 0x00, 0x04, 0x40, 0x41, 0xa0, 0x29, 0x28, + 0x02, 0x00, 0x10, 0x23, 0x21, 0x01, 0x0b, 0x41, 0x98, 0x2a, 0x28, 0x02, + 0x00, 0x04, 0x40, 0x41, 0x98, 0x2a, 0x28, 0x02, 0x00, 0x10, 0x23, 0x20, + 0x01, 0x72, 0x21, 0x01, 0x0b, 0x41, 0xec, 0x1f, 0x28, 0x02, 0x00, 0x22, + 0x00, 0x04, 0x40, 0x03, 0x40, 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, 0x00, + 0x28, 0x02, 0x18, 0x47, 0x04, 0x40, 0x20, 0x00, 0x41, 0x00, 0x41, 0x00, + 0x20, 0x00, 0x28, 0x02, 0x20, 0x11, 0x00, 0x00, 0x1a, 0x02, 0x7f, 0x41, + 0x7f, 0x20, 0x00, 0x28, 0x02, 0x14, 0x45, 0x0d, 0x00, 0x1a, 0x20, 0x00, + 0x28, 0x02, 0x04, 0x22, 0x02, 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, 0x03, + 0x47, 0x04, 0x40, 0x20, 0x00, 0x20, 0x02, 0x20, 0x03, 0x6b, 0xac, 0x41, + 0x00, 0x20, 0x00, 0x28, 0x02, 0x24, 0x11, 0x03, 0x00, 0x1a, 0x0b, 0x20, + 0x00, 0x41, 0x00, 0x36, 0x02, 0x18, 0x20, 0x00, 0x42, 0x00, 0x37, 0x03, + 0x10, 0x20, 0x00, 0x42, 0x00, 0x37, 0x02, 0x04, 0x41, 0x00, 0x0b, 0x20, + 0x01, 0x72, 0x21, 0x01, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x34, 0x22, 0x00, + 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x01, 0x0f, 0x0b, 0x02, 0x40, 0x20, 0x00, + 0x28, 0x02, 0x14, 0x20, 0x00, 0x28, 0x02, 0x18, 0x46, 0x0d, 0x00, 0x20, + 0x00, 0x41, 0x00, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, 0x20, 0x11, 0x00, + 0x00, 0x1a, 0x20, 0x00, 0x28, 0x02, 0x14, 0x0d, 0x00, 0x41, 0x7f, 0x0f, + 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, 0x01, 0x20, 0x00, 0x28, 0x02, + 0x08, 0x22, 0x02, 0x47, 0x04, 0x40, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, + 0x6b, 0xac, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, 0x24, 0x11, 0x03, 0x00, + 0x1a, 0x0b, 0x20, 0x00, 0x41, 0x00, 0x36, 0x02, 0x18, 0x20, 0x00, 0x42, + 0x00, 0x37, 0x03, 0x10, 0x20, 0x00, 0x42, 0x00, 0x37, 0x02, 0x04, 0x41, + 0x00, 0x0b, 0x84, 0x01, 0x01, 0x04, 0x7f, 0x41, 0x88, 0x20, 0x28, 0x02, + 0x00, 0x22, 0x02, 0x45, 0x04, 0x40, 0x41, 0x88, 0x20, 0x41, 0xf0, 0x1f, + 0x36, 0x02, 0x00, 0x41, 0xf0, 0x1f, 0x21, 0x02, 0x0b, 0x02, 0x40, 0x02, + 0x40, 0x03, 0x40, 0x20, 0x00, 0x20, 0x01, 0x41, 0xb0, 0x09, 0x6a, 0x2d, + 0x00, 0x00, 0x47, 0x04, 0x40, 0x41, 0xcd, 0x00, 0x21, 0x03, 0x20, 0x01, + 0x41, 0x01, 0x6a, 0x22, 0x01, 0x41, 0xcd, 0x00, 0x47, 0x0d, 0x01, 0x0c, + 0x02, 0x0b, 0x0b, 0x20, 0x01, 0x22, 0x03, 0x0d, 0x00, 0x41, 0x80, 0x0a, + 0x21, 0x00, 0x0c, 0x01, 0x0b, 0x41, 0x80, 0x0a, 0x21, 0x01, 0x03, 0x40, + 0x20, 0x01, 0x2d, 0x00, 0x00, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x22, 0x00, + 0x21, 0x01, 0x0d, 0x00, 0x20, 0x00, 0x21, 0x01, 0x20, 0x03, 0x41, 0x7f, + 0x6a, 0x22, 0x03, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x02, 0x28, 0x02, 0x14, + 0x1a, 0x20, 0x00, 0x0b, 0xdd, 0x02, 0x01, 0x03, 0x7f, 0x23, 0x00, 0x41, + 0xd0, 0x01, 0x6b, 0x22, 0x02, 0x24, 0x00, 0x20, 0x02, 0x20, 0x01, 0x36, + 0x02, 0xcc, 0x01, 0x20, 0x02, 0x41, 0xc0, 0x01, 0x6a, 0x42, 0x00, 0x37, + 0x03, 0x00, 0x20, 0x02, 0x41, 0xb8, 0x01, 0x6a, 0x42, 0x00, 0x37, 0x03, + 0x00, 0x20, 0x02, 0x41, 0xb0, 0x01, 0x6a, 0x42, 0x00, 0x37, 0x03, 0x00, + 0x20, 0x02, 0x42, 0x00, 0x37, 0x03, 0xa8, 0x01, 0x20, 0x02, 0x42, 0x00, + 0x37, 0x03, 0xa0, 0x01, 0x20, 0x02, 0x20, 0x01, 0x36, 0x02, 0xc8, 0x01, + 0x41, 0x00, 0x20, 0x00, 0x20, 0x02, 0x41, 0xc8, 0x01, 0x6a, 0x20, 0x02, + 0x41, 0xd0, 0x00, 0x6a, 0x20, 0x02, 0x41, 0xa0, 0x01, 0x6a, 0x10, 0x26, + 0x41, 0x00, 0x4e, 0x04, 0x40, 0x41, 0xb0, 0x28, 0x28, 0x02, 0x00, 0x21, + 0x03, 0x41, 0xec, 0x28, 0x28, 0x02, 0x00, 0x41, 0x00, 0x4c, 0x04, 0x40, + 0x41, 0xb0, 0x28, 0x20, 0x03, 0x41, 0x5f, 0x71, 0x36, 0x02, 0x00, 0x0b, + 0x02, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x41, 0xdc, 0x28, 0x28, 0x02, 0x00, + 0x45, 0x04, 0x40, 0x41, 0xdc, 0x28, 0x41, 0xd0, 0x00, 0x36, 0x02, 0x00, + 0x41, 0xc8, 0x28, 0x41, 0x00, 0x36, 0x02, 0x00, 0x41, 0xc0, 0x28, 0x42, + 0x00, 0x37, 0x03, 0x00, 0x41, 0xd8, 0x28, 0x28, 0x02, 0x00, 0x21, 0x04, + 0x41, 0xd8, 0x28, 0x20, 0x02, 0x36, 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x41, + 0xc0, 0x28, 0x28, 0x02, 0x00, 0x0d, 0x01, 0x0b, 0x41, 0x7f, 0x41, 0xb0, + 0x28, 0x10, 0x31, 0x0d, 0x01, 0x1a, 0x0b, 0x41, 0xb0, 0x28, 0x20, 0x00, + 0x20, 0x02, 0x41, 0xc8, 0x01, 0x6a, 0x20, 0x02, 0x41, 0xd0, 0x00, 0x6a, + 0x20, 0x02, 0x41, 0xa0, 0x01, 0x6a, 0x10, 0x26, 0x0b, 0x21, 0x01, 0x20, + 0x04, 0x04, 0x7f, 0x41, 0xb0, 0x28, 0x41, 0x00, 0x41, 0x00, 0x41, 0xd0, + 0x28, 0x28, 0x02, 0x00, 0x11, 0x00, 0x00, 0x1a, 0x41, 0xdc, 0x28, 0x41, + 0x00, 0x36, 0x02, 0x00, 0x41, 0xd8, 0x28, 0x20, 0x04, 0x36, 0x02, 0x00, + 0x41, 0xc8, 0x28, 0x41, 0x00, 0x36, 0x02, 0x00, 0x41, 0xc0, 0x28, 0x41, + 0x00, 0x36, 0x02, 0x00, 0x41, 0xc4, 0x28, 0x28, 0x02, 0x00, 0x21, 0x00, + 0x41, 0xc4, 0x28, 0x41, 0x00, 0x36, 0x02, 0x00, 0x41, 0x00, 0x05, 0x20, + 0x01, 0x0b, 0x1a, 0x41, 0xb0, 0x28, 0x41, 0xb0, 0x28, 0x28, 0x02, 0x00, + 0x20, 0x03, 0x41, 0x20, 0x71, 0x72, 0x36, 0x02, 0x00, 0x0b, 0x20, 0x02, + 0x41, 0xd0, 0x01, 0x6a, 0x24, 0x00, 0x0b, 0xc7, 0x45, 0x03, 0x1d, 0x7f, + 0x02, 0x7e, 0x02, 0x7c, 0x23, 0x00, 0x41, 0xf0, 0x06, 0x6b, 0x22, 0x09, + 0x24, 0x00, 0x20, 0x09, 0x41, 0xd0, 0x02, 0x6a, 0x41, 0x08, 0x72, 0x21, + 0x1e, 0x20, 0x09, 0x41, 0x37, 0x6a, 0x21, 0x1f, 0x41, 0xae, 0x7d, 0x20, + 0x09, 0x6b, 0x21, 0x20, 0x20, 0x09, 0x41, 0xd0, 0x02, 0x6a, 0x41, 0x09, + 0x72, 0x21, 0x1b, 0x20, 0x09, 0x41, 0x90, 0x05, 0x6a, 0x21, 0x21, 0x20, + 0x09, 0x41, 0xd0, 0x02, 0x6a, 0x21, 0x19, 0x20, 0x09, 0x41, 0x38, 0x6a, + 0x21, 0x15, 0x02, 0x40, 0x02, 0x40, 0x03, 0x40, 0x02, 0x40, 0x20, 0x01, + 0x21, 0x08, 0x20, 0x05, 0x41, 0xff, 0xff, 0xff, 0xff, 0x07, 0x20, 0x13, + 0x6b, 0x4a, 0x0d, 0x00, 0x20, 0x05, 0x20, 0x13, 0x6a, 0x21, 0x13, 0x02, + 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x08, 0x2d, 0x00, 0x00, 0x22, 0x05, + 0x04, 0x40, 0x03, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x05, 0x41, 0xff, + 0x01, 0x71, 0x22, 0x06, 0x04, 0x40, 0x20, 0x06, 0x41, 0x25, 0x47, 0x0d, + 0x02, 0x20, 0x01, 0x22, 0x06, 0x21, 0x05, 0x03, 0x40, 0x20, 0x05, 0x41, + 0x01, 0x6a, 0x2d, 0x00, 0x00, 0x41, 0x25, 0x47, 0x04, 0x40, 0x20, 0x05, + 0x21, 0x01, 0x0c, 0x03, 0x0b, 0x20, 0x06, 0x41, 0x01, 0x6a, 0x21, 0x06, + 0x20, 0x05, 0x2d, 0x00, 0x02, 0x20, 0x05, 0x41, 0x02, 0x6a, 0x22, 0x01, + 0x21, 0x05, 0x41, 0x25, 0x46, 0x0d, 0x00, 0x0b, 0x0c, 0x01, 0x0b, 0x20, + 0x01, 0x21, 0x06, 0x0b, 0x20, 0x06, 0x20, 0x08, 0x6b, 0x22, 0x05, 0x41, + 0xff, 0xff, 0xff, 0xff, 0x07, 0x20, 0x13, 0x6b, 0x22, 0x18, 0x4a, 0x0d, + 0x06, 0x02, 0x40, 0x20, 0x00, 0x45, 0x0d, 0x00, 0x20, 0x00, 0x2d, 0x00, + 0x00, 0x41, 0x20, 0x71, 0x0d, 0x00, 0x20, 0x08, 0x20, 0x05, 0x20, 0x00, + 0x10, 0x33, 0x1a, 0x0b, 0x20, 0x05, 0x0d, 0x07, 0x20, 0x01, 0x41, 0x01, + 0x6a, 0x21, 0x05, 0x02, 0x7f, 0x41, 0x7f, 0x20, 0x01, 0x2c, 0x00, 0x01, + 0x22, 0x0b, 0x41, 0x50, 0x6a, 0x22, 0x07, 0x41, 0x09, 0x4b, 0x0d, 0x00, + 0x1a, 0x20, 0x01, 0x41, 0x03, 0x6a, 0x20, 0x05, 0x20, 0x01, 0x2d, 0x00, + 0x02, 0x41, 0x24, 0x46, 0x22, 0x06, 0x1b, 0x21, 0x05, 0x41, 0x01, 0x20, + 0x1a, 0x20, 0x06, 0x1b, 0x21, 0x1a, 0x20, 0x01, 0x41, 0x03, 0x41, 0x01, + 0x20, 0x06, 0x1b, 0x6a, 0x2c, 0x00, 0x00, 0x21, 0x0b, 0x20, 0x07, 0x41, + 0x7f, 0x20, 0x06, 0x1b, 0x0b, 0x21, 0x06, 0x41, 0x00, 0x21, 0x0c, 0x02, + 0x40, 0x20, 0x0b, 0x41, 0x60, 0x6a, 0x22, 0x01, 0x41, 0x1f, 0x4b, 0x0d, + 0x00, 0x41, 0x01, 0x20, 0x01, 0x74, 0x22, 0x01, 0x41, 0x89, 0xd1, 0x04, + 0x71, 0x45, 0x0d, 0x00, 0x20, 0x05, 0x41, 0x01, 0x6a, 0x21, 0x07, 0x03, + 0x40, 0x20, 0x01, 0x20, 0x0c, 0x72, 0x21, 0x0c, 0x20, 0x07, 0x22, 0x05, + 0x2c, 0x00, 0x00, 0x22, 0x0b, 0x41, 0x60, 0x6a, 0x22, 0x01, 0x41, 0x20, + 0x4f, 0x0d, 0x01, 0x20, 0x05, 0x41, 0x01, 0x6a, 0x21, 0x07, 0x41, 0x01, + 0x20, 0x01, 0x74, 0x22, 0x01, 0x41, 0x89, 0xd1, 0x04, 0x71, 0x0d, 0x00, + 0x0b, 0x0b, 0x02, 0x40, 0x20, 0x0b, 0x41, 0x2a, 0x46, 0x04, 0x40, 0x02, + 0x7f, 0x02, 0x40, 0x20, 0x05, 0x2c, 0x00, 0x01, 0x41, 0x50, 0x6a, 0x22, + 0x01, 0x41, 0x09, 0x4b, 0x0d, 0x00, 0x20, 0x05, 0x2d, 0x00, 0x02, 0x41, + 0x24, 0x47, 0x0d, 0x00, 0x20, 0x04, 0x20, 0x01, 0x41, 0x02, 0x74, 0x6a, + 0x41, 0x0a, 0x36, 0x02, 0x00, 0x20, 0x05, 0x41, 0x03, 0x6a, 0x21, 0x0a, + 0x41, 0x01, 0x21, 0x1a, 0x20, 0x05, 0x2c, 0x00, 0x01, 0x41, 0x03, 0x74, + 0x20, 0x03, 0x6a, 0x41, 0x80, 0x7d, 0x6a, 0x28, 0x02, 0x00, 0x0c, 0x01, + 0x0b, 0x20, 0x1a, 0x0d, 0x06, 0x20, 0x05, 0x41, 0x01, 0x6a, 0x21, 0x0a, + 0x20, 0x00, 0x45, 0x04, 0x40, 0x41, 0x00, 0x21, 0x1a, 0x41, 0x00, 0x21, + 0x0e, 0x0c, 0x03, 0x0b, 0x20, 0x02, 0x20, 0x02, 0x28, 0x02, 0x00, 0x22, + 0x01, 0x41, 0x04, 0x6a, 0x36, 0x02, 0x00, 0x41, 0x00, 0x21, 0x1a, 0x20, + 0x01, 0x28, 0x02, 0x00, 0x0b, 0x22, 0x0e, 0x41, 0x7f, 0x4a, 0x0d, 0x01, + 0x41, 0x00, 0x20, 0x0e, 0x6b, 0x21, 0x0e, 0x20, 0x0c, 0x41, 0x80, 0xc0, + 0x00, 0x72, 0x21, 0x0c, 0x0c, 0x01, 0x0b, 0x41, 0x00, 0x21, 0x0e, 0x20, + 0x0b, 0x41, 0x50, 0x6a, 0x22, 0x07, 0x41, 0x09, 0x4b, 0x04, 0x40, 0x20, + 0x05, 0x21, 0x0a, 0x0c, 0x01, 0x0b, 0x41, 0x00, 0x21, 0x01, 0x03, 0x40, + 0x41, 0x7f, 0x21, 0x0e, 0x20, 0x05, 0x2c, 0x00, 0x01, 0x20, 0x05, 0x41, + 0x01, 0x6a, 0x22, 0x0a, 0x21, 0x05, 0x20, 0x01, 0x41, 0xcc, 0x99, 0xb3, + 0xe6, 0x00, 0x4d, 0x04, 0x40, 0x41, 0x7f, 0x20, 0x01, 0x41, 0x0a, 0x6c, + 0x22, 0x01, 0x20, 0x07, 0x6a, 0x20, 0x07, 0x41, 0xff, 0xff, 0xff, 0xff, + 0x07, 0x20, 0x01, 0x6b, 0x4a, 0x1b, 0x21, 0x0e, 0x0b, 0x20, 0x0e, 0x21, + 0x01, 0x41, 0x50, 0x6a, 0x22, 0x07, 0x41, 0x0a, 0x49, 0x0d, 0x00, 0x0b, + 0x20, 0x0e, 0x41, 0x00, 0x48, 0x0d, 0x07, 0x0b, 0x41, 0x00, 0x21, 0x05, + 0x41, 0x7f, 0x21, 0x0b, 0x02, 0x40, 0x20, 0x0a, 0x2d, 0x00, 0x00, 0x41, + 0x2e, 0x47, 0x04, 0x40, 0x20, 0x0a, 0x21, 0x01, 0x41, 0x00, 0x21, 0x0d, + 0x0c, 0x01, 0x0b, 0x20, 0x0a, 0x2c, 0x00, 0x01, 0x22, 0x07, 0x41, 0x2a, + 0x46, 0x04, 0x40, 0x02, 0x7f, 0x02, 0x40, 0x20, 0x0a, 0x2c, 0x00, 0x02, + 0x41, 0x50, 0x6a, 0x22, 0x01, 0x41, 0x09, 0x4b, 0x0d, 0x00, 0x20, 0x0a, + 0x2d, 0x00, 0x03, 0x41, 0x24, 0x47, 0x0d, 0x00, 0x20, 0x04, 0x20, 0x01, + 0x41, 0x02, 0x74, 0x6a, 0x41, 0x0a, 0x36, 0x02, 0x00, 0x20, 0x0a, 0x41, + 0x04, 0x6a, 0x21, 0x01, 0x20, 0x0a, 0x2c, 0x00, 0x02, 0x41, 0x03, 0x74, + 0x20, 0x03, 0x6a, 0x41, 0x80, 0x7d, 0x6a, 0x28, 0x02, 0x00, 0x0c, 0x01, + 0x0b, 0x20, 0x1a, 0x0d, 0x06, 0x20, 0x0a, 0x41, 0x02, 0x6a, 0x21, 0x01, + 0x41, 0x00, 0x20, 0x00, 0x45, 0x0d, 0x00, 0x1a, 0x20, 0x02, 0x20, 0x02, + 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, 0x04, 0x6a, 0x36, 0x02, 0x00, 0x20, + 0x07, 0x28, 0x02, 0x00, 0x0b, 0x22, 0x0b, 0x41, 0x7f, 0x73, 0x41, 0x1f, + 0x76, 0x21, 0x0d, 0x0c, 0x01, 0x0b, 0x20, 0x0a, 0x41, 0x01, 0x6a, 0x21, + 0x01, 0x20, 0x07, 0x41, 0x50, 0x6a, 0x22, 0x10, 0x41, 0x09, 0x4b, 0x04, + 0x40, 0x41, 0x01, 0x21, 0x0d, 0x41, 0x00, 0x21, 0x0b, 0x0c, 0x01, 0x0b, + 0x41, 0x00, 0x21, 0x0a, 0x20, 0x01, 0x21, 0x07, 0x03, 0x40, 0x41, 0x7f, + 0x21, 0x0b, 0x20, 0x0a, 0x41, 0xcc, 0x99, 0xb3, 0xe6, 0x00, 0x4d, 0x04, + 0x40, 0x41, 0x7f, 0x20, 0x0a, 0x41, 0x0a, 0x6c, 0x22, 0x01, 0x20, 0x10, + 0x6a, 0x20, 0x10, 0x41, 0xff, 0xff, 0xff, 0xff, 0x07, 0x20, 0x01, 0x6b, + 0x4a, 0x1b, 0x21, 0x0b, 0x0b, 0x41, 0x01, 0x21, 0x0d, 0x20, 0x07, 0x2c, + 0x00, 0x01, 0x20, 0x07, 0x41, 0x01, 0x6a, 0x22, 0x01, 0x21, 0x07, 0x20, + 0x0b, 0x21, 0x0a, 0x41, 0x50, 0x6a, 0x22, 0x10, 0x41, 0x0a, 0x49, 0x0d, + 0x00, 0x0b, 0x0b, 0x03, 0x40, 0x20, 0x05, 0x21, 0x07, 0x20, 0x01, 0x2c, + 0x00, 0x00, 0x41, 0xbf, 0x7f, 0x6a, 0x22, 0x05, 0x41, 0x39, 0x4b, 0x0d, + 0x04, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, 0x07, 0x41, 0x3a, + 0x6c, 0x20, 0x05, 0x6a, 0x41, 0xc0, 0x16, 0x6a, 0x2d, 0x00, 0x00, 0x22, + 0x05, 0x41, 0x7f, 0x6a, 0x41, 0x08, 0x49, 0x0d, 0x00, 0x0b, 0x20, 0x05, + 0x45, 0x0d, 0x03, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x05, 0x41, + 0x1b, 0x46, 0x04, 0x40, 0x20, 0x06, 0x41, 0x7f, 0x4c, 0x0d, 0x01, 0x0c, + 0x07, 0x0b, 0x20, 0x06, 0x41, 0x00, 0x48, 0x0d, 0x01, 0x20, 0x04, 0x20, + 0x06, 0x41, 0x02, 0x74, 0x6a, 0x20, 0x05, 0x36, 0x02, 0x00, 0x20, 0x09, + 0x20, 0x03, 0x20, 0x06, 0x41, 0x03, 0x74, 0x6a, 0x29, 0x03, 0x00, 0x37, + 0x03, 0x38, 0x0b, 0x41, 0x00, 0x21, 0x05, 0x20, 0x00, 0x45, 0x0d, 0x09, + 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x45, 0x04, 0x40, 0x41, 0x00, 0x21, 0x13, + 0x0c, 0x0b, 0x0b, 0x20, 0x09, 0x41, 0x38, 0x6a, 0x20, 0x05, 0x20, 0x02, + 0x10, 0x27, 0x0b, 0x20, 0x0c, 0x41, 0xff, 0xff, 0x7b, 0x71, 0x22, 0x06, + 0x20, 0x0c, 0x20, 0x0c, 0x41, 0x80, 0xc0, 0x00, 0x71, 0x1b, 0x21, 0x0f, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x01, 0x41, 0x7f, 0x6a, 0x2c, + 0x00, 0x00, 0x22, 0x05, 0x41, 0x5f, 0x71, 0x20, 0x05, 0x20, 0x05, 0x41, + 0x0f, 0x71, 0x41, 0x03, 0x46, 0x1b, 0x20, 0x05, 0x20, 0x07, 0x1b, 0x22, + 0x11, 0x41, 0xbf, 0x7f, 0x6a, 0x22, 0x05, 0x41, 0x37, 0x4b, 0x0d, 0x00, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x02, 0x7f, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x7f, 0x02, 0x40, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x05, + 0x41, 0x01, 0x6b, 0x0e, 0x37, 0x11, 0x0d, 0x11, 0x10, 0x10, 0x10, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0c, 0x11, + 0x11, 0x11, 0x11, 0x03, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x10, 0x11, 0x08, 0x05, 0x10, 0x10, 0x10, 0x11, 0x05, 0x11, 0x11, 0x11, + 0x09, 0x01, 0x04, 0x02, 0x11, 0x11, 0x0a, 0x11, 0x00, 0x11, 0x11, 0x03, + 0x10, 0x0b, 0x41, 0x00, 0x21, 0x0a, 0x20, 0x09, 0x29, 0x03, 0x38, 0x21, + 0x22, 0x41, 0xa6, 0x16, 0x0c, 0x05, 0x0b, 0x41, 0x00, 0x21, 0x05, 0x20, + 0x07, 0x41, 0xff, 0x01, 0x71, 0x22, 0x06, 0x41, 0x07, 0x4b, 0x0d, 0x19, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, + 0x02, 0x40, 0x20, 0x06, 0x41, 0x01, 0x6b, 0x0e, 0x07, 0x01, 0x02, 0x03, + 0x04, 0x20, 0x05, 0x06, 0x00, 0x0b, 0x20, 0x09, 0x28, 0x02, 0x38, 0x20, + 0x13, 0x36, 0x02, 0x00, 0x0c, 0x1f, 0x0b, 0x20, 0x09, 0x28, 0x02, 0x38, + 0x20, 0x13, 0x36, 0x02, 0x00, 0x0c, 0x1e, 0x0b, 0x20, 0x09, 0x28, 0x02, + 0x38, 0x20, 0x13, 0xac, 0x37, 0x03, 0x00, 0x0c, 0x1d, 0x0b, 0x20, 0x09, + 0x28, 0x02, 0x38, 0x20, 0x13, 0x3b, 0x01, 0x00, 0x0c, 0x1c, 0x0b, 0x20, + 0x09, 0x28, 0x02, 0x38, 0x20, 0x13, 0x3a, 0x00, 0x00, 0x0c, 0x1b, 0x0b, + 0x20, 0x09, 0x28, 0x02, 0x38, 0x20, 0x13, 0x36, 0x02, 0x00, 0x0c, 0x1a, + 0x0b, 0x20, 0x09, 0x28, 0x02, 0x38, 0x20, 0x13, 0xac, 0x37, 0x03, 0x00, + 0x0c, 0x19, 0x0b, 0x20, 0x0b, 0x41, 0x08, 0x20, 0x0b, 0x41, 0x08, 0x4b, + 0x1b, 0x21, 0x0b, 0x20, 0x0f, 0x41, 0x08, 0x72, 0x21, 0x0f, 0x41, 0xf8, + 0x00, 0x21, 0x11, 0x0b, 0x41, 0x00, 0x21, 0x0a, 0x41, 0xa6, 0x16, 0x21, + 0x10, 0x20, 0x09, 0x29, 0x03, 0x38, 0x22, 0x22, 0x50, 0x04, 0x40, 0x20, + 0x15, 0x21, 0x08, 0x0c, 0x04, 0x0b, 0x20, 0x11, 0x41, 0x20, 0x71, 0x21, + 0x06, 0x20, 0x15, 0x21, 0x08, 0x03, 0x40, 0x20, 0x08, 0x41, 0x7f, 0x6a, + 0x22, 0x08, 0x20, 0x22, 0xa7, 0x41, 0x0f, 0x71, 0x41, 0xa0, 0x1b, 0x6a, + 0x2d, 0x00, 0x00, 0x20, 0x06, 0x72, 0x3a, 0x00, 0x00, 0x20, 0x22, 0x42, + 0x04, 0x88, 0x22, 0x22, 0x42, 0x00, 0x52, 0x0d, 0x00, 0x0b, 0x20, 0x0f, + 0x41, 0x08, 0x71, 0x45, 0x0d, 0x03, 0x20, 0x09, 0x29, 0x03, 0x38, 0x50, + 0x0d, 0x03, 0x20, 0x11, 0x41, 0x04, 0x75, 0x41, 0xa6, 0x16, 0x6a, 0x21, + 0x10, 0x41, 0x02, 0x21, 0x0a, 0x0c, 0x03, 0x0b, 0x20, 0x15, 0x21, 0x08, + 0x20, 0x09, 0x29, 0x03, 0x38, 0x22, 0x22, 0x50, 0x45, 0x04, 0x40, 0x03, + 0x40, 0x20, 0x08, 0x41, 0x7f, 0x6a, 0x22, 0x08, 0x20, 0x22, 0xa7, 0x41, + 0x07, 0x71, 0x41, 0x30, 0x72, 0x3a, 0x00, 0x00, 0x20, 0x22, 0x42, 0x03, + 0x88, 0x22, 0x22, 0x42, 0x00, 0x52, 0x0d, 0x00, 0x0b, 0x0b, 0x41, 0x00, + 0x21, 0x0a, 0x41, 0xa6, 0x16, 0x21, 0x10, 0x20, 0x0f, 0x41, 0x08, 0x71, + 0x45, 0x0d, 0x02, 0x20, 0x0b, 0x20, 0x15, 0x20, 0x08, 0x6b, 0x22, 0x06, + 0x41, 0x01, 0x6a, 0x20, 0x0b, 0x20, 0x06, 0x4a, 0x1b, 0x21, 0x0b, 0x0c, + 0x02, 0x0b, 0x20, 0x09, 0x29, 0x03, 0x38, 0x22, 0x22, 0x42, 0x7f, 0x57, + 0x04, 0x40, 0x20, 0x09, 0x42, 0x00, 0x20, 0x22, 0x7d, 0x22, 0x22, 0x37, + 0x03, 0x38, 0x41, 0x01, 0x21, 0x0a, 0x41, 0xa6, 0x16, 0x0c, 0x01, 0x0b, + 0x20, 0x0f, 0x41, 0x80, 0x10, 0x71, 0x04, 0x40, 0x41, 0x01, 0x21, 0x0a, + 0x41, 0xa7, 0x16, 0x0c, 0x01, 0x0b, 0x41, 0xa8, 0x16, 0x41, 0xa6, 0x16, + 0x20, 0x0f, 0x41, 0x01, 0x71, 0x22, 0x0a, 0x1b, 0x0b, 0x21, 0x10, 0x02, + 0x40, 0x20, 0x22, 0x42, 0x80, 0x80, 0x80, 0x80, 0x10, 0x54, 0x04, 0x40, + 0x20, 0x22, 0x21, 0x23, 0x20, 0x15, 0x21, 0x08, 0x0c, 0x01, 0x0b, 0x20, + 0x15, 0x21, 0x08, 0x03, 0x40, 0x20, 0x08, 0x41, 0x7f, 0x6a, 0x22, 0x08, + 0x20, 0x22, 0x20, 0x22, 0x42, 0x0a, 0x80, 0x22, 0x23, 0x42, 0x0a, 0x7e, + 0x7d, 0xa7, 0x41, 0x30, 0x72, 0x3a, 0x00, 0x00, 0x20, 0x22, 0x42, 0xff, + 0xff, 0xff, 0xff, 0x9f, 0x01, 0x56, 0x20, 0x23, 0x21, 0x22, 0x0d, 0x00, + 0x0b, 0x0b, 0x20, 0x23, 0xa7, 0x22, 0x05, 0x45, 0x0d, 0x00, 0x03, 0x40, + 0x20, 0x08, 0x41, 0x7f, 0x6a, 0x22, 0x08, 0x20, 0x05, 0x20, 0x05, 0x41, + 0x0a, 0x6e, 0x22, 0x06, 0x41, 0x0a, 0x6c, 0x6b, 0x41, 0x30, 0x72, 0x3a, + 0x00, 0x00, 0x20, 0x05, 0x41, 0x09, 0x4b, 0x20, 0x06, 0x21, 0x05, 0x0d, + 0x00, 0x0b, 0x0b, 0x20, 0x0d, 0x41, 0x00, 0x20, 0x0b, 0x41, 0x00, 0x48, + 0x1b, 0x0d, 0x12, 0x20, 0x0f, 0x41, 0xff, 0xff, 0x7b, 0x71, 0x20, 0x0f, + 0x20, 0x0d, 0x1b, 0x21, 0x0f, 0x20, 0x09, 0x29, 0x03, 0x38, 0x21, 0x22, + 0x02, 0x40, 0x20, 0x0b, 0x0d, 0x00, 0x20, 0x22, 0x50, 0x45, 0x0d, 0x00, + 0x20, 0x15, 0x22, 0x08, 0x21, 0x05, 0x41, 0x00, 0x21, 0x0b, 0x0c, 0x12, + 0x0b, 0x20, 0x0b, 0x20, 0x22, 0x50, 0x20, 0x15, 0x20, 0x08, 0x6b, 0x6a, + 0x22, 0x06, 0x20, 0x0b, 0x20, 0x06, 0x4a, 0x1b, 0x21, 0x0b, 0x0c, 0x0a, + 0x0b, 0x20, 0x09, 0x20, 0x09, 0x29, 0x03, 0x38, 0x3c, 0x00, 0x37, 0x41, + 0x00, 0x21, 0x0a, 0x41, 0xa6, 0x16, 0x21, 0x10, 0x41, 0x01, 0x21, 0x0b, + 0x20, 0x1f, 0x21, 0x08, 0x20, 0x15, 0x21, 0x05, 0x20, 0x06, 0x21, 0x0f, + 0x0c, 0x10, 0x0b, 0x41, 0xe0, 0x1f, 0x28, 0x02, 0x00, 0x10, 0x24, 0x0c, + 0x01, 0x0b, 0x20, 0x09, 0x28, 0x02, 0x38, 0x22, 0x05, 0x41, 0xb0, 0x16, + 0x20, 0x05, 0x1b, 0x0b, 0x21, 0x08, 0x41, 0x00, 0x21, 0x0a, 0x20, 0x08, + 0x20, 0x08, 0x41, 0xff, 0xff, 0xff, 0xff, 0x07, 0x20, 0x0b, 0x20, 0x0b, + 0x41, 0x00, 0x48, 0x1b, 0x22, 0x05, 0x10, 0x3c, 0x22, 0x07, 0x20, 0x08, + 0x6b, 0x20, 0x05, 0x20, 0x07, 0x1b, 0x22, 0x07, 0x6a, 0x21, 0x05, 0x41, + 0xa6, 0x16, 0x21, 0x10, 0x20, 0x0b, 0x41, 0x7f, 0x4c, 0x0d, 0x07, 0x20, + 0x06, 0x21, 0x0f, 0x20, 0x07, 0x21, 0x0b, 0x0c, 0x0d, 0x0b, 0x20, 0x09, + 0x28, 0x02, 0x38, 0x22, 0x08, 0x20, 0x0b, 0x0d, 0x01, 0x1a, 0x41, 0x00, + 0x21, 0x05, 0x0c, 0x02, 0x0b, 0x20, 0x09, 0x41, 0x00, 0x36, 0x02, 0x0c, + 0x20, 0x09, 0x20, 0x09, 0x29, 0x03, 0x38, 0x3e, 0x02, 0x08, 0x20, 0x09, + 0x20, 0x09, 0x41, 0x08, 0x6a, 0x36, 0x02, 0x38, 0x41, 0x7f, 0x21, 0x0b, + 0x20, 0x09, 0x41, 0x08, 0x6a, 0x0b, 0x21, 0x08, 0x41, 0x00, 0x21, 0x05, + 0x20, 0x08, 0x21, 0x06, 0x02, 0x40, 0x03, 0x40, 0x20, 0x06, 0x28, 0x02, + 0x00, 0x22, 0x07, 0x45, 0x0d, 0x01, 0x02, 0x40, 0x20, 0x09, 0x41, 0x04, + 0x6a, 0x20, 0x07, 0x10, 0x3d, 0x22, 0x07, 0x41, 0x00, 0x48, 0x22, 0x0a, + 0x0d, 0x00, 0x20, 0x07, 0x20, 0x0b, 0x20, 0x05, 0x6b, 0x4b, 0x0d, 0x00, + 0x20, 0x06, 0x41, 0x04, 0x6a, 0x21, 0x06, 0x20, 0x0b, 0x20, 0x05, 0x20, + 0x07, 0x6a, 0x22, 0x05, 0x4b, 0x0d, 0x01, 0x0c, 0x02, 0x0b, 0x0b, 0x20, + 0x0a, 0x0d, 0x0e, 0x0b, 0x20, 0x05, 0x41, 0x00, 0x48, 0x0d, 0x0b, 0x0b, + 0x02, 0x40, 0x20, 0x0f, 0x41, 0x80, 0xc0, 0x04, 0x71, 0x22, 0x0a, 0x0d, + 0x00, 0x20, 0x0e, 0x20, 0x05, 0x4c, 0x0d, 0x00, 0x20, 0x09, 0x41, 0x40, + 0x6b, 0x41, 0x20, 0x20, 0x0e, 0x20, 0x05, 0x6b, 0x22, 0x10, 0x41, 0x80, + 0x02, 0x20, 0x10, 0x41, 0x80, 0x02, 0x49, 0x22, 0x07, 0x1b, 0x10, 0x3a, + 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x0b, 0x41, 0x20, 0x71, 0x21, 0x06, + 0x02, 0x40, 0x20, 0x07, 0x45, 0x04, 0x40, 0x20, 0x06, 0x45, 0x21, 0x06, + 0x20, 0x10, 0x21, 0x07, 0x03, 0x40, 0x20, 0x06, 0x41, 0x01, 0x71, 0x04, + 0x40, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, + 0x33, 0x1a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x21, 0x0b, 0x0b, 0x20, 0x0b, + 0x41, 0x20, 0x71, 0x22, 0x0c, 0x45, 0x21, 0x06, 0x20, 0x07, 0x41, 0x80, + 0x7e, 0x6a, 0x22, 0x07, 0x41, 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, + 0x0c, 0x0d, 0x02, 0x20, 0x10, 0x41, 0xff, 0x01, 0x71, 0x21, 0x10, 0x0c, + 0x01, 0x0b, 0x20, 0x06, 0x0d, 0x01, 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, + 0x20, 0x10, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x02, 0x40, 0x20, 0x05, + 0x45, 0x0d, 0x00, 0x41, 0x00, 0x21, 0x06, 0x03, 0x40, 0x20, 0x08, 0x28, + 0x02, 0x00, 0x22, 0x07, 0x45, 0x0d, 0x01, 0x20, 0x09, 0x41, 0x04, 0x6a, + 0x20, 0x07, 0x10, 0x3d, 0x22, 0x07, 0x20, 0x06, 0x6a, 0x22, 0x06, 0x20, + 0x05, 0x4b, 0x0d, 0x01, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, 0x20, 0x71, + 0x45, 0x04, 0x40, 0x20, 0x09, 0x41, 0x04, 0x6a, 0x20, 0x07, 0x20, 0x00, + 0x10, 0x33, 0x1a, 0x0b, 0x20, 0x08, 0x41, 0x04, 0x6a, 0x21, 0x08, 0x20, + 0x06, 0x20, 0x05, 0x49, 0x0d, 0x00, 0x0b, 0x0b, 0x02, 0x40, 0x20, 0x0a, + 0x41, 0x80, 0xc0, 0x00, 0x47, 0x0d, 0x00, 0x20, 0x0e, 0x20, 0x05, 0x4c, + 0x0d, 0x00, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x20, 0x20, 0x0e, 0x20, + 0x05, 0x6b, 0x22, 0x0c, 0x41, 0x80, 0x02, 0x20, 0x0c, 0x41, 0x80, 0x02, + 0x49, 0x22, 0x07, 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, + 0x08, 0x41, 0x20, 0x71, 0x21, 0x06, 0x02, 0x40, 0x20, 0x07, 0x45, 0x04, + 0x40, 0x20, 0x06, 0x45, 0x21, 0x06, 0x20, 0x0c, 0x21, 0x07, 0x03, 0x40, + 0x20, 0x06, 0x41, 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, 0x40, 0x6b, + 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, 0x28, 0x02, + 0x00, 0x21, 0x08, 0x0b, 0x20, 0x08, 0x41, 0x20, 0x71, 0x22, 0x0a, 0x45, + 0x21, 0x06, 0x20, 0x07, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x07, 0x41, 0xff, + 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x0a, 0x0d, 0x02, 0x20, 0x0c, 0x41, + 0xff, 0x01, 0x71, 0x21, 0x0c, 0x0c, 0x01, 0x0b, 0x20, 0x06, 0x0d, 0x01, + 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, 0x0c, 0x20, 0x00, 0x10, 0x33, + 0x1a, 0x0b, 0x20, 0x0e, 0x20, 0x05, 0x20, 0x0e, 0x20, 0x05, 0x4a, 0x1b, + 0x21, 0x05, 0x0c, 0x0b, 0x0b, 0x20, 0x0b, 0x41, 0x7f, 0x4c, 0x41, 0x00, + 0x20, 0x0d, 0x1b, 0x0d, 0x09, 0x20, 0x09, 0x2b, 0x03, 0x38, 0x21, 0x24, + 0x20, 0x09, 0x41, 0x00, 0x36, 0x02, 0xec, 0x02, 0x02, 0x7f, 0x20, 0x24, + 0xbd, 0x42, 0x7f, 0x57, 0x04, 0x40, 0x20, 0x24, 0x9a, 0x21, 0x24, 0x41, + 0x01, 0x21, 0x14, 0x41, 0xb0, 0x1b, 0x0c, 0x01, 0x0b, 0x20, 0x0f, 0x41, + 0x80, 0x10, 0x71, 0x04, 0x40, 0x41, 0x01, 0x21, 0x14, 0x41, 0xb3, 0x1b, + 0x0c, 0x01, 0x0b, 0x41, 0xb6, 0x1b, 0x41, 0xb1, 0x1b, 0x20, 0x0f, 0x41, + 0x01, 0x71, 0x22, 0x14, 0x1b, 0x0b, 0x21, 0x18, 0x02, 0x40, 0x20, 0x24, + 0x99, 0x22, 0x25, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f, + 0x62, 0x20, 0x25, 0x20, 0x25, 0x61, 0x71, 0x45, 0x04, 0x40, 0x20, 0x14, + 0x41, 0x03, 0x6a, 0x21, 0x08, 0x02, 0x40, 0x20, 0x0f, 0x41, 0x80, 0xc0, + 0x00, 0x71, 0x0d, 0x00, 0x20, 0x0e, 0x20, 0x08, 0x4c, 0x0d, 0x00, 0x20, + 0x09, 0x41, 0x40, 0x6b, 0x41, 0x20, 0x20, 0x0e, 0x20, 0x08, 0x6b, 0x22, + 0x0c, 0x41, 0x80, 0x02, 0x20, 0x0c, 0x41, 0x80, 0x02, 0x49, 0x22, 0x05, + 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, 0x20, + 0x71, 0x21, 0x06, 0x02, 0x40, 0x20, 0x05, 0x45, 0x04, 0x40, 0x20, 0x06, + 0x45, 0x21, 0x05, 0x20, 0x0c, 0x21, 0x06, 0x03, 0x40, 0x20, 0x05, 0x41, + 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x80, 0x02, + 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x21, 0x07, + 0x0b, 0x20, 0x07, 0x41, 0x20, 0x71, 0x22, 0x0a, 0x45, 0x21, 0x05, 0x20, + 0x06, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x06, 0x41, 0xff, 0x01, 0x4b, 0x0d, + 0x00, 0x0b, 0x20, 0x0a, 0x0d, 0x02, 0x20, 0x0c, 0x41, 0xff, 0x01, 0x71, + 0x21, 0x0c, 0x0c, 0x01, 0x0b, 0x20, 0x06, 0x0d, 0x01, 0x0b, 0x20, 0x09, + 0x41, 0x40, 0x6b, 0x20, 0x0c, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x20, + 0x00, 0x28, 0x02, 0x00, 0x22, 0x06, 0x41, 0x20, 0x71, 0x04, 0x7f, 0x20, + 0x06, 0x05, 0x20, 0x18, 0x20, 0x14, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, + 0x00, 0x28, 0x02, 0x00, 0x0b, 0x41, 0x20, 0x71, 0x45, 0x04, 0x40, 0x41, + 0xcb, 0x1b, 0x41, 0xcf, 0x1b, 0x20, 0x11, 0x41, 0x20, 0x71, 0x41, 0x05, + 0x76, 0x22, 0x06, 0x1b, 0x41, 0xc3, 0x1b, 0x41, 0xc7, 0x1b, 0x20, 0x06, + 0x1b, 0x20, 0x24, 0x20, 0x24, 0x62, 0x1b, 0x41, 0x03, 0x20, 0x00, 0x10, + 0x33, 0x1a, 0x0b, 0x02, 0x40, 0x20, 0x0f, 0x41, 0x80, 0xc0, 0x04, 0x71, + 0x41, 0x80, 0xc0, 0x00, 0x47, 0x0d, 0x00, 0x20, 0x0e, 0x20, 0x08, 0x4c, + 0x0d, 0x00, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x20, 0x20, 0x0e, 0x20, + 0x08, 0x6b, 0x22, 0x0c, 0x41, 0x80, 0x02, 0x20, 0x0c, 0x41, 0x80, 0x02, + 0x49, 0x22, 0x05, 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, + 0x07, 0x41, 0x20, 0x71, 0x21, 0x06, 0x02, 0x40, 0x20, 0x05, 0x45, 0x04, + 0x40, 0x20, 0x06, 0x45, 0x21, 0x05, 0x20, 0x0c, 0x21, 0x06, 0x03, 0x40, + 0x20, 0x05, 0x41, 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, 0x40, 0x6b, + 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, 0x28, 0x02, + 0x00, 0x21, 0x07, 0x0b, 0x20, 0x07, 0x41, 0x20, 0x71, 0x22, 0x0a, 0x45, + 0x21, 0x05, 0x20, 0x06, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x06, 0x41, 0xff, + 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x0a, 0x0d, 0x02, 0x20, 0x0c, 0x41, + 0xff, 0x01, 0x71, 0x21, 0x0c, 0x0c, 0x01, 0x0b, 0x20, 0x06, 0x0d, 0x01, + 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, 0x0c, 0x20, 0x00, 0x10, 0x33, + 0x1a, 0x0b, 0x20, 0x0e, 0x20, 0x08, 0x20, 0x0e, 0x20, 0x08, 0x4a, 0x1b, + 0x21, 0x05, 0x0c, 0x01, 0x0b, 0x20, 0x24, 0x20, 0x09, 0x41, 0xec, 0x02, + 0x6a, 0x10, 0x3f, 0x22, 0x24, 0x20, 0x24, 0xa0, 0x22, 0x24, 0x44, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x04, 0x40, 0x20, 0x09, + 0x20, 0x09, 0x28, 0x02, 0xec, 0x02, 0x41, 0x7f, 0x6a, 0x36, 0x02, 0xec, + 0x02, 0x0b, 0x20, 0x11, 0x41, 0x20, 0x72, 0x22, 0x0c, 0x41, 0xe1, 0x00, + 0x46, 0x04, 0x40, 0x20, 0x18, 0x41, 0x09, 0x6a, 0x20, 0x18, 0x20, 0x11, + 0x41, 0x20, 0x71, 0x22, 0x0a, 0x1b, 0x21, 0x0c, 0x02, 0x40, 0x20, 0x0b, + 0x41, 0x0b, 0x4b, 0x0d, 0x00, 0x41, 0x0c, 0x20, 0x0b, 0x6b, 0x45, 0x0d, + 0x00, 0x20, 0x0b, 0x41, 0x74, 0x6a, 0x21, 0x05, 0x44, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x40, 0x21, 0x25, 0x03, 0x40, 0x20, 0x25, 0x44, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x40, 0xa2, 0x21, 0x25, 0x20, + 0x05, 0x41, 0x01, 0x6a, 0x22, 0x06, 0x20, 0x05, 0x4f, 0x20, 0x06, 0x21, + 0x05, 0x0d, 0x00, 0x0b, 0x20, 0x0c, 0x2d, 0x00, 0x00, 0x41, 0x2d, 0x46, + 0x04, 0x40, 0x20, 0x25, 0x20, 0x24, 0x9a, 0x20, 0x25, 0xa1, 0xa0, 0x9a, + 0x21, 0x24, 0x0c, 0x01, 0x0b, 0x20, 0x24, 0x20, 0x25, 0xa0, 0x20, 0x25, + 0xa1, 0x21, 0x24, 0x0b, 0x20, 0x19, 0x21, 0x07, 0x02, 0x40, 0x20, 0x09, + 0x28, 0x02, 0xec, 0x02, 0x22, 0x08, 0x20, 0x08, 0x41, 0x1f, 0x75, 0x22, + 0x06, 0x6a, 0x20, 0x06, 0x73, 0x22, 0x05, 0x04, 0x40, 0x41, 0x00, 0x21, + 0x06, 0x03, 0x40, 0x20, 0x06, 0x20, 0x09, 0x6a, 0x41, 0xcf, 0x02, 0x6a, + 0x20, 0x05, 0x20, 0x05, 0x41, 0x0a, 0x6e, 0x22, 0x07, 0x41, 0x0a, 0x6c, + 0x6b, 0x41, 0x30, 0x72, 0x3a, 0x00, 0x00, 0x20, 0x06, 0x41, 0x7f, 0x6a, + 0x21, 0x06, 0x20, 0x05, 0x41, 0x09, 0x4b, 0x20, 0x07, 0x21, 0x05, 0x0d, + 0x00, 0x0b, 0x20, 0x06, 0x20, 0x09, 0x6a, 0x41, 0xd0, 0x02, 0x6a, 0x21, + 0x07, 0x20, 0x06, 0x0d, 0x01, 0x0b, 0x20, 0x07, 0x41, 0x7f, 0x6a, 0x22, + 0x07, 0x41, 0x30, 0x3a, 0x00, 0x00, 0x0b, 0x20, 0x14, 0x41, 0x02, 0x72, + 0x21, 0x0d, 0x20, 0x07, 0x41, 0x7e, 0x6a, 0x22, 0x12, 0x20, 0x11, 0x41, + 0x0f, 0x6a, 0x3a, 0x00, 0x00, 0x20, 0x07, 0x41, 0x7f, 0x6a, 0x41, 0x2d, + 0x41, 0x2b, 0x20, 0x08, 0x41, 0x00, 0x48, 0x1b, 0x3a, 0x00, 0x00, 0x20, + 0x0f, 0x41, 0x08, 0x71, 0x21, 0x07, 0x20, 0x09, 0x41, 0xd0, 0x02, 0x6a, + 0x21, 0x06, 0x03, 0x40, 0x20, 0x06, 0x22, 0x05, 0x02, 0x7f, 0x20, 0x24, + 0x99, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x41, 0x63, 0x04, + 0x40, 0x20, 0x24, 0xaa, 0x0c, 0x01, 0x0b, 0x41, 0x80, 0x80, 0x80, 0x80, + 0x78, 0x0b, 0x22, 0x06, 0x41, 0xa0, 0x1b, 0x6a, 0x2d, 0x00, 0x00, 0x20, + 0x0a, 0x72, 0x3a, 0x00, 0x00, 0x20, 0x24, 0x20, 0x06, 0xb7, 0xa1, 0x44, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x40, 0xa2, 0x21, 0x24, 0x02, + 0x40, 0x20, 0x05, 0x41, 0x01, 0x6a, 0x22, 0x06, 0x20, 0x09, 0x41, 0xd0, + 0x02, 0x6a, 0x6b, 0x41, 0x01, 0x47, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x07, + 0x0d, 0x00, 0x20, 0x0b, 0x41, 0x00, 0x4a, 0x0d, 0x00, 0x20, 0x24, 0x44, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x0d, 0x01, 0x0b, + 0x20, 0x05, 0x41, 0x2e, 0x3a, 0x00, 0x01, 0x20, 0x05, 0x41, 0x02, 0x6a, + 0x21, 0x06, 0x0b, 0x20, 0x24, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x62, 0x0d, 0x00, 0x0b, 0x41, 0x7f, 0x21, 0x05, 0x41, 0xfd, + 0xff, 0xff, 0xff, 0x07, 0x20, 0x0d, 0x20, 0x19, 0x20, 0x12, 0x6b, 0x22, + 0x11, 0x6a, 0x22, 0x07, 0x6b, 0x20, 0x0b, 0x48, 0x0d, 0x01, 0x20, 0x07, + 0x20, 0x0b, 0x41, 0x02, 0x6a, 0x20, 0x06, 0x20, 0x09, 0x41, 0xd0, 0x02, + 0x6a, 0x6b, 0x22, 0x0a, 0x20, 0x06, 0x20, 0x20, 0x6a, 0x20, 0x0b, 0x48, + 0x1b, 0x20, 0x0a, 0x20, 0x0b, 0x1b, 0x22, 0x14, 0x6a, 0x21, 0x08, 0x02, + 0x40, 0x20, 0x0f, 0x41, 0x80, 0xc0, 0x04, 0x71, 0x22, 0x0b, 0x0d, 0x00, + 0x20, 0x0e, 0x20, 0x08, 0x4c, 0x0d, 0x00, 0x20, 0x09, 0x41, 0x40, 0x6b, + 0x41, 0x20, 0x20, 0x0e, 0x20, 0x08, 0x6b, 0x22, 0x0f, 0x41, 0x80, 0x02, + 0x20, 0x0f, 0x41, 0x80, 0x02, 0x49, 0x22, 0x05, 0x1b, 0x10, 0x3a, 0x20, + 0x00, 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, 0x20, 0x71, 0x21, 0x06, 0x02, + 0x40, 0x20, 0x05, 0x45, 0x04, 0x40, 0x20, 0x06, 0x45, 0x21, 0x05, 0x20, + 0x0f, 0x21, 0x06, 0x03, 0x40, 0x20, 0x05, 0x41, 0x01, 0x71, 0x04, 0x40, + 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, + 0x1a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x21, 0x07, 0x0b, 0x20, 0x07, 0x41, + 0x20, 0x71, 0x22, 0x10, 0x45, 0x21, 0x05, 0x20, 0x06, 0x41, 0x80, 0x7e, + 0x6a, 0x22, 0x06, 0x41, 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x10, + 0x0d, 0x02, 0x20, 0x0f, 0x41, 0xff, 0x01, 0x71, 0x21, 0x0f, 0x0c, 0x01, + 0x0b, 0x20, 0x06, 0x0d, 0x01, 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, + 0x0f, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x20, 0x00, 0x2d, 0x00, 0x00, + 0x41, 0x20, 0x71, 0x45, 0x04, 0x40, 0x20, 0x0c, 0x20, 0x0d, 0x20, 0x00, + 0x10, 0x33, 0x1a, 0x0b, 0x02, 0x40, 0x20, 0x0b, 0x41, 0x80, 0x80, 0x04, + 0x47, 0x0d, 0x00, 0x20, 0x0e, 0x20, 0x08, 0x4c, 0x0d, 0x00, 0x20, 0x09, + 0x41, 0x40, 0x6b, 0x41, 0x30, 0x20, 0x0e, 0x20, 0x08, 0x6b, 0x22, 0x10, + 0x41, 0x80, 0x02, 0x20, 0x10, 0x41, 0x80, 0x02, 0x49, 0x22, 0x05, 0x1b, + 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, 0x20, 0x71, + 0x21, 0x06, 0x02, 0x40, 0x20, 0x05, 0x45, 0x04, 0x40, 0x20, 0x06, 0x45, + 0x21, 0x05, 0x20, 0x10, 0x21, 0x06, 0x03, 0x40, 0x20, 0x05, 0x41, 0x01, + 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x80, 0x02, 0x20, + 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x21, 0x07, 0x0b, + 0x20, 0x07, 0x41, 0x20, 0x71, 0x22, 0x0c, 0x45, 0x21, 0x05, 0x20, 0x06, + 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x06, 0x41, 0xff, 0x01, 0x4b, 0x0d, 0x00, + 0x0b, 0x20, 0x0c, 0x0d, 0x02, 0x20, 0x10, 0x41, 0xff, 0x01, 0x71, 0x21, + 0x10, 0x0c, 0x01, 0x0b, 0x20, 0x06, 0x0d, 0x01, 0x0b, 0x20, 0x09, 0x41, + 0x40, 0x6b, 0x20, 0x10, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x20, 0x00, + 0x2d, 0x00, 0x00, 0x41, 0x20, 0x71, 0x45, 0x04, 0x40, 0x20, 0x09, 0x41, + 0xd0, 0x02, 0x6a, 0x20, 0x0a, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x02, + 0x40, 0x20, 0x14, 0x20, 0x0a, 0x6b, 0x22, 0x0c, 0x41, 0x01, 0x48, 0x0d, + 0x00, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x30, 0x20, 0x0c, 0x41, 0x80, + 0x02, 0x20, 0x0c, 0x41, 0x80, 0x02, 0x49, 0x22, 0x05, 0x1b, 0x10, 0x3a, + 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, 0x20, 0x71, 0x21, 0x06, + 0x02, 0x40, 0x20, 0x05, 0x45, 0x04, 0x40, 0x20, 0x06, 0x45, 0x21, 0x05, + 0x20, 0x0c, 0x21, 0x06, 0x03, 0x40, 0x20, 0x05, 0x41, 0x01, 0x71, 0x04, + 0x40, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, + 0x33, 0x1a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x21, 0x07, 0x0b, 0x20, 0x07, + 0x41, 0x20, 0x71, 0x22, 0x0a, 0x45, 0x21, 0x05, 0x20, 0x06, 0x41, 0x80, + 0x7e, 0x6a, 0x22, 0x06, 0x41, 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, + 0x0a, 0x0d, 0x02, 0x20, 0x0c, 0x41, 0xff, 0x01, 0x71, 0x21, 0x0c, 0x0c, + 0x01, 0x0b, 0x20, 0x06, 0x0d, 0x01, 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, + 0x20, 0x0c, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x20, 0x00, 0x2d, 0x00, + 0x00, 0x41, 0x20, 0x71, 0x45, 0x04, 0x40, 0x20, 0x12, 0x20, 0x11, 0x20, + 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x02, 0x40, 0x20, 0x0b, 0x41, 0x80, 0xc0, + 0x00, 0x47, 0x0d, 0x00, 0x20, 0x0e, 0x20, 0x08, 0x4c, 0x0d, 0x00, 0x20, + 0x09, 0x41, 0x40, 0x6b, 0x41, 0x20, 0x20, 0x0e, 0x20, 0x08, 0x6b, 0x22, + 0x0c, 0x41, 0x80, 0x02, 0x20, 0x0c, 0x41, 0x80, 0x02, 0x49, 0x22, 0x05, + 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, 0x20, + 0x71, 0x21, 0x06, 0x02, 0x40, 0x20, 0x05, 0x45, 0x04, 0x40, 0x20, 0x06, + 0x45, 0x21, 0x05, 0x20, 0x0c, 0x21, 0x06, 0x03, 0x40, 0x20, 0x05, 0x41, + 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x80, 0x02, + 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x21, 0x07, + 0x0b, 0x20, 0x07, 0x41, 0x20, 0x71, 0x22, 0x0a, 0x45, 0x21, 0x05, 0x20, + 0x06, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x06, 0x41, 0xff, 0x01, 0x4b, 0x0d, + 0x00, 0x0b, 0x20, 0x0a, 0x0d, 0x02, 0x20, 0x0c, 0x41, 0xff, 0x01, 0x71, + 0x21, 0x0c, 0x0c, 0x01, 0x0b, 0x20, 0x06, 0x0d, 0x01, 0x0b, 0x20, 0x09, + 0x41, 0x40, 0x6b, 0x20, 0x0c, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x20, + 0x0e, 0x20, 0x08, 0x20, 0x0e, 0x20, 0x08, 0x4a, 0x1b, 0x21, 0x05, 0x0c, + 0x01, 0x0b, 0x20, 0x0b, 0x41, 0x00, 0x48, 0x21, 0x06, 0x02, 0x40, 0x20, + 0x24, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x04, + 0x40, 0x20, 0x09, 0x28, 0x02, 0xec, 0x02, 0x21, 0x08, 0x0c, 0x01, 0x0b, + 0x20, 0x09, 0x20, 0x09, 0x28, 0x02, 0xec, 0x02, 0x41, 0x64, 0x6a, 0x22, + 0x08, 0x36, 0x02, 0xec, 0x02, 0x20, 0x24, 0x44, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xb0, 0x41, 0xa2, 0x21, 0x24, 0x0b, 0x41, 0x06, 0x20, 0x0b, + 0x20, 0x06, 0x1b, 0x21, 0x0d, 0x20, 0x09, 0x41, 0xf0, 0x02, 0x6a, 0x20, + 0x21, 0x20, 0x08, 0x41, 0x00, 0x48, 0x1b, 0x22, 0x12, 0x21, 0x07, 0x03, + 0x40, 0x20, 0x07, 0x02, 0x7f, 0x20, 0x24, 0x44, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xf0, 0x41, 0x63, 0x20, 0x24, 0x44, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x66, 0x71, 0x04, 0x40, 0x20, 0x24, 0xab, 0x0c, + 0x01, 0x0b, 0x41, 0x00, 0x0b, 0x22, 0x06, 0x36, 0x02, 0x00, 0x20, 0x07, + 0x41, 0x04, 0x6a, 0x21, 0x07, 0x20, 0x24, 0x20, 0x06, 0xb8, 0xa1, 0x44, + 0x00, 0x00, 0x00, 0x00, 0x65, 0xcd, 0xcd, 0x41, 0xa2, 0x22, 0x24, 0x44, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x0d, 0x00, 0x0b, + 0x02, 0x40, 0x20, 0x08, 0x41, 0x01, 0x48, 0x04, 0x40, 0x20, 0x07, 0x21, + 0x05, 0x20, 0x12, 0x21, 0x06, 0x0c, 0x01, 0x0b, 0x20, 0x12, 0x21, 0x06, + 0x03, 0x40, 0x20, 0x08, 0x41, 0x1d, 0x20, 0x08, 0x41, 0x1d, 0x48, 0x1b, + 0x21, 0x08, 0x02, 0x40, 0x20, 0x07, 0x41, 0x7c, 0x6a, 0x22, 0x05, 0x20, + 0x06, 0x49, 0x0d, 0x00, 0x20, 0x08, 0xad, 0x21, 0x23, 0x42, 0x00, 0x21, + 0x22, 0x03, 0x40, 0x20, 0x05, 0x20, 0x22, 0x42, 0xff, 0xff, 0xff, 0xff, + 0x0f, 0x83, 0x20, 0x05, 0x35, 0x02, 0x00, 0x20, 0x23, 0x86, 0x7c, 0x22, + 0x22, 0x20, 0x22, 0x42, 0x80, 0x94, 0xeb, 0xdc, 0x03, 0x80, 0x22, 0x22, + 0x42, 0x80, 0x94, 0xeb, 0xdc, 0x03, 0x7e, 0x7d, 0x3e, 0x02, 0x00, 0x20, + 0x05, 0x41, 0x7c, 0x6a, 0x22, 0x05, 0x20, 0x06, 0x4f, 0x0d, 0x00, 0x0b, + 0x20, 0x22, 0xa7, 0x22, 0x05, 0x45, 0x0d, 0x00, 0x20, 0x06, 0x41, 0x7c, + 0x6a, 0x22, 0x06, 0x20, 0x05, 0x36, 0x02, 0x00, 0x0b, 0x03, 0x40, 0x20, + 0x07, 0x22, 0x05, 0x20, 0x06, 0x4b, 0x04, 0x40, 0x20, 0x05, 0x41, 0x7c, + 0x6a, 0x22, 0x07, 0x28, 0x02, 0x00, 0x45, 0x0d, 0x01, 0x0b, 0x0b, 0x20, + 0x09, 0x20, 0x09, 0x28, 0x02, 0xec, 0x02, 0x20, 0x08, 0x6b, 0x22, 0x08, + 0x36, 0x02, 0xec, 0x02, 0x20, 0x05, 0x21, 0x07, 0x20, 0x08, 0x41, 0x00, + 0x4a, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x08, 0x41, 0x7f, 0x4c, 0x04, 0x40, + 0x20, 0x0d, 0x41, 0x19, 0x6a, 0x41, 0x09, 0x6e, 0x41, 0x01, 0x6a, 0x21, + 0x0b, 0x03, 0x40, 0x41, 0x00, 0x20, 0x08, 0x6b, 0x22, 0x07, 0x41, 0x09, + 0x20, 0x07, 0x41, 0x09, 0x48, 0x1b, 0x21, 0x0a, 0x02, 0x40, 0x20, 0x06, + 0x20, 0x05, 0x4f, 0x04, 0x40, 0x20, 0x06, 0x20, 0x06, 0x41, 0x04, 0x6a, + 0x20, 0x06, 0x28, 0x02, 0x00, 0x1b, 0x21, 0x06, 0x0c, 0x01, 0x0b, 0x41, + 0x80, 0x94, 0xeb, 0xdc, 0x03, 0x20, 0x0a, 0x76, 0x21, 0x10, 0x41, 0x7f, + 0x20, 0x0a, 0x74, 0x41, 0x7f, 0x73, 0x21, 0x16, 0x41, 0x00, 0x21, 0x08, + 0x20, 0x06, 0x21, 0x07, 0x03, 0x40, 0x20, 0x07, 0x20, 0x08, 0x20, 0x07, + 0x28, 0x02, 0x00, 0x22, 0x17, 0x20, 0x0a, 0x76, 0x6a, 0x36, 0x02, 0x00, + 0x20, 0x16, 0x20, 0x17, 0x71, 0x20, 0x10, 0x6c, 0x21, 0x08, 0x20, 0x07, + 0x41, 0x04, 0x6a, 0x22, 0x07, 0x20, 0x05, 0x49, 0x0d, 0x00, 0x0b, 0x20, + 0x06, 0x20, 0x06, 0x41, 0x04, 0x6a, 0x20, 0x06, 0x28, 0x02, 0x00, 0x1b, + 0x21, 0x06, 0x20, 0x08, 0x45, 0x0d, 0x00, 0x20, 0x05, 0x20, 0x08, 0x36, + 0x02, 0x00, 0x20, 0x05, 0x41, 0x04, 0x6a, 0x21, 0x05, 0x0b, 0x20, 0x09, + 0x20, 0x09, 0x28, 0x02, 0xec, 0x02, 0x20, 0x0a, 0x6a, 0x22, 0x08, 0x36, + 0x02, 0xec, 0x02, 0x20, 0x12, 0x20, 0x06, 0x20, 0x0c, 0x41, 0xe6, 0x00, + 0x46, 0x1b, 0x22, 0x07, 0x20, 0x0b, 0x41, 0x02, 0x74, 0x6a, 0x20, 0x05, + 0x20, 0x05, 0x20, 0x07, 0x6b, 0x41, 0x02, 0x75, 0x20, 0x0b, 0x4a, 0x1b, + 0x21, 0x05, 0x20, 0x08, 0x41, 0x00, 0x48, 0x0d, 0x00, 0x0b, 0x0b, 0x41, + 0x00, 0x21, 0x07, 0x02, 0x40, 0x20, 0x06, 0x20, 0x05, 0x4f, 0x0d, 0x00, + 0x20, 0x12, 0x20, 0x06, 0x6b, 0x41, 0x02, 0x75, 0x41, 0x09, 0x6c, 0x21, + 0x07, 0x20, 0x06, 0x28, 0x02, 0x00, 0x22, 0x0a, 0x41, 0x0a, 0x49, 0x0d, + 0x00, 0x41, 0x0a, 0x21, 0x08, 0x03, 0x40, 0x20, 0x07, 0x41, 0x01, 0x6a, + 0x21, 0x07, 0x20, 0x0a, 0x20, 0x08, 0x41, 0x0a, 0x6c, 0x22, 0x08, 0x4f, + 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x0d, 0x41, 0x00, 0x20, 0x07, 0x20, 0x0c, + 0x41, 0xe6, 0x00, 0x46, 0x1b, 0x22, 0x0a, 0x6b, 0x20, 0x0c, 0x41, 0xe7, + 0x00, 0x46, 0x22, 0x10, 0x20, 0x0d, 0x41, 0x00, 0x47, 0x71, 0x22, 0x0b, + 0x6b, 0x22, 0x08, 0x20, 0x05, 0x20, 0x12, 0x6b, 0x41, 0x02, 0x75, 0x41, + 0x09, 0x6c, 0x41, 0x77, 0x6a, 0x48, 0x04, 0x40, 0x20, 0x08, 0x41, 0x80, + 0xc8, 0x00, 0x6a, 0x22, 0x16, 0x41, 0x09, 0x6d, 0x22, 0x17, 0x41, 0x02, + 0x74, 0x20, 0x12, 0x6a, 0x22, 0x1d, 0x41, 0x84, 0x60, 0x6a, 0x21, 0x0c, + 0x41, 0x0a, 0x21, 0x08, 0x20, 0x16, 0x20, 0x17, 0x41, 0x09, 0x6c, 0x22, + 0x16, 0x6b, 0x41, 0x01, 0x6a, 0x41, 0x08, 0x4c, 0x04, 0x40, 0x20, 0x0a, + 0x20, 0x16, 0x6a, 0x20, 0x0b, 0x6a, 0x20, 0x0d, 0x6b, 0x41, 0x88, 0xb8, + 0x7f, 0x6a, 0x21, 0x0b, 0x03, 0x40, 0x20, 0x08, 0x41, 0x0a, 0x6c, 0x21, + 0x08, 0x20, 0x0b, 0x41, 0x7f, 0x6a, 0x22, 0x0b, 0x0d, 0x00, 0x0b, 0x0b, + 0x02, 0x40, 0x41, 0x00, 0x20, 0x05, 0x20, 0x0c, 0x41, 0x04, 0x6a, 0x22, + 0x16, 0x46, 0x20, 0x0c, 0x28, 0x02, 0x00, 0x22, 0x0b, 0x20, 0x0b, 0x20, + 0x08, 0x6e, 0x22, 0x17, 0x20, 0x08, 0x6c, 0x6b, 0x22, 0x0a, 0x1b, 0x0d, + 0x00, 0x02, 0x40, 0x20, 0x17, 0x41, 0x01, 0x71, 0x45, 0x04, 0x40, 0x44, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x43, 0x21, 0x24, 0x20, 0x0c, + 0x20, 0x06, 0x4d, 0x0d, 0x01, 0x20, 0x08, 0x41, 0x80, 0x94, 0xeb, 0xdc, + 0x03, 0x47, 0x0d, 0x01, 0x20, 0x0c, 0x41, 0x7c, 0x6a, 0x2d, 0x00, 0x00, + 0x41, 0x01, 0x71, 0x45, 0x0d, 0x01, 0x0b, 0x44, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x43, 0x21, 0x24, 0x0b, 0x44, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xe0, 0x3f, 0x21, 0x25, 0x20, 0x0a, 0x20, 0x08, 0x41, 0x01, + 0x76, 0x22, 0x17, 0x4f, 0x04, 0x40, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x3f, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x3f, + 0x20, 0x0a, 0x20, 0x17, 0x46, 0x1b, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf8, 0x3f, 0x20, 0x05, 0x20, 0x16, 0x46, 0x1b, 0x21, 0x25, 0x0b, + 0x02, 0x40, 0x20, 0x14, 0x45, 0x0d, 0x00, 0x20, 0x18, 0x2d, 0x00, 0x00, + 0x41, 0x2d, 0x47, 0x0d, 0x00, 0x20, 0x25, 0x9a, 0x21, 0x25, 0x20, 0x24, + 0x9a, 0x21, 0x24, 0x0b, 0x20, 0x0c, 0x20, 0x0b, 0x20, 0x0a, 0x6b, 0x22, + 0x0a, 0x36, 0x02, 0x00, 0x20, 0x24, 0x20, 0x25, 0xa0, 0x20, 0x24, 0x61, + 0x0d, 0x00, 0x20, 0x0c, 0x20, 0x08, 0x20, 0x0a, 0x6a, 0x22, 0x07, 0x36, + 0x02, 0x00, 0x20, 0x07, 0x41, 0x80, 0x94, 0xeb, 0xdc, 0x03, 0x4f, 0x04, + 0x40, 0x20, 0x1d, 0x41, 0x80, 0x60, 0x6a, 0x21, 0x07, 0x03, 0x40, 0x20, + 0x07, 0x41, 0x04, 0x6a, 0x41, 0x00, 0x36, 0x02, 0x00, 0x20, 0x07, 0x20, + 0x06, 0x49, 0x04, 0x40, 0x20, 0x06, 0x41, 0x7c, 0x6a, 0x22, 0x06, 0x41, + 0x00, 0x36, 0x02, 0x00, 0x0b, 0x20, 0x07, 0x20, 0x07, 0x28, 0x02, 0x00, + 0x41, 0x01, 0x6a, 0x22, 0x08, 0x36, 0x02, 0x00, 0x20, 0x07, 0x41, 0x7c, + 0x6a, 0x21, 0x07, 0x20, 0x08, 0x41, 0xff, 0x93, 0xeb, 0xdc, 0x03, 0x4b, + 0x0d, 0x00, 0x0b, 0x20, 0x07, 0x41, 0x04, 0x6a, 0x21, 0x0c, 0x0b, 0x20, + 0x12, 0x20, 0x06, 0x6b, 0x41, 0x02, 0x75, 0x41, 0x09, 0x6c, 0x21, 0x07, + 0x20, 0x06, 0x28, 0x02, 0x00, 0x22, 0x0a, 0x41, 0x0a, 0x49, 0x0d, 0x00, + 0x41, 0x0a, 0x21, 0x08, 0x03, 0x40, 0x20, 0x07, 0x41, 0x01, 0x6a, 0x21, + 0x07, 0x20, 0x0a, 0x20, 0x08, 0x41, 0x0a, 0x6c, 0x22, 0x08, 0x4f, 0x0d, + 0x00, 0x0b, 0x0b, 0x20, 0x0c, 0x41, 0x04, 0x6a, 0x22, 0x08, 0x20, 0x05, + 0x20, 0x05, 0x20, 0x08, 0x4b, 0x1b, 0x21, 0x05, 0x0b, 0x02, 0x7f, 0x03, + 0x40, 0x41, 0x00, 0x20, 0x05, 0x22, 0x0b, 0x20, 0x06, 0x4d, 0x0d, 0x01, + 0x1a, 0x20, 0x0b, 0x41, 0x7c, 0x6a, 0x22, 0x05, 0x28, 0x02, 0x00, 0x45, + 0x0d, 0x00, 0x0b, 0x41, 0x01, 0x0b, 0x21, 0x16, 0x02, 0x40, 0x20, 0x10, + 0x45, 0x04, 0x40, 0x20, 0x0f, 0x41, 0x08, 0x71, 0x21, 0x10, 0x0c, 0x01, + 0x0b, 0x20, 0x07, 0x41, 0x7f, 0x73, 0x41, 0x7f, 0x20, 0x0d, 0x41, 0x01, + 0x20, 0x0d, 0x1b, 0x22, 0x05, 0x20, 0x07, 0x4a, 0x20, 0x07, 0x41, 0x7b, + 0x4a, 0x71, 0x22, 0x08, 0x1b, 0x20, 0x05, 0x6a, 0x21, 0x0d, 0x41, 0x7f, + 0x41, 0x7e, 0x20, 0x08, 0x1b, 0x20, 0x11, 0x6a, 0x21, 0x11, 0x20, 0x0f, + 0x41, 0x08, 0x71, 0x22, 0x10, 0x0d, 0x00, 0x41, 0x09, 0x21, 0x05, 0x02, + 0x40, 0x20, 0x16, 0x45, 0x0d, 0x00, 0x20, 0x0b, 0x41, 0x7c, 0x6a, 0x28, + 0x02, 0x00, 0x22, 0x0a, 0x45, 0x0d, 0x00, 0x41, 0x00, 0x21, 0x05, 0x20, + 0x0a, 0x41, 0x0a, 0x70, 0x0d, 0x00, 0x41, 0x0a, 0x21, 0x08, 0x03, 0x40, + 0x20, 0x05, 0x41, 0x01, 0x6a, 0x21, 0x05, 0x20, 0x0a, 0x20, 0x08, 0x41, + 0x0a, 0x6c, 0x22, 0x08, 0x70, 0x45, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x0b, + 0x20, 0x12, 0x6b, 0x41, 0x02, 0x75, 0x41, 0x09, 0x6c, 0x41, 0x77, 0x6a, + 0x21, 0x08, 0x20, 0x11, 0x41, 0x20, 0x72, 0x41, 0xe6, 0x00, 0x46, 0x04, + 0x40, 0x41, 0x00, 0x21, 0x10, 0x20, 0x0d, 0x20, 0x08, 0x20, 0x05, 0x6b, + 0x22, 0x05, 0x41, 0x00, 0x20, 0x05, 0x41, 0x00, 0x4a, 0x1b, 0x22, 0x05, + 0x20, 0x0d, 0x20, 0x05, 0x48, 0x1b, 0x21, 0x0d, 0x0c, 0x01, 0x0b, 0x41, + 0x00, 0x21, 0x10, 0x20, 0x0d, 0x20, 0x07, 0x20, 0x08, 0x6a, 0x20, 0x05, + 0x6b, 0x22, 0x05, 0x41, 0x00, 0x20, 0x05, 0x41, 0x00, 0x4a, 0x1b, 0x22, + 0x05, 0x20, 0x0d, 0x20, 0x05, 0x48, 0x1b, 0x21, 0x0d, 0x0b, 0x41, 0x7f, + 0x21, 0x05, 0x20, 0x0d, 0x41, 0xfd, 0xff, 0xff, 0xff, 0x07, 0x41, 0xfe, + 0xff, 0xff, 0xff, 0x07, 0x20, 0x0d, 0x20, 0x10, 0x72, 0x22, 0x17, 0x1b, + 0x4a, 0x0d, 0x00, 0x20, 0x0d, 0x20, 0x17, 0x41, 0x00, 0x47, 0x6a, 0x41, + 0x01, 0x6a, 0x21, 0x0c, 0x02, 0x40, 0x20, 0x11, 0x41, 0x20, 0x72, 0x41, + 0xe6, 0x00, 0x47, 0x22, 0x1d, 0x45, 0x04, 0x40, 0x20, 0x07, 0x41, 0xff, + 0xff, 0xff, 0xff, 0x07, 0x20, 0x0c, 0x6b, 0x4a, 0x0d, 0x02, 0x20, 0x07, + 0x41, 0x00, 0x20, 0x07, 0x41, 0x00, 0x4a, 0x1b, 0x21, 0x07, 0x0c, 0x01, + 0x0b, 0x20, 0x19, 0x21, 0x08, 0x20, 0x07, 0x20, 0x07, 0x41, 0x1f, 0x75, + 0x22, 0x05, 0x6a, 0x20, 0x05, 0x73, 0x22, 0x05, 0x04, 0x40, 0x03, 0x40, + 0x20, 0x08, 0x41, 0x7f, 0x6a, 0x22, 0x08, 0x20, 0x05, 0x20, 0x05, 0x41, + 0x0a, 0x6e, 0x22, 0x0a, 0x41, 0x0a, 0x6c, 0x6b, 0x41, 0x30, 0x72, 0x3a, + 0x00, 0x00, 0x20, 0x05, 0x41, 0x09, 0x4b, 0x20, 0x0a, 0x21, 0x05, 0x0d, + 0x00, 0x0b, 0x0b, 0x20, 0x19, 0x20, 0x08, 0x6b, 0x41, 0x01, 0x4c, 0x04, + 0x40, 0x20, 0x08, 0x41, 0x7f, 0x6a, 0x21, 0x05, 0x03, 0x40, 0x20, 0x05, + 0x41, 0x30, 0x3a, 0x00, 0x00, 0x20, 0x19, 0x20, 0x05, 0x6b, 0x20, 0x05, + 0x41, 0x7f, 0x6a, 0x22, 0x0a, 0x21, 0x05, 0x41, 0x02, 0x48, 0x0d, 0x00, + 0x0b, 0x20, 0x0a, 0x41, 0x01, 0x6a, 0x21, 0x08, 0x0b, 0x20, 0x08, 0x41, + 0x7e, 0x6a, 0x22, 0x1c, 0x20, 0x11, 0x3a, 0x00, 0x00, 0x41, 0x7f, 0x21, + 0x05, 0x20, 0x08, 0x41, 0x7f, 0x6a, 0x41, 0x2d, 0x41, 0x2b, 0x20, 0x07, + 0x41, 0x00, 0x48, 0x1b, 0x3a, 0x00, 0x00, 0x20, 0x19, 0x20, 0x1c, 0x6b, + 0x22, 0x07, 0x41, 0xff, 0xff, 0xff, 0xff, 0x07, 0x20, 0x0c, 0x6b, 0x4a, + 0x0d, 0x01, 0x0b, 0x20, 0x07, 0x20, 0x0c, 0x6a, 0x22, 0x07, 0x20, 0x14, + 0x41, 0xff, 0xff, 0xff, 0xff, 0x07, 0x73, 0x4a, 0x0d, 0x00, 0x20, 0x07, + 0x20, 0x14, 0x6a, 0x21, 0x11, 0x02, 0x40, 0x20, 0x0f, 0x41, 0x80, 0xc0, + 0x04, 0x71, 0x22, 0x0f, 0x0d, 0x00, 0x20, 0x0e, 0x20, 0x11, 0x4c, 0x0d, + 0x00, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x20, 0x20, 0x0e, 0x20, 0x11, + 0x6b, 0x22, 0x0a, 0x41, 0x80, 0x02, 0x20, 0x0a, 0x41, 0x80, 0x02, 0x49, + 0x22, 0x07, 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x08, + 0x41, 0x20, 0x71, 0x21, 0x05, 0x02, 0x40, 0x20, 0x07, 0x45, 0x04, 0x40, + 0x20, 0x05, 0x45, 0x21, 0x05, 0x20, 0x0a, 0x21, 0x07, 0x03, 0x40, 0x20, + 0x05, 0x41, 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, + 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, 0x28, 0x02, 0x00, + 0x21, 0x08, 0x0b, 0x20, 0x08, 0x41, 0x20, 0x71, 0x22, 0x0c, 0x45, 0x21, + 0x05, 0x20, 0x07, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x07, 0x41, 0xff, 0x01, + 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x0c, 0x0d, 0x02, 0x20, 0x0a, 0x41, 0xff, + 0x01, 0x71, 0x21, 0x0a, 0x0c, 0x01, 0x0b, 0x20, 0x05, 0x0d, 0x01, 0x0b, + 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, 0x0a, 0x20, 0x00, 0x10, 0x33, 0x1a, + 0x0b, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, 0x20, 0x71, 0x45, 0x04, 0x40, + 0x20, 0x18, 0x20, 0x14, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x02, 0x40, + 0x20, 0x0f, 0x41, 0x80, 0x80, 0x04, 0x47, 0x0d, 0x00, 0x20, 0x0e, 0x20, + 0x11, 0x4c, 0x0d, 0x00, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x30, 0x20, + 0x0e, 0x20, 0x11, 0x6b, 0x22, 0x0a, 0x41, 0x80, 0x02, 0x20, 0x0a, 0x41, + 0x80, 0x02, 0x49, 0x22, 0x07, 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, + 0x00, 0x22, 0x08, 0x41, 0x20, 0x71, 0x21, 0x05, 0x02, 0x40, 0x20, 0x07, + 0x45, 0x04, 0x40, 0x20, 0x05, 0x45, 0x21, 0x05, 0x20, 0x0a, 0x21, 0x07, + 0x03, 0x40, 0x20, 0x05, 0x41, 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, + 0x40, 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, + 0x28, 0x02, 0x00, 0x21, 0x08, 0x0b, 0x20, 0x08, 0x41, 0x20, 0x71, 0x22, + 0x0c, 0x45, 0x21, 0x05, 0x20, 0x07, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x07, + 0x41, 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x0c, 0x0d, 0x02, 0x20, + 0x0a, 0x41, 0xff, 0x01, 0x71, 0x21, 0x0a, 0x0c, 0x01, 0x0b, 0x20, 0x05, + 0x0d, 0x01, 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, 0x0a, 0x20, 0x00, + 0x10, 0x33, 0x1a, 0x0b, 0x02, 0x40, 0x20, 0x1d, 0x45, 0x04, 0x40, 0x20, + 0x12, 0x20, 0x06, 0x20, 0x06, 0x20, 0x12, 0x4b, 0x1b, 0x22, 0x08, 0x21, + 0x0c, 0x03, 0x40, 0x02, 0x40, 0x20, 0x0c, 0x28, 0x02, 0x00, 0x22, 0x05, + 0x45, 0x04, 0x40, 0x41, 0x00, 0x21, 0x06, 0x0c, 0x01, 0x0b, 0x41, 0x00, + 0x21, 0x06, 0x03, 0x40, 0x20, 0x06, 0x20, 0x1e, 0x6a, 0x20, 0x05, 0x20, + 0x05, 0x41, 0x0a, 0x6e, 0x22, 0x07, 0x41, 0x0a, 0x6c, 0x6b, 0x41, 0x30, + 0x72, 0x3a, 0x00, 0x00, 0x20, 0x06, 0x41, 0x7f, 0x6a, 0x21, 0x06, 0x20, + 0x05, 0x41, 0x09, 0x4b, 0x20, 0x07, 0x21, 0x05, 0x0d, 0x00, 0x0b, 0x0b, + 0x20, 0x06, 0x20, 0x1b, 0x6a, 0x21, 0x05, 0x02, 0x40, 0x20, 0x08, 0x20, + 0x0c, 0x47, 0x04, 0x40, 0x20, 0x05, 0x20, 0x09, 0x41, 0xd0, 0x02, 0x6a, + 0x4d, 0x0d, 0x01, 0x03, 0x40, 0x20, 0x05, 0x41, 0x7f, 0x6a, 0x22, 0x05, + 0x41, 0x30, 0x3a, 0x00, 0x00, 0x20, 0x05, 0x20, 0x09, 0x41, 0xd0, 0x02, + 0x6a, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x09, 0x41, 0xd0, 0x02, 0x6a, 0x21, + 0x05, 0x0c, 0x01, 0x0b, 0x20, 0x06, 0x0d, 0x00, 0x20, 0x05, 0x41, 0x7f, + 0x6a, 0x22, 0x05, 0x41, 0x30, 0x3a, 0x00, 0x00, 0x0b, 0x20, 0x00, 0x2d, + 0x00, 0x00, 0x41, 0x20, 0x71, 0x45, 0x04, 0x40, 0x20, 0x05, 0x20, 0x1b, + 0x20, 0x05, 0x6b, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x20, 0x0c, 0x41, + 0x04, 0x6a, 0x22, 0x0c, 0x20, 0x12, 0x4d, 0x0d, 0x00, 0x0b, 0x02, 0x40, + 0x20, 0x17, 0x45, 0x0d, 0x00, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, 0x20, + 0x71, 0x0d, 0x00, 0x41, 0xd3, 0x1b, 0x41, 0x01, 0x20, 0x00, 0x10, 0x33, + 0x1a, 0x0b, 0x02, 0x40, 0x20, 0x0d, 0x41, 0x01, 0x48, 0x0d, 0x00, 0x20, + 0x0c, 0x20, 0x0b, 0x4f, 0x0d, 0x00, 0x03, 0x40, 0x20, 0x1b, 0x21, 0x05, + 0x02, 0x40, 0x20, 0x0c, 0x28, 0x02, 0x00, 0x22, 0x06, 0x04, 0x40, 0x03, + 0x40, 0x20, 0x05, 0x41, 0x7f, 0x6a, 0x22, 0x05, 0x20, 0x06, 0x20, 0x06, + 0x41, 0x0a, 0x6e, 0x22, 0x07, 0x41, 0x0a, 0x6c, 0x6b, 0x41, 0x30, 0x72, + 0x3a, 0x00, 0x00, 0x20, 0x06, 0x41, 0x09, 0x4b, 0x20, 0x07, 0x21, 0x06, + 0x0d, 0x00, 0x0b, 0x20, 0x05, 0x20, 0x09, 0x41, 0xd0, 0x02, 0x6a, 0x4d, + 0x0d, 0x01, 0x0b, 0x03, 0x40, 0x20, 0x05, 0x41, 0x7f, 0x6a, 0x22, 0x05, + 0x41, 0x30, 0x3a, 0x00, 0x00, 0x20, 0x05, 0x20, 0x09, 0x41, 0xd0, 0x02, + 0x6a, 0x4b, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, + 0x20, 0x71, 0x45, 0x04, 0x40, 0x20, 0x05, 0x20, 0x0d, 0x41, 0x09, 0x20, + 0x0d, 0x41, 0x09, 0x48, 0x1b, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x20, + 0x0d, 0x41, 0x77, 0x6a, 0x22, 0x0d, 0x41, 0x01, 0x48, 0x0d, 0x01, 0x20, + 0x0c, 0x41, 0x04, 0x6a, 0x22, 0x0c, 0x20, 0x0b, 0x49, 0x0d, 0x00, 0x0b, + 0x0b, 0x20, 0x0d, 0x41, 0x01, 0x48, 0x0d, 0x01, 0x20, 0x09, 0x41, 0x40, + 0x6b, 0x41, 0x30, 0x20, 0x0d, 0x41, 0x80, 0x02, 0x20, 0x0d, 0x41, 0x80, + 0x02, 0x49, 0x22, 0x05, 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, 0x00, + 0x22, 0x07, 0x41, 0x20, 0x71, 0x21, 0x06, 0x02, 0x40, 0x20, 0x05, 0x45, + 0x04, 0x40, 0x20, 0x06, 0x45, 0x21, 0x05, 0x20, 0x0d, 0x21, 0x06, 0x03, + 0x40, 0x20, 0x05, 0x41, 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, 0x40, + 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, 0x28, + 0x02, 0x00, 0x21, 0x07, 0x0b, 0x20, 0x07, 0x41, 0x20, 0x71, 0x22, 0x08, + 0x45, 0x21, 0x05, 0x20, 0x06, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x06, 0x41, + 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x08, 0x0d, 0x03, 0x20, 0x0d, + 0x41, 0xff, 0x01, 0x71, 0x21, 0x0d, 0x0c, 0x01, 0x0b, 0x20, 0x06, 0x0d, + 0x02, 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, 0x0d, 0x20, 0x00, 0x10, + 0x33, 0x1a, 0x0c, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x0d, 0x41, 0x7f, 0x4c, + 0x0d, 0x00, 0x20, 0x0b, 0x20, 0x06, 0x41, 0x04, 0x6a, 0x20, 0x16, 0x1b, + 0x21, 0x0a, 0x20, 0x06, 0x21, 0x0c, 0x03, 0x40, 0x20, 0x1b, 0x21, 0x08, + 0x02, 0x40, 0x20, 0x0c, 0x28, 0x02, 0x00, 0x22, 0x05, 0x04, 0x40, 0x41, + 0x00, 0x21, 0x07, 0x03, 0x40, 0x20, 0x07, 0x20, 0x09, 0x6a, 0x41, 0xd8, + 0x02, 0x6a, 0x20, 0x05, 0x20, 0x05, 0x41, 0x0a, 0x6e, 0x22, 0x08, 0x41, + 0x0a, 0x6c, 0x6b, 0x41, 0x30, 0x72, 0x3a, 0x00, 0x00, 0x20, 0x07, 0x41, + 0x7f, 0x6a, 0x21, 0x07, 0x20, 0x05, 0x41, 0x09, 0x4b, 0x20, 0x08, 0x21, + 0x05, 0x0d, 0x00, 0x0b, 0x20, 0x07, 0x20, 0x09, 0x6a, 0x41, 0xd9, 0x02, + 0x6a, 0x21, 0x08, 0x20, 0x07, 0x0d, 0x01, 0x0b, 0x20, 0x08, 0x41, 0x7f, + 0x6a, 0x22, 0x08, 0x41, 0x30, 0x3a, 0x00, 0x00, 0x0b, 0x02, 0x40, 0x20, + 0x06, 0x20, 0x0c, 0x47, 0x04, 0x40, 0x20, 0x08, 0x20, 0x09, 0x41, 0xd0, + 0x02, 0x6a, 0x4d, 0x0d, 0x01, 0x03, 0x40, 0x20, 0x08, 0x41, 0x7f, 0x6a, + 0x22, 0x08, 0x41, 0x30, 0x3a, 0x00, 0x00, 0x20, 0x08, 0x20, 0x09, 0x41, + 0xd0, 0x02, 0x6a, 0x4b, 0x0d, 0x00, 0x0b, 0x0c, 0x01, 0x0b, 0x20, 0x00, + 0x2d, 0x00, 0x00, 0x41, 0x20, 0x71, 0x45, 0x04, 0x40, 0x20, 0x08, 0x41, + 0x01, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x20, 0x08, 0x41, 0x01, 0x6a, + 0x21, 0x08, 0x20, 0x10, 0x45, 0x41, 0x00, 0x20, 0x0d, 0x41, 0x01, 0x48, + 0x1b, 0x0d, 0x00, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, 0x20, 0x71, 0x0d, + 0x00, 0x41, 0xd3, 0x1b, 0x41, 0x01, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, + 0x20, 0x1b, 0x20, 0x08, 0x6b, 0x21, 0x05, 0x20, 0x00, 0x2d, 0x00, 0x00, + 0x41, 0x20, 0x71, 0x45, 0x04, 0x40, 0x20, 0x08, 0x20, 0x05, 0x20, 0x0d, + 0x20, 0x0d, 0x20, 0x05, 0x4a, 0x1b, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, + 0x20, 0x0c, 0x41, 0x04, 0x6a, 0x22, 0x0c, 0x20, 0x0a, 0x49, 0x41, 0x00, + 0x20, 0x0d, 0x20, 0x05, 0x6b, 0x22, 0x0d, 0x41, 0x7f, 0x4a, 0x1b, 0x0d, + 0x00, 0x0b, 0x20, 0x0d, 0x41, 0x01, 0x48, 0x0d, 0x00, 0x20, 0x09, 0x41, + 0x40, 0x6b, 0x41, 0x30, 0x20, 0x0d, 0x41, 0x80, 0x02, 0x20, 0x0d, 0x41, + 0x80, 0x02, 0x49, 0x22, 0x05, 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, + 0x00, 0x22, 0x07, 0x41, 0x20, 0x71, 0x21, 0x06, 0x02, 0x40, 0x20, 0x05, + 0x45, 0x04, 0x40, 0x20, 0x06, 0x45, 0x21, 0x05, 0x20, 0x0d, 0x21, 0x06, + 0x03, 0x40, 0x20, 0x05, 0x41, 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, + 0x40, 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, + 0x28, 0x02, 0x00, 0x21, 0x07, 0x0b, 0x20, 0x07, 0x41, 0x20, 0x71, 0x22, + 0x08, 0x45, 0x21, 0x05, 0x20, 0x06, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x06, + 0x41, 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x08, 0x0d, 0x02, 0x20, + 0x0d, 0x41, 0xff, 0x01, 0x71, 0x21, 0x0d, 0x0c, 0x01, 0x0b, 0x20, 0x06, + 0x0d, 0x01, 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, 0x0d, 0x20, 0x00, + 0x10, 0x33, 0x1a, 0x0b, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, 0x20, 0x71, + 0x0d, 0x00, 0x20, 0x1c, 0x20, 0x19, 0x20, 0x1c, 0x6b, 0x20, 0x00, 0x10, + 0x33, 0x1a, 0x0b, 0x02, 0x40, 0x20, 0x0f, 0x41, 0x80, 0xc0, 0x00, 0x47, + 0x0d, 0x00, 0x20, 0x0e, 0x20, 0x11, 0x4c, 0x0d, 0x00, 0x20, 0x09, 0x41, + 0x40, 0x6b, 0x41, 0x20, 0x20, 0x0e, 0x20, 0x11, 0x6b, 0x22, 0x0b, 0x41, + 0x80, 0x02, 0x20, 0x0b, 0x41, 0x80, 0x02, 0x49, 0x22, 0x05, 0x1b, 0x10, + 0x3a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, 0x20, 0x71, 0x21, + 0x06, 0x02, 0x40, 0x20, 0x05, 0x45, 0x04, 0x40, 0x20, 0x06, 0x45, 0x21, + 0x05, 0x20, 0x0b, 0x21, 0x06, 0x03, 0x40, 0x20, 0x05, 0x41, 0x01, 0x71, + 0x04, 0x40, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, + 0x10, 0x33, 0x1a, 0x20, 0x00, 0x28, 0x02, 0x00, 0x21, 0x07, 0x0b, 0x20, + 0x07, 0x41, 0x20, 0x71, 0x22, 0x08, 0x45, 0x21, 0x05, 0x20, 0x06, 0x41, + 0x80, 0x7e, 0x6a, 0x22, 0x06, 0x41, 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, + 0x20, 0x08, 0x0d, 0x02, 0x20, 0x0b, 0x41, 0xff, 0x01, 0x71, 0x21, 0x0b, + 0x0c, 0x01, 0x0b, 0x20, 0x06, 0x0d, 0x01, 0x0b, 0x20, 0x09, 0x41, 0x40, + 0x6b, 0x20, 0x0b, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x20, 0x0e, 0x20, + 0x11, 0x20, 0x0e, 0x20, 0x11, 0x4a, 0x1b, 0x21, 0x05, 0x0b, 0x20, 0x05, + 0x41, 0x00, 0x4e, 0x0d, 0x0a, 0x0c, 0x09, 0x0b, 0x41, 0x00, 0x21, 0x0a, + 0x41, 0xa6, 0x16, 0x21, 0x10, 0x0b, 0x20, 0x15, 0x21, 0x05, 0x0c, 0x06, + 0x0b, 0x20, 0x06, 0x21, 0x0f, 0x20, 0x07, 0x21, 0x0b, 0x20, 0x05, 0x2d, + 0x00, 0x00, 0x45, 0x0d, 0x05, 0x0c, 0x06, 0x0b, 0x20, 0x01, 0x2d, 0x00, + 0x01, 0x21, 0x05, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x0c, 0x00, + 0x0b, 0x00, 0x0b, 0x20, 0x00, 0x0d, 0x06, 0x20, 0x1a, 0x45, 0x04, 0x40, + 0x41, 0x00, 0x21, 0x13, 0x0c, 0x07, 0x0b, 0x02, 0x7f, 0x41, 0x01, 0x20, + 0x04, 0x28, 0x02, 0x04, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x1a, 0x20, 0x03, + 0x41, 0x08, 0x6a, 0x20, 0x00, 0x20, 0x02, 0x10, 0x27, 0x41, 0x02, 0x20, + 0x04, 0x28, 0x02, 0x08, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x1a, 0x20, 0x03, + 0x41, 0x10, 0x6a, 0x20, 0x00, 0x20, 0x02, 0x10, 0x27, 0x41, 0x03, 0x20, + 0x04, 0x28, 0x02, 0x0c, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x1a, 0x20, 0x03, + 0x41, 0x18, 0x6a, 0x20, 0x00, 0x20, 0x02, 0x10, 0x27, 0x41, 0x04, 0x20, + 0x04, 0x28, 0x02, 0x10, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x1a, 0x20, 0x03, + 0x41, 0x20, 0x6a, 0x20, 0x00, 0x20, 0x02, 0x10, 0x27, 0x41, 0x05, 0x20, + 0x04, 0x28, 0x02, 0x14, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x1a, 0x20, 0x03, + 0x41, 0x28, 0x6a, 0x20, 0x00, 0x20, 0x02, 0x10, 0x27, 0x41, 0x06, 0x20, + 0x04, 0x28, 0x02, 0x18, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x1a, 0x20, 0x03, + 0x41, 0x30, 0x6a, 0x20, 0x00, 0x20, 0x02, 0x10, 0x27, 0x41, 0x07, 0x20, + 0x04, 0x28, 0x02, 0x1c, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x1a, 0x20, 0x03, + 0x41, 0x38, 0x6a, 0x20, 0x00, 0x20, 0x02, 0x10, 0x27, 0x41, 0x08, 0x20, + 0x04, 0x28, 0x02, 0x20, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x1a, 0x20, 0x03, + 0x41, 0x40, 0x6b, 0x20, 0x00, 0x20, 0x02, 0x10, 0x27, 0x20, 0x04, 0x28, + 0x02, 0x24, 0x22, 0x00, 0x0d, 0x02, 0x41, 0x09, 0x0b, 0x41, 0x02, 0x74, + 0x21, 0x01, 0x03, 0x40, 0x20, 0x01, 0x20, 0x04, 0x6a, 0x28, 0x02, 0x00, + 0x0d, 0x01, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x22, 0x01, 0x41, 0x28, 0x47, + 0x0d, 0x00, 0x0b, 0x41, 0x01, 0x21, 0x13, 0x0c, 0x06, 0x0b, 0x41, 0xe0, + 0x1f, 0x41, 0x1c, 0x36, 0x02, 0x00, 0x0c, 0x04, 0x0b, 0x20, 0x03, 0x41, + 0xc8, 0x00, 0x6a, 0x20, 0x00, 0x20, 0x02, 0x10, 0x27, 0x41, 0x01, 0x21, + 0x13, 0x0c, 0x04, 0x0b, 0x20, 0x05, 0x20, 0x08, 0x6b, 0x22, 0x11, 0x20, + 0x0b, 0x20, 0x0b, 0x20, 0x11, 0x48, 0x1b, 0x22, 0x14, 0x41, 0xff, 0xff, + 0xff, 0xff, 0x07, 0x20, 0x0a, 0x6b, 0x4a, 0x0d, 0x00, 0x20, 0x0a, 0x20, + 0x14, 0x6a, 0x22, 0x12, 0x20, 0x0e, 0x20, 0x0e, 0x20, 0x12, 0x48, 0x1b, + 0x22, 0x05, 0x20, 0x18, 0x4a, 0x0d, 0x00, 0x02, 0x40, 0x20, 0x0f, 0x41, + 0x80, 0xc0, 0x04, 0x71, 0x22, 0x0f, 0x0d, 0x00, 0x20, 0x12, 0x20, 0x0e, + 0x4e, 0x0d, 0x00, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x20, 0x20, 0x05, + 0x20, 0x12, 0x6b, 0x22, 0x0d, 0x41, 0x80, 0x02, 0x20, 0x0d, 0x41, 0x80, + 0x02, 0x49, 0x22, 0x07, 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, 0x00, + 0x22, 0x0c, 0x41, 0x20, 0x71, 0x21, 0x06, 0x02, 0x40, 0x20, 0x07, 0x45, + 0x04, 0x40, 0x20, 0x06, 0x45, 0x21, 0x06, 0x20, 0x0d, 0x21, 0x07, 0x03, + 0x40, 0x20, 0x06, 0x41, 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, 0x40, + 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, 0x28, + 0x02, 0x00, 0x21, 0x0c, 0x0b, 0x20, 0x0c, 0x41, 0x20, 0x71, 0x22, 0x18, + 0x45, 0x21, 0x06, 0x20, 0x07, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x07, 0x41, + 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x18, 0x0d, 0x02, 0x20, 0x0d, + 0x41, 0xff, 0x01, 0x71, 0x21, 0x0d, 0x0c, 0x01, 0x0b, 0x20, 0x06, 0x0d, + 0x01, 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, 0x0d, 0x20, 0x00, 0x10, + 0x33, 0x1a, 0x0b, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, 0x20, 0x71, 0x45, + 0x04, 0x40, 0x20, 0x10, 0x20, 0x0a, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, + 0x02, 0x40, 0x20, 0x0f, 0x41, 0x80, 0x80, 0x04, 0x47, 0x0d, 0x00, 0x20, + 0x12, 0x20, 0x0e, 0x4e, 0x0d, 0x00, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, + 0x30, 0x20, 0x05, 0x20, 0x12, 0x6b, 0x22, 0x0a, 0x41, 0x80, 0x02, 0x20, + 0x0a, 0x41, 0x80, 0x02, 0x49, 0x22, 0x07, 0x1b, 0x10, 0x3a, 0x20, 0x00, + 0x28, 0x02, 0x00, 0x22, 0x0c, 0x41, 0x20, 0x71, 0x21, 0x06, 0x02, 0x40, + 0x20, 0x07, 0x45, 0x04, 0x40, 0x20, 0x06, 0x45, 0x21, 0x06, 0x20, 0x0a, + 0x21, 0x07, 0x03, 0x40, 0x20, 0x06, 0x41, 0x01, 0x71, 0x04, 0x40, 0x20, + 0x09, 0x41, 0x40, 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, 0x1a, + 0x20, 0x00, 0x28, 0x02, 0x00, 0x21, 0x0c, 0x0b, 0x20, 0x0c, 0x41, 0x20, + 0x71, 0x22, 0x0d, 0x45, 0x21, 0x06, 0x20, 0x07, 0x41, 0x80, 0x7e, 0x6a, + 0x22, 0x07, 0x41, 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x0d, 0x0d, + 0x02, 0x20, 0x0a, 0x41, 0xff, 0x01, 0x71, 0x21, 0x0a, 0x0c, 0x01, 0x0b, + 0x20, 0x06, 0x0d, 0x01, 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, 0x0a, + 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, 0x02, 0x40, 0x20, 0x11, 0x20, 0x0b, + 0x4e, 0x0d, 0x00, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x30, 0x20, 0x14, + 0x20, 0x11, 0x6b, 0x22, 0x0a, 0x41, 0x80, 0x02, 0x20, 0x0a, 0x41, 0x80, + 0x02, 0x49, 0x22, 0x07, 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, 0x00, + 0x22, 0x0b, 0x41, 0x20, 0x71, 0x21, 0x06, 0x02, 0x40, 0x20, 0x07, 0x45, + 0x04, 0x40, 0x20, 0x06, 0x45, 0x21, 0x06, 0x20, 0x0a, 0x21, 0x07, 0x03, + 0x40, 0x20, 0x06, 0x41, 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, 0x40, + 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, 0x28, + 0x02, 0x00, 0x21, 0x0b, 0x0b, 0x20, 0x0b, 0x41, 0x20, 0x71, 0x22, 0x0c, + 0x45, 0x21, 0x06, 0x20, 0x07, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x07, 0x41, + 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x0c, 0x0d, 0x02, 0x20, 0x0a, + 0x41, 0xff, 0x01, 0x71, 0x21, 0x0a, 0x0c, 0x01, 0x0b, 0x20, 0x06, 0x0d, + 0x01, 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, 0x0a, 0x20, 0x00, 0x10, + 0x33, 0x1a, 0x0b, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, 0x20, 0x71, 0x45, + 0x04, 0x40, 0x20, 0x08, 0x20, 0x11, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x0b, + 0x20, 0x0f, 0x41, 0x80, 0xc0, 0x00, 0x47, 0x0d, 0x01, 0x20, 0x12, 0x20, + 0x0e, 0x4e, 0x0d, 0x01, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x41, 0x20, 0x20, + 0x05, 0x20, 0x12, 0x6b, 0x22, 0x0b, 0x41, 0x80, 0x02, 0x20, 0x0b, 0x41, + 0x80, 0x02, 0x49, 0x22, 0x07, 0x1b, 0x10, 0x3a, 0x20, 0x00, 0x28, 0x02, + 0x00, 0x22, 0x08, 0x41, 0x20, 0x71, 0x21, 0x06, 0x02, 0x40, 0x20, 0x07, + 0x45, 0x04, 0x40, 0x20, 0x06, 0x45, 0x21, 0x06, 0x20, 0x0b, 0x21, 0x07, + 0x03, 0x40, 0x20, 0x06, 0x41, 0x01, 0x71, 0x04, 0x40, 0x20, 0x09, 0x41, + 0x40, 0x6b, 0x41, 0x80, 0x02, 0x20, 0x00, 0x10, 0x33, 0x1a, 0x20, 0x00, + 0x28, 0x02, 0x00, 0x21, 0x08, 0x0b, 0x20, 0x08, 0x41, 0x20, 0x71, 0x22, + 0x0a, 0x45, 0x21, 0x06, 0x20, 0x07, 0x41, 0x80, 0x7e, 0x6a, 0x22, 0x07, + 0x41, 0xff, 0x01, 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x0a, 0x0d, 0x03, 0x20, + 0x0b, 0x41, 0xff, 0x01, 0x71, 0x21, 0x0b, 0x0c, 0x01, 0x0b, 0x20, 0x06, + 0x0d, 0x02, 0x0b, 0x20, 0x09, 0x41, 0x40, 0x6b, 0x20, 0x0b, 0x20, 0x00, + 0x10, 0x33, 0x1a, 0x0c, 0x01, 0x0b, 0x0b, 0x41, 0xe0, 0x1f, 0x41, 0x3d, + 0x36, 0x02, 0x00, 0x0b, 0x41, 0x7f, 0x21, 0x13, 0x0b, 0x20, 0x09, 0x41, + 0xf0, 0x06, 0x6a, 0x24, 0x00, 0x20, 0x13, 0x0b, 0xa2, 0x02, 0x00, 0x02, + 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x01, 0x41, 0x77, 0x6a, 0x22, 0x01, + 0x41, 0x11, 0x4d, 0x04, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, + 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x01, 0x41, 0x01, 0x6b, 0x0e, 0x11, + 0x07, 0x08, 0x09, 0x07, 0x08, 0x00, 0x01, 0x02, 0x03, 0x09, 0x08, 0x09, + 0x09, 0x07, 0x08, 0x09, 0x04, 0x05, 0x0b, 0x20, 0x02, 0x20, 0x02, 0x28, + 0x02, 0x00, 0x22, 0x01, 0x41, 0x04, 0x6a, 0x36, 0x02, 0x00, 0x20, 0x00, + 0x20, 0x01, 0x32, 0x01, 0x00, 0x37, 0x03, 0x00, 0x0f, 0x0b, 0x20, 0x02, + 0x20, 0x02, 0x28, 0x02, 0x00, 0x22, 0x01, 0x41, 0x04, 0x6a, 0x36, 0x02, + 0x00, 0x20, 0x00, 0x20, 0x01, 0x33, 0x01, 0x00, 0x37, 0x03, 0x00, 0x0f, + 0x0b, 0x20, 0x02, 0x20, 0x02, 0x28, 0x02, 0x00, 0x22, 0x01, 0x41, 0x04, + 0x6a, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x01, 0x30, 0x00, 0x00, 0x37, + 0x03, 0x00, 0x0f, 0x0b, 0x20, 0x02, 0x20, 0x02, 0x28, 0x02, 0x00, 0x22, + 0x01, 0x41, 0x04, 0x6a, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x01, 0x31, + 0x00, 0x00, 0x37, 0x03, 0x00, 0x0f, 0x0b, 0x41, 0x90, 0x1a, 0x41, 0xa8, + 0x29, 0x10, 0x29, 0x1a, 0x00, 0x0b, 0x20, 0x02, 0x20, 0x02, 0x28, 0x02, + 0x00, 0x22, 0x01, 0x41, 0x04, 0x6a, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, + 0x01, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x0b, 0x0f, 0x0b, 0x20, 0x02, + 0x20, 0x02, 0x28, 0x02, 0x00, 0x22, 0x01, 0x41, 0x04, 0x6a, 0x36, 0x02, + 0x00, 0x20, 0x00, 0x20, 0x01, 0x34, 0x02, 0x00, 0x37, 0x03, 0x00, 0x0f, + 0x0b, 0x20, 0x02, 0x20, 0x02, 0x28, 0x02, 0x00, 0x22, 0x01, 0x41, 0x04, + 0x6a, 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x01, 0x35, 0x02, 0x00, 0x37, + 0x03, 0x00, 0x0f, 0x0b, 0x20, 0x02, 0x20, 0x02, 0x28, 0x02, 0x00, 0x41, + 0x07, 0x6a, 0x41, 0x78, 0x71, 0x22, 0x01, 0x41, 0x08, 0x6a, 0x36, 0x02, + 0x00, 0x20, 0x00, 0x20, 0x01, 0x29, 0x03, 0x00, 0x37, 0x03, 0x00, 0x0b, + 0x38, 0x01, 0x01, 0x7f, 0x02, 0x40, 0x41, 0xf0, 0x28, 0x28, 0x02, 0x00, + 0x41, 0x0a, 0x46, 0x0d, 0x00, 0x41, 0xc4, 0x28, 0x28, 0x02, 0x00, 0x22, + 0x00, 0x41, 0xc0, 0x28, 0x28, 0x02, 0x00, 0x46, 0x0d, 0x00, 0x41, 0xc4, + 0x28, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x36, 0x02, 0x00, 0x20, 0x00, 0x41, + 0x0a, 0x3a, 0x00, 0x00, 0x0f, 0x0b, 0x10, 0x2a, 0x0b, 0x18, 0x01, 0x01, + 0x7f, 0x41, 0x7f, 0x41, 0x00, 0x20, 0x00, 0x10, 0x38, 0x22, 0x02, 0x20, + 0x00, 0x20, 0x02, 0x20, 0x01, 0x10, 0x34, 0x47, 0x1b, 0x0b, 0x84, 0x01, + 0x01, 0x02, 0x7f, 0x23, 0x00, 0x41, 0x10, 0x6b, 0x22, 0x00, 0x24, 0x00, + 0x20, 0x00, 0x41, 0x0a, 0x3a, 0x00, 0x0f, 0x02, 0x40, 0x02, 0x40, 0x41, + 0xc0, 0x28, 0x28, 0x02, 0x00, 0x22, 0x01, 0x04, 0x7f, 0x20, 0x01, 0x05, + 0x41, 0xb0, 0x28, 0x10, 0x31, 0x0d, 0x02, 0x41, 0xc0, 0x28, 0x28, 0x02, + 0x00, 0x0b, 0x41, 0xc4, 0x28, 0x28, 0x02, 0x00, 0x22, 0x01, 0x46, 0x0d, + 0x00, 0x41, 0xf0, 0x28, 0x28, 0x02, 0x00, 0x41, 0x0a, 0x46, 0x0d, 0x00, + 0x41, 0xc4, 0x28, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x36, 0x02, 0x00, 0x20, + 0x01, 0x41, 0x0a, 0x3a, 0x00, 0x00, 0x0c, 0x01, 0x0b, 0x41, 0xb0, 0x28, + 0x20, 0x00, 0x41, 0x0f, 0x6a, 0x41, 0x01, 0x41, 0xd0, 0x28, 0x28, 0x02, + 0x00, 0x11, 0x00, 0x00, 0x41, 0x01, 0x47, 0x0d, 0x00, 0x20, 0x00, 0x2d, + 0x00, 0x0f, 0x1a, 0x0b, 0x20, 0x00, 0x41, 0x10, 0x6a, 0x24, 0x00, 0x0b, + 0x09, 0x00, 0x20, 0x00, 0x28, 0x02, 0x38, 0x10, 0x19, 0x0b, 0x48, 0x01, + 0x01, 0x7f, 0x23, 0x00, 0x41, 0x10, 0x6b, 0x22, 0x03, 0x24, 0x00, 0x02, + 0x7e, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x41, 0xff, 0x01, 0x71, 0x20, + 0x03, 0x41, 0x08, 0x6a, 0x10, 0x0d, 0x22, 0x00, 0x04, 0x40, 0x41, 0xe0, + 0x1f, 0x41, 0xc6, 0x00, 0x20, 0x00, 0x20, 0x00, 0x41, 0xcc, 0x00, 0x46, + 0x1b, 0x36, 0x02, 0x00, 0x42, 0x7f, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x29, + 0x03, 0x08, 0x0b, 0x20, 0x03, 0x41, 0x10, 0x6a, 0x24, 0x00, 0x0b, 0x0d, + 0x00, 0x20, 0x00, 0x28, 0x02, 0x38, 0x20, 0x01, 0x20, 0x02, 0x10, 0x2c, + 0x0b, 0x4d, 0x01, 0x01, 0x7f, 0x23, 0x00, 0x41, 0x20, 0x6b, 0x22, 0x01, + 0x24, 0x00, 0x02, 0x7f, 0x02, 0x40, 0x20, 0x00, 0x20, 0x01, 0x41, 0x08, + 0x6a, 0x10, 0x0a, 0x22, 0x00, 0x0d, 0x00, 0x41, 0x3b, 0x21, 0x00, 0x20, + 0x01, 0x2d, 0x00, 0x08, 0x41, 0x02, 0x47, 0x0d, 0x00, 0x20, 0x01, 0x2d, + 0x00, 0x10, 0x41, 0x24, 0x71, 0x0d, 0x00, 0x41, 0x01, 0x0c, 0x01, 0x0b, + 0x41, 0xe0, 0x1f, 0x20, 0x00, 0x36, 0x02, 0x00, 0x41, 0x00, 0x0b, 0x20, + 0x01, 0x41, 0x20, 0x6a, 0x24, 0x00, 0x0b, 0x2f, 0x00, 0x20, 0x00, 0x41, + 0x04, 0x36, 0x02, 0x20, 0x02, 0x40, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x41, + 0xc0, 0x00, 0x71, 0x0d, 0x00, 0x20, 0x00, 0x28, 0x02, 0x38, 0x10, 0x2e, + 0x0d, 0x00, 0x20, 0x00, 0x41, 0x7f, 0x36, 0x02, 0x40, 0x0b, 0x20, 0x00, + 0x20, 0x01, 0x20, 0x02, 0x10, 0x36, 0x0b, 0xca, 0x02, 0x01, 0x03, 0x7f, + 0x41, 0xec, 0x1f, 0x28, 0x02, 0x00, 0x22, 0x00, 0x04, 0x40, 0x03, 0x40, + 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, 0x00, 0x28, 0x02, 0x18, 0x47, 0x04, + 0x40, 0x20, 0x00, 0x41, 0x00, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, 0x20, + 0x11, 0x00, 0x00, 0x1a, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, 0x01, + 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, 0x02, 0x47, 0x04, 0x40, 0x20, 0x00, + 0x20, 0x01, 0x20, 0x02, 0x6b, 0xac, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, + 0x24, 0x11, 0x03, 0x00, 0x1a, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x34, 0x22, + 0x00, 0x0d, 0x00, 0x0b, 0x0b, 0x02, 0x40, 0x41, 0x98, 0x28, 0x28, 0x02, + 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, + 0x00, 0x28, 0x02, 0x18, 0x47, 0x04, 0x40, 0x20, 0x00, 0x41, 0x00, 0x41, + 0x00, 0x20, 0x00, 0x28, 0x02, 0x20, 0x11, 0x00, 0x00, 0x1a, 0x0b, 0x20, + 0x00, 0x28, 0x02, 0x04, 0x22, 0x01, 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, + 0x02, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x6b, 0xac, + 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, 0x24, 0x11, 0x03, 0x00, 0x1a, 0x0b, + 0x02, 0x40, 0x41, 0xa0, 0x29, 0x28, 0x02, 0x00, 0x22, 0x00, 0x45, 0x0d, + 0x00, 0x20, 0x00, 0x28, 0x02, 0x14, 0x20, 0x00, 0x28, 0x02, 0x18, 0x47, + 0x04, 0x40, 0x20, 0x00, 0x41, 0x00, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, + 0x20, 0x11, 0x00, 0x00, 0x1a, 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, + 0x01, 0x20, 0x00, 0x28, 0x02, 0x08, 0x22, 0x02, 0x46, 0x0d, 0x00, 0x20, + 0x00, 0x20, 0x01, 0x20, 0x02, 0x6b, 0xac, 0x41, 0x00, 0x20, 0x00, 0x28, + 0x02, 0x24, 0x11, 0x03, 0x00, 0x1a, 0x0b, 0x02, 0x40, 0x41, 0x98, 0x2a, + 0x28, 0x02, 0x00, 0x22, 0x00, 0x45, 0x0d, 0x00, 0x20, 0x00, 0x28, 0x02, + 0x14, 0x20, 0x00, 0x28, 0x02, 0x18, 0x47, 0x04, 0x40, 0x20, 0x00, 0x41, + 0x00, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, 0x20, 0x11, 0x00, 0x00, 0x1a, + 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, 0x22, 0x01, 0x20, 0x00, 0x28, 0x02, + 0x08, 0x22, 0x02, 0x46, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, + 0x6b, 0xac, 0x41, 0x00, 0x20, 0x00, 0x28, 0x02, 0x24, 0x11, 0x03, 0x00, + 0x1a, 0x0b, 0x0b, 0x59, 0x01, 0x01, 0x7f, 0x20, 0x00, 0x20, 0x00, 0x28, + 0x02, 0x3c, 0x22, 0x01, 0x41, 0x7f, 0x6a, 0x20, 0x01, 0x72, 0x36, 0x02, + 0x3c, 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x01, 0x41, 0x08, 0x71, 0x04, + 0x40, 0x20, 0x00, 0x20, 0x01, 0x41, 0x20, 0x72, 0x36, 0x02, 0x00, 0x41, + 0x7f, 0x0f, 0x0b, 0x20, 0x00, 0x42, 0x00, 0x37, 0x02, 0x04, 0x20, 0x00, + 0x20, 0x00, 0x28, 0x02, 0x28, 0x22, 0x01, 0x36, 0x02, 0x18, 0x20, 0x00, + 0x20, 0x01, 0x36, 0x02, 0x14, 0x20, 0x00, 0x20, 0x01, 0x20, 0x00, 0x28, + 0x02, 0x2c, 0x6a, 0x36, 0x02, 0x10, 0x41, 0x00, 0x0b, 0x47, 0x01, 0x01, + 0x7f, 0x41, 0x93, 0x09, 0x41, 0xb0, 0x28, 0x10, 0x29, 0x41, 0x00, 0x48, + 0x04, 0x40, 0x0f, 0x0b, 0x02, 0x40, 0x41, 0xf0, 0x28, 0x28, 0x02, 0x00, + 0x41, 0x0a, 0x46, 0x0d, 0x00, 0x41, 0xc4, 0x28, 0x28, 0x02, 0x00, 0x22, + 0x00, 0x41, 0xc0, 0x28, 0x28, 0x02, 0x00, 0x46, 0x0d, 0x00, 0x41, 0xc4, + 0x28, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x36, 0x02, 0x00, 0x20, 0x00, 0x41, + 0x0a, 0x3a, 0x00, 0x00, 0x0f, 0x0b, 0x10, 0x2a, 0x0b, 0xcf, 0x01, 0x01, + 0x06, 0x7f, 0x02, 0x40, 0x20, 0x02, 0x28, 0x02, 0x10, 0x22, 0x03, 0x04, + 0x7f, 0x20, 0x03, 0x05, 0x20, 0x02, 0x10, 0x31, 0x0d, 0x01, 0x20, 0x02, + 0x28, 0x02, 0x10, 0x0b, 0x20, 0x02, 0x28, 0x02, 0x14, 0x22, 0x06, 0x6b, + 0x20, 0x01, 0x49, 0x04, 0x40, 0x20, 0x02, 0x20, 0x00, 0x20, 0x01, 0x20, + 0x02, 0x28, 0x02, 0x20, 0x11, 0x00, 0x00, 0x0f, 0x0b, 0x02, 0x40, 0x20, + 0x02, 0x28, 0x02, 0x40, 0x41, 0x00, 0x48, 0x0d, 0x00, 0x20, 0x00, 0x21, + 0x04, 0x41, 0x00, 0x21, 0x03, 0x03, 0x40, 0x20, 0x01, 0x20, 0x03, 0x46, + 0x0d, 0x01, 0x20, 0x03, 0x41, 0x01, 0x6a, 0x21, 0x03, 0x20, 0x01, 0x20, + 0x04, 0x6a, 0x20, 0x04, 0x41, 0x7f, 0x6a, 0x22, 0x08, 0x21, 0x04, 0x41, + 0x7f, 0x6a, 0x2d, 0x00, 0x00, 0x41, 0x0a, 0x47, 0x0d, 0x00, 0x0b, 0x20, + 0x02, 0x20, 0x00, 0x20, 0x01, 0x20, 0x03, 0x6b, 0x41, 0x01, 0x6a, 0x22, + 0x05, 0x20, 0x02, 0x28, 0x02, 0x20, 0x11, 0x00, 0x00, 0x22, 0x04, 0x20, + 0x05, 0x49, 0x0d, 0x01, 0x20, 0x01, 0x20, 0x08, 0x6a, 0x41, 0x01, 0x6a, + 0x21, 0x00, 0x20, 0x02, 0x28, 0x02, 0x14, 0x21, 0x06, 0x20, 0x03, 0x41, + 0x7f, 0x6a, 0x21, 0x01, 0x0b, 0x20, 0x06, 0x20, 0x00, 0x20, 0x01, 0x10, + 0x39, 0x1a, 0x20, 0x02, 0x20, 0x02, 0x28, 0x02, 0x14, 0x20, 0x01, 0x6a, + 0x36, 0x02, 0x14, 0x20, 0x01, 0x20, 0x05, 0x6a, 0x21, 0x04, 0x0b, 0x20, + 0x04, 0x0b, 0x17, 0x00, 0x20, 0x01, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, + 0x10, 0x33, 0x22, 0x00, 0x46, 0x04, 0x40, 0x20, 0x01, 0x0f, 0x0b, 0x20, + 0x00, 0x0b, 0x52, 0x01, 0x02, 0x7f, 0x23, 0x00, 0x41, 0x10, 0x6b, 0x22, + 0x03, 0x24, 0x00, 0x41, 0x7f, 0x21, 0x04, 0x02, 0x40, 0x20, 0x02, 0x41, + 0x7f, 0x4c, 0x04, 0x40, 0x41, 0xe0, 0x1f, 0x41, 0x1c, 0x36, 0x02, 0x00, + 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x41, + 0x0c, 0x6a, 0x10, 0x0e, 0x22, 0x00, 0x04, 0x40, 0x41, 0xe0, 0x1f, 0x20, + 0x00, 0x36, 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x28, 0x02, 0x0c, + 0x21, 0x04, 0x0b, 0x20, 0x03, 0x41, 0x10, 0x6a, 0x24, 0x00, 0x20, 0x04, + 0x0b, 0x96, 0x02, 0x01, 0x06, 0x7f, 0x23, 0x00, 0x41, 0x10, 0x6b, 0x22, + 0x03, 0x24, 0x00, 0x20, 0x03, 0x20, 0x02, 0x36, 0x02, 0x0c, 0x20, 0x03, + 0x20, 0x01, 0x36, 0x02, 0x08, 0x20, 0x03, 0x20, 0x00, 0x28, 0x02, 0x18, + 0x22, 0x01, 0x36, 0x02, 0x00, 0x20, 0x03, 0x20, 0x00, 0x28, 0x02, 0x14, + 0x20, 0x01, 0x6b, 0x22, 0x01, 0x36, 0x02, 0x04, 0x41, 0x02, 0x21, 0x06, + 0x02, 0x7f, 0x20, 0x01, 0x20, 0x02, 0x6a, 0x22, 0x07, 0x20, 0x00, 0x28, + 0x02, 0x38, 0x20, 0x03, 0x41, 0x02, 0x10, 0x35, 0x22, 0x04, 0x47, 0x04, + 0x40, 0x20, 0x03, 0x21, 0x01, 0x03, 0x40, 0x20, 0x04, 0x41, 0x7f, 0x4c, + 0x04, 0x40, 0x20, 0x00, 0x41, 0x00, 0x36, 0x02, 0x18, 0x20, 0x00, 0x42, + 0x00, 0x37, 0x03, 0x10, 0x20, 0x00, 0x20, 0x00, 0x28, 0x02, 0x00, 0x41, + 0x20, 0x72, 0x36, 0x02, 0x00, 0x41, 0x00, 0x20, 0x06, 0x41, 0x02, 0x46, + 0x0d, 0x03, 0x1a, 0x20, 0x02, 0x20, 0x01, 0x28, 0x02, 0x04, 0x6b, 0x0c, + 0x03, 0x0b, 0x20, 0x01, 0x41, 0x08, 0x6a, 0x20, 0x01, 0x20, 0x04, 0x20, + 0x01, 0x28, 0x02, 0x04, 0x22, 0x08, 0x4b, 0x22, 0x05, 0x1b, 0x22, 0x01, + 0x20, 0x04, 0x20, 0x08, 0x41, 0x00, 0x20, 0x05, 0x1b, 0x6b, 0x22, 0x08, + 0x20, 0x01, 0x28, 0x02, 0x00, 0x6a, 0x36, 0x02, 0x00, 0x20, 0x01, 0x20, + 0x01, 0x28, 0x02, 0x04, 0x20, 0x08, 0x6b, 0x36, 0x02, 0x04, 0x20, 0x07, + 0x20, 0x04, 0x6b, 0x21, 0x07, 0x20, 0x00, 0x28, 0x02, 0x38, 0x20, 0x01, + 0x20, 0x06, 0x20, 0x05, 0x6b, 0x22, 0x06, 0x10, 0x35, 0x22, 0x05, 0x21, + 0x04, 0x20, 0x05, 0x20, 0x07, 0x47, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x00, + 0x20, 0x00, 0x28, 0x02, 0x28, 0x22, 0x01, 0x36, 0x02, 0x18, 0x20, 0x00, + 0x20, 0x01, 0x36, 0x02, 0x14, 0x20, 0x00, 0x20, 0x01, 0x20, 0x00, 0x28, + 0x02, 0x2c, 0x6a, 0x36, 0x02, 0x10, 0x20, 0x02, 0x0b, 0x20, 0x03, 0x41, + 0x10, 0x6a, 0x24, 0x00, 0x0b, 0x20, 0x01, 0x02, 0x7f, 0x20, 0x00, 0x10, + 0x38, 0x41, 0x01, 0x6a, 0x22, 0x01, 0x10, 0x14, 0x22, 0x02, 0x45, 0x04, + 0x40, 0x41, 0x00, 0x0f, 0x0b, 0x20, 0x02, 0x20, 0x00, 0x20, 0x01, 0x10, + 0x39, 0x0b, 0xa4, 0x01, 0x01, 0x03, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x02, + 0x40, 0x20, 0x00, 0x22, 0x01, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, 0x20, + 0x00, 0x2d, 0x00, 0x00, 0x45, 0x04, 0x40, 0x41, 0x00, 0x0f, 0x0b, 0x20, + 0x00, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x03, 0x40, 0x20, 0x01, 0x41, 0x03, + 0x71, 0x45, 0x0d, 0x01, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x20, 0x01, 0x41, + 0x01, 0x6a, 0x22, 0x03, 0x21, 0x01, 0x0d, 0x00, 0x0b, 0x0c, 0x01, 0x0b, + 0x20, 0x01, 0x41, 0x7c, 0x6a, 0x21, 0x01, 0x03, 0x40, 0x20, 0x01, 0x41, + 0x04, 0x6a, 0x22, 0x01, 0x28, 0x02, 0x00, 0x22, 0x02, 0x41, 0x7f, 0x73, + 0x20, 0x02, 0x41, 0xff, 0xfd, 0xfb, 0x77, 0x6a, 0x71, 0x41, 0x80, 0x81, + 0x82, 0x84, 0x78, 0x71, 0x45, 0x0d, 0x00, 0x0b, 0x20, 0x02, 0x41, 0xff, + 0x01, 0x71, 0x45, 0x04, 0x40, 0x20, 0x01, 0x20, 0x00, 0x6b, 0x0f, 0x0b, + 0x03, 0x40, 0x20, 0x01, 0x2d, 0x00, 0x01, 0x20, 0x01, 0x41, 0x01, 0x6a, + 0x22, 0x02, 0x21, 0x01, 0x0d, 0x00, 0x0b, 0x0c, 0x01, 0x0b, 0x20, 0x03, + 0x41, 0x7f, 0x6a, 0x21, 0x02, 0x0b, 0x20, 0x02, 0x20, 0x00, 0x6b, 0x0b, + 0x92, 0x0b, 0x01, 0x08, 0x7f, 0x02, 0x40, 0x02, 0x40, 0x20, 0x02, 0x45, + 0x0d, 0x00, 0x20, 0x01, 0x41, 0x03, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x00, + 0x21, 0x03, 0x03, 0x40, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x3a, + 0x00, 0x00, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x21, 0x04, 0x20, 0x03, 0x41, + 0x01, 0x6a, 0x21, 0x03, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, + 0x02, 0x41, 0x01, 0x46, 0x0d, 0x02, 0x20, 0x04, 0x21, 0x02, 0x20, 0x01, + 0x41, 0x03, 0x71, 0x0d, 0x00, 0x0b, 0x0c, 0x01, 0x0b, 0x20, 0x02, 0x21, + 0x04, 0x20, 0x00, 0x21, 0x03, 0x0b, 0x02, 0x40, 0x20, 0x03, 0x41, 0x03, + 0x71, 0x22, 0x02, 0x45, 0x04, 0x40, 0x02, 0x40, 0x20, 0x04, 0x41, 0x10, + 0x49, 0x04, 0x40, 0x20, 0x04, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x20, 0x04, + 0x41, 0x70, 0x6a, 0x21, 0x02, 0x03, 0x40, 0x20, 0x03, 0x20, 0x01, 0x28, + 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, 0x03, 0x41, 0x04, 0x6a, 0x20, 0x01, + 0x41, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, 0x03, 0x41, + 0x08, 0x6a, 0x20, 0x01, 0x41, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x36, 0x02, + 0x00, 0x20, 0x03, 0x41, 0x0c, 0x6a, 0x20, 0x01, 0x41, 0x0c, 0x6a, 0x28, + 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, 0x03, 0x41, 0x10, 0x6a, 0x21, 0x03, + 0x20, 0x01, 0x41, 0x10, 0x6a, 0x21, 0x01, 0x20, 0x04, 0x41, 0x70, 0x6a, + 0x22, 0x04, 0x41, 0x0f, 0x4b, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x02, 0x41, + 0x08, 0x71, 0x04, 0x40, 0x20, 0x03, 0x20, 0x01, 0x29, 0x02, 0x00, 0x37, + 0x02, 0x00, 0x20, 0x03, 0x41, 0x08, 0x6a, 0x21, 0x03, 0x20, 0x01, 0x41, + 0x08, 0x6a, 0x21, 0x01, 0x0b, 0x20, 0x02, 0x41, 0x04, 0x71, 0x04, 0x40, + 0x20, 0x03, 0x20, 0x01, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, 0x03, + 0x41, 0x04, 0x6a, 0x21, 0x03, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, 0x01, + 0x0b, 0x20, 0x02, 0x41, 0x02, 0x71, 0x04, 0x40, 0x20, 0x03, 0x20, 0x01, + 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, + 0x01, 0x3a, 0x00, 0x01, 0x20, 0x03, 0x41, 0x02, 0x6a, 0x21, 0x03, 0x20, + 0x01, 0x41, 0x02, 0x6a, 0x21, 0x01, 0x0b, 0x20, 0x02, 0x41, 0x01, 0x71, + 0x45, 0x0d, 0x01, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x3a, 0x00, + 0x00, 0x20, 0x00, 0x0f, 0x0b, 0x02, 0x40, 0x20, 0x04, 0x41, 0x20, 0x49, + 0x0d, 0x00, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x22, 0x02, 0x41, 0x02, 0x4b, + 0x0d, 0x00, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x02, 0x41, 0x01, + 0x6b, 0x0e, 0x02, 0x01, 0x02, 0x00, 0x0b, 0x20, 0x03, 0x20, 0x01, 0x2d, + 0x00, 0x01, 0x3a, 0x00, 0x01, 0x20, 0x03, 0x20, 0x01, 0x28, 0x02, 0x00, + 0x22, 0x05, 0x3a, 0x00, 0x00, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x02, + 0x3a, 0x00, 0x02, 0x20, 0x04, 0x41, 0x7d, 0x6a, 0x21, 0x08, 0x20, 0x03, + 0x41, 0x03, 0x6a, 0x21, 0x09, 0x20, 0x04, 0x41, 0x6c, 0x6a, 0x41, 0x70, + 0x71, 0x21, 0x0a, 0x41, 0x00, 0x21, 0x02, 0x03, 0x40, 0x20, 0x02, 0x20, + 0x09, 0x6a, 0x22, 0x03, 0x20, 0x01, 0x20, 0x02, 0x6a, 0x22, 0x06, 0x41, + 0x04, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, 0x08, 0x74, 0x20, 0x05, + 0x41, 0x18, 0x76, 0x72, 0x36, 0x02, 0x00, 0x20, 0x03, 0x41, 0x04, 0x6a, + 0x20, 0x06, 0x41, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x05, 0x41, 0x08, + 0x74, 0x20, 0x07, 0x41, 0x18, 0x76, 0x72, 0x36, 0x02, 0x00, 0x20, 0x03, + 0x41, 0x08, 0x6a, 0x20, 0x06, 0x41, 0x0c, 0x6a, 0x28, 0x02, 0x00, 0x22, + 0x07, 0x41, 0x08, 0x74, 0x20, 0x05, 0x41, 0x18, 0x76, 0x72, 0x36, 0x02, + 0x00, 0x20, 0x03, 0x41, 0x0c, 0x6a, 0x20, 0x06, 0x41, 0x10, 0x6a, 0x28, + 0x02, 0x00, 0x22, 0x05, 0x41, 0x08, 0x74, 0x20, 0x07, 0x41, 0x18, 0x76, + 0x72, 0x36, 0x02, 0x00, 0x20, 0x02, 0x41, 0x10, 0x6a, 0x21, 0x02, 0x20, + 0x08, 0x41, 0x70, 0x6a, 0x22, 0x08, 0x41, 0x10, 0x4b, 0x0d, 0x00, 0x0b, + 0x20, 0x02, 0x20, 0x09, 0x6a, 0x21, 0x03, 0x20, 0x01, 0x20, 0x02, 0x6a, + 0x41, 0x03, 0x6a, 0x21, 0x01, 0x20, 0x04, 0x20, 0x0a, 0x6b, 0x41, 0x6d, + 0x6a, 0x21, 0x04, 0x0c, 0x02, 0x0b, 0x20, 0x03, 0x20, 0x01, 0x28, 0x02, + 0x00, 0x22, 0x05, 0x3a, 0x00, 0x00, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, + 0x01, 0x3a, 0x00, 0x01, 0x20, 0x04, 0x41, 0x7e, 0x6a, 0x21, 0x08, 0x20, + 0x03, 0x41, 0x02, 0x6a, 0x21, 0x09, 0x20, 0x04, 0x41, 0x6c, 0x6a, 0x41, + 0x70, 0x71, 0x21, 0x0a, 0x41, 0x00, 0x21, 0x02, 0x03, 0x40, 0x20, 0x02, + 0x20, 0x09, 0x6a, 0x22, 0x03, 0x20, 0x01, 0x20, 0x02, 0x6a, 0x22, 0x06, + 0x41, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, 0x10, 0x74, 0x20, + 0x05, 0x41, 0x10, 0x76, 0x72, 0x36, 0x02, 0x00, 0x20, 0x03, 0x41, 0x04, + 0x6a, 0x20, 0x06, 0x41, 0x08, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x05, 0x41, + 0x10, 0x74, 0x20, 0x07, 0x41, 0x10, 0x76, 0x72, 0x36, 0x02, 0x00, 0x20, + 0x03, 0x41, 0x08, 0x6a, 0x20, 0x06, 0x41, 0x0c, 0x6a, 0x28, 0x02, 0x00, + 0x22, 0x07, 0x41, 0x10, 0x74, 0x20, 0x05, 0x41, 0x10, 0x76, 0x72, 0x36, + 0x02, 0x00, 0x20, 0x03, 0x41, 0x0c, 0x6a, 0x20, 0x06, 0x41, 0x10, 0x6a, + 0x28, 0x02, 0x00, 0x22, 0x05, 0x41, 0x10, 0x74, 0x20, 0x07, 0x41, 0x10, + 0x76, 0x72, 0x36, 0x02, 0x00, 0x20, 0x02, 0x41, 0x10, 0x6a, 0x21, 0x02, + 0x20, 0x08, 0x41, 0x70, 0x6a, 0x22, 0x08, 0x41, 0x11, 0x4b, 0x0d, 0x00, + 0x0b, 0x20, 0x02, 0x20, 0x09, 0x6a, 0x21, 0x03, 0x20, 0x01, 0x20, 0x02, + 0x6a, 0x41, 0x02, 0x6a, 0x21, 0x01, 0x20, 0x04, 0x20, 0x0a, 0x6b, 0x41, + 0x6e, 0x6a, 0x21, 0x04, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x20, 0x01, 0x28, + 0x02, 0x00, 0x22, 0x05, 0x3a, 0x00, 0x00, 0x20, 0x04, 0x41, 0x7f, 0x6a, + 0x21, 0x08, 0x20, 0x03, 0x41, 0x01, 0x6a, 0x21, 0x09, 0x20, 0x04, 0x41, + 0x6c, 0x6a, 0x41, 0x70, 0x71, 0x21, 0x0a, 0x41, 0x00, 0x21, 0x02, 0x03, + 0x40, 0x20, 0x02, 0x20, 0x09, 0x6a, 0x22, 0x03, 0x20, 0x01, 0x20, 0x02, + 0x6a, 0x22, 0x06, 0x41, 0x04, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, + 0x18, 0x74, 0x20, 0x05, 0x41, 0x08, 0x76, 0x72, 0x36, 0x02, 0x00, 0x20, + 0x03, 0x41, 0x04, 0x6a, 0x20, 0x06, 0x41, 0x08, 0x6a, 0x28, 0x02, 0x00, + 0x22, 0x05, 0x41, 0x18, 0x74, 0x20, 0x07, 0x41, 0x08, 0x76, 0x72, 0x36, + 0x02, 0x00, 0x20, 0x03, 0x41, 0x08, 0x6a, 0x20, 0x06, 0x41, 0x0c, 0x6a, + 0x28, 0x02, 0x00, 0x22, 0x07, 0x41, 0x18, 0x74, 0x20, 0x05, 0x41, 0x08, + 0x76, 0x72, 0x36, 0x02, 0x00, 0x20, 0x03, 0x41, 0x0c, 0x6a, 0x20, 0x06, + 0x41, 0x10, 0x6a, 0x28, 0x02, 0x00, 0x22, 0x05, 0x41, 0x18, 0x74, 0x20, + 0x07, 0x41, 0x08, 0x76, 0x72, 0x36, 0x02, 0x00, 0x20, 0x02, 0x41, 0x10, + 0x6a, 0x21, 0x02, 0x20, 0x08, 0x41, 0x70, 0x6a, 0x22, 0x08, 0x41, 0x12, + 0x4b, 0x0d, 0x00, 0x0b, 0x20, 0x02, 0x20, 0x09, 0x6a, 0x21, 0x03, 0x20, + 0x01, 0x20, 0x02, 0x6a, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, 0x04, 0x20, + 0x0a, 0x6b, 0x41, 0x6f, 0x6a, 0x21, 0x04, 0x0b, 0x20, 0x04, 0x41, 0x10, + 0x71, 0x04, 0x40, 0x20, 0x03, 0x20, 0x01, 0x2f, 0x00, 0x00, 0x3b, 0x00, + 0x00, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x02, 0x3a, 0x00, 0x02, 0x20, + 0x03, 0x20, 0x01, 0x2d, 0x00, 0x03, 0x3a, 0x00, 0x03, 0x20, 0x03, 0x20, + 0x01, 0x2d, 0x00, 0x04, 0x3a, 0x00, 0x04, 0x20, 0x03, 0x20, 0x01, 0x2d, + 0x00, 0x05, 0x3a, 0x00, 0x05, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x06, + 0x3a, 0x00, 0x06, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x07, 0x3a, 0x00, + 0x07, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x08, 0x3a, 0x00, 0x08, 0x20, + 0x03, 0x20, 0x01, 0x2d, 0x00, 0x09, 0x3a, 0x00, 0x09, 0x20, 0x03, 0x20, + 0x01, 0x2d, 0x00, 0x0a, 0x3a, 0x00, 0x0a, 0x20, 0x03, 0x20, 0x01, 0x2d, + 0x00, 0x0b, 0x3a, 0x00, 0x0b, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x0c, + 0x3a, 0x00, 0x0c, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x0d, 0x3a, 0x00, + 0x0d, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x0e, 0x3a, 0x00, 0x0e, 0x20, + 0x03, 0x20, 0x01, 0x2d, 0x00, 0x0f, 0x3a, 0x00, 0x0f, 0x20, 0x03, 0x41, + 0x10, 0x6a, 0x21, 0x03, 0x20, 0x01, 0x41, 0x10, 0x6a, 0x21, 0x01, 0x0b, + 0x20, 0x04, 0x41, 0x08, 0x71, 0x04, 0x40, 0x20, 0x03, 0x20, 0x01, 0x2d, + 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x01, + 0x3a, 0x00, 0x01, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x02, 0x3a, 0x00, + 0x02, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x03, 0x3a, 0x00, 0x03, 0x20, + 0x03, 0x20, 0x01, 0x2d, 0x00, 0x04, 0x3a, 0x00, 0x04, 0x20, 0x03, 0x20, + 0x01, 0x2d, 0x00, 0x05, 0x3a, 0x00, 0x05, 0x20, 0x03, 0x20, 0x01, 0x2d, + 0x00, 0x06, 0x3a, 0x00, 0x06, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x07, + 0x3a, 0x00, 0x07, 0x20, 0x03, 0x41, 0x08, 0x6a, 0x21, 0x03, 0x20, 0x01, + 0x41, 0x08, 0x6a, 0x21, 0x01, 0x0b, 0x20, 0x04, 0x41, 0x04, 0x71, 0x04, + 0x40, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x20, + 0x03, 0x20, 0x01, 0x2d, 0x00, 0x01, 0x3a, 0x00, 0x01, 0x20, 0x03, 0x20, + 0x01, 0x2d, 0x00, 0x02, 0x3a, 0x00, 0x02, 0x20, 0x03, 0x20, 0x01, 0x2d, + 0x00, 0x03, 0x3a, 0x00, 0x03, 0x20, 0x03, 0x41, 0x04, 0x6a, 0x21, 0x03, + 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, 0x01, 0x0b, 0x20, 0x04, 0x41, 0x02, + 0x71, 0x04, 0x40, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x00, 0x3a, 0x00, + 0x00, 0x20, 0x03, 0x20, 0x01, 0x2d, 0x00, 0x01, 0x3a, 0x00, 0x01, 0x20, + 0x03, 0x41, 0x02, 0x6a, 0x21, 0x03, 0x20, 0x01, 0x41, 0x02, 0x6a, 0x21, + 0x01, 0x0b, 0x20, 0x04, 0x41, 0x01, 0x71, 0x45, 0x0d, 0x00, 0x20, 0x03, + 0x20, 0x01, 0x2d, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x0b, 0x20, 0x00, 0x0b, + 0xfa, 0x02, 0x02, 0x02, 0x7f, 0x01, 0x7e, 0x02, 0x40, 0x20, 0x02, 0x45, + 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x00, 0x20, + 0x02, 0x6a, 0x22, 0x03, 0x41, 0x7f, 0x6a, 0x20, 0x01, 0x3a, 0x00, 0x00, + 0x20, 0x02, 0x41, 0x03, 0x49, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, 0x3a, + 0x00, 0x02, 0x20, 0x00, 0x20, 0x01, 0x3a, 0x00, 0x01, 0x20, 0x03, 0x41, + 0x7d, 0x6a, 0x20, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x03, 0x41, 0x7e, 0x6a, + 0x20, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x02, 0x41, 0x07, 0x49, 0x0d, 0x00, + 0x20, 0x00, 0x20, 0x01, 0x3a, 0x00, 0x03, 0x20, 0x03, 0x41, 0x7c, 0x6a, + 0x20, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x02, 0x41, 0x09, 0x49, 0x0d, 0x00, + 0x20, 0x00, 0x41, 0x00, 0x20, 0x00, 0x6b, 0x41, 0x03, 0x71, 0x22, 0x04, + 0x6a, 0x22, 0x03, 0x20, 0x01, 0x41, 0xff, 0x01, 0x71, 0x41, 0x81, 0x82, + 0x84, 0x08, 0x6c, 0x22, 0x00, 0x36, 0x02, 0x00, 0x20, 0x03, 0x20, 0x02, + 0x20, 0x04, 0x6b, 0x41, 0x7c, 0x71, 0x22, 0x02, 0x6a, 0x22, 0x01, 0x41, + 0x7c, 0x6a, 0x20, 0x00, 0x36, 0x02, 0x00, 0x20, 0x02, 0x41, 0x09, 0x49, + 0x0d, 0x00, 0x20, 0x03, 0x20, 0x00, 0x36, 0x02, 0x08, 0x20, 0x03, 0x20, + 0x00, 0x36, 0x02, 0x04, 0x20, 0x01, 0x41, 0x78, 0x6a, 0x20, 0x00, 0x36, + 0x02, 0x00, 0x20, 0x01, 0x41, 0x74, 0x6a, 0x20, 0x00, 0x36, 0x02, 0x00, + 0x20, 0x02, 0x41, 0x19, 0x49, 0x0d, 0x00, 0x20, 0x03, 0x20, 0x00, 0x36, + 0x02, 0x18, 0x20, 0x03, 0x20, 0x00, 0x36, 0x02, 0x14, 0x20, 0x03, 0x20, + 0x00, 0x36, 0x02, 0x10, 0x20, 0x03, 0x20, 0x00, 0x36, 0x02, 0x0c, 0x20, + 0x01, 0x41, 0x70, 0x6a, 0x20, 0x00, 0x36, 0x02, 0x00, 0x20, 0x01, 0x41, + 0x6c, 0x6a, 0x20, 0x00, 0x36, 0x02, 0x00, 0x20, 0x01, 0x41, 0x68, 0x6a, + 0x20, 0x00, 0x36, 0x02, 0x00, 0x20, 0x01, 0x41, 0x64, 0x6a, 0x20, 0x00, + 0x36, 0x02, 0x00, 0x20, 0x02, 0x20, 0x03, 0x41, 0x04, 0x71, 0x41, 0x18, + 0x72, 0x22, 0x01, 0x6b, 0x22, 0x02, 0x41, 0x20, 0x49, 0x0d, 0x00, 0x20, + 0x00, 0xad, 0x22, 0x05, 0x42, 0x20, 0x86, 0x20, 0x05, 0x84, 0x21, 0x05, + 0x20, 0x01, 0x20, 0x03, 0x6a, 0x21, 0x01, 0x03, 0x40, 0x20, 0x01, 0x20, + 0x05, 0x37, 0x03, 0x00, 0x20, 0x01, 0x41, 0x18, 0x6a, 0x20, 0x05, 0x37, + 0x03, 0x00, 0x20, 0x01, 0x41, 0x10, 0x6a, 0x20, 0x05, 0x37, 0x03, 0x00, + 0x20, 0x01, 0x41, 0x08, 0x6a, 0x20, 0x05, 0x37, 0x03, 0x00, 0x20, 0x01, + 0x41, 0x20, 0x6a, 0x21, 0x01, 0x20, 0x02, 0x41, 0x60, 0x6a, 0x22, 0x02, + 0x41, 0x1f, 0x4b, 0x0d, 0x00, 0x0b, 0x0b, 0x0b, 0x5a, 0x01, 0x03, 0x7f, + 0x41, 0x8f, 0x09, 0x2d, 0x00, 0x00, 0x21, 0x01, 0x02, 0x40, 0x20, 0x00, + 0x2d, 0x00, 0x00, 0x22, 0x02, 0x45, 0x0d, 0x00, 0x20, 0x01, 0x20, 0x02, + 0x47, 0x0d, 0x00, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x21, 0x00, 0x41, 0x90, + 0x09, 0x21, 0x03, 0x03, 0x40, 0x20, 0x03, 0x2d, 0x00, 0x00, 0x21, 0x01, + 0x20, 0x00, 0x2d, 0x00, 0x00, 0x22, 0x02, 0x45, 0x0d, 0x01, 0x20, 0x00, + 0x41, 0x01, 0x6a, 0x21, 0x00, 0x20, 0x03, 0x41, 0x01, 0x6a, 0x21, 0x03, + 0x20, 0x01, 0x20, 0x02, 0x46, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x02, 0x20, + 0x01, 0x6b, 0x0b, 0xd7, 0x01, 0x01, 0x02, 0x7f, 0x20, 0x01, 0x41, 0x00, + 0x47, 0x21, 0x03, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x01, 0x45, + 0x04, 0x40, 0x20, 0x01, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x41, + 0x03, 0x71, 0x45, 0x04, 0x40, 0x20, 0x01, 0x21, 0x02, 0x0c, 0x01, 0x0b, + 0x03, 0x40, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x45, 0x04, 0x40, 0x20, 0x01, + 0x21, 0x02, 0x0c, 0x03, 0x0b, 0x20, 0x01, 0x41, 0x01, 0x47, 0x21, 0x03, + 0x20, 0x01, 0x41, 0x7f, 0x6a, 0x21, 0x02, 0x20, 0x00, 0x41, 0x01, 0x6a, + 0x21, 0x00, 0x20, 0x01, 0x41, 0x01, 0x46, 0x0d, 0x01, 0x20, 0x02, 0x21, + 0x01, 0x20, 0x00, 0x41, 0x03, 0x71, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x03, + 0x45, 0x0d, 0x01, 0x0b, 0x02, 0x40, 0x20, 0x00, 0x2d, 0x00, 0x00, 0x45, + 0x0d, 0x00, 0x20, 0x02, 0x41, 0x04, 0x49, 0x0d, 0x00, 0x03, 0x40, 0x20, + 0x00, 0x28, 0x02, 0x00, 0x22, 0x01, 0x41, 0x7f, 0x73, 0x20, 0x01, 0x41, + 0xff, 0xfd, 0xfb, 0x77, 0x6a, 0x71, 0x41, 0x80, 0x81, 0x82, 0x84, 0x78, + 0x71, 0x0d, 0x01, 0x20, 0x00, 0x41, 0x04, 0x6a, 0x21, 0x00, 0x20, 0x02, + 0x41, 0x7c, 0x6a, 0x22, 0x02, 0x41, 0x03, 0x4b, 0x0d, 0x00, 0x0b, 0x0b, + 0x20, 0x02, 0x45, 0x0d, 0x00, 0x03, 0x40, 0x20, 0x00, 0x2d, 0x00, 0x00, + 0x45, 0x04, 0x40, 0x20, 0x00, 0x0f, 0x0b, 0x20, 0x00, 0x41, 0x01, 0x6a, + 0x21, 0x00, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x22, 0x02, 0x0d, 0x00, 0x0b, + 0x0b, 0x41, 0x00, 0x0b, 0x11, 0x00, 0x20, 0x00, 0x45, 0x04, 0x40, 0x41, + 0x00, 0x0f, 0x0b, 0x20, 0x00, 0x20, 0x01, 0x10, 0x3e, 0x0b, 0x8c, 0x02, + 0x00, 0x20, 0x00, 0x04, 0x7f, 0x20, 0x01, 0x41, 0xff, 0x00, 0x4d, 0x04, + 0x40, 0x20, 0x00, 0x20, 0x01, 0x3a, 0x00, 0x00, 0x41, 0x01, 0x0f, 0x0b, + 0x02, 0x40, 0x41, 0xf0, 0x1f, 0x28, 0x02, 0x00, 0x45, 0x04, 0x40, 0x20, + 0x01, 0x41, 0x80, 0x7f, 0x71, 0x41, 0x80, 0xbf, 0x03, 0x47, 0x0d, 0x01, + 0x20, 0x00, 0x20, 0x01, 0x3a, 0x00, 0x00, 0x41, 0x01, 0x0f, 0x0b, 0x20, + 0x01, 0x41, 0xff, 0x0f, 0x4d, 0x04, 0x40, 0x20, 0x00, 0x20, 0x01, 0x41, + 0x3f, 0x71, 0x41, 0x80, 0x01, 0x72, 0x3a, 0x00, 0x01, 0x20, 0x00, 0x20, + 0x01, 0x41, 0x06, 0x76, 0x41, 0xc0, 0x01, 0x72, 0x3a, 0x00, 0x00, 0x41, + 0x02, 0x0f, 0x0b, 0x20, 0x01, 0x41, 0x80, 0xb0, 0x03, 0x4f, 0x41, 0x00, + 0x20, 0x01, 0x41, 0x80, 0x40, 0x71, 0x41, 0x80, 0xc0, 0x03, 0x47, 0x1b, + 0x45, 0x04, 0x40, 0x20, 0x00, 0x20, 0x01, 0x41, 0x3f, 0x71, 0x41, 0x80, + 0x01, 0x72, 0x3a, 0x00, 0x02, 0x20, 0x00, 0x20, 0x01, 0x41, 0x0c, 0x76, + 0x41, 0xe0, 0x01, 0x72, 0x3a, 0x00, 0x00, 0x20, 0x00, 0x20, 0x01, 0x41, + 0x06, 0x76, 0x41, 0x3f, 0x71, 0x41, 0x80, 0x01, 0x72, 0x3a, 0x00, 0x01, + 0x41, 0x03, 0x0f, 0x0b, 0x20, 0x01, 0x41, 0x80, 0x80, 0x7c, 0x6a, 0x41, + 0xff, 0xff, 0x3f, 0x4d, 0x04, 0x40, 0x20, 0x00, 0x20, 0x01, 0x41, 0x3f, + 0x71, 0x41, 0x80, 0x01, 0x72, 0x3a, 0x00, 0x03, 0x20, 0x00, 0x20, 0x01, + 0x41, 0x12, 0x76, 0x41, 0xf0, 0x01, 0x72, 0x3a, 0x00, 0x00, 0x20, 0x00, + 0x20, 0x01, 0x41, 0x06, 0x76, 0x41, 0x3f, 0x71, 0x41, 0x80, 0x01, 0x72, + 0x3a, 0x00, 0x02, 0x20, 0x00, 0x20, 0x01, 0x41, 0x0c, 0x76, 0x41, 0x3f, + 0x71, 0x41, 0x80, 0x01, 0x72, 0x3a, 0x00, 0x01, 0x41, 0x04, 0x0f, 0x0b, + 0x0b, 0x41, 0xe0, 0x1f, 0x41, 0x19, 0x36, 0x02, 0x00, 0x41, 0x7f, 0x05, + 0x41, 0x01, 0x0b, 0x0b, 0x81, 0x01, 0x02, 0x01, 0x7f, 0x01, 0x7e, 0x20, + 0x00, 0xbd, 0x22, 0x03, 0x42, 0x34, 0x88, 0xa7, 0x41, 0xff, 0x0f, 0x71, + 0x22, 0x02, 0x41, 0xff, 0x0f, 0x47, 0x04, 0x7c, 0x20, 0x02, 0x45, 0x04, + 0x40, 0x20, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x61, 0x04, 0x40, 0x20, 0x01, 0x41, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00, + 0x0f, 0x0b, 0x20, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, + 0x43, 0xa2, 0x20, 0x01, 0x10, 0x3f, 0x20, 0x01, 0x20, 0x01, 0x28, 0x02, + 0x00, 0x41, 0x40, 0x6a, 0x36, 0x02, 0x00, 0x0f, 0x0b, 0x20, 0x01, 0x20, + 0x02, 0x41, 0x82, 0x78, 0x6a, 0x36, 0x02, 0x00, 0x20, 0x03, 0x42, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x87, 0x80, 0x7f, 0x83, 0x42, 0x80, + 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xf0, 0x3f, 0x84, 0xbf, 0x05, 0x20, + 0x00, 0x0b, 0x0b, 0x0b, 0xa0, 0x13, 0x1b, 0x00, 0x41, 0x80, 0x08, 0x0b, + 0xa5, 0x01, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x6f, + 0x72, 0x20, 0x4f, 0x4b, 0x0a, 0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, + 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x0a, 0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, + 0x20, 0x25, 0x73, 0x21, 0x0a, 0x00, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x66, + 0x00, 0x41, 0x72, 0x67, 0x73, 0x3a, 0x20, 0x00, 0x25, 0x73, 0x3b, 0x20, + 0x00, 0x25, 0x64, 0x20, 0x2b, 0x20, 0x25, 0x64, 0x20, 0x3d, 0x20, 0x25, + 0x64, 0x0a, 0x00, 0x4e, 0x6f, 0x77, 0x3a, 0x20, 0x25, 0x6c, 0x6c, 0x64, + 0x20, 0x73, 0x65, 0x63, 0x2c, 0x20, 0x25, 0x6c, 0x64, 0x20, 0x6e, 0x73, + 0x0a, 0x00, 0x66, 0x69, 0x62, 0x28, 0x25, 0x64, 0x29, 0x20, 0x3d, 0x20, + 0x00, 0x25, 0x64, 0x20, 0x5b, 0x25, 0x2e, 0x33, 0x66, 0x20, 0x6d, 0x73, + 0x5d, 0x0a, 0x00, 0x25, 0x30, 0x32, 0x78, 0x20, 0x00, 0x43, 0x61, 0x6e, + 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x25, 0x73, 0x0a, + 0x00, 0x63, 0x61, 0x74, 0x00, 0x3d, 0x3d, 0x3d, 0x20, 0x64, 0x6f, 0x6e, + 0x65, 0x20, 0x3d, 0x3d, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x00, + 0x41, 0xb1, 0x09, 0x0b, 0x85, 0x0d, 0x19, 0x12, 0x44, 0x3b, 0x02, 0x3f, + 0x2c, 0x47, 0x14, 0x3d, 0x33, 0x30, 0x0a, 0x1b, 0x06, 0x46, 0x4b, 0x45, + 0x37, 0x0f, 0x49, 0x0e, 0x17, 0x03, 0x40, 0x1d, 0x3c, 0x2b, 0x36, 0x1f, + 0x4a, 0x2d, 0x1c, 0x01, 0x20, 0x25, 0x29, 0x21, 0x08, 0x0c, 0x15, 0x16, + 0x22, 0x2e, 0x10, 0x38, 0x3e, 0x0b, 0x34, 0x31, 0x18, 0x2f, 0x41, 0x09, + 0x39, 0x11, 0x23, 0x43, 0x32, 0x42, 0x3a, 0x05, 0x04, 0x26, 0x28, 0x27, + 0x0d, 0x2a, 0x1e, 0x35, 0x07, 0x1a, 0x48, 0x13, 0x24, 0x4c, 0xff, 0x00, + 0x00, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x00, 0x49, 0x6c, 0x6c, + 0x65, 0x67, 0x61, 0x6c, 0x20, 0x62, 0x79, 0x74, 0x65, 0x20, 0x73, 0x65, + 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x00, 0x44, 0x6f, 0x6d, 0x61, 0x69, + 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x00, 0x52, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, 0x65, 0x70, 0x72, 0x65, + 0x73, 0x65, 0x6e, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x4e, 0x6f, 0x74, + 0x20, 0x61, 0x20, 0x74, 0x74, 0x79, 0x00, 0x50, 0x65, 0x72, 0x6d, 0x69, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x64, 0x65, 0x6e, 0x69, 0x65, 0x64, + 0x00, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6e, + 0x6f, 0x74, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x74, 0x65, 0x64, + 0x00, 0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x20, 0x6f, 0x72, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, + 0x72, 0x79, 0x00, 0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, 0x70, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x00, 0x46, 0x69, 0x6c, 0x65, 0x20, + 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x00, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x64, 0x61, 0x74, 0x61, 0x20, 0x74, 0x79, 0x70, 0x65, + 0x00, 0x4e, 0x6f, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x6c, 0x65, + 0x66, 0x74, 0x20, 0x6f, 0x6e, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x00, 0x4f, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x65, 0x6d, 0x6f, + 0x72, 0x79, 0x00, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x20, + 0x62, 0x75, 0x73, 0x79, 0x00, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x72, 0x75, + 0x70, 0x74, 0x65, 0x64, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, + 0x63, 0x61, 0x6c, 0x6c, 0x00, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x20, 0x74, 0x65, 0x6d, 0x70, 0x6f, 0x72, 0x61, 0x72, 0x69, 0x6c, + 0x79, 0x20, 0x75, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, + 0x65, 0x00, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x73, 0x65, + 0x65, 0x6b, 0x00, 0x43, 0x72, 0x6f, 0x73, 0x73, 0x2d, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x00, 0x52, 0x65, 0x61, + 0x64, 0x2d, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, + 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x00, 0x44, 0x69, 0x72, 0x65, 0x63, + 0x74, 0x6f, 0x72, 0x79, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x6d, 0x70, + 0x74, 0x79, 0x00, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x72, 0x65, 0x73, 0x65, 0x74, 0x20, 0x62, 0x79, 0x20, 0x70, + 0x65, 0x65, 0x72, 0x00, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x64, 0x20, 0x6f, 0x75, 0x74, 0x00, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, + 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x00, 0x48, 0x6f, 0x73, 0x74, 0x20, + 0x69, 0x73, 0x20, 0x75, 0x6e, 0x72, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, + 0x6c, 0x65, 0x00, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x69, + 0x6e, 0x20, 0x75, 0x73, 0x65, 0x00, 0x42, 0x72, 0x6f, 0x6b, 0x65, 0x6e, + 0x20, 0x70, 0x69, 0x70, 0x65, 0x00, 0x49, 0x2f, 0x4f, 0x20, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x00, 0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, 0x68, 0x20, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x00, 0x4e, 0x6f, 0x20, 0x73, 0x75, 0x63, + 0x68, 0x20, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x4e, 0x6f, 0x74, + 0x20, 0x61, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, + 0x00, 0x49, 0x73, 0x20, 0x61, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x79, 0x00, 0x54, 0x65, 0x78, 0x74, 0x20, 0x66, 0x69, 0x6c, + 0x65, 0x20, 0x62, 0x75, 0x73, 0x79, 0x00, 0x45, 0x78, 0x65, 0x63, 0x20, + 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x00, 0x49, 0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x61, 0x72, 0x67, + 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x00, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, + 0x6e, 0x74, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x74, 0x6f, 0x6f, 0x20, + 0x6c, 0x6f, 0x6e, 0x67, 0x00, 0x53, 0x79, 0x6d, 0x62, 0x6f, 0x6c, 0x69, + 0x63, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x6c, 0x6f, 0x6f, 0x70, 0x00, + 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x74, 0x6f, 0x6f, + 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x00, 0x54, 0x6f, 0x6f, 0x20, 0x6d, 0x61, + 0x6e, 0x79, 0x20, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x66, 0x69, 0x6c, 0x65, + 0x73, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x00, + 0x4e, 0x6f, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x20, 0x61, 0x76, 0x61, 0x69, + 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x42, 0x61, 0x64, 0x20, 0x66, 0x69, + 0x6c, 0x65, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, + 0x72, 0x00, 0x4e, 0x6f, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x70, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x00, 0x42, 0x61, 0x64, 0x20, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x00, 0x46, 0x69, 0x6c, 0x65, 0x20, + 0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x61, 0x72, 0x67, 0x65, 0x00, 0x54, 0x6f, + 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x73, + 0x00, 0x4e, 0x6f, 0x20, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x20, 0x61, 0x76, + 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x20, 0x64, 0x65, 0x61, 0x64, 0x6c, 0x6f, 0x63, + 0x6b, 0x20, 0x77, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x63, 0x63, 0x75, + 0x72, 0x00, 0x53, 0x74, 0x61, 0x74, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, + 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x00, + 0x50, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x20, 0x6f, 0x77, 0x6e, + 0x65, 0x72, 0x20, 0x64, 0x69, 0x65, 0x64, 0x00, 0x4f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, + 0x65, 0x64, 0x00, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x6e, 0x6f, 0x74, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x65, 0x64, 0x00, 0x4e, 0x6f, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x64, 0x65, 0x73, 0x69, 0x72, 0x65, + 0x64, 0x20, 0x74, 0x79, 0x70, 0x65, 0x00, 0x49, 0x64, 0x65, 0x6e, 0x74, + 0x69, 0x66, 0x69, 0x65, 0x72, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x64, 0x00, 0x4c, 0x69, 0x6e, 0x6b, 0x20, 0x68, 0x61, 0x73, 0x20, 0x62, + 0x65, 0x65, 0x6e, 0x20, 0x73, 0x65, 0x76, 0x65, 0x72, 0x65, 0x64, 0x00, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x00, 0x42, 0x61, 0x64, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x00, 0x4e, 0x6f, 0x74, 0x20, 0x61, 0x20, 0x73, 0x6f, 0x63, + 0x6b, 0x65, 0x74, 0x00, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, + 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x00, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x20, 0x6c, 0x61, 0x72, + 0x67, 0x65, 0x00, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x20, + 0x77, 0x72, 0x6f, 0x6e, 0x67, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x00, 0x50, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, + 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x00, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, + 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x4e, 0x6f, 0x74, 0x20, + 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, 0x41, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, + 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, + 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6c, 0x00, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x20, 0x6e, + 0x6f, 0x74, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, + 0x00, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x69, 0x73, 0x20, + 0x64, 0x6f, 0x77, 0x6e, 0x00, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, + 0x20, 0x75, 0x6e, 0x72, 0x65, 0x61, 0x63, 0x68, 0x61, 0x62, 0x6c, 0x65, + 0x00, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x72, 0x65, 0x73, 0x65, 0x74, 0x20, 0x62, 0x79, 0x20, 0x6e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x00, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x62, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x00, + 0x4e, 0x6f, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, + 0x65, 0x00, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x20, 0x69, 0x73, 0x20, + 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x00, 0x53, 0x6f, + 0x63, 0x6b, 0x65, 0x74, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x63, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x00, 0x4f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, + 0x20, 0x69, 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, + 0x00, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, + 0x6e, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x00, 0x53, + 0x74, 0x61, 0x6c, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x68, 0x61, + 0x6e, 0x64, 0x6c, 0x65, 0x00, 0x51, 0x75, 0x6f, 0x74, 0x61, 0x20, 0x65, + 0x78, 0x63, 0x65, 0x65, 0x64, 0x65, 0x64, 0x00, 0x4d, 0x75, 0x6c, 0x74, + 0x69, 0x68, 0x6f, 0x70, 0x20, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, + 0x65, 0x64, 0x00, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, + 0x69, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x73, 0x75, 0x66, 0x66, 0x69, 0x63, + 0x69, 0x65, 0x6e, 0x74, 0x00, 0x4e, 0x6f, 0x20, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x20, 0x69, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x00, 0x00, 0x2d, 0x2b, 0x20, 0x20, 0x20, 0x30, 0x58, 0x30, 0x78, + 0x00, 0x28, 0x6e, 0x75, 0x6c, 0x6c, 0x29, 0x00, 0x41, 0xc0, 0x16, 0x0b, + 0x18, 0x19, 0x00, 0x0a, 0x00, 0x19, 0x19, 0x19, 0x00, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, + 0x0b, 0x00, 0x41, 0xe0, 0x16, 0x0b, 0x21, 0x19, 0x00, 0x11, 0x0a, 0x19, + 0x19, 0x19, 0x03, 0x0a, 0x07, 0x00, 0x01, 0x1b, 0x09, 0x0b, 0x18, 0x00, + 0x00, 0x09, 0x06, 0x0b, 0x00, 0x00, 0x0b, 0x00, 0x06, 0x19, 0x00, 0x00, + 0x00, 0x19, 0x19, 0x19, 0x00, 0x41, 0x91, 0x17, 0x0b, 0x01, 0x0e, 0x00, + 0x41, 0x9a, 0x17, 0x0b, 0x18, 0x19, 0x00, 0x0a, 0x0d, 0x19, 0x19, 0x19, + 0x00, 0x0d, 0x00, 0x00, 0x02, 0x00, 0x09, 0x0e, 0x00, 0x00, 0x00, 0x09, + 0x00, 0x0e, 0x00, 0x00, 0x0e, 0x00, 0x41, 0xcb, 0x17, 0x0b, 0x01, 0x0c, + 0x00, 0x41, 0xd7, 0x17, 0x0b, 0x15, 0x13, 0x00, 0x00, 0x00, 0x00, 0x13, + 0x00, 0x00, 0x00, 0x00, 0x09, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, + 0x00, 0x00, 0x0c, 0x00, 0x41, 0x85, 0x18, 0x0b, 0x01, 0x10, 0x00, 0x41, + 0x91, 0x18, 0x0b, 0x15, 0x0f, 0x00, 0x00, 0x00, 0x04, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x09, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x10, 0x00, 0x41, 0xbf, 0x18, 0x0b, 0x01, 0x12, 0x00, 0x41, 0xcb, 0x18, + 0x0b, 0x1e, 0x11, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x12, 0x00, + 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x1a, 0x1a, 0x00, 0x41, 0x82, 0x19, + 0x0b, 0x0e, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x1a, 0x1a, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x00, 0x41, 0xb3, 0x19, 0x0b, 0x01, 0x14, 0x00, + 0x41, 0xbf, 0x19, 0x0b, 0x15, 0x17, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, + 0x00, 0x14, 0x00, 0x41, 0xed, 0x19, 0x0b, 0x01, 0x16, 0x00, 0x41, 0xf9, + 0x19, 0x0b, 0x99, 0x01, 0x15, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, + 0x00, 0x00, 0x09, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, + 0x16, 0x00, 0x00, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x66, + 0x6f, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x74, 0x69, 0x6e, + 0x67, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x20, 0x64, 0x6f, 0x75, 0x62, 0x6c, + 0x65, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x20, 0x69, 0x73, 0x20, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x20, 0x64, 0x69, + 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x2e, 0x0a, 0x54, 0x6f, 0x20, 0x65, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x69, 0x74, 0x2c, 0x20, 0x61, 0x64, + 0x64, 0x20, 0x2d, 0x6c, 0x63, 0x2d, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, + 0x63, 0x61, 0x6e, 0x2d, 0x6c, 0x6f, 0x6e, 0x67, 0x2d, 0x64, 0x6f, 0x75, + 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, + 0x69, 0x6e, 0x6b, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, + 0x0a, 0x00, 0x41, 0xa0, 0x1b, 0x0b, 0x3a, 0x30, 0x31, 0x32, 0x33, 0x34, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x2d, + 0x30, 0x58, 0x2b, 0x30, 0x58, 0x20, 0x30, 0x58, 0x2d, 0x30, 0x78, 0x2b, + 0x30, 0x78, 0x20, 0x30, 0x78, 0x00, 0x69, 0x6e, 0x66, 0x00, 0x49, 0x4e, + 0x46, 0x00, 0x6e, 0x61, 0x6e, 0x00, 0x4e, 0x41, 0x4e, 0x00, 0x2e, 0x00, + 0x00, 0x00, 0x00, 0x30, 0x14, 0x00, 0x41, 0xb0, 0x28, 0x0b, 0x01, 0x05, + 0x00, 0x41, 0xbc, 0x28, 0x0b, 0x01, 0x01, 0x00, 0x41, 0xd0, 0x28, 0x0b, + 0x0e, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18, 0x10, 0x00, + 0x00, 0x00, 0x04, 0x00, 0x41, 0xe8, 0x28, 0x0b, 0x09, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x41, 0xa0, 0x29, 0x0b, 0x09, + 0x30, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x41, 0xb4, + 0x29, 0x0b, 0x01, 0x01, 0x00, 0x41, 0xc8, 0x29, 0x0b, 0x0a, 0x04, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x24, 0x14, 0x00, 0x41, 0xe0, 0x29, + 0x0b, 0x0c, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x41, 0x98, 0x2a, 0x0b, 0x02, 0xa8, 0x14 +}; +unsigned int wasi_test_wasm_len = 27646; diff --git a/ext/wasm3/platforms/embedded/esp32-idf-wasi/main/wasm3 b/ext/wasm3/platforms/embedded/esp32-idf-wasi/main/wasm3 new file mode 120000 index 0000000..17056a9 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf-wasi/main/wasm3 @@ -0,0 +1 @@ +../../../../source \ No newline at end of file diff --git a/ext/wasm3/platforms/embedded/esp32-idf-wasi/sdkconfig.defaults b/ext/wasm3/platforms/embedded/esp32-idf-wasi/sdkconfig.defaults new file mode 100644 index 0000000..e5f6486 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf-wasi/sdkconfig.defaults @@ -0,0 +1,14 @@ +# Increased stack size +CONFIG_ESP_MAIN_TASK_STACK_SIZE=65536 + +# Disable task watchdog +CONFIG_ESP_TASK_WDT=n + +# Increase CPU frequency +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y + +# PSRAM support +CONFIG_SPIRAM_SUPPORT=y +CONFIG_SPIRAM_IGNORE_NOTFOUND=y +CONFIG_SPIRAM_USE_MALLOC=y + diff --git a/ext/wasm3/platforms/embedded/esp32-idf/.gitignore b/ext/wasm3/platforms/embedded/esp32-idf/.gitignore new file mode 100644 index 0000000..d054d84 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf/.gitignore @@ -0,0 +1,3 @@ +build +sdkconfig +sdkconfig.old diff --git a/ext/wasm3/platforms/embedded/esp32-idf/.old/Makefile b/ext/wasm3/platforms/embedded/esp32-idf/.old/Makefile new file mode 100644 index 0000000..2f23716 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf/.old/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := wasm3 + +include $(IDF_PATH)/make/project.mk + diff --git a/ext/wasm3/platforms/embedded/esp32-idf/.old/component.mk b/ext/wasm3/platforms/embedded/esp32-idf/.old/component.mk new file mode 100644 index 0000000..0b9d758 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf/.old/component.mk @@ -0,0 +1,5 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + diff --git a/ext/wasm3/platforms/embedded/esp32-idf/CMakeLists.txt b/ext/wasm3/platforms/embedded/esp32-idf/CMakeLists.txt new file mode 100644 index 0000000..d88e541 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(wasm3) diff --git a/ext/wasm3/platforms/embedded/esp32-idf/README.md b/ext/wasm3/platforms/embedded/esp32-idf/README.md new file mode 100644 index 0000000..d340fd6 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf/README.md @@ -0,0 +1,24 @@ +## Build for ESP-IDF + +Download and install ESP-IDF v4.3-beta1 + +```sh +export IDF_PATH=/opt/esp32/esp-idf + +# Set tools path if needed: +#export IDF_TOOLS_PATH=/opt/esp32 + +source $IDF_PATH/export.sh + +idf.py menuconfig + +# Select target: +idf.py set-target esp32 +#idf.py set-target esp32s2 +#idf.py --preview set-target esp32c3 + +idf.py build + +idf.py -p /dev/ttyUSB0 flash monitor + +``` diff --git a/ext/wasm3/platforms/embedded/esp32-idf/main/CMakeLists.txt b/ext/wasm3/platforms/embedded/esp32-idf/main/CMakeLists.txt new file mode 100644 index 0000000..eaa975a --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf/main/CMakeLists.txt @@ -0,0 +1,26 @@ +set(idf_ver "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}") + +if (NOT CMAKE_BUILD_EARLY_EXPANSION) + idf_build_get_property(build_dir BUILD_DIR) + add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../../../../source ${build_dir}/m3) +endif() + +set(APP_SOURCES "main.cpp") + +idf_component_register(SRCS ${APP_SOURCES} + INCLUDE_DIRS "" + LDFRAGMENTS linker.lf) + +if (idf_ver STREQUAL "4.0") + # IDF v4.0 links apps with -nostdlib, so need to explicitly list the dependencies. + + add_library(m3_deps INTERFACE) + target_link_libraries(m3_deps INTERFACE c m gcc) + target_link_libraries(${COMPONENT_TARGET} PRIVATE m3 m3_deps) +else() + # For IDF v4.1 and later, no tricks required. + + target_link_libraries(${COMPONENT_TARGET} PRIVATE m3) +endif() + +target_compile_options(m3 PUBLIC -DM3_IN_IRAM -DESP32 -O3 -freorder-blocks) diff --git a/ext/wasm3/platforms/embedded/esp32-idf/main/linker.lf b/ext/wasm3/platforms/embedded/esp32-idf/main/linker.lf new file mode 100644 index 0000000..077c98a --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf/main/linker.lf @@ -0,0 +1,6 @@ +[mapping:wasm3] +archive: libm3.a +entries: + m3_core (noflash_text) + m3_exec (noflash_text) + m3_compile (noflash_text) diff --git a/ext/wasm3/platforms/embedded/esp32-idf/main/main.cpp b/ext/wasm3/platforms/embedded/esp32-idf/main/main.cpp new file mode 100644 index 0000000..43db66e --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf/main/main.cpp @@ -0,0 +1,70 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include "esp_system.h" + +#include +#include +#include + +#include "wasm3.h" + +#include "extra/fib32.wasm.h" + +#define FATAL(msg, ...) { printf("Fatal: " msg "\n", ##__VA_ARGS__); return; } + +static void run_wasm(void) +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + uint32_t fsize = fib32_wasm_len; + + printf("Loading WebAssembly...\n"); + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + if (!runtime) FATAL("m3_NewRuntime failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule: %s", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule: %s", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction: %s", result); + + printf("Running...\n"); + + result = m3_CallV(f, 24); + if (result) FATAL("m3_Call: %s", result); + + unsigned value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults: %s", result); + + printf("Result: %u\n", value); +} + +extern "C" void app_main(void) +{ + printf("\nWasm3 v" M3_VERSION " on " CONFIG_IDF_TARGET ", build " __DATE__ " " __TIME__ "\n"); + + clock_t start = clock(); + run_wasm(); + clock_t end = clock(); + + printf("Elapsed: %ld ms\n", (end - start)*1000 / CLOCKS_PER_SEC); + + sleep(3); + printf("Restarting...\n\n\n"); + esp_restart(); +} diff --git a/ext/wasm3/platforms/embedded/esp32-idf/sdkconfig.defaults b/ext/wasm3/platforms/embedded/esp32-idf/sdkconfig.defaults new file mode 100644 index 0000000..41dc237 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-idf/sdkconfig.defaults @@ -0,0 +1,8 @@ +# Increased stack size +CONFIG_ESP_MAIN_TASK_STACK_SIZE=32768 + +# Disable task watchdog +CONFIG_ESP_TASK_WDT=n + +# Increase CPU frequency +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y diff --git a/ext/wasm3/platforms/embedded/esp32-pio/.gitignore b/ext/wasm3/platforms/embedded/esp32-pio/.gitignore new file mode 100644 index 0000000..03f4a3c --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-pio/.gitignore @@ -0,0 +1 @@ +.pio diff --git a/ext/wasm3/platforms/embedded/esp32-pio/lib/wasm3/README.md b/ext/wasm3/platforms/embedded/esp32-pio/lib/wasm3/README.md new file mode 100644 index 0000000..6152d55 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-pio/lib/wasm3/README.md @@ -0,0 +1,3 @@ +This is a placeholder for the wasm3 PIO library. + +At the moment it simply adds the source code as a symlink, and sets some build flags. diff --git a/ext/wasm3/platforms/embedded/esp32-pio/lib/wasm3/library.json b/ext/wasm3/platforms/embedded/esp32-pio/lib/wasm3/library.json new file mode 100644 index 0000000..f1b6cbe --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-pio/lib/wasm3/library.json @@ -0,0 +1,5 @@ +{ + "build" : { + "flags": "-DESP32 -O3 -Wfatal-errors -Wno-unused-function -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers" + } +} diff --git a/ext/wasm3/platforms/embedded/esp32-pio/lib/wasm3/src b/ext/wasm3/platforms/embedded/esp32-pio/lib/wasm3/src new file mode 120000 index 0000000..e3e41d7 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-pio/lib/wasm3/src @@ -0,0 +1 @@ +../../../../../source \ No newline at end of file diff --git a/ext/wasm3/platforms/embedded/esp32-pio/platformio.ini b/ext/wasm3/platforms/embedded/esp32-pio/platformio.ini new file mode 100644 index 0000000..42e4107 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-pio/platformio.ini @@ -0,0 +1,18 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp32dev] +platform = espressif32 +board = esp32dev +framework = espidf + +monitor_speed = 115200 + +board_build.f_cpu = 240000000L diff --git a/ext/wasm3/platforms/embedded/esp32-pio/src/main.cpp b/ext/wasm3/platforms/embedded/esp32-pio/src/main.cpp new file mode 100644 index 0000000..43db66e --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-pio/src/main.cpp @@ -0,0 +1,70 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include "esp_system.h" + +#include +#include +#include + +#include "wasm3.h" + +#include "extra/fib32.wasm.h" + +#define FATAL(msg, ...) { printf("Fatal: " msg "\n", ##__VA_ARGS__); return; } + +static void run_wasm(void) +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + uint32_t fsize = fib32_wasm_len; + + printf("Loading WebAssembly...\n"); + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + if (!runtime) FATAL("m3_NewRuntime failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule: %s", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule: %s", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction: %s", result); + + printf("Running...\n"); + + result = m3_CallV(f, 24); + if (result) FATAL("m3_Call: %s", result); + + unsigned value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults: %s", result); + + printf("Result: %u\n", value); +} + +extern "C" void app_main(void) +{ + printf("\nWasm3 v" M3_VERSION " on " CONFIG_IDF_TARGET ", build " __DATE__ " " __TIME__ "\n"); + + clock_t start = clock(); + run_wasm(); + clock_t end = clock(); + + printf("Elapsed: %ld ms\n", (end - start)*1000 / CLOCKS_PER_SEC); + + sleep(3); + printf("Restarting...\n\n\n"); + esp_restart(); +} diff --git a/ext/wasm3/platforms/embedded/esp32-pio/src/sdkconfig b/ext/wasm3/platforms/embedded/esp32-pio/src/sdkconfig new file mode 100644 index 0000000..20625d8 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-pio/src/sdkconfig @@ -0,0 +1,962 @@ +# +# Automatically generated file; DO NOT EDIT. +# Espressif IoT Development Framework Configuration +# +CONFIG_IDF_TARGET="esp32" + +# +# SDK tool configuration +# +CONFIG_TOOLPREFIX="xtensa-esp32-elf-" +CONFIG_PYTHON="python" +CONFIG_MAKE_WARN_UNDEFINED_VARIABLES=y + +# +# Application manager +# +CONFIG_APP_COMPILE_TIME_DATE=y +CONFIG_APP_EXCLUDE_PROJECT_VER_VAR= +CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR= + +# +# Bootloader config +# +CONFIG_LOG_BOOTLOADER_LEVEL_NONE= +CONFIG_LOG_BOOTLOADER_LEVEL_ERROR= +CONFIG_LOG_BOOTLOADER_LEVEL_WARN= +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG= +CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE= +CONFIG_LOG_BOOTLOADER_LEVEL=3 +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V= +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y +CONFIG_BOOTLOADER_FACTORY_RESET= +CONFIG_BOOTLOADER_APP_TEST= +CONFIG_BOOTLOADER_WDT_ENABLE=y +CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE= +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +CONFIG_APP_ROLLBACK_ENABLE= + +# +# Security features +# +CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT= +CONFIG_SECURE_BOOT_ENABLED= +CONFIG_FLASH_ENCRYPTION_ENABLED= + +# +# Serial flasher config +# +CONFIG_ESPTOOLPY_PORT="COM19" +CONFIG_ESPTOOLPY_BAUD_115200B=y +CONFIG_ESPTOOLPY_BAUD_230400B= +CONFIG_ESPTOOLPY_BAUD_921600B= +CONFIG_ESPTOOLPY_BAUD_2MB= +CONFIG_ESPTOOLPY_BAUD_OTHER= +CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 +CONFIG_ESPTOOLPY_BAUD=115200 +CONFIG_ESPTOOLPY_COMPRESSED=y +CONFIG_FLASHMODE_QIO= +CONFIG_FLASHMODE_QOUT= +CONFIG_FLASHMODE_DIO=y +CONFIG_FLASHMODE_DOUT= +CONFIG_ESPTOOLPY_FLASHMODE="dio" +CONFIG_ESPTOOLPY_FLASHFREQ_80M= +CONFIG_ESPTOOLPY_FLASHFREQ_40M=y +CONFIG_ESPTOOLPY_FLASHFREQ_26M= +CONFIG_ESPTOOLPY_FLASHFREQ_20M= +CONFIG_ESPTOOLPY_FLASHFREQ="40m" +CONFIG_ESPTOOLPY_FLASHSIZE_1MB= +CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y +CONFIG_ESPTOOLPY_FLASHSIZE_4MB= +CONFIG_ESPTOOLPY_FLASHSIZE_8MB= +CONFIG_ESPTOOLPY_FLASHSIZE_16MB= +CONFIG_ESPTOOLPY_FLASHSIZE="2MB" +CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y +CONFIG_ESPTOOLPY_BEFORE_RESET=y +CONFIG_ESPTOOLPY_BEFORE_NORESET= +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +CONFIG_ESPTOOLPY_AFTER_NORESET= +CONFIG_ESPTOOLPY_AFTER="hard_reset" +CONFIG_MONITOR_BAUD_9600B= +CONFIG_MONITOR_BAUD_57600B= +CONFIG_MONITOR_BAUD_115200B=y +CONFIG_MONITOR_BAUD_230400B= +CONFIG_MONITOR_BAUD_921600B= +CONFIG_MONITOR_BAUD_2MB= +CONFIG_MONITOR_BAUD_OTHER= +CONFIG_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_MONITOR_BAUD=115200 + +# +# Partition Table +# +CONFIG_PARTITION_TABLE_SINGLE_APP=y +CONFIG_PARTITION_TABLE_TWO_OTA= +CONFIG_PARTITION_TABLE_CUSTOM= +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" +CONFIG_PARTITION_TABLE_OFFSET=0x8000 +CONFIG_PARTITION_TABLE_MD5=y + +# +# Compiler options +# +CONFIG_OPTIMIZATION_LEVEL_DEBUG=y +CONFIG_OPTIMIZATION_LEVEL_RELEASE= +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +CONFIG_OPTIMIZATION_ASSERTIONS_SILENT= +CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED= +CONFIG_CXX_EXCEPTIONS=y +CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE=0 +CONFIG_STACK_CHECK_NONE=y +CONFIG_STACK_CHECK_NORM= +CONFIG_STACK_CHECK_STRONG= +CONFIG_STACK_CHECK_ALL= +CONFIG_STACK_CHECK= +CONFIG_WARN_WRITE_STRINGS= +CONFIG_DISABLE_GCC8_WARNINGS= + +# +# Component config +# + +# +# Application Level Tracing +# +CONFIG_ESP32_APPTRACE_DEST_TRAX= +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_ENABLE= +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +CONFIG_AWS_IOT_SDK=y +CONFIG_AWS_IOT_MQTT_HOST="" +CONFIG_AWS_IOT_MQTT_PORT=8883 +CONFIG_AWS_IOT_MQTT_TX_BUF_LEN=512 +CONFIG_AWS_IOT_MQTT_RX_BUF_LEN=512 +CONFIG_AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS=5 +CONFIG_AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL=1000 +CONFIG_AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL=128000 + +# +# Thing Shadow +# +CONFIG_AWS_IOT_OVERRIDE_THING_SHADOW_RX_BUFFER= +CONFIG_AWS_IOT_SHADOW_MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES=80 +CONFIG_AWS_IOT_SHADOW_MAX_SIMULTANEOUS_ACKS=10 +CONFIG_AWS_IOT_SHADOW_MAX_SIMULTANEOUS_THINGNAMES=10 +CONFIG_AWS_IOT_SHADOW_MAX_JSON_TOKEN_EXPECTED=120 +CONFIG_AWS_IOT_SHADOW_MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME=60 +CONFIG_AWS_IOT_SHADOW_MAX_SIZE_OF_THING_NAME=20 + +# +# Bluetooth +# +CONFIG_BT_ENABLED=y + +# +# Bluetooth controller +# +CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY=y +CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY= +CONFIG_BTDM_CONTROLLER_MODE_BTDM= +CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN=3 +CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF=3 +CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_0=y +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_1= +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 +CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI=y +CONFIG_BTDM_CONTROLLER_HCI_MODE_UART_H4= + +# +# MODEM SLEEP Options +# +CONFIG_BTDM_CONTROLLER_MODEM_SLEEP= +CONFIG_BLE_SCAN_DUPLICATE=y +CONFIG_SCAN_DUPLICATE_BY_DEVICE_ADDR=y +CONFIG_SCAN_DUPLICATE_BY_ADV_DATA= +CONFIG_SCAN_DUPLICATE_BY_ADV_DATA_AND_DEVICE_ADDR= +CONFIG_SCAN_DUPLICATE_TYPE=0 +CONFIG_DUPLICATE_SCAN_CACHE_SIZE=50 +CONFIG_BLE_MESH_SCAN_DUPLICATE_EN= +CONFIG_BTDM_CONTROLLER_FULL_SCAN_SUPPORTED= +CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_SUPPORTED=y +CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_NUM=100 +CONFIG_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 +CONFIG_BLUEDROID_ENABLED=y +CONFIG_BLUEDROID_PINNED_TO_CORE_0=y +CONFIG_BLUEDROID_PINNED_TO_CORE_1= +CONFIG_BLUEDROID_PINNED_TO_CORE=0 +CONFIG_BTC_TASK_STACK_SIZE=32768 +CONFIG_BTU_TASK_STACK_SIZE=4096 +CONFIG_BLUEDROID_MEM_DEBUG= +CONFIG_CLASSIC_BT_ENABLED= +CONFIG_GATTS_ENABLE=y +CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL= +CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO=y +CONFIG_GATTS_SEND_SERVICE_CHANGE_MODE=0 +CONFIG_GATTC_ENABLE=y +CONFIG_GATTC_CACHE_NVS_FLASH= +CONFIG_BLE_SMP_ENABLE=y +CONFIG_SMP_SLAVE_CON_PARAMS_UPD_ENABLE= +CONFIG_BT_STACK_NO_LOG= + +# +# BT DEBUG LOG LEVEL +# +CONFIG_HCI_TRACE_LEVEL_NONE= +CONFIG_HCI_TRACE_LEVEL_ERROR= +CONFIG_HCI_TRACE_LEVEL_WARNING=y +CONFIG_HCI_TRACE_LEVEL_API= +CONFIG_HCI_TRACE_LEVEL_EVENT= +CONFIG_HCI_TRACE_LEVEL_DEBUG= +CONFIG_HCI_TRACE_LEVEL_VERBOSE= +CONFIG_HCI_INITIAL_TRACE_LEVEL=2 +CONFIG_BTM_TRACE_LEVEL_NONE= +CONFIG_BTM_TRACE_LEVEL_ERROR= +CONFIG_BTM_TRACE_LEVEL_WARNING=y +CONFIG_BTM_TRACE_LEVEL_API= +CONFIG_BTM_TRACE_LEVEL_EVENT= +CONFIG_BTM_TRACE_LEVEL_DEBUG= +CONFIG_BTM_TRACE_LEVEL_VERBOSE= +CONFIG_BTM_INITIAL_TRACE_LEVEL=2 +CONFIG_L2CAP_TRACE_LEVEL_NONE= +CONFIG_L2CAP_TRACE_LEVEL_ERROR= +CONFIG_L2CAP_TRACE_LEVEL_WARNING=y +CONFIG_L2CAP_TRACE_LEVEL_API= +CONFIG_L2CAP_TRACE_LEVEL_EVENT= +CONFIG_L2CAP_TRACE_LEVEL_DEBUG= +CONFIG_L2CAP_TRACE_LEVEL_VERBOSE= +CONFIG_L2CAP_INITIAL_TRACE_LEVEL=2 +CONFIG_RFCOMM_TRACE_LEVEL_NONE= +CONFIG_RFCOMM_TRACE_LEVEL_ERROR= +CONFIG_RFCOMM_TRACE_LEVEL_WARNING=y +CONFIG_RFCOMM_TRACE_LEVEL_API= +CONFIG_RFCOMM_TRACE_LEVEL_EVENT= +CONFIG_RFCOMM_TRACE_LEVEL_DEBUG= +CONFIG_RFCOMM_TRACE_LEVEL_VERBOSE= +CONFIG_RFCOMM_INITIAL_TRACE_LEVEL=2 +CONFIG_SDP_TRACE_LEVEL_NONE= +CONFIG_SDP_TRACE_LEVEL_ERROR= +CONFIG_SDP_TRACE_LEVEL_WARNING=y +CONFIG_SDP_TRACE_LEVEL_API= +CONFIG_SDP_TRACE_LEVEL_EVENT= +CONFIG_SDP_TRACE_LEVEL_DEBUG= +CONFIG_SDP_TRACE_LEVEL_VERBOSE= +CONFIG_SDP_INITIAL_TRACE_LEVEL=2 +CONFIG_GAP_TRACE_LEVEL_NONE= +CONFIG_GAP_TRACE_LEVEL_ERROR= +CONFIG_GAP_TRACE_LEVEL_WARNING=y +CONFIG_GAP_TRACE_LEVEL_API= +CONFIG_GAP_TRACE_LEVEL_EVENT= +CONFIG_GAP_TRACE_LEVEL_DEBUG= +CONFIG_GAP_TRACE_LEVEL_VERBOSE= +CONFIG_GAP_INITIAL_TRACE_LEVEL=2 +CONFIG_BNEP_TRACE_LEVEL_NONE= +CONFIG_BNEP_TRACE_LEVEL_ERROR= +CONFIG_BNEP_TRACE_LEVEL_WARNING=y +CONFIG_BNEP_TRACE_LEVEL_API= +CONFIG_BNEP_TRACE_LEVEL_EVENT= +CONFIG_BNEP_TRACE_LEVEL_DEBUG= +CONFIG_BNEP_TRACE_LEVEL_VERBOSE= +CONFIG_BNEP_INITIAL_TRACE_LEVEL=2 +CONFIG_PAN_TRACE_LEVEL_NONE= +CONFIG_PAN_TRACE_LEVEL_ERROR= +CONFIG_PAN_TRACE_LEVEL_WARNING=y +CONFIG_PAN_TRACE_LEVEL_API= +CONFIG_PAN_TRACE_LEVEL_EVENT= +CONFIG_PAN_TRACE_LEVEL_DEBUG= +CONFIG_PAN_TRACE_LEVEL_VERBOSE= +CONFIG_PAN_INITIAL_TRACE_LEVEL=2 +CONFIG_A2D_TRACE_LEVEL_NONE= +CONFIG_A2D_TRACE_LEVEL_ERROR= +CONFIG_A2D_TRACE_LEVEL_WARNING=y +CONFIG_A2D_TRACE_LEVEL_API= +CONFIG_A2D_TRACE_LEVEL_EVENT= +CONFIG_A2D_TRACE_LEVEL_DEBUG= +CONFIG_A2D_TRACE_LEVEL_VERBOSE= +CONFIG_A2D_INITIAL_TRACE_LEVEL=2 +CONFIG_AVDT_TRACE_LEVEL_NONE= +CONFIG_AVDT_TRACE_LEVEL_ERROR= +CONFIG_AVDT_TRACE_LEVEL_WARNING=y +CONFIG_AVDT_TRACE_LEVEL_API= +CONFIG_AVDT_TRACE_LEVEL_EVENT= +CONFIG_AVDT_TRACE_LEVEL_DEBUG= +CONFIG_AVDT_TRACE_LEVEL_VERBOSE= +CONFIG_AVDT_INITIAL_TRACE_LEVEL=2 +CONFIG_AVCT_TRACE_LEVEL_NONE= +CONFIG_AVCT_TRACE_LEVEL_ERROR= +CONFIG_AVCT_TRACE_LEVEL_WARNING=y +CONFIG_AVCT_TRACE_LEVEL_API= +CONFIG_AVCT_TRACE_LEVEL_EVENT= +CONFIG_AVCT_TRACE_LEVEL_DEBUG= +CONFIG_AVCT_TRACE_LEVEL_VERBOSE= +CONFIG_AVCT_INITIAL_TRACE_LEVEL=2 +CONFIG_AVRC_TRACE_LEVEL_NONE= +CONFIG_AVRC_TRACE_LEVEL_ERROR= +CONFIG_AVRC_TRACE_LEVEL_WARNING=y +CONFIG_AVRC_TRACE_LEVEL_API= +CONFIG_AVRC_TRACE_LEVEL_EVENT= +CONFIG_AVRC_TRACE_LEVEL_DEBUG= +CONFIG_AVRC_TRACE_LEVEL_VERBOSE= +CONFIG_AVRC_INITIAL_TRACE_LEVEL=2 +CONFIG_MCA_TRACE_LEVEL_NONE= +CONFIG_MCA_TRACE_LEVEL_ERROR= +CONFIG_MCA_TRACE_LEVEL_WARNING=y +CONFIG_MCA_TRACE_LEVEL_API= +CONFIG_MCA_TRACE_LEVEL_EVENT= +CONFIG_MCA_TRACE_LEVEL_DEBUG= +CONFIG_MCA_TRACE_LEVEL_VERBOSE= +CONFIG_MCA_INITIAL_TRACE_LEVEL=2 +CONFIG_HID_TRACE_LEVEL_NONE= +CONFIG_HID_TRACE_LEVEL_ERROR= +CONFIG_HID_TRACE_LEVEL_WARNING=y +CONFIG_HID_TRACE_LEVEL_API= +CONFIG_HID_TRACE_LEVEL_EVENT= +CONFIG_HID_TRACE_LEVEL_DEBUG= +CONFIG_HID_TRACE_LEVEL_VERBOSE= +CONFIG_HID_INITIAL_TRACE_LEVEL=2 +CONFIG_APPL_TRACE_LEVEL_NONE= +CONFIG_APPL_TRACE_LEVEL_ERROR= +CONFIG_APPL_TRACE_LEVEL_WARNING=y +CONFIG_APPL_TRACE_LEVEL_API= +CONFIG_APPL_TRACE_LEVEL_EVENT= +CONFIG_APPL_TRACE_LEVEL_DEBUG= +CONFIG_APPL_TRACE_LEVEL_VERBOSE= +CONFIG_APPL_INITIAL_TRACE_LEVEL=2 +CONFIG_GATT_TRACE_LEVEL_NONE= +CONFIG_GATT_TRACE_LEVEL_ERROR= +CONFIG_GATT_TRACE_LEVEL_WARNING=y +CONFIG_GATT_TRACE_LEVEL_API= +CONFIG_GATT_TRACE_LEVEL_EVENT= +CONFIG_GATT_TRACE_LEVEL_DEBUG= +CONFIG_GATT_TRACE_LEVEL_VERBOSE= +CONFIG_GATT_INITIAL_TRACE_LEVEL=2 +CONFIG_SMP_TRACE_LEVEL_NONE= +CONFIG_SMP_TRACE_LEVEL_ERROR= +CONFIG_SMP_TRACE_LEVEL_WARNING=y +CONFIG_SMP_TRACE_LEVEL_API= +CONFIG_SMP_TRACE_LEVEL_EVENT= +CONFIG_SMP_TRACE_LEVEL_DEBUG= +CONFIG_SMP_TRACE_LEVEL_VERBOSE= +CONFIG_SMP_INITIAL_TRACE_LEVEL=2 +CONFIG_BTIF_TRACE_LEVEL_NONE= +CONFIG_BTIF_TRACE_LEVEL_ERROR= +CONFIG_BTIF_TRACE_LEVEL_WARNING=y +CONFIG_BTIF_TRACE_LEVEL_API= +CONFIG_BTIF_TRACE_LEVEL_EVENT= +CONFIG_BTIF_TRACE_LEVEL_DEBUG= +CONFIG_BTIF_TRACE_LEVEL_VERBOSE= +CONFIG_BTIF_INITIAL_TRACE_LEVEL=2 +CONFIG_BTC_TRACE_LEVEL_NONE= +CONFIG_BTC_TRACE_LEVEL_ERROR= +CONFIG_BTC_TRACE_LEVEL_WARNING=y +CONFIG_BTC_TRACE_LEVEL_API= +CONFIG_BTC_TRACE_LEVEL_EVENT= +CONFIG_BTC_TRACE_LEVEL_DEBUG= +CONFIG_BTC_TRACE_LEVEL_VERBOSE= +CONFIG_BTC_INITIAL_TRACE_LEVEL=2 +CONFIG_OSI_TRACE_LEVEL_NONE= +CONFIG_OSI_TRACE_LEVEL_ERROR= +CONFIG_OSI_TRACE_LEVEL_WARNING=y +CONFIG_OSI_TRACE_LEVEL_API= +CONFIG_OSI_TRACE_LEVEL_EVENT= +CONFIG_OSI_TRACE_LEVEL_DEBUG= +CONFIG_OSI_TRACE_LEVEL_VERBOSE= +CONFIG_OSI_INITIAL_TRACE_LEVEL=2 +CONFIG_BLUFI_TRACE_LEVEL_NONE= +CONFIG_BLUFI_TRACE_LEVEL_ERROR= +CONFIG_BLUFI_TRACE_LEVEL_WARNING=y +CONFIG_BLUFI_TRACE_LEVEL_API= +CONFIG_BLUFI_TRACE_LEVEL_EVENT= +CONFIG_BLUFI_TRACE_LEVEL_DEBUG= +CONFIG_BLUFI_TRACE_LEVEL_VERBOSE= +CONFIG_BLUFI_INITIAL_TRACE_LEVEL=2 +CONFIG_BT_ACL_CONNECTIONS=4 +CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST= +CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY= +CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK= +CONFIG_SMP_ENABLE=y +CONFIG_BLE_ACTIVE_SCAN_REPORT_ADV_SCAN_RSP_INDIVIDUALLY= +CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT=30 +CONFIG_BT_RESERVE_DRAM=0xdb5c + +# +# Driver configurations +# + +# +# ADC configuration +# +CONFIG_ADC_FORCE_XPD_FSM= +CONFIG_ADC2_DISABLE_DAC=y + +# +# SPI configuration +# +CONFIG_SPI_MASTER_IN_IRAM= +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +CONFIG_SPI_SLAVE_IN_IRAM= +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y + +# +# eFuse Bit Manager +# +CONFIG_EFUSE_CUSTOM_TABLE= +CONFIG_EFUSE_VIRTUAL= +CONFIG_EFUSE_CODE_SCHEME_COMPAT_NONE= +CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4=y +CONFIG_EFUSE_CODE_SCHEME_COMPAT_REPEAT= +CONFIG_EFUSE_MAX_BLK_LEN=192 + +# +# ESP32-specific +# +CONFIG_IDF_TARGET_ESP32=y +CONFIG_ESP32_REV_MIN_0= +CONFIG_ESP32_REV_MIN_1=y +CONFIG_ESP32_REV_MIN_2= +CONFIG_ESP32_REV_MIN_3= +CONFIG_ESP32_REV_MIN=1 +CONFIG_ESP32_DPORT_WORKAROUND=y +CONFIG_ESP32_DEFAULT_CPU_FREQ_80= +CONFIG_ESP32_DEFAULT_CPU_FREQ_160=y +CONFIG_ESP32_DEFAULT_CPU_FREQ_240= +CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=160 +CONFIG_SPIRAM_SUPPORT= +CONFIG_MEMMAP_TRACEMEM= +CONFIG_MEMMAP_TRACEMEM_TWOBANKS= +CONFIG_ESP32_TRAX= +CONFIG_TRACEMEM_RESERVE_DRAM=0x0 +CONFIG_TWO_UNIVERSAL_MAC_ADDRESS= +CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y +CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_MAIN_TASK_STACK_SIZE=3584 +CONFIG_IPC_TASK_STACK_SIZE=1024 +CONFIG_TIMER_TASK_STACK_SIZE=3584 +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF= +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR= +CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF= +CONFIG_NEWLIB_STDIN_LINE_ENDING_LF= +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +CONFIG_NEWLIB_NANO_FORMAT= +CONFIG_CONSOLE_UART_DEFAULT=y +CONFIG_CONSOLE_UART_CUSTOM= +CONFIG_CONSOLE_UART_NONE= +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ULP_COPROC_ENABLED= +CONFIG_ULP_COPROC_RESERVE_MEM=0 +CONFIG_ESP32_PANIC_PRINT_HALT= +CONFIG_ESP32_PANIC_PRINT_REBOOT=y +CONFIG_ESP32_PANIC_SILENT_REBOOT= +CONFIG_ESP32_PANIC_GDBSTUB= +CONFIG_ESP32_DEBUG_OCDAWARE=y +CONFIG_ESP32_DEBUG_STUBS_ENABLE=y +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +CONFIG_TASK_WDT=y +CONFIG_TASK_WDT_PANIC= +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y +CONFIG_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_0=y +CONFIG_BROWNOUT_DET_LVL_SEL_1= +CONFIG_BROWNOUT_DET_LVL_SEL_2= +CONFIG_BROWNOUT_DET_LVL_SEL_3= +CONFIG_BROWNOUT_DET_LVL_SEL_4= +CONFIG_BROWNOUT_DET_LVL_SEL_5= +CONFIG_BROWNOUT_DET_LVL_SEL_6= +CONFIG_BROWNOUT_DET_LVL_SEL_7= +CONFIG_BROWNOUT_DET_LVL=0 +CONFIG_REDUCE_PHY_TX_POWER=y +CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y +CONFIG_ESP32_TIME_SYSCALL_USE_RTC= +CONFIG_ESP32_TIME_SYSCALL_USE_FRC1= +CONFIG_ESP32_TIME_SYSCALL_USE_NONE= +CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y +CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL= +CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_OSC= +CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_8MD256= +CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024 +CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP32_XTAL_FREQ_40=y +CONFIG_ESP32_XTAL_FREQ_26= +CONFIG_ESP32_XTAL_FREQ_AUTO= +CONFIG_ESP32_XTAL_FREQ=40 +CONFIG_DISABLE_BASIC_ROM_CONSOLE= +CONFIG_ESP_TIMER_PROFILING= +CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS= +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y + +# +# Wi-Fi +# +CONFIG_SW_COEXIST_ENABLE=y +CONFIG_SW_COEXIST_PREFERENCE_WIFI= +CONFIG_SW_COEXIST_PREFERENCE_BT= +CONFIG_SW_COEXIST_PREFERENCE_BALANCE=y +CONFIG_SW_COEXIST_PREFERENCE_VALUE=2 +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER= +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +CONFIG_ESP32_WIFI_CSI_ENABLED= +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y +CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1= +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +CONFIG_ESP32_WIFI_DEBUG_LOG_ENABLE= +CONFIG_ESP32_WIFI_IRAM_OPT=y + +# +# PHY +# +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION= +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 + +# +# Power Management +# +CONFIG_PM_ENABLE= + +# +# ADC-Calibration +# +CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y +CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y +CONFIG_ADC_CAL_LUT_ENABLE=y + +# +# Event Loop Library +# +CONFIG_EVENT_LOOP_PROFILING= + +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y + +# +# HTTP Server +# +CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 +CONFIG_HTTPD_MAX_URI_LEN=512 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +CONFIG_HTTPD_LOG_PURGE_DATA= + +# +# ESP HTTPS OTA +# +CONFIG_OTA_ALLOW_HTTP= + +# +# Core dump +# +CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH= +CONFIG_ESP32_ENABLE_COREDUMP_TO_UART= +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +CONFIG_ESP32_ENABLE_COREDUMP= + +# +# Ethernet +# +CONFIG_DMA_RX_BUF_NUM=10 +CONFIG_DMA_TX_BUF_NUM=10 +CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE= +CONFIG_EMAC_CHECK_LINK_PERIOD_MS=2000 +CONFIG_EMAC_TASK_PRIORITY=20 +CONFIG_EMAC_TASK_STACK_SIZE=3072 + +# +# FAT Filesystem support +# +CONFIG_FATFS_CODEPAGE_DYNAMIC= +CONFIG_FATFS_CODEPAGE_437=y +CONFIG_FATFS_CODEPAGE_720= +CONFIG_FATFS_CODEPAGE_737= +CONFIG_FATFS_CODEPAGE_771= +CONFIG_FATFS_CODEPAGE_775= +CONFIG_FATFS_CODEPAGE_850= +CONFIG_FATFS_CODEPAGE_852= +CONFIG_FATFS_CODEPAGE_855= +CONFIG_FATFS_CODEPAGE_857= +CONFIG_FATFS_CODEPAGE_860= +CONFIG_FATFS_CODEPAGE_861= +CONFIG_FATFS_CODEPAGE_862= +CONFIG_FATFS_CODEPAGE_863= +CONFIG_FATFS_CODEPAGE_864= +CONFIG_FATFS_CODEPAGE_865= +CONFIG_FATFS_CODEPAGE_866= +CONFIG_FATFS_CODEPAGE_869= +CONFIG_FATFS_CODEPAGE_932= +CONFIG_FATFS_CODEPAGE_936= +CONFIG_FATFS_CODEPAGE_949= +CONFIG_FATFS_CODEPAGE_950= +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_LFN_NONE=y +CONFIG_FATFS_LFN_HEAP= +CONFIG_FATFS_LFN_STACK= +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y + +# +# Modbus configuration +# +CONFIG_MB_QUEUE_LENGTH=20 +CONFIG_MB_SERIAL_TASK_STACK_SIZE=2048 +CONFIG_MB_SERIAL_BUF_SIZE=256 +CONFIG_MB_SERIAL_TASK_PRIO=10 +CONFIG_MB_CONTROLLER_SLAVE_ID_SUPPORT= +CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT=20 +CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE=20 +CONFIG_MB_CONTROLLER_STACK_SIZE=4096 +CONFIG_MB_EVENT_QUEUE_TIMEOUT=20 +CONFIG_MB_TIMER_PORT_ENABLED=y +CONFIG_MB_TIMER_GROUP=0 +CONFIG_MB_TIMER_INDEX=0 + +# +# FreeRTOS +# +CONFIG_FREERTOS_UNICORE= +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_CORETIMER_0=y +CONFIG_FREERTOS_CORETIMER_1= +CONFIG_FREERTOS_HZ=100 +CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE= +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL= +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK= +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y +CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE= +CONFIG_FREERTOS_ASSERT_DISABLE= +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +CONFIG_FREERTOS_LEGACY_HOOKS= +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +CONFIG_SUPPORT_STATIC_ALLOCATION= +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_USE_TRACE_FACILITY= +CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS= +CONFIG_FREERTOS_DEBUG_INTERNALS= +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE= + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +CONFIG_HEAP_POISONING_LIGHT= +CONFIG_HEAP_POISONING_COMPREHENSIVE= +CONFIG_HEAP_TRACING= + +# +# libsodium +# +CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y + +# +# Log output +# +CONFIG_LOG_DEFAULT_LEVEL_NONE= +CONFIG_LOG_DEFAULT_LEVEL_ERROR= +CONFIG_LOG_DEFAULT_LEVEL_WARN= +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +CONFIG_LOG_DEFAULT_LEVEL_DEBUG= +CONFIG_LOG_DEFAULT_LEVEL_VERBOSE= +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_COLORS=y + +# +# LWIP +# +CONFIG_L2_TO_L3_COPY= +CONFIG_LWIP_IRAM_OPTIMIZATION= +CONFIG_LWIP_MAX_SOCKETS=10 +CONFIG_USE_ONLY_LWIP_SELECT= +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +CONFIG_LWIP_SO_RCVBUF= +CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1 +CONFIG_LWIP_IP_FRAG= +CONFIG_LWIP_IP_REASSEMBLY= +CONFIG_LWIP_STATS= +CONFIG_LWIP_ETHARP_TRUST_IP_MAC= +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +CONFIG_LWIP_DHCP_RESTORE_LAST_IP= + +# +# DHCP server +# +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +CONFIG_LWIP_AUTOIP= +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=6 +CONFIG_TCP_MSS=1436 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5744 +CONFIG_TCP_WND_DEFAULT=5744 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +CONFIG_ESP_TCP_KEEP_CONNECTION_WHEN_IP_CHANGES= +CONFIG_TCP_OVERSIZE_MSS=y +CONFIG_TCP_OVERSIZE_QUARTER_MSS= +CONFIG_TCP_OVERSIZE_DISABLE= + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=2048 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +CONFIG_TCPIP_TASK_AFFINITY_CPU0= +CONFIG_TCPIP_TASK_AFFINITY_CPU1= +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +CONFIG_PPP_SUPPORT= + +# +# ICMP +# +CONFIG_LWIP_MULTICAST_PING= +CONFIG_LWIP_BROADCAST_PING= + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 + +# +# mbedTLS +# +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC= +CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC= +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN= +CONFIG_MBEDTLS_DEBUG= +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_HARDWARE_MPI= +CONFIG_MBEDTLS_HARDWARE_SHA= +CONFIG_MBEDTLS_HAVE_TIME=y +CONFIG_MBEDTLS_HAVE_TIME_DATE= +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +CONFIG_MBEDTLS_TLS_SERVER_ONLY= +CONFIG_MBEDTLS_TLS_CLIENT_ONLY= +CONFIG_MBEDTLS_TLS_DISABLED= +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +CONFIG_MBEDTLS_PSK_MODES= +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +CONFIG_MBEDTLS_SSL_PROTO_SSL3= +CONFIG_MBEDTLS_SSL_PROTO_TLS1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +CONFIG_MBEDTLS_SSL_PROTO_DTLS= +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +CONFIG_MBEDTLS_CAMELLIA_C= +CONFIG_MBEDTLS_DES_C= +CONFIG_MBEDTLS_RC4_DISABLED=y +CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT= +CONFIG_MBEDTLS_RC4_ENABLED= +CONFIG_MBEDTLS_BLOWFISH_C= +CONFIG_MBEDTLS_XTEA_C= +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +CONFIG_MBEDTLS_RIPEMD160_C= + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y + +# +# mDNS +# +CONFIG_MDNS_MAX_SERVICES=10 + +# +# ESP-MQTT Configurations +# +CONFIG_MQTT_PROTOCOL_311=y +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +CONFIG_MQTT_USE_CUSTOM_CONFIG= +CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED= +CONFIG_MQTT_CUSTOM_OUTBOX= + +# +# NVS +# + +# +# OpenSSL +# +CONFIG_OPENSSL_DEBUG= +CONFIG_OPENSSL_ASSERT_DO_NOTHING=y +CONFIG_OPENSSL_ASSERT_EXIT= + +# +# PThreads +# +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0= +CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1= +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" + +# +# SPI Flash driver +# +CONFIG_SPI_FLASH_VERIFY_WRITE= +CONFIG_SPI_FLASH_ENABLE_COUNTERS= +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS= +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED= +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +CONFIG_SPIFFS_CACHE_STATS= +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +CONFIG_SPIFFS_GC_STATS= +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +CONFIG_SPIFFS_DBG= +CONFIG_SPIFFS_API_DBG= +CONFIG_SPIFFS_GC_DBG= +CONFIG_SPIFFS_CACHE_DBG= +CONFIG_SPIFFS_CHECK_DBG= +CONFIG_SPIFFS_TEST_VISUALISATION= + +# +# TCP/IP Adapter +# +CONFIG_IP_LOST_TIMER_INTERVAL=120 +CONFIG_TCPIP_LWIP=y + +# +# Unity unit testing library +# +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +CONFIG_UNITY_ENABLE_COLOR= +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +CONFIG_UNITY_ENABLE_FIXTURE= + +# +# Virtual file system +# +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y + +# +# Wear Levelling +# +CONFIG_WL_SECTOR_SIZE_512= +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 + +# +# Wi-Fi Provisioning Manager +# +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 diff --git a/ext/wasm3/platforms/embedded/esp32-pio/src/sdkconfig.h b/ext/wasm3/platforms/embedded/esp32-pio/src/sdkconfig.h new file mode 100644 index 0000000..4423559 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp32-pio/src/sdkconfig.h @@ -0,0 +1,371 @@ +/* + * + * Automatically generated file; DO NOT EDIT. + * Espressif IoT Development Framework Configuration + * + */ + +#define CONFIG_ENABLE_ARDUINO_DEPENDS 1 +#define CONFIG_AUTOSTART_ARDUINO 1 +#define CONFIG_ARDUINO_RUNNING_CORE 1 +#define CONFIG_ARDUINO_UDP_RUN_CORE1 1 +#define CONFIG_ARDUINO_EVENT_RUN_CORE1 1 +#define CONFIG_ARDUINO_EVENT_RUNNING_CORE 1 +#define CONFIG_ARDUINO_UDP_RUNNING_CORE 1 + +#define CONFIG_GATTC_ENABLE 1 +#define CONFIG_ESP32_PHY_MAX_TX_POWER 20 +#define CONFIG_TRACEMEM_RESERVE_DRAM 0x0 +#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16 +#define CONFIG_MQTT_TRANSPORT_SSL 1 +#define CONFIG_BLE_SMP_ENABLE 1 +#define CONFIG_FATFS_LFN_NONE 1 +#define CONFIG_SDP_INITIAL_TRACE_LEVEL 2 +#define CONFIG_MB_SERIAL_TASK_PRIO 10 +#define CONFIG_MQTT_PROTOCOL_311 1 +#define CONFIG_TCP_RECVMBOX_SIZE 6 +#define CONFIG_FATFS_CODEPAGE_437 1 +#define CONFIG_BLE_SCAN_DUPLICATE 1 +#define CONFIG_AVDT_TRACE_LEVEL_WARNING 1 +#define CONFIG_AWS_IOT_SHADOW_MAX_SIMULTANEOUS_ACKS 10 +#define CONFIG_TCP_WND_DEFAULT 5744 +#define CONFIG_PARTITION_TABLE_OFFSET 0x8000 +#define CONFIG_SW_COEXIST_ENABLE 1 +#define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1 +#define CONFIG_AVCT_INITIAL_TRACE_LEVEL 2 +#define CONFIG_IPC_TASK_STACK_SIZE 1024 +#define CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES 16 +#define CONFIG_FATFS_PER_FILE_CACHE 1 +#define CONFIG_ESPTOOLPY_FLASHFREQ "40m" +#define CONFIG_AWS_IOT_SHADOW_MAX_SIZE_OF_THING_NAME 20 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA 1 +#define CONFIG_UDP_RECVMBOX_SIZE 6 +#define CONFIG_SPI_FLASH_YIELD_DURING_ERASE 1 +#define CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE 0 +#define CONFIG_MBEDTLS_AES_C 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED 1 +#define CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN 752 +#define CONFIG_MBEDTLS_GCM_C 1 +#define CONFIG_ESPTOOLPY_FLASHSIZE "2MB" +#define CONFIG_HEAP_POISONING_DISABLED 1 +#define CONFIG_SPIFFS_CACHE_WR 1 +#define CONFIG_BROWNOUT_DET_LVL_SEL_0 1 +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER 1 +#define CONFIG_SPIFFS_CACHE 1 +#define CONFIG_INT_WDT 1 +#define CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN 3 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1 1 +#define CONFIG_ESP_GRATUITOUS_ARP 1 +#define CONFIG_AWS_IOT_SHADOW_MAX_SIZE_OF_UNIQUE_CLIENT_ID_BYTES 80 +#define CONFIG_MBEDTLS_ECDSA_C 1 +#define CONFIG_ESPTOOLPY_FLASHFREQ_40M 1 +#define CONFIG_LOG_BOOTLOADER_LEVEL_INFO 1 +#define CONFIG_ESPTOOLPY_FLASHSIZE_2MB 1 +#define CONFIG_HTTPD_MAX_REQ_HDR_LEN 512 +#define CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE 0 +#define CONFIG_AWS_IOT_MQTT_PORT 8883 +#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1 +#define CONFIG_MBEDTLS_ECDH_C 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE 1 +#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM 10 +#define CONFIG_AWS_IOT_MQTT_MAX_RECONNECT_WAIT_INTERVAL 128000 +#define CONFIG_MBEDTLS_SSL_ALPN 1 +#define CONFIG_BTM_TRACE_LEVEL_WARNING 1 +#define CONFIG_MBEDTLS_PEM_WRITE_C 1 +#define CONFIG_RFCOMM_TRACE_LEVEL_WARNING 1 +#define CONFIG_LOG_DEFAULT_LEVEL_INFO 1 +#define CONFIG_BT_RESERVE_DRAM 0xdb5c +#define CONFIG_APP_COMPILE_TIME_DATE 1 +#define CONFIG_FATFS_FS_LOCK 0 +#define CONFIG_IP_LOST_TIMER_INTERVAL 120 +#define CONFIG_SPIFFS_META_LENGTH 4 +#define CONFIG_ESP32_PANIC_PRINT_REBOOT 1 +#define CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE 20 +#define CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED 1 +#define CONFIG_AWS_IOT_MQTT_RX_BUF_LEN 512 +#define CONFIG_MB_SERIAL_BUF_SIZE 256 +#define CONFIG_CONSOLE_UART_BAUDRATE 115200 +#define CONFIG_LWIP_MAX_SOCKETS 10 +#define CONFIG_LWIP_NETIF_LOOPBACK 1 +#define CONFIG_MCA_TRACE_LEVEL_WARNING 1 +#define CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT "pthread" +#define CONFIG_EMAC_TASK_PRIORITY 20 +#define CONFIG_TIMER_TASK_STACK_DEPTH 2048 +#define CONFIG_TCP_MSS 1436 +#define CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED 1 +#define CONFIG_BTIF_INITIAL_TRACE_LEVEL 2 +#define CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF 3 +#define CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4 1 +#define CONFIG_FATFS_CODEPAGE 437 +#define CONFIG_APPL_TRACE_LEVEL_WARNING 1 +#define CONFIG_BTC_INITIAL_TRACE_LEVEL 2 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_160 1 +#define CONFIG_ULP_COPROC_RESERVE_MEM 0 +#define CONFIG_LWIP_MAX_UDP_PCBS 16 +#define CONFIG_ESPTOOLPY_BAUD 115200 +#define CONFIG_INT_WDT_CHECK_CPU1 1 +#define CONFIG_AVRC_INITIAL_TRACE_LEVEL 2 +#define CONFIG_ADC_CAL_LUT_ENABLE 1 +#define CONFIG_AWS_IOT_MQTT_TX_BUF_LEN 512 +#define CONFIG_FLASHMODE_DIO 1 +#define CONFIG_ESPTOOLPY_AFTER_RESET 1 +#define CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED 1 +#define CONFIG_LWIP_DHCPS_MAX_STATION_NUM 8 +#define CONFIG_TOOLPREFIX "xtensa-esp32-elf-" +#define CONFIG_MBEDTLS_ECP_C 1 +#define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1536 +#define CONFIG_MBEDTLS_RC4_DISABLED 1 +#define CONFIG_GAP_TRACE_LEVEL_WARNING 1 +#define CONFIG_CONSOLE_UART_NUM 0 +#define CONFIG_AWS_IOT_SHADOW_MAX_JSON_TOKEN_EXPECTED 120 +#define CONFIG_ESP32_APPTRACE_LOCK_ENABLE 1 +#define CONFIG_PTHREAD_STACK_MIN 768 +#define CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC 1 +#define CONFIG_ESPTOOLPY_BAUD_115200B 1 +#define CONFIG_TCP_OVERSIZE_MSS 1 +#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS 1 +#define CONFIG_CONSOLE_UART_DEFAULT 1 +#define CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN 16384 +#define CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS 4 +#define CONFIG_GATT_TRACE_LEVEL_WARNING 1 +#define CONFIG_ESPTOOLPY_FLASHSIZE_DETECT 1 +#define CONFIG_TIMER_TASK_STACK_SIZE 3584 +#define CONFIG_BTIF_TRACE_LEVEL_WARNING 1 +#define CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE 1 +#define CONFIG_HCI_INITIAL_TRACE_LEVEL 2 +#define CONFIG_AVDT_INITIAL_TRACE_LEVEL 2 +#define CONFIG_MBEDTLS_X509_CRL_PARSE_C 1 +#define CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER 1 +#define CONFIG_HTTPD_PURGE_BUF_LEN 32 +#define CONFIG_SCAN_DUPLICATE_BY_DEVICE_ADDR 1 +#define CONFIG_AWS_IOT_SHADOW_MAX_SHADOW_TOPIC_LENGTH_WITHOUT_THINGNAME 60 +#define CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER 1 +#define CONFIG_MB_SERIAL_TASK_STACK_SIZE 2048 +#define CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO 1 +#define CONFIG_LWIP_DHCPS_LEASE_UNIT 60 +#define CONFIG_EFUSE_MAX_BLK_LEN 192 +#define CONFIG_SPIFFS_USE_MAGIC 1 +#define CONFIG_TCPIP_TASK_STACK_SIZE 2048 +#define CONFIG_BLUFI_TRACE_LEVEL_WARNING 1 +#define CONFIG_BLUEDROID_PINNED_TO_CORE_0 1 +#define CONFIG_TASK_WDT 1 +#define CONFIG_RFCOMM_INITIAL_TRACE_LEVEL 2 +#define CONFIG_MAIN_TASK_STACK_SIZE 32768 +#define CONFIG_SPIFFS_PAGE_CHECK 1 +#define CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0 1 +#define CONFIG_LWIP_MAX_ACTIVE_TCP 16 +#define CONFIG_TASK_WDT_TIMEOUT_S 5 +#define CONFIG_INT_WDT_TIMEOUT_MS 300 +#define CONFIG_ESPTOOLPY_FLASHMODE "dio" +#define CONFIG_BTC_TASK_STACK_SIZE 3072 +#define CONFIG_BLUEDROID_ENABLED 1 +#define CONFIG_NEWLIB_STDIN_LINE_ENDING_CR 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA 1 +#define CONFIG_ESPTOOLPY_BEFORE "default_reset" +#define CONFIG_ADC2_DISABLE_DAC 1 +#define CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_NUM 100 +#define CONFIG_ESP32_REV_MIN_1 1 +#define CONFIG_LOG_DEFAULT_LEVEL 3 +#define CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION 1 +#define CONFIG_TIMER_QUEUE_LENGTH 10 +#define CONFIG_ESP32_REV_MIN 1 +#define CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT 1 +#define CONFIG_GATTS_SEND_SERVICE_CHANGE_MODE 0 +#define CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY 1 +#define CONFIG_MAKE_WARN_UNDEFINED_VARIABLES 1 +#define CONFIG_FATFS_TIMEOUT_MS 10000 +#define CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM 32 +#define CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS 1 +#define CONFIG_PAN_INITIAL_TRACE_LEVEL 2 +#define CONFIG_MBEDTLS_CCM_C 1 +#define CONFIG_SPI_MASTER_ISR_IN_IRAM 1 +#define CONFIG_MCA_INITIAL_TRACE_LEVEL 2 +#define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER 20 +#define CONFIG_A2D_INITIAL_TRACE_LEVEL 2 +#define CONFIG_ESP32_RTC_CLK_CAL_CYCLES 1024 +#define CONFIG_ESP32_WIFI_TX_BA_WIN 6 +#define CONFIG_ESP32_WIFI_NVS_ENABLED 1 +#define CONFIG_MDNS_MAX_SERVICES 10 +#define CONFIG_IDF_TARGET_ESP32 1 +#define CONFIG_EMAC_CHECK_LINK_PERIOD_MS 2000 +#define CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED 1 +#define CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS 20 +#define CONFIG_LIBSODIUM_USE_MBEDTLS_SHA 1 +#define CONFIG_AWS_IOT_SDK 1 +#define CONFIG_DMA_RX_BUF_NUM 10 +#define CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED 1 +#define CONFIG_TCP_SYNMAXRTX 6 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA 1 +#define CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF 0 +#define CONFIG_PYTHON "python" +#define CONFIG_MBEDTLS_ECP_NIST_OPTIM 1 +#define CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 1 +#define CONFIG_ESPTOOLPY_COMPRESSED 1 +#define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv" +#define CONFIG_MB_CONTROLLER_STACK_SIZE 4096 +#define CONFIG_TCP_SND_BUF_DEFAULT 5744 +#define CONFIG_GARP_TMR_INTERVAL 60 +#define CONFIG_LWIP_DHCP_MAX_NTP_SERVERS 1 +#define CONFIG_BNEP_INITIAL_TRACE_LEVEL 2 +#define CONFIG_HCI_TRACE_LEVEL_WARNING 1 +#define CONFIG_TCP_MSL 60000 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_1 1 +#define CONFIG_LWIP_SO_REUSE_RXTOALL 1 +#define CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT 20 +#define CONFIG_ESP32_WIFI_MGMT_SBUF_NUM 32 +#define CONFIG_PARTITION_TABLE_SINGLE_APP 1 +#define CONFIG_UNITY_ENABLE_FLOAT 1 +#define CONFIG_ESP32_WIFI_RX_BA_WIN 6 +#define CONFIG_MBEDTLS_X509_CSR_PARSE_C 1 +#define CONFIG_SPIFFS_USE_MTIME 1 +#define CONFIG_BTC_TRACE_LEVEL_WARNING 1 +#define CONFIG_EMAC_TASK_STACK_SIZE 3072 +#define CONFIG_SMP_TRACE_LEVEL_WARNING 1 +#define CONFIG_MB_QUEUE_LENGTH 20 +#define CONFIG_SW_COEXIST_PREFERENCE_VALUE 2 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA 1 +#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1 +#define CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER 1 +#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE 2304 +#define CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V 1 +#define CONFIG_A2D_TRACE_LEVEL_WARNING 1 +#define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000 +#define CONFIG_AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS 5 +#define CONFIG_BROWNOUT_DET_LVL 0 +#define CONFIG_MBEDTLS_PEM_PARSE_C 1 +#define CONFIG_SPIFFS_GC_MAX_RUNS 10 +#define CONFIG_ESP32_APPTRACE_DEST_NONE 1 +#define CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA 1 +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM 32 +#define CONFIG_HTTPD_MAX_URI_LEN 512 +#define CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED 1 +#define CONFIG_AVCT_TRACE_LEVEL_WARNING 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED 1 +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 1 +#define CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ 160 +#define CONFIG_MBEDTLS_HARDWARE_AES 1 +#define CONFIG_FREERTOS_HZ 100 +#define CONFIG_LOG_COLORS 1 +#define CONFIG_OSI_TRACE_LEVEL_WARNING 1 +#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE 1 +#define CONFIG_STACK_CHECK_NONE 1 +#define CONFIG_ADC_CAL_EFUSE_TP_ENABLE 1 +#define CONFIG_BNEP_TRACE_LEVEL_WARNING 1 +#define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1 +#define CONFIG_BROWNOUT_DET 1 +#define CONFIG_AWS_IOT_SHADOW_MAX_SIMULTANEOUS_THINGNAMES 10 +#define CONFIG_ESP32_XTAL_FREQ 40 +#define CONFIG_OSI_INITIAL_TRACE_LEVEL 2 +#define CONFIG_MONITOR_BAUD_115200B 1 +#define CONFIG_LOG_BOOTLOADER_LEVEL 3 +#define CONFIG_MBEDTLS_TLS_ENABLED 1 +#define CONFIG_LWIP_MAX_RAW_PCBS 16 +#define CONFIG_BTU_TASK_STACK_SIZE 4096 +#define CONFIG_SMP_ENABLE 1 +#define CONFIG_HID_TRACE_LEVEL_WARNING 1 +#define CONFIG_AVRC_TRACE_LEVEL_WARNING 1 +#define CONFIG_MBEDTLS_SSL_SESSION_TICKETS 1 +#define CONFIG_SPIFFS_MAX_PARTITIONS 3 +#define CONFIG_ESP_ERR_TO_NAME_LOOKUP 1 +#define CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_0 1 +#define CONFIG_MBEDTLS_SSL_RENEGOTIATION 1 +#define CONFIG_HID_INITIAL_TRACE_LEVEL 2 +#define CONFIG_ESPTOOLPY_BEFORE_RESET 1 +#define CONFIG_MB_EVENT_QUEUE_TIMEOUT 20 +#define CONFIG_ESPTOOLPY_BAUD_OTHER_VAL 115200 +#define CONFIG_SPIFFS_OBJ_NAME_LEN 32 +#define CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT 5 +#define CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF 0 +#define CONFIG_PARTITION_TABLE_MD5 1 +#define CONFIG_TCPIP_RECVMBOX_SIZE 32 +#define CONFIG_TCP_MAXRTX 12 +#define CONFIG_BTM_INITIAL_TRACE_LEVEL 2 +#define CONFIG_ESPTOOLPY_AFTER "hard_reset" +#define CONFIG_TCPIP_TASK_AFFINITY 0x7FFFFFFF +#define CONFIG_LWIP_SO_REUSE 1 +#define CONFIG_ESP32_XTAL_FREQ_40 1 +#define CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY 1 +#define CONFIG_DMA_TX_BUF_NUM 10 +#define CONFIG_LWIP_MAX_LISTENING_TCP 16 +#define CONFIG_FREERTOS_INTERRUPT_BACKTRACE 1 +#define CONFIG_WL_SECTOR_SIZE 4096 +#define CONFIG_ESP32_DEBUG_OCDAWARE 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET 1 +#define CONFIG_TIMER_TASK_PRIORITY 1 +#define CONFIG_MBEDTLS_TLS_CLIENT 1 +#define CONFIG_AWS_IOT_MQTT_MIN_RECONNECT_WAIT_INTERVAL 1000 +#define CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI 1 +#define CONFIG_BT_ENABLED 1 +#define CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY 1 +#define CONFIG_SDP_TRACE_LEVEL_WARNING 1 +#define CONFIG_SW_COEXIST_PREFERENCE_BALANCE 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED 1 +#define CONFIG_MONITOR_BAUD 115200 +#define CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT -1 +#define CONFIG_ESP32_DEBUG_STUBS_ENABLE 1 +#define CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT 30 +#define CONFIG_TCPIP_LWIP 1 +#define CONFIG_REDUCE_PHY_TX_POWER 1 +#define CONFIG_BOOTLOADER_WDT_TIME_MS 9000 +#define CONFIG_PAN_TRACE_LEVEL_WARNING 1 +#define CONFIG_FREERTOS_CORETIMER_0 1 +#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv" +#define CONFIG_MBEDTLS_HAVE_TIME 1 +#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1 +#define CONFIG_TCP_QUEUE_OOSEQ 1 +#define CONFIG_GATTS_ENABLE 1 +#define CONFIG_ADC_CAL_EFUSE_VREF_ENABLE 1 +#define CONFIG_MBEDTLS_TLS_SERVER 1 +#define CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT 1 +#define CONFIG_BLE_ADV_REPORT_FLOW_CONTROL_SUPPORTED 1 +#define CONFIG_FREERTOS_ISR_STACKSIZE 1536 +#define CONFIG_SUPPORT_TERMIOS 1 +#define CONFIG_OPENSSL_ASSERT_DO_NOTHING 1 +#define CONFIG_IDF_TARGET "esp32" +#define CONFIG_WL_SECTOR_SIZE_4096 1 +#define CONFIG_OPTIMIZATION_LEVEL_DEBUG 1 +#define CONFIG_GATT_INITIAL_TRACE_LEVEL 2 +#define CONFIG_FREERTOS_NO_AFFINITY 0x7FFFFFFF +#define CONFIG_AWS_IOT_MQTT_HOST "" +#define CONFIG_L2CAP_TRACE_LEVEL_WARNING 1 +#define CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED 1 +#define CONFIG_HTTPD_ERR_RESP_NO_DELAY 1 +#define CONFIG_MB_TIMER_INDEX 0 +#define CONFIG_SCAN_DUPLICATE_TYPE 0 +#define CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED 1 +#define CONFIG_APPL_INITIAL_TRACE_LEVEL 2 +#define CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED 1 +#define CONFIG_SPI_FLASH_ERASE_YIELD_TICKS 1 +#define CONFIG_SMP_INITIAL_TRACE_LEVEL 2 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA 1 +#define CONFIG_SPI_SLAVE_ISR_IN_IRAM 1 +#define CONFIG_L2CAP_INITIAL_TRACE_LEVEL 2 +#define CONFIG_SYSTEM_EVENT_QUEUE_SIZE 32 +#define CONFIG_BT_ACL_CONNECTIONS 4 +#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 1 +#define CONFIG_BOOTLOADER_WDT_ENABLE 1 +#define CONFIG_GAP_INITIAL_TRACE_LEVEL 2 +#define CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED 1 +#define CONFIG_LWIP_LOOPBACK_MAX_PBUFS 8 +#define CONFIG_MB_TIMER_GROUP 0 +#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE 1 +#define CONFIG_SPIFFS_PAGE_SIZE 256 +#define CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED 1 +#define CONFIG_ESP32_DPORT_WORKAROUND 1 +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0 1 +#define CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT 3072 +#define CONFIG_MB_TIMER_PORT_ENABLED 1 +#define CONFIG_DUPLICATE_SCAN_CACHE_SIZE 50 +#define CONFIG_MONITOR_BAUD_OTHER_VAL 115200 +#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 1 +#define CONFIG_ESPTOOLPY_PORT "COM19" +#define CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS 1 +#define CONFIG_UNITY_ENABLE_DOUBLE 1 +#define CONFIG_BLE_ADV_REPORT_DISCARD_THRSHOLD 20 +#define CONFIG_BLUEDROID_PINNED_TO_CORE 0 +#define CONFIG_ESP32_WIFI_IRAM_OPT 1 +#define CONFIG_BLUFI_INITIAL_TRACE_LEVEL 2 diff --git a/ext/wasm3/platforms/embedded/esp8266/.gitignore b/ext/wasm3/platforms/embedded/esp8266/.gitignore new file mode 100644 index 0000000..03f4a3c --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp8266/.gitignore @@ -0,0 +1 @@ +.pio diff --git a/ext/wasm3/platforms/embedded/esp8266/lib/wasm3 b/ext/wasm3/platforms/embedded/esp8266/lib/wasm3 new file mode 120000 index 0000000..17056a9 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp8266/lib/wasm3 @@ -0,0 +1 @@ +../../../../source \ No newline at end of file diff --git a/ext/wasm3/platforms/embedded/esp8266/platformio.ini b/ext/wasm3/platforms/embedded/esp8266/platformio.ini new file mode 100644 index 0000000..5e1b0d8 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp8266/platformio.ini @@ -0,0 +1,29 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp8266] +platform = espressif8266 +board = nodemcuv2 +framework = arduino +monitor_speed = 115200 +upload_speed = 460800 + +board_build.f_cpu = 160000000L + +src_filter = + +<*> + - + +src_build_flags = + -Dd_m3FixedHeap=8192 + -O3 -Wfatal-errors + -flto + #-fPIC -fverbose-asm -save-temps=obj + diff --git a/ext/wasm3/platforms/embedded/esp8266/src/main.cpp b/ext/wasm3/platforms/embedded/esp8266/src/main.cpp new file mode 100644 index 0000000..41d5417 --- /dev/null +++ b/ext/wasm3/platforms/embedded/esp8266/src/main.cpp @@ -0,0 +1,71 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include "Arduino.h" + +#include +#include "wasm3.h" + +#include "extra/fib32.wasm.h" + +#define FATAL(msg, ...) { printf("Fatal: " msg "\n", ##__VA_ARGS__); return; } + +void run_wasm() +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + uint32_t fsize = fib32_wasm_len; + + printf("Loading WebAssembly...\n"); + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + if (!runtime) FATAL("m3_NewRuntime failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule: %s", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule: %s", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction: %s", result); + + printf("Running...\n"); + + result = m3_CallV(f, 24); + if (result) FATAL("m3_Call: %s", result); + + uint32_t value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults: %s", result); + + printf("Result: %d\n", value); +} + +void setup() +{ + Serial.begin(115200); + delay(10); + + Serial.print("\nWasm3 v" M3_VERSION " on ESP8266, build " __DATE__ " " __TIME__ "\n"); + + u32 start = millis(); + run_wasm(); + u32 end = millis(); + + Serial.print(String("Elapsed: ") + (end - start) + " ms\n"); +} + +void loop() +{ + delay(100); +} diff --git a/ext/wasm3/platforms/embedded/fomu/.env b/ext/wasm3/platforms/embedded/fomu/.env new file mode 100644 index 0000000..c4f2f8b --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/.env @@ -0,0 +1,17 @@ +fomu-reset () { + wishbone-tool 0xe0006000 0xac +} + +fomu-reload () { + fomu-reset + dfu-util -e +} + +fomu-load-dbg () { + dfu-util -e + wishbone-tool -s gdb +} + +fomu-gdb () { + riscv64-unknown-elf-gdb $1 -ex 'target remote localhost:1234' +} diff --git a/ext/wasm3/platforms/embedded/fomu/.gitignore b/ext/wasm3/platforms/embedded/fomu/.gitignore new file mode 100644 index 0000000..ba969de --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/.gitignore @@ -0,0 +1,5 @@ +.obj +wasm3.bin +wasm3.dfu +wasm3.elf +wasm3.ihex diff --git a/ext/wasm3/platforms/embedded/fomu/Makefile b/ext/wasm3/platforms/embedded/fomu/Makefile new file mode 100644 index 0000000..4619d6b --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/Makefile @@ -0,0 +1,121 @@ +GIT_VERSION := $(shell git describe --tags) + +# There is no 64-bit gcc on Raspberry Pi, so use the 32-bit version +ifneq (,$(wildcard /etc/rpi-issue)) +TRGT ?= riscv32-unknown-elf- +else +TRGT ?= riscv64-unknown-elf- +endif + +CC := $(TRGT)gcc +CXX := $(TRGT)g++ +OBJCOPY := $(TRGT)objcopy + +RM := rm -rf +COPY := cp -a +PATH_SEP := / + +ifeq ($(OS),Windows_NT) +COPY := copy +RM := del +PATH_SEP := \\ +endif + +BASE_DIR := . +LD_DIR := $(BASE_DIR)/ld +LDSCRIPT := $(BASE_DIR)/ld/linker.ld +ADD_CFLAGS := -I$(BASE_DIR)/include -I$(BASE_DIR)/src/wasm3/ -D__vexriscv__ \ + -DFOMU -Dd_m3FixedHeap=8192 + +ADD_LFLAGS := -lm +PACKAGE := wasm3 + +LTO := -flto -Wl,--allow-multiple-definition + +LDSCRIPTS := $(LDSCRIPT) $(LD_DIR)/output_format.ld $(LD_DIR)/regions.ld +SRC_DIR := $(BASE_DIR)/src +DBG_CFLAGS := -ggdb -g -DDEBUG -Wall +DBG_LFLAGS := -ggdb -g -Wall +CFLAGS := $(ADD_CFLAGS) \ + -Wall -Wextra -Wno-unused-parameter -Wno-unused-variable \ + -Wno-missing-field-initializers \ + -ffunction-sections -fdata-sections -fno-common \ + -fomit-frame-pointer -Os $(LTO) \ + -march=rv32i -mabi=ilp32 \ + -DGIT_VERSION=u\"$(GIT_VERSION)\" -std=gnu11 +CXXFLAGS := $(CFLAGS) -std=c++11 -fno-rtti -fno-exceptions +LFLAGS := $(CFLAGS) $(ADD_LFLAGS) -L$(LD_DIR) \ + -nostartfiles $(LTO) \ + -Wl,--gc-sections \ + -Wl,--script=$(LDSCRIPT) \ + -Wl,--build-id=none + +OBJ_DIR := .obj + +CSOURCES := $(shell find -L $(SRC_DIR) -type f -name '*.c') +CPPSOURCES := $(shell find -L $(SRC_DIR) -type f -name '*.cpp') +ASOURCES := $(shell find -L $(SRC_DIR) -type f -name '*.S') +COBJS := $(addprefix $(OBJ_DIR)/,$(CSOURCES:.c=.o)) +CXXOBJS := $(addprefix $(OBJ_DIR)/,$(CPPSOURCES:.cpp=.o)) +AOBJS := $(addprefix $(OBJ_DIR)/,$(ASOURCES:.S=.o)) +OBJECTS := $(COBJS) $(CXXOBJS) $(AOBJS) +VPATH := $(SRC_DIR) + +QUIET := @ + +ALL := all +TARGET := $(PACKAGE).elf +CLEAN := clean + +$(ALL): $(TARGET) $(PACKAGE).bin $(PACKAGE).ihex $(PACKAGE).dfu + +#$(OBJECTS): | $(OBJ_DIR) + +$(TARGET): $(OBJECTS) $(LDSCRIPTS) + $(QUIET) echo " LD $@" + $(QUIET) $(CC) $(OBJECTS) $(LFLAGS) -o $@ + +$(PACKAGE).bin: $(TARGET) + $(QUIET) echo " OBJCOPY $@" + $(QUIET) $(OBJCOPY) -O binary $(TARGET) $@ + +$(PACKAGE).dfu: $(PACKAGE).bin + $(QUIET) echo " DFU $@" + $(QUIET) $(COPY) $(PACKAGE).bin $@ + $(QUIET) dfu-suffix -v 1209 -p 70b1 -a $@ + +$(PACKAGE).ihex: $(TARGET) + $(QUIET) echo " IHEX $(PACKAGE).ihex" + $(QUIET) $(OBJCOPY) -O ihex $(TARGET) $@ + +$(DEBUG): CFLAGS += $(DBG_CFLAGS) +$(DEBUG): LFLAGS += $(DBG_LFLAGS) +CFLAGS += $(DBG_CFLAGS) +LFLAGS += $(DBG_LFLAGS) +$(DEBUG): $(TARGET) + +$(OBJ_DIR): + $(QUIET) mkdir $(OBJ_DIR) + +$(COBJS) : $(OBJ_DIR)/%.o : %.c $(BASE_DIR)/Makefile + $(QUIET) mkdir -p $(@D) + $(QUIET) echo " CC $< $@" + $(QUIET) $(CC) -c $< $(CFLAGS) -o $@ -MMD + +$(OBJ_DIR)/%.o: %.cpp + $(QUIET) mkdir -p $(@D) + $(QUIET) echo " CXX $< $@" + $(QUIET) $(CXX) -c $< $(CXXFLAGS) -o $@ -MMD + +$(OBJ_DIR)/%.o: %.S + $(QUIET) mkdir -p $(@D) + $(QUIET) echo " AS $< $@" + $(QUIET) $(CC) -x assembler-with-cpp -c $< $(CFLAGS) -o $@ -MMD + +.PHONY: clean + +clean: + - $(RM) -rf $(OBJ_DIR) + - $(RM) $(TARGET) $(PACKAGE).bin $(PACKAGE).symbol $(PACKAGE).ihex $(PACKAGE).dfu + +-include $(OBJECTS:.o=.d) diff --git a/ext/wasm3/platforms/embedded/fomu/README.md b/ext/wasm3/platforms/embedded/fomu/README.md new file mode 100644 index 0000000..e919a41 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/README.md @@ -0,0 +1,36 @@ +## Build for Fomu + +```sh +export PATH=/opt/fomu-toolchain-linux_x86_64-v1.5.6/bin:$PATH +make +``` + +### Upload: + +```sh +dfu-util -D wasm3.dfu +``` + +## Hints + +```sh +# To reboot fomu: +wishbone-tool 0xe0006000 0xac + +# To run previously flashed program on Fomu: +dfu-util -e +``` + +## Debugging + +```sh +wishbone-tool -s gdb +``` +On second tab: +```sh +riscv64-unknown-elf-gdb wasm3.elf -ex 'target remote localhost:1234' + +b m3_CallWithArgs +print *(uint64_t*)env->stack + +``` diff --git a/ext/wasm3/platforms/embedded/fomu/gdb_init b/ext/wasm3/platforms/embedded/fomu/gdb_init new file mode 100644 index 0000000..e2287c9 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/gdb_init @@ -0,0 +1,11 @@ +set history save on +set confirm off +set remotetimeout 240 +set print asm-demangle on + +target remote localhost:1234 + +# monitor reset halt +# load +# continue +# quit diff --git a/ext/wasm3/platforms/embedded/fomu/include/console.h b/ext/wasm3/platforms/embedded/fomu/include/console.h new file mode 100644 index 0000000..a1cf599 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/console.h @@ -0,0 +1,24 @@ +#ifndef __CONSOLE_H +#define __CONSOLE_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*console_write_hook)(char); +typedef char (*console_read_hook)(void); +typedef int (*console_read_nonblock_hook)(void); + +void console_set_write_hook(console_write_hook h); +void console_set_read_hook(console_read_hook r, console_read_nonblock_hook rn); + +char readchar(void); +int readchar_nonblock(void); + +void putsnonl(const char *s); + +#ifdef __cplusplus +} +#endif + +#endif /* __CONSOLE_H */ diff --git a/ext/wasm3/platforms/embedded/fomu/include/crc.h b/ext/wasm3/platforms/embedded/fomu/include/crc.h new file mode 100644 index 0000000..88c8d95 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/crc.h @@ -0,0 +1,15 @@ +#ifndef __CRC_H +#define __CRC_H + +#ifdef __cplusplus +extern "C" { +#endif + +unsigned short crc16(const unsigned char *buffer, int len); +unsigned int crc32(const unsigned char *buffer, unsigned int len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ext/wasm3/platforms/embedded/fomu/include/csr-defs.h b/ext/wasm3/platforms/embedded/fomu/include/csr-defs.h new file mode 100644 index 0000000..d98e8df --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/csr-defs.h @@ -0,0 +1,11 @@ +#ifndef CSR_DEFS__H +#define CSR_DEFS__H + +#define CSR_MSTATUS_MIE 0x8 + +#define CSR_IRQ_MASK 0xBC0 +#define CSR_IRQ_PENDING 0xFC0 + +#define CSR_DCACHE_INFO 0xCC0 + +#endif /* CSR_DEFS__H */ diff --git a/ext/wasm3/platforms/embedded/fomu/include/generated/csr.h b/ext/wasm3/platforms/embedded/fomu/include/generated/csr.h new file mode 100644 index 0000000..c18b102 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/generated/csr.h @@ -0,0 +1,773 @@ +//-------------------------------------------------------------------------------- +// Auto-generated by Migen (ae42105) & LiteX (3a72688b) on 2019-08-23 13:21:26 +//-------------------------------------------------------------------------------- +#ifndef __GENERATED_CSR_H +#define __GENERATED_CSR_H +#include +#ifdef CSR_ACCESSORS_DEFINED +extern void csr_writeb(uint8_t value, unsigned long addr); +extern uint8_t csr_readb(unsigned long addr); +extern void csr_writew(uint16_t value, unsigned long addr); +extern uint16_t csr_readw(unsigned long addr); +extern void csr_writel(uint32_t value, unsigned long addr); +extern uint32_t csr_readl(unsigned long addr); +#else /* ! CSR_ACCESSORS_DEFINED */ +#include +#endif /* ! CSR_ACCESSORS_DEFINED */ + +/* ctrl */ +#define CSR_CTRL_BASE 0xe0000000L +#define CSR_CTRL_RESET_ADDR 0xe0000000L +#define CSR_CTRL_RESET_SIZE 1 +static inline unsigned char ctrl_reset_read(void) { + unsigned char r = csr_readl(0xe0000000L); + return r; +} +static inline void ctrl_reset_write(unsigned char value) { + csr_writel(value, 0xe0000000L); +} +#define CSR_CTRL_SCRATCH_ADDR 0xe0000004L +#define CSR_CTRL_SCRATCH_SIZE 4 +static inline unsigned int ctrl_scratch_read(void) { + unsigned int r = csr_readl(0xe0000004L); + r <<= 8; + r |= csr_readl(0xe0000008L); + r <<= 8; + r |= csr_readl(0xe000000cL); + r <<= 8; + r |= csr_readl(0xe0000010L); + return r; +} +static inline void ctrl_scratch_write(unsigned int value) { + csr_writel(value >> 24, 0xe0000004L); + csr_writel(value >> 16, 0xe0000008L); + csr_writel(value >> 8, 0xe000000cL); + csr_writel(value, 0xe0000010L); +} +#define CSR_CTRL_BUS_ERRORS_ADDR 0xe0000014L +#define CSR_CTRL_BUS_ERRORS_SIZE 4 +static inline unsigned int ctrl_bus_errors_read(void) { + unsigned int r = csr_readl(0xe0000014L); + r <<= 8; + r |= csr_readl(0xe0000018L); + r <<= 8; + r |= csr_readl(0xe000001cL); + r <<= 8; + r |= csr_readl(0xe0000020L); + return r; +} + +/* picorvspi */ +#define CSR_PICORVSPI_BASE 0xe0005000L +#define CSR_PICORVSPI_CFG1_ADDR 0xe0005000L +#define CSR_PICORVSPI_CFG1_SIZE 1 +static inline unsigned char picorvspi_cfg1_read(void) { + unsigned char r = csr_readl(0xe0005000L); + return r; +} +static inline void picorvspi_cfg1_write(unsigned char value) { + csr_writel(value, 0xe0005000L); +} +#define CSR_PICORVSPI_CFG2_ADDR 0xe0005004L +#define CSR_PICORVSPI_CFG2_SIZE 1 +static inline unsigned char picorvspi_cfg2_read(void) { + unsigned char r = csr_readl(0xe0005004L); + return r; +} +static inline void picorvspi_cfg2_write(unsigned char value) { + csr_writel(value, 0xe0005004L); +} +#define CSR_PICORVSPI_CFG3_ADDR 0xe0005008L +#define CSR_PICORVSPI_CFG3_SIZE 1 +static inline unsigned char picorvspi_cfg3_read(void) { + unsigned char r = csr_readl(0xe0005008L); + return r; +} +static inline void picorvspi_cfg3_write(unsigned char value) { + csr_writel(value, 0xe0005008L); +} +#define CSR_PICORVSPI_CFG4_ADDR 0xe000500cL +#define CSR_PICORVSPI_CFG4_SIZE 1 +static inline unsigned char picorvspi_cfg4_read(void) { + unsigned char r = csr_readl(0xe000500cL); + return r; +} +static inline void picorvspi_cfg4_write(unsigned char value) { + csr_writel(value, 0xe000500cL); +} +#define CSR_PICORVSPI_STAT1_ADDR 0xe0005010L +#define CSR_PICORVSPI_STAT1_SIZE 1 +static inline unsigned char picorvspi_stat1_read(void) { + unsigned char r = csr_readl(0xe0005010L); + return r; +} +#define CSR_PICORVSPI_STAT2_ADDR 0xe0005014L +#define CSR_PICORVSPI_STAT2_SIZE 1 +static inline unsigned char picorvspi_stat2_read(void) { + unsigned char r = csr_readl(0xe0005014L); + return r; +} +#define CSR_PICORVSPI_STAT3_ADDR 0xe0005018L +#define CSR_PICORVSPI_STAT3_SIZE 1 +static inline unsigned char picorvspi_stat3_read(void) { + unsigned char r = csr_readl(0xe0005018L); + return r; +} +#define CSR_PICORVSPI_STAT4_ADDR 0xe000501cL +#define CSR_PICORVSPI_STAT4_SIZE 1 +static inline unsigned char picorvspi_stat4_read(void) { + unsigned char r = csr_readl(0xe000501cL); + return r; +} + +/* reboot */ +#define CSR_REBOOT_BASE 0xe0006000L +#define CSR_REBOOT_CTRL_ADDR 0xe0006000L +#define CSR_REBOOT_CTRL_SIZE 1 +static inline unsigned char reboot_ctrl_read(void) { + unsigned char r = csr_readl(0xe0006000L); + return r; +} +static inline void reboot_ctrl_write(unsigned char value) { + csr_writel(value, 0xe0006000L); +} +#define CSR_REBOOT_ADDR_ADDR 0xe0006004L +#define CSR_REBOOT_ADDR_SIZE 4 +static inline unsigned int reboot_addr_read(void) { + unsigned int r = csr_readl(0xe0006004L); + r <<= 8; + r |= csr_readl(0xe0006008L); + r <<= 8; + r |= csr_readl(0xe000600cL); + r <<= 8; + r |= csr_readl(0xe0006010L); + return r; +} +static inline void reboot_addr_write(unsigned int value) { + csr_writel(value >> 24, 0xe0006004L); + csr_writel(value >> 16, 0xe0006008L); + csr_writel(value >> 8, 0xe000600cL); + csr_writel(value, 0xe0006010L); +} + +/* rgb */ +#define CSR_RGB_BASE 0xe0006800L +#define CSR_RGB_DAT_ADDR 0xe0006800L +#define CSR_RGB_DAT_SIZE 1 +static inline unsigned char rgb_dat_read(void) { + unsigned char r = csr_readl(0xe0006800L); + return r; +} +static inline void rgb_dat_write(unsigned char value) { + csr_writel(value, 0xe0006800L); +} +#define CSR_RGB_ADDR_ADDR 0xe0006804L +#define CSR_RGB_ADDR_SIZE 1 +static inline unsigned char rgb_addr_read(void) { + unsigned char r = csr_readl(0xe0006804L); + return r; +} +static inline void rgb_addr_write(unsigned char value) { + csr_writel(value, 0xe0006804L); +} +#define CSR_RGB_CTRL_ADDR 0xe0006808L +#define CSR_RGB_CTRL_SIZE 1 +static inline unsigned char rgb_ctrl_read(void) { + unsigned char r = csr_readl(0xe0006808L); + return r; +} +static inline void rgb_ctrl_write(unsigned char value) { + csr_writel(value, 0xe0006808L); +} +#define CSR_RGB_RAW_ADDR 0xe000680cL +#define CSR_RGB_RAW_SIZE 1 +static inline unsigned char rgb_raw_read(void) { + unsigned char r = csr_readl(0xe000680cL); + return r; +} +static inline void rgb_raw_write(unsigned char value) { + csr_writel(value, 0xe000680cL); +} + +/* timer0 */ +#define CSR_TIMER0_BASE 0xe0002800L +#define CSR_TIMER0_LOAD_ADDR 0xe0002800L +#define CSR_TIMER0_LOAD_SIZE 4 +static inline unsigned int timer0_load_read(void) { + unsigned int r = csr_readl(0xe0002800L); + r <<= 8; + r |= csr_readl(0xe0002804L); + r <<= 8; + r |= csr_readl(0xe0002808L); + r <<= 8; + r |= csr_readl(0xe000280cL); + return r; +} +static inline void timer0_load_write(unsigned int value) { + csr_writel(value >> 24, 0xe0002800L); + csr_writel(value >> 16, 0xe0002804L); + csr_writel(value >> 8, 0xe0002808L); + csr_writel(value, 0xe000280cL); +} +#define CSR_TIMER0_RELOAD_ADDR 0xe0002810L +#define CSR_TIMER0_RELOAD_SIZE 4 +static inline unsigned int timer0_reload_read(void) { + unsigned int r = csr_readl(0xe0002810L); + r <<= 8; + r |= csr_readl(0xe0002814L); + r <<= 8; + r |= csr_readl(0xe0002818L); + r <<= 8; + r |= csr_readl(0xe000281cL); + return r; +} +static inline void timer0_reload_write(unsigned int value) { + csr_writel(value >> 24, 0xe0002810L); + csr_writel(value >> 16, 0xe0002814L); + csr_writel(value >> 8, 0xe0002818L); + csr_writel(value, 0xe000281cL); +} +#define CSR_TIMER0_EN_ADDR 0xe0002820L +#define CSR_TIMER0_EN_SIZE 1 +static inline unsigned char timer0_en_read(void) { + unsigned char r = csr_readl(0xe0002820L); + return r; +} +static inline void timer0_en_write(unsigned char value) { + csr_writel(value, 0xe0002820L); +} +#define CSR_TIMER0_UPDATE_VALUE_ADDR 0xe0002824L +#define CSR_TIMER0_UPDATE_VALUE_SIZE 1 +static inline unsigned char timer0_update_value_read(void) { + unsigned char r = csr_readl(0xe0002824L); + return r; +} +static inline void timer0_update_value_write(unsigned char value) { + csr_writel(value, 0xe0002824L); +} +#define CSR_TIMER0_VALUE_ADDR 0xe0002828L +#define CSR_TIMER0_VALUE_SIZE 4 +static inline unsigned int timer0_value_read(void) { + unsigned int r = csr_readl(0xe0002828L); + r <<= 8; + r |= csr_readl(0xe000282cL); + r <<= 8; + r |= csr_readl(0xe0002830L); + r <<= 8; + r |= csr_readl(0xe0002834L); + return r; +} +#define CSR_TIMER0_EV_STATUS_ADDR 0xe0002838L +#define CSR_TIMER0_EV_STATUS_SIZE 1 +static inline unsigned char timer0_ev_status_read(void) { + unsigned char r = csr_readl(0xe0002838L); + return r; +} +static inline void timer0_ev_status_write(unsigned char value) { + csr_writel(value, 0xe0002838L); +} +#define CSR_TIMER0_EV_PENDING_ADDR 0xe000283cL +#define CSR_TIMER0_EV_PENDING_SIZE 1 +static inline unsigned char timer0_ev_pending_read(void) { + unsigned char r = csr_readl(0xe000283cL); + return r; +} +static inline void timer0_ev_pending_write(unsigned char value) { + csr_writel(value, 0xe000283cL); +} +#define CSR_TIMER0_EV_ENABLE_ADDR 0xe0002840L +#define CSR_TIMER0_EV_ENABLE_SIZE 1 +static inline unsigned char timer0_ev_enable_read(void) { + unsigned char r = csr_readl(0xe0002840L); + return r; +} +static inline void timer0_ev_enable_write(unsigned char value) { + csr_writel(value, 0xe0002840L); +} + +/* touch */ +#define CSR_TOUCH_BASE 0xe0005800L +#define CSR_TOUCH_O_ADDR 0xe0005800L +#define CSR_TOUCH_O_SIZE 1 +static inline unsigned char touch_o_read(void) { + unsigned char r = csr_readl(0xe0005800L); + return r; +} +static inline void touch_o_write(unsigned char value) { + csr_writel(value, 0xe0005800L); +} +#define CSR_TOUCH_OE_ADDR 0xe0005804L +#define CSR_TOUCH_OE_SIZE 1 +static inline unsigned char touch_oe_read(void) { + unsigned char r = csr_readl(0xe0005804L); + return r; +} +static inline void touch_oe_write(unsigned char value) { + csr_writel(value, 0xe0005804L); +} +#define CSR_TOUCH_I_ADDR 0xe0005808L +#define CSR_TOUCH_I_SIZE 1 +static inline unsigned char touch_i_read(void) { + unsigned char r = csr_readl(0xe0005808L); + return r; +} + +/* usb */ +#define CSR_USB_BASE 0xe0004800L +#define CSR_USB_PULLUP_OUT_ADDR 0xe0004800L +#define CSR_USB_PULLUP_OUT_SIZE 1 +static inline unsigned char usb_pullup_out_read(void) { + unsigned char r = csr_readl(0xe0004800L); + return r; +} +static inline void usb_pullup_out_write(unsigned char value) { + csr_writel(value, 0xe0004800L); +} +#define CSR_USB_EP_0_OUT_EV_STATUS_ADDR 0xe0004804L +#define CSR_USB_EP_0_OUT_EV_STATUS_SIZE 1 +static inline unsigned char usb_ep_0_out_ev_status_read(void) { + unsigned char r = csr_readl(0xe0004804L); + return r; +} +static inline void usb_ep_0_out_ev_status_write(unsigned char value) { + csr_writel(value, 0xe0004804L); +} +#define CSR_USB_EP_0_OUT_EV_PENDING_ADDR 0xe0004808L +#define CSR_USB_EP_0_OUT_EV_PENDING_SIZE 1 +static inline unsigned char usb_ep_0_out_ev_pending_read(void) { + unsigned char r = csr_readl(0xe0004808L); + return r; +} +static inline void usb_ep_0_out_ev_pending_write(unsigned char value) { + csr_writel(value, 0xe0004808L); +} +#define CSR_USB_EP_0_OUT_EV_ENABLE_ADDR 0xe000480cL +#define CSR_USB_EP_0_OUT_EV_ENABLE_SIZE 1 +static inline unsigned char usb_ep_0_out_ev_enable_read(void) { + unsigned char r = csr_readl(0xe000480cL); + return r; +} +static inline void usb_ep_0_out_ev_enable_write(unsigned char value) { + csr_writel(value, 0xe000480cL); +} +#define CSR_USB_EP_0_OUT_LAST_TOK_ADDR 0xe0004810L +#define CSR_USB_EP_0_OUT_LAST_TOK_SIZE 1 +static inline unsigned char usb_ep_0_out_last_tok_read(void) { + unsigned char r = csr_readl(0xe0004810L); + return r; +} +#define CSR_USB_EP_0_OUT_RESPOND_ADDR 0xe0004814L +#define CSR_USB_EP_0_OUT_RESPOND_SIZE 1 +static inline unsigned char usb_ep_0_out_respond_read(void) { + unsigned char r = csr_readl(0xe0004814L); + return r; +} +static inline void usb_ep_0_out_respond_write(unsigned char value) { + csr_writel(value, 0xe0004814L); +} +#define CSR_USB_EP_0_OUT_DTB_ADDR 0xe0004818L +#define CSR_USB_EP_0_OUT_DTB_SIZE 1 +static inline unsigned char usb_ep_0_out_dtb_read(void) { + unsigned char r = csr_readl(0xe0004818L); + return r; +} +static inline void usb_ep_0_out_dtb_write(unsigned char value) { + csr_writel(value, 0xe0004818L); +} +#define CSR_USB_EP_0_OUT_OBUF_HEAD_ADDR 0xe000481cL +#define CSR_USB_EP_0_OUT_OBUF_HEAD_SIZE 1 +static inline unsigned char usb_ep_0_out_obuf_head_read(void) { + unsigned char r = csr_readl(0xe000481cL); + return r; +} +static inline void usb_ep_0_out_obuf_head_write(unsigned char value) { + csr_writel(value, 0xe000481cL); +} +#define CSR_USB_EP_0_OUT_OBUF_EMPTY_ADDR 0xe0004820L +#define CSR_USB_EP_0_OUT_OBUF_EMPTY_SIZE 1 +static inline unsigned char usb_ep_0_out_obuf_empty_read(void) { + unsigned char r = csr_readl(0xe0004820L); + return r; +} +#define CSR_USB_EP_0_IN_EV_STATUS_ADDR 0xe0004824L +#define CSR_USB_EP_0_IN_EV_STATUS_SIZE 1 +static inline unsigned char usb_ep_0_in_ev_status_read(void) { + unsigned char r = csr_readl(0xe0004824L); + return r; +} +static inline void usb_ep_0_in_ev_status_write(unsigned char value) { + csr_writel(value, 0xe0004824L); +} +#define CSR_USB_EP_0_IN_EV_PENDING_ADDR 0xe0004828L +#define CSR_USB_EP_0_IN_EV_PENDING_SIZE 1 +static inline unsigned char usb_ep_0_in_ev_pending_read(void) { + unsigned char r = csr_readl(0xe0004828L); + return r; +} +static inline void usb_ep_0_in_ev_pending_write(unsigned char value) { + csr_writel(value, 0xe0004828L); +} +#define CSR_USB_EP_0_IN_EV_ENABLE_ADDR 0xe000482cL +#define CSR_USB_EP_0_IN_EV_ENABLE_SIZE 1 +static inline unsigned char usb_ep_0_in_ev_enable_read(void) { + unsigned char r = csr_readl(0xe000482cL); + return r; +} +static inline void usb_ep_0_in_ev_enable_write(unsigned char value) { + csr_writel(value, 0xe000482cL); +} +#define CSR_USB_EP_0_IN_LAST_TOK_ADDR 0xe0004830L +#define CSR_USB_EP_0_IN_LAST_TOK_SIZE 1 +static inline unsigned char usb_ep_0_in_last_tok_read(void) { + unsigned char r = csr_readl(0xe0004830L); + return r; +} +#define CSR_USB_EP_0_IN_RESPOND_ADDR 0xe0004834L +#define CSR_USB_EP_0_IN_RESPOND_SIZE 1 +static inline unsigned char usb_ep_0_in_respond_read(void) { + unsigned char r = csr_readl(0xe0004834L); + return r; +} +static inline void usb_ep_0_in_respond_write(unsigned char value) { + csr_writel(value, 0xe0004834L); +} +#define CSR_USB_EP_0_IN_DTB_ADDR 0xe0004838L +#define CSR_USB_EP_0_IN_DTB_SIZE 1 +static inline unsigned char usb_ep_0_in_dtb_read(void) { + unsigned char r = csr_readl(0xe0004838L); + return r; +} +static inline void usb_ep_0_in_dtb_write(unsigned char value) { + csr_writel(value, 0xe0004838L); +} +#define CSR_USB_EP_0_IN_IBUF_HEAD_ADDR 0xe000483cL +#define CSR_USB_EP_0_IN_IBUF_HEAD_SIZE 1 +static inline unsigned char usb_ep_0_in_ibuf_head_read(void) { + unsigned char r = csr_readl(0xe000483cL); + return r; +} +static inline void usb_ep_0_in_ibuf_head_write(unsigned char value) { + csr_writel(value, 0xe000483cL); +} +#define CSR_USB_EP_0_IN_IBUF_EMPTY_ADDR 0xe0004840L +#define CSR_USB_EP_0_IN_IBUF_EMPTY_SIZE 1 +static inline unsigned char usb_ep_0_in_ibuf_empty_read(void) { + unsigned char r = csr_readl(0xe0004840L); + return r; +} +#define CSR_USB_EP_1_IN_EV_STATUS_ADDR 0xe0004844L +#define CSR_USB_EP_1_IN_EV_STATUS_SIZE 1 +static inline unsigned char usb_ep_1_in_ev_status_read(void) { + unsigned char r = csr_readl(0xe0004844L); + return r; +} +static inline void usb_ep_1_in_ev_status_write(unsigned char value) { + csr_writel(value, 0xe0004844L); +} +#define CSR_USB_EP_1_IN_EV_PENDING_ADDR 0xe0004848L +#define CSR_USB_EP_1_IN_EV_PENDING_SIZE 1 +static inline unsigned char usb_ep_1_in_ev_pending_read(void) { + unsigned char r = csr_readl(0xe0004848L); + return r; +} +static inline void usb_ep_1_in_ev_pending_write(unsigned char value) { + csr_writel(value, 0xe0004848L); +} +#define CSR_USB_EP_1_IN_EV_ENABLE_ADDR 0xe000484cL +#define CSR_USB_EP_1_IN_EV_ENABLE_SIZE 1 +static inline unsigned char usb_ep_1_in_ev_enable_read(void) { + unsigned char r = csr_readl(0xe000484cL); + return r; +} +static inline void usb_ep_1_in_ev_enable_write(unsigned char value) { + csr_writel(value, 0xe000484cL); +} +#define CSR_USB_EP_1_IN_LAST_TOK_ADDR 0xe0004850L +#define CSR_USB_EP_1_IN_LAST_TOK_SIZE 1 +static inline unsigned char usb_ep_1_in_last_tok_read(void) { + unsigned char r = csr_readl(0xe0004850L); + return r; +} +#define CSR_USB_EP_1_IN_RESPOND_ADDR 0xe0004854L +#define CSR_USB_EP_1_IN_RESPOND_SIZE 1 +static inline unsigned char usb_ep_1_in_respond_read(void) { + unsigned char r = csr_readl(0xe0004854L); + return r; +} +static inline void usb_ep_1_in_respond_write(unsigned char value) { + csr_writel(value, 0xe0004854L); +} +#define CSR_USB_EP_1_IN_DTB_ADDR 0xe0004858L +#define CSR_USB_EP_1_IN_DTB_SIZE 1 +static inline unsigned char usb_ep_1_in_dtb_read(void) { + unsigned char r = csr_readl(0xe0004858L); + return r; +} +static inline void usb_ep_1_in_dtb_write(unsigned char value) { + csr_writel(value, 0xe0004858L); +} +#define CSR_USB_EP_1_IN_IBUF_HEAD_ADDR 0xe000485cL +#define CSR_USB_EP_1_IN_IBUF_HEAD_SIZE 1 +static inline unsigned char usb_ep_1_in_ibuf_head_read(void) { + unsigned char r = csr_readl(0xe000485cL); + return r; +} +static inline void usb_ep_1_in_ibuf_head_write(unsigned char value) { + csr_writel(value, 0xe000485cL); +} +#define CSR_USB_EP_1_IN_IBUF_EMPTY_ADDR 0xe0004860L +#define CSR_USB_EP_1_IN_IBUF_EMPTY_SIZE 1 +static inline unsigned char usb_ep_1_in_ibuf_empty_read(void) { + unsigned char r = csr_readl(0xe0004860L); + return r; +} +#define CSR_USB_EP_2_OUT_EV_STATUS_ADDR 0xe0004864L +#define CSR_USB_EP_2_OUT_EV_STATUS_SIZE 1 +static inline unsigned char usb_ep_2_out_ev_status_read(void) { + unsigned char r = csr_readl(0xe0004864L); + return r; +} +static inline void usb_ep_2_out_ev_status_write(unsigned char value) { + csr_writel(value, 0xe0004864L); +} +#define CSR_USB_EP_2_OUT_EV_PENDING_ADDR 0xe0004868L +#define CSR_USB_EP_2_OUT_EV_PENDING_SIZE 1 +static inline unsigned char usb_ep_2_out_ev_pending_read(void) { + unsigned char r = csr_readl(0xe0004868L); + return r; +} +static inline void usb_ep_2_out_ev_pending_write(unsigned char value) { + csr_writel(value, 0xe0004868L); +} +#define CSR_USB_EP_2_OUT_EV_ENABLE_ADDR 0xe000486cL +#define CSR_USB_EP_2_OUT_EV_ENABLE_SIZE 1 +static inline unsigned char usb_ep_2_out_ev_enable_read(void) { + unsigned char r = csr_readl(0xe000486cL); + return r; +} +static inline void usb_ep_2_out_ev_enable_write(unsigned char value) { + csr_writel(value, 0xe000486cL); +} +#define CSR_USB_EP_2_OUT_LAST_TOK_ADDR 0xe0004870L +#define CSR_USB_EP_2_OUT_LAST_TOK_SIZE 1 +static inline unsigned char usb_ep_2_out_last_tok_read(void) { + unsigned char r = csr_readl(0xe0004870L); + return r; +} +#define CSR_USB_EP_2_OUT_RESPOND_ADDR 0xe0004874L +#define CSR_USB_EP_2_OUT_RESPOND_SIZE 1 +static inline unsigned char usb_ep_2_out_respond_read(void) { + unsigned char r = csr_readl(0xe0004874L); + return r; +} +static inline void usb_ep_2_out_respond_write(unsigned char value) { + csr_writel(value, 0xe0004874L); +} +#define CSR_USB_EP_2_OUT_DTB_ADDR 0xe0004878L +#define CSR_USB_EP_2_OUT_DTB_SIZE 1 +static inline unsigned char usb_ep_2_out_dtb_read(void) { + unsigned char r = csr_readl(0xe0004878L); + return r; +} +static inline void usb_ep_2_out_dtb_write(unsigned char value) { + csr_writel(value, 0xe0004878L); +} +#define CSR_USB_EP_2_OUT_OBUF_HEAD_ADDR 0xe000487cL +#define CSR_USB_EP_2_OUT_OBUF_HEAD_SIZE 1 +static inline unsigned char usb_ep_2_out_obuf_head_read(void) { + unsigned char r = csr_readl(0xe000487cL); + return r; +} +static inline void usb_ep_2_out_obuf_head_write(unsigned char value) { + csr_writel(value, 0xe000487cL); +} +#define CSR_USB_EP_2_OUT_OBUF_EMPTY_ADDR 0xe0004880L +#define CSR_USB_EP_2_OUT_OBUF_EMPTY_SIZE 1 +static inline unsigned char usb_ep_2_out_obuf_empty_read(void) { + unsigned char r = csr_readl(0xe0004880L); + return r; +} +#define CSR_USB_EP_2_IN_EV_STATUS_ADDR 0xe0004884L +#define CSR_USB_EP_2_IN_EV_STATUS_SIZE 1 +static inline unsigned char usb_ep_2_in_ev_status_read(void) { + unsigned char r = csr_readl(0xe0004884L); + return r; +} +static inline void usb_ep_2_in_ev_status_write(unsigned char value) { + csr_writel(value, 0xe0004884L); +} +#define CSR_USB_EP_2_IN_EV_PENDING_ADDR 0xe0004888L +#define CSR_USB_EP_2_IN_EV_PENDING_SIZE 1 +static inline unsigned char usb_ep_2_in_ev_pending_read(void) { + unsigned char r = csr_readl(0xe0004888L); + return r; +} +static inline void usb_ep_2_in_ev_pending_write(unsigned char value) { + csr_writel(value, 0xe0004888L); +} +#define CSR_USB_EP_2_IN_EV_ENABLE_ADDR 0xe000488cL +#define CSR_USB_EP_2_IN_EV_ENABLE_SIZE 1 +static inline unsigned char usb_ep_2_in_ev_enable_read(void) { + unsigned char r = csr_readl(0xe000488cL); + return r; +} +static inline void usb_ep_2_in_ev_enable_write(unsigned char value) { + csr_writel(value, 0xe000488cL); +} +#define CSR_USB_EP_2_IN_LAST_TOK_ADDR 0xe0004890L +#define CSR_USB_EP_2_IN_LAST_TOK_SIZE 1 +static inline unsigned char usb_ep_2_in_last_tok_read(void) { + unsigned char r = csr_readl(0xe0004890L); + return r; +} +#define CSR_USB_EP_2_IN_RESPOND_ADDR 0xe0004894L +#define CSR_USB_EP_2_IN_RESPOND_SIZE 1 +static inline unsigned char usb_ep_2_in_respond_read(void) { + unsigned char r = csr_readl(0xe0004894L); + return r; +} +static inline void usb_ep_2_in_respond_write(unsigned char value) { + csr_writel(value, 0xe0004894L); +} +#define CSR_USB_EP_2_IN_DTB_ADDR 0xe0004898L +#define CSR_USB_EP_2_IN_DTB_SIZE 1 +static inline unsigned char usb_ep_2_in_dtb_read(void) { + unsigned char r = csr_readl(0xe0004898L); + return r; +} +static inline void usb_ep_2_in_dtb_write(unsigned char value) { + csr_writel(value, 0xe0004898L); +} +#define CSR_USB_EP_2_IN_IBUF_HEAD_ADDR 0xe000489cL +#define CSR_USB_EP_2_IN_IBUF_HEAD_SIZE 1 +static inline unsigned char usb_ep_2_in_ibuf_head_read(void) { + unsigned char r = csr_readl(0xe000489cL); + return r; +} +static inline void usb_ep_2_in_ibuf_head_write(unsigned char value) { + csr_writel(value, 0xe000489cL); +} +#define CSR_USB_EP_2_IN_IBUF_EMPTY_ADDR 0xe00048a0L +#define CSR_USB_EP_2_IN_IBUF_EMPTY_SIZE 1 +static inline unsigned char usb_ep_2_in_ibuf_empty_read(void) { + unsigned char r = csr_readl(0xe00048a0L); + return r; +} +#define CSR_USB_ADDRESS_ADDR 0xe00048a4L +#define CSR_USB_ADDRESS_SIZE 1 +static inline unsigned char usb_address_read(void) { + unsigned char r = csr_readl(0xe00048a4L); + return r; +} +static inline void usb_address_write(unsigned char value) { + csr_writel(value, 0xe00048a4L); +} + +/* version */ +#define CSR_VERSION_BASE 0xe0007000L +#define CSR_VERSION_MAJOR_ADDR 0xe0007000L +#define CSR_VERSION_MAJOR_SIZE 1 +static inline unsigned char version_major_read(void) { + unsigned char r = csr_readl(0xe0007000L); + return r; +} +#define CSR_VERSION_MINOR_ADDR 0xe0007004L +#define CSR_VERSION_MINOR_SIZE 1 +static inline unsigned char version_minor_read(void) { + unsigned char r = csr_readl(0xe0007004L); + return r; +} +#define CSR_VERSION_REVISION_ADDR 0xe0007008L +#define CSR_VERSION_REVISION_SIZE 1 +static inline unsigned char version_revision_read(void) { + unsigned char r = csr_readl(0xe0007008L); + return r; +} +#define CSR_VERSION_GITREV_ADDR 0xe000700cL +#define CSR_VERSION_GITREV_SIZE 4 +static inline unsigned int version_gitrev_read(void) { + unsigned int r = csr_readl(0xe000700cL); + r <<= 8; + r |= csr_readl(0xe0007010L); + r <<= 8; + r |= csr_readl(0xe0007014L); + r <<= 8; + r |= csr_readl(0xe0007018L); + return r; +} +#define CSR_VERSION_GITEXTRA_ADDR 0xe000701cL +#define CSR_VERSION_GITEXTRA_SIZE 2 +static inline unsigned short int version_gitextra_read(void) { + unsigned short int r = csr_readl(0xe000701cL); + r <<= 8; + r |= csr_readl(0xe0007020L); + return r; +} +#define CSR_VERSION_DIRTY_ADDR 0xe0007024L +#define CSR_VERSION_DIRTY_SIZE 1 +static inline unsigned char version_dirty_read(void) { + unsigned char r = csr_readl(0xe0007024L); + return r; +} +#define CSR_VERSION_MODEL_ADDR 0xe0007028L +#define CSR_VERSION_MODEL_SIZE 1 +static inline unsigned char version_model_read(void) { + unsigned char r = csr_readl(0xe0007028L); + return r; +} + +/* constants */ +#define TIMER0_INTERRUPT 0 +static inline int timer0_interrupt_read(void) { + return 0; +} +#define USB_INTERRUPT 3 +static inline int usb_interrupt_read(void) { + return 3; +} +#define CSR_DATA_WIDTH 8 +static inline int csr_data_width_read(void) { + return 8; +} +#define SYSTEM_CLOCK_FREQUENCY 12000000 +static inline int system_clock_frequency_read(void) { + return 12000000; +} +#define CONFIG_BITSTREAM_SYNC_HEADER1 2123999870 +static inline int config_bitstream_sync_header1_read(void) { + return 2123999870; +} +#define CONFIG_BITSTREAM_SYNC_HEADER2 2125109630 +static inline int config_bitstream_sync_header2_read(void) { + return 2125109630; +} +#define CONFIG_CLOCK_FREQUENCY 12000000 +static inline int config_clock_frequency_read(void) { + return 12000000; +} +#define CONFIG_CPU_RESET_ADDR 0 +static inline int config_cpu_reset_addr_read(void) { + return 0; +} +#define CONFIG_CPU_TYPE "VEXRISCV" +static inline const char * config_cpu_type_read(void) { + return "VEXRISCV"; +} +#define CONFIG_CPU_VARIANT "VEXRISCV" +static inline const char * config_cpu_variant_read(void) { + return "VEXRISCV"; +} +#define CONFIG_CSR_DATA_WIDTH 8 +static inline int config_csr_data_width_read(void) { + return 8; +} +#define CONFIG_FOMU_REV "HACKER" +static inline const char * config_fomu_rev_read(void) { + return "HACKER"; +} +#define CONFIG_FOMU_REV_HACKER 1 +static inline int config_fomu_rev_hacker_read(void) { + return 1; +} + +#endif diff --git a/ext/wasm3/platforms/embedded/fomu/include/generated/mem.h b/ext/wasm3/platforms/embedded/fomu/include/generated/mem.h new file mode 100644 index 0000000..6fe108e --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/generated/mem.h @@ -0,0 +1,16 @@ +#ifndef __GENERATED_MEM_H +#define __GENERATED_MEM_H + +#define VEXRISCV_DEBUG_BASE 0xf00f0000 +#define VEXRISCV_DEBUG_SIZE 0x00000010 + +#define SRAM_BASE 0x10000000 +#define SRAM_SIZE 0x00020000 + +#define ROM_BASE 0x00000000 +#define ROM_SIZE 0x00002000 + +#define SPIFLASH_BASE 0x20000000 +#define SPIFLASH_SIZE 0x00200000 + +#endif diff --git a/ext/wasm3/platforms/embedded/fomu/include/hw/common.h b/ext/wasm3/platforms/embedded/fomu/include/hw/common.h new file mode 100644 index 0000000..af668f7 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/hw/common.h @@ -0,0 +1,52 @@ +#ifndef __HW_COMMON_H +#define __HW_COMMON_H + +#include + +/* To overwrite CSR accessors, define extern, non-inlined versions + * of csr_read[bwl]() and csr_write[bwl](), and define + * CSR_ACCESSORS_DEFINED. + */ + +#ifndef CSR_ACCESSORS_DEFINED +#define CSR_ACCESSORS_DEFINED + +#ifdef __ASSEMBLER__ +#define MMPTR(x) x +#else /* ! __ASSEMBLER__ */ +#define MMPTR(x) (*((volatile unsigned int *)(x))) + +static inline void csr_writeb(uint8_t value, uint32_t addr) +{ + *((volatile uint8_t *)addr) = value; +} + +static inline uint8_t csr_readb(uint32_t addr) +{ + return *(volatile uint8_t *)addr; +} + +static inline void csr_writew(uint16_t value, uint32_t addr) +{ + *((volatile uint16_t *)addr) = value; +} + +static inline uint16_t csr_readw(uint32_t addr) +{ + return *(volatile uint16_t *)addr; +} + +static inline void csr_writel(uint32_t value, uint32_t addr) +{ + *((volatile uint32_t *)addr) = value; +} + +static inline uint32_t csr_readl(uint32_t addr) +{ + return *(volatile uint32_t *)addr; +} +#endif /* ! __ASSEMBLER__ */ + +#endif /* ! CSR_ACCESSORS_DEFINED */ + +#endif /* __HW_COMMON_H */ diff --git a/ext/wasm3/platforms/embedded/fomu/include/hw/flags.h b/ext/wasm3/platforms/embedded/fomu/include/hw/flags.h new file mode 100644 index 0000000..911a1b6 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/hw/flags.h @@ -0,0 +1,40 @@ +#ifndef __HW_FLAGS_H +#define __HW_FLAGS_H + +#define UART_EV_TX 0x1 +#define UART_EV_RX 0x2 + +#define DFII_CONTROL_SEL 0x01 +#define DFII_CONTROL_CKE 0x02 +#define DFII_CONTROL_ODT 0x04 +#define DFII_CONTROL_RESET_N 0x08 + +#define DFII_COMMAND_CS 0x01 +#define DFII_COMMAND_WE 0x02 +#define DFII_COMMAND_CAS 0x04 +#define DFII_COMMAND_RAS 0x08 +#define DFII_COMMAND_WRDATA 0x10 +#define DFII_COMMAND_RDDATA 0x20 + +#define ETHMAC_EV_SRAM_WRITER 0x1 +#define ETHMAC_EV_SRAM_READER 0x1 + +#define CLKGEN_STATUS_BUSY 0x1 +#define CLKGEN_STATUS_PROGDONE 0x2 +#define CLKGEN_STATUS_LOCKED 0x4 + +#define DVISAMPLER_TOO_LATE 0x1 +#define DVISAMPLER_TOO_EARLY 0x2 + +#define DVISAMPLER_DELAY_MASTER_CAL 0x01 +#define DVISAMPLER_DELAY_MASTER_RST 0x02 +#define DVISAMPLER_DELAY_SLAVE_CAL 0x04 +#define DVISAMPLER_DELAY_SLAVE_RST 0x08 +#define DVISAMPLER_DELAY_INC 0x10 +#define DVISAMPLER_DELAY_DEC 0x20 + +#define DVISAMPLER_SLOT_EMPTY 0 +#define DVISAMPLER_SLOT_LOADED 1 +#define DVISAMPLER_SLOT_PENDING 2 + +#endif /* __HW_FLAGS_H */ diff --git a/ext/wasm3/platforms/embedded/fomu/include/irq.h b/ext/wasm3/platforms/embedded/fomu/include/irq.h new file mode 100644 index 0000000..19f00b1 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/irq.h @@ -0,0 +1,144 @@ +#ifndef __IRQ_H +#define __IRQ_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifdef __picorv32__ +// PicoRV32 has a very limited interrupt support, implemented via custom +// instructions. It also doesn't have a global interrupt enable/disable, so +// we have to emulate it via saving and restoring a mask and using 0/~1 as a +// hardware mask. +// Due to all this somewhat low-level mess, all of the glue is implemented in +// the RiscV crt0, and this header is kept as a thin wrapper. Since interrupts +// managed by this layer, do not call interrupt instructions directly, as the +// state will go out of sync with the hardware. + +// Read only. +extern unsigned int _irq_pending; +// Read only. +extern unsigned int _irq_mask; +// Read only. +extern unsigned int _irq_enabled; +extern void _irq_enable(void); +extern void _irq_disable(void); +extern void _irq_setmask(unsigned int); +#endif + +static inline unsigned int irq_getie(void) +{ +#if defined (__lm32__) + unsigned int ie; + __asm__ __volatile__("rcsr %0, IE" : "=r" (ie)); + return ie; +#elif defined (__or1k__) + return !!(mfspr(SPR_SR) & SPR_SR_IEE); +#elif defined (__picorv32__) + return _irq_enabled != 0; +#elif defined (__vexriscv__) + return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0; +#elif defined (__minerva__) + return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0; +#else +#error Unsupported architecture +#endif +} + +static inline void irq_setie(unsigned int ie) +{ +#if defined (__lm32__) + __asm__ __volatile__("wcsr IE, %0" : : "r" (ie)); +#elif defined (__or1k__) + if (ie & 0x1) + mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_IEE); + else + mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_IEE); +#elif defined (__picorv32__) + if (ie & 0x1) + _irq_enable(); + else + _irq_disable(); +#elif defined (__vexriscv__) + if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE); +#elif defined (__minerva__) + if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE); +#else +#error Unsupported architecture +#endif +} + +static inline unsigned int irq_getmask(void) +{ +#if defined (__lm32__) + unsigned int mask; + __asm__ __volatile__("rcsr %0, IM" : "=r" (mask)); + return mask; +#elif defined (__or1k__) + return mfspr(SPR_PICMR); +#elif defined (__picorv32__) + // PicoRV32 interrupt mask bits are high-disabled. This is the inverse of how + // LiteX sees things. + return ~_irq_mask; +#elif defined (__vexriscv__) + unsigned int mask; + asm volatile ("csrr %0, %1" : "=r"(mask) : "i"(CSR_IRQ_MASK)); + return mask; +#elif defined (__minerva__) + unsigned int mask; + asm volatile ("csrr %0, %1" : "=r"(mask) : "i"(CSR_IRQ_MASK)); + return mask; +#else +#error Unsupported architecture +#endif +} + +static inline void irq_setmask(unsigned int mask) +{ +#if defined (__lm32__) + __asm__ __volatile__("wcsr IM, %0" : : "r" (mask)); +#elif defined (__or1k__) + mtspr(SPR_PICMR, mask); +#elif defined (__picorv32__) + // PicoRV32 interrupt mask bits are high-disabled. This is the inverse of how + // LiteX sees things. + _irq_setmask(~mask); +#elif defined (__vexriscv__) + asm volatile ("csrw %0, %1" :: "i"(CSR_IRQ_MASK), "r"(mask)); +#elif defined (__minerva__) + asm volatile ("csrw %0, %1" :: "i"(CSR_IRQ_MASK), "r"(mask)); +#else +#error Unsupported architecture +#endif +} + +static inline unsigned int irq_pending(void) +{ +#if defined (__lm32__) + unsigned int pending; + __asm__ __volatile__("rcsr %0, IP" : "=r" (pending)); + return pending; +#elif defined (__or1k__) + return mfspr(SPR_PICSR); +#elif defined (__picorv32__) + return _irq_pending; +#elif defined (__vexriscv__) + unsigned int pending; + asm volatile ("csrr %0, %1" : "=r"(pending) : "i"(CSR_IRQ_PENDING)); + return pending; +#elif defined (__minerva__) + unsigned int pending; + asm volatile ("csrr %0, %1" : "=r"(pending) : "i"(CSR_IRQ_PENDING)); + return pending; +#else +#error Unsupported architecture +#endif +} + +#ifdef __cplusplus +} +#endif + +#endif /* __IRQ_H */ diff --git a/ext/wasm3/platforms/embedded/fomu/include/printf.h b/ext/wasm3/platforms/embedded/fomu/include/printf.h new file mode 100644 index 0000000..73a80a7 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/printf.h @@ -0,0 +1,124 @@ +/* +File: printf.h + +Copyright (c) 2004,2012 Kustaa Nyholm / SpareTimeLabs + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or other +materials provided with the distribution. + +Neither the name of the Kustaa Nyholm or SpareTimeLabs nor the names of its +contributors may be used to endorse or promote products derived from this software +without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. + +---------------------------------------------------------------------- + +This library is really just two files: 'printf.h' and 'printf.c'. + +They provide a simple and small (+200 loc) printf functionality to +be used in embedded systems. + +I've found them so useful in debugging that I do not bother with a +debugger at all. + +They are distributed in source form, so to use them, just compile them +into your project. + +Two printf variants are provided: printf and sprintf. + +The formats supported by this implementation are: 'd' 'u' 'c' 's' 'x' 'X'. + +Zero padding and field width are also supported. + +If the library is compiled with 'PRINTF_SUPPORT_LONG' defined then the +long specifier is also +supported. Note that this will pull in some long math routines (pun intended!) +and thus make your executable noticeably longer. + +The memory footprint of course depends on the target cpu, compiler and +compiler options, but a rough guestimate (based on a H8S target) is about +1.4 kB for code and some twenty 'int's and 'char's, say 60 bytes of stack space. +Not too bad. Your mileage may vary. By hacking the source code you can +get rid of some hundred bytes, I'm sure, but personally I feel the balance of +functionality and flexibility versus code size is close to optimal for +many embedded systems. + +To use the printf you need to supply your own character output function, +something like : + +void putc ( void* p, char c) + { + while (!SERIAL_PORT_EMPTY) ; + SERIAL_PORT_TX_REGISTER = c; + } + +Before you can call printf you need to initialize it to use your +character output function with something like: + +init_printf(NULL,putc); + +Notice the 'NULL' in 'init_printf' and the parameter 'void* p' in 'putc', +the NULL (or any pointer) you pass into the 'init_printf' will eventually be +passed to your 'putc' routine. This allows you to pass some storage space (or +anything really) to the character output function, if necessary. +This is not often needed but it was implemented like that because it made +implementing the sprintf function so neat (look at the source code). + +The code is re-entrant, except for the 'init_printf' function, so it +is safe to call it from interrupts too, although this may result in mixed output. +If you rely on re-entrancy, take care that your 'putc' function is re-entrant! + +The printf and sprintf functions are actually macros that translate to +'tfp_printf' and 'tfp_sprintf'. This makes it possible +to use them along with 'stdio.h' printf's in a single source file. +You just need to undef the names before you include the 'stdio.h'. +Note that these are not function like macros, so if you have variables +or struct members with these names, things will explode in your face. +Without variadic macros this is the best we can do to wrap these +fucnctions. If it is a problem just give up the macros and use the +functions directly or rename them. + +For further details see source code. + +regs Kusti, 23.10.2004 +*/ + + +#ifndef __TFP_PRINTF__ +#define __TFP_PRINTF__ + +#include + +void init_printf(void* putp,void (*putf) (void*,char)); + +void tfp_printf(char *fmt, ...); +void tfp_sprintf(char* s,char *fmt, ...); + +void tfp_format(void* putp,void (*putf) (void*,char),char *fmt, va_list va); + +#define printf tfp_printf +#define sprintf tfp_sprintf + +#endif + + + diff --git a/ext/wasm3/platforms/embedded/fomu/include/rgb.h b/ext/wasm3/platforms/embedded/fomu/include/rgb.h new file mode 100644 index 0000000..5455429 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/rgb.h @@ -0,0 +1,29 @@ +#ifndef _RGB_H_ +#define _RGB_H_ + +void rgb_init(void); +void rgb_set(uint8_t r, uint8_t g, uint8_t b); + +// The amount of time to stay off or on +void rgb_on_time(uint8_t ms); +void rgb_off_time(uint8_t ms); + +// The amount of time to breathe in/out +void rgb_in_time(uint8_t ms); +void rgb_out_time(uint8_t ms); + +enum led_registers { + LEDDCR0 = 8, + LEDDBR = 9, + LEDDONR = 10, + LEDDOFR = 11, + LEDDBCRR = 5, + LEDDBCFR = 6, + LEDDPWRR = 1, + LEDDPWRG = 2, + LEDDPWRB = 3, +}; + +void rgb_write(uint8_t value, uint8_t addr); + +#endif /* _RGB_H_ */ \ No newline at end of file diff --git a/ext/wasm3/platforms/embedded/fomu/include/spi.h b/ext/wasm3/platforms/embedded/fomu/include/spi.h new file mode 100644 index 0000000..190cec8 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/spi.h @@ -0,0 +1,93 @@ +#ifndef BB_SPI_H_ +#define BB_SPI_H_ + +#include + +enum spi_state { + SS_UNCONFIGURED = 0, + SS_SINGLE, + SS_DUAL_RX, + SS_DUAL_TX, + SS_QUAD_RX, + SS_QUAD_TX, + SS_HARDWARE, +}; + +enum spi_type { + ST_UNCONFIGURED, + ST_SINGLE, + ST_DUAL, + ST_QUAD, + ST_QPI, +}; + +enum spi_pin { + SP_MOSI, + SP_MISO, + SP_HOLD, + SP_WP, + SP_CS, + SP_CLK, + SP_D0, + SP_D1, + SP_D2, + SP_D3, +}; + +struct spi_id { + uint8_t manufacturer_id; // Result from 0x90 + uint8_t device_id; // Result from 0x90 + uint8_t _manufacturer_id; // Result from 0x9f + uint8_t memory_type; // Result from 0x9f + uint8_t memory_size; // Result from 0x9f + uint8_t signature; // Result from 0xab + uint8_t serial[4]; // Result from 0x4b + int bytes; // -1 if unknown + const char *manufacturer; + const char *model; + const char *capacity; +}; + +struct ff_spi; + +void spiPause(struct ff_spi *spi); +void spiBegin(struct ff_spi *spi); +void spiEnd(struct ff_spi *spi); + +//void spiSingleTx(struct ff_spi *spi, uint8_t out); +//uint8_t spiSingleRx(struct ff_spi *spi); +//void spiDualTx(struct ff_spi *spi, uint8_t out); +//void spiQuadTx(struct ff_spi *spi, uint8_t out); +void spiCommand(struct ff_spi *spi, uint8_t cmd); +//uint8_t spiDualRx(struct ff_spi *spi); +//uint8_t spiQuadRx(struct ff_spi *spi); +int spiTx(struct ff_spi *spi, uint8_t word); +uint8_t spiRx(struct ff_spi *spi); +uint8_t spiReadStatus(struct ff_spi *spi, uint8_t sr); +void spiWriteStatus(struct ff_spi *spi, uint8_t sr, uint8_t val); +void spiReadSecurity(struct ff_spi *spi, uint8_t sr, uint8_t security[256]); +void spiWriteSecurity(struct ff_spi *spi, uint8_t sr, uint8_t security[256]); +int spiSetType(struct ff_spi *spi, enum spi_type type); +int spiRead(struct ff_spi *spi, uint32_t addr, uint8_t *data, unsigned int count); +int spiIsBusy(struct ff_spi *spi); +int spiBeginErase32(struct ff_spi *spi, uint32_t erase_addr); +int spiBeginErase64(struct ff_spi *spi, uint32_t erase_addr); +int spiBeginWrite(struct ff_spi *spi, uint32_t addr, const void *data, unsigned int count); + +struct spi_id spiId(struct ff_spi *spi); +void spiOverrideSize(struct ff_spi *spi, uint32_t new_size); + +//int spi_wait_for_not_busy(struct ff_spi *spi); +int spiWrite(struct ff_spi *spi, uint32_t addr, const uint8_t *data, unsigned int count); +uint8_t spiReset(struct ff_spi *spi); +int spiInit(struct ff_spi *spi); + +void spiHold(struct ff_spi *spi); +void spiUnhold(struct ff_spi *spi); +void spiSwapTxRx(struct ff_spi *spi); + +struct ff_spi *spiAlloc(void); +void spiSetPin(struct ff_spi *spi, enum spi_pin pin, int val); +void spiFree(void); + +#endif /* BB_SPI_H_ */ diff --git a/ext/wasm3/platforms/embedded/fomu/include/spiflash.h b/ext/wasm3/platforms/embedded/fomu/include/spiflash.h new file mode 100644 index 0000000..a4ff495 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/spiflash.h @@ -0,0 +1,8 @@ +#ifndef __SPIFLASH_H +#define __SPIFLASH_H + +void write_to_flash_page(unsigned int addr, const unsigned char *c, unsigned int len); +void erase_flash_sector(unsigned int addr); +void write_to_flash(unsigned int addr, const unsigned char *c, unsigned int len); + +#endif /* __SPIFLASH_H */ diff --git a/ext/wasm3/platforms/embedded/fomu/include/system.h b/ext/wasm3/platforms/embedded/fomu/include/system.h new file mode 100644 index 0000000..ea3da85 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/system.h @@ -0,0 +1,67 @@ +#ifndef __SYSTEM_H +#define __SYSTEM_H + +#ifdef __cplusplus +extern "C" { +#endif + +void flush_cpu_icache(void); +void flush_cpu_dcache(void); +void flush_l2_cache(void); + +#ifdef __or1k__ +#include +static inline unsigned long mfspr(unsigned long add) +{ + unsigned long ret; + + __asm__ __volatile__ ("l.mfspr %0,%1,0" : "=r" (ret) : "r" (add)); + + return ret; +} + +static inline void mtspr(unsigned long add, unsigned long val) +{ + __asm__ __volatile__ ("l.mtspr %0,%1,0" : : "r" (add), "r" (val)); +} +#endif + + +#if defined(__vexriscv__) || defined(__minerva__) +#include +#define csrr(reg) ({ unsigned long __tmp; \ + asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \ + __tmp; }) + +#define csrw(reg, val) ({ \ + if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \ + asm volatile ("csrw " #reg ", %0" :: "i"(val)); \ + else \ + asm volatile ("csrw " #reg ", %0" :: "r"(val)); }) + +#define csrs(reg, bit) ({ \ + if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ + asm volatile ("csrrs x0, " #reg ", %0" :: "i"(bit)); \ + else \ + asm volatile ("csrrs x0, " #reg ", %0" :: "r"(bit)); }) + +#define csrc(reg, bit) ({ \ + if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \ + asm volatile ("csrrc x0, " #reg ", %0" :: "i"(bit)); \ + else \ + asm volatile ("csrrc x0, " #reg ", %0" :: "r"(bit)); }) +#endif + +#ifdef __cplusplus +} +#endif + +#include + +__attribute__((noreturn)) void reboot(void); + +__attribute__((noreturn)) static inline void warmboot_to_image(uint8_t image_index) { + reboot_ctrl_write(0xac | (image_index & 3) << 0); + while (1); +} +#endif /* __SYSTEM_H */ diff --git a/ext/wasm3/platforms/embedded/fomu/include/time.h b/ext/wasm3/platforms/embedded/fomu/include/time.h new file mode 100644 index 0000000..cbbc688 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/time.h @@ -0,0 +1,16 @@ +#ifndef __TIME_H +#define __TIME_H + +#ifdef __cplusplus +extern "C" { +#endif + +void time_init(void); +int elapsed(int *last_event, int period); +void msleep(int ms); + +#ifdef __cplusplus +} +#endif + +#endif /* __TIME_H */ diff --git a/ext/wasm3/platforms/embedded/fomu/include/toboot-api.h b/ext/wasm3/platforms/embedded/fomu/include/toboot-api.h new file mode 100644 index 0000000..a957f79 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/toboot-api.h @@ -0,0 +1,109 @@ +#ifndef TOBOOT_API_H_ +#define TOBOOT_API_H_ + +#include + +/// Store this configuration struct at offset 0x94 from the start +/// of your binary image. +/// You may set all RESERVED values to 0. as they will be calculated +/// when the program is written to flash. +struct toboot_configuration { + /// Set to 0x907070b2 to indicate a valid configuration header. + uint32_t magic; + + /// Reserved value. Used as a generational counter. Toboot will + /// overwrite this value with a monotonically-increasing counter + /// every time a new image is burned. This is used to determine + /// which image is the newest. + uint16_t reserved_gen; + + /// The starting page for your program in 1024-byte blocks. + /// Toboot itself sets this to 0. If this is nonzero, then it + /// must be located after the Toboot image. Toboot is currently + /// under 5 kilobytes, so make sure this value is at least 6. + uint8_t start; + + /// Configuration bitmask. See below for values. + uint8_t config; + + /// Set to 0x18349420 to prevent the user from entering Toboot manually. + /// Use this value with caution, as it can be used to lockout a Tomu. + uint32_t lock_entry; + + /// A bitmask of sectors to erase when updating the program. Each "1" + /// causes that sector to be erased, unless it's Toboot itself. Bit values + /// determine flash blocks 0-31. + uint32_t erase_mask_lo; + + /// A bitmask of sectors to erase when updating the program. Each "1" + /// causes that sector to e erased. Use these two values to e.g. force + /// private keys to be erased when updating. Bit values determine flash + /// blocks 32-63. + uint32_t erase_mask_hi; + + /// A hash of the entire header, minus this entry. Toboot calculates + /// this when it programs the first block. A Toboot configuration + /// header MUST have a valid hash in order to be considered valid. + uint32_t reserved_hash; +} __attribute__((packed)); + +/// Toboot V1.0 leaves IRQs enabled, mimicking the behavior of +/// AN0042. Toboot V2.0 makes this configurable by adding a +/// bit to the configuration area. +#define TOBOOT_CONFIG_FLAG_ENABLE_IRQ_MASK 0x01 +#define TOBOOT_CONFIG_FLAG_ENABLE_IRQ_SHIFT 0 +#define TOBOOT_CONFIG_FLAG_ENABLE_IRQ (1 << 0) +#define TOBOOT_CONFIG_FLAG_DISABLE_IRQ (0 << 0) + +/// When running a normal program, you won't want Toboot to run. +/// However, when developing new software it is handy to have +/// Toboot run at poweron, instead of jumping straight to your +/// program. Set this flag to enter your program whenever the +/// system has just powered on. +#define TOBOOT_CONFIG_FLAG_AUTORUN_MASK 0x02 +#define TOBOOT_CONFIG_FLAG_AUTORUN_SHIFT 1 +#define TOBOOT_CONFIG_FLAG_AUTORUN (1 << 1) +#define TOBOOT_CONFIG_FLAG_AUTORUN_DISABLED (0 << 1) + +/// When we create a fake header, this flag will be set. Otherwise, +/// leave the flag cleared. This field has no meaning in user +/// applications, and is only used internally. +#define TOBOOT_CONFIG_FAKE_MASK 0x04 +#define TOBOOT_CONFIG_FAKE_SHIFT 2 +#define TOBOOT_CONFIG_FAKE (1 << 2) + +/// Various magic values describing Toboot configuration headers. +#define TOBOOT_V1_MAGIC 0x6fb0 +#define TOBOOT_V1_MAGIC_MASK 0x0000ffff +#define TOBOOT_V2_MAGIC 0x907070b2 +#define TOBOOT_V2_MAGIC_MASK 0xffffffff + +/// This value is used to prevent manual entry into Toboot. +#define TOBOOT_LOCKOUT_MAGIC 0x18349420 + +/// The seed value for the hash of Toboot's configuration header +#define TOBOOT_HASH_SEED 0x037a5cf1 + +/// This is the runtime part that lives at the start of RAM. +/// Running programs can use this to force entry into Toboot +/// during the next reboot. +struct toboot_runtime { + /// Set this to 0x74624346 and reboot to enter bootloader, + /// even if LOCKOUT is enabled. + uint32_t magic; + + /// Set this to 0 when your program starts. + uint8_t boot_count; + + /// The bootloader should set this to 0x23 for Tomu. + uint8_t board_model; + + /// Unused. + uint16_t reserved; +}; + +/// Set runtime.magic to this value and reboot to force +/// entry into Toboot. +#define TOBOOT_FORCE_ENTRY_MAGIC 0x74624346 + +#endif /* TOBOOT_API_H_ */ \ No newline at end of file diff --git a/ext/wasm3/platforms/embedded/fomu/include/toboot-internal.h b/ext/wasm3/platforms/embedded/fomu/include/toboot-internal.h new file mode 100644 index 0000000..9463766 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/toboot-internal.h @@ -0,0 +1,49 @@ +#ifndef TOBOOT_INTERNAL_H_ +#define TOBOOT_INTERNAL_H_ + +#include + +/// This describes the structure that allows the OS to communicate +/// with the bootloader. It keeps track of how many times we've +/// tried booting, as well as a magic value that tells us to enter +/// the bootloader instead of booting the app. +/// It also keeps track of the board model. +__attribute__((section(".boot_token"))) extern struct toboot_runtime boot_token; + +enum bootloader_reason +{ + NOT_ENTERING_BOOTLOADER = 0, + BOOT_TOKEN_PRESENT = 1, + BOOT_FAILED_TOO_MANY_TIMES = 2, + NO_PROGRAM_PRESENT = 3, + BUTTON_HELD_DOWN = 4, + COLD_BOOT_CONFIGURATION_FLAG = 5, +}; + +extern enum bootloader_reason bootloader_reason; + +/// Legacy Toboot V1 configuration values +#ifndef TOBOOT_V1_CFG_FLAGS +#define TOBOOT_V1_CFG_FLAGS 0 +#endif +#define TOBOOT_V1_CFG_MAGIC_MASK 0xffff +#define TOBOOT_V1_CFG_MAGIC 0x70b0 + +#ifndef TOBOOT_V1_APP_FLAGS +#define TOBOOT_V1_APP_FLAGS 0 +#endif + +#define TOBOOT_V1_APP_MAGIC_MASK 0xffff +#define TOBOOT_V1_APP_MAGIC 0x6fb0 +#define TOBOOT_V1_APP_PAGE_MASK 0x00ff0000 +#define TOBOOT_V1_APP_PAGE_SHIFT 16 + +uint32_t tb_first_free_address(void); +uint32_t tb_first_free_sector(void); +const struct toboot_configuration *tb_get_config(void); +uint32_t tb_config_hash(const struct toboot_configuration *cfg); +void tb_sign_config(struct toboot_configuration *cfg); +uint32_t tb_generation(const struct toboot_configuration *cfg); +int tb_valid_signature_at_page(uint32_t page); + +#endif /* TOBOOT_INTERNAL_H_ */ \ No newline at end of file diff --git a/ext/wasm3/platforms/embedded/fomu/include/usb-desc.h b/ext/wasm3/platforms/embedded/fomu/include/usb-desc.h new file mode 100644 index 0000000..6ad6771 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/usb-desc.h @@ -0,0 +1,91 @@ +/* Teensyduino Core Library + * http://www.pjrc.com/teensy/ + * Copyright (c) 2013 PJRC.COM, LLC. + * + * 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: + * + * 1. The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * 2. If the Software is incorporated into a build system that allows + * selection among a list of target devices, then similar target + * devices manufactured by PJRC.COM must be included in the list of + * target devices and selectable in the same manner. + * + * 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. + */ + +#ifndef _usb_desc_h_ +#define _usb_desc_h_ + +#include +#include +#include + +struct usb_setup_request { + union { + struct { + uint8_t bmRequestType; + uint8_t bRequest; + }; + uint16_t wRequestAndType; + }; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +}; + +struct usb_string_descriptor_struct { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wString[]; +}; + +#define NUM_USB_BUFFERS 8 +#define VENDOR_ID 0x1209 // pid.codes +#define PRODUCT_ID 0x5bf0 // Assigned to Fomu project +#define DEVICE_VER 0x0101 // Bootloader version +#define MANUFACTURER_NAME u"Foosn" +#define MANUFACTURER_NAME_LEN sizeof(MANUFACTURER_NAME) +#define PRODUCT_NAME u"Fomu App " GIT_VERSION +#define PRODUCT_NAME_LEN sizeof(PRODUCT_NAME) + +// Microsoft Compatible ID Feature Descriptor +#define MSFT_VENDOR_CODE '~' // Arbitrary, but should be printable ASCII +#define MSFT_WCID_LEN 40 +extern const uint8_t usb_microsoft_wcid[MSFT_WCID_LEN]; + +typedef struct { + uint16_t wValue; + uint16_t length; + const uint8_t *addr; +} usb_descriptor_list_t; + +extern const usb_descriptor_list_t usb_descriptor_list[]; + +// WebUSB Landing page URL descriptor +#define WEBUSB_VENDOR_CODE 2 + +#ifndef LANDING_PAGE_URL +#define LANDING_PAGE_URL "dfu.tomu.im" +#endif + +#define LANDING_PAGE_DESCRIPTOR_SIZE (WEBUSB_DT_URL_DESCRIPTOR_SIZE \ + + sizeof(LANDING_PAGE_URL) - 1) + +extern const struct webusb_url_descriptor landing_url_descriptor; + +#endif diff --git a/ext/wasm3/platforms/embedded/fomu/include/usb.h b/ext/wasm3/platforms/embedded/fomu/include/usb.h new file mode 100644 index 0000000..60d57e4 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/usb.h @@ -0,0 +1,40 @@ +#ifndef __USB_H +#define __USB_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +struct usb_setup_request; + +void usb_isr(void); +void usb_init(void); +void usb_connect(void); +void usb_disconnect(void); + +int usb_irq_happened(void); +void usb_setup(const struct usb_setup_request *setup); +int usb_send(const void *data, int total_count); +void usb_ack_in(void); +void usb_ack_out(void); +void usb_err_in(void); +void usb_err_out(void); +int usb_recv(void *buffer, unsigned int buffer_len); +void usb_poll(void); +int usb_wait_for_send_done(void); +void usb_recv_done(void); +void usb_set_address(uint8_t new_address); + +void usb_putc(char c); +int usb_getc(void); +int usb_write(const char *buf, int count); +int usb_can_getc(void); +int usb_can_putc(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ext/wasm3/platforms/embedded/fomu/include/usbcdc.h b/ext/wasm3/platforms/embedded/fomu/include/usbcdc.h new file mode 100644 index 0000000..20b7836 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/usbcdc.h @@ -0,0 +1,162 @@ +/** @defgroup usb_cdc_defines USB CDC Type Definitions + +@brief Defined Constants and Types for the USB CDC Type Definitions + +@ingroup USB_defines + +@version 1.0.0 + +@author @htmlonly © @endhtmlonly 2010 +Gareth McMullin + +@date 10 March 2013 + +LGPL License Terms @ref lgpl_license +*/ + +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Gareth McMullin + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/**@{*/ + +#ifndef __CDC_H +#define __CDC_H + +/* Definitions of Communications Device Class from + * "Universal Serial Bus Class Definitions for Communications Devices + * Revision 1.2" + */ + +/* Table 2: Communications Device Class Code */ +#define USB_CLASS_CDC 0x02 + +/* Table 4: Class Subclass Code */ +#define USB_CDC_SUBCLASS_DLCM 0x01 +#define USB_CDC_SUBCLASS_ACM 0x02 +/* ... */ + +/* Table 5 Communications Interface Class Control Protocol Codes */ +#define USB_CDC_PROTOCOL_NONE 0x00 +#define USB_CDC_PROTOCOL_AT 0x01 +/* ... */ + +/* Table 6: Data Interface Class Code */ +#define USB_CLASS_DATA 0x0A + +/* Table 12: Type Values for the bDescriptorType Field */ +#define CS_INTERFACE 0x24 +#define CS_ENDPOINT 0x25 + +/* Table 13: bDescriptor SubType in Communications Class Functional + * Descriptors */ +#define USB_CDC_TYPE_HEADER 0x00 +#define USB_CDC_TYPE_CALL_MANAGEMENT 0x01 +#define USB_CDC_TYPE_ACM 0x02 +/* ... */ +#define USB_CDC_TYPE_UNION 0x06 +/* ... */ + +/* Table 15: Class-Specific Descriptor Header Format */ +struct usb_cdc_header_descriptor { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint16_t bcdCDC; +} __attribute__((packed)); + +/* Table 16: Union Interface Functional Descriptor */ +struct usb_cdc_union_descriptor { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bControlInterface; + uint8_t bSubordinateInterface0; + /* ... */ +} __attribute__((packed)); + + +/* Definitions for Abstract Control Model devices from: + * "Universal Serial Bus Communications Class Subclass Specification for + * PSTN Devices" + */ + +/* Table 3: Call Management Functional Descriptor */ +struct usb_cdc_call_management_descriptor { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bmCapabilities; + uint8_t bDataInterface; +} __attribute__((packed)); + +/* Table 4: Abstract Control Management Functional Descriptor */ +struct usb_cdc_acm_descriptor { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubtype; + uint8_t bmCapabilities; +} __attribute__((packed)); + +/* Table 13: Class-Specific Request Codes for PSTN subclasses */ +/* ... */ +#define USB_CDC_REQ_SET_LINE_CODING 0x20 +/* ... */ +#define USB_CDC_REQ_SET_CONTROL_LINE_STATE 0x22 +/* ... */ + +/* Table 17: Line Coding Structure */ +struct usb_cdc_line_coding { + uint32_t dwDTERate; + uint8_t bCharFormat; + uint8_t bParityType; + uint8_t bDataBits; +} __attribute__((packed)); + +enum usb_cdc_line_coding_bCharFormat { + USB_CDC_1_STOP_BITS = 0, + USB_CDC_1_5_STOP_BITS = 1, + USB_CDC_2_STOP_BITS = 2, +}; + +enum usb_cdc_line_coding_bParityType { + USB_CDC_NO_PARITY = 0, + USB_CDC_ODD_PARITY = 1, + USB_CDC_EVEN_PARITY = 2, + USB_CDC_MARK_PARITY = 3, + USB_CDC_SPACE_PARITY = 4, +}; + +/* Table 30: Class-Specific Notification Codes for PSTN subclasses */ +/* ... */ +#define USB_CDC_NOTIFY_SERIAL_STATE 0x20 +/* ... */ + +/* Notification Structure */ +struct usb_cdc_notification { + uint8_t bmRequestType; + uint8_t bNotification; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} __attribute__((packed)); + +#endif + +/**@}*/ + diff --git a/ext/wasm3/platforms/embedded/fomu/include/usbstd.h b/ext/wasm3/platforms/embedded/fomu/include/usbstd.h new file mode 100644 index 0000000..3c61700 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/usbstd.h @@ -0,0 +1,277 @@ +/** @defgroup usb_type_defines USB Standard Structure Definitions + +@brief Defined Constants and Types for the USB Standard Structure +Definitions + +@ingroup USB_defines + +@version 1.0.0 + +@author @htmlonly © @endhtmlonly 2010 +Gareth McMullin + +@date 10 March 2013 + +A set of structure definitions for the USB control structures +defined in chapter 9 of the "Universal Serial Bus Specification Revision 2.0" +Available from the USB Implementers Forum - http://www.usb.org/ + +LGPL License Terms @ref lgpl_license +*/ + +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2010 Gareth McMullin + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/**@{*/ + +#ifndef __USBSTD_H +#define __USBSTD_H + +#include + +/* + * This file contains structure definitions for the USB control structures + * defined in chapter 9 of the "Universal Serial Bus Specification Revision 2.0" + * Available from the USB Implementers Forum - http://www.usb.org/ + */ + +/* USB Setup Data structure - Table 9-2 */ +struct usb_setup_data { + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t wValue; + uint16_t wIndex; + uint16_t wLength; +} __attribute__((packed)); + +/* Class Definition */ +#define USB_CLASS_VENDOR 0xFF + +/* bmRequestType bit definitions */ +/* bit 7 : direction */ +#define USB_REQ_TYPE_DIRECTION 0x80 +#define USB_REQ_TYPE_IN 0x80 +/* bits 6..5 : type */ +#define USB_REQ_TYPE_TYPE 0x60 +#define USB_REQ_TYPE_STANDARD 0x00 +#define USB_REQ_TYPE_CLASS 0x20 +#define USB_REQ_TYPE_VENDOR 0x40 +/* bits 4..0 : recipient */ +#define USB_REQ_TYPE_RECIPIENT 0x1F +#define USB_REQ_TYPE_DEVICE 0x00 +#define USB_REQ_TYPE_INTERFACE 0x01 +#define USB_REQ_TYPE_ENDPOINT 0x02 +#define USB_REQ_TYPE_OTHER 0x03 + +/* USB Standard Request Codes - Table 9-4 */ +#define USB_REQ_GET_STATUS 0 +#define USB_REQ_CLEAR_FEATURE 1 +/* Reserved for future use: 2 */ +#define USB_REQ_SET_FEATURE 3 +/* Reserved for future use: 3 */ +#define USB_REQ_SET_ADDRESS 5 +#define USB_REQ_GET_DESCRIPTOR 6 +#define USB_REQ_SET_DESCRIPTOR 7 +#define USB_REQ_GET_CONFIGURATION 8 +#define USB_REQ_SET_CONFIGURATION 9 +#define USB_REQ_GET_INTERFACE 10 +#define USB_REQ_SET_INTERFACE 11 +#define USB_REQ_SET_SYNCH_FRAME 12 + +/* USB Descriptor Types - Table 9-5 */ +#define USB_DT_DEVICE 1 +#define USB_DT_CONFIGURATION 2 +#define USB_DT_STRING 3 +#define USB_DT_INTERFACE 4 +#define USB_DT_ENDPOINT 5 +#define USB_DT_DEVICE_QUALIFIER 6 +#define USB_DT_OTHER_SPEED_CONFIGURATION 7 +#define USB_DT_INTERFACE_POWER 8 +/* From ECNs */ +#define USB_DT_OTG 9 +#define USB_DT_DEBUG 10 +#define USB_DT_INTERFACE_ASSOCIATION 11 + +/* USB Standard Feature Selectors - Table 9-6 */ +#define USB_FEAT_ENDPOINT_HALT 0 +#define USB_FEAT_DEVICE_REMOTE_WAKEUP 1 +#define USB_FEAT_TEST_MODE 2 + +/* Information Returned by a GetStatus() Request to a Device - Figure 9-4 */ +#define USB_DEV_STATUS_SELF_POWERED 0x01 +#define USB_DEV_STATUS_REMOTE_WAKEUP 0x02 + +/* USB Standard Device Descriptor - Table 9-8 */ +struct usb_device_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint16_t idVendor; + uint16_t idProduct; + uint16_t bcdDevice; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; +} __attribute__((packed)); + +#define USB_DT_DEVICE_SIZE sizeof(struct usb_device_descriptor) + +/* USB Device_Qualifier Descriptor - Table 9-9 + * Not used in this implementation. + */ +struct usb_device_qualifier_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdUSB; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint8_t bNumConfigurations; + uint8_t bReserved; +} __attribute__((packed)); + +/* This is only defined as a top level named struct to improve c++ + * compatibility. You should never need to instance this struct + * in user code! */ +struct usb_interface { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bmAttributes; + uint16_t wMaxPacketSize; + uint8_t bInterval; +}; + +/* USB Standard Configuration Descriptor - Table 9-10 */ +struct usb_config_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t bMaxPower; + + /* Descriptor ends here. The following are used internally: */ + const struct usb_interface interface[0]; +} __attribute__((packed)); +#define USB_DT_CONFIGURATION_SIZE 9 + +/* USB Configuration Descriptor bmAttributes bit definitions */ +#define USB_CONFIG_ATTR_DEFAULT 0x80 /** always required (USB2.0 table 9-10) */ +#define USB_CONFIG_ATTR_SELF_POWERED 0x40 +#define USB_CONFIG_ATTR_REMOTE_WAKEUP 0x20 + +/* Other Speed Configuration is the same as Configuration Descriptor. + * - Table 9-11 + */ + +/* USB Standard Interface Descriptor - Table 9-12 */ +struct usb_interface_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bNumEndpoints; + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t iInterface; + + /* Descriptor ends here. The following are used internally: */ + const struct usb_endpoint_descriptor *endpoint; + const void *extra; + int extralen; +} __attribute__((packed)); +#define USB_DT_INTERFACE_SIZE 9 + +/* USB Standard Endpoint Descriptor - Table 9-13 */ +struct usb_endpoint_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint16_t wMaxPacketSize; + uint8_t bInterval; + + /* Descriptor ends here. The following are used internally: */ + const void *extra; + int extralen; +} __attribute__((packed)); +#define USB_DT_ENDPOINT_SIZE 7 + +/* USB bEndpointAddress helper macros */ +#define USB_ENDPOINT_ADDR_OUT(x) (x) +#define USB_ENDPOINT_ADDR_IN(x) (0x80 | (x)) + +/* USB Endpoint Descriptor bmAttributes bit definitions - Table 9-13 */ +/* bits 1..0 : transfer type */ +#define USB_ENDPOINT_ATTR_CONTROL 0x00 +#define USB_ENDPOINT_ATTR_ISOCHRONOUS 0x01 +#define USB_ENDPOINT_ATTR_BULK 0x02 +#define USB_ENDPOINT_ATTR_INTERRUPT 0x03 +#define USB_ENDPOINT_ATTR_TYPE 0x03 +/* bits 3..2 : Sync type (only if ISOCHRONOUS) */ +#define USB_ENDPOINT_ATTR_NOSYNC 0x00 +#define USB_ENDPOINT_ATTR_ASYNC 0x04 +#define USB_ENDPOINT_ATTR_ADAPTIVE 0x08 +#define USB_ENDPOINT_ATTR_SYNC 0x0C +#define USB_ENDPOINT_ATTR_SYNCTYPE 0x0C +/* bits 5..4 : usage type (only if ISOCHRONOUS) */ +#define USB_ENDPOINT_ATTR_DATA 0x00 +#define USB_ENDPOINT_ATTR_FEEDBACK 0x10 +#define USB_ENDPOINT_ATTR_IMPLICIT_FEEDBACK_DATA 0x20 +#define USB_ENDPOINT_ATTR_USAGETYPE 0x30 + +/* Table 9-15 specifies String Descriptor Zero. + * Table 9-16 specified UNICODE String Descriptor. + */ +struct usb_string_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wData[]; +} __attribute__((packed)); + +/* From ECN: Interface Association Descriptors, Table 9-Z */ +struct usb_iface_assoc_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bFirstInterface; + uint8_t bInterfaceCount; + uint8_t bFunctionClass; + uint8_t bFunctionSubClass; + uint8_t bFunctionProtocol; + uint8_t iFunction; +} __attribute__((packed)); +#define USB_DT_INTERFACE_ASSOCIATION_SIZE \ + sizeof(struct usb_iface_assoc_descriptor) + +enum usb_language_id { + USB_LANGID_ENGLISH_US = 0x409, +}; +#endif + +/**@}*/ + diff --git a/ext/wasm3/platforms/embedded/fomu/include/webusb-defs.h b/ext/wasm3/platforms/embedded/fomu/include/webusb-defs.h new file mode 100644 index 0000000..fd699e9 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/webusb-defs.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016, Devan Lai + * + * Permission to use, copy, modify, and/or distribute this software + * for any purpose with or without fee is hereby granted, provided + * that the above copyright notice and this permission notice + * appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef WEBUSB_DEFS_H_INCLUDED +#define WEBUSB_DEFS_H_INCLUDED + +#include + +#define WEBUSB_REQ_GET_URL 0x02 + +#define WEBUSB_DT_URL 3 + +#define WEBUSB_URL_SCHEME_HTTP 0 +#define WEBUSB_URL_SCHEME_HTTPS 1 + +struct webusb_platform_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bDevCapabilityType; + uint8_t bReserved; + uint8_t platformCapabilityUUID[16]; + uint16_t bcdVersion; + uint8_t bVendorCode; + uint8_t iLandingPage; +} __attribute__((packed)); + +#define WEBUSB_PLATFORM_DESCRIPTOR_SIZE sizeof(struct webusb_platform_descriptor) + +#define WEBUSB_UUID {0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47,0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65} + +struct webusb_url_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bScheme; + char URL[]; +} __attribute__((packed)); + +#define WEBUSB_DT_URL_DESCRIPTOR_SIZE 3 + +#endif diff --git a/ext/wasm3/platforms/embedded/fomu/include/xxhash.c b/ext/wasm3/platforms/embedded/fomu/include/xxhash.c new file mode 100644 index 0000000..6f85fc4 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/xxhash.c @@ -0,0 +1,912 @@ +/* +* xxHash - Fast Hash algorithm +* Copyright (C) 2012-2016, Yann Collet +* +* BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following disclaimer +* in the documentation and/or other materials provided with the +* distribution. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* You can contact the author at : +* - xxHash homepage: http://www.xxhash.com +* - xxHash source repository : https://github.com/Cyan4973/xxHash +*/ + + +/* ************************************* +* Tuning parameters +***************************************/ +/*!XXH_FORCE_MEMORY_ACCESS : + * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. + * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal. + * The below switch allow to select different access method for improved performance. + * Method 0 (default) : use `memcpy()`. Safe and portable. + * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable). + * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`. + * Method 2 : direct access. This method doesn't depend on compiler but violate C standard. + * It can generate buggy code on targets which do not support unaligned memory accesses. + * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6) + * See http://stackoverflow.com/a/32095106/646947 for details. + * Prefer these methods in priority order (0 > 1 > 2) + */ +#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ +# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ + || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \ + || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) +# define XXH_FORCE_MEMORY_ACCESS 2 +# elif defined(__INTEL_COMPILER) || \ + (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ + || defined(__ARM_ARCH_7S__) )) +# define XXH_FORCE_MEMORY_ACCESS 1 +# endif +#endif + +/*!XXH_ACCEPT_NULL_INPUT_POINTER : + * If input pointer is NULL, xxHash default behavior is to dereference it, triggering a segfault. + * When this macro is enabled, xxHash actively checks input for null pointer. + * It it is, result for null input pointers is the same as a null-length input. + */ +#ifndef XXH_ACCEPT_NULL_INPUT_POINTER /* can be defined externally */ +# define XXH_ACCEPT_NULL_INPUT_POINTER 0 +#endif + +/*!XXH_FORCE_NATIVE_FORMAT : + * By default, xxHash library provides endian-independent Hash values, based on little-endian convention. + * Results are therefore identical for little-endian and big-endian CPU. + * This comes at a performance cost for big-endian CPU, since some swapping is required to emulate little-endian format. + * Should endian-independence be of no importance for your application, you may set the #define below to 1, + * to improve speed for Big-endian CPU. + * This option has no impact on Little_Endian CPU. + */ +#ifndef XXH_FORCE_NATIVE_FORMAT /* can be defined externally */ +# define XXH_FORCE_NATIVE_FORMAT 0 +#endif + +/*!XXH_FORCE_ALIGN_CHECK : + * This is a minor performance trick, only useful with lots of very small keys. + * It means : check for aligned/unaligned input. + * The check costs one initial branch per hash; + * set it to 0 when the input is guaranteed to be aligned, + * or when alignment doesn't matter for performance. + */ +#ifndef XXH_FORCE_ALIGN_CHECK /* can be defined externally */ +# if defined(__i386) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) +# define XXH_FORCE_ALIGN_CHECK 0 +# else +# define XXH_FORCE_ALIGN_CHECK 1 +# endif +#endif + + +/* ************************************* +* Includes & Memory related functions +***************************************/ +/*! Modify the local functions below should you wish to use some other memory routines +* for malloc(), free() */ +#include +static void* XXH_malloc(size_t s) { return malloc(s); } +static void XXH_free (void* p) { free(p); } +/*! and for memcpy() */ +#include +static void* XXH_memcpy(void* dest, const void* src, size_t size) { return memcpy(dest,src,size); } + +#define XXH_STATIC_LINKING_ONLY +#include "xxhash.h" + + +/* ************************************* +* Compiler Specific Options +***************************************/ +#ifdef _MSC_VER /* Visual Studio */ +# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +# define FORCE_INLINE static __forceinline +#else +# if defined (__cplusplus) || defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 */ +# ifdef __GNUC__ +# define FORCE_INLINE static inline __attribute__((always_inline)) +# else +# define FORCE_INLINE static inline +# endif +# else +# define FORCE_INLINE static +# endif /* __STDC_VERSION__ */ +#endif + + +/* ************************************* +* Basic Types +***************************************/ +#ifndef MEM_MODULE +# if !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# include + typedef uint8_t BYTE; + typedef uint16_t U16; + typedef uint32_t U32; +# else + typedef unsigned char BYTE; + typedef unsigned short U16; + typedef unsigned int U32; +# endif +#endif + +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) + +/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ +static U32 XXH_read32(const void* memPtr) { return *(const U32*) memPtr; } + +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) + +/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ +/* currently only defined for gcc and icc */ +typedef union { U32 u32; } __attribute__((packed)) unalign; +static U32 XXH_read32(const void* ptr) { return ((const unalign*)ptr)->u32; } + +#else + +/* portable and safe solution. Generally efficient. + * see : http://stackoverflow.com/a/32095106/646947 + */ +static U32 XXH_read32(const void* memPtr) +{ + U32 val; + memcpy(&val, memPtr, sizeof(val)); + return val; +} + +#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ + + +/* **************************************** +* Compiler-specific Functions and Macros +******************************************/ +#define XXH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) + +/* Note : although _rotl exists for minGW (GCC under windows), performance seems poor */ +#if defined(_MSC_VER) +# define XXH_rotl32(x,r) _rotl(x,r) +# define XXH_rotl64(x,r) _rotl64(x,r) +#else +# define XXH_rotl32(x,r) ((x << r) | (x >> (32 - r))) +# define XXH_rotl64(x,r) ((x << r) | (x >> (64 - r))) +#endif + +#if defined(_MSC_VER) /* Visual Studio */ +# define XXH_swap32 _byteswap_ulong +#elif XXH_GCC_VERSION >= 403 +# define XXH_swap32 __builtin_bswap32 +#else +static U32 XXH_swap32 (U32 x) +{ + return ((x << 24) & 0xff000000 ) | + ((x << 8) & 0x00ff0000 ) | + ((x >> 8) & 0x0000ff00 ) | + ((x >> 24) & 0x000000ff ); +} +#endif + + +/* ************************************* +* Architecture Macros +***************************************/ +typedef enum { XXH_bigEndian=0, XXH_littleEndian=1 } XXH_endianess; + +/* XXH_CPU_LITTLE_ENDIAN can be defined externally, for example on the compiler command line */ +#ifndef XXH_CPU_LITTLE_ENDIAN + static const int g_one = 1; +# define XXH_CPU_LITTLE_ENDIAN (*(const char*)(&g_one)) +#endif + + +/* *************************** +* Memory reads +*****************************/ +typedef enum { XXH_aligned, XXH_unaligned } XXH_alignment; + +FORCE_INLINE U32 XXH_readLE32_align(const void* ptr, XXH_endianess endian, XXH_alignment align) +{ + if (align==XXH_unaligned) + return endian==XXH_littleEndian ? XXH_read32(ptr) : XXH_swap32(XXH_read32(ptr)); + else + return endian==XXH_littleEndian ? *(const U32*)ptr : XXH_swap32(*(const U32*)ptr); +} + +FORCE_INLINE U32 XXH_readLE32(const void* ptr, XXH_endianess endian) +{ + return XXH_readLE32_align(ptr, endian, XXH_unaligned); +} + +static U32 XXH_readBE32(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_swap32(XXH_read32(ptr)) : XXH_read32(ptr); +} + + +/* ************************************* +* Macros +***************************************/ +#define XXH_STATIC_ASSERT(c) { enum { XXH_sa = 1/(int)(!!(c)) }; } /* use after variable declarations */ +XXH_PUBLIC_API unsigned XXH_versionNumber (void) { return XXH_VERSION_NUMBER; } + + +/* ******************************************************************* +* 32-bit hash functions +*********************************************************************/ +static const U32 PRIME32_1 = 2654435761U; +static const U32 PRIME32_2 = 2246822519U; +static const U32 PRIME32_3 = 3266489917U; +static const U32 PRIME32_4 = 668265263U; +static const U32 PRIME32_5 = 374761393U; + +static U32 XXH32_round(U32 seed, U32 input) +{ + seed += input * PRIME32_2; + seed = XXH_rotl32(seed, 13); + seed *= PRIME32_1; + return seed; +} + +FORCE_INLINE U32 XXH32_endian_align(const void* input, size_t len, U32 seed, XXH_endianess endian, XXH_alignment align) +{ + const BYTE* p = (const BYTE*)input; + const BYTE* bEnd = p + len; + U32 h32; +#define XXH_get32bits(p) XXH_readLE32_align(p, endian, align) + +#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) + if (p==NULL) { + len=0; + bEnd=p=(const BYTE*)(size_t)16; + } +#endif + + if (len>=16) { + const BYTE* const limit = bEnd - 16; + U32 v1 = seed + PRIME32_1 + PRIME32_2; + U32 v2 = seed + PRIME32_2; + U32 v3 = seed + 0; + U32 v4 = seed - PRIME32_1; + + do { + v1 = XXH32_round(v1, XXH_get32bits(p)); p+=4; + v2 = XXH32_round(v2, XXH_get32bits(p)); p+=4; + v3 = XXH32_round(v3, XXH_get32bits(p)); p+=4; + v4 = XXH32_round(v4, XXH_get32bits(p)); p+=4; + } while (p<=limit); + + h32 = XXH_rotl32(v1, 1) + XXH_rotl32(v2, 7) + XXH_rotl32(v3, 12) + XXH_rotl32(v4, 18); + } else { + h32 = seed + PRIME32_5; + } + + h32 += (U32) len; + + while (p+4<=bEnd) { + h32 += XXH_get32bits(p) * PRIME32_3; + h32 = XXH_rotl32(h32, 17) * PRIME32_4 ; + p+=4; + } + + while (p> 15; + h32 *= PRIME32_2; + h32 ^= h32 >> 13; + h32 *= PRIME32_3; + h32 ^= h32 >> 16; + + return h32; +} + + +XXH_PUBLIC_API unsigned int XXH32 (const void* input, size_t len, unsigned int seed) +{ +#if 0 + /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ + XXH32_state_t state; + XXH32_reset(&state, seed); + XXH32_update(&state, input, len); + return XXH32_digest(&state); +#else + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if (XXH_FORCE_ALIGN_CHECK) { + if ((((size_t)input) & 3) == 0) { /* Input is 4-bytes aligned, leverage the speed benefit */ + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); + else + return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); + } } + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); + else + return XXH32_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); +#endif +} + + + +/*====== Hash streaming ======*/ + +XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void) +{ + return (XXH32_state_t*)XXH_malloc(sizeof(XXH32_state_t)); +} +XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr) +{ + XXH_free(statePtr); + return XXH_OK; +} + +XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dstState, const XXH32_state_t* srcState) +{ + memcpy(dstState, srcState, sizeof(*dstState)); +} + +XXH_PUBLIC_API XXH_errorcode XXH32_reset(XXH32_state_t* statePtr, unsigned int seed) +{ + XXH32_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ + memset(&state, 0, sizeof(state)); + state.v1 = seed + PRIME32_1 + PRIME32_2; + state.v2 = seed + PRIME32_2; + state.v3 = seed + 0; + state.v4 = seed - PRIME32_1; + /* do not write into reserved, planned to be removed in a future version */ + memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved)); + return XXH_OK; +} + + +FORCE_INLINE +XXH_errorcode XXH32_update_endian (XXH32_state_t* state, const void* input, size_t len, XXH_endianess endian) +{ + const BYTE* p = (const BYTE*)input; + const BYTE* const bEnd = p + len; + + if (input==NULL) +#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) + return XXH_OK; +#else + return XXH_ERROR; +#endif + + state->total_len_32 += (unsigned)len; + state->large_len |= (len>=16) | (state->total_len_32>=16); + + if (state->memsize + len < 16) { /* fill in tmp buffer */ + XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, len); + state->memsize += (unsigned)len; + return XXH_OK; + } + + if (state->memsize) { /* some data left from previous update */ + XXH_memcpy((BYTE*)(state->mem32) + state->memsize, input, 16-state->memsize); + { const unsigned* p32 = state->mem32; + state->v1 = XXH32_round(state->v1, XXH_readLE32(p32, endian)); p32++; + state->v2 = XXH32_round(state->v2, XXH_readLE32(p32, endian)); p32++; + state->v3 = XXH32_round(state->v3, XXH_readLE32(p32, endian)); p32++; + state->v4 = XXH32_round(state->v4, XXH_readLE32(p32, endian)); + } + p += 16-state->memsize; + state->memsize = 0; + } + + if (p <= bEnd-16) { + const BYTE* const limit = bEnd - 16; + U32 v1 = state->v1; + U32 v2 = state->v2; + U32 v3 = state->v3; + U32 v4 = state->v4; + + do { + v1 = XXH32_round(v1, XXH_readLE32(p, endian)); p+=4; + v2 = XXH32_round(v2, XXH_readLE32(p, endian)); p+=4; + v3 = XXH32_round(v3, XXH_readLE32(p, endian)); p+=4; + v4 = XXH32_round(v4, XXH_readLE32(p, endian)); p+=4; + } while (p<=limit); + + state->v1 = v1; + state->v2 = v2; + state->v3 = v3; + state->v4 = v4; + } + + if (p < bEnd) { + XXH_memcpy(state->mem32, p, (size_t)(bEnd-p)); + state->memsize = (unsigned)(bEnd-p); + } + + return XXH_OK; +} + +XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* state_in, const void* input, size_t len) +{ + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_update_endian(state_in, input, len, XXH_littleEndian); + else + return XXH32_update_endian(state_in, input, len, XXH_bigEndian); +} + + + +FORCE_INLINE U32 XXH32_digest_endian (const XXH32_state_t* state, XXH_endianess endian) +{ + const BYTE * p = (const BYTE*)state->mem32; + const BYTE* const bEnd = (const BYTE*)(state->mem32) + state->memsize; + U32 h32; + + if (state->large_len) { + h32 = XXH_rotl32(state->v1, 1) + + XXH_rotl32(state->v2, 7) + + XXH_rotl32(state->v3, 12) + + XXH_rotl32(state->v4, 18); + } else { + h32 = state->v3 /* == seed */ + PRIME32_5; + } + + h32 += state->total_len_32; + + while (p+4<=bEnd) { + h32 += XXH_readLE32(p, endian) * PRIME32_3; + h32 = XXH_rotl32(h32, 17) * PRIME32_4; + p+=4; + } + + while (p> 15; + h32 *= PRIME32_2; + h32 ^= h32 >> 13; + h32 *= PRIME32_3; + h32 ^= h32 >> 16; + + return h32; +} + + +XXH_PUBLIC_API unsigned int XXH32_digest (const XXH32_state_t* state_in) +{ + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH32_digest_endian(state_in, XXH_littleEndian); + else + return XXH32_digest_endian(state_in, XXH_bigEndian); +} + + +/*====== Canonical representation ======*/ + +/*! Default XXH result types are basic unsigned 32 and 64 bits. +* The canonical representation follows human-readable write convention, aka big-endian (large digits first). +* These functions allow transformation of hash result into and from its canonical format. +* This way, hash values can be written into a file or buffer, remaining comparable across different systems. +*/ + +XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash) +{ + XXH_STATIC_ASSERT(sizeof(XXH32_canonical_t) == sizeof(XXH32_hash_t)); + if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap32(hash); + memcpy(dst, &hash, sizeof(*dst)); +} + +XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src) +{ + return XXH_readBE32(src); +} + + +#ifndef XXH_NO_LONG_LONG + +/* ******************************************************************* +* 64-bit hash functions +*********************************************************************/ + +/*====== Memory access ======*/ + +#ifndef MEM_MODULE +# define MEM_MODULE +# if !defined (__VMS) \ + && (defined (__cplusplus) \ + || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) ) +# include + typedef uint64_t U64; +# else + /* if compiler doesn't support unsigned long long, replace by another 64-bit type */ + typedef unsigned long long U64; +# endif +#endif + + +#if (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==2)) + +/* Force direct memory access. Only works on CPU which support unaligned memory access in hardware */ +static U64 XXH_read64(const void* memPtr) { return *(const U64*) memPtr; } + +#elif (defined(XXH_FORCE_MEMORY_ACCESS) && (XXH_FORCE_MEMORY_ACCESS==1)) + +/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ +/* currently only defined for gcc and icc */ +typedef union { U32 u32; U64 u64; } __attribute__((packed)) unalign64; +static U64 XXH_read64(const void* ptr) { return ((const unalign64*)ptr)->u64; } + +#else + +/* portable and safe solution. Generally efficient. + * see : http://stackoverflow.com/a/32095106/646947 + */ + +static U64 XXH_read64(const void* memPtr) +{ + U64 val; + memcpy(&val, memPtr, sizeof(val)); + return val; +} + +#endif /* XXH_FORCE_DIRECT_MEMORY_ACCESS */ + +#if defined(_MSC_VER) /* Visual Studio */ +# define XXH_swap64 _byteswap_uint64 +#elif XXH_GCC_VERSION >= 403 +# define XXH_swap64 __builtin_bswap64 +#else +static U64 XXH_swap64 (U64 x) +{ + return ((x << 56) & 0xff00000000000000ULL) | + ((x << 40) & 0x00ff000000000000ULL) | + ((x << 24) & 0x0000ff0000000000ULL) | + ((x << 8) & 0x000000ff00000000ULL) | + ((x >> 8) & 0x00000000ff000000ULL) | + ((x >> 24) & 0x0000000000ff0000ULL) | + ((x >> 40) & 0x000000000000ff00ULL) | + ((x >> 56) & 0x00000000000000ffULL); +} +#endif + +FORCE_INLINE U64 XXH_readLE64_align(const void* ptr, XXH_endianess endian, XXH_alignment align) +{ + if (align==XXH_unaligned) + return endian==XXH_littleEndian ? XXH_read64(ptr) : XXH_swap64(XXH_read64(ptr)); + else + return endian==XXH_littleEndian ? *(const U64*)ptr : XXH_swap64(*(const U64*)ptr); +} + +FORCE_INLINE U64 XXH_readLE64(const void* ptr, XXH_endianess endian) +{ + return XXH_readLE64_align(ptr, endian, XXH_unaligned); +} + +static U64 XXH_readBE64(const void* ptr) +{ + return XXH_CPU_LITTLE_ENDIAN ? XXH_swap64(XXH_read64(ptr)) : XXH_read64(ptr); +} + + +/*====== xxh64 ======*/ + +static const U64 PRIME64_1 = 11400714785074694791ULL; +static const U64 PRIME64_2 = 14029467366897019727ULL; +static const U64 PRIME64_3 = 1609587929392839161ULL; +static const U64 PRIME64_4 = 9650029242287828579ULL; +static const U64 PRIME64_5 = 2870177450012600261ULL; + +static U64 XXH64_round(U64 acc, U64 input) +{ + acc += input * PRIME64_2; + acc = XXH_rotl64(acc, 31); + acc *= PRIME64_1; + return acc; +} + +static U64 XXH64_mergeRound(U64 acc, U64 val) +{ + val = XXH64_round(0, val); + acc ^= val; + acc = acc * PRIME64_1 + PRIME64_4; + return acc; +} + +FORCE_INLINE U64 XXH64_endian_align(const void* input, size_t len, U64 seed, XXH_endianess endian, XXH_alignment align) +{ + const BYTE* p = (const BYTE*)input; + const BYTE* bEnd = p + len; + U64 h64; +#define XXH_get64bits(p) XXH_readLE64_align(p, endian, align) + +#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) + if (p==NULL) { + len=0; + bEnd=p=(const BYTE*)(size_t)32; + } +#endif + + if (len>=32) { + const BYTE* const limit = bEnd - 32; + U64 v1 = seed + PRIME64_1 + PRIME64_2; + U64 v2 = seed + PRIME64_2; + U64 v3 = seed + 0; + U64 v4 = seed - PRIME64_1; + + do { + v1 = XXH64_round(v1, XXH_get64bits(p)); p+=8; + v2 = XXH64_round(v2, XXH_get64bits(p)); p+=8; + v3 = XXH64_round(v3, XXH_get64bits(p)); p+=8; + v4 = XXH64_round(v4, XXH_get64bits(p)); p+=8; + } while (p<=limit); + + h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); + h64 = XXH64_mergeRound(h64, v1); + h64 = XXH64_mergeRound(h64, v2); + h64 = XXH64_mergeRound(h64, v3); + h64 = XXH64_mergeRound(h64, v4); + + } else { + h64 = seed + PRIME64_5; + } + + h64 += (U64) len; + + while (p+8<=bEnd) { + U64 const k1 = XXH64_round(0, XXH_get64bits(p)); + h64 ^= k1; + h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4; + p+=8; + } + + if (p+4<=bEnd) { + h64 ^= (U64)(XXH_get32bits(p)) * PRIME64_1; + h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; + p+=4; + } + + while (p> 33; + h64 *= PRIME64_2; + h64 ^= h64 >> 29; + h64 *= PRIME64_3; + h64 ^= h64 >> 32; + + return h64; +} + + +XXH_PUBLIC_API unsigned long long XXH64 (const void* input, size_t len, unsigned long long seed) +{ +#if 0 + /* Simple version, good for code maintenance, but unfortunately slow for small inputs */ + XXH64_state_t state; + XXH64_reset(&state, seed); + XXH64_update(&state, input, len); + return XXH64_digest(&state); +#else + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if (XXH_FORCE_ALIGN_CHECK) { + if ((((size_t)input) & 7)==0) { /* Input is aligned, let's leverage the speed advantage */ + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_aligned); + else + return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_aligned); + } } + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH64_endian_align(input, len, seed, XXH_littleEndian, XXH_unaligned); + else + return XXH64_endian_align(input, len, seed, XXH_bigEndian, XXH_unaligned); +#endif +} + +/*====== Hash Streaming ======*/ + +XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void) +{ + return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t)); +} +XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr) +{ + XXH_free(statePtr); + return XXH_OK; +} + +XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dstState, const XXH64_state_t* srcState) +{ + memcpy(dstState, srcState, sizeof(*dstState)); +} + +XXH_PUBLIC_API XXH_errorcode XXH64_reset(XXH64_state_t* statePtr, unsigned long long seed) +{ + XXH64_state_t state; /* using a local state to memcpy() in order to avoid strict-aliasing warnings */ + memset(&state, 0, sizeof(state)); + state.v1 = seed + PRIME64_1 + PRIME64_2; + state.v2 = seed + PRIME64_2; + state.v3 = seed + 0; + state.v4 = seed - PRIME64_1; + /* do not write into reserved, planned to be removed in a future version */ + memcpy(statePtr, &state, sizeof(state) - sizeof(state.reserved)); + return XXH_OK; +} + +FORCE_INLINE +XXH_errorcode XXH64_update_endian (XXH64_state_t* state, const void* input, size_t len, XXH_endianess endian) +{ + const BYTE* p = (const BYTE*)input; + const BYTE* const bEnd = p + len; + + if (input==NULL) +#if defined(XXH_ACCEPT_NULL_INPUT_POINTER) && (XXH_ACCEPT_NULL_INPUT_POINTER>=1) + return XXH_OK; +#else + return XXH_ERROR; +#endif + + state->total_len += len; + + if (state->memsize + len < 32) { /* fill in tmp buffer */ + XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, len); + state->memsize += (U32)len; + return XXH_OK; + } + + if (state->memsize) { /* tmp buffer is full */ + XXH_memcpy(((BYTE*)state->mem64) + state->memsize, input, 32-state->memsize); + state->v1 = XXH64_round(state->v1, XXH_readLE64(state->mem64+0, endian)); + state->v2 = XXH64_round(state->v2, XXH_readLE64(state->mem64+1, endian)); + state->v3 = XXH64_round(state->v3, XXH_readLE64(state->mem64+2, endian)); + state->v4 = XXH64_round(state->v4, XXH_readLE64(state->mem64+3, endian)); + p += 32-state->memsize; + state->memsize = 0; + } + + if (p+32 <= bEnd) { + const BYTE* const limit = bEnd - 32; + U64 v1 = state->v1; + U64 v2 = state->v2; + U64 v3 = state->v3; + U64 v4 = state->v4; + + do { + v1 = XXH64_round(v1, XXH_readLE64(p, endian)); p+=8; + v2 = XXH64_round(v2, XXH_readLE64(p, endian)); p+=8; + v3 = XXH64_round(v3, XXH_readLE64(p, endian)); p+=8; + v4 = XXH64_round(v4, XXH_readLE64(p, endian)); p+=8; + } while (p<=limit); + + state->v1 = v1; + state->v2 = v2; + state->v3 = v3; + state->v4 = v4; + } + + if (p < bEnd) { + XXH_memcpy(state->mem64, p, (size_t)(bEnd-p)); + state->memsize = (unsigned)(bEnd-p); + } + + return XXH_OK; +} + +XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* state_in, const void* input, size_t len) +{ + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH64_update_endian(state_in, input, len, XXH_littleEndian); + else + return XXH64_update_endian(state_in, input, len, XXH_bigEndian); +} + +FORCE_INLINE U64 XXH64_digest_endian (const XXH64_state_t* state, XXH_endianess endian) +{ + const BYTE * p = (const BYTE*)state->mem64; + const BYTE* const bEnd = (const BYTE*)state->mem64 + state->memsize; + U64 h64; + + if (state->total_len >= 32) { + U64 const v1 = state->v1; + U64 const v2 = state->v2; + U64 const v3 = state->v3; + U64 const v4 = state->v4; + + h64 = XXH_rotl64(v1, 1) + XXH_rotl64(v2, 7) + XXH_rotl64(v3, 12) + XXH_rotl64(v4, 18); + h64 = XXH64_mergeRound(h64, v1); + h64 = XXH64_mergeRound(h64, v2); + h64 = XXH64_mergeRound(h64, v3); + h64 = XXH64_mergeRound(h64, v4); + } else { + h64 = state->v3 + PRIME64_5; + } + + h64 += (U64) state->total_len; + + while (p+8<=bEnd) { + U64 const k1 = XXH64_round(0, XXH_readLE64(p, endian)); + h64 ^= k1; + h64 = XXH_rotl64(h64,27) * PRIME64_1 + PRIME64_4; + p+=8; + } + + if (p+4<=bEnd) { + h64 ^= (U64)(XXH_readLE32(p, endian)) * PRIME64_1; + h64 = XXH_rotl64(h64, 23) * PRIME64_2 + PRIME64_3; + p+=4; + } + + while (p> 33; + h64 *= PRIME64_2; + h64 ^= h64 >> 29; + h64 *= PRIME64_3; + h64 ^= h64 >> 32; + + return h64; +} + +XXH_PUBLIC_API unsigned long long XXH64_digest (const XXH64_state_t* state_in) +{ + XXH_endianess endian_detected = (XXH_endianess)XXH_CPU_LITTLE_ENDIAN; + + if ((endian_detected==XXH_littleEndian) || XXH_FORCE_NATIVE_FORMAT) + return XXH64_digest_endian(state_in, XXH_littleEndian); + else + return XXH64_digest_endian(state_in, XXH_bigEndian); +} + + +/*====== Canonical representation ======*/ + +XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash) +{ + XXH_STATIC_ASSERT(sizeof(XXH64_canonical_t) == sizeof(XXH64_hash_t)); + if (XXH_CPU_LITTLE_ENDIAN) hash = XXH_swap64(hash); + memcpy(dst, &hash, sizeof(*dst)); +} + +XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src) +{ + return XXH_readBE64(src); +} + +#endif /* XXH_NO_LONG_LONG */ diff --git a/ext/wasm3/platforms/embedded/fomu/include/xxhash.h b/ext/wasm3/platforms/embedded/fomu/include/xxhash.h new file mode 100644 index 0000000..4099da0 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/include/xxhash.h @@ -0,0 +1,294 @@ +/* + xxHash - Extremely Fast Hash algorithm + Header File + Copyright (C) 2012-2016, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - xxHash source repository : https://github.com/Cyan4973/xxHash +*/ + +/* Notice extracted from xxHash homepage : + +xxHash is an extremely fast Hash algorithm, running at RAM speed limits. +It also successfully passes all tests from the SMHasher suite. + +Comparison (single thread, Windows Seven 32 bits, using SMHasher on a Core 2 Duo @3GHz) + +Name Speed Q.Score Author +xxHash 5.4 GB/s 10 +CrapWow 3.2 GB/s 2 Andrew +MumurHash 3a 2.7 GB/s 10 Austin Appleby +SpookyHash 2.0 GB/s 10 Bob Jenkins +SBox 1.4 GB/s 9 Bret Mulvey +Lookup3 1.2 GB/s 9 Bob Jenkins +SuperFastHash 1.2 GB/s 1 Paul Hsieh +CityHash64 1.05 GB/s 10 Pike & Alakuijala +FNV 0.55 GB/s 5 Fowler, Noll, Vo +CRC32 0.43 GB/s 9 +MD5-32 0.33 GB/s 10 Ronald L. Rivest +SHA1-32 0.28 GB/s 10 + +Q.Score is a measure of quality of the hash function. +It depends on successfully passing SMHasher test set. +10 is a perfect score. + +A 64-bit version, named XXH64, is available since r35. +It offers much better speed, but for 64-bit applications only. +Name Speed on 64 bits Speed on 32 bits +XXH64 13.8 GB/s 1.9 GB/s +XXH32 6.8 GB/s 6.0 GB/s +*/ + +#ifndef XXHASH_H_5627135585666179 +#define XXHASH_H_5627135585666179 1 + +#if defined (__cplusplus) +extern "C" { +#endif + + +/* **************************** +* Definitions +******************************/ +#include /* size_t */ +typedef enum { XXH_OK=0, XXH_ERROR } XXH_errorcode; + + +/* **************************** +* API modifier +******************************/ +/** XXH_PRIVATE_API +* This is useful to include xxhash functions in `static` mode +* in order to inline them, and remove their symbol from the public list. +* Methodology : +* #define XXH_PRIVATE_API +* #include "xxhash.h" +* `xxhash.c` is automatically included. +* It's not useful to compile and link it as a separate module. +*/ +#ifdef XXH_PRIVATE_API +# ifndef XXH_STATIC_LINKING_ONLY +# define XXH_STATIC_LINKING_ONLY +# endif +# if defined(__GNUC__) +# define XXH_PUBLIC_API static __inline __attribute__((unused)) +# elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +# define XXH_PUBLIC_API static inline +# elif defined(_MSC_VER) +# define XXH_PUBLIC_API static __inline +# else + /* this version may generate warnings for unused static functions */ +# define XXH_PUBLIC_API static +# endif +#else +# define XXH_PUBLIC_API /* do nothing */ +#endif /* XXH_PRIVATE_API */ + +/*!XXH_NAMESPACE, aka Namespace Emulation : + +If you want to include _and expose_ xxHash functions from within your own library, +but also want to avoid symbol collisions with other libraries which may also include xxHash, + +you can use XXH_NAMESPACE, to automatically prefix any public symbol from xxhash library +with the value of XXH_NAMESPACE (therefore, avoid NULL and numeric values). + +Note that no change is required within the calling program as long as it includes `xxhash.h` : +regular symbol name will be automatically translated by this header. +*/ +#ifdef XXH_NAMESPACE +# define XXH_CAT(A,B) A##B +# define XXH_NAME2(A,B) XXH_CAT(A,B) +# define XXH_versionNumber XXH_NAME2(XXH_NAMESPACE, XXH_versionNumber) +# define XXH32 XXH_NAME2(XXH_NAMESPACE, XXH32) +# define XXH32_createState XXH_NAME2(XXH_NAMESPACE, XXH32_createState) +# define XXH32_freeState XXH_NAME2(XXH_NAMESPACE, XXH32_freeState) +# define XXH32_reset XXH_NAME2(XXH_NAMESPACE, XXH32_reset) +# define XXH32_update XXH_NAME2(XXH_NAMESPACE, XXH32_update) +# define XXH32_digest XXH_NAME2(XXH_NAMESPACE, XXH32_digest) +# define XXH32_copyState XXH_NAME2(XXH_NAMESPACE, XXH32_copyState) +# define XXH32_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH32_canonicalFromHash) +# define XXH32_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH32_hashFromCanonical) +# define XXH64 XXH_NAME2(XXH_NAMESPACE, XXH64) +# define XXH64_createState XXH_NAME2(XXH_NAMESPACE, XXH64_createState) +# define XXH64_freeState XXH_NAME2(XXH_NAMESPACE, XXH64_freeState) +# define XXH64_reset XXH_NAME2(XXH_NAMESPACE, XXH64_reset) +# define XXH64_update XXH_NAME2(XXH_NAMESPACE, XXH64_update) +# define XXH64_digest XXH_NAME2(XXH_NAMESPACE, XXH64_digest) +# define XXH64_copyState XXH_NAME2(XXH_NAMESPACE, XXH64_copyState) +# define XXH64_canonicalFromHash XXH_NAME2(XXH_NAMESPACE, XXH64_canonicalFromHash) +# define XXH64_hashFromCanonical XXH_NAME2(XXH_NAMESPACE, XXH64_hashFromCanonical) +#endif + + +/* ************************************* +* Version +***************************************/ +#define XXH_VERSION_MAJOR 0 +#define XXH_VERSION_MINOR 6 +#define XXH_VERSION_RELEASE 4 +#define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE) +XXH_PUBLIC_API unsigned XXH_versionNumber (void); + + +/*-********************************************************************** +* 32-bit hash +************************************************************************/ +typedef unsigned int XXH32_hash_t; + +/*! XXH32() : + Calculate the 32-bit hash of sequence "length" bytes stored at memory address "input". + The memory between input & input+length must be valid (allocated and read-accessible). + "seed" can be used to alter the result predictably. + Speed on Core 2 Duo @ 3 GHz (single thread, SMHasher benchmark) : 5.4 GB/s */ +XXH_PUBLIC_API XXH32_hash_t XXH32 (const void* input, size_t length, unsigned int seed); + +/*====== Streaming ======*/ +typedef struct XXH32_state_s XXH32_state_t; /* incomplete type */ +XXH_PUBLIC_API XXH32_state_t* XXH32_createState(void); +XXH_PUBLIC_API XXH_errorcode XXH32_freeState(XXH32_state_t* statePtr); +XXH_PUBLIC_API void XXH32_copyState(XXH32_state_t* dst_state, const XXH32_state_t* src_state); + +XXH_PUBLIC_API XXH_errorcode XXH32_reset (XXH32_state_t* statePtr, unsigned int seed); +XXH_PUBLIC_API XXH_errorcode XXH32_update (XXH32_state_t* statePtr, const void* input, size_t length); +XXH_PUBLIC_API XXH32_hash_t XXH32_digest (const XXH32_state_t* statePtr); + +/* +These functions generate the xxHash of an input provided in multiple segments. +Note that, for small input, they are slower than single-call functions, due to state management. +For small input, prefer `XXH32()` and `XXH64()` . + +XXH state must first be allocated, using XXH*_createState() . + +Start a new hash by initializing state with a seed, using XXH*_reset(). + +Then, feed the hash state by calling XXH*_update() as many times as necessary. +Obviously, input must be allocated and read accessible. +The function returns an error code, with 0 meaning OK, and any other value meaning there is an error. + +Finally, a hash value can be produced anytime, by using XXH*_digest(). +This function returns the nn-bits hash as an int or long long. + +It's still possible to continue inserting input into the hash state after a digest, +and generate some new hashes later on, by calling again XXH*_digest(). + +When done, free XXH state space if it was allocated dynamically. +*/ + +/*====== Canonical representation ======*/ + +typedef struct { unsigned char digest[4]; } XXH32_canonical_t; +XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t hash); +XXH_PUBLIC_API XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src); + +/* Default result type for XXH functions are primitive unsigned 32 and 64 bits. +* The canonical representation uses human-readable write convention, aka big-endian (large digits first). +* These functions allow transformation of hash result into and from its canonical format. +* This way, hash values can be written into a file / memory, and remain comparable on different systems and programs. +*/ + + +#ifndef XXH_NO_LONG_LONG +/*-********************************************************************** +* 64-bit hash +************************************************************************/ +typedef unsigned long long XXH64_hash_t; + +/*! XXH64() : + Calculate the 64-bit hash of sequence of length "len" stored at memory address "input". + "seed" can be used to alter the result predictably. + This function runs faster on 64-bit systems, but slower on 32-bit systems (see benchmark). +*/ +XXH_PUBLIC_API XXH64_hash_t XXH64 (const void* input, size_t length, unsigned long long seed); + +/*====== Streaming ======*/ +typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */ +XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void); +XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr); +XXH_PUBLIC_API void XXH64_copyState(XXH64_state_t* dst_state, const XXH64_state_t* src_state); + +XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH64_state_t* statePtr, unsigned long long seed); +XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH64_state_t* statePtr, const void* input, size_t length); +XXH_PUBLIC_API XXH64_hash_t XXH64_digest (const XXH64_state_t* statePtr); + +/*====== Canonical representation ======*/ +typedef struct { unsigned char digest[8]; } XXH64_canonical_t; +XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH64_canonical_t* dst, XXH64_hash_t hash); +XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(const XXH64_canonical_t* src); +#endif /* XXH_NO_LONG_LONG */ + + +#ifdef XXH_STATIC_LINKING_ONLY + +/* ================================================================================================ + This section contains declarations which are not guaranteed to remain stable. + They may change in future versions, becoming incompatible with a different version of the library. + These declarations should only be used with static linking. + Never use them in association with dynamic linking ! +=================================================================================================== */ + +/* These definitions are only meant to make possible + static allocation of XXH state, on stack or in a struct for example. + Never use members directly. */ + +struct XXH32_state_s { + unsigned total_len_32; + unsigned large_len; + unsigned v1; + unsigned v2; + unsigned v3; + unsigned v4; + unsigned mem32[4]; /* buffer defined as U32 for alignment */ + unsigned memsize; + unsigned reserved; /* never read nor write, will be removed in a future version */ +}; /* typedef'd to XXH32_state_t */ + +#ifndef XXH_NO_LONG_LONG /* remove 64-bit support */ +struct XXH64_state_s { + unsigned long long total_len; + unsigned long long v1; + unsigned long long v2; + unsigned long long v3; + unsigned long long v4; + unsigned long long mem64[4]; /* buffer defined as U64 for alignment */ + unsigned memsize; + unsigned reserved[2]; /* never read nor write, will be removed in a future version */ +}; /* typedef'd to XXH64_state_t */ +#endif + +#ifdef XXH_PRIVATE_API +# include "xxhash.c" /* include xxhash function bodies as `static`, for inlining */ +#endif + +#endif /* XXH_STATIC_LINKING_ONLY */ + + +#if defined (__cplusplus) +} +#endif + +#endif /* XXHASH_H_5627135585666179 */ diff --git a/ext/wasm3/platforms/embedded/fomu/ld/linker.ld b/ext/wasm3/platforms/embedded/fomu/ld/linker.ld new file mode 100644 index 0000000..a0fa473 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/ld/linker.ld @@ -0,0 +1,56 @@ +INCLUDE output_format.ld +ENTRY(_start) + +__DYNAMIC = 0; + +INCLUDE regions.ld + +SECTIONS +{ + .text : + { + _ftext = .; + *(.text.start) + *(.text .stub .text.* .gnu.linkonce.t.*) + _etext = .; + } > rom + + .rodata : + { + . = ALIGN(4); + _frodata = .; + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.srodata .srodata.*) + _erodata = .; + } > rom + + .data : AT (ADDR(.rodata) + SIZEOF (.rodata)) + { + . = ALIGN(4); + _fdata = .; + *(.data .data.* .gnu.linkonce.d.*) + *(.data1) + _gp = ALIGN(16); + *(.sdata .sdata.* .gnu.linkonce.s.* .sdata2 .sdata2.*) + *(.ramtext .ramtext.*) + _edata = ALIGN(16); /* Make sure _edata is >= _gp. */ + } > sram + + .bss : + { + . = ALIGN(4); + _fbss = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + _ebss = .; + _end = .; + } > sram +} + +PROVIDE(_fstack = ORIGIN(sram) + LENGTH(sram) - 4); diff --git a/ext/wasm3/platforms/embedded/fomu/ld/output_format.ld b/ext/wasm3/platforms/embedded/fomu/ld/output_format.ld new file mode 100644 index 0000000..5e76f5f --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/ld/output_format.ld @@ -0,0 +1 @@ +OUTPUT_FORMAT("elf32-littleriscv") diff --git a/ext/wasm3/platforms/embedded/fomu/ld/regions.ld b/ext/wasm3/platforms/embedded/fomu/ld/regions.ld new file mode 100644 index 0000000..72cb118 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/ld/regions.ld @@ -0,0 +1,4 @@ +MEMORY { + sram : ORIGIN = 0x10000000, LENGTH = 0x00020000 + rom : ORIGIN = 0x20040000, LENGTH = 0x100000 /* 1 MBit */ +} diff --git a/ext/wasm3/platforms/embedded/fomu/src/crt0-vexriscv.S b/ext/wasm3/platforms/embedded/fomu/src/crt0-vexriscv.S new file mode 100644 index 0000000..a02c3aa --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/src/crt0-vexriscv.S @@ -0,0 +1,83 @@ +.global main +.global isr + +.section .text.start +.global _start + +_start: + j crt_init + +.global trap_entry +.section .ramtext +trap_entry: + sw x1, - 1*4(sp) + sw x5, - 2*4(sp) + sw x6, - 3*4(sp) + sw x7, - 4*4(sp) + sw x10, - 5*4(sp) + sw x11, - 6*4(sp) + sw x12, - 7*4(sp) + sw x13, - 8*4(sp) + sw x14, - 9*4(sp) + sw x15, -10*4(sp) + sw x16, -11*4(sp) + sw x17, -12*4(sp) + sw x28, -13*4(sp) + sw x29, -14*4(sp) + sw x30, -15*4(sp) + sw x31, -16*4(sp) + addi sp,sp,-16*4 + call isr + lw x1 , 15*4(sp) + lw x5, 14*4(sp) + lw x6, 13*4(sp) + lw x7, 12*4(sp) + lw x10, 11*4(sp) + lw x11, 10*4(sp) + lw x12, 9*4(sp) + lw x13, 8*4(sp) + lw x14, 7*4(sp) + lw x15, 6*4(sp) + lw x16, 5*4(sp) + lw x17, 4*4(sp) + lw x28, 3*4(sp) + lw x29, 2*4(sp) + lw x30, 1*4(sp) + lw x31, 0*4(sp) + addi sp,sp,16*4 + mret + +.text +crt_init: + la sp, _fstack + 4 + la a0, trap_entry + csrw mtvec, a0 + +bss_init: + la a0, _fbss + la a1, _ebss +bss_loop: + beq a0,a1,bss_done + sw zero,0(a0) + add a0,a0,4 + j bss_loop +bss_done: + + /* Load DATA */ + la t0, _erodata + la t1, _fdata + la t2, _edata +3: + lw t3, 0(t0) + sw t3, 0(t1) + /* _edata is aligned to 16 bytes. Use word-xfers. */ + addi t0, t0, 4 + addi t1, t1, 4 + bltu t1, t2, 3b + + li a0, 0x880 //880 enable timer + external interrupt sources (until mstatus.MIE is set, they will never trigger an interrupt) + csrw mie,a0 + + call main +infinite_loop: + j infinite_loop diff --git a/ext/wasm3/platforms/embedded/fomu/src/ltoa.c b/ext/wasm3/platforms/embedded/fomu/src/ltoa.c new file mode 100644 index 0000000..f0bdcd6 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/src/ltoa.c @@ -0,0 +1,58 @@ +/* +** LTOA.C +** +** Converts a long integer to a string. +** +** Copyright 1988-90 by Robert B. Stout dba MicroFirm +** +** Released to public domain, 1991 +** +** Parameters: 1 - number to be converted +** 2 - buffer in which to build the converted string +** 3 - number base to use for conversion +** +** Returns: A character pointer to the converted string if +** successful, a NULL pointer if the number base specified +** is out of range. +*/ + +#include +#include + +#define BUFSIZE (sizeof(long) * 8 + 1) + +char *ltoa(long N, char *str, int base) +{ + register int i = 2; + long uarg; + char *tail, *head = str, buf[BUFSIZE]; + + if (36 < base || 2 > base) + base = 10; /* can only use 0-9, A-Z */ + tail = &buf[BUFSIZE - 1]; /* last character position */ + *tail-- = '\0'; + + if (10 == base && N < 0L) + { + *head++ = '-'; + uarg = -N; + } + else uarg = N; + + if (uarg) + { + for (i = 1; uarg; ++i) + { + register ldiv_t r; + + r = ldiv(uarg, base); + *tail-- = (char)(r.rem + ((9L < r.rem) ? + ('A' - 10L) : '0')); + uarg = r.quot; + } + } + else *tail-- = '0'; + + memcpy(head, ++tail, i); + return str; +} diff --git a/ext/wasm3/platforms/embedded/fomu/src/main.c b/ext/wasm3/platforms/embedded/fomu/src/main.c new file mode 100644 index 0000000..77cea3e --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/src/main.c @@ -0,0 +1,148 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct ff_spi *spi; + +char *ltoa(long N, char *str, int base); + +void uart_write(const char *str, unsigned len) { + if (!usb_can_putc()) return; + + while (len) { + while (!usb_can_putc()) + usb_poll(); + int bytes_written = usb_write(str, len); + str += bytes_written; + len -= bytes_written; + } +} + +void uart_print(const char *str) { + uart_write(str, strlen(str)); +} + +#include "wasm3.h" + +#include "extra/fib32.wasm.h" + +#define FATAL(func, msg) { \ + uart_print("Fatal: " func ": "); \ + uart_print(msg); uart_print("\n"); \ + return false; } + +bool run_wasm() +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + size_t fsize = fib32_wasm_len; + + uart_print("Loading WebAssembly...\n"); + + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment", "failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + if (!runtime) FATAL("m3_NewRuntime", "failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction", result); + + uart_print("Running...\n"); + + result = m3_CallV (f, 24); + if (result) FATAL("m3_Call", result); + + uint32_t value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults", result); + + char buff[32]; + ltoa(value, buff, 10); + + uart_print("Result: "); + uart_print(buff); + uart_print("\n"); + + return true; +} + + +__attribute__((section(".ramtext"))) +void isr(void) +{ + unsigned int irqs; + + irqs = irq_pending() & irq_getmask(); + + if (irqs & (1 << USB_INTERRUPT)) + usb_isr(); +} + +__attribute__((section(".ramtext"))) +static void init(void) +{ + irq_setmask(0); + irq_setie(1); + usb_init(); + time_init(); + rgb_init(); +} + +void m3Yield () +{ + usb_poll(); +} + +__attribute__((section(".ramtext"))) +int main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + init(); + + usb_connect(); + + for (int i = 0; i< 10000; i++) { + usb_poll(); + msleep(1); + } + + uart_print("\nWasm3 v" M3_VERSION " on Fomu (" M3_ARCH "), build " __DATE__ " " __TIME__ "\n"); + + rgb_set(0, 0, 255); + if (run_wasm()) { + rgb_set(0, 255, 0); + } else { + rgb_set(255, 0, 0); + } + + while (1) + { + usb_poll(); + } + return 0; +} diff --git a/ext/wasm3/platforms/embedded/fomu/src/rgb.c b/ext/wasm3/platforms/embedded/fomu/src/rgb.c new file mode 100644 index 0000000..7cc3d21 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/src/rgb.c @@ -0,0 +1,73 @@ +#include +#include +#include + +#define BREATHE_ENABLE (1 << 7) +#define BREATHE_EDGE_ON (0 << 6) +#define BREATHE_EDGE_BOTH (1 << 6) +#define BREATHE_MODE_MODULATE (1 << 5) +#define BREATHE_MODE_FIXED (0 << 5) + +// Breathe rate is in 128 ms increments +#define BREATHE_RATE_MS(x) ((((x)+1) / 128 & 7) << 0) + +// Blink on/off time is in 32 ms increments +#define BLINK_TIME_MS(x) (((x)) / 32) + +#define LEDDEN (1 << 7) +#define FR250 (1 << 6) +#define OUTPUL (1 << 5) +#define OUTSKEW (1 << 4) +#define QUICK_STOP (1 << 3) +#define PWM_MODE_LFSR (1 << 2) +#define PWM_MODE_LINEAR (0 << 2) + +void rgb_write(uint8_t value, uint8_t addr) { + rgb_addr_write(addr); + rgb_dat_write(value); +} + +void rgb_init(void) { + // Turn on the RGB block and current enable, as well as enabling led control + rgb_ctrl_write((1 << 0) | (1 << 1) | (1 << 2)); + + // Enable the LED driver, and set 250 Hz mode. + // Also set quick stop, which we'll use to switch patterns quickly. + rgb_write(LEDDEN | FR250 | QUICK_STOP, LEDDCR0); + + // Set clock register to 12 MHz / 64 kHz - 1 + rgb_write((12000000/64000)-1, LEDDBR); + + rgb_write(BLINK_TIME_MS(32), LEDDONR); // Amount of time to stay "on" + rgb_write(BLINK_TIME_MS(0), LEDDOFR); // Amount of time to stay "off" + + rgb_write(BREATHE_ENABLE | BREATHE_MODE_FIXED | BREATHE_RATE_MS(128), LEDDBCRR); + rgb_write(BREATHE_ENABLE | BREATHE_MODE_FIXED | BREATHE_RATE_MS(128), LEDDBCFR); +} + +void rgb_set(uint8_t r, uint8_t g, uint8_t b) { + // Note: the LEDD control registers have arbitrary names that + // do not match up with the LEDD pin outputs. Hence this strange + // mapping. + rgb_write(r, LEDDPWRR); // Blue + rgb_write(g, LEDDPWRG); // Red + rgb_write(b, LEDDPWRB); // Green +} + +// The amount of time to stay off or on +void rgb_on_time(uint8_t ms) { + rgb_write(BLINK_TIME_MS(ms), LEDDONR); // Amount of time to stay "on" +} + +void rgb_off_time(uint8_t ms) { + rgb_write(BLINK_TIME_MS(ms), LEDDOFR); // Amount of time to stay "off" +} + +// The amount of time to breathe in/out +void rgb_in_time(uint8_t ms) { + rgb_write(BREATHE_ENABLE| BREATHE_MODE_FIXED | BREATHE_RATE_MS(ms), LEDDBCRR); +} + +void rgb_out_time(uint8_t ms) { + rgb_write(BREATHE_ENABLE | BREATHE_MODE_FIXED | BREATHE_RATE_MS(ms), LEDDBCFR); +} diff --git a/ext/wasm3/platforms/embedded/fomu/src/time.c b/ext/wasm3/platforms/embedded/fomu/src/time.c new file mode 100644 index 0000000..c7ab3f7 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/src/time.c @@ -0,0 +1,43 @@ +#include +#include + +void time_init(void) +{ + int t; + + timer0_en_write(0); + t = 2*SYSTEM_CLOCK_FREQUENCY; + timer0_reload_write(t); + timer0_load_write(t); + timer0_en_write(1); +} + +int elapsed(int *last_event, int period) +{ + int t, dt; + + timer0_update_value_write(1); + t = timer0_reload_read() - timer0_value_read(); + if(period < 0) { + *last_event = t; + return 1; + } + dt = t - *last_event; + if(dt < 0) + dt += timer0_reload_read(); + if((dt > period) || (dt < 0)) { + *last_event = t; + return 1; + } else + return 0; +} + +void msleep(int ms) +{ + timer0_en_write(0); + timer0_reload_write(0); + timer0_load_write(SYSTEM_CLOCK_FREQUENCY/1000*ms); + timer0_en_write(1); + timer0_update_value_write(1); + while(timer0_value_read()) timer0_update_value_write(1); +} diff --git a/ext/wasm3/platforms/embedded/fomu/src/usb-desc.c b/ext/wasm3/platforms/embedded/fomu/src/usb-desc.c new file mode 100644 index 0000000..105cc29 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/src/usb-desc.c @@ -0,0 +1,284 @@ +/* Teensyduino Core Library + * http://www.pjrc.com/teensy/ + * Copyright (c) 2013 PJRC.COM, LLC. + * + * 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: + * + * 1. The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * 2. If the Software is incorporated into a build system that allows + * selection among a list of target devices, then similar target + * devices manufactured by PJRC.COM must be included in the list of + * target devices and selectable in the same manner. + * + * 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. + */ + +#include +#include +#include + +// USB Descriptors are binary data which the USB host reads to +// automatically detect a USB device's capabilities. The format +// and meaning of every field is documented in numerous USB +// standards. When working with USB descriptors, despite the +// complexity of the standards and poor writing quality in many +// of those documents, remember descriptors are nothing more +// than constant binary data that tells the USB host what the +// device can do. Computers will load drivers based on this data. +// Those drivers then communicate on the endpoints specified by +// the descriptors. + +// To configure a new combination of interfaces or make minor +// changes to existing configuration (eg, change the name or ID +// numbers), usually you would edit "usb_desc.h". This file +// is meant to be configured by the header, so generally it is +// only edited to add completely new USB interfaces or features. + +// ************************************************************** +// USB Device +// ************************************************************** + +#define LSB(n) ((n) & 255) +#define MSB(n) (((n) >> 8) & 255) + +#define USB_DT_BOS_SIZE 5 +#define USB_DT_BOS 0xf +#define USB_DT_DEVICE_CAPABILITY 0x10 +#define USB_DC_PLATFORM 5 + +struct usb_bos_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumDeviceCaps; +} __attribute__((packed)); + +// USB Device Descriptor. The USB host reads this first, to learn +// what type of device is connected. +static const uint8_t device_descriptor[] = { + 18, // bLength + 1, // bDescriptorType + 0x10, 0x02, // bcdUSB + USB_CLASS_CDC, // bDeviceClass + 0x00, // bDeviceSubClass + 0x00, // bDeviceProtocol + 64, // bMaxPacketSize0 + LSB(VENDOR_ID), MSB(VENDOR_ID), // idVendor + LSB(PRODUCT_ID), MSB(PRODUCT_ID), // idProduct + LSB(DEVICE_VER), MSB(DEVICE_VER), // bcdDevice + 1, // iManufacturer + 2, // iProduct + 0, // iSerialNumber + 1 // bNumConfigurations +}; + + +// ************************************************************** +// USB Configuration +// ************************************************************** + +// USB Configuration Descriptor. This huge descriptor tells all +// of the devices capbilities. +#define CONFIG_DESC_SIZE 67 +static const uint8_t config_descriptor[CONFIG_DESC_SIZE] = { + // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10 + 9, // bLength; + 2, // bDescriptorType; + LSB(CONFIG_DESC_SIZE), // wTotalLength + MSB(CONFIG_DESC_SIZE), + 2, // bNumInterfaces + 1, // bConfigurationValue + 0, // iConfiguration + 0x80, // bmAttributes + 50, // bMaxPower + + // interface descriptor, CDC + USB_DT_INTERFACE_SIZE, // bLength + USB_DT_INTERFACE, // bDescriptorType + 0, // bInterfaceNumber + 0, // bAlternateSetting + 1, // bNumEndpoints + USB_CLASS_CDC, // bInterfaceClass + USB_CDC_SUBCLASS_ACM, // bInterfaceSubClass + USB_CDC_PROTOCOL_AT, // bInterfaceProtocol + 0, // iInterface + + // Header Functional Descriptor + 0x05, // bLength: Endpoint Descriptor size + CS_INTERFACE, // bDescriptorType: CS_INTERFACE + USB_CDC_TYPE_HEADER, // bDescriptorSubtype: Header Func Desc + 0x10, // bcdCDC: spec release number + 0x01, + + // Call Management Functional Descriptor + 0x05, // bFunctionLength + CS_INTERFACE, // bDescriptorType: CS_INTERFACE + USB_CDC_TYPE_CALL_MANAGEMENT, // bDescriptorSubtype: Call Management Func Desc + 0, // bmCapabilities: D0+D1 + 1, // bDataInterface: 1 + + // ACM Functional Descriptor + 0x04, // bFunctionLength + CS_INTERFACE, // bDescriptorType: CS_INTERFACE + USB_CDC_TYPE_ACM, // bDescriptorSubtype: Abstract Control Management desc + 6, // bmCapabilities + + // Union Functional Descriptor + 0x05, // bFunctionLength + CS_INTERFACE, // bDescriptorType: CS_INTERFACE + USB_CDC_TYPE_UNION, // bDescriptorSubtype: Union func desc + 0, // bMasterInterface: Communication class interface + 1, // bSlaveInterface0: Data Class Interface + + // Endpoint descriptor + USB_DT_ENDPOINT_SIZE, // bLength + USB_DT_ENDPOINT, // bDescriptorType + 0x81, // bEndpointAddress + USB_ENDPOINT_ATTR_INTERRUPT, // bmAttributes + LSB(16), // wMaxPacketSize + MSB(16), // wMaxPacketSize + 255, // bInterval + + // interface descriptor, CDC + USB_DT_INTERFACE_SIZE, // bLength + USB_DT_INTERFACE, // bDescriptorType + 1, // bInterfaceNumber + 0, // bAlternateSetting + 2, // bNumEndpoints + USB_CLASS_DATA, // bInterfaceClass + 0, // bInterfaceSubClass + 0, // bInterfaceProtocol + 0, // iInterface + + // Endpoint descriptor + USB_DT_ENDPOINT_SIZE, // bLength + USB_DT_ENDPOINT, // bDescriptorType + 0x82, // bEndpointAddress + USB_ENDPOINT_ATTR_BULK, // bmAttributes + LSB(64), // wMaxPacketSize + MSB(64), // wMaxPacketSize + 1, // bInterval + + // Endpoint descriptor + USB_DT_ENDPOINT_SIZE, // bLength + USB_DT_ENDPOINT, // bDescriptorType + 0x02, // bEndpointAddress + USB_ENDPOINT_ATTR_BULK, // bmAttributes + LSB(64), // wMaxPacketSize + MSB(64), // wMaxPacketSize + 1, // bInterval +}; + + +// ************************************************************** +// String Descriptors +// ************************************************************** + +// The descriptors above can provide human readable strings, +// referenced by index numbers. These descriptors are the +// actual string data + +static const struct usb_string_descriptor_struct string0 = { + 4, + 3, + {0x0409} +}; + +// Microsoft OS String Descriptor. See: https://github.com/pbatard/libwdi/wiki/WCID-Devices +static const struct usb_string_descriptor_struct usb_string_microsoft = { + 18, 3, + {'M','S','F','T','1','0','0', MSFT_VENDOR_CODE} +}; + +// Microsoft WCID +const uint8_t usb_microsoft_wcid[MSFT_WCID_LEN] = { + MSFT_WCID_LEN, 0, 0, 0, // Length + 0x00, 0x01, // Version + 0x04, 0x00, // Compatibility ID descriptor index + 0x01, // Number of sections + 0, 0, 0, 0, 0, 0, 0, // Reserved (7 bytes) + + 0, // Interface number + 0x01, // Reserved + 'W','I','N','U','S','B',0,0, // Compatible ID + 0,0,0,0,0,0,0,0, // Sub-compatible ID (unused) + 0,0,0,0,0,0, // Reserved +}; + +const struct webusb_url_descriptor landing_url_descriptor = { + .bLength = LANDING_PAGE_DESCRIPTOR_SIZE, + .bDescriptorType = WEBUSB_DT_URL, + .bScheme = WEBUSB_URL_SCHEME_HTTPS, + .URL = LANDING_PAGE_URL +}; + +struct full_bos { + struct usb_bos_descriptor bos; + struct webusb_platform_descriptor webusb; +}; + +static const struct full_bos full_bos = { + .bos = { + .bLength = USB_DT_BOS_SIZE, + .bDescriptorType = USB_DT_BOS, + .wTotalLength = USB_DT_BOS_SIZE + WEBUSB_PLATFORM_DESCRIPTOR_SIZE, + .bNumDeviceCaps = 1, + }, + .webusb = { + .bLength = WEBUSB_PLATFORM_DESCRIPTOR_SIZE, + .bDescriptorType = USB_DT_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_DC_PLATFORM, + .bReserved = 0, + .platformCapabilityUUID = WEBUSB_UUID, + .bcdVersion = 0x0100, + .bVendorCode = WEBUSB_VENDOR_CODE, + .iLandingPage = 1, + }, +}; + +__attribute__((aligned(4))) +static const struct usb_string_descriptor_struct usb_string_manufacturer_name = { + 2 + MANUFACTURER_NAME_LEN, + 3, + MANUFACTURER_NAME +}; + +__attribute__((aligned(4))) +struct usb_string_descriptor_struct usb_string_product_name = { + 2 + PRODUCT_NAME_LEN, + 3, + PRODUCT_NAME +}; + +// ************************************************************** +// Descriptors List +// ************************************************************** + +// This table provides access to all the descriptor data above. + +__attribute__((section(".data"))) +const usb_descriptor_list_t usb_descriptor_list[] = { + {0x0100, sizeof(device_descriptor), device_descriptor}, + {0x0200, sizeof(config_descriptor), config_descriptor}, + {0x0300, 0, (const uint8_t *)&string0}, + {0x0301, 0, (const uint8_t *)&usb_string_manufacturer_name}, + {0x0302, 0, (const uint8_t *)&usb_string_product_name}, + {0x03EE, 0, (const uint8_t *)&usb_string_microsoft}, + {0x0F00, sizeof(full_bos), (const uint8_t *)&full_bos}, + {0, 0, NULL} +}; diff --git a/ext/wasm3/platforms/embedded/fomu/src/usb-dev.c b/ext/wasm3/platforms/embedded/fomu/src/usb-dev.c new file mode 100644 index 0000000..bf0739e --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/src/usb-dev.c @@ -0,0 +1,285 @@ +#include +#include +#include +#include +#include + +static uint8_t reply_buffer[8]; +static uint8_t usb_configuration = 0; +// #define USB_MAX_PACKET_SIZE 64 +// static uint32_t rx_buffer[USB_MAX_PACKET_SIZE/4]; + +volatile uint8_t terminal_is_connected; + +__attribute__((section(".ramtext"))) +void usb_setup(const struct usb_setup_request *setup) { + const uint8_t *data = NULL; + uint32_t datalen = 0; + const usb_descriptor_list_t *list; + + switch (setup->wRequestAndType) + { + case 0x2021: // Set Line Coding + break; + case 0x2221: // Set control line state + terminal_is_connected = setup->wValue & 1; + break; + + case 0x0500: // SET_ADDRESS + usb_set_address(((uint8_t *)setup)[2]); + break; + + case 0x0b01: // SET_INTERFACE + //dfu_clrstatus(); + break; + + case 0x0900: // SET_CONFIGURATION + usb_configuration = setup->wValue; + break; + + case 0x0880: // GET_CONFIGURATION + reply_buffer[0] = usb_configuration; + datalen = 1; + data = reply_buffer; + break; + + case 0x0080: // GET_STATUS (device) + reply_buffer[0] = 0; + reply_buffer[1] = 0; + datalen = 2; + data = reply_buffer; + break; + + case 0x0082: // GET_STATUS (endpoint) + if (setup->wIndex > 0) + { + usb_err_in(); + return; + } + reply_buffer[0] = 0; + reply_buffer[1] = 0; + + // XXX handle endpoint stall here +// if (USB->DIEP0CTL & USB_DIEP_CTL_STALL) +// reply_buffer[0] = 1; + data = reply_buffer; + datalen = 2; + break; + + case 0x0102: // CLEAR_FEATURE (endpoint) + // if (setup->wIndex > 0 || setup->wValue != 0) + // { + // // TODO: do we need to handle IN vs OUT here? + // usb_err_in(); + // return; + // } + // XXX: Should we clear the stall bit? + // USB->DIEP0CTL &= ~USB_DIEP_CTL_STALL; + // TODO: do we need to clear the data toggle here? + break; + + case 0x0302: // SET_FEATURE (endpoint) + // if (setup->wIndex > 0 || setup->wValue != 0) + // { + // // TODO: do we need to handle IN vs OUT here? + // usb_err_in(); + // return; + // } + // XXX: Should we set the stall bit? + // USB->DIEP0CTL |= USB_DIEP_CTL_STALL; + // TODO: do we need to clear the data toggle here? + break; + + case 0x0680: // GET_DESCRIPTOR + case 0x0681: + for (list = usb_descriptor_list; 1; list++) + { + if (list->addr == NULL) + break; + if (setup->wValue == list->wValue) + { + data = list->addr; + if ((setup->wValue >> 8) == 3) + { + // for string descriptors, use the descriptor's + // length field, allowing runtime configured + // length. + datalen = *(list->addr); + } + else + { + datalen = list->length; + } + goto send; + } + } + usb_err_in(); + return; +#if 0 + case (MSFT_VENDOR_CODE << 8) | 0xC0: // Get Microsoft descriptor + case (MSFT_VENDOR_CODE << 8) | 0xC1: + if (setup->wIndex == 0x0004) + { + // Return WCID descriptor + data = usb_microsoft_wcid; + datalen = MSFT_WCID_LEN; + break; + } + usb_err(); + return; + + case (WEBUSB_VENDOR_CODE << 8) | 0xC0: // Get WebUSB descriptor + if (setup->wIndex == 0x0002) + { + if (setup->wValue == 0x0001) + { + // Return landing page URL descriptor + data = (uint8_t*)&landing_url_descriptor; + datalen = LANDING_PAGE_DESCRIPTOR_SIZE; + break; + } + } + // printf("%s:%d couldn't find webusb descriptor (%d / %d)\n", __FILE__, __LINE__, setup->wIndex, setup->wValue); + usb_err(); + return; +#endif + +#if 0 + case 0x0121: // DFU_DNLOAD + if (setup->wIndex > 0) + { + usb_err(); + return; + } + // Data comes in the OUT phase. But if it's a zero-length request, handle it now. + if (setup->wLength == 0) + { + if (!dfu_download(setup->wValue, 0, 0, 0, NULL)) + { + usb_err(); + return; + } + usb_ack_in(); + return; + } + + // ACK the setup packet + // usb_ack_out(); + + int bytes_remaining = setup->wLength; + int ep0_rx_offset = 0; + // Fill the buffer, or if there is enough space transfer the whole packet. + unsigned int blockLength = setup->wLength; + unsigned int blockNum = setup->wValue; + + while (bytes_remaining > 0) { + unsigned int i; + unsigned int len = blockLength; + if (len > sizeof(rx_buffer)) + len = sizeof(rx_buffer); + for (i = 0; i < sizeof(rx_buffer)/4; i++) + rx_buffer[i] = 0xffffffff; + + // Receive DATA packets (which are automatically ACKed) + len = usb_recv((void *)rx_buffer, len); + + // Append the data to the download buffer. + dfu_download(blockNum, blockLength, ep0_rx_offset, len, (void *)rx_buffer); + + bytes_remaining -= len; + ep0_rx_offset += len; + } + + // ACK the final IN packet. + usb_ack_in(); + + return; + + case 0x0021: // DFU_DETACH + // Send the "ACK" packet and wait for it + // to be received. + usb_ack_in(); + usb_wait_for_send_done(); + reboot(); + while (1) + ; + return; + + case 0x03a1: // DFU_GETSTATUS + if (setup->wIndex > 0) + { + usb_err(); + return; + } + if (dfu_getstatus(reply_buffer)) + { + data = reply_buffer; + datalen = 6; + break; + } + else + { + usb_err(); + return; + } + break; + + case 0x0421: // DFU_CLRSTATUS + if (setup->wIndex > 0) + { + usb_err(); + return; + } + if (dfu_clrstatus()) + { + break; + } + else + { + usb_err(); + return; + } + + case 0x05a1: // DFU_GETSTATE + if (setup->wIndex > 0) + { + usb_err(); + return; + } + reply_buffer[0] = dfu_getstate(); + data = reply_buffer; + datalen = 1; + break; + + case 0x0621: // DFU_ABORT + if (setup->wIndex > 0) + { + usb_err(); + return; + } + if (dfu_abort()) + { + break; + } + else + { + usb_err(); + return; + } +#endif + + default: + usb_err_in(); + return; + } + +send: + if (data && datalen) { + if (datalen > setup->wLength) + datalen = setup->wLength; + usb_send(data, datalen); + } + else + usb_ack_in(); + return; +} diff --git a/ext/wasm3/platforms/embedded/fomu/src/usb-epfifo.c b/ext/wasm3/platforms/embedded/fomu/src/usb-epfifo.c new file mode 100644 index 0000000..35dd83c --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/src/usb-epfifo.c @@ -0,0 +1,369 @@ +#include +#include +#include +#include +#include + +#ifdef CSR_USB_EP_0_OUT_EV_PENDING_ADDR + +static volatile uint8_t usb_rx_fifo[64]; +static volatile uint8_t usb_rx_fifo_rd; +static volatile uint8_t usb_rx_fifo_wr; + +static volatile int have_new_address; +static volatile uint8_t new_address; + +// Firmware versions < 1.9 didn't have usb_address_write() +static inline void usb_set_address_wrapper(uint8_t address) { + if (version_major_read() < 1) + return; + if (version_minor_read() < 9) + return; + usb_address_write(address); +} + +// Note that our PIDs are only bits 2 and 3 of the token, +// since all other bits are effectively redundant at this point. +enum USB_PID { + USB_PID_OUT = 0, + USB_PID_SOF = 1, + USB_PID_IN = 2, + USB_PID_SETUP = 3, +}; + +enum epfifo_response { + EPF_ACK = 0, + EPF_NAK = 1, + EPF_NONE = 2, + EPF_STALL = 3, +}; + +#define USB_EV_ERROR 1 +#define USB_EV_PACKET 2 + +void usb_disconnect(void) { + usb_ep_0_out_ev_enable_write(0); + usb_ep_0_in_ev_enable_write(0); + irq_setmask(irq_getmask() & ~(1 << USB_INTERRUPT)); + usb_pullup_out_write(0); + usb_set_address_wrapper(0); +} + +void usb_connect(void) { + + usb_set_address_wrapper(0); + usb_ep_0_out_ev_pending_write(usb_ep_0_out_ev_enable_read()); + usb_ep_0_in_ev_pending_write(usb_ep_0_in_ev_pending_read()); + usb_ep_0_out_ev_enable_write(USB_EV_PACKET | USB_EV_ERROR); + usb_ep_0_in_ev_enable_write(USB_EV_PACKET | USB_EV_ERROR); + + usb_ep_1_in_ev_pending_write(usb_ep_1_in_ev_enable_read()); + usb_ep_1_in_ev_enable_write(USB_EV_PACKET | USB_EV_ERROR); + + usb_ep_2_out_ev_pending_write(usb_ep_2_out_ev_enable_read()); + usb_ep_2_in_ev_pending_write(usb_ep_2_in_ev_pending_read()); + usb_ep_2_out_ev_enable_write(USB_EV_PACKET | USB_EV_ERROR); + usb_ep_2_in_ev_enable_write(USB_EV_PACKET | USB_EV_ERROR); + + // Accept incoming data by default. + usb_ep_0_out_respond_write(EPF_ACK); + usb_ep_2_out_respond_write(EPF_ACK); + + // Reject outgoing data, since we have none to give yet. + usb_ep_0_in_respond_write(EPF_NAK); + usb_ep_1_in_respond_write(EPF_NAK); + usb_ep_2_in_respond_write(EPF_NAK); + + usb_pullup_out_write(1); + + irq_setmask(irq_getmask() | (1 << USB_INTERRUPT)); +} + +void usb_init(void) { + usb_pullup_out_write(0); + return; +} + +#define EP0OUT_BUFFERS 4 +__attribute__((aligned(4))) +static uint8_t volatile usb_ep0out_buffer[EP0OUT_BUFFERS][256]; +static uint8_t volatile usb_ep0out_buffer_len[EP0OUT_BUFFERS]; +static uint8_t volatile usb_ep0out_last_tok[EP0OUT_BUFFERS]; +static volatile uint8_t usb_ep0out_wr_ptr; +static volatile uint8_t usb_ep0out_rd_ptr; +static const int max_byte_length = 64; + +static const uint8_t * volatile current_data; +static volatile int current_length; +static volatile int data_offset; +static volatile int data_to_send; +static int next_packet_is_empty; +static volatile uint8_t ep2_fifo_bytes; + +__attribute__((section(".ramtext"))) +static void process_tx(void) { + + // Don't allow requeueing -- only queue more data if we're + // currently set up to respond NAK. + if (usb_ep_0_in_respond_read() != EPF_NAK) { + return; + } + + // Prevent us from double-filling the buffer. + if (!usb_ep_0_in_ibuf_empty_read()) { + return; + } + + if (!current_data || !current_length) { + return; + } + + data_offset += data_to_send; + + data_to_send = current_length - data_offset; + + // Clamp the data to the maximum packet length + if (data_to_send > max_byte_length) { + data_to_send = max_byte_length; + next_packet_is_empty = 0; + } + else if (data_to_send == max_byte_length) { + next_packet_is_empty = 1; + } + else if (next_packet_is_empty) { + next_packet_is_empty = 0; + data_to_send = 0; + } + else if (current_data == NULL || data_to_send <= 0) { + next_packet_is_empty = 0; + current_data = NULL; + current_length = 0; + data_offset = 0; + data_to_send = 0; + return; + } + + int this_offset; + for (this_offset = data_offset; this_offset < (data_offset + data_to_send); this_offset++) { + usb_ep_0_in_ibuf_head_write(current_data[this_offset]); + } + usb_ep_0_in_respond_write(EPF_ACK); + return; +} + +int usb_send(const void *data, int total_count) { + + while ((current_length || current_data))// && usb_ep_0_in_respond_read() != EPF_NAK) + ; + current_data = (uint8_t *)data; + current_length = total_count; + data_offset = 0; + data_to_send = 0; + process_tx(); + + return 0; +} + +int usb_wait_for_send_done(void) { + while (current_data && current_length) + usb_poll(); + while ((usb_ep_0_in_dtb_read() & 1) == 1) + usb_poll(); + return 0; +} + +__attribute__((section(".ramtext"))) +void usb_isr(void) { + uint8_t ep_pending; + + ep_pending = usb_ep_0_out_ev_pending_read(); + + // We got an OUT or a SETUP packet. Copy it to usb_ep0out_buffer + // and clear the "pending" bit. + if (ep_pending) { + uint8_t last_tok = usb_ep_0_out_last_tok_read(); + + int byte_count = 0; + usb_ep0out_last_tok[usb_ep0out_wr_ptr] = last_tok; + volatile uint8_t * obuf = usb_ep0out_buffer[usb_ep0out_wr_ptr]; + while (!usb_ep_0_out_obuf_empty_read()) { + obuf[byte_count++] = usb_ep_0_out_obuf_head_read(); + usb_ep_0_out_obuf_head_write(0); + } + + if (last_tok == USB_PID_SETUP) { + usb_ep_0_in_dtb_write(1); + data_offset = 0; + current_length = 0; + current_data = NULL; + const struct usb_setup_request *request = (const struct usb_setup_request *)obuf; + usb_setup(request); + } + else { + usb_ep0out_buffer_len[usb_ep0out_wr_ptr] = byte_count - 2 /* Strip off CRC16 */; + usb_ep0out_wr_ptr = (usb_ep0out_wr_ptr + 1) & (EP0OUT_BUFFERS-1); + } + usb_ep_0_out_ev_pending_write(ep_pending); + usb_ep_0_out_respond_write(EPF_ACK); + } + + ep_pending = usb_ep_0_in_ev_pending_read(); + // We just got an "IN" token. Send data if we have it. + if (ep_pending) { + usb_ep_0_in_respond_write(EPF_NAK); + usb_ep_0_in_ev_pending_write(ep_pending); + if (have_new_address) { + have_new_address = 0; + usb_set_address_wrapper(new_address); + } + process_tx(); + } + + ep_pending = usb_ep_1_in_ev_pending_read(); + if (ep_pending) { + usb_ep_1_in_respond_write(EPF_NAK); + usb_ep_1_in_ev_pending_write(ep_pending); + } + + ep_pending = usb_ep_2_in_ev_pending_read(); + if (ep_pending) { + usb_ep_2_in_respond_write(EPF_NAK); + usb_ep_2_in_ev_pending_write(ep_pending); + ep2_fifo_bytes = 0; + } + + ep_pending = usb_ep_2_out_ev_pending_read(); + if (ep_pending) { + while (!usb_ep_2_out_obuf_empty_read()) { + usb_rx_fifo[(usb_rx_fifo_wr++) & 0x3f] = usb_ep_2_out_obuf_head_read(); + usb_ep_2_out_obuf_head_write(0); + } + // Strip off the CRC16. + usb_rx_fifo_wr -= 2; + + usb_ep_2_out_ev_pending_write(ep_pending); + usb_ep_2_out_respond_write(EPF_NAK); + } + + return; +} + +__attribute__((section(".ramtext"))) +int usb_getc(void) { + if (usb_rx_fifo_rd == usb_rx_fifo_wr) { + usb_ep_2_out_respond_write(EPF_ACK); + return -1; + } + return usb_rx_fifo[(usb_rx_fifo_rd++) & 0x3f]; +} + +__attribute__((section(".ramtext"))) +void usb_putc(char c) { + usb_ep_2_in_ibuf_head_write(c); + ep2_fifo_bytes++; + usb_ep_2_in_respond_write(EPF_ACK); +} + +__attribute__((section(".ramtext"))) +int usb_write(const char *buf, int count) { + int to_write = 64; + int i; + if (to_write > count) + to_write = count; + for (i = 0; i < to_write; i++) + usb_ep_2_in_ibuf_head_write(buf[i]); + ep2_fifo_bytes += to_write; + usb_ep_2_in_respond_write(EPF_ACK); + + return to_write; +} + +extern volatile uint8_t terminal_is_connected; + +__attribute__((section(".ramtext"))) +int usb_can_getc(void) { + if (usb_rx_fifo_rd == usb_rx_fifo_wr) { + usb_ep_2_out_respond_write(EPF_ACK); + return 0; + } + return terminal_is_connected; +} + +__attribute__((section(".ramtext"))) +int usb_can_putc(void) { + return terminal_is_connected && usb_ep_2_in_ibuf_empty_read() && (usb_ep_2_in_respond_read() == EPF_NAK);// (ep2_fifo_bytes <= 60); +} + +__attribute__((section(".ramtext"))) +void usb_ack_in(void) { + // usb_ep_0_in_dtb_write(1); + while (usb_ep_0_in_respond_read() == EPF_ACK) + ; + usb_ep_0_in_respond_write(EPF_ACK); +} + +__attribute__((section(".ramtext"))) +void usb_ack_out(void) { + // usb_ep_0_out_dtb_write(1); + while (usb_ep_0_out_respond_read() == EPF_ACK) + ; + usb_ep_0_out_respond_write(EPF_ACK); +} + +__attribute__((section(".ramtext"))) +void usb_err_in(void) { + usb_ep_0_in_respond_write(EPF_STALL); +} + +__attribute__((section(".ramtext"))) +void usb_err_out(void) { + usb_ep_0_out_respond_write(EPF_STALL); +} + +__attribute__((section(".ramtext"))) +int usb_recv(void *buffer, unsigned int buffer_len) { + + // Set the OUT response to ACK, since we are in a position to receive data now. + usb_ep_0_out_respond_write(EPF_ACK); + while (1) { + if (usb_ep0out_rd_ptr != usb_ep0out_wr_ptr) { + if (usb_ep0out_last_tok[usb_ep0out_rd_ptr] == USB_PID_OUT) { + unsigned int ep0_buffer_len = usb_ep0out_buffer_len[usb_ep0out_rd_ptr]; + if (ep0_buffer_len < buffer_len) + buffer_len = ep0_buffer_len; + usb_ep0out_buffer_len[usb_ep0out_rd_ptr] = 0; + memcpy(buffer, (void *)&usb_ep0out_buffer[usb_ep0out_rd_ptr], buffer_len); + usb_ep0out_rd_ptr = (usb_ep0out_rd_ptr + 1) & (EP0OUT_BUFFERS-1); + return buffer_len; + } + usb_ep0out_rd_ptr = (usb_ep0out_rd_ptr + 1) & (EP0OUT_BUFFERS-1); + } + } + return 0; +} + +void usb_set_address(uint8_t new_address_) { + new_address = new_address_; + have_new_address = 1; +} + +__attribute__((section(".ramtext"))) +void usb_poll(void) { + // If some data was received, then process it. + while (usb_ep0out_rd_ptr != usb_ep0out_wr_ptr) { + const struct usb_setup_request *request = (const struct usb_setup_request *)(usb_ep0out_buffer[usb_ep0out_rd_ptr]); + // unsigned int len = usb_ep0out_buffer_len[usb_ep0out_rd_ptr]; + uint8_t last_tok = usb_ep0out_last_tok[usb_ep0out_rd_ptr]; + + usb_ep0out_buffer_len[usb_ep0out_rd_ptr] = 0; + usb_ep0out_rd_ptr = (usb_ep0out_rd_ptr + 1) & (EP0OUT_BUFFERS-1); + + if (last_tok == USB_PID_SETUP) { + usb_setup(request); + } + } + + process_tx(); +} + +#endif /* CSR_USB_EP_0_OUT_EV_PENDING_ADDR */ \ No newline at end of file diff --git a/ext/wasm3/platforms/embedded/fomu/src/wasm3 b/ext/wasm3/platforms/embedded/fomu/src/wasm3 new file mode 120000 index 0000000..17056a9 --- /dev/null +++ b/ext/wasm3/platforms/embedded/fomu/src/wasm3 @@ -0,0 +1 @@ +../../../../source \ No newline at end of file diff --git a/ext/wasm3/platforms/embedded/hifive1/.gitignore b/ext/wasm3/platforms/embedded/hifive1/.gitignore new file mode 100644 index 0000000..03f4a3c --- /dev/null +++ b/ext/wasm3/platforms/embedded/hifive1/.gitignore @@ -0,0 +1 @@ +.pio diff --git a/ext/wasm3/platforms/embedded/hifive1/README.md b/ext/wasm3/platforms/embedded/hifive1/README.md new file mode 100644 index 0000000..f49dfbc --- /dev/null +++ b/ext/wasm3/platforms/embedded/hifive1/README.md @@ -0,0 +1,19 @@ +## Build for HiFive1 + +### Debugging: + +On first console, run +```sh +JLinkGDBServer -singlerun -if JTAG -select USB -speed 1000 -jtagconf -1,-1 -device FE310 --port 2331 +``` + +On second console, run `riscv64-unknown-elf-gdb`: +```gdb +file ".pio/build/hifive1-revb/firmware.elf" +target extended-remote :2331 +b main +monitor halt +monitor reset +load +c +``` diff --git a/ext/wasm3/platforms/embedded/hifive1/lib/wasm3 b/ext/wasm3/platforms/embedded/hifive1/lib/wasm3 new file mode 120000 index 0000000..17056a9 --- /dev/null +++ b/ext/wasm3/platforms/embedded/hifive1/lib/wasm3 @@ -0,0 +1 @@ +../../../../source \ No newline at end of file diff --git a/ext/wasm3/platforms/embedded/hifive1/platformio.ini b/ext/wasm3/platforms/embedded/hifive1/platformio.ini new file mode 100644 index 0000000..50b1d46 --- /dev/null +++ b/ext/wasm3/platforms/embedded/hifive1/platformio.ini @@ -0,0 +1,36 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[platformio] +default_envs = hifive1-revb + +[env] +platform = sifive +framework = freedom-e-sdk +monitor_speed = 115200 + +board_build.f_cpu = 320000000L + +src_filter = + +<*> + - + +src_build_flags = + -Dd_m3FixedHeap=8192 + -Os -Wfatal-errors + -flto + +build_flags = -lm + +[env:hifive1] +board = hifive1 + +[env:hifive1-revb] +board = hifive1-revb diff --git a/ext/wasm3/platforms/embedded/hifive1/src/main.c b/ext/wasm3/platforms/embedded/hifive1/src/main.c new file mode 100644 index 0000000..3e489c3 --- /dev/null +++ b/ext/wasm3/platforms/embedded/hifive1/src/main.c @@ -0,0 +1,62 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include +#include +#include "wasm3.h" + +#include "extra/fib32.wasm.h" + +#define FATAL(msg, ...) { printf("Fatal: " msg "\n", ##__VA_ARGS__); return; } + +void run_wasm() +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + uint32_t fsize = fib32_wasm_len; + + printf("Loading WebAssembly...\n"); + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + if (!runtime) FATAL("m3_NewRuntime failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule: %s", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule: %s", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction: %s", result); + + printf("Running...\n"); + + result = m3_CallV (f, 24); + if (result) FATAL("m3_Call: %s", result); + + uint32_t value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults: %s", result); + + printf("Result: %d\n", value); +} + +int main() { + printf("\n"); + printf("Wasm3 v" M3_VERSION " on HiFive1 (" M3_ARCH "), build " __DATE__ " " __TIME__ "\n"); + // TODO: fix clock (shows wrong time) + clock_t start = clock(); + run_wasm(); + clock_t end = clock(); + + printf("Elapsed: %ld ms\n", (end - start)*1000 / CLOCKS_PER_SEC); +} diff --git a/ext/wasm3/platforms/embedded/particle/.gitignore b/ext/wasm3/platforms/embedded/particle/.gitignore new file mode 100644 index 0000000..a8a0dce --- /dev/null +++ b/ext/wasm3/platforms/embedded/particle/.gitignore @@ -0,0 +1 @@ +*.bin diff --git a/ext/wasm3/platforms/embedded/particle/README.md b/ext/wasm3/platforms/embedded/particle/README.md new file mode 100644 index 0000000..bbb0420 --- /dev/null +++ b/ext/wasm3/platforms/embedded/particle/README.md @@ -0,0 +1,18 @@ +## Build for Particle + +You need to install Particle CLI. + +Build for `photon`, `electron`, `pi`, `duo`, `p1`, `argon`, `boron`, `xenon`: +```sh +particle compile --followSymlinks photon +``` + +Upload to device: +``` +particle list +particle flash MyDevice1 ./firmware_*.bin + +# Or using USB: +particle flash --usb ./firmware_*.bin +``` + diff --git a/ext/wasm3/platforms/embedded/particle/lib/wasm3/library.properties b/ext/wasm3/platforms/embedded/particle/lib/wasm3/library.properties new file mode 100644 index 0000000..a257fd2 --- /dev/null +++ b/ext/wasm3/platforms/embedded/particle/lib/wasm3/library.properties @@ -0,0 +1,6 @@ +name=wasm3 +version=0.1.0 +license=MIT +author=Volodymyr Shymanskyy +sentence=WebAssembly interpreter for Particle devices +url=https://github.com/vshymanskyy/wasm3 diff --git a/ext/wasm3/platforms/embedded/particle/lib/wasm3/src b/ext/wasm3/platforms/embedded/particle/lib/wasm3/src new file mode 120000 index 0000000..e3e41d7 --- /dev/null +++ b/ext/wasm3/platforms/embedded/particle/lib/wasm3/src @@ -0,0 +1 @@ +../../../../../source \ No newline at end of file diff --git a/ext/wasm3/platforms/embedded/particle/project.properties b/ext/wasm3/platforms/embedded/particle/project.properties new file mode 100644 index 0000000..e09fa29 --- /dev/null +++ b/ext/wasm3/platforms/embedded/particle/project.properties @@ -0,0 +1 @@ +name=wasm3 diff --git a/ext/wasm3/platforms/embedded/particle/src/main.ino b/ext/wasm3/platforms/embedded/particle/src/main.ino new file mode 100644 index 0000000..5578a2b --- /dev/null +++ b/ext/wasm3/platforms/embedded/particle/src/main.ino @@ -0,0 +1,81 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include "wasm3.h" + +#include "extra/fib32.wasm.h" + +#define FATAL(func, msg) { \ + Serial.print("Fatal: " func ": "); \ + Serial.println(msg); return; } + +// Redefine puts +int puts(const char* s) { + Serial.println(s); + return 1; +} + +void run_wasm() +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + size_t fsize = fib32_wasm_len; + + Serial.println("Loading WebAssembly..."); + + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment", "failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + if (!runtime) FATAL("m3_NewRuntime", "failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction", result); + + Serial.println("Running..."); + + result = m3_CallV (f, 24); + if (result) FATAL("m3_Call: %s", result); + + uint32_t value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults: %s", result); + + Serial.print("Result: "); + Serial.println(value); +} + +void setup() +{ + Serial.begin(115200); + delay(10); + + Serial.println(); + Serial.println("Wasm3 v" M3_VERSION " on Particle, build " __DATE__ " " __TIME__); + + uint32_t start = millis(); + run_wasm(); + uint32_t end = millis(); + + Serial.print("Elapsed: "); + Serial.print(end - start); + Serial.println(" ms"); +} + +void loop() +{ + delay(100); +} diff --git a/ext/wasm3/platforms/embedded/wm_w600/.gitignore b/ext/wasm3/platforms/embedded/wm_w600/.gitignore new file mode 100644 index 0000000..16ff3c7 --- /dev/null +++ b/ext/wasm3/platforms/embedded/wm_w600/.gitignore @@ -0,0 +1 @@ +.output diff --git a/ext/wasm3/platforms/embedded/wm_w600/Makefile b/ext/wasm3/platforms/embedded/wm_w600/Makefile new file mode 100644 index 0000000..645616f --- /dev/null +++ b/ext/wasm3/platforms/embedded/wm_w600/Makefile @@ -0,0 +1,120 @@ +############################################################# +# Required variables for each makefile +# Discard this section from all parent makefiles +# Expected variables (with automatic defaults): +# CSRCS (all "C" files in the dir) +# SUBDIRS (all subdirs with a Makefile) +# GEN_LIBS - list of libs to be generated () +# GEN_IMAGES - list of object file images to be generated () +# GEN_BINS - list of binaries to be generated () +# COMPONENTS_xxx - a list of libs/objs in the form +# subdir/lib to be extracted and rolled up into +# a generated lib/image xxx.a () +# + +TOP_DIR:= $(WM_SDK) + +sinclude $(TOP_DIR)/tools/tool_chain.def + +USE_LIB=1 + +CSRCS = $(wildcard *.c) $(wildcard wasm3/*.c) + +#EXTRA_CCFLAGS += -u +ifndef PDIR +GEN_IMAGES= $(TARGET).out +GEN_BINS = $(TARGET).bin +SUBDIRS = \ + $(TOP_DIR)/platform/boot/$(COMPILE) + +ifeq ($(USE_LIB), 0) +SUBDIRS += \ + $(TOP_DIR)/platform/common \ + $(TOP_DIR)/platform/drivers \ + $(TOP_DIR)/platform/sys \ + $(TOP_DIR)/src/os \ + $(TOP_DIR)/src/app \ + $(TOP_DIR)/src/network +endif +endif + +COMPONENTS_$(TARGET) = \ + $(TOP_DIR)/platform/boot/$(COMPILE)/startup.o \ + $(TOP_DIR)/platform/boot/$(COMPILE)/misc.o \ + $(TOP_DIR)/platform/boot/$(COMPILE)/retarget.o + +ifeq ($(USE_LIB), 0) +COMPONENTS_$(TARGET) += \ + $(TOP_DIR)/platform/common/libcommon$(LIB_EXT) \ + $(TOP_DIR)/platform/drivers/libdrivers$(LIB_EXT) \ + $(TOP_DIR)/platform/sys/libsys$(LIB_EXT) \ + $(TOP_DIR)/src/os/libos$(LIB_EXT) \ + $(TOP_DIR)/src/network/libnetwork$(LIB_EXT) \ + $(TOP_DIR)/src/app/libapp$(LIB_EXT) +endif + +ifeq ($(USE_LIB), 1) +LINKLIB = \ + $(TOP_DIR)/lib/libcommon$(LIB_EXT) \ + $(TOP_DIR)/lib/libdrivers$(LIB_EXT) \ + $(TOP_DIR)/lib/libsys$(LIB_EXT) \ + $(TOP_DIR)/lib/libos$(LIB_EXT) \ + $(TOP_DIR)/lib/libnetwork$(LIB_EXT) \ + $(TOP_DIR)/lib/libapp$(LIB_EXT) +endif + +LINKLIB += \ + $(TOP_DIR)/lib/libairkiss_log$(LIB_EXT) \ + $(TOP_DIR)/lib/libwlan$(LIB_EXT) + +ifeq ($(COMPILE), gcc) +LINKFLAGS_$(TARGET) = \ + $(LINKLIB) \ + -T$(LD_FILE) \ + -Wl,-warn-common +else +LINKFLAGS_$(TARGET) = \ + --library_type=microlib \ + $(LINKLIB) \ + --strict --scatter $(LD_FILE) +endif + +############################################################# +# Configuration i.e. compile options etc. +# Target specific stuff (defines etc.) goes in here! +# Generally values applying to a tree are captured in the +# makefile at its root level - these are then overridden +# for a subtree within the makefile rooted therein +# + +CONFIGURATION_DEFINES += -DWM_W600 + +DEFINES += $(CONFIGURATION_DEFINES) -Os -flto -Wfatal-errors \ + -fomit-frame-pointer -fno-stack-check -fno-stack-protector \ + -Wno-unused-function -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers +# -Dd_m3FixedHeap=8192 +# -fno-optimize-sibling-calls + +LINKFLAGS_$(TARGET) += -Os -flto + +LINKLIB += -lm + +############################################################# +# Recursion Magic - Don't touch this!! +# +# Each subtree potentially has an include directory +# corresponding to the common APIs applicable to modules +# rooted at that subtree. Accordingly, the INCLUDE PATH +# of a module can only contain the include directories up +# its parent path, and not its siblings +# +# Required for each makefile to inherit from the parent +# + +INCLUDES := $(INCLUDES) -I$(PDIR)include +INCLUDES += -I ./ -I ./wasm3/ + +sinclude $(TOP_DIR)/tools/rules.mk + +.PHONY: FORCE +FORCE: diff --git a/ext/wasm3/platforms/embedded/wm_w600/README.md b/ext/wasm3/platforms/embedded/wm_w600/README.md new file mode 100644 index 0000000..7e7983d --- /dev/null +++ b/ext/wasm3/platforms/embedded/wm_w600/README.md @@ -0,0 +1,28 @@ +## Build for Winner Micro W600 + +You will need: + +- [W600 SDK from ThingsTurn](https://github.com/w600/sdk) + `git clone --depth=1 --branch=sdk_v3.2.0 https://github.com/w600/sdk.git /opt/w600-sdk` +- [gcc-arm-none-eabi-4_9-2015q3](https://launchpad.net/gcc-arm-embedded/4.9/4.9-2015-q3-update) +- [w600tool](https://github.com/vshymanskyy/w600tool) + +```sh +export PATH=/opt/gcc-arm-none-eabi-4_9-2015q3/bin:$PATH + +export PATH=/opt/w600tool:$PATH + +export WM_SDK=/opt/w600-sdk + +./build.sh +``` + +To upload: + +```sh +w600tool.py --upload .output/wasm3_gz.img +``` +or +```sh +w600tool.py --upload .output/wasm3.fls +``` diff --git a/ext/wasm3/platforms/embedded/wm_w600/build.sh b/ext/wasm3/platforms/embedded/wm_w600/build.sh new file mode 100755 index 0000000..dc28b5f --- /dev/null +++ b/ext/wasm3/platforms/embedded/wm_w600/build.sh @@ -0,0 +1,10 @@ +#!/bin/sh +rm -rf .output + +mkdir -p .output/wasm3/obj/wasm3/ + +make COMPILE=gcc TARGET=wasm3 FLASH_SIZE=1M VERBOSE=YES + +cp $WM_SDK/bin/wasm3/* ./.output/ + +rm test.bin diff --git a/ext/wasm3/platforms/embedded/wm_w600/main.c b/ext/wasm3/platforms/embedded/wm_w600/main.c new file mode 100644 index 0000000..8777eb0 --- /dev/null +++ b/ext/wasm3/platforms/embedded/wm_w600/main.c @@ -0,0 +1,91 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include "wm_include.h" + +#include "wasm3.h" + +#include "extra/fib32.wasm.h" + +#define FATAL(msg, ...) { printf("Fatal: " msg "\n", ##__VA_ARGS__); return; } + +unsigned int millis(void) +{ + return tls_os_get_time()*2; +} + +void run_wasm() +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + uint32_t fsize = fib32_wasm_len; + + printf("Loading WebAssembly...\n"); + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + if (!runtime) FATAL("m3_NewRuntime failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule: %s", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule: %s", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction: %s", result); + + printf("Running...\n"); + + result = m3_CallV (f, 24); + if (result) FATAL("m3_Call: %s", result); + + uint32_t value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults: %s", result); + + printf("Result: %ld\n", value); +} + + +#define USER_TASK_STK_SIZE 32768 +#define USER_TASK_PRIO 32 + +static u8 user_task_stk[USER_TASK_STK_SIZE]; + +void wasm3_task(void *data) +{ + printf("\nWasm3 v" M3_VERSION " on W600, build " __DATE__ " " __TIME__ "\n"); + + uint32_t start = millis(); + run_wasm(); + uint32_t end = millis(); + + printf("Elapsed: %ld ms\n", (end - start)); +} + +void pre_gpio_config(void) +{ + +} + +void UserMain(void) +{ + /* create task */ + tls_os_task_create(NULL, + "wasm3", + wasm3_task, + (void*) 0, + (void*) &user_task_stk, + USER_TASK_STK_SIZE, + USER_TASK_PRIO, + 0); +} diff --git a/ext/wasm3/platforms/embedded/wm_w600/wasm3 b/ext/wasm3/platforms/embedded/wm_w600/wasm3 new file mode 120000 index 0000000..03cc5a6 --- /dev/null +++ b/ext/wasm3/platforms/embedded/wm_w600/wasm3 @@ -0,0 +1 @@ +../../../source \ No newline at end of file diff --git a/ext/wasm3/platforms/emscripten/README.md b/ext/wasm3/platforms/emscripten/README.md new file mode 100644 index 0000000..d16d5bd --- /dev/null +++ b/ext/wasm3/platforms/emscripten/README.md @@ -0,0 +1,35 @@ +## Build using Emscripten + +In root: + +```sh +source /opt/emsdk/emsdk_env.sh --build=Release +mkdir -p build +cd build +cmake -GNinja -DEMSCRIPTEN=1 .. +ninja +``` + +**Note:** + +To enable WebAssembly extensions: +```sh +cmake -GNinja -DEMSCRIPTEN=1 -DWASM_EXT=1 .. +``` + +You can convert the generated wasm to wat to see the effect: +```sh +wasm2wat --enable-tail-call --enable-bulk-memory wasm3.wasm > wasm3.wat +``` + +Running `tail-call` version will require Chrome with experimental flags: +```sh +emrun --no_browser --no_emrun_detect --port 8080 . +chrome --js-flags="--experimental-wasm-return-call --wasm-opt" --no-sandbox http://localhost:8080/wasm3.html +``` + +Or use Node.js: +```sh +node --experimental-wasm-return-call --wasm-opt ./wasm3.js +``` + diff --git a/ext/wasm3/platforms/emscripten/main.c b/ext/wasm3/platforms/emscripten/main.c new file mode 100644 index 0000000..da7633f --- /dev/null +++ b/ext/wasm3/platforms/emscripten/main.c @@ -0,0 +1,65 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include +#include +#include + +#include "wasm3.h" + +#include "extra/fib32.wasm.h" + +#define FATAL(msg, ...) { printf("Fatal: " msg "\n", ##__VA_ARGS__); return; } + +void run_wasm() +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)fib32_wasm; + size_t fsize = fib32_wasm_len; + + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 64*1024, NULL); + if (!runtime) FATAL("m3_NewRuntime failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule: %s", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule: %s", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "fib"); + if (result) FATAL("m3_FindFunction: %s", result); + + result = m3_CallV (f, 40); + + if (result) FATAL("Call: %s", result); + + uint32_t value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults: %s", result); + + printf("Result: %d\n", value); +} + +int main (int i_argc, const char * i_argv []) +{ + printf("Wasm3 v" M3_VERSION " on WASM, build " __DATE__ " " __TIME__ "\n"); + + clock_t start = clock(); + run_wasm(); + clock_t end = clock(); + + uint32_t elapsed_time = (end - start)*1000 / CLOCKS_PER_SEC ; + printf("Elapsed: %d ms\n", elapsed_time); + + return 0; +} diff --git a/ext/wasm3/platforms/emscripten_lib/main.c b/ext/wasm3/platforms/emscripten_lib/main.c new file mode 100644 index 0000000..81a909a --- /dev/null +++ b/ext/wasm3/platforms/emscripten_lib/main.c @@ -0,0 +1,57 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include +#include +#include + +#include "wasm3.h" +#include "m3_env.h" + +IM3Environment env; + +EMSCRIPTEN_KEEPALIVE +void init() { + env = m3_NewEnvironment (); + if (!env) return; +} + +EMSCRIPTEN_KEEPALIVE +IM3Runtime new_runtime() { + return m3_NewRuntime (env, 64*1024, NULL); +} + +EMSCRIPTEN_KEEPALIVE +void free_runtime(IM3Runtime runtime) { + m3_FreeRuntime (runtime); +} + +EMSCRIPTEN_KEEPALIVE +void load(IM3Runtime runtime, uint8_t* wasm, size_t fsize) { + M3Result result = m3Err_none; + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) return; + + result = m3_LoadModule (runtime, module); + if (result) return; +} + +EMSCRIPTEN_KEEPALIVE +uint32_t call(IM3Runtime runtime, int argc, const char* argv[]) { + M3Result result = m3Err_none; + + IM3Function f; + result = m3_FindFunction (&f, runtime, argv[0]); + if (result) return -1; + + result = m3_CallArgv (f, argc-1, argv+1); + if (result) return -2; + + return *(uint64_t*)(runtime->stack); +} diff --git a/ext/wasm3/platforms/emscripten_lib/run_native.js b/ext/wasm3/platforms/emscripten_lib/run_native.js new file mode 100644 index 0000000..13c93d1 --- /dev/null +++ b/ext/wasm3/platforms/emscripten_lib/run_native.js @@ -0,0 +1,28 @@ +'use strict'; + +if (typeof(process) != 'undefined') { // Node.js environment? + var scriptArgs = process.argv.slice(2); + const fs = require('fs'); + var readFile = (fn) => new Uint8Array(fs.readFileSync(fn)); +} else { + var readFile = (fn) => read(fn, 'binary'); +} + +let instances = []; + +(async() => { + const wasm = scriptArgs[0]; + const func = scriptArgs[1]; + const args = scriptArgs.slice(2); + + const binary = readFile(wasm); + + for (let i=0; i<1000; i++) { // V8: 1028 max, SpiderMonkey: 32650 max + let instance = (await WebAssembly.instantiate(binary)).instance; + + instances[i] = instance; + + let result = instance.exports[func](...args); + //console.log(i, result); + } +})(); diff --git a/ext/wasm3/platforms/emscripten_lib/run_wasm3.js b/ext/wasm3/platforms/emscripten_lib/run_wasm3.js new file mode 100644 index 0000000..56a80b9 --- /dev/null +++ b/ext/wasm3/platforms/emscripten_lib/run_wasm3.js @@ -0,0 +1,129 @@ +'use strict'; + +/* + Node.js + ------- + node --v8-options | grep -A1 wasm + --print_wasm_code --code-comments + --wasm_interpret_all --trace_wasm_interpreter + + SpiderMonkey + ------------ + export PATH=/opt/jsshell/:$PATH + js --help | grep wasm + --wasm-compiler=baseline/ion/cranelift/baseline+ion/baseline+cranelift + --wasm-verbose + --ion-full-warmup-threshold=1 +*/ + +if (typeof(process) != 'undefined') { // Node.js environment? + var scriptArgs = process.argv.slice(2); + const fs = require('fs'); + var readFile = (fn) => new Uint8Array(fs.readFileSync(fn)); +} else { + var readFile = (fn) => read(fn, 'binary'); +} + + +// Encode string into Uint8Array (with '\0' terminator) +// Could use TextEncoder instead +function encode(str) { + const len = str.length; + const res = new Uint8Array(len + 1); + let pos = 0; + for (let i = 0; i < len; i++) { + const point = str.charCodeAt(i); + if (point <= 0x007f) { + res[pos++] = point; + } + } + return res.subarray(0, pos + 1); +} + +let instance; +let runtimes = {}; + +const imports = { + "env": { + "emscripten_notify_memory_growth": function() {}, + "emscripten_get_sbrk_ptr": function() {}, + }, + "wasi_snapshot_preview1": { + "fd_close": function() { return -1; }, + "fd_seek": function() { return -1; }, + "fd_write": function() { return -1; }, + "proc_exit": function() { } + } +} + +function load(buff) { + const runtime = instance.exports.new_runtime(); + const ptr = instance.exports.malloc(buff.length); + const mem = new Uint8Array(instance.exports.memory.buffer); + mem.set(buff, ptr); + instance.exports.load(runtime, ptr, buff.length); + runtimes[runtime] = { binary_ptr: ptr } + return runtime; +} + +function unload(runtime) { + if (!runtimes[runtime]) return; + instance.exports.free_runtime(runtime); + instance.exports.free(runtimes[runtime].binary_ptr); + runtimes[runtime] = undefined; +} + +function call(runtime, fname, args) { + // Convert names to buffers + args = [fname].concat(args).map(arg => encode(arg.toString())); + + const arglen = args.length; + let argbytes = arglen*4; + for (let arg of args) { + argbytes += arg.length; + } + + // Allocate the required memory + const buff = instance.exports.malloc(argbytes); + const mem = new Uint8Array(instance.exports.memory.buffer); + const ptrs = new Uint32Array(mem.buffer, buff, arglen); + + // Fill-in memory + let ptr = buff + ptrs.byteLength; + for (let i=0; i { + instance = (await WebAssembly.instantiate(readFile('wasm3.wasm'), imports)).instance; + instance.exports.init(); + + const wasm = scriptArgs[0]; + const func = scriptArgs[1]; + const args = scriptArgs.slice(2); + + const binary = readFile(wasm); + + for (let i=0; i<100000; i++) { + let module = load(binary); + + let result = call(module, func, args); + //console.log(i, result); + + unload(module); + } + + console.log(`Memory size: ${instance.exports.memory.buffer.byteLength/(1024*1024)} MB`); +})(); diff --git a/ext/wasm3/platforms/ios/.gitignore b/ext/wasm3/platforms/ios/.gitignore new file mode 100644 index 0000000..5073505 --- /dev/null +++ b/ext/wasm3/platforms/ios/.gitignore @@ -0,0 +1,2 @@ +## User settings +xcuserdata/ diff --git a/ext/wasm3/platforms/ios/README.md b/ext/wasm3/platforms/ios/README.md new file mode 100644 index 0000000..4fd1a31 --- /dev/null +++ b/ext/wasm3/platforms/ios/README.md @@ -0,0 +1,17 @@ +## Build for iOS + +


      + Wasm3 running on iPhone 8 +

      + + +Install Xcode, then open and build the project as usual. + +**Note:** Xcode runs apps in `Debug` mode by default. Select `Release` mode for significantly better performance. + +You can also build the project from command line: + +```sh +xcodebuild build -scheme wasm3 -project wasm3.xcodeproj -configuration Release -destination 'platform=iOS Simulator,name=iPhone 11,OS=13.3' +``` + diff --git a/ext/wasm3/platforms/ios/wasm3.xcodeproj/project.pbxproj b/ext/wasm3/platforms/ios/wasm3.xcodeproj/project.pbxproj new file mode 100644 index 0000000..d60e707 --- /dev/null +++ b/ext/wasm3/platforms/ios/wasm3.xcodeproj/project.pbxproj @@ -0,0 +1,459 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 48; + objects = { + +/* Begin PBXBuildFile section */ + 3D1B3B1123C8E20D00142C16 /* m3_api_libc.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3AF423C8E20C00142C16 /* m3_api_libc.c */; }; + 3D1B3B1223C8E20D00142C16 /* m3_api_meta_wasi.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3AF623C8E20C00142C16 /* m3_api_meta_wasi.c */; }; + 3D1B3B1323C8E20D00142C16 /* m3_api_wasi.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3AF723C8E20C00142C16 /* m3_api_wasi.c */; }; + 3D1B3B1423C8E20D00142C16 /* m3_bind.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3AF923C8E20C00142C16 /* m3_bind.c */; }; + 3D1B3B1523C8E20D00142C16 /* m3_code.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3AFA23C8E20C00142C16 /* m3_code.c */; }; + 3D1B3B1623C8E20D00142C16 /* m3_compile.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3AFC23C8E20C00142C16 /* m3_compile.c */; }; + 3D1B3B1723C8E20D00142C16 /* m3_core.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3B0023C8E20C00142C16 /* m3_core.c */; }; + 3D1B3B1923C8E20D00142C16 /* m3_env.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3B0423C8E20C00142C16 /* m3_env.c */; }; + 3D1B3B1A23C8E20D00142C16 /* m3_exec.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3B0723C8E20C00142C16 /* m3_exec.c */; }; + 3D1B3B1B23C8E20D00142C16 /* m3_info.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3B0A23C8E20C00142C16 /* m3_info.c */; }; + 3D1B3B1C23C8E20D00142C16 /* m3_module.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3B0D23C8E20C00142C16 /* m3_module.c */; }; + 3D1B3B1E23C8E20D00142C16 /* m3_parse.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1B3B0F23C8E20C00142C16 /* m3_parse.c */; }; + 3D1ED51023C8C8E70072E395 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D1ED50F23C8C8E70072E395 /* AppDelegate.swift */; }; + 3D1ED51223C8C8E70072E395 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D1ED51123C8C8E70072E395 /* ViewController.swift */; }; + 3D1ED51523C8C8E70072E395 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3D1ED51323C8C8E70072E395 /* Main.storyboard */; }; + 3D1ED51723C8C8E70072E395 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3D1ED51623C8C8E70072E395 /* Assets.xcassets */; }; + 3D1ED51A23C8C8E70072E395 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3D1ED51823C8C8E70072E395 /* LaunchScreen.storyboard */; }; + 3D1ED52423C8CB560072E395 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D1ED52223C8CB560072E395 /* main.c */; }; + 3D3C322E23C9319A00DB9F7E /* icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 3D3C322D23C9319A00DB9F7E /* icon.png */; }; + B5E985C8262018B700FBE0FC /* m3_function.c in Sources */ = {isa = PBXBuildFile; fileRef = B5E985C7262018B700FBE0FC /* m3_function.c */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 3D1B3AEF23C8E20C00142C16 /* coremark_minimal.wasm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = coremark_minimal.wasm.h; sourceTree = ""; }; + 3D1B3AEE23C8E20C00142C16 /* fib32.wasm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fib32.wasm.h; sourceTree = ""; }; + 3D1B3AF023C8E20C00142C16 /* fib64.wasm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fib64.wasm.h; sourceTree = ""; }; + 3D1B3AF123C8E20C00142C16 /* wasi_core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wasi_core.h; sourceTree = ""; }; + 3D1B3AF423C8E20C00142C16 /* m3_api_libc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_api_libc.c; sourceTree = ""; }; + 3D1B3AF523C8E20C00142C16 /* m3_api_libc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_api_libc.h; sourceTree = ""; }; + 3D1B3AF623C8E20C00142C16 /* m3_api_meta_wasi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_api_meta_wasi.c; sourceTree = ""; }; + 3D1B3AF723C8E20C00142C16 /* m3_api_wasi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_api_wasi.c; sourceTree = ""; }; + 3D1B3AF823C8E20C00142C16 /* m3_api_wasi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_api_wasi.h; sourceTree = ""; }; + 3D1B3AF923C8E20C00142C16 /* m3_bind.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_bind.c; sourceTree = ""; }; + 3D1B3AFA23C8E20C00142C16 /* m3_code.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_code.c; sourceTree = ""; }; + 3D1B3AFB23C8E20C00142C16 /* m3_code.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_code.h; sourceTree = ""; }; + 3D1B3AFC23C8E20C00142C16 /* m3_compile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_compile.c; sourceTree = ""; }; + 3D1B3AFD23C8E20C00142C16 /* m3_compile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_compile.h; sourceTree = ""; }; + 3D1B3AFE23C8E20C00142C16 /* m3_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_config.h; sourceTree = ""; }; + 3D1B3AFF23C8E20C00142C16 /* m3_config_platforms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_config_platforms.h; sourceTree = ""; }; + 3D1B3B0023C8E20C00142C16 /* m3_core.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_core.c; sourceTree = ""; }; + 3D1B3B0123C8E20C00142C16 /* m3_core.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_core.h; sourceTree = ""; }; + 3D1B3B0423C8E20C00142C16 /* m3_env.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_env.c; sourceTree = ""; }; + 3D1B3B0523C8E20C00142C16 /* m3_env.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_env.h; sourceTree = ""; }; + 3D1B3B0623C8E20C00142C16 /* m3_exception.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_exception.h; sourceTree = ""; }; + 3D1B3B0723C8E20C00142C16 /* m3_exec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_exec.c; sourceTree = ""; }; + 3D1B3B0823C8E20C00142C16 /* m3_exec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_exec.h; sourceTree = ""; }; + 3D1B3B0923C8E20C00142C16 /* m3_exec_defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_exec_defs.h; sourceTree = ""; }; + 3D1B3B0A23C8E20C00142C16 /* m3_info.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_info.c; sourceTree = ""; }; + 3D1B3B0B23C8E20C00142C16 /* m3_info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_info.h; sourceTree = ""; }; + 3D1B3B0C23C8E20C00142C16 /* m3_math_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_math_utils.h; sourceTree = ""; }; + 3D1B3B0D23C8E20C00142C16 /* m3_module.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_module.c; sourceTree = ""; }; + 3D1B3B0F23C8E20C00142C16 /* m3_parse.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_parse.c; sourceTree = ""; }; + 3D1ED50C23C8C8E70072E395 /* wasm3.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = wasm3.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 3D1ED50F23C8C8E70072E395 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 3D1ED51123C8C8E70072E395 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + 3D1ED51423C8C8E70072E395 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 3D1ED51623C8C8E70072E395 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 3D1ED51923C8C8E70072E395 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 3D1ED51B23C8C8E70072E395 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 3D1ED52123C8CB550072E395 /* Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = ""; }; + 3D1ED52223C8CB560072E395 /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + 3D3C322D23C9319A00DB9F7E /* icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon.png; sourceTree = ""; }; + 3D3EC19D23D558D5008FD665 /* wasm3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wasm3.h; sourceTree = ""; }; + B5E985C6262018B700FBE0FC /* m3_function.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m3_function.h; sourceTree = ""; }; + B5E985C7262018B700FBE0FC /* m3_function.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m3_function.c; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 3D1ED50923C8C8E70072E395 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 3D1B3AEC23C8E20C00142C16 /* source */ = { + isa = PBXGroup; + children = ( + B5E985C7262018B700FBE0FC /* m3_function.c */, + B5E985C6262018B700FBE0FC /* m3_function.h */, + 3D1B3AED23C8E20C00142C16 /* extra */, + 3D3EC19D23D558D5008FD665 /* wasm3.h */, + 3D1B3AF423C8E20C00142C16 /* m3_api_libc.c */, + 3D1B3AF523C8E20C00142C16 /* m3_api_libc.h */, + 3D1B3AF623C8E20C00142C16 /* m3_api_meta_wasi.c */, + 3D1B3AF723C8E20C00142C16 /* m3_api_wasi.c */, + 3D1B3AF823C8E20C00142C16 /* m3_api_wasi.h */, + 3D1B3AF923C8E20C00142C16 /* m3_bind.c */, + 3D1B3AFA23C8E20C00142C16 /* m3_code.c */, + 3D1B3AFB23C8E20C00142C16 /* m3_code.h */, + 3D1B3AFC23C8E20C00142C16 /* m3_compile.c */, + 3D1B3AFD23C8E20C00142C16 /* m3_compile.h */, + 3D1B3AFE23C8E20C00142C16 /* m3_config.h */, + 3D1B3AFF23C8E20C00142C16 /* m3_config_platforms.h */, + 3D1B3B0023C8E20C00142C16 /* m3_core.c */, + 3D1B3B0123C8E20C00142C16 /* m3_core.h */, + 3D1B3B0423C8E20C00142C16 /* m3_env.c */, + 3D1B3B0523C8E20C00142C16 /* m3_env.h */, + 3D1B3B0623C8E20C00142C16 /* m3_exception.h */, + 3D1B3B0723C8E20C00142C16 /* m3_exec.c */, + 3D1B3B0823C8E20C00142C16 /* m3_exec.h */, + 3D1B3B0923C8E20C00142C16 /* m3_exec_defs.h */, + 3D1B3B0A23C8E20C00142C16 /* m3_info.c */, + 3D1B3B0B23C8E20C00142C16 /* m3_info.h */, + 3D1B3B0C23C8E20C00142C16 /* m3_math_utils.h */, + 3D1B3B0D23C8E20C00142C16 /* m3_module.c */, + 3D1B3B0F23C8E20C00142C16 /* m3_parse.c */, + ); + name = source; + path = ../../source; + sourceTree = SOURCE_ROOT; + }; + 3D1B3AED23C8E20C00142C16 /* extra */ = { + isa = PBXGroup; + children = ( + 3D1B3AEF23C8E20C00142C16 /* coremark_minimal.wasm.h */, + 3D1B3AEE23C8E20C00142C16 /* fib32.wasm.h */, + 3D1B3AF023C8E20C00142C16 /* fib64.wasm.h */, + 3D1B3AF123C8E20C00142C16 /* wasi_core.h */, + ); + path = extra; + sourceTree = ""; + }; + 3D1ED50323C8C8E70072E395 = { + isa = PBXGroup; + children = ( + 3D1ED50E23C8C8E70072E395 /* wasm3 */, + 3D1ED50D23C8C8E70072E395 /* Products */, + ); + sourceTree = ""; + }; + 3D1ED50D23C8C8E70072E395 /* Products */ = { + isa = PBXGroup; + children = ( + 3D1ED50C23C8C8E70072E395 /* wasm3.app */, + ); + name = Products; + sourceTree = ""; + }; + 3D1ED50E23C8C8E70072E395 /* wasm3 */ = { + isa = PBXGroup; + children = ( + 3D1B3AEC23C8E20C00142C16 /* source */, + 3D1ED50F23C8C8E70072E395 /* AppDelegate.swift */, + 3D1ED51123C8C8E70072E395 /* ViewController.swift */, + 3D1ED51323C8C8E70072E395 /* Main.storyboard */, + 3D1ED51623C8C8E70072E395 /* Assets.xcassets */, + 3D1ED51823C8C8E70072E395 /* LaunchScreen.storyboard */, + 3D1ED51B23C8C8E70072E395 /* Info.plist */, + 3D1ED52223C8CB560072E395 /* main.c */, + 3D3C322D23C9319A00DB9F7E /* icon.png */, + 3D1ED52123C8CB550072E395 /* Bridging-Header.h */, + ); + path = wasm3; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 3D1ED50B23C8C8E70072E395 /* wasm3 */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3D1ED51E23C8C8E70072E395 /* Build configuration list for PBXNativeTarget "wasm3" */; + buildPhases = ( + 3D1ED50823C8C8E70072E395 /* Sources */, + 3D1ED50923C8C8E70072E395 /* Frameworks */, + 3D1ED50A23C8C8E70072E395 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = wasm3; + productName = wasm3; + productReference = 3D1ED50C23C8C8E70072E395 /* wasm3.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 3D1ED50423C8C8E70072E395 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0900; + LastUpgradeCheck = 1130; + ORGANIZATIONNAME = wasm3; + TargetAttributes = { + 3D1ED50B23C8C8E70072E395 = { + CreatedOnToolsVersion = 9.0.1; + LastSwiftMigration = 0900; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 3D1ED50723C8C8E70072E395 /* Build configuration list for PBXProject "wasm3" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 3D1ED50323C8C8E70072E395; + productRefGroup = 3D1ED50D23C8C8E70072E395 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 3D1ED50B23C8C8E70072E395 /* wasm3 */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 3D1ED50A23C8C8E70072E395 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3D1ED51A23C8C8E70072E395 /* LaunchScreen.storyboard in Resources */, + 3D3C322E23C9319A00DB9F7E /* icon.png in Resources */, + 3D1ED51723C8C8E70072E395 /* Assets.xcassets in Resources */, + 3D1ED51523C8C8E70072E395 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 3D1ED50823C8C8E70072E395 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 3D1B3B1323C8E20D00142C16 /* m3_api_wasi.c in Sources */, + 3D1B3B1123C8E20D00142C16 /* m3_api_libc.c in Sources */, + 3D1B3B1723C8E20D00142C16 /* m3_core.c in Sources */, + B5E985C8262018B700FBE0FC /* m3_function.c in Sources */, + 3D1ED51223C8C8E70072E395 /* ViewController.swift in Sources */, + 3D1B3B1A23C8E20D00142C16 /* m3_exec.c in Sources */, + 3D1B3B1223C8E20D00142C16 /* m3_api_meta_wasi.c in Sources */, + 3D1B3B1523C8E20D00142C16 /* m3_code.c in Sources */, + 3D1B3B1423C8E20D00142C16 /* m3_bind.c in Sources */, + 3D1B3B1C23C8E20D00142C16 /* m3_module.c in Sources */, + 3D1B3B1B23C8E20D00142C16 /* m3_info.c in Sources */, + 3D1ED51023C8C8E70072E395 /* AppDelegate.swift in Sources */, + 3D1B3B1923C8E20D00142C16 /* m3_env.c in Sources */, + 3D1B3B1623C8E20D00142C16 /* m3_compile.c in Sources */, + 3D1ED52423C8CB560072E395 /* main.c in Sources */, + 3D1B3B1E23C8E20D00142C16 /* m3_parse.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 3D1ED51323C8C8E70072E395 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 3D1ED51423C8C8E70072E395 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 3D1ED51823C8C8E70072E395 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 3D1ED51923C8C8E70072E395 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 3D1ED51C23C8C8E70072E395 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_CFLAGS = ""; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 3D1ED51D23C8C8E70072E395 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 3; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CFLAGS = "-fomit-frame-pointer"; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 3D1ED51F23C8C8E70072E395 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = wasm3/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.wasm3; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "wasm3/Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 3D1ED52023C8C8E70072E395 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + HEADER_SEARCH_PATHS = ""; + INFOPLIST_FILE = wasm3/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = com.wasm3; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "wasm3/Bridging-Header.h"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 3D1ED50723C8C8E70072E395 /* Build configuration list for PBXProject "wasm3" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3D1ED51C23C8C8E70072E395 /* Debug */, + 3D1ED51D23C8C8E70072E395 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3D1ED51E23C8C8E70072E395 /* Build configuration list for PBXNativeTarget "wasm3" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3D1ED51F23C8C8E70072E395 /* Debug */, + 3D1ED52023C8C8E70072E395 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 3D1ED50423C8C8E70072E395 /* Project object */; +} diff --git a/ext/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ext/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..b90c664 --- /dev/null +++ b/ext/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ext/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ext/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ext/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ext/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ext/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..0c67376 --- /dev/null +++ b/ext/wasm3/platforms/ios/wasm3.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,5 @@ + + + + + diff --git a/ext/wasm3/platforms/ios/wasm3.xcodeproj/xcshareddata/xcschemes/wasm3 Release.xcscheme b/ext/wasm3/platforms/ios/wasm3.xcodeproj/xcshareddata/xcschemes/wasm3 Release.xcscheme new file mode 100644 index 0000000..f65f4f6 --- /dev/null +++ b/ext/wasm3/platforms/ios/wasm3.xcodeproj/xcshareddata/xcschemes/wasm3 Release.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/wasm3/platforms/ios/wasm3.xcodeproj/xcshareddata/xcschemes/wasm3.xcscheme b/ext/wasm3/platforms/ios/wasm3.xcodeproj/xcshareddata/xcschemes/wasm3.xcscheme new file mode 100644 index 0000000..d925f22 --- /dev/null +++ b/ext/wasm3/platforms/ios/wasm3.xcodeproj/xcshareddata/xcschemes/wasm3.xcscheme @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/wasm3/platforms/ios/wasm3/AppDelegate.swift b/ext/wasm3/platforms/ios/wasm3/AppDelegate.swift new file mode 100644 index 0000000..99e5823 --- /dev/null +++ b/ext/wasm3/platforms/ios/wasm3/AppDelegate.swift @@ -0,0 +1,46 @@ +// +// AppDelegate.swift +// wasm3 +// +// Created by Volodymyr Shymanskyy on 1/10/20. +// Copyright © 2020 wasm3. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } + + func applicationWillResignActive(_ application: UIApplication) { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. + } + + func applicationDidEnterBackground(_ application: UIApplication) { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(_ application: UIApplication) { + // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. + } + + func applicationDidBecomeActive(_ application: UIApplication) { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + } + + func applicationWillTerminate(_ application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + } + + +} + diff --git a/ext/wasm3/platforms/ios/wasm3/Assets.xcassets/AppIcon.appiconset/Contents.json b/ext/wasm3/platforms/ios/wasm3/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d8db8d6 --- /dev/null +++ b/ext/wasm3/platforms/ios/wasm3/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/ext/wasm3/platforms/ios/wasm3/Base.lproj/LaunchScreen.storyboard b/ext/wasm3/platforms/ios/wasm3/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..438943d --- /dev/null +++ b/ext/wasm3/platforms/ios/wasm3/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/wasm3/platforms/ios/wasm3/Base.lproj/Main.storyboard b/ext/wasm3/platforms/ios/wasm3/Base.lproj/Main.storyboard new file mode 100644 index 0000000..280c7f8 --- /dev/null +++ b/ext/wasm3/platforms/ios/wasm3/Base.lproj/Main.storyboard @@ -0,0 +1,55 @@ + + + + + + + + + + + + + Menlo-Regular + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/wasm3/platforms/ios/wasm3/Bridging-Header.h b/ext/wasm3/platforms/ios/wasm3/Bridging-Header.h new file mode 100644 index 0000000..efa8f80 --- /dev/null +++ b/ext/wasm3/platforms/ios/wasm3/Bridging-Header.h @@ -0,0 +1,8 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +typedef void (*print_cbk_t)(const char* buff, int len); + +void redirect_output (print_cbk_t f); +int run_app (void); diff --git a/ext/wasm3/platforms/ios/wasm3/Info.plist b/ext/wasm3/platforms/ios/wasm3/Info.plist new file mode 100644 index 0000000..d67a26c --- /dev/null +++ b/ext/wasm3/platforms/ios/wasm3/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleIconFiles + + logo.png + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 0.1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/ext/wasm3/platforms/ios/wasm3/ViewController.swift b/ext/wasm3/platforms/ios/wasm3/ViewController.swift new file mode 100644 index 0000000..77b1b43 --- /dev/null +++ b/ext/wasm3/platforms/ios/wasm3/ViewController.swift @@ -0,0 +1,41 @@ +// +// ViewController.swift +// wasm3 +// +// Created by Volodymyr Shymanskyy on 1/10/20. +// Copyright © 2020 wasm3. All rights reserved. +// + +import UIKit + +var gLog: UITextView! + +class ViewController: UIViewController { + + // MARK: Properties + @IBOutlet var log: UITextView! + + override func viewDidLoad() { + super.viewDidLoad() + + gLog = log + + redirect_output({ + if let ptr = $0 { + let data = Data(bytes: ptr, count: Int($1)) + if let str = String(data: data, encoding: String.Encoding.utf8) { + DispatchQueue.main.async { + gLog.text += str + } + } + } + }) + + run_app() + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + } +} + diff --git a/ext/wasm3/platforms/ios/wasm3/icon.png b/ext/wasm3/platforms/ios/wasm3/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..85c1d0671735930948c7d9ec7d6dd0faee35e11e GIT binary patch literal 3769 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 literal 0 HcmV?d00001 diff --git a/ext/wasm3/platforms/ios/wasm3/main.c b/ext/wasm3/platforms/ios/wasm3/main.c new file mode 100644 index 0000000..bcbfa8c --- /dev/null +++ b/ext/wasm3/platforms/ios/wasm3/main.c @@ -0,0 +1,117 @@ +// +// Wasm3 - high performance WebAssembly interpreter written in C. +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wasm3.h" +#include "m3_config.h" +#include "m3_api_libc.h" + +#include "coremark_minimal.wasm.h" + +#define FATAL(msg, ...) { printf("Fatal: " msg "\n", ##__VA_ARGS__); return; } + +void run_wasm() +{ + M3Result result = m3Err_none; + + uint8_t* wasm = (uint8_t*)coremark_minimal_wasm; + size_t fsize = coremark_minimal_wasm_len; + + printf("Loading WebAssembly...\n"); + + IM3Environment env = m3_NewEnvironment (); + if (!env) FATAL("m3_NewEnvironment failed"); + + IM3Runtime runtime = m3_NewRuntime (env, 8192, NULL); + if (!runtime) FATAL("m3_NewRuntime failed"); + + IM3Module module; + result = m3_ParseModule (env, &module, wasm, fsize); + if (result) FATAL("m3_ParseModule: %s", result); + + result = m3_LoadModule (runtime, module); + if (result) FATAL("m3_LoadModule: %s", result); + + result = m3_LinkLibC (module); + if (result) FATAL("m3_LinkLibC: %s", result); + + IM3Function f; + result = m3_FindFunction (&f, runtime, "run"); + if (result) FATAL("m3_FindFunction: %s", result); + + printf("Running CoreMark 1.0...\n"); + + result = m3_CallV (f); + if (result) FATAL("m3_Call: %s", result); + + float value = 0; + result = m3_GetResultsV (f, &value); + if (result) FATAL("m3_GetResults: %s", result); + + printf("Result: %0.3f\n", value); +} + +static void* runMain(void* ctx) +{ + struct utsname systemInfo; + uname(&systemInfo); + + printf("Wasm3 v" M3_VERSION " on iOS (" M3_ARCH ")\n"); + printf("Build " __DATE__ " " __TIME__ "\n"); + printf("Device: %s\n\n", systemInfo.machine); + + run_wasm(); + + return 0; +} + +// +// Swift Bridging +// + +#include "Bridging-Header.h" + +static print_cbk_t gPrintFunc; + +static int stdout_redirect(void* prefix, const char* buffer, int size) +{ + if (gPrintFunc) + gPrintFunc(buffer, size); + return size; +} + +void redirect_output(print_cbk_t f) +{ + gPrintFunc = f; + + setvbuf(stdout, 0, _IOLBF, 0); // stdout: line-buffered + setvbuf(stderr, 0, _IONBF, 0); // stderr: unbuffered + + stdout->_write = stdout_redirect; + stderr->_write = stdout_redirect; +} + +int run_app() +{ + mlockall(MCL_CURRENT | MCL_FUTURE); + static pthread_t mainThread; + pthread_attr_t threadAttr; + pthread_attr_init(&threadAttr); + pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED); + pthread_create(&mainThread, &threadAttr, runMain, NULL); + pthread_attr_destroy(&threadAttr); + return 0; +} + diff --git a/ext/wasm3/platforms/openwrt/README.md b/ext/wasm3/platforms/openwrt/README.md new file mode 100644 index 0000000..70dd8c3 --- /dev/null +++ b/ext/wasm3/platforms/openwrt/README.md @@ -0,0 +1,6 @@ +# wasm3 for OpenWrt + +You can find `wasm3` package and build instructions here: + +https://github.com/wasm3/wasm3-openwrt-packages + diff --git a/ext/wasm3/platforms/openwrt/build/Makefile b/ext/wasm3/platforms/openwrt/build/Makefile new file mode 100644 index 0000000..6ef904d --- /dev/null +++ b/ext/wasm3/platforms/openwrt/build/Makefile @@ -0,0 +1,15 @@ + +M3_SRC_DIR := ../../../source + +SOURCES := ../../app/main.c \ + $(shell find $(M3_SRC_DIR) -type f -name '*.c') + +override CFLAGS += -std=c99 -O3 -flto -Dd_m3HasWASI -Wno-error=format-security -Wfatal-errors -I$(M3_SRC_DIR) + +all: wasm3 + +wasm3: $(SOURCES) + $(CC) $(CFLAGS) $(SOURCES) -o wasm3 -lm + +clean: + $(RM) wasm3 diff --git a/ext/wasm3/platforms/python/README.md b/ext/wasm3/platforms/python/README.md new file mode 100644 index 0000000..38b89df --- /dev/null +++ b/ext/wasm3/platforms/python/README.md @@ -0,0 +1,5 @@ +# pywasm3 + +Python binding for Wasm3, the fastest WebAssembly interpreter. + +## Moved to https://github.com/wasm3/pywasm3 diff --git a/ext/wasm3/source/CMakeLists.txt b/ext/wasm3/source/CMakeLists.txt new file mode 100644 index 0000000..ecfd40b --- /dev/null +++ b/ext/wasm3/source/CMakeLists.txt @@ -0,0 +1,55 @@ +set(sources + "m3_api_libc.c" + "m3_api_wasi.c" + "m3_api_uvwasi.c" + "m3_api_meta_wasi.c" + "m3_api_tracer.c" + "m3_bind.c" + "m3_code.c" + "m3_compile.c" + "m3_core.c" + "m3_env.c" + "m3_exec.c" + "m3_function.c" + "m3_info.c" + "m3_module.c" + "m3_parse.c" +) + +add_library(m3 STATIC ${sources}) + +target_include_directories(m3 PUBLIC .) + +target_compile_features(m3 PRIVATE c_std_99) + +if (CMAKE_C_COMPILER_ID MATCHES "MSVC") + # add MSVC specific flags here +else() + # Flags common for GCC and Clang + + + # FIXME: comparison of integers of different signs: 'u32' and 'i32' + set_source_files_properties(m3_env.c PROPERTIES COMPILE_FLAGS -Wno-sign-compare) + + if (WASIENV) + # FIXME: declaration of 'struct sigaction' will not be visible outside of this function + target_compile_options(m3 PUBLIC -Wno-visibility) + # FIXME incompatible pointer types passing 'u32 *' to parameter of type 'char **' + set_source_files_properties(m3_api_meta_wasi.c PROPERTIES COMPILE_FLAGS -Wno-incompatible-pointer-types) + endif() + + if (CMAKE_C_COMPILER_ID MATCHES "Clang") + # Clang specific flags here + else() + # GCC specific flags here + endif() +endif() + +if(BUILD_WASI MATCHES "simple") + target_compile_definitions(m3 PUBLIC d_m3HasWASI) +elseif(BUILD_WASI MATCHES "metawasi") + target_compile_definitions(m3 PUBLIC d_m3HasMetaWASI) +elseif(BUILD_WASI MATCHES "uvwasi") + target_compile_definitions(m3 PUBLIC d_m3HasUVWASI) + include_directories("${libuv_SOURCE_DIR}/include") +endif() diff --git a/ext/wasm3/source/extensions/m3_extensions.c b/ext/wasm3/source/extensions/m3_extensions.c new file mode 100644 index 0000000..17ba6ee --- /dev/null +++ b/ext/wasm3/source/extensions/m3_extensions.c @@ -0,0 +1,112 @@ +// +// m3_extensions.c +// +// Created by Steven Massey on 3/30/21. +// Copyright © 2021 Steven Massey. All rights reserved. +// + +#include "wasm3_ext.h" + +#include "m3_env.h" +#include "m3_bind.h" +#include "m3_exception.h" + + +IM3Module m3_NewModule (IM3Environment i_environment) +{ + IM3Module module = m3_AllocStruct (M3Module); + + if (module) + { + module->name = ".unnamed"; + module->startFunction = -1; + module->environment = i_environment; + + module->wasmStart = NULL; + module->wasmEnd = NULL; + } + + return module; +} + + + +M3Result m3_InjectFunction (IM3Module i_module, + int32_t * io_functionIndex, + const char * const i_signature, + const uint8_t * const i_wasmBytes, + bool i_doCompilation) +{ + M3Result result = m3Err_none; d_m3Assert (io_functionIndex); + + IM3Function function = NULL; + IM3FuncType ftype = NULL; +_ (SignatureToFuncType (& ftype, i_signature)); + + i32 index = * io_functionIndex; + + bytes_t bytes = i_wasmBytes; + bytes_t end = i_wasmBytes + 5; + + u32 size; +_ (ReadLEB_u32 (& size, & bytes, end)); + end = bytes + size; + + if (index >= 0) + { + _throwif ("function index out of bounds", index >= i_module->numFunctions); + + function = & i_module->functions [index]; + + if (not AreFuncTypesEqual (ftype, function->funcType)) + _throw ("function type mismatch"); + } + else + { + // add slot to function type table in the module + u32 funcTypeIndex = i_module->numFuncTypes++; + i_module->funcTypes = m3_ReallocArray (IM3FuncType, i_module->funcTypes, i_module->numFuncTypes, funcTypeIndex); + _throwifnull (i_module->funcTypes); + + // add functype object to the environment + Environment_AddFuncType (i_module->environment, & ftype); + i_module->funcTypes [funcTypeIndex] = ftype; + ftype = NULL; // prevent freeing below + + index = (i32) i_module->numFunctions; +_ (Module_AddFunction (i_module, funcTypeIndex, NULL)); + function = Module_GetFunction (i_module, index); + + * io_functionIndex = index; + } + + function->compiled = NULL; + + if (function->ownsWasmCode) + m3_Free (function->wasm); + + size_t numBytes = end - i_wasmBytes; + function->wasm = m3_CopyMem (i_wasmBytes, numBytes); + _throwifnull (function->wasm); + + function->wasmEnd = function->wasm + numBytes; + function->ownsWasmCode = true; + + function->module = i_module; + + if (i_doCompilation and not i_module->runtime) + _throw ("module must be loaded into runtime to compile function"); + +_ (CompileFunction (function)); + + _catch: + m3_Free (ftype); + + return result; +} + + +IM3Function m3_GetFunctionByIndex (IM3Module i_module, uint32_t i_index) +{ + return Module_GetFunction (i_module, i_index); +} diff --git a/ext/wasm3/source/extensions/wasm3_ext.h b/ext/wasm3/source/extensions/wasm3_ext.h new file mode 100644 index 0000000..2de1fc3 --- /dev/null +++ b/ext/wasm3/source/extensions/wasm3_ext.h @@ -0,0 +1,51 @@ +// +// Wasm3, high performance WebAssembly interpreter +// +// Extensions +// +// Copyright © 2019-2021 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#ifndef wasm3_ext_h +#define wasm3_ext_h + +#include "wasm3.h" +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +//------------------------------------------------------------------------------------------------------------------------------- +// API extensions +//------------------------------------------------------------------------------------------------------------------------------- +/* + These extensions allow for unconventional uses of Wasm3 -- mainly dynamic modification of modules to inject new Wasm + functions during runtime. +*/ +//------------------------------------------------------------------------------------------------------------------------------- + + // Creates an empty module. + IM3Module m3_NewModule (IM3Environment i_environment); + + + // To append a new function, set io_functionIndex to negative. On return, the new function index will be set. + // To overwrite an existing function, set io_functionIndex to the desired element. i_signature must match the existing + // function signature. + // ** InjectFunction invalidates any existing IM3Function pointers + M3Result m3_InjectFunction (IM3Module i_module, + int32_t * io_functionIndex, + const char * const i_signature, + const uint8_t * const i_wasmBytes, // i_wasmBytes is copied + bool i_doCompilation); + + + IM3Function m3_GetFunctionByIndex (IM3Module i_module, + uint32_t i_index); + +#if defined(__cplusplus) +} +#endif + +#endif // wasm3_h diff --git a/ext/wasm3/source/extra/coremark_minimal.wasm.h b/ext/wasm3/source/extra/coremark_minimal.wasm.h new file mode 100644 index 0000000..cf5aba8 --- /dev/null +++ b/ext/wasm3/source/extra/coremark_minimal.wasm.h @@ -0,0 +1,651 @@ +unsigned char coremark_minimal_wasm[] = { + 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x3e, 0x0a, 0x60, + 0x02, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x00, 0x60, 0x02, 0x7f, 0x7f, + 0x00, 0x60, 0x03, 0x7f, 0x7f, 0x7f, 0x00, 0x60, 0x04, 0x7f, 0x7f, 0x7f, + 0x7f, 0x00, 0x60, 0x00, 0x01, 0x7f, 0x60, 0x03, 0x7f, 0x7f, 0x7f, 0x01, + 0x7f, 0x60, 0x05, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x06, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x00, 0x01, 0x7d, + 0x02, 0x10, 0x01, 0x03, 0x65, 0x6e, 0x76, 0x08, 0x63, 0x6c, 0x6f, 0x63, + 0x6b, 0x5f, 0x6d, 0x73, 0x00, 0x05, 0x03, 0x10, 0x0f, 0x00, 0x00, 0x06, + 0x09, 0x07, 0x04, 0x08, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x01, 0x01, + 0x05, 0x03, 0x01, 0x00, 0x01, 0x06, 0x07, 0x01, 0x7f, 0x01, 0x41, 0x80, + 0x04, 0x0b, 0x07, 0x10, 0x02, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, + 0x02, 0x00, 0x03, 0x72, 0x75, 0x6e, 0x00, 0x04, 0x0a, 0x82, 0x39, 0x0f, + 0xdb, 0x01, 0x01, 0x04, 0x7f, 0x20, 0x00, 0x2f, 0x01, 0x00, 0x22, 0x03, + 0x41, 0x80, 0x01, 0x71, 0x04, 0x40, 0x20, 0x03, 0x41, 0xff, 0x00, 0x71, + 0x0f, 0x0b, 0x20, 0x03, 0x41, 0x03, 0x76, 0x41, 0x0f, 0x71, 0x22, 0x02, + 0x41, 0x04, 0x74, 0x20, 0x02, 0x72, 0x21, 0x04, 0x02, 0x40, 0x02, 0x40, + 0x02, 0x40, 0x20, 0x03, 0x22, 0x02, 0x41, 0x07, 0x71, 0x0e, 0x02, 0x00, + 0x01, 0x02, 0x0b, 0x20, 0x01, 0x28, 0x02, 0x18, 0x20, 0x01, 0x41, 0x14, + 0x6a, 0x28, 0x02, 0x00, 0x20, 0x01, 0x2e, 0x01, 0x00, 0x20, 0x01, 0x2e, + 0x01, 0x02, 0x20, 0x04, 0x41, 0x22, 0x20, 0x04, 0x41, 0x22, 0x4b, 0x1b, + 0x20, 0x01, 0x2f, 0x01, 0x38, 0x10, 0x07, 0x21, 0x02, 0x20, 0x01, 0x2f, + 0x01, 0x3e, 0x0d, 0x01, 0x20, 0x01, 0x20, 0x02, 0x3b, 0x01, 0x3e, 0x0c, + 0x01, 0x0b, 0x20, 0x01, 0x2f, 0x01, 0x38, 0x21, 0x02, 0x20, 0x01, 0x41, + 0x28, 0x6a, 0x22, 0x05, 0x28, 0x02, 0x00, 0x20, 0x05, 0x28, 0x02, 0x0c, + 0x20, 0x05, 0x28, 0x02, 0x04, 0x20, 0x05, 0x28, 0x02, 0x08, 0x20, 0x04, + 0x10, 0x05, 0x20, 0x02, 0x10, 0x0c, 0x21, 0x02, 0x20, 0x01, 0x2f, 0x01, + 0x3c, 0x0d, 0x00, 0x20, 0x01, 0x20, 0x02, 0x3b, 0x01, 0x3c, 0x0b, 0x20, + 0x01, 0x20, 0x02, 0x20, 0x01, 0x2f, 0x01, 0x38, 0x10, 0x0a, 0x3b, 0x01, + 0x38, 0x20, 0x00, 0x20, 0x02, 0x41, 0xff, 0x00, 0x71, 0x22, 0x00, 0x20, + 0x03, 0x41, 0x80, 0xfe, 0x03, 0x71, 0x72, 0x41, 0x80, 0x01, 0x72, 0x3b, + 0x01, 0x00, 0x20, 0x00, 0x0b, 0x97, 0x0a, 0x01, 0x10, 0x7f, 0x20, 0x00, + 0x28, 0x02, 0x24, 0x21, 0x04, 0x02, 0x7f, 0x20, 0x00, 0x2e, 0x01, 0x04, + 0x22, 0x0b, 0x41, 0x01, 0x48, 0x04, 0x40, 0x20, 0x01, 0x21, 0x09, 0x41, + 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x01, 0x21, 0x09, 0x03, 0x40, 0x20, 0x04, + 0x21, 0x03, 0x02, 0x40, 0x02, 0x40, 0x20, 0x09, 0x41, 0x10, 0x74, 0x41, + 0x10, 0x75, 0x41, 0x7f, 0x4a, 0x04, 0x40, 0x03, 0x40, 0x20, 0x03, 0x28, + 0x02, 0x04, 0x2f, 0x01, 0x02, 0x20, 0x09, 0x41, 0xff, 0xff, 0x03, 0x71, + 0x46, 0x0d, 0x03, 0x20, 0x03, 0x28, 0x02, 0x00, 0x22, 0x03, 0x0d, 0x00, + 0x0b, 0x0c, 0x01, 0x0b, 0x03, 0x40, 0x20, 0x03, 0x28, 0x02, 0x04, 0x2d, + 0x00, 0x00, 0x20, 0x06, 0x41, 0xff, 0x01, 0x71, 0x73, 0x45, 0x0d, 0x02, + 0x20, 0x03, 0x28, 0x02, 0x00, 0x22, 0x03, 0x0d, 0x00, 0x0b, 0x0b, 0x41, + 0x00, 0x21, 0x03, 0x0b, 0x02, 0x40, 0x20, 0x04, 0x45, 0x04, 0x40, 0x41, + 0x00, 0x21, 0x04, 0x0c, 0x01, 0x0b, 0x41, 0x00, 0x21, 0x05, 0x20, 0x04, + 0x21, 0x02, 0x03, 0x40, 0x20, 0x02, 0x22, 0x04, 0x28, 0x02, 0x00, 0x21, + 0x02, 0x20, 0x04, 0x20, 0x05, 0x36, 0x02, 0x00, 0x20, 0x04, 0x21, 0x05, + 0x20, 0x02, 0x0d, 0x00, 0x0b, 0x0b, 0x02, 0x40, 0x20, 0x03, 0x45, 0x04, + 0x40, 0x20, 0x0e, 0x41, 0x01, 0x6a, 0x21, 0x0e, 0x20, 0x04, 0x28, 0x02, + 0x00, 0x28, 0x02, 0x04, 0x2d, 0x00, 0x01, 0x41, 0x01, 0x71, 0x20, 0x0d, + 0x6a, 0x21, 0x0d, 0x0c, 0x01, 0x0b, 0x20, 0x0f, 0x41, 0x01, 0x6a, 0x21, + 0x0f, 0x20, 0x03, 0x28, 0x02, 0x04, 0x2f, 0x01, 0x00, 0x22, 0x02, 0x41, + 0x09, 0x76, 0x20, 0x02, 0x71, 0x41, 0x01, 0x71, 0x20, 0x0d, 0x6a, 0x21, + 0x0d, 0x20, 0x03, 0x28, 0x02, 0x00, 0x22, 0x02, 0x45, 0x0d, 0x00, 0x20, + 0x03, 0x20, 0x02, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, 0x02, 0x20, + 0x04, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, 0x04, 0x20, 0x02, 0x36, + 0x02, 0x00, 0x0b, 0x20, 0x09, 0x41, 0x7f, 0x73, 0x41, 0x80, 0x80, 0x02, + 0x71, 0x41, 0x0f, 0x76, 0x20, 0x09, 0x6a, 0x21, 0x09, 0x20, 0x06, 0x41, + 0x10, 0x74, 0x41, 0x80, 0x80, 0x04, 0x6a, 0x41, 0x10, 0x75, 0x22, 0x06, + 0x20, 0x0b, 0x48, 0x0d, 0x00, 0x0b, 0x20, 0x0b, 0x41, 0x7f, 0x6a, 0x41, + 0xff, 0x01, 0x71, 0x0b, 0x21, 0x10, 0x02, 0x40, 0x02, 0x40, 0x20, 0x01, + 0x41, 0x01, 0x48, 0x0d, 0x00, 0x41, 0x01, 0x21, 0x0a, 0x03, 0x40, 0x20, + 0x0a, 0x41, 0x01, 0x48, 0x0d, 0x02, 0x41, 0x00, 0x21, 0x0c, 0x41, 0x00, + 0x21, 0x06, 0x20, 0x04, 0x21, 0x02, 0x41, 0x00, 0x21, 0x04, 0x03, 0x40, + 0x20, 0x0c, 0x22, 0x11, 0x41, 0x01, 0x6a, 0x21, 0x0c, 0x41, 0x00, 0x21, + 0x03, 0x20, 0x02, 0x21, 0x05, 0x02, 0x7f, 0x02, 0x40, 0x03, 0x40, 0x20, + 0x05, 0x28, 0x02, 0x00, 0x22, 0x05, 0x45, 0x0d, 0x01, 0x20, 0x0a, 0x20, + 0x03, 0x41, 0x01, 0x6a, 0x22, 0x03, 0x47, 0x0d, 0x00, 0x0b, 0x20, 0x0a, + 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x41, 0x01, 0x6a, 0x0b, 0x21, 0x08, 0x20, + 0x02, 0x21, 0x03, 0x20, 0x05, 0x21, 0x02, 0x20, 0x0a, 0x21, 0x07, 0x03, + 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x7f, 0x02, 0x40, 0x02, 0x7f, 0x02, + 0x40, 0x20, 0x08, 0x41, 0x00, 0x4a, 0x0d, 0x00, 0x20, 0x02, 0x45, 0x0d, + 0x04, 0x20, 0x07, 0x41, 0x01, 0x48, 0x0d, 0x04, 0x20, 0x08, 0x0d, 0x00, + 0x20, 0x07, 0x41, 0x7f, 0x6a, 0x21, 0x07, 0x41, 0x00, 0x21, 0x08, 0x20, + 0x02, 0x28, 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x02, 0x45, 0x0d, 0x01, + 0x20, 0x07, 0x45, 0x0d, 0x01, 0x20, 0x02, 0x28, 0x02, 0x04, 0x21, 0x01, + 0x20, 0x03, 0x28, 0x02, 0x04, 0x20, 0x00, 0x10, 0x01, 0x41, 0xff, 0xff, + 0x03, 0x71, 0x20, 0x01, 0x20, 0x00, 0x10, 0x01, 0x41, 0xff, 0xff, 0x03, + 0x71, 0x4d, 0x0d, 0x01, 0x20, 0x07, 0x41, 0x7f, 0x6a, 0x21, 0x07, 0x20, + 0x02, 0x28, 0x02, 0x00, 0x0b, 0x21, 0x01, 0x20, 0x03, 0x21, 0x0b, 0x20, + 0x02, 0x0c, 0x01, 0x0b, 0x20, 0x08, 0x41, 0x7f, 0x6a, 0x21, 0x08, 0x20, + 0x03, 0x28, 0x02, 0x00, 0x21, 0x0b, 0x20, 0x02, 0x21, 0x01, 0x20, 0x03, + 0x0b, 0x21, 0x05, 0x20, 0x06, 0x45, 0x04, 0x40, 0x20, 0x05, 0x21, 0x04, + 0x0c, 0x02, 0x0b, 0x20, 0x06, 0x20, 0x05, 0x36, 0x02, 0x00, 0x0c, 0x01, + 0x0b, 0x20, 0x02, 0x0d, 0x02, 0x20, 0x06, 0x41, 0x00, 0x36, 0x02, 0x00, + 0x20, 0x0a, 0x41, 0x01, 0x74, 0x21, 0x0a, 0x20, 0x11, 0x0d, 0x03, 0x0c, + 0x04, 0x0b, 0x20, 0x0b, 0x21, 0x03, 0x20, 0x01, 0x21, 0x02, 0x20, 0x05, + 0x21, 0x06, 0x0c, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x20, + 0x0f, 0x41, 0x02, 0x74, 0x20, 0x0e, 0x6b, 0x20, 0x0d, 0x6a, 0x21, 0x0c, + 0x20, 0x04, 0x28, 0x02, 0x00, 0x22, 0x01, 0x28, 0x02, 0x04, 0x21, 0x06, + 0x20, 0x01, 0x20, 0x01, 0x28, 0x02, 0x00, 0x22, 0x00, 0x28, 0x02, 0x04, + 0x36, 0x02, 0x04, 0x20, 0x01, 0x20, 0x00, 0x28, 0x02, 0x00, 0x36, 0x02, + 0x00, 0x20, 0x00, 0x20, 0x06, 0x36, 0x02, 0x04, 0x20, 0x00, 0x41, 0x00, + 0x36, 0x02, 0x00, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x09, 0x41, + 0x10, 0x74, 0x41, 0x10, 0x75, 0x41, 0x7f, 0x4c, 0x04, 0x40, 0x20, 0x04, + 0x45, 0x0d, 0x01, 0x20, 0x04, 0x21, 0x02, 0x03, 0x40, 0x20, 0x10, 0x20, + 0x02, 0x28, 0x02, 0x04, 0x2d, 0x00, 0x00, 0x46, 0x0d, 0x03, 0x20, 0x02, + 0x28, 0x02, 0x00, 0x22, 0x02, 0x0d, 0x00, 0x0b, 0x0c, 0x01, 0x0b, 0x20, + 0x04, 0x45, 0x0d, 0x00, 0x20, 0x09, 0x41, 0xff, 0xff, 0x03, 0x71, 0x21, + 0x01, 0x20, 0x04, 0x21, 0x02, 0x03, 0x40, 0x20, 0x02, 0x28, 0x02, 0x04, + 0x2f, 0x01, 0x02, 0x20, 0x01, 0x46, 0x0d, 0x02, 0x20, 0x02, 0x28, 0x02, + 0x00, 0x22, 0x02, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x04, 0x28, 0x02, 0x00, + 0x22, 0x02, 0x45, 0x0d, 0x01, 0x0b, 0x03, 0x40, 0x20, 0x04, 0x28, 0x02, + 0x04, 0x2e, 0x01, 0x00, 0x20, 0x0c, 0x41, 0xff, 0xff, 0x03, 0x71, 0x10, + 0x0c, 0x21, 0x0c, 0x20, 0x02, 0x28, 0x02, 0x00, 0x22, 0x02, 0x0d, 0x00, + 0x0b, 0x20, 0x00, 0x28, 0x02, 0x04, 0x21, 0x06, 0x0b, 0x20, 0x00, 0x20, + 0x04, 0x28, 0x02, 0x00, 0x22, 0x01, 0x28, 0x02, 0x04, 0x36, 0x02, 0x04, + 0x20, 0x00, 0x20, 0x01, 0x28, 0x02, 0x00, 0x36, 0x02, 0x00, 0x20, 0x01, + 0x20, 0x06, 0x36, 0x02, 0x04, 0x20, 0x01, 0x20, 0x00, 0x36, 0x02, 0x00, + 0x41, 0x01, 0x21, 0x00, 0x03, 0x40, 0x20, 0x00, 0x41, 0x01, 0x4e, 0x04, + 0x40, 0x41, 0x00, 0x21, 0x0a, 0x41, 0x00, 0x21, 0x06, 0x20, 0x04, 0x21, + 0x02, 0x41, 0x00, 0x21, 0x04, 0x03, 0x40, 0x20, 0x0a, 0x22, 0x09, 0x41, + 0x01, 0x6a, 0x21, 0x0a, 0x41, 0x00, 0x21, 0x03, 0x20, 0x02, 0x21, 0x05, + 0x02, 0x7f, 0x02, 0x40, 0x03, 0x40, 0x20, 0x05, 0x28, 0x02, 0x00, 0x22, + 0x05, 0x45, 0x0d, 0x01, 0x20, 0x00, 0x20, 0x03, 0x41, 0x01, 0x6a, 0x22, + 0x03, 0x47, 0x0d, 0x00, 0x0b, 0x20, 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x03, + 0x41, 0x01, 0x6a, 0x0b, 0x21, 0x08, 0x20, 0x02, 0x21, 0x03, 0x20, 0x05, + 0x21, 0x02, 0x20, 0x00, 0x21, 0x07, 0x03, 0x40, 0x02, 0x40, 0x02, 0x40, + 0x02, 0x7f, 0x02, 0x40, 0x02, 0x7f, 0x02, 0x40, 0x20, 0x08, 0x41, 0x00, + 0x4a, 0x0d, 0x00, 0x20, 0x02, 0x45, 0x0d, 0x04, 0x20, 0x07, 0x41, 0x01, + 0x48, 0x0d, 0x04, 0x20, 0x08, 0x0d, 0x00, 0x20, 0x07, 0x41, 0x7f, 0x6a, + 0x21, 0x07, 0x41, 0x00, 0x21, 0x08, 0x20, 0x02, 0x28, 0x02, 0x00, 0x0c, + 0x01, 0x0b, 0x20, 0x02, 0x45, 0x0d, 0x01, 0x20, 0x07, 0x45, 0x0d, 0x01, + 0x20, 0x03, 0x28, 0x02, 0x04, 0x22, 0x01, 0x20, 0x01, 0x2d, 0x00, 0x01, + 0x3a, 0x00, 0x00, 0x20, 0x02, 0x28, 0x02, 0x04, 0x22, 0x05, 0x20, 0x05, + 0x2d, 0x00, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x01, 0x2e, 0x01, 0x02, 0x20, + 0x05, 0x2e, 0x01, 0x02, 0x4c, 0x0d, 0x01, 0x20, 0x07, 0x41, 0x7f, 0x6a, + 0x21, 0x07, 0x20, 0x02, 0x28, 0x02, 0x00, 0x0b, 0x21, 0x0b, 0x20, 0x02, + 0x21, 0x05, 0x20, 0x03, 0x0c, 0x01, 0x0b, 0x20, 0x08, 0x41, 0x7f, 0x6a, + 0x21, 0x08, 0x20, 0x02, 0x21, 0x0b, 0x20, 0x03, 0x21, 0x05, 0x20, 0x03, + 0x28, 0x02, 0x00, 0x0b, 0x21, 0x01, 0x20, 0x06, 0x45, 0x04, 0x40, 0x20, + 0x05, 0x21, 0x04, 0x0c, 0x02, 0x0b, 0x20, 0x06, 0x20, 0x05, 0x36, 0x02, + 0x00, 0x0c, 0x01, 0x0b, 0x20, 0x02, 0x0d, 0x02, 0x20, 0x06, 0x41, 0x00, + 0x36, 0x02, 0x00, 0x20, 0x00, 0x41, 0x01, 0x74, 0x21, 0x00, 0x20, 0x09, + 0x0d, 0x04, 0x20, 0x04, 0x28, 0x02, 0x00, 0x22, 0x02, 0x04, 0x40, 0x03, + 0x40, 0x20, 0x04, 0x28, 0x02, 0x04, 0x2e, 0x01, 0x00, 0x20, 0x0c, 0x41, + 0xff, 0xff, 0x03, 0x71, 0x10, 0x0c, 0x21, 0x0c, 0x20, 0x02, 0x28, 0x02, + 0x00, 0x22, 0x02, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x0c, 0x41, 0xff, 0xff, + 0x03, 0x71, 0x0f, 0x0b, 0x20, 0x01, 0x21, 0x03, 0x20, 0x0b, 0x21, 0x02, + 0x20, 0x05, 0x21, 0x06, 0x0c, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x0b, + 0x03, 0x40, 0x0c, 0x00, 0x0b, 0x00, 0x0b, 0x03, 0x40, 0x0c, 0x00, 0x0b, + 0x00, 0x0b, 0xac, 0x05, 0x01, 0x09, 0x7f, 0x20, 0x01, 0x41, 0x00, 0x36, + 0x02, 0x00, 0x20, 0x01, 0x20, 0x01, 0x20, 0x00, 0x41, 0x14, 0x6e, 0x41, + 0x7e, 0x6a, 0x22, 0x06, 0x41, 0x03, 0x74, 0x6a, 0x22, 0x07, 0x36, 0x02, + 0x04, 0x20, 0x07, 0x41, 0x80, 0x81, 0x02, 0x36, 0x01, 0x00, 0x20, 0x07, + 0x20, 0x06, 0x41, 0x02, 0x74, 0x6a, 0x21, 0x09, 0x20, 0x01, 0x41, 0x08, + 0x6a, 0x21, 0x03, 0x20, 0x07, 0x41, 0x04, 0x6a, 0x21, 0x05, 0x02, 0x40, + 0x20, 0x00, 0x41, 0xe4, 0x00, 0x49, 0x0d, 0x00, 0x20, 0x09, 0x20, 0x05, + 0x41, 0x04, 0x6a, 0x22, 0x00, 0x4d, 0x04, 0x40, 0x0c, 0x01, 0x0b, 0x20, + 0x01, 0x20, 0x03, 0x36, 0x02, 0x00, 0x20, 0x01, 0x41, 0x00, 0x36, 0x02, + 0x08, 0x20, 0x05, 0x41, 0xff, 0xff, 0xff, 0xff, 0x07, 0x36, 0x01, 0x00, + 0x20, 0x01, 0x41, 0x0c, 0x6a, 0x20, 0x05, 0x36, 0x02, 0x00, 0x20, 0x03, + 0x21, 0x04, 0x20, 0x00, 0x21, 0x05, 0x20, 0x01, 0x41, 0x10, 0x6a, 0x21, + 0x03, 0x0b, 0x20, 0x06, 0x04, 0x40, 0x41, 0x00, 0x21, 0x00, 0x03, 0x40, + 0x02, 0x40, 0x20, 0x03, 0x41, 0x08, 0x6a, 0x22, 0x08, 0x20, 0x07, 0x4f, + 0x0d, 0x00, 0x20, 0x05, 0x41, 0x04, 0x6a, 0x22, 0x0a, 0x20, 0x09, 0x4f, + 0x0d, 0x00, 0x20, 0x03, 0x20, 0x04, 0x36, 0x02, 0x00, 0x20, 0x03, 0x20, + 0x05, 0x36, 0x02, 0x04, 0x20, 0x05, 0x41, 0xff, 0xff, 0x01, 0x3b, 0x01, + 0x02, 0x20, 0x05, 0x20, 0x00, 0x20, 0x02, 0x73, 0x41, 0x03, 0x74, 0x41, + 0xf8, 0x00, 0x71, 0x20, 0x00, 0x41, 0x07, 0x71, 0x72, 0x22, 0x04, 0x41, + 0x08, 0x74, 0x20, 0x04, 0x72, 0x3b, 0x01, 0x00, 0x20, 0x01, 0x20, 0x03, + 0x36, 0x02, 0x00, 0x20, 0x03, 0x21, 0x04, 0x20, 0x0a, 0x21, 0x05, 0x20, + 0x08, 0x21, 0x03, 0x0b, 0x20, 0x06, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x22, + 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x04, 0x28, 0x02, 0x00, 0x22, + 0x03, 0x04, 0x40, 0x20, 0x06, 0x41, 0x05, 0x6e, 0x21, 0x08, 0x41, 0x01, + 0x21, 0x00, 0x03, 0x40, 0x20, 0x00, 0x41, 0x01, 0x6a, 0x21, 0x05, 0x20, + 0x04, 0x28, 0x02, 0x04, 0x20, 0x00, 0x20, 0x08, 0x4f, 0x04, 0x7f, 0x20, + 0x05, 0x41, 0x08, 0x74, 0x41, 0x80, 0x0e, 0x71, 0x20, 0x00, 0x20, 0x02, + 0x73, 0x41, 0xff, 0xff, 0x00, 0x71, 0x72, 0x05, 0x20, 0x00, 0x0b, 0x3b, + 0x01, 0x02, 0x20, 0x05, 0x21, 0x00, 0x20, 0x03, 0x22, 0x04, 0x28, 0x02, + 0x00, 0x22, 0x03, 0x0d, 0x00, 0x0b, 0x0b, 0x41, 0x01, 0x21, 0x06, 0x03, + 0x40, 0x20, 0x06, 0x41, 0x01, 0x4e, 0x04, 0x40, 0x41, 0x00, 0x21, 0x09, + 0x41, 0x00, 0x21, 0x05, 0x20, 0x01, 0x21, 0x00, 0x41, 0x00, 0x21, 0x01, + 0x03, 0x40, 0x20, 0x09, 0x22, 0x0b, 0x41, 0x01, 0x6a, 0x21, 0x09, 0x41, + 0x00, 0x21, 0x03, 0x20, 0x00, 0x21, 0x04, 0x02, 0x7f, 0x02, 0x40, 0x03, + 0x40, 0x20, 0x04, 0x28, 0x02, 0x00, 0x22, 0x04, 0x45, 0x0d, 0x01, 0x20, + 0x06, 0x20, 0x03, 0x41, 0x01, 0x6a, 0x22, 0x03, 0x47, 0x0d, 0x00, 0x0b, + 0x20, 0x06, 0x0c, 0x01, 0x0b, 0x20, 0x03, 0x41, 0x01, 0x6a, 0x0b, 0x21, + 0x07, 0x20, 0x00, 0x21, 0x03, 0x20, 0x04, 0x21, 0x00, 0x20, 0x06, 0x21, + 0x02, 0x03, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x7f, 0x02, 0x40, 0x02, + 0x7f, 0x02, 0x40, 0x20, 0x07, 0x41, 0x00, 0x4a, 0x0d, 0x00, 0x20, 0x00, + 0x45, 0x0d, 0x04, 0x20, 0x02, 0x41, 0x01, 0x48, 0x0d, 0x04, 0x20, 0x07, + 0x0d, 0x00, 0x20, 0x00, 0x28, 0x02, 0x00, 0x21, 0x08, 0x41, 0x00, 0x21, + 0x07, 0x20, 0x02, 0x41, 0x7f, 0x6a, 0x0c, 0x01, 0x0b, 0x20, 0x00, 0x45, + 0x0d, 0x01, 0x20, 0x02, 0x45, 0x0d, 0x01, 0x20, 0x03, 0x28, 0x02, 0x04, + 0x22, 0x04, 0x20, 0x04, 0x2d, 0x00, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x00, + 0x28, 0x02, 0x04, 0x22, 0x08, 0x20, 0x08, 0x2d, 0x00, 0x01, 0x3a, 0x00, + 0x00, 0x20, 0x04, 0x2e, 0x01, 0x02, 0x20, 0x08, 0x2e, 0x01, 0x02, 0x4c, + 0x0d, 0x01, 0x20, 0x00, 0x28, 0x02, 0x00, 0x21, 0x08, 0x20, 0x02, 0x41, + 0x7f, 0x6a, 0x0b, 0x21, 0x02, 0x20, 0x03, 0x21, 0x0a, 0x20, 0x00, 0x0c, + 0x01, 0x0b, 0x20, 0x07, 0x41, 0x7f, 0x6a, 0x21, 0x07, 0x20, 0x03, 0x28, + 0x02, 0x00, 0x21, 0x0a, 0x20, 0x00, 0x21, 0x08, 0x20, 0x03, 0x0b, 0x21, + 0x04, 0x20, 0x05, 0x45, 0x04, 0x40, 0x20, 0x04, 0x21, 0x01, 0x0c, 0x02, + 0x0b, 0x20, 0x05, 0x20, 0x04, 0x36, 0x02, 0x00, 0x0c, 0x01, 0x0b, 0x20, + 0x00, 0x0d, 0x02, 0x20, 0x05, 0x41, 0x00, 0x36, 0x02, 0x00, 0x20, 0x06, + 0x41, 0x01, 0x74, 0x21, 0x06, 0x20, 0x0b, 0x0d, 0x04, 0x20, 0x01, 0x0f, + 0x0b, 0x20, 0x0a, 0x21, 0x03, 0x20, 0x08, 0x21, 0x00, 0x20, 0x04, 0x21, + 0x05, 0x0c, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x0b, 0x03, 0x40, 0x0c, + 0x00, 0x0b, 0x00, 0x0b, 0xa7, 0x0c, 0x03, 0x0f, 0x7f, 0x01, 0x7d, 0x01, + 0x7c, 0x23, 0x00, 0x41, 0xd0, 0x00, 0x6b, 0x22, 0x00, 0x24, 0x00, 0x20, + 0x00, 0x41, 0x00, 0x36, 0x02, 0x4c, 0x20, 0x00, 0x41, 0xc2, 0x00, 0x6a, + 0x22, 0x0e, 0x41, 0x01, 0x3a, 0x00, 0x00, 0x20, 0x00, 0x41, 0xa0, 0x06, + 0x28, 0x02, 0x00, 0x28, 0x02, 0x00, 0x3b, 0x01, 0x00, 0x20, 0x00, 0x41, + 0xa4, 0x06, 0x28, 0x02, 0x00, 0x28, 0x02, 0x00, 0x3b, 0x01, 0x02, 0x20, + 0x00, 0x41, 0xa8, 0x06, 0x28, 0x02, 0x00, 0x28, 0x02, 0x00, 0x3b, 0x01, + 0x04, 0x20, 0x00, 0x41, 0xac, 0x06, 0x28, 0x02, 0x00, 0x28, 0x02, 0x00, + 0x36, 0x02, 0x1c, 0x20, 0x00, 0x41, 0xb0, 0x06, 0x28, 0x02, 0x00, 0x28, + 0x02, 0x00, 0x22, 0x01, 0x41, 0x07, 0x20, 0x01, 0x1b, 0x22, 0x01, 0x36, + 0x02, 0x20, 0x02, 0x40, 0x20, 0x00, 0x2f, 0x01, 0x04, 0x22, 0x05, 0x20, + 0x00, 0x2f, 0x01, 0x02, 0x22, 0x04, 0x20, 0x00, 0x2f, 0x01, 0x00, 0x22, + 0x02, 0x72, 0x72, 0x04, 0x40, 0x20, 0x02, 0x41, 0xff, 0xff, 0x03, 0x71, + 0x41, 0x01, 0x47, 0x0d, 0x01, 0x41, 0x95, 0xe8, 0x00, 0x21, 0x03, 0x20, + 0x04, 0x20, 0x05, 0x72, 0x0d, 0x01, 0x0b, 0x20, 0x00, 0x41, 0xe6, 0x00, + 0x3b, 0x01, 0x04, 0x20, 0x00, 0x20, 0x03, 0x3b, 0x01, 0x02, 0x20, 0x00, + 0x20, 0x03, 0x3b, 0x01, 0x00, 0x20, 0x03, 0x21, 0x02, 0x0b, 0x20, 0x00, + 0x41, 0x00, 0x3b, 0x01, 0x40, 0x20, 0x00, 0x41, 0xc0, 0x06, 0x36, 0x02, + 0x08, 0x20, 0x00, 0x41, 0xd0, 0x0f, 0x20, 0x01, 0x41, 0x01, 0x71, 0x22, + 0x05, 0x20, 0x01, 0x41, 0x02, 0x71, 0x22, 0x04, 0x41, 0x01, 0x76, 0x6a, + 0x20, 0x01, 0x41, 0x04, 0x71, 0x22, 0x03, 0x41, 0x02, 0x76, 0x6a, 0x6e, + 0x22, 0x06, 0x36, 0x02, 0x18, 0x20, 0x05, 0x04, 0x40, 0x20, 0x00, 0x41, + 0xc0, 0x06, 0x36, 0x02, 0x0c, 0x41, 0x01, 0x21, 0x07, 0x0b, 0x20, 0x04, + 0x04, 0x40, 0x20, 0x00, 0x41, 0x10, 0x6a, 0x20, 0x06, 0x20, 0x07, 0x6c, + 0x41, 0xc0, 0x06, 0x6a, 0x36, 0x02, 0x00, 0x20, 0x07, 0x41, 0x01, 0x6a, + 0x21, 0x07, 0x0b, 0x20, 0x03, 0x04, 0x40, 0x20, 0x00, 0x41, 0x14, 0x6a, + 0x20, 0x06, 0x20, 0x07, 0x6c, 0x41, 0xc0, 0x06, 0x6a, 0x36, 0x02, 0x00, + 0x0b, 0x20, 0x05, 0x04, 0x7f, 0x20, 0x00, 0x20, 0x06, 0x20, 0x00, 0x28, + 0x02, 0x0c, 0x20, 0x02, 0x41, 0x10, 0x74, 0x41, 0x10, 0x75, 0x10, 0x03, + 0x36, 0x02, 0x24, 0x20, 0x00, 0x28, 0x02, 0x20, 0x22, 0x01, 0x41, 0x02, + 0x71, 0x05, 0x20, 0x04, 0x0b, 0x04, 0x7f, 0x20, 0x00, 0x28, 0x02, 0x18, + 0x20, 0x00, 0x28, 0x02, 0x10, 0x20, 0x00, 0x2e, 0x01, 0x00, 0x20, 0x00, + 0x2f, 0x01, 0x02, 0x41, 0x10, 0x74, 0x72, 0x20, 0x00, 0x41, 0x28, 0x6a, + 0x10, 0x06, 0x20, 0x00, 0x28, 0x02, 0x20, 0x05, 0x20, 0x01, 0x0b, 0x41, + 0x04, 0x71, 0x04, 0x40, 0x20, 0x00, 0x28, 0x02, 0x18, 0x20, 0x00, 0x2e, + 0x01, 0x00, 0x20, 0x00, 0x28, 0x02, 0x14, 0x10, 0x09, 0x0b, 0x20, 0x00, + 0x28, 0x02, 0x1c, 0x45, 0x04, 0x40, 0x20, 0x00, 0x41, 0x01, 0x36, 0x02, + 0x1c, 0x41, 0x01, 0x21, 0x01, 0x03, 0x40, 0x20, 0x00, 0x20, 0x01, 0x41, + 0x0a, 0x6c, 0x36, 0x02, 0x1c, 0x10, 0x0e, 0x20, 0x00, 0x42, 0x00, 0x37, + 0x03, 0x38, 0x02, 0x40, 0x20, 0x00, 0x28, 0x02, 0x1c, 0x22, 0x01, 0x45, + 0x0d, 0x00, 0x20, 0x00, 0x20, 0x00, 0x41, 0x01, 0x10, 0x02, 0x20, 0x00, + 0x2f, 0x01, 0x38, 0x10, 0x0a, 0x3b, 0x01, 0x38, 0x20, 0x00, 0x20, 0x00, + 0x41, 0x7f, 0x10, 0x02, 0x20, 0x00, 0x2f, 0x01, 0x38, 0x10, 0x0a, 0x22, + 0x03, 0x3b, 0x01, 0x3a, 0x20, 0x00, 0x20, 0x03, 0x3b, 0x01, 0x38, 0x20, + 0x01, 0x41, 0x01, 0x46, 0x0d, 0x00, 0x20, 0x01, 0x41, 0x7f, 0x6a, 0x21, + 0x01, 0x03, 0x40, 0x20, 0x00, 0x20, 0x00, 0x41, 0x01, 0x10, 0x02, 0x20, + 0x00, 0x2f, 0x01, 0x38, 0x10, 0x0a, 0x3b, 0x01, 0x38, 0x20, 0x00, 0x20, + 0x00, 0x41, 0x7f, 0x10, 0x02, 0x20, 0x00, 0x2f, 0x01, 0x38, 0x10, 0x0a, + 0x3b, 0x01, 0x38, 0x20, 0x01, 0x41, 0x7f, 0x6a, 0x22, 0x01, 0x0d, 0x00, + 0x0b, 0x0b, 0x10, 0x0f, 0x41, 0xa4, 0x16, 0x28, 0x02, 0x00, 0x41, 0xa0, + 0x16, 0x28, 0x02, 0x00, 0x6b, 0xb8, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x8f, 0x40, 0xa3, 0x22, 0x10, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x3f, 0x63, 0x41, 0x01, 0x73, 0x45, 0x04, 0x40, 0x20, 0x00, + 0x28, 0x02, 0x1c, 0x21, 0x01, 0x0c, 0x01, 0x0b, 0x0b, 0x20, 0x00, 0x20, + 0x00, 0x28, 0x02, 0x1c, 0x41, 0x0a, 0x02, 0x7f, 0x20, 0x10, 0x44, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x41, 0x63, 0x20, 0x10, 0x44, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x71, 0x04, 0x40, 0x20, + 0x10, 0xab, 0x0c, 0x01, 0x0b, 0x41, 0x00, 0x0b, 0x22, 0x03, 0x41, 0x01, + 0x20, 0x03, 0x1b, 0x6e, 0x41, 0x01, 0x6a, 0x6c, 0x36, 0x02, 0x1c, 0x0b, + 0x10, 0x0e, 0x20, 0x00, 0x42, 0x00, 0x37, 0x03, 0x38, 0x02, 0x40, 0x20, + 0x00, 0x28, 0x02, 0x1c, 0x22, 0x01, 0x45, 0x0d, 0x00, 0x20, 0x00, 0x20, + 0x00, 0x41, 0x01, 0x10, 0x02, 0x20, 0x00, 0x2f, 0x01, 0x38, 0x10, 0x0a, + 0x3b, 0x01, 0x38, 0x20, 0x00, 0x20, 0x00, 0x41, 0x7f, 0x10, 0x02, 0x20, + 0x00, 0x2f, 0x01, 0x38, 0x10, 0x0a, 0x22, 0x03, 0x3b, 0x01, 0x3a, 0x20, + 0x00, 0x20, 0x03, 0x3b, 0x01, 0x38, 0x20, 0x01, 0x41, 0x01, 0x46, 0x0d, + 0x00, 0x20, 0x01, 0x41, 0x7f, 0x6a, 0x21, 0x01, 0x03, 0x40, 0x20, 0x00, + 0x20, 0x00, 0x41, 0x01, 0x10, 0x02, 0x20, 0x00, 0x2f, 0x01, 0x38, 0x10, + 0x0a, 0x3b, 0x01, 0x38, 0x20, 0x00, 0x20, 0x00, 0x41, 0x7f, 0x10, 0x02, + 0x20, 0x00, 0x2f, 0x01, 0x38, 0x10, 0x0a, 0x3b, 0x01, 0x38, 0x20, 0x01, + 0x41, 0x7f, 0x6a, 0x22, 0x01, 0x0d, 0x00, 0x0b, 0x0b, 0x10, 0x0f, 0x41, + 0x00, 0x21, 0x02, 0x41, 0xa4, 0x16, 0x28, 0x02, 0x00, 0x41, 0xa0, 0x16, + 0x28, 0x02, 0x00, 0x6b, 0x21, 0x0c, 0x20, 0x00, 0x2e, 0x01, 0x00, 0x41, + 0x00, 0x10, 0x0c, 0x21, 0x03, 0x20, 0x00, 0x2e, 0x01, 0x02, 0x20, 0x03, + 0x10, 0x0c, 0x21, 0x03, 0x20, 0x00, 0x2e, 0x01, 0x04, 0x20, 0x03, 0x10, + 0x0c, 0x21, 0x01, 0x41, 0xff, 0xff, 0x03, 0x21, 0x03, 0x02, 0x40, 0x02, + 0x40, 0x02, 0x40, 0x20, 0x00, 0x2e, 0x01, 0x18, 0x20, 0x01, 0x10, 0x0c, + 0x22, 0x01, 0x41, 0x84, 0xf6, 0x01, 0x4c, 0x04, 0x40, 0x20, 0x01, 0x41, + 0xf2, 0x31, 0x46, 0x0d, 0x01, 0x20, 0x01, 0x41, 0xaf, 0x9d, 0x01, 0x47, + 0x0d, 0x03, 0x41, 0x02, 0x21, 0x02, 0x0c, 0x02, 0x0b, 0x20, 0x01, 0x41, + 0xf5, 0xd3, 0x03, 0x47, 0x04, 0x40, 0x20, 0x01, 0x41, 0x82, 0x94, 0x02, + 0x46, 0x0d, 0x02, 0x20, 0x01, 0x41, 0x85, 0xf6, 0x01, 0x47, 0x0d, 0x03, + 0x41, 0x01, 0x21, 0x02, 0x0c, 0x02, 0x0b, 0x41, 0x03, 0x21, 0x02, 0x0c, + 0x01, 0x0b, 0x41, 0x04, 0x21, 0x02, 0x0b, 0x41, 0x00, 0x21, 0x03, 0x41, + 0xb8, 0x06, 0x28, 0x02, 0x00, 0x22, 0x08, 0x45, 0x0d, 0x00, 0x20, 0x00, + 0x28, 0x02, 0x20, 0x22, 0x04, 0x41, 0x04, 0x71, 0x21, 0x09, 0x20, 0x04, + 0x41, 0x02, 0x71, 0x21, 0x0d, 0x20, 0x02, 0x41, 0x01, 0x74, 0x22, 0x01, + 0x41, 0x94, 0x04, 0x6a, 0x21, 0x0a, 0x20, 0x01, 0x41, 0x8a, 0x04, 0x6a, + 0x21, 0x07, 0x20, 0x00, 0x2f, 0x01, 0x3e, 0x21, 0x0b, 0x20, 0x00, 0x2f, + 0x01, 0x3c, 0x21, 0x06, 0x02, 0x40, 0x20, 0x04, 0x41, 0x01, 0x71, 0x04, + 0x40, 0x41, 0x02, 0x41, 0x01, 0x20, 0x00, 0x2f, 0x01, 0x3a, 0x20, 0x01, + 0x41, 0x80, 0x04, 0x6a, 0x2f, 0x01, 0x00, 0x47, 0x22, 0x04, 0x1b, 0x21, + 0x05, 0x41, 0x00, 0x21, 0x02, 0x03, 0x40, 0x20, 0x04, 0x21, 0x01, 0x20, + 0x0d, 0x04, 0x40, 0x20, 0x04, 0x20, 0x05, 0x20, 0x06, 0x20, 0x07, 0x2f, + 0x01, 0x00, 0x46, 0x1b, 0x21, 0x01, 0x0b, 0x20, 0x09, 0x04, 0x40, 0x20, + 0x01, 0x20, 0x0b, 0x20, 0x0a, 0x2f, 0x01, 0x00, 0x47, 0x6a, 0x21, 0x01, + 0x0b, 0x20, 0x01, 0x20, 0x03, 0x6a, 0x21, 0x03, 0x20, 0x08, 0x20, 0x02, + 0x41, 0x01, 0x6a, 0x22, 0x02, 0x41, 0xff, 0xff, 0x03, 0x71, 0x4b, 0x0d, + 0x00, 0x0b, 0x0c, 0x01, 0x0b, 0x20, 0x0d, 0x45, 0x04, 0x40, 0x41, 0x00, + 0x21, 0x02, 0x03, 0x40, 0x41, 0x00, 0x21, 0x01, 0x20, 0x09, 0x04, 0x40, + 0x20, 0x0b, 0x20, 0x0a, 0x2f, 0x01, 0x00, 0x47, 0x21, 0x01, 0x0b, 0x20, + 0x01, 0x20, 0x03, 0x6a, 0x21, 0x03, 0x20, 0x08, 0x20, 0x02, 0x41, 0x01, + 0x6a, 0x22, 0x02, 0x41, 0xff, 0xff, 0x03, 0x71, 0x4b, 0x0d, 0x00, 0x0b, + 0x0c, 0x01, 0x0b, 0x41, 0x02, 0x41, 0x01, 0x20, 0x06, 0x20, 0x07, 0x2f, + 0x01, 0x00, 0x47, 0x22, 0x04, 0x1b, 0x21, 0x05, 0x41, 0x00, 0x21, 0x02, + 0x03, 0x40, 0x20, 0x04, 0x21, 0x01, 0x20, 0x09, 0x04, 0x40, 0x20, 0x04, + 0x20, 0x05, 0x20, 0x0b, 0x20, 0x0a, 0x2f, 0x01, 0x00, 0x46, 0x1b, 0x21, + 0x01, 0x0b, 0x20, 0x01, 0x20, 0x03, 0x6a, 0x21, 0x03, 0x20, 0x08, 0x20, + 0x02, 0x41, 0x01, 0x6a, 0x22, 0x02, 0x41, 0xff, 0xff, 0x03, 0x71, 0x4b, + 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x00, 0x20, 0x01, 0x3b, 0x01, 0x40, 0x0b, + 0x20, 0x0c, 0xb8, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x8f, 0x40, + 0xa3, 0x21, 0x10, 0x20, 0x00, 0x28, 0x02, 0x20, 0x22, 0x06, 0x41, 0x01, + 0x71, 0x04, 0x40, 0x41, 0xb8, 0x06, 0x28, 0x02, 0x00, 0x21, 0x02, 0x41, + 0x00, 0x21, 0x01, 0x03, 0x40, 0x20, 0x01, 0x41, 0xff, 0xff, 0x03, 0x71, + 0x21, 0x04, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, 0x02, 0x20, + 0x04, 0x4b, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x06, 0x41, 0x02, 0x71, 0x04, + 0x40, 0x41, 0x00, 0x21, 0x01, 0x41, 0xb8, 0x06, 0x28, 0x02, 0x00, 0x21, + 0x02, 0x03, 0x40, 0x20, 0x01, 0x41, 0xff, 0xff, 0x03, 0x71, 0x21, 0x04, + 0x20, 0x01, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, 0x02, 0x20, 0x04, 0x4b, + 0x0d, 0x00, 0x0b, 0x0b, 0x41, 0x00, 0x21, 0x01, 0x41, 0xb8, 0x06, 0x28, + 0x02, 0x00, 0x21, 0x05, 0x20, 0x06, 0x41, 0x04, 0x71, 0x04, 0x40, 0x03, + 0x40, 0x20, 0x01, 0x41, 0xff, 0xff, 0x03, 0x71, 0x21, 0x04, 0x20, 0x01, + 0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, 0x05, 0x20, 0x04, 0x4b, 0x0d, 0x00, + 0x0b, 0x0b, 0x41, 0x7f, 0x41, 0x00, 0x20, 0x10, 0x44, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x24, 0x40, 0x63, 0x1b, 0x21, 0x02, 0x41, 0x00, 0x21, + 0x01, 0x03, 0x40, 0x20, 0x01, 0x41, 0xff, 0xff, 0x03, 0x71, 0x21, 0x04, + 0x20, 0x01, 0x41, 0x01, 0x6a, 0x21, 0x01, 0x20, 0x05, 0x20, 0x04, 0x4b, + 0x0d, 0x00, 0x0b, 0x20, 0x0e, 0x41, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x03, + 0x41, 0xff, 0xff, 0x03, 0x71, 0x20, 0x02, 0x41, 0xff, 0xff, 0x03, 0x71, + 0x46, 0x04, 0x40, 0x20, 0x00, 0x28, 0x02, 0x1c, 0x41, 0xb8, 0x06, 0x28, + 0x02, 0x00, 0x6c, 0xb8, 0x20, 0x0c, 0xb8, 0x44, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x8f, 0x40, 0xa3, 0xa3, 0xb6, 0x21, 0x0f, 0x0b, 0x20, 0x00, + 0x41, 0xd0, 0x00, 0x6a, 0x24, 0x00, 0x20, 0x0f, 0x0b, 0xfb, 0x09, 0x01, + 0x0d, 0x7f, 0x02, 0x40, 0x20, 0x00, 0x04, 0x40, 0x20, 0x04, 0x41, 0x80, + 0x60, 0x72, 0x21, 0x10, 0x20, 0x00, 0x41, 0x01, 0x74, 0x21, 0x0a, 0x20, + 0x02, 0x21, 0x07, 0x03, 0x40, 0x20, 0x00, 0x21, 0x05, 0x20, 0x07, 0x21, + 0x06, 0x03, 0x40, 0x20, 0x06, 0x20, 0x06, 0x2f, 0x01, 0x00, 0x20, 0x04, + 0x6a, 0x3b, 0x01, 0x00, 0x20, 0x06, 0x41, 0x02, 0x6a, 0x21, 0x06, 0x20, + 0x05, 0x41, 0x7f, 0x6a, 0x22, 0x05, 0x0d, 0x00, 0x0b, 0x20, 0x07, 0x20, + 0x0a, 0x6a, 0x21, 0x07, 0x20, 0x0b, 0x41, 0x01, 0x6a, 0x22, 0x0b, 0x20, + 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x20, 0x00, 0x41, 0x01, 0x74, 0x21, 0x0a, + 0x20, 0x00, 0x41, 0x02, 0x74, 0x21, 0x0c, 0x20, 0x02, 0x21, 0x0b, 0x20, + 0x01, 0x21, 0x08, 0x03, 0x40, 0x20, 0x00, 0x21, 0x07, 0x20, 0x0b, 0x21, + 0x06, 0x20, 0x08, 0x21, 0x05, 0x03, 0x40, 0x20, 0x05, 0x20, 0x06, 0x2e, + 0x01, 0x00, 0x20, 0x04, 0x6c, 0x36, 0x02, 0x00, 0x20, 0x06, 0x41, 0x02, + 0x6a, 0x21, 0x06, 0x20, 0x05, 0x41, 0x04, 0x6a, 0x21, 0x05, 0x20, 0x07, + 0x41, 0x7f, 0x6a, 0x22, 0x07, 0x0d, 0x00, 0x0b, 0x20, 0x0a, 0x20, 0x0b, + 0x6a, 0x21, 0x0b, 0x20, 0x08, 0x20, 0x0c, 0x6a, 0x21, 0x08, 0x20, 0x09, + 0x41, 0x01, 0x6a, 0x22, 0x09, 0x20, 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x20, + 0x00, 0x41, 0x02, 0x74, 0x21, 0x0d, 0x20, 0x01, 0x21, 0x0a, 0x41, 0x00, + 0x21, 0x0c, 0x41, 0x00, 0x21, 0x08, 0x41, 0x00, 0x21, 0x07, 0x41, 0x00, + 0x21, 0x09, 0x03, 0x40, 0x20, 0x00, 0x21, 0x0b, 0x20, 0x0a, 0x21, 0x05, + 0x03, 0x40, 0x41, 0x00, 0x20, 0x05, 0x28, 0x02, 0x00, 0x22, 0x06, 0x20, + 0x09, 0x6a, 0x22, 0x09, 0x20, 0x09, 0x20, 0x10, 0x4a, 0x22, 0x0e, 0x1b, + 0x21, 0x09, 0x41, 0x0a, 0x20, 0x06, 0x20, 0x07, 0x4a, 0x20, 0x0e, 0x1b, + 0x20, 0x08, 0x6a, 0x21, 0x08, 0x20, 0x05, 0x41, 0x04, 0x6a, 0x21, 0x05, + 0x20, 0x06, 0x21, 0x07, 0x20, 0x0b, 0x41, 0x7f, 0x6a, 0x22, 0x0b, 0x0d, + 0x00, 0x0b, 0x20, 0x0a, 0x20, 0x0d, 0x6a, 0x21, 0x0a, 0x20, 0x0c, 0x41, + 0x01, 0x6a, 0x22, 0x0c, 0x20, 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x20, 0x00, + 0x41, 0x01, 0x74, 0x21, 0x0a, 0x20, 0x08, 0x41, 0x10, 0x74, 0x41, 0x10, + 0x75, 0x41, 0x00, 0x10, 0x0c, 0x21, 0x0e, 0x20, 0x02, 0x21, 0x08, 0x41, + 0x00, 0x21, 0x09, 0x03, 0x40, 0x20, 0x01, 0x20, 0x09, 0x41, 0x02, 0x74, + 0x6a, 0x22, 0x0c, 0x41, 0x00, 0x36, 0x02, 0x00, 0x20, 0x03, 0x21, 0x06, + 0x20, 0x00, 0x21, 0x0b, 0x20, 0x08, 0x21, 0x05, 0x41, 0x00, 0x21, 0x07, + 0x03, 0x40, 0x20, 0x06, 0x2e, 0x01, 0x00, 0x20, 0x05, 0x2e, 0x01, 0x00, + 0x6c, 0x20, 0x07, 0x6a, 0x21, 0x07, 0x20, 0x06, 0x41, 0x02, 0x6a, 0x21, + 0x06, 0x20, 0x05, 0x41, 0x02, 0x6a, 0x21, 0x05, 0x20, 0x0b, 0x41, 0x7f, + 0x6a, 0x22, 0x0b, 0x0d, 0x00, 0x0b, 0x20, 0x0c, 0x20, 0x07, 0x36, 0x02, + 0x00, 0x20, 0x08, 0x20, 0x0a, 0x6a, 0x21, 0x08, 0x20, 0x09, 0x41, 0x01, + 0x6a, 0x22, 0x09, 0x20, 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x20, 0x00, 0x41, + 0x02, 0x74, 0x21, 0x0d, 0x20, 0x01, 0x21, 0x0a, 0x41, 0x00, 0x21, 0x0c, + 0x41, 0x00, 0x21, 0x09, 0x41, 0x00, 0x21, 0x07, 0x41, 0x00, 0x21, 0x08, + 0x03, 0x40, 0x20, 0x00, 0x21, 0x0b, 0x20, 0x0a, 0x21, 0x05, 0x03, 0x40, + 0x41, 0x00, 0x20, 0x05, 0x28, 0x02, 0x00, 0x22, 0x06, 0x20, 0x08, 0x6a, + 0x22, 0x08, 0x20, 0x08, 0x20, 0x10, 0x4a, 0x22, 0x0f, 0x1b, 0x21, 0x08, + 0x41, 0x0a, 0x20, 0x06, 0x20, 0x07, 0x4a, 0x20, 0x0f, 0x1b, 0x20, 0x09, + 0x6a, 0x21, 0x09, 0x20, 0x05, 0x41, 0x04, 0x6a, 0x21, 0x05, 0x20, 0x06, + 0x21, 0x07, 0x20, 0x0b, 0x41, 0x7f, 0x6a, 0x22, 0x0b, 0x0d, 0x00, 0x0b, + 0x20, 0x0a, 0x20, 0x0d, 0x6a, 0x21, 0x0a, 0x20, 0x0c, 0x41, 0x01, 0x6a, + 0x22, 0x0c, 0x20, 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x20, 0x00, 0x41, 0x01, + 0x74, 0x21, 0x0d, 0x41, 0x00, 0x21, 0x0a, 0x20, 0x09, 0x41, 0x10, 0x74, + 0x41, 0x10, 0x75, 0x20, 0x0e, 0x10, 0x0c, 0x21, 0x0e, 0x20, 0x02, 0x21, + 0x0c, 0x03, 0x40, 0x20, 0x00, 0x20, 0x0a, 0x6c, 0x21, 0x0f, 0x20, 0x03, + 0x21, 0x09, 0x41, 0x00, 0x21, 0x08, 0x03, 0x40, 0x41, 0x00, 0x21, 0x07, + 0x20, 0x01, 0x20, 0x08, 0x20, 0x0f, 0x6a, 0x41, 0x02, 0x74, 0x6a, 0x22, + 0x11, 0x41, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00, 0x21, 0x0b, 0x20, 0x0c, + 0x21, 0x06, 0x20, 0x09, 0x21, 0x05, 0x03, 0x40, 0x20, 0x05, 0x2e, 0x01, + 0x00, 0x20, 0x06, 0x2e, 0x01, 0x00, 0x6c, 0x20, 0x07, 0x6a, 0x21, 0x07, + 0x20, 0x06, 0x41, 0x02, 0x6a, 0x21, 0x06, 0x20, 0x05, 0x20, 0x0d, 0x6a, + 0x21, 0x05, 0x20, 0x0b, 0x41, 0x7f, 0x6a, 0x22, 0x0b, 0x0d, 0x00, 0x0b, + 0x20, 0x11, 0x20, 0x07, 0x36, 0x02, 0x00, 0x20, 0x09, 0x41, 0x02, 0x6a, + 0x21, 0x09, 0x20, 0x08, 0x41, 0x01, 0x6a, 0x22, 0x08, 0x20, 0x00, 0x47, + 0x0d, 0x00, 0x0b, 0x20, 0x0c, 0x20, 0x0d, 0x6a, 0x21, 0x0c, 0x20, 0x0a, + 0x41, 0x01, 0x6a, 0x22, 0x0a, 0x20, 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x20, + 0x00, 0x41, 0x02, 0x74, 0x21, 0x0d, 0x20, 0x01, 0x21, 0x0a, 0x41, 0x00, + 0x21, 0x0c, 0x41, 0x00, 0x21, 0x08, 0x41, 0x00, 0x21, 0x07, 0x41, 0x00, + 0x21, 0x09, 0x03, 0x40, 0x20, 0x00, 0x21, 0x0b, 0x20, 0x0a, 0x21, 0x05, + 0x03, 0x40, 0x41, 0x00, 0x20, 0x05, 0x28, 0x02, 0x00, 0x22, 0x06, 0x20, + 0x09, 0x6a, 0x22, 0x09, 0x20, 0x09, 0x20, 0x10, 0x4a, 0x22, 0x0f, 0x1b, + 0x21, 0x09, 0x41, 0x0a, 0x20, 0x06, 0x20, 0x07, 0x4a, 0x20, 0x0f, 0x1b, + 0x20, 0x08, 0x6a, 0x21, 0x08, 0x20, 0x05, 0x41, 0x04, 0x6a, 0x21, 0x05, + 0x20, 0x06, 0x21, 0x07, 0x20, 0x0b, 0x41, 0x7f, 0x6a, 0x22, 0x0b, 0x0d, + 0x00, 0x0b, 0x20, 0x0a, 0x20, 0x0d, 0x6a, 0x21, 0x0a, 0x20, 0x0c, 0x41, + 0x01, 0x6a, 0x22, 0x0c, 0x20, 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x20, 0x00, + 0x41, 0x01, 0x74, 0x21, 0x0d, 0x41, 0x00, 0x21, 0x0c, 0x20, 0x08, 0x41, + 0x10, 0x74, 0x41, 0x10, 0x75, 0x20, 0x0e, 0x10, 0x0c, 0x21, 0x0e, 0x20, + 0x02, 0x21, 0x09, 0x03, 0x40, 0x20, 0x00, 0x20, 0x0c, 0x6c, 0x21, 0x0f, + 0x20, 0x03, 0x21, 0x08, 0x41, 0x00, 0x21, 0x0a, 0x03, 0x40, 0x41, 0x00, + 0x21, 0x07, 0x20, 0x01, 0x20, 0x0a, 0x20, 0x0f, 0x6a, 0x41, 0x02, 0x74, + 0x6a, 0x22, 0x11, 0x41, 0x00, 0x36, 0x02, 0x00, 0x20, 0x00, 0x21, 0x0b, + 0x20, 0x09, 0x21, 0x06, 0x20, 0x08, 0x21, 0x05, 0x03, 0x40, 0x20, 0x07, + 0x20, 0x05, 0x2f, 0x01, 0x00, 0x20, 0x06, 0x2f, 0x01, 0x00, 0x6c, 0x22, + 0x07, 0x41, 0x02, 0x76, 0x41, 0x0f, 0x71, 0x20, 0x07, 0x41, 0x05, 0x76, + 0x41, 0xff, 0x00, 0x71, 0x6c, 0x6a, 0x21, 0x07, 0x20, 0x06, 0x41, 0x02, + 0x6a, 0x21, 0x06, 0x20, 0x05, 0x20, 0x0d, 0x6a, 0x21, 0x05, 0x20, 0x0b, + 0x41, 0x7f, 0x6a, 0x22, 0x0b, 0x0d, 0x00, 0x0b, 0x20, 0x11, 0x20, 0x07, + 0x36, 0x02, 0x00, 0x20, 0x08, 0x41, 0x02, 0x6a, 0x21, 0x08, 0x20, 0x0a, + 0x41, 0x01, 0x6a, 0x22, 0x0a, 0x20, 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x20, + 0x09, 0x20, 0x0d, 0x6a, 0x21, 0x09, 0x20, 0x0c, 0x41, 0x01, 0x6a, 0x22, + 0x0c, 0x20, 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x20, 0x00, 0x41, 0x02, 0x74, + 0x21, 0x06, 0x41, 0x00, 0x21, 0x0a, 0x41, 0x00, 0x21, 0x08, 0x41, 0x00, + 0x21, 0x07, 0x41, 0x00, 0x21, 0x09, 0x03, 0x40, 0x20, 0x00, 0x21, 0x0b, + 0x20, 0x01, 0x21, 0x05, 0x03, 0x40, 0x41, 0x00, 0x20, 0x05, 0x28, 0x02, + 0x00, 0x22, 0x03, 0x20, 0x09, 0x6a, 0x22, 0x09, 0x20, 0x09, 0x20, 0x10, + 0x4a, 0x22, 0x0c, 0x1b, 0x21, 0x09, 0x41, 0x0a, 0x20, 0x03, 0x20, 0x07, + 0x4a, 0x20, 0x0c, 0x1b, 0x20, 0x08, 0x6a, 0x21, 0x08, 0x20, 0x05, 0x41, + 0x04, 0x6a, 0x21, 0x05, 0x20, 0x03, 0x21, 0x07, 0x20, 0x0b, 0x41, 0x7f, + 0x6a, 0x22, 0x0b, 0x0d, 0x00, 0x0b, 0x20, 0x01, 0x20, 0x06, 0x6a, 0x21, + 0x01, 0x20, 0x0a, 0x41, 0x01, 0x6a, 0x22, 0x0a, 0x20, 0x00, 0x47, 0x0d, + 0x00, 0x0b, 0x20, 0x00, 0x41, 0x01, 0x74, 0x21, 0x01, 0x41, 0x00, 0x21, + 0x07, 0x20, 0x08, 0x41, 0x10, 0x74, 0x41, 0x10, 0x75, 0x20, 0x0e, 0x10, + 0x0c, 0x21, 0x08, 0x03, 0x40, 0x20, 0x00, 0x21, 0x05, 0x20, 0x02, 0x21, + 0x06, 0x03, 0x40, 0x20, 0x06, 0x20, 0x06, 0x2f, 0x01, 0x00, 0x20, 0x04, + 0x6b, 0x3b, 0x01, 0x00, 0x20, 0x06, 0x41, 0x02, 0x6a, 0x21, 0x06, 0x20, + 0x05, 0x41, 0x7f, 0x6a, 0x22, 0x05, 0x0d, 0x00, 0x0b, 0x20, 0x01, 0x20, + 0x02, 0x6a, 0x21, 0x02, 0x20, 0x07, 0x41, 0x01, 0x6a, 0x22, 0x07, 0x20, + 0x00, 0x47, 0x0d, 0x00, 0x0b, 0x0c, 0x01, 0x0b, 0x41, 0x00, 0x41, 0x00, + 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x10, 0x0c, 0x10, 0x0c, 0x10, 0x0c, + 0x10, 0x0c, 0x21, 0x08, 0x0b, 0x20, 0x08, 0x41, 0x10, 0x74, 0x41, 0x10, + 0x75, 0x0b, 0x91, 0x02, 0x01, 0x0b, 0x7f, 0x02, 0x40, 0x20, 0x00, 0x45, + 0x04, 0x40, 0x41, 0x7f, 0x21, 0x04, 0x0c, 0x01, 0x0b, 0x41, 0x7f, 0x21, + 0x05, 0x41, 0x08, 0x21, 0x06, 0x03, 0x40, 0x20, 0x06, 0x20, 0x05, 0x41, + 0x02, 0x6a, 0x6c, 0x20, 0x06, 0x41, 0x08, 0x6a, 0x21, 0x06, 0x20, 0x05, + 0x41, 0x01, 0x6a, 0x22, 0x04, 0x21, 0x05, 0x20, 0x00, 0x49, 0x0d, 0x00, + 0x0b, 0x0b, 0x20, 0x01, 0x41, 0x03, 0x6a, 0x41, 0x7c, 0x71, 0x22, 0x07, + 0x20, 0x04, 0x20, 0x04, 0x6c, 0x22, 0x09, 0x41, 0x01, 0x74, 0x6a, 0x21, + 0x0a, 0x20, 0x04, 0x04, 0x40, 0x20, 0x02, 0x41, 0x01, 0x20, 0x02, 0x1b, + 0x21, 0x00, 0x20, 0x04, 0x41, 0x01, 0x74, 0x21, 0x0b, 0x20, 0x09, 0x41, + 0x01, 0x74, 0x21, 0x0c, 0x20, 0x07, 0x21, 0x02, 0x41, 0x01, 0x21, 0x01, + 0x03, 0x40, 0x20, 0x01, 0x41, 0x01, 0x74, 0x21, 0x08, 0x20, 0x02, 0x21, + 0x05, 0x41, 0x00, 0x21, 0x06, 0x03, 0x40, 0x20, 0x05, 0x20, 0x0c, 0x6a, + 0x20, 0x01, 0x20, 0x06, 0x6a, 0x22, 0x0d, 0x20, 0x00, 0x20, 0x0d, 0x6c, + 0x41, 0x80, 0x80, 0x04, 0x6f, 0x22, 0x00, 0x6a, 0x3b, 0x01, 0x00, 0x20, + 0x05, 0x20, 0x00, 0x20, 0x08, 0x6a, 0x41, 0xff, 0x01, 0x71, 0x3b, 0x01, + 0x00, 0x20, 0x08, 0x41, 0x02, 0x6a, 0x21, 0x08, 0x20, 0x05, 0x41, 0x02, + 0x6a, 0x21, 0x05, 0x20, 0x04, 0x20, 0x06, 0x41, 0x01, 0x6a, 0x22, 0x06, + 0x47, 0x0d, 0x00, 0x0b, 0x20, 0x01, 0x20, 0x06, 0x6a, 0x21, 0x01, 0x20, + 0x02, 0x20, 0x0b, 0x6a, 0x21, 0x02, 0x20, 0x0e, 0x41, 0x01, 0x6a, 0x22, + 0x0e, 0x20, 0x04, 0x47, 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x03, 0x20, 0x0a, + 0x36, 0x02, 0x08, 0x20, 0x03, 0x20, 0x07, 0x36, 0x02, 0x04, 0x20, 0x03, + 0x20, 0x04, 0x36, 0x02, 0x00, 0x20, 0x03, 0x20, 0x0a, 0x20, 0x09, 0x41, + 0x01, 0x74, 0x6a, 0x41, 0x03, 0x6a, 0x41, 0x7c, 0x71, 0x36, 0x02, 0x0c, + 0x0b, 0x88, 0x04, 0x01, 0x04, 0x7f, 0x23, 0x00, 0x41, 0xd0, 0x00, 0x6b, + 0x22, 0x06, 0x24, 0x00, 0x20, 0x06, 0x41, 0x20, 0x6a, 0x42, 0x00, 0x37, + 0x03, 0x00, 0x20, 0x06, 0x41, 0x28, 0x6a, 0x42, 0x00, 0x37, 0x03, 0x00, + 0x20, 0x06, 0x41, 0x40, 0x6b, 0x42, 0x00, 0x37, 0x03, 0x00, 0x20, 0x06, + 0x41, 0xc8, 0x00, 0x6a, 0x42, 0x00, 0x37, 0x03, 0x00, 0x20, 0x06, 0x42, + 0x00, 0x37, 0x03, 0x30, 0x20, 0x06, 0x42, 0x00, 0x37, 0x03, 0x38, 0x20, + 0x06, 0x42, 0x00, 0x37, 0x03, 0x10, 0x20, 0x06, 0x42, 0x00, 0x37, 0x03, + 0x18, 0x20, 0x06, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x20, 0x01, 0x2d, 0x00, + 0x00, 0x04, 0x40, 0x03, 0x40, 0x20, 0x06, 0x41, 0x30, 0x6a, 0x20, 0x06, + 0x41, 0x0c, 0x6a, 0x20, 0x06, 0x41, 0x10, 0x6a, 0x10, 0x08, 0x41, 0x02, + 0x74, 0x6a, 0x22, 0x07, 0x20, 0x07, 0x28, 0x02, 0x00, 0x41, 0x01, 0x6a, + 0x36, 0x02, 0x00, 0x20, 0x06, 0x28, 0x02, 0x0c, 0x2d, 0x00, 0x00, 0x0d, + 0x00, 0x0b, 0x0b, 0x20, 0x06, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x20, 0x00, + 0x20, 0x01, 0x6a, 0x21, 0x08, 0x20, 0x00, 0x41, 0x01, 0x4e, 0x04, 0x40, + 0x20, 0x01, 0x21, 0x07, 0x03, 0x40, 0x20, 0x07, 0x2d, 0x00, 0x00, 0x22, + 0x09, 0x41, 0x2c, 0x47, 0x04, 0x40, 0x20, 0x07, 0x20, 0x02, 0x20, 0x09, + 0x73, 0x3a, 0x00, 0x00, 0x0b, 0x20, 0x06, 0x20, 0x04, 0x20, 0x07, 0x6a, + 0x22, 0x07, 0x36, 0x02, 0x0c, 0x20, 0x07, 0x20, 0x08, 0x49, 0x0d, 0x00, + 0x0b, 0x0b, 0x20, 0x06, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x20, 0x01, 0x2d, + 0x00, 0x00, 0x04, 0x40, 0x03, 0x40, 0x20, 0x06, 0x41, 0x30, 0x6a, 0x20, + 0x06, 0x41, 0x0c, 0x6a, 0x20, 0x06, 0x41, 0x10, 0x6a, 0x10, 0x08, 0x41, + 0x02, 0x74, 0x6a, 0x22, 0x02, 0x20, 0x02, 0x28, 0x02, 0x00, 0x41, 0x01, + 0x6a, 0x36, 0x02, 0x00, 0x20, 0x06, 0x28, 0x02, 0x0c, 0x2d, 0x00, 0x00, + 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x06, 0x20, 0x01, 0x36, 0x02, 0x0c, 0x20, + 0x00, 0x41, 0x01, 0x4e, 0x04, 0x40, 0x03, 0x40, 0x20, 0x01, 0x2d, 0x00, + 0x00, 0x22, 0x00, 0x41, 0x2c, 0x47, 0x04, 0x40, 0x20, 0x01, 0x20, 0x00, + 0x20, 0x03, 0x73, 0x3a, 0x00, 0x00, 0x0b, 0x20, 0x06, 0x20, 0x01, 0x20, + 0x04, 0x6a, 0x22, 0x01, 0x36, 0x02, 0x0c, 0x20, 0x01, 0x20, 0x08, 0x49, + 0x0d, 0x00, 0x0b, 0x0b, 0x20, 0x06, 0x28, 0x02, 0x30, 0x20, 0x05, 0x10, + 0x0b, 0x21, 0x00, 0x20, 0x06, 0x28, 0x02, 0x10, 0x20, 0x00, 0x10, 0x0b, + 0x21, 0x00, 0x20, 0x06, 0x28, 0x02, 0x34, 0x20, 0x00, 0x10, 0x0b, 0x21, + 0x00, 0x20, 0x06, 0x28, 0x02, 0x14, 0x20, 0x00, 0x10, 0x0b, 0x21, 0x00, + 0x20, 0x06, 0x28, 0x02, 0x38, 0x20, 0x00, 0x10, 0x0b, 0x21, 0x00, 0x20, + 0x06, 0x28, 0x02, 0x18, 0x20, 0x00, 0x10, 0x0b, 0x21, 0x00, 0x20, 0x06, + 0x28, 0x02, 0x3c, 0x20, 0x00, 0x10, 0x0b, 0x21, 0x00, 0x20, 0x06, 0x28, + 0x02, 0x1c, 0x20, 0x00, 0x10, 0x0b, 0x21, 0x00, 0x20, 0x06, 0x28, 0x02, + 0x40, 0x20, 0x00, 0x10, 0x0b, 0x21, 0x00, 0x20, 0x06, 0x28, 0x02, 0x20, + 0x20, 0x00, 0x10, 0x0b, 0x21, 0x00, 0x20, 0x06, 0x28, 0x02, 0x44, 0x20, + 0x00, 0x10, 0x0b, 0x21, 0x00, 0x20, 0x06, 0x28, 0x02, 0x24, 0x20, 0x00, + 0x10, 0x0b, 0x21, 0x00, 0x20, 0x06, 0x28, 0x02, 0x48, 0x20, 0x00, 0x10, + 0x0b, 0x21, 0x00, 0x20, 0x06, 0x28, 0x02, 0x28, 0x20, 0x00, 0x10, 0x0b, + 0x21, 0x00, 0x20, 0x06, 0x28, 0x02, 0x4c, 0x20, 0x00, 0x10, 0x0b, 0x21, + 0x00, 0x20, 0x06, 0x28, 0x02, 0x2c, 0x20, 0x00, 0x10, 0x0b, 0x20, 0x06, + 0x41, 0xd0, 0x00, 0x6a, 0x24, 0x00, 0x0b, 0x8c, 0x04, 0x01, 0x08, 0x7f, + 0x20, 0x00, 0x28, 0x02, 0x00, 0x22, 0x04, 0x2d, 0x00, 0x00, 0x22, 0x03, + 0x45, 0x04, 0x40, 0x20, 0x00, 0x20, 0x04, 0x36, 0x02, 0x00, 0x41, 0x00, + 0x0f, 0x0b, 0x20, 0x04, 0x41, 0x01, 0x6a, 0x21, 0x05, 0x20, 0x01, 0x41, + 0x10, 0x6a, 0x21, 0x06, 0x20, 0x01, 0x41, 0x14, 0x6a, 0x21, 0x07, 0x20, + 0x01, 0x41, 0x0c, 0x6a, 0x21, 0x04, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, + 0x08, 0x02, 0x40, 0x03, 0x40, 0x20, 0x03, 0x41, 0x2c, 0x46, 0x0d, 0x01, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, + 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x40, 0x20, 0x02, 0x0e, 0x08, + 0x00, 0x09, 0x01, 0x04, 0x02, 0x03, 0x05, 0x06, 0x09, 0x0b, 0x41, 0x04, + 0x21, 0x02, 0x02, 0x40, 0x20, 0x03, 0x41, 0x50, 0x6a, 0x41, 0xff, 0x01, + 0x71, 0x41, 0x0a, 0x49, 0x0d, 0x00, 0x41, 0x02, 0x21, 0x02, 0x02, 0x40, + 0x02, 0x40, 0x20, 0x03, 0x41, 0x55, 0x6a, 0x0e, 0x04, 0x02, 0x01, 0x02, + 0x00, 0x01, 0x0b, 0x41, 0x05, 0x21, 0x02, 0x0c, 0x01, 0x0b, 0x41, 0x01, + 0x21, 0x02, 0x20, 0x08, 0x20, 0x08, 0x28, 0x02, 0x00, 0x41, 0x01, 0x6a, + 0x36, 0x02, 0x00, 0x0b, 0x20, 0x01, 0x20, 0x01, 0x28, 0x02, 0x00, 0x41, + 0x01, 0x6a, 0x36, 0x02, 0x00, 0x0c, 0x08, 0x0b, 0x20, 0x03, 0x41, 0x50, + 0x6a, 0x41, 0xff, 0x01, 0x71, 0x41, 0x09, 0x4b, 0x0d, 0x06, 0x20, 0x01, + 0x20, 0x01, 0x28, 0x02, 0x08, 0x41, 0x01, 0x6a, 0x36, 0x02, 0x08, 0x41, + 0x04, 0x21, 0x02, 0x0c, 0x07, 0x0b, 0x20, 0x03, 0x41, 0x2e, 0x46, 0x04, + 0x40, 0x20, 0x06, 0x20, 0x06, 0x28, 0x02, 0x00, 0x41, 0x01, 0x6a, 0x36, + 0x02, 0x00, 0x41, 0x05, 0x21, 0x02, 0x0c, 0x07, 0x0b, 0x41, 0x04, 0x21, + 0x02, 0x20, 0x03, 0x41, 0x50, 0x6a, 0x41, 0xff, 0x01, 0x71, 0x41, 0x09, + 0x4d, 0x0d, 0x06, 0x20, 0x06, 0x21, 0x04, 0x0c, 0x04, 0x0b, 0x20, 0x03, + 0x41, 0x20, 0x72, 0x41, 0xe5, 0x00, 0x46, 0x04, 0x40, 0x20, 0x07, 0x20, + 0x07, 0x28, 0x02, 0x00, 0x41, 0x01, 0x6a, 0x36, 0x02, 0x00, 0x41, 0x03, + 0x21, 0x02, 0x0c, 0x06, 0x0b, 0x41, 0x05, 0x21, 0x02, 0x20, 0x03, 0x41, + 0x50, 0x6a, 0x41, 0xff, 0x01, 0x71, 0x41, 0x09, 0x4d, 0x0d, 0x05, 0x20, + 0x07, 0x21, 0x04, 0x0c, 0x03, 0x0b, 0x02, 0x40, 0x20, 0x03, 0x41, 0x55, + 0x6a, 0x0e, 0x03, 0x00, 0x03, 0x00, 0x03, 0x0b, 0x20, 0x04, 0x20, 0x04, + 0x28, 0x02, 0x00, 0x41, 0x01, 0x6a, 0x36, 0x02, 0x00, 0x41, 0x06, 0x21, + 0x02, 0x0c, 0x04, 0x0b, 0x20, 0x01, 0x20, 0x01, 0x28, 0x02, 0x18, 0x41, + 0x01, 0x6a, 0x36, 0x02, 0x18, 0x41, 0x01, 0x41, 0x07, 0x20, 0x03, 0x41, + 0x50, 0x6a, 0x41, 0xff, 0x01, 0x71, 0x41, 0x09, 0x4b, 0x1b, 0x21, 0x02, + 0x0c, 0x03, 0x0b, 0x41, 0x07, 0x21, 0x02, 0x20, 0x03, 0x41, 0x50, 0x6a, + 0x41, 0xff, 0x01, 0x71, 0x41, 0x0a, 0x49, 0x0d, 0x02, 0x20, 0x08, 0x21, + 0x04, 0x0b, 0x20, 0x04, 0x20, 0x04, 0x28, 0x02, 0x00, 0x41, 0x01, 0x6a, + 0x36, 0x02, 0x00, 0x20, 0x00, 0x20, 0x05, 0x36, 0x02, 0x00, 0x41, 0x01, + 0x0f, 0x0b, 0x20, 0x01, 0x20, 0x01, 0x28, 0x02, 0x08, 0x41, 0x01, 0x6a, + 0x36, 0x02, 0x08, 0x41, 0x05, 0x41, 0x01, 0x20, 0x03, 0x41, 0x2e, 0x46, + 0x1b, 0x21, 0x02, 0x0b, 0x20, 0x05, 0x41, 0x01, 0x6a, 0x21, 0x09, 0x20, + 0x02, 0x41, 0x01, 0x47, 0x04, 0x40, 0x20, 0x05, 0x2d, 0x00, 0x00, 0x21, + 0x03, 0x20, 0x09, 0x21, 0x05, 0x20, 0x03, 0x0d, 0x01, 0x0b, 0x0b, 0x20, + 0x09, 0x41, 0x7f, 0x6a, 0x21, 0x05, 0x0b, 0x20, 0x00, 0x20, 0x05, 0x36, + 0x02, 0x00, 0x20, 0x02, 0x0b, 0xad, 0x01, 0x01, 0x06, 0x7f, 0x20, 0x00, + 0x41, 0x7f, 0x6a, 0x22, 0x08, 0x41, 0x02, 0x4f, 0x04, 0x40, 0x03, 0x40, + 0x20, 0x04, 0x04, 0x40, 0x20, 0x02, 0x20, 0x03, 0x6a, 0x21, 0x06, 0x20, + 0x04, 0x21, 0x07, 0x03, 0x40, 0x20, 0x06, 0x20, 0x05, 0x2d, 0x00, 0x00, + 0x3a, 0x00, 0x00, 0x20, 0x05, 0x41, 0x01, 0x6a, 0x21, 0x05, 0x20, 0x06, + 0x41, 0x01, 0x6a, 0x21, 0x06, 0x20, 0x07, 0x41, 0x7f, 0x6a, 0x22, 0x07, + 0x0d, 0x00, 0x0b, 0x20, 0x02, 0x20, 0x03, 0x6a, 0x20, 0x04, 0x6a, 0x41, + 0x2c, 0x3a, 0x00, 0x00, 0x20, 0x03, 0x20, 0x04, 0x6a, 0x41, 0x01, 0x6a, + 0x21, 0x03, 0x0b, 0x20, 0x01, 0x41, 0x01, 0x6a, 0x22, 0x01, 0x41, 0x07, + 0x71, 0x41, 0x02, 0x74, 0x22, 0x04, 0x41, 0xe0, 0x05, 0x6a, 0x28, 0x02, + 0x00, 0x20, 0x01, 0x41, 0x01, 0x76, 0x41, 0x0c, 0x71, 0x6a, 0x28, 0x02, + 0x00, 0x21, 0x05, 0x20, 0x03, 0x20, 0x04, 0x41, 0x80, 0x06, 0x6a, 0x28, + 0x02, 0x00, 0x22, 0x04, 0x6a, 0x41, 0x01, 0x6a, 0x20, 0x08, 0x49, 0x0d, + 0x00, 0x0b, 0x0b, 0x20, 0x03, 0x20, 0x00, 0x49, 0x04, 0x40, 0x20, 0x02, + 0x20, 0x03, 0x6a, 0x20, 0x00, 0x20, 0x03, 0x6b, 0x10, 0x0d, 0x0b, 0x0b, + 0xf2, 0x03, 0x01, 0x02, 0x7f, 0x20, 0x01, 0x41, 0x01, 0x76, 0x22, 0x02, + 0x41, 0x81, 0xc0, 0x7e, 0x73, 0x20, 0x02, 0x20, 0x00, 0x20, 0x01, 0x73, + 0x41, 0x01, 0x71, 0x1b, 0x22, 0x01, 0x41, 0x01, 0x76, 0x41, 0xff, 0xff, + 0x01, 0x71, 0x22, 0x02, 0x41, 0x81, 0xc0, 0x7e, 0x73, 0x20, 0x02, 0x20, + 0x01, 0x20, 0x00, 0x41, 0xff, 0x01, 0x71, 0x22, 0x01, 0x41, 0x01, 0x76, + 0x73, 0x41, 0x01, 0x71, 0x1b, 0x22, 0x02, 0x41, 0x01, 0x76, 0x41, 0xff, + 0xff, 0x01, 0x71, 0x22, 0x03, 0x41, 0x81, 0xc0, 0x7e, 0x73, 0x20, 0x03, + 0x20, 0x01, 0x41, 0x02, 0x76, 0x20, 0x02, 0x73, 0x41, 0x01, 0x71, 0x1b, + 0x22, 0x02, 0x41, 0x01, 0x76, 0x41, 0xff, 0xff, 0x01, 0x71, 0x22, 0x03, + 0x41, 0x81, 0xc0, 0x7e, 0x73, 0x20, 0x03, 0x20, 0x01, 0x41, 0x03, 0x76, + 0x20, 0x02, 0x73, 0x41, 0x01, 0x71, 0x1b, 0x22, 0x02, 0x41, 0x01, 0x76, + 0x41, 0xff, 0xff, 0x01, 0x71, 0x22, 0x03, 0x41, 0x81, 0xc0, 0x7e, 0x73, + 0x20, 0x03, 0x20, 0x01, 0x41, 0x04, 0x76, 0x20, 0x02, 0x73, 0x41, 0x01, + 0x71, 0x1b, 0x22, 0x02, 0x41, 0x01, 0x76, 0x41, 0xff, 0xff, 0x01, 0x71, + 0x22, 0x03, 0x41, 0x81, 0xc0, 0x7e, 0x73, 0x20, 0x03, 0x20, 0x01, 0x41, + 0x05, 0x76, 0x20, 0x02, 0x73, 0x41, 0x01, 0x71, 0x1b, 0x22, 0x02, 0x41, + 0x01, 0x76, 0x41, 0xff, 0xff, 0x01, 0x71, 0x22, 0x03, 0x41, 0x81, 0xc0, + 0x7e, 0x73, 0x20, 0x03, 0x20, 0x01, 0x41, 0x06, 0x76, 0x20, 0x02, 0x73, + 0x41, 0x01, 0x71, 0x1b, 0x22, 0x02, 0x41, 0x01, 0x76, 0x41, 0xff, 0xff, + 0x01, 0x71, 0x22, 0x03, 0x20, 0x03, 0x41, 0x81, 0xc0, 0x7e, 0x73, 0x20, + 0x02, 0x41, 0x01, 0x71, 0x20, 0x01, 0x41, 0x07, 0x76, 0x46, 0x1b, 0x22, + 0x01, 0x41, 0x01, 0x76, 0x41, 0xff, 0xff, 0x01, 0x71, 0x22, 0x02, 0x41, + 0x81, 0xc0, 0x7e, 0x73, 0x20, 0x02, 0x20, 0x01, 0x20, 0x00, 0x41, 0x08, + 0x76, 0x73, 0x41, 0x01, 0x71, 0x1b, 0x22, 0x01, 0x41, 0x01, 0x76, 0x41, + 0xff, 0xff, 0x01, 0x71, 0x22, 0x02, 0x41, 0x81, 0xc0, 0x7e, 0x73, 0x20, + 0x02, 0x20, 0x01, 0x20, 0x00, 0x41, 0x09, 0x76, 0x73, 0x41, 0x01, 0x71, + 0x1b, 0x22, 0x01, 0x41, 0x01, 0x76, 0x41, 0xff, 0xff, 0x01, 0x71, 0x22, + 0x02, 0x41, 0x81, 0xc0, 0x7e, 0x73, 0x20, 0x02, 0x20, 0x01, 0x20, 0x00, + 0x41, 0x0a, 0x76, 0x73, 0x41, 0x01, 0x71, 0x1b, 0x22, 0x01, 0x41, 0x01, + 0x76, 0x41, 0xff, 0xff, 0x01, 0x71, 0x22, 0x02, 0x41, 0x81, 0xc0, 0x7e, + 0x73, 0x20, 0x02, 0x20, 0x01, 0x20, 0x00, 0x41, 0x0b, 0x76, 0x73, 0x41, + 0x01, 0x71, 0x1b, 0x22, 0x01, 0x41, 0x01, 0x76, 0x41, 0xff, 0xff, 0x01, + 0x71, 0x22, 0x02, 0x41, 0x81, 0xc0, 0x7e, 0x73, 0x20, 0x02, 0x20, 0x01, + 0x20, 0x00, 0x41, 0x0c, 0x76, 0x73, 0x41, 0x01, 0x71, 0x1b, 0x22, 0x01, + 0x41, 0x01, 0x76, 0x41, 0xff, 0xff, 0x01, 0x71, 0x22, 0x02, 0x41, 0x81, + 0xc0, 0x7e, 0x73, 0x20, 0x02, 0x20, 0x01, 0x20, 0x00, 0x41, 0x0d, 0x76, + 0x73, 0x41, 0x01, 0x71, 0x1b, 0x22, 0x01, 0x41, 0x01, 0x76, 0x41, 0xff, + 0xff, 0x01, 0x71, 0x22, 0x02, 0x41, 0x81, 0xc0, 0x7e, 0x73, 0x20, 0x02, + 0x20, 0x01, 0x20, 0x00, 0x41, 0x0e, 0x76, 0x73, 0x41, 0x01, 0x71, 0x1b, + 0x22, 0x01, 0x41, 0x01, 0x76, 0x41, 0xff, 0xff, 0x01, 0x71, 0x22, 0x02, + 0x20, 0x02, 0x41, 0x81, 0xc0, 0x02, 0x73, 0x20, 0x01, 0x41, 0x01, 0x71, + 0x20, 0x00, 0x41, 0x0f, 0x76, 0x46, 0x1b, 0x0b, 0x14, 0x00, 0x20, 0x00, + 0x41, 0x10, 0x76, 0x20, 0x00, 0x41, 0xff, 0xff, 0x03, 0x71, 0x20, 0x01, + 0x10, 0x0a, 0x10, 0x0a, 0x0b, 0x0d, 0x00, 0x20, 0x00, 0x41, 0xff, 0xff, + 0x03, 0x71, 0x20, 0x01, 0x10, 0x0a, 0x0b, 0xae, 0x01, 0x01, 0x02, 0x7f, + 0x02, 0x40, 0x20, 0x01, 0x45, 0x0d, 0x00, 0x20, 0x00, 0x20, 0x01, 0x6a, + 0x22, 0x02, 0x41, 0x7f, 0x6a, 0x41, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x00, + 0x41, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x01, 0x41, 0x03, 0x49, 0x0d, 0x00, + 0x20, 0x02, 0x41, 0x7e, 0x6a, 0x41, 0x00, 0x3a, 0x00, 0x00, 0x20, 0x00, + 0x41, 0x00, 0x3a, 0x00, 0x01, 0x20, 0x02, 0x41, 0x7d, 0x6a, 0x41, 0x00, + 0x3a, 0x00, 0x00, 0x20, 0x00, 0x41, 0x00, 0x3a, 0x00, 0x02, 0x20, 0x01, + 0x41, 0x07, 0x49, 0x0d, 0x00, 0x20, 0x02, 0x41, 0x7c, 0x6a, 0x41, 0x00, + 0x3a, 0x00, 0x00, 0x20, 0x00, 0x41, 0x00, 0x3a, 0x00, 0x03, 0x20, 0x01, + 0x41, 0x09, 0x49, 0x0d, 0x00, 0x20, 0x01, 0x41, 0x00, 0x20, 0x00, 0x6b, + 0x41, 0x03, 0x71, 0x22, 0x01, 0x6b, 0x41, 0x02, 0x76, 0x22, 0x02, 0x45, + 0x0d, 0x00, 0x41, 0x00, 0x20, 0x02, 0x6b, 0x21, 0x02, 0x20, 0x00, 0x20, + 0x01, 0x6a, 0x21, 0x01, 0x03, 0x40, 0x20, 0x01, 0x41, 0x00, 0x36, 0x02, + 0x00, 0x20, 0x01, 0x41, 0x04, 0x6a, 0x21, 0x01, 0x20, 0x02, 0x41, 0x01, + 0x6a, 0x22, 0x00, 0x20, 0x02, 0x4f, 0x20, 0x00, 0x21, 0x02, 0x0d, 0x00, + 0x0b, 0x0b, 0x0b, 0x0a, 0x00, 0x41, 0xa0, 0x16, 0x10, 0x00, 0x36, 0x02, + 0x00, 0x0b, 0x0a, 0x00, 0x41, 0xa4, 0x16, 0x10, 0x00, 0x36, 0x02, 0x00, + 0x0b, 0x0b, 0xc5, 0x02, 0x02, 0x00, 0x41, 0x80, 0x04, 0x0b, 0xb2, 0x02, + 0xb0, 0xd4, 0x40, 0x33, 0x79, 0x6a, 0x14, 0xe7, 0xc1, 0xe3, 0x52, 0xbe, + 0x99, 0x11, 0x08, 0x56, 0xd7, 0x1f, 0x47, 0x07, 0x47, 0x5e, 0xbf, 0x39, + 0xa4, 0xe5, 0x3a, 0x8e, 0x84, 0x8d, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, + 0x65, 0x02, 0x00, 0x00, 0x6a, 0x02, 0x00, 0x00, 0x6f, 0x02, 0x00, 0x00, + 0x74, 0x02, 0x00, 0x00, 0x7d, 0x02, 0x00, 0x00, 0x86, 0x02, 0x00, 0x00, + 0x8f, 0x02, 0x00, 0x00, 0x98, 0x02, 0x00, 0x00, 0xa1, 0x02, 0x00, 0x00, + 0xaa, 0x02, 0x00, 0x00, 0xb3, 0x02, 0x00, 0x00, 0xbc, 0x02, 0x00, 0x00, + 0xc5, 0x02, 0x00, 0x00, 0xce, 0x02, 0x00, 0x00, 0xd7, 0x02, 0x00, 0x00, + 0x35, 0x30, 0x31, 0x32, 0x00, 0x31, 0x32, 0x33, 0x34, 0x00, 0x2d, 0x38, + 0x37, 0x34, 0x00, 0x2b, 0x31, 0x32, 0x32, 0x00, 0x33, 0x35, 0x2e, 0x35, + 0x34, 0x34, 0x30, 0x30, 0x00, 0x2e, 0x31, 0x32, 0x33, 0x34, 0x35, 0x30, + 0x30, 0x00, 0x2d, 0x31, 0x31, 0x30, 0x2e, 0x37, 0x30, 0x30, 0x00, 0x2b, + 0x30, 0x2e, 0x36, 0x34, 0x34, 0x30, 0x30, 0x00, 0x35, 0x2e, 0x35, 0x30, + 0x30, 0x65, 0x2b, 0x33, 0x00, 0x2d, 0x2e, 0x31, 0x32, 0x33, 0x65, 0x2d, + 0x32, 0x00, 0x2d, 0x38, 0x37, 0x65, 0x2b, 0x38, 0x33, 0x32, 0x00, 0x2b, + 0x30, 0x2e, 0x36, 0x65, 0x2d, 0x31, 0x32, 0x00, 0x54, 0x30, 0x2e, 0x33, + 0x65, 0x2d, 0x31, 0x46, 0x00, 0x2d, 0x54, 0x2e, 0x54, 0x2b, 0x2b, 0x54, + 0x71, 0x00, 0x31, 0x54, 0x33, 0x2e, 0x34, 0x65, 0x34, 0x7a, 0x00, 0x33, + 0x34, 0x2e, 0x30, 0x65, 0x2d, 0x54, 0x5e, 0x00, 0x20, 0x02, 0x00, 0x00, + 0x20, 0x02, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x30, 0x02, 0x00, 0x00, + 0x30, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, + 0x50, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x10, 0x0b, 0x00, 0x00, 0x14, 0x0b, 0x00, 0x00, 0x34, 0x03, 0x00, 0x00, + 0x18, 0x0b, 0x00, 0x00, 0x1c, 0x0b, 0x00, 0x41, 0xb4, 0x06, 0x0b, 0x05, + 0x66, 0x00, 0x00, 0x00, 0x01 +}; +unsigned int coremark_minimal_wasm_len = 7769; diff --git a/ext/wasm3/source/extra/fib32.wasm.h b/ext/wasm3/source/extra/fib32.wasm.h new file mode 100644 index 0000000..f553f69 --- /dev/null +++ b/ext/wasm3/source/extra/fib32.wasm.h @@ -0,0 +1,9 @@ +unsigned char fib32_wasm[] = { + 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, + 0x01, 0x7f, 0x01, 0x7f, 0x03, 0x02, 0x01, 0x00, 0x07, 0x07, 0x01, 0x03, + 0x66, 0x69, 0x62, 0x00, 0x00, 0x0a, 0x1f, 0x01, 0x1d, 0x00, 0x20, 0x00, + 0x41, 0x02, 0x49, 0x04, 0x40, 0x20, 0x00, 0x0f, 0x0b, 0x20, 0x00, 0x41, + 0x02, 0x6b, 0x10, 0x00, 0x20, 0x00, 0x41, 0x01, 0x6b, 0x10, 0x00, 0x6a, + 0x0f, 0x0b +}; +unsigned int fib32_wasm_len = 62; diff --git a/ext/wasm3/source/extra/fib32_tail.wasm.h b/ext/wasm3/source/extra/fib32_tail.wasm.h new file mode 100644 index 0000000..132ef97 --- /dev/null +++ b/ext/wasm3/source/extra/fib32_tail.wasm.h @@ -0,0 +1,10 @@ +unsigned char fib32_tail_wasm[] = { + 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0d, 0x02, 0x60, + 0x03, 0x7f, 0x7f, 0x7f, 0x01, 0x7f, 0x60, 0x01, 0x7f, 0x01, 0x7f, 0x03, + 0x03, 0x02, 0x00, 0x01, 0x07, 0x07, 0x01, 0x03, 0x66, 0x69, 0x62, 0x00, + 0x01, 0x0a, 0x26, 0x02, 0x19, 0x00, 0x20, 0x00, 0x45, 0x04, 0x7f, 0x20, + 0x01, 0x05, 0x20, 0x00, 0x41, 0x01, 0x6b, 0x20, 0x02, 0x20, 0x01, 0x20, + 0x02, 0x6a, 0x12, 0x00, 0x0b, 0x0b, 0x0a, 0x00, 0x20, 0x00, 0x41, 0x00, + 0x41, 0x01, 0x12, 0x00, 0x0b +}; +unsigned int fib32_tail_wasm_len = 77; diff --git a/ext/wasm3/source/extra/fib64.wasm.h b/ext/wasm3/source/extra/fib64.wasm.h new file mode 100644 index 0000000..20ae6e7 --- /dev/null +++ b/ext/wasm3/source/extra/fib64.wasm.h @@ -0,0 +1,9 @@ +unsigned char fib64_wasm[] = { + 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, + 0x01, 0x7e, 0x01, 0x7e, 0x03, 0x02, 0x01, 0x00, 0x07, 0x07, 0x01, 0x03, + 0x66, 0x69, 0x62, 0x00, 0x00, 0x0a, 0x1f, 0x01, 0x1d, 0x00, 0x20, 0x00, + 0x42, 0x02, 0x54, 0x04, 0x40, 0x20, 0x00, 0x0f, 0x0b, 0x20, 0x00, 0x42, + 0x02, 0x7d, 0x10, 0x00, 0x20, 0x00, 0x42, 0x01, 0x7d, 0x10, 0x00, 0x7c, + 0x0f, 0x0b +}; +unsigned int fib64_wasm_len = 62; diff --git a/ext/wasm3/source/extra/wasi_core.h b/ext/wasm3/source/extra/wasi_core.h new file mode 100644 index 0000000..6bf42f5 --- /dev/null +++ b/ext/wasm3/source/extra/wasi_core.h @@ -0,0 +1,2764 @@ +/** + * THIS FILE IS AUTO-GENERATED from the following files: + * typenames.witx, wasi_snapshot_preview1.witx + * + * @file + * This file describes the [WASI] interface, consisting of functions, types, + * and defined values (macros). + * + * The interface described here is greatly inspired by [CloudABI]'s clean, + * thoughtfully-designed, capability-oriented, POSIX-style API. + * + * [CloudABI]: https://github.com/NuxiNL/cloudlibc + * [WASI]: https://github.com/WebAssembly/WASI/ + */ + +/* + * File origin: + * https://github.com/CraneStation/wasi-libc/blob/master/libc-bottom-half/headers/public/wasi/api.h + * Revision: + * 2c2fc9a2fddd0927a66f1c142e65c8dab6f5c5d7 + * License: + * CC0 1.0 Universal (CC0 1.0) Public Domain Dedication + * https://creativecommons.org/publicdomain/zero/1.0/ + */ + +#ifndef __wasi_api_h +#define __wasi_api_h + +#include +#include + +#ifdef __cplusplus +// Hacks alert +#undef _Static_assert +#define _Static_assert(...) +#undef _Noreturn +#define _Noreturn +#endif + +_Static_assert(_Alignof(int8_t) == 1, "non-wasi data layout"); +_Static_assert(_Alignof(uint8_t) == 1, "non-wasi data layout"); +_Static_assert(_Alignof(int16_t) == 2, "non-wasi data layout"); +_Static_assert(_Alignof(uint16_t) == 2, "non-wasi data layout"); +_Static_assert(_Alignof(int32_t) == 4, "non-wasi data layout"); +_Static_assert(_Alignof(uint32_t) == 4, "non-wasi data layout"); +_Static_assert(_Alignof(int64_t) == 8, "non-wasi data layout"); +_Static_assert(_Alignof(uint64_t) == 8, "non-wasi data layout"); +// _Static_assert(_Alignof(void*) == 4, "non-wasi data layout"); + +#ifdef __cplusplus +extern "C" { +#endif + +// TODO: Encoding this in witx. +#define __WASI_DIRCOOKIE_START (UINT64_C(0)) +// typedef __SIZE_TYPE__ __wasi_size_t; +typedef uint32_t __wasi_size_t; // fixme for wasm64 + +// _Static_assert(sizeof(__wasi_size_t) == 4, "witx calculated size"); +// _Static_assert(_Alignof(__wasi_size_t) == 4, "witx calculated align"); + +/** + * Non-negative file size or length of a region within a file. + */ +typedef uint64_t __wasi_filesize_t; + +_Static_assert(sizeof(__wasi_filesize_t) == 8, "witx calculated size"); +_Static_assert(_Alignof(__wasi_filesize_t) == 8, "witx calculated align"); + +/** + * Timestamp in nanoseconds. + */ +typedef uint64_t __wasi_timestamp_t; + +_Static_assert(sizeof(__wasi_timestamp_t) == 8, "witx calculated size"); +_Static_assert(_Alignof(__wasi_timestamp_t) == 8, "witx calculated align"); + +/** + * Identifiers for clocks. + */ +typedef uint32_t __wasi_clockid_t; + +/** + * The clock measuring real time. Time value zero corresponds with + * 1970-01-01T00:00:00Z. + */ +#define __WASI_CLOCKID_REALTIME (UINT32_C(0)) + +/** + * The store-wide monotonic clock, which is defined as a clock measuring + * real time, whose value cannot be adjusted and which cannot have negative + * clock jumps. The epoch of this clock is undefined. The absolute time + * value of this clock therefore has no meaning. + */ +#define __WASI_CLOCKID_MONOTONIC (UINT32_C(1)) + +/** + * The CPU-time clock associated with the current process. + */ +#define __WASI_CLOCKID_PROCESS_CPUTIME_ID (UINT32_C(2)) + +/** + * The CPU-time clock associated with the current thread. + */ +#define __WASI_CLOCKID_THREAD_CPUTIME_ID (UINT32_C(3)) + +_Static_assert(sizeof(__wasi_clockid_t) == 4, "witx calculated size"); +_Static_assert(_Alignof(__wasi_clockid_t) == 4, "witx calculated align"); + +/** + * Error codes returned by functions. + * Not all of these error codes are returned by the functions provided by this + * API; some are used in higher-level library layers, and others are provided + * merely for alignment with POSIX. + */ +typedef uint16_t __wasi_errno_t; + +/** + * No error occurred. System call completed successfully. + */ +#define __WASI_ERRNO_SUCCESS (UINT16_C(0)) + +/** + * Argument list too long. + */ +#define __WASI_ERRNO_2BIG (UINT16_C(1)) + +/** + * Permission denied. + */ +#define __WASI_ERRNO_ACCES (UINT16_C(2)) + +/** + * Address in use. + */ +#define __WASI_ERRNO_ADDRINUSE (UINT16_C(3)) + +/** + * Address not available. + */ +#define __WASI_ERRNO_ADDRNOTAVAIL (UINT16_C(4)) + +/** + * Address family not supported. + */ +#define __WASI_ERRNO_AFNOSUPPORT (UINT16_C(5)) + +/** + * Resource unavailable, or operation would block. + */ +#define __WASI_ERRNO_AGAIN (UINT16_C(6)) + +/** + * Connection already in progress. + */ +#define __WASI_ERRNO_ALREADY (UINT16_C(7)) + +/** + * Bad file descriptor. + */ +#define __WASI_ERRNO_BADF (UINT16_C(8)) + +/** + * Bad message. + */ +#define __WASI_ERRNO_BADMSG (UINT16_C(9)) + +/** + * Device or resource busy. + */ +#define __WASI_ERRNO_BUSY (UINT16_C(10)) + +/** + * Operation canceled. + */ +#define __WASI_ERRNO_CANCELED (UINT16_C(11)) + +/** + * No child processes. + */ +#define __WASI_ERRNO_CHILD (UINT16_C(12)) + +/** + * Connection aborted. + */ +#define __WASI_ERRNO_CONNABORTED (UINT16_C(13)) + +/** + * Connection refused. + */ +#define __WASI_ERRNO_CONNREFUSED (UINT16_C(14)) + +/** + * Connection reset. + */ +#define __WASI_ERRNO_CONNRESET (UINT16_C(15)) + +/** + * Resource deadlock would occur. + */ +#define __WASI_ERRNO_DEADLK (UINT16_C(16)) + +/** + * Destination address required. + */ +#define __WASI_ERRNO_DESTADDRREQ (UINT16_C(17)) + +/** + * Mathematics argument out of domain of function. + */ +#define __WASI_ERRNO_DOM (UINT16_C(18)) + +/** + * Reserved. + */ +#define __WASI_ERRNO_DQUOT (UINT16_C(19)) + +/** + * File exists. + */ +#define __WASI_ERRNO_EXIST (UINT16_C(20)) + +/** + * Bad address. + */ +#define __WASI_ERRNO_FAULT (UINT16_C(21)) + +/** + * File too large. + */ +#define __WASI_ERRNO_FBIG (UINT16_C(22)) + +/** + * Host is unreachable. + */ +#define __WASI_ERRNO_HOSTUNREACH (UINT16_C(23)) + +/** + * Identifier removed. + */ +#define __WASI_ERRNO_IDRM (UINT16_C(24)) + +/** + * Illegal byte sequence. + */ +#define __WASI_ERRNO_ILSEQ (UINT16_C(25)) + +/** + * Operation in progress. + */ +#define __WASI_ERRNO_INPROGRESS (UINT16_C(26)) + +/** + * Interrupted function. + */ +#define __WASI_ERRNO_INTR (UINT16_C(27)) + +/** + * Invalid argument. + */ +#define __WASI_ERRNO_INVAL (UINT16_C(28)) + +/** + * I/O error. + */ +#define __WASI_ERRNO_IO (UINT16_C(29)) + +/** + * Socket is connected. + */ +#define __WASI_ERRNO_ISCONN (UINT16_C(30)) + +/** + * Is a directory. + */ +#define __WASI_ERRNO_ISDIR (UINT16_C(31)) + +/** + * Too many levels of symbolic links. + */ +#define __WASI_ERRNO_LOOP (UINT16_C(32)) + +/** + * File descriptor value too large. + */ +#define __WASI_ERRNO_MFILE (UINT16_C(33)) + +/** + * Too many links. + */ +#define __WASI_ERRNO_MLINK (UINT16_C(34)) + +/** + * Message too large. + */ +#define __WASI_ERRNO_MSGSIZE (UINT16_C(35)) + +/** + * Reserved. + */ +#define __WASI_ERRNO_MULTIHOP (UINT16_C(36)) + +/** + * Filename too long. + */ +#define __WASI_ERRNO_NAMETOOLONG (UINT16_C(37)) + +/** + * Network is down. + */ +#define __WASI_ERRNO_NETDOWN (UINT16_C(38)) + +/** + * Connection aborted by network. + */ +#define __WASI_ERRNO_NETRESET (UINT16_C(39)) + +/** + * Network unreachable. + */ +#define __WASI_ERRNO_NETUNREACH (UINT16_C(40)) + +/** + * Too many files open in system. + */ +#define __WASI_ERRNO_NFILE (UINT16_C(41)) + +/** + * No buffer space available. + */ +#define __WASI_ERRNO_NOBUFS (UINT16_C(42)) + +/** + * No such device. + */ +#define __WASI_ERRNO_NODEV (UINT16_C(43)) + +/** + * No such file or directory. + */ +#define __WASI_ERRNO_NOENT (UINT16_C(44)) + +/** + * Executable file format error. + */ +#define __WASI_ERRNO_NOEXEC (UINT16_C(45)) + +/** + * No locks available. + */ +#define __WASI_ERRNO_NOLCK (UINT16_C(46)) + +/** + * Reserved. + */ +#define __WASI_ERRNO_NOLINK (UINT16_C(47)) + +/** + * Not enough space. + */ +#define __WASI_ERRNO_NOMEM (UINT16_C(48)) + +/** + * No message of the desired type. + */ +#define __WASI_ERRNO_NOMSG (UINT16_C(49)) + +/** + * Protocol not available. + */ +#define __WASI_ERRNO_NOPROTOOPT (UINT16_C(50)) + +/** + * No space left on device. + */ +#define __WASI_ERRNO_NOSPC (UINT16_C(51)) + +/** + * Function not supported. + */ +#define __WASI_ERRNO_NOSYS (UINT16_C(52)) + +/** + * The socket is not connected. + */ +#define __WASI_ERRNO_NOTCONN (UINT16_C(53)) + +/** + * Not a directory or a symbolic link to a directory. + */ +#define __WASI_ERRNO_NOTDIR (UINT16_C(54)) + +/** + * Directory not empty. + */ +#define __WASI_ERRNO_NOTEMPTY (UINT16_C(55)) + +/** + * State not recoverable. + */ +#define __WASI_ERRNO_NOTRECOVERABLE (UINT16_C(56)) + +/** + * Not a socket. + */ +#define __WASI_ERRNO_NOTSOCK (UINT16_C(57)) + +/** + * Not supported, or operation not supported on socket. + */ +#define __WASI_ERRNO_NOTSUP (UINT16_C(58)) + +/** + * Inappropriate I/O control operation. + */ +#define __WASI_ERRNO_NOTTY (UINT16_C(59)) + +/** + * No such device or address. + */ +#define __WASI_ERRNO_NXIO (UINT16_C(60)) + +/** + * Value too large to be stored in data type. + */ +#define __WASI_ERRNO_OVERFLOW (UINT16_C(61)) + +/** + * Previous owner died. + */ +#define __WASI_ERRNO_OWNERDEAD (UINT16_C(62)) + +/** + * Operation not permitted. + */ +#define __WASI_ERRNO_PERM (UINT16_C(63)) + +/** + * Broken pipe. + */ +#define __WASI_ERRNO_PIPE (UINT16_C(64)) + +/** + * Protocol error. + */ +#define __WASI_ERRNO_PROTO (UINT16_C(65)) + +/** + * Protocol not supported. + */ +#define __WASI_ERRNO_PROTONOSUPPORT (UINT16_C(66)) + +/** + * Protocol wrong type for socket. + */ +#define __WASI_ERRNO_PROTOTYPE (UINT16_C(67)) + +/** + * Result too large. + */ +#define __WASI_ERRNO_RANGE (UINT16_C(68)) + +/** + * Read-only file system. + */ +#define __WASI_ERRNO_ROFS (UINT16_C(69)) + +/** + * Invalid seek. + */ +#define __WASI_ERRNO_SPIPE (UINT16_C(70)) + +/** + * No such process. + */ +#define __WASI_ERRNO_SRCH (UINT16_C(71)) + +/** + * Reserved. + */ +#define __WASI_ERRNO_STALE (UINT16_C(72)) + +/** + * Connection timed out. + */ +#define __WASI_ERRNO_TIMEDOUT (UINT16_C(73)) + +/** + * Text file busy. + */ +#define __WASI_ERRNO_TXTBSY (UINT16_C(74)) + +/** + * Cross-device link. + */ +#define __WASI_ERRNO_XDEV (UINT16_C(75)) + +/** + * Extension: Capabilities insufficient. + */ +#define __WASI_ERRNO_NOTCAPABLE (UINT16_C(76)) + +_Static_assert(sizeof(__wasi_errno_t) == 2, "witx calculated size"); +_Static_assert(_Alignof(__wasi_errno_t) == 2, "witx calculated align"); + +/** + * File descriptor rights, determining which actions may be performed. + */ +typedef uint64_t __wasi_rights_t; + +/** + * The right to invoke `fd_datasync`. + * If `path_open` is set, includes the right to invoke + * `path_open` with `fdflags::dsync`. + */ +#define __WASI_RIGHTS_FD_DATASYNC (UINT64_C(1)) + +/** + * The right to invoke `fd_read` and `sock_recv`. + * If `rights::fd_seek` is set, includes the right to invoke `fd_pread`. + */ +#define __WASI_RIGHTS_FD_READ (UINT64_C(2)) + +/** + * The right to invoke `fd_seek`. This flag implies `rights::fd_tell`. + */ +#define __WASI_RIGHTS_FD_SEEK (UINT64_C(4)) + +/** + * The right to invoke `fd_fdstat_set_flags`. + */ +#define __WASI_RIGHTS_FD_FDSTAT_SET_FLAGS (UINT64_C(8)) + +/** + * The right to invoke `fd_sync`. + * If `path_open` is set, includes the right to invoke + * `path_open` with `fdflags::rsync` and `fdflags::dsync`. + */ +#define __WASI_RIGHTS_FD_SYNC (UINT64_C(16)) + +/** + * The right to invoke `fd_seek` in such a way that the file offset + * remains unaltered (i.e., `whence::cur` with offset zero), or to + * invoke `fd_tell`. + */ +#define __WASI_RIGHTS_FD_TELL (UINT64_C(32)) + +/** + * The right to invoke `fd_write` and `sock_send`. + * If `rights::fd_seek` is set, includes the right to invoke `fd_pwrite`. + */ +#define __WASI_RIGHTS_FD_WRITE (UINT64_C(64)) + +/** + * The right to invoke `fd_advise`. + */ +#define __WASI_RIGHTS_FD_ADVISE (UINT64_C(128)) + +/** + * The right to invoke `fd_allocate`. + */ +#define __WASI_RIGHTS_FD_ALLOCATE (UINT64_C(256)) + +/** + * The right to invoke `path_create_directory`. + */ +#define __WASI_RIGHTS_PATH_CREATE_DIRECTORY (UINT64_C(512)) + +/** + * If `path_open` is set, the right to invoke `path_open` with `oflags::creat`. + */ +#define __WASI_RIGHTS_PATH_CREATE_FILE (UINT64_C(1024)) + +/** + * The right to invoke `path_link` with the file descriptor as the + * source directory. + */ +#define __WASI_RIGHTS_PATH_LINK_SOURCE (UINT64_C(2048)) + +/** + * The right to invoke `path_link` with the file descriptor as the + * target directory. + */ +#define __WASI_RIGHTS_PATH_LINK_TARGET (UINT64_C(4096)) + +/** + * The right to invoke `path_open`. + */ +#define __WASI_RIGHTS_PATH_OPEN (UINT64_C(8192)) + +/** + * The right to invoke `fd_readdir`. + */ +#define __WASI_RIGHTS_FD_READDIR (UINT64_C(16384)) + +/** + * The right to invoke `path_readlink`. + */ +#define __WASI_RIGHTS_PATH_READLINK (UINT64_C(32768)) + +/** + * The right to invoke `path_rename` with the file descriptor as the source directory. + */ +#define __WASI_RIGHTS_PATH_RENAME_SOURCE (UINT64_C(65536)) + +/** + * The right to invoke `path_rename` with the file descriptor as the target directory. + */ +#define __WASI_RIGHTS_PATH_RENAME_TARGET (UINT64_C(131072)) + +/** + * The right to invoke `path_filestat_get`. + */ +#define __WASI_RIGHTS_PATH_FILESTAT_GET (UINT64_C(262144)) + +/** + * The right to change a file's size (there is no `path_filestat_set_size`). + * If `path_open` is set, includes the right to invoke `path_open` with `oflags::trunc`. + */ +#define __WASI_RIGHTS_PATH_FILESTAT_SET_SIZE (UINT64_C(524288)) + +/** + * The right to invoke `path_filestat_set_times`. + */ +#define __WASI_RIGHTS_PATH_FILESTAT_SET_TIMES (UINT64_C(1048576)) + +/** + * The right to invoke `fd_filestat_get`. + */ +#define __WASI_RIGHTS_FD_FILESTAT_GET (UINT64_C(2097152)) + +/** + * The right to invoke `fd_filestat_set_size`. + */ +#define __WASI_RIGHTS_FD_FILESTAT_SET_SIZE (UINT64_C(4194304)) + +/** + * The right to invoke `fd_filestat_set_times`. + */ +#define __WASI_RIGHTS_FD_FILESTAT_SET_TIMES (UINT64_C(8388608)) + +/** + * The right to invoke `path_symlink`. + */ +#define __WASI_RIGHTS_PATH_SYMLINK (UINT64_C(16777216)) + +/** + * The right to invoke `path_remove_directory`. + */ +#define __WASI_RIGHTS_PATH_REMOVE_DIRECTORY (UINT64_C(33554432)) + +/** + * The right to invoke `path_unlink_file`. + */ +#define __WASI_RIGHTS_PATH_UNLINK_FILE (UINT64_C(67108864)) + +/** + * If `rights::fd_read` is set, includes the right to invoke `poll_oneoff` to subscribe to `eventtype::fd_read`. + * If `rights::fd_write` is set, includes the right to invoke `poll_oneoff` to subscribe to `eventtype::fd_write`. + */ +#define __WASI_RIGHTS_POLL_FD_READWRITE (UINT64_C(134217728)) + +/** + * The right to invoke `sock_shutdown`. + */ +#define __WASI_RIGHTS_SOCK_SHUTDOWN (UINT64_C(268435456)) + +_Static_assert(sizeof(__wasi_rights_t) == 8, "witx calculated size"); +_Static_assert(_Alignof(__wasi_rights_t) == 8, "witx calculated align"); + +/** + * A file descriptor index. + */ +typedef uint32_t __wasi_fd_t; + +_Static_assert(sizeof(__wasi_fd_t) == 4, "witx calculated size"); +_Static_assert(_Alignof(__wasi_fd_t) == 4, "witx calculated align"); + +/** + * A region of memory for scatter/gather reads. + */ +typedef struct __wasi_iovec_t { + /** + * The address of the buffer to be filled. + */ + uint8_t * buf; + + /** + * The length of the buffer to be filled. + */ + __wasi_size_t buf_len; + +} __wasi_iovec_t; + +// _Static_assert(sizeof(__wasi_iovec_t) == 8, "witx calculated size"); +// _Static_assert(_Alignof(__wasi_iovec_t) == 4, "witx calculated align"); +// _Static_assert(offsetof(__wasi_iovec_t, buf) == 0, "witx calculated offset"); +// _Static_assert(offsetof(__wasi_iovec_t, buf_len) == 4, "witx calculated offset"); + +/** + * A region of memory for scatter/gather writes. + */ +typedef struct __wasi_ciovec_t { + /** + * The address of the buffer to be written. + */ + const uint8_t * buf; + + /** + * The length of the buffer to be written. + */ + __wasi_size_t buf_len; + +} __wasi_ciovec_t; + +// _Static_assert(sizeof(__wasi_ciovec_t) == 8, "witx calculated size"); +// _Static_assert(_Alignof(__wasi_ciovec_t) == 4, "witx calculated align"); +// _Static_assert(offsetof(__wasi_ciovec_t, buf) == 0, "witx calculated offset"); +// _Static_assert(offsetof(__wasi_ciovec_t, buf_len) == 4, "witx calculated offset"); + +/** + * Relative offset within a file. + */ +typedef int64_t __wasi_filedelta_t; + +_Static_assert(sizeof(__wasi_filedelta_t) == 8, "witx calculated size"); +_Static_assert(_Alignof(__wasi_filedelta_t) == 8, "witx calculated align"); + +/** + * The position relative to which to set the offset of the file descriptor. + */ +typedef uint8_t __wasi_whence_t; + +/** + * Seek relative to start-of-file. + */ +#define __WASI_WHENCE_SET (UINT8_C(0)) + +/** + * Seek relative to current position. + */ +#define __WASI_WHENCE_CUR (UINT8_C(1)) + +/** + * Seek relative to end-of-file. + */ +#define __WASI_WHENCE_END (UINT8_C(2)) + +_Static_assert(sizeof(__wasi_whence_t) == 1, "witx calculated size"); +_Static_assert(_Alignof(__wasi_whence_t) == 1, "witx calculated align"); + +/** + * A reference to the offset of a directory entry. + * + * The value 0 signifies the start of the directory. + */ +typedef uint64_t __wasi_dircookie_t; + +_Static_assert(sizeof(__wasi_dircookie_t) == 8, "witx calculated size"); +_Static_assert(_Alignof(__wasi_dircookie_t) == 8, "witx calculated align"); + +/** + * The type for the $d_namlen field of $dirent. + */ +typedef uint32_t __wasi_dirnamlen_t; + +_Static_assert(sizeof(__wasi_dirnamlen_t) == 4, "witx calculated size"); +_Static_assert(_Alignof(__wasi_dirnamlen_t) == 4, "witx calculated align"); + +/** + * File serial number that is unique within its file system. + */ +typedef uint64_t __wasi_inode_t; + +_Static_assert(sizeof(__wasi_inode_t) == 8, "witx calculated size"); +_Static_assert(_Alignof(__wasi_inode_t) == 8, "witx calculated align"); + +/** + * The type of a file descriptor or file. + */ +typedef uint8_t __wasi_filetype_t; + +/** + * The type of the file descriptor or file is unknown or is different from any of the other types specified. + */ +#define __WASI_FILETYPE_UNKNOWN (UINT8_C(0)) + +/** + * The file descriptor or file refers to a block device inode. + */ +#define __WASI_FILETYPE_BLOCK_DEVICE (UINT8_C(1)) + +/** + * The file descriptor or file refers to a character device inode. + */ +#define __WASI_FILETYPE_CHARACTER_DEVICE (UINT8_C(2)) + +/** + * The file descriptor or file refers to a directory inode. + */ +#define __WASI_FILETYPE_DIRECTORY (UINT8_C(3)) + +/** + * The file descriptor or file refers to a regular file inode. + */ +#define __WASI_FILETYPE_REGULAR_FILE (UINT8_C(4)) + +/** + * The file descriptor or file refers to a datagram socket. + */ +#define __WASI_FILETYPE_SOCKET_DGRAM (UINT8_C(5)) + +/** + * The file descriptor or file refers to a byte-stream socket. + */ +#define __WASI_FILETYPE_SOCKET_STREAM (UINT8_C(6)) + +/** + * The file refers to a symbolic link inode. + */ +#define __WASI_FILETYPE_SYMBOLIC_LINK (UINT8_C(7)) + +_Static_assert(sizeof(__wasi_filetype_t) == 1, "witx calculated size"); +_Static_assert(_Alignof(__wasi_filetype_t) == 1, "witx calculated align"); + +/** + * A directory entry. + */ +typedef struct __wasi_dirent_t { + /** + * The offset of the next directory entry stored in this directory. + */ + __wasi_dircookie_t d_next; + + /** + * The serial number of the file referred to by this directory entry. + */ + __wasi_inode_t d_ino; + + /** + * The length of the name of the directory entry. + */ + __wasi_dirnamlen_t d_namlen; + + /** + * The type of the file referred to by this directory entry. + */ + __wasi_filetype_t d_type; + +} __wasi_dirent_t; + +_Static_assert(sizeof(__wasi_dirent_t) == 24, "witx calculated size"); +_Static_assert(_Alignof(__wasi_dirent_t) == 8, "witx calculated align"); +_Static_assert(offsetof(__wasi_dirent_t, d_next) == 0, "witx calculated offset"); +_Static_assert(offsetof(__wasi_dirent_t, d_ino) == 8, "witx calculated offset"); +_Static_assert(offsetof(__wasi_dirent_t, d_namlen) == 16, "witx calculated offset"); +_Static_assert(offsetof(__wasi_dirent_t, d_type) == 20, "witx calculated offset"); + +/** + * File or memory access pattern advisory information. + */ +typedef uint8_t __wasi_advice_t; + +/** + * The application has no advice to give on its behavior with respect to the specified data. + */ +#define __WASI_ADVICE_NORMAL (UINT8_C(0)) + +/** + * The application expects to access the specified data sequentially from lower offsets to higher offsets. + */ +#define __WASI_ADVICE_SEQUENTIAL (UINT8_C(1)) + +/** + * The application expects to access the specified data in a random order. + */ +#define __WASI_ADVICE_RANDOM (UINT8_C(2)) + +/** + * The application expects to access the specified data in the near future. + */ +#define __WASI_ADVICE_WILLNEED (UINT8_C(3)) + +/** + * The application expects that it will not access the specified data in the near future. + */ +#define __WASI_ADVICE_DONTNEED (UINT8_C(4)) + +/** + * The application expects to access the specified data once and then not reuse it thereafter. + */ +#define __WASI_ADVICE_NOREUSE (UINT8_C(5)) + +_Static_assert(sizeof(__wasi_advice_t) == 1, "witx calculated size"); +_Static_assert(_Alignof(__wasi_advice_t) == 1, "witx calculated align"); + +/** + * File descriptor flags. + */ +typedef uint16_t __wasi_fdflags_t; + +/** + * Append mode: Data written to the file is always appended to the file's end. + */ +#define __WASI_FDFLAGS_APPEND (UINT16_C(1)) + +/** + * Write according to synchronized I/O data integrity completion. Only the data stored in the file is synchronized. + */ +#define __WASI_FDFLAGS_DSYNC (UINT16_C(2)) + +/** + * Non-blocking mode. + */ +#define __WASI_FDFLAGS_NONBLOCK (UINT16_C(4)) + +/** + * Synchronized read I/O operations. + */ +#define __WASI_FDFLAGS_RSYNC (UINT16_C(8)) + +/** + * Write according to synchronized I/O file integrity completion. In + * addition to synchronizing the data stored in the file, the implementation + * may also synchronously update the file's metadata. + */ +#define __WASI_FDFLAGS_SYNC (UINT16_C(16)) + +_Static_assert(sizeof(__wasi_fdflags_t) == 2, "witx calculated size"); +_Static_assert(_Alignof(__wasi_fdflags_t) == 2, "witx calculated align"); + +/** + * File descriptor attributes. + */ +typedef struct __wasi_fdstat_t { + /** + * File type. + */ + __wasi_filetype_t fs_filetype; + + /** + * File descriptor flags. + */ + __wasi_fdflags_t fs_flags; + + /** + * Rights that apply to this file descriptor. + */ + __wasi_rights_t fs_rights_base; + + /** + * Maximum set of rights that may be installed on new file descriptors that + * are created through this file descriptor, e.g., through `path_open`. + */ + __wasi_rights_t fs_rights_inheriting; + +} __wasi_fdstat_t; + +_Static_assert(sizeof(__wasi_fdstat_t) == 24, "witx calculated size"); +_Static_assert(_Alignof(__wasi_fdstat_t) == 8, "witx calculated align"); +_Static_assert(offsetof(__wasi_fdstat_t, fs_filetype) == 0, "witx calculated offset"); +_Static_assert(offsetof(__wasi_fdstat_t, fs_flags) == 2, "witx calculated offset"); +_Static_assert(offsetof(__wasi_fdstat_t, fs_rights_base) == 8, "witx calculated offset"); +_Static_assert(offsetof(__wasi_fdstat_t, fs_rights_inheriting) == 16, "witx calculated offset"); + +/** + * Identifier for a device containing a file system. Can be used in combination + * with `inode` to uniquely identify a file or directory in the filesystem. + */ +typedef uint64_t __wasi_device_t; + +_Static_assert(sizeof(__wasi_device_t) == 8, "witx calculated size"); +_Static_assert(_Alignof(__wasi_device_t) == 8, "witx calculated align"); + +/** + * Which file time attributes to adjust. + */ +typedef uint16_t __wasi_fstflags_t; + +/** + * Adjust the last data access timestamp to the value stored in `filestat::atim`. + */ +#define __WASI_FSTFLAGS_ATIM (UINT16_C(1)) + +/** + * Adjust the last data access timestamp to the time of clock `clockid::realtime`. + */ +#define __WASI_FSTFLAGS_ATIM_NOW (UINT16_C(2)) + +/** + * Adjust the last data modification timestamp to the value stored in `filestat::mtim`. + */ +#define __WASI_FSTFLAGS_MTIM (UINT16_C(4)) + +/** + * Adjust the last data modification timestamp to the time of clock `clockid::realtime`. + */ +#define __WASI_FSTFLAGS_MTIM_NOW (UINT16_C(8)) + +_Static_assert(sizeof(__wasi_fstflags_t) == 2, "witx calculated size"); +_Static_assert(_Alignof(__wasi_fstflags_t) == 2, "witx calculated align"); + +/** + * Flags determining the method of how paths are resolved. + */ +typedef uint32_t __wasi_lookupflags_t; + +/** + * As long as the resolved path corresponds to a symbolic link, it is expanded. + */ +#define __WASI_LOOKUPFLAGS_SYMLINK_FOLLOW (UINT32_C(1)) + +_Static_assert(sizeof(__wasi_lookupflags_t) == 4, "witx calculated size"); +_Static_assert(_Alignof(__wasi_lookupflags_t) == 4, "witx calculated align"); + +/** + * Open flags used by `path_open`. + */ +typedef uint16_t __wasi_oflags_t; + +/** + * Create file if it does not exist. + */ +#define __WASI_OFLAGS_CREAT (UINT16_C(1)) + +/** + * Fail if not a directory. + */ +#define __WASI_OFLAGS_DIRECTORY (UINT16_C(2)) + +/** + * Fail if file already exists. + */ +#define __WASI_OFLAGS_EXCL (UINT16_C(4)) + +/** + * Truncate file to size 0. + */ +#define __WASI_OFLAGS_TRUNC (UINT16_C(8)) + +_Static_assert(sizeof(__wasi_oflags_t) == 2, "witx calculated size"); +_Static_assert(_Alignof(__wasi_oflags_t) == 2, "witx calculated align"); + +/** + * Number of hard links to an inode. + */ +typedef uint64_t __wasi_linkcount_t; + +_Static_assert(sizeof(__wasi_linkcount_t) == 8, "witx calculated size"); +_Static_assert(_Alignof(__wasi_linkcount_t) == 8, "witx calculated align"); + +/** + * File attributes. + */ +typedef struct __wasi_filestat_t { + /** + * Device ID of device containing the file. + */ + __wasi_device_t dev; + + /** + * File serial number. + */ + __wasi_inode_t ino; + + /** + * File type. + */ + __wasi_filetype_t filetype; + + /** + * Number of hard links to the file. + */ + __wasi_linkcount_t nlink; + + /** + * For regular files, the file size in bytes. For symbolic links, the length in bytes of the pathname contained in the symbolic link. + */ + __wasi_filesize_t size; + + /** + * Last data access timestamp. + */ + __wasi_timestamp_t atim; + + /** + * Last data modification timestamp. + */ + __wasi_timestamp_t mtim; + + /** + * Last file status change timestamp. + */ + __wasi_timestamp_t ctim; + +} __wasi_filestat_t; + +_Static_assert(sizeof(__wasi_filestat_t) == 64, "witx calculated size"); +_Static_assert(_Alignof(__wasi_filestat_t) == 8, "witx calculated align"); +_Static_assert(offsetof(__wasi_filestat_t, dev) == 0, "witx calculated offset"); +_Static_assert(offsetof(__wasi_filestat_t, ino) == 8, "witx calculated offset"); +_Static_assert(offsetof(__wasi_filestat_t, filetype) == 16, "witx calculated offset"); +_Static_assert(offsetof(__wasi_filestat_t, nlink) == 24, "witx calculated offset"); +_Static_assert(offsetof(__wasi_filestat_t, size) == 32, "witx calculated offset"); +_Static_assert(offsetof(__wasi_filestat_t, atim) == 40, "witx calculated offset"); +_Static_assert(offsetof(__wasi_filestat_t, mtim) == 48, "witx calculated offset"); +_Static_assert(offsetof(__wasi_filestat_t, ctim) == 56, "witx calculated offset"); + +/** + * User-provided value that may be attached to objects that is retained when + * extracted from the implementation. + */ +typedef uint64_t __wasi_userdata_t; + +_Static_assert(sizeof(__wasi_userdata_t) == 8, "witx calculated size"); +_Static_assert(_Alignof(__wasi_userdata_t) == 8, "witx calculated align"); + +/** + * Type of a subscription to an event or its occurrence. + */ +typedef uint8_t __wasi_eventtype_t; + +/** + * The time value of clock `subscription_clock::id` has + * reached timestamp `subscription_clock::timeout`. + */ +#define __WASI_EVENTTYPE_CLOCK (UINT8_C(0)) + +/** + * File descriptor `subscription_fd_readwrite::file_descriptor` has data + * available for reading. This event always triggers for regular files. + */ +#define __WASI_EVENTTYPE_FD_READ (UINT8_C(1)) + +/** + * File descriptor `subscription_fd_readwrite::file_descriptor` has capacity + * available for writing. This event always triggers for regular files. + */ +#define __WASI_EVENTTYPE_FD_WRITE (UINT8_C(2)) + +_Static_assert(sizeof(__wasi_eventtype_t) == 1, "witx calculated size"); +_Static_assert(_Alignof(__wasi_eventtype_t) == 1, "witx calculated align"); + +/** + * The state of the file descriptor subscribed to with + * `eventtype::fd_read` or `eventtype::fd_write`. + */ +typedef uint16_t __wasi_eventrwflags_t; + +/** + * The peer of this socket has closed or disconnected. + */ +#define __WASI_EVENTRWFLAGS_FD_READWRITE_HANGUP (UINT16_C(1)) + +_Static_assert(sizeof(__wasi_eventrwflags_t) == 2, "witx calculated size"); +_Static_assert(_Alignof(__wasi_eventrwflags_t) == 2, "witx calculated align"); + +/** + * The contents of an $event when type is `eventtype::fd_read` or + * `eventtype::fd_write`. + */ +typedef struct __wasi_event_fd_readwrite_t { + /** + * The number of bytes available for reading or writing. + */ + __wasi_filesize_t nbytes; + + /** + * The state of the file descriptor. + */ + __wasi_eventrwflags_t flags; + +} __wasi_event_fd_readwrite_t; + +_Static_assert(sizeof(__wasi_event_fd_readwrite_t) == 16, "witx calculated size"); +_Static_assert(_Alignof(__wasi_event_fd_readwrite_t) == 8, "witx calculated align"); +_Static_assert(offsetof(__wasi_event_fd_readwrite_t, nbytes) == 0, "witx calculated offset"); +_Static_assert(offsetof(__wasi_event_fd_readwrite_t, flags) == 8, "witx calculated offset"); + +/** + * The contents of an $event. + */ +typedef union __wasi_event_u_t { + /** + * When type is `eventtype::fd_read` or `eventtype::fd_write`: + */ + __wasi_event_fd_readwrite_t fd_readwrite; + +} __wasi_event_u_t; + +_Static_assert(sizeof(__wasi_event_u_t) == 16, "witx calculated size"); +_Static_assert(_Alignof(__wasi_event_u_t) == 8, "witx calculated align"); + +/** + * An event that occurred. + */ +typedef struct __wasi_event_t { + /** + * User-provided value that got attached to `subscription::userdata`. + */ + __wasi_userdata_t userdata; + + /** + * If non-zero, an error that occurred while processing the subscription request. + */ + __wasi_errno_t error; + + /** + * The type of the event that occurred. + */ + __wasi_eventtype_t type; + + /** + * The contents of the event. + */ + __wasi_event_u_t u; + +} __wasi_event_t; + +_Static_assert(sizeof(__wasi_event_t) == 32, "witx calculated size"); +_Static_assert(_Alignof(__wasi_event_t) == 8, "witx calculated align"); +_Static_assert(offsetof(__wasi_event_t, userdata) == 0, "witx calculated offset"); +_Static_assert(offsetof(__wasi_event_t, error) == 8, "witx calculated offset"); +_Static_assert(offsetof(__wasi_event_t, type) == 10, "witx calculated offset"); +_Static_assert(offsetof(__wasi_event_t, u) == 16, "witx calculated offset"); + +/** + * Flags determining how to interpret the timestamp provided in + * `subscription_clock::timeout`. + */ +typedef uint16_t __wasi_subclockflags_t; + +/** + * If set, treat the timestamp provided in + * `subscription_clock::timeout` as an absolute timestamp of clock + * `subscription_clock::id`. If clear, treat the timestamp + * provided in `subscription_clock::timeout` relative to the + * current time value of clock `subscription_clock::id`. + */ +#define __WASI_SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME (UINT16_C(1)) + +_Static_assert(sizeof(__wasi_subclockflags_t) == 2, "witx calculated size"); +_Static_assert(_Alignof(__wasi_subclockflags_t) == 2, "witx calculated align"); + +/** + * The contents of a $subscription when type is `eventtype::clock`. + */ +typedef struct __wasi_subscription_clock_t { + /** + * The clock against which to compare the timestamp. + */ + __wasi_clockid_t id; + + /** + * The absolute or relative timestamp. + */ + __wasi_timestamp_t timeout; + + /** + * The amount of time that the implementation may wait additionally + * to coalesce with other events. + */ + __wasi_timestamp_t precision; + + /** + * Flags specifying whether the timeout is absolute or relative + */ + __wasi_subclockflags_t flags; + +} __wasi_subscription_clock_t; + +_Static_assert(sizeof(__wasi_subscription_clock_t) == 32, "witx calculated size"); +_Static_assert(_Alignof(__wasi_subscription_clock_t) == 8, "witx calculated align"); +_Static_assert(offsetof(__wasi_subscription_clock_t, id) == 0, "witx calculated offset"); +_Static_assert(offsetof(__wasi_subscription_clock_t, timeout) == 8, "witx calculated offset"); +_Static_assert(offsetof(__wasi_subscription_clock_t, precision) == 16, "witx calculated offset"); +_Static_assert(offsetof(__wasi_subscription_clock_t, flags) == 24, "witx calculated offset"); + +/** + * The contents of a $subscription when type is type is + * `eventtype::fd_read` or `eventtype::fd_write`. + */ +typedef struct __wasi_subscription_fd_readwrite_t { + /** + * The file descriptor on which to wait for it to become ready for reading or writing. + */ + __wasi_fd_t file_descriptor; + +} __wasi_subscription_fd_readwrite_t; + +_Static_assert(sizeof(__wasi_subscription_fd_readwrite_t) == 4, "witx calculated size"); +_Static_assert(_Alignof(__wasi_subscription_fd_readwrite_t) == 4, "witx calculated align"); +_Static_assert(offsetof(__wasi_subscription_fd_readwrite_t, file_descriptor) == 0, "witx calculated offset"); + +/** + * The contents of a $subscription. + */ +typedef union __wasi_subscription_u_t { + /** + * When type is `eventtype::clock`: + */ + __wasi_subscription_clock_t clock; + + /** + * When type is `eventtype::fd_read` or `eventtype::fd_write`: + */ + __wasi_subscription_fd_readwrite_t fd_readwrite; + +} __wasi_subscription_u_t; + +_Static_assert(sizeof(__wasi_subscription_u_t) == 32, "witx calculated size"); +_Static_assert(_Alignof(__wasi_subscription_u_t) == 8, "witx calculated align"); + +/** + * Subscription to an event. + */ +typedef struct __wasi_subscription_t { + /** + * User-provided value that is attached to the subscription in the + * implementation and returned through `event::userdata`. + */ + __wasi_userdata_t userdata; + + /** + * The type of the event to which to subscribe. + */ + __wasi_eventtype_t type; + + /** + * The contents of the subscription. + */ + __wasi_subscription_u_t u; + +} __wasi_subscription_t; + +_Static_assert(sizeof(__wasi_subscription_t) == 48, "witx calculated size"); +_Static_assert(_Alignof(__wasi_subscription_t) == 8, "witx calculated align"); +_Static_assert(offsetof(__wasi_subscription_t, userdata) == 0, "witx calculated offset"); +_Static_assert(offsetof(__wasi_subscription_t, type) == 8, "witx calculated offset"); +_Static_assert(offsetof(__wasi_subscription_t, u) == 16, "witx calculated offset"); + +/** + * Exit code generated by a process when exiting. + */ +typedef uint32_t __wasi_exitcode_t; + +_Static_assert(sizeof(__wasi_exitcode_t) == 4, "witx calculated size"); +_Static_assert(_Alignof(__wasi_exitcode_t) == 4, "witx calculated align"); + +/** + * Signal condition. + */ +typedef uint8_t __wasi_signal_t; + +/** + * No signal. Note that POSIX has special semantics for `kill(pid, 0)`, + * so this value is reserved. + */ +#define __WASI_SIGNAL_NONE (UINT8_C(0)) + +/** + * Hangup. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_HUP (UINT8_C(1)) + +/** + * Terminate interrupt signal. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_INT (UINT8_C(2)) + +/** + * Terminal quit signal. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_QUIT (UINT8_C(3)) + +/** + * Illegal instruction. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_ILL (UINT8_C(4)) + +/** + * Trace/breakpoint trap. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_TRAP (UINT8_C(5)) + +/** + * Process abort signal. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_ABRT (UINT8_C(6)) + +/** + * Access to an undefined portion of a memory object. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_BUS (UINT8_C(7)) + +/** + * Erroneous arithmetic operation. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_FPE (UINT8_C(8)) + +/** + * Kill. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_KILL (UINT8_C(9)) + +/** + * User-defined signal 1. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_USR1 (UINT8_C(10)) + +/** + * Invalid memory reference. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_SEGV (UINT8_C(11)) + +/** + * User-defined signal 2. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_USR2 (UINT8_C(12)) + +/** + * Write on a pipe with no one to read it. + * Action: Ignored. + */ +#define __WASI_SIGNAL_PIPE (UINT8_C(13)) + +/** + * Alarm clock. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_ALRM (UINT8_C(14)) + +/** + * Termination signal. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_TERM (UINT8_C(15)) + +/** + * Child process terminated, stopped, or continued. + * Action: Ignored. + */ +#define __WASI_SIGNAL_CHLD (UINT8_C(16)) + +/** + * Continue executing, if stopped. + * Action: Continues executing, if stopped. + */ +#define __WASI_SIGNAL_CONT (UINT8_C(17)) + +/** + * Stop executing. + * Action: Stops executing. + */ +#define __WASI_SIGNAL_STOP (UINT8_C(18)) + +/** + * Terminal stop signal. + * Action: Stops executing. + */ +#define __WASI_SIGNAL_TSTP (UINT8_C(19)) + +/** + * Background process attempting read. + * Action: Stops executing. + */ +#define __WASI_SIGNAL_TTIN (UINT8_C(20)) + +/** + * Background process attempting write. + * Action: Stops executing. + */ +#define __WASI_SIGNAL_TTOU (UINT8_C(21)) + +/** + * High bandwidth data is available at a socket. + * Action: Ignored. + */ +#define __WASI_SIGNAL_URG (UINT8_C(22)) + +/** + * CPU time limit exceeded. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_XCPU (UINT8_C(23)) + +/** + * File size limit exceeded. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_XFSZ (UINT8_C(24)) + +/** + * Virtual timer expired. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_VTALRM (UINT8_C(25)) + +/** + * Profiling timer expired. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_PROF (UINT8_C(26)) + +/** + * Window changed. + * Action: Ignored. + */ +#define __WASI_SIGNAL_WINCH (UINT8_C(27)) + +/** + * I/O possible. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_POLL (UINT8_C(28)) + +/** + * Power failure. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_PWR (UINT8_C(29)) + +/** + * Bad system call. + * Action: Terminates the process. + */ +#define __WASI_SIGNAL_SYS (UINT8_C(30)) + +_Static_assert(sizeof(__wasi_signal_t) == 1, "witx calculated size"); +_Static_assert(_Alignof(__wasi_signal_t) == 1, "witx calculated align"); + +/** + * Flags provided to `sock_recv`. + */ +typedef uint16_t __wasi_riflags_t; + +/** + * Returns the message without removing it from the socket's receive queue. + */ +#define __WASI_RIFLAGS_RECV_PEEK (UINT16_C(1)) + +/** + * On byte-stream sockets, block until the full amount of data can be returned. + */ +#define __WASI_RIFLAGS_RECV_WAITALL (UINT16_C(2)) + +_Static_assert(sizeof(__wasi_riflags_t) == 2, "witx calculated size"); +_Static_assert(_Alignof(__wasi_riflags_t) == 2, "witx calculated align"); + +/** + * Flags returned by `sock_recv`. + */ +typedef uint16_t __wasi_roflags_t; + +/** + * Returned by `sock_recv`: Message data has been truncated. + */ +#define __WASI_ROFLAGS_RECV_DATA_TRUNCATED (UINT16_C(1)) + +_Static_assert(sizeof(__wasi_roflags_t) == 2, "witx calculated size"); +_Static_assert(_Alignof(__wasi_roflags_t) == 2, "witx calculated align"); + +/** + * Flags provided to `sock_send`. As there are currently no flags + * defined, it must be set to zero. + */ +typedef uint16_t __wasi_siflags_t; + +_Static_assert(sizeof(__wasi_siflags_t) == 2, "witx calculated size"); +_Static_assert(_Alignof(__wasi_siflags_t) == 2, "witx calculated align"); + +/** + * Which channels on a socket to shut down. + */ +typedef uint8_t __wasi_sdflags_t; + +/** + * Disables further receive operations. + */ +#define __WASI_SDFLAGS_RD (UINT8_C(1)) + +/** + * Disables further send operations. + */ +#define __WASI_SDFLAGS_WR (UINT8_C(2)) + +_Static_assert(sizeof(__wasi_sdflags_t) == 1, "witx calculated size"); +_Static_assert(_Alignof(__wasi_sdflags_t) == 1, "witx calculated align"); + +/** + * Identifiers for preopened capabilities. + */ +typedef uint8_t __wasi_preopentype_t; + +/** + * A pre-opened directory. + */ +#define __WASI_PREOPENTYPE_DIR (UINT8_C(0)) + +_Static_assert(sizeof(__wasi_preopentype_t) == 1, "witx calculated size"); +_Static_assert(_Alignof(__wasi_preopentype_t) == 1, "witx calculated align"); + +/** + * The contents of a $prestat when type is `preopentype::dir`. + */ +typedef struct __wasi_prestat_dir_t { + /** + * The length of the directory name for use with `fd_prestat_dir_name`. + */ + __wasi_size_t pr_name_len; + +} __wasi_prestat_dir_t; + +_Static_assert(sizeof(__wasi_prestat_dir_t) == 4, "witx calculated size"); +_Static_assert(_Alignof(__wasi_prestat_dir_t) == 4, "witx calculated align"); +_Static_assert(offsetof(__wasi_prestat_dir_t, pr_name_len) == 0, "witx calculated offset"); + +/** + * The contents of an $prestat. + */ +typedef union __wasi_prestat_u_t { + /** + * When type is `preopentype::dir`: + */ + __wasi_prestat_dir_t dir; + +} __wasi_prestat_u_t; + +_Static_assert(sizeof(__wasi_prestat_u_t) == 4, "witx calculated size"); +_Static_assert(_Alignof(__wasi_prestat_u_t) == 4, "witx calculated align"); + +/** + * Information about a pre-opened capability. + */ +typedef struct __wasi_prestat_t { + /** + * The type of the pre-opened capability. + */ + __wasi_preopentype_t pr_type; + + /** + * The contents of the information. + */ + __wasi_prestat_u_t u; + +} __wasi_prestat_t; + +_Static_assert(sizeof(__wasi_prestat_t) == 8, "witx calculated size"); +_Static_assert(_Alignof(__wasi_prestat_t) == 4, "witx calculated align"); +_Static_assert(offsetof(__wasi_prestat_t, pr_type) == 0, "witx calculated offset"); +_Static_assert(offsetof(__wasi_prestat_t, u) == 4, "witx calculated offset"); + +/** + * @defgroup wasi_snapshot_preview1 + * @{ + */ + +/** + * Read command-line argument data. + * The size of the array should match that returned by `args_sizes_get` + */ +__wasi_errno_t __wasi_args_get( + uint8_t * * argv, + + uint8_t * argv_buf +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("args_get"), + __warn_unused_result__ +)); + +/** + * Return command-line argument data sizes. + */ +__wasi_errno_t __wasi_args_sizes_get( + /** + * The number of arguments. + */ + __wasi_size_t *argc, + /** + * The size of the argument string data. + */ + __wasi_size_t *argv_buf_size +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("args_sizes_get"), + __warn_unused_result__ +)); + +/** + * Read environment variable data. + * The sizes of the buffers should match that returned by `environ_sizes_get`. + */ +__wasi_errno_t __wasi_environ_get( + uint8_t * * environ, + + uint8_t * environ_buf +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("environ_get"), + __warn_unused_result__ +)); + +/** + * Return command-line argument data sizes. + */ +__wasi_errno_t __wasi_environ_sizes_get( + /** + * The number of arguments. + */ + __wasi_size_t *argc, + /** + * The size of the argument string data. + */ + __wasi_size_t *argv_buf_size +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("environ_sizes_get"), + __warn_unused_result__ +)); + +/** + * Return the resolution of a clock. + * Implementations are required to provide a non-zero value for supported clocks. For unsupported clocks, + * return `errno::inval`. + * Note: This is similar to `clock_getres` in POSIX. + */ +__wasi_errno_t __wasi_clock_res_get( + /** + * The clock for which to return the resolution. + */ + __wasi_clockid_t id, + + /** + * The resolution of the clock. + */ + __wasi_timestamp_t *resolution +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("clock_res_get"), + __warn_unused_result__ +)); + +/** + * Return the time value of a clock. + * Note: This is similar to `clock_gettime` in POSIX. + */ +__wasi_errno_t __wasi_clock_time_get( + /** + * The clock for which to return the time. + */ + __wasi_clockid_t id, + + /** + * The maximum lag (exclusive) that the returned time value may have, compared to its actual value. + */ + __wasi_timestamp_t precision, + + /** + * The time value of the clock. + */ + __wasi_timestamp_t *time +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("clock_time_get"), + __warn_unused_result__ +)); + +/** + * Provide file advisory information on a file descriptor. + * Note: This is similar to `posix_fadvise` in POSIX. + */ +__wasi_errno_t __wasi_fd_advise( + __wasi_fd_t fd, + + /** + * The offset within the file to which the advisory applies. + */ + __wasi_filesize_t offset, + + /** + * The length of the region to which the advisory applies. + */ + __wasi_filesize_t len, + + /** + * The advice. + */ + __wasi_advice_t advice +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_advise"), + __warn_unused_result__ +)); + +/** + * Force the allocation of space in a file. + * Note: This is similar to `posix_fallocate` in POSIX. + */ +__wasi_errno_t __wasi_fd_allocate( + __wasi_fd_t fd, + + /** + * The offset at which to start the allocation. + */ + __wasi_filesize_t offset, + + /** + * The length of the area that is allocated. + */ + __wasi_filesize_t len +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_allocate"), + __warn_unused_result__ +)); + +/** + * Close a file descriptor. + * Note: This is similar to `close` in POSIX. + */ +__wasi_errno_t __wasi_fd_close( + __wasi_fd_t fd +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_close"), + __warn_unused_result__ +)); + +/** + * Synchronize the data of a file to disk. + * Note: This is similar to `fdatasync` in POSIX. + */ +__wasi_errno_t __wasi_fd_datasync( + __wasi_fd_t fd +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_datasync"), + __warn_unused_result__ +)); + +/** + * Get the attributes of a file descriptor. + * Note: This returns similar flags to `fsync(fd, F_GETFL)` in POSIX, as well as additional fields. + */ +__wasi_errno_t __wasi_fd_fdstat_get( + __wasi_fd_t fd, + + /** + * The buffer where the file descriptor's attributes are stored. + */ + __wasi_fdstat_t *stat +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_fdstat_get"), + __warn_unused_result__ +)); + +/** + * Adjust the flags associated with a file descriptor. + * Note: This is similar to `fcntl(fd, F_SETFL, flags)` in POSIX. + */ +__wasi_errno_t __wasi_fd_fdstat_set_flags( + __wasi_fd_t fd, + + /** + * The desired values of the file descriptor flags. + */ + __wasi_fdflags_t flags +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_fdstat_set_flags"), + __warn_unused_result__ +)); + +/** + * Adjust the rights associated with a file descriptor. + * This can only be used to remove rights, and returns `errno::notcapable` if called in a way that would attempt to add rights + */ +__wasi_errno_t __wasi_fd_fdstat_set_rights( + __wasi_fd_t fd, + + /** + * The desired rights of the file descriptor. + */ + __wasi_rights_t fs_rights_base, + + __wasi_rights_t fs_rights_inheriting +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_fdstat_set_rights"), + __warn_unused_result__ +)); + +/** + * Return the attributes of an open file. + */ +__wasi_errno_t __wasi_fd_filestat_get( + __wasi_fd_t fd, + + /** + * The buffer where the file's attributes are stored. + */ + __wasi_filestat_t *buf +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_filestat_get"), + __warn_unused_result__ +)); + +/** + * Adjust the size of an open file. If this increases the file's size, the extra bytes are filled with zeros. + * Note: This is similar to `ftruncate` in POSIX. + */ +__wasi_errno_t __wasi_fd_filestat_set_size( + __wasi_fd_t fd, + + /** + * The desired file size. + */ + __wasi_filesize_t size +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_filestat_set_size"), + __warn_unused_result__ +)); + +/** + * Adjust the timestamps of an open file or directory. + * Note: This is similar to `futimens` in POSIX. + */ +__wasi_errno_t __wasi_fd_filestat_set_times( + __wasi_fd_t fd, + + /** + * The desired values of the data access timestamp. + */ + __wasi_timestamp_t atim, + + /** + * The desired values of the data modification timestamp. + */ + __wasi_timestamp_t mtim, + + /** + * A bitmask indicating which timestamps to adjust. + */ + __wasi_fstflags_t fst_flags +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_filestat_set_times"), + __warn_unused_result__ +)); + +/** + * Read from a file descriptor, without using and updating the file descriptor's offset. + * Note: This is similar to `preadv` in POSIX. + */ +__wasi_errno_t __wasi_fd_pread( + __wasi_fd_t fd, + + /** + * List of scatter/gather vectors in which to store data. + */ + const __wasi_iovec_t *iovs, + + /** + * The length of the array pointed to by `iovs`. + */ + size_t iovs_len, + + /** + * The offset within the file at which to read. + */ + __wasi_filesize_t offset, + + /** + * The number of bytes read. + */ + __wasi_size_t *nread +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_pread"), + __warn_unused_result__ +)); + +/** + * Return a description of the given preopened file descriptor. + */ +__wasi_errno_t __wasi_fd_prestat_get( + __wasi_fd_t fd, + + /** + * The buffer where the description is stored. + */ + __wasi_prestat_t *buf +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_prestat_get"), + __warn_unused_result__ +)); + +/** + * Return a description of the given preopened file descriptor. + */ +__wasi_errno_t __wasi_fd_prestat_dir_name( + __wasi_fd_t fd, + + /** + * A buffer into which to write the preopened directory name. + */ + uint8_t * path, + + __wasi_size_t path_len +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_prestat_dir_name"), + __warn_unused_result__ +)); + +/** + * Write to a file descriptor, without using and updating the file descriptor's offset. + * Note: This is similar to `pwritev` in POSIX. + */ +__wasi_errno_t __wasi_fd_pwrite( + __wasi_fd_t fd, + + /** + * List of scatter/gather vectors from which to retrieve data. + */ + const __wasi_ciovec_t *iovs, + + /** + * The length of the array pointed to by `iovs`. + */ + size_t iovs_len, + + /** + * The offset within the file at which to write. + */ + __wasi_filesize_t offset, + + /** + * The number of bytes written. + */ + __wasi_size_t *nwritten +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_pwrite"), + __warn_unused_result__ +)); + +/** + * Read from a file descriptor. + * Note: This is similar to `readv` in POSIX. + */ +__wasi_errno_t __wasi_fd_read( + __wasi_fd_t fd, + + /** + * List of scatter/gather vectors to which to store data. + */ + const __wasi_iovec_t *iovs, + + /** + * The length of the array pointed to by `iovs`. + */ + size_t iovs_len, + + /** + * The number of bytes read. + */ + __wasi_size_t *nread +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_read"), + __warn_unused_result__ +)); + +/** + * Read directory entries from a directory. + * When successful, the contents of the output buffer consist of a sequence of + * directory entries. Each directory entry consists of a dirent_t object, + * followed by dirent_t::d_namlen bytes holding the name of the directory + * entry. + * This function fills the output buffer as much as possible, potentially + * truncating the last directory entry. This allows the caller to grow its + * read buffer size in case it's too small to fit a single large directory + * entry, or skip the oversized directory entry. + */ +__wasi_errno_t __wasi_fd_readdir( + __wasi_fd_t fd, + + /** + * The buffer where directory entries are stored + */ + uint8_t * buf, + + __wasi_size_t buf_len, + + /** + * The location within the directory to start reading + */ + __wasi_dircookie_t cookie, + + /** + * The number of bytes stored in the read buffer. If less than the size of the read buffer, the end of the directory has been reached. + */ + __wasi_size_t *bufused +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_readdir"), + __warn_unused_result__ +)); + +/** + * Atomically replace a file descriptor by renumbering another file descriptor. + * Due to the strong focus on thread safety, this environment does not provide + * a mechanism to duplicate or renumber a file descriptor to an arbitrary + * number, like `dup2()`. This would be prone to race conditions, as an actual + * file descriptor with the same number could be allocated by a different + * thread at the same time. + * This function provides a way to atomically renumber file descriptors, which + * would disappear if `dup2()` were to be removed entirely. + */ +__wasi_errno_t __wasi_fd_renumber( + __wasi_fd_t fd, + + /** + * The file descriptor to overwrite. + */ + __wasi_fd_t to +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_renumber"), + __warn_unused_result__ +)); + +/** + * Move the offset of a file descriptor. + * Note: This is similar to `lseek` in POSIX. + */ +__wasi_errno_t __wasi_fd_seek( + __wasi_fd_t fd, + + /** + * The number of bytes to move. + */ + __wasi_filedelta_t offset, + + /** + * The base from which the offset is relative. + */ + __wasi_whence_t whence, + + /** + * The new offset of the file descriptor, relative to the start of the file. + */ + __wasi_filesize_t *newoffset +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_seek"), + __warn_unused_result__ +)); + +/** + * Synchronize the data and metadata of a file to disk. + * Note: This is similar to `fsync` in POSIX. + */ +__wasi_errno_t __wasi_fd_sync( + __wasi_fd_t fd +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_sync"), + __warn_unused_result__ +)); + +/** + * Return the current offset of a file descriptor. + * Note: This is similar to `lseek(fd, 0, SEEK_CUR)` in POSIX. + */ +__wasi_errno_t __wasi_fd_tell( + __wasi_fd_t fd, + + /** + * The current offset of the file descriptor, relative to the start of the file. + */ + __wasi_filesize_t *offset +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_tell"), + __warn_unused_result__ +)); + +/** + * Write to a file descriptor. + * Note: This is similar to `writev` in POSIX. + */ +__wasi_errno_t __wasi_fd_write( + __wasi_fd_t fd, + + /** + * List of scatter/gather vectors from which to retrieve data. + */ + const __wasi_ciovec_t *iovs, + + /** + * The length of the array pointed to by `iovs`. + */ + size_t iovs_len, + + /** + * The number of bytes written. + */ + __wasi_size_t *nwritten +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("fd_write"), + __warn_unused_result__ +)); + +/** + * Create a directory. + * Note: This is similar to `mkdirat` in POSIX. + */ +__wasi_errno_t __wasi_path_create_directory( + __wasi_fd_t fd, + + /** + * The path at which to create the directory. + */ + const char *path, + + /** + * The length of the buffer pointed to by `path`. + */ + size_t path_len +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("path_create_directory"), + __warn_unused_result__ +)); + +/** + * Return the attributes of a file or directory. + * Note: This is similar to `stat` in POSIX. + */ +__wasi_errno_t __wasi_path_filestat_get( + __wasi_fd_t fd, + + /** + * Flags determining the method of how the path is resolved. + */ + __wasi_lookupflags_t flags, + + /** + * The path of the file or directory to inspect. + */ + const char *path, + + /** + * The length of the buffer pointed to by `path`. + */ + size_t path_len, + + /** + * The buffer where the file's attributes are stored. + */ + __wasi_filestat_t *buf +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("path_filestat_get"), + __warn_unused_result__ +)); + +/** + * Adjust the timestamps of a file or directory. + * Note: This is similar to `utimensat` in POSIX. + */ +__wasi_errno_t __wasi_path_filestat_set_times( + __wasi_fd_t fd, + + /** + * Flags determining the method of how the path is resolved. + */ + __wasi_lookupflags_t flags, + + /** + * The path of the file or directory to operate on. + */ + const char *path, + + /** + * The length of the buffer pointed to by `path`. + */ + size_t path_len, + + /** + * The desired values of the data access timestamp. + */ + __wasi_timestamp_t atim, + + /** + * The desired values of the data modification timestamp. + */ + __wasi_timestamp_t mtim, + + /** + * A bitmask indicating which timestamps to adjust. + */ + __wasi_fstflags_t fst_flags +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("path_filestat_set_times"), + __warn_unused_result__ +)); + +/** + * Create a hard link. + * Note: This is similar to `linkat` in POSIX. + */ +__wasi_errno_t __wasi_path_link( + __wasi_fd_t old_fd, + + /** + * Flags determining the method of how the path is resolved. + */ + __wasi_lookupflags_t old_flags, + + /** + * The source path from which to link. + */ + const char *old_path, + + /** + * The length of the buffer pointed to by `old_path`. + */ + size_t old_path_len, + + /** + * The working directory at which the resolution of the new path starts. + */ + __wasi_fd_t new_fd, + + /** + * The destination path at which to create the hard link. + */ + const char *new_path, + + /** + * The length of the buffer pointed to by `new_path`. + */ + size_t new_path_len +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("path_link"), + __warn_unused_result__ +)); + +/** + * Open a file or directory. + * The returned file descriptor is not guaranteed to be the lowest-numbered + * file descriptor not currently open; it is randomized to prevent + * applications from depending on making assumptions about indexes, since this + * is error-prone in multi-threaded contexts. The returned file descriptor is + * guaranteed to be less than 2**31. + * Note: This is similar to `openat` in POSIX. + */ +__wasi_errno_t __wasi_path_open( + __wasi_fd_t fd, + + /** + * Flags determining the method of how the path is resolved. + */ + __wasi_lookupflags_t dirflags, + + /** + * The relative path of the file or directory to open, relative to the + * `path_open::fd` directory. + */ + const char *path, + + /** + * The length of the buffer pointed to by `path`. + */ + size_t path_len, + + /** + * The method by which to open the file. + */ + __wasi_oflags_t oflags, + + /** + * The initial rights of the newly created file descriptor. The + * implementation is allowed to return a file descriptor with fewer rights + * than specified, if and only if those rights do not apply to the type of + * file being opened. + * The *base* rights are rights that will apply to operations using the file + * descriptor itself, while the *inheriting* rights are rights that apply to + * file descriptors derived from it. + */ + __wasi_rights_t fs_rights_base, + + __wasi_rights_t fs_rights_inherting, + + __wasi_fdflags_t fdflags, + + /** + * The file descriptor of the file that has been opened. + */ + __wasi_fd_t *opened_fd +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("path_open"), + __warn_unused_result__ +)); + +/** + * Read the contents of a symbolic link. + * Note: This is similar to `readlinkat` in POSIX. + */ +__wasi_errno_t __wasi_path_readlink( + __wasi_fd_t fd, + + /** + * The path of the symbolic link from which to read. + */ + const char *path, + + /** + * The length of the buffer pointed to by `path`. + */ + size_t path_len, + + /** + * The buffer to which to write the contents of the symbolic link. + */ + uint8_t * buf, + + __wasi_size_t buf_len, + + /** + * The number of bytes placed in the buffer. + */ + __wasi_size_t *bufused +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("path_readlink"), + __warn_unused_result__ +)); + +/** + * Remove a directory. + * Return `errno::notempty` if the directory is not empty. + * Note: This is similar to `unlinkat(fd, path, AT_REMOVEDIR)` in POSIX. + */ +__wasi_errno_t __wasi_path_remove_directory( + __wasi_fd_t fd, + + /** + * The path to a directory to remove. + */ + const char *path, + + /** + * The length of the buffer pointed to by `path`. + */ + size_t path_len +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("path_remove_directory"), + __warn_unused_result__ +)); + +/** + * Rename a file or directory. + * Note: This is similar to `renameat` in POSIX. + */ +__wasi_errno_t __wasi_path_rename( + __wasi_fd_t fd, + + /** + * The source path of the file or directory to rename. + */ + const char *old_path, + + /** + * The length of the buffer pointed to by `old_path`. + */ + size_t old_path_len, + + /** + * The working directory at which the resolution of the new path starts. + */ + __wasi_fd_t new_fd, + + /** + * The destination path to which to rename the file or directory. + */ + const char *new_path, + + /** + * The length of the buffer pointed to by `new_path`. + */ + size_t new_path_len +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("path_rename"), + __warn_unused_result__ +)); + +/** + * Create a symbolic link. + * Note: This is similar to `symlinkat` in POSIX. + */ +__wasi_errno_t __wasi_path_symlink( + /** + * The contents of the symbolic link. + */ + const char *old_path, + + /** + * The length of the buffer pointed to by `old_path`. + */ + size_t old_path_len, + + __wasi_fd_t fd, + + /** + * The destination path at which to create the symbolic link. + */ + const char *new_path, + + /** + * The length of the buffer pointed to by `new_path`. + */ + size_t new_path_len +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("path_symlink"), + __warn_unused_result__ +)); + +/** + * Unlink a file. + * Return `errno::isdir` if the path refers to a directory. + * Note: This is similar to `unlinkat(fd, path, 0)` in POSIX. + */ +__wasi_errno_t __wasi_path_unlink_file( + __wasi_fd_t fd, + + /** + * The path to a file to unlink. + */ + const char *path, + + /** + * The length of the buffer pointed to by `path`. + */ + size_t path_len +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("path_unlink_file"), + __warn_unused_result__ +)); + +/** + * Concurrently poll for the occurrence of a set of events. + */ +__wasi_errno_t __wasi_poll_oneoff( + /** + * The events to which to subscribe. + */ + const __wasi_subscription_t * in, + + /** + * The events that have occurred. + */ + __wasi_event_t * out, + + /** + * Both the number of subscriptions and events. + */ + __wasi_size_t nsubscriptions, + + /** + * The number of events stored. + */ + __wasi_size_t *nevents +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("poll_oneoff"), + __warn_unused_result__ +)); + +/** + * Terminate the process normally. An exit code of 0 indicates successful + * termination of the program. The meanings of other values is dependent on + * the environment. + */ +_Noreturn void __wasi_proc_exit( + /** + * The exit code returned by the process. + */ + __wasi_exitcode_t rval +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("proc_exit")) +)); + +/** + * Send a signal to the process of the calling thread. + * Note: This is similar to `raise` in POSIX. + */ +__wasi_errno_t __wasi_proc_raise( + /** + * The signal condition to trigger. + */ + __wasi_signal_t sig +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("proc_raise"), + __warn_unused_result__ +)); + +/** + * Temporarily yield execution of the calling thread. + * Note: This is similar to `sched_yield` in POSIX. + */ +__wasi_errno_t __wasi_sched_yield( + void +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("sched_yield"), + __warn_unused_result__ +)); + +/** + * Write high-quality random data into a buffer. + * This function blocks when the implementation is unable to immediately + * provide sufficient high-quality random data. + * This function may execute slowly, so when large mounts of random data are + * required, it's advisable to use this function to seed a pseudo-random + * number generator, rather than to provide the random data directly. + */ +__wasi_errno_t __wasi_random_get( + /** + * The buffer to fill with random data. + */ + uint8_t * buf, + + __wasi_size_t buf_len +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("random_get"), + __warn_unused_result__ +)); + +/** + * Receive a message from a socket. + * Note: This is similar to `recv` in POSIX, though it also supports reading + * the data into multiple buffers in the manner of `readv`. + */ +__wasi_errno_t __wasi_sock_recv( + __wasi_fd_t fd, + + /** + * List of scatter/gather vectors to which to store data. + */ + const __wasi_iovec_t *ri_data, + + /** + * The length of the array pointed to by `ri_data`. + */ + size_t ri_data_len, + + /** + * Message flags. + */ + __wasi_riflags_t ri_flags, + + /** + * Number of bytes stored in ri_data. + */ + __wasi_size_t *ro_datalen, + /** + * Message flags. + */ + __wasi_roflags_t *ro_flags +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("sock_recv"), + __warn_unused_result__ +)); + +/** + * Send a message on a socket. + * Note: This is similar to `send` in POSIX, though it also supports writing + * the data from multiple buffers in the manner of `writev`. + */ +__wasi_errno_t __wasi_sock_send( + __wasi_fd_t fd, + + /** + * List of scatter/gather vectors to which to retrieve data + */ + const __wasi_ciovec_t *si_data, + + /** + * The length of the array pointed to by `si_data`. + */ + size_t si_data_len, + + /** + * Message flags. + */ + __wasi_siflags_t si_flags, + + /** + * Number of bytes transmitted. + */ + __wasi_size_t *so_datalen +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // __import_name__("sock_send"), + __warn_unused_result__ +)); + +/** + * Shut down socket send and receive channels. + * Note: This is similar to `shutdown` in POSIX. + */ +__wasi_errno_t __wasi_sock_shutdown( + __wasi_fd_t fd, + + /** + * Which channels on the socket to shut down. + */ + __wasi_sdflags_t how +) __attribute__(( + // __import_module__("wasi_snapshot_preview1"), + // // __import_name__("sock_shutdown"), + __warn_unused_result__ +)); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ext/wasm3/source/m3_api_libc.c b/ext/wasm3/source/m3_api_libc.c new file mode 100644 index 0000000..1c9649a --- /dev/null +++ b/ext/wasm3/source/m3_api_libc.c @@ -0,0 +1,245 @@ +// +// m3_api_libc.c +// +// Created by Volodymyr Shymanskyy on 11/20/19. +// Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. +// + +#define _POSIX_C_SOURCE 200809L + +#include "m3_api_libc.h" + +#include "m3_env.h" +#include "m3_exception.h" + +#include +#include +#include + +typedef uint32_t wasm_ptr_t; +typedef uint32_t wasm_size_t; + +m3ApiRawFunction(m3_libc_abort) +{ + m3ApiTrap(m3Err_trapAbort); +} + +m3ApiRawFunction(m3_libc_exit) +{ + m3ApiGetArg (int32_t, code) + + m3ApiTrap(m3Err_trapExit); +} + + +m3ApiRawFunction(m3_libc_memset) +{ + m3ApiReturnType (int32_t) + + m3ApiGetArgMem (void*, i_ptr) + m3ApiGetArg (int32_t, i_value) + m3ApiGetArg (wasm_size_t, i_size) + + m3ApiCheckMem(i_ptr, i_size); + + u32 result = m3ApiPtrToOffset(memset (i_ptr, i_value, i_size)); + m3ApiReturn(result); +} + +m3ApiRawFunction(m3_libc_memmove) +{ + m3ApiReturnType (int32_t) + + m3ApiGetArgMem (void*, o_dst) + m3ApiGetArgMem (void*, i_src) + m3ApiGetArg (wasm_size_t, i_size) + + m3ApiCheckMem(o_dst, i_size); + m3ApiCheckMem(i_src, i_size); + + u32 result = m3ApiPtrToOffset(memmove (o_dst, i_src, i_size)); + m3ApiReturn(result); +} + +m3ApiRawFunction(m3_libc_print) +{ + m3ApiReturnType (uint32_t) + + m3ApiGetArgMem (void*, i_ptr) + m3ApiGetArg (wasm_size_t, i_size) + + m3ApiCheckMem(i_ptr, i_size); + + fwrite(i_ptr, i_size, 1, stdout); + fflush(stdout); + + m3ApiReturn(i_size); +} + +static +void internal_itoa(int n, char s[], int radix) +{ + static char const HEXDIGITS[0x10] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + }; + + int i, j, sign; + char c; + + if ((sign = n) < 0) { n = -n; } + i = 0; + do { + s[i++] = HEXDIGITS[n % radix]; + } while ((n /= radix) > 0); + + if (sign < 0) { s[i++] = '-'; } + s[i] = '\0'; + + // reverse + for (i = 0, j = strlen(s)-1; i +# define USE_NEW_WASI + +#elif __has_include("wasi/core.h") +# warning "Using legacy WASI headers" +# include +# define __WASI_ERRNO_SUCCESS __WASI_ESUCCESS +# define __WASI_ERRNO_INVAL __WASI_EINVAL + +#else +# error "Missing WASI headers" +#endif + +static m3_wasi_context_t* wasi_context; + +typedef size_t __wasi_size_t; + +static inline +const void* copy_iov_to_host(IM3Runtime runtime, void* _mem, __wasi_iovec_t* host_iov, __wasi_iovec_t* wasi_iov, int32_t iovs_len) +{ + // Convert wasi memory offsets to host addresses + for (int i = 0; i < iovs_len; i++) { + host_iov[i].buf = m3ApiOffsetToPtr(wasi_iov[i].buf); + host_iov[i].buf_len = wasi_iov[i].buf_len; + m3ApiCheckMem(host_iov[i].buf, host_iov[i].buf_len); + } + m3ApiSuccess(); +} + +#if d_m3EnableWasiTracing + +const char* wasi_errno2str(__wasi_errno_t err) +{ + switch (err) { + case 0: return "ESUCCESS"; + case 1: return "E2BIG"; + case 2: return "EACCES"; + case 3: return "EADDRINUSE"; + case 4: return "EADDRNOTAVAIL"; + case 5: return "EAFNOSUPPORT"; + case 6: return "EAGAIN"; + case 7: return "EALREADY"; + case 8: return "EBADF"; + case 9: return "EBADMSG"; + case 10: return "EBUSY"; + case 11: return "ECANCELED"; + case 12: return "ECHILD"; + case 13: return "ECONNABORTED"; + case 14: return "ECONNREFUSED"; + case 15: return "ECONNRESET"; + case 16: return "EDEADLK"; + case 17: return "EDESTADDRREQ"; + case 18: return "EDOM"; + case 19: return "EDQUOT"; + case 20: return "EEXIST"; + case 21: return "EFAULT"; + case 22: return "EFBIG"; + case 23: return "EHOSTUNREACH"; + case 24: return "EIDRM"; + case 25: return "EILSEQ"; + case 26: return "EINPROGRESS"; + case 27: return "EINTR"; + case 28: return "EINVAL"; + case 29: return "EIO"; + case 30: return "EISCONN"; + case 31: return "EISDIR"; + case 32: return "ELOOP"; + case 33: return "EMFILE"; + case 34: return "EMLINK"; + case 35: return "EMSGSIZE"; + case 36: return "EMULTIHOP"; + case 37: return "ENAMETOOLONG"; + case 38: return "ENETDOWN"; + case 39: return "ENETRESET"; + case 40: return "ENETUNREACH"; + case 41: return "ENFILE"; + case 42: return "ENOBUFS"; + case 43: return "ENODEV"; + case 44: return "ENOENT"; + case 45: return "ENOEXEC"; + case 46: return "ENOLCK"; + case 47: return "ENOLINK"; + case 48: return "ENOMEM"; + case 49: return "ENOMSG"; + case 50: return "ENOPROTOOPT"; + case 51: return "ENOSPC"; + case 52: return "ENOSYS"; + case 53: return "ENOTCONN"; + case 54: return "ENOTDIR"; + case 55: return "ENOTEMPTY"; + case 56: return "ENOTRECOVERABLE"; + case 57: return "ENOTSOCK"; + case 58: return "ENOTSUP"; + case 59: return "ENOTTY"; + case 60: return "ENXIO"; + case 61: return "EOVERFLOW"; + case 62: return "EOWNERDEAD"; + case 63: return "EPERM"; + case 64: return "EPIPE"; + case 65: return "EPROTO"; + case 66: return "EPROTONOSUPPORT"; + case 67: return "EPROTOTYPE"; + case 68: return "ERANGE"; + case 69: return "EROFS"; + case 70: return "ESPIPE"; + case 71: return "ESRCH"; + case 72: return "ESTALE"; + case 73: return "ETIMEDOUT"; + case 74: return "ETXTBSY"; + case 75: return "EXDEV"; + case 76: return "ENOTCAPABLE"; + default: return ""; + } +} + +# define WASI_TRACE(fmt, ...) { fprintf(stderr, "%s " fmt, __FUNCTION__+16, ##__VA_ARGS__); fprintf(stderr, " => %s\n", wasi_errno2str(ret)); } +#else +# define WASI_TRACE(fmt, ...) +#endif + +/* + * WASI API implementation + */ + +m3ApiRawFunction(m3_wasi_generic_args_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint32_t * , argv) + m3ApiGetArgMem (char * , argv_buf) + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context == NULL) { m3ApiReturn(__WASI_ERRNO_INVAL); } + + m3ApiCheckMem(argv, context->argc * sizeof(uint32_t)); + + for (u32 i = 0; i < context->argc; ++i) + { + m3ApiWriteMem32(&argv[i], m3ApiPtrToOffset(argv_buf)); + + size_t len = strlen (context->argv[i]); + + m3ApiCheckMem(argv_buf, len); + memcpy (argv_buf, context->argv[i], len); + argv_buf += len; + * argv_buf++ = 0; + } + + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_args_sizes_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (__wasi_size_t * , argc) + m3ApiGetArgMem (__wasi_size_t * , argv_buf_size) + + m3ApiCheckMem(argc, sizeof(__wasi_size_t)); + m3ApiCheckMem(argv_buf_size, sizeof(__wasi_size_t)); + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context == NULL) { m3ApiReturn(__WASI_ERRNO_INVAL); } + + __wasi_size_t buf_len = 0; + for (u32 i = 0; i < context->argc; ++i) + { + buf_len += strlen (context->argv[i]) + 1; + } + + m3ApiWriteMem32(argc, context->argc); + m3ApiWriteMem32(argv_buf_size, buf_len); + + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_environ_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint32_t * , env) + m3ApiGetArgMem (char * , env_buf) + + __wasi_errno_t ret; + __wasi_size_t env_count, env_buf_size; + + ret = __wasi_environ_sizes_get(&env_count, &env_buf_size); + if (ret != __WASI_ERRNO_SUCCESS) m3ApiReturn(ret); + + m3ApiCheckMem(env, env_count * sizeof(uint32_t)); + m3ApiCheckMem(env_buf, env_buf_size); + + ret = __wasi_environ_get(env, env_buf); + if (ret != __WASI_ERRNO_SUCCESS) m3ApiReturn(ret); + + for (u32 i = 0; i < env_count; ++i) { + env[i] = m3ApiPtrToOffset (env[i]); + } + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_environ_sizes_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (__wasi_size_t * , env_count) + m3ApiGetArgMem (__wasi_size_t * , env_buf_size) + + m3ApiCheckMem(env_count, sizeof(__wasi_size_t)); + m3ApiCheckMem(env_buf_size, sizeof(__wasi_size_t)); + + __wasi_errno_t ret = __wasi_environ_sizes_get(env_count, env_buf_size); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_prestat_dir_name) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (char * , path) + m3ApiGetArg (__wasi_size_t , path_len) + + m3ApiCheckMem(path, path_len); + + __wasi_errno_t ret = __wasi_fd_prestat_dir_name(fd, path, path_len); + + WASI_TRACE("fd:%d, len:%d | path:%s", fd, path_len, path); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_prestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (__wasi_prestat_t * , buf) + + m3ApiCheckMem(buf, sizeof(__wasi_prestat_t)); + + __wasi_errno_t ret = __wasi_fd_prestat_get(fd, buf); + + WASI_TRACE("fd:%d | type:%d, name_len:%d", fd, buf->pr_type, buf->u.dir.pr_name_len); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_fdstat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (__wasi_fdstat_t * , fdstat) + + m3ApiCheckMem(fdstat, sizeof(__wasi_fdstat_t)); + + __wasi_errno_t ret = __wasi_fd_fdstat_get(fd, fdstat); + + WASI_TRACE("fd:%d", fd); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_fdstat_set_flags) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_fdflags_t , flags) + + __wasi_errno_t ret = __wasi_fd_fdstat_set_flags(fd, flags); + + WASI_TRACE("fd:%d, flags:0x%x", fd, flags); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_unstable_fd_filestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(buf, 56); // wasi_filestat_t + + __wasi_filestat_t stat; + + __wasi_errno_t ret = __wasi_fd_filestat_get(fd, &stat); + + if (ret != __WASI_ERRNO_SUCCESS) { + m3ApiReturn(ret); + } + + memset(buf, 0, 56); + m3ApiWriteMem64(buf+0, stat.st_dev); + m3ApiWriteMem64(buf+8, stat.st_ino); + m3ApiWriteMem8 (buf+16, stat.st_filetype); + m3ApiWriteMem32(buf+20, stat.st_nlink); + m3ApiWriteMem64(buf+24, stat.st_size); + m3ApiWriteMem64(buf+32, stat.st_atim); + m3ApiWriteMem64(buf+40, stat.st_mtim); + m3ApiWriteMem64(buf+48, stat.st_ctim); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_snapshot_preview1_fd_filestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(buf, 64); // wasi_filestat_t + + __wasi_filestat_t stat; + + __wasi_errno_t ret = __wasi_fd_filestat_get(fd, &stat); + + if (ret != __WASI_ERRNO_SUCCESS) { + m3ApiReturn(ret); + } + + memset(buf, 0, 64); + m3ApiWriteMem64(buf+0, stat.st_dev); + m3ApiWriteMem64(buf+8, stat.st_ino); + m3ApiWriteMem8 (buf+16, stat.st_filetype); + m3ApiWriteMem64(buf+24, stat.st_nlink); + m3ApiWriteMem64(buf+32, stat.st_size); + m3ApiWriteMem64(buf+40, stat.st_atim); + m3ApiWriteMem64(buf+48, stat.st_mtim); + m3ApiWriteMem64(buf+56, stat.st_ctim); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_unstable_fd_seek) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_filedelta_t , offset) + m3ApiGetArg (uint32_t , wasi_whence) + m3ApiGetArgMem (__wasi_filesize_t * , result) + + m3ApiCheckMem(result, sizeof(__wasi_filesize_t)); + + __wasi_whence_t whence = -1; + const char* whstr = "???"; + + switch (wasi_whence) { + case 0: whence = __WASI_WHENCE_CUR; whstr = "CUR"; break; + case 1: whence = __WASI_WHENCE_END; whstr = "END"; break; + case 2: whence = __WASI_WHENCE_SET; whstr = "SET"; break; + } + + __wasi_errno_t ret = __wasi_fd_seek(fd, offset, whence, result); + + WASI_TRACE("fd:%d, offset:%d, whence:%s | result:%d", fd, offset, whstr, *result); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_snapshot_preview1_fd_seek) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_filedelta_t , offset) + m3ApiGetArg (uint32_t , wasi_whence) + m3ApiGetArgMem (__wasi_filesize_t * , result) + + m3ApiCheckMem(result, sizeof(__wasi_filesize_t)); + + __wasi_whence_t whence = -1; + const char* whstr = "???"; + + switch (wasi_whence) { + case 0: whence = __WASI_WHENCE_SET; whstr = "SET"; break; + case 1: whence = __WASI_WHENCE_CUR; whstr = "CUR"; break; + case 2: whence = __WASI_WHENCE_END; whstr = "END"; break; + } + + __wasi_errno_t ret = __wasi_fd_seek(fd, offset, whence, result); + + WASI_TRACE("fd:%d, offset:%d, whence:%s | result:%d", fd, offset, whstr, *result); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_renumber) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , from) + m3ApiGetArg (__wasi_fd_t , to) + + __wasi_errno_t ret = __wasi_fd_renumber(from, to); + + WASI_TRACE("from:%d, to:%d", from, to); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_sync) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + + __wasi_errno_t ret = __wasi_fd_sync(fd); + + WASI_TRACE("fd:%d", fd); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_tell) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (__wasi_filesize_t * , result) + + m3ApiCheckMem(result, sizeof(__wasi_filesize_t)); + + __wasi_errno_t ret = __wasi_fd_tell(fd, result); + + WASI_TRACE("fd:%d | result:%d", fd, *result); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_create_directory) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (__wasi_size_t , path_len) + + m3ApiCheckMem(path, path_len); + + __wasi_errno_t ret = __wasi_path_create_directory(fd, path, path_len); + + WASI_TRACE("fd:%d, path:%s", fd, path); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_readlink) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (__wasi_size_t , path_len) + m3ApiGetArgMem (char * , buf) + m3ApiGetArg (__wasi_size_t , buf_len) + m3ApiGetArgMem (__wasi_size_t * , bufused) + + m3ApiCheckMem(path, path_len); + m3ApiCheckMem(buf, buf_len); + m3ApiCheckMem(bufused, sizeof(__wasi_size_t)); + + __wasi_errno_t ret = __wasi_path_readlink(fd, path, path_len, buf, buf_len, bufused); + + WASI_TRACE("fd:%d, path:%s | buf:%s, bufused:%d", fd, path, buf, *bufused); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_remove_directory) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (__wasi_size_t , path_len) + + m3ApiCheckMem(path, path_len); + + __wasi_errno_t ret = __wasi_path_remove_directory(fd, path, path_len); + + WASI_TRACE("fd:%d, path:%s", fd, path); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_rename) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , old_fd) + m3ApiGetArgMem (const char * , old_path) + m3ApiGetArg (__wasi_size_t , old_path_len) + m3ApiGetArg (__wasi_fd_t , new_fd) + m3ApiGetArgMem (const char * , new_path) + m3ApiGetArg (__wasi_size_t , new_path_len) + + m3ApiCheckMem(old_path, old_path_len); + m3ApiCheckMem(new_path, new_path_len); + + __wasi_errno_t ret = __wasi_path_rename(old_fd, old_path, old_path_len, + new_fd, new_path, new_path_len); + + WASI_TRACE("old_fd:%d, old_path:%s, new_fd:%d, new_path:%s", old_fd, old_path, new_fd, new_path); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_symlink) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (const char * , old_path) + m3ApiGetArg (__wasi_size_t , old_path_len) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (const char * , new_path) + m3ApiGetArg (__wasi_size_t , new_path_len) + + m3ApiCheckMem(old_path, old_path_len); + m3ApiCheckMem(new_path, new_path_len); + + __wasi_errno_t ret = __wasi_path_symlink(old_path, old_path_len, + fd, new_path, new_path_len); + + WASI_TRACE("old_path:%s, fd:%d, new_path:%s", old_path, fd, new_path); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_unlink_file) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (__wasi_size_t , path_len) + + m3ApiCheckMem(path, path_len); + + __wasi_errno_t ret = __wasi_path_unlink_file(fd, path, path_len); + + WASI_TRACE("fd:%d, path:%s", fd, path); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_open) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , dirfd) + m3ApiGetArg (__wasi_lookupflags_t , dirflags) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (__wasi_size_t , path_len) + m3ApiGetArg (__wasi_oflags_t , oflags) + m3ApiGetArg (__wasi_rights_t , fs_rights_base) + m3ApiGetArg (__wasi_rights_t , fs_rights_inheriting) + m3ApiGetArg (__wasi_fdflags_t , fs_flags) + m3ApiGetArgMem (__wasi_fd_t * , fd) + + m3ApiCheckMem(path, path_len); + m3ApiCheckMem(fd, sizeof(__wasi_fd_t)); + + __wasi_errno_t ret = __wasi_path_open(dirfd, + dirflags, + path, + path_len, + oflags, + fs_rights_base, + fs_rights_inheriting, + fs_flags, + fd); + + WASI_TRACE("dirfd:%d, dirflags:0x%x, path:%s, oflags:0x%x, fs_flags:0x%x | fd:%d", dirfd, dirflags, path, oflags, fs_flags, *fd); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_unstable_path_filestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_lookupflags_t , flags) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (uint32_t , path_len) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(path, path_len); + m3ApiCheckMem(buf, 56); // wasi_filestat_t + + __wasi_filestat_t stat; + + __wasi_errno_t ret = __wasi_path_filestat_get(fd, flags, path, path_len, &stat); + + WASI_TRACE("fd:%d, flags:0x%x, path:%s | fs.size:%d", fd, flags, path, stat.st_size); + + if (ret != __WASI_ERRNO_SUCCESS) { + m3ApiReturn(ret); + } + + memset(buf, 0, 56); + m3ApiWriteMem64(buf+0, stat.st_dev); + m3ApiWriteMem64(buf+8, stat.st_ino); + m3ApiWriteMem8 (buf+16, stat.st_filetype); + m3ApiWriteMem32(buf+20, stat.st_nlink); + m3ApiWriteMem64(buf+24, stat.st_size); + m3ApiWriteMem64(buf+32, stat.st_atim); + m3ApiWriteMem64(buf+40, stat.st_mtim); + m3ApiWriteMem64(buf+48, stat.st_ctim); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_snapshot_preview1_path_filestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_lookupflags_t , flags) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (uint32_t , path_len) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(path, path_len); + m3ApiCheckMem(buf, 64); // wasi_filestat_t + + __wasi_filestat_t stat; + + __wasi_errno_t ret = __wasi_path_filestat_get(fd, flags, path, path_len, &stat); + + WASI_TRACE("fd:%d, flags:0x%x, path:%s | fs.size:%d", fd, flags, path, stat.st_size); + + if (ret != __WASI_ERRNO_SUCCESS) { + m3ApiReturn(ret); + } + + memset(buf, 0, 64); + m3ApiWriteMem64(buf+0, stat.st_dev); + m3ApiWriteMem64(buf+8, stat.st_ino); + m3ApiWriteMem8 (buf+16, stat.st_filetype); + m3ApiWriteMem64(buf+24, stat.st_nlink); + m3ApiWriteMem64(buf+32, stat.st_size); + m3ApiWriteMem64(buf+40, stat.st_atim); + m3ApiWriteMem64(buf+48, stat.st_mtim); + m3ApiWriteMem64(buf+56, stat.st_ctim); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_pread) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (__wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (__wasi_size_t , iovs_len) + m3ApiGetArg (__wasi_filesize_t , offset) + m3ApiGetArgMem (__wasi_size_t * , nread) + + m3ApiCheckMem(wasi_iovs, iovs_len * sizeof(__wasi_iovec_t)); + m3ApiCheckMem(nread, sizeof(__wasi_size_t)); + + __wasi_iovec_t iovs[iovs_len]; + const void* mem_check = copy_iov_to_host(runtime, _mem, iovs, wasi_iovs, iovs_len); + if (mem_check != m3Err_none) { + return mem_check; + } + + __wasi_errno_t ret = __wasi_fd_pread(fd, iovs, iovs_len, offset, nread); + + WASI_TRACE("fd:%d | nread:%d", fd, *nread); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_read) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (__wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (__wasi_size_t , iovs_len) + m3ApiGetArgMem (__wasi_size_t * , nread) + + m3ApiCheckMem(wasi_iovs, iovs_len * sizeof(__wasi_iovec_t)); + m3ApiCheckMem(nread, sizeof(__wasi_size_t)); + + __wasi_iovec_t iovs[iovs_len]; + const void* mem_check = copy_iov_to_host(runtime, _mem, iovs, wasi_iovs, iovs_len); + if (mem_check != m3Err_none) { + return mem_check; + } + + __wasi_errno_t ret = __wasi_fd_read(fd, iovs, iovs_len, nread); + + WASI_TRACE("fd:%d | nread:%d", fd, *nread); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_write) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (__wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (__wasi_size_t , iovs_len) + m3ApiGetArgMem (__wasi_size_t * , nwritten) + + m3ApiCheckMem(wasi_iovs, iovs_len * sizeof(__wasi_iovec_t)); + m3ApiCheckMem(nwritten, sizeof(__wasi_size_t)); + + __wasi_iovec_t iovs[iovs_len]; + const void* mem_check = copy_iov_to_host(runtime, _mem, iovs, wasi_iovs, iovs_len); + if (mem_check != m3Err_none) { + return mem_check; + } + + __wasi_errno_t ret = __wasi_fd_write(fd, (__wasi_ciovec_t*)iovs, iovs_len, nwritten); + + WASI_TRACE("fd:%d | nwritten:%d", fd, *nwritten); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_pwrite) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (__wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (__wasi_size_t , iovs_len) + m3ApiGetArg (__wasi_filesize_t , offset) + m3ApiGetArgMem (__wasi_size_t * , nwritten) + + m3ApiCheckMem(wasi_iovs, iovs_len * sizeof(__wasi_iovec_t)); + m3ApiCheckMem(nwritten, sizeof(__wasi_size_t)); + + __wasi_iovec_t iovs[iovs_len]; + const void* mem_check = copy_iov_to_host(runtime, _mem, iovs, wasi_iovs, iovs_len); + if (mem_check != m3Err_none) { + return mem_check; + } + + __wasi_errno_t ret = __wasi_fd_pwrite(fd, (__wasi_ciovec_t*)iovs, iovs_len, offset, nwritten); + + WASI_TRACE("fd:%d | nwritten:%d", fd, *nwritten); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_readdir) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (void * , buf) + m3ApiGetArg (__wasi_size_t , buf_len) + m3ApiGetArg (__wasi_dircookie_t , cookie) + m3ApiGetArgMem (__wasi_size_t * , bufused) + + m3ApiCheckMem(buf, buf_len); + m3ApiCheckMem(bufused, sizeof(__wasi_size_t)); + + __wasi_errno_t ret = __wasi_fd_readdir(fd, buf, buf_len, cookie, bufused); + + WASI_TRACE("fd:%d | bufused:%d", fd, *bufused); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_close) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t, fd) + + __wasi_errno_t ret = __wasi_fd_close(fd); + + WASI_TRACE("fd:%d", fd); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_datasync) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t, fd) + + __wasi_errno_t ret = __wasi_fd_datasync(fd); + + WASI_TRACE("fd:%d", fd); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_random_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint8_t * , buf) + m3ApiGetArg (__wasi_size_t , buf_len) + + m3ApiCheckMem(buf, buf_len); + + __wasi_errno_t ret = __wasi_random_get(buf, buf_len); + + WASI_TRACE("len:%d", buf_len); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_clock_res_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_clockid_t , wasi_clk_id) + m3ApiGetArgMem (__wasi_timestamp_t * , resolution) + + m3ApiCheckMem(resolution, sizeof(__wasi_timestamp_t)); + + __wasi_errno_t ret = __wasi_clock_res_get(wasi_clk_id, resolution); + + WASI_TRACE("clk_id:%d", wasi_clk_id); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_clock_time_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_clockid_t , wasi_clk_id) + m3ApiGetArg (__wasi_timestamp_t , precision) + m3ApiGetArgMem (__wasi_timestamp_t * , time) + + m3ApiCheckMem(time, sizeof(__wasi_timestamp_t)); + + __wasi_errno_t ret = __wasi_clock_time_get(wasi_clk_id, precision, time); + + WASI_TRACE("clk_id:%d", wasi_clk_id); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_poll_oneoff) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (const __wasi_subscription_t * , in) + m3ApiGetArgMem (__wasi_event_t * , out) + m3ApiGetArg (__wasi_size_t , nsubscriptions) + m3ApiGetArgMem (__wasi_size_t * , nevents) + + m3ApiCheckMem(in, nsubscriptions * sizeof(__wasi_subscription_t)); + m3ApiCheckMem(out, nsubscriptions * sizeof(__wasi_event_t)); + m3ApiCheckMem(nevents, sizeof(__wasi_size_t)); + + __wasi_errno_t ret = __wasi_poll_oneoff(in, out, nsubscriptions, nevents); + + WASI_TRACE("nsubscriptions:%d | nevents:%d", nsubscriptions, *nevents); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_proc_exit) +{ + m3ApiGetArg (uint32_t, code) + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context) { + context->exit_code = code; + } + + m3ApiTrap(m3Err_trapExit); +} + +m3ApiRawFunction(m3_wasi_generic_proc_raise) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_signal_t, sig) + + __wasi_errno_t ret = __WASI_ERRNO_INVAL; +#ifdef USE_NEW_WASI + ret = __wasi_proc_raise(sig); +#endif + + WASI_TRACE("sig:%d", sig); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_sched_yield) +{ + m3ApiReturnType (uint32_t) + __wasi_errno_t ret = __wasi_sched_yield(); + + WASI_TRACE(""); + + m3ApiReturn(ret); +} + + +static +M3Result SuppressLookupFailure(M3Result i_result) +{ + if (i_result == m3Err_functionLookupFailed) + return m3Err_none; + else + return i_result; +} + +m3_wasi_context_t* m3_GetWasiContext() +{ + return wasi_context; +} + + +M3Result m3_LinkWASI (IM3Module module) +{ + M3Result result = m3Err_none; + + if (!wasi_context) { + wasi_context = (m3_wasi_context_t*)malloc(sizeof(m3_wasi_context_t)); + wasi_context->exit_code = 0; + wasi_context->argc = 0; + wasi_context->argv = 0; + } + + static const char* namespaces[2] = { "wasi_unstable", "wasi_snapshot_preview1" }; + + // Some functions are incompatible between WASI versions +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_unstable", "fd_seek", "i(iIi*)", &m3_wasi_unstable_fd_seek))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1", "fd_seek", "i(iIi*)", &m3_wasi_snapshot_preview1_fd_seek))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_unstable", "fd_filestat_get", "i(i*)", &m3_wasi_unstable_fd_filestat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1", "fd_filestat_get", "i(i*)", &m3_wasi_snapshot_preview1_fd_filestat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_unstable", "path_filestat_get", "i(ii*i*)", &m3_wasi_unstable_path_filestat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1", "path_filestat_get", "i(ii*i*)", &m3_wasi_snapshot_preview1_path_filestat_get))); + + for (int i=0; i<2; i++) + { + const char* wasi = namespaces[i]; + +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "args_get", "i(**)", &m3_wasi_generic_args_get, wasi_context))); +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "args_sizes_get", "i(**)", &m3_wasi_generic_args_sizes_get, wasi_context))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_res_get", "i(i*)", &m3_wasi_generic_clock_res_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_time_get", "i(iI*)", &m3_wasi_generic_clock_time_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_get", "i(**)", &m3_wasi_generic_environ_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_sizes_get", "i(**)", &m3_wasi_generic_environ_sizes_get))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_advise", "i(iIIi)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_allocate", "i(iII)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_close", "i(i)", &m3_wasi_generic_fd_close))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_datasync", "i(i)", &m3_wasi_generic_fd_datasync))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_get", "i(i*)", &m3_wasi_generic_fd_fdstat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_flags", "i(ii)", &m3_wasi_generic_fd_fdstat_set_flags))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_rights", "i(iII)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_size", "i(iI)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_times","i(iIIi)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pread", "i(i*iI*)",&m3_wasi_generic_fd_pread))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_get", "i(i*)", &m3_wasi_generic_fd_prestat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_dir_name", "i(i*i)", &m3_wasi_generic_fd_prestat_dir_name))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pwrite", "i(i*iI*)",&m3_wasi_generic_fd_pwrite))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_read", "i(i*i*)", &m3_wasi_generic_fd_read))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_readdir", "i(i*iI*)",&m3_wasi_generic_fd_readdir))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_renumber", "i(ii)", &m3_wasi_generic_fd_renumber))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_sync", "i(i)", &m3_wasi_generic_fd_sync))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_tell", "i(i*)", &m3_wasi_generic_fd_tell))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_write", "i(i*i*)", &m3_wasi_generic_fd_write))); + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_create_directory", "i(i*i)", &m3_wasi_generic_path_create_directory))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_filestat_set_times", "i(ii*iIIi)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_link", "i(ii*ii*i)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_open", "i(ii*iiIIi*)", &m3_wasi_generic_path_open))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_readlink", "i(i*i*i*)", &m3_wasi_generic_path_readlink))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_remove_directory", "i(i*i)", &m3_wasi_generic_path_remove_directory))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_rename", "i(i*ii*i)", &m3_wasi_generic_path_rename))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_symlink", "i(*ii*i)", &m3_wasi_generic_path_symlink))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_unlink_file", "i(i*i)", &m3_wasi_generic_path_unlink_file))); + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "poll_oneoff", "i(**i*)", &m3_wasi_generic_poll_oneoff))); +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "proc_exit", "v(i)", &m3_wasi_generic_proc_exit, wasi_context))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "proc_raise", "i(i)", &m3_wasi_generic_proc_raise))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "random_get", "i(*i)", &m3_wasi_generic_random_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sched_yield", "i()", &m3_wasi_generic_sched_yield))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_recv", "i(i*ii**)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_send", "i(i*ii*)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_shutdown", "i(ii)", ))); + } + +_catch: + return result; +} + +#endif // d_m3HasMetaWASI + diff --git a/ext/wasm3/source/m3_api_tracer.c b/ext/wasm3/source/m3_api_tracer.c new file mode 100644 index 0000000..4abedbd --- /dev/null +++ b/ext/wasm3/source/m3_api_tracer.c @@ -0,0 +1,168 @@ +// +// m3_api_tracer.c +// +// Created by Volodymyr Shymanskyy on 02/18/20. +// Copyright © 2020 Volodymyr Shymanskyy. All rights reserved. +// + +#include "m3_api_tracer.h" + +#include "m3_env.h" +#include "m3_exception.h" + +#if defined(d_m3HasTracer) + + +static FILE* trace = NULL; + +m3ApiRawFunction(m3_env_log_execution) +{ + m3ApiGetArg (uint32_t, id) + fprintf(trace, "exec;%d\n", id); + m3ApiSuccess(); +} + +m3ApiRawFunction(m3_env_log_exec_enter) +{ + m3ApiGetArg (uint32_t, id) + m3ApiGetArg (uint32_t, func) + fprintf(trace, "enter;%d;%d\n", id, func); + m3ApiSuccess(); +} + +m3ApiRawFunction(m3_env_log_exec_exit) +{ + m3ApiGetArg (uint32_t, id) + m3ApiGetArg (uint32_t, func) + fprintf(trace, "exit;%d;%d\n", id, func); + m3ApiSuccess(); +} + +m3ApiRawFunction(m3_env_log_exec_loop) +{ + m3ApiGetArg (uint32_t, id) + fprintf(trace, "loop;%d\n", id); + m3ApiSuccess(); +} + +m3ApiRawFunction(m3_env_load_ptr) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uint32_t, id) + m3ApiGetArg (uint32_t, align) + m3ApiGetArg (uint32_t, offset) + m3ApiGetArg (uint32_t, address) + fprintf(trace, "load ptr;%d;%d;%d;%d\n", id, align, offset, address); + m3ApiReturn(address); +} + +m3ApiRawFunction(m3_env_store_ptr) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uint32_t, id) + m3ApiGetArg (uint32_t, align) + m3ApiGetArg (uint32_t, offset) + m3ApiGetArg (uint32_t, address) + fprintf(trace, "store ptr;%d;%d;%d;%d\n", id, align, offset, address); + m3ApiReturn(address); +} + + +#define d_m3TraceMemory(FUNC, NAME, TYPE, FMT) \ +m3ApiRawFunction(m3_env_##FUNC) \ +{ \ + m3ApiReturnType (TYPE) \ + m3ApiGetArg (uint32_t, id) \ + m3ApiGetArg (TYPE, val) \ + fprintf(trace, NAME ";%d;" FMT "\n", id, val); \ + m3ApiReturn(val); \ +} + +d_m3TraceMemory( load_val_i32, "load i32", int32_t, "%" PRIi32) +d_m3TraceMemory(store_val_i32, "store i32", int32_t, "%" PRIi32) +d_m3TraceMemory( load_val_i64, "load i64", int64_t, "%" PRIi64) +d_m3TraceMemory(store_val_i64, "store i64", int64_t, "%" PRIi64) +d_m3TraceMemory( load_val_f32, "load f32", float, "%" PRIf32) +d_m3TraceMemory(store_val_f32, "store f32", float, "%" PRIf32) +d_m3TraceMemory( load_val_f64, "load f64", double, "%" PRIf64) +d_m3TraceMemory(store_val_f64, "store f64", double, "%" PRIf64) + + +#define d_m3TraceLocal(FUNC, NAME, TYPE, FMT) \ +m3ApiRawFunction(m3_env_##FUNC) \ +{ \ + m3ApiReturnType (TYPE) \ + m3ApiGetArg (uint32_t, id) \ + m3ApiGetArg (uint32_t, local) \ + m3ApiGetArg (TYPE, val) \ + fprintf(trace, NAME ";%d;%d;" FMT "\n", id, local, val); \ + m3ApiReturn(val); \ +} + + +d_m3TraceLocal(get_i32, "get i32", int32_t, "%" PRIi32) +d_m3TraceLocal(set_i32, "set i32", int32_t, "%" PRIi32) +d_m3TraceLocal(get_i64, "get i64", int64_t, "%" PRIi64) +d_m3TraceLocal(set_i64, "set i64", int64_t, "%" PRIi64) +d_m3TraceLocal(get_f32, "get f32", float, "%" PRIf32) +d_m3TraceLocal(set_f32, "set f32", float, "%" PRIf32) +d_m3TraceLocal(get_f64, "get f64", double, "%" PRIf64) +d_m3TraceLocal(set_f64, "set f64", double, "%" PRIf64) + + +static +M3Result SuppressLookupFailure(M3Result i_result) +{ + if (i_result == m3Err_none) { + // If any trace function is found in the module, open the trace file + if (!trace) { + trace = fopen ("wasm3_trace.csv","w"); + } + } else if (i_result == m3Err_functionLookupFailed) { + i_result = m3Err_none; + } + return i_result; +} + + +M3Result m3_LinkTracer (IM3Module module) +{ + M3Result result = m3Err_none; + + const char* env = "env"; + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "log_execution", "v(i)", &m3_env_log_execution))); + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "log_exec_enter", "v(ii)", &m3_env_log_exec_enter))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "log_exec_exit", "v(ii)", &m3_env_log_exec_exit))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "log_exec_loop", "v(i)", &m3_env_log_exec_loop))); + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "load_ptr", "i(iiii)", &m3_env_load_ptr))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "store_ptr", "i(iiii)", &m3_env_store_ptr))); + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "load_val_i32", "i(ii)", &m3_env_load_val_i32))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "load_val_i64", "I(iI)", &m3_env_load_val_i64))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "load_val_f32", "f(if)", &m3_env_load_val_f32))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "load_val_f64", "F(iF)", &m3_env_load_val_f64))); + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "store_val_i32", "i(ii)", &m3_env_store_val_i32))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "store_val_i64", "I(iI)", &m3_env_store_val_i64))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "store_val_f32", "f(if)", &m3_env_store_val_f32))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "store_val_f64", "F(iF)", &m3_env_store_val_f64))); + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "get_i32", "i(iii)", &m3_env_get_i32))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "get_i64", "I(iiI)", &m3_env_get_i64))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "get_f32", "f(iif)", &m3_env_get_f32))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "get_f64", "F(iiF)", &m3_env_get_f64))); + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "set_i32", "i(iii)", &m3_env_set_i32))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "set_i64", "I(iiI)", &m3_env_set_i64))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "set_f32", "f(iif)", &m3_env_set_f32))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, env, "set_f64", "F(iiF)", &m3_env_set_f64))); + +_catch: + return result; +} + +#endif // d_m3HasTracer + diff --git a/ext/wasm3/source/m3_api_tracer.h b/ext/wasm3/source/m3_api_tracer.h new file mode 100644 index 0000000..5744b87 --- /dev/null +++ b/ext/wasm3/source/m3_api_tracer.h @@ -0,0 +1,19 @@ +// +// m3_api_tracer.h +// +// Created by Volodymyr Shymanskyy on 02/18/20. +// Copyright © 2020 Volodymyr Shymanskyy. All rights reserved. +// + +#ifndef m3_api_tracer_h +#define m3_api_tracer_h + +#include "m3_core.h" + +d_m3BeginExternC + +M3Result m3_LinkTracer (IM3Module io_module); + +d_m3EndExternC + +#endif // m3_api_tracer_h diff --git a/ext/wasm3/source/m3_api_uvwasi.c b/ext/wasm3/source/m3_api_uvwasi.c new file mode 100644 index 0000000..9e6ccb0 --- /dev/null +++ b/ext/wasm3/source/m3_api_uvwasi.c @@ -0,0 +1,1144 @@ +// +// m3_api_uvwasi.c +// +// Created by Colin J. Ihrig on 4/20/20. +// Copyright © 2020 Colin J. Ihrig, Volodymyr Shymanskyy. All rights reserved. +// + +#define _POSIX_C_SOURCE 200809L + +#include "m3_api_wasi.h" + +#include "m3_env.h" +#include "m3_exception.h" + +#if defined(d_m3HasUVWASI) + +#include +#include + +#ifndef d_m3EnableWasiTracing +# define d_m3EnableWasiTracing 0 +#endif + +#ifdef __APPLE__ +# include +# define environ (*_NSGetEnviron()) +#elif !defined(_MSC_VER) +extern char** environ; +#endif + +static m3_wasi_context_t* wasi_context; +static uvwasi_t uvwasi; + +typedef struct wasi_iovec_t +{ + uvwasi_size_t buf; + uvwasi_size_t buf_len; +} wasi_iovec_t; + +#if d_m3EnableWasiTracing + +const char* wasi_errno2str(uvwasi_errno_t err) +{ + switch (err) { + case 0: return "ESUCCESS"; + case 1: return "E2BIG"; + case 2: return "EACCES"; + case 3: return "EADDRINUSE"; + case 4: return "EADDRNOTAVAIL"; + case 5: return "EAFNOSUPPORT"; + case 6: return "EAGAIN"; + case 7: return "EALREADY"; + case 8: return "EBADF"; + case 9: return "EBADMSG"; + case 10: return "EBUSY"; + case 11: return "ECANCELED"; + case 12: return "ECHILD"; + case 13: return "ECONNABORTED"; + case 14: return "ECONNREFUSED"; + case 15: return "ECONNRESET"; + case 16: return "EDEADLK"; + case 17: return "EDESTADDRREQ"; + case 18: return "EDOM"; + case 19: return "EDQUOT"; + case 20: return "EEXIST"; + case 21: return "EFAULT"; + case 22: return "EFBIG"; + case 23: return "EHOSTUNREACH"; + case 24: return "EIDRM"; + case 25: return "EILSEQ"; + case 26: return "EINPROGRESS"; + case 27: return "EINTR"; + case 28: return "EINVAL"; + case 29: return "EIO"; + case 30: return "EISCONN"; + case 31: return "EISDIR"; + case 32: return "ELOOP"; + case 33: return "EMFILE"; + case 34: return "EMLINK"; + case 35: return "EMSGSIZE"; + case 36: return "EMULTIHOP"; + case 37: return "ENAMETOOLONG"; + case 38: return "ENETDOWN"; + case 39: return "ENETRESET"; + case 40: return "ENETUNREACH"; + case 41: return "ENFILE"; + case 42: return "ENOBUFS"; + case 43: return "ENODEV"; + case 44: return "ENOENT"; + case 45: return "ENOEXEC"; + case 46: return "ENOLCK"; + case 47: return "ENOLINK"; + case 48: return "ENOMEM"; + case 49: return "ENOMSG"; + case 50: return "ENOPROTOOPT"; + case 51: return "ENOSPC"; + case 52: return "ENOSYS"; + case 53: return "ENOTCONN"; + case 54: return "ENOTDIR"; + case 55: return "ENOTEMPTY"; + case 56: return "ENOTRECOVERABLE"; + case 57: return "ENOTSOCK"; + case 58: return "ENOTSUP"; + case 59: return "ENOTTY"; + case 60: return "ENXIO"; + case 61: return "EOVERFLOW"; + case 62: return "EOWNERDEAD"; + case 63: return "EPERM"; + case 64: return "EPIPE"; + case 65: return "EPROTO"; + case 66: return "EPROTONOSUPPORT"; + case 67: return "EPROTOTYPE"; + case 68: return "ERANGE"; + case 69: return "EROFS"; + case 70: return "ESPIPE"; + case 71: return "ESRCH"; + case 72: return "ESTALE"; + case 73: return "ETIMEDOUT"; + case 74: return "ETXTBSY"; + case 75: return "EXDEV"; + case 76: return "ENOTCAPABLE"; + default: return ""; + } +} + +# define WASI_TRACE(fmt, ...) { fprintf(stderr, "%s " fmt, __FUNCTION__+16, ##__VA_ARGS__); fprintf(stderr, " => %s\n", wasi_errno2str(ret)); } +#else +# define WASI_TRACE(fmt, ...) +#endif + +/* + * WASI API implementation + */ + +m3ApiRawFunction(m3_wasi_generic_args_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint32_t * , argv) + m3ApiGetArgMem (char * , argv_buf) + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context == NULL) { m3ApiReturn(UVWASI_EINVAL); } + + m3ApiCheckMem(argv, context->argc * sizeof(uint32_t)); + + for (u32 i = 0; i < context->argc; ++i) + { + m3ApiWriteMem32(&argv[i], m3ApiPtrToOffset(argv_buf)); + + size_t len = strlen (context->argv[i]); + + m3ApiCheckMem(argv_buf, len); + memcpy (argv_buf, context->argv[i], len); + argv_buf += len; + * argv_buf++ = 0; + } + + m3ApiReturn(UVWASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_args_sizes_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uvwasi_size_t * , argc) + m3ApiGetArgMem (uvwasi_size_t * , argv_buf_size) + + m3ApiCheckMem(argc, sizeof(uvwasi_size_t)); + m3ApiCheckMem(argv_buf_size, sizeof(uvwasi_size_t)); + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context == NULL) { m3ApiReturn(UVWASI_EINVAL); } + + uvwasi_size_t buf_len = 0; + for (u32 i = 0; i < context->argc; ++i) + { + buf_len += strlen (context->argv[i]) + 1; + } + + m3ApiWriteMem32(argc, context->argc); + m3ApiWriteMem32(argv_buf_size, buf_len); + + m3ApiReturn(UVWASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_environ_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint32_t * , env) + m3ApiGetArgMem (char * , env_buf) + + char **environment; + uvwasi_errno_t ret; + uvwasi_size_t env_count, env_buf_size; + + ret = uvwasi_environ_sizes_get(&uvwasi, &env_count, &env_buf_size); + if (ret != UVWASI_ESUCCESS) { + m3ApiReturn(ret); + } + + m3ApiCheckMem(env, env_count * sizeof(uint32_t)); + m3ApiCheckMem(env_buf, env_buf_size); + + environment = calloc(env_count, sizeof(char *)); + if (environment == NULL) { + m3ApiReturn(UVWASI_ENOMEM); + } + + ret = uvwasi_environ_get(&uvwasi, environment, env_buf); + if (ret != UVWASI_ESUCCESS) { + free(environment); + m3ApiReturn(ret); + } + + uint32_t environ_buf_offset = m3ApiPtrToOffset(env_buf); + + for (u32 i = 0; i < env_count; ++i) + { + uint32_t offset = environ_buf_offset + + (environment[i] - environment[0]); + m3ApiWriteMem32(&env[i], offset); + } + + free(environment); + m3ApiReturn(UVWASI_ESUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_environ_sizes_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uvwasi_size_t * , env_count) + m3ApiGetArgMem (uvwasi_size_t * , env_buf_size) + + m3ApiCheckMem(env_count, sizeof(uvwasi_size_t)); + m3ApiCheckMem(env_buf_size, sizeof(uvwasi_size_t)); + + uvwasi_size_t count; + uvwasi_size_t buf_size; + + uvwasi_errno_t ret = uvwasi_environ_sizes_get(&uvwasi, &count, &buf_size); + + m3ApiWriteMem32(env_count, count); + m3ApiWriteMem32(env_buf_size, buf_size); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_prestat_dir_name) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (char * , path) + m3ApiGetArg (uvwasi_size_t , path_len) + + m3ApiCheckMem(path, path_len); + + uvwasi_errno_t ret = uvwasi_fd_prestat_dir_name(&uvwasi, fd, path, path_len); + + WASI_TRACE("fd:%d, len:%d | path:%s", fd, path_len, path); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_prestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(buf, 8); + + uvwasi_prestat_t prestat; + + uvwasi_errno_t ret = uvwasi_fd_prestat_get(&uvwasi, fd, &prestat); + + WASI_TRACE("fd:%d | type:%d, name_len:%d", fd, prestat.pr_type, prestat.u.dir.pr_name_len); + + if (ret != UVWASI_ESUCCESS) { + m3ApiReturn(ret); + } + + m3ApiWriteMem32(buf+0, prestat.pr_type); + m3ApiWriteMem32(buf+4, prestat.u.dir.pr_name_len); + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_fdstat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(buf, 24); + + uvwasi_fdstat_t stat; + uvwasi_errno_t ret = uvwasi_fd_fdstat_get(&uvwasi, fd, &stat); + + WASI_TRACE("fd:%d", fd); + + if (ret != UVWASI_ESUCCESS) { + m3ApiReturn(ret); + } + + memset(buf, 0, 24); + m3ApiWriteMem8 (buf+0, stat.fs_filetype); + m3ApiWriteMem16(buf+2, stat.fs_flags); + m3ApiWriteMem64(buf+8, stat.fs_rights_base); + m3ApiWriteMem64(buf+16, stat.fs_rights_inheriting); + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_fdstat_set_flags) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArg (uvwasi_fdflags_t , flags) + + uvwasi_errno_t ret = uvwasi_fd_fdstat_set_flags(&uvwasi, fd, flags); + + WASI_TRACE("fd:%d, flags:0x%x", fd, flags); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_unstable_fd_filestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(buf, 56); // wasi_filestat_t + + uvwasi_filestat_t stat; + + uvwasi_errno_t ret = uvwasi_fd_filestat_get(&uvwasi, fd, &stat); + + WASI_TRACE("fd:%d | fs.size:%ld", fd, stat.st_size); + + if (ret != UVWASI_ESUCCESS) { + m3ApiReturn(ret); + } + + memset(buf, 0, 56); + m3ApiWriteMem64(buf+0, stat.st_dev); + m3ApiWriteMem64(buf+8, stat.st_ino); + m3ApiWriteMem8 (buf+16, stat.st_filetype); + m3ApiWriteMem32(buf+20, stat.st_nlink); + m3ApiWriteMem64(buf+24, stat.st_size); + m3ApiWriteMem64(buf+32, stat.st_atim); + m3ApiWriteMem64(buf+40, stat.st_mtim); + m3ApiWriteMem64(buf+48, stat.st_ctim); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_snapshot_preview1_fd_filestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(buf, 64); // wasi_filestat_t + + uvwasi_filestat_t stat; + + uvwasi_errno_t ret = uvwasi_fd_filestat_get(&uvwasi, fd, &stat); + + WASI_TRACE("fd:%d | fs.size:%ld", fd, stat.st_size); + + if (ret != UVWASI_ESUCCESS) { + m3ApiReturn(ret); + } + + memset(buf, 0, 64); + m3ApiWriteMem64(buf+0, stat.st_dev); + m3ApiWriteMem64(buf+8, stat.st_ino); + m3ApiWriteMem8 (buf+16, stat.st_filetype); + m3ApiWriteMem64(buf+24, stat.st_nlink); + m3ApiWriteMem64(buf+32, stat.st_size); + m3ApiWriteMem64(buf+40, stat.st_atim); + m3ApiWriteMem64(buf+48, stat.st_mtim); + m3ApiWriteMem64(buf+56, stat.st_ctim); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_unstable_fd_seek) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArg (uvwasi_filedelta_t , offset) + m3ApiGetArg (uint32_t , wasi_whence) + m3ApiGetArgMem (uvwasi_filesize_t * , result) + + m3ApiCheckMem(result, sizeof(uvwasi_filesize_t)); + + uvwasi_whence_t whence = -1; + const char* whstr = "???"; + + switch (wasi_whence) { + case 0: whence = UVWASI_WHENCE_CUR; whstr = "CUR"; break; + case 1: whence = UVWASI_WHENCE_END; whstr = "END"; break; + case 2: whence = UVWASI_WHENCE_SET; whstr = "SET"; break; + } + + uvwasi_filesize_t pos; + uvwasi_errno_t ret = uvwasi_fd_seek(&uvwasi, fd, offset, whence, &pos); + + WASI_TRACE("fd:%d, offset:%ld, whence:%s | result:%ld", fd, offset, whstr, pos); + + m3ApiWriteMem64(result, pos); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_snapshot_preview1_fd_seek) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArg (uvwasi_filedelta_t , offset) + m3ApiGetArg (uint32_t , wasi_whence) + m3ApiGetArgMem (uvwasi_filesize_t * , result) + + m3ApiCheckMem(result, sizeof(uvwasi_filesize_t)); + + uvwasi_whence_t whence = -1; + const char* whstr = "???"; + + switch (wasi_whence) { + case 0: whence = UVWASI_WHENCE_SET; whstr = "SET"; break; + case 1: whence = UVWASI_WHENCE_CUR; whstr = "CUR"; break; + case 2: whence = UVWASI_WHENCE_END; whstr = "END"; break; + } + + uvwasi_filesize_t pos; + uvwasi_errno_t ret = uvwasi_fd_seek(&uvwasi, fd, offset, whence, &pos); + + WASI_TRACE("fd:%d, offset:%ld, whence:%s | result:%ld", fd, offset, whstr, pos); + + m3ApiWriteMem64(result, pos); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_renumber) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , from) + m3ApiGetArg (uvwasi_fd_t , to) + + uvwasi_errno_t ret = uvwasi_fd_renumber(&uvwasi, from, to); + + WASI_TRACE("from:%d, to:%d", from, to); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_sync) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + + uvwasi_errno_t ret = uvwasi_fd_sync(&uvwasi, fd); + + WASI_TRACE("fd:%d", fd); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_tell) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (uvwasi_filesize_t * , result) + + m3ApiCheckMem(result, sizeof(uvwasi_filesize_t)); + + uvwasi_filesize_t pos; + uvwasi_errno_t ret = uvwasi_fd_tell(&uvwasi, fd, &pos); + + WASI_TRACE("fd:%d | result:%d", fd, *result); + + m3ApiWriteMem64(result, pos); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_create_directory) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (uvwasi_size_t , path_len) + + m3ApiCheckMem(path, path_len); + + uvwasi_errno_t ret = uvwasi_path_create_directory(&uvwasi, fd, path, path_len); + + WASI_TRACE("fd:%d, path:%s", fd, path); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_readlink) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (uvwasi_size_t , path_len) + m3ApiGetArgMem (char * , buf) + m3ApiGetArg (uvwasi_size_t , buf_len) + m3ApiGetArgMem (uvwasi_size_t * , bufused) + + m3ApiCheckMem(path, path_len); + m3ApiCheckMem(buf, buf_len); + m3ApiCheckMem(bufused, sizeof(uvwasi_size_t)); + + uvwasi_size_t uvbufused; + + uvwasi_errno_t ret = uvwasi_path_readlink(&uvwasi, fd, path, path_len, buf, buf_len, &uvbufused); + + WASI_TRACE("fd:%d, path:%s | buf:%s, bufused:%d", fd, path, buf, uvbufused); + + m3ApiWriteMem32(bufused, uvbufused); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_remove_directory) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (uvwasi_size_t , path_len) + + m3ApiCheckMem(path, path_len); + + uvwasi_errno_t ret = uvwasi_path_remove_directory(&uvwasi, fd, path, path_len); + + WASI_TRACE("fd:%d, path:%s", fd, path); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_rename) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , old_fd) + m3ApiGetArgMem (const char * , old_path) + m3ApiGetArg (uvwasi_size_t , old_path_len) + m3ApiGetArg (uvwasi_fd_t , new_fd) + m3ApiGetArgMem (const char * , new_path) + m3ApiGetArg (uvwasi_size_t , new_path_len) + + m3ApiCheckMem(old_path, old_path_len); + m3ApiCheckMem(new_path, new_path_len); + + uvwasi_errno_t ret = uvwasi_path_rename(&uvwasi, old_fd, old_path, old_path_len, + new_fd, new_path, new_path_len); + + WASI_TRACE("old_fd:%d, old_path:%s, new_fd:%d, new_path:%s", old_fd, old_path, new_fd, new_path); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_symlink) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (const char * , old_path) + m3ApiGetArg (uvwasi_size_t , old_path_len) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (const char * , new_path) + m3ApiGetArg (uvwasi_size_t , new_path_len) + + m3ApiCheckMem(old_path, old_path_len); + m3ApiCheckMem(new_path, new_path_len); + + uvwasi_errno_t ret = uvwasi_path_symlink(&uvwasi, old_path, old_path_len, + fd, new_path, new_path_len); + + WASI_TRACE("old_path:%s, fd:%d, new_path:%s", old_path, fd, new_path); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_unlink_file) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (uvwasi_size_t , path_len) + + m3ApiCheckMem(path, path_len); + + uvwasi_errno_t ret = uvwasi_path_unlink_file(&uvwasi, fd, path, path_len); + + WASI_TRACE("fd:%d, path:%s", fd, path); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_path_open) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , dirfd) + m3ApiGetArg (uvwasi_lookupflags_t , dirflags) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (uvwasi_size_t , path_len) + m3ApiGetArg (uvwasi_oflags_t , oflags) + m3ApiGetArg (uvwasi_rights_t , fs_rights_base) + m3ApiGetArg (uvwasi_rights_t , fs_rights_inheriting) + m3ApiGetArg (uvwasi_fdflags_t , fs_flags) + m3ApiGetArgMem (uvwasi_fd_t * , fd) + + m3ApiCheckMem(path, path_len); + m3ApiCheckMem(fd, sizeof(uvwasi_fd_t)); + + uvwasi_fd_t uvfd; + + uvwasi_errno_t ret = uvwasi_path_open(&uvwasi, + dirfd, + dirflags, + path, + path_len, + oflags, + fs_rights_base, + fs_rights_inheriting, + fs_flags, + &uvfd); + + WASI_TRACE("dirfd:%d, dirflags:0x%x, path:%s, oflags:0x%x, fs_flags:0x%x | fd:%d", dirfd, dirflags, path, oflags, fs_flags, uvfd); + + m3ApiWriteMem32(fd, uvfd); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_unstable_path_filestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArg (uvwasi_lookupflags_t , flags) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (uint32_t , path_len) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(path, path_len); + m3ApiCheckMem(buf, 56); // wasi_filestat_t + + uvwasi_filestat_t stat; + + uvwasi_errno_t ret = uvwasi_path_filestat_get(&uvwasi, fd, flags, path, path_len, &stat); + + WASI_TRACE("fd:%d, flags:0x%x, path:%s | fs.size:%d", fd, flags, path, stat.st_size); + + if (ret != UVWASI_ESUCCESS) { + m3ApiReturn(ret); + } + + memset(buf, 0, 56); + m3ApiWriteMem64(buf+0, stat.st_dev); + m3ApiWriteMem64(buf+8, stat.st_ino); + m3ApiWriteMem8 (buf+16, stat.st_filetype); + m3ApiWriteMem32(buf+20, stat.st_nlink); + m3ApiWriteMem64(buf+24, stat.st_size); + m3ApiWriteMem64(buf+32, stat.st_atim); + m3ApiWriteMem64(buf+40, stat.st_mtim); + m3ApiWriteMem64(buf+48, stat.st_ctim); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_snapshot_preview1_path_filestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArg (uvwasi_lookupflags_t , flags) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (uint32_t , path_len) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(path, path_len); + m3ApiCheckMem(buf, 64); // wasi_filestat_t + + uvwasi_filestat_t stat; + + uvwasi_errno_t ret = uvwasi_path_filestat_get(&uvwasi, fd, flags, path, path_len, &stat); + + WASI_TRACE("fd:%d, flags:0x%x, path:%s | fs.size:%d", fd, flags, path, stat.st_size); + + if (ret != UVWASI_ESUCCESS) { + m3ApiReturn(ret); + } + + memset(buf, 0, 64); + m3ApiWriteMem64(buf+0, stat.st_dev); + m3ApiWriteMem64(buf+8, stat.st_ino); + m3ApiWriteMem8 (buf+16, stat.st_filetype); + m3ApiWriteMem64(buf+24, stat.st_nlink); + m3ApiWriteMem64(buf+32, stat.st_size); + m3ApiWriteMem64(buf+40, stat.st_atim); + m3ApiWriteMem64(buf+48, stat.st_mtim); + m3ApiWriteMem64(buf+56, stat.st_ctim); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_pread) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (uvwasi_size_t , iovs_len) + m3ApiGetArg (uvwasi_filesize_t , offset) + m3ApiGetArgMem (uvwasi_size_t * , nread) + + m3ApiCheckMem(wasi_iovs, iovs_len * sizeof(wasi_iovec_t)); + m3ApiCheckMem(nread, sizeof(uvwasi_size_t)); + +#if defined(M3_COMPILER_MSVC) + if (iovs_len > 32) m3ApiReturn(UVWASI_EINVAL); + uvwasi_ciovec_t iovs[32]; +#else + if (iovs_len > 128) m3ApiReturn(UVWASI_EINVAL); + uvwasi_ciovec_t iovs[iovs_len]; +#endif + + for (uvwasi_size_t i = 0; i < iovs_len; ++i) { + iovs[i].buf = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iovs[i].buf)); + iovs[i].buf_len = m3ApiReadMem32(&wasi_iovs[i].buf_len); + m3ApiCheckMem(iovs[i].buf, iovs[i].buf_len); + //fprintf(stderr, "> fd_pread fd:%d iov%d.len:%d\n", fd, i, iovs[i].buf_len); + } + + uvwasi_size_t num_read; + + uvwasi_errno_t ret = uvwasi_fd_pread(&uvwasi, fd, (const uvwasi_iovec_t *) iovs, iovs_len, offset, &num_read); + + WASI_TRACE("fd:%d | nread:%d", fd, num_read); + + m3ApiWriteMem32(nread, num_read); + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_read) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (uvwasi_size_t , iovs_len) + m3ApiGetArgMem (uvwasi_size_t * , nread) + + m3ApiCheckMem(wasi_iovs, iovs_len * sizeof(wasi_iovec_t)); + m3ApiCheckMem(nread, sizeof(uvwasi_size_t)); + +#if defined(M3_COMPILER_MSVC) + if (iovs_len > 32) m3ApiReturn(UVWASI_EINVAL); + uvwasi_ciovec_t iovs[32]; +#else + if (iovs_len > 128) m3ApiReturn(UVWASI_EINVAL); + uvwasi_ciovec_t iovs[iovs_len]; +#endif + uvwasi_size_t num_read; + uvwasi_errno_t ret; + + for (uvwasi_size_t i = 0; i < iovs_len; ++i) { + iovs[i].buf = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iovs[i].buf)); + iovs[i].buf_len = m3ApiReadMem32(&wasi_iovs[i].buf_len); + m3ApiCheckMem(iovs[i].buf, iovs[i].buf_len); + //fprintf(stderr, "> fd_read fd:%d iov%d.len:%d\n", fd, i, iovs[i].buf_len); + } + + ret = uvwasi_fd_read(&uvwasi, fd, (const uvwasi_iovec_t *) iovs, iovs_len, &num_read); + + WASI_TRACE("fd:%d | nread:%d", fd, num_read); + + m3ApiWriteMem32(nread, num_read); + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_write) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (uvwasi_size_t , iovs_len) + m3ApiGetArgMem (uvwasi_size_t * , nwritten) + + m3ApiCheckMem(wasi_iovs, iovs_len * sizeof(wasi_iovec_t)); + m3ApiCheckMem(nwritten, sizeof(uvwasi_size_t)); + +#if defined(M3_COMPILER_MSVC) + if (iovs_len > 32) m3ApiReturn(UVWASI_EINVAL); + uvwasi_ciovec_t iovs[32]; +#else + if (iovs_len > 128) m3ApiReturn(UVWASI_EINVAL); + uvwasi_ciovec_t iovs[iovs_len]; +#endif + uvwasi_size_t num_written; + uvwasi_errno_t ret; + + for (uvwasi_size_t i = 0; i < iovs_len; ++i) { + iovs[i].buf = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iovs[i].buf)); + iovs[i].buf_len = m3ApiReadMem32(&wasi_iovs[i].buf_len); + m3ApiCheckMem(iovs[i].buf, iovs[i].buf_len); + } + + ret = uvwasi_fd_write(&uvwasi, fd, iovs, iovs_len, &num_written); + + WASI_TRACE("fd:%d | nwritten:%d", fd, num_written); + + m3ApiWriteMem32(nwritten, num_written); + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_pwrite) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (uvwasi_size_t , iovs_len) + m3ApiGetArg (uvwasi_filesize_t , offset) + m3ApiGetArgMem (uvwasi_size_t * , nwritten) + + m3ApiCheckMem(wasi_iovs, iovs_len * sizeof(wasi_iovec_t)); + m3ApiCheckMem(nwritten, sizeof(uvwasi_size_t)); + +#if defined(M3_COMPILER_MSVC) + if (iovs_len > 32) m3ApiReturn(UVWASI_EINVAL); + uvwasi_ciovec_t iovs[32]; +#else + if (iovs_len > 128) m3ApiReturn(UVWASI_EINVAL); + uvwasi_ciovec_t iovs[iovs_len]; +#endif + uvwasi_size_t num_written; + uvwasi_errno_t ret; + + for (uvwasi_size_t i = 0; i < iovs_len; ++i) { + iovs[i].buf = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iovs[i].buf)); + iovs[i].buf_len = m3ApiReadMem32(&wasi_iovs[i].buf_len); + m3ApiCheckMem(iovs[i].buf, iovs[i].buf_len); + } + + ret = uvwasi_fd_pwrite(&uvwasi, fd, iovs, iovs_len, offset, &num_written); + + WASI_TRACE("fd:%d | nwritten:%d", fd, num_written); + + m3ApiWriteMem32(nwritten, num_written); + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_readdir) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t , fd) + m3ApiGetArgMem (void * , buf) + m3ApiGetArg (uvwasi_size_t , buf_len) + m3ApiGetArg (uvwasi_dircookie_t , cookie) + m3ApiGetArgMem (uvwasi_size_t * , bufused) + + m3ApiCheckMem(buf, buf_len); + m3ApiCheckMem(bufused, sizeof(uvwasi_size_t)); + + uvwasi_size_t uvbufused; + uvwasi_errno_t ret = uvwasi_fd_readdir(&uvwasi, fd, buf, buf_len, cookie, &uvbufused); + + WASI_TRACE("fd:%d | bufused:%d", fd, uvbufused); + + m3ApiWriteMem32(bufused, uvbufused); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_close) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t, fd) + + uvwasi_errno_t ret = uvwasi_fd_close(&uvwasi, fd); + + WASI_TRACE("fd:%d", fd); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_datasync) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_fd_t, fd) + + uvwasi_errno_t ret = uvwasi_fd_datasync(&uvwasi, fd); + + WASI_TRACE("fd:%d", fd); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_random_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint8_t * , buf) + m3ApiGetArg (uvwasi_size_t , buf_len) + + m3ApiCheckMem(buf, buf_len); + + uvwasi_errno_t ret = uvwasi_random_get(&uvwasi, buf, buf_len); + + WASI_TRACE("len:%d", buf_len); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_clock_res_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_clockid_t , wasi_clk_id) + m3ApiGetArgMem (uvwasi_timestamp_t * , resolution) + + m3ApiCheckMem(resolution, sizeof(uvwasi_timestamp_t)); + + uvwasi_timestamp_t t; + uvwasi_errno_t ret = uvwasi_clock_res_get(&uvwasi, wasi_clk_id, &t); + + WASI_TRACE("clk_id:%d", wasi_clk_id); + + m3ApiWriteMem64(resolution, t); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_clock_time_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_clockid_t , wasi_clk_id) + m3ApiGetArg (uvwasi_timestamp_t , precision) + m3ApiGetArgMem (uvwasi_timestamp_t * , time) + + m3ApiCheckMem(time, sizeof(uvwasi_timestamp_t)); + + uvwasi_timestamp_t t; + uvwasi_errno_t ret = uvwasi_clock_time_get(&uvwasi, wasi_clk_id, precision, &t); + + WASI_TRACE("clk_id:%d", wasi_clk_id); + + m3ApiWriteMem64(time, t); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_poll_oneoff) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (const uvwasi_subscription_t * , in) + m3ApiGetArgMem (uvwasi_event_t * , out) + m3ApiGetArg (uvwasi_size_t , nsubscriptions) + m3ApiGetArgMem (uvwasi_size_t * , nevents) + + m3ApiCheckMem(in, nsubscriptions * sizeof(uvwasi_subscription_t)); + m3ApiCheckMem(out, nsubscriptions * sizeof(uvwasi_event_t)); + m3ApiCheckMem(nevents, sizeof(uvwasi_size_t)); + + // TODO: unstable/snapshot_preview1 compatibility + + uvwasi_errno_t ret = uvwasi_poll_oneoff(&uvwasi, in, out, nsubscriptions, nevents); + + WASI_TRACE("nsubscriptions:%d | nevents:%d", nsubscriptions, *nevents); + + //TODO: m3ApiWriteMem + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_proc_exit) +{ + m3ApiGetArg (uint32_t, code) + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context) { + context->exit_code = code; + } + + //TODO: fprintf(stderr, "proc_exit code:%d\n", code); + + m3ApiTrap(m3Err_trapExit); +} + +m3ApiRawFunction(m3_wasi_generic_proc_raise) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (uvwasi_signal_t, sig) + + uvwasi_errno_t ret = uvwasi_proc_raise(&uvwasi, sig); + + WASI_TRACE("sig:%d", sig); + + m3ApiReturn(ret); +} + +m3ApiRawFunction(m3_wasi_generic_sched_yield) +{ + m3ApiReturnType (uint32_t) + uvwasi_errno_t ret = uvwasi_sched_yield(&uvwasi); + + WASI_TRACE(""); + + m3ApiReturn(ret); +} + + +static +M3Result SuppressLookupFailure(M3Result i_result) +{ + if (i_result == m3Err_functionLookupFailed) + return m3Err_none; + else + return i_result; +} + +m3_wasi_context_t* m3_GetWasiContext() +{ + return wasi_context; +} + + +M3Result m3_LinkWASI (IM3Module module) +{ + #define ENV_COUNT 9 + + char* env[ENV_COUNT]; + env[0] = "TERM=xterm-256color"; + env[1] = "COLORTERM=truecolor"; + env[2] = "LANG=en_US.UTF-8"; + env[3] = "PWD=/"; + env[4] = "HOME=/"; + env[5] = "PATH=/"; + env[6] = "WASM3=1"; + env[7] = "WASM3_ARCH=" M3_ARCH; + env[8] = NULL; + + #define PREOPENS_COUNT 2 + + uvwasi_preopen_t preopens[PREOPENS_COUNT]; + preopens[0].mapped_path = "/"; + preopens[0].real_path = "."; + preopens[1].mapped_path = "./"; + preopens[1].real_path = "."; + + uvwasi_options_t init_options; + uvwasi_options_init(&init_options); + init_options.argc = 0; // runtime->argc is not initialized at this point, so we implement args_get directly + init_options.envp = (const char **) env; + init_options.preopenc = PREOPENS_COUNT; + init_options.preopens = preopens; + + return m3_LinkWASIWithOptions(module, init_options); +} + +M3Result m3_LinkWASIWithOptions (IM3Module module, uvwasi_options_t init_options) +{ + M3Result result = m3Err_none; + + if (!wasi_context) { + wasi_context = (m3_wasi_context_t*)malloc(sizeof(m3_wasi_context_t)); + wasi_context->exit_code = 0; + wasi_context->argc = 0; + wasi_context->argv = 0; + + uvwasi_errno_t ret = uvwasi_init(&uvwasi, &init_options); + + if (ret != UVWASI_ESUCCESS) { + return "uvwasi_init failed"; + } + } + + static const char* namespaces[2] = { "wasi_unstable", "wasi_snapshot_preview1" }; + + // Some functions are incompatible between WASI versions +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_unstable", "fd_seek", "i(iIi*)", &m3_wasi_unstable_fd_seek))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1", "fd_seek", "i(iIi*)", &m3_wasi_snapshot_preview1_fd_seek))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_unstable", "fd_filestat_get", "i(i*)", &m3_wasi_unstable_fd_filestat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1", "fd_filestat_get", "i(i*)", &m3_wasi_snapshot_preview1_fd_filestat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_unstable", "path_filestat_get", "i(ii*i*)", &m3_wasi_unstable_path_filestat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1", "path_filestat_get", "i(ii*i*)", &m3_wasi_snapshot_preview1_path_filestat_get))); + + for (int i=0; i<2; i++) + { + const char* wasi = namespaces[i]; + +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "args_get", "i(**)", &m3_wasi_generic_args_get, wasi_context))); +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "args_sizes_get", "i(**)", &m3_wasi_generic_args_sizes_get, wasi_context))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_res_get", "i(i*)", &m3_wasi_generic_clock_res_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_time_get", "i(iI*)", &m3_wasi_generic_clock_time_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_get", "i(**)", &m3_wasi_generic_environ_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_sizes_get", "i(**)", &m3_wasi_generic_environ_sizes_get))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_advise", "i(iIIi)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_allocate", "i(iII)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_close", "i(i)", &m3_wasi_generic_fd_close))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_datasync", "i(i)", &m3_wasi_generic_fd_datasync))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_get", "i(i*)", &m3_wasi_generic_fd_fdstat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_flags", "i(ii)", &m3_wasi_generic_fd_fdstat_set_flags))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_rights", "i(iII)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_size", "i(iI)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_times","i(iIIi)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pread", "i(i*iI*)",&m3_wasi_generic_fd_pread))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_get", "i(i*)", &m3_wasi_generic_fd_prestat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_dir_name", "i(i*i)", &m3_wasi_generic_fd_prestat_dir_name))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pwrite", "i(i*iI*)",&m3_wasi_generic_fd_pwrite))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_read", "i(i*i*)", &m3_wasi_generic_fd_read))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_readdir", "i(i*iI*)",&m3_wasi_generic_fd_readdir))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_renumber", "i(ii)", &m3_wasi_generic_fd_renumber))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_sync", "i(i)", &m3_wasi_generic_fd_sync))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_tell", "i(i*)", &m3_wasi_generic_fd_tell))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_write", "i(i*i*)", &m3_wasi_generic_fd_write))); + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_create_directory", "i(i*i)", &m3_wasi_generic_path_create_directory))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_filestat_set_times", "i(ii*iIIi)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_link", "i(ii*ii*i)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_open", "i(ii*iiIIi*)", &m3_wasi_generic_path_open))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_readlink", "i(i*i*i*)", &m3_wasi_generic_path_readlink))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_remove_directory", "i(i*i)", &m3_wasi_generic_path_remove_directory))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_rename", "i(i*ii*i)", &m3_wasi_generic_path_rename))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_symlink", "i(*ii*i)", &m3_wasi_generic_path_symlink))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_unlink_file", "i(i*i)", &m3_wasi_generic_path_unlink_file))); + +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "poll_oneoff", "i(**i*)", &m3_wasi_generic_poll_oneoff))); +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "proc_exit", "v(i)", &m3_wasi_generic_proc_exit, wasi_context))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "proc_raise", "i(i)", &m3_wasi_generic_proc_raise))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "random_get", "i(*i)", &m3_wasi_generic_random_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sched_yield", "i()", &m3_wasi_generic_sched_yield))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_recv", "i(i*ii**)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_send", "i(i*ii*)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_shutdown", "i(ii)", ))); + } + +_catch: + return result; +} + +#endif // d_m3HasUVWASI + diff --git a/ext/wasm3/source/m3_api_wasi.c b/ext/wasm3/source/m3_api_wasi.c new file mode 100644 index 0000000..52714ec --- /dev/null +++ b/ext/wasm3/source/m3_api_wasi.c @@ -0,0 +1,873 @@ +// +// m3_api_wasi.c +// +// Created by Volodymyr Shymanskyy on 11/20/19. +// Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. +// + +#define _POSIX_C_SOURCE 200809L + +#include "m3_api_wasi.h" + +#include "m3_env.h" +#include "m3_exception.h" + +#if defined(d_m3HasWASI) + +// Fixup wasi_core.h +#if defined (M3_COMPILER_MSVC) +# define _Static_assert(...) +# define __attribute__(...) +# define _Noreturn +#endif + +#include "extra/wasi_core.h" + +#include +#include +#include +#include +#include +#include + +#if defined(APE) +// Actually Portable Executable +// All functions are already included in cosmopolitan.h +#elif defined(__wasi__) || defined(__APPLE__) || defined(__ANDROID_API__) || defined(__OpenBSD__) || defined(__linux__) || defined(__EMSCRIPTEN__) || defined(__CYGWIN__) +# include +# include +# if defined(__APPLE__) +# include +# if TARGET_OS_OSX // TARGET_OS_MAC includes iOS +# include +# else // iOS / Simulator +# include +# endif +# else +# include +# endif +# define HAS_IOVEC +#elif defined(_WIN32) +# include +# include +// See http://msdn.microsoft.com/en-us/library/windows/desktop/aa387694.aspx +# define SystemFunction036 NTAPI SystemFunction036 +# include +# undef SystemFunction036 +# define ssize_t SSIZE_T + +# define open _open +# define read _read +# define write _write +# define close _close +#endif + +static m3_wasi_context_t* wasi_context; + +typedef struct wasi_iovec_t +{ + __wasi_size_t buf; + __wasi_size_t buf_len; +} wasi_iovec_t; + +#define PREOPEN_CNT 5 + +typedef struct Preopen { + int fd; + const char* path; + const char* real_path; +} Preopen; + +Preopen preopen[PREOPEN_CNT] = { + { 0, "" , "" }, + { 1, "", "" }, + { 2, "", "" }, + { -1, "/" , "." }, + { -1, "./" , "." }, +}; + +#if defined(APE) +# define APE_SWITCH_BEG +# define APE_SWITCH_END {} +# define APE_CASE_RET(e1,e2) if (errnum == e1) return e2; else +#else +# define APE_SWITCH_BEG switch (errnum) { +# define APE_SWITCH_END } +# define APE_CASE_RET(e1,e2) case e1: return e2; break; +#endif + +static +__wasi_errno_t errno_to_wasi(int errnum) { + APE_SWITCH_BEG + APE_CASE_RET( EPERM , __WASI_ERRNO_PERM ) + APE_CASE_RET( ENOENT , __WASI_ERRNO_NOENT ) + APE_CASE_RET( ESRCH , __WASI_ERRNO_SRCH ) + APE_CASE_RET( EINTR , __WASI_ERRNO_INTR ) + APE_CASE_RET( EIO , __WASI_ERRNO_IO ) + APE_CASE_RET( ENXIO , __WASI_ERRNO_NXIO ) + APE_CASE_RET( E2BIG , __WASI_ERRNO_2BIG ) + APE_CASE_RET( ENOEXEC , __WASI_ERRNO_NOEXEC ) + APE_CASE_RET( EBADF , __WASI_ERRNO_BADF ) + APE_CASE_RET( ECHILD , __WASI_ERRNO_CHILD ) + APE_CASE_RET( EAGAIN , __WASI_ERRNO_AGAIN ) + APE_CASE_RET( ENOMEM , __WASI_ERRNO_NOMEM ) + APE_CASE_RET( EACCES , __WASI_ERRNO_ACCES ) + APE_CASE_RET( EFAULT , __WASI_ERRNO_FAULT ) + APE_CASE_RET( EBUSY , __WASI_ERRNO_BUSY ) + APE_CASE_RET( EEXIST , __WASI_ERRNO_EXIST ) + APE_CASE_RET( EXDEV , __WASI_ERRNO_XDEV ) + APE_CASE_RET( ENODEV , __WASI_ERRNO_NODEV ) + APE_CASE_RET( ENOTDIR , __WASI_ERRNO_NOTDIR ) + APE_CASE_RET( EISDIR , __WASI_ERRNO_ISDIR ) + APE_CASE_RET( EINVAL , __WASI_ERRNO_INVAL ) + APE_CASE_RET( ENFILE , __WASI_ERRNO_NFILE ) + APE_CASE_RET( EMFILE , __WASI_ERRNO_MFILE ) + APE_CASE_RET( ENOTTY , __WASI_ERRNO_NOTTY ) + APE_CASE_RET( ETXTBSY , __WASI_ERRNO_TXTBSY ) + APE_CASE_RET( EFBIG , __WASI_ERRNO_FBIG ) + APE_CASE_RET( ENOSPC , __WASI_ERRNO_NOSPC ) + APE_CASE_RET( ESPIPE , __WASI_ERRNO_SPIPE ) + APE_CASE_RET( EROFS , __WASI_ERRNO_ROFS ) + APE_CASE_RET( EMLINK , __WASI_ERRNO_MLINK ) + APE_CASE_RET( EPIPE , __WASI_ERRNO_PIPE ) + APE_CASE_RET( EDOM , __WASI_ERRNO_DOM ) + APE_CASE_RET( ERANGE , __WASI_ERRNO_RANGE ) + APE_SWITCH_END + return __WASI_ERRNO_INVAL; +} + +#if defined(_WIN32) + +#if !defined(__MINGW32__) + +static inline +int clock_gettime(int clk_id, struct timespec *spec) +{ + __int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime); + wintime -= 116444736000000000i64; //1jan1601 to 1jan1970 + spec->tv_sec = wintime / 10000000i64; //seconds + spec->tv_nsec = wintime % 10000000i64 *100; //nano-seconds + return 0; +} + +static inline +int clock_getres(int clk_id, struct timespec *spec) { + return -1; // Defaults to 1000000 +} + +#endif + +static inline +int convert_clockid(__wasi_clockid_t in) { + return 0; +} + +#else // _WIN32 + +static inline +int convert_clockid(__wasi_clockid_t in) { + switch (in) { + case __WASI_CLOCKID_MONOTONIC: return CLOCK_MONOTONIC; + case __WASI_CLOCKID_PROCESS_CPUTIME_ID: return CLOCK_PROCESS_CPUTIME_ID; + case __WASI_CLOCKID_REALTIME: return CLOCK_REALTIME; + case __WASI_CLOCKID_THREAD_CPUTIME_ID: return CLOCK_THREAD_CPUTIME_ID; + default: return -1; + } +} + +#endif // _WIN32 + +static inline +__wasi_timestamp_t convert_timespec(const struct timespec *ts) { + if (ts->tv_sec < 0) + return 0; + if ((__wasi_timestamp_t)ts->tv_sec >= UINT64_MAX / 1000000000) + return UINT64_MAX; + return (__wasi_timestamp_t)ts->tv_sec * 1000000000 + ts->tv_nsec; +} + +#if defined(HAS_IOVEC) + +static inline +const void* copy_iov_to_host(IM3Runtime runtime, void* _mem, struct iovec* host_iov, wasi_iovec_t* wasi_iov, int32_t iovs_len) +{ + // Convert wasi memory offsets to host addresses + for (int i = 0; i < iovs_len; i++) { + host_iov[i].iov_base = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iov[i].buf)); + host_iov[i].iov_len = m3ApiReadMem32(&wasi_iov[i].buf_len); + m3ApiCheckMem(host_iov[i].iov_base, host_iov[i].iov_len); + } + m3ApiSuccess(); +} + +#endif + +/* + * WASI API implementation + */ + +m3ApiRawFunction(m3_wasi_generic_args_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint32_t * , argv) + m3ApiGetArgMem (char * , argv_buf) + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context == NULL) { m3ApiReturn(__WASI_ERRNO_INVAL); } + + m3ApiCheckMem(argv, context->argc * sizeof(uint32_t)); + + for (u32 i = 0; i < context->argc; ++i) + { + m3ApiWriteMem32(&argv[i], m3ApiPtrToOffset(argv_buf)); + + size_t len = strlen (context->argv[i]); + + m3ApiCheckMem(argv_buf, len); + memcpy (argv_buf, context->argv[i], len); + argv_buf += len; + * argv_buf++ = 0; + } + + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_args_sizes_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (__wasi_size_t * , argc) + m3ApiGetArgMem (__wasi_size_t * , argv_buf_size) + + m3ApiCheckMem(argc, sizeof(__wasi_size_t)); + m3ApiCheckMem(argv_buf_size, sizeof(__wasi_size_t)); + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context == NULL) { m3ApiReturn(__WASI_ERRNO_INVAL); } + + __wasi_size_t buf_len = 0; + for (u32 i = 0; i < context->argc; ++i) + { + buf_len += strlen (context->argv[i]) + 1; + } + + m3ApiWriteMem32(argc, context->argc); + m3ApiWriteMem32(argv_buf_size, buf_len); + + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_environ_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint32_t * , env) + m3ApiGetArgMem (char * , env_buf) + + // TODO + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_environ_sizes_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (__wasi_size_t * , env_count) + m3ApiGetArgMem (__wasi_size_t * , env_buf_size) + + m3ApiCheckMem(env_count, sizeof(__wasi_size_t)); + m3ApiCheckMem(env_buf_size, sizeof(__wasi_size_t)); + + // TODO + m3ApiWriteMem32(env_count, 0); + m3ApiWriteMem32(env_buf_size, 0); + + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_fd_prestat_dir_name) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (char * , path) + m3ApiGetArg (__wasi_size_t , path_len) + + m3ApiCheckMem(path, path_len); + + if (fd < 3 || fd >= PREOPEN_CNT) { m3ApiReturn(__WASI_ERRNO_BADF); } + size_t slen = strlen(preopen[fd].path) + 1; + memcpy(path, preopen[fd].path, M3_MIN(slen, path_len)); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_fd_prestat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (uint8_t * , buf) + + m3ApiCheckMem(buf, 8); + + if (fd < 3 || fd >= PREOPEN_CNT) { m3ApiReturn(__WASI_ERRNO_BADF); } + + m3ApiWriteMem32(buf+0, __WASI_PREOPENTYPE_DIR); + m3ApiWriteMem32(buf+4, strlen(preopen[fd].path) + 1); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_fd_fdstat_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (__wasi_fdstat_t * , fdstat) + + m3ApiCheckMem(fdstat, sizeof(__wasi_fdstat_t)); + +#ifdef _WIN32 + + // TODO: This needs a proper implementation + if (fd < PREOPEN_CNT) { + fdstat->fs_filetype= __WASI_FILETYPE_DIRECTORY; + } else { + fdstat->fs_filetype= __WASI_FILETYPE_REGULAR_FILE; + } + + fdstat->fs_flags = 0; + fdstat->fs_rights_base = (uint64_t)-1; // all rights + fdstat->fs_rights_inheriting = (uint64_t)-1; // all rights + m3ApiReturn(__WASI_ERRNO_SUCCESS); +#else + struct stat fd_stat; + +#if !defined(APE) // TODO: not implemented in Cosmopolitan + int fl = fcntl(fd, F_GETFL); + if (fl < 0) { m3ApiReturn(errno_to_wasi(errno)); } +#endif + + fstat(fd, &fd_stat); + int mode = fd_stat.st_mode; + fdstat->fs_filetype = (S_ISBLK(mode) ? __WASI_FILETYPE_BLOCK_DEVICE : 0) | + (S_ISCHR(mode) ? __WASI_FILETYPE_CHARACTER_DEVICE : 0) | + (S_ISDIR(mode) ? __WASI_FILETYPE_DIRECTORY : 0) | + (S_ISREG(mode) ? __WASI_FILETYPE_REGULAR_FILE : 0) | + //(S_ISSOCK(mode) ? __WASI_FILETYPE_SOCKET_STREAM : 0) | + (S_ISLNK(mode) ? __WASI_FILETYPE_SYMBOLIC_LINK : 0); +#if !defined(APE) + m3ApiWriteMem16(&fdstat->fs_flags, + ((fl & O_APPEND) ? __WASI_FDFLAGS_APPEND : 0) | + ((fl & O_DSYNC) ? __WASI_FDFLAGS_DSYNC : 0) | + ((fl & O_NONBLOCK) ? __WASI_FDFLAGS_NONBLOCK : 0) | + //((fl & O_RSYNC) ? __WASI_FDFLAGS_RSYNC : 0) | + ((fl & O_SYNC) ? __WASI_FDFLAGS_SYNC : 0)); +#endif // APE + + fdstat->fs_rights_base = (uint64_t)-1; // all rights + + // Make descriptors 0,1,2 look like a TTY + if (fd <= 2) { + fdstat->fs_rights_base &= ~(__WASI_RIGHTS_FD_SEEK | __WASI_RIGHTS_FD_TELL); + } + + fdstat->fs_rights_inheriting = (uint64_t)-1; // all rights + m3ApiReturn(__WASI_ERRNO_SUCCESS); +#endif +} + +m3ApiRawFunction(m3_wasi_generic_fd_fdstat_set_flags) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_fdflags_t , flags) + + // TODO + + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_unstable_fd_seek) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_filedelta_t , offset) + m3ApiGetArg (uint32_t , wasi_whence) + m3ApiGetArgMem (__wasi_filesize_t * , result) + + m3ApiCheckMem(result, sizeof(__wasi_filesize_t)); + + int whence; + + switch (wasi_whence) { + case 0: whence = SEEK_CUR; break; + case 1: whence = SEEK_END; break; + case 2: whence = SEEK_SET; break; + default: m3ApiReturn(__WASI_ERRNO_INVAL); + } + + int64_t ret; +#if defined(M3_COMPILER_MSVC) || defined(__MINGW32__) + ret = _lseeki64(fd, offset, whence); +#else + ret = lseek(fd, offset, whence); +#endif + if (ret < 0) { m3ApiReturn(errno_to_wasi(errno)); } + m3ApiWriteMem64(result, ret); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_snapshot_preview1_fd_seek) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArg (__wasi_filedelta_t , offset) + m3ApiGetArg (uint32_t , wasi_whence) + m3ApiGetArgMem (__wasi_filesize_t * , result) + + m3ApiCheckMem(result, sizeof(__wasi_filesize_t)); + + int whence; + + switch (wasi_whence) { + case 0: whence = SEEK_SET; break; + case 1: whence = SEEK_CUR; break; + case 2: whence = SEEK_END; break; + default: m3ApiReturn(__WASI_ERRNO_INVAL); + } + + int64_t ret; +#if defined(M3_COMPILER_MSVC) || defined(__MINGW32__) + ret = _lseeki64(fd, offset, whence); +#else + ret = lseek(fd, offset, whence); +#endif + if (ret < 0) { m3ApiReturn(errno_to_wasi(errno)); } + m3ApiWriteMem64(result, ret); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + + +m3ApiRawFunction(m3_wasi_generic_path_open) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , dirfd) + m3ApiGetArg (__wasi_lookupflags_t , dirflags) + m3ApiGetArgMem (const char * , path) + m3ApiGetArg (__wasi_size_t , path_len) + m3ApiGetArg (__wasi_oflags_t , oflags) + m3ApiGetArg (__wasi_rights_t , fs_rights_base) + m3ApiGetArg (__wasi_rights_t , fs_rights_inheriting) + m3ApiGetArg (__wasi_fdflags_t , fs_flags) + m3ApiGetArgMem (__wasi_fd_t * , fd) + + m3ApiCheckMem(path, path_len); + m3ApiCheckMem(fd, sizeof(__wasi_fd_t)); + + if (path_len >= 512) + m3ApiReturn(__WASI_ERRNO_INVAL); + + // copy path so we can ensure it is NULL terminated +#if defined(M3_COMPILER_MSVC) + char host_path[512]; +#else + char host_path[path_len+1]; +#endif + memcpy (host_path, path, path_len); + host_path[path_len] = '\0'; // NULL terminator + +#if defined(APE) + // TODO: This all needs a proper implementation + + int flags = ((oflags & __WASI_OFLAGS_CREAT) ? O_CREAT : 0) | + ((oflags & __WASI_OFLAGS_EXCL) ? O_EXCL : 0) | + ((oflags & __WASI_OFLAGS_TRUNC) ? O_TRUNC : 0) | + ((fs_flags & __WASI_FDFLAGS_APPEND) ? O_APPEND : 0); + + if ((fs_rights_base & __WASI_RIGHTS_FD_READ) && + (fs_rights_base & __WASI_RIGHTS_FD_WRITE)) { + flags |= O_RDWR; + } else if ((fs_rights_base & __WASI_RIGHTS_FD_WRITE)) { + flags |= O_WRONLY; + } else if ((fs_rights_base & __WASI_RIGHTS_FD_READ)) { + flags |= O_RDONLY; // no-op because O_RDONLY is 0 + } + int mode = 0644; + + int host_fd = open (host_path, flags, mode); + + if (host_fd < 0) + { + m3ApiReturn(errno_to_wasi (errno)); + } + else + { + m3ApiWriteMem32(fd, host_fd); + m3ApiReturn(__WASI_ERRNO_SUCCESS); + } +#elif defined(_WIN32) + // TODO: This all needs a proper implementation + + int flags = ((oflags & __WASI_OFLAGS_CREAT) ? _O_CREAT : 0) | + ((oflags & __WASI_OFLAGS_EXCL) ? _O_EXCL : 0) | + ((oflags & __WASI_OFLAGS_TRUNC) ? _O_TRUNC : 0) | + ((fs_flags & __WASI_FDFLAGS_APPEND) ? _O_APPEND : 0) | + _O_BINARY; + + if ((fs_rights_base & __WASI_RIGHTS_FD_READ) && + (fs_rights_base & __WASI_RIGHTS_FD_WRITE)) { + flags |= _O_RDWR; + } else if ((fs_rights_base & __WASI_RIGHTS_FD_WRITE)) { + flags |= _O_WRONLY; + } else if ((fs_rights_base & __WASI_RIGHTS_FD_READ)) { + flags |= _O_RDONLY; // no-op because O_RDONLY is 0 + } + int mode = 0644; + + int host_fd = open (host_path, flags, mode); + + if (host_fd < 0) + { + m3ApiReturn(errno_to_wasi (errno)); + } + else + { + m3ApiWriteMem32(fd, host_fd); + m3ApiReturn(__WASI_ERRNO_SUCCESS); + } +#else + // translate o_flags and fs_flags into flags and mode + int flags = ((oflags & __WASI_OFLAGS_CREAT) ? O_CREAT : 0) | + //((oflags & __WASI_OFLAGS_DIRECTORY) ? O_DIRECTORY : 0) | + ((oflags & __WASI_OFLAGS_EXCL) ? O_EXCL : 0) | + ((oflags & __WASI_OFLAGS_TRUNC) ? O_TRUNC : 0) | + ((fs_flags & __WASI_FDFLAGS_APPEND) ? O_APPEND : 0) | + ((fs_flags & __WASI_FDFLAGS_DSYNC) ? O_DSYNC : 0) | + ((fs_flags & __WASI_FDFLAGS_NONBLOCK) ? O_NONBLOCK : 0) | + //((fs_flags & __WASI_FDFLAGS_RSYNC) ? O_RSYNC : 0) | + ((fs_flags & __WASI_FDFLAGS_SYNC) ? O_SYNC : 0); + if ((fs_rights_base & __WASI_RIGHTS_FD_READ) && + (fs_rights_base & __WASI_RIGHTS_FD_WRITE)) { + flags |= O_RDWR; + } else if ((fs_rights_base & __WASI_RIGHTS_FD_WRITE)) { + flags |= O_WRONLY; + } else if ((fs_rights_base & __WASI_RIGHTS_FD_READ)) { + flags |= O_RDONLY; // no-op because O_RDONLY is 0 + } + int mode = 0644; + int host_fd = openat (preopen[dirfd].fd, host_path, flags, mode); + + if (host_fd < 0) + { + m3ApiReturn(errno_to_wasi (errno)); + } + else + { + m3ApiWriteMem32(fd, host_fd); + m3ApiReturn(__WASI_ERRNO_SUCCESS); + } +#endif +} + +m3ApiRawFunction(m3_wasi_generic_fd_read) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (__wasi_size_t , iovs_len) + m3ApiGetArgMem (__wasi_size_t * , nread) + + m3ApiCheckMem(wasi_iovs, iovs_len * sizeof(wasi_iovec_t)); + m3ApiCheckMem(nread, sizeof(__wasi_size_t)); + +#if defined(HAS_IOVEC) + struct iovec iovs[iovs_len]; + const void* mem_check = copy_iov_to_host(runtime, _mem, iovs, wasi_iovs, iovs_len); + if (mem_check != m3Err_none) { + return mem_check; + } + + ssize_t ret = readv(fd, iovs, iovs_len); + if (ret < 0) { m3ApiReturn(errno_to_wasi(errno)); } + m3ApiWriteMem32(nread, ret); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +#else + ssize_t res = 0; + for (__wasi_size_t i = 0; i < iovs_len; i++) { + void* addr = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iovs[i].buf)); + size_t len = m3ApiReadMem32(&wasi_iovs[i].buf_len); + if (len == 0) continue; + m3ApiCheckMem(addr, len); + int ret = read (fd, addr, len); + if (ret < 0) m3ApiReturn(errno_to_wasi(errno)); + res += ret; + if ((size_t)ret < len) break; + } + m3ApiWriteMem32(nread, res); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +#endif +} + +m3ApiRawFunction(m3_wasi_generic_fd_write) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t , fd) + m3ApiGetArgMem (wasi_iovec_t * , wasi_iovs) + m3ApiGetArg (__wasi_size_t , iovs_len) + m3ApiGetArgMem (__wasi_size_t * , nwritten) + + m3ApiCheckMem(wasi_iovs, iovs_len * sizeof(wasi_iovec_t)); + m3ApiCheckMem(nwritten, sizeof(__wasi_size_t)); + +#if defined(HAS_IOVEC) + struct iovec iovs[iovs_len]; + const void* mem_check = copy_iov_to_host(runtime, _mem, iovs, wasi_iovs, iovs_len); + if (mem_check != m3Err_none) { + return mem_check; + } + + ssize_t ret = writev(fd, iovs, iovs_len); + if (ret < 0) { m3ApiReturn(errno_to_wasi(errno)); } + m3ApiWriteMem32(nwritten, ret); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +#else + ssize_t res = 0; + for (__wasi_size_t i = 0; i < iovs_len; i++) { + void* addr = m3ApiOffsetToPtr(m3ApiReadMem32(&wasi_iovs[i].buf)); + size_t len = m3ApiReadMem32(&wasi_iovs[i].buf_len); + if (len == 0) continue; + m3ApiCheckMem(addr, len); + int ret = write (fd, addr, len); + if (ret < 0) m3ApiReturn(errno_to_wasi(errno)); + res += ret; + if ((size_t)ret < len) break; + } + m3ApiWriteMem32(nwritten, res); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +#endif +} + +m3ApiRawFunction(m3_wasi_generic_fd_close) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t, fd) + + int ret = close(fd); + m3ApiReturn(ret == 0 ? __WASI_ERRNO_SUCCESS : ret); +} + +m3ApiRawFunction(m3_wasi_generic_fd_datasync) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_fd_t, fd) + +#if defined(_WIN32) + int ret = _commit(fd); +#elif defined(__APPLE__) + int ret = fsync(fd); +#elif defined(__ANDROID_API__) || defined(__OpenBSD__) || defined(__linux__) || defined(__EMSCRIPTEN__) + int ret = fdatasync(fd); +#else + int ret = __WASI_ERRNO_NOSYS; +#endif + m3ApiReturn(ret == 0 ? __WASI_ERRNO_SUCCESS : ret); +} + +m3ApiRawFunction(m3_wasi_generic_random_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArgMem (uint8_t * , buf) + m3ApiGetArg (__wasi_size_t , buf_len) + + m3ApiCheckMem(buf, buf_len); + + while (1) { + ssize_t retlen = 0; + +#if defined(__wasi__) || defined(__APPLE__) || defined(__ANDROID_API__) || defined(__OpenBSD__) || defined(__EMSCRIPTEN__) + size_t reqlen = M3_MIN (buf_len, 256); +# if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR) + retlen = SecRandomCopyBytes(kSecRandomDefault, reqlen, buf) < 0 ? -1 : reqlen; +# else + retlen = getentropy(buf, reqlen) < 0 ? -1 : reqlen; +# endif +#elif defined(__FreeBSD__) || defined(__linux__) + retlen = getrandom(buf, buf_len, 0); +#elif defined(_WIN32) + if (RtlGenRandom(buf, buf_len) == TRUE) { + m3ApiReturn(__WASI_ERRNO_SUCCESS); + } +#else + m3ApiReturn(__WASI_ERRNO_NOSYS); +#endif + if (retlen < 0) { + if (errno == EINTR || errno == EAGAIN) { + continue; + } + m3ApiReturn(errno_to_wasi(errno)); + } else if (retlen == buf_len) { + m3ApiReturn(__WASI_ERRNO_SUCCESS); + } else { + buf += retlen; + buf_len -= retlen; + } + } +} + +m3ApiRawFunction(m3_wasi_generic_clock_res_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_clockid_t , wasi_clk_id) + m3ApiGetArgMem (__wasi_timestamp_t * , resolution) + + m3ApiCheckMem(resolution, sizeof(__wasi_timestamp_t)); + + int clk = convert_clockid(wasi_clk_id); + if (clk < 0) m3ApiReturn(__WASI_ERRNO_INVAL); + + struct timespec tp; + if (clock_getres(clk, &tp) != 0) { + m3ApiWriteMem64(resolution, 1000000); + } else { + m3ApiWriteMem64(resolution, convert_timespec(&tp)); + } + + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_clock_time_get) +{ + m3ApiReturnType (uint32_t) + m3ApiGetArg (__wasi_clockid_t , wasi_clk_id) + m3ApiGetArg (__wasi_timestamp_t , precision) + m3ApiGetArgMem (__wasi_timestamp_t * , time) + + m3ApiCheckMem(time, sizeof(__wasi_timestamp_t)); + + int clk = convert_clockid(wasi_clk_id); + if (clk < 0) m3ApiReturn(__WASI_ERRNO_INVAL); + + struct timespec tp; + if (clock_gettime(clk, &tp) != 0) { + m3ApiReturn(errno_to_wasi(errno)); + } + + m3ApiWriteMem64(time, convert_timespec(&tp)); + m3ApiReturn(__WASI_ERRNO_SUCCESS); +} + +m3ApiRawFunction(m3_wasi_generic_proc_exit) +{ + m3ApiGetArg (uint32_t, code) + + m3_wasi_context_t* context = (m3_wasi_context_t*)(_ctx->userdata); + + if (context) { + context->exit_code = code; + } + + m3ApiTrap(m3Err_trapExit); +} + + +static +M3Result SuppressLookupFailure(M3Result i_result) +{ + if (i_result == m3Err_functionLookupFailed) + return m3Err_none; + else + return i_result; +} + +m3_wasi_context_t* m3_GetWasiContext() +{ + return wasi_context; +} + + +M3Result m3_LinkWASI (IM3Module module) +{ + M3Result result = m3Err_none; + +#ifdef _WIN32 + setmode(fileno(stdin), O_BINARY); + setmode(fileno(stdout), O_BINARY); + setmode(fileno(stderr), O_BINARY); + +#else + // Preopen dirs + for (int i = 3; i < PREOPEN_CNT; i++) { + preopen[i].fd = open(preopen[i].real_path, O_RDONLY); + } +#endif + + if (!wasi_context) { + wasi_context = (m3_wasi_context_t*)malloc(sizeof(m3_wasi_context_t)); + wasi_context->exit_code = 0; + wasi_context->argc = 0; + wasi_context->argv = 0; + } + + static const char* namespaces[2] = { "wasi_unstable", "wasi_snapshot_preview1" }; + + // Some functions are incompatible between WASI versions +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_unstable", "fd_seek", "i(iIi*)", &m3_wasi_unstable_fd_seek))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1", "fd_seek", "i(iIi*)", &m3_wasi_snapshot_preview1_fd_seek))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_unstable", "fd_filestat_get", "i(i*)", &m3_wasi_unstable_fd_filestat_get))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1", "fd_filestat_get", "i(i*)", &m3_wasi_snapshot_preview1_fd_filestat_get))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_unstable", "path_filestat_get", "i(ii*i*)", &m3_wasi_unstable_path_filestat_get))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, "wasi_snapshot_preview1", "path_filestat_get", "i(ii*i*)", &m3_wasi_snapshot_preview1_path_filestat_get))); + + for (int i=0; i<2; i++) + { + const char* wasi = namespaces[i]; + +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "args_get", "i(**)", &m3_wasi_generic_args_get, wasi_context))); +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "args_sizes_get", "i(**)", &m3_wasi_generic_args_sizes_get, wasi_context))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_res_get", "i(i*)", &m3_wasi_generic_clock_res_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "clock_time_get", "i(iI*)", &m3_wasi_generic_clock_time_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_get", "i(**)", &m3_wasi_generic_environ_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "environ_sizes_get", "i(**)", &m3_wasi_generic_environ_sizes_get))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_advise", "i(iIIi)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_allocate", "i(iII)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_close", "i(i)", &m3_wasi_generic_fd_close))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_datasync", "i(i)", &m3_wasi_generic_fd_datasync))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_get", "i(i*)", &m3_wasi_generic_fd_fdstat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_flags", "i(ii)", &m3_wasi_generic_fd_fdstat_set_flags))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_fdstat_set_rights", "i(iII)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_size", "i(iI)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_filestat_set_times","i(iIIi)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pread", "i(i*iI*)",))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_get", "i(i*)", &m3_wasi_generic_fd_prestat_get))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_prestat_dir_name", "i(i*i)", &m3_wasi_generic_fd_prestat_dir_name))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_pwrite", "i(i*iI*)",))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_read", "i(i*i*)", &m3_wasi_generic_fd_read))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_readdir", "i(i*iI*)",))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_renumber", "i(ii)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_sync", "i(i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_tell", "i(i*)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "fd_write", "i(i*i*)", &m3_wasi_generic_fd_write))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_create_directory", "i(i*i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_filestat_set_times", "i(ii*iIIi)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_link", "i(ii*ii*i)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_open", "i(ii*iiIIi*)", &m3_wasi_generic_path_open))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_readlink", "i(i*i*i*)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_remove_directory", "i(i*i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_rename", "i(i*ii*i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_symlink", "i(*ii*i)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "path_unlink_file", "i(i*i)", ))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "poll_oneoff", "i(**i*)", &m3_wasi_generic_poll_oneoff))); +_ (SuppressLookupFailure (m3_LinkRawFunctionEx (module, wasi, "proc_exit", "v(i)", &m3_wasi_generic_proc_exit, wasi_context))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "proc_raise", "i(i)", ))); +_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "random_get", "i(*i)", &m3_wasi_generic_random_get))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sched_yield", "i()", ))); + +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_recv", "i(i*ii**)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_send", "i(i*ii*)", ))); +//_ (SuppressLookupFailure (m3_LinkRawFunction (module, wasi, "sock_shutdown", "i(ii)", ))); + } + +_catch: + return result; +} + +#endif // d_m3HasWASI diff --git a/ext/wasm3/source/m3_api_wasi.h b/ext/wasm3/source/m3_api_wasi.h new file mode 100644 index 0000000..5f7ffcd --- /dev/null +++ b/ext/wasm3/source/m3_api_wasi.h @@ -0,0 +1,38 @@ +// +// m3_api_wasi.h +// +// Created by Volodymyr Shymanskyy on 11/20/19. +// Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. +// + +#ifndef m3_api_wasi_h +#define m3_api_wasi_h + +#include "m3_core.h" + +#if defined(d_m3HasUVWASI) +#include "uvwasi.h" +#endif + +d_m3BeginExternC + +typedef struct m3_wasi_context_t +{ + i32 exit_code; + u32 argc; + ccstr_t * argv; +} m3_wasi_context_t; + +M3Result m3_LinkWASI (IM3Module io_module); + +#if defined(d_m3HasUVWASI) + +M3Result m3_LinkWASIWithOptions (IM3Module io_module, uvwasi_options_t uvwasiOptions); + +#endif + +m3_wasi_context_t* m3_GetWasiContext(); + +d_m3EndExternC + +#endif // m3_api_wasi_h diff --git a/ext/wasm3/source/m3_bind.c b/ext/wasm3/source/m3_bind.c new file mode 100644 index 0000000..f6dc88b --- /dev/null +++ b/ext/wasm3/source/m3_bind.c @@ -0,0 +1,175 @@ +// +// m3_bind.c +// +// Created by Steven Massey on 4/29/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#include "m3_env.h" +#include "m3_exception.h" +#include "m3_info.h" + + +u8 ConvertTypeCharToTypeId (char i_code) +{ + switch (i_code) { + case 'v': return c_m3Type_none; + case 'i': return c_m3Type_i32; + case 'I': return c_m3Type_i64; + case 'f': return c_m3Type_f32; + case 'F': return c_m3Type_f64; + case '*': return c_m3Type_i32; + } + return c_m3Type_unknown; +} + + +M3Result SignatureToFuncType (IM3FuncType * o_functionType, ccstr_t i_signature) +{ + IM3FuncType funcType = NULL; + +_try { + if (not o_functionType) + _throw ("null function type"); + + if (not i_signature) + _throw ("null function signature"); + + cstr_t sig = i_signature; + + size_t maxNumTypes = strlen (i_signature); + + // assume min signature is "()" + _throwif (m3Err_malformedFunctionSignature, maxNumTypes < 2); + maxNumTypes -= 2; + + _throwif (m3Err_tooManyArgsRets, maxNumTypes > d_m3MaxSaneFunctionArgRetCount); + +_ (AllocFuncType (& funcType, (u32) maxNumTypes)); + + u8 * typelist = funcType->types; + + bool parsingRets = true; + while (* sig) + { + char typeChar = * sig++; + + if (typeChar == '(') + { + parsingRets = false; + continue; + } + else if ( typeChar == ' ') + continue; + else if (typeChar == ')') + break; + + u8 type = ConvertTypeCharToTypeId (typeChar); + + _throwif ("unknown argument type char", c_m3Type_unknown == type); + + if (type == c_m3Type_none) + continue; + + if (parsingRets) + { + _throwif ("malformed signature; return count overflow", funcType->numRets >= maxNumTypes); + funcType->numRets++; + *typelist++ = type; + } + else + { + _throwif ("malformed signature; arg count overflow", (u32)(funcType->numRets) + funcType->numArgs >= maxNumTypes); + funcType->numArgs++; + *typelist++ = type; + } + } + +} _catch: + + if (result) + m3_Free (funcType); + + * o_functionType = funcType; + + return result; +} + + +static +M3Result ValidateSignature (IM3Function i_function, ccstr_t i_linkingSignature) +{ + M3Result result = m3Err_none; + + IM3FuncType ftype = NULL; +_ (SignatureToFuncType (& ftype, i_linkingSignature)); + + if (not AreFuncTypesEqual (ftype, i_function->funcType)) + { + m3log (module, "expected: %s", SPrintFuncTypeSignature (ftype)); + m3log (module, " found: %s", SPrintFuncTypeSignature (i_function->funcType)); + + _throw ("function signature mismatch"); + } + + _catch: + + m3_Free (ftype); + + return result; +} + + +M3Result FindAndLinkFunction (IM3Module io_module, + ccstr_t i_moduleName, + ccstr_t i_functionName, + ccstr_t i_signature, + voidptr_t i_function, + voidptr_t i_userdata) +{ +_try { + _throwif(m3Err_moduleNotLinked, !io_module->runtime); + + const bool wildcardModule = (strcmp (i_moduleName, "*") == 0); + + result = m3Err_functionLookupFailed; + + for (u32 i = 0; i < io_module->numFunctions; ++i) + { + const IM3Function f = & io_module->functions [i]; + + if (f->import.moduleUtf8 and f->import.fieldUtf8) + { + if (strcmp (f->import.fieldUtf8, i_functionName) == 0 and + (wildcardModule or strcmp (f->import.moduleUtf8, i_moduleName) == 0)) + { + if (i_signature) { +_ (ValidateSignature (f, i_signature)); + } +_ (CompileRawFunction (io_module, f, i_function, i_userdata)); + } + } + } +} _catch: + return result; +} + +M3Result m3_LinkRawFunctionEx (IM3Module io_module, + const char * const i_moduleName, + const char * const i_functionName, + const char * const i_signature, + M3RawCall i_function, + const void * i_userdata) +{ + return FindAndLinkFunction (io_module, i_moduleName, i_functionName, i_signature, (voidptr_t)i_function, i_userdata); +} + +M3Result m3_LinkRawFunction (IM3Module io_module, + const char * const i_moduleName, + const char * const i_functionName, + const char * const i_signature, + M3RawCall i_function) +{ + return FindAndLinkFunction (io_module, i_moduleName, i_functionName, i_signature, (voidptr_t)i_function, NULL); +} + diff --git a/ext/wasm3/source/m3_bind.h b/ext/wasm3/source/m3_bind.h new file mode 100644 index 0000000..a80317a --- /dev/null +++ b/ext/wasm3/source/m3_bind.h @@ -0,0 +1,20 @@ +// +// m3_bind.h +// +// Created by Steven Massey on 2/27/20. +// Copyright © 2020 Steven Massey. All rights reserved. +// + +#ifndef m3_bind_h +#define m3_bind_h + +#include "m3_env.h" + +d_m3BeginExternC + +u8 ConvertTypeCharToTypeId (char i_code); +M3Result SignatureToFuncType (IM3FuncType * o_functionType, ccstr_t i_signature); + +d_m3EndExternC + +#endif /* m3_bind_h */ diff --git a/ext/wasm3/source/m3_code.c b/ext/wasm3/source/m3_code.c new file mode 100644 index 0000000..a5dd5d3 --- /dev/null +++ b/ext/wasm3/source/m3_code.c @@ -0,0 +1,231 @@ +// +// m3_code.c +// +// Created by Steven Massey on 4/19/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#include "m3_code.h" +#include "m3_env.h" + +//--------------------------------------------------------------------------------------------------------------------------------- + + +IM3CodePage NewCodePage (IM3Runtime i_runtime, u32 i_minNumLines) +{ + IM3CodePage page; + + u32 pageSize = sizeof (M3CodePageHeader) + sizeof (code_t) * i_minNumLines; + + pageSize = (pageSize + (d_m3CodePageAlignSize-1)) & ~(d_m3CodePageAlignSize-1); // align + page = (IM3CodePage)m3_Malloc ("M3CodePage", pageSize); + + if (page) + { + page->info.sequence = ++i_runtime->newCodePageSequence; + page->info.numLines = (pageSize - sizeof (M3CodePageHeader)) / sizeof (code_t); + +#if d_m3RecordBacktraces + u32 pageSizeBt = sizeof (M3CodeMappingPage) + sizeof (M3CodeMapEntry) * page->info.numLines; + page->info.mapping = (M3CodeMappingPage *)m3_Malloc ("M3CodeMappingPage", pageSizeBt); + + if (page->info.mapping) + { + page->info.mapping->size = 0; + page->info.mapping->capacity = page->info.numLines; + } + else + { + m3_Free (page); + return NULL; + } + page->info.mapping->basePC = GetPageStartPC(page); +#endif // d_m3RecordBacktraces + + m3log (runtime, "new page: %p; seq: %d; bytes: %d; lines: %d", GetPagePC (page), page->info.sequence, pageSize, page->info.numLines); + } + + return page; +} + + +void FreeCodePages (IM3CodePage * io_list) +{ + IM3CodePage page = * io_list; + + while (page) + { + m3log (code, "free page: %d; %p; util: %3.1f%%", page->info.sequence, page, 100. * page->info.lineIndex / page->info.numLines); + + IM3CodePage next = page->info.next; +#if d_m3RecordBacktraces + m3_Free (page->info.mapping); +#endif // d_m3RecordBacktraces + m3_Free (page); + page = next; + } + + * io_list = NULL; +} + + +u32 NumFreeLines (IM3CodePage i_page) +{ + d_m3Assert (i_page->info.lineIndex <= i_page->info.numLines); + + return i_page->info.numLines - i_page->info.lineIndex; +} + + +void EmitWord_impl (IM3CodePage i_page, void * i_word) +{ d_m3Assert (i_page->info.lineIndex+1 <= i_page->info.numLines); + i_page->code [i_page->info.lineIndex++] = i_word; +} + +void EmitWord32 (IM3CodePage i_page, const u32 i_word) +{ d_m3Assert (i_page->info.lineIndex+1 <= i_page->info.numLines); + * ((u32 *) & i_page->code [i_page->info.lineIndex++]) = i_word; +} + +void EmitWord64 (IM3CodePage i_page, const u64 i_word) +{ +#if M3_SIZEOF_PTR == 4 + d_m3Assert (i_page->info.lineIndex+2 <= i_page->info.numLines); + * ((u64 *) & i_page->code [i_page->info.lineIndex]) = i_word; + i_page->info.lineIndex += 2; +#else + d_m3Assert (i_page->info.lineIndex+1 <= i_page->info.numLines); + * ((u64 *) & i_page->code [i_page->info.lineIndex]) = i_word; + i_page->info.lineIndex += 1; +#endif +} + + +#if d_m3RecordBacktraces +void EmitMappingEntry (IM3CodePage i_page, u32 i_moduleOffset) +{ + M3CodeMappingPage * page = i_page->info.mapping; + d_m3Assert (page->size < page->capacity); + + M3CodeMapEntry * entry = & page->entries[page->size++]; + pc_t pc = GetPagePC (i_page); + + entry->pcOffset = pc - page->basePC; + entry->moduleOffset = i_moduleOffset; +} +#endif // d_m3RecordBacktraces + +pc_t GetPageStartPC (IM3CodePage i_page) +{ + return & i_page->code [0]; +} + + +pc_t GetPagePC (IM3CodePage i_page) +{ + if (i_page) + return & i_page->code [i_page->info.lineIndex]; + else + return NULL; +} + + +void PushCodePage (IM3CodePage * i_list, IM3CodePage i_codePage) +{ + IM3CodePage next = * i_list; + i_codePage->info.next = next; + * i_list = i_codePage; +} + + +IM3CodePage PopCodePage (IM3CodePage * i_list) +{ + IM3CodePage page = * i_list; + * i_list = page->info.next; + page->info.next = NULL; + + return page; +} + + + +u32 FindCodePageEnd (IM3CodePage i_list, IM3CodePage * o_end) +{ + u32 numPages = 0; + * o_end = NULL; + + while (i_list) + { + * o_end = i_list; + ++numPages; + i_list = i_list->info.next; + } + + return numPages; +} + + +u32 CountCodePages (IM3CodePage i_list) +{ + IM3CodePage unused; + return FindCodePageEnd (i_list, & unused); +} + + +IM3CodePage GetEndCodePage (IM3CodePage i_list) +{ + IM3CodePage end; + FindCodePageEnd (i_list, & end); + + return end; +} + +#if d_m3RecordBacktraces +bool ContainsPC (IM3CodePage i_page, pc_t i_pc) +{ + return GetPageStartPC (i_page) <= i_pc && i_pc < GetPagePC (i_page); +} + + +bool MapPCToOffset (IM3CodePage i_page, pc_t i_pc, u32 * o_moduleOffset) +{ + M3CodeMappingPage * mapping = i_page->info.mapping; + + u32 pcOffset = i_pc - mapping->basePC; + + u32 left = 0; + u32 right = mapping->size; + + while (left < right) + { + u32 mid = left + (right - left) / 2; + + if (mapping->entries[mid].pcOffset < pcOffset) + { + left = mid + 1; + } + else if (mapping->entries[mid].pcOffset > pcOffset) + { + right = mid; + } + else + { + *o_moduleOffset = mapping->entries[mid].moduleOffset; + return true; + } + } + + // Getting here means left is now one more than the element we want. + if (left > 0) + { + left--; + *o_moduleOffset = mapping->entries[left].moduleOffset; + return true; + } + else return false; +} +#endif // d_m3RecordBacktraces + +//--------------------------------------------------------------------------------------------------------------------------------- + + diff --git a/ext/wasm3/source/m3_code.h b/ext/wasm3/source/m3_code.h new file mode 100644 index 0000000..25dcb81 --- /dev/null +++ b/ext/wasm3/source/m3_code.h @@ -0,0 +1,80 @@ +// +// m3_code.h +// +// Created by Steven Massey on 4/19/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#ifndef m3_code_h +#define m3_code_h + +#include "m3_core.h" + +d_m3BeginExternC + +typedef struct M3CodePage +{ + M3CodePageHeader info; + code_t code [1]; +} +M3CodePage; + +typedef M3CodePage * IM3CodePage; + + +IM3CodePage NewCodePage (IM3Runtime i_runtime, u32 i_minNumLines); + +void FreeCodePages (IM3CodePage * io_list); + +u32 NumFreeLines (IM3CodePage i_page); +pc_t GetPageStartPC (IM3CodePage i_page); +pc_t GetPagePC (IM3CodePage i_page); +void EmitWord_impl (IM3CodePage i_page, void* i_word); +void EmitWord32 (IM3CodePage i_page, u32 i_word); +void EmitWord64 (IM3CodePage i_page, u64 i_word); +# if d_m3RecordBacktraces +void EmitMappingEntry (IM3CodePage i_page, u32 i_moduleOffset); +# endif // d_m3RecordBacktraces + +void PushCodePage (IM3CodePage * io_list, IM3CodePage i_codePage); +IM3CodePage PopCodePage (IM3CodePage * io_list); + +IM3CodePage GetEndCodePage (IM3CodePage i_list); // i_list = NULL is valid +u32 CountCodePages (IM3CodePage i_list); // i_list = NULL is valid + +# if d_m3RecordBacktraces +bool ContainsPC (IM3CodePage i_page, pc_t i_pc); +bool MapPCToOffset (IM3CodePage i_page, pc_t i_pc, u32 * o_moduleOffset); +# endif // d_m3RecordBacktraces + +# ifdef DEBUG +void dump_code_page (IM3CodePage i_codePage, pc_t i_startPC); +# endif + +#define EmitWord(page, val) EmitWord_impl(page, (void*)(val)) + +//--------------------------------------------------------------------------------------------------------------------------------- + +# if d_m3RecordBacktraces + +typedef struct M3CodeMapEntry +{ + u32 pcOffset; + u32 moduleOffset; +} +M3CodeMapEntry; + +typedef struct M3CodeMappingPage +{ + pc_t basePC; + u32 size; + u32 capacity; + M3CodeMapEntry entries []; +} +M3CodeMappingPage; + +# endif // d_m3RecordBacktraces + +d_m3EndExternC + +#endif // m3_code_h diff --git a/ext/wasm3/source/m3_compile.c b/ext/wasm3/source/m3_compile.c new file mode 100644 index 0000000..8a93330 --- /dev/null +++ b/ext/wasm3/source/m3_compile.c @@ -0,0 +1,2922 @@ +// +// m3_compile.c +// +// Created by Steven Massey on 4/17/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +// Allow using opcodes for compilation process +#define M3_COMPILE_OPCODES + +#include "m3_env.h" +#include "m3_compile.h" +#include "m3_exec.h" +#include "m3_exception.h" +#include "m3_info.h" + +//----- EMIT -------------------------------------------------------------------------------------------------------------- + +static inline +pc_t GetPC (IM3Compilation o) +{ + return GetPagePC (o->page); +} + +static M3_NOINLINE +M3Result EnsureCodePageNumLines (IM3Compilation o, u32 i_numLines) +{ + M3Result result = m3Err_none; + + i_numLines += 2; // room for Bridge + + if (NumFreeLines (o->page) < i_numLines) + { + IM3CodePage page = AcquireCodePageWithCapacity (o->runtime, i_numLines); + + if (page) + { + m3log (emit, "bridging new code page from: %d %p (free slots: %d) to: %d", o->page->info.sequence, GetPC (o), NumFreeLines (o->page), page->info.sequence); + d_m3Assert (NumFreeLines (o->page) >= 2); + + EmitWord (o->page, op_Branch); + EmitWord (o->page, GetPagePC (page)); + + ReleaseCodePage (o->runtime, o->page); + + o->page = page; + } + else result = m3Err_mallocFailedCodePage; + } + + return result; +} + +static M3_NOINLINE +M3Result EmitOp (IM3Compilation o, IM3Operation i_operation) +{ + M3Result result = m3Err_none; d_m3Assert (i_operation or IsStackPolymorphic (o)); + + // it's OK for page to be null; when compile-walking the bytecode without emitting + if (o->page) + { +# if d_m3EnableOpTracing + if (i_operation != op_DumpStack) + o->numEmits++; +# endif + + // have execution jump to a new page if slots are critically low + result = EnsureCodePageNumLines (o, d_m3CodePageFreeLinesThreshold); + + if (not result) + { if (d_m3LogEmit) log_emit (o, i_operation); +# if d_m3RecordBacktraces + EmitMappingEntry (o->page, o->lastOpcodeStart - o->module->wasmStart); +# endif // d_m3RecordBacktraces + EmitWord (o->page, i_operation); + } + } + + return result; +} + +// Push an immediate constant into the M3 codestream +static M3_NOINLINE +void EmitConstant32 (IM3Compilation o, const u32 i_immediate) +{ + if (o->page) + EmitWord32 (o->page, i_immediate); +} + +static M3_NOINLINE +void EmitSlotOffset (IM3Compilation o, const i32 i_offset) +{ + if (o->page) + EmitWord32 (o->page, i_offset); +} + +static M3_NOINLINE +pc_t EmitPointer (IM3Compilation o, const void * const i_pointer) +{ + pc_t ptr = GetPagePC (o->page); + + if (o->page) + EmitWord (o->page, i_pointer); + + return ptr; +} + +static M3_NOINLINE +void * ReservePointer (IM3Compilation o) +{ + pc_t ptr = GetPagePC (o->page); + EmitPointer (o, NULL); + return (void *) ptr; +} + + +//------------------------------------------------------------------------------------------------------------------------- + +#define d_indent " | %s" + +// just want less letters and numbers to stare at down the way in the compiler table +#define i_32 c_m3Type_i32 +#define i_64 c_m3Type_i64 +#define f_32 c_m3Type_f32 +#define f_64 c_m3Type_f64 +#define none c_m3Type_none +#define any (u8)-1 + +#if d_m3HasFloat +# define FPOP(x) x +#else +# define FPOP(x) NULL +#endif + +static const IM3Operation c_preserveSetSlot [] = { NULL, op_PreserveSetSlot_i32, op_PreserveSetSlot_i64, + FPOP(op_PreserveSetSlot_f32), FPOP(op_PreserveSetSlot_f64) }; +static const IM3Operation c_setSetOps [] = { NULL, op_SetSlot_i32, op_SetSlot_i64, + FPOP(op_SetSlot_f32), FPOP(op_SetSlot_f64) }; +static const IM3Operation c_setGlobalOps [] = { NULL, op_SetGlobal_i32, op_SetGlobal_i64, + FPOP(op_SetGlobal_f32), FPOP(op_SetGlobal_f64) }; +static const IM3Operation c_setRegisterOps [] = { NULL, op_SetRegister_i32, op_SetRegister_i64, + FPOP(op_SetRegister_f32), FPOP(op_SetRegister_f64) }; + +static const IM3Operation c_intSelectOps [2] [4] = { { op_Select_i32_rss, op_Select_i32_srs, op_Select_i32_ssr, op_Select_i32_sss }, + { op_Select_i64_rss, op_Select_i64_srs, op_Select_i64_ssr, op_Select_i64_sss } }; +#if d_m3HasFloat +static const IM3Operation c_fpSelectOps [2] [2] [3] = { { { op_Select_f32_sss, op_Select_f32_srs, op_Select_f32_ssr }, // selector in slot + { op_Select_f32_rss, op_Select_f32_rrs, op_Select_f32_rsr } }, // selector in reg + { { op_Select_f64_sss, op_Select_f64_srs, op_Select_f64_ssr }, // selector in slot + { op_Select_f64_rss, op_Select_f64_rrs, op_Select_f64_rsr } } }; // selector in reg +#endif + +// all args & returns are 64-bit aligned, so use 2 slots for a d_m3Use32BitSlots=1 build +static const u16 c_ioSlotCount = sizeof (u64) / sizeof (m3slot_t); + +static +M3Result AcquireCompilationCodePage (IM3Compilation o, IM3CodePage * o_codePage) +{ + M3Result result = m3Err_none; + + IM3CodePage page = AcquireCodePage (o->runtime); + + if (page) + { +# if (d_m3EnableCodePageRefCounting) + { + if (o->function) + { + IM3Function func = o->function; + page->info.usageCount++; + + u32 index = func->numCodePageRefs++; +_ (m3ReallocArray (& func->codePageRefs, IM3CodePage, func->numCodePageRefs, index)); + func->codePageRefs [index] = page; + } + } +# endif + } + else _throw (m3Err_mallocFailedCodePage); + + _catch: + + * o_codePage = page; + + return result; +} + +static inline +void ReleaseCompilationCodePage (IM3Compilation o) +{ + ReleaseCodePage (o->runtime, o->page); +} + +static inline +u16 GetTypeNumSlots (u8 i_type) +{ +# if d_m3Use32BitSlots + return Is64BitType (i_type) ? 2 : 1; +# else + return 1; +# endif +} + +static inline +void AlignSlotToType (u16 * io_slot, u8 i_type) +{ + // align 64-bit words to even slots (if d_m3Use32BitSlots) + u16 numSlots = GetTypeNumSlots (i_type); + + u16 mask = numSlots - 1; + * io_slot = (* io_slot + mask) & ~mask; +} + +static inline +i16 GetStackTopIndex (IM3Compilation o) +{ d_m3Assert (o->stackIndex > o->stackFirstDynamicIndex or IsStackPolymorphic (o)); + return o->stackIndex - 1; +} + + +// Items in the static portion of the stack (args/locals) are hidden from GetStackTypeFromTop () +// In other words, only "real" Wasm stack items can be inspected. This is important when +// returning values, etc. and you need an accurate wasm-view of the stack. +static +u8 GetStackTypeFromTop (IM3Compilation o, u16 i_offset) +{ + u8 type = c_m3Type_none; + + ++i_offset; + if (o->stackIndex >= i_offset) + { + u16 index = o->stackIndex - i_offset; + + if (index >= o->stackFirstDynamicIndex) + type = o->typeStack [index]; + } + + return type; +} + +static inline +u8 GetStackTopType (IM3Compilation o) +{ + return GetStackTypeFromTop (o, 0); +} + +static inline +u8 GetStackTypeFromBottom (IM3Compilation o, u16 i_offset) +{ + u8 type = c_m3Type_none; + + if (i_offset < o->stackIndex) + type = o->typeStack [i_offset]; + + return type; +} + + +static inline bool IsConstantSlot (IM3Compilation o, u16 i_slot) { return (i_slot >= o->slotFirstConstIndex and i_slot < o->slotMaxConstIndex); } +static inline bool IsSlotAllocated (IM3Compilation o, u16 i_slot) { return o->m3Slots [i_slot]; } + +static inline +bool IsStackIndexInRegister (IM3Compilation o, i32 i_stackIndex) +{ d_m3Assert (i_stackIndex < o->stackIndex or IsStackPolymorphic (o)); + if (i_stackIndex >= 0 and i_stackIndex < o->stackIndex) + return (o->wasmStack [i_stackIndex] >= d_m3Reg0SlotAlias); + else + return false; +} + +static inline u16 GetNumBlockValuesOnStack (IM3Compilation o) { return o->stackIndex - o->block.blockStackIndex; } + +static inline bool IsStackTopInRegister (IM3Compilation o) { return IsStackIndexInRegister (o, (i32) GetStackTopIndex (o)); } +static inline bool IsStackTopMinus1InRegister (IM3Compilation o) { return IsStackIndexInRegister (o, (i32) GetStackTopIndex (o) - 1); } +static inline bool IsStackTopMinus2InRegister (IM3Compilation o) { return IsStackIndexInRegister (o, (i32) GetStackTopIndex (o) - 2); } + +static inline bool IsStackTopInSlot (IM3Compilation o) { return not IsStackTopInRegister (o); } + +static inline bool IsValidSlot (u16 i_slot) { return (i_slot < d_m3MaxFunctionSlots); } + +static inline +u16 GetStackTopSlotNumber (IM3Compilation o) +{ + i16 i = GetStackTopIndex (o); + + u16 slot = c_slotUnused; + + if (i >= 0) + slot = o->wasmStack [i]; + + return slot; +} + + +// from bottom +static inline +u16 GetSlotForStackIndex (IM3Compilation o, u16 i_stackIndex) +{ d_m3Assert (i_stackIndex < o->stackIndex or IsStackPolymorphic (o)); + u16 slot = c_slotUnused; + + if (i_stackIndex < o->stackIndex) + slot = o->wasmStack [i_stackIndex]; + + return slot; +} + +static inline +u16 GetExtraSlotForStackIndex (IM3Compilation o, u16 i_stackIndex) +{ + u16 baseSlot = GetSlotForStackIndex (o, i_stackIndex); + + if (baseSlot != c_slotUnused) + { + u16 extraSlot = GetTypeNumSlots (GetStackTypeFromBottom (o, i_stackIndex)) - 1; + baseSlot += extraSlot; + } + + return baseSlot; +} + + +static inline +void TouchSlot (IM3Compilation o, u16 i_slot) +{ + if (o->function) + { + // op_Entry uses this value to track and detect stack overflow + o->maxStackSlots = M3_MAX (o->maxStackSlots, i_slot + 1); + } +} + +static inline +void MarkSlotAllocated (IM3Compilation o, u16 i_slot) +{ d_m3Assert (o->m3Slots [i_slot] == 0); // shouldn't be already allocated + o->m3Slots [i_slot] = 1; + + o->slotMaxAllocatedIndexPlusOne = M3_MAX (o->slotMaxAllocatedIndexPlusOne, i_slot + 1); + + TouchSlot (o, i_slot); +} + +static inline +void MarkSlotsAllocated (IM3Compilation o, u16 i_slot, u16 i_numSlots) +{ + while (i_numSlots--) + MarkSlotAllocated (o, i_slot++); +} + +static inline +void MarkSlotsAllocatedByType (IM3Compilation o, u16 i_slot, u8 i_type) +{ + u16 numSlots = GetTypeNumSlots (i_type); + MarkSlotsAllocated (o, i_slot, numSlots); +} + + +static +M3Result AllocateSlotsWithinRange (IM3Compilation o, u16 * o_slot, u8 i_type, u16 i_startSlot, u16 i_endSlot) +{ + M3Result result = m3Err_functionStackOverflow; + + u16 numSlots = GetTypeNumSlots (i_type); + u16 searchOffset = numSlots - 1; + + AlignSlotToType (& i_startSlot, i_type); + + // search for 1 or 2 consecutive slots in the execution stack + u16 i = i_startSlot; + while (i + searchOffset < i_endSlot) + { + if (o->m3Slots [i] == 0 and o->m3Slots [i + searchOffset] == 0) + { + MarkSlotsAllocated (o, i, numSlots); + + * o_slot = i; + result = m3Err_none; + break; + } + + // keep 2-slot allocations even-aligned + i += numSlots; + } + + return result; +} + +static inline +M3Result AllocateSlots (IM3Compilation o, u16 * o_slot, u8 i_type) +{ + return AllocateSlotsWithinRange (o, o_slot, i_type, o->slotFirstDynamicIndex, d_m3MaxFunctionSlots); +} + +static inline +M3Result AllocateConstantSlots (IM3Compilation o, u16 * o_slot, u8 i_type) +{ + u16 maxTableIndex = o->slotFirstConstIndex + d_m3MaxConstantTableSize; + return AllocateSlotsWithinRange (o, o_slot, i_type, o->slotFirstConstIndex, M3_MIN(o->slotFirstDynamicIndex, maxTableIndex)); +} + + +// TOQUE: this usage count system could be eliminated. real world code doesn't frequently trigger it. just copy to multiple +// unique slots. +static inline +M3Result IncrementSlotUsageCount (IM3Compilation o, u16 i_slot) +{ d_m3Assert (i_slot < d_m3MaxFunctionSlots); + M3Result result = m3Err_none; d_m3Assert (o->m3Slots [i_slot] > 0); + + // OPTZ (memory): 'm3Slots' could still be fused with 'typeStack' if 4 bits were used to indicate: [0,1,2,many]. The many-case + // would scan 'wasmStack' to determine the actual usage count + if (o->m3Slots [i_slot] < 0xFF) + { + o->m3Slots [i_slot]++; + } + else result = "slot usage count overflow"; + + return result; +} + +static inline +void DeallocateSlot (IM3Compilation o, i16 i_slot, u8 i_type) +{ d_m3Assert (i_slot >= o->slotFirstDynamicIndex); + d_m3Assert (i_slot < o->slotMaxAllocatedIndexPlusOne); + for (u16 i = 0; i < GetTypeNumSlots (i_type); ++i, ++i_slot) + { d_m3Assert (o->m3Slots [i_slot]); + -- o->m3Slots [i_slot]; + } +} + + +static inline +bool IsRegisterTypeAllocated (IM3Compilation o, u8 i_type) +{ + return IsRegisterAllocated (o, IsFpType (i_type)); +} + +static inline +void AllocateRegister (IM3Compilation o, u32 i_register, u16 i_stackIndex) +{ d_m3Assert (not IsRegisterAllocated (o, i_register)); + o->regStackIndexPlusOne [i_register] = i_stackIndex + 1; +} + +static inline +void DeallocateRegister (IM3Compilation o, u32 i_register) +{ d_m3Assert (IsRegisterAllocated (o, i_register)); + o->regStackIndexPlusOne [i_register] = c_m3RegisterUnallocated; +} + +static inline +u16 GetRegisterStackIndex (IM3Compilation o, u32 i_register) +{ d_m3Assert (IsRegisterAllocated (o, i_register)); + return o->regStackIndexPlusOne [i_register] - 1; +} + +u16 GetMaxUsedSlotPlusOne (IM3Compilation o) +{ + while (o->slotMaxAllocatedIndexPlusOne > o->slotFirstDynamicIndex) + { + if (IsSlotAllocated (o, o->slotMaxAllocatedIndexPlusOne - 1)) + break; + + o->slotMaxAllocatedIndexPlusOne--; + } + +# ifdef DEBUG + u16 maxSlot = o->slotMaxAllocatedIndexPlusOne; + while (maxSlot < d_m3MaxFunctionSlots) + { + d_m3Assert (o->m3Slots [maxSlot] == 0); + maxSlot++; + } +# endif + + return o->slotMaxAllocatedIndexPlusOne; +} + +static +M3Result PreserveRegisterIfOccupied (IM3Compilation o, u8 i_registerType) +{ + M3Result result = m3Err_none; + + u32 regSelect = IsFpType (i_registerType); + + if (IsRegisterAllocated (o, regSelect)) + { + u16 stackIndex = GetRegisterStackIndex (o, regSelect); + DeallocateRegister (o, regSelect); + + u8 type = GetStackTypeFromBottom (o, stackIndex); + + // and point to a exec slot + u16 slot = c_slotUnused; +_ (AllocateSlots (o, & slot, type)); + o->wasmStack [stackIndex] = slot; + +_ (EmitOp (o, c_setSetOps [type])); + EmitSlotOffset (o, slot); + } + + _catch: return result; +} + + +// all values must be in slots before entering loop, if, and else blocks +// otherwise they'd end up preserve-copied in the block to probably different locations (if/else) +static inline +M3Result PreserveRegisters (IM3Compilation o) +{ + M3Result result; + +_ (PreserveRegisterIfOccupied (o, c_m3Type_f64)); +_ (PreserveRegisterIfOccupied (o, c_m3Type_i64)); + + _catch: return result; +} + +static +M3Result PreserveNonTopRegisters (IM3Compilation o) +{ + M3Result result = m3Err_none; + + i16 stackTop = GetStackTopIndex (o); + + if (stackTop >= 0) + { + if (IsRegisterAllocated (o, 0)) // r0 + { + if (GetRegisterStackIndex (o, 0) != stackTop) +_ (PreserveRegisterIfOccupied (o, c_m3Type_i64)); + } + + if (IsRegisterAllocated (o, 1)) // fp0 + { + if (GetRegisterStackIndex (o, 1) != stackTop) +_ (PreserveRegisterIfOccupied (o, c_m3Type_f64)); + } + } + + _catch: return result; +} + + +//---------------------------------------------------------------------------------------------------------------------- + +static +M3Result Push (IM3Compilation o, u8 i_type, u16 i_slot) +{ + M3Result result = m3Err_none; + +#if !d_m3HasFloat + if (i_type == c_m3Type_f32 || i_type == c_m3Type_f64) { + return m3Err_unknownOpcode; + } +#endif + + u16 stackIndex = o->stackIndex++; // printf ("push: %d\n", (i32) i); + + if (stackIndex < d_m3MaxFunctionStackHeight) + { + o->wasmStack [stackIndex] = i_slot; + o->typeStack [stackIndex] = i_type; + + if (IsRegisterSlotAlias (i_slot)) + { + u32 regSelect = IsFpRegisterSlotAlias (i_slot); + AllocateRegister (o, regSelect, stackIndex); + } + + if (d_m3LogWasmStack) dump_type_stack (o); + } + else result = m3Err_functionStackOverflow; + + return result; +} + +static inline +M3Result PushRegister (IM3Compilation o, u8 i_type) +{ + M3Result result = m3Err_none; d_m3Assert ((u16) d_m3Reg0SlotAlias > (u16) d_m3MaxFunctionSlots); + u16 slot = IsFpType (i_type) ? d_m3Fp0SlotAlias : d_m3Reg0SlotAlias; d_m3Assert (i_type or IsStackPolymorphic (o)); + +_ (Push (o, i_type, slot)); + + _catch: return result; +} + +static +M3Result Pop (IM3Compilation o) +{ + M3Result result = m3Err_none; + + if (o->stackIndex > o->block.blockStackIndex) + { + o->stackIndex--; // printf ("pop: %d\n", (i32) o->stackIndex); + + u16 slot = o->wasmStack [o->stackIndex]; + u8 type = o->typeStack [o->stackIndex]; + + if (IsRegisterSlotAlias (slot)) + { + u32 regSelect = IsFpRegisterSlotAlias (slot); + DeallocateRegister (o, regSelect); + } + else if (slot >= o->slotFirstDynamicIndex) + { + DeallocateSlot (o, slot, type); + } + } + else if (not IsStackPolymorphic (o)) + result = m3Err_functionStackUnderrun; + + return result; +} + +static +M3Result PopType (IM3Compilation o, u8 i_type) +{ + M3Result result = m3Err_none; + + u8 topType = GetStackTopType (o); + + if (i_type == topType or o->block.isPolymorphic) + { +_ (Pop (o)); + } + else _throw (m3Err_typeMismatch); + + _catch: + return result; +} + +static +M3Result _PushAllocatedSlotAndEmit (IM3Compilation o, u8 i_type, bool i_doEmit) +{ + M3Result result = m3Err_none; + + u16 slot = c_slotUnused; + +_ (AllocateSlots (o, & slot, i_type)); +_ (Push (o, i_type, slot)); + + if (i_doEmit) + EmitSlotOffset (o, slot); + +// printf ("push: %d\n", (u32) slot); + + _catch: return result; +} + +static inline +M3Result PushAllocatedSlotAndEmit (IM3Compilation o, u8 i_type) +{ + return _PushAllocatedSlotAndEmit (o, i_type, true); +} + +static inline +M3Result PushAllocatedSlot (IM3Compilation o, u8 i_type) +{ + return _PushAllocatedSlotAndEmit (o, i_type, false); +} + +static +M3Result PushConst (IM3Compilation o, u64 i_word, u8 i_type) +{ + M3Result result = m3Err_none; + + // Early-exit if we're not emitting + if (!o->page) return result; + + bool matchFound = false; + bool is64BitType = Is64BitType (i_type); + + u16 numRequiredSlots = GetTypeNumSlots (i_type); + u16 numUsedConstSlots = o->slotMaxConstIndex - o->slotFirstConstIndex; + + // search for duplicate matching constant slot to reuse + if (numRequiredSlots == 2 and numUsedConstSlots >= 2) + { + u16 firstConstSlot = o->slotFirstConstIndex; + AlignSlotToType (& firstConstSlot, c_m3Type_i64); + + for (u16 slot = firstConstSlot; slot < o->slotMaxConstIndex - 1; slot += 2) + { + if (IsSlotAllocated (o, slot) and IsSlotAllocated (o, slot + 1)) + { + u64 constant = * (u64 *) & o->constants [slot - o->slotFirstConstIndex]; + + if (constant == i_word) + { + matchFound = true; +_ (Push (o, i_type, slot)); + break; + } + } + } + } + else if (numRequiredSlots == 1) + { + for (u16 i = 0; i < numUsedConstSlots; ++i) + { + u16 slot = o->slotFirstConstIndex + i; + + if (IsSlotAllocated (o, slot)) + { + u64 constant; + if (is64BitType) { + constant = * (u64 *) & o->constants [i]; + } else { + constant = * (u32 *) & o->constants [i]; + } + if (constant == i_word) + { + matchFound = true; +_ (Push (o, i_type, slot)); + break; + } + } + } + } + + if (not matchFound) + { + u16 slot = c_slotUnused; + result = AllocateConstantSlots (o, & slot, i_type); + + if (result || slot == c_slotUnused) // no more constant table space; use inline constants + { + result = m3Err_none; + + if (is64BitType) { +_ (EmitOp (o, op_Const64)); + EmitWord64 (o->page, i_word); + } else { +_ (EmitOp (o, op_Const32)); + EmitWord32 (o->page, (u32) i_word); + } + +_ (PushAllocatedSlotAndEmit (o, i_type)); + } + else + { + u16 constTableIndex = slot - o->slotFirstConstIndex; + + d_m3Assert(constTableIndex < d_m3MaxConstantTableSize); + + if (is64BitType) + { + u64 * constant = (u64 *) & o->constants [constTableIndex]; + * constant = i_word; + } + else + { + u32 * constant = (u32 *) & o->constants [constTableIndex]; + * constant = (u32) i_word; + } + +_ (Push (o, i_type, slot)); + + o->slotMaxConstIndex = M3_MAX (slot + numRequiredSlots, o->slotMaxConstIndex); + } + } + + _catch: return result; +} + +static inline +M3Result EmitSlotNumOfStackTopAndPop (IM3Compilation o) +{ + // no emit if value is in register + if (IsStackTopInSlot (o)) + EmitSlotOffset (o, GetStackTopSlotNumber (o)); + + return Pop (o); +} + + +// Or, maybe: EmitTrappingOp +M3Result AddTrapRecord (IM3Compilation o) +{ + M3Result result = m3Err_none; + + if (o->function) + { + } + + return result; +} + +static +M3Result UnwindBlockStack (IM3Compilation o) +{ + M3Result result = m3Err_none; + + u32 popCount = 0; + while (o->stackIndex > o->block.blockStackIndex) + { +_ (Pop (o)); + ++popCount; + } + + if (popCount) + { + m3log (compile, "unwound stack top: %d", popCount); + } + + _catch: return result; +} + +static inline +M3Result SetStackPolymorphic (IM3Compilation o) +{ + o->block.isPolymorphic = true; m3log (compile, "stack set polymorphic"); + return UnwindBlockStack (o); +} + +static +void PatchBranches (IM3Compilation o) +{ + pc_t pc = GetPC (o); + + pc_t patches = o->block.patches; + o->block.patches = NULL; + + while (patches) + { m3log (compile, "patching location: %p to pc: %p", patches, pc); + pc_t next = * (pc_t *) patches; + * (pc_t *) patches = pc; + patches = next; + } +} + +//------------------------------------------------------------------------------------------------------------------------- + +static +M3Result CopyStackIndexToSlot (IM3Compilation o, u16 i_destSlot, u16 i_stackIndex) // NoPushPop +{ + M3Result result = m3Err_none; + + IM3Operation op; + + u8 type = GetStackTypeFromBottom (o, i_stackIndex); + bool inRegister = IsStackIndexInRegister (o, i_stackIndex); + + if (inRegister) + { + op = c_setSetOps [type]; + } + else op = Is64BitType (type) ? op_CopySlot_64 : op_CopySlot_32; + +_ (EmitOp (o, op)); + EmitSlotOffset (o, i_destSlot); + + if (not inRegister) + { + u16 srcSlot = GetSlotForStackIndex (o, i_stackIndex); + EmitSlotOffset (o, srcSlot); + } + + _catch: return result; +} + +static +M3Result CopyStackTopToSlot (IM3Compilation o, u16 i_destSlot) // NoPushPop +{ + M3Result result; + + i16 stackTop = GetStackTopIndex (o); +_ (CopyStackIndexToSlot (o, i_destSlot, (u16) stackTop)); + + _catch: return result; +} + + +// a copy-on-write strategy is used with locals. when a get local occurs, it's not copied anywhere. the stack +// entry just has a index pointer to that local memory slot. +// then, when a previously referenced local is set, the current value needs to be preserved for those references + +// TODO: consider getting rid of these specialized operations: PreserveSetSlot & PreserveCopySlot. +// They likely just take up space (which seems to reduce performance) without improving performance. +static +M3Result PreservedCopyTopSlot (IM3Compilation o, u16 i_destSlot, u16 i_preserveSlot) +{ + M3Result result = m3Err_none; d_m3Assert (i_destSlot != i_preserveSlot); + + IM3Operation op; + + u8 type = GetStackTopType (o); + + if (IsStackTopInRegister (o)) + { + op = c_preserveSetSlot [type]; + } + else op = Is64BitType (type) ? op_PreserveCopySlot_64 : op_PreserveCopySlot_32; + +_ (EmitOp (o, op)); + EmitSlotOffset (o, i_destSlot); + + if (IsStackTopInSlot (o)) + EmitSlotOffset (o, GetStackTopSlotNumber (o)); + + EmitSlotOffset (o, i_preserveSlot); + + _catch: return result; +} + +static +M3Result CopyStackTopToRegister (IM3Compilation o, bool i_updateStack) +{ + M3Result result = m3Err_none; + + if (IsStackTopInSlot (o)) + { + u8 type = GetStackTopType (o); + +_ (PreserveRegisterIfOccupied (o, type)); + + IM3Operation op = c_setRegisterOps [type]; + +_ (EmitOp (o, op)); + EmitSlotOffset (o, GetStackTopSlotNumber (o)); + + if (i_updateStack) + { +_ (PopType (o, type)); +_ (PushRegister (o, type)); + } + } + + _catch: return result; +} + + +// if local is unreferenced, o_preservedSlotNumber will be equal to localIndex on return +static +M3Result FindReferencedLocalWithinCurrentBlock (IM3Compilation o, u16 * o_preservedSlotNumber, u32 i_localSlot) +{ + M3Result result = m3Err_none; + + IM3CompilationScope scope = & o->block; + i16 startIndex = scope->blockStackIndex; + + while (scope->opcode == c_waOp_block) + { + scope = scope->outer; + if (not scope) + break; + + startIndex = scope->blockStackIndex; + } + + * o_preservedSlotNumber = (u16) i_localSlot; + + for (u32 i = startIndex; i < o->stackIndex; ++i) + { + if (o->wasmStack [i] == i_localSlot) + { + if (* o_preservedSlotNumber == i_localSlot) + { + u8 type = GetStackTypeFromBottom (o, i); d_m3Assert (type != c_m3Type_none) + +_ (AllocateSlots (o, o_preservedSlotNumber, type)); + } + else +_ (IncrementSlotUsageCount (o, * o_preservedSlotNumber)); + + o->wasmStack [i] = * o_preservedSlotNumber; + } + } + + _catch: return result; +} + +static +M3Result GetBlockScope (IM3Compilation o, IM3CompilationScope * o_scope, u32 i_depth) +{ + M3Result result = m3Err_none; + + IM3CompilationScope scope = & o->block; + + while (i_depth--) + { + scope = scope->outer; + _throwif ("invalid block depth", not scope); + } + + * o_scope = scope; + + _catch: + return result; +} + +static +M3Result CopyStackSlotsR (IM3Compilation o, u16 i_targetSlotStackIndex, u16 i_stackIndex, u16 i_endStackIndex, u16 i_tempSlot) +{ + M3Result result = m3Err_none; + + if (i_stackIndex < i_endStackIndex) + { + u16 srcSlot = GetSlotForStackIndex (o, i_stackIndex); + + u8 type = GetStackTypeFromBottom (o, i_stackIndex); + u16 numSlots = GetTypeNumSlots (type); + u16 extraSlot = numSlots - 1; + + u16 targetSlot = GetSlotForStackIndex (o, i_targetSlotStackIndex); + + u16 preserveIndex = i_stackIndex; + u16 collisionSlot = srcSlot; + + if (targetSlot != srcSlot) + { + // search for collisions + u16 checkIndex = i_stackIndex + 1; + while (checkIndex < i_endStackIndex) + { + u16 otherSlot1 = GetSlotForStackIndex (o, checkIndex); + u16 otherSlot2 = GetExtraSlotForStackIndex (o, checkIndex); + + if (targetSlot == otherSlot1 or + targetSlot == otherSlot2 or + targetSlot + extraSlot == otherSlot1) + { + _throwif (m3Err_functionStackOverflow, i_tempSlot >= d_m3MaxFunctionSlots); + +_ (CopyStackIndexToSlot (o, i_tempSlot, checkIndex)); + o->wasmStack [checkIndex] = i_tempSlot; + i_tempSlot += GetTypeNumSlots (c_m3Type_i64); + TouchSlot (o, i_tempSlot - 1); + + // restore this on the way back down + preserveIndex = checkIndex; + collisionSlot = otherSlot1; + + break; + } + + ++checkIndex; + } + +_ (CopyStackIndexToSlot (o, targetSlot, i_stackIndex)); m3log (compile, " copying slot: %d to slot: %d", srcSlot, targetSlot); + o->wasmStack [i_stackIndex] = targetSlot; + + } + +_ (CopyStackSlotsR (o, i_targetSlotStackIndex + 1, i_stackIndex + 1, i_endStackIndex, i_tempSlot)); + + // restore the stack state + o->wasmStack [i_stackIndex] = srcSlot; + o->wasmStack [preserveIndex] = collisionSlot; + } + + _catch: + return result; +} + +static +M3Result ResolveBlockResults (IM3Compilation o, IM3CompilationScope i_targetBlock, bool i_isBranch) +{ + M3Result result = m3Err_none; if (d_m3LogWasmStack) dump_type_stack (o); + + bool isLoop = (i_targetBlock->opcode == c_waOp_loop and i_isBranch); + + u16 numParams = GetFuncTypeNumParams (i_targetBlock->type); + u16 numResults = GetFuncTypeNumResults (i_targetBlock->type); + + u16 slotRecords = i_targetBlock->exitStackIndex; + + u16 numValues; + + if (not isLoop) + { + numValues = numResults; + slotRecords += numParams; + } + else numValues = numParams; + + u16 blockHeight = GetNumBlockValuesOnStack (o); + + _throwif (m3Err_typeCountMismatch, i_isBranch ? (blockHeight < numValues) : (blockHeight != numValues)); + + if (numValues) + { + u16 endIndex = GetStackTopIndex (o) + 1; + + if (not isLoop and IsFpType (GetStackTopType (o))) + { +_ (CopyStackTopToRegister (o, false)); + --endIndex; + } + + // TODO: tempslot affects maxStackSlots, so can grow unnecess each time. + u16 tempSlot = o->maxStackSlots;// GetMaxUsedSlotPlusOne (o); doesn't work cause can collide with slotRecords + AlignSlotToType (& tempSlot, c_m3Type_i64); + +_ (CopyStackSlotsR (o, slotRecords, endIndex - numValues, endIndex, tempSlot)); + + if (d_m3LogWasmStack) dump_type_stack (o); + } + + _catch: return result; +} + + +static +M3Result ReturnValues (IM3Compilation o, IM3CompilationScope i_functionBlock, bool i_isBranch) +{ + M3Result result = m3Err_none; if (d_m3LogWasmStack) dump_type_stack (o); + + u16 numReturns = GetFuncTypeNumResults (i_functionBlock->type); // could just o->function too... + u16 blockHeight = GetNumBlockValuesOnStack (o); + + if (not IsStackPolymorphic (o)) + _throwif (m3Err_typeCountMismatch, i_isBranch ? (blockHeight < numReturns) : (blockHeight != numReturns)); + + if (numReturns) + { + // return slots like args are 64-bit aligned + u16 returnSlot = numReturns * c_ioSlotCount; + u16 stackTop = GetStackTopIndex (o); + + for (u16 i = 0; i < numReturns; ++i) + { + u8 returnType = GetFuncTypeResultType (i_functionBlock->type, numReturns - 1 - i); + + u8 stackType = GetStackTypeFromTop (o, i); // using FromTop so that only dynamic items are checked + + if (IsStackPolymorphic (o) and stackType == c_m3Type_none) + stackType = returnType; + + _throwif (m3Err_typeMismatch, returnType != stackType); + + if (not IsStackPolymorphic (o)) + { + returnSlot -= c_ioSlotCount; +_ (CopyStackIndexToSlot (o, returnSlot, stackTop--)); + } + } + + if (not i_isBranch) + { + while (numReturns--) +_ (Pop (o)); + } + } + + _catch: return result; +} + + +//------------------------------------------------------------------------------------------------------------------------- + +static +M3Result Compile_Const_i32 (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + i32 value; +_ (ReadLEB_i32 (& value, & o->wasm, o->wasmEnd)); +_ (PushConst (o, value, c_m3Type_i32)); m3log (compile, d_indent " (const i32 = %" PRIi32 ")", get_indention_string (o), value); + _catch: return result; +} + +static +M3Result Compile_Const_i64 (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + i64 value; +_ (ReadLEB_i64 (& value, & o->wasm, o->wasmEnd)); +_ (PushConst (o, value, c_m3Type_i64)); m3log (compile, d_indent " (const i64 = %" PRIi64 ")", get_indention_string (o), value); + _catch: return result; +} + + +#if d_m3ImplementFloat +static +M3Result Compile_Const_f32 (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + union { u32 u; f32 f; } value = { 0 }; + +_ (Read_f32 (& value.f, & o->wasm, o->wasmEnd)); m3log (compile, d_indent " (const f32 = %" PRIf32 ")", get_indention_string (o), value.f); +_ (PushConst (o, value.u, c_m3Type_f32)); + + _catch: return result; +} + +static +M3Result Compile_Const_f64 (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + union { u64 u; f64 f; } value = { 0 }; + +_ (Read_f64 (& value.f, & o->wasm, o->wasmEnd)); m3log (compile, d_indent " (const f64 = %" PRIf64 ")", get_indention_string (o), value.f); +_ (PushConst (o, value.u, c_m3Type_f64)); + + _catch: return result; +} +#endif + +#if d_m3CascadedOpcodes + +static +M3Result Compile_ExtendedOpcode (IM3Compilation o, m3opcode_t i_opcode) +{ +_try { + u8 opcode; +_ (Read_u8 (& opcode, & o->wasm, o->wasmEnd)); m3log (compile, d_indent " (FC: %" PRIi32 ")", get_indention_string (o), opcode); + + i_opcode = (i_opcode << 8) | opcode; + + //printf("Extended opcode: 0x%x\n", i_opcode); + + IM3OpInfo opInfo = GetOpInfo (i_opcode); + _throwif (m3Err_unknownOpcode, not opInfo); + + M3Compiler compiler = opInfo->compiler; + _throwif (m3Err_noCompiler, not compiler); + +_ ((* compiler) (o, i_opcode)); + + o->previousOpcode = i_opcode; + + } _catch: return result; +} +#endif + +static +M3Result Compile_Return (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result = m3Err_none; + + if (not IsStackPolymorphic (o)) + { + IM3CompilationScope functionScope; +_ (GetBlockScope (o, & functionScope, o->block.depth)); + +_ (ReturnValues (o, functionScope, true)); + +_ (EmitOp (o, op_Return)); + +_ (SetStackPolymorphic (o)); + } + + _catch: return result; +} + +static +M3Result ValidateBlockEnd (IM3Compilation o) +{ + M3Result result = m3Err_none; +/* + u16 numResults = GetFuncTypeNumResults (o->block.type); + u16 blockHeight = GetNumBlockValuesOnStack (o); + + if (IsStackPolymorphic (o)) + { + } + else + { + } + + _catch: */ return result; +} + +static +M3Result Compile_End (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result = m3Err_none; //dump_type_stack (o); + + // function end: + if (o->block.depth == 0) + { + ValidateBlockEnd (o); + +// if (not IsStackPolymorphic (o)) + { + if (o->function) + { +_ (ReturnValues (o, & o->block, false)); + } + +_ (EmitOp (o, op_Return)); + } + } + + _catch: return result; +} + + +static +M3Result Compile_SetLocal (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + u32 localIndex; +_ (ReadLEB_u32 (& localIndex, & o->wasm, o->wasmEnd)); // printf ("--- set local: %d \n", localSlot); + + if (localIndex < GetFunctionNumArgsAndLocals (o->function)) + { + u16 localSlot = GetSlotForStackIndex (o, localIndex); + + u16 preserveSlot; +_ (FindReferencedLocalWithinCurrentBlock (o, & preserveSlot, localSlot)); // preserve will be different than local, if referenced + + if (preserveSlot == localSlot) +_ (CopyStackTopToSlot (o, localSlot)) + else +_ (PreservedCopyTopSlot (o, localSlot, preserveSlot)) + + if (i_opcode != c_waOp_teeLocal) +_ (Pop (o)); + } + else _throw ("local index out of bounds"); + + _catch: return result; +} + +static +M3Result Compile_GetLocal (IM3Compilation o, m3opcode_t i_opcode) +{ +_try { + + u32 localIndex; +_ (ReadLEB_u32 (& localIndex, & o->wasm, o->wasmEnd)); + + if (localIndex >= GetFunctionNumArgsAndLocals (o->function)) + _throw ("local index out of bounds"); + + u8 type = GetStackTypeFromBottom (o, localIndex); + u16 slot = GetSlotForStackIndex (o, localIndex); + +_ (Push (o, type, slot)); + + } _catch: return result; +} + +static +M3Result Compile_GetGlobal (IM3Compilation o, M3Global * i_global) +{ + M3Result result; + + IM3Operation op = Is64BitType (i_global->type) ? op_GetGlobal_s64 : op_GetGlobal_s32; +_ (EmitOp (o, op)); + EmitPointer (o, & i_global->intValue); +_ (PushAllocatedSlotAndEmit (o, i_global->type)); + + _catch: return result; +} + +static +M3Result Compile_SetGlobal (IM3Compilation o, M3Global * i_global) +{ + M3Result result = m3Err_none; + + if (i_global->isMutable) + { + IM3Operation op; + u8 type = GetStackTopType (o); + + if (IsStackTopInRegister (o)) + { + op = c_setGlobalOps [type]; + } + else op = Is64BitType (type) ? op_SetGlobal_s64 : op_SetGlobal_s32; + +_ (EmitOp (o, op)); + EmitPointer (o, & i_global->intValue); + + if (IsStackTopInSlot (o)) + EmitSlotOffset (o, GetStackTopSlotNumber (o)); + +_ (Pop (o)); + } + else _throw (m3Err_settingImmutableGlobal); + + _catch: return result; +} + +static +M3Result Compile_GetSetGlobal (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result = m3Err_none; + + u32 globalIndex; +_ (ReadLEB_u32 (& globalIndex, & o->wasm, o->wasmEnd)); + + if (globalIndex < o->module->numGlobals) + { + if (o->module->globals) + { + M3Global * global = & o->module->globals [globalIndex]; + +_ ((i_opcode == c_waOp_getGlobal) ? Compile_GetGlobal (o, global) : Compile_SetGlobal (o, global)); + } + else _throw (ErrorCompile (m3Err_globalMemoryNotAllocated, o, "module '%s' is missing global memory", o->module->name)); + } + else _throw (m3Err_globaIndexOutOfBounds); + + _catch: return result; +} + +static +void EmitPatchingBranchPointer (IM3Compilation o, IM3CompilationScope i_scope) +{ + pc_t patch = EmitPointer (o, i_scope->patches); m3log (compile, "branch patch required at: %p", patch); + i_scope->patches = patch; +} + +static +M3Result EmitPatchingBranch (IM3Compilation o, IM3CompilationScope i_scope) +{ + M3Result result = m3Err_none; + +_ (EmitOp (o, op_Branch)); + EmitPatchingBranchPointer (o, i_scope); + + _catch: return result; +} + +static +M3Result Compile_Branch (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + u32 depth; +_ (ReadLEB_u32 (& depth, & o->wasm, o->wasmEnd)); + + IM3CompilationScope scope; +_ (GetBlockScope (o, & scope, depth)); + + // branch target is a loop (continue) + if (scope->opcode == c_waOp_loop) + { + if (i_opcode == c_waOp_branchIf) + { + if (GetFuncTypeNumParams (scope->type)) + { + IM3Operation op = IsStackTopInRegister (o) ? op_BranchIfPrologue_r : op_BranchIfPrologue_s; + +_ (EmitOp (o, op)); +_ (EmitSlotNumOfStackTopAndPop (o)); + + pc_t * jumpTo = (pc_t *) ReservePointer (o); + +_ (ResolveBlockResults (o, scope, /* isBranch: */ true)); + +_ (EmitOp (o, op_ContinueLoop)); + EmitPointer (o, scope->pc); + + * jumpTo = GetPC (o); + } + else + { + // move the condition to a register +_ (CopyStackTopToRegister (o, false)); +_ (PopType (o, c_m3Type_i32)); + +_ (EmitOp (o, op_ContinueLoopIf)); + EmitPointer (o, scope->pc); + } + +// dump_type_stack(o); + } + else // is c_waOp_branch + { + _ (EmitOp (o, op_ContinueLoop)); + EmitPointer (o, scope->pc); + o->block.isPolymorphic = true; + } + } + else // forward branch + { + pc_t * jumpTo = NULL; + + bool isReturn = (scope->depth == 0); + bool targetHasResults = GetFuncTypeNumResults (scope->type); + + if (i_opcode == c_waOp_branchIf) + { + if (targetHasResults or isReturn) + { + IM3Operation op = IsStackTopInRegister (o) ? op_BranchIfPrologue_r : op_BranchIfPrologue_s; + + _ (EmitOp (o, op)); + _ (EmitSlotNumOfStackTopAndPop (o)); // condition + + // this is continuation point, if the branch isn't taken + jumpTo = (pc_t *) ReservePointer (o); + } + else + { + IM3Operation op = IsStackTopInRegister (o) ? op_BranchIf_r : op_BranchIf_s; + + _ (EmitOp (o, op)); + _ (EmitSlotNumOfStackTopAndPop (o)); // condition + + EmitPatchingBranchPointer (o, scope); + goto _catch; + } + } + + if (not IsStackPolymorphic (o)) + { + if (isReturn) + { +_ (ReturnValues (o, scope, true)); +_ (EmitOp (o, op_Return)); + } + else + { +_ (ResolveBlockResults (o, scope, true)); +_ (EmitPatchingBranch (o, scope)); + } + } + + if (jumpTo) + { + * jumpTo = GetPC (o); + } + + if (i_opcode == c_waOp_branch) +_ (SetStackPolymorphic (o)); + } + + _catch: return result; +} + +static +M3Result Compile_BranchTable (IM3Compilation o, m3opcode_t i_opcode) +{ +_try { + u32 targetCount; +_ (ReadLEB_u32 (& targetCount, & o->wasm, o->wasmEnd)); + +_ (PreserveRegisterIfOccupied (o, c_m3Type_i64)); // move branch operand to a slot + u16 slot = GetStackTopSlotNumber (o); +_ (Pop (o)); + + // OPTZ: according to spec: "forward branches that target a control instruction with a non-empty + // result type consume matching operands first and push them back on the operand stack after unwinding" + // So, this move-to-reg is only necessary if the target scopes have a type. + + u32 numCodeLines = targetCount + 4; // 3 => IM3Operation + slot + target_count + default_target +_ (EnsureCodePageNumLines (o, numCodeLines)); + +_ (EmitOp (o, op_BranchTable)); + EmitSlotOffset (o, slot); + EmitConstant32 (o, targetCount); + + IM3CodePage continueOpPage = NULL; + + ++targetCount; // include default + for (u32 i = 0; i < targetCount; ++i) + { + u32 target; +_ (ReadLEB_u32 (& target, & o->wasm, o->wasmEnd)); + + IM3CompilationScope scope; +_ (GetBlockScope (o, & scope, target)); + + // TODO: don't need codepage rigmarole for + // no-param forward-branch targets + +_ (AcquireCompilationCodePage (o, & continueOpPage)); + + pc_t startPC = GetPagePC (continueOpPage); + IM3CodePage savedPage = o->page; + o->page = continueOpPage; + + if (scope->opcode == c_waOp_loop) + { +_ (ResolveBlockResults (o, scope, true)); + +_ (EmitOp (o, op_ContinueLoop)); + EmitPointer (o, scope->pc); + } + else + { + // TODO: this could be fused with equivalent targets + if (not IsStackPolymorphic (o)) + { + if (scope->depth == 0) + { +_ (ReturnValues (o, scope, true)); +_ (EmitOp (o, op_Return)); + } + else + { +_ (ResolveBlockResults (o, scope, true)); + +_ (EmitPatchingBranch (o, scope)); + } + } + } + + ReleaseCompilationCodePage (o); // FIX: continueOpPage can get lost if thrown + o->page = savedPage; + + EmitPointer (o, startPC); + } + +_ (SetStackPolymorphic (o)); + + } + + _catch: return result; +} + +static +M3Result CompileCallArgsAndReturn (IM3Compilation o, u16 * o_stackOffset, IM3FuncType i_type, bool i_isIndirect) +{ +_try { + + u16 topSlot = GetMaxUsedSlotPlusOne (o); + + // force use of at least one stack slot; this is to help ensure + // the m3 stack overflows (and traps) before the native stack can overflow. + // e.g. see Wasm spec test 'runaway' in call.wast + topSlot = M3_MAX (1, topSlot); + + // stack frame is 64-bit aligned + AlignSlotToType (& topSlot, c_m3Type_i64); + + * o_stackOffset = topSlot; + + // wait to pop this here so that topSlot search is correct + if (i_isIndirect) +_ (Pop (o)); + + u16 numArgs = GetFuncTypeNumParams (i_type); + u16 numRets = GetFuncTypeNumResults (i_type); + + u16 argTop = topSlot + (numArgs + numRets) * c_ioSlotCount; + + while (numArgs--) + { +_ (CopyStackTopToSlot (o, argTop -= c_ioSlotCount)); +_ (Pop (o)); + } + + u16 i = 0; + while (numRets--) + { + u8 type = GetFuncTypeResultType (i_type, i++); + +_ (Push (o, type, topSlot)); + MarkSlotsAllocatedByType (o, topSlot, type); + + topSlot += c_ioSlotCount; + } + + } _catch: return result; +} + +static +M3Result Compile_Call (IM3Compilation o, m3opcode_t i_opcode) +{ +_try { + u32 functionIndex; +_ (ReadLEB_u32 (& functionIndex, & o->wasm, o->wasmEnd)); + + IM3Function function = Module_GetFunction (o->module, functionIndex); + + if (function) + { m3log (compile, d_indent " (func= [%d] '%s'; args= %d)", + get_indention_string (o), functionIndex, m3_GetFunctionName (function), function->funcType->numArgs); + if (function->module) + { + u16 slotTop; +_ (CompileCallArgsAndReturn (o, & slotTop, function->funcType, false)); + + IM3Operation op; + const void * operand; + + if (function->compiled) + { + op = op_Call; + operand = function->compiled; + } + else + { + op = op_Compile; + operand = function; + } + +_ (EmitOp (o, op)); + EmitPointer (o, operand); + EmitSlotOffset (o, slotTop); + } + else + { + _throw (ErrorCompile (m3Err_functionImportMissing, o, "'%s.%s'", GetFunctionImportModuleName (function), m3_GetFunctionName (function))); + } + } + else _throw (m3Err_functionLookupFailed); + + } _catch: return result; +} + +static +M3Result Compile_CallIndirect (IM3Compilation o, m3opcode_t i_opcode) +{ +_try { + u32 typeIndex; +_ (ReadLEB_u32 (& typeIndex, & o->wasm, o->wasmEnd)); + + u32 tableIndex; +_ (ReadLEB_u32 (& tableIndex, & o->wasm, o->wasmEnd)); + + _throwif ("function call type index out of range", typeIndex >= o->module->numFuncTypes); + + if (IsStackTopInRegister (o)) +_ (PreserveRegisterIfOccupied (o, c_m3Type_i32)); + + u16 tableIndexSlot = GetStackTopSlotNumber (o); + + u16 execTop; + IM3FuncType type = o->module->funcTypes [typeIndex]; +_ (CompileCallArgsAndReturn (o, & execTop, type, true)); + +_ (EmitOp (o, op_CallIndirect)); + EmitSlotOffset (o, tableIndexSlot); + EmitPointer (o, o->module); + EmitPointer (o, type); // TODO: unify all types in M3Environment + EmitSlotOffset (o, execTop); + +} _catch: + return result; +} + +static +M3Result Compile_Memory_Size (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + i8 reserved; +_ (ReadLEB_i7 (& reserved, & o->wasm, o->wasmEnd)); + +_ (PreserveRegisterIfOccupied (o, c_m3Type_i32)); + +_ (EmitOp (o, op_MemSize)); + +_ (PushRegister (o, c_m3Type_i32)); + + _catch: return result; +} + +static +M3Result Compile_Memory_Grow (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + i8 reserved; +_ (ReadLEB_i7 (& reserved, & o->wasm, o->wasmEnd)); + +_ (CopyStackTopToRegister (o, false)); +_ (PopType (o, c_m3Type_i32)); + +_ (EmitOp (o, op_MemGrow)); + +_ (PushRegister (o, c_m3Type_i32)); + + _catch: return result; +} + +static +M3Result Compile_Memory_CopyFill (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result = m3Err_none; + + u32 sourceMemoryIdx, targetMemoryIdx; + IM3Operation op; + if (i_opcode == c_waOp_memoryCopy) + { +_ (ReadLEB_u32 (& sourceMemoryIdx, & o->wasm, o->wasmEnd)); + op = op_MemCopy; + } + else op = op_MemFill; + +_ (ReadLEB_u32 (& targetMemoryIdx, & o->wasm, o->wasmEnd)); + +_ (CopyStackTopToRegister (o, false)); + +_ (EmitOp (o, op)); +_ (PopType (o, c_m3Type_i32)); +_ (EmitSlotNumOfStackTopAndPop (o)); +_ (EmitSlotNumOfStackTopAndPop (o)); + + _catch: return result; +} + + +static +M3Result ReadBlockType (IM3Compilation o, IM3FuncType * o_blockType) +{ + M3Result result; + + i64 type; +_ (ReadLebSigned (& type, 33, & o->wasm, o->wasmEnd)); + + if (type < 0) + { + u8 valueType; +_ (NormalizeType (&valueType, type)); m3log (compile, d_indent " (type: %s)", get_indention_string (o), c_waTypes [valueType]); + *o_blockType = o->module->environment->retFuncTypes[valueType]; + } + else + { + _throwif("func type out of bounds", type >= o->module->numFuncTypes); + *o_blockType = o->module->funcTypes[type]; m3log (compile, d_indent " (type: %s)", get_indention_string (o), SPrintFuncTypeSignature (*o_blockType)); + } + _catch: return result; +} + +static +M3Result PreserveArgsAndLocals (IM3Compilation o) +{ + M3Result result = m3Err_none; + + if (o->stackIndex > o->stackFirstDynamicIndex) + { + u32 numArgsAndLocals = GetFunctionNumArgsAndLocals (o->function); + + for (u32 i = 0; i < numArgsAndLocals; ++i) + { + u16 slot = GetSlotForStackIndex (o, i); + + u16 preservedSlotNumber; +_ (FindReferencedLocalWithinCurrentBlock (o, & preservedSlotNumber, slot)); + + if (preservedSlotNumber != slot) + { + u8 type = GetStackTypeFromBottom (o, i); d_m3Assert (type != c_m3Type_none) + IM3Operation op = Is64BitType (type) ? op_CopySlot_64 : op_CopySlot_32; + + EmitOp (o, op); + EmitSlotOffset (o, preservedSlotNumber); + EmitSlotOffset (o, slot); + } + } + } + + _catch: + return result; +} + +static +M3Result Compile_LoopOrBlock (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + // TODO: these shouldn't be necessary for non-loop blocks? +_ (PreserveRegisters (o)); +_ (PreserveArgsAndLocals (o)); + + IM3FuncType blockType; +_ (ReadBlockType (o, & blockType)); + + if (i_opcode == c_waOp_loop) + { + u16 numParams = GetFuncTypeNumParams (blockType); + if (numParams) + { + // instantiate constants + u16 numValues = GetNumBlockValuesOnStack (o); // CompileBlock enforces this at comptime + d_m3Assert (numValues >= numParams); + if (numValues >= numParams) + { + u16 stackTop = GetStackTopIndex (o) + 1; + + for (u16 i = stackTop - numParams; i < stackTop; ++i) + { + u16 slot = GetSlotForStackIndex (o, i); + u8 type = GetStackTypeFromBottom (o, i); + + if (IsConstantSlot (o, slot)) + { + u16 newSlot; +_ (AllocateSlots (o, & newSlot, type)); +_ (CopyStackIndexToSlot (o, newSlot, i)); + o->wasmStack [i] = newSlot; + } + } + } + } + +_ (EmitOp (o, op_Loop)); + } + else + { + } + +_ (CompileBlock (o, blockType, i_opcode)); + + _catch: return result; +} + +static +M3Result CompileElseBlock (IM3Compilation o, pc_t * o_startPC, IM3FuncType i_blockType) +{ +_try { + + IM3CodePage elsePage; +_ (AcquireCompilationCodePage (o, & elsePage)); + + * o_startPC = GetPagePC (elsePage); + + IM3CodePage savedPage = o->page; + o->page = elsePage; + +_ (CompileBlock (o, i_blockType, c_waOp_else)); + +_ (EmitOp (o, op_Branch)); + EmitPointer (o, GetPagePC (savedPage)); + + ReleaseCompilationCodePage (o); + + o->page = savedPage; + +} _catch: + return result; +} + +static +M3Result Compile_If (IM3Compilation o, m3opcode_t i_opcode) +{ + /* [ op_If ] + [ ] ----> [ ..else.. ] + [ ..if.. ] [ ..block.. ] + [ ..block.. ] [ op_Branch ] + [ end ] <----- [ ] */ + +_try { + +_ (PreserveNonTopRegisters (o)); +_ (PreserveArgsAndLocals (o)); + + IM3Operation op = IsStackTopInRegister (o) ? op_If_r : op_If_s; + +_ (EmitOp (o, op)); +_ (EmitSlotNumOfStackTopAndPop (o)); + + pc_t * pc = (pc_t *) ReservePointer (o); + + IM3FuncType blockType; +_ (ReadBlockType (o, & blockType)); + +// dump_type_stack (o); + + u16 stackIndex = o->stackIndex; + +_ (CompileBlock (o, blockType, i_opcode)); + + if (o->previousOpcode == c_waOp_else) + { + o->stackIndex = stackIndex; +_ (CompileElseBlock (o, pc, blockType)); + } + else + { + // if block produces values and there isn't a defined else + // case, then we need to make one up so that the pass-through + // results end up in the right place + if (GetFuncTypeNumResults (blockType)) + { + // rewind to the if's end to create a fake else block + o->wasm--; + o->stackIndex = stackIndex; + +// dump_type_stack (o); + +_ (CompileElseBlock (o, pc, blockType)); + } + else * pc = GetPC (o); + } + + } _catch: return result; +} + +static +M3Result Compile_Select (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result = m3Err_none; + + u16 slots [3] = { c_slotUnused, c_slotUnused, c_slotUnused }; + + u8 type = GetStackTypeFromTop (o, 1); // get type of selection + + IM3Operation op = NULL; + + if (IsFpType (type)) + { +# if d_m3HasFloat + // not consuming a fp reg, so preserve + if (not IsStackTopMinus1InRegister (o) and + not IsStackTopMinus2InRegister (o)) + { +_ (PreserveRegisterIfOccupied (o, type)); + } + + bool selectorInReg = IsStackTopInRegister (o); + slots [0] = GetStackTopSlotNumber (o); +_ (Pop (o)); + + u32 opIndex = 0; + + for (u32 i = 1; i <= 2; ++i) + { + if (IsStackTopInRegister (o)) + opIndex = i; + else + slots [i] = GetStackTopSlotNumber (o); + +_ (Pop (o)); + } + + op = c_fpSelectOps [type - c_m3Type_f32] [selectorInReg] [opIndex]; +# else + _throw (m3Err_unknownOpcode); +# endif + } + else if (IsIntType (type)) + { + // 'sss' operation doesn't consume a register, so might have to protected its contents + if (not IsStackTopInRegister (o) and + not IsStackTopMinus1InRegister (o) and + not IsStackTopMinus2InRegister (o)) + { +_ (PreserveRegisterIfOccupied (o, type)); + } + + u32 opIndex = 3; // op_Select_*_sss + + for (u32 i = 0; i < 3; ++i) + { + if (IsStackTopInRegister (o)) + opIndex = i; + else + slots [i] = GetStackTopSlotNumber (o); + +_ (Pop (o)); + } + + op = c_intSelectOps [type - c_m3Type_i32] [opIndex]; + } + else if (not IsStackPolymorphic (o)) + _throw (m3Err_functionStackUnderrun); + + EmitOp (o, op); + for (u32 i = 0; i < 3; i++) + { + if (IsValidSlot (slots [i])) + EmitSlotOffset (o, slots [i]); + } +_ (PushRegister (o, type)); + + _catch: return result; +} + +static +M3Result Compile_Drop (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result = Pop (o); if (d_m3LogWasmStack) dump_type_stack (o); + return result; +} + +static +M3Result Compile_Nop (IM3Compilation o, m3opcode_t i_opcode) +{ + return m3Err_none; +} + +static +M3Result Compile_Unreachable (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + +_ (AddTrapRecord (o)); + +_ (EmitOp (o, op_Unreachable)); +_ (SetStackPolymorphic (o)); + + _catch: + return result; +} + + +// OPTZ: currently all stack slot indices take up a full word, but +// dual stack source operands could be packed together +static +M3Result Compile_Operator (IM3Compilation o, m3opcode_t i_opcode) +{ + M3Result result; + + IM3OpInfo opInfo = GetOpInfo (i_opcode); + _throwif (m3Err_unknownOpcode, not opInfo); + + IM3Operation op; + + // This preserve is for for FP compare operations. + // either need additional slot destination operations or the + // easy fix, move _r0 out of the way. + // moving out the way might be the optimal solution most often? + // otherwise, the _r0 reg can get buried down in the stack + // and be idle & wasted for a moment. + if (IsFpType (GetStackTopType (o)) and IsIntType (opInfo->type)) + { +_ (PreserveRegisterIfOccupied (o, opInfo->type)); + } + + if (opInfo->stackOffset == 0) + { + if (IsStackTopInRegister (o)) + { + op = opInfo->operations [0]; // _s + } + else + { +_ (PreserveRegisterIfOccupied (o, opInfo->type)); + op = opInfo->operations [1]; // _r + } + } + else + { + if (IsStackTopInRegister (o)) + { + op = opInfo->operations [0]; // _rs + + if (IsStackTopMinus1InRegister (o)) + { d_m3Assert (i_opcode == c_waOp_store_f32 or i_opcode == c_waOp_store_f64); + op = opInfo->operations [3]; // _rr for fp.store + } + } + else if (IsStackTopMinus1InRegister (o)) + { + op = opInfo->operations [1]; // _sr + + if (not op) // must be commutative, then + op = opInfo->operations [0]; + } + else + { +_ (PreserveRegisterIfOccupied (o, opInfo->type)); // _ss + op = opInfo->operations [2]; + } + } + + if (op) + { +_ (EmitOp (o, op)); + +_ (EmitSlotNumOfStackTopAndPop (o)); + + if (opInfo->stackOffset < 0) +_ (EmitSlotNumOfStackTopAndPop (o)); + + if (opInfo->type != c_m3Type_none) +_ (PushRegister (o, opInfo->type)); + } + else + { +# ifdef DEBUG + result = ErrorCompile ("no operation found for opcode", o, "'%s'", opInfo->name); +# else + result = ErrorCompile ("no operation found for opcode", o, "%x", i_opcode); +# endif + _throw (result); + } + + _catch: return result; +} + +static +M3Result Compile_Convert (IM3Compilation o, m3opcode_t i_opcode) +{ +_try { + IM3OpInfo opInfo = GetOpInfo (i_opcode); + _throwif (m3Err_unknownOpcode, not opInfo); + + bool destInSlot = IsRegisterTypeAllocated (o, opInfo->type); + bool sourceInSlot = IsStackTopInSlot (o); + + IM3Operation op = opInfo->operations [destInSlot * 2 + sourceInSlot]; + +_ (EmitOp (o, op)); +_ (EmitSlotNumOfStackTopAndPop (o)); + + if (destInSlot) +_ (PushAllocatedSlotAndEmit (o, opInfo->type)) + else +_ (PushRegister (o, opInfo->type)) + +} + _catch: return result; +} + +static +M3Result Compile_Load_Store (IM3Compilation o, m3opcode_t i_opcode) +{ +_try { + u32 alignHint, memoryOffset; + +_ (ReadLEB_u32 (& alignHint, & o->wasm, o->wasmEnd)); +_ (ReadLEB_u32 (& memoryOffset, & o->wasm, o->wasmEnd)); + m3log (compile, d_indent " (offset = %d)", get_indention_string (o), memoryOffset); + IM3OpInfo opInfo = GetOpInfo (i_opcode); + _throwif (m3Err_unknownOpcode, not opInfo); + + if (IsFpType (opInfo->type)) +_ (PreserveRegisterIfOccupied (o, c_m3Type_f64)); + +_ (Compile_Operator (o, i_opcode)); + + EmitConstant32 (o, memoryOffset); +} + _catch: return result; +} + + +M3Result CompileRawFunction (IM3Module io_module, IM3Function io_function, const void * i_function, const void * i_userdata) +{ + d_m3Assert (io_module->runtime); + + IM3CodePage page = AcquireCodePageWithCapacity (io_module->runtime, 4); + + if (page) + { + io_function->compiled = GetPagePC (page); + io_function->module = io_module; + + EmitWord (page, op_CallRawFunction); + EmitWord (page, i_function); + EmitWord (page, io_function); + EmitWord (page, i_userdata); + + ReleaseCodePage (io_module->runtime, page); + return m3Err_none; + } + else { + return m3Err_mallocFailedCodePage; + } +} + + + +// d_logOp, d_logOp2 macros aren't actually used by the compiler, just codepage decoding (d_m3LogCodePages = 1) +#define d_logOp(OP) { op_##OP, NULL, NULL, NULL } +#define d_logOp2(OP1,OP2) { op_##OP1, op_##OP2, NULL, NULL } + +#define d_emptyOpList { NULL, NULL, NULL, NULL } +#define d_unaryOpList(TYPE, NAME) { op_##TYPE##_##NAME##_r, op_##TYPE##_##NAME##_s, NULL, NULL } +#define d_binOpList(TYPE, NAME) { op_##TYPE##_##NAME##_rs, op_##TYPE##_##NAME##_sr, op_##TYPE##_##NAME##_ss, NULL } +#define d_storeFpOpList(TYPE, NAME) { op_##TYPE##_##NAME##_rs, op_##TYPE##_##NAME##_sr, op_##TYPE##_##NAME##_ss, op_##TYPE##_##NAME##_rr } +#define d_commutativeBinOpList(TYPE, NAME) { op_##TYPE##_##NAME##_rs, NULL, op_##TYPE##_##NAME##_ss, NULL } +#define d_convertOpList(OP) { op_##OP##_r_r, op_##OP##_r_s, op_##OP##_s_r, op_##OP##_s_s } + + +const M3OpInfo c_operations [] = +{ + M3OP( "unreachable", 0, none, d_logOp (Unreachable), Compile_Unreachable ), // 0x00 + M3OP( "nop", 0, none, d_emptyOpList, Compile_Nop ), // 0x01 . + M3OP( "block", 0, none, d_emptyOpList, Compile_LoopOrBlock ), // 0x02 + M3OP( "loop", 0, none, d_logOp (Loop), Compile_LoopOrBlock ), // 0x03 + M3OP( "if", -1, none, d_emptyOpList, Compile_If ), // 0x04 + M3OP( "else", 0, none, d_emptyOpList, Compile_Nop ), // 0x05 + + M3OP_RESERVED, M3OP_RESERVED, M3OP_RESERVED, M3OP_RESERVED, M3OP_RESERVED, // 0x06...0x0a + + M3OP( "end", 0, none, d_emptyOpList, Compile_End ), // 0x0b + M3OP( "br", 0, none, d_logOp (Branch), Compile_Branch ), // 0x0c + M3OP( "br_if", -1, none, d_logOp2 (BranchIf_r, BranchIf_s), Compile_Branch ), // 0x0d + M3OP( "br_table", -1, none, d_logOp (BranchTable), Compile_BranchTable ), // 0x0e + M3OP( "return", 0, any, d_logOp (Return), Compile_Return ), // 0x0f + M3OP( "call", 0, any, d_logOp (Call), Compile_Call ), // 0x10 + M3OP( "call_indirect", 0, any, d_logOp (CallIndirect), Compile_CallIndirect ), // 0x11 + M3OP( "return_call", 0, any, d_emptyOpList, Compile_Call ), // 0x12 TODO: Optimize + M3OP( "return_call_indirect",0, any, d_emptyOpList, Compile_CallIndirect ), // 0x13 + + M3OP_RESERVED, M3OP_RESERVED, // 0x14... + M3OP_RESERVED, M3OP_RESERVED, M3OP_RESERVED, M3OP_RESERVED, // ...0x19 + + M3OP( "drop", -1, none, d_emptyOpList, Compile_Drop ), // 0x1a + M3OP( "select", -2, any, d_emptyOpList, Compile_Select ), // 0x1b + + M3OP_RESERVED, M3OP_RESERVED, M3OP_RESERVED, M3OP_RESERVED, // 0x1c...0x1f + + M3OP( "local.get", 1, any, d_emptyOpList, Compile_GetLocal ), // 0x20 + M3OP( "local.set", 1, none, d_emptyOpList, Compile_SetLocal ), // 0x21 + M3OP( "local.tee", 0, any, d_emptyOpList, Compile_SetLocal ), // 0x22 + M3OP( "global.get", 1, none, d_emptyOpList, Compile_GetSetGlobal ), // 0x23 + M3OP( "global.set", 1, none, d_emptyOpList, Compile_GetSetGlobal ), // 0x24 + + M3OP_RESERVED, M3OP_RESERVED, M3OP_RESERVED, // 0x25...0x27 + + M3OP( "i32.load", 0, i_32, d_unaryOpList (i32, Load_i32), Compile_Load_Store ), // 0x28 + M3OP( "i64.load", 0, i_64, d_unaryOpList (i64, Load_i64), Compile_Load_Store ), // 0x29 + M3OP_F( "f32.load", 0, f_32, d_unaryOpList (f32, Load_f32), Compile_Load_Store ), // 0x2a + M3OP_F( "f64.load", 0, f_64, d_unaryOpList (f64, Load_f64), Compile_Load_Store ), // 0x2b + + M3OP( "i32.load8_s", 0, i_32, d_unaryOpList (i32, Load_i8), Compile_Load_Store ), // 0x2c + M3OP( "i32.load8_u", 0, i_32, d_unaryOpList (i32, Load_u8), Compile_Load_Store ), // 0x2d + M3OP( "i32.load16_s", 0, i_32, d_unaryOpList (i32, Load_i16), Compile_Load_Store ), // 0x2e + M3OP( "i32.load16_u", 0, i_32, d_unaryOpList (i32, Load_u16), Compile_Load_Store ), // 0x2f + + M3OP( "i64.load8_s", 0, i_64, d_unaryOpList (i64, Load_i8), Compile_Load_Store ), // 0x30 + M3OP( "i64.load8_u", 0, i_64, d_unaryOpList (i64, Load_u8), Compile_Load_Store ), // 0x31 + M3OP( "i64.load16_s", 0, i_64, d_unaryOpList (i64, Load_i16), Compile_Load_Store ), // 0x32 + M3OP( "i64.load16_u", 0, i_64, d_unaryOpList (i64, Load_u16), Compile_Load_Store ), // 0x33 + M3OP( "i64.load32_s", 0, i_64, d_unaryOpList (i64, Load_i32), Compile_Load_Store ), // 0x34 + M3OP( "i64.load32_u", 0, i_64, d_unaryOpList (i64, Load_u32), Compile_Load_Store ), // 0x35 + + M3OP( "i32.store", -2, none, d_binOpList (i32, Store_i32), Compile_Load_Store ), // 0x36 + M3OP( "i64.store", -2, none, d_binOpList (i64, Store_i64), Compile_Load_Store ), // 0x37 + M3OP_F( "f32.store", -2, none, d_storeFpOpList (f32, Store_f32), Compile_Load_Store ), // 0x38 + M3OP_F( "f64.store", -2, none, d_storeFpOpList (f64, Store_f64), Compile_Load_Store ), // 0x39 + + M3OP( "i32.store8", -2, none, d_binOpList (i32, Store_u8), Compile_Load_Store ), // 0x3a + M3OP( "i32.store16", -2, none, d_binOpList (i32, Store_i16), Compile_Load_Store ), // 0x3b + + M3OP( "i64.store8", -2, none, d_binOpList (i64, Store_u8), Compile_Load_Store ), // 0x3c + M3OP( "i64.store16", -2, none, d_binOpList (i64, Store_i16), Compile_Load_Store ), // 0x3d + M3OP( "i64.store32", -2, none, d_binOpList (i64, Store_i32), Compile_Load_Store ), // 0x3e + + M3OP( "memory.size", 1, i_32, d_logOp (MemSize), Compile_Memory_Size ), // 0x3f + M3OP( "memory.grow", 1, i_32, d_logOp (MemGrow), Compile_Memory_Grow ), // 0x40 + + M3OP( "i32.const", 1, i_32, d_logOp (Const32), Compile_Const_i32 ), // 0x41 + M3OP( "i64.const", 1, i_64, d_logOp (Const64), Compile_Const_i64 ), // 0x42 + M3OP_F( "f32.const", 1, f_32, d_emptyOpList, Compile_Const_f32 ), // 0x43 + M3OP_F( "f64.const", 1, f_64, d_emptyOpList, Compile_Const_f64 ), // 0x44 + + M3OP( "i32.eqz", 0, i_32, d_unaryOpList (i32, EqualToZero) , NULL ), // 0x45 + M3OP( "i32.eq", -1, i_32, d_commutativeBinOpList (i32, Equal) , NULL ), // 0x46 + M3OP( "i32.ne", -1, i_32, d_commutativeBinOpList (i32, NotEqual) , NULL ), // 0x47 + M3OP( "i32.lt_s", -1, i_32, d_binOpList (i32, LessThan) , NULL ), // 0x48 + M3OP( "i32.lt_u", -1, i_32, d_binOpList (u32, LessThan) , NULL ), // 0x49 + M3OP( "i32.gt_s", -1, i_32, d_binOpList (i32, GreaterThan) , NULL ), // 0x4a + M3OP( "i32.gt_u", -1, i_32, d_binOpList (u32, GreaterThan) , NULL ), // 0x4b + M3OP( "i32.le_s", -1, i_32, d_binOpList (i32, LessThanOrEqual) , NULL ), // 0x4c + M3OP( "i32.le_u", -1, i_32, d_binOpList (u32, LessThanOrEqual) , NULL ), // 0x4d + M3OP( "i32.ge_s", -1, i_32, d_binOpList (i32, GreaterThanOrEqual) , NULL ), // 0x4e + M3OP( "i32.ge_u", -1, i_32, d_binOpList (u32, GreaterThanOrEqual) , NULL ), // 0x4f + + M3OP( "i64.eqz", 0, i_32, d_unaryOpList (i64, EqualToZero) , NULL ), // 0x50 + M3OP( "i64.eq", -1, i_32, d_commutativeBinOpList (i64, Equal) , NULL ), // 0x51 + M3OP( "i64.ne", -1, i_32, d_commutativeBinOpList (i64, NotEqual) , NULL ), // 0x52 + M3OP( "i64.lt_s", -1, i_32, d_binOpList (i64, LessThan) , NULL ), // 0x53 + M3OP( "i64.lt_u", -1, i_32, d_binOpList (u64, LessThan) , NULL ), // 0x54 + M3OP( "i64.gt_s", -1, i_32, d_binOpList (i64, GreaterThan) , NULL ), // 0x55 + M3OP( "i64.gt_u", -1, i_32, d_binOpList (u64, GreaterThan) , NULL ), // 0x56 + M3OP( "i64.le_s", -1, i_32, d_binOpList (i64, LessThanOrEqual) , NULL ), // 0x57 + M3OP( "i64.le_u", -1, i_32, d_binOpList (u64, LessThanOrEqual) , NULL ), // 0x58 + M3OP( "i64.ge_s", -1, i_32, d_binOpList (i64, GreaterThanOrEqual) , NULL ), // 0x59 + M3OP( "i64.ge_u", -1, i_32, d_binOpList (u64, GreaterThanOrEqual) , NULL ), // 0x5a + + M3OP_F( "f32.eq", -1, i_32, d_commutativeBinOpList (f32, Equal) , NULL ), // 0x5b + M3OP_F( "f32.ne", -1, i_32, d_commutativeBinOpList (f32, NotEqual) , NULL ), // 0x5c + M3OP_F( "f32.lt", -1, i_32, d_binOpList (f32, LessThan) , NULL ), // 0x5d + M3OP_F( "f32.gt", -1, i_32, d_binOpList (f32, GreaterThan) , NULL ), // 0x5e + M3OP_F( "f32.le", -1, i_32, d_binOpList (f32, LessThanOrEqual) , NULL ), // 0x5f + M3OP_F( "f32.ge", -1, i_32, d_binOpList (f32, GreaterThanOrEqual) , NULL ), // 0x60 + + M3OP_F( "f64.eq", -1, i_32, d_commutativeBinOpList (f64, Equal) , NULL ), // 0x61 + M3OP_F( "f64.ne", -1, i_32, d_commutativeBinOpList (f64, NotEqual) , NULL ), // 0x62 + M3OP_F( "f64.lt", -1, i_32, d_binOpList (f64, LessThan) , NULL ), // 0x63 + M3OP_F( "f64.gt", -1, i_32, d_binOpList (f64, GreaterThan) , NULL ), // 0x64 + M3OP_F( "f64.le", -1, i_32, d_binOpList (f64, LessThanOrEqual) , NULL ), // 0x65 + M3OP_F( "f64.ge", -1, i_32, d_binOpList (f64, GreaterThanOrEqual) , NULL ), // 0x66 + + M3OP( "i32.clz", 0, i_32, d_unaryOpList (u32, Clz) , NULL ), // 0x67 + M3OP( "i32.ctz", 0, i_32, d_unaryOpList (u32, Ctz) , NULL ), // 0x68 + M3OP( "i32.popcnt", 0, i_32, d_unaryOpList (u32, Popcnt) , NULL ), // 0x69 + + M3OP( "i32.add", -1, i_32, d_commutativeBinOpList (i32, Add) , NULL ), // 0x6a + M3OP( "i32.sub", -1, i_32, d_binOpList (i32, Subtract) , NULL ), // 0x6b + M3OP( "i32.mul", -1, i_32, d_commutativeBinOpList (i32, Multiply) , NULL ), // 0x6c + M3OP( "i32.div_s", -1, i_32, d_binOpList (i32, Divide) , NULL ), // 0x6d + M3OP( "i32.div_u", -1, i_32, d_binOpList (u32, Divide) , NULL ), // 0x6e + M3OP( "i32.rem_s", -1, i_32, d_binOpList (i32, Remainder) , NULL ), // 0x6f + M3OP( "i32.rem_u", -1, i_32, d_binOpList (u32, Remainder) , NULL ), // 0x70 + M3OP( "i32.and", -1, i_32, d_commutativeBinOpList (u32, And) , NULL ), // 0x71 + M3OP( "i32.or", -1, i_32, d_commutativeBinOpList (u32, Or) , NULL ), // 0x72 + M3OP( "i32.xor", -1, i_32, d_commutativeBinOpList (u32, Xor) , NULL ), // 0x73 + M3OP( "i32.shl", -1, i_32, d_binOpList (u32, ShiftLeft) , NULL ), // 0x74 + M3OP( "i32.shr_s", -1, i_32, d_binOpList (i32, ShiftRight) , NULL ), // 0x75 + M3OP( "i32.shr_u", -1, i_32, d_binOpList (u32, ShiftRight) , NULL ), // 0x76 + M3OP( "i32.rotl", -1, i_32, d_binOpList (u32, Rotl) , NULL ), // 0x77 + M3OP( "i32.rotr", -1, i_32, d_binOpList (u32, Rotr) , NULL ), // 0x78 + + M3OP( "i64.clz", 0, i_64, d_unaryOpList (u64, Clz) , NULL ), // 0x79 + M3OP( "i64.ctz", 0, i_64, d_unaryOpList (u64, Ctz) , NULL ), // 0x7a + M3OP( "i64.popcnt", 0, i_64, d_unaryOpList (u64, Popcnt) , NULL ), // 0x7b + + M3OP( "i64.add", -1, i_64, d_commutativeBinOpList (i64, Add) , NULL ), // 0x7c + M3OP( "i64.sub", -1, i_64, d_binOpList (i64, Subtract) , NULL ), // 0x7d + M3OP( "i64.mul", -1, i_64, d_commutativeBinOpList (i64, Multiply) , NULL ), // 0x7e + M3OP( "i64.div_s", -1, i_64, d_binOpList (i64, Divide) , NULL ), // 0x7f + M3OP( "i64.div_u", -1, i_64, d_binOpList (u64, Divide) , NULL ), // 0x80 + M3OP( "i64.rem_s", -1, i_64, d_binOpList (i64, Remainder) , NULL ), // 0x81 + M3OP( "i64.rem_u", -1, i_64, d_binOpList (u64, Remainder) , NULL ), // 0x82 + M3OP( "i64.and", -1, i_64, d_commutativeBinOpList (u64, And) , NULL ), // 0x83 + M3OP( "i64.or", -1, i_64, d_commutativeBinOpList (u64, Or) , NULL ), // 0x84 + M3OP( "i64.xor", -1, i_64, d_commutativeBinOpList (u64, Xor) , NULL ), // 0x85 + M3OP( "i64.shl", -1, i_64, d_binOpList (u64, ShiftLeft) , NULL ), // 0x86 + M3OP( "i64.shr_s", -1, i_64, d_binOpList (i64, ShiftRight) , NULL ), // 0x87 + M3OP( "i64.shr_u", -1, i_64, d_binOpList (u64, ShiftRight) , NULL ), // 0x88 + M3OP( "i64.rotl", -1, i_64, d_binOpList (u64, Rotl) , NULL ), // 0x89 + M3OP( "i64.rotr", -1, i_64, d_binOpList (u64, Rotr) , NULL ), // 0x8a + + M3OP_F( "f32.abs", 0, f_32, d_unaryOpList(f32, Abs) , NULL ), // 0x8b + M3OP_F( "f32.neg", 0, f_32, d_unaryOpList(f32, Negate) , NULL ), // 0x8c + M3OP_F( "f32.ceil", 0, f_32, d_unaryOpList(f32, Ceil) , NULL ), // 0x8d + M3OP_F( "f32.floor", 0, f_32, d_unaryOpList(f32, Floor) , NULL ), // 0x8e + M3OP_F( "f32.trunc", 0, f_32, d_unaryOpList(f32, Trunc) , NULL ), // 0x8f + M3OP_F( "f32.nearest", 0, f_32, d_unaryOpList(f32, Nearest) , NULL ), // 0x90 + M3OP_F( "f32.sqrt", 0, f_32, d_unaryOpList(f32, Sqrt) , NULL ), // 0x91 + + M3OP_F( "f32.add", -1, f_32, d_commutativeBinOpList (f32, Add) , NULL ), // 0x92 + M3OP_F( "f32.sub", -1, f_32, d_binOpList (f32, Subtract) , NULL ), // 0x93 + M3OP_F( "f32.mul", -1, f_32, d_commutativeBinOpList (f32, Multiply) , NULL ), // 0x94 + M3OP_F( "f32.div", -1, f_32, d_binOpList (f32, Divide) , NULL ), // 0x95 + M3OP_F( "f32.min", -1, f_32, d_commutativeBinOpList (f32, Min) , NULL ), // 0x96 + M3OP_F( "f32.max", -1, f_32, d_commutativeBinOpList (f32, Max) , NULL ), // 0x97 + M3OP_F( "f32.copysign", -1, f_32, d_binOpList (f32, CopySign) , NULL ), // 0x98 + + M3OP_F( "f64.abs", 0, f_64, d_unaryOpList(f64, Abs) , NULL ), // 0x99 + M3OP_F( "f64.neg", 0, f_64, d_unaryOpList(f64, Negate) , NULL ), // 0x9a + M3OP_F( "f64.ceil", 0, f_64, d_unaryOpList(f64, Ceil) , NULL ), // 0x9b + M3OP_F( "f64.floor", 0, f_64, d_unaryOpList(f64, Floor) , NULL ), // 0x9c + M3OP_F( "f64.trunc", 0, f_64, d_unaryOpList(f64, Trunc) , NULL ), // 0x9d + M3OP_F( "f64.nearest", 0, f_64, d_unaryOpList(f64, Nearest) , NULL ), // 0x9e + M3OP_F( "f64.sqrt", 0, f_64, d_unaryOpList(f64, Sqrt) , NULL ), // 0x9f + + M3OP_F( "f64.add", -1, f_64, d_commutativeBinOpList (f64, Add) , NULL ), // 0xa0 + M3OP_F( "f64.sub", -1, f_64, d_binOpList (f64, Subtract) , NULL ), // 0xa1 + M3OP_F( "f64.mul", -1, f_64, d_commutativeBinOpList (f64, Multiply) , NULL ), // 0xa2 + M3OP_F( "f64.div", -1, f_64, d_binOpList (f64, Divide) , NULL ), // 0xa3 + M3OP_F( "f64.min", -1, f_64, d_commutativeBinOpList (f64, Min) , NULL ), // 0xa4 + M3OP_F( "f64.max", -1, f_64, d_commutativeBinOpList (f64, Max) , NULL ), // 0xa5 + M3OP_F( "f64.copysign", -1, f_64, d_binOpList (f64, CopySign) , NULL ), // 0xa6 + + M3OP( "i32.wrap/i64", 0, i_32, d_unaryOpList (i32, Wrap_i64), NULL ), // 0xa7 + M3OP_F( "i32.trunc_s/f32", 0, i_32, d_convertOpList (i32_Trunc_f32), Compile_Convert ), // 0xa8 + M3OP_F( "i32.trunc_u/f32", 0, i_32, d_convertOpList (u32_Trunc_f32), Compile_Convert ), // 0xa9 + M3OP_F( "i32.trunc_s/f64", 0, i_32, d_convertOpList (i32_Trunc_f64), Compile_Convert ), // 0xaa + M3OP_F( "i32.trunc_u/f64", 0, i_32, d_convertOpList (u32_Trunc_f64), Compile_Convert ), // 0xab + + M3OP( "i64.extend_s/i32", 0, i_64, d_unaryOpList (i64, Extend_i32), NULL ), // 0xac + M3OP( "i64.extend_u/i32", 0, i_64, d_unaryOpList (i64, Extend_u32), NULL ), // 0xad + + M3OP_F( "i64.trunc_s/f32", 0, i_64, d_convertOpList (i64_Trunc_f32), Compile_Convert ), // 0xae + M3OP_F( "i64.trunc_u/f32", 0, i_64, d_convertOpList (u64_Trunc_f32), Compile_Convert ), // 0xaf + M3OP_F( "i64.trunc_s/f64", 0, i_64, d_convertOpList (i64_Trunc_f64), Compile_Convert ), // 0xb0 + M3OP_F( "i64.trunc_u/f64", 0, i_64, d_convertOpList (u64_Trunc_f64), Compile_Convert ), // 0xb1 + + M3OP_F( "f32.convert_s/i32",0, f_32, d_convertOpList (f32_Convert_i32), Compile_Convert ), // 0xb2 + M3OP_F( "f32.convert_u/i32",0, f_32, d_convertOpList (f32_Convert_u32), Compile_Convert ), // 0xb3 + M3OP_F( "f32.convert_s/i64",0, f_32, d_convertOpList (f32_Convert_i64), Compile_Convert ), // 0xb4 + M3OP_F( "f32.convert_u/i64",0, f_32, d_convertOpList (f32_Convert_u64), Compile_Convert ), // 0xb5 + + M3OP_F( "f32.demote/f64", 0, f_32, d_unaryOpList (f32, Demote_f64), NULL ), // 0xb6 + + M3OP_F( "f64.convert_s/i32",0, f_64, d_convertOpList (f64_Convert_i32), Compile_Convert ), // 0xb7 + M3OP_F( "f64.convert_u/i32",0, f_64, d_convertOpList (f64_Convert_u32), Compile_Convert ), // 0xb8 + M3OP_F( "f64.convert_s/i64",0, f_64, d_convertOpList (f64_Convert_i64), Compile_Convert ), // 0xb9 + M3OP_F( "f64.convert_u/i64",0, f_64, d_convertOpList (f64_Convert_u64), Compile_Convert ), // 0xba + + M3OP_F( "f64.promote/f32", 0, f_64, d_unaryOpList (f64, Promote_f32), NULL ), // 0xbb + + M3OP_F( "i32.reinterpret/f32",0,i_32, d_convertOpList (i32_Reinterpret_f32), Compile_Convert ), // 0xbc + M3OP_F( "i64.reinterpret/f64",0,i_64, d_convertOpList (i64_Reinterpret_f64), Compile_Convert ), // 0xbd + M3OP_F( "f32.reinterpret/i32",0,f_32, d_convertOpList (f32_Reinterpret_i32), Compile_Convert ), // 0xbe + M3OP_F( "f64.reinterpret/i64",0,f_64, d_convertOpList (f64_Reinterpret_i64), Compile_Convert ), // 0xbf + + M3OP( "i32.extend8_s", 0, i_32, d_unaryOpList (i32, Extend8_s), NULL ), // 0xc0 + M3OP( "i32.extend16_s", 0, i_32, d_unaryOpList (i32, Extend16_s), NULL ), // 0xc1 + M3OP( "i64.extend8_s", 0, i_64, d_unaryOpList (i64, Extend8_s), NULL ), // 0xc2 + M3OP( "i64.extend16_s", 0, i_64, d_unaryOpList (i64, Extend16_s), NULL ), // 0xc3 + M3OP( "i64.extend32_s", 0, i_64, d_unaryOpList (i64, Extend32_s), NULL ), // 0xc4 + +# ifdef DEBUG // for codepage logging. the order doesn't matter: +# define d_m3DebugOp(OP) M3OP (#OP, 0, none, { op_##OP }) + +# if d_m3HasFloat +# define d_m3DebugTypedOp(OP) M3OP (#OP, 0, none, { op_##OP##_i32, op_##OP##_i64, op_##OP##_f32, op_##OP##_f64, }) +# else +# define d_m3DebugTypedOp(OP) M3OP (#OP, 0, none, { op_##OP##_i32, op_##OP##_i64 }) +# endif + + d_m3DebugOp (Compile), d_m3DebugOp (Entry), d_m3DebugOp (End), + d_m3DebugOp (Unsupported), d_m3DebugOp (CallRawFunction), + + d_m3DebugOp (GetGlobal_s32), d_m3DebugOp (GetGlobal_s64), d_m3DebugOp (ContinueLoop), d_m3DebugOp (ContinueLoopIf), + + d_m3DebugOp (CopySlot_32), d_m3DebugOp (PreserveCopySlot_32), d_m3DebugOp (If_s), d_m3DebugOp (BranchIfPrologue_s), + d_m3DebugOp (CopySlot_64), d_m3DebugOp (PreserveCopySlot_64), d_m3DebugOp (If_r), d_m3DebugOp (BranchIfPrologue_r), + + d_m3DebugOp (Select_i32_rss), d_m3DebugOp (Select_i32_srs), d_m3DebugOp (Select_i32_ssr), d_m3DebugOp (Select_i32_sss), + d_m3DebugOp (Select_i64_rss), d_m3DebugOp (Select_i64_srs), d_m3DebugOp (Select_i64_ssr), d_m3DebugOp (Select_i64_sss), + +# if d_m3HasFloat + d_m3DebugOp (Select_f32_sss), d_m3DebugOp (Select_f32_srs), d_m3DebugOp (Select_f32_ssr), + d_m3DebugOp (Select_f32_rss), d_m3DebugOp (Select_f32_rrs), d_m3DebugOp (Select_f32_rsr), + + d_m3DebugOp (Select_f64_sss), d_m3DebugOp (Select_f64_srs), d_m3DebugOp (Select_f64_ssr), + d_m3DebugOp (Select_f64_rss), d_m3DebugOp (Select_f64_rrs), d_m3DebugOp (Select_f64_rsr), +# endif + + d_m3DebugOp (MemFill), d_m3DebugOp (MemCopy), + + d_m3DebugTypedOp (SetGlobal), d_m3DebugOp (SetGlobal_s32), d_m3DebugOp (SetGlobal_s64), + + d_m3DebugTypedOp (SetRegister), d_m3DebugTypedOp (SetSlot), d_m3DebugTypedOp (PreserveSetSlot), +# endif + +# if d_m3CascadedOpcodes + [c_waOp_extended] = M3OP( "0xFC", 0, c_m3Type_unknown, d_emptyOpList, Compile_ExtendedOpcode ), +# endif + +# ifdef DEBUG + M3OP( "termination", 0, c_m3Type_unknown ) // for find_operation_info +# endif +}; + +const M3OpInfo c_operationsFC [] = +{ + M3OP_F( "i32.trunc_s:sat/f32",0, i_32, d_convertOpList (i32_TruncSat_f32), Compile_Convert ), // 0x00 + M3OP_F( "i32.trunc_u:sat/f32",0, i_32, d_convertOpList (u32_TruncSat_f32), Compile_Convert ), // 0x01 + M3OP_F( "i32.trunc_s:sat/f64",0, i_32, d_convertOpList (i32_TruncSat_f64), Compile_Convert ), // 0x02 + M3OP_F( "i32.trunc_u:sat/f64",0, i_32, d_convertOpList (u32_TruncSat_f64), Compile_Convert ), // 0x03 + M3OP_F( "i64.trunc_s:sat/f32",0, i_64, d_convertOpList (i64_TruncSat_f32), Compile_Convert ), // 0x04 + M3OP_F( "i64.trunc_u:sat/f32",0, i_64, d_convertOpList (u64_TruncSat_f32), Compile_Convert ), // 0x05 + M3OP_F( "i64.trunc_s:sat/f64",0, i_64, d_convertOpList (i64_TruncSat_f64), Compile_Convert ), // 0x06 + M3OP_F( "i64.trunc_u:sat/f64",0, i_64, d_convertOpList (u64_TruncSat_f64), Compile_Convert ), // 0x07 + + M3OP_RESERVED, M3OP_RESERVED, + + M3OP( "memory.copy", 0, none, d_emptyOpList, Compile_Memory_CopyFill ), // 0x0a + M3OP( "memory.fill", 0, none, d_emptyOpList, Compile_Memory_CopyFill ), // 0x0b + + +# ifdef DEBUG + M3OP( "termination", 0, c_m3Type_unknown ) // for find_operation_info +# endif +}; + + +IM3OpInfo GetOpInfo (m3opcode_t opcode) +{ + switch (opcode >> 8) { + case 0x00: + if (M3_LIKELY(opcode < M3_COUNT_OF(c_operations))) { + return &c_operations[opcode]; + } + break; + case c_waOp_extended: + opcode &= 0xFF; + if (M3_LIKELY(opcode < M3_COUNT_OF(c_operationsFC))) { + return &c_operationsFC[opcode]; + } + break; + } + return NULL; +} + +M3Result CompileBlockStatements (IM3Compilation o) +{ + M3Result result = m3Err_none; + bool validEnd = false; + + while (o->wasm < o->wasmEnd) + { +# if d_m3EnableOpTracing + if (o->numEmits) + { + EmitOp (o, op_DumpStack); + EmitConstant32 (o, o->numOpcodes); + EmitConstant32 (o, GetMaxUsedSlotPlusOne(o)); + EmitPointer (o, o->function); + + o->numEmits = 0; + } +# endif + m3opcode_t opcode; + o->lastOpcodeStart = o->wasm; +_ (Read_opcode (& opcode, & o->wasm, o->wasmEnd)); log_opcode (o, opcode); + + // Restrict opcodes when evaluating expressions + if (not o->function) { + switch (opcode) { + case c_waOp_i32_const: case c_waOp_i64_const: + case c_waOp_f32_const: case c_waOp_f64_const: + case c_waOp_getGlobal: case c_waOp_end: + break; + default: + _throw(m3Err_restrictedOpcode); + } + } + + IM3OpInfo opinfo = GetOpInfo (opcode); + + if (opinfo == NULL) + _throw (ErrorCompile (m3Err_unknownOpcode, o, "opcode '%x' not available", opcode)); + + if (opinfo->compiler) { +_ ((* opinfo->compiler) (o, opcode)) + } else { +_ (Compile_Operator (o, opcode)); + } + + o->previousOpcode = opcode; + + if (opcode == c_waOp_else) + { + _throwif (m3Err_wasmMalformed, o->block.opcode != c_waOp_if); + validEnd = true; + break; + } + else if (opcode == c_waOp_end) + { + validEnd = true; + break; + } + } + _throwif(m3Err_wasmMalformed, !(validEnd)); + +_catch: + return result; +} + +static +M3Result PushBlockResults (IM3Compilation o) +{ + M3Result result = m3Err_none; + + u16 numResults = GetFuncTypeNumResults (o->block.type); + + for (u16 i = 0; i < numResults; ++i) + { + u8 type = GetFuncTypeResultType (o->block.type, i); + + if (i == numResults - 1 and IsFpType (type)) + { +_ (PushRegister (o, type)); + } + else +_ (PushAllocatedSlot (o, type)); + } + + _catch: return result; +} + + +M3Result CompileBlock (IM3Compilation o, IM3FuncType i_blockType, m3opcode_t i_blockOpcode) +{ + d_m3Assert (not IsRegisterAllocated (o, 0)); + d_m3Assert (not IsRegisterAllocated (o, 1)); + M3CompilationScope outerScope = o->block; + M3CompilationScope * block = & o->block; + + block->outer = & outerScope; + block->pc = GetPagePC (o->page); + block->patches = NULL; + block->type = i_blockType; + block->depth ++; + block->opcode = i_blockOpcode; + + /* + The block stack frame is a little strange but for good reasons. Because blocks need to be restarted to + compile different pathways (if/else), the incoming params must be saved. The parameters are popped + and validated. But, then the stack top is readjusted so they aren't subsequently overwritten. + Next, the result are preallocated to find destination slots. But again these are immediately popped + (deallocated) and the stack top is readjusted to keep these records in pace. This allows branch instructions + to find their result landing pads. Finally, the params are copied from the "dead" records and pushed back + onto the stack as active stack items for the CompileBlockStatements () call. + + [ block ] + [ params ] + ------------------ + [ result ] <---- blockStackIndex + [ slots ] + ------------------ + [ saved param ] + [ records ] + <----- exitStackIndex + */ + +_try { + // validate and dealloc params ---------------------------- + + u16 stackIndex = o->stackIndex; + + u16 numParams = GetFuncTypeNumParams (i_blockType); + + if (i_blockOpcode != c_waOp_else) + { + for (u16 i = 0; i < numParams; ++i) + { + u8 type = GetFuncTypeParamType (i_blockType, numParams - 1 - i); +_ (PopType (o, type)); + } + } + else o->stackIndex -= numParams; + + u16 paramIndex = o->stackIndex; + block->exitStackIndex = paramIndex; // consume the params at block exit + + // keep copies of param slots in the stack + o->stackIndex = stackIndex; + + // find slots for the results ---------------------------- + PushBlockResults (o); + + stackIndex = o->stackIndex; + + // dealloc but keep record of the result slots in the stack + u16 numResults = GetFuncTypeNumResults (i_blockType); + while (numResults--) + Pop (o); + + block->blockStackIndex = o->stackIndex = stackIndex; + + // push the params back onto the stack ------------------- + for (u16 i = 0; i < numParams; ++i) + { + u8 type = GetFuncTypeParamType (i_blockType, i); + + u16 slot = GetSlotForStackIndex (o, paramIndex + i); + Push (o, type, slot); + + if (slot >= o->slotFirstDynamicIndex) + MarkSlotsAllocatedByType (o, slot, type); + } + + //-------------------------------------------------------- + +_ (CompileBlockStatements (o)); + +_ (ValidateBlockEnd (o)); + + if (o->function) // skip for expressions + { + if (not IsStackPolymorphic (o)) +_ (ResolveBlockResults (o, & o->block, /* isBranch: */ false)); + +_ (UnwindBlockStack (o)) + + if (not ((i_blockOpcode == c_waOp_if and numResults) or o->previousOpcode == c_waOp_else)) + { + o->stackIndex = o->block.exitStackIndex; +_ (PushBlockResults (o)); + } + } + + PatchBranches (o); + + o->block = outerScope; + +} _catch: return result; +} + +static +M3Result CompileLocals (IM3Compilation o) +{ + M3Result result; + + u32 numLocals = 0; + u32 numLocalBlocks; +_ (ReadLEB_u32 (& numLocalBlocks, & o->wasm, o->wasmEnd)); + + for (u32 l = 0; l < numLocalBlocks; ++l) + { + u32 varCount; + i8 waType; + u8 localType; + +_ (ReadLEB_u32 (& varCount, & o->wasm, o->wasmEnd)); +_ (ReadLEB_i7 (& waType, & o->wasm, o->wasmEnd)); +_ (NormalizeType (& localType, waType)); + numLocals += varCount; m3log (compile, "pushing locals. count: %d; type: %s", varCount, c_waTypes [localType]); + while (varCount--) +_ (PushAllocatedSlot (o, localType)); + } + + if (o->function) + o->function->numLocals = numLocals; + + _catch: return result; +} + +static +M3Result ReserveConstants (IM3Compilation o) +{ + M3Result result = m3Err_none; + + // in the interest of speed, this blindly scans the Wasm code looking for any byte + // that looks like an const opcode. + u16 numConstantSlots = 0; + + bytes_t wa = o->wasm; + while (wa < o->wasmEnd) + { + u8 code = * wa++; + + if (code == c_waOp_i32_const or code == c_waOp_f32_const) + numConstantSlots += 1; + else if (code == c_waOp_i64_const or code == c_waOp_f64_const) + numConstantSlots += GetTypeNumSlots (c_m3Type_i64); + + if (numConstantSlots >= d_m3MaxConstantTableSize) + break; + } + + // if constants overflow their reserved stack space, the compiler simply emits op_Const + // operations as needed. Compiled expressions (global inits) don't pass through this + // ReserveConstants function and thus always produce inline constants. + + AlignSlotToType (& numConstantSlots, c_m3Type_i64); m3log (compile, "reserved constant slots: %d", numConstantSlots); + + o->slotFirstDynamicIndex = o->slotFirstConstIndex + numConstantSlots; + + if (o->slotFirstDynamicIndex >= d_m3MaxFunctionSlots) + _throw (m3Err_functionStackOverflow); + + _catch: + return result; +} + + +M3Result CompileFunction (IM3Function io_function) +{ + if (!io_function->wasm) return "function body is missing"; + + IM3FuncType funcType = io_function->funcType; m3log (compile, "compiling: [%d] %s %s; wasm-size: %d", + io_function->index, m3_GetFunctionName (io_function), SPrintFuncTypeSignature (funcType), (u32) (io_function->wasmEnd - io_function->wasm)); + IM3Runtime runtime = io_function->module->runtime; + + IM3Compilation o = & runtime->compilation; d_m3Assert (d_m3MaxFunctionSlots >= d_m3MaxFunctionStackHeight * (d_m3Use32BitSlots + 1)) // need twice as many slots in 32-bit mode + memset (o, 0x0, sizeof (M3Compilation)); + + o->runtime = runtime; + o->module = io_function->module; + o->function = io_function; + o->wasm = io_function->wasm; + o->wasmEnd = io_function->wasmEnd; + o->block.type = funcType; + +_try { + // skip over code size. the end was already calculated during parse phase + u32 size; +_ (ReadLEB_u32 (& size, & o->wasm, o->wasmEnd)); d_m3Assert (size == (o->wasmEnd - o->wasm)) + +_ (AcquireCompilationCodePage (o, & o->page)); + + pc_t pc = GetPagePC (o->page); + + u16 numRetSlots = GetFunctionNumReturns (o->function) * c_ioSlotCount; + + for (u16 i = 0; i < numRetSlots; ++i) + MarkSlotAllocated (o, i); + + o->function->numRetSlots = o->slotFirstDynamicIndex = numRetSlots; + + u16 numArgs = GetFunctionNumArgs (o->function); + + // push the arg types to the type stack + for (u16 i = 0; i < numArgs; ++i) + { + u8 type = GetFunctionArgType (o->function, i); +_ (PushAllocatedSlot (o, type)); + + // prevent allocator fill-in + o->slotFirstDynamicIndex += c_ioSlotCount; + } + + o->slotMaxAllocatedIndexPlusOne = o->function->numRetAndArgSlots = o->slotFirstLocalIndex = o->slotFirstDynamicIndex; + +_ (CompileLocals (o)); + + u16 maxSlot = GetMaxUsedSlotPlusOne (o); + + o->function->numLocalBytes = (maxSlot - o->slotFirstLocalIndex) * sizeof (m3slot_t); + + o->slotFirstConstIndex = o->slotMaxConstIndex = maxSlot; + + // ReserveConstants initializes o->firstDynamicSlotNumber +_ (ReserveConstants (o)); + + // start tracking the max stack used (Push() also updates this value) so that op_Entry can precisely detect stack overflow + o->maxStackSlots = o->slotMaxAllocatedIndexPlusOne = o->slotFirstDynamicIndex; + + o->block.blockStackIndex = o->stackFirstDynamicIndex = o->stackIndex; m3log (compile, "start stack index: %d", + (u32) o->stackFirstDynamicIndex); +_ (EmitOp (o, op_Entry)); + EmitPointer (o, io_function); + +_ (CompileBlockStatements (o)); + + // TODO: validate opcode sequences + _throwif(m3Err_wasmMalformed, o->previousOpcode != c_waOp_end); + + io_function->compiled = pc; + io_function->maxStackSlots = o->maxStackSlots; + + u16 numConstantSlots = o->slotMaxConstIndex - o->slotFirstConstIndex; m3log (compile, "unique constant slots: %d; unused slots: %d", + numConstantSlots, o->slotFirstDynamicIndex - o->slotMaxConstIndex); + io_function->numConstantBytes = numConstantSlots * sizeof (m3slot_t); + + if (numConstantSlots) + { + io_function->constants = m3_CopyMem (o->constants, io_function->numConstantBytes); + _throwifnull(io_function->constants); + } + +} _catch: + + ReleaseCompilationCodePage (o); + + return result; +} diff --git a/ext/wasm3/source/m3_compile.h b/ext/wasm3/source/m3_compile.h new file mode 100644 index 0000000..52f7ab2 --- /dev/null +++ b/ext/wasm3/source/m3_compile.h @@ -0,0 +1,206 @@ +// +// m3_compile.h +// +// Created by Steven Massey on 4/17/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#ifndef m3_compile_h +#define m3_compile_h + +#include "m3_code.h" +#include "m3_exec_defs.h" +#include "m3_function.h" + +d_m3BeginExternC + +enum +{ + c_waOp_block = 0x02, + c_waOp_loop = 0x03, + c_waOp_if = 0x04, + c_waOp_else = 0x05, + c_waOp_end = 0x0b, + c_waOp_branch = 0x0c, + c_waOp_branchTable = 0x0e, + c_waOp_branchIf = 0x0d, + c_waOp_call = 0x10, + c_waOp_getLocal = 0x20, + c_waOp_setLocal = 0x21, + c_waOp_teeLocal = 0x22, + + c_waOp_getGlobal = 0x23, + + c_waOp_store_f32 = 0x38, + c_waOp_store_f64 = 0x39, + + c_waOp_i32_const = 0x41, + c_waOp_i64_const = 0x42, + c_waOp_f32_const = 0x43, + c_waOp_f64_const = 0x44, + + c_waOp_extended = 0xfc, + + c_waOp_memoryCopy = 0xfc0a, + c_waOp_memoryFill = 0xfc0b +}; + + +#define d_FuncRetType(ftype,i) ((ftype)->types[(i)]) +#define d_FuncArgType(ftype,i) ((ftype)->types[(ftype)->numRets + (i)]) + +//----------------------------------------------------------------------------------------------------------------------------------- + +typedef struct M3CompilationScope +{ + struct M3CompilationScope * outer; + + pc_t pc; // used by ContinueLoop's + pc_t patches; + i32 depth; + u16 exitStackIndex; + i16 blockStackIndex; +// u16 topSlot; + IM3FuncType type; + m3opcode_t opcode; + bool isPolymorphic; +} +M3CompilationScope; + +typedef M3CompilationScope * IM3CompilationScope; + +typedef struct +{ + IM3Runtime runtime; + IM3Module module; + + bytes_t wasm; + bytes_t wasmEnd; + bytes_t lastOpcodeStart; + + M3CompilationScope block; + + IM3Function function; + + IM3CodePage page; + +#ifdef DEBUG + u32 numEmits; + u32 numOpcodes; +#endif + + u16 stackFirstDynamicIndex; // args and locals are pushed to the stack so that their slot locations can be tracked. the wasm model itself doesn't + // treat these values as being on the stack, so stackFirstDynamicIndex marks the start of the real Wasm stack + u16 stackIndex; // current stack top + + u16 slotFirstConstIndex; + u16 slotMaxConstIndex; // as const's are encountered during compilation this tracks their location in the "real" stack + + u16 slotFirstLocalIndex; + u16 slotFirstDynamicIndex; // numArgs + numLocals + numReservedConstants. the first mutable slot available to the compiler. + + u16 maxStackSlots; + + m3slot_t constants [d_m3MaxConstantTableSize]; + + // 'wasmStack' holds slot locations + u16 wasmStack [d_m3MaxFunctionStackHeight]; + u8 typeStack [d_m3MaxFunctionStackHeight]; + + // 'm3Slots' contains allocation usage counts + u8 m3Slots [d_m3MaxFunctionSlots]; + + u16 slotMaxAllocatedIndexPlusOne; + + u16 regStackIndexPlusOne [2]; + + m3opcode_t previousOpcode; +} +M3Compilation; + +typedef M3Compilation * IM3Compilation; + +typedef M3Result (* M3Compiler) (IM3Compilation, m3opcode_t); + + +//----------------------------------------------------------------------------------------------------------------------------------- + + +typedef struct M3OpInfo +{ +#ifdef DEBUG + const char * const name; +#endif + + i8 stackOffset; + u8 type; + + // for most operations: + // [0]= top operand in register, [1]= top operand in stack, [2]= both operands in stack + IM3Operation operations [4]; + + M3Compiler compiler; +} +M3OpInfo; + +typedef const M3OpInfo * IM3OpInfo; + +IM3OpInfo GetOpInfo (m3opcode_t opcode); + +// TODO: This helper should be removed, when MultiValue is implemented +static inline +u8 GetSingleRetType(IM3FuncType ftype) { + return (ftype && ftype->numRets) ? ftype->types[0] : (u8)c_m3Type_none; +} + +static const u16 c_m3RegisterUnallocated = 0; +static const u16 c_slotUnused = 0xffff; + +static inline +bool IsRegisterAllocated (IM3Compilation o, u32 i_register) +{ + return (o->regStackIndexPlusOne [i_register] != c_m3RegisterUnallocated); +} + +static inline +bool IsStackPolymorphic (IM3Compilation o) +{ + return o->block.isPolymorphic; +} + +static inline bool IsRegisterSlotAlias (u16 i_slot) { return (i_slot >= d_m3Reg0SlotAlias and i_slot != c_slotUnused); } +static inline bool IsFpRegisterSlotAlias (u16 i_slot) { return (i_slot == d_m3Fp0SlotAlias); } +static inline bool IsIntRegisterSlotAlias (u16 i_slot) { return (i_slot == d_m3Reg0SlotAlias); } + + +#ifdef DEBUG + #define M3OP(...) { __VA_ARGS__ } + #define M3OP_RESERVED { "reserved" } +#else + // Strip-off name + #define M3OP(name, ...) { __VA_ARGS__ } + #define M3OP_RESERVED { 0 } +#endif + +#if d_m3HasFloat + #define M3OP_F M3OP +#elif d_m3NoFloatDynamic + #define M3OP_F(n,o,t,op,...) M3OP(n, o, t, { op_Unsupported, op_Unsupported, op_Unsupported, op_Unsupported }, __VA_ARGS__) +#else + #define M3OP_F(...) { 0 } +#endif + +//----------------------------------------------------------------------------------------------------------------------------------- + +u16 GetMaxUsedSlotPlusOne (IM3Compilation o); + +M3Result CompileBlock (IM3Compilation io, IM3FuncType i_blockType, m3opcode_t i_blockOpcode); + +M3Result CompileBlockStatements (IM3Compilation io); +M3Result CompileFunction (IM3Function io_function); + +M3Result CompileRawFunction (IM3Module io_module, IM3Function io_function, const void * i_function, const void * i_userdata); + +d_m3EndExternC + +#endif // m3_compile_h diff --git a/ext/wasm3/source/m3_config.h b/ext/wasm3/source/m3_config.h new file mode 100644 index 0000000..7766f57 --- /dev/null +++ b/ext/wasm3/source/m3_config.h @@ -0,0 +1,154 @@ +// +// m3_config.h +// +// Created by Steven Massey on 5/4/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#ifndef m3_config_h +#define m3_config_h + +#include "m3_config_platforms.h" + +// general -------------------------------------------------------------------- + +# ifndef d_m3CodePageAlignSize +# define d_m3CodePageAlignSize 32*1024 +# endif + +# ifndef d_m3EnableCodePageRefCounting +# define d_m3EnableCodePageRefCounting 0 +# endif + +# ifndef d_m3MaxFunctionStackHeight +# define d_m3MaxFunctionStackHeight 4000 // max: 32768 +# endif + +# ifndef d_m3MaxLinearMemoryPages +# define d_m3MaxLinearMemoryPages 32768 +# endif + +# ifndef d_m3MaxFunctionSlots +# define d_m3MaxFunctionSlots ((d_m3MaxFunctionStackHeight)*2) +# endif + +# ifndef d_m3MaxConstantTableSize +# define d_m3MaxConstantTableSize 120 +# endif + +# ifndef d_m3MaxDuplicateFunctionImpl +# define d_m3MaxDuplicateFunctionImpl 3 +# endif + +# ifndef d_m3CascadedOpcodes // Cascaded opcodes are slightly faster at the expense of some memory +# define d_m3CascadedOpcodes 1 // Adds ~3Kb to operations table in m3_compile.c +# endif + +# ifndef d_m3VerboseErrorMessages +# define d_m3VerboseErrorMessages 1 +# endif + +# ifndef d_m3FixedHeap +# define d_m3FixedHeap false +//# define d_m3FixedHeap (32*1024) +# endif + +# ifndef d_m3FixedHeapAlign +# define d_m3FixedHeapAlign 16 +# endif + +# ifndef d_m3Use32BitSlots +# define d_m3Use32BitSlots 1 +# endif + +# ifndef d_m3ProfilerSlotMask +# define d_m3ProfilerSlotMask 0xFFFF +# endif + +# ifndef d_m3RecordBacktraces +# define d_m3RecordBacktraces 0 +# endif + +# ifndef d_m3EnableExceptionBreakpoint +# define d_m3EnableExceptionBreakpoint 0 // see m3_exception.h +# endif + + +// profiling and tracing ------------------------------------------------------ + +# ifndef d_m3EnableOpProfiling +# define d_m3EnableOpProfiling 0 // opcode usage counters +# endif + +# ifndef d_m3EnableOpTracing +# define d_m3EnableOpTracing 0 // only works with DEBUG +# endif + +# ifndef d_m3EnableStrace +# define d_m3EnableStrace 0 // 1 - trace exported function calls + // 2 - trace all calls (structured) - requires DEBUG + // 3 - all calls + loops + memory operations +# endif + + +// logging -------------------------------------------------------------------- + +# ifndef d_m3LogParse +# define d_m3LogParse 0 // .wasm binary decoding info +# endif + +# ifndef d_m3LogModule +# define d_m3LogModule 0 // wasm module info +# endif + +# ifndef d_m3LogCompile +# define d_m3LogCompile 0 // wasm -> metacode generation phase +# endif + +# ifndef d_m3LogWasmStack +# define d_m3LogWasmStack 0 // dump the wasm stack when pushed or popped +# endif + +# ifndef d_m3LogEmit +# define d_m3LogEmit 0 // metacode generation info +# endif + +# ifndef d_m3LogCodePages +# define d_m3LogCodePages 0 // dump metacode pages when released +# endif + +# ifndef d_m3LogRuntime +# define d_m3LogRuntime 0 // higher-level runtime information +# endif + +# ifndef d_m3LogNativeStack +# define d_m3LogNativeStack 0 // track the memory usage of the C-stack +# endif + +# ifndef d_m3LogHeapOps +# define d_m3LogHeapOps 0 // track heap usage +# endif + +# ifndef d_m3LogTimestamps +# define d_m3LogTimestamps 0 // track timestamps on heap logs +# endif + +// other ---------------------------------------------------------------------- + +# ifndef d_m3HasFloat +# define d_m3HasFloat 1 // implement floating point ops +# endif + +#if !d_m3HasFloat && !defined(d_m3NoFloatDynamic) +# define d_m3NoFloatDynamic 1 // if no floats, do not fail until flops are actually executed +#endif + +# ifndef d_m3SkipStackCheck +# define d_m3SkipStackCheck 0 // skip stack overrun checks +# endif + +# ifndef d_m3SkipMemoryBoundsCheck +# define d_m3SkipMemoryBoundsCheck 0 // skip memory bounds checks +# endif + +#endif // m3_config_h diff --git a/ext/wasm3/source/m3_config_platforms.h b/ext/wasm3/source/m3_config_platforms.h new file mode 100644 index 0000000..0cb475d --- /dev/null +++ b/ext/wasm3/source/m3_config_platforms.h @@ -0,0 +1,202 @@ +// +// m3_config_platforms.h +// +// Created by Volodymyr Shymanskyy on 11/20/19. +// Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. +// + +#ifndef m3_config_platforms_h +#define m3_config_platforms_h + +#include "wasm3_defs.h" + +/* + * Internal helpers + */ + +# if !defined(__cplusplus) || defined(_MSC_VER) +# define not ! +# define and && +# define or || +# endif + +/* + * Detect/define features + */ + +# if defined(M3_COMPILER_MSVC) +# include +# if UINTPTR_MAX == 0xFFFFFFFF +# define M3_SIZEOF_PTR 4 +# elif UINTPTR_MAX == 0xFFFFFFFFFFFFFFFFu +# define M3_SIZEOF_PTR 8 +# else +# error "Pointer size not supported" +# endif +# elif defined(__SIZEOF_POINTER__) +# define M3_SIZEOF_PTR __SIZEOF_POINTER__ +#else +# error "Pointer size not detected" +# endif + +# if defined(M3_BIG_ENDIAN) +# define M3_BSWAP_u8(X) {} +# define M3_BSWAP_u16(X) { (X)=m3_bswap16((X)); } +# define M3_BSWAP_u32(X) { (X)=m3_bswap32((X)); } +# define M3_BSWAP_u64(X) { (X)=m3_bswap64((X)); } +# define M3_BSWAP_i8(X) {} +# define M3_BSWAP_i16(X) M3_BSWAP_u16(X) +# define M3_BSWAP_i32(X) M3_BSWAP_u32(X) +# define M3_BSWAP_i64(X) M3_BSWAP_u64(X) +# define M3_BSWAP_f32(X) { union { f32 f; u32 i; } u; u.f = (X); M3_BSWAP_u32(u.i); (X) = u.f; } +# define M3_BSWAP_f64(X) { union { f64 f; u64 i; } u; u.f = (X); M3_BSWAP_u64(u.i); (X) = u.f; } +# else +# define M3_BSWAP_u8(X) {} +# define M3_BSWAP_u16(x) {} +# define M3_BSWAP_u32(x) {} +# define M3_BSWAP_u64(x) {} +# define M3_BSWAP_i8(X) {} +# define M3_BSWAP_i16(X) {} +# define M3_BSWAP_i32(X) {} +# define M3_BSWAP_i64(X) {} +# define M3_BSWAP_f32(X) {} +# define M3_BSWAP_f64(X) {} +# endif + +# if defined(M3_COMPILER_MSVC) +# define M3_WEAK //__declspec(selectany) +# define M3_NO_UBSAN +# define M3_NOINLINE +# elif defined(__MINGW32__) || defined(__CYGWIN__) +# define M3_WEAK //__attribute__((selectany)) +# define M3_NO_UBSAN +# define M3_NOINLINE __attribute__((noinline)) +# else +# define M3_WEAK __attribute__((weak)) +# define M3_NO_UBSAN //__attribute__((no_sanitize("undefined"))) +// Workaround for Cosmopolitan noinline conflict: https://github.com/jart/cosmopolitan/issues/310 +# if defined(noinline) +# define M3_NOINLINE noinline +# else +# define M3_NOINLINE __attribute__((noinline)) +# endif +# endif + +# ifndef M3_MIN +# define M3_MIN(A,B) (((A) < (B)) ? (A) : (B)) +# endif +# ifndef M3_MAX +# define M3_MAX(A,B) (((A) > (B)) ? (A) : (B)) +# endif + +#define M3_INIT(field) memset(&field, 0, sizeof(field)) + +#define M3_COUNT_OF(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) + +#if defined(__AVR__) + +#include + +# define PRIu64 "llu" +# define PRIi64 "lli" + +# define d_m3ShortTypesDefined +typedef double f64; +typedef float f32; +typedef uint64_t u64; +typedef int64_t i64; +typedef uint32_t u32; +typedef int32_t i32; +typedef short unsigned u16; +typedef short i16; +typedef uint8_t u8; +typedef int8_t i8; + +#endif + +/* + * Apply settings + */ + +# if defined (M3_COMPILER_MSVC) +# define vectorcall // For MSVC, better not to specify any call convention +# elif defined(__x86_64__) +# define vectorcall __attribute__((aligned(32))) +//# elif defined(__riscv) && (__riscv_xlen == 64) +//# define vectorcall __attribute__((aligned(16))) +# elif defined(__MINGW32__) +# define vectorcall +# elif defined(WIN32) +# define vectorcall __vectorcall +# elif defined (ESP8266) +# include +# define vectorcall //ICACHE_FLASH_ATTR +# elif defined (ESP32) +# if defined(M3_IN_IRAM) // the interpreter is in IRAM, attribute not needed +# define vectorcall +# else +# include "esp_system.h" +# define vectorcall IRAM_ATTR +# endif +# elif defined (FOMU) +# define vectorcall __attribute__((section(".ramtext"))) +# endif + +#ifndef vectorcall +#define vectorcall +#endif + + +/* + * Device-specific defaults + */ + +# ifndef d_m3MaxFunctionStackHeight +# if defined(ESP8266) || defined(ESP32) || defined(ARDUINO_AMEBA) || defined(TEENSYDUINO) +# define d_m3MaxFunctionStackHeight 128 +# endif +# endif + +# ifndef d_m3FixedHeap +# if defined(ARDUINO_AMEBA) +# define d_m3FixedHeap (128*1024) +# elif defined(BLUE_PILL) || defined(FOMU) +# define d_m3FixedHeap (12*1024) +# elif defined(ARDUINO_ARCH_ARC32) // Arduino 101 +# define d_m3FixedHeap (10*1024) +# endif +# endif + +/* + * Platform-specific defaults + */ + +# if defined(ARDUINO) || defined(PARTICLE) || defined(PLATFORMIO) || defined(__MBED__) || \ + defined(ESP8266) || defined(ESP32) || defined(BLUE_PILL) || defined(WM_W600) || defined(FOMU) +# ifndef d_m3CascadedOpcodes +# define d_m3CascadedOpcodes 0 +# endif +# ifndef d_m3VerboseErrorMessages +# define d_m3VerboseErrorMessages 0 +# endif +# ifndef d_m3MaxConstantTableSize +# define d_m3MaxConstantTableSize 64 +# endif +# ifndef d_m3MaxFunctionStackHeight +# define d_m3MaxFunctionStackHeight 64 +# endif +# ifndef d_m3CodePageAlignSize +# define d_m3CodePageAlignSize 1024 +# endif +# endif + +/* + * Arch-specific defaults + */ +#if defined(__riscv) && (__riscv_xlen == 64) +# ifndef d_m3Use32BitSlots +# define d_m3Use32BitSlots 0 +# endif +#endif + +#endif // m3_config_platforms_h diff --git a/ext/wasm3/source/m3_core.c b/ext/wasm3/source/m3_core.c new file mode 100644 index 0000000..5980ab8 --- /dev/null +++ b/ext/wasm3/source/m3_core.c @@ -0,0 +1,615 @@ +// +// m3_core.c +// +// Created by Steven Massey on 4/15/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#define M3_IMPLEMENT_ERROR_STRINGS +#include "m3_config.h" +#include "wasm3.h" + +#include "m3_core.h" +#include "m3_env.h" + +void m3_Abort(const char* message) { +#ifdef DEBUG + fprintf(stderr, "Error: %s\n", message); +#endif + abort(); +} + +M3_WEAK +M3Result m3_Yield () +{ + return m3Err_none; +} + +#if d_m3LogTimestamps + +#include + +#define SEC_TO_US(sec) ((sec)*1000000) +#define NS_TO_US(ns) ((ns)/1000) + +static uint64_t initial_ts = -1; + +uint64_t m3_GetTimestamp() +{ + if (initial_ts == -1) { + initial_ts = 0; + initial_ts = m3_GetTimestamp(); + } + struct timespec ts; + timespec_get(&ts, TIME_UTC); + uint64_t us = SEC_TO_US((uint64_t)ts.tv_sec) + NS_TO_US((uint64_t)ts.tv_nsec); + return us - initial_ts; +} + +#endif + +#if d_m3FixedHeap + +static u8 fixedHeap[d_m3FixedHeap]; +static u8* fixedHeapPtr = fixedHeap; +static u8* const fixedHeapEnd = fixedHeap + d_m3FixedHeap; +static u8* fixedHeapLast = NULL; + +#if d_m3FixedHeapAlign > 1 +# define HEAP_ALIGN_PTR(P) P = (u8*)(((size_t)(P)+(d_m3FixedHeapAlign-1)) & ~ (d_m3FixedHeapAlign-1)); +#else +# define HEAP_ALIGN_PTR(P) +#endif + +void * m3_Malloc_Impl (size_t i_size) +{ + u8 * ptr = fixedHeapPtr; + + fixedHeapPtr += i_size; + HEAP_ALIGN_PTR(fixedHeapPtr); + + if (fixedHeapPtr >= fixedHeapEnd) + { + return NULL; + } + + memset (ptr, 0x0, i_size); + fixedHeapLast = ptr; + + return ptr; +} + +void m3_Free_Impl (void * i_ptr) +{ + // Handle the last chunk + if (i_ptr && i_ptr == fixedHeapLast) { + fixedHeapPtr = fixedHeapLast; + fixedHeapLast = NULL; + } else { + //printf("== free %p [failed]\n", io_ptr); + } +} + +void * m3_Realloc_Impl (void * i_ptr, size_t i_newSize, size_t i_oldSize) +{ + if (M3_UNLIKELY(i_newSize == i_oldSize)) return i_ptr; + + void * newPtr; + + // Handle the last chunk + if (i_ptr && i_ptr == fixedHeapLast) { + fixedHeapPtr = fixedHeapLast + i_newSize; + HEAP_ALIGN_PTR(fixedHeapPtr); + if (fixedHeapPtr >= fixedHeapEnd) + { + return NULL; + } + newPtr = i_ptr; + } else { + newPtr = m3_Malloc_Impl(i_newSize); + if (!newPtr) { + return NULL; + } + if (i_ptr) { + memcpy(newPtr, i_ptr, i_oldSize); + } + } + + if (i_newSize > i_oldSize) { + memset ((u8 *) newPtr + i_oldSize, 0x0, i_newSize - i_oldSize); + } + + return newPtr; +} + +#else + +void * m3_Malloc_Impl (size_t i_size) +{ + return calloc (i_size, 1); +} + +void m3_Free_Impl (void * io_ptr) +{ + free (io_ptr); +} + +void * m3_Realloc_Impl (void * i_ptr, size_t i_newSize, size_t i_oldSize) +{ + if (M3_UNLIKELY(i_newSize == i_oldSize)) return i_ptr; + + void * newPtr = realloc (i_ptr, i_newSize); + + if (M3_LIKELY(newPtr)) + { + if (i_newSize > i_oldSize) { + memset ((u8 *) newPtr + i_oldSize, 0x0, i_newSize - i_oldSize); + } + return newPtr; + } + return NULL; +} + +#endif + +void * m3_CopyMem (const void * i_from, size_t i_size) +{ + void * ptr = m3_Malloc("CopyMem", i_size); + if (ptr) { + memcpy (ptr, i_from, i_size); + } + return ptr; +} + +//-------------------------------------------------------------------------------------------- + +#if d_m3LogNativeStack + +static size_t stack_start; +static size_t stack_end; + +void m3StackCheckInit () +{ + char stack; + stack_end = stack_start = (size_t)&stack; +} + +void m3StackCheck () +{ + char stack; + size_t addr = (size_t)&stack; + + size_t stackEnd = stack_end; + stack_end = M3_MIN (stack_end, addr); + +// if (stackEnd != stack_end) +// printf ("maxStack: %ld\n", m3StackGetMax ()); +} + +int m3StackGetMax () +{ + return stack_start - stack_end; +} + +#endif + +//-------------------------------------------------------------------------------------------- + +M3Result NormalizeType (u8 * o_type, i8 i_convolutedWasmType) +{ + M3Result result = m3Err_none; + + u8 type = -i_convolutedWasmType; + + if (type == 0x40) + type = c_m3Type_none; + else if (type < c_m3Type_i32 or type > c_m3Type_f64) + result = m3Err_invalidTypeId; + + * o_type = type; + + return result; +} + + +bool IsFpType (u8 i_m3Type) +{ + return (i_m3Type == c_m3Type_f32 or i_m3Type == c_m3Type_f64); +} + + +bool IsIntType (u8 i_m3Type) +{ + return (i_m3Type == c_m3Type_i32 or i_m3Type == c_m3Type_i64); +} + + +bool Is64BitType (u8 i_m3Type) +{ + if (i_m3Type == c_m3Type_i64 or i_m3Type == c_m3Type_f64) + return true; + else if (i_m3Type == c_m3Type_i32 or i_m3Type == c_m3Type_f32 or i_m3Type == c_m3Type_none) + return false; + else + return (sizeof (voidptr_t) == 8); // all other cases are pointers +} + +u32 SizeOfType (u8 i_m3Type) +{ + if (i_m3Type == c_m3Type_i32 or i_m3Type == c_m3Type_f32) + return sizeof (i32); + + return sizeof (i64); +} + + +//-- Binary Wasm parsing utils ------------------------------------------------------------------------------------------ + + +M3Result Read_u64 (u64 * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + const u8 * ptr = * io_bytes; + ptr += sizeof (u64); + + if (ptr <= i_end) + { + memcpy(o_value, * io_bytes, sizeof(u64)); + M3_BSWAP_u64(*o_value); + * io_bytes = ptr; + return m3Err_none; + } + else return m3Err_wasmUnderrun; +} + + +M3Result Read_u32 (u32 * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + const u8 * ptr = * io_bytes; + ptr += sizeof (u32); + + if (ptr <= i_end) + { + memcpy(o_value, * io_bytes, sizeof(u32)); + M3_BSWAP_u32(*o_value); + * io_bytes = ptr; + return m3Err_none; + } + else return m3Err_wasmUnderrun; +} + +#if d_m3ImplementFloat + +M3Result Read_f64 (f64 * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + const u8 * ptr = * io_bytes; + ptr += sizeof (f64); + + if (ptr <= i_end) + { + memcpy(o_value, * io_bytes, sizeof(f64)); + M3_BSWAP_f64(*o_value); + * io_bytes = ptr; + return m3Err_none; + } + else return m3Err_wasmUnderrun; +} + + +M3Result Read_f32 (f32 * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + const u8 * ptr = * io_bytes; + ptr += sizeof (f32); + + if (ptr <= i_end) + { + memcpy(o_value, * io_bytes, sizeof(f32)); + M3_BSWAP_f32(*o_value); + * io_bytes = ptr; + return m3Err_none; + } + else return m3Err_wasmUnderrun; +} + +#endif + +M3Result Read_u8 (u8 * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + const u8 * ptr = * io_bytes; + + if (ptr < i_end) + { + * o_value = * ptr; + * io_bytes = ptr + 1; + + return m3Err_none; + } + else return m3Err_wasmUnderrun; +} + +M3Result Read_opcode (m3opcode_t * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + const u8 * ptr = * io_bytes; + + if (ptr < i_end) + { + m3opcode_t opcode = * ptr++; + +#if d_m3CascadedOpcodes == 0 + if (M3_UNLIKELY(opcode == c_waOp_extended)) + { + if (ptr < i_end) + { + opcode = (opcode << 8) | (* ptr++); + } + else return m3Err_wasmUnderrun; + } +#endif + * o_value = opcode; + * io_bytes = ptr; + + return m3Err_none; + } + else return m3Err_wasmUnderrun; +} + + +M3Result ReadLebUnsigned (u64 * o_value, u32 i_maxNumBits, bytes_t * io_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_wasmUnderrun; + + u64 value = 0; + + u32 shift = 0; + const u8 * ptr = * io_bytes; + + while (ptr < i_end) + { + u64 byte = * (ptr++); + + value |= ((byte & 0x7f) << shift); + shift += 7; + + if ((byte & 0x80) == 0) + { + result = m3Err_none; + break; + } + + if (shift >= i_maxNumBits) + { + result = m3Err_lebOverflow; + break; + } + } + + * o_value = value; + * io_bytes = ptr; + + return result; +} + + +M3Result ReadLebSigned (i64 * o_value, u32 i_maxNumBits, bytes_t * io_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_wasmUnderrun; + + i64 value = 0; + + u32 shift = 0; + const u8 * ptr = * io_bytes; + + while (ptr < i_end) + { + u64 byte = * (ptr++); + + value |= ((byte & 0x7f) << shift); + shift += 7; + + if ((byte & 0x80) == 0) + { + result = m3Err_none; + + if ((byte & 0x40) and (shift < 64)) // do sign extension + { + u64 extend = 0; + value |= (~extend << shift); + } + + break; + } + + if (shift >= i_maxNumBits) + { + result = m3Err_lebOverflow; + break; + } + } + + * o_value = value; + * io_bytes = ptr; + + return result; +} + + +M3Result ReadLEB_u32 (u32 * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + u64 value; + M3Result result = ReadLebUnsigned (& value, 32, io_bytes, i_end); + * o_value = (u32) value; + + return result; +} + + +M3Result ReadLEB_u7 (u8 * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + u64 value; + M3Result result = ReadLebUnsigned (& value, 7, io_bytes, i_end); + * o_value = (u8) value; + + return result; +} + + +M3Result ReadLEB_i7 (i8 * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + i64 value; + M3Result result = ReadLebSigned (& value, 7, io_bytes, i_end); + * o_value = (i8) value; + + return result; +} + + +M3Result ReadLEB_i32 (i32 * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + i64 value; + M3Result result = ReadLebSigned (& value, 32, io_bytes, i_end); + * o_value = (i32) value; + + return result; +} + + +M3Result ReadLEB_i64 (i64 * o_value, bytes_t * io_bytes, cbytes_t i_end) +{ + i64 value; + M3Result result = ReadLebSigned (& value, 64, io_bytes, i_end); + * o_value = value; + + return result; +} + + +M3Result Read_utf8 (cstr_t * o_utf8, bytes_t * io_bytes, cbytes_t i_end) +{ + *o_utf8 = NULL; + + u32 utf8Length; + M3Result result = ReadLEB_u32 (& utf8Length, io_bytes, i_end); + + if (not result) + { + if (utf8Length <= d_m3MaxSaneUtf8Length) + { + const u8 * ptr = * io_bytes; + const u8 * end = ptr + utf8Length; + + if (end <= i_end) + { + char * utf8 = (char *)m3_Malloc ("UTF8", utf8Length + 1); + + if (utf8) + { + memcpy (utf8, ptr, utf8Length); + utf8 [utf8Length] = 0; + * o_utf8 = utf8; + } + + * io_bytes = end; + } + else result = m3Err_wasmUnderrun; + } + else result = m3Err_missingUTF8; + } + + return result; +} + +#if d_m3RecordBacktraces +u32 FindModuleOffset (IM3Runtime i_runtime, pc_t i_pc) +{ + // walk the code pages + IM3CodePage curr = i_runtime->pagesOpen; + bool pageFound = false; + + while (curr) + { + if (ContainsPC (curr, i_pc)) + { + pageFound = true; + break; + } + curr = curr->info.next; + } + + if (!pageFound) + { + curr = i_runtime->pagesFull; + while (curr) + { + if (ContainsPC (curr, i_pc)) + { + pageFound = true; + break; + } + curr = curr->info.next; + } + } + + if (pageFound) + { + u32 result = 0; + + bool pcFound = MapPCToOffset (curr, i_pc, & result); + d_m3Assert (pcFound); + + return result; + } + else return 0; +} + + +void PushBacktraceFrame (IM3Runtime io_runtime, pc_t i_pc) +{ + // don't try to push any more frames if we've already had an alloc failure + if (M3_UNLIKELY (io_runtime->backtrace.lastFrame == M3_BACKTRACE_TRUNCATED)) + return; + + M3BacktraceFrame * newFrame = m3_AllocStruct(M3BacktraceFrame); + + if (!newFrame) + { + io_runtime->backtrace.lastFrame = M3_BACKTRACE_TRUNCATED; + return; + } + + newFrame->moduleOffset = FindModuleOffset (io_runtime, i_pc); + + if (!io_runtime->backtrace.frames || !io_runtime->backtrace.lastFrame) + io_runtime->backtrace.frames = newFrame; + else + io_runtime->backtrace.lastFrame->next = newFrame; + io_runtime->backtrace.lastFrame = newFrame; +} + + +void FillBacktraceFunctionInfo (IM3Runtime io_runtime, IM3Function i_function) +{ + // If we've had an alloc failure then the last frame doesn't refer to the + // frame we want to fill in the function info for. + if (M3_UNLIKELY (io_runtime->backtrace.lastFrame == M3_BACKTRACE_TRUNCATED)) + return; + + if (!io_runtime->backtrace.lastFrame) + return; + + io_runtime->backtrace.lastFrame->function = i_function; +} + + +void ClearBacktrace (IM3Runtime io_runtime) +{ + M3BacktraceFrame * currentFrame = io_runtime->backtrace.frames; + while (currentFrame) + { + M3BacktraceFrame * nextFrame = currentFrame->next; + m3_Free (currentFrame); + currentFrame = nextFrame; + } + + io_runtime->backtrace.frames = NULL; + io_runtime->backtrace.lastFrame = NULL; +} +#endif // d_m3RecordBacktraces diff --git a/ext/wasm3/source/m3_core.h b/ext/wasm3/source/m3_core.h new file mode 100644 index 0000000..802a265 --- /dev/null +++ b/ext/wasm3/source/m3_core.h @@ -0,0 +1,311 @@ +// +// m3_core.h +// +// Created by Steven Massey on 4/15/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#ifndef m3_core_h +#define m3_core_h + +#include +#include +#include +#include +#include + +#include "wasm3.h" +#include "m3_config.h" + +# if defined(__cplusplus) +# define d_m3BeginExternC extern "C" { +# define d_m3EndExternC } +# else +# define d_m3BeginExternC +# define d_m3EndExternC +# endif + +d_m3BeginExternC + +#define d_m3ImplementFloat (d_m3HasFloat || d_m3NoFloatDynamic) + +#if !defined(d_m3ShortTypesDefined) + +typedef uint64_t u64; +typedef int64_t i64; +typedef uint32_t u32; +typedef int32_t i32; +typedef uint16_t u16; +typedef int16_t i16; +typedef uint8_t u8; +typedef int8_t i8; + +#if d_m3ImplementFloat +typedef double f64; +typedef float f32; +#endif + +#endif // d_m3ShortTypesDefined + +#define PRIf32 "f" +#define PRIf64 "lf" + +typedef const void * m3ret_t; +typedef const void * voidptr_t; +typedef const char * cstr_t; +typedef const char * const ccstr_t; +typedef const u8 * bytes_t; +typedef const u8 * const cbytes_t; + +typedef u16 m3opcode_t; + +typedef i64 m3reg_t; + +# if d_m3Use32BitSlots +typedef u32 m3slot_t; +# else +typedef u64 m3slot_t; +# endif + +typedef m3slot_t * m3stack_t; + +typedef +const void * const cvptr_t; + +# if defined (DEBUG) + +# define d_m3Log(CATEGORY, FMT, ...) printf (" %8s | " FMT, #CATEGORY, ##__VA_ARGS__); + +# if d_m3LogParse +# define m3log_parse(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__) +# else +# define m3log_parse(...) {} +# endif + +# if d_m3LogCompile +# define m3log_compile(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__) +# else +# define m3log_compile(...) {} +# endif + +# if d_m3LogEmit +# define m3log_emit(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__) +# else +# define m3log_emit(...) {} +# endif + +# if d_m3LogCodePages +# define m3log_code(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__) +# else +# define m3log_code(...) {} +# endif + +# if d_m3LogModule +# define m3log_module(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__) +# else +# define m3log_module(...) {} +# endif + +# if d_m3LogRuntime +# define m3log_runtime(CATEGORY, FMT, ...) d_m3Log(CATEGORY, FMT, ##__VA_ARGS__) +# else +# define m3log_runtime(...) {} +# endif + +# define m3log(CATEGORY, FMT, ...) m3log_##CATEGORY (CATEGORY, FMT "\n", ##__VA_ARGS__) +# else +# define d_m3Log(CATEGORY, FMT, ...) {} +# define m3log(CATEGORY, FMT, ...) {} +# endif + + +# if defined(ASSERTS) || (defined(DEBUG) && !defined(NASSERTS)) +# define d_m3Assert(ASS) if (!(ASS)) { printf("Assertion failed at %s:%d : %s\n", __FILE__, __LINE__, #ASS); abort(); } +# else +# define d_m3Assert(ASS) +# endif + +typedef void /*const*/ * code_t; +typedef code_t const * /*__restrict__*/ pc_t; + + +typedef struct M3MemoryHeader +{ + IM3Runtime runtime; + void * maxStack; + size_t length; +} +M3MemoryHeader; + +struct M3CodeMappingPage; + +typedef struct M3CodePageHeader +{ + struct M3CodePage * next; + + u32 lineIndex; + u32 numLines; + u32 sequence; // this is just used for debugging; could be removed + u32 usageCount; + +# if d_m3RecordBacktraces + struct M3CodeMappingPage * mapping; +# endif // d_m3RecordBacktraces +} +M3CodePageHeader; + + +#define d_m3CodePageFreeLinesThreshold 4+2 // max is: select _sss & CallIndirect + 2 for bridge + +#define d_m3MemPageSize 65536 + +#define d_m3Reg0SlotAlias 60000 +#define d_m3Fp0SlotAlias (d_m3Reg0SlotAlias + 2) + +#define d_m3MaxSaneTypesCount 100000 +#define d_m3MaxSaneFunctionsCount 100000 +#define d_m3MaxSaneImportsCount 10000 +#define d_m3MaxSaneExportsCount 10000 +#define d_m3MaxSaneGlobalsCount 100000 +#define d_m3MaxSaneElementSegments 100000 +#define d_m3MaxSaneDataSegments 100000 +#define d_m3MaxSaneTableSize 100000 +#define d_m3MaxSaneUtf8Length 10000 +#define d_m3MaxSaneFunctionArgRetCount 1000 // still insane, but whatever + +#define d_externalKind_function 0 +#define d_externalKind_table 1 +#define d_externalKind_memory 2 +#define d_externalKind_global 3 + +static const char * const c_waTypes [] = { "nil", "i32", "i64", "f32", "f64", "unknown" }; +static const char * const c_waCompactTypes [] = { "_", "i", "I", "f", "F", "?" }; + + +# if d_m3VerboseErrorMessages + +M3Result m3Error (M3Result i_result, IM3Runtime i_runtime, IM3Module i_module, IM3Function i_function, + const char * const i_file, u32 i_lineNum, const char * const i_errorMessage, ...); + +# define _m3Error(RESULT, RT, MOD, FUN, FILE, LINE, FORMAT, ...) \ + m3Error (RESULT, RT, MOD, FUN, FILE, LINE, FORMAT, ##__VA_ARGS__) + +# else +# define _m3Error(RESULT, RT, MOD, FUN, FILE, LINE, FORMAT, ...) (RESULT) +# endif + +#define ErrorRuntime(RESULT, RUNTIME, FORMAT, ...) _m3Error (RESULT, RUNTIME, NULL, NULL, __FILE__, __LINE__, FORMAT, ##__VA_ARGS__) +#define ErrorModule(RESULT, MOD, FORMAT, ...) _m3Error (RESULT, MOD->runtime, MOD, NULL, __FILE__, __LINE__, FORMAT, ##__VA_ARGS__) +#define ErrorCompile(RESULT, COMP, FORMAT, ...) _m3Error (RESULT, COMP->runtime, COMP->module, NULL, __FILE__, __LINE__, FORMAT, ##__VA_ARGS__) + +#if d_m3LogNativeStack +void m3StackCheckInit (); +void m3StackCheck (); +int m3StackGetMax (); +#else +#define m3StackCheckInit() +#define m3StackCheck() +#define m3StackGetMax() 0 +#endif + +#if d_m3LogTimestamps +#define PRIts "%llu" +uint64_t m3_GetTimestamp (); +#else +#define PRIts "%s" +#define m3_GetTimestamp() "" +#endif + +void m3_Abort (const char* message); +void * m3_Malloc_Impl (size_t i_size); +void * m3_Realloc_Impl (void * i_ptr, size_t i_newSize, size_t i_oldSize); +void m3_Free_Impl (void * i_ptr); +void * m3_CopyMem (const void * i_from, size_t i_size); + +#if d_m3LogHeapOps + +// Tracing format: timestamp;heap:OpCode;name;size(bytes);new items;new ptr;old items;old ptr + +static inline void * m3_AllocStruct_Impl(ccstr_t name, size_t i_size) { + void * result = m3_Malloc_Impl(i_size); + fprintf(stderr, PRIts ";heap:AllocStruct;%s;%zu;;%p;;\n", m3_GetTimestamp(), name, i_size, result); + return result; +} + +static inline void * m3_AllocArray_Impl(ccstr_t name, size_t i_num, size_t i_size) { + void * result = m3_Malloc_Impl(i_size * i_num); + fprintf(stderr, PRIts ";heap:AllocArr;%s;%zu;%zu;%p;;\n", m3_GetTimestamp(), name, i_size, i_num, result); + return result; +} + +static inline void * m3_ReallocArray_Impl(ccstr_t name, void * i_ptr_old, size_t i_num_new, size_t i_num_old, size_t i_size) { + void * result = m3_Realloc_Impl (i_ptr_old, i_size * i_num_new, i_size * i_num_old); + fprintf(stderr, PRIts ";heap:ReallocArr;%s;%zu;%zu;%p;%zu;%p\n", m3_GetTimestamp(), name, i_size, i_num_new, result, i_num_old, i_ptr_old); + return result; +} + +static inline void * m3_Malloc (ccstr_t name, size_t i_size) { + void * result = m3_Malloc_Impl (i_size); + fprintf(stderr, PRIts ";heap:AllocMem;%s;%zu;;%p;;\n", m3_GetTimestamp(), name, i_size, result); + return result; +} +static inline void * m3_Realloc (ccstr_t name, void * i_ptr, size_t i_newSize, size_t i_oldSize) { + void * result = m3_Realloc_Impl (i_ptr, i_newSize, i_oldSize); + fprintf(stderr, PRIts ";heap:ReallocMem;%s;;%zu;%p;%zu;%p\n", m3_GetTimestamp(), name, i_newSize, result, i_oldSize, i_ptr); + return result; +} + +#define m3_AllocStruct(STRUCT) (STRUCT *)m3_AllocStruct_Impl (#STRUCT, sizeof (STRUCT)) +#define m3_AllocArray(STRUCT, NUM) (STRUCT *)m3_AllocArray_Impl (#STRUCT, NUM, sizeof (STRUCT)) +#define m3_ReallocArray(STRUCT, PTR, NEW, OLD) (STRUCT *)m3_ReallocArray_Impl (#STRUCT, (void *)(PTR), (NEW), (OLD), sizeof (STRUCT)) +#define m3_Free(P) do { void* p = (void*)(P); \ + if (p) { fprintf(stderr, PRIts ";heap:FreeMem;;;;%p;\n", m3_GetTimestamp(), p); } \ + m3_Free_Impl (p); (P) = NULL; } while(0) +#else +#define m3_Malloc(NAME, SIZE) m3_Malloc_Impl(SIZE) +#define m3_Realloc(NAME, PTR, NEW, OLD) m3_Realloc_Impl(PTR, NEW, OLD) +#define m3_AllocStruct(STRUCT) (STRUCT *)m3_Malloc_Impl (sizeof (STRUCT)) +#define m3_AllocArray(STRUCT, NUM) (STRUCT *)m3_Malloc_Impl (sizeof (STRUCT) * (NUM)) +#define m3_ReallocArray(STRUCT, PTR, NEW, OLD) (STRUCT *)m3_Realloc_Impl ((void *)(PTR), sizeof (STRUCT) * (NEW), sizeof (STRUCT) * (OLD)) +#define m3_Free(P) do { m3_Free_Impl ((void*)(P)); (P) = NULL; } while(0) +#endif + +M3Result NormalizeType (u8 * o_type, i8 i_convolutedWasmType); + +bool IsIntType (u8 i_wasmType); +bool IsFpType (u8 i_wasmType); +bool Is64BitType (u8 i_m3Type); +u32 SizeOfType (u8 i_m3Type); + +M3Result Read_u64 (u64 * o_value, bytes_t * io_bytes, cbytes_t i_end); +M3Result Read_u32 (u32 * o_value, bytes_t * io_bytes, cbytes_t i_end); +#if d_m3ImplementFloat +M3Result Read_f64 (f64 * o_value, bytes_t * io_bytes, cbytes_t i_end); +M3Result Read_f32 (f32 * o_value, bytes_t * io_bytes, cbytes_t i_end); +#endif +M3Result Read_u8 (u8 * o_value, bytes_t * io_bytes, cbytes_t i_end); +M3Result Read_opcode (m3opcode_t * o_value, bytes_t * io_bytes, cbytes_t i_end); + +M3Result ReadLebUnsigned (u64 * o_value, u32 i_maxNumBits, bytes_t * io_bytes, cbytes_t i_end); +M3Result ReadLebSigned (i64 * o_value, u32 i_maxNumBits, bytes_t * io_bytes, cbytes_t i_end); +M3Result ReadLEB_u32 (u32 * o_value, bytes_t * io_bytes, cbytes_t i_end); +M3Result ReadLEB_u7 (u8 * o_value, bytes_t * io_bytes, cbytes_t i_end); +M3Result ReadLEB_i7 (i8 * o_value, bytes_t * io_bytes, cbytes_t i_end); +M3Result ReadLEB_i32 (i32 * o_value, bytes_t * io_bytes, cbytes_t i_end); +M3Result ReadLEB_i64 (i64 * o_value, bytes_t * io_bytes, cbytes_t i_end); +M3Result Read_utf8 (cstr_t * o_utf8, bytes_t * io_bytes, cbytes_t i_end); + +cstr_t SPrintValue (void * i_value, u8 i_type); +size_t SPrintArg (char * o_string, size_t i_stringBufferSize, voidptr_t i_sp, u8 i_type); + +void ReportError (IM3Runtime io_runtime, IM3Module i_module, IM3Function i_function, ccstr_t i_errorMessage, ccstr_t i_file, u32 i_lineNum); + +# if d_m3RecordBacktraces +void PushBacktraceFrame (IM3Runtime io_runtime, pc_t i_pc); +void FillBacktraceFunctionInfo (IM3Runtime io_runtime, IM3Function i_function); +void ClearBacktrace (IM3Runtime io_runtime); +# endif + +d_m3EndExternC + +#endif // m3_core_h diff --git a/ext/wasm3/source/m3_env.c b/ext/wasm3/source/m3_env.c new file mode 100644 index 0000000..2f678ed --- /dev/null +++ b/ext/wasm3/source/m3_env.c @@ -0,0 +1,1225 @@ +// +// m3_env.c +// +// Created by Steven Massey on 4/19/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#include +#include + +#include "m3_env.h" +#include "m3_compile.h" +#include "m3_exception.h" +#include "m3_info.h" + + +IM3Environment m3_NewEnvironment () +{ + IM3Environment env = m3_AllocStruct (M3Environment); + + if (env) + { + _try + { + // create FuncTypes for all simple block return ValueTypes + for (u8 t = c_m3Type_none; t <= c_m3Type_f64; t++) + { + IM3FuncType ftype; +_ (AllocFuncType (& ftype, 1)); + + ftype->numArgs = 0; + ftype->numRets = (t == c_m3Type_none) ? 0 : 1; + ftype->types [0] = t; + + Environment_AddFuncType (env, & ftype); + + d_m3Assert (t < 5); + env->retFuncTypes [t] = ftype; + } + } + + _catch: + if (result) + { + m3_FreeEnvironment (env); + env = NULL; + } + } + + return env; +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +//NOTE(martin): patched to allow controlling runtime memory externally +void m3_RuntimeSetMemoryCallbacks(IM3Runtime runtime, m3_resize_proc resizeCallback, m3_free_proc freeCallback, void* userData) +{ + runtime->resizeCallback = resizeCallback; + runtime->freeCallback = freeCallback; + runtime->memoryUserData = userData; +} +////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void Environment_Release (IM3Environment i_environment) +{ + IM3FuncType ftype = i_environment->funcTypes; + + while (ftype) + { + IM3FuncType next = ftype->next; + m3_Free (ftype); + ftype = next; + } + + m3log (runtime, "freeing %d pages from environment", CountCodePages (i_environment->pagesReleased)); + FreeCodePages (& i_environment->pagesReleased); +} + + +void m3_FreeEnvironment (IM3Environment i_environment) +{ + if (i_environment) + { + Environment_Release (i_environment); + m3_Free (i_environment); + } +} + + +void m3_SetCustomSectionHandler (IM3Environment i_environment, M3SectionHandler i_handler) +{ + if (i_environment) i_environment->customSectionHandler = i_handler; +} + + +// returns the same io_funcType or replaces it with an equivalent that's already in the type linked list +void Environment_AddFuncType (IM3Environment i_environment, IM3FuncType * io_funcType) +{ + IM3FuncType addType = * io_funcType; + IM3FuncType newType = i_environment->funcTypes; + + while (newType) + { + if (AreFuncTypesEqual (newType, addType)) + { + m3_Free (addType); + break; + } + + newType = newType->next; + } + + if (newType == NULL) + { + newType = addType; + newType->next = i_environment->funcTypes; + i_environment->funcTypes = newType; + } + + * io_funcType = newType; +} + + +IM3CodePage RemoveCodePageOfCapacity (M3CodePage ** io_list, u32 i_minimumLineCount) +{ + IM3CodePage prev = NULL; + IM3CodePage page = * io_list; + + while (page) + { + if (NumFreeLines (page) >= i_minimumLineCount) + { d_m3Assert (page->info.usageCount == 0); + IM3CodePage next = page->info.next; + if (prev) + prev->info.next = next; // mid-list + else + * io_list = next; // front of list + + break; + } + + prev = page; + page = page->info.next; + } + + return page; +} + + +IM3CodePage Environment_AcquireCodePage (IM3Environment i_environment, u32 i_minimumLineCount) +{ + return RemoveCodePageOfCapacity (& i_environment->pagesReleased, i_minimumLineCount); +} + + +void Environment_ReleaseCodePages (IM3Environment i_environment, IM3CodePage i_codePageList) +{ + IM3CodePage end = i_codePageList; + + while (end) + { + end->info.lineIndex = 0; // reset page +#if d_m3RecordBacktraces + end->info.mapping->size = 0; +#endif // d_m3RecordBacktraces + + IM3CodePage next = end->info.next; + if (not next) + break; + + end = next; + } + + if (end) + { + // push list to front + end->info.next = i_environment->pagesReleased; + i_environment->pagesReleased = i_codePageList; + } +} + + +IM3Runtime m3_NewRuntime (IM3Environment i_environment, u32 i_stackSizeInBytes, void * i_userdata) +{ + IM3Runtime runtime = m3_AllocStruct (M3Runtime); + + if (runtime) + { + m3_ResetErrorInfo(runtime); + + runtime->environment = i_environment; + runtime->userdata = i_userdata; + + runtime->stack = m3_Malloc ("Wasm Stack", i_stackSizeInBytes + 4*sizeof (m3slot_t)); // TODO: more precise stack checks + + if (runtime->stack) + { + runtime->numStackSlots = i_stackSizeInBytes / sizeof (m3slot_t); m3log (runtime, "new stack: %p", runtime->stack); + } + else m3_Free (runtime); + } + + return runtime; +} + +void * m3_GetUserData (IM3Runtime i_runtime) +{ + return i_runtime ? i_runtime->userdata : NULL; +} + + +void * ForEachModule (IM3Runtime i_runtime, ModuleVisitor i_visitor, void * i_info) +{ + void * r = NULL; + + IM3Module module = i_runtime->modules; + + while (module) + { + IM3Module next = module->next; + r = i_visitor (module, i_info); + if (r) + break; + + module = next; + } + + return r; +} + + +void * _FreeModule (IM3Module i_module, void * i_info) +{ + m3_FreeModule (i_module); + return NULL; +} + + +void Runtime_Release (IM3Runtime i_runtime) +{ + ForEachModule (i_runtime, _FreeModule, NULL); d_m3Assert (i_runtime->numActiveCodePages == 0); + + Environment_ReleaseCodePages (i_runtime->environment, i_runtime->pagesOpen); + Environment_ReleaseCodePages (i_runtime->environment, i_runtime->pagesFull); + + m3_Free (i_runtime->stack); + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +//NOTE(martin): patched to allow controlling runtime memory externally +#if 0 + m3_Free (i_runtime->memory.mallocated); +#else + if(i_runtime->freeCallback) + { + i_runtime->freeCallback(i_runtime->memory.mallocated, i_runtime->memoryUserData); + } + else + { + m3_Free(i_runtime->memory.mallocated); + } +#endif +////////////////////////////////////////////////////////////////////////////////////////////////////////// +} + + +void m3_FreeRuntime (IM3Runtime i_runtime) +{ + if (i_runtime) + { + m3_PrintProfilerInfo (); + + Runtime_Release (i_runtime); + m3_Free (i_runtime); + } +} + +M3Result EvaluateExpression (IM3Module i_module, void * o_expressed, u8 i_type, bytes_t * io_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + // OPTZ: use a simplified interpreter for expressions + + // create a temporary runtime context +#if defined(d_m3PreferStaticAlloc) + static M3Runtime runtime; +#else + M3Runtime runtime; +#endif + M3_INIT (runtime); + + runtime.environment = i_module->runtime->environment; + runtime.numStackSlots = i_module->runtime->numStackSlots; + runtime.stack = i_module->runtime->stack; + + m3stack_t stack = (m3stack_t)runtime.stack; + + IM3Runtime savedRuntime = i_module->runtime; + i_module->runtime = & runtime; + + IM3Compilation o = & runtime.compilation; + o->runtime = & runtime; + o->module = i_module; + o->wasm = * io_bytes; + o->wasmEnd = i_end; + o->lastOpcodeStart = o->wasm; + + o->block.depth = -1; // so that root compilation depth = 0 + + // OPTZ: this code page could be erased after use. maybe have 'empty' list in addition to full and open? + o->page = AcquireCodePage (& runtime); // AcquireUnusedCodePage (...) + + if (o->page) + { + IM3FuncType ftype = runtime.environment->retFuncTypes[i_type]; + + pc_t m3code = GetPagePC (o->page); + result = CompileBlock (o, ftype, c_waOp_block); + + if (not result && o->maxStackSlots >= runtime.numStackSlots) { + result = m3Err_trapStackOverflow; + } + + if (not result) + { + m3ret_t r = RunCode (m3code, stack, NULL, d_m3OpDefaultArgs); + + if (r == 0) + { m3log (runtime, "expression result: %s", SPrintValue (stack, i_type)); + if (SizeOfType (i_type) == sizeof (u32)) + { + * (u32 *) o_expressed = * ((u32 *) stack); + } + else + { + * (u64 *) o_expressed = * ((u64 *) stack); + } + } + } + + // TODO: EraseCodePage (...) see OPTZ above + ReleaseCodePage (& runtime, o->page); + } + else result = m3Err_mallocFailedCodePage; + + runtime.stack = NULL; // prevent free(stack) in ReleaseRuntime + Runtime_Release (& runtime); + i_module->runtime = savedRuntime; + + * io_bytes = o->wasm; + + return result; +} + + +M3Result InitMemory (IM3Runtime io_runtime, IM3Module i_module) +{ + M3Result result = m3Err_none; //d_m3Assert (not io_runtime->memory.wasmPages); + + if (not i_module->memoryImported) + { + u32 maxPages = i_module->memoryInfo.maxPages; + io_runtime->memory.maxPages = maxPages ? maxPages : 65536; + + result = ResizeMemory (io_runtime, i_module->memoryInfo.initPages); + } + + return result; +} + + +M3Result ResizeMemory (IM3Runtime io_runtime, u32 i_numPages) +{ + M3Result result = m3Err_none; + + u32 numPagesToAlloc = i_numPages; + + M3Memory * memory = & io_runtime->memory; + +#if 0 // Temporary fix for memory allocation + if (memory->mallocated) { + memory->numPages = i_numPages; + memory->mallocated->end = memory->wasmPages + (memory->numPages * c_m3MemPageSize); + return result; + } + + i_numPagesToAlloc = 256; +#endif + + if (numPagesToAlloc <= memory->maxPages) + { + size_t numPageBytes = numPagesToAlloc * d_m3MemPageSize; + +#if d_m3MaxLinearMemoryPages > 0 + _throwif("linear memory limitation exceeded", numPagesToAlloc > d_m3MaxLinearMemoryPages); +#endif + + // Limit the amount of memory that gets actually allocated + if (io_runtime->memoryLimit) { + numPageBytes = M3_MIN (numPageBytes, io_runtime->memoryLimit); + } + + size_t numBytes = numPageBytes + sizeof (M3MemoryHeader); + + size_t numPreviousBytes = memory->numPages * d_m3MemPageSize; + if (numPreviousBytes) + numPreviousBytes += sizeof (M3MemoryHeader); + +////////////////////////////////////////////////////////////////////////////////////////////////////////// +//NOTE(martin): patched to allow controlling runtime memory externally +#if 0 + void* newMem = m3_Realloc ("Wasm Linear Memory", memory->mallocated, numBytes, numPreviousBytes); +#else + void* newMem = 0; + if(io_runtime->resizeCallback) + { + newMem = io_runtime->resizeCallback(memory->mallocated, numBytes, io_runtime->memoryUserData); + + #if d_m3LogHeapOps + fprintf(stderr, + PRIts ";heap:ReallocMem;%s;;%zu;%p;%zu;%p\n", + m3_GetTimestamp(), + "Wasm Linear Memory", + numBytes, + newMem, + numPreviousBytes, + memory->mallocated); + #endif + } + else + { + newMem = m3_Realloc ("Wasm Linear Memory", memory->mallocated, numBytes, numPreviousBytes); + } +#endif +////////////////////////////////////////////////////////////////////////////////////////////////////////// + _throwifnull(newMem); + + + memory->mallocated = (M3MemoryHeader*)newMem; + +# if d_m3LogRuntime + M3MemoryHeader * oldMallocated = memory->mallocated; +# endif + + memory->numPages = numPagesToAlloc; + + memory->mallocated->length = numPageBytes; + memory->mallocated->runtime = io_runtime; + + memory->mallocated->maxStack = (m3slot_t *) io_runtime->stack + io_runtime->numStackSlots; + + m3log (runtime, "resized old: %p; mem: %p; length: %zu; pages: %d", oldMallocated, memory->mallocated, memory->mallocated->length, memory->numPages); + } + else result = m3Err_wasmMemoryOverflow; + + _catch: return result; +} + + +M3Result InitGlobals (IM3Module io_module) +{ + M3Result result = m3Err_none; + + if (io_module->numGlobals) + { + // placing the globals in their structs isn't good for cache locality, but i don't really know what the global + // access patterns typically look like yet. + + // io_module->globalMemory = m3Alloc (m3reg_t, io_module->numGlobals); + + // if (io_module->globalMemory) + { + for (u32 i = 0; i < io_module->numGlobals; ++i) + { + M3Global * g = & io_module->globals [i]; m3log (runtime, "initializing global: %d", i); + + if (g->initExpr) + { + bytes_t start = g->initExpr; + result = EvaluateExpression (io_module, & g->intValue, g->type, & start, g->initExpr + g->initExprSize); + + if (not result) + { + // io_module->globalMemory [i] = initValue; + } + else break; + } + else + { m3log (runtime, "importing global"); + + } + } + } + // else result = ErrorModule (m3Err_mallocFailed, io_module, "could allocate globals for module: '%s", io_module->name); + } + + return result; +} + + +M3Result InitDataSegments (M3Memory * io_memory, IM3Module io_module) +{ + M3Result result = m3Err_none; + + _throwif ("unallocated linear memory", !(io_memory->mallocated)); + + for (u32 i = 0; i < io_module->numDataSegments; ++i) + { + M3DataSegment * segment = & io_module->dataSegments [i]; + + i32 segmentOffset; + bytes_t start = segment->initExpr; +_ (EvaluateExpression (io_module, & segmentOffset, c_m3Type_i32, & start, segment->initExpr + segment->initExprSize)); + + m3log (runtime, "loading data segment: %d; size: %d; offset: %d", i, segment->size, segmentOffset); + + if (segmentOffset >= 0 && (size_t)(segmentOffset) + segment->size <= io_memory->mallocated->length) + { + u8 * dest = m3MemData (io_memory->mallocated) + segmentOffset; + memcpy (dest, segment->data, segment->size); + } else { + _throw ("data segment out of bounds"); + } + } + + _catch: return result; +} + + +M3Result InitElements (IM3Module io_module) +{ + M3Result result = m3Err_none; + + bytes_t bytes = io_module->elementSection; + cbytes_t end = io_module->elementSectionEnd; + + for (u32 i = 0; i < io_module->numElementSegments; ++i) + { + u32 index; +_ (ReadLEB_u32 (& index, & bytes, end)); + + if (index == 0) + { + i32 offset; +_ (EvaluateExpression (io_module, & offset, c_m3Type_i32, & bytes, end)); + _throwif ("table underflow", offset < 0); + + u32 numElements; +_ (ReadLEB_u32 (& numElements, & bytes, end)); + + size_t endElement = (size_t) numElements + offset; + _throwif ("table overflow", endElement > d_m3MaxSaneTableSize); + + // is there any requirement that elements must be in increasing sequence? + // make sure the table isn't shrunk. + if (endElement > io_module->table0Size) + { + io_module->table0 = m3_ReallocArray (IM3Function, io_module->table0, endElement, io_module->table0Size); + io_module->table0Size = (u32) endElement; + } + _throwifnull(io_module->table0); + + for (u32 e = 0; e < numElements; ++e) + { + u32 functionIndex; +_ (ReadLEB_u32 (& functionIndex, & bytes, end)); + _throwif ("function index out of range", functionIndex >= io_module->numFunctions); + IM3Function function = & io_module->functions [functionIndex]; d_m3Assert (function); //printf ("table: %s\n", m3_GetFunctionName(function)); + io_module->table0 [e + offset] = function; + } + } + else _throw ("element table index must be zero for MVP"); + } + + _catch: return result; +} + +M3Result m3_CompileModule (IM3Module io_module) +{ + M3Result result = m3Err_none; + + for (u32 i = 0; i < io_module->numFunctions; ++i) + { + IM3Function f = & io_module->functions [i]; + if (f->wasm and not f->compiled) + { +_ (CompileFunction (f)); + } + } + + _catch: return result; +} + +M3Result m3_RunStart (IM3Module io_module) +{ +#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION + // Execution disabled for fuzzing builds + return m3Err_none; +#endif + + M3Result result = m3Err_none; + i32 startFunctionTmp = -1; + + if (io_module and io_module->startFunction >= 0) + { + IM3Function function = & io_module->functions [io_module->startFunction]; + + if (not function->compiled) + { +_ (CompileFunction (function)); + } + + IM3FuncType ftype = function->funcType; + if (ftype->numArgs != 0 || ftype->numRets != 0) + _throw (m3Err_argumentCountMismatch); + + IM3Module module = function->module; + IM3Runtime runtime = module->runtime; + + startFunctionTmp = io_module->startFunction; + io_module->startFunction = -1; + + result = (M3Result) RunCode (function->compiled, (m3stack_t) runtime->stack, runtime->memory.mallocated, d_m3OpDefaultArgs); + + if (result) + { + io_module->startFunction = startFunctionTmp; + EXCEPTION_PRINT(result); + goto _catch; + } + } + + _catch: return result; +} + +// TODO: deal with main + side-modules loading efforcement +M3Result m3_LoadModule (IM3Runtime io_runtime, IM3Module io_module) +{ + M3Result result = m3Err_none; + + if (M3_UNLIKELY(io_module->runtime)) { + return m3Err_moduleAlreadyLinked; + } + + io_module->runtime = io_runtime; + M3Memory * memory = & io_runtime->memory; + +_ (InitMemory (io_runtime, io_module)); +_ (InitGlobals (io_module)); +_ (InitDataSegments (memory, io_module)); +_ (InitElements (io_module)); + + // Start func might use imported functions, which are not liked here yet, + // so it will be called before a function call is attempted (in m3_FindFunction) + +#ifdef DEBUG + Module_GenerateNames(io_module); +#endif + + io_module->next = io_runtime->modules; + io_runtime->modules = io_module; + return result; // ok + +_catch: + io_module->runtime = NULL; + return result; +} + +IM3Global m3_FindGlobal (IM3Module io_module, + const char * const i_globalName) +{ + // Search exports + for (u32 i = 0; i < io_module->numGlobals; ++i) + { + IM3Global g = & io_module->globals [i]; + if (g->name and strcmp (g->name, i_globalName) == 0) + { + return g; + } + } + + // Search imports + for (u32 i = 0; i < io_module->numGlobals; ++i) + { + IM3Global g = & io_module->globals [i]; + + if (g->import.moduleUtf8 and g->import.fieldUtf8) + { + if (strcmp (g->import.fieldUtf8, i_globalName) == 0) + { + return g; + } + } + } + return NULL; +} + +M3Result m3_GetGlobal (IM3Global i_global, + IM3TaggedValue o_value) +{ + if (not i_global) return m3Err_globalLookupFailed; + + switch (i_global->type) { + case c_m3Type_i32: o_value->value.i32 = i_global->intValue; break; + case c_m3Type_i64: o_value->value.i64 = i_global->intValue; break; +# if d_m3HasFloat + case c_m3Type_f32: o_value->value.f32 = i_global->f32Value; break; + case c_m3Type_f64: o_value->value.f64 = i_global->f64Value; break; +# endif + default: return m3Err_invalidTypeId; + } + + o_value->type = (M3ValueType)(i_global->type); + return m3Err_none; +} + +M3Result m3_SetGlobal (IM3Global i_global, + const IM3TaggedValue i_value) +{ + if (not i_global) return m3Err_globalLookupFailed; + // TODO: if (not g->isMutable) return m3Err_globalNotMutable; + + if (i_global->type != i_value->type) return m3Err_globalTypeMismatch; + + switch (i_value->type) { + case c_m3Type_i32: i_global->intValue = i_value->value.i32; break; + case c_m3Type_i64: i_global->intValue = i_value->value.i64; break; +# if d_m3HasFloat + case c_m3Type_f32: i_global->f32Value = i_value->value.f32; break; + case c_m3Type_f64: i_global->f64Value = i_value->value.f64; break; +# endif + default: return m3Err_invalidTypeId; + } + + return m3Err_none; +} + +M3ValueType m3_GetGlobalType (IM3Global i_global) +{ + return (i_global) ? (M3ValueType)(i_global->type) : c_m3Type_none; +} + + +void * v_FindFunction (IM3Module i_module, const char * const i_name) +{ + for (u32 i = 0; i < i_module->numFunctions; ++i) + { + IM3Function f = & i_module->functions [i]; + + bool isImported = f->import.moduleUtf8 or f->import.fieldUtf8; + + if (isImported) + continue; + + for (int j = 0; j < f->numNames; j++) + { + if (f->names [j] and strcmp (f->names [j], i_name) == 0) + return f; + } + } + + return NULL; +} + + +M3Result m3_FindFunction (IM3Function * o_function, IM3Runtime i_runtime, const char * const i_functionName) +{ + M3Result result = m3Err_none; d_m3Assert (o_function and i_runtime and i_functionName); + + IM3Function function = NULL; + + if (not i_runtime->modules) { + _throw ("no modules loaded"); + } + + function = (IM3Function) ForEachModule (i_runtime, (ModuleVisitor) v_FindFunction, (void *) i_functionName); + + if (function) + { + if (not function->compiled) + { +_ (CompileFunction (function)) + } + } + else _throw (ErrorModule (m3Err_functionLookupFailed, i_runtime->modules, "'%s'", i_functionName)); + + _catch: + if (result) + function = NULL; + + * o_function = function; + + return result; +} + +static +M3Result checkStartFunction(IM3Module i_module) +{ + M3Result result = m3Err_none; d_m3Assert(i_module); + + // Check if start function needs to be called + if (i_module->startFunction >= 0) + { + result = m3_RunStart (i_module); + } + + return result; +} + +uint32_t m3_GetArgCount (IM3Function i_function) +{ + if (i_function) { + IM3FuncType ft = i_function->funcType; + if (ft) { + return ft->numArgs; + } + } + return 0; +} + +uint32_t m3_GetRetCount (IM3Function i_function) +{ + if (i_function) { + IM3FuncType ft = i_function->funcType; + if (ft) { + return ft->numRets; + } + } + return 0; +} + + +M3ValueType m3_GetArgType (IM3Function i_function, uint32_t index) +{ + if (i_function) { + IM3FuncType ft = i_function->funcType; + if (ft and index < ft->numArgs) { + return (M3ValueType)d_FuncArgType(ft, index); + } + } + return c_m3Type_none; +} + +M3ValueType m3_GetRetType (IM3Function i_function, uint32_t index) +{ + if (i_function) { + IM3FuncType ft = i_function->funcType; + if (ft and index < ft->numRets) { + return (M3ValueType) d_FuncRetType (ft, index); + } + } + return c_m3Type_none; +} + + +u8 * GetStackPointerForArgs (IM3Function i_function) +{ + u64 * stack = (u64 *) i_function->module->runtime->stack; + IM3FuncType ftype = i_function->funcType; + + stack += ftype->numRets; + + return (u8 *) stack; +} + + +M3Result m3_CallV (IM3Function i_function, ...) +{ + va_list ap; + va_start(ap, i_function); + M3Result r = m3_CallVL(i_function, ap); + va_end(ap); + return r; +} + +static +void ReportNativeStackUsage () +{ +# if d_m3LogNativeStack + int stackUsed = m3StackGetMax(); + fprintf (stderr, "Native stack used: %d\n", stackUsed); +# endif +} + + +M3Result m3_CallVL (IM3Function i_function, va_list i_args) +{ + IM3Runtime runtime = i_function->module->runtime; + IM3FuncType ftype = i_function->funcType; + M3Result result = m3Err_none; + + if (!i_function->compiled) { + return m3Err_missingCompiledCode; + } + +# if d_m3RecordBacktraces + ClearBacktrace (runtime); +# endif + + u8* s = GetStackPointerForArgs (i_function); + + for (u32 i = 0; i < ftype->numArgs; ++i) + { + switch (d_FuncArgType(ftype, i)) { + case c_m3Type_i32: *(i32*)(s) = va_arg(i_args, i32); s += 8; break; + case c_m3Type_i64: *(i64*)(s) = va_arg(i_args, i64); s += 8; break; +# if d_m3HasFloat + case c_m3Type_f32: *(f32*)(s) = va_arg(i_args, f64); s += 8; break; // f32 is passed as f64 + case c_m3Type_f64: *(f64*)(s) = va_arg(i_args, f64); s += 8; break; +# endif + default: return "unknown argument type"; + } + } + m3StackCheckInit(); + +_ (checkStartFunction(i_function->module)) + + result = (M3Result) RunCode (i_function->compiled, (m3stack_t)(runtime->stack), runtime->memory.mallocated, d_m3OpDefaultArgs); + ReportNativeStackUsage (); + + runtime->lastCalled = result ? NULL : i_function; + + _catch: return result; +} + +M3Result m3_Call (IM3Function i_function, uint32_t i_argc, const void * i_argptrs[]) +{ + IM3Runtime runtime = i_function->module->runtime; + IM3FuncType ftype = i_function->funcType; + M3Result result = m3Err_none; + + if (i_argc != ftype->numArgs) { + return m3Err_argumentCountMismatch; + } + if (!i_function->compiled) { + return m3Err_missingCompiledCode; + } + +# if d_m3RecordBacktraces + ClearBacktrace (runtime); +# endif + + u8* s = GetStackPointerForArgs (i_function); + + for (u32 i = 0; i < ftype->numArgs; ++i) + { + switch (d_FuncArgType(ftype, i)) { + case c_m3Type_i32: *(i32*)(s) = *(i32*)i_argptrs[i]; s += 8; break; + case c_m3Type_i64: *(i64*)(s) = *(i64*)i_argptrs[i]; s += 8; break; +# if d_m3HasFloat + case c_m3Type_f32: *(f32*)(s) = *(f32*)i_argptrs[i]; s += 8; break; + case c_m3Type_f64: *(f64*)(s) = *(f64*)i_argptrs[i]; s += 8; break; +# endif + default: return "unknown argument type"; + } + } + + m3StackCheckInit(); + +_ (checkStartFunction(i_function->module)) + + result = (M3Result) RunCode (i_function->compiled, (m3stack_t)(runtime->stack), runtime->memory.mallocated, d_m3OpDefaultArgs); + ReportNativeStackUsage (); + + runtime->lastCalled = result ? NULL : i_function; + + _catch: return result; +} + +M3Result m3_CallArgv (IM3Function i_function, uint32_t i_argc, const char * i_argv[]) +{ + IM3FuncType ftype = i_function->funcType; + IM3Runtime runtime = i_function->module->runtime; + M3Result result = m3Err_none; + + if (i_argc != ftype->numArgs) { + return m3Err_argumentCountMismatch; + } + if (!i_function->compiled) { + return m3Err_missingCompiledCode; + } + +# if d_m3RecordBacktraces + ClearBacktrace (runtime); +# endif + + u8* s = GetStackPointerForArgs (i_function); + + for (u32 i = 0; i < ftype->numArgs; ++i) + { + switch (d_FuncArgType(ftype, i)) { + case c_m3Type_i32: *(i32*)(s) = strtoul(i_argv[i], NULL, 10); s += 8; break; + case c_m3Type_i64: *(i64*)(s) = strtoull(i_argv[i], NULL, 10); s += 8; break; +# if d_m3HasFloat + case c_m3Type_f32: *(f32*)(s) = strtod(i_argv[i], NULL); s += 8; break; // strtof would be less portable + case c_m3Type_f64: *(f64*)(s) = strtod(i_argv[i], NULL); s += 8; break; +# endif + default: return "unknown argument type"; + } + } + + m3StackCheckInit(); + +_ (checkStartFunction(i_function->module)) + + result = (M3Result) RunCode (i_function->compiled, (m3stack_t)(runtime->stack), runtime->memory.mallocated, d_m3OpDefaultArgs); + ReportNativeStackUsage (); + + runtime->lastCalled = result ? NULL : i_function; + + _catch: return result; +} + + +//u8 * AlignStackPointerTo64Bits (const u8 * i_stack) +//{ +// uintptr_t ptr = (uintptr_t) i_stack; +// return (u8 *) ((ptr + 7) & ~7); +//} + + +M3Result m3_GetResults (IM3Function i_function, uint32_t i_retc, const void * o_retptrs[]) +{ + IM3FuncType ftype = i_function->funcType; + IM3Runtime runtime = i_function->module->runtime; + + if (i_retc != ftype->numRets) { + return m3Err_argumentCountMismatch; + } + if (i_function != runtime->lastCalled) { + return "function not called"; + } + + u8* s = (u8*) runtime->stack; + + for (u32 i = 0; i < ftype->numRets; ++i) + { + switch (d_FuncRetType(ftype, i)) { + case c_m3Type_i32: *(i32*)o_retptrs[i] = *(i32*)(s); s += 8; break; + case c_m3Type_i64: *(i64*)o_retptrs[i] = *(i64*)(s); s += 8; break; +# if d_m3HasFloat + case c_m3Type_f32: *(f32*)o_retptrs[i] = *(f32*)(s); s += 8; break; + case c_m3Type_f64: *(f64*)o_retptrs[i] = *(f64*)(s); s += 8; break; +# endif + default: return "unknown return type"; + } + } + return m3Err_none; +} + +M3Result m3_GetResultsV (IM3Function i_function, ...) +{ + va_list ap; + va_start(ap, i_function); + M3Result r = m3_GetResultsVL(i_function, ap); + va_end(ap); + return r; +} + +M3Result m3_GetResultsVL (IM3Function i_function, va_list o_rets) +{ + IM3Runtime runtime = i_function->module->runtime; + IM3FuncType ftype = i_function->funcType; + + if (i_function != runtime->lastCalled) { + return "function not called"; + } + + u8* s = (u8*) runtime->stack; + for (u32 i = 0; i < ftype->numRets; ++i) + { + switch (d_FuncRetType(ftype, i)) { + case c_m3Type_i32: *va_arg(o_rets, i32*) = *(i32*)(s); s += 8; break; + case c_m3Type_i64: *va_arg(o_rets, i64*) = *(i64*)(s); s += 8; break; +# if d_m3HasFloat + case c_m3Type_f32: *va_arg(o_rets, f32*) = *(f32*)(s); s += 8; break; + case c_m3Type_f64: *va_arg(o_rets, f64*) = *(f64*)(s); s += 8; break; +# endif + default: return "unknown argument type"; + } + } + return m3Err_none; +} + +void ReleaseCodePageNoTrack (IM3Runtime i_runtime, IM3CodePage i_codePage) +{ + if (i_codePage) + { + IM3CodePage * list; + + bool pageFull = (NumFreeLines (i_codePage) < d_m3CodePageFreeLinesThreshold); + if (pageFull) + list = & i_runtime->pagesFull; + else + list = & i_runtime->pagesOpen; + + PushCodePage (list, i_codePage); m3log (emit, "release page: %d to queue: '%s'", i_codePage->info.sequence, pageFull ? "full" : "open") + } +} + + +IM3CodePage AcquireCodePageWithCapacity (IM3Runtime i_runtime, u32 i_minLineCount) +{ + IM3CodePage page = RemoveCodePageOfCapacity (& i_runtime->pagesOpen, i_minLineCount); + + if (not page) + { + page = Environment_AcquireCodePage (i_runtime->environment, i_minLineCount); + + if (not page) + page = NewCodePage (i_runtime, i_minLineCount); + + if (page) + i_runtime->numCodePages++; + } + + if (page) + { m3log (emit, "acquire page: %d", page->info.sequence); + i_runtime->numActiveCodePages++; + } + + return page; +} + + +IM3CodePage AcquireCodePage (IM3Runtime i_runtime) +{ + return AcquireCodePageWithCapacity (i_runtime, d_m3CodePageFreeLinesThreshold); +} + + +void ReleaseCodePage (IM3Runtime i_runtime, IM3CodePage i_codePage) +{ + if (i_codePage) + { + ReleaseCodePageNoTrack (i_runtime, i_codePage); + i_runtime->numActiveCodePages--; + +# if defined (DEBUG) + u32 numOpen = CountCodePages (i_runtime->pagesOpen); + u32 numFull = CountCodePages (i_runtime->pagesFull); + + m3log (runtime, "runtime: %p; open-pages: %d; full-pages: %d; active: %d; total: %d", i_runtime, numOpen, numFull, i_runtime->numActiveCodePages, i_runtime->numCodePages); + + d_m3Assert (numOpen + numFull + i_runtime->numActiveCodePages == i_runtime->numCodePages); + +# if d_m3LogCodePages + dump_code_page (i_codePage, /* startPC: */ NULL); +# endif +# endif + } +} + + +#if d_m3VerboseErrorMessages +M3Result m3Error (M3Result i_result, IM3Runtime i_runtime, IM3Module i_module, IM3Function i_function, + const char * const i_file, u32 i_lineNum, const char * const i_errorMessage, ...) +{ + if (i_runtime) + { + i_runtime->error = (M3ErrorInfo){ .result = i_result, .runtime = i_runtime, .module = i_module, + .function = i_function, .file = i_file, .line = i_lineNum }; + i_runtime->error.message = i_runtime->error_message; + + va_list args; + va_start (args, i_errorMessage); + vsnprintf (i_runtime->error_message, sizeof(i_runtime->error_message), i_errorMessage, args); + va_end (args); + } + + return i_result; +} +#endif + + +void m3_GetErrorInfo (IM3Runtime i_runtime, M3ErrorInfo* o_info) +{ + if (i_runtime) + { + *o_info = i_runtime->error; + m3_ResetErrorInfo (i_runtime); + } +} + + +void m3_ResetErrorInfo (IM3Runtime i_runtime) +{ + if (i_runtime) + { + M3_INIT(i_runtime->error); + i_runtime->error.message = ""; + } +} + +uint8_t * m3_GetMemory (IM3Runtime i_runtime, uint32_t * o_memorySizeInBytes, uint32_t i_memoryIndex) +{ + uint8_t * memory = NULL; d_m3Assert (i_memoryIndex == 0); + + if (i_runtime) + { + u32 size = (u32) i_runtime->memory.mallocated->length; + + if (o_memorySizeInBytes) + * o_memorySizeInBytes = size; + + if (size) + memory = m3MemData (i_runtime->memory.mallocated); + } + + return memory; +} + + +uint32_t m3_GetMemorySize (IM3Runtime i_runtime) +{ + return i_runtime->memory.mallocated->length; +} + + +M3BacktraceInfo * m3_GetBacktrace (IM3Runtime i_runtime) +{ +# if d_m3RecordBacktraces + return & i_runtime->backtrace; +# else + return NULL; +# endif +} diff --git a/ext/wasm3/source/m3_env.h b/ext/wasm3/source/m3_env.h new file mode 100644 index 0000000..453d593 --- /dev/null +++ b/ext/wasm3/source/m3_env.h @@ -0,0 +1,219 @@ +// +// m3_env.h +// +// Created by Steven Massey on 4/19/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#ifndef m3_env_h +#define m3_env_h + +#include "wasm3.h" +#include "m3_code.h" +#include "m3_compile.h" + +d_m3BeginExternC + + +//--------------------------------------------------------------------------------------------------------------------------------- + +typedef struct M3MemoryInfo +{ + u32 initPages; + u32 maxPages; +} +M3MemoryInfo; + + +typedef struct M3Memory +{ + M3MemoryHeader * mallocated; + + u32 numPages; + u32 maxPages; +} +M3Memory; + +typedef M3Memory * IM3Memory; + + +//--------------------------------------------------------------------------------------------------------------------------------- + +typedef struct M3DataSegment +{ + const u8 * initExpr; // wasm code + const u8 * data; + + u32 initExprSize; + u32 memoryRegion; + u32 size; +} +M3DataSegment; + +//--------------------------------------------------------------------------------------------------------------------------------- + +typedef struct M3Global +{ + M3ImportInfo import; + + union + { + i64 intValue; +#if d_m3HasFloat + f64 f64Value; + f32 f32Value; +#endif + }; + + cstr_t name; + bytes_t initExpr; // wasm code + u32 initExprSize; + u8 type; + bool imported; + bool isMutable; +} +M3Global; + + +//--------------------------------------------------------------------------------------------------------------------------------- +typedef struct M3Module +{ + struct M3Runtime * runtime; + struct M3Environment * environment; + + bytes_t wasmStart; + bytes_t wasmEnd; + + cstr_t name; + + u32 numFuncTypes; + IM3FuncType * funcTypes; // array of pointers to list of FuncTypes + + u32 numFuncImports; + u32 numFunctions; + u32 allFunctions; // allocated functions count + M3Function * functions; + + i32 startFunction; + + u32 numDataSegments; + M3DataSegment * dataSegments; + + //u32 importedGlobals; + u32 numGlobals; + M3Global * globals; + + u32 numElementSegments; + bytes_t elementSection; + bytes_t elementSectionEnd; + + IM3Function * table0; + u32 table0Size; + + M3MemoryInfo memoryInfo; + bool memoryImported; + + //bool hasWasmCodeCopy; + + struct M3Module * next; +} +M3Module; + +M3Result Module_AddGlobal (IM3Module io_module, IM3Global * o_global, u8 i_type, bool i_mutable, bool i_isImported); + +M3Result Module_PreallocFunctions (IM3Module io_module, u32 i_totalFunctions); +M3Result Module_AddFunction (IM3Module io_module, u32 i_typeIndex, IM3ImportInfo i_importInfo /* can be null */); +IM3Function Module_GetFunction (IM3Module i_module, u32 i_functionIndex); + +void Module_GenerateNames (IM3Module i_module); + +void FreeImportInfo (M3ImportInfo * i_info); + +//--------------------------------------------------------------------------------------------------------------------------------- + +typedef struct M3Environment +{ +// struct M3Runtime * runtimes; + + IM3FuncType funcTypes; // linked list of unique M3FuncType structs that can be compared using pointer-equivalence + + IM3FuncType retFuncTypes [c_m3Type_unknown]; // these 'point' to elements in the linked list above. + // the number of elements must match the basic types as per M3ValueType + M3CodePage * pagesReleased; + + M3SectionHandler customSectionHandler; +} +M3Environment; + +void Environment_Release (IM3Environment i_environment); + +// takes ownership of io_funcType and returns a pointer to the persistent version (could be same or different) +void Environment_AddFuncType (IM3Environment i_environment, IM3FuncType * io_funcType); + +//--------------------------------------------------------------------------------------------------------------------------------- + +typedef struct M3Runtime +{ + M3Compilation compilation; + + IM3Environment environment; + + M3CodePage * pagesOpen; // linked list of code pages with writable space on them + M3CodePage * pagesFull; // linked list of at-capacity pages + + u32 numCodePages; + u32 numActiveCodePages; + + IM3Module modules; // linked list of imported modules + + void * stack; + u32 stackSize; + u32 numStackSlots; + IM3Function lastCalled; // last function that successfully executed + + void * userdata; + + M3Memory memory; + u32 memoryLimit; + +#if d_m3EnableStrace >= 2 + u32 callDepth; +#endif + + M3ErrorInfo error; +#if d_m3VerboseErrorMessages + char error_message[256]; // the actual buffer. M3ErrorInfo can point to this +#endif + +#if d_m3RecordBacktraces + M3BacktraceInfo backtrace; +#endif + + u32 newCodePageSequence; + +/////////////////////////////////////////////////////////////////////////////////////////// +//NOTE(Martin): allow controlling memory resize +/////////////////////////////////////////////////////////////////////////////////////////// + m3_resize_proc resizeCallback; + m3_free_proc freeCallback; + void* memoryUserData; +} +M3Runtime; + +void InitRuntime (IM3Runtime io_runtime, u32 i_stackSizeInBytes); +void Runtime_Release (IM3Runtime io_runtime); + +M3Result ResizeMemory (IM3Runtime io_runtime, u32 i_numPages); + +typedef void * (* ModuleVisitor) (IM3Module i_module, void * i_info); +void * ForEachModule (IM3Runtime i_runtime, ModuleVisitor i_visitor, void * i_info); + +void * v_FindFunction (IM3Module i_module, const char * const i_name); + +IM3CodePage AcquireCodePage (IM3Runtime io_runtime); +IM3CodePage AcquireCodePageWithCapacity (IM3Runtime io_runtime, u32 i_lineCount); +void ReleaseCodePage (IM3Runtime io_runtime, IM3CodePage i_codePage); + +d_m3EndExternC + +#endif // m3_env_h diff --git a/ext/wasm3/source/m3_exception.h b/ext/wasm3/source/m3_exception.h new file mode 100644 index 0000000..258f6f3 --- /dev/null +++ b/ext/wasm3/source/m3_exception.h @@ -0,0 +1,33 @@ +// +// m3_exception.h +// +// Created by Steven Massey on 7/5/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// +// some macros to emulate try/catch + +#ifndef m3_exception_h +#define m3_exception_h + +#include "m3_config.h" + +# if d_m3EnableExceptionBreakpoint + +// declared in m3_info.c +void ExceptionBreakpoint (cstr_t i_exception, cstr_t i_message); + +# define EXCEPTION_PRINT(ERROR) ExceptionBreakpoint (ERROR, (__FILE__ ":" M3_STR(__LINE__))) + +# else +# define EXCEPTION_PRINT(...) +# endif + + +#define _try M3Result result = m3Err_none; +#define _(TRY) { result = TRY; if (M3_UNLIKELY(result)) { EXCEPTION_PRINT (result); goto _catch; } } +#define _throw(ERROR) { result = ERROR; EXCEPTION_PRINT (result); goto _catch; } +#define _throwif(ERROR, COND) if (M3_UNLIKELY(COND)) { _throw(ERROR); } + +#define _throwifnull(PTR) _throwif (m3Err_mallocFailed, !(PTR)) + +#endif // m3_exception_h diff --git a/ext/wasm3/source/m3_exec.c b/ext/wasm3/source/m3_exec.c new file mode 100644 index 0000000..718e447 --- /dev/null +++ b/ext/wasm3/source/m3_exec.c @@ -0,0 +1,8 @@ +// +// m3_exec.c +// +// Created by Steven Massey on 4/17/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +// EMPTY FOR NOW diff --git a/ext/wasm3/source/m3_exec.h b/ext/wasm3/source/m3_exec.h new file mode 100644 index 0000000..461ffaa --- /dev/null +++ b/ext/wasm3/source/m3_exec.h @@ -0,0 +1,1488 @@ +// +// m3_exec.h +// +// Created by Steven Massey on 4/17/19. +// Copyright © 2019 Steven Massey. All rights reserved. + + +#ifndef m3_exec_h +#define m3_exec_h + +// TODO: all these functions could move over to the .c at some point. normally, I'd say screw it, +// but it might prove useful to be able to compile m3_exec alone w/ optimizations while the remaining +// code is at debug O0 + + +// About the naming convention of these operations/macros (_rs, _sr_, _ss, _srs, etc.) +//------------------------------------------------------------------------------------------------------ +// - 'r' means register and 's' means slot +// - the first letter is the top of the stack +// +// so, for example, _rs means the first operand (the first thing pushed to the stack) is in a slot +// and the second operand (the top of the stack) is in a register +//------------------------------------------------------------------------------------------------------ + +#ifndef M3_COMPILE_OPCODES +# error "Opcodes should only be included in one compilation unit" +#endif + +#include "m3_math_utils.h" +#include "m3_compile.h" +#include "m3_env.h" +#include "m3_info.h" +#include "m3_exec_defs.h" + +#include + +d_m3BeginExternC + +# define rewrite_op(OP) * ((void **) (_pc-1)) = (void*)(OP) + +# define immediate(TYPE) * ((TYPE *) _pc++) +# define skip_immediate(TYPE) (_pc++) + +# define slot(TYPE) * (TYPE *) (_sp + immediate (i32)) +# define slot_ptr(TYPE) (TYPE *) (_sp + immediate (i32)) + + +# if d_m3EnableOpProfiling + d_m3RetSig profileOp (d_m3OpSig, cstr_t i_operationName); +# define nextOp() return profileOp (d_m3OpAllArgs, __FUNCTION__) +# elif d_m3EnableOpTracing + d_m3RetSig debugOp (d_m3OpSig, cstr_t i_operationName); +# define nextOp() return debugOp (d_m3OpAllArgs, __FUNCTION__) +# else +# define nextOp() nextOpDirect() +# endif + +#define jumpOp(PC) jumpOpDirect(PC) + +#if d_m3RecordBacktraces + #define pushBacktraceFrame() (PushBacktraceFrame (_mem->runtime, _pc - 1)) + #define fillBacktraceFrame(FUNCTION) (FillBacktraceFunctionInfo (_mem->runtime, function)) + + #define newTrap(err) return (pushBacktraceFrame (), err) + #define forwardTrap(err) return err +#else + #define pushBacktraceFrame() do {} while (0) + #define fillBacktraceFrame(FUNCTION) do {} while (0) + + #define newTrap(err) return err + #define forwardTrap(err) return err +#endif + + +#if d_m3EnableStrace == 1 + // Flat trace + #define d_m3TracePrepare + #define d_m3TracePrint(fmt, ...) fprintf(stderr, fmt "\n", ##__VA_ARGS__) +#elif d_m3EnableStrace >= 2 + // Structured trace + #define d_m3TracePrepare const IM3Runtime trace_rt = m3MemRuntime(_mem); + #define d_m3TracePrint(fmt, ...) fprintf(stderr, "%*s" fmt "\n", (trace_rt->callDepth)*2, "", ##__VA_ARGS__) +#else + #define d_m3TracePrepare + #define d_m3TracePrint(fmt, ...) +#endif + +#if d_m3EnableStrace >= 3 + #define d_m3TraceLoad(TYPE,offset,val) d_m3TracePrint("load." #TYPE " 0x%x = %" PRI##TYPE, offset, val) + #define d_m3TraceStore(TYPE,offset,val) d_m3TracePrint("store." #TYPE " 0x%x , %" PRI##TYPE, offset, val) +#else + #define d_m3TraceLoad(TYPE,offset,val) + #define d_m3TraceStore(TYPE,offset,val) +#endif + +#ifdef DEBUG + #define d_outOfBounds newTrap (ErrorRuntime (m3Err_trapOutOfBoundsMemoryAccess, \ + _mem->runtime, "memory size: %zu; access offset: %zu", \ + _mem->length, operand)) + +# define d_outOfBoundsMemOp(OFFSET, SIZE) newTrap (ErrorRuntime (m3Err_trapOutOfBoundsMemoryAccess, \ + _mem->runtime, "memory size: %zu; access offset: %zu; size: %u", \ + _mem->length, OFFSET, SIZE)) +#else + #define d_outOfBounds newTrap (m3Err_trapOutOfBoundsMemoryAccess) + +# define d_outOfBoundsMemOp(OFFSET, SIZE) newTrap (m3Err_trapOutOfBoundsMemoryAccess) + +#endif + + +d_m3RetSig Call (d_m3OpSig) +{ + m3ret_t possible_trap = m3_Yield (); + if (M3_UNLIKELY(possible_trap)) return possible_trap; + + nextOpDirect(); +} + +// TODO: OK, this needs some explanation here ;0 + +#define d_m3CommutativeOpMacro(RES, REG, TYPE, NAME, OP, ...) \ +d_m3Op(TYPE##_##NAME##_rs) \ +{ \ + TYPE operand = slot (TYPE); \ + OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ + nextOp (); \ +} \ +d_m3Op(TYPE##_##NAME##_ss) \ +{ \ + TYPE operand2 = slot (TYPE); \ + TYPE operand1 = slot (TYPE); \ + OP((RES), operand1, operand2, ##__VA_ARGS__); \ + nextOp (); \ +} + +#define d_m3OpMacro(RES, REG, TYPE, NAME, OP, ...) \ +d_m3Op(TYPE##_##NAME##_sr) \ +{ \ + TYPE operand = slot (TYPE); \ + OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ + nextOp (); \ +} \ +d_m3CommutativeOpMacro(RES, REG, TYPE,NAME, OP, ##__VA_ARGS__) + +// Accept macros +#define d_m3CommutativeOpMacro_i(TYPE, NAME, MACRO, ...) d_m3CommutativeOpMacro ( _r0, _r0, TYPE, NAME, MACRO, ##__VA_ARGS__) +#define d_m3OpMacro_i(TYPE, NAME, MACRO, ...) d_m3OpMacro ( _r0, _r0, TYPE, NAME, MACRO, ##__VA_ARGS__) +#define d_m3CommutativeOpMacro_f(TYPE, NAME, MACRO, ...) d_m3CommutativeOpMacro (_fp0, _fp0, TYPE, NAME, MACRO, ##__VA_ARGS__) +#define d_m3OpMacro_f(TYPE, NAME, MACRO, ...) d_m3OpMacro (_fp0, _fp0, TYPE, NAME, MACRO, ##__VA_ARGS__) + +#define M3_FUNC(RES, A, B, OP) (RES) = OP((A), (B)) // Accept functions: res = OP(a,b) +#define M3_OPER(RES, A, B, OP) (RES) = ((A) OP (B)) // Accept operators: res = a OP b + +#define d_m3CommutativeOpFunc_i(TYPE, NAME, OP) d_m3CommutativeOpMacro_i (TYPE, NAME, M3_FUNC, OP) +#define d_m3OpFunc_i(TYPE, NAME, OP) d_m3OpMacro_i (TYPE, NAME, M3_FUNC, OP) +#define d_m3CommutativeOpFunc_f(TYPE, NAME, OP) d_m3CommutativeOpMacro_f (TYPE, NAME, M3_FUNC, OP) +#define d_m3OpFunc_f(TYPE, NAME, OP) d_m3OpMacro_f (TYPE, NAME, M3_FUNC, OP) + +#define d_m3CommutativeOp_i(TYPE, NAME, OP) d_m3CommutativeOpMacro_i (TYPE, NAME, M3_OPER, OP) +#define d_m3Op_i(TYPE, NAME, OP) d_m3OpMacro_i (TYPE, NAME, M3_OPER, OP) +#define d_m3CommutativeOp_f(TYPE, NAME, OP) d_m3CommutativeOpMacro_f (TYPE, NAME, M3_OPER, OP) +#define d_m3Op_f(TYPE, NAME, OP) d_m3OpMacro_f (TYPE, NAME, M3_OPER, OP) + +// compare needs to be distinct for fp 'cause the result must be _r0 +#define d_m3CompareOp_f(TYPE, NAME, OP) d_m3OpMacro (_r0, _fp0, TYPE, NAME, M3_OPER, OP) +#define d_m3CommutativeCmpOp_f(TYPE, NAME, OP) d_m3CommutativeOpMacro (_r0, _fp0, TYPE, NAME, M3_OPER, OP) + + +//----------------------- + +// signed +d_m3CommutativeOp_i (i32, Equal, ==) d_m3CommutativeOp_i (i64, Equal, ==) +d_m3CommutativeOp_i (i32, NotEqual, !=) d_m3CommutativeOp_i (i64, NotEqual, !=) + +d_m3Op_i (i32, LessThan, < ) d_m3Op_i (i64, LessThan, < ) +d_m3Op_i (i32, GreaterThan, > ) d_m3Op_i (i64, GreaterThan, > ) +d_m3Op_i (i32, LessThanOrEqual, <=) d_m3Op_i (i64, LessThanOrEqual, <=) +d_m3Op_i (i32, GreaterThanOrEqual, >=) d_m3Op_i (i64, GreaterThanOrEqual, >=) + +// unsigned +d_m3Op_i (u32, LessThan, < ) d_m3Op_i (u64, LessThan, < ) +d_m3Op_i (u32, GreaterThan, > ) d_m3Op_i (u64, GreaterThan, > ) +d_m3Op_i (u32, LessThanOrEqual, <=) d_m3Op_i (u64, LessThanOrEqual, <=) +d_m3Op_i (u32, GreaterThanOrEqual, >=) d_m3Op_i (u64, GreaterThanOrEqual, >=) + +#if d_m3HasFloat +d_m3CommutativeCmpOp_f (f32, Equal, ==) d_m3CommutativeCmpOp_f (f64, Equal, ==) +d_m3CommutativeCmpOp_f (f32, NotEqual, !=) d_m3CommutativeCmpOp_f (f64, NotEqual, !=) +d_m3CompareOp_f (f32, LessThan, < ) d_m3CompareOp_f (f64, LessThan, < ) +d_m3CompareOp_f (f32, GreaterThan, > ) d_m3CompareOp_f (f64, GreaterThan, > ) +d_m3CompareOp_f (f32, LessThanOrEqual, <=) d_m3CompareOp_f (f64, LessThanOrEqual, <=) +d_m3CompareOp_f (f32, GreaterThanOrEqual, >=) d_m3CompareOp_f (f64, GreaterThanOrEqual, >=) +#endif + +d_m3CommutativeOp_i (i32, Add, +) d_m3CommutativeOp_i (i64, Add, +) +d_m3CommutativeOp_i (i32, Multiply, *) d_m3CommutativeOp_i (i64, Multiply, *) + +d_m3Op_i (i32, Subtract, -) d_m3Op_i (i64, Subtract, -) + +#define OP_SHL_32(X,N) ((X) << ((u32)(N) % 32)) +#define OP_SHL_64(X,N) ((X) << ((u64)(N) % 64)) +#define OP_SHR_32(X,N) ((X) >> ((u32)(N) % 32)) +#define OP_SHR_64(X,N) ((X) >> ((u64)(N) % 64)) + +d_m3OpFunc_i (u32, ShiftLeft, OP_SHL_32) d_m3OpFunc_i (u64, ShiftLeft, OP_SHL_64) +d_m3OpFunc_i (i32, ShiftRight, OP_SHR_32) d_m3OpFunc_i (i64, ShiftRight, OP_SHR_64) +d_m3OpFunc_i (u32, ShiftRight, OP_SHR_32) d_m3OpFunc_i (u64, ShiftRight, OP_SHR_64) + +d_m3CommutativeOp_i (u32, And, &) +d_m3CommutativeOp_i (u32, Or, |) +d_m3CommutativeOp_i (u32, Xor, ^) + +d_m3CommutativeOp_i (u64, And, &) +d_m3CommutativeOp_i (u64, Or, |) +d_m3CommutativeOp_i (u64, Xor, ^) + +#if d_m3HasFloat +d_m3CommutativeOp_f (f32, Add, +) d_m3CommutativeOp_f (f64, Add, +) +d_m3CommutativeOp_f (f32, Multiply, *) d_m3CommutativeOp_f (f64, Multiply, *) +d_m3Op_f (f32, Subtract, -) d_m3Op_f (f64, Subtract, -) +d_m3Op_f (f32, Divide, /) d_m3Op_f (f64, Divide, /) +#endif + +d_m3OpFunc_i(u32, Rotl, rotl32) +d_m3OpFunc_i(u32, Rotr, rotr32) +d_m3OpFunc_i(u64, Rotl, rotl64) +d_m3OpFunc_i(u64, Rotr, rotr64) + +d_m3OpMacro_i(u32, Divide, OP_DIV_U); +d_m3OpMacro_i(i32, Divide, OP_DIV_S, INT32_MIN); +d_m3OpMacro_i(u64, Divide, OP_DIV_U); +d_m3OpMacro_i(i64, Divide, OP_DIV_S, INT64_MIN); + +d_m3OpMacro_i(u32, Remainder, OP_REM_U); +d_m3OpMacro_i(i32, Remainder, OP_REM_S, INT32_MIN); +d_m3OpMacro_i(u64, Remainder, OP_REM_U); +d_m3OpMacro_i(i64, Remainder, OP_REM_S, INT64_MIN); + +#if d_m3HasFloat +d_m3OpFunc_f(f32, Min, min_f32); +d_m3OpFunc_f(f32, Max, max_f32); +d_m3OpFunc_f(f64, Min, min_f64); +d_m3OpFunc_f(f64, Max, max_f64); + +d_m3OpFunc_f(f32, CopySign, copysignf); +d_m3OpFunc_f(f64, CopySign, copysign); +#endif + +// Unary operations +// Note: This macro follows the principle of d_m3OpMacro + +#define d_m3UnaryMacro(RES, REG, TYPE, NAME, OP, ...) \ +d_m3Op(TYPE##_##NAME##_r) \ +{ \ + OP((RES), (TYPE) REG, ##__VA_ARGS__); \ + nextOp (); \ +} \ +d_m3Op(TYPE##_##NAME##_s) \ +{ \ + TYPE operand = slot (TYPE); \ + OP((RES), operand, ##__VA_ARGS__); \ + nextOp (); \ +} + +#define M3_UNARY(RES, X, OP) (RES) = OP(X) +#define d_m3UnaryOp_i(TYPE, NAME, OPERATION) d_m3UnaryMacro( _r0, _r0, TYPE, NAME, M3_UNARY, OPERATION) +#define d_m3UnaryOp_f(TYPE, NAME, OPERATION) d_m3UnaryMacro(_fp0, _fp0, TYPE, NAME, M3_UNARY, OPERATION) + +#if d_m3HasFloat +d_m3UnaryOp_f (f32, Abs, fabsf); d_m3UnaryOp_f (f64, Abs, fabs); +d_m3UnaryOp_f (f32, Ceil, ceilf); d_m3UnaryOp_f (f64, Ceil, ceil); +d_m3UnaryOp_f (f32, Floor, floorf); d_m3UnaryOp_f (f64, Floor, floor); +d_m3UnaryOp_f (f32, Trunc, truncf); d_m3UnaryOp_f (f64, Trunc, trunc); +d_m3UnaryOp_f (f32, Sqrt, sqrtf); d_m3UnaryOp_f (f64, Sqrt, sqrt); +d_m3UnaryOp_f (f32, Nearest, rintf); d_m3UnaryOp_f (f64, Nearest, rint); +d_m3UnaryOp_f (f32, Negate, -); d_m3UnaryOp_f (f64, Negate, -); +#endif + +#define OP_EQZ(x) ((x) == 0) + +d_m3UnaryOp_i (i32, EqualToZero, OP_EQZ) +d_m3UnaryOp_i (i64, EqualToZero, OP_EQZ) + +// clz(0), ctz(0) results are undefined for rest platforms, fix it +#if (defined(__i386__) || defined(__x86_64__)) && !(defined(__AVX2__) || (defined(__ABM__) && defined(__BMI__))) + #define OP_CLZ_32(x) (M3_UNLIKELY((x) == 0) ? 32 : __builtin_clz(x)) + #define OP_CTZ_32(x) (M3_UNLIKELY((x) == 0) ? 32 : __builtin_ctz(x)) + // for 64-bit instructions branchless approach more preferable + #define OP_CLZ_64(x) (__builtin_clzll((x) | (1LL << 0)) + OP_EQZ(x)) + #define OP_CTZ_64(x) (__builtin_ctzll((x) | (1LL << 63)) + OP_EQZ(x)) +#elif defined(__ppc__) || defined(__ppc64__) +// PowerPC is defined for __builtin_clz(0) and __builtin_ctz(0). +// See (https://github.com/aquynh/capstone/blob/master/MathExtras.h#L99) + #define OP_CLZ_32(x) __builtin_clz(x) + #define OP_CTZ_32(x) __builtin_ctz(x) + #define OP_CLZ_64(x) __builtin_clzll(x) + #define OP_CTZ_64(x) __builtin_ctzll(x) +#else + #define OP_CLZ_32(x) (M3_UNLIKELY((x) == 0) ? 32 : __builtin_clz(x)) + #define OP_CTZ_32(x) (M3_UNLIKELY((x) == 0) ? 32 : __builtin_ctz(x)) + #define OP_CLZ_64(x) (M3_UNLIKELY((x) == 0) ? 64 : __builtin_clzll(x)) + #define OP_CTZ_64(x) (M3_UNLIKELY((x) == 0) ? 64 : __builtin_ctzll(x)) +#endif + +d_m3UnaryOp_i (u32, Clz, OP_CLZ_32) +d_m3UnaryOp_i (u64, Clz, OP_CLZ_64) + +d_m3UnaryOp_i (u32, Ctz, OP_CTZ_32) +d_m3UnaryOp_i (u64, Ctz, OP_CTZ_64) + +d_m3UnaryOp_i (u32, Popcnt, __builtin_popcount) +d_m3UnaryOp_i (u64, Popcnt, __builtin_popcountll) + +#define OP_WRAP_I64(X) ((X) & 0x00000000ffffffff) + +d_m3Op(i32_Wrap_i64_r) +{ + _r0 = OP_WRAP_I64((i64) _r0); + nextOp (); +} + +d_m3Op(i32_Wrap_i64_s) +{ + i64 operand = slot (i64); + _r0 = OP_WRAP_I64(operand); + nextOp (); +} + +// Integer sign extension operations +#define OP_EXTEND8_S_I32(X) ((int32_t)(int8_t)(X)) +#define OP_EXTEND16_S_I32(X) ((int32_t)(int16_t)(X)) +#define OP_EXTEND8_S_I64(X) ((int64_t)(int8_t)(X)) +#define OP_EXTEND16_S_I64(X) ((int64_t)(int16_t)(X)) +#define OP_EXTEND32_S_I64(X) ((int64_t)(int32_t)(X)) + +d_m3UnaryOp_i (i32, Extend8_s, OP_EXTEND8_S_I32) +d_m3UnaryOp_i (i32, Extend16_s, OP_EXTEND16_S_I32) +d_m3UnaryOp_i (i64, Extend8_s, OP_EXTEND8_S_I64) +d_m3UnaryOp_i (i64, Extend16_s, OP_EXTEND16_S_I64) +d_m3UnaryOp_i (i64, Extend32_s, OP_EXTEND32_S_I64) + +#define d_m3TruncMacro(DEST, SRC, TYPE, NAME, FROM, OP, ...) \ +d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \ +{ \ + OP((DEST), (FROM) SRC, ##__VA_ARGS__); \ + nextOp (); \ +} \ +d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \ +{ \ + FROM * stack = slot_ptr (FROM); \ + OP((DEST), (* stack), ##__VA_ARGS__); \ + nextOp (); \ +} \ +d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \ +{ \ + TYPE * dest = slot_ptr (TYPE); \ + OP((* dest), (FROM) SRC, ##__VA_ARGS__); \ + nextOp (); \ +} \ +d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \ +{ \ + FROM * stack = slot_ptr (FROM); \ + TYPE * dest = slot_ptr (TYPE); \ + OP((* dest), (* stack), ##__VA_ARGS__); \ + nextOp (); \ +} + +#if d_m3HasFloat +d_m3TruncMacro(_r0, _fp0, i32, Trunc, f32, OP_I32_TRUNC_F32) +d_m3TruncMacro(_r0, _fp0, u32, Trunc, f32, OP_U32_TRUNC_F32) +d_m3TruncMacro(_r0, _fp0, i32, Trunc, f64, OP_I32_TRUNC_F64) +d_m3TruncMacro(_r0, _fp0, u32, Trunc, f64, OP_U32_TRUNC_F64) + +d_m3TruncMacro(_r0, _fp0, i64, Trunc, f32, OP_I64_TRUNC_F32) +d_m3TruncMacro(_r0, _fp0, u64, Trunc, f32, OP_U64_TRUNC_F32) +d_m3TruncMacro(_r0, _fp0, i64, Trunc, f64, OP_I64_TRUNC_F64) +d_m3TruncMacro(_r0, _fp0, u64, Trunc, f64, OP_U64_TRUNC_F64) + +d_m3TruncMacro(_r0, _fp0, i32, TruncSat, f32, OP_I32_TRUNC_SAT_F32) +d_m3TruncMacro(_r0, _fp0, u32, TruncSat, f32, OP_U32_TRUNC_SAT_F32) +d_m3TruncMacro(_r0, _fp0, i32, TruncSat, f64, OP_I32_TRUNC_SAT_F64) +d_m3TruncMacro(_r0, _fp0, u32, TruncSat, f64, OP_U32_TRUNC_SAT_F64) + +d_m3TruncMacro(_r0, _fp0, i64, TruncSat, f32, OP_I64_TRUNC_SAT_F32) +d_m3TruncMacro(_r0, _fp0, u64, TruncSat, f32, OP_U64_TRUNC_SAT_F32) +d_m3TruncMacro(_r0, _fp0, i64, TruncSat, f64, OP_I64_TRUNC_SAT_F64) +d_m3TruncMacro(_r0, _fp0, u64, TruncSat, f64, OP_U64_TRUNC_SAT_F64) +#endif + +#define d_m3TypeModifyOp(REG_TO, REG_FROM, TO, NAME, FROM) \ +d_m3Op(TO##_##NAME##_##FROM##_r) \ +{ \ + REG_TO = (TO) ((FROM) REG_FROM); \ + nextOp (); \ +} \ + \ +d_m3Op(TO##_##NAME##_##FROM##_s) \ +{ \ + FROM from = slot (FROM); \ + REG_TO = (TO) (from); \ + nextOp (); \ +} + +// Int to int +d_m3TypeModifyOp (_r0, _r0, i64, Extend, i32); +d_m3TypeModifyOp (_r0, _r0, i64, Extend, u32); + +// Float to float +#if d_m3HasFloat +d_m3TypeModifyOp (_fp0, _fp0, f32, Demote, f64); +d_m3TypeModifyOp (_fp0, _fp0, f64, Promote, f32); +#endif + +#define d_m3TypeConvertOp(REG_TO, REG_FROM, TO, NAME, FROM) \ +d_m3Op(TO##_##NAME##_##FROM##_r_r) \ +{ \ + REG_TO = (TO) ((FROM) REG_FROM); \ + nextOp (); \ +} \ + \ +d_m3Op(TO##_##NAME##_##FROM##_s_r) \ +{ \ + slot (TO) = (TO) ((FROM) REG_FROM); \ + nextOp (); \ +} \ + \ +d_m3Op(TO##_##NAME##_##FROM##_r_s) \ +{ \ + FROM from = slot (FROM); \ + REG_TO = (TO) (from); \ + nextOp (); \ +} \ + \ +d_m3Op(TO##_##NAME##_##FROM##_s_s) \ +{ \ + FROM from = slot (FROM); \ + slot (TO) = (TO) (from); \ + nextOp (); \ +} + +// Int to float +#if d_m3HasFloat +d_m3TypeConvertOp (_fp0, _r0, f64, Convert, i32); +d_m3TypeConvertOp (_fp0, _r0, f64, Convert, u32); +d_m3TypeConvertOp (_fp0, _r0, f64, Convert, i64); +d_m3TypeConvertOp (_fp0, _r0, f64, Convert, u64); + +d_m3TypeConvertOp (_fp0, _r0, f32, Convert, i32); +d_m3TypeConvertOp (_fp0, _r0, f32, Convert, u32); +d_m3TypeConvertOp (_fp0, _r0, f32, Convert, i64); +d_m3TypeConvertOp (_fp0, _r0, f32, Convert, u64); +#endif + +#define d_m3ReinterpretOp(REG, TO, SRC, FROM) \ +d_m3Op(TO##_Reinterpret_##FROM##_r_r) \ +{ \ + union { FROM c; TO t; } u; \ + u.c = (FROM) SRC; \ + REG = u.t; \ + nextOp (); \ +} \ + \ +d_m3Op(TO##_Reinterpret_##FROM##_r_s) \ +{ \ + union { FROM c; TO t; } u; \ + u.c = slot (FROM); \ + REG = u.t; \ + nextOp (); \ +} \ + \ +d_m3Op(TO##_Reinterpret_##FROM##_s_r) \ +{ \ + union { FROM c; TO t; } u; \ + u.c = (FROM) SRC; \ + slot (TO) = u.t; \ + nextOp (); \ +} \ + \ +d_m3Op(TO##_Reinterpret_##FROM##_s_s) \ +{ \ + union { FROM c; TO t; } u; \ + u.c = slot (FROM); \ + slot (TO) = u.t; \ + nextOp (); \ +} + +#if d_m3HasFloat +d_m3ReinterpretOp (_r0, i32, _fp0, f32) +d_m3ReinterpretOp (_r0, i64, _fp0, f64) +d_m3ReinterpretOp (_fp0, f32, _r0, i32) +d_m3ReinterpretOp (_fp0, f64, _r0, i64) +#endif + + +d_m3Op (GetGlobal_s32) +{ + u32 * global = immediate (u32 *); + slot (u32) = * global; // printf ("get global: %p %" PRIi64 "\n", global, *global); + + nextOp (); +} + + +d_m3Op (GetGlobal_s64) +{ + u64 * global = immediate (u64 *); + slot (u64) = * global; // printf ("get global: %p %" PRIi64 "\n", global, *global); + + nextOp (); +} + + +d_m3Op (SetGlobal_i32) +{ + u32 * global = immediate (u32 *); + * global = (u32) _r0; // printf ("set global: %p %" PRIi64 "\n", global, _r0); + + nextOp (); +} + + +d_m3Op (SetGlobal_i64) +{ + u64 * global = immediate (u64 *); + * global = (u64) _r0; // printf ("set global: %p %" PRIi64 "\n", global, _r0); + + nextOp (); +} + + +d_m3Op (Call) +{ + pc_t callPC = immediate (pc_t); + i32 stackOffset = immediate (i32); + IM3Memory memory = m3MemInfo (_mem); + + m3stack_t sp = _sp + stackOffset; + + m3ret_t r = Call (callPC, sp, _mem, d_m3OpDefaultArgs); + _mem = memory->mallocated; + + if (M3_LIKELY(not r)) + nextOp (); + else + { + pushBacktraceFrame (); + forwardTrap (r); + } +} + + +d_m3Op (CallIndirect) +{ + u32 tableIndex = slot (u32); + IM3Module module = immediate (IM3Module); + IM3FuncType type = immediate (IM3FuncType); + i32 stackOffset = immediate (i32); + IM3Memory memory = m3MemInfo (_mem); + + m3stack_t sp = _sp + stackOffset; + + m3ret_t r = m3Err_none; + + if (M3_LIKELY(tableIndex < module->table0Size)) + { + IM3Function function = module->table0 [tableIndex]; + + if (M3_LIKELY(function)) + { + if (M3_LIKELY(type == function->funcType)) + { + if (M3_UNLIKELY(not function->compiled)) + r = CompileFunction (function); + + if (M3_LIKELY(not r)) + { + r = Call (function->compiled, sp, _mem, d_m3OpDefaultArgs); + _mem = memory->mallocated; + + if (M3_LIKELY(not r)) + nextOpDirect (); + else + { + pushBacktraceFrame (); + forwardTrap (r); + } + } + } + else r = m3Err_trapIndirectCallTypeMismatch; + } + else r = m3Err_trapTableElementIsNull; + } + else r = m3Err_trapTableIndexOutOfRange; + + if (M3_UNLIKELY(r)) + newTrap (r); + else forwardTrap (r); +} + + +d_m3Op (CallRawFunction) +{ + d_m3TracePrepare + + M3ImportContext ctx; + + M3RawCall call = (M3RawCall) (* _pc++); + ctx.function = immediate (IM3Function); + ctx.userdata = immediate (void *); + u64* const sp = ((u64*)_sp); + IM3Memory memory = m3MemInfo (_mem); + + IM3Runtime runtime = m3MemRuntime(_mem); + +#if d_m3EnableStrace + IM3FuncType ftype = ctx.function->funcType; + + FILE* out = stderr; + char outbuff[1024]; + char* outp = outbuff; + char* oute = outbuff+1024; + + outp += snprintf(outp, oute-outp, "%s!%s(", ctx.function->import.moduleUtf8, ctx.function->import.fieldUtf8); + + const int nArgs = ftype->numArgs; + const int nRets = ftype->numRets; + u64 * args = sp + nRets; + for (int i=0; itypes[nRets + i]; + switch (type) { + case c_m3Type_i32: outp += snprintf(outp, oute-outp, "%" PRIi32, *(i32*)(args+i)); break; + case c_m3Type_i64: outp += snprintf(outp, oute-outp, "%" PRIi64, *(i64*)(args+i)); break; + case c_m3Type_f32: outp += snprintf(outp, oute-outp, "%" PRIf32, *(f32*)(args+i)); break; + case c_m3Type_f64: outp += snprintf(outp, oute-outp, "%" PRIf64, *(f64*)(args+i)); break; + default: outp += snprintf(outp, oute-outp, "", type); break; + } + outp += snprintf(outp, oute-outp, (i < nArgs-1) ? ", " : ")"); + } +# if d_m3EnableStrace >= 2 + outp += snprintf(outp, oute-outp, " { }"); +# endif +#endif + + // m3_Call uses runtime->stack to set-up initial exported function stack. + // Reconfigure the stack to enable recursive invocations of m3_Call. + // I.e. exported/table function can be called from an impoted function. + void* stack_backup = runtime->stack; + runtime->stack = sp; + m3ret_t possible_trap = call (runtime, &ctx, sp, m3MemData(_mem)); + runtime->stack = stack_backup; + +#if d_m3EnableStrace + if (M3_UNLIKELY(possible_trap)) { + d_m3TracePrint("%s -> %s", outbuff, (char*)possible_trap); + } else { + switch (GetSingleRetType(ftype)) { + case c_m3Type_none: d_m3TracePrint("%s", outbuff); break; + case c_m3Type_i32: d_m3TracePrint("%s = %" PRIi32, outbuff, *(i32*)sp); break; + case c_m3Type_i64: d_m3TracePrint("%s = %" PRIi64, outbuff, *(i64*)sp); break; + case c_m3Type_f32: d_m3TracePrint("%s = %" PRIf32, outbuff, *(f32*)sp); break; + case c_m3Type_f64: d_m3TracePrint("%s = %" PRIf64, outbuff, *(f64*)sp); break; + } + } +#endif + + if (M3_UNLIKELY(possible_trap)) { + _mem = memory->mallocated; + pushBacktraceFrame (); + } + forwardTrap (possible_trap); +} + + +d_m3Op (MemSize) +{ + IM3Memory memory = m3MemInfo (_mem); + + _r0 = memory->numPages; + + nextOp (); +} + + +d_m3Op (MemGrow) +{ + IM3Runtime runtime = m3MemRuntime(_mem); + IM3Memory memory = & runtime->memory; + + u32 numPagesToGrow = (u32) _r0; + _r0 = memory->numPages; + + if (M3_LIKELY(numPagesToGrow)) + { + u32 requiredPages = memory->numPages + numPagesToGrow; + + M3Result r = ResizeMemory (runtime, requiredPages); + if (r) + _r0 = -1; + + _mem = memory->mallocated; + } + + nextOp (); +} + + +d_m3Op (MemCopy) +{ + u32 size = (u32) _r0; + u64 source = slot (u32); + u64 destination = slot (u32); + + if (M3_LIKELY(destination + size <= _mem->length)) + { + if (M3_LIKELY(source + size <= _mem->length)) + { + u8 * dst = m3MemData (_mem) + destination; + u8 * src = m3MemData (_mem) + source; + memmove (dst, src, size); + + nextOp (); + } + else d_outOfBoundsMemOp (source, size); + } + else d_outOfBoundsMemOp (destination, size); +} + + +d_m3Op (MemFill) +{ + u32 size = (u32) _r0; + u32 byte = slot (u32); + u64 destination = slot (u32); + + if (M3_LIKELY(destination + size <= _mem->length)) + { + u8 * mem8 = m3MemData (_mem) + destination; + memset (mem8, (u8) byte, size); + nextOp (); + } + else d_outOfBoundsMemOp (destination, size); +} + + +// it's a debate: should the compilation be trigger be the caller or callee page. +// it's a much easier to put it in the caller pager. if it's in the callee, either the entire page +// has be left dangling or it's just a stub that jumps to a newly acquired page. In Gestalt, I opted +// for the stub approach. Stubbing makes it easier to dynamically free the compilation. You can also +// do both. +d_m3Op (Compile) +{ + rewrite_op (op_Call); + + IM3Function function = immediate (IM3Function); + + m3ret_t result = m3Err_none; + + if (M3_UNLIKELY(not function->compiled)) // check to see if function was compiled since this operation was emitted. + result = CompileFunction (function); + + if (not result) + { + // patch up compiled pc and call rewritten op_Call + * ((void**) --_pc) = (void*) (function->compiled); + --_pc; + nextOpDirect (); + } + + newTrap (result); +} + + + +d_m3Op (Entry) +{ + d_m3ClearRegisters + + d_m3TracePrepare + + IM3Function function = immediate (IM3Function); + IM3Memory memory = m3MemInfo (_mem); + +#if d_m3SkipStackCheck + if (true) +#else + if (M3_LIKELY ((void *) (_sp + function->maxStackSlots) < _mem->maxStack)) +#endif + { +#if defined(DEBUG) + function->hits++; +#endif + u8 * stack = (u8 *) ((m3slot_t *) _sp + function->numRetAndArgSlots); + + memset (stack, 0x0, function->numLocalBytes); + stack += function->numLocalBytes; + + if (function->constants) + { + memcpy (stack, function->constants, function->numConstantBytes); + } + +#if d_m3EnableStrace >= 2 + d_m3TracePrint("%s %s {", m3_GetFunctionName(function), SPrintFunctionArgList (function, _sp + function->numRetSlots)); + trace_rt->callDepth++; +#endif + + m3ret_t r = nextOpImpl (); + +#if d_m3EnableStrace >= 2 + trace_rt->callDepth--; + + if (r) { + d_m3TracePrint("} !trap = %s", (char*)r); + } else { + int rettype = GetSingleRetType(function->funcType); + if (rettype != c_m3Type_none) { + char str [128] = { 0 }; + SPrintArg (str, 127, _sp, rettype); + d_m3TracePrint("} = %s", str); + } else { + d_m3TracePrint("}"); + } + } +#endif + + if (M3_UNLIKELY(r)) { + _mem = memory->mallocated; + fillBacktraceFrame (); + } + forwardTrap (r); + } + else newTrap (m3Err_trapStackOverflow); +} + + +d_m3Op (Loop) +{ + d_m3TracePrepare + + // regs are unused coming into a loop anyway + // this reduces code size & stack usage + d_m3ClearRegisters + + m3ret_t r; + + IM3Memory memory = m3MemInfo (_mem); + + do + { +#if d_m3EnableStrace >= 3 + d_m3TracePrint("iter {"); + trace_rt->callDepth++; +#endif + r = nextOpImpl (); + +#if d_m3EnableStrace >= 3 + trace_rt->callDepth--; + d_m3TracePrint("}"); +#endif + // linear memory pointer needs refreshed here because the block it's looping over + // can potentially invoke the grow operation. + _mem = memory->mallocated; + } + while (r == _pc); + + forwardTrap (r); +} + + +d_m3Op (Branch) +{ + jumpOp (* _pc); +} + + +d_m3Op (If_r) +{ + i32 condition = (i32) _r0; + + pc_t elsePC = immediate (pc_t); + + if (condition) + nextOp (); + else + jumpOp (elsePC); +} + + +d_m3Op (If_s) +{ + i32 condition = slot (i32); + + pc_t elsePC = immediate (pc_t); + + if (condition) + nextOp (); + else + jumpOp (elsePC); +} + + +d_m3Op (BranchTable) +{ + u32 branchIndex = slot (u32); // branch index is always in a slot + u32 numTargets = immediate (u32); + + pc_t * branches = (pc_t *) _pc; + + if (branchIndex > numTargets) + branchIndex = numTargets; // the default index + + jumpOp (branches [branchIndex]); +} + + +#define d_m3SetRegisterSetSlot(TYPE, REG) \ +d_m3Op (SetRegister_##TYPE) \ +{ \ + REG = slot (TYPE); \ + nextOp (); \ +} \ + \ +d_m3Op (SetSlot_##TYPE) \ +{ \ + slot (TYPE) = (TYPE) REG; \ + nextOp (); \ +} \ + \ +d_m3Op (PreserveSetSlot_##TYPE) \ +{ \ + TYPE * stack = slot_ptr (TYPE); \ + TYPE * preserve = slot_ptr (TYPE); \ + \ + * preserve = * stack; \ + * stack = (TYPE) REG; \ + \ + nextOp (); \ +} + +d_m3SetRegisterSetSlot (i32, _r0) +d_m3SetRegisterSetSlot (i64, _r0) +#if d_m3HasFloat +d_m3SetRegisterSetSlot (f32, _fp0) +d_m3SetRegisterSetSlot (f64, _fp0) +#endif + +d_m3Op (CopySlot_32) +{ + u32 * dst = slot_ptr (u32); + u32 * src = slot_ptr (u32); + + * dst = * src; + + nextOp (); +} + + +d_m3Op (PreserveCopySlot_32) +{ + u32 * dest = slot_ptr (u32); + u32 * src = slot_ptr (u32); + u32 * preserve = slot_ptr (u32); + + * preserve = * dest; + * dest = * src; + + nextOp (); +} + + +d_m3Op (CopySlot_64) +{ + u64 * dst = slot_ptr (u64); + u64 * src = slot_ptr (u64); + + * dst = * src; // printf ("copy: %p <- %" PRIi64 " <- %p\n", dst, * dst, src); + + nextOp (); +} + + +d_m3Op (PreserveCopySlot_64) +{ + u64 * dest = slot_ptr (u64); + u64 * src = slot_ptr (u64); + u64 * preserve = slot_ptr (u64); + + * preserve = * dest; + * dest = * src; + + nextOp (); +} + + +#if d_m3EnableOpTracing +//-------------------------------------------------------------------------------------------------------- +d_m3Op (DumpStack) +{ + u32 opcodeIndex = immediate (u32); + u32 stackHeight = immediate (u32); + IM3Function function = immediate (IM3Function); + + cstr_t funcName = (function) ? m3_GetFunctionName(function) : ""; + + printf (" %4d ", opcodeIndex); + printf (" %-25s r0: 0x%016" PRIx64 " i:%" PRIi64 " u:%" PRIu64 "\n", funcName, _r0, _r0, _r0); +#if d_m3HasFloat + printf (" fp0: %" PRIf64 "\n", _fp0); +#endif + m3stack_t sp = _sp; + + for (u32 i = 0; i < stackHeight; ++i) + { + cstr_t kind = ""; + + printf ("%p %5s %2d: 0x%" PRIx64 " i:%" PRIi64 "\n", sp, kind, i, (u64) *(sp), (i64) *(sp)); + + ++sp; + } + printf ("---------------------------------------------------------------------------------------------------------\n"); + + nextOpDirect(); +} +#endif + + +#define d_m3Select_i(TYPE, REG) \ +d_m3Op (Select_##TYPE##_rss) \ +{ \ + i32 condition = (i32) _r0; \ + \ + TYPE operand2 = slot (TYPE); \ + TYPE operand1 = slot (TYPE); \ + \ + REG = (condition) ? operand1 : operand2; \ + \ + nextOp (); \ +} \ + \ +d_m3Op (Select_##TYPE##_srs) \ +{ \ + i32 condition = slot (i32); \ + \ + TYPE operand2 = (TYPE) REG; \ + TYPE operand1 = slot (TYPE); \ + \ + REG = (condition) ? operand1 : operand2; \ + \ + nextOp (); \ +} \ + \ +d_m3Op (Select_##TYPE##_ssr) \ +{ \ + i32 condition = slot (i32); \ + \ + TYPE operand2 = slot (TYPE); \ + TYPE operand1 = (TYPE) REG; \ + \ + REG = (condition) ? operand1 : operand2; \ + \ + nextOp (); \ +} \ + \ +d_m3Op (Select_##TYPE##_sss) \ +{ \ + i32 condition = slot (i32); \ + \ + TYPE operand2 = slot (TYPE); \ + TYPE operand1 = slot (TYPE); \ + \ + REG = (condition) ? operand1 : operand2; \ + \ + nextOp (); \ +} + + +d_m3Select_i (i32, _r0) +d_m3Select_i (i64, _r0) + + +#define d_m3Select_f(TYPE, REG, LABEL, SELECTOR) \ +d_m3Op (Select_##TYPE##_##LABEL##ss) \ +{ \ + i32 condition = (i32) SELECTOR; \ + \ + TYPE operand2 = slot (TYPE); \ + TYPE operand1 = slot (TYPE); \ + \ + REG = (condition) ? operand1 : operand2; \ + \ + nextOp (); \ +} \ + \ +d_m3Op (Select_##TYPE##_##LABEL##rs) \ +{ \ + i32 condition = (i32) SELECTOR; \ + \ + TYPE operand2 = (TYPE) REG; \ + TYPE operand1 = slot (TYPE); \ + \ + REG = (condition) ? operand1 : operand2; \ + \ + nextOp (); \ +} \ + \ +d_m3Op (Select_##TYPE##_##LABEL##sr) \ +{ \ + i32 condition = (i32) SELECTOR; \ + \ + TYPE operand2 = slot (TYPE); \ + TYPE operand1 = (TYPE) REG; \ + \ + REG = (condition) ? operand1 : operand2; \ + \ + nextOp (); \ +} + +#if d_m3HasFloat +d_m3Select_f (f32, _fp0, r, _r0) +d_m3Select_f (f32, _fp0, s, slot (i32)) + +d_m3Select_f (f64, _fp0, r, _r0) +d_m3Select_f (f64, _fp0, s, slot (i32)) +#endif + +d_m3Op (Return) +{ + m3StackCheck(); + return m3Err_none; +} + + +d_m3Op (BranchIf_r) +{ + i32 condition = (i32) _r0; + pc_t branch = immediate (pc_t); + + if (condition) + { + jumpOp (branch); + } + else nextOp (); +} + + +d_m3Op (BranchIf_s) +{ + i32 condition = slot (i32); + pc_t branch = immediate (pc_t); + + if (condition) + { + jumpOp (branch); + } + else nextOp (); +} + + +d_m3Op (BranchIfPrologue_r) +{ + i32 condition = (i32) _r0; + pc_t branch = immediate (pc_t); + + if (condition) + { + // this is the "prologue" that ends with + // a plain branch to the actual target + nextOp (); + } + else jumpOp (branch); // jump over the prologue +} + + +d_m3Op (BranchIfPrologue_s) +{ + i32 condition = slot (i32); + pc_t branch = immediate (pc_t); + + if (condition) + { + nextOp (); + } + else jumpOp (branch); +} + + +d_m3Op (ContinueLoop) +{ + m3StackCheck(); + + // TODO: this is where execution can "escape" the M3 code and callback to the client / fiber switch + // OR it can go in the Loop operation. I think it's best to do here. adding code to the loop operation + // has the potential to increase its native-stack usage. (don't forget ContinueLoopIf too.) + + void * loopId = immediate (void *); + return loopId; +} + + +d_m3Op (ContinueLoopIf) +{ + i32 condition = (i32) _r0; + void * loopId = immediate (void *); + + if (condition) + { + return loopId; + } + else nextOp (); +} + + +d_m3Op (Const32) +{ + u32 value = * (u32 *)_pc++; + slot (u32) = value; + nextOp (); +} + + +d_m3Op (Const64) +{ + u64 value = * (u64 *)_pc; + _pc += (M3_SIZEOF_PTR == 4) ? 2 : 1; + slot (u64) = value; + nextOp (); +} + +d_m3Op (Unsupported) +{ + newTrap ("unsupported instruction executed"); +} + +d_m3Op (Unreachable) +{ + m3StackCheck(); + newTrap (m3Err_trapUnreachable); +} + + +d_m3Op (End) +{ + m3StackCheck(); + return m3Err_none; +} + + +d_m3Op (SetGlobal_s32) +{ + u32 * global = immediate (u32 *); + * global = slot (u32); + + nextOp (); +} + + +d_m3Op (SetGlobal_s64) +{ + u64 * global = immediate (u64 *); + * global = slot (u64); + + nextOp (); +} + +#if d_m3HasFloat +d_m3Op (SetGlobal_f32) +{ + f32 * global = immediate (f32 *); + * global = _fp0; + + nextOp (); +} + + +d_m3Op (SetGlobal_f64) +{ + f64 * global = immediate (f64 *); + * global = _fp0; + + nextOp (); +} +#endif + + +#if d_m3SkipMemoryBoundsCheck +# define m3MemCheck(x) true +#else +# define m3MemCheck(x) M3_LIKELY(x) +#endif + +// memcpy here is to support non-aligned access on some platforms. + +#define d_m3Load(REG,DEST_TYPE,SRC_TYPE) \ +d_m3Op(DEST_TYPE##_Load_##SRC_TYPE##_r) \ +{ \ + d_m3TracePrepare \ + u32 offset = immediate (u32); \ + u64 operand = (u32) _r0; \ + operand += offset; \ + \ + if (m3MemCheck( \ + operand + sizeof (SRC_TYPE) <= _mem->length \ + )) { \ + u8* src8 = m3MemData(_mem) + operand; \ + SRC_TYPE value; \ + memcpy(&value, src8, sizeof(value)); \ + M3_BSWAP_##SRC_TYPE(value); \ + REG = (DEST_TYPE)value; \ + d_m3TraceLoad(DEST_TYPE, operand, REG); \ + nextOp (); \ + } else d_outOfBounds; \ +} \ +d_m3Op(DEST_TYPE##_Load_##SRC_TYPE##_s) \ +{ \ + d_m3TracePrepare \ + u64 operand = slot (u32); \ + u32 offset = immediate (u32); \ + operand += offset; \ + \ + if (m3MemCheck( \ + operand + sizeof (SRC_TYPE) <= _mem->length \ + )) { \ + u8* src8 = m3MemData(_mem) + operand; \ + SRC_TYPE value; \ + memcpy(&value, src8, sizeof(value)); \ + M3_BSWAP_##SRC_TYPE(value); \ + REG = (DEST_TYPE)value; \ + d_m3TraceLoad(DEST_TYPE, operand, REG); \ + nextOp (); \ + } else d_outOfBounds; \ +} + +// printf ("get: %d -> %d\n", operand + offset, (i64) REG); + + +#define d_m3Load_i(DEST_TYPE, SRC_TYPE) d_m3Load(_r0, DEST_TYPE, SRC_TYPE) +#define d_m3Load_f(DEST_TYPE, SRC_TYPE) d_m3Load(_fp0, DEST_TYPE, SRC_TYPE) + +#if d_m3HasFloat +d_m3Load_f (f32, f32); +d_m3Load_f (f64, f64); +#endif + +d_m3Load_i (i32, i8); +d_m3Load_i (i32, u8); +d_m3Load_i (i32, i16); +d_m3Load_i (i32, u16); +d_m3Load_i (i32, i32); + +d_m3Load_i (i64, i8); +d_m3Load_i (i64, u8); +d_m3Load_i (i64, i16); +d_m3Load_i (i64, u16); +d_m3Load_i (i64, i32); +d_m3Load_i (i64, u32); +d_m3Load_i (i64, i64); + +#define d_m3Store(REG, SRC_TYPE, DEST_TYPE) \ +d_m3Op (SRC_TYPE##_Store_##DEST_TYPE##_rs) \ +{ \ + d_m3TracePrepare \ + u64 operand = slot (u32); \ + u32 offset = immediate (u32); \ + operand += offset; \ + \ + if (m3MemCheck( \ + operand + sizeof (DEST_TYPE) <= _mem->length \ + )) { \ + d_m3TraceStore(SRC_TYPE, operand, REG); \ + u8* mem8 = m3MemData(_mem) + operand; \ + DEST_TYPE val = (DEST_TYPE) REG; \ + M3_BSWAP_##DEST_TYPE(val); \ + memcpy(mem8, &val, sizeof(val)); \ + nextOp (); \ + } else d_outOfBounds; \ +} \ +d_m3Op (SRC_TYPE##_Store_##DEST_TYPE##_sr) \ +{ \ + d_m3TracePrepare \ + const SRC_TYPE value = slot (SRC_TYPE); \ + u64 operand = (u32) _r0; \ + u32 offset = immediate (u32); \ + operand += offset; \ + \ + if (m3MemCheck( \ + operand + sizeof (DEST_TYPE) <= _mem->length \ + )) { \ + d_m3TraceStore(SRC_TYPE, operand, value); \ + u8* mem8 = m3MemData(_mem) + operand; \ + DEST_TYPE val = (DEST_TYPE) value; \ + M3_BSWAP_##DEST_TYPE(val); \ + memcpy(mem8, &val, sizeof(val)); \ + nextOp (); \ + } else d_outOfBounds; \ +} \ +d_m3Op (SRC_TYPE##_Store_##DEST_TYPE##_ss) \ +{ \ + d_m3TracePrepare \ + const SRC_TYPE value = slot (SRC_TYPE); \ + u64 operand = slot (u32); \ + u32 offset = immediate (u32); \ + operand += offset; \ + \ + if (m3MemCheck( \ + operand + sizeof (DEST_TYPE) <= _mem->length \ + )) { \ + d_m3TraceStore(SRC_TYPE, operand, value); \ + u8* mem8 = m3MemData(_mem) + operand; \ + DEST_TYPE val = (DEST_TYPE) value; \ + M3_BSWAP_##DEST_TYPE(val); \ + memcpy(mem8, &val, sizeof(val)); \ + nextOp (); \ + } else d_outOfBounds; \ +} + +// both operands can be in regs when storing a float +#define d_m3StoreFp(REG, TYPE) \ +d_m3Op (TYPE##_Store_##TYPE##_rr) \ +{ \ + d_m3TracePrepare \ + u64 operand = (u32) _r0; \ + u32 offset = immediate (u32); \ + operand += offset; \ + \ + if (m3MemCheck( \ + operand + sizeof (TYPE) <= _mem->length \ + )) { \ + d_m3TraceStore(TYPE, operand, REG); \ + u8* mem8 = m3MemData(_mem) + operand; \ + TYPE val = (TYPE) REG; \ + M3_BSWAP_##TYPE(val); \ + memcpy(mem8, &val, sizeof(val)); \ + nextOp (); \ + } else d_outOfBounds; \ +} + + +#define d_m3Store_i(SRC_TYPE, DEST_TYPE) d_m3Store(_r0, SRC_TYPE, DEST_TYPE) +#define d_m3Store_f(SRC_TYPE, DEST_TYPE) d_m3Store(_fp0, SRC_TYPE, DEST_TYPE) d_m3StoreFp (_fp0, SRC_TYPE); + +#if d_m3HasFloat +d_m3Store_f (f32, f32) +d_m3Store_f (f64, f64) +#endif + +d_m3Store_i (i32, u8) +d_m3Store_i (i32, i16) +d_m3Store_i (i32, i32) + +d_m3Store_i (i64, u8) +d_m3Store_i (i64, i16) +d_m3Store_i (i64, i32) +d_m3Store_i (i64, i64) + +#undef m3MemCheck + + +//--------------------------------------------------------------------------------------------------------------------- +// debug/profiling +//--------------------------------------------------------------------------------------------------------------------- +#if d_m3EnableOpTracing +d_m3RetSig debugOp (d_m3OpSig, cstr_t i_opcode) +{ + char name [100]; + strcpy (name, strstr (i_opcode, "op_") + 3); + char * bracket = strstr (name, "("); + if (bracket) { + *bracket = 0; + } + + puts (name); + nextOpDirect(); +} +# endif + +# if d_m3EnableOpProfiling +d_m3RetSig profileOp (d_m3OpSig, cstr_t i_operationName) +{ + ProfileHit (i_operationName); + + nextOpDirect(); +} +# endif + +d_m3EndExternC + +#endif // m3_exec_h diff --git a/ext/wasm3/source/m3_exec_defs.h b/ext/wasm3/source/m3_exec_defs.h new file mode 100644 index 0000000..c156ecc --- /dev/null +++ b/ext/wasm3/source/m3_exec_defs.h @@ -0,0 +1,63 @@ +// +// m3_exec_defs.h +// +// Created by Steven Massey on 5/1/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#ifndef m3_exec_defs_h +#define m3_exec_defs_h + +#include "m3_core.h" + +d_m3BeginExternC + +# define m3MemData(mem) (u8*)(((M3MemoryHeader*)(mem))+1) +# define m3MemRuntime(mem) (((M3MemoryHeader*)(mem))->runtime) +# define m3MemInfo(mem) (&(((M3MemoryHeader*)(mem))->runtime->memory)) + +# define d_m3BaseOpSig pc_t _pc, m3stack_t _sp, M3MemoryHeader * _mem, m3reg_t _r0 +# define d_m3BaseOpArgs _sp, _mem, _r0 +# define d_m3BaseOpAllArgs _pc, _sp, _mem, _r0 +# define d_m3BaseOpDefaultArgs 0 +# define d_m3BaseClearRegisters _r0 = 0; + +# define d_m3ExpOpSig(...) d_m3BaseOpSig, __VA_ARGS__ +# define d_m3ExpOpArgs(...) d_m3BaseOpArgs, __VA_ARGS__ +# define d_m3ExpOpAllArgs(...) d_m3BaseOpAllArgs, __VA_ARGS__ +# define d_m3ExpOpDefaultArgs(...) d_m3BaseOpDefaultArgs, __VA_ARGS__ +# define d_m3ExpClearRegisters(...) d_m3BaseClearRegisters; __VA_ARGS__ + +# if d_m3HasFloat +# define d_m3OpSig d_m3ExpOpSig (f64 _fp0) +# define d_m3OpArgs d_m3ExpOpArgs (_fp0) +# define d_m3OpAllArgs d_m3ExpOpAllArgs (_fp0) +# define d_m3OpDefaultArgs d_m3ExpOpDefaultArgs (0.) +# define d_m3ClearRegisters d_m3ExpClearRegisters (_fp0 = 0.;) +# else +# define d_m3OpSig d_m3BaseOpSig +# define d_m3OpArgs d_m3BaseOpArgs +# define d_m3OpAllArgs d_m3BaseOpAllArgs +# define d_m3OpDefaultArgs d_m3BaseOpDefaultArgs +# define d_m3ClearRegisters d_m3BaseClearRegisters +# endif + +typedef m3ret_t (vectorcall * IM3Operation) (d_m3OpSig); + +#define d_m3RetSig static inline m3ret_t vectorcall +#define d_m3Op(NAME) M3_NO_UBSAN d_m3RetSig op_##NAME (d_m3OpSig) + +#define nextOpImpl() ((IM3Operation)(* _pc))(_pc + 1, d_m3OpArgs) +#define jumpOpImpl(PC) ((IM3Operation)(* PC))( PC + 1, d_m3OpArgs) + +#define nextOpDirect() return nextOpImpl() +#define jumpOpDirect(PC) return jumpOpImpl((pc_t)(PC)) + +d_m3RetSig RunCode (d_m3OpSig) +{ + nextOpDirect(); +} + +d_m3EndExternC + +#endif // m3_exec_defs_h diff --git a/ext/wasm3/source/m3_function.c b/ext/wasm3/source/m3_function.c new file mode 100644 index 0000000..b100cae --- /dev/null +++ b/ext/wasm3/source/m3_function.c @@ -0,0 +1,233 @@ +// +// m3_function.c +// +// Created by Steven Massey on 4/7/21. +// Copyright © 2021 Steven Massey. All rights reserved. +// + +#include "m3_function.h" +#include "m3_env.h" + + +M3Result AllocFuncType (IM3FuncType * o_functionType, u32 i_numTypes) +{ + *o_functionType = (IM3FuncType) m3_Malloc ("M3FuncType", sizeof (M3FuncType) + i_numTypes); + return (*o_functionType) ? m3Err_none : m3Err_mallocFailed; +} + + +bool AreFuncTypesEqual (const IM3FuncType i_typeA, const IM3FuncType i_typeB) +{ + if (i_typeA->numRets == i_typeB->numRets && i_typeA->numArgs == i_typeB->numArgs) + { + return (memcmp (i_typeA->types, i_typeB->types, i_typeA->numRets + i_typeA->numArgs) == 0); + } + + return false; +} + +u16 GetFuncTypeNumParams (const IM3FuncType i_funcType) +{ + return i_funcType ? i_funcType->numArgs : 0; +} + + +u8 GetFuncTypeParamType (const IM3FuncType i_funcType, u16 i_index) +{ + u8 type = c_m3Type_unknown; + + if (i_funcType) + { + if (i_index < i_funcType->numArgs) + { + type = i_funcType->types [i_funcType->numRets + i_index]; + } + } + + return type; +} + + + +u16 GetFuncTypeNumResults (const IM3FuncType i_funcType) +{ + return i_funcType ? i_funcType->numRets : 0; +} + + +u8 GetFuncTypeResultType (const IM3FuncType i_funcType, u16 i_index) +{ + u8 type = c_m3Type_unknown; + + if (i_funcType) + { + if (i_index < i_funcType->numRets) + { + type = i_funcType->types [i_index]; + } + } + + return type; +} + + +//--------------------------------------------------------------------------------------------------------------- + + +void FreeImportInfo (M3ImportInfo * i_info) +{ + m3_Free (i_info->moduleUtf8); + m3_Free (i_info->fieldUtf8); +} + + +void Function_Release (IM3Function i_function) +{ + m3_Free (i_function->constants); + + for (int i = 0; i < i_function->numNames; i++) + { + // name can be an alias of fieldUtf8 + if (i_function->names[i] != i_function->import.fieldUtf8) + { + m3_Free (i_function->names[i]); + } + } + + FreeImportInfo (& i_function->import); + + if (i_function->ownsWasmCode) + m3_Free (i_function->wasm); + + // Function_FreeCompiledCode (func); + +# if (d_m3EnableCodePageRefCounting) + { + m3_Free (i_function->codePageRefs); + i_function->numCodePageRefs = 0; + } +# endif +} + + +void Function_FreeCompiledCode (IM3Function i_function) +{ +# if (d_m3EnableCodePageRefCounting) + { + i_function->compiled = NULL; + + while (i_function->numCodePageRefs--) + { + IM3CodePage page = i_function->codePageRefs [i_function->numCodePageRefs]; + + if (--(page->info.usageCount) == 0) + { +// printf ("free %p\n", page); + } + } + + m3_Free (i_function->codePageRefs); + + Runtime_ReleaseCodePages (i_function->module->runtime); + } +# endif +} + + +cstr_t m3_GetFunctionName (IM3Function i_function) +{ + u16 numNames = 0; + cstr_t *names = GetFunctionNames(i_function, &numNames); + if (numNames > 0) + return names[0]; + else + return ""; +} + + +IM3Module m3_GetFunctionModule (IM3Function i_function) +{ + return i_function ? i_function->module : NULL; +} + + +cstr_t * GetFunctionNames (IM3Function i_function, u16 * o_numNames) +{ + if (!i_function || !o_numNames) + return NULL; + + if (i_function->import.fieldUtf8) + { + *o_numNames = 1; + return &i_function->import.fieldUtf8; + } + else + { + *o_numNames = i_function->numNames; + return i_function->names; + } +} + + +cstr_t GetFunctionImportModuleName (IM3Function i_function) +{ + return (i_function->import.moduleUtf8) ? i_function->import.moduleUtf8 : ""; +} + + +u16 GetFunctionNumArgs (IM3Function i_function) +{ + u16 numArgs = 0; + + if (i_function) + { + if (i_function->funcType) + numArgs = i_function->funcType->numArgs; + } + + return numArgs; +} + +u8 GetFunctionArgType (IM3Function i_function, u32 i_index) +{ + u8 type = c_m3Type_none; + + if (i_index < GetFunctionNumArgs (i_function)) + { + u32 numReturns = i_function->funcType->numRets; + + type = i_function->funcType->types [numReturns + i_index]; + } + + return type; +} + + +u16 GetFunctionNumReturns (IM3Function i_function) +{ + u16 numReturns = 0; + + if (i_function) + { + if (i_function->funcType) + numReturns = i_function->funcType->numRets; + } + + return numReturns; +} + + +u8 GetFunctionReturnType (const IM3Function i_function, u16 i_index) +{ + return i_function ? GetFuncTypeResultType (i_function->funcType, i_index) : c_m3Type_unknown; +} + + +u32 GetFunctionNumArgsAndLocals (IM3Function i_function) +{ + if (i_function) + return i_function->numLocals + GetFunctionNumArgs (i_function); + else + return 0; +} + diff --git a/ext/wasm3/source/m3_function.h b/ext/wasm3/source/m3_function.h new file mode 100644 index 0000000..e25b3f8 --- /dev/null +++ b/ext/wasm3/source/m3_function.h @@ -0,0 +1,102 @@ +// +// m3_function.h +// +// Created by Steven Massey on 4/7/21. +// Copyright © 2021 Steven Massey. All rights reserved. +// + +#ifndef m3_function_h +#define m3_function_h + +#include "m3_core.h" + +d_m3BeginExternC + +//--------------------------------------------------------------------------------------------------------------------------------- + +typedef struct M3FuncType +{ + struct M3FuncType * next; + + u16 numRets; + u16 numArgs; + u8 types []; // returns, then args +} +M3FuncType; + +typedef M3FuncType * IM3FuncType; + + +M3Result AllocFuncType (IM3FuncType * o_functionType, u32 i_numTypes); +bool AreFuncTypesEqual (const IM3FuncType i_typeA, const IM3FuncType i_typeB); + +u16 GetFuncTypeNumParams (const IM3FuncType i_funcType); +u8 GetFuncTypeParamType (const IM3FuncType i_funcType, u16 i_index); + +u16 GetFuncTypeNumResults (const IM3FuncType i_funcType); +u8 GetFuncTypeResultType (const IM3FuncType i_funcType, u16 i_index); + +//--------------------------------------------------------------------------------------------------------------------------------- + +typedef struct M3Function +{ + struct M3Module * module; + + M3ImportInfo import; + + bytes_t wasm; + bytes_t wasmEnd; + + cstr_t names[d_m3MaxDuplicateFunctionImpl]; + u16 numNames; // maximum of d_m3MaxDuplicateFunctionImpl + + IM3FuncType funcType; + + pc_t compiled; + +# if (d_m3EnableCodePageRefCounting) + IM3CodePage * codePageRefs; // array of all pages used + u32 numCodePageRefs; +# endif + +# if defined (DEBUG) + u32 hits; + u32 index; +# endif + + u16 maxStackSlots; + + u16 numRetSlots; + u16 numRetAndArgSlots; + + u16 numLocals; // not including args + u16 numLocalBytes; + + bool ownsWasmCode; + + u16 numConstantBytes; + void * constants; +} +M3Function; + +void Function_Release (IM3Function i_function); +void Function_FreeCompiledCode (IM3Function i_function); + +cstr_t GetFunctionImportModuleName (IM3Function i_function); +cstr_t * GetFunctionNames (IM3Function i_function, u16 * o_numNames); +u16 GetFunctionNumArgs (IM3Function i_function); +u8 GetFunctionArgType (IM3Function i_function, u32 i_index); + +u16 GetFunctionNumReturns (IM3Function i_function); +u8 GetFunctionReturnType (const IM3Function i_function, u16 i_index); + +u32 GetFunctionNumArgsAndLocals (IM3Function i_function); + +cstr_t SPrintFunctionArgList (IM3Function i_function, m3stack_t i_sp); + +//--------------------------------------------------------------------------------------------------------------------------------- + + +d_m3EndExternC + +#endif /* m3_function_h */ diff --git a/ext/wasm3/source/m3_info.c b/ext/wasm3/source/m3_info.c new file mode 100644 index 0000000..f8c0a58 --- /dev/null +++ b/ext/wasm3/source/m3_info.c @@ -0,0 +1,561 @@ +// +// m3_info.c +// +// Created by Steven Massey on 4/27/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#include "m3_env.h" +#include "m3_info.h" +#include "m3_compile.h" + +#ifdef DEBUG + +// a central function you can be breakpoint: +void ExceptionBreakpoint (cstr_t i_exception, cstr_t i_message) +{ + printf ("\nexception: '%s' @ %s\n", i_exception, i_message); + return; +} + + +typedef struct OpInfo +{ + IM3OpInfo info; + m3opcode_t opcode; +} +OpInfo; + +void m3_PrintM3Info () +{ + printf ("\n-- m3 configuration --------------------------------------------\n"); +// printf (" sizeof M3CodePage : %zu bytes (%d slots) \n", sizeof (M3CodePage), c_m3CodePageNumSlots); + printf (" sizeof M3MemPage : %u bytes \n", d_m3MemPageSize); + printf (" sizeof M3Compilation : %zu bytes \n", sizeof (M3Compilation)); + printf (" sizeof M3Function : %zu bytes \n", sizeof (M3Function)); + printf ("----------------------------------------------------------------\n\n"); +} + + +void * v_PrintEnvModuleInfo (IM3Module i_module, u32 * io_index) +{ + printf (" module [%u] name: '%s'; funcs: %d \n", * io_index++, i_module->name, i_module->numFunctions); + + return NULL; +} + + +void m3_PrintRuntimeInfo (IM3Runtime i_runtime) +{ + printf ("\n-- m3 runtime -------------------------------------------------\n"); + + printf (" stack-size: %zu \n\n", i_runtime->numStackSlots * sizeof (m3slot_t)); + + u32 moduleIndex = 0; + ForEachModule (i_runtime, (ModuleVisitor) v_PrintEnvModuleInfo, & moduleIndex); + + printf ("----------------------------------------------------------------\n\n"); +} + + +cstr_t GetTypeName (u8 i_m3Type) +{ + if (i_m3Type < 5) + return c_waTypes [i_m3Type]; + else + return "?"; +} + + +// TODO: these 'static char string []' aren't thread-friendly. though these functions are +// mainly for simple diagnostics during development, it'd be nice if they were fully reliable. + +cstr_t SPrintFuncTypeSignature (IM3FuncType i_funcType) +{ + static char string [256]; + + sprintf (string, "("); + + for (u32 i = 0; i < i_funcType->numArgs; ++i) + { + if (i != 0) + strcat (string, ", "); + + strcat (string, GetTypeName (d_FuncArgType(i_funcType, i))); + } + + strcat (string, ") -> "); + + for (u32 i = 0; i < i_funcType->numRets; ++i) + { + if (i != 0) + strcat (string, ", "); + + strcat (string, GetTypeName (d_FuncRetType(i_funcType, i))); + } + + return string; +} + + +size_t SPrintArg (char * o_string, size_t i_stringBufferSize, voidptr_t i_sp, u8 i_type) +{ + int len = 0; + + * o_string = 0; + + if (i_type == c_m3Type_i32) + len = snprintf (o_string, i_stringBufferSize, "%" PRIi32, * (i32 *) i_sp); + else if (i_type == c_m3Type_i64) + len = snprintf (o_string, i_stringBufferSize, "%" PRIi64, * (i64 *) i_sp); +#if d_m3HasFloat + else if (i_type == c_m3Type_f32) + len = snprintf (o_string, i_stringBufferSize, "%" PRIf32, * (f32 *) i_sp); + else if (i_type == c_m3Type_f64) + len = snprintf (o_string, i_stringBufferSize, "%" PRIf64, * (f64 *) i_sp); +#endif + + len = M3_MAX (0, len); + + return len; +} + + +cstr_t SPrintValue (void * i_value, u8 i_type) +{ + static char string [100]; + SPrintArg (string, 100, (m3stack_t) i_value, i_type); + return string; +} + + +cstr_t SPrintFunctionArgList (IM3Function i_function, m3stack_t i_sp) +{ + int ret; + static char string [256]; + + char * s = string; + ccstr_t e = string + sizeof(string) - 1; + + ret = snprintf (s, e-s, "("); + s += M3_MAX (0, ret); + + u64 * argSp = (u64 *) i_sp; + + IM3FuncType funcType = i_function->funcType; + if (funcType) + { + u32 numArgs = funcType->numArgs; + + for (u32 i = 0; i < numArgs; ++i) + { + u8 type = d_FuncArgType(funcType, i); + + ret = snprintf (s, e-s, "%s: ", c_waTypes [type]); + s += M3_MAX (0, ret); + + s += SPrintArg (s, e-s, argSp + i, type); + + if (i != numArgs - 1) { + ret = snprintf (s, e-s, ", "); + s += M3_MAX (0, ret); + } + } + } + else printf ("null signature"); + + ret = snprintf (s, e-s, ")"); + s += M3_MAX (0, ret); + + return string; +} + +static +OpInfo find_operation_info (IM3Operation i_operation) +{ + OpInfo opInfo = { NULL, 0 }; + + if (!i_operation) return opInfo; + + // TODO: find also extended opcodes + for (u32 i = 0; i <= 0xff; ++i) + { + IM3OpInfo oi = GetOpInfo (i); + + if (oi->type != c_m3Type_unknown) + { + for (u32 o = 0; o < 4; ++o) + { + if (oi->operations [o] == i_operation) + { + opInfo.info = oi; + opInfo.opcode = i; + break; + } + } + } + else break; + } + + return opInfo; +} + + +#undef fetch +#define fetch(TYPE) (* (TYPE *) ((*o_pc)++)) + +#define d_m3Decoder(FUNC) void Decode_##FUNC (char * o_string, u8 i_opcode, IM3Operation i_operation, IM3OpInfo i_opInfo, pc_t * o_pc) + +d_m3Decoder (Call) +{ + void * function = fetch (void *); + i32 stackOffset = fetch (i32); + + sprintf (o_string, "%p; stack-offset: %d", function, stackOffset); +} + + +d_m3Decoder (Entry) +{ + IM3Function function = fetch (IM3Function); + + // only prints out the first registered name for the function + sprintf (o_string, "%s", m3_GetFunctionName(function)); +} + + +d_m3Decoder (f64_Store) +{ + if (i_operation == i_opInfo->operations [0]) + { + u32 operand = fetch (u32); + u32 offset = fetch (u32); + + sprintf (o_string, "offset= slot:%d + immediate:%d", operand, offset); + } + +// sprintf (o_string, "%s", function->name); +} + + +d_m3Decoder (Branch) +{ + void * target = fetch (void *); + sprintf (o_string, "%p", target); +} + +d_m3Decoder (BranchTable) +{ + u32 slot = fetch (u32); + + o_string += sprintf (o_string, "slot: %" PRIu32 "; targets: ", slot); + +// IM3Function function = fetch2 (IM3Function); + + i32 targets = fetch (i32); + + for (i32 i = 0; i < targets; ++i) + { + pc_t addr = fetch (pc_t); + o_string += sprintf (o_string, "%" PRIi32 "=%p, ", i, addr); + } + + pc_t addr = fetch (pc_t); + sprintf (o_string, "def=%p ", addr); +} + + +d_m3Decoder (Const) +{ + u64 value = fetch (u64); i32 offset = fetch (i32); + sprintf (o_string, " slot [%d] = %" PRIu64, offset, value); +} + + +#undef fetch + +void DecodeOperation (char * o_string, u8 i_opcode, IM3Operation i_operation, IM3OpInfo i_opInfo, pc_t * o_pc) +{ + #define d_m3Decode(OPCODE, FUNC) case OPCODE: Decode_##FUNC (o_string, i_opcode, i_operation, i_opInfo, o_pc); break; + + switch (i_opcode) + { +// d_m3Decode (0xc0, Const) + d_m3Decode (0xc5, Entry) + d_m3Decode (c_waOp_call, Call) + d_m3Decode (c_waOp_branch, Branch) + d_m3Decode (c_waOp_branchTable, BranchTable) + d_m3Decode (0x39, f64_Store) + } +} + +// WARNING/TODO: this isn't fully implemented. it blindly assumes each word is a Operation pointer +// and, if an operation happens to missing from the c_operations table it won't be recognized here +void dump_code_page (IM3CodePage i_codePage, pc_t i_startPC) +{ + m3log (code, "code page seq: %d", i_codePage->info.sequence); + + pc_t pc = i_startPC ? i_startPC : GetPageStartPC (i_codePage); + pc_t end = GetPagePC (i_codePage); + + m3log (code, "---------------------------------------------------------------------------------------"); + + while (pc < end) + { + pc_t operationPC = pc; + IM3Operation op = (IM3Operation) (* pc++); + + OpInfo i = find_operation_info (op); + + if (i.info) + { + char infoString [8*1024] = { 0 }; + + DecodeOperation (infoString, i.opcode, op, i.info, & pc); + + m3log (code, "%p | %20s %s", operationPC, i.info->name, infoString); + } + else + m3log (code, "%p | %p", operationPC, op); + + } + + m3log (code, "---------------------------------------------------------------------------------------"); + + m3log (code, "free-lines: %d", i_codePage->info.numLines - i_codePage->info.lineIndex); +} + + +void dump_type_stack (IM3Compilation o) +{ + /* Reminders about how the stack works! :) + -- args & locals remain on the type stack for duration of the function. Denoted with a constant 'A' and 'L' in this dump. + -- the initial stack dumps originate from the CompileLocals () function, so these identifiers won't/can't be + applied until this compilation stage is finished + -- constants are not statically represented in the type stack (like args & constants) since they don't have/need + write counts + + -- the number shown for static args and locals (value in wasmStack [i]) represents the write count for the variable + + -- (does Wasm ever write to an arg? I dunno/don't remember.) + -- the number for the dynamic stack values represents the slot number. + -- if the slot index points to arg, local or constant it's denoted with a lowercase 'a', 'l' or 'c' + + */ + + // for the assert at end of dump: + i32 regAllocated [2] = { (i32) IsRegisterAllocated (o, 0), (i32) IsRegisterAllocated (o, 1) }; + + // display whether r0 or fp0 is allocated. these should then also be reflected somewhere in the stack too. + d_m3Log(stack, "\n"); + d_m3Log(stack, " "); + printf ("%s %s ", regAllocated [0] ? "(r0)" : " ", regAllocated [1] ? "(fp0)" : " "); + printf("\n"); + + for (u32 p = 1; p <= 2; ++p) + { + d_m3Log(stack, " "); + + for (u32 i = 0; i < o->stackIndex; ++i) + { + if (i > 0 and i == o->stackFirstDynamicIndex) + printf ("#"); + + if (i == o->block.blockStackIndex) + printf (">"); + + const char * type = c_waCompactTypes [o->typeStack [i]]; + + const char * location = ""; + + i32 slot = o->wasmStack [i]; + + if (IsRegisterSlotAlias (slot)) + { + bool isFp = IsFpRegisterSlotAlias (slot); + location = isFp ? "/f" : "/r"; + + regAllocated [isFp]--; + slot = -1; + } + else + { + if (slot < o->slotFirstDynamicIndex) + { + if (slot >= o->slotFirstConstIndex) + location = "c"; + else if (slot >= o->function->numRetAndArgSlots) + location = "L"; + else + location = "a"; + } + } + + char item [100]; + + if (slot >= 0) + sprintf (item, "%s%s%d", type, location, slot); + else + sprintf (item, "%s%s", type, location); + + if (p == 1) + { + size_t s = strlen (item); + + sprintf (item, "%d", i); + + while (strlen (item) < s) + strcat (item, " "); + } + + printf ("|%s ", item); + + } + printf ("\n"); + } + +// for (u32 r = 0; r < 2; ++r) +// d_m3Assert (regAllocated [r] == 0); // reg allocation & stack out of sync + + u16 maxSlot = GetMaxUsedSlotPlusOne (o); + + if (maxSlot > o->slotFirstDynamicIndex) + { + d_m3Log (stack, " -"); + + for (u16 i = o->slotFirstDynamicIndex; i < maxSlot; ++i) + printf ("----"); + + printf ("\n"); + + d_m3Log (stack, " slot |"); + for (u16 i = o->slotFirstDynamicIndex; i < maxSlot; ++i) + printf ("%3d|", i); + + printf ("\n"); + d_m3Log (stack, " alloc |"); + + for (u16 i = o->slotFirstDynamicIndex; i < maxSlot; ++i) + { + printf ("%3d|", o->m3Slots [i]); + } + + printf ("\n"); + } + d_m3Log(stack, "\n"); +} + + +static const char * GetOpcodeIndentionString (i32 blockDepth) +{ + blockDepth += 1; + + if (blockDepth < 0) + blockDepth = 0; + + static const char * s_spaces = "......................................................................................."; + const char * indent = s_spaces + strlen (s_spaces); + indent -= (blockDepth * 2); + if (indent < s_spaces) + indent = s_spaces; + + return indent; +} + + +const char * get_indention_string (IM3Compilation o) +{ + return GetOpcodeIndentionString (o->block.depth+4); +} + + +void log_opcode (IM3Compilation o, m3opcode_t i_opcode) +{ + i32 depth = o->block.depth; + if (i_opcode == c_waOp_end or i_opcode == c_waOp_else) + depth--; + + m3log (compile, "%4d | 0x%02x %s %s", o->numOpcodes++, i_opcode, GetOpcodeIndentionString (depth), GetOpInfo(i_opcode)->name); +} + + +void log_emit (IM3Compilation o, IM3Operation i_operation) +{ + OpInfo i = find_operation_info (i_operation); + + d_m3Log(emit, ""); + if (i.info) + { + printf ("%p: %s\n", GetPagePC (o->page), i.info->name); + } + else printf ("not found: %p\n", i_operation); +} + +#endif // DEBUG + + +# if d_m3EnableOpProfiling + +typedef struct M3ProfilerSlot +{ + cstr_t opName; + u64 hitCount; +} +M3ProfilerSlot; + +static M3ProfilerSlot s_opProfilerCounts [d_m3ProfilerSlotMask + 1] = {}; + +void ProfileHit (cstr_t i_operationName) +{ + u64 ptr = (u64) i_operationName; + + M3ProfilerSlot * slot = & s_opProfilerCounts [ptr & d_m3ProfilerSlotMask]; + + if (slot->opName) + { + if (slot->opName != i_operationName) + { + m3_Abort ("profiler slot collision; increase d_m3ProfilerSlotMask"); + } + } + + slot->opName = i_operationName; + slot->hitCount++; +} + + +void m3_PrintProfilerInfo () +{ + M3ProfilerSlot dummy; + M3ProfilerSlot * maxSlot = & dummy; + + do + { + maxSlot->hitCount = 0; + + for (u32 i = 0; i <= d_m3ProfilerSlotMask; ++i) + { + M3ProfilerSlot * slot = & s_opProfilerCounts [i]; + + if (slot->opName) + { + if (slot->hitCount > maxSlot->hitCount) + maxSlot = slot; + } + } + + if (maxSlot->opName) + { + fprintf (stderr, "%13llu %s\n", maxSlot->hitCount, maxSlot->opName); + maxSlot->opName = NULL; + } + } + while (maxSlot->hitCount); +} + +# else + +void m3_PrintProfilerInfo () {} + +# endif + diff --git a/ext/wasm3/source/m3_info.h b/ext/wasm3/source/m3_info.h new file mode 100644 index 0000000..228e93f --- /dev/null +++ b/ext/wasm3/source/m3_info.h @@ -0,0 +1,38 @@ +// +// m3_info.h +// +// Created by Steven Massey on 12/6/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#ifndef m3_info_h +#define m3_info_h + +#include "m3_compile.h" + +d_m3BeginExternC + +void ProfileHit (cstr_t i_operationName); + +#ifdef DEBUG + +void dump_type_stack (IM3Compilation o); +void log_opcode (IM3Compilation o, m3opcode_t i_opcode); +const char * get_indention_string (IM3Compilation o); +void log_emit (IM3Compilation o, IM3Operation i_operation); + +cstr_t SPrintFuncTypeSignature (IM3FuncType i_funcType); + +#else // DEBUG + +#define dump_type_stack(...) {} +#define log_opcode(...) {} +#define get_indention_string(...) "" +#define emit_stack_dump(...) {} +#define log_emit(...) {} + +#endif // DEBUG + +d_m3EndExternC + +#endif // m3_info_h diff --git a/ext/wasm3/source/m3_math_utils.h b/ext/wasm3/source/m3_math_utils.h new file mode 100644 index 0000000..8c6ff6d --- /dev/null +++ b/ext/wasm3/source/m3_math_utils.h @@ -0,0 +1,268 @@ +// +// m3_math_utils.h +// +// Created by Volodymyr Shymanksyy on 8/10/19. +// Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. +// + +#ifndef m3_math_utils_h +#define m3_math_utils_h + +#include "m3_core.h" + +#include + +#if defined(M3_COMPILER_MSVC) + +#include + +#define __builtin_popcount __popcnt + +static inline +int __builtin_ctz(uint32_t x) { + unsigned long ret; + _BitScanForward(&ret, x); + return (int)ret; +} + +static inline +int __builtin_clz(uint32_t x) { + unsigned long ret; + _BitScanReverse(&ret, x); + return (int)(31 ^ ret); +} + + + +#ifdef _WIN64 + +#define __builtin_popcountll __popcnt64 + +static inline +int __builtin_ctzll(uint64_t value) { + unsigned long ret; + _BitScanForward64(&ret, value); + return (int)ret; +} + +static inline +int __builtin_clzll(uint64_t value) { + unsigned long ret; + _BitScanReverse64(&ret, value); + return (int)(63 ^ ret); +} + +#else // _WIN64 + +#define __builtin_popcountll(x) (__popcnt((x) & 0xFFFFFFFF) + __popcnt((x) >> 32)) + +static inline +int __builtin_ctzll(uint64_t value) { + //if (value == 0) return 64; // Note: ctz(0) result is undefined anyway + uint32_t msh = (uint32_t)(value >> 32); + uint32_t lsh = (uint32_t)(value & 0xFFFFFFFF); + if (lsh != 0) return __builtin_ctz(lsh); + return 32 + __builtin_ctz(msh); +} + +static inline +int __builtin_clzll(uint64_t value) { + //if (value == 0) return 64; // Note: clz(0) result is undefined anyway + uint32_t msh = (uint32_t)(value >> 32); + uint32_t lsh = (uint32_t)(value & 0xFFFFFFFF); + if (msh != 0) return __builtin_clz(msh); + return 32 + __builtin_clz(lsh); +} + +#endif // _WIN64 + +#endif // defined(M3_COMPILER_MSVC) + + +// TODO: not sure why, signbit is actually defined in math.h +#if (defined(ESP8266) || defined(ESP32)) && !defined(signbit) + #define signbit(__x) \ + ((sizeof(__x) == sizeof(float)) ? __signbitf(__x) : __signbitd(__x)) +#endif + +#if defined(__AVR__) + +static inline +float rintf( float arg ) { + union { float f; uint32_t i; } u; + u.f = arg; + uint32_t ux = u.i & 0x7FFFFFFF; + if (M3_UNLIKELY(ux == 0 || ux > 0x5A000000)) { + return arg; + } + return (float)lrint(arg); +} + +static inline +double rint( double arg ) { + union { double f; uint32_t i[2]; } u; + u.f = arg; + uint32_t ux = u.i[1] & 0x7FFFFFFF; + if (M3_UNLIKELY((ux == 0 && u.i[0] == 0) || ux > 0x433FFFFF)) { + return arg; + } + return (double)lrint(arg); +} + +//TODO +static inline +uint64_t strtoull(const char* str, char** endptr, int base) { + return 0; +} + +#endif + +/* + * Rotr, Rotl + */ + +static inline +u32 rotl32(u32 n, unsigned c) { + const unsigned mask = CHAR_BIT * sizeof(n) - 1; + c &= mask & 31; + return (n << c) | (n >> ((-c) & mask)); +} + +static inline +u32 rotr32(u32 n, unsigned c) { + const unsigned mask = CHAR_BIT * sizeof(n) - 1; + c &= mask & 31; + return (n >> c) | (n << ((-c) & mask)); +} + +static inline +u64 rotl64(u64 n, unsigned c) { + const unsigned mask = CHAR_BIT * sizeof(n) - 1; + c &= mask & 63; + return (n << c) | (n >> ((-c) & mask)); +} + +static inline +u64 rotr64(u64 n, unsigned c) { + const unsigned mask = CHAR_BIT * sizeof(n) - 1; + c &= mask & 63; + return (n >> c) | (n << ((-c) & mask)); +} + +/* + * Integer Div, Rem + */ + +#define OP_DIV_U(RES, A, B) \ + if (M3_UNLIKELY(B == 0)) newTrap (m3Err_trapDivisionByZero); \ + RES = A / B; + +#define OP_REM_U(RES, A, B) \ + if (M3_UNLIKELY(B == 0)) newTrap (m3Err_trapDivisionByZero); \ + RES = A % B; + +// 2's complement detection +#if (INT_MIN != -INT_MAX) + + #define OP_DIV_S(RES, A, B, TYPE_MIN) \ + if (M3_UNLIKELY(B == 0)) newTrap (m3Err_trapDivisionByZero); \ + if (M3_UNLIKELY(B == -1 and A == TYPE_MIN)) { \ + newTrap (m3Err_trapIntegerOverflow); \ + } \ + RES = A / B; + + #define OP_REM_S(RES, A, B, TYPE_MIN) \ + if (M3_UNLIKELY(B == 0)) newTrap (m3Err_trapDivisionByZero); \ + if (M3_UNLIKELY(B == -1 and A == TYPE_MIN)) RES = 0; \ + else RES = A % B; + +#else + + #define OP_DIV_S(RES, A, B, TYPE_MIN) OP_DIV_U(RES, A, B) + #define OP_REM_S(RES, A, B, TYPE_MIN) OP_REM_U(RES, A, B) + +#endif + +/* + * Trunc + */ + +#define OP_TRUNC(RES, A, TYPE, RMIN, RMAX) \ + if (M3_UNLIKELY(isnan(A))) { \ + newTrap (m3Err_trapIntegerConversion); \ + } \ + if (M3_UNLIKELY(A <= RMIN or A >= RMAX)) { \ + newTrap (m3Err_trapIntegerOverflow); \ + } \ + RES = (TYPE)A; + + +#define OP_I32_TRUNC_F32(RES, A) OP_TRUNC(RES, A, i32, -2147483904.0f, 2147483648.0f) +#define OP_U32_TRUNC_F32(RES, A) OP_TRUNC(RES, A, u32, -1.0f, 4294967296.0f) +#define OP_I32_TRUNC_F64(RES, A) OP_TRUNC(RES, A, i32, -2147483649.0 , 2147483648.0 ) +#define OP_U32_TRUNC_F64(RES, A) OP_TRUNC(RES, A, u32, -1.0 , 4294967296.0 ) + +#define OP_I64_TRUNC_F32(RES, A) OP_TRUNC(RES, A, i64, -9223373136366403584.0f, 9223372036854775808.0f) +#define OP_U64_TRUNC_F32(RES, A) OP_TRUNC(RES, A, u64, -1.0f, 18446744073709551616.0f) +#define OP_I64_TRUNC_F64(RES, A) OP_TRUNC(RES, A, i64, -9223372036854777856.0 , 9223372036854775808.0 ) +#define OP_U64_TRUNC_F64(RES, A) OP_TRUNC(RES, A, u64, -1.0 , 18446744073709551616.0 ) + +#define OP_TRUNC_SAT(RES, A, TYPE, RMIN, RMAX, IMIN, IMAX) \ + if (M3_UNLIKELY(isnan(A))) { \ + RES = 0; \ + } else if (M3_UNLIKELY(A <= RMIN)) { \ + RES = IMIN; \ + } else if (M3_UNLIKELY(A >= RMAX)) { \ + RES = IMAX; \ + } else { \ + RES = (TYPE)A; \ + } + +#define OP_I32_TRUNC_SAT_F32(RES, A) OP_TRUNC_SAT(RES, A, i32, -2147483904.0f, 2147483648.0f, INT32_MIN, INT32_MAX) +#define OP_U32_TRUNC_SAT_F32(RES, A) OP_TRUNC_SAT(RES, A, u32, -1.0f, 4294967296.0f, 0UL, UINT32_MAX) +#define OP_I32_TRUNC_SAT_F64(RES, A) OP_TRUNC_SAT(RES, A, i32, -2147483649.0 , 2147483648.0, INT32_MIN, INT32_MAX) +#define OP_U32_TRUNC_SAT_F64(RES, A) OP_TRUNC_SAT(RES, A, u32, -1.0 , 4294967296.0, 0UL, UINT32_MAX) + +#define OP_I64_TRUNC_SAT_F32(RES, A) OP_TRUNC_SAT(RES, A, i64, -9223373136366403584.0f, 9223372036854775808.0f, INT64_MIN, INT64_MAX) +#define OP_U64_TRUNC_SAT_F32(RES, A) OP_TRUNC_SAT(RES, A, u64, -1.0f, 18446744073709551616.0f, 0ULL, UINT64_MAX) +#define OP_I64_TRUNC_SAT_F64(RES, A) OP_TRUNC_SAT(RES, A, i64, -9223372036854777856.0 , 9223372036854775808.0, INT64_MIN, INT64_MAX) +#define OP_U64_TRUNC_SAT_F64(RES, A) OP_TRUNC_SAT(RES, A, u64, -1.0 , 18446744073709551616.0, 0ULL, UINT64_MAX) + +/* + * Min, Max + */ + +#if d_m3HasFloat + +#include + +static inline +f32 min_f32(f32 a, f32 b) { + if (M3_UNLIKELY(isnan(a) or isnan(b))) return NAN; + if (M3_UNLIKELY(a == 0 and a == b)) return signbit(a) ? a : b; + return a > b ? b : a; +} + +static inline +f32 max_f32(f32 a, f32 b) { + if (M3_UNLIKELY(isnan(a) or isnan(b))) return NAN; + if (M3_UNLIKELY(a == 0 and a == b)) return signbit(a) ? b : a; + return a > b ? a : b; +} + +static inline +f64 min_f64(f64 a, f64 b) { + if (M3_UNLIKELY(isnan(a) or isnan(b))) return NAN; + if (M3_UNLIKELY(a == 0 and a == b)) return signbit(a) ? a : b; + return a > b ? b : a; +} + +static inline +f64 max_f64(f64 a, f64 b) { + if (M3_UNLIKELY(isnan(a) or isnan(b))) return NAN; + if (M3_UNLIKELY(a == 0 and a == b)) return signbit(a) ? b : a; + return a > b ? a : b; +} +#endif + +#endif // m3_math_utils_h diff --git a/ext/wasm3/source/m3_module.c b/ext/wasm3/source/m3_module.c new file mode 100644 index 0000000..5742db6 --- /dev/null +++ b/ext/wasm3/source/m3_module.c @@ -0,0 +1,171 @@ +// +// m3_module.c +// +// Created by Steven Massey on 5/7/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#include "m3_env.h" +#include "m3_exception.h" + + +void Module_FreeFunctions (IM3Module i_module) +{ + for (u32 i = 0; i < i_module->numFunctions; ++i) + { + IM3Function func = & i_module->functions [i]; + Function_Release (func); + } +} + + +void m3_FreeModule (IM3Module i_module) +{ + if (i_module) + { + m3log (module, "freeing module: %s (funcs: %d; segments: %d)", + i_module->name, i_module->numFunctions, i_module->numDataSegments); + + Module_FreeFunctions (i_module); + + m3_Free (i_module->functions); + //m3_Free (i_module->imports); + m3_Free (i_module->funcTypes); + m3_Free (i_module->dataSegments); + m3_Free (i_module->table0); + + for (u32 i = 0; i < i_module->numGlobals; ++i) + { + m3_Free (i_module->globals[i].name); + FreeImportInfo(&(i_module->globals[i].import)); + } + m3_Free (i_module->globals); + + m3_Free (i_module); + } +} + + +M3Result Module_AddGlobal (IM3Module io_module, IM3Global * o_global, u8 i_type, bool i_mutable, bool i_isImported) +{ +_try { + u32 index = io_module->numGlobals++; + io_module->globals = m3_ReallocArray (M3Global, io_module->globals, io_module->numGlobals, index); + _throwifnull (io_module->globals); + M3Global * global = & io_module->globals [index]; + + global->type = i_type; + global->imported = i_isImported; + global->isMutable = i_mutable; + + if (o_global) + * o_global = global; + +} _catch: + return result; +} + +M3Result Module_PreallocFunctions (IM3Module io_module, u32 i_totalFunctions) +{ +_try { + if (i_totalFunctions > io_module->allFunctions) { + io_module->functions = m3_ReallocArray (M3Function, io_module->functions, i_totalFunctions, io_module->allFunctions); + io_module->allFunctions = i_totalFunctions; + _throwifnull (io_module->functions); + } +} _catch: + return result; +} + +M3Result Module_AddFunction (IM3Module io_module, u32 i_typeIndex, IM3ImportInfo i_importInfo) +{ +_try { + + u32 index = io_module->numFunctions++; +_ (Module_PreallocFunctions(io_module, io_module->numFunctions)); + + _throwif ("type sig index out of bounds", i_typeIndex >= io_module->numFuncTypes); + + IM3FuncType ft = io_module->funcTypes [i_typeIndex]; + + IM3Function func = Module_GetFunction (io_module, index); + func->funcType = ft; + +# ifdef DEBUG + func->index = index; +# endif + + if (i_importInfo and func->numNames == 0) + { + func->import = * i_importInfo; + func->names[0] = i_importInfo->fieldUtf8; + func->numNames = 1; + } + + m3log (module, " added function: %3d; sig: %d", index, i_typeIndex); + +} _catch: + return result; +} + +#ifdef DEBUG +void Module_GenerateNames (IM3Module i_module) +{ + for (u32 i = 0; i < i_module->numFunctions; ++i) + { + IM3Function func = & i_module->functions [i]; + + if (func->numNames == 0) + { + char* buff = m3_AllocArray(char, 16); + snprintf(buff, 16, "$func%d", i); + func->names[0] = buff; + func->numNames = 1; + } + } + for (u32 i = 0; i < i_module->numGlobals; ++i) + { + IM3Global global = & i_module->globals [i]; + + if (global->name == NULL) + { + char* buff = m3_AllocArray(char, 16); + snprintf(buff, 16, "$global%d", i); + global->name = buff; + } + } +} +#endif + +IM3Function Module_GetFunction (IM3Module i_module, u32 i_functionIndex) +{ + IM3Function func = NULL; + + if (i_functionIndex < i_module->numFunctions) + { + func = & i_module->functions [i_functionIndex]; + //func->module = i_module; + } + + return func; +} + + +const char* m3_GetModuleName (IM3Module i_module) +{ + if (!i_module || !i_module->name) + return ".unnamed"; + + return i_module->name; +} + +void m3_SetModuleName (IM3Module i_module, const char* name) +{ + if (i_module) i_module->name = name; +} + +IM3Runtime m3_GetModuleRuntime (IM3Module i_module) +{ + return i_module ? i_module->runtime : NULL; +} + diff --git a/ext/wasm3/source/m3_parse.c b/ext/wasm3/source/m3_parse.c new file mode 100644 index 0000000..edf426c --- /dev/null +++ b/ext/wasm3/source/m3_parse.c @@ -0,0 +1,649 @@ +// +// m3_parse.c +// +// Created by Steven Massey on 4/19/19. +// Copyright © 2019 Steven Massey. All rights reserved. +// + +#include "m3_env.h" +#include "m3_compile.h" +#include "m3_exception.h" +#include "m3_info.h" + + +M3Result ParseType_Table (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + return result; +} + + +M3Result ParseType_Memory (M3MemoryInfo * o_memory, bytes_t * io_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + u8 flag; + +_ (ReadLEB_u7 (& flag, io_bytes, i_end)); // really a u1 +_ (ReadLEB_u32 (& o_memory->initPages, io_bytes, i_end)); + + o_memory->maxPages = 0; + if (flag) +_ (ReadLEB_u32 (& o_memory->maxPages, io_bytes, i_end)); + + _catch: return result; +} + + +M3Result ParseSection_Type (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end) +{ + IM3FuncType ftype = NULL; + +_try { + u32 numTypes; +_ (ReadLEB_u32 (& numTypes, & i_bytes, i_end)); m3log (parse, "** Type [%d]", numTypes); + + _throwif("too many types", numTypes > d_m3MaxSaneTypesCount); + + if (numTypes) + { + // table of IM3FuncType (that point to the actual M3FuncType struct in the Environment) + io_module->funcTypes = m3_AllocArray (IM3FuncType, numTypes); + _throwifnull (io_module->funcTypes); + io_module->numFuncTypes = numTypes; + + for (u32 i = 0; i < numTypes; ++i) + { + i8 form; +_ (ReadLEB_i7 (& form, & i_bytes, i_end)); + _throwif (m3Err_wasmMalformed, form != -32); // for Wasm MVP + + u32 numArgs; +_ (ReadLEB_u32 (& numArgs, & i_bytes, i_end)); + + _throwif (m3Err_tooManyArgsRets, numArgs > d_m3MaxSaneFunctionArgRetCount); +#if defined(M3_COMPILER_MSVC) + u8 argTypes [d_m3MaxSaneFunctionArgRetCount]; +#else + u8 argTypes[numArgs+1]; // make ubsan happy +#endif + for (u32 a = 0; a < numArgs; ++a) + { + i8 wasmType; + u8 argType; +_ (ReadLEB_i7 (& wasmType, & i_bytes, i_end)); +_ (NormalizeType (& argType, wasmType)); + + argTypes[a] = argType; + } + + u32 numRets; +_ (ReadLEB_u32 (& numRets, & i_bytes, i_end)); + _throwif (m3Err_tooManyArgsRets, (u64)(numRets) + numArgs > d_m3MaxSaneFunctionArgRetCount); + +_ (AllocFuncType (& ftype, numRets + numArgs)); + ftype->numArgs = numArgs; + ftype->numRets = numRets; + + for (u32 r = 0; r < numRets; ++r) + { + i8 wasmType; + u8 retType; +_ (ReadLEB_i7 (& wasmType, & i_bytes, i_end)); +_ (NormalizeType (& retType, wasmType)); + + ftype->types[r] = retType; + } + memcpy (ftype->types + numRets, argTypes, numArgs); m3log (parse, " type %2d: %s", i, SPrintFuncTypeSignature (ftype)); + + Environment_AddFuncType (io_module->environment, & ftype); + io_module->funcTypes [i] = ftype; + ftype = NULL; // ownership transferred to environment + } + } + +} _catch: + + if (result) + { + m3_Free (ftype); + // FIX: M3FuncTypes in the table are leaked + m3_Free (io_module->funcTypes); + io_module->numFuncTypes = 0; + } + + return result; +} + + +M3Result ParseSection_Function (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + u32 numFunctions; +_ (ReadLEB_u32 (& numFunctions, & i_bytes, i_end)); m3log (parse, "** Function [%d]", numFunctions); + + _throwif("too many functions", numFunctions > d_m3MaxSaneFunctionsCount); + +_ (Module_PreallocFunctions(io_module, io_module->numFunctions + numFunctions)); + + for (u32 i = 0; i < numFunctions; ++i) + { + u32 funcTypeIndex; +_ (ReadLEB_u32 (& funcTypeIndex, & i_bytes, i_end)); + +_ (Module_AddFunction (io_module, funcTypeIndex, NULL /* import info */)); + } + + _catch: return result; +} + + +M3Result ParseSection_Import (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + M3ImportInfo import = { NULL, NULL }, clearImport = { NULL, NULL }; + + u32 numImports; +_ (ReadLEB_u32 (& numImports, & i_bytes, i_end)); m3log (parse, "** Import [%d]", numImports); + + _throwif("too many imports", numImports > d_m3MaxSaneImportsCount); + + // Most imports are functions, so we won't waste much space anyway (if any) +_ (Module_PreallocFunctions(io_module, numImports)); + + for (u32 i = 0; i < numImports; ++i) + { + u8 importKind; + +_ (Read_utf8 (& import.moduleUtf8, & i_bytes, i_end)); +_ (Read_utf8 (& import.fieldUtf8, & i_bytes, i_end)); +_ (Read_u8 (& importKind, & i_bytes, i_end)); m3log (parse, " kind: %d '%s.%s' ", + (u32) importKind, import.moduleUtf8, import.fieldUtf8); + switch (importKind) + { + case d_externalKind_function: + { + u32 typeIndex; +_ (ReadLEB_u32 (& typeIndex, & i_bytes, i_end)) + +_ (Module_AddFunction (io_module, typeIndex, & import)) + import = clearImport; + + io_module->numFuncImports++; + } + break; + + case d_externalKind_table: +// result = ParseType_Table (& i_bytes, i_end); + break; + + case d_externalKind_memory: + { +_ (ParseType_Memory (& io_module->memoryInfo, & i_bytes, i_end)); + io_module->memoryImported = true; + } + break; + + case d_externalKind_global: + { + i8 waType; + u8 type, isMutable; + +_ (ReadLEB_i7 (& waType, & i_bytes, i_end)); +_ (NormalizeType (& type, waType)); +_ (ReadLEB_u7 (& isMutable, & i_bytes, i_end)); m3log (parse, " global: %s mutable=%d", c_waTypes [type], (u32) isMutable); + + IM3Global global; +_ (Module_AddGlobal (io_module, & global, type, isMutable, true /* isImport */)); + global->import = import; + import = clearImport; + } + break; + + default: + _throw (m3Err_wasmMalformed); + } + + FreeImportInfo (& import); + } + + _catch: + + FreeImportInfo (& import); + + return result; +} + + +M3Result ParseSection_Export (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + const char * utf8 = NULL; + + u32 numExports; +_ (ReadLEB_u32 (& numExports, & i_bytes, i_end)); m3log (parse, "** Export [%d]", numExports); + + _throwif("too many exports", numExports > d_m3MaxSaneExportsCount); + + for (u32 i = 0; i < numExports; ++i) + { + u8 exportKind; + u32 index; + +_ (Read_utf8 (& utf8, & i_bytes, i_end)); +_ (Read_u8 (& exportKind, & i_bytes, i_end)); +_ (ReadLEB_u32 (& index, & i_bytes, i_end)); m3log (parse, " index: %3d; kind: %d; export: '%s'; ", index, (u32) exportKind, utf8); + + if (exportKind == d_externalKind_function) + { + _throwif(m3Err_wasmMalformed, index >= io_module->numFunctions); + IM3Function func = &(io_module->functions [index]); + if (func->numNames < d_m3MaxDuplicateFunctionImpl) + { + func->names[func->numNames++] = utf8; + utf8 = NULL; // ownership transferred to M3Function + } + } + else if (exportKind == d_externalKind_global) + { + _throwif(m3Err_wasmMalformed, index >= io_module->numGlobals); + IM3Global global = &(io_module->globals [index]); + m3_Free (global->name); + global->name = utf8; + utf8 = NULL; // ownership transferred to M3Global + } + + m3_Free (utf8); + } + +_catch: + m3_Free (utf8); + return result; +} + + +M3Result ParseSection_Start (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + u32 startFuncIndex; +_ (ReadLEB_u32 (& startFuncIndex, & i_bytes, i_end)); m3log (parse, "** Start Function: %d", startFuncIndex); + + if (startFuncIndex < io_module->numFunctions) + { + io_module->startFunction = startFuncIndex; + } + else result = "start function index out of bounds"; + + _catch: return result; +} + + +M3Result Parse_InitExpr (M3Module * io_module, bytes_t * io_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + // this doesn't generate code pages. just walks the wasm bytecode to find the end + +#if defined(d_m3PreferStaticAlloc) + static M3Compilation compilation; +#else + M3Compilation compilation; +#endif + compilation = (M3Compilation){ .runtime = NULL, .module = io_module, .wasm = * io_bytes, .wasmEnd = i_end }; + + result = CompileBlockStatements (& compilation); + + * io_bytes = compilation.wasm; + + return result; +} + + +M3Result ParseSection_Element (IM3Module io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + u32 numSegments; +_ (ReadLEB_u32 (& numSegments, & i_bytes, i_end)); m3log (parse, "** Element [%d]", numSegments); + + _throwif ("too many element segments", numSegments > d_m3MaxSaneElementSegments); + + io_module->elementSection = i_bytes; + io_module->elementSectionEnd = i_end; + io_module->numElementSegments = numSegments; + + _catch: return result; +} + + +M3Result ParseSection_Code (M3Module * io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result; + + u32 numFunctions; +_ (ReadLEB_u32 (& numFunctions, & i_bytes, i_end)); m3log (parse, "** Code [%d]", numFunctions); + + if (numFunctions != io_module->numFunctions - io_module->numFuncImports) + { + _throw ("mismatched function count in code section"); + } + + for (u32 f = 0; f < numFunctions; ++f) + { + const u8 * start = i_bytes; + + u32 size; +_ (ReadLEB_u32 (& size, & i_bytes, i_end)); + + if (size) + { + const u8 * ptr = i_bytes; + i_bytes += size; + + if (i_bytes <= i_end) + { + /* + u32 numLocalBlocks; +_ (ReadLEB_u32 (& numLocalBlocks, & ptr, i_end)); m3log (parse, " code size: %-4d", size); + + u32 numLocals = 0; + + for (u32 l = 0; l < numLocalBlocks; ++l) + { + u32 varCount; + i8 wasmType; + u8 normalType; + +_ (ReadLEB_u32 (& varCount, & ptr, i_end)); +_ (ReadLEB_i7 (& wasmType, & ptr, i_end)); +_ (NormalizeType (& normalType, wasmType)); + + numLocals += varCount; m3log (parse, " %2d locals; type: '%s'", varCount, c_waTypes [normalType]); + } + */ + + IM3Function func = Module_GetFunction (io_module, f + io_module->numFuncImports); + + func->module = io_module; + func->wasm = start; + func->wasmEnd = i_bytes; + //func->ownsWasmCode = io_module->hasWasmCodeCopy; +// func->numLocals = numLocals; + } + else _throw (m3Err_wasmSectionOverrun); + } + } + + _catch: + + if (not result and i_bytes != i_end) + result = m3Err_wasmSectionUnderrun; + + return result; +} + + +M3Result ParseSection_Data (M3Module * io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + u32 numDataSegments; +_ (ReadLEB_u32 (& numDataSegments, & i_bytes, i_end)); m3log (parse, "** Data [%d]", numDataSegments); + + _throwif("too many data segments", numDataSegments > d_m3MaxSaneDataSegments); + + io_module->dataSegments = m3_AllocArray (M3DataSegment, numDataSegments); + _throwifnull(io_module->dataSegments); + io_module->numDataSegments = numDataSegments; + + for (u32 i = 0; i < numDataSegments; ++i) + { + M3DataSegment * segment = & io_module->dataSegments [i]; + +_ (ReadLEB_u32 (& segment->memoryRegion, & i_bytes, i_end)); + + segment->initExpr = i_bytes; +_ (Parse_InitExpr (io_module, & i_bytes, i_end)); + segment->initExprSize = (u32) (i_bytes - segment->initExpr); + + _throwif (m3Err_wasmMissingInitExpr, segment->initExprSize <= 1); + +_ (ReadLEB_u32 (& segment->size, & i_bytes, i_end)); + segment->data = i_bytes; m3log (parse, " segment [%u] memory: %u; expr-size: %d; size: %d", + i, segment->memoryRegion, segment->initExprSize, segment->size); + i_bytes += segment->size; + + _throwif("data segment underflow", i_bytes > i_end); + } + + _catch: + + return result; +} + + +M3Result ParseSection_Memory (M3Module * io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + // TODO: MVP; assert no memory imported + + u32 numMemories; +_ (ReadLEB_u32 (& numMemories, & i_bytes, i_end)); m3log (parse, "** Memory [%d]", numMemories); + + _throwif (m3Err_tooManyMemorySections, numMemories != 1); + + ParseType_Memory (& io_module->memoryInfo, & i_bytes, i_end); + + _catch: return result; +} + + +M3Result ParseSection_Global (M3Module * io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result = m3Err_none; + + u32 numGlobals; +_ (ReadLEB_u32 (& numGlobals, & i_bytes, i_end)); m3log (parse, "** Global [%d]", numGlobals); + + _throwif("too many globals", numGlobals > d_m3MaxSaneGlobalsCount); + + for (u32 i = 0; i < numGlobals; ++i) + { + i8 waType; + u8 type, isMutable; + +_ (ReadLEB_i7 (& waType, & i_bytes, i_end)); +_ (NormalizeType (& type, waType)); +_ (ReadLEB_u7 (& isMutable, & i_bytes, i_end)); m3log (parse, " global: [%d] %s mutable: %d", i, c_waTypes [type], (u32) isMutable); + + IM3Global global; +_ (Module_AddGlobal (io_module, & global, type, isMutable, false /* isImport */)); + + global->initExpr = i_bytes; +_ (Parse_InitExpr (io_module, & i_bytes, i_end)); + global->initExprSize = (u32) (i_bytes - global->initExpr); + + _throwif (m3Err_wasmMissingInitExpr, global->initExprSize <= 1); + } + + _catch: return result; +} + + +M3Result ParseSection_Name (M3Module * io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result; + + cstr_t name; + + while (i_bytes < i_end) + { + u8 nameType; + u32 payloadLength; + +_ (ReadLEB_u7 (& nameType, & i_bytes, i_end)); +_ (ReadLEB_u32 (& payloadLength, & i_bytes, i_end)); + + bytes_t start = i_bytes; + if (nameType == 1) + { + u32 numNames; +_ (ReadLEB_u32 (& numNames, & i_bytes, i_end)); + + _throwif("too many names", numNames > d_m3MaxSaneFunctionsCount); + + for (u32 i = 0; i < numNames; ++i) + { + u32 index; +_ (ReadLEB_u32 (& index, & i_bytes, i_end)); +_ (Read_utf8 (& name, & i_bytes, i_end)); + + if (index < io_module->numFunctions) + { + IM3Function func = &(io_module->functions [index]); + if (func->numNames == 0) + { + func->names[0] = name; m3log (parse, " naming function%5d: %s", index, name); + func->numNames = 1; + name = NULL; // transfer ownership + } +// else m3log (parse, "prenamed: %s", io_module->functions [index].name); + } + + m3_Free (name); + } + } + + i_bytes = start + payloadLength; + } + + _catch: return result; +} + + +M3Result ParseSection_Custom (M3Module * io_module, bytes_t i_bytes, cbytes_t i_end) +{ + M3Result result; + + cstr_t name; +_ (Read_utf8 (& name, & i_bytes, i_end)); + m3log (parse, "** Custom: '%s'", name); + if (strcmp (name, "name") == 0) { +_ (ParseSection_Name(io_module, i_bytes, i_end)); + } else if (io_module->environment->customSectionHandler) { +_ (io_module->environment->customSectionHandler(io_module, name, i_bytes, i_end)); + } + + m3_Free (name); + + _catch: return result; +} + + +M3Result ParseModuleSection (M3Module * o_module, u8 i_sectionType, bytes_t i_bytes, u32 i_numBytes) +{ + M3Result result = m3Err_none; + + typedef M3Result (* M3Parser) (M3Module *, bytes_t, cbytes_t); + + static M3Parser s_parsers [] = + { + ParseSection_Custom, // 0 + ParseSection_Type, // 1 + ParseSection_Import, // 2 + ParseSection_Function, // 3 + NULL, // 4: TODO Table + ParseSection_Memory, // 5 + ParseSection_Global, // 6 + ParseSection_Export, // 7 + ParseSection_Start, // 8 + ParseSection_Element, // 9 + ParseSection_Code, // 10 + ParseSection_Data, // 11 + NULL, // 12: TODO DataCount + }; + + M3Parser parser = NULL; + + if (i_sectionType <= 12) + parser = s_parsers [i_sectionType]; + + if (parser) + { + cbytes_t end = i_bytes + i_numBytes; + result = parser (o_module, i_bytes, end); + } + else + { + m3log (parse, " skipped section type: %d", (u32) i_sectionType); + } + + return result; +} + + +M3Result m3_ParseModule (IM3Environment i_environment, IM3Module * o_module, cbytes_t i_bytes, u32 i_numBytes) +{ + IM3Module module; m3log (parse, "load module: %d bytes", i_numBytes); +_try { + module = m3_AllocStruct (M3Module); + _throwifnull (module); + module->name = ".unnamed"; m3log (parse, "load module: %d bytes", i_numBytes); + module->startFunction = -1; + //module->hasWasmCodeCopy = false; + module->environment = i_environment; + + const u8 * pos = i_bytes; + const u8 * end = pos + i_numBytes; + + module->wasmStart = pos; + module->wasmEnd = end; + + u32 magic, version; +_ (Read_u32 (& magic, & pos, end)); +_ (Read_u32 (& version, & pos, end)); + + _throwif (m3Err_wasmMalformed, magic != 0x6d736100); + _throwif (m3Err_incompatibleWasmVersion, version != 1); + + static const u8 sectionsOrder[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 10, 11, 0 }; // 0 is a placeholder + u8 expectedSection = 0; + + while (pos < end) + { + u8 section; +_ (ReadLEB_u7 (& section, & pos, end)); + + if (section != 0) { + // Ensure sections appear only once and in order + while (sectionsOrder[expectedSection++] != section) { + _throwif(m3Err_misorderedWasmSection, expectedSection >= 12); + } + } + + u32 sectionLength; +_ (ReadLEB_u32 (& sectionLength, & pos, end)); + _throwif(m3Err_wasmMalformed, pos + sectionLength > end); + +_ (ParseModuleSection (module, section, pos, sectionLength)); + + pos += sectionLength; + } + +} _catch: + + if (result) + { + m3_FreeModule (module); + module = NULL; + } + + * o_module = module; + + return result; +} diff --git a/ext/wasm3/source/wasm3.h b/ext/wasm3/source/wasm3.h new file mode 100644 index 0000000..df163e5 --- /dev/null +++ b/ext/wasm3/source/wasm3.h @@ -0,0 +1,373 @@ +// +// Wasm3, high performance WebAssembly interpreter +// +// Copyright © 2019 Steven Massey, Volodymyr Shymanskyy. +// All rights reserved. +// + +#ifndef wasm3_h +#define wasm3_h + +#define M3_VERSION_MAJOR 0 +#define M3_VERSION_MINOR 5 +#define M3_VERSION_REV 0 +#define M3_VERSION "0.5.0" + +#include +#include +#include +#include + +#include "wasm3_defs.h" + +// Constants +#define M3_BACKTRACE_TRUNCATED (void*)(SIZE_MAX) + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef const char * M3Result; + +struct M3Environment; typedef struct M3Environment * IM3Environment; +struct M3Runtime; typedef struct M3Runtime * IM3Runtime; +struct M3Module; typedef struct M3Module * IM3Module; +struct M3Function; typedef struct M3Function * IM3Function; +struct M3Global; typedef struct M3Global * IM3Global; + +typedef struct M3ErrorInfo +{ + M3Result result; + + IM3Runtime runtime; + IM3Module module; + IM3Function function; + + const char * file; + uint32_t line; + + const char * message; +} M3ErrorInfo; + +typedef struct M3BacktraceFrame +{ + uint32_t moduleOffset; + IM3Function function; + + struct M3BacktraceFrame * next; +} +M3BacktraceFrame, * IM3BacktraceFrame; + +typedef struct M3BacktraceInfo +{ + IM3BacktraceFrame frames; + IM3BacktraceFrame lastFrame; // can be M3_BACKTRACE_TRUNCATED +} +M3BacktraceInfo, * IM3BacktraceInfo; + + +typedef enum M3ValueType +{ + c_m3Type_none = 0, + c_m3Type_i32 = 1, + c_m3Type_i64 = 2, + c_m3Type_f32 = 3, + c_m3Type_f64 = 4, + + c_m3Type_unknown +} M3ValueType; + +typedef struct M3TaggedValue +{ + M3ValueType type; + union M3ValueUnion + { + uint32_t i32; + uint64_t i64; + float f32; + double f64; + } value; +} +M3TaggedValue, * IM3TaggedValue; + +typedef struct M3ImportInfo +{ + const char * moduleUtf8; + const char * fieldUtf8; +} +M3ImportInfo, * IM3ImportInfo; + + +typedef struct M3ImportContext +{ + void * userdata; + IM3Function function; +} +M3ImportContext, * IM3ImportContext; + +// ------------------------------------------------------------------------------------------------------------------------------- +// error codes +// ------------------------------------------------------------------------------------------------------------------------------- + +# if defined(M3_IMPLEMENT_ERROR_STRINGS) +# define d_m3ErrorConst(LABEL, STRING) extern const M3Result m3Err_##LABEL = { STRING }; +# else +# define d_m3ErrorConst(LABEL, STRING) extern const M3Result m3Err_##LABEL; +# endif + +// ------------------------------------------------------------------------------------------------------------------------------- + +d_m3ErrorConst (none, NULL) + +// general errors +d_m3ErrorConst (mallocFailed, "memory allocation failed") + +// parse errors +d_m3ErrorConst (incompatibleWasmVersion, "incompatible Wasm binary version") +d_m3ErrorConst (wasmMalformed, "malformed Wasm binary") +d_m3ErrorConst (misorderedWasmSection, "out of order Wasm section") +d_m3ErrorConst (wasmUnderrun, "underrun while parsing Wasm binary") +d_m3ErrorConst (wasmOverrun, "overrun while parsing Wasm binary") +d_m3ErrorConst (wasmMissingInitExpr, "missing init_expr in Wasm binary") +d_m3ErrorConst (lebOverflow, "LEB encoded value overflow") +d_m3ErrorConst (missingUTF8, "invalid length UTF-8 string") +d_m3ErrorConst (wasmSectionUnderrun, "section underrun while parsing Wasm binary") +d_m3ErrorConst (wasmSectionOverrun, "section overrun while parsing Wasm binary") +d_m3ErrorConst (invalidTypeId, "unknown value_type") +d_m3ErrorConst (tooManyMemorySections, "only one memory per module is supported") +d_m3ErrorConst (tooManyArgsRets, "too many arguments or return values") + +// link errors +d_m3ErrorConst (moduleNotLinked, "attempting to use module that is not loaded") +d_m3ErrorConst (moduleAlreadyLinked, "attempting to bind module to multiple runtimes") +d_m3ErrorConst (functionLookupFailed, "function lookup failed") +d_m3ErrorConst (functionImportMissing, "missing imported function") + +d_m3ErrorConst (malformedFunctionSignature, "malformed function signature") + +// compilation errors +d_m3ErrorConst (noCompiler, "no compiler found for opcode") +d_m3ErrorConst (unknownOpcode, "unknown opcode") +d_m3ErrorConst (restrictedOpcode, "restricted opcode") +d_m3ErrorConst (functionStackOverflow, "compiling function overran its stack height limit") +d_m3ErrorConst (functionStackUnderrun, "compiling function underran the stack") +d_m3ErrorConst (mallocFailedCodePage, "memory allocation failed when acquiring a new M3 code page") +d_m3ErrorConst (settingImmutableGlobal, "attempting to set an immutable global") +d_m3ErrorConst (typeMismatch, "incorrect type on stack") +d_m3ErrorConst (typeCountMismatch, "incorrect value count on stack") + +// runtime errors +d_m3ErrorConst (missingCompiledCode, "function is missing compiled m3 code") +d_m3ErrorConst (wasmMemoryOverflow, "runtime ran out of memory") +d_m3ErrorConst (globalMemoryNotAllocated, "global memory is missing from a module") +d_m3ErrorConst (globaIndexOutOfBounds, "global index is too large") +d_m3ErrorConst (argumentCountMismatch, "argument count mismatch") +d_m3ErrorConst (argumentTypeMismatch, "argument type mismatch") +d_m3ErrorConst (globalLookupFailed, "global lookup failed") +d_m3ErrorConst (globalTypeMismatch, "global type mismatch") +d_m3ErrorConst (globalNotMutable, "global is not mutable") + +// traps +d_m3ErrorConst (trapOutOfBoundsMemoryAccess, "[trap] out of bounds memory access") +d_m3ErrorConst (trapDivisionByZero, "[trap] integer divide by zero") +d_m3ErrorConst (trapIntegerOverflow, "[trap] integer overflow") +d_m3ErrorConst (trapIntegerConversion, "[trap] invalid conversion to integer") +d_m3ErrorConst (trapIndirectCallTypeMismatch, "[trap] indirect call type mismatch") +d_m3ErrorConst (trapTableIndexOutOfRange, "[trap] undefined element") +d_m3ErrorConst (trapTableElementIsNull, "[trap] null table element") +d_m3ErrorConst (trapExit, "[trap] program called exit") +d_m3ErrorConst (trapAbort, "[trap] program called abort") +d_m3ErrorConst (trapUnreachable, "[trap] unreachable executed") +d_m3ErrorConst (trapStackOverflow, "[trap] stack overflow") + + +//------------------------------------------------------------------------------------------------------------------------------- +// configuration, can be found in m3_config.h, m3_config_platforms.h, m3_core.h) +//------------------------------------------------------------------------------------------------------------------------------- + +//------------------------------------------------------------------------------------------------------------------------------- +// global environment than can host multiple runtimes +//------------------------------------------------------------------------------------------------------------------------------- + IM3Environment m3_NewEnvironment (void); + + void m3_FreeEnvironment (IM3Environment i_environment); + + typedef M3Result (* M3SectionHandler) (IM3Module i_module, const char* name, const uint8_t * start, const uint8_t * end); + + void m3_SetCustomSectionHandler (IM3Environment i_environment, M3SectionHandler i_handler); + + +//------------------------------------------------------------------------------------------------------------------------------- +// execution context +//------------------------------------------------------------------------------------------------------------------------------- + + IM3Runtime m3_NewRuntime (IM3Environment io_environment, + uint32_t i_stackSizeInBytes, + void * i_userdata); + + void m3_FreeRuntime (IM3Runtime i_runtime); + + // Wasm currently only supports one memory region. i_memoryIndex should be zero. + uint8_t * m3_GetMemory (IM3Runtime i_runtime, + uint32_t * o_memorySizeInBytes, + uint32_t i_memoryIndex); + + // This is used internally by Raw Function helpers + uint32_t m3_GetMemorySize (IM3Runtime i_runtime); + + void * m3_GetUserData (IM3Runtime i_runtime); + +/////////////////////////////////////////////////////////////////////////////////////////// +//NOTE(Martin): allow controlling memory resize +/////////////////////////////////////////////////////////////////////////////////////////// +typedef void* (*m3_resize_proc)(void* p, unsigned long size, void* userData); +typedef void (*m3_free_proc)(void* p, void* userData); +void m3_RuntimeSetMemoryCallbacks(IM3Runtime runtime, m3_resize_proc resizeCallback, m3_free_proc freeCallback, void* userData); + + +//------------------------------------------------------------------------------------------------------------------------------- +// modules +//------------------------------------------------------------------------------------------------------------------------------- + + // i_wasmBytes data must be persistent during the lifetime of the module + M3Result m3_ParseModule (IM3Environment i_environment, + IM3Module * o_module, + const uint8_t * const i_wasmBytes, + uint32_t i_numWasmBytes); + + // Only modules not loaded into a M3Runtime need to be freed. A module is considered unloaded if + // a. m3_LoadModule has not yet been called on that module. Or, + // b. m3_LoadModule returned a result. + void m3_FreeModule (IM3Module i_module); + + // LoadModule transfers ownership of a module to the runtime. Do not free modules once successfully loaded into the runtime + M3Result m3_LoadModule (IM3Runtime io_runtime, IM3Module io_module); + + // Optional, compiles all functions in the module + M3Result m3_CompileModule (IM3Module io_module); + + // Calling m3_RunStart is optional + M3Result m3_RunStart (IM3Module i_module); + + // Arguments and return values are passed in and out through the stack pointer _sp. + // Placeholder return value slots are first and arguments after. So, the first argument is at _sp [numReturns] + // Return values should be written into _sp [0] to _sp [num_returns - 1] + typedef const void * (* M3RawCall) (IM3Runtime runtime, IM3ImportContext _ctx, uint64_t * _sp, void * _mem); + + M3Result m3_LinkRawFunction (IM3Module io_module, + const char * const i_moduleName, + const char * const i_functionName, + const char * const i_signature, + M3RawCall i_function); + + M3Result m3_LinkRawFunctionEx (IM3Module io_module, + const char * const i_moduleName, + const char * const i_functionName, + const char * const i_signature, + M3RawCall i_function, + const void * i_userdata); + + const char* m3_GetModuleName (IM3Module i_module); + void m3_SetModuleName (IM3Module i_module, const char* name); + IM3Runtime m3_GetModuleRuntime (IM3Module i_module); + +//------------------------------------------------------------------------------------------------------------------------------- +// globals +//------------------------------------------------------------------------------------------------------------------------------- + IM3Global m3_FindGlobal (IM3Module io_module, + const char * const i_globalName); + + M3Result m3_GetGlobal (IM3Global i_global, + IM3TaggedValue o_value); + + M3Result m3_SetGlobal (IM3Global i_global, + const IM3TaggedValue i_value); + + M3ValueType m3_GetGlobalType (IM3Global i_global); + +//------------------------------------------------------------------------------------------------------------------------------- +// functions +//------------------------------------------------------------------------------------------------------------------------------- + M3Result m3_Yield (void); + + // o_function is valid during the lifetime of the originating runtime + M3Result m3_FindFunction (IM3Function * o_function, + IM3Runtime i_runtime, + const char * const i_functionName); + + uint32_t m3_GetArgCount (IM3Function i_function); + uint32_t m3_GetRetCount (IM3Function i_function); + M3ValueType m3_GetArgType (IM3Function i_function, uint32_t i_index); + M3ValueType m3_GetRetType (IM3Function i_function, uint32_t i_index); + + M3Result m3_CallV (IM3Function i_function, ...); + M3Result m3_CallVL (IM3Function i_function, va_list i_args); + M3Result m3_Call (IM3Function i_function, uint32_t i_argc, const void * i_argptrs[]); + M3Result m3_CallArgv (IM3Function i_function, uint32_t i_argc, const char * i_argv[]); + + M3Result m3_GetResultsV (IM3Function i_function, ...); + M3Result m3_GetResultsVL (IM3Function i_function, va_list o_rets); + M3Result m3_GetResults (IM3Function i_function, uint32_t i_retc, const void * o_retptrs[]); + + + void m3_GetErrorInfo (IM3Runtime i_runtime, M3ErrorInfo* o_info); + void m3_ResetErrorInfo (IM3Runtime i_runtime); + + const char* m3_GetFunctionName (IM3Function i_function); + IM3Module m3_GetFunctionModule (IM3Function i_function); + +//------------------------------------------------------------------------------------------------------------------------------- +// debug info +//------------------------------------------------------------------------------------------------------------------------------- + + void m3_PrintRuntimeInfo (IM3Runtime i_runtime); + void m3_PrintM3Info (void); + void m3_PrintProfilerInfo (void); + + // The runtime owns the backtrace, do not free the backtrace you obtain. Returns NULL if there's no backtrace. + IM3BacktraceInfo m3_GetBacktrace (IM3Runtime i_runtime); + +//------------------------------------------------------------------------------------------------------------------------------- +// raw function definition helpers +//------------------------------------------------------------------------------------------------------------------------------- + +# define m3ApiOffsetToPtr(offset) (void*)((uint8_t*)_mem + (uint32_t)(offset)) +# define m3ApiPtrToOffset(ptr) (uint32_t)((uint8_t*)ptr - (uint8_t*)_mem) + +# define m3ApiReturnType(TYPE) TYPE* raw_return = ((TYPE*) (_sp++)); +# define m3ApiGetArg(TYPE, NAME) TYPE NAME = * ((TYPE *) (_sp++)); +# define m3ApiGetArgMem(TYPE, NAME) TYPE NAME = (TYPE)m3ApiOffsetToPtr(* ((uint32_t *) (_sp++))); + +# define m3ApiIsNullPtr(addr) ((void*)(addr) <= _mem) +# define m3ApiCheckMem(addr, len) { if (M3_UNLIKELY(((void*)(addr) < _mem) || ((uint64_t)(uintptr_t)(addr) + (len)) > ((uint64_t)(uintptr_t)(_mem)+m3_GetMemorySize(runtime)))) m3ApiTrap(m3Err_trapOutOfBoundsMemoryAccess); } + +# define m3ApiRawFunction(NAME) const void * NAME (IM3Runtime runtime, IM3ImportContext _ctx, uint64_t * _sp, void * _mem) +# define m3ApiReturn(VALUE) { *raw_return = (VALUE); return m3Err_none; } +# define m3ApiTrap(VALUE) { return VALUE; } +# define m3ApiSuccess() { return m3Err_none; } + +# if defined(M3_BIG_ENDIAN) +# define m3ApiReadMem8(ptr) (* (uint8_t *)(ptr)) +# define m3ApiReadMem16(ptr) m3_bswap16((* (uint16_t *)(ptr))) +# define m3ApiReadMem32(ptr) m3_bswap32((* (uint32_t *)(ptr))) +# define m3ApiReadMem64(ptr) m3_bswap64((* (uint64_t *)(ptr))) +# define m3ApiWriteMem8(ptr, val) { * (uint8_t *)(ptr) = (val); } +# define m3ApiWriteMem16(ptr, val) { * (uint16_t *)(ptr) = m3_bswap16((val)); } +# define m3ApiWriteMem32(ptr, val) { * (uint32_t *)(ptr) = m3_bswap32((val)); } +# define m3ApiWriteMem64(ptr, val) { * (uint64_t *)(ptr) = m3_bswap64((val)); } +# else +# define m3ApiReadMem8(ptr) (* (uint8_t *)(ptr)) +# define m3ApiReadMem16(ptr) (* (uint16_t *)(ptr)) +# define m3ApiReadMem32(ptr) (* (uint32_t *)(ptr)) +# define m3ApiReadMem64(ptr) (* (uint64_t *)(ptr)) +# define m3ApiWriteMem8(ptr, val) { * (uint8_t *)(ptr) = (val); } +# define m3ApiWriteMem16(ptr, val) { * (uint16_t *)(ptr) = (val); } +# define m3ApiWriteMem32(ptr, val) { * (uint32_t *)(ptr) = (val); } +# define m3ApiWriteMem64(ptr, val) { * (uint64_t *)(ptr) = (val); } +# endif + +#if defined(__cplusplus) +} +#endif + +#endif // wasm3_h diff --git a/ext/wasm3/source/wasm3_defs.h b/ext/wasm3/source/wasm3_defs.h new file mode 100644 index 0000000..521ed9e --- /dev/null +++ b/ext/wasm3/source/wasm3_defs.h @@ -0,0 +1,282 @@ +// +// wasm3_defs.h +// +// Created by Volodymyr Shymanskyy on 11/20/19. +// Copyright © 2019 Volodymyr Shymanskyy. All rights reserved. +// + +#ifndef wasm3_defs_h +#define wasm3_defs_h + +#define M3_STR__(x) #x +#define M3_STR(x) M3_STR__(x) + +#define M3_CONCAT__(a,b) a##b +#define M3_CONCAT(a,b) M3_CONCAT__(a,b) + +/* + * Detect compiler + */ + +# if defined(__clang__) +# define M3_COMPILER_CLANG 1 +# elif defined(__INTEL_COMPILER) +# define M3_COMPILER_ICC 1 +# elif defined(__GNUC__) || defined(__GNUG__) +# define M3_COMPILER_GCC 1 +# elif defined(_MSC_VER) +# define M3_COMPILER_MSVC 1 +# else +# warning "Compiler not detected" +# endif + +# if defined(M3_COMPILER_CLANG) +# if defined(WIN32) +# define M3_COMPILER_VER __VERSION__ " for Windows" +# else +# define M3_COMPILER_VER __VERSION__ +# endif +# elif defined(M3_COMPILER_GCC) +# define M3_COMPILER_VER "GCC " __VERSION__ +# elif defined(M3_COMPILER_ICC) +# define M3_COMPILER_VER __VERSION__ +# elif defined(M3_COMPILER_MSVC) +# define M3_COMPILER_VER "MSVC " M3_STR(_MSC_VER) +# else +# define M3_COMPILER_VER "unknown" +# endif + +# ifdef __has_feature +# define M3_COMPILER_HAS_FEATURE(x) __has_feature(x) +# else +# define M3_COMPILER_HAS_FEATURE(x) 0 +# endif + +# ifdef __has_builtin +# define M3_COMPILER_HAS_BUILTIN(x) __has_builtin(x) +# else +# define M3_COMPILER_HAS_BUILTIN(x) 0 +# endif + +/* + * Detect endianness + */ + +# if defined(M3_COMPILER_MSVC) +# define M3_LITTLE_ENDIAN +# elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define M3_LITTLE_ENDIAN +# elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +# define M3_BIG_ENDIAN +# else +# error "Byte order not detected" +# endif + +/* + * Detect platform + */ + +# if defined(M3_COMPILER_CLANG) || defined(M3_COMPILER_GCC) || defined(M3_COMPILER_ICC) +# if defined(__wasm__) +# define M3_ARCH "wasm" + +# elif defined(__x86_64__) +# define M3_ARCH "x86_64" + +# elif defined(__i386__) +# define M3_ARCH "i386" + +# elif defined(__aarch64__) +# define M3_ARCH "arm64-v8a" + +# elif defined(__arm__) +# if defined(__ARM_ARCH_7A__) +# if defined(__ARM_NEON__) +# if defined(__ARM_PCS_VFP) +# define M3_ARCH "arm-v7a/NEON hard-float" +# else +# define M3_ARCH "arm-v7a/NEON" +# endif +# else +# if defined(__ARM_PCS_VFP) +# define M3_ARCH "arm-v7a hard-float" +# else +# define M3_ARCH "arm-v7a" +# endif +# endif +# else +# define M3_ARCH "arm" +# endif + +# elif defined(__riscv) +# if defined(__riscv_32e) +# define _M3_ARCH_RV "rv32e" +# elif __riscv_xlen == 128 +# define _M3_ARCH_RV "rv128i" +# elif __riscv_xlen == 64 +# define _M3_ARCH_RV "rv64i" +# elif __riscv_xlen == 32 +# define _M3_ARCH_RV "rv32i" +# endif +# if defined(__riscv_muldiv) +# define _M3_ARCH_RV_M _M3_ARCH_RV "m" +# else +# define _M3_ARCH_RV_M _M3_ARCH_RV +# endif +# if defined(__riscv_atomic) +# define _M3_ARCH_RV_A _M3_ARCH_RV_M "a" +# else +# define _M3_ARCH_RV_A _M3_ARCH_RV_M +# endif +# if defined(__riscv_flen) +# define _M3_ARCH_RV_F _M3_ARCH_RV_A "f" +# else +# define _M3_ARCH_RV_F _M3_ARCH_RV_A +# endif +# if defined(__riscv_flen) && __riscv_flen >= 64 +# define _M3_ARCH_RV_D _M3_ARCH_RV_F "d" +# else +# define _M3_ARCH_RV_D _M3_ARCH_RV_F +# endif +# if defined(__riscv_compressed) +# define _M3_ARCH_RV_C _M3_ARCH_RV_D "c" +# else +# define _M3_ARCH_RV_C _M3_ARCH_RV_D +# endif +# define M3_ARCH _M3_ARCH_RV_C + +# elif defined(__mips__) +# if defined(__MIPSEB__) && defined(__mips64) +# define M3_ARCH "mips64 " _MIPS_ARCH +# elif defined(__MIPSEL__) && defined(__mips64) +# define M3_ARCH "mips64el " _MIPS_ARCH +# elif defined(__MIPSEB__) +# define M3_ARCH "mips " _MIPS_ARCH +# elif defined(__MIPSEL__) +# define M3_ARCH "mipsel " _MIPS_ARCH +# endif + +# elif defined(__PPC__) +# if defined(__PPC64__) && defined(__LITTLE_ENDIAN__) +# define M3_ARCH "ppc64le" +# elif defined(__PPC64__) +# define M3_ARCH "ppc64" +# else +# define M3_ARCH "ppc" +# endif + +# elif defined(__sparc__) +# if defined(__arch64__) +# define M3_ARCH "sparc64" +# else +# define M3_ARCH "sparc" +# endif + +# elif defined(__s390x__) +# define M3_ARCH "s390x" + +# elif defined(__alpha__) +# define M3_ARCH "alpha" + +# elif defined(__m68k__) +# define M3_ARCH "m68k" + +# elif defined(__xtensa__) +# define M3_ARCH "xtensa" + +# elif defined(__arc__) +# define M3_ARCH "arc32" + +# elif defined(__AVR__) +# define M3_ARCH "avr" +# endif +# endif + +# if defined(M3_COMPILER_MSVC) +# if defined(_M_X64) +# define M3_ARCH "x86_64" +# elif defined(_M_IX86) +# define M3_ARCH "i386" +# elif defined(_M_ARM64) +# define M3_ARCH "arm64" +# elif defined(_M_ARM) +# define M3_ARCH "arm" +# endif +# endif + +# if !defined(M3_ARCH) +# warning "Architecture not detected" +# define M3_ARCH "unknown" +# endif + +/* + * Byte swapping (for Big-Endian systems only) + */ + +# if defined(M3_COMPILER_MSVC) +# define m3_bswap16(x) _byteswap_ushort((x)) +# define m3_bswap32(x) _byteswap_ulong((x)) +# define m3_bswap64(x) _byteswap_uint64((x)) +# elif defined(M3_COMPILER_GCC) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) +// __builtin_bswap32/64 added in gcc 4.3, __builtin_bswap16 added in gcc 4.8 +# define m3_bswap16(x) __builtin_bswap16((x)) +# define m3_bswap32(x) __builtin_bswap32((x)) +# define m3_bswap64(x) __builtin_bswap64((x)) +# elif defined(M3_COMPILER_CLANG) && M3_COMPILER_HAS_BUILTIN(__builtin_bswap16) +# define m3_bswap16(x) __builtin_bswap16((x)) +# define m3_bswap32(x) __builtin_bswap32((x)) +# define m3_bswap64(x) __builtin_bswap64((x)) +# elif defined(M3_COMPILER_ICC) +# define m3_bswap16(x) __builtin_bswap16((x)) +# define m3_bswap32(x) __builtin_bswap32((x)) +# define m3_bswap64(x) __builtin_bswap64((x)) +# else +# ifdef __linux__ +# include +# else +# include +# endif +# if defined(__bswap_16) +# define m3_bswap16(x) __bswap_16((x)) +# define m3_bswap32(x) __bswap_32((x)) +# define m3_bswap64(x) __bswap_64((x)) +# else +# warning "Using naive (probably slow) bswap operations" + static inline + uint16_t m3_bswap16(uint16_t x) { + return ((( x >> 8 ) & 0xffu ) | (( x & 0xffu ) << 8 )); + } + static inline + uint32_t m3_bswap32(uint32_t x) { + return ((( x & 0xff000000u ) >> 24 ) | + (( x & 0x00ff0000u ) >> 8 ) | + (( x & 0x0000ff00u ) << 8 ) | + (( x & 0x000000ffu ) << 24 )); + } + static inline + uint64_t m3_bswap64(uint64_t x) { + return ((( x & 0xff00000000000000ull ) >> 56 ) | + (( x & 0x00ff000000000000ull ) >> 40 ) | + (( x & 0x0000ff0000000000ull ) >> 24 ) | + (( x & 0x000000ff00000000ull ) >> 8 ) | + (( x & 0x00000000ff000000ull ) << 8 ) | + (( x & 0x0000000000ff0000ull ) << 24 ) | + (( x & 0x000000000000ff00ull ) << 40 ) | + (( x & 0x00000000000000ffull ) << 56 )); + } +# endif +# endif + +/* + * Other + */ + +# if defined(M3_COMPILER_GCC) || defined(M3_COMPILER_CLANG) || defined(M3_COMPILER_ICC) +# define M3_UNLIKELY(x) __builtin_expect(!!(x), 0) +# define M3_LIKELY(x) __builtin_expect(!!(x), 1) +# else +# define M3_UNLIKELY(x) (x) +# define M3_LIKELY(x) (x) +# endif + +#endif // wasm3_defs_h diff --git a/ext/wasm3/test/internal/m3_test.c b/ext/wasm3/test/internal/m3_test.c new file mode 100644 index 0000000..9332d2d --- /dev/null +++ b/ext/wasm3/test/internal/m3_test.c @@ -0,0 +1,262 @@ +// +// m3_test.c +// +// Created by Steven Massey on 2/27/20. +// Copyright © 2020 Steven Massey. All rights reserved. +// + +#include + +#include "wasm3_ext.h" +#include "m3_bind.h" + +#define Test(NAME) if (RunTest (argc, argv, #NAME) != 0) +#define DisabledTest(NAME) printf ("\ndisabled: %s\n", #NAME); if (false) +#define expect(TEST) if (not (TEST)) { printf ("failed: (%s) on line: %d\n", #TEST, __LINE__); } + + +bool RunTest (int i_argc, const char * i_argv [], cstr_t i_name) +{ + cstr_t option = (i_argc == 2) ? i_argv [1] : NULL; + + bool runningTest = option ? strcmp (option, i_name) == 0 : true; + + if (runningTest) + printf ("\n test: %s\n", i_name); + + return runningTest; +} + + +int main (int argc, const char * argv []) +{ + Test (signatures) + { + M3Result result; + + IM3FuncType ftype = NULL; + + result = SignatureToFuncType (& ftype, ""); expect (result == m3Err_malformedFunctionSignature) + m3_Free (ftype); + + // implicit void return + result = SignatureToFuncType (& ftype, "()"); expect (result == m3Err_none) + m3_Free (ftype); + + result = SignatureToFuncType (& ftype, " v () "); expect (result == m3Err_none) + expect (ftype->numRets == 0) + expect (ftype->numArgs == 0) + m3_Free (ftype); + + result = SignatureToFuncType (& ftype, "f(IiF)"); expect (result == m3Err_none) + expect (ftype->numRets == 1) + expect (ftype->types [0] == c_m3Type_f32) + expect (ftype->numArgs == 3) + expect (ftype->types [1] == c_m3Type_i64) + expect (ftype->types [2] == c_m3Type_i32) + expect (ftype->types [3] == c_m3Type_f64) + + IM3FuncType ftype2 = NULL; + result = SignatureToFuncType (& ftype2, "f(I i F)"); expect (result == m3Err_none); + expect (AreFuncTypesEqual (ftype, ftype2)); + m3_Free (ftype); + m3_Free (ftype2); + } + + + Test (codepages.simple) + { + M3Environment env = { 0 }; + M3Runtime runtime = { 0 }; + runtime.environment = & env; + + IM3CodePage page = AcquireCodePage (& runtime); expect (page); + expect (runtime.numCodePages == 1); + expect (runtime.numActiveCodePages == 1); + + IM3CodePage page2 = AcquireCodePage (& runtime); expect (page2); + expect (runtime.numCodePages == 2); + expect (runtime.numActiveCodePages == 2); + + ReleaseCodePage (& runtime, page); expect (runtime.numCodePages == 2); + expect (runtime.numActiveCodePages == 1); + + ReleaseCodePage (& runtime, page2); expect (runtime.numCodePages == 2); + expect (runtime.numActiveCodePages == 0); + + Runtime_Release (& runtime); expect (CountCodePages (env.pagesReleased) == 2); + Environment_Release (& env); expect (CountCodePages (env.pagesReleased) == 0); + } + + + Test (codepages.b) + { + const u32 c_numPages = 2000; + IM3CodePage pages [2000] = { NULL }; + + M3Environment env = { 0 }; + M3Runtime runtime = { 0 }; + runtime.environment = & env; + + u32 numActive = 0; + + for (u32 i = 0; i < 2000000; ++i) + { + u32 index = rand () % c_numPages; // printf ("%5u ", index); + + if (pages [index] == NULL) + { +// printf ("acq\n"); + pages [index] = AcquireCodePage (& runtime); + ++numActive; + } + else + { +// printf ("rel\n"); + ReleaseCodePage (& runtime, pages [index]); + pages [index] = NULL; + --numActive; + } + + expect (runtime.numActiveCodePages == numActive); + } + + printf ("num pages: %d\n", runtime.numCodePages); + + for (u32 i = 0; i < c_numPages; ++i) + { + if (pages [i]) + { + ReleaseCodePage (& runtime, pages [i]); + pages [i] = NULL; + --numActive; expect (runtime.numActiveCodePages == numActive); + } + } + + Runtime_Release (& runtime); + Environment_Release (& env); + } + + + Test (extensions) + { + M3Result result; + + IM3Environment env = m3_NewEnvironment (); + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + + IM3Module module = m3_NewModule (env); + + + i32 functionIndex = -1; + + u8 wasm [5] = { 0x04, // size + 0x00, // num local defs + 0x41, 0x37, // i32.const= 55 + 0x0b // end block + }; + + // will partially fail (compilation) because module isn't attached to a runtime yet. + result = m3_InjectFunction (module, & functionIndex, "i()", wasm, true); expect (result != m3Err_none) + expect (functionIndex >= 0) + + result = m3_LoadModule (runtime, module); expect (result == m3Err_none) + + // try again + result = m3_InjectFunction (module, & functionIndex, "i()", wasm, true); expect (result == m3Err_none) + + IM3Function function = m3_GetFunctionByIndex (module, functionIndex); expect (function) + + if (function) + { + result = m3_CallV (function); expect (result == m3Err_none) + u32 ret = 0; + m3_GetResultsV (function, & ret); expect (ret == 55); + } + + m3_FreeRuntime (runtime); + } + + IM3Environment env = m3_NewEnvironment (); + + + Test (multireturn.a) + { + M3Result result; + + IM3Runtime runtime = m3_NewRuntime (env, 1024, NULL); + +# if 0 + (module + (func (result i32 f32) + + i32.const 1234 + f32.const 5678.9 + ) + + (export "main" (func 0)) + ) +# endif + + u8 wasm [44] = { + 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x06, 0x01, 0x60, 0x00, 0x02, 0x7f, 0x7d, 0x03, 0x02, 0x01, 0x00, 0x07, 0x08, 0x01, 0x04, + 0x6d, 0x61, 0x69, 0x6e, 0x00, 0x00, 0x0a, 0x0c, 0x01, 0x0a, 0x00, 0x41, 0xd2, 0x09, 0x43, 0x33, 0x77, 0xb1, 0x45, 0x0b + }; + + IM3Module module; + result = m3_ParseModule (env, & module, wasm, 44); expect (result == m3Err_none) + + result = m3_LoadModule (runtime, module); expect (result == m3Err_none) + + IM3Function function = NULL; + result = m3_FindFunction (& function, runtime, "main"); expect (result == m3Err_none) + expect (function) + printf ("\n%s\n", result); + + if (function) + { + result = m3_CallV (function); expect (result == m3Err_none) + + i32 ret0 = 0; + f32 ret1 = 0.; + m3_GetResultsV (function, & ret0, & ret1); + + printf ("%d %f\n", ret0, ret1); + } + } + + + Test (multireturn.branch) + { +# if 0 + (module + (func (param i32) (result i32 i32) + + i32.const 123 + i32.const 456 + i32.const 789 + + block (param i32 i32) (result i32 i32 i32) + + local.get 0 + local.get 0 + + local.get 0 + br_if 0 + + drop + + end + + drop + drop + ) + + (export "main" (func 0)) + ) +# endif + } + + return 0; +} diff --git a/ext/wasm3/test/internal/tailcall/build.sh b/ext/wasm3/test/internal/tailcall/build.sh new file mode 100755 index 0000000..cc9887c --- /dev/null +++ b/ext/wasm3/test/internal/tailcall/build.sh @@ -0,0 +1,91 @@ +# Misc. helper commands: +#llc-9 --version +#llc-9 -march=wasm32 -mattr=help +#llc-9 -march=riscv32 -mattr=help +#echo | clang-9 -E - -march=native -### + +# MSVC +#cl /TP /c /Ox /Oy /FA /Fax64.msvc.S ops.c + +FLAGS="-Os -fverbose-asm" + +OPT="/media/vshymanskyy/Data" + +# x86 - clang and gcc + +clang-9 $FLAGS -m64 -S ops.c -o x64.clang.S +gcc $FLAGS -m64 -S ops.c -o x64.S + +clang-9 $FLAGS -m32 -S ops.c -o x86.clang.S +gcc $FLAGS -m32 -S ops.c -o x86.S + +# clang - risc-v + +clang-9 $FLAGS --target=riscv32 -march=rv32i -mabi=ilp32 -S ops.c -o riscv32i.clang.S +clang-9 $FLAGS --target=riscv64 -S ops.c -o riscv64.clang.S + +# clang - arm + +clang-9 $FLAGS --target=arm -mcpu=cortex-m4 -mthumb -S ops.c -o arm-m4.clang.S +clang-9 $FLAGS --target=arm -mcpu=cortex-m0 -mthumb -S ops.c -o arm-m0.clang.S +clang-9 $FLAGS --target=aarch64 -S ops.c -o arm.aarch64.clang.S + +# clang - other + +clang-9 $FLAGS --target=mipsel -S ops.c -o mipsel.clang.S +clang-9 $FLAGS --target=ppc32 -S ops.c -o ppc32.clang.S + +# enable tail-call for wasm +clang-9 $FLAGS --target=wasm32 -Xclang -target-feature -Xclang +tail-call -S ops.c -o wasm32.clang.S + + +clang-9 $FLAGS --target=wasm32 -Xclang -target-feature -Xclang +tail-call -nostdlib -Wl,--no-entry -Wl,--export-all -o wasm32.clang.wasm ops.c + +# clang - xtensa + +export PATH=$OPT/llvm_build_xtensa/bin:$PATH +clang -target xtensa -mcpu=esp32 -O3 -S ops.c -o esp32.clang.S +clang -target xtensa -mcpu=esp8266 -O3 -S ops.c -o esp8266.clang.S + +# gcc - xtensa + +export PATH=~/.platformio/packages/toolchain-xtensa/bin/:$PATH +xtensa-lx106-elf-gcc $FLAGS -S ops.c -o esp8266.S + +export PATH=~/.platformio/packages/toolchain-xtensa32/bin/:$PATH +xtensa-esp32-elf-gcc $FLAGS -S ops.c -o esp32.S + +# gcc - arm + +export PATH=/opt/gcc-arm-none-eabi-8-2018-q4/bin:$PATH +arm-none-eabi-gcc $FLAGS -mcpu=cortex-m4 -mthumb -mabi=aapcs -S ops.c -o arm-m4.S +arm-none-eabi-gcc $FLAGS -mcpu=cortex-m0 -mthumb -mabi=aapcs -S ops.c -o arm-m0.S + +# gcc - risc-v + +export PATH=~/.platformio/packages/toolchain-riscv/bin:$PATH +riscv64-unknown-elf-gcc $FLAGS -march=rv32i -mabi=ilp32 -S ops.c -o riscv32i.S +riscv64-unknown-elf-gcc $FLAGS -S ops.c -o riscv64.S + +# gcc - mips + +export STAGING_DIR=$OPT/openwrt-chaoscalmer/staging_dir +export PATH=$OPT/openwrt-chaoscalmer/staging_dir/toolchain-mipsel_24kec+dsp_gcc-4.8-linaro_uClibc-0.9.33.2/bin:$PATH +mipsel-openwrt-linux-gcc $FLAGS -mno-branch-likely -mips32r2 -mtune=24kc -fno-caller-saves -fno-plt -fhonour-copts -S ops.c -o mips24kc.S + +# gcc - arc + +export PATH=~/.platformio/packages/toolchain-intelarc32/bin:$PATH +arc-elf32-gcc $FLAGS -S ops.c -o arc32.S + +# ---------------------- +# Just for fun ;) + +export PATH=~/.platformio/packages/toolchain-atmelavr/bin:$PATH +avr-gcc $FLAGS -S ops.c -o avr.S + +export PATH=~/.platformio/packages/toolchain-timsp430/bin:$PATH +msp430-gcc $FLAGS -S ops.c -o msp430.S + +#clang-9 --target=avr -mmcu=atmega328p $FLAGS -S ops.c -o avr.clang.S +clang-9 --target=msp430 $FLAGS -S ops.c -o msp430.clang.S diff --git a/ext/wasm3/test/internal/tailcall/ops.c b/ext/wasm3/test/internal/tailcall/ops.c new file mode 100644 index 0000000..0d592ed --- /dev/null +++ b/ext/wasm3/test/internal/tailcall/ops.c @@ -0,0 +1,111 @@ +#include + +#define NULL (0) + +typedef double f64; +typedef float f32; +typedef uint64_t u64; +typedef int64_t i64; +typedef uint32_t u32; +typedef int32_t i32; +typedef uint16_t u16; +typedef int16_t i16; +typedef uint8_t u8; +typedef int8_t i8; + + +typedef i64 m3reg_t; +typedef void /*const*/ * code_t; +typedef code_t const * /*__restrict__*/ pc_t; +typedef const void * m3ret_t; + +# define vectorcall + +# define d_m3OpSig pc_t _pc, u64 * _sp, u8 * _mem, m3reg_t _r0, f64 _fp0 +# define d_m3OpArgs _sp, _mem, _r0, _fp0 +# define d_m3OpAllArgs _pc, _sp, _mem, _r0, _fp0 +# define d_m3OpDefaultArgs 666, 666.0 + +typedef m3ret_t (vectorcall * IM3Operation) (d_m3OpSig); + +# define immediate(TYPE) * ((TYPE *) _pc++) +# define slot(TYPE) * (TYPE *) (_sp + immediate (i32)) + + +# define d_m3RetSig static inline m3ret_t vectorcall +# define d_m3Op(NAME) d_m3RetSig op_##NAME (d_m3OpSig) + + +# define nextOp() ((IM3Operation)(* _pc))(_pc + 1, d_m3OpArgs) + + +#define d_m3CommutativeOpMacro(RES, REG, TYPE, NAME, OP, ...) \ +d_m3Op(TYPE##_##NAME##_sr) \ +{ \ + TYPE * stack = (TYPE *) (_sp + immediate (i32)); \ + OP((RES), (* stack), ((TYPE) REG), ##__VA_ARGS__); \ + return nextOp (); \ +} \ +d_m3Op(TYPE##_##NAME##_ss) \ +{ \ + TYPE * stackB = (TYPE *) (_sp + immediate (i32)); \ + TYPE * stackA = (TYPE *) (_sp + immediate (i32)); \ + OP((RES), (* stackA), (* stackB), ##__VA_ARGS__); \ + return nextOp (); \ +} + +#define d_m3OpMacro(RES, REG, TYPE, NAME, OP, ...) \ +d_m3Op(TYPE##_##NAME##_rs) \ +{ \ + TYPE * stack = (TYPE *) (_sp + immediate (i32)); \ + OP((RES), (* stack), ((TYPE) REG), ##__VA_ARGS__); \ + return nextOp (); \ +} \ +d_m3CommutativeOpMacro(RES, REG, TYPE,NAME, OP, ##__VA_ARGS__) + +// Accept macros +#define d_m3CommutativeOpMacro_i(TYPE, NAME, MACRO, ...) d_m3CommutativeOpMacro ( _r0, _r0, TYPE, NAME, MACRO, ##__VA_ARGS__) +#define d_m3OpMacro_i(TYPE, NAME, MACRO, ...) d_m3OpMacro ( _r0, _r0, TYPE, NAME, MACRO, ##__VA_ARGS__) +#define d_m3CommutativeOpMacro_f(TYPE, NAME, MACRO, ...) d_m3CommutativeOpMacro (_fp0, _fp0, TYPE, NAME, MACRO, ##__VA_ARGS__) +#define d_m3OpMacro_f(TYPE, NAME, MACRO, ...) d_m3OpMacro (_fp0, _fp0, TYPE, NAME, MACRO, ##__VA_ARGS__) + +#define M3_FUNC(RES, A, B, OP) (RES) = OP((A), (B)) // Accept functions: res = OP(a,b) +#define M3_OPER(RES, A, B, OP) (RES) = ((A) OP (B)) // Accept operators: res = a OP b + +#define d_m3CommutativeOpFunc_i(TYPE, NAME, OP) d_m3CommutativeOpMacro_i (TYPE, NAME, M3_FUNC, OP) +#define d_m3OpFunc_i(TYPE, NAME, OP) d_m3OpMacro_i (TYPE, NAME, M3_FUNC, OP) +#define d_m3CommutativeOpFunc_f(TYPE, NAME, OP) d_m3CommutativeOpMacro_f (TYPE, NAME, M3_FUNC, OP) +#define d_m3OpFunc_f(TYPE, NAME, OP) d_m3OpMacro_f (TYPE, NAME, M3_FUNC, OP) + +#define d_m3CommutativeOp_i(TYPE, NAME, OP) d_m3CommutativeOpMacro_i (TYPE, NAME, M3_OPER, OP) +#define d_m3Op_i(TYPE, NAME, OP) d_m3OpMacro_i (TYPE, NAME, M3_OPER, OP) +#define d_m3CommutativeOp_f(TYPE, NAME, OP) d_m3CommutativeOpMacro_f (TYPE, NAME, M3_OPER, OP) +#define d_m3Op_f(TYPE, NAME, OP) d_m3OpMacro_f (TYPE, NAME, M3_OPER, OP) + + +d_m3CommutativeOp_i (i32, Equal, ==) +d_m3CommutativeOp_i (i64, Equal, ==) +d_m3Op_i (i32, NotEqual, !=) +d_m3Op_i (i64, NotEqual, !=) + + +typedef struct M3OpInfo +{ + IM3Operation operation_sr; // top operand in register + IM3Operation operation_rs; // top operand in stack + IM3Operation operation_ss; // both operands in stack +} +M3OpInfo; + +#define d_emptyOpList() NULL, NULL, NULL +#define d_unaryOpList(TYPE, NAME) op_##TYPE##_##NAME##_r, op_##TYPE##_##NAME##_s, NULL +#define d_binOpList(TYPE, NAME) op_##TYPE##_##NAME##_sr, op_##TYPE##_##NAME##_rs, op_##TYPE##_##NAME##_ss +#define d_commutativeBinOpList(TYPE, NAME) op_##TYPE##_##NAME##_sr, NULL, op_##TYPE##_##NAME##_ss + + +M3OpInfo c_operations[] = { + { d_commutativeBinOpList (i32, Equal) }, + { d_binOpList (i32, NotEqual) }, + { d_commutativeBinOpList (i64, Equal) }, + { d_binOpList (i64, NotEqual) }, +}; diff --git a/ext/wasm3/test/lang/README.md b/ext/wasm3/test/lang/README.md new file mode 100644 index 0000000..ba12029 --- /dev/null +++ b/ext/wasm3/test/lang/README.md @@ -0,0 +1,31 @@ +# Performance + +```log +Function: fib(40) +----------------------------------------------------- + Device: Lenovo Ideapad 720s [i5-8250U @ 1.60GHz] +----------------------------------------------------- +Linux x64 gcc 7.4.0 4.63s +Linux x64 clang 9 5.32s +Win 10 x64 clang 9 5.35s +Win 10 x64 msvc 2019 6.10s +Win 10 x86 clang 9.43s - no TCO +Linux x86 gcc 11.34s +Linux x86 clang 15.37s - no TCO +``` + +## Running + +```sh +# WAC +time $(ENGINES_PATH)/wac/wac fib32.wasm fib 40 + +# WAMR +time $(ENGINES_PATH)/wasm-micro-runtime/core/iwasm/products/linux/build/iwasm -f fib fib32.wasm 40 + +# Wasmer +time wasmer run --em-entrypoint fib fib32.wasm -- 40 + +# WAVM +time $(ENGINES_PATH)/wasm-jit-prototype/_build/bin/wavm run -f fib fib32.wasm 40 +``` diff --git a/ext/wasm3/test/lang/fib.c b/ext/wasm3/test/lang/fib.c new file mode 100644 index 0000000..aa75f9f --- /dev/null +++ b/ext/wasm3/test/lang/fib.c @@ -0,0 +1,30 @@ +/* + * emcc -g0 -O3 -s SIDE_MODULE=1 -s STRICT=1 -s WASM=1 -s ONLY_MY_CODE=1 -o fib.c.wasm fib.c + * gcc -g0 -O3 fib.c -o fib.c.elf + */ + +#include +#define WASM_EXPORT __attribute__((used)) __attribute__((visibility ("default"))) + +WASM_EXPORT +uint32_t fib(uint32_t n) +{ + if(n < 2) { + return n; + } + return fib(n-1) + fib(n-2); +} + +int parseInt(char* str) { + int res = 0; + for (int i = 0; str[i] != '\0'; ++i) { + res = res * 10 + str[i] - '0'; + } + return res; +} + +WASM_EXPORT +int main(int args, char* argv[]) { + uint32_t n = parseInt(argv[1]); + return fib(n); +} diff --git a/ext/wasm3/test/lang/fib.js b/ext/wasm3/test/lang/fib.js new file mode 100755 index 0000000..a685186 --- /dev/null +++ b/ext/wasm3/test/lang/fib.js @@ -0,0 +1,8 @@ +function fib(n) { + if(n < 2) { + return n; + } + return fib(n-1) + fib(n-2) +} + +console.log(fib(process.argv[2])) diff --git a/ext/wasm3/test/lang/fib.lua b/ext/wasm3/test/lang/fib.lua new file mode 100755 index 0000000..bc14e7a --- /dev/null +++ b/ext/wasm3/test/lang/fib.lua @@ -0,0 +1,8 @@ +local function fib(n) + if n < 2 then + return n + end + return fib(n-1) + fib(n-2) +end + +print(fib(tonumber(arg[1]))) diff --git a/ext/wasm3/test/lang/fib.min.js b/ext/wasm3/test/lang/fib.min.js new file mode 100755 index 0000000..0903156 --- /dev/null +++ b/ext/wasm3/test/lang/fib.min.js @@ -0,0 +1,3 @@ +function fib(f){if(f<2)return f +return fib(f-1)+fib(f-2)} +console.log(fib(32)); diff --git a/ext/wasm3/test/lang/fib.py b/ext/wasm3/test/lang/fib.py new file mode 100755 index 0000000..cb47c8f --- /dev/null +++ b/ext/wasm3/test/lang/fib.py @@ -0,0 +1,7 @@ +import sys +def fib(n): + if n < 2: + return n + return fib(n-1) + fib(n-2) + +print(fib(int(sys.argv[1]))) diff --git a/ext/wasm3/test/lang/fib.walt b/ext/wasm3/test/lang/fib.walt new file mode 100644 index 0000000..45d02dd --- /dev/null +++ b/ext/wasm3/test/lang/fib.walt @@ -0,0 +1,6 @@ +export function fib(n: i32): i32 { + if (n < 2) { + return n; + } + return fib(n-1) + fib(n-2); +} diff --git a/ext/wasm3/test/lang/fib32.wat b/ext/wasm3/test/lang/fib32.wat new file mode 100644 index 0000000..5316eb2 --- /dev/null +++ b/ext/wasm3/test/lang/fib32.wat @@ -0,0 +1,30 @@ +(module + (export "fib" (func $fib)) + (func $fib (param $n i32) (result i32) + (if + (i32.lt_u + (get_local $n) + (i32.const 2) + ) + (return + (get_local $n) + ) + ) + (return + (i32.add + (call $fib + (i32.sub + (get_local $n) + (i32.const 2) + ) + ) + (call $fib + (i32.sub + (get_local $n) + (i32.const 1) + ) + ) + ) + ) + ) +) diff --git a/ext/wasm3/test/lang/fib32_tail.wat b/ext/wasm3/test/lang/fib32_tail.wat new file mode 100644 index 0000000..36d2614 --- /dev/null +++ b/ext/wasm3/test/lang/fib32_tail.wat @@ -0,0 +1,17 @@ +(module + (func $fib2 (param $n i32) (param $a i32) (param $b i32) (result i32) + (if (result i32) + (i32.eqz (get_local $n)) + (then (get_local $a)) + (else (return_call $fib2 (i32.sub (get_local $n) + (i32.const 1)) + (get_local $b) + (i32.add (get_local $a) + (get_local $b)))))) + + (func $fib (param i32) (result i32) + (return_call $fib2 (get_local 0) + (i32.const 0) ;; seed value $a + (i32.const 1))) ;; seed value $b + + (export "fib" (func $fib))) diff --git a/ext/wasm3/test/lang/fib64.wat b/ext/wasm3/test/lang/fib64.wat new file mode 100644 index 0000000..9a31ba3 --- /dev/null +++ b/ext/wasm3/test/lang/fib64.wat @@ -0,0 +1,30 @@ +(module + (export "fib" (func $fib)) + (func $fib (param $n i64) (result i64) + (if + (i64.lt_u + (get_local $n) + (i64.const 2) + ) + (return + (get_local $n) + ) + ) + (return + (i64.add + (call $fib + (i64.sub + (get_local $n) + (i64.const 2) + ) + ) + (call $fib + (i64.sub + (get_local $n) + (i64.const 1) + ) + ) + ) + ) + ) +) diff --git a/ext/wasm3/test/run-spec-test.py b/ext/wasm3/test/run-spec-test.py new file mode 100755 index 0000000..48c361c --- /dev/null +++ b/ext/wasm3/test/run-spec-test.py @@ -0,0 +1,597 @@ +#!/usr/bin/env python3 + +# Author: Volodymyr Shymanskyy +# Usage: +# ./run-spec-test.py +# ./run-spec-test.py --spec=opam-1.1.1 +# ./run-spec-test.py .spec-v1.1/core/i32.json +# ./run-spec-test.py .spec-v1.1/core/float_exprs.json --line 2070 +# ./run-spec-test.py .spec-v1.1/proposals/tail-call/*.json +# ./run-spec-test.py --exec "../build-custom/wasm3 --repl" +# +# Running WASI version with different engines: +# cp ../build-wasi/wasm3.wasm ./ +# ./run-spec-test.py --exec "../build/wasm3 wasm3.wasm --repl" +# ./run-spec-test.py --exec "wasmtime --dir=. wasm3.wasm -- --repl" +# ./run-spec-test.py --exec "wasmer run --dir=. wasm3.wasm -- --repl" +# ./run-spec-test.py --exec "wasmer run --dir=. --backend=llvm wasm3.wasm -- --repl" +# ./run-spec-test.py --exec "wasmer-js run wasm3.wasm --dir=. -- --repl" +# ./run-spec-test.py --exec "wasirun wasm3.wasm --repl" +# ./run-spec-test.py --exec "wavm run --mount-root ./ wasm3.wasm -- --repl" +# ./run-spec-test.py --exec "iwasm --dir=. wasm3.wasm --repl" +# + +# TODO +# - Get more tests from: https://github.com/microsoft/ChakraCore/tree/master/test/WasmSpec +# - Fix "Empty Stack" check +# - Check Canonical NaN and Arithmetic NaN separately +# - Fix imports.wast + +import argparse +import os, sys, glob, time +import subprocess +import json +import re +import struct +import math +import pathlib + +scriptDir = os.path.dirname(os.path.abspath(sys.argv[0])) +sys.path.append(os.path.join(scriptDir, '..', 'extra')) + +from testutils import * +from pprint import pprint + + +# +# Args handling +# + +parser = argparse.ArgumentParser() +parser.add_argument("--exec", metavar="", default="../build/wasm3 --repl") +parser.add_argument("--spec", default="opam-1.1.1") +parser.add_argument("--timeout", type=int, default=30) +parser.add_argument("--line", metavar="", type=int) +parser.add_argument("--all", action="store_true") +parser.add_argument("--show-logs", action="store_true") +parser.add_argument("--format", choices=["raw", "hex", "fp"], default="fp") +parser.add_argument("-v", "--verbose", action="store_true") +parser.add_argument("-s", "--silent", action="store_true") +parser.add_argument("file", nargs='*') + +args = parser.parse_args() + +if args.line: + args.show_logs = True + +# +# Utilities +# + +log = open("spec-test.log","w+") +log.write("======================\n") + +def warning(msg, force=False): + log.write("Warning: " + msg + "\n") + log.flush() + if args.verbose or force: + print(f"{ansi.WARNING}Warning:{ansi.ENDC} {msg}") + +def fatal(msg): + log.write("Fatal: " + msg + "\n") + log.flush() + print(f"{ansi.FAIL}Fatal:{ansi.ENDC} {msg}") + sys.exit(1) + +def safe_fn(fn): + keepcharacters = (' ','.','_','-') + return "".join(c for c in fn if c.isalnum() or c in keepcharacters).strip() + +def binaryToFloat(num, t): + if t == "f32": + return struct.unpack('!f', struct.pack('!L', int(num)))[0] + elif t == "f64": + return struct.unpack('!d', struct.pack('!Q', int(num)))[0] + else: + fatal(f"Unknown type '{t}'") + +def escape_str(s): + if s == "": + return r'\x00' + + if all((ord(c) < 128 and c.isprintable() and c not in " \n\r\t\\") for c in s): + return s + + return '\\x' + '\\x'.join('{0:02x}'.format(x) for x in s.encode('utf-8')) + +# +# Value format options +# + +def formatValueRaw(num, t): + return str(num) + +def formatValueHex(num, t): + if t == "f32" or t == "i32": + return "{0:#0{1}x}".format(int(num), 8+2) + elif t == "f64" or t == "i64": + return "{0:#0{1}x}".format(int(num), 16+2) + else: + return str(num) + +def formatValueFloat(num, t): + if t == "f32": + s = 6 + elif t == "f64": + s = 10 + else: + return str(num) + + result = "{0:.{1}f}".format(binaryToFloat(num, t), s).rstrip('0') + if result.endswith('.'): + result = result + '0' + if len(result) > s*2: + result = "{0:.{1}e}".format(binaryToFloat(num, t), s) + return result + +formaters = { + 'raw': formatValueRaw, + 'hex': formatValueHex, + 'fp': formatValueFloat, +} +formatValue = formaters[args.format] + +if args.format == "fp": + print("When using fp display format, values are compared loosely (some tests may produce false positives)") + +# +# Spec tests preparation +# + +spec_dir = os.path.join(".", ".spec-" + safe_fn(args.spec)) + +if not (os.path.isdir(spec_dir)): + from io import BytesIO + from zipfile import ZipFile + from urllib.request import urlopen + + officialSpec = f"https://github.com/wasm3/wasm-core-testsuite/archive/{args.spec}.zip" + + print(f"Downloading {officialSpec}") + resp = urlopen(officialSpec) + with ZipFile(BytesIO(resp.read())) as zipFile: + for zipInfo in zipFile.infolist(): + if re.match(r".*-.*/.*/.*(\.wasm|\.json)", zipInfo.filename): + parts = pathlib.Path(zipInfo.filename).parts + newpath = str(pathlib.Path(*parts[1:-1])) + newfn = str(pathlib.Path(*parts[-1:])) + ensure_path(os.path.join(spec_dir, newpath)) + newpath = os.path.join(spec_dir, newpath, newfn) + zipInfo.filename = newpath + zipFile.extract(zipInfo) + +# +# Wasm3 REPL +# + +from subprocess import Popen, STDOUT, PIPE +from threading import Thread +from queue import Queue, Empty + +import shlex + +class Wasm3(): + def __init__(self, exe): + self.exe = exe + self.p = None + self.loaded = None + self.timeout = args.timeout + self.autorestart = True + + self.run() + + def run(self): + if self.p: + self.terminate() + + cmd = shlex.split(self.exe) + + #print(f"wasm3: Starting {' '.join(cmd)}") + + self.q = Queue() + self.p = Popen(cmd, bufsize=0, stdin=PIPE, stdout=PIPE, stderr=STDOUT) + + def _read_output(out, queue): + for data in iter(lambda: out.read(1024), b''): + queue.put(data) + queue.put(None) + + self.t = Thread(target=_read_output, args=(self.p.stdout, self.q)) + self.t.daemon = True + self.t.start() + + try: + self._read_until("wasm3> ") + except Exception as e: + print(f"wasm3: Could not start: {e}") + + def restart(self): + print(f"wasm3: Restarting") + for i in range(10): + try: + self.run() + try: + if self.loaded: + self.load(self.loaded) + except Exception as e: + pass + break + except Exception as e: + print(f"wasm3: {e} => retry") + time.sleep(0.1) + + def init(self): + return self._run_cmd(f":init\n") + + def version(self): + return self._run_cmd(f":version\n") + + def load(self, fn): + self.loaded = None + with open(fn,"rb") as f: + wasm = f.read() + res = self._run_cmd(f":load-hex {len(wasm)}\n{wasm.hex()}\n") + self.loaded = fn + return res + + def invoke(self, cmd): + return self._run_cmd(":invoke " + " ".join(map(str, cmd)) + "\n") + + def _run_cmd(self, cmd): + if self.autorestart and not self._is_running(): + self.restart() + self._flush_input() + + #print(f"wasm3: {cmd.strip()}") + self._write(cmd) + return self._read_until("wasm3> ") + + def _read_until(self, token): + buff = "" + tout = time.time() + self.timeout + error = None + + while time.time() < tout: + try: + data = self.q.get(timeout=0.1) + if data is None: + error = "Crashed" + break + buff = buff + data.decode("utf-8") + idx = buff.rfind(token) + if idx >= 0: + return buff[0:idx].strip() + except Empty: + pass + else: + error = "Timeout" + + self.terminate() + raise Exception(error) + + def _write(self, data): + self.p.stdin.write(data.encode("utf-8")) + self.p.stdin.flush() + + def _is_running(self): + return self.p and (self.p.poll() is None) + + def _flush_input(self): + while not self.q.empty(): + self.q.get() + + def terminate(self): + self.p.stdin.close() + self.p.terminate() + self.p.wait(timeout=1.0) + self.p = None + +# +# Multi-value result handling +# + +def parseResults(s): + values = s.split(", ") + values = [x.split(":") for x in values] + values = [{ "type": x[1], "value": int(x[0]) } for x in values] + + return normalizeResults(values) + +def normalizeResults(values): + for x in values: + t = x["type"] + v = x["value"] + if t == "f32" or t == "f64": + if v == "nan:canonical" or v == "nan:arithmetic" or math.isnan(binaryToFloat(v, t)): + x["value"] = "nan:any" + else: + x["value"] = formatValue(v, t) + else: + x["value"] = formatValue(v, t) + return values + +def combineResults(values): + values = [x["value"]+":"+x["type"] for x in values] + return ", ".join(values) + +# +# Actual test +# + +wasm3 = Wasm3(args.exec) + +wasm3_ver = wasm3.version() +print(wasm3_ver) + +blacklist = Blacklist([ + "float_exprs.wast:* f32.nonarithmetic_nan_bitpattern*", + "imports.wast:*", + "names.wast:* *.wasm \\x00*", # names that start with '\0' +]) + +if wasm3_ver in Blacklist(["* on i386* MSVC *", "* on i386* Clang * for Windows"]): + warning("Win32 x86 has i64->f32 conversion precision issues, skipping some tests", True) + # See: https://docs.microsoft.com/en-us/cpp/c-runtime-library/floating-point-support + blacklist.add([ + "conversions.wast:* f32.convert_i64_u(9007199791611905)", + "conversions.wast:* f32.convert_i64_u(9223371761976868863)", + "conversions.wast:* f32.convert_i64_u(9223372586610589697)", + ]) +elif wasm3_ver in Blacklist(["* on mips* GCC *"]): + warning("MIPS has NaN representation issues, skipping some tests", True) + blacklist.add([ + "float_exprs.wast:* *_nan_bitpattern(*", + "float_exprs.wast:* *no_fold_*", + ]) +elif wasm3_ver in Blacklist(["* on sparc* GCC *"]): + warning("SPARC has NaN representation issues, skipping some tests", True) + blacklist.add([ + "float_exprs.wast:* *.canonical_nan_bitpattern(0, 0)", + ]) + +stats = dotdict(total_run=0, skipped=0, failed=0, crashed=0, timeout=0, success=0, missing=0) + +# Convert some trap names from the original spec +trapmap = { + "unreachable": "unreachable executed" +} + +def runInvoke(test): + test.cmd = [test.action.field] + + displayArgs = [] + for arg in test.action.args: + test.cmd.append(arg['value']) + displayArgs.append(formatValue(arg['value'], arg['type'])) + + test_id = f"{test.source} {test.wasm} {test.cmd[0]}({', '.join(test.cmd[1:])})" + if test_id in blacklist and not args.all: + warning(f"Skipped {test_id} (blacklisted)") + stats.skipped += 1 + return + + if args.verbose: + print(f"Running {test_id}") + + stats.total_run += 1 + + output = "" + actual = None + actual_val = None + force_fail = False + + try: + output = wasm3.invoke(test.cmd) + except Exception as e: + actual = f"<{e}>" + force_fail = True + + # Parse the actual output + if not actual: + result = re.findall(r'Result: (.*?)$', "\n" + output + "\n", re.MULTILINE) + if len(result) > 0: + actual = "result " + result[-1] + actual_val = result[0] + if not actual: + result = re.findall(r'Error: \[trap\] (.*?) \(', "\n" + output + "\n", re.MULTILINE) + if len(result) > 0: + actual = "trap " + result[-1] + if not actual: + result = re.findall(r'Error: (.*?)$', "\n" + output + "\n", re.MULTILINE) + if len(result) > 0: + actual = "error " + result[-1] + if not actual: + actual = "" + force_fail = True + + if actual == "error no operation ()": + actual = "" + stats.missing += 1 + force_fail = True + elif actual == "": + stats.crashed += 1 + force_fail = True + elif actual == "": + stats.timeout += 1 + force_fail = True + + # Prepare the expected result + expect = None + if "expected" in test: + if len(test.expected) == 0: + expect = "result " + else: + if actual_val is not None: + actual = "result " + combineResults(parseResults(actual_val)) + expect = "result " + combineResults(normalizeResults(test.expected)) + + elif "expected_trap" in test: + if test.expected_trap in trapmap: + test.expected_trap = trapmap[test.expected_trap] + + expect = "trap " + str(test.expected_trap) + elif "expected_anything" in test: + expect = "" + else: + expect = "" + + def showTestResult(): + print(" ----------------------") + print(f"Test: {ansi.HEADER}{test_id}{ansi.ENDC}") + print(f"Args: {', '.join(displayArgs)}") + print(f"Expected: {ansi.OKGREEN}{expect}{ansi.ENDC}") + print(f"Actual: {ansi.WARNING}{actual}{ansi.ENDC}") + if args.show_logs and len(output): + print(f"Log:") + print(output) + + log.write(f"{test.source}\t|\t{test.wasm} {test.action.field}({', '.join(displayArgs)})\t=>\t\t") + if actual == expect or (expect == "" and not force_fail): + stats.success += 1 + log.write(f"OK: {actual}\n") + if args.line: + showTestResult() + else: + stats.failed += 1 + log.write(f"FAIL: {actual}, should be: {expect}\n") + if args.silent: + return + + showTestResult() + #sys.exit(1) + +if args.file: + jsonFiles = args.file +else: + jsonFiles = glob.glob(os.path.join(spec_dir, "core", "*.json")) + jsonFiles += glob.glob(os.path.join(spec_dir, "proposals", "sign-extension-ops", "*.json")) + jsonFiles += glob.glob(os.path.join(spec_dir, "proposals", "nontrapping-float-to-int-conversions", "*.json")) + +jsonFiles = list(map(lambda x: os.path.relpath(x, scriptDir), jsonFiles)) +jsonFiles.sort() + +for fn in jsonFiles: + with open(fn, encoding='utf-8') as f: + data = json.load(f) + + wast_source = filename(data["source_filename"]) + wasm_module = "" + + print(f"Running {fn}") + + for cmd in data["commands"]: + test = dotdict() + test.line = int(cmd["line"]) + test.source = wast_source + ":" + str(test.line) + test.wasm = wasm_module + test.type = cmd["type"] + + if test.type == "module": + wasm_module = cmd["filename"] + + if args.verbose: + print(f"Loading {wasm_module}") + + try: + wasm_fn = os.path.join(pathname(fn), wasm_module) + + wasm3.init() + + res = wasm3.load(wasm_fn) + if res: + warning(res) + except Exception as e: + pass #fatal(str(e)) + + elif ( test.type == "action" or + test.type == "assert_return" or + test.type == "assert_trap" or + test.type == "assert_exhaustion" or + test.type == "assert_return_canonical_nan" or + test.type == "assert_return_arithmetic_nan"): + + if args.line and test.line != args.line: + continue + + if test.type == "action": + test.expected_anything = True + elif test.type == "assert_return": + test.expected = cmd["expected"] + elif test.type == "assert_return_canonical_nan": + test.expected = cmd["expected"] + test.expected[0]["value"] = "nan:canonical" + elif test.type == "assert_return_arithmetic_nan": + test.expected = cmd["expected"] + test.expected[0]["value"] = "nan:arithmetic" + elif test.type == "assert_trap": + test.expected_trap = cmd["text"] + elif test.type == "assert_exhaustion": + test.expected_trap = "stack overflow" + else: + stats.skipped += 1 + warning(f"Skipped {test.source} ({test.type} not implemented)") + continue + + test.action = dotdict(cmd["action"]) + if test.action.type == "invoke": + + # TODO: invoking in modules not implemented + if test.action.module: + stats.skipped += 1 + warning(f"Skipped {test.source} (invoke in module)") + continue + + test.action.field = escape_str(test.action.field) + + runInvoke(test) + else: + stats.skipped += 1 + warning(f"Skipped {test.source} (unknown action type '{test.action.type}')") + + + # These are irrelevant + elif (test.type == "assert_invalid" or + test.type == "assert_malformed" or + test.type == "assert_uninstantiable"): + pass + + # Others - report as skipped + else: + stats.skipped += 1 + warning(f"Skipped {test.source} ('{test.type}' not implemented)") + +if (stats.failed + stats.success) != stats.total_run: + warning("Statistics summary invalid", True) + +pprint(stats) + +if stats.failed > 0: + failed = (stats.failed*100)/stats.total_run + print(f"{ansi.FAIL}=======================") + print(f" FAILED: {failed:.2f}%") + if stats.crashed > 0: + print(f" Crashed: {stats.crashed}") + print(f"======================={ansi.ENDC}") + sys.exit(1) + +elif stats.success > 0: + print(f"{ansi.OKGREEN}=======================") + print(f" {stats.success}/{stats.total_run} tests OK") + if stats.skipped > 0: + print(f"{ansi.WARNING} ({stats.skipped} tests skipped){ansi.OKGREEN}") + print(f"======================={ansi.ENDC}") + +elif stats.total_run == 0: + print("Error: No tests run") + sys.exit(1) + diff --git a/ext/wasm3/test/run-wasi-test.py b/ext/wasm3/test/run-wasi-test.py new file mode 100755 index 0000000..9773b1e --- /dev/null +++ b/ext/wasm3/test/run-wasi-test.py @@ -0,0 +1,216 @@ +#!/usr/bin/env python3 + +# Author: Volodymyr Shymanskyy +# Usage: +# ./run-wasi-test.py +# ./run-wasi-test.py --exec ../custom_build/wasm3 --timeout 120 +# ./run-wasi-test.py --exec "wasmer run --mapdir=/:." --separate-args +# ./run-wasi-test.py --exec "wasmer run --mapdir=/:. wasm3.wasm --" --fast + +import argparse +import sys +import subprocess +import hashlib +import fnmatch + +sys.path.append('../extra') + +from testutils import * +from pprint import pprint + +# +# Args handling +# + +parser = argparse.ArgumentParser() +parser.add_argument("--exec", metavar="", default="../build/wasm3") +parser.add_argument("--separate-args", action='store_true') # use "--" separator for wasmer, wasmtime +parser.add_argument("--timeout", type=int, default=120) +parser.add_argument("--fast", action='store_true') + +args = parser.parse_args() + +stats = dotdict(total_run=0, failed=0, crashed=0, timeout=0) + +commands_full = [ + { + "name": "Simple WASI test", + "wasm": "./wasi/simple/test.wasm", + "args": ["cat", "/wasi/simple/0.txt"], + "expect_pattern": "Hello world*Constructor OK*Args: *; cat; /wasi/simple/0.txt;*fib(20) = 6765* ms*48 65 6c 6c 6f 20 77 6f 72 6c 64*=== done ===*" + }, { + "name": "Simple WASI test (wasm-opt -O3)", + "wasm": "./wasi/simple/test-opt.wasm", + "args": ["cat", "./wasi/simple/0.txt"], + "expect_pattern": "Hello world*Constructor OK*Args: *; cat; ./wasi/simple/0.txt;*fib(20) = 6765* ms*48 65 6c 6c 6f 20 77 6f 72 6c 64*=== done ===*" + }, { + "name": "mandelbrot", + "wasm": "./wasi/mandelbrot/mandel.wasm", + "args": ["128", "4e5"], + "expect_sha1": "37091e7ce96adeea88f079ad95d239a651308a56" + }, { + "name": "mandelbrot (doubledouble)", + "wasm": "./wasi/mandelbrot/mandel_dd.wasm", + "args": ["128", "4e5"], + "expect_sha1": "b3f904daf1c972b4f7d3f8996743cb5b5146b877" + }, { + "name": "C-Ray", + "stdin": "./wasi/c-ray/scene", + "wasm": "./wasi/c-ray/c-ray.wasm", + "args": ["-s", "128x128"], + "expect_sha1": "90f86845ae227466a06ea8db06e753af4838f2fa" + }, { + "name": "smallpt (explicit light sampling)", + "wasm": "./wasi/smallpt/smallpt-ex.wasm", + "args": ["16", "64"], + "expect_sha1": "d85df3561eb15f6f0e6f20d5640e8e1306222c6d" + }, { + "name": "smallpt (explicit light sampling, multi-value)", + "wasm": "./wasi/smallpt/smallpt-ex-mv.wasm", + "args": ["16", "64"], + "expect_sha1": "d85df3561eb15f6f0e6f20d5640e8e1306222c6d" + }, { + "name": "mal", + "wasm": "./wasi/mal/mal.wasm", + "args": ["./wasi/mal/test-fib.mal", "16"], + "expect_pattern": "987\n", + }, { + "name": "STREAM", + "wasm": "./wasi/stream/stream.wasm", + "expect_pattern": "----*Solution Validates:*on all three arrays*----*" + }, { + # TODO "if": { "file_exists": "./self-hosting/wasm3-fib.wasm" }, + "name": "Self-hosting", + "wasm": "./self-hosting/wasm3-fib.wasm", + "expect_pattern": "wasm3 on WASM*Result: 832040*Elapsed: * ms*" + }, { + "name": "Brotli", + "stdin": "./wasi/brotli/alice29.txt", + "wasm": "./wasi/brotli/brotli.wasm", + "args": ["-c", "-f"], + "expect_sha1": "8eacda4b80fc816cad185330caa7556e19643dff" + }, { + "name": "CoreMark", + "wasm": "./wasi/coremark/coremark.wasm", + "expect_pattern": "*Correct operation validated.*CoreMark 1.0 : * / Clang* / STATIC*" + } +] + +commands_fast = [ + { + "name": "Simple WASI test", + "wasm": "./wasi/simple/test.wasm", + "args": ["cat", "./wasi/simple/0.txt"], + "expect_pattern": "Hello world*Constructor OK*Args: *; cat; ./wasi/simple/0.txt;*fib(20) = 6765* ms*48 65 6c 6c 6f 20 77 6f 72 6c 64*=== done ===*" + }, { + "skip": True, # Backtraces not enabled by default + "name": "Simple WASI test", + "wasm": "./wasi/test.wasm", + "args": ["trap"], + "can_crash": True, + "expect_pattern": "Hello world*Constructor OK*Args: *; trap;* wasm backtrace:* 6: 0x*Error:* unreachable executed*" + }, { + "name": "mandelbrot", + "wasm": "./wasi/mandelbrot/mandel.wasm", + "args": ["32", "4e5"], + "expect_sha1": "1fdb7dea7ec0f2465054cc623dc5a7225a876361" + }, { + "name": "mandelbrot (doubledouble)", + "wasm": "./wasi/mandelbrot/mandel_dd.wasm", + "args": ["32", "4e5"], + "expect_sha1": "b6d3c158a5c0dff1f6e82a3556c071e4f8b9e3f0" + }, { + "name": "C-Ray", + "stdin": "./wasi/c-ray/scene", + "wasm": "./wasi/c-ray/c-ray.wasm", + "args": ["-s", "32x32"], + "expect_sha1": "05af9604bf352234276e4d64e84b8d666574316c" + }, { + "name": "smallpt (explicit light sampling)", + "wasm": "./wasi/smallpt/smallpt-ex.wasm", + "args": ["4", "32"], + "expect_sha1": "ea05d85998b2f453b588ef76a1256215bf9b851c" + }, { + "name": "smallpt (explicit light sampling, multi-value)", + "wasm": "./wasi/smallpt/smallpt-ex-mv.wasm", + "args": ["4", "32"], + "expect_sha1": "ea05d85998b2f453b588ef76a1256215bf9b851c" + }, { + "name": "mal", + "wasm": "./wasi/mal/mal.wasm", + "args": ["./wasi/mal/test-fib.mal", "16"], + "expect_pattern": "987\n", + }, { + "name": "Brotli", + "stdin": "./wasi/brotli/alice29_small.txt", + "wasm": "./wasi/brotli/brotli.wasm", + "args": ["-c", "-f"], + "expect_sha1": "0e8af02a7207c0c617d7d38eed92853c4a619987" + } +] + +def fail(msg): + print(f"{ansi.FAIL}FAIL:{ansi.ENDC} {msg}") + stats.failed += 1 + +commands = commands_fast if args.fast else commands_full + +for cmd in commands: + if "skip" in cmd: + continue + + command = args.exec.split(' ') + command.append(cmd['wasm']) + if "args" in cmd: + if args.separate_args: + command.append("--") + command.extend(cmd['args']) + + command = list(map(str, command)) + print(f"=== {cmd['name']} ===") + stats.total_run += 1 + try: + if "stdin" in cmd: + fn = cmd['stdin'] + f = open(fn, "rb") + print(f"cat {fn} | {' '.join(command)}") + output = subprocess.check_output(command, timeout=args.timeout, stdin=f) + elif "can_crash" in cmd: + print(f"{' '.join(command)}") + output = subprocess.run(command, timeout=args.timeout, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).stdout + else: + print(f"{' '.join(command)}") + output = subprocess.check_output(command, timeout=args.timeout) + except subprocess.TimeoutExpired: + stats.timeout += 1 + fail("Timeout") + continue + except subprocess.CalledProcessError as e: + stats.crashed += 1 + fail(f"Exited with error code {e.returncode}") + continue + + if "expect_sha1" in cmd: + actual = hashlib.sha1(output).hexdigest() + if actual != cmd['expect_sha1']: + fail(f"Actual sha1: {actual}") + + if "expect_pattern" in cmd: + actual = output.decode("utf-8") + if not fnmatch.fnmatch(actual, cmd['expect_pattern']): + fail(f"Output does not match pattern:\n{actual}") + + print() + +pprint(stats) + +if stats.failed: + print(f"{ansi.FAIL}=======================") + print(f" FAILED: {stats.failed}/{stats.total_run}") + print(f"======================={ansi.ENDC}") + sys.exit(1) + +else: + print(f"{ansi.OKGREEN}=======================") + print(f" All {stats.total_run} tests OK") + print(f"======================={ansi.ENDC}") diff --git a/ext/wasm3/test/wasi/brotli/README.md b/ext/wasm3/test/wasi/brotli/README.md new file mode 100644 index 0000000..ec8f6aa --- /dev/null +++ b/ext/wasm3/test/wasi/brotli/README.md @@ -0,0 +1,47 @@ +# Brotli 1.0.7 + +https://github.com/google/brotli + +### Results + +```log +TODO +``` + +### Building + +```sh +export CC=wasicc +make +cd bin +wasm-opt -O3 brotli.wasm -o brotli.wasm +``` + +### Running + +```sh +export ENGINES_PATH=/opt/wasm_engines + +# Wasm3 +cat alice29.txt | ../../../build/wasm3 brotli.wasm -c > alice29.txt.comp + +# WAC +cat alice29.txt | $ENGINES_PATH/wac/wax brotli.wasm -c > alice29.txt.comp + +# wasm-micro-runtime +cat alice29.txt | $ENGINES_PATH/wasm-micro-runtime/core/iwasm/products/linux/build/iwasm brotli.wasm -c > alice29.txt.comp + +# wasmtime +cat alice29.txt | wasmtime --optimize brotli.wasm -- -c > alice29.txt.comp + +# Wasmer +cat alice29.txt | wasmer run brotli.wasm -- -c > alice29.txt.comp + +# Wasmer-JS (V8) +cat alice29.txt | wasmer-js run brotli.wasm -- -c > alice29.txt.comp + +cat alice29.txt | node --wasm_interpret_all $(which wasmer-js) run brotli.wasm -- -c > alice29.txt.comp + +# WAVM +cat alice29.txt | $ENGINES_PATH/WAVM/Release/bin/wavm run brotli.wasm -c > alice29.txt.comp +``` diff --git a/ext/wasm3/test/wasi/brotli/alice29.txt b/ext/wasm3/test/wasi/brotli/alice29.txt new file mode 100644 index 0000000..f115686 --- /dev/null +++ b/ext/wasm3/test/wasi/brotli/alice29.txt @@ -0,0 +1,3609 @@ + + + + + ALICE'S ADVENTURES IN WONDERLAND + + Lewis Carroll + + THE MILLENNIUM FULCRUM EDITION 2.9 + + + + + CHAPTER I + + Down the Rabbit-Hole + + + Alice was beginning to get very tired of sitting by her sister +on the bank, and of having nothing to do: once or twice she had +peeped into the book her sister was reading, but it had no +pictures or conversations in it, `and what is the use of a book,' +thought Alice `without pictures or conversation?' + + So she was considering in her own mind (as well as she could, +for the hot day made her feel very sleepy and stupid), whether +the pleasure of making a daisy-chain would be worth the trouble +of getting up and picking the daisies, when suddenly a White +Rabbit with pink eyes ran close by her. + + There was nothing so VERY remarkable in that; nor did Alice +think it so VERY much out of the way to hear the Rabbit say to +itself, `Oh dear! Oh dear! I shall be late!' (when she thought +it over afterwards, it occurred to her that she ought to have +wondered at this, but at the time it all seemed quite natural); +but when the Rabbit actually TOOK A WATCH OUT OF ITS WAISTCOAT- +POCKET, and looked at it, and then hurried on, Alice started to +her feet, for it flashed across her mind that she had never +before seen a rabbit with either a waistcoat-pocket, or a watch to +take out of it, and burning with curiosity, she ran across the +field after it, and fortunately was just in time to see it pop +down a large rabbit-hole under the hedge. + + In another moment down went Alice after it, never once +considering how in the world she was to get out again. + + The rabbit-hole went straight on like a tunnel for some way, +and then dipped suddenly down, so suddenly that Alice had not a +moment to think about stopping herself before she found herself +falling down a very deep well. + + Either the well was very deep, or she fell very slowly, for she +had plenty of time as she went down to look about her and to +wonder what was going to happen next. First, she tried to look +down and make out what she was coming to, but it was too dark to +see anything; then she looked at the sides of the well, and +noticed that they were filled with cupboards and book-shelves; +here and there she saw maps and pictures hung upon pegs. She +took down a jar from one of the shelves as she passed; it was +labelled `ORANGE MARMALADE', but to her great disappointment it +was empty: she did not like to drop the jar for fear of killing +somebody, so managed to put it into one of the cupboards as she +fell past it. + + `Well!' thought Alice to herself, `after such a fall as this, I +shall think nothing of tumbling down stairs! How brave they'll +all think me at home! Why, I wouldn't say anything about it, +even if I fell off the top of the house!' (Which was very likely +true.) + + Down, down, down. Would the fall NEVER come to an end! `I +wonder how many miles I've fallen by this time?' she said aloud. +`I must be getting somewhere near the centre of the earth. Let +me see: that would be four thousand miles down, I think--' (for, +you see, Alice had learnt several things of this sort in her +lessons in the schoolroom, and though this was not a VERY good +opportunity for showing off her knowledge, as there was no one to +listen to her, still it was good practice to say it over) `--yes, +that's about the right distance--but then I wonder what Latitude +or Longitude I've got to?' (Alice had no idea what Latitude was, +or Longitude either, but thought they were nice grand words to +say.) + + Presently she began again. `I wonder if I shall fall right +THROUGH the earth! How funny it'll seem to come out among the +people that walk with their heads downward! The Antipathies, I +think--' (she was rather glad there WAS no one listening, this +time, as it didn't sound at all the right word) `--but I shall +have to ask them what the name of the country is, you know. +Please, Ma'am, is this New Zealand or Australia?' (and she tried +to curtsey as she spoke--fancy CURTSEYING as you're falling +through the air! Do you think you could manage it?) `And what +an ignorant little girl she'll think me for asking! No, it'll +never do to ask: perhaps I shall see it written up somewhere.' + + Down, down, down. There was nothing else to do, so Alice soon +began talking again. `Dinah'll miss me very much to-night, I +should think!' (Dinah was the cat.) `I hope they'll remember +her saucer of milk at tea-time. Dinah my dear! I wish you were +down here with me! There are no mice in the air, I'm afraid, but +you might catch a bat, and that's very like a mouse, you know. +But do cats eat bats, I wonder?' And here Alice began to get +rather sleepy, and went on saying to herself, in a dreamy sort of +way, `Do cats eat bats? Do cats eat bats?' and sometimes, `Do +bats eat cats?' for, you see, as she couldn't answer either +question, it didn't much matter which way she put it. She felt +that she was dozing off, and had just begun to dream that she +was walking hand in hand with Dinah, and saying to her very +earnestly, `Now, Dinah, tell me the truth: did you ever eat a +bat?' when suddenly, thump! thump! down she came upon a heap of +sticks and dry leaves, and the fall was over. + + Alice was not a bit hurt, and she jumped up on to her feet in a +moment: she looked up, but it was all dark overhead; before her +was another long passage, and the White Rabbit was still in +sight, hurrying down it. There was not a moment to be lost: +away went Alice like the wind, and was just in time to hear it +say, as it turned a corner, `Oh my ears and whiskers, how late +it's getting!' She was close behind it when she turned the +corner, but the Rabbit was no longer to be seen: she found +herself in a long, low hall, which was lit up by a row of lamps +hanging from the roof. + + There were doors all round the hall, but they were all locked; +and when Alice had been all the way down one side and up the +other, trying every door, she walked sadly down the middle, +wondering how she was ever to get out again. + + Suddenly she came upon a little three-legged table, all made of +solid glass; there was nothing on it except a tiny golden key, +and Alice's first thought was that it might belong to one of the +doors of the hall; but, alas! either the locks were too large, or +the key was too small, but at any rate it would not open any of +them. However, on the second time round, she came upon a low +curtain she had not noticed before, and behind it was a little +door about fifteen inches high: she tried the little golden key +in the lock, and to her great delight it fitted! + + Alice opened the door and found that it led into a small +passage, not much larger than a rat-hole: she knelt down and +looked along the passage into the loveliest garden you ever saw. +How she longed to get out of that dark hall, and wander about +among those beds of bright flowers and those cool fountains, but +she could not even get her head though the doorway; `and even if +my head would go through,' thought poor Alice, `it would be of +very little use without my shoulders. Oh, how I wish +I could shut up like a telescope! I think I could, if I only +know how to begin.' For, you see, so many out-of-the-way things +had happened lately, that Alice had begun to think that very few +things indeed were really impossible. + + There seemed to be no use in waiting by the little door, so she +went back to the table, half hoping she might find another key on +it, or at any rate a book of rules for shutting people up like +telescopes: this time she found a little bottle on it, (`which +certainly was not here before,' said Alice,) and round the neck +of the bottle was a paper label, with the words `DRINK ME' +beautifully printed on it in large letters. + + It was all very well to say `Drink me,' but the wise little +Alice was not going to do THAT in a hurry. `No, I'll look +first,' she said, `and see whether it's marked "poison" or not'; +for she had read several nice little histories about children who +had got burnt, and eaten up by wild beasts and other unpleasant +things, all because they WOULD not remember the simple rules +their friends had taught them: such as, that a red-hot poker +will burn you if you hold it too long; and that if you cut your +finger VERY deeply with a knife, it usually bleeds; and she had +never forgotten that, if you drink much from a bottle marked +`poison,' it is almost certain to disagree with you, sooner or +later. + + However, this bottle was NOT marked `poison,' so Alice ventured +to taste it, and finding it very nice, (it had, in fact, a sort +of mixed flavour of cherry-tart, custard, pine-apple, roast +turkey, toffee, and hot buttered toast,) she very soon finished +it off. + + * * * * * * * + + * * * * * * + + * * * * * * * + + `What a curious feeling!' said Alice; `I must be shutting up +like a telescope.' + + And so it was indeed: she was now only ten inches high, and +her face brightened up at the thought that she was now the right +size for going though the little door into that lovely garden. +First, however, she waited for a few minutes to see if she was +going to shrink any further: she felt a little nervous about +this; `for it might end, you know,' said Alice to herself, `in my +going out altogether, like a candle. I wonder what I should be +like then?' And she tried to fancy what the flame of a candle is +like after the candle is blown out, for she could not remember +ever having seen such a thing. + + After a while, finding that nothing more happened, she decided +on going into the garden at once; but, alas for poor Alice! when +she got to the door, she found he had forgotten the little golden +key, and when she went back to the table for it, she found she +could not possibly reach it: she could see it quite plainly +through the glass, and she tried her best to climb up one of the +legs of the table, but it was too slippery; and when she had +tired herself out with trying, the poor little thing sat down and +cried. + + `Come, there's no use in crying like that!' said Alice to +herself, rather sharply; `I advise you to leave off this minute!' +She generally gave herself very good advice, (though she very +seldom followed it), and sometimes she scolded herself so +severely as to bring tears into her eyes; and once she remembered +trying to box her own ears for having cheated herself in a game +of croquet she was playing against herself, for this curious +child was very fond of pretending to be two people. `But it's no +use now,' thought poor Alice, `to pretend to be two people! Why, +there's hardly enough of me left to make ONE respectable +person!' + + Soon her eye fell on a little glass box that was lying under +the table: she opened it, and found in it a very small cake, on +which the words `EAT ME' were beautifully marked in currants. +`Well, I'll eat it,' said Alice, `and if it makes me grow larger, +I can reach the key; and if it makes me grow smaller, I can creep +under the door; so either way I'll get into the garden, and I +don't care which happens!' + + She ate a little bit, and said anxiously to herself, `Which +way? Which way?', holding her hand on the top of her head to +feel which way it was growing, and she was quite surprised to +find that she remained the same size: to be sure, this generally +happens when one eats cake, but Alice had got so much into the +way of expecting nothing but out-of-the-way things to happen, +that it seemed quite dull and stupid for life to go on in the +common way. + + So she set to work, and very soon finished off the cake. + + * * * * * * * + + * * * * * * + + * * * * * * * + + + + + CHAPTER II + + The Pool of Tears + + + `Curiouser and curiouser!' cried Alice (she was so much +surprised, that for the moment she quite forgot how to speak good +English); `now I'm opening out like the largest telescope that +ever was! Good-bye, feet!' (for when she looked down at her +feet, they seemed to be almost out of sight, they were getting so +far off). `Oh, my poor little feet, I wonder who will put on +your shoes and stockings for you now, dears? I'm sure _I_ shan't +be able! I shall be a great deal too far off to trouble myself +about you: you must manage the best way you can; --but I must be +kind to them,' thought Alice, `or perhaps they won't walk the +way I want to go! Let me see: I'll give them a new pair of +boots every Christmas.' + + And she went on planning to herself how she would manage it. +`They must go by the carrier,' she thought; `and how funny it'll +seem, sending presents to one's own feet! And how odd the +directions will look! + + ALICE'S RIGHT FOOT, ESQ. + HEARTHRUG, + NEAR THE FENDER, + (WITH ALICE'S LOVE). + +Oh dear, what nonsense I'm talking!' + + Just then her head struck against the roof of the hall: in +fact she was now more than nine feet high, and she at once took +up the little golden key and hurried off to the garden door. + + Poor Alice! It was as much as she could do, lying down on one +side, to look through into the garden with one eye; but to get +through was more hopeless than ever: she sat down and began to +cry again. + + `You ought to be ashamed of yourself,' said Alice, `a great +girl like you,' (she might well say this), `to go on crying in +this way! Stop this moment, I tell you!' But she went on all +the same, shedding gallons of tears, until there was a large pool +all round her, about four inches deep and reaching half down the +hall. + + After a time she heard a little pattering of feet in the +distance, and she hastily dried her eyes to see what was coming. +It was the White Rabbit returning, splendidly dressed, with a +pair of white kid gloves in one hand and a large fan in the +other: he came trotting along in a great hurry, muttering to +himself as he came, `Oh! the Duchess, the Duchess! Oh! won't she +be savage if I've kept her waiting!' Alice felt so desperate +that she was ready to ask help of any one; so, when the Rabbit +came near her, she began, in a low, timid voice, `If you please, +sir--' The Rabbit started violently, dropped the white kid +gloves and the fan, and skurried away into the darkness as hard +as he could go. + + Alice took up the fan and gloves, and, as the hall was very +hot, she kept fanning herself all the time she went on talking: +`Dear, dear! How queer everything is to-day! And yesterday +things went on just as usual. I wonder if I've been changed in +the night? Let me think: was I the same when I got up this +morning? I almost think I can remember feeling a little +different. But if I'm not the same, the next question is, Who in +the world am I? Ah, THAT'S the great puzzle!' And she began +thinking over all the children she knew that were of the same age +as herself, to see if she could have been changed for any of +them. + + `I'm sure I'm not Ada,' she said, `for her hair goes in such +long ringlets, and mine doesn't go in ringlets at all; and I'm +sure I can't be Mabel, for I know all sorts of things, and she, +oh! she knows such a very little! Besides, SHE'S she, and I'm I, +and--oh dear, how puzzling it all is! I'll try if I know all the +things I used to know. Let me see: four times five is twelve, +and four times six is thirteen, and four times seven is--oh dear! +I shall never get to twenty at that rate! However, the +Multiplication Table doesn't signify: let's try Geography. +London is the capital of Paris, and Paris is the capital of Rome, +and Rome--no, THAT'S all wrong, I'm certain! I must have been +changed for Mabel! I'll try and say "How doth the little--"' +and she crossed her hands on her lap as if she were saying lessons, +and began to repeat it, but her voice sounded hoarse and +strange, and the words did not come the same as they used to do:-- + + `How doth the little crocodile + Improve his shining tail, + And pour the waters of the Nile + On every golden scale! + + `How cheerfully he seems to grin, + How neatly spread his claws, + And welcome little fishes in + With gently smiling jaws!' + + `I'm sure those are not the right words,' said poor Alice, and +her eyes filled with tears again as she went on, `I must be Mabel +after all, and I shall have to go and live in that poky little +house, and have next to no toys to play with, and oh! ever so +many lessons to learn! No, I've made up my mind about it; if I'm +Mabel, I'll stay down here! It'll be no use their putting their +heads down and saying "Come up again, dear!" I shall only look +up and say "Who am I then? Tell me that first, and then, if I +like being that person, I'll come up: if not, I'll stay down +here till I'm somebody else"--but, oh dear!' cried Alice, with a +sudden burst of tears, `I do wish they WOULD put their heads +down! I am so VERY tired of being all alone here!' + + As she said this she looked down at her hands, and was +surprised to see that she had put on one of the Rabbit's little +white kid gloves while she was talking. `How CAN I have done +that?' she thought. `I must be growing small again.' She got up +and went to the table to measure herself by it, and found that, +as nearly as she could guess, she was now about two feet high, +and was going on shrinking rapidly: she soon found out that the +cause of this was the fan she was holding, and she dropped it +hastily, just in time to avoid shrinking away altogether. + +`That WAS a narrow escape!' said Alice, a good deal frightened at +the sudden change, but very glad to find herself still in +existence; `and now for the garden!' and she ran with all speed +back to the little door: but, alas! the little door was shut +again, and the little golden key was lying on the glass table as +before, `and things are worse than ever,' thought the poor child, +`for I never was so small as this before, never! And I declare +it's too bad, that it is!' + + As she said these words her foot slipped, and in another +moment, splash! she was up to her chin in salt water. He first +idea was that she had somehow fallen into the sea, `and in that +case I can go back by railway,' she said to herself. (Alice had +been to the seaside once in her life, and had come to the general +conclusion, that wherever you go to on the English coast you find +a number of bathing machines in the sea, some children digging in +the sand with wooden spades, then a row of lodging houses, and +behind them a railway station.) However, she soon made out that +she was in the pool of tears which she had wept when she was nine +feet high. + + `I wish I hadn't cried so much!' said Alice, as she swam about, +trying to find her way out. `I shall be punished for it now, I +suppose, by being drowned in my own tears! That WILL be a queer +thing, to be sure! However, everything is queer to-day.' + + Just then she heard something splashing about in the pool a +little way off, and she swam nearer to make out what it was: at +first she thought it must be a walrus or hippopotamus, but then +she remembered how small she was now, and she soon made out that +it was only a mouse that had slipped in like herself. + + `Would it be of any use, now,' thought Alice, `to speak to this +mouse? Everything is so out-of-the-way down here, that I should +think very likely it can talk: at any rate, there's no harm in +trying.' So she began: `O Mouse, do you know the way out of +this pool? I am very tired of swimming about here, O Mouse!' +(Alice thought this must be the right way of speaking to a mouse: +she had never done such a thing before, but she remembered having +seen in her brother's Latin Grammar, `A mouse--of a mouse--to a +mouse--a mouse--O mouse!' The Mouse looked at her rather +inquisitively, and seemed to her to wink with one of its little +eyes, but it said nothing. + + `Perhaps it doesn't understand English,' thought Alice; `I +daresay it's a French mouse, come over with William the +Conqueror.' (For, with all her knowledge of history, Alice had +no very clear notion how long ago anything had happened.) So she +began again: `Ou est ma chatte?' which was the first sentence in +her French lesson-book. The Mouse gave a sudden leap out of the +water, and seemed to quiver all over with fright. `Oh, I beg +your pardon!' cried Alice hastily, afraid that she had hurt the +poor animal's feelings. `I quite forgot you didn't like cats.' + + `Not like cats!' cried the Mouse, in a shrill, passionate +voice. `Would YOU like cats if you were me?' + + `Well, perhaps not,' said Alice in a soothing tone: `don't be +angry about it. And yet I wish I could show you our cat Dinah: +I think you'd take a fancy to cats if you could only see her. +She is such a dear quiet thing,' Alice went on, half to herself, +as she swam lazily about in the pool, `and she sits purring so +nicely by the fire, licking her paws and washing her face--and +she is such a nice soft thing to nurse--and she's such a capital +one for catching mice--oh, I beg your pardon!' cried Alice again, +for this time the Mouse was bristling all over, and she felt +certain it must be really offended. `We won't talk about her any +more if you'd rather not.' + + `We indeed!' cried the Mouse, who was trembling down to the end +of his tail. `As if I would talk on such a subject! Our family +always HATED cats: nasty, low, vulgar things! Don't let me hear +the name again!' + + `I won't indeed!' said Alice, in a great hurry to change the +subject of conversation. `Are you--are you fond--of--of dogs?' +The Mouse did not answer, so Alice went on eagerly: `There is +such a nice little dog near our house I should like to show you! +A little bright-eyed terrier, you know, with oh, such long curly +brown hair! And it'll fetch things when you throw them, and +it'll sit up and beg for its dinner, and all sorts of things--I +can't remember half of them--and it belongs to a farmer, you +know, and he says it's so useful, it's worth a hundred pounds! +He says it kills all the rats and--oh dear!' cried Alice in a +sorrowful tone, `I'm afraid I've offended it again!' For the +Mouse was swimming away from her as hard as it could go, and +making quite a commotion in the pool as it went. + + So she called softly after it, `Mouse dear! Do come back +again, and we won't talk about cats or dogs either, if you don't +like them!' When the Mouse heard this, it turned round and swam +slowly back to her: its face was quite pale (with passion, Alice +thought), and it said in a low trembling voice, `Let us get to +the shore, and then I'll tell you my history, and you'll +understand why it is I hate cats and dogs.' + + It was high time to go, for the pool was getting quite crowded +with the birds and animals that had fallen into it: there were a +Duck and a Dodo, a Lory and an Eaglet, and several other curious +creatures. Alice led the way, and the whole party swam to the +shore. + + + + CHAPTER III + + A Caucus-Race and a Long Tale + + + They were indeed a queer-looking party that assembled on the +bank--the birds with draggled feathers, the animals with their +fur clinging close to them, and all dripping wet, cross, and +uncomfortable. + + The first question of course was, how to get dry again: they +had a consultation about this, and after a few minutes it seemed +quite natural to Alice to find herself talking familiarly with +them, as if she had known them all her life. Indeed, she had +quite a long argument with the Lory, who at last turned sulky, +and would only say, `I am older than you, and must know better'; +and this Alice would not allow without knowing how old it was, +and, as the Lory positively refused to tell its age, there was no +more to be said. + + At last the Mouse, who seemed to be a person of authority among +them, called out, `Sit down, all of you, and listen to me! I'LL +soon make you dry enough!' They all sat down at once, in a large +ring, with the Mouse in the middle. Alice kept her eyes +anxiously fixed on it, for she felt sure she would catch a bad +cold if she did not get dry very soon. + + `Ahem!' said the Mouse with an important air, `are you all ready? +This is the driest thing I know. Silence all round, if you please! +"William the Conqueror, whose cause was favoured by the pope, was +soon submitted to by the English, who wanted leaders, and had been +of late much accustomed to usurpation and conquest. Edwin and +Morcar, the earls of Mercia and Northumbria--"' + + `Ugh!' said the Lory, with a shiver. + + `I beg your pardon!' said the Mouse, frowning, but very +politely: `Did you speak?' + + `Not I!' said the Lory hastily. + + `I thought you did,' said the Mouse. `--I proceed. "Edwin and +Morcar, the earls of Mercia and Northumbria, declared for him: +and even Stigand, the patriotic archbishop of Canterbury, found +it advisable--"' + + `Found WHAT?' said the Duck. + + `Found IT,' the Mouse replied rather crossly: `of course you +know what "it" means.' + + `I know what "it" means well enough, when I find a thing,' said +the Duck: `it's generally a frog or a worm. The question is, +what did the archbishop find?' + + The Mouse did not notice this question, but hurriedly went on, +`"--found it advisable to go with Edgar Atheling to meet William +and offer him the crown. William's conduct at first was +moderate. But the insolence of his Normans--" How are you +getting on now, my dear?' it continued, turning to Alice as it +spoke. + + `As wet as ever,' said Alice in a melancholy tone: `it doesn't +seem to dry me at all.' + + `In that case,' said the Dodo solemnly, rising to its feet, `I +move that the meeting adjourn, for the immediate adoption of more +energetic remedies--' + + `Speak English!' said the Eaglet. `I don't know the meaning of +half those long words, and, what's more, I don't believe you do +either!' And the Eaglet bent down its head to hide a smile: +some of the other birds tittered audibly. + + `What I was going to say,' said the Dodo in an offended tone, +`was, that the best thing to get us dry would be a Caucus-race.' + + `What IS a Caucus-race?' said Alice; not that she wanted much +to know, but the Dodo had paused as if it thought that SOMEBODY +ought to speak, and no one else seemed inclined to say anything. + + `Why,' said the Dodo, `the best way to explain it is to do it.' +(And, as you might like to try the thing yourself, some winter +day, I will tell you how the Dodo managed it.) + + First it marked out a race-course, in a sort of circle, (`the +exact shape doesn't matter,' it said,) and then all the party +were placed along the course, here and there. There was no `One, +two, three, and away,' but they began running when they liked, +and left off when they liked, so that it was not easy to know +when the race was over. However, when they had been running half +an hour or so, and were quite dry again, the Dodo suddenly called +out `The race is over!' and they all crowded round it, panting, +and asking, `But who has won?' + + This question the Dodo could not answer without a great deal of +thought, and it sat for a long time with one finger pressed upon +its forehead (the position in which you usually see Shakespeare, +in the pictures of him), while the rest waited in silence. At +last the Dodo said, `EVERYBODY has won, and all must have +prizes.' + + `But who is to give the prizes?' quite a chorus of voices +asked. + + `Why, SHE, of course,' said the Dodo, pointing to Alice with +one finger; and the whole party at once crowded round her, +calling out in a confused way, `Prizes! Prizes!' + + Alice had no idea what to do, and in despair she put her hand +in her pocket, and pulled out a box of comfits, (luckily the salt +water had not got into it), and handed them round as prizes. +There was exactly one a-piece all round. + + `But she must have a prize herself, you know,' said the Mouse. + + `Of course,' the Dodo replied very gravely. `What else have +you got in your pocket?' he went on, turning to Alice. + + `Only a thimble,' said Alice sadly. + + `Hand it over here,' said the Dodo. + + Then they all crowded round her once more, while the Dodo +solemnly presented the thimble, saying `We beg your acceptance of +this elegant thimble'; and, when it had finished this short +speech, they all cheered. + + Alice thought the whole thing very absurd, but they all looked +so grave that she did not dare to laugh; and, as she could not +think of anything to say, she simply bowed, and took the thimble, +looking as solemn as she could. + + The next thing was to eat the comfits: this caused some noise +and confusion, as the large birds complained that they could not +taste theirs, and the small ones choked and had to be patted on +the back. However, it was over at last, and they sat down again +in a ring, and begged the Mouse to tell them something more. + + `You promised to tell me your history, you know,' said Alice, +`and why it is you hate--C and D,' she added in a whisper, half +afraid that it would be offended again. + + `Mine is a long and a sad tale!' said the Mouse, turning to +Alice, and sighing. + + `It IS a long tail, certainly,' said Alice, looking down with +wonder at the Mouse's tail; `but why do you call it sad?' And +she kept on puzzling about it while the Mouse was speaking, so +that her idea of the tale was something like this:-- + + `Fury said to a + mouse, That he + met in the + house, + "Let us + both go to + law: I will + prosecute + YOU. --Come, + I'll take no + denial; We + must have a + trial: For + really this + morning I've + nothing + to do." + Said the + mouse to the + cur, "Such + a trial, + dear Sir, + With + no jury + or judge, + would be + wasting + our + breath." + "I'll be + judge, I'll + be jury," + Said + cunning + old Fury: + "I'll + try the + whole + cause, + and + condemn + you + to + death."' + + + `You are not attending!' said the Mouse to Alice severely. +`What are you thinking of?' + + `I beg your pardon,' said Alice very humbly: `you had got to +the fifth bend, I think?' + + `I had NOT!' cried the Mouse, sharply and very angrily. + + `A knot!' said Alice, always ready to make herself useful, and +looking anxiously about her. `Oh, do let me help to undo it!' + + `I shall do nothing of the sort,' said the Mouse, getting up +and walking away. `You insult me by talking such nonsense!' + + `I didn't mean it!' pleaded poor Alice. `But you're so easily +offended, you know!' + + The Mouse only growled in reply. + + `Please come back and finish your story!' Alice called after +it; and the others all joined in chorus, `Yes, please do!' but +the Mouse only shook its head impatiently, and walked a little +quicker. + + `What a pity it wouldn't stay!' sighed the Lory, as soon as it +was quite out of sight; and an old Crab took the opportunity of +saying to her daughter `Ah, my dear! Let this be a lesson to you +never to lose YOUR temper!' `Hold your tongue, Ma!' said the +young Crab, a little snappishly. `You're enough to try the +patience of an oyster!' + + `I wish I had our Dinah here, I know I do!' said Alice aloud, +addressing nobody in particular. `She'd soon fetch it back!' + + `And who is Dinah, if I might venture to ask the question?' +said the Lory. + + Alice replied eagerly, for she was always ready to talk about +her pet: `Dinah's our cat. And she's such a capital one for +catching mice you can't think! And oh, I wish you could see her +after the birds! Why, she'll eat a little bird as soon as look +at it!' + + This speech caused a remarkable sensation among the party. +Some of the birds hurried off at once: one the old Magpie began +wrapping itself up very carefully, remarking, `I really must be +getting home; the night-air doesn't suit my throat!' and a Canary +called out in a trembling voice to its children, `Come away, my +dears! It's high time you were all in bed!' On various pretexts +they all moved off, and Alice was soon left alone. + + `I wish I hadn't mentioned Dinah!' she said to herself in a +melancholy tone. `Nobody seems to like her, down here, and I'm +sure she's the best cat in the world! Oh, my dear Dinah! I +wonder if I shall ever see you any more!' And here poor Alice +began to cry again, for she felt very lonely and low-spirited. +In a little while, however, she again heard a little pattering of +footsteps in the distance, and she looked up eagerly, half hoping +that the Mouse had changed his mind, and was coming back to +finish his story. + + + + CHAPTER IV + + The Rabbit Sends in a Little Bill + + + It was the White Rabbit, trotting slowly back again, and +looking anxiously about as it went, as if it had lost something; +and she heard it muttering to itself `The Duchess! The Duchess! +Oh my dear paws! Oh my fur and whiskers! She'll get me +executed, as sure as ferrets are ferrets! Where CAN I have +dropped them, I wonder?' Alice guessed in a moment that it was +looking for the fan and the pair of white kid gloves, and she +very good-naturedly began hunting about for them, but they were +nowhere to be seen--everything seemed to have changed since her +swim in the pool, and the great hall, with the glass table and +the little door, had vanished completely. + + Very soon the Rabbit noticed Alice, as she went hunting about, +and called out to her in an angry tone, `Why, Mary Ann, what ARE +you doing out here? Run home this moment, and fetch me a pair of +gloves and a fan! Quick, now!' And Alice was so much frightened +that she ran off at once in the direction it pointed to, without +trying to explain the mistake it had made. + + `He took me for his housemaid,' she said to herself as she ran. +`How surprised he'll be when he finds out who I am! But I'd +better take him his fan and gloves--that is, if I can find them.' +As she said this, she came upon a neat little house, on the door +of which was a bright brass plate with the name `W. RABBIT' +engraved upon it. She went in without knocking, and hurried +upstairs, in great fear lest she should meet the real Mary Ann, +and be turned out of the house before she had found the fan and +gloves. + + `How queer it seems,' Alice said to herself, `to be going +messages for a rabbit! I suppose Dinah'll be sending me on +messages next!' And she began fancying the sort of thing that +would happen: `"Miss Alice! Come here directly, and get ready +for your walk!" "Coming in a minute, nurse! But I've got to see +that the mouse doesn't get out." Only I don't think,' Alice went +on, `that they'd let Dinah stop in the house if it began ordering +people about like that!' + + By this time she had found her way into a tidy little room with +a table in the window, and on it (as she had hoped) a fan and two +or three pairs of tiny white kid gloves: she took up the fan and +a pair of the gloves, and was just going to leave the room, when +her eye fell upon a little bottle that stood near the looking- +glass. There was no label this time with the words `DRINK ME,' +but nevertheless she uncorked it and put it to her lips. `I know +SOMETHING interesting is sure to happen,' she said to herself, +`whenever I eat or drink anything; so I'll just see what this +bottle does. I do hope it'll make me grow large again, for +really I'm quite tired of being such a tiny little thing!' + + It did so indeed, and much sooner than she had expected: +before she had drunk half the bottle, she found her head pressing +against the ceiling, and had to stoop to save her neck from being +broken. She hastily put down the bottle, saying to herself +`That's quite enough--I hope I shan't grow any more--As it is, I +can't get out at the door--I do wish I hadn't drunk quite so +much!' + + Alas! it was too late to wish that! She went on growing, and +growing, and very soon had to kneel down on the floor: in +another minute there was not even room for this, and she tried +the effect of lying down with one elbow against the door, and the +other arm curled round her head. Still she went on growing, and, +as a last resource, she put one arm out of the window, and one +foot up the chimney, and said to herself `Now I can do no more, +whatever happens. What WILL become of me?' + + Luckily for Alice, the little magic bottle had now had its full +effect, and she grew no larger: still it was very uncomfortable, +and, as there seemed to be no sort of chance of her ever getting +out of the room again, no wonder she felt unhappy. + + `It was much pleasanter at home,' thought poor Alice, `when one +wasn't always growing larger and smaller, and being ordered about +by mice and rabbits. I almost wish I hadn't gone down that +rabbit-hole--and yet--and yet--it's rather curious, you know, +this sort of life! I do wonder what CAN have happened to me! +When I used to read fairy-tales, I fancied that kind of thing +never happened, and now here I am in the middle of one! There +ought to be a book written about me, that there ought! And when +I grow up, I'll write one--but I'm grown up now,' she added in a +sorrowful tone; `at least there's no room to grow up any more +HERE.' + + `But then,' thought Alice, `shall I NEVER get any older than I +am now? That'll be a comfort, one way--never to be an old woman- +-but then--always to have lessons to learn! Oh, I shouldn't like +THAT!' + + `Oh, you foolish Alice!' she answered herself. `How can you +learn lessons in here? Why, there's hardly room for YOU, and no +room at all for any lesson-books!' + + And so she went on, taking first one side and then the other, +and making quite a conversation of it altogether; but after a few +minutes she heard a voice outside, and stopped to listen. + + `Mary Ann! Mary Ann!' said the voice. `Fetch me my gloves +this moment!' Then came a little pattering of feet on the +stairs. Alice knew it was the Rabbit coming to look for her, and +she trembled till she shook the house, quite forgetting that she +was now about a thousand times as large as the Rabbit, and had no +reason to be afraid of it. + + Presently the Rabbit came up to the door, and tried to open it; +but, as the door opened inwards, and Alice's elbow was pressed +hard against it, that attempt proved a failure. Alice heard it +say to itself `Then I'll go round and get in at the window.' + + `THAT you won't' thought Alice, and, after waiting till she +fancied she heard the Rabbit just under the window, she suddenly +spread out her hand, and made a snatch in the air. She did not +get hold of anything, but she heard a little shriek and a fall, +and a crash of broken glass, from which she concluded that it was +just possible it had fallen into a cucumber-frame, or something +of the sort. + + Next came an angry voice--the Rabbit's--`Pat! Pat! Where are +you?' And then a voice she had never heard before, `Sure then +I'm here! Digging for apples, yer honour!' + + `Digging for apples, indeed!' said the Rabbit angrily. `Here! +Come and help me out of THIS!' (Sounds of more broken glass.) + + `Now tell me, Pat, what's that in the window?' + + `Sure, it's an arm, yer honour!' (He pronounced it `arrum.') + + `An arm, you goose! Who ever saw one that size? Why, it +fills the whole window!' + + `Sure, it does, yer honour: but it's an arm for all that.' + + `Well, it's got no business there, at any rate: go and take it +away!' + + There was a long silence after this, and Alice could only hear +whispers now and then; such as, `Sure, I don't like it, yer +honour, at all, at all!' `Do as I tell you, you coward!' and at +last she spread out her hand again, and made another snatch in +the air. This time there were TWO little shrieks, and more +sounds of broken glass. `What a number of cucumber-frames there +must be!' thought Alice. `I wonder what they'll do next! As for +pulling me out of the window, I only wish they COULD! I'm sure I +don't want to stay in here any longer!' + + She waited for some time without hearing anything more: at +last came a rumbling of little cartwheels, and the sound of a +good many voice all talking together: she made out the words: +`Where's the other ladder?--Why, I hadn't to bring but one; +Bill's got the other--Bill! fetch it here, lad!--Here, put 'em up +at this corner--No, tie 'em together first--they don't reach half +high enough yet--Oh! they'll do well enough; don't be particular- +-Here, Bill! catch hold of this rope--Will the roof bear?--Mind +that loose slate--Oh, it's coming down! Heads below!' (a loud +crash)--`Now, who did that?--It was Bill, I fancy--Who's to go +down the chimney?--Nay, I shan't! YOU do it!--That I won't, +then!--Bill's to go down--Here, Bill! the master says you're to +go down the chimney!' + + `Oh! So Bill's got to come down the chimney, has he?' said +Alice to herself. `Shy, they seem to put everything upon Bill! +I wouldn't be in Bill's place for a good deal: this fireplace is +narrow, to be sure; but I THINK I can kick a little!' + + She drew her foot as far down the chimney as she could, and +waited till she heard a little animal (she couldn't guess of what +sort it was) scratching and scrambling about in the chimney close +above her: then, saying to herself `This is Bill,' she gave one +sharp kick, and waited to see what would happen next. + + The first thing she heard was a general chorus of `There goes +Bill!' then the Rabbit's voice along--`Catch him, you by the +hedge!' then silence, and then another confusion of voices--`Hold +up his head--Brandy now--Don't choke him--How was it, old fellow? +What happened to you? Tell us all about it!' + + Last came a little feeble, squeaking voice, (`That's Bill,' +thought Alice,) `Well, I hardly know--No more, thank ye; I'm +better now--but I'm a deal too flustered to tell you--all I know +is, something comes at me like a Jack-in-the-box, and up I goes +like a sky-rocket!' + + `So you did, old fellow!' said the others. + + `We must burn the house down!' said the Rabbit's voice; and +Alice called out as loud as she could, `If you do. I'll set +Dinah at you!' + + There was a dead silence instantly, and Alice thought to +herself, `I wonder what they WILL do next! If they had any +sense, they'd take the roof off.' After a minute or two, they +began moving about again, and Alice heard the Rabbit say, `A +barrowful will do, to begin with.' + + `A barrowful of WHAT?' thought Alice; but she had not long to +doubt, for the next moment a shower of little pebbles came +rattling in at the window, and some of them hit her in the face. +`I'll put a stop to this,' she said to herself, and shouted out, +`You'd better not do that again!' which produced another dead +silence. + + Alice noticed with some surprise that the pebbles were all +turning into little cakes as they lay on the floor, and a bright +idea came into her head. `If I eat one of these cakes,' she +thought, `it's sure to make SOME change in my size; and as it +can't possibly make me larger, it must make me smaller, I +suppose.' + + So she swallowed one of the cakes, and was delighted to find +that she began shrinking directly. As soon as she was small +enough to get through the door, she ran out of the house, and +found quite a crowd of little animals and birds waiting outside. +The poor little Lizard, Bill, was in the middle, being held up by +two guinea-pigs, who were giving it something out of a bottle. +They all made a rush at Alice the moment she appeared; but she +ran off as hard as she could, and soon found herself safe in a +thick wood. + + `The first thing I've got to do,' said Alice to herself, as she +wandered about in the wood, `is to grow to my right size again; +and the second thing is to find my way into that lovely garden. +I think that will be the best plan.' + + It sounded an excellent plan, no doubt, and very neatly and +simply arranged; the only difficulty was, that she had not the +smallest idea how to set about it; and while she was peering +about anxiously among the trees, a little sharp bark just over +her head made her look up in a great hurry. + + An enormous puppy was looking down at her with large round +eyes, and feebly stretching out one paw, trying to touch her. +`Poor little thing!' said Alice, in a coaxing tone, and she tried +hard to whistle to it; but she was terribly frightened all the +time at the thought that it might be hungry, in which case it +would be very likely to eat her up in spite of all her coaxing. + + Hardly knowing what she did, she picked up a little bit of +stick, and held it out to the puppy; whereupon the puppy jumped +into the air off all its feet at once, with a yelp of delight, +and rushed at the stick, and made believe to worry it; then Alice +dodged behind a great thistle, to keep herself from being run +over; and the moment she appeared on the other side, the puppy +made another rush at the stick, and tumbled head over heels in +its hurry to get hold of it; then Alice, thinking it was very +like having a game of play with a cart-horse, and expecting every +moment to be trampled under its feet, ran round the thistle +again; then the puppy began a series of short charges at the +stick, running a very little way forwards each time and a long +way back, and barking hoarsely all the while, till at last it sat +down a good way off, panting, with its tongue hanging out of its +mouth, and its great eyes half shut. + + This seemed to Alice a good opportunity for making her escape; +so she set off at once, and ran till she was quite tired and out +of breath, and till the puppy's bark sounded quite faint in the +distance. + + `And yet what a dear little puppy it was!' said Alice, as she +leant against a buttercup to rest herself, and fanned herself +with one of the leaves: `I should have liked teaching it tricks +very much, if--if I'd only been the right size to do it! Oh +dear! I'd nearly forgotten that I've got to grow up again! Let +me see--how IS it to be managed? I suppose I ought to eat or +drink something or other; but the great question is, what?' + + The great question certainly was, what? Alice looked all round +her at the flowers and the blades of grass, but she did not see +anything that looked like the right thing to eat or drink under +the circumstances. There was a large mushroom growing near her, +about the same height as herself; and when she had looked under +it, and on both sides of it, and behind it, it occurred to her +that she might as well look and see what was on the top of it. + + She stretched herself up on tiptoe, and peeped over the edge of +the mushroom, and her eyes immediately met those of a large +caterpillar, that was sitting on the top with its arms folded, +quietly smoking a long hookah, and taking not the smallest notice +of her or of anything else. + + + + CHAPTER V + + Advice from a Caterpillar + + + The Caterpillar and Alice looked at each other for some time in +silence: at last the Caterpillar took the hookah out of its +mouth, and addressed her in a languid, sleepy voice. + + `Who are YOU?' said the Caterpillar. + + This was not an encouraging opening for a conversation. Alice +replied, rather shyly, `I--I hardly know, sir, just at present-- +at least I know who I WAS when I got up this morning, but I think +I must have been changed several times since then.' + + `What do you mean by that?' said the Caterpillar sternly. +`Explain yourself!' + + `I can't explain MYSELF, I'm afraid, sir' said Alice, `because +I'm not myself, you see.' + + `I don't see,' said the Caterpillar. + + `I'm afraid I can't put it more clearly,' Alice replied very +politely, `for I can't understand it myself to begin with; and +being so many different sizes in a day is very confusing.' + + `It isn't,' said the Caterpillar. + + `Well, perhaps you haven't found it so yet,' said Alice; `but +when you have to turn into a chrysalis--you will some day, you +know--and then after that into a butterfly, I should think you'll +feel it a little queer, won't you?' + + `Not a bit,' said the Caterpillar. + + `Well, perhaps your feelings may be different,' said Alice; +`all I know is, it would feel very queer to ME.' + + `You!' said the Caterpillar contemptuously. `Who are YOU?' + + Which brought them back again to the beginning of the +conversation. Alice felt a little irritated at the Caterpillar's +making such VERY short remarks, and she drew herself up and said, +very gravely, `I think, you ought to tell me who YOU are, first.' + + `Why?' said the Caterpillar. + + Here was another puzzling question; and as Alice could not +think of any good reason, and as the Caterpillar seemed to be in +a VERY unpleasant state of mind, she turned away. + + `Come back!' the Caterpillar called after her. `I've something +important to say!' + + This sounded promising, certainly: Alice turned and came back +again. + + `Keep your temper,' said the Caterpillar. + + `Is that all?' said Alice, swallowing down her anger as well as +she could. + + `No,' said the Caterpillar. + + Alice thought she might as well wait, as she had nothing else +to do, and perhaps after all it might tell her something worth +hearing. For some minutes it puffed away without speaking, but +at last it unfolded its arms, took the hookah out of its mouth +again, and said, `So you think you're changed, do you?' + + `I'm afraid I am, sir,' said Alice; `I can't remember things as +I used--and I don't keep the same size for ten minutes together!' + + `Can't remember WHAT things?' said the Caterpillar. + + `Well, I've tried to say "HOW DOTH THE LITTLE BUSY BEE," but it +all came different!' Alice replied in a very melancholy voice. + + `Repeat, "YOU ARE OLD, FATHER WILLIAM,"' said the Caterpillar. + + Alice folded her hands, and began:-- + + `You are old, Father William,' the young man said, + `And your hair has become very white; + And yet you incessantly stand on your head-- + Do you think, at your age, it is right?' + + `In my youth,' Father William replied to his son, + `I feared it might injure the brain; + But, now that I'm perfectly sure I have none, + Why, I do it again and again.' + + `You are old,' said the youth, `as I mentioned before, + And have grown most uncommonly fat; + Yet you turned a back-somersault in at the door-- + Pray, what is the reason of that?' + + `In my youth,' said the sage, as he shook his grey locks, + `I kept all my limbs very supple + By the use of this ointment--one shilling the box-- + Allow me to sell you a couple?' + + `You are old,' said the youth, `and your jaws are too weak + For anything tougher than suet; + Yet you finished the goose, with the bones and the beak-- + Pray how did you manage to do it?' + + `In my youth,' said his father, `I took to the law, + And argued each case with my wife; + And the muscular strength, which it gave to my jaw, + Has lasted the rest of my life.' + + `You are old,' said the youth, `one would hardly suppose + That your eye was as steady as ever; + Yet you balanced an eel on the end of your nose-- + What made you so awfully clever?' + + `I have answered three questions, and that is enough,' + Said his father; `don't give yourself airs! + Do you think I can listen all day to such stuff? + Be off, or I'll kick you down stairs!' + + + `That is not said right,' said the Caterpillar. + + `Not QUITE right, I'm afraid,' said Alice, timidly; `some of the +words have got altered.' + + `It is wrong from beginning to end,' said the Caterpillar +decidedly, and there was silence for some minutes. + + The Caterpillar was the first to speak. + + `What size do you want to be?' it asked. + + `Oh, I'm not particular as to size,' Alice hastily replied; +`only one doesn't like changing so often, you know.' + + `I DON'T know,' said the Caterpillar. + + Alice said nothing: she had never been so much contradicted in +her life before, and she felt that she was losing her temper. + + `Are you content now?' said the Caterpillar. + + `Well, I should like to be a LITTLE larger, sir, if you +wouldn't mind,' said Alice: `three inches is such a wretched +height to be.' + + `It is a very good height indeed!' said the Caterpillar +angrily, rearing itself upright as it spoke (it was exactly three +inches high). + + `But I'm not used to it!' pleaded poor Alice in a piteous tone. +And she thought of herself, `I wish the creatures wouldn't be so +easily offended!' + + `You'll get used to it in time,' said the Caterpillar; and it +put the hookah into its mouth and began smoking again. + + This time Alice waited patiently until it chose to speak again. +In a minute or two the Caterpillar took the hookah out of its +mouth and yawned once or twice, and shook itself. Then it got +down off the mushroom, and crawled away in the grass, merely +remarking as it went, `One side will make you grow taller, and +the other side will make you grow shorter.' + + `One side of WHAT? The other side of WHAT?' thought Alice to +herself. + + `Of the mushroom,' said the Caterpillar, just as if she had +asked it aloud; and in another moment it was out of sight. + + Alice remained looking thoughtfully at the mushroom for a +minute, trying to make out which were the two sides of it; and as +it was perfectly round, she found this a very difficult question. +However, at last she stretched her arms round it as far as they +would go, and broke off a bit of the edge with each hand. + + `And now which is which?' she said to herself, and nibbled a +little of the right-hand bit to try the effect: the next moment +she felt a violent blow underneath her chin: it had struck her +foot! + + She was a good deal frightened by this very sudden change, but +she felt that there was no time to be lost, as she was shrinking +rapidly; so she set to work at once to eat some of the other bit. +Her chin was pressed so closely against her foot, that there was +hardly room to open her mouth; but she did it at last, and +managed to swallow a morsel of the lefthand bit. + + + * * * * * * * + + * * * * * * + + * * * * * * * + + `Come, my head's free at last!' said Alice in a tone of +delight, which changed into alarm in another moment, when she +found that her shoulders were nowhere to be found: all she could +see, when she looked down, was an immense length of neck, which +seemed to rise like a stalk out of a sea of green leaves that lay +far below her. + + `What CAN all that green stuff be?' said Alice. `And where +HAVE my shoulders got to? And oh, my poor hands, how is it I +can't see you?' She was moving them about as she spoke, but no +result seemed to follow, except a little shaking among the +distant green leaves. + + As there seemed to be no chance of getting her hands up to her +head, she tried to get her head down to them, and was delighted +to find that her neck would bend about easily in any direction, +like a serpent. She had just succeeded in curving it down into a +graceful zigzag, and was going to dive in among the leaves, which +she found to be nothing but the tops of the trees under which she +had been wandering, when a sharp hiss made her draw back in a +hurry: a large pigeon had flown into her face, and was beating +her violently with its wings. + + `Serpent!' screamed the Pigeon. + + `I'm NOT a serpent!' said Alice indignantly. `Let me alone!' + + `Serpent, I say again!' repeated the Pigeon, but in a more +subdued tone, and added with a kind of sob, `I've tried every +way, and nothing seems to suit them!' + + `I haven't the least idea what you're talking about,' said +Alice. + + `I've tried the roots of trees, and I've tried banks, and I've +tried hedges,' the Pigeon went on, without attending to her; `but +those serpents! There's no pleasing them!' + + Alice was more and more puzzled, but she thought there was no +use in saying anything more till the Pigeon had finished. + + `As if it wasn't trouble enough hatching the eggs,' said the +Pigeon; `but I must be on the look-out for serpents night and +day! Why, I haven't had a wink of sleep these three weeks!' + + `I'm very sorry you've been annoyed,' said Alice, who was +beginning to see its meaning. + + `And just as I'd taken the highest tree in the wood,' continued +the Pigeon, raising its voice to a shriek, `and just as I was +thinking I should be free of them at last, they must needs come +wriggling down from the sky! Ugh, Serpent!' + + `But I'm NOT a serpent, I tell you!' said Alice. `I'm a--I'm +a--' + + `Well! WHAT are you?' said the Pigeon. `I can see you're +trying to invent something!' + + `I--I'm a little girl,' said Alice, rather doubtfully, as she +remembered the number of changes she had gone through that day. + + `A likely story indeed!' said the Pigeon in a tone of the +deepest contempt. `I've seen a good many little girls in my +time, but never ONE with such a neck as that! No, no! You're a +serpent; and there's no use denying it. I suppose you'll be +telling me next that you never tasted an egg!' + + `I HAVE tasted eggs, certainly,' said Alice, who was a very +truthful child; `but little girls eat eggs quite as much as +serpents do, you know.' + + `I don't believe it,' said the Pigeon; `but if they do, why +then they're a kind of serpent, that's all I can say.' + + This was such a new idea to Alice, that she was quite silent +for a minute or two, which gave the Pigeon the opportunity of +adding, `You're looking for eggs, I know THAT well enough; and +what does it matter to me whether you're a little girl or a +serpent?' + + `It matters a good deal to ME,' said Alice hastily; `but I'm +not looking for eggs, as it happens; and if I was, I shouldn't +want YOURS: I don't like them raw.' + + `Well, be off, then!' said the Pigeon in a sulky tone, as it +settled down again into its nest. Alice crouched down among the +trees as well as she could, for her neck kept getting entangled +among the branches, and every now and then she had to stop and +untwist it. After a while she remembered that she still held the +pieces of mushroom in her hands, and she set to work very +carefully, nibbling first at one and then at the other, and +growing sometimes taller and sometimes shorter, until she had +succeeded in bringing herself down to her usual height. + + It was so long since she had been anything near the right size, +that it felt quite strange at first; but she got used to it in a +few minutes, and began talking to herself, as usual. `Come, +there's half my plan done now! How puzzling all these changes +are! I'm never sure what I'm going to be, from one minute to +another! However, I've got back to my right size: the next +thing is, to get into that beautiful garden--how IS that to be +done, I wonder?' As she said this, she came suddenly upon an +open place, with a little house in it about four feet high. +`Whoever lives there,' thought Alice, `it'll never do to come +upon them THIS size: why, I should frighten them out of their +wits!' So she began nibbling at the righthand bit again, and did +not venture to go near the house till she had brought herself +down to nine inches high. + + + + CHAPTER VI + + Pig and Pepper + + + For a minute or two she stood looking at the house, and +wondering what to do next, when suddenly a footman in livery came +running out of the wood--(she considered him to be a footman +because he was in livery: otherwise, judging by his face only, +she would have called him a fish)--and rapped loudly at the door +with his knuckles. It was opened by another footman in livery, +with a round face, and large eyes like a frog; and both footmen, +Alice noticed, had powdered hair that curled all over their +heads. She felt very curious to know what it was all about, and +crept a little way out of the wood to listen. + + The Fish-Footman began by producing from under his arm a great +letter, nearly as large as himself, and this he handed over to +the other, saying, in a solemn tone, `For the Duchess. An +invitation from the Queen to play croquet.' The Frog-Footman +repeated, in the same solemn tone, only changing the order of the +words a little, `From the Queen. An invitation for the Duchess +to play croquet.' + + Then they both bowed low, and their curls got entangled +together. + + Alice laughed so much at this, that she had to run back into +the wood for fear of their hearing her; and when she next peeped +out the Fish-Footman was gone, and the other was sitting on the +ground near the door, staring stupidly up into the sky. + + Alice went timidly up to the door, and knocked. + + `There's no sort of use in knocking,' said the Footman, `and +that for two reasons. First, because I'm on the same side of the +door as you are; secondly, because they're making such a noise +inside, no one could possibly hear you.' And certainly there was +a most extraordinary noise going on within--a constant howling +and sneezing, and every now and then a great crash, as if a dish +or kettle had been broken to pieces. + + `Please, then,' said Alice, `how am I to get in?' + + `There might be some sense in your knocking,' the Footman went +on without attending to her, `if we had the door between us. For +instance, if you were INSIDE, you might knock, and I could let +you out, you know.' He was looking up into the sky all the time +he was speaking, and this Alice thought decidedly uncivil. `But +perhaps he can't help it,' she said to herself; `his eyes are so +VERY nearly at the top of his head. But at any rate he might +answer questions.--How am I to get in?' she repeated, aloud. + + `I shall sit here,' the Footman remarked, `till tomorrow--' + + At this moment the door of the house opened, and a large plate +came skimming out, straight at the Footman's head: it just +grazed his nose, and broke to pieces against one of the trees +behind him. + + `--or next day, maybe,' the Footman continued in the same tone, +exactly as if nothing had happened. + + `How am I to get in?' asked Alice again, in a louder tone. + + `ARE you to get in at all?' said the Footman. `That's the +first question, you know.' + + It was, no doubt: only Alice did not like to be told so. +`It's really dreadful,' she muttered to herself, `the way all the +creatures argue. It's enough to drive one crazy!' + + The Footman seemed to think this a good opportunity for +repeating his remark, with variations. `I shall sit here,' he +said, `on and off, for days and days.' + + `But what am I to do?' said Alice. + + `Anything you like,' said the Footman, and began whistling. + + `Oh, there's no use in talking to him,' said Alice desperately: +`he's perfectly idiotic!' And she opened the door and went in. + + The door led right into a large kitchen, which was full of +smoke from one end to the other: the Duchess was sitting on a +three-legged stool in the middle, nursing a baby; the cook was +leaning over the fire, stirring a large cauldron which seemed to +be full of soup. + + `There's certainly too much pepper in that soup!' Alice said to +herself, as well as she could for sneezing. + + There was certainly too much of it in the air. Even the +Duchess sneezed occasionally; and as for the baby, it was +sneezing and howling alternately without a moment's pause. The +only things in the kitchen that did not sneeze, were the cook, +and a large cat which was sitting on the hearth and grinning from +ear to ear. + + `Please would you tell me,' said Alice, a little timidly, for +she was not quite sure whether it was good manners for her to +speak first, `why your cat grins like that?' + + `It's a Cheshire cat,' said the Duchess, `and that's why. +Pig!' + + She said the last word with such sudden violence that Alice +quite jumped; but she saw in another moment that it was addressed +to the baby, and not to her, so she took courage, and went on +again:-- + + `I didn't know that Cheshire cats always grinned; in fact, I +didn't know that cats COULD grin.' + + `They all can,' said the Duchess; `and most of 'em do.' + + `I don't know of any that do,' Alice said very politely, +feeling quite pleased to have got into a conversation. + + `You don't know much,' said the Duchess; `and that's a fact.' + + Alice did not at all like the tone of this remark, and thought +it would be as well to introduce some other subject of +conversation. While she was trying to fix on one, the cook took +the cauldron of soup off the fire, and at once set to work +throwing everything within her reach at the Duchess and the baby +--the fire-irons came first; then followed a shower of saucepans, +plates, and dishes. The Duchess took no notice of them even when +they hit her; and the baby was howling so much already, that it +was quite impossible to say whether the blows hurt it or not. + + `Oh, PLEASE mind what you're doing!' cried Alice, jumping up +and down in an agony of terror. `Oh, there goes his PRECIOUS +nose'; as an unusually large saucepan flew close by it, and very +nearly carried it off. + + `If everybody minded their own business,' the Duchess said in a +hoarse growl, `the world would go round a deal faster than it +does.' + + `Which would NOT be an advantage,' said Alice, who felt very +glad to get an opportunity of showing off a little of her +knowledge. `Just think of what work it would make with the day +and night! You see the earth takes twenty-four hours to turn +round on its axis--' + + `Talking of axes,' said the Duchess, `chop off her head!' + + Alice glanced rather anxiously at the cook, to see if she meant +to take the hint; but the cook was busily stirring the soup, and +seemed not to be listening, so she went on again: `Twenty-four +hours, I THINK; or is it twelve? I--' + + `Oh, don't bother ME,' said the Duchess; `I never could abide +figures!' And with that she began nursing her child again, +singing a sort of lullaby to it as she did so, and giving it a +violent shake at the end of every line: + + `Speak roughly to your little boy, + And beat him when he sneezes: + He only does it to annoy, + Because he knows it teases.' + + CHORUS. + + (In which the cook and the baby joined):-- + + `Wow! wow! wow!' + + While the Duchess sang the second verse of the song, she kept +tossing the baby violently up and down, and the poor little thing +howled so, that Alice could hardly hear the words:-- + + `I speak severely to my boy, + I beat him when he sneezes; + For he can thoroughly enjoy + The pepper when he pleases!' + + CHORUS. + + `Wow! wow! wow!' + + `Here! you may nurse it a bit, if you like!' the Duchess said +to Alice, flinging the baby at her as she spoke. `I must go and +get ready to play croquet with the Queen,' and she hurried out of +the room. The cook threw a frying-pan after her as she went out, +but it just missed her. + + Alice caught the baby with some difficulty, as it was a queer- +shaped little creature, and held out its arms and legs in all +directions, `just like a star-fish,' thought Alice. The poor +little thing was snorting like a steam-engine when she caught it, +and kept doubling itself up and straightening itself out again, +so that altogether, for the first minute or two, it was as much +as she could do to hold it. + + As soon as she had made out the proper way of nursing it, +(which was to twist it up into a sort of knot, and then keep +tight hold of its right ear and left foot, so as to prevent its +undoing itself,) she carried it out into the open air. `IF I +don't take this child away with me,' thought Alice, `they're sure +to kill it in a day or two: wouldn't it be murder to leave it +behind?' She said the last words out loud, and the little thing +grunted in reply (it had left off sneezing by this time). `Don't +grunt,' said Alice; `that's not at all a proper way of expressing +yourself.' + + The baby grunted again, and Alice looked very anxiously into +its face to see what was the matter with it. There could be no +doubt that it had a VERY turn-up nose, much more like a snout +than a real nose; also its eyes were getting extremely small for +a baby: altogether Alice did not like the look of the thing at +all. `But perhaps it was only sobbing,' she thought, and looked +into its eyes again, to see if there were any tears. + + No, there were no tears. `If you're going to turn into a pig, +my dear,' said Alice, seriously, `I'll have nothing more to do +with you. Mind now!' The poor little thing sobbed again (or +grunted, it was impossible to say which), and they went on for +some while in silence. + + Alice was just beginning to think to herself, `Now, what am I +to do with this creature when I get it home?' when it grunted +again, so violently, that she looked down into its face in some +alarm. This time there could be NO mistake about it: it was +neither more nor less than a pig, and she felt that it would be +quite absurd for her to carry it further. + + So she set the little creature down, and felt quite relieved to +see it trot away quietly into the wood. `If it had grown up,' +she said to herself, `it would have made a dreadfully ugly child: +but it makes rather a handsome pig, I think.' And she began +thinking over other children she knew, who might do very well as +pigs, and was just saying to herself, `if one only knew the right +way to change them--' when she was a little startled by seeing +the Cheshire Cat sitting on a bough of a tree a few yards off. + + The Cat only grinned when it saw Alice. It looked good- +natured, she thought: still it had VERY long claws and a great +many teeth, so she felt that it ought to be treated with respect. + + `Cheshire Puss,' she began, rather timidly, as she did not at +all know whether it would like the name: however, it only +grinned a little wider. `Come, it's pleased so far,' thought +Alice, and she went on. `Would you tell me, please, which way I +ought to go from here?' + + `That depends a good deal on where you want to get to,' said +the Cat. + + `I don't much care where--' said Alice. + + `Then it doesn't matter which way you go,' said the Cat. + + `--so long as I get SOMEWHERE,' Alice added as an explanation. + + `Oh, you're sure to do that,' said the Cat, `if you only walk +long enough.' + + Alice felt that this could not be denied, so she tried another +question. `What sort of people live about here?' + + `In THAT direction,' the Cat said, waving its right paw round, +`lives a Hatter: and in THAT direction,' waving the other paw, +`lives a March Hare. Visit either you like: they're both mad.' + + `But I don't want to go among mad people,' Alice remarked. + + `Oh, you can't help that,' said the Cat: `we're all mad here. +I'm mad. You're mad.' + + `How do you know I'm mad?' said Alice. + + `You must be,' said the Cat, `or you wouldn't have come here.' + + Alice didn't think that proved it at all; however, she went on +`And how do you know that you're mad?' + + `To begin with,' said the Cat, `a dog's not mad. You grant +that?' + + `I suppose so,' said Alice. + + `Well, then,' the Cat went on, `you see, a dog growls when it's +angry, and wags its tail when it's pleased. Now I growl when I'm +pleased, and wag my tail when I'm angry. Therefore I'm mad.' + + `I call it purring, not growling,' said Alice. + + `Call it what you like,' said the Cat. `Do you play croquet +with the Queen to-day?' + + `I should like it very much,' said Alice, `but I haven't been +invited yet.' + + `You'll see me there,' said the Cat, and vanished. + + Alice was not much surprised at this, she was getting so used +to queer things happening. While she was looking at the place +where it had been, it suddenly appeared again. + + `By-the-bye, what became of the baby?' said the Cat. `I'd +nearly forgotten to ask.' + + `It turned into a pig,' Alice quietly said, just as if it had +come back in a natural way. + + `I thought it would,' said the Cat, and vanished again. + + Alice waited a little, half expecting to see it again, but it +did not appear, and after a minute or two she walked on in the +direction in which the March Hare was said to live. `I've seen +hatters before,' she said to herself; `the March Hare will be +much the most interesting, and perhaps as this is May it won't be +raving mad--at least not so mad as it was in March.' As she said +this, she looked up, and there was the Cat again, sitting on a +branch of a tree. + + `Did you say pig, or fig?' said the Cat. + + `I said pig,' replied Alice; `and I wish you wouldn't keep +appearing and vanishing so suddenly: you make one quite giddy.' + + `All right,' said the Cat; and this time it vanished quite +slowly, beginning with the end of the tail, and ending with the +grin, which remained some time after the rest of it had gone. + + `Well! I've often seen a cat without a grin,' thought Alice; +`but a grin without a cat! It's the most curious thing I ever +say in my life!' + + She had not gone much farther before she came in sight of the +house of the March Hare: she thought it must be the right house, +because the chimneys were shaped like ears and the roof was +thatched with fur. It was so large a house, that she did not +like to go nearer till she had nibbled some more of the lefthand +bit of mushroom, and raised herself to about two feet high: even +then she walked up towards it rather timidly, saying to herself +`Suppose it should be raving mad after all! I almost wish I'd +gone to see the Hatter instead!' + + + + CHAPTER VII + + A Mad Tea-Party + + + There was a table set out under a tree in front of the house, +and the March Hare and the Hatter were having tea at it: a +Dormouse was sitting between them, fast asleep, and the other two +were using it as a cushion, resting their elbows on it, and the +talking over its head. `Very uncomfortable for the Dormouse,' +thought Alice; `only, as it's asleep, I suppose it doesn't mind.' + + The table was a large one, but the three were all crowded +together at one corner of it: `No room! No room!' they cried +out when they saw Alice coming. `There's PLENTY of room!' said +Alice indignantly, and she sat down in a large arm-chair at one +end of the table. + + `Have some wine,' the March Hare said in an encouraging tone. + + Alice looked all round the table, but there was nothing on it +but tea. `I don't see any wine,' she remarked. + + `There isn't any,' said the March Hare. + + `Then it wasn't very civil of you to offer it,' said Alice +angrily. + + `It wasn't very civil of you to sit down without being +invited,' said the March Hare. + + `I didn't know it was YOUR table,' said Alice; `it's laid for a +great many more than three.' + + `Your hair wants cutting,' said the Hatter. He had been +looking at Alice for some time with great curiosity, and this was +his first speech. + + `You should learn not to make personal remarks,' Alice said +with some severity; `it's very rude.' + + The Hatter opened his eyes very wide on hearing this; but all +he SAID was, `Why is a raven like a writing-desk?' + + `Come, we shall have some fun now!' thought Alice. `I'm glad +they've begun asking riddles.--I believe I can guess that,' she +added aloud. + + `Do you mean that you think you can find out the answer to it?' +said the March Hare. + + `Exactly so,' said Alice. + + `Then you should say what you mean,' the March Hare went on. + + `I do,' Alice hastily replied; `at least--at least I mean what +I say--that's the same thing, you know.' + + `Not the same thing a bit!' said the Hatter. `You might just +as well say that "I see what I eat" is the same thing as "I eat +what I see"!' + + `You might just as well say,' added the March Hare, `that "I +like what I get" is the same thing as "I get what I like"!' + + `You might just as well say,' added the Dormouse, who seemed to +be talking in his sleep, `that "I breathe when I sleep" is the +same thing as "I sleep when I breathe"!' + + `It IS the same thing with you,' said the Hatter, and here the +conversation dropped, and the party sat silent for a minute, +while Alice thought over all she could remember about ravens and +writing-desks, which wasn't much. + + The Hatter was the first to break the silence. `What day of +the month is it?' he said, turning to Alice: he had taken his +watch out of his pocket, and was looking at it uneasily, shaking +it every now and then, and holding it to his ear. + + Alice considered a little, and then said `The fourth.' + + `Two days wrong!' sighed the Hatter. `I told you butter +wouldn't suit the works!' he added looking angrily at the March +Hare. + + `It was the BEST butter,' the March Hare meekly replied. + + `Yes, but some crumbs must have got in as well,' the Hatter +grumbled: `you shouldn't have put it in with the bread-knife.' + + The March Hare took the watch and looked at it gloomily: then +he dipped it into his cup of tea, and looked at it again: but he +could think of nothing better to say than his first remark, `It +was the BEST butter, you know.' + + Alice had been looking over his shoulder with some curiosity. +`What a funny watch!' she remarked. `It tells the day of the +month, and doesn't tell what o'clock it is!' + + `Why should it?' muttered the Hatter. `Does YOUR watch tell +you what year it is?' + + `Of course not,' Alice replied very readily: `but that's +because it stays the same year for such a long time together.' + + `Which is just the case with MINE,' said the Hatter. + + Alice felt dreadfully puzzled. The Hatter's remark seemed to +have no sort of meaning in it, and yet it was certainly English. +`I don't quite understand you,' she said, as politely as she +could. + + `The Dormouse is asleep again,' said the Hatter, and he poured +a little hot tea upon its nose. + + The Dormouse shook its head impatiently, and said, without +opening its eyes, `Of course, of course; just what I was going to +remark myself.' + + `Have you guessed the riddle yet?' the Hatter said, turning to +Alice again. + + `No, I give it up,' Alice replied: `what's the answer?' + + `I haven't the slightest idea,' said the Hatter. + + `Nor I,' said the March Hare. + + Alice sighed wearily. `I think you might do something better +with the time,' she said, `than waste it in asking riddles that +have no answers.' + + `If you knew Time as well as I do,' said the Hatter, `you +wouldn't talk about wasting IT. It's HIM.' + + `I don't know what you mean,' said Alice. + + `Of course you don't!' the Hatter said, tossing his head +contemptuously. `I dare say you never even spoke to Time!' + + `Perhaps not,' Alice cautiously replied: `but I know I have to +beat time when I learn music.' + + `Ah! that accounts for it,' said the Hatter. `He won't stand +beating. Now, if you only kept on good terms with him, he'd do +almost anything you liked with the clock. For instance, suppose +it were nine o'clock in the morning, just time to begin lessons: +you'd only have to whisper a hint to Time, and round goes the +clock in a twinkling! Half-past one, time for dinner!' + + (`I only wish it was,' the March Hare said to itself in a +whisper.) + + `That would be grand, certainly,' said Alice thoughtfully: +`but then--I shouldn't be hungry for it, you know.' + + `Not at first, perhaps,' said the Hatter: `but you could keep +it to half-past one as long as you liked.' + + `Is that the way YOU manage?' Alice asked. + + The Hatter shook his head mournfully. `Not I!' he replied. +`We quarrelled last March--just before HE went mad, you know--' +(pointing with his tea spoon at the March Hare,) `--it was at the +great concert given by the Queen of Hearts, and I had to sing + + "Twinkle, twinkle, little bat! + How I wonder what you're at!" + +You know the song, perhaps?' + + `I've heard something like it,' said Alice. + + `It goes on, you know,' the Hatter continued, `in this way:-- + + "Up above the world you fly, + Like a tea-tray in the sky. + Twinkle, twinkle--"' + +Here the Dormouse shook itself, and began singing in its sleep +`Twinkle, twinkle, twinkle, twinkle--' and went on so long that +they had to pinch it to make it stop. + + `Well, I'd hardly finished the first verse,' said the Hatter, +`when the Queen jumped up and bawled out, "He's murdering the +time! Off with his head!"' + + `How dreadfully savage!' exclaimed Alice. + + `And ever since that,' the Hatter went on in a mournful tone, +`he won't do a thing I ask! It's always six o'clock now.' + + A bright idea came into Alice's head. `Is that the reason so +many tea-things are put out here?' she asked. + + `Yes, that's it,' said the Hatter with a sigh: `it's always +tea-time, and we've no time to wash the things between whiles.' + + `Then you keep moving round, I suppose?' said Alice. + + `Exactly so,' said the Hatter: `as the things get used up.' + + `But what happens when you come to the beginning again?' Alice +ventured to ask. + + `Suppose we change the subject,' the March Hare interrupted, +yawning. `I'm getting tired of this. I vote the young lady +tells us a story.' + + `I'm afraid I don't know one,' said Alice, rather alarmed at +the proposal. + + `Then the Dormouse shall!' they both cried. `Wake up, +Dormouse!' And they pinched it on both sides at once. + + The Dormouse slowly opened his eyes. `I wasn't asleep,' he +said in a hoarse, feeble voice: `I heard every word you fellows +were saying.' + + `Tell us a story!' said the March Hare. + + `Yes, please do!' pleaded Alice. + + `And be quick about it,' added the Hatter, `or you'll be asleep +again before it's done.' + + `Once upon a time there were three little sisters,' the +Dormouse began in a great hurry; `and their names were Elsie, +Lacie, and Tillie; and they lived at the bottom of a well--' + + `What did they live on?' said Alice, who always took a great +interest in questions of eating and drinking. + + `They lived on treacle,' said the Dormouse, after thinking a +minute or two. + + `They couldn't have done that, you know,' Alice gently +remarked; `they'd have been ill.' + + `So they were,' said the Dormouse; `VERY ill.' + + Alice tried to fancy to herself what such an extraordinary ways +of living would be like, but it puzzled her too much, so she went +on: `But why did they live at the bottom of a well?' + + `Take some more tea,' the March Hare said to Alice, very +earnestly. + + `I've had nothing yet,' Alice replied in an offended tone, `so +I can't take more.' + + `You mean you can't take LESS,' said the Hatter: `it's very +easy to take MORE than nothing.' + + `Nobody asked YOUR opinion,' said Alice. + + `Who's making personal remarks now?' the Hatter asked +triumphantly. + + Alice did not quite know what to say to this: so she helped +herself to some tea and bread-and-butter, and then turned to the +Dormouse, and repeated her question. `Why did they live at the +bottom of a well?' + + The Dormouse again took a minute or two to think about it, and +then said, `It was a treacle-well.' + + `There's no such thing!' Alice was beginning very angrily, but +the Hatter and the March Hare went `Sh! sh!' and the Dormouse +sulkily remarked, `If you can't be civil, you'd better finish the +story for yourself.' + + `No, please go on!' Alice said very humbly; `I won't interrupt +again. I dare say there may be ONE.' + + `One, indeed!' said the Dormouse indignantly. However, he +consented to go on. `And so these three little sisters--they +were learning to draw, you know--' + + `What did they draw?' said Alice, quite forgetting her promise. + + `Treacle,' said the Dormouse, without considering at all this +time. + + `I want a clean cup,' interrupted the Hatter: `let's all move +one place on.' + + He moved on as he spoke, and the Dormouse followed him: the +March Hare moved into the Dormouse's place, and Alice rather +unwillingly took the place of the March Hare. The Hatter was the +only one who got any advantage from the change: and Alice was a +good deal worse off than before, as the March Hare had just upset +the milk-jug into his plate. + + Alice did not wish to offend the Dormouse again, so she began +very cautiously: `But I don't understand. Where did they draw +the treacle from?' + + `You can draw water out of a water-well,' said the Hatter; `so +I should think you could draw treacle out of a treacle-well--eh, +stupid?' + + `But they were IN the well,' Alice said to the Dormouse, not +choosing to notice this last remark. + + `Of course they were', said the Dormouse; `--well in.' + + This answer so confused poor Alice, that she let the Dormouse +go on for some time without interrupting it. + + `They were learning to draw,' the Dormouse went on, yawning and +rubbing its eyes, for it was getting very sleepy; `and they drew +all manner of things--everything that begins with an M--' + + `Why with an M?' said Alice. + + `Why not?' said the March Hare. + + Alice was silent. + + The Dormouse had closed its eyes by this time, and was going +off into a doze; but, on being pinched by the Hatter, it woke up +again with a little shriek, and went on: `--that begins with an +M, such as mouse-traps, and the moon, and memory, and muchness-- +you know you say things are "much of a muchness"--did you ever +see such a thing as a drawing of a muchness?' + + `Really, now you ask me,' said Alice, very much confused, `I +don't think--' + + `Then you shouldn't talk,' said the Hatter. + + This piece of rudeness was more than Alice could bear: she got +up in great disgust, and walked off; the Dormouse fell asleep +instantly, and neither of the others took the least notice of her +going, though she looked back once or twice, half hoping that +they would call after her: the last time she saw them, they were +trying to put the Dormouse into the teapot. + + `At any rate I'll never go THERE again!' said Alice as she +picked her way through the wood. `It's the stupidest tea-party I +ever was at in all my life!' + + Just as she said this, she noticed that one of the trees had a +door leading right into it. `That's very curious!' she thought. +`But everything's curious today. I think I may as well go in at +once.' And in she went. + + Once more she found herself in the long hall, and close to the +little glass table. `Now, I'll manage better this time,' she +said to herself, and began by taking the little golden key, and +unlocking the door that led into the garden. Then she went to +work nibbling at the mushroom (she had kept a piece of it in her +pocked) till she was about a foot high: then she walked down the +little passage: and THEN--she found herself at last in the +beautiful garden, among the bright flower-beds and the cool +fountains. + + + + CHAPTER VIII + + The Queen's Croquet-Ground + + + A large rose-tree stood near the entrance of the garden: the +roses growing on it were white, but there were three gardeners at +it, busily painting them red. Alice thought this a very curious +thing, and she went nearer to watch them, and just as she came up +to them she heard one of them say, `Look out now, Five! Don't go +splashing paint over me like that!' + + `I couldn't help it,' said Five, in a sulky tone; `Seven jogged +my elbow.' + + On which Seven looked up and said, `That's right, Five! Always +lay the blame on others!' + + `YOU'D better not talk!' said Five. `I heard the Queen say only +yesterday you deserved to be beheaded!' + + `What for?' said the one who had spoken first. + + `That's none of YOUR business, Two!' said Seven. + + `Yes, it IS his business!' said Five, `and I'll tell him--it +was for bringing the cook tulip-roots instead of onions.' + + Seven flung down his brush, and had just begun `Well, of all +the unjust things--' when his eye chanced to fall upon Alice, as +she stood watching them, and he checked himself suddenly: the +others looked round also, and all of them bowed low. + + `Would you tell me,' said Alice, a little timidly, `why you are +painting those roses?' + + Five and Seven said nothing, but looked at Two. Two began in a +low voice, `Why the fact is, you see, Miss, this here ought to +have been a RED rose-tree, and we put a white one in by mistake; +and if the Queen was to find it out, we should all have our heads +cut off, you know. So you see, Miss, we're doing our best, afore +she comes, to--' At this moment Five, who had been anxiously +looking across the garden, called out `The Queen! The Queen!' +and the three gardeners instantly threw themselves flat upon +their faces. There was a sound of many footsteps, and Alice +looked round, eager to see the Queen. + + First came ten soldiers carrying clubs; these were all shaped +like the three gardeners, oblong and flat, with their hands and +feet at the corners: next the ten courtiers; these were +ornamented all over with diamonds, and walked two and two, as the +soldiers did. After these came the royal children; there were +ten of them, and the little dears came jumping merrily along hand +in hand, in couples: they were all ornamented with hearts. Next +came the guests, mostly Kings and Queens, and among them Alice +recognised the White Rabbit: it was talking in a hurried nervous +manner, smiling at everything that was said, and went by without +noticing her. Then followed the Knave of Hearts, carrying the +King's crown on a crimson velvet cushion; and, last of all this +grand procession, came THE KING AND QUEEN OF HEARTS. + + Alice was rather doubtful whether she ought not to lie down on +her face like the three gardeners, but she could not remember +every having heard of such a rule at processions; `and besides, +what would be the use of a procession,' thought she, `if people +had all to lie down upon their faces, so that they couldn't see +it?' So she stood still where she was, and waited. + + When the procession came opposite to Alice, they all stopped +and looked at her, and the Queen said severely `Who is this?' +She said it to the Knave of Hearts, who only bowed and smiled in +reply. + + `Idiot!' said the Queen, tossing her head impatiently; and, +turning to Alice, she went on, `What's your name, child?' + + `My name is Alice, so please your Majesty,' said Alice very +politely; but she added, to herself, `Why, they're only a pack of +cards, after all. I needn't be afraid of them!' + + `And who are THESE?' said the Queen, pointing to the three +gardeners who were lying round the rosetree; for, you see, as +they were lying on their faces, and the pattern on their backs +was the same as the rest of the pack, she could not tell whether +they were gardeners, or soldiers, or courtiers, or three of her +own children. + + `How should I know?' said Alice, surprised at her own courage. +`It's no business of MINE.' + + The Queen turned crimson with fury, and, after glaring at her +for a moment like a wild beast, screamed `Off with her head! +Off--' + + `Nonsense!' said Alice, very loudly and decidedly, and the +Queen was silent. + + The King laid his hand upon her arm, and timidly said +`Consider, my dear: she is only a child!' + + The Queen turned angrily away from him, and said to the Knave +`Turn them over!' + + The Knave did so, very carefully, with one foot. + + `Get up!' said the Queen, in a shrill, loud voice, and the +three gardeners instantly jumped up, and began bowing to the +King, the Queen, the royal children, and everybody else. + + `Leave off that!' screamed the Queen. `You make me giddy.' +And then, turning to the rose-tree, she went on, `What HAVE you +been doing here?' + + `May it please your Majesty,' said Two, in a very humble tone, +going down on one knee as he spoke, `we were trying--' + + `I see!' said the Queen, who had meanwhile been examining the +roses. `Off with their heads!' and the procession moved on, +three of the soldiers remaining behind to execute the unfortunate +gardeners, who ran to Alice for protection. + + `You shan't be beheaded!' said Alice, and she put them into a +large flower-pot that stood near. The three soldiers wandered +about for a minute or two, looking for them, and then quietly +marched off after the others. + + `Are their heads off?' shouted the Queen. + + `Their heads are gone, if it please your Majesty!' the soldiers +shouted in reply. + + `That's right!' shouted the Queen. `Can you play croquet?' + + The soldiers were silent, and looked at Alice, as the question +was evidently meant for her. + + `Yes!' shouted Alice. + + `Come on, then!' roared the Queen, and Alice joined the +procession, wondering very much what would happen next. + + `It's--it's a very fine day!' said a timid voice at her side. +She was walking by the White Rabbit, who was peeping anxiously +into her face. + + `Very,' said Alice: `--where's the Duchess?' + + `Hush! Hush!' said the Rabbit in a low, hurried tone. He +looked anxiously over his shoulder as he spoke, and then raised +himself upon tiptoe, put his mouth close to her ear, and +whispered `She's under sentence of execution.' + + `What for?' said Alice. + + `Did you say "What a pity!"?' the Rabbit asked. + + `No, I didn't,' said Alice: `I don't think it's at all a pity. +I said "What for?"' + + `She boxed the Queen's ears--' the Rabbit began. Alice gave a +little scream of laughter. `Oh, hush!' the Rabbit whispered in a +frightened tone. `The Queen will hear you! You see, she came +rather late, and the Queen said--' + + `Get to your places!' shouted the Queen in a voice of thunder, +and people began running about in all directions, tumbling up +against each other; however, they got settled down in a minute or +two, and the game began. Alice thought she had never seen such a +curious croquet-ground in her life; it was all ridges and +furrows; the balls were live hedgehogs, the mallets live +flamingoes, and the soldiers had to double themselves up and to +stand on their hands and feet, to make the arches. + + The chief difficulty Alice found at first was in managing her +flamingo: she succeeded in getting its body tucked away, +comfortably enough, under her arm, with its legs hanging down, +but generally, just as she had got its neck nicely straightened +out, and was going to give the hedgehog a blow with its head, it +WOULD twist itself round and look up in her face, with such a +puzzled expression that she could not help bursting out laughing: +and when she had got its head down, and was going to begin again, +it was very provoking to find that the hedgehog had unrolled +itself, and was in the act of crawling away: besides all this, +there was generally a ridge or furrow in the way wherever she +wanted to send the hedgehog to, and, as the doubled-up soldiers +were always getting up and walking off to other parts of the +ground, Alice soon came to the conclusion that it was a very +difficult game indeed. + + The players all played at once without waiting for turns, +quarrelling all the while, and fighting for the hedgehogs; and in +a very short time the Queen was in a furious passion, and went +stamping about, and shouting `Off with his head!' or `Off with +her head!' about once in a minute. + + Alice began to feel very uneasy: to be sure, she had not as +yet had any dispute with the Queen, but she knew that it might +happen any minute, `and then,' thought she, `what would become of +me? They're dreadfully fond of beheading people here; the great +wonder is, that there's any one left alive!' + + She was looking about for some way of escape, and wondering +whether she could get away without being seen, when she noticed a +curious appearance in the air: it puzzled her very much at +first, but, after watching it a minute or two, she made it out to +be a grin, and she said to herself `It's the Cheshire Cat: now I +shall have somebody to talk to.' + + `How are you getting on?' said the Cat, as soon as there was +mouth enough for it to speak with. + + Alice waited till the eyes appeared, and then nodded. `It's no +use speaking to it,' she thought, `till its ears have come, or at +least one of them.' In another minute the whole head appeared, +and then Alice put down her flamingo, and began an account of the +game, feeling very glad she had someone to listen to her. The +Cat seemed to think that there was enough of it now in sight, and +no more of it appeared. + + `I don't think they play at all fairly,' Alice began, in rather +a complaining tone, `and they all quarrel so dreadfully one can't +hear oneself speak--and they don't seem to have any rules in +particular; at least, if there are, nobody attends to them--and +you've no idea how confusing it is all the things being alive; +for instance, there's the arch I've got to go through next +walking about at the other end of the ground--and I should have +croqueted the Queen's hedgehog just now, only it ran away when it +saw mine coming!' + + `How do you like the Queen?' said the Cat in a low voice. + + `Not at all,' said Alice: `she's so extremely--' Just then +she noticed that the Queen was close behind her, listening: so +she went on, `--likely to win, that it's hardly worth while +finishing the game.' + + The Queen smiled and passed on. + + `Who ARE you talking to?' said the King, going up to Alice, and +looking at the Cat's head with great curiosity. + + `It's a friend of mine--a Cheshire Cat,' said Alice: `allow me +to introduce it.' + + `I don't like the look of it at all,' said the King: `however, +it may kiss my hand if it likes.' + + `I'd rather not,' the Cat remarked. + + `Don't be impertinent,' said the King, `and don't look at me +like that!' He got behind Alice as he spoke. + + `A cat may look at a king,' said Alice. `I've read that in +some book, but I don't remember where.' + + `Well, it must be removed,' said the King very decidedly, and +he called the Queen, who was passing at the moment, `My dear! I +wish you would have this cat removed!' + + The Queen had only one way of settling all difficulties, great +or small. `Off with his head!' she said, without even looking +round. + + `I'll fetch the executioner myself,' said the King eagerly, and +he hurried off. + + Alice thought she might as well go back, and see how the game +was going on, as she heard the Queen's voice in the distance, +screaming with passion. She had already heard her sentence three +of the players to be executed for having missed their turns, and +she did not like the look of things at all, as the game was in +such confusion that she never knew whether it was her turn or +not. So she went in search of her hedgehog. + + The hedgehog was engaged in a fight with another hedgehog, +which seemed to Alice an excellent opportunity for croqueting one +of them with the other: the only difficulty was, that her +flamingo was gone across to the other side of the garden, where +Alice could see it trying in a helpless sort of way to fly up +into a tree. + + By the time she had caught the flamingo and brought it back, +the fight was over, and both the hedgehogs were out of sight: +`but it doesn't matter much,' thought Alice, `as all the arches +are gone from this side of the ground.' So she tucked it away +under her arm, that it might not escape again, and went back for +a little more conversation with her friend. + + When she got back to the Cheshire Cat, she was surprised to +find quite a large crowd collected round it: there was a dispute +going on between the executioner, the King, and the Queen, who +were all talking at once, while all the rest were quite silent, +and looked very uncomfortable. + + The moment Alice appeared, she was appealed to by all three to +settle the question, and they repeated their arguments to her, +though, as they all spoke at once, she found it very hard indeed +to make out exactly what they said. + + The executioner's argument was, that you couldn't cut off a +head unless there was a body to cut it off from: that he had +never had to do such a thing before, and he wasn't going to begin +at HIS time of life. + + The King's argument was, that anything that had a head could be +beheaded, and that you weren't to talk nonsense. + + The Queen's argument was, that if something wasn't done about +it in less than no time she'd have everybody executed, all round. +(It was this last remark that had made the whole party look so +grave and anxious.) + + Alice could think of nothing else to say but `It belongs to the +Duchess: you'd better ask HER about it.' + + `She's in prison,' the Queen said to the executioner: `fetch +her here.' And the executioner went off like an arrow. + + The Cat's head began fading away the moment he was gone, and, +by the time he had come back with the Dutchess, it had entirely +disappeared; so the King and the executioner ran wildly up and +down looking for it, while the rest of the party went back to the game. + + + + CHAPTER IX + + The Mock Turtle's Story + + + `You can't think how glad I am to see you again, you dear old +thing!' said the Duchess, as she tucked her arm affectionately +into Alice's, and they walked off together. + + Alice was very glad to find her in such a pleasant temper, and +thought to herself that perhaps it was only the pepper that had +made her so savage when they met in the kitchen. + + `When I'M a Duchess,' she said to herself, (not in a very +hopeful tone though), `I won't have any pepper in my kitchen AT +ALL. Soup does very well without--Maybe it's always pepper that +makes people hot-tempered,' she went on, very much pleased at +having found out a new kind of rule, `and vinegar that makes them +sour--and camomile that makes them bitter--and--and barley-sugar +and such things that make children sweet-tempered. I only wish +people knew that: then they wouldn't be so stingy about it, you +know--' + + She had quite forgotten the Duchess by this time, and was a +little startled when she heard her voice close to her ear. +`You're thinking about something, my dear, and that makes you +forget to talk. I can't tell you just now what the moral of that +is, but I shall remember it in a bit.' + + `Perhaps it hasn't one,' Alice ventured to remark. + + `Tut, tut, child!' said the Duchess. `Everything's got a +moral, if only you can find it.' And she squeezed herself up +closer to Alice's side as she spoke. + + Alice did not much like keeping so close to her: first, +because the Duchess was VERY ugly; and secondly, because she was +exactly the right height to rest her chin upon Alice's shoulder, +and it was an uncomfortably sharp chin. However, she did not +like to be rude, so she bore it as well as she could. + + `The game's going on rather better now,' she said, by way of +keeping up the conversation a little. + + `'Tis so,' said the Duchess: `and the moral of that is--"Oh, +'tis love, 'tis love, that makes the world go round!"' + + `Somebody said,' Alice whispered, `that it's done by everybody +minding their own business!' + + `Ah, well! It means much the same thing,' said the Duchess, +digging her sharp little chin into Alice's shoulder as she added, +`and the moral of THAT is--"Take care of the sense, and the +sounds will take care of themselves."' + + `How fond she is of finding morals in things!' Alice thought to +herself. + + `I dare say you're wondering why I don't put my arm round your +waist,' the Duchess said after a pause: `the reason is, that I'm +doubtful about the temper of your flamingo. Shall I try the +experiment?' + + `HE might bite,' Alice cautiously replied, not feeling at all +anxious to have the experiment tried. + + `Very true,' said the Duchess: `flamingoes and mustard both +bite. And the moral of that is--"Birds of a feather flock +together."' + + `Only mustard isn't a bird,' Alice remarked. + + `Right, as usual,' said the Duchess: `what a clear way you +have of putting things!' + + `It's a mineral, I THINK,' said Alice. + + `Of course it is,' said the Duchess, who seemed ready to agree +to everything that Alice said; `there's a large mustard-mine near +here. And the moral of that is--"The more there is of mine, the +less there is of yours."' + + `Oh, I know!' exclaimed Alice, who had not attended to this +last remark, `it's a vegetable. It doesn't look like one, but it +is.' + + `I quite agree with you,' said the Duchess; `and the moral of +that is--"Be what you would seem to be"--or if you'd like it put +more simply--"Never imagine yourself not to be otherwise than +what it might appear to others that what you were or might have +been was not otherwise than what you had been would have appeared +to them to be otherwise."' + + `I think I should understand that better,' Alice said very +politely, `if I had it written down: but I can't quite follow it +as you say it.' + + `That's nothing to what I could say if I chose,' the Duchess +replied, in a pleased tone. + + `Pray don't trouble yourself to say it any longer than that,' +said Alice. + + `Oh, don't talk about trouble!' said the Duchess. `I make you +a present of everything I've said as yet.' + + `A cheap sort of present!' thought Alice. `I'm glad they don't +give birthday presents like that!' But she did not venture to +say it out loud. + + `Thinking again?' the Duchess asked, with another dig of her +sharp little chin. + + `I've a right to think,' said Alice sharply, for she was +beginning to feel a little worried. + + `Just about as much right,' said the Duchess, `as pigs have to +fly; and the m--' + + But here, to Alice's great surprise, the Duchess's voice died +away, even in the middle of her favourite word `moral,' and the +arm that was linked into hers began to tremble. Alice looked up, +and there stood the Queen in front of them, with her arms folded, +frowning like a thunderstorm. + + `A fine day, your Majesty!' the Duchess began in a low, weak +voice. + + `Now, I give you fair warning,' shouted the Queen, stamping on +the ground as she spoke; `either you or your head must be off, +and that in about half no time! Take your choice!' + + The Duchess took her choice, and was gone in a moment. + + `Let's go on with the game,' the Queen said to Alice; and Alice +was too much frightened to say a word, but slowly followed her +back to the croquet-ground. + + The other guests had taken advantage of the Queen's absence, +and were resting in the shade: however, the moment they saw her, +they hurried back to the game, the Queen merely remarking that a +moment's delay would cost them their lives. + + All the time they were playing the Queen never left off +quarrelling with the other players, and shouting `Off with his +head!' or `Off with her head!' Those whom she sentenced were +taken into custody by the soldiers, who of course had to leave +off being arches to do this, so that by the end of half an hour +or so there were no arches left, and all the players, except the +King, the Queen, and Alice, were in custody and under sentence of +execution. + + Then the Queen left off, quite out of breath, and said to +Alice, `Have you seen the Mock Turtle yet?' + + `No,' said Alice. `I don't even know what a Mock Turtle is.' + + `It's the thing Mock Turtle Soup is made from,' said the Queen. + + `I never saw one, or heard of one,' said Alice. + + `Come on, then,' said the Queen, `and he shall tell you his +history,' + + As they walked off together, Alice heard the King say in a low +voice, to the company generally, `You are all pardoned.' `Come, +THAT'S a good thing!' she said to herself, for she had felt quite +unhappy at the number of executions the Queen had ordered. + + They very soon came upon a Gryphon, lying fast asleep in the +sun. (IF you don't know what a Gryphon is, look at the picture.) +`Up, lazy thing!' said the Queen, `and take this young lady to +see the Mock Turtle, and to hear his history. I must go back and +see after some executions I have ordered'; and she walked off, +leaving Alice alone with the Gryphon. Alice did not quite like +the look of the creature, but on the whole she thought it would +be quite as safe to stay with it as to go after that savage +Queen: so she waited. + + The Gryphon sat up and rubbed its eyes: then it watched the +Queen till she was out of sight: then it chuckled. `What fun!' +said the Gryphon, half to itself, half to Alice. + + `What IS the fun?' said Alice. + + `Why, SHE,' said the Gryphon. `It's all her fancy, that: they +never executes nobody, you know. Come on!' + + `Everybody says "come on!" here,' thought Alice, as she went +slowly after it: `I never was so ordered about in all my life, +never!' + + They had not gone far before they saw the Mock Turtle in the +distance, sitting sad and lonely on a little ledge of rock, and, +as they came nearer, Alice could hear him sighing as if his heart +would break. She pitied him deeply. `What is his sorrow?' she +asked the Gryphon, and the Gryphon answered, very nearly in the +same words as before, `It's all his fancy, that: he hasn't got +no sorrow, you know. Come on!' + + So they went up to the Mock Turtle, who looked at them with +large eyes full of tears, but said nothing. + + `This here young lady,' said the Gryphon, `she wants for to +know your history, she do.' + + `I'll tell it her,' said the Mock Turtle in a deep, hollow +tone: `sit down, both of you, and don't speak a word till I've +finished.' + + So they sat down, and nobody spoke for some minutes. Alice +thought to herself, `I don't see how he can EVEN finish, if he +doesn't begin.' But she waited patiently. + + `Once,' said the Mock Turtle at last, with a deep sigh, `I was +a real Turtle.' + + These words were followed by a very long silence, broken only +by an occasional exclamation of `Hjckrrh!' from the Gryphon, and +the constant heavy sobbing of the Mock Turtle. Alice was very +nearly getting up and saying, `Thank you, sir, for your +interesting story,' but she could not help thinking there MUST be +more to come, so she sat still and said nothing. + + `When we were little,' the Mock Turtle went on at last, more +calmly, though still sobbing a little now and then, `we went to +school in the sea. The master was an old Turtle--we used to call +him Tortoise--' + + `Why did you call him Tortoise, if he wasn't one?' Alice asked. + + `We called him Tortoise because he taught us,' said the Mock +Turtle angrily: `really you are very dull!' + + `You ought to be ashamed of yourself for asking such a simple +question,' added the Gryphon; and then they both sat silent and +looked at poor Alice, who felt ready to sink into the earth. At +last the Gryphon said to the Mock Turtle, `Drive on, old fellow! +Don't be all day about it!' and he went on in these words: + + `Yes, we went to school in the sea, though you mayn't believe +it--' + + `I never said I didn't!' interrupted Alice. + + `You did,' said the Mock Turtle. + + `Hold your tongue!' added the Gryphon, before Alice could speak +again. The Mock Turtle went on. + + `We had the best of educations--in fact, we went to school +every day--' + + `I'VE been to a day-school, too,' said Alice; `you needn't be +so proud as all that.' + + `With extras?' asked the Mock Turtle a little anxiously. + + `Yes,' said Alice, `we learned French and music.' + + `And washing?' said the Mock Turtle. + + `Certainly not!' said Alice indignantly. + + `Ah! then yours wasn't a really good school,' said the Mock +Turtle in a tone of great relief. `Now at OURS they had at the +end of the bill, "French, music, AND WASHING--extra."' + + `You couldn't have wanted it much,' said Alice; `living at the +bottom of the sea.' + + `I couldn't afford to learn it.' said the Mock Turtle with a +sigh. `I only took the regular course.' + + `What was that?' inquired Alice. + + `Reeling and Writhing, of course, to begin with,' the Mock +Turtle replied; `and then the different branches of Arithmetic-- +Ambition, Distraction, Uglification, and Derision.' + + `I never heard of "Uglification,"' Alice ventured to say. `What +is it?' + + The Gryphon lifted up both its paws in surprise. `What! Never +heard of uglifying!' it exclaimed. `You know what to beautify +is, I suppose?' + + `Yes,' said Alice doubtfully: `it means--to--make--anything-- +prettier.' + + `Well, then,' the Gryphon went on, `if you don't know what to +uglify is, you ARE a simpleton.' + + Alice did not feel encouraged to ask any more questions about +it, so she turned to the Mock Turtle, and said `What else had you +to learn?' + + `Well, there was Mystery,' the Mock Turtle replied, counting +off the subjects on his flappers, `--Mystery, ancient and modern, +with Seaography: then Drawling--the Drawling-master was an old +conger-eel, that used to come once a week: HE taught us +Drawling, Stretching, and Fainting in Coils.' + + `What was THAT like?' said Alice. + + `Well, I can't show it you myself,' the Mock Turtle said: `I'm +too stiff. And the Gryphon never learnt it.' + + `Hadn't time,' said the Gryphon: `I went to the Classics +master, though. He was an old crab, HE was.' + + `I never went to him,' the Mock Turtle said with a sigh: `he +taught Laughing and Grief, they used to say.' + + `So he did, so he did,' said the Gryphon, sighing in his turn; +and both creatures hid their faces in their paws. + + `And how many hours a day did you do lessons?' said Alice, in a +hurry to change the subject. + + `Ten hours the first day,' said the Mock Turtle: `nine the +next, and so on.' + + `What a curious plan!' exclaimed Alice. + + `That's the reason they're called lessons,' the Gryphon +remarked: `because they lessen from day to day.' + + This was quite a new idea to Alice, and she thought it over a +little before she made her next remark. `Then the eleventh day +must have been a holiday?' + + `Of course it was,' said the Mock Turtle. + + `And how did you manage on the twelfth?' Alice went on eagerly. + + `That's enough about lessons,' the Gryphon interrupted in a +very decided tone: `tell her something about the games now.' + + + + CHAPTER X + + The Lobster Quadrille + + + The Mock Turtle sighed deeply, and drew the back of one flapper +across his eyes. He looked at Alice, and tried to speak, but for +a minute or two sobs choked his voice. `Same as if he had a bone +in his throat,' said the Gryphon: and it set to work shaking him +and punching him in the back. At last the Mock Turtle recovered +his voice, and, with tears running down his cheeks, he went on +again:-- + + `You may not have lived much under the sea--' (`I haven't,' +said Alice)--`and perhaps you were never even introduced to a lobster--' +(Alice began to say `I once tasted--' but checked herself hastily, +and said `No, never') `--so you can have no idea what a delightful +thing a Lobster Quadrille is!' + + `No, indeed,' said Alice. `What sort of a dance is it?' + + `Why,' said the Gryphon, `you first form into a line along the +sea-shore--' + + `Two lines!' cried the Mock Turtle. `Seals, turtles, salmon, +and so on; then, when you've cleared all the jelly-fish out of +the way--' + + `THAT generally takes some time,' interrupted the Gryphon. + + `--you advance twice--' + + `Each with a lobster as a partner!' cried the Gryphon. + + `Of course,' the Mock Turtle said: `advance twice, set to +partners--' + + `--change lobsters, and retire in same order,' continued the +Gryphon. + + `Then, you know,' the Mock Turtle went on, `you throw the--' + + `The lobsters!' shouted the Gryphon, with a bound into the air. + + `--as far out to sea as you can--' + + `Swim after them!' screamed the Gryphon. + + `Turn a somersault in the sea!' cried the Mock Turtle, +capering wildly about. + + `Back to land again, and that's all the first figure,' said the +Mock Turtle, suddenly dropping his voice; and the two creatures, +who had been jumping about like mad things all this time, sat +down again very sadly and quietly, and looked at Alice. + + `It must be a very pretty dance,' said Alice timidly. + + `Would you like to see a little of it?' said the Mock Turtle. + + `Very much indeed,' said Alice. + + `Come, let's try the first figure!' said the Mock Turtle to the +Gryphon. `We can do without lobsters, you know. Which shall +sing?' + + `Oh, YOU sing,' said the Gryphon. `I've forgotten the words.' + + So they began solemnly dancing round and round Alice, every now +and then treading on her toes when they passed too close, and +waving their forepaws to mark the time, while the Mock Turtle +sang this, very slowly and sadly:-- + + +`"Will you walk a little faster?" said a whiting to a snail. +"There's a porpoise close behind us, and he's treading on my + tail. +See how eagerly the lobsters and the turtles all advance! +They are waiting on the shingle--will you come and join the +dance? + +Will you, won't you, will you, won't you, will you join the +dance? +Will you, won't you, will you, won't you, won't you join the +dance? + + +"You can really have no notion how delightful it will be +When they take us up and throw us, with the lobsters, out to + sea!" +But the snail replied "Too far, too far!" and gave a look + askance-- +Said he thanked the whiting kindly, but he would not join the + dance. + Would not, could not, would not, could not, would not join + the dance. + Would not, could not, would not, could not, could not join + the dance. + +`"What matters it how far we go?" his scaly friend replied. +"There is another shore, you know, upon the other side. +The further off from England the nearer is to France-- +Then turn not pale, beloved snail, but come and join the dance. + + Will you, won't you, will you, won't you, will you join the + dance? + Will you, won't you, will you, won't you, won't you join the + dance?"' + + + + `Thank you, it's a very interesting dance to watch,' said +Alice, feeling very glad that it was over at last: `and I do so +like that curious song about the whiting!' + + `Oh, as to the whiting,' said the Mock Turtle, `they--you've +seen them, of course?' + + `Yes,' said Alice, `I've often seen them at dinn--' she +checked herself hastily. + + `I don't know where Dinn may be,' said the Mock Turtle, `but +if you've seen them so often, of course you know what they're +like.' + + `I believe so,' Alice replied thoughtfully. `They have their +tails in their mouths--and they're all over crumbs.' + + `You're wrong about the crumbs,' said the Mock Turtle: +`crumbs would all wash off in the sea. But they HAVE their tails +in their mouths; and the reason is--' here the Mock Turtle +yawned and shut his eyes.--`Tell her about the reason and all +that,' he said to the Gryphon. + + `The reason is,' said the Gryphon, `that they WOULD go with +the lobsters to the dance. So they got thrown out to sea. So +they had to fall a long way. So they got their tails fast in +their mouths. So they couldn't get them out again. That's all.' + + `Thank you,' said Alice, `it's very interesting. I never knew +so much about a whiting before.' + + `I can tell you more than that, if you like,' said the +Gryphon. `Do you know why it's called a whiting?' + + `I never thought about it,' said Alice. `Why?' + + `IT DOES THE BOOTS AND SHOES.' the Gryphon replied very +solemnly. + + Alice was thoroughly puzzled. `Does the boots and shoes!' she +repeated in a wondering tone. + + `Why, what are YOUR shoes done with?' said the Gryphon. `I +mean, what makes them so shiny?' + + Alice looked down at them, and considered a little before she +gave her answer. `They're done with blacking, I believe.' + + `Boots and shoes under the sea,' the Gryphon went on in a deep +voice, `are done with a whiting. Now you know.' + + `And what are they made of?' Alice asked in a tone of great +curiosity. + + `Soles and eels, of course,' the Gryphon replied rather +impatiently: `any shrimp could have told you that.' + + `If I'd been the whiting,' said Alice, whose thoughts were +still running on the song, `I'd have said to the porpoise, "Keep +back, please: we don't want YOU with us!"' + + `They were obliged to have him with them,' the Mock Turtle +said: `no wise fish would go anywhere without a porpoise.' + + `Wouldn't it really?' said Alice in a tone of great surprise. + + `Of course not,' said the Mock Turtle: `why, if a fish came +to ME, and told me he was going a journey, I should say "With +what porpoise?"' + + `Don't you mean "purpose"?' said Alice. + + `I mean what I say,' the Mock Turtle replied in an offended +tone. And the Gryphon added `Come, let's hear some of YOUR +adventures.' + + `I could tell you my adventures--beginning from this morning,' +said Alice a little timidly: `but it's no use going back to +yesterday, because I was a different person then.' + + `Explain all that,' said the Mock Turtle. + + `No, no! The adventures first,' said the Gryphon in an +impatient tone: `explanations take such a dreadful time.' + + So Alice began telling them her adventures from the time when +she first saw the White Rabbit. She was a little nervous about +it just at first, the two creatures got so close to her, one on +each side, and opened their eyes and mouths so VERY wide, but she +gained courage as she went on. Her listeners were perfectly +quiet till she got to the part about her repeating `YOU ARE OLD, +FATHER WILLIAM,' to the Caterpillar, and the words all coming +different, and then the Mock Turtle drew a long breath, and said +`That's very curious.' + + `It's all about as curious as it can be,' said the Gryphon. + + `It all came different!' the Mock Turtle repeated +thoughtfully. `I should like to hear her try and repeat +something now. Tell her to begin.' He looked at the Gryphon as +if he thought it had some kind of authority over Alice. + + `Stand up and repeat "'TIS THE VOICE OF THE SLUGGARD,"' said +the Gryphon. + + `How the creatures order one about, and make one repeat +lessons!' thought Alice; `I might as well be at school at once.' +However, she got up, and began to repeat it, but her head was so +full of the Lobster Quadrille, that she hardly knew what she was +saying, and the words came very queer indeed:-- + + `'Tis the voice of the Lobster; I heard him declare, + "You have baked me too brown, I must sugar my hair." + As a duck with its eyelids, so he with his nose + Trims his belt and his buttons, and turns out his toes.' + + [later editions continued as follows + When the sands are all dry, he is gay as a lark, + And will talk in contemptuous tones of the Shark, + But, when the tide rises and sharks are around, + His voice has a timid and tremulous sound.] + + `That's different from what I used to say when I was a child,' +said the Gryphon. + + `Well, I never heard it before,' said the Mock Turtle; `but it +sounds uncommon nonsense.' + + Alice said nothing; she had sat down with her face in her +hands, wondering if anything would EVER happen in a natural way +again. + + `I should like to have it explained,' said the Mock Turtle. + + `She can't explain it,' said the Gryphon hastily. `Go on with +the next verse.' + + `But about his toes?' the Mock Turtle persisted. `How COULD +he turn them out with his nose, you know?' + + `It's the first position in dancing.' Alice said; but was +dreadfully puzzled by the whole thing, and longed to change the +subject. + + `Go on with the next verse,' the Gryphon repeated impatiently: +`it begins "I passed by his garden."' + + Alice did not dare to disobey, though she felt sure it would +all come wrong, and she went on in a trembling voice:-- + + `I passed by his garden, and marked, with one eye, + How the Owl and the Panther were sharing a pie--' + + [later editions continued as follows + The Panther took pie-crust, and gravy, and meat, + While the Owl had the dish as its share of the treat. + When the pie was all finished, the Owl, as a boon, + Was kindly permitted to pocket the spoon: + While the Panther received knife and fork with a growl, + And concluded the banquet--] + + `What IS the use of repeating all that stuff,' the Mock Turtle +interrupted, `if you don't explain it as you go on? It's by far +the most confusing thing I ever heard!' + + `Yes, I think you'd better leave off,' said the Gryphon: and +Alice was only too glad to do so. + + `Shall we try another figure of the Lobster Quadrille?' the +Gryphon went on. `Or would you like the Mock Turtle to sing you +a song?' + + `Oh, a song, please, if the Mock Turtle would be so kind,' +Alice replied, so eagerly that the Gryphon said, in a rather +offended tone, `Hm! No accounting for tastes! Sing her "Turtle +Soup," will you, old fellow?' + + The Mock Turtle sighed deeply, and began, in a voice sometimes +choked with sobs, to sing this:-- + + + `Beautiful Soup, so rich and green, + Waiting in a hot tureen! + Who for such dainties would not stoop? + Soup of the evening, beautiful Soup! + Soup of the evening, beautiful Soup! + Beau--ootiful Soo--oop! + Beau--ootiful Soo--oop! + Soo--oop of the e--e--evening, + Beautiful, beautiful Soup! + + `Beautiful Soup! Who cares for fish, + Game, or any other dish? + Who would not give all else for two p + ennyworth only of beautiful Soup? + Pennyworth only of beautiful Soup? + Beau--ootiful Soo--oop! + Beau--ootiful Soo--oop! + Soo--oop of the e--e--evening, + Beautiful, beauti--FUL SOUP!' + + `Chorus again!' cried the Gryphon, and the Mock Turtle had +just begun to repeat it, when a cry of `The trial's beginning!' +was heard in the distance. + + `Come on!' cried the Gryphon, and, taking Alice by the hand, +it hurried off, without waiting for the end of the song. + + `What trial is it?' Alice panted as she ran; but the Gryphon +only answered `Come on!' and ran the faster, while more and more +faintly came, carried on the breeze that followed them, the +melancholy words:-- + + `Soo--oop of the e--e--evening, + Beautiful, beautiful Soup!' + + + + CHAPTER XI + + Who Stole the Tarts? + + + The King and Queen of Hearts were seated on their throne when +they arrived, with a great crowd assembled about them--all sorts +of little birds and beasts, as well as the whole pack of cards: +the Knave was standing before them, in chains, with a soldier on +each side to guard him; and near the King was the White Rabbit, +with a trumpet in one hand, and a scroll of parchment in the +other. In the very middle of the court was a table, with a large +dish of tarts upon it: they looked so good, that it made Alice +quite hungry to look at them--`I wish they'd get the trial done,' +she thought, `and hand round the refreshments!' But there seemed +to be no chance of this, so she began looking at everything about +her, to pass away the time. + + Alice had never been in a court of justice before, but she had +read about them in books, and she was quite pleased to find that +she knew the name of nearly everything there. `That's the +judge,' she said to herself, `because of his great wig.' + + The judge, by the way, was the King; and as he wore his crown +over the wig, (look at the frontispiece if you want to see how he +did it,) he did not look at all comfortable, and it was certainly +not becoming. + + `And that's the jury-box,' thought Alice, `and those twelve +creatures,' (she was obliged to say `creatures,' you see, because +some of them were animals, and some were birds,) `I suppose they +are the jurors.' She said this last word two or three times over +to herself, being rather proud of it: for she thought, and +rightly too, that very few little girls of her age knew the +meaning of it at all. However, `jury-men' would have done just +as well. + + The twelve jurors were all writing very busily on slates. +`What are they doing?' Alice whispered to the Gryphon. `They +can't have anything to put down yet, before the trial's begun.' + + `They're putting down their names,' the Gryphon whispered in +reply, `for fear they should forget them before the end of the +trial.' + + `Stupid things!' Alice began in a loud, indignant voice, but +she stopped hastily, for the White Rabbit cried out, `Silence in +the court!' and the King put on his spectacles and looked +anxiously round, to make out who was talking. + + Alice could see, as well as if she were looking over their +shoulders, that all the jurors were writing down `stupid things!' +on their slates, and she could even make out that one of them +didn't know how to spell `stupid,' and that he had to ask his +neighbour to tell him. `A nice muddle their slates'll be in +before the trial's over!' thought Alice. + + One of the jurors had a pencil that squeaked. This of course, +Alice could not stand, and she went round the court and got +behind him, and very soon found an opportunity of taking it +away. She did it so quickly that the poor little juror (it was +Bill, the Lizard) could not make out at all what had become of +it; so, after hunting all about for it, he was obliged to write +with one finger for the rest of the day; and this was of very +little use, as it left no mark on the slate. + + `Herald, read the accusation!' said the King. + + On this the White Rabbit blew three blasts on the trumpet, and +then unrolled the parchment scroll, and read as follows:-- + + `The Queen of Hearts, she made some tarts, + All on a summer day: + The Knave of Hearts, he stole those tarts, + And took them quite away!' + + `Consider your verdict,' the King said to the jury. + + `Not yet, not yet!' the Rabbit hastily interrupted. `There's +a great deal to come before that!' + + `Call the first witness,' said the King; and the White Rabbit +blew three blasts on the trumpet, and called out, `First +witness!' + + The first witness was the Hatter. He came in with a teacup in +one hand and a piece of bread-and-butter in the other. `I beg +pardon, your Majesty,' he began, `for bringing these in: but I +hadn't quite finished my tea when I was sent for.' + + `You ought to have finished,' said the King. `When did you +begin?' + + The Hatter looked at the March Hare, who had followed him into +the court, arm-in-arm with the Dormouse. `Fourteenth of March, I +think it was,' he said. + + `Fifteenth,' said the March Hare. + + `Sixteenth,' added the Dormouse. + + `Write that down,' the King said to the jury, and the jury +eagerly wrote down all three dates on their slates, and then +added them up, and reduced the answer to shillings and pence. + + `Take off your hat,' the King said to the Hatter. + + `It isn't mine,' said the Hatter. + + `Stolen!' the King exclaimed, turning to the jury, who +instantly made a memorandum of the fact. + + `I keep them to sell,' the Hatter added as an explanation; +`I've none of my own. I'm a hatter.' + + Here the Queen put on her spectacles, and began staring at the +Hatter, who turned pale and fidgeted. + + `Give your evidence,' said the King; `and don't be nervous, or +I'll have you executed on the spot.' + + This did not seem to encourage the witness at all: he kept +shifting from one foot to the other, looking uneasily at the +Queen, and in his confusion he bit a large piece out of his +teacup instead of the bread-and-butter. + + Just at this moment Alice felt a very curious sensation, which +puzzled her a good deal until she made out what it was: she was +beginning to grow larger again, and she thought at first she +would get up and leave the court; but on second thoughts she +decided to remain where she was as long as there was room for +her. + + `I wish you wouldn't squeeze so.' said the Dormouse, who was +sitting next to her. `I can hardly breathe.' + + `I can't help it,' said Alice very meekly: `I'm growing.' + + `You've no right to grow here,' said the Dormouse. + + `Don't talk nonsense,' said Alice more boldly: `you know +you're growing too.' + + `Yes, but I grow at a reasonable pace,' said the Dormouse: +`not in that ridiculous fashion.' And he got up very sulkily +and crossed over to the other side of the court. + + All this time the Queen had never left off staring at the +Hatter, and, just as the Dormouse crossed the court, she said to +one of the officers of the court, `Bring me the list of the +singers in the last concert!' on which the wretched Hatter +trembled so, that he shook both his shoes off. + + `Give your evidence,' the King repeated angrily, `or I'll have +you executed, whether you're nervous or not.' + + `I'm a poor man, your Majesty,' the Hatter began, in a +trembling voice, `--and I hadn't begun my tea--not above a week +or so--and what with the bread-and-butter getting so thin--and +the twinkling of the tea--' + + `The twinkling of the what?' said the King. + + `It began with the tea,' the Hatter replied. + + `Of course twinkling begins with a T!' said the King sharply. +`Do you take me for a dunce? Go on!' + + `I'm a poor man,' the Hatter went on, `and most things +twinkled after that--only the March Hare said--' + + `I didn't!' the March Hare interrupted in a great hurry. + + `You did!' said the Hatter. + + `I deny it!' said the March Hare. + + `He denies it,' said the King: `leave out that part.' + + `Well, at any rate, the Dormouse said--' the Hatter went on, +looking anxiously round to see if he would deny it too: but the +Dormouse denied nothing, being fast asleep. + + `After that,' continued the Hatter, `I cut some more bread- +and-butter--' + + `But what did the Dormouse say?' one of the jury asked. + + `That I can't remember,' said the Hatter. + + `You MUST remember,' remarked the King, `or I'll have you +executed.' + + The miserable Hatter dropped his teacup and bread-and-butter, +and went down on one knee. `I'm a poor man, your Majesty,' he +began. + + `You're a very poor speaker,' said the King. + + Here one of the guinea-pigs cheered, and was immediately +suppressed by the officers of the court. (As that is rather a +hard word, I will just explain to you how it was done. They had +a large canvas bag, which tied up at the mouth with strings: +into this they slipped the guinea-pig, head first, and then sat +upon it.) + + `I'm glad I've seen that done,' thought Alice. `I've so often +read in the newspapers, at the end of trials, "There was some +attempts at applause, which was immediately suppressed by the +officers of the court," and I never understood what it meant +till now.' + + `If that's all you know about it, you may stand down,' +continued the King. + + `I can't go no lower,' said the Hatter: `I'm on the floor, as +it is.' + + `Then you may SIT down,' the King replied. + + Here the other guinea-pig cheered, and was suppressed. + + `Come, that finished the guinea-pigs!' thought Alice. `Now we +shall get on better.' + + `I'd rather finish my tea,' said the Hatter, with an anxious +look at the Queen, who was reading the list of singers. + + `You may go,' said the King, and the Hatter hurriedly left the +court, without even waiting to put his shoes on. + + `--and just take his head off outside,' the Queen added to one +of the officers: but the Hatter was out of sight before the +officer could get to the door. + + `Call the next witness!' said the King. + + The next witness was the Duchess's cook. She carried the +pepper-box in her hand, and Alice guessed who it was, even before +she got into the court, by the way the people near the door began +sneezing all at once. + + `Give your evidence,' said the King. + + `Shan't,' said the cook. + + The King looked anxiously at the White Rabbit, who said in a +low voice, `Your Majesty must cross-examine THIS witness.' + + `Well, if I must, I must,' the King said, with a melancholy +air, and, after folding his arms and frowning at the cook till +his eyes were nearly out of sight, he said in a deep voice, `What +are tarts made of?' + + `Pepper, mostly,' said the cook. + + `Treacle,' said a sleepy voice behind her. + + `Collar that Dormouse,' the Queen shrieked out. `Behead that +Dormouse! Turn that Dormouse out of court! Suppress him! Pinch +him! Off with his whiskers!' + + For some minutes the whole court was in confusion, getting the +Dormouse turned out, and, by the time they had settled down +again, the cook had disappeared. + + `Never mind!' said the King, with an air of great relief. +`Call the next witness.' And he added in an undertone to the +Queen, `Really, my dear, YOU must cross-examine the next witness. +It quite makes my forehead ache!' + + Alice watched the White Rabbit as he fumbled over the list, +feeling very curious to see what the next witness would be like, +`--for they haven't got much evidence YET,' she said to herself. +Imagine her surprise, when the White Rabbit read out, at the top +of his shrill little voice, the name `Alice!' + + + + CHAPTER XII + + Alice's Evidence + + + `Here!' cried Alice, quite forgetting in the flurry of the +moment how large she had grown in the last few minutes, and she +jumped up in such a hurry that she tipped over the jury-box with +the edge of her skirt, upsetting all the jurymen on to the heads +of the crowd below, and there they lay sprawling about, reminding +her very much of a globe of goldfish she had accidentally upset +the week before. + + `Oh, I BEG your pardon!' she exclaimed in a tone of great +dismay, and began picking them up again as quickly as she could, +for the accident of the goldfish kept running in her head, and +she had a vague sort of idea that they must be collected at once +and put back into the jury-box, or they would die. + + `The trial cannot proceed,' said the King in a very grave +voice, `until all the jurymen are back in their proper places-- +ALL,' he repeated with great emphasis, looking hard at Alice as +he said do. + + Alice looked at the jury-box, and saw that, in her haste, she +had put the Lizard in head downwards, and the poor little thing +was waving its tail about in a melancholy way, being quite unable +to move. She soon got it out again, and put it right; `not that +it signifies much,' she said to herself; `I should think it +would be QUITE as much use in the trial one way up as the other.' + + As soon as the jury had a little recovered from the shock of +being upset, and their slates and pencils had been found and +handed back to them, they set to work very diligently to write +out a history of the accident, all except the Lizard, who seemed +too much overcome to do anything but sit with its mouth open, +gazing up into the roof of the court. + + `What do you know about this business?' the King said to +Alice. + + `Nothing,' said Alice. + + `Nothing WHATEVER?' persisted the King. + + `Nothing whatever,' said Alice. + + `That's very important,' the King said, turning to the jury. +They were just beginning to write this down on their slates, when +the White Rabbit interrupted: `UNimportant, your Majesty means, +of course,' he said in a very respectful tone, but frowning and +making faces at him as he spoke. + + `UNimportant, of course, I meant,' the King hastily said, and +went on to himself in an undertone, `important--unimportant-- +unimportant--important--' as if he were trying which word +sounded best. + + Some of the jury wrote it down `important,' and some +`unimportant.' Alice could see this, as she was near enough to +look over their slates; `but it doesn't matter a bit,' she +thought to herself. + + At this moment the King, who had been for some time busily +writing in his note-book, cackled out `Silence!' and read out +from his book, `Rule Forty-two. ALL PERSONS MORE THAN A MILE +HIGH TO LEAVE THE COURT.' + + Everybody looked at Alice. + + `I'M not a mile high,' said Alice. + + `You are,' said the King. + + `Nearly two miles high,' added the Queen. + + `Well, I shan't go, at any rate,' said Alice: `besides, +that's not a regular rule: you invented it just now.' + + `It's the oldest rule in the book,' said the King. + + `Then it ought to be Number One,' said Alice. + + The King turned pale, and shut his note-book hastily. +`Consider your verdict,' he said to the jury, in a low, trembling +voice. + + `There's more evidence to come yet, please your Majesty,' said +the White Rabbit, jumping up in a great hurry; `this paper has +just been picked up.' + + `What's in it?' said the Queen. + + `I haven't opened it yet,' said the White Rabbit, `but it seems +to be a letter, written by the prisoner to--to somebody.' + + `It must have been that,' said the King, `unless it was +written to nobody, which isn't usual, you know.' + + `Who is it directed to?' said one of the jurymen. + + `It isn't directed at all,' said the White Rabbit; `in fact, +there's nothing written on the OUTSIDE.' He unfolded the paper +as he spoke, and added `It isn't a letter, after all: it's a set +of verses.' + + `Are they in the prisoner's handwriting?' asked another of +they jurymen. + + `No, they're not,' said the White Rabbit, `and that's the +queerest thing about it.' (The jury all looked puzzled.) + + `He must have imitated somebody else's hand,' said the King. +(The jury all brightened up again.) + + `Please your Majesty,' said the Knave, `I didn't write it, and +they can't prove I did: there's no name signed at the end.' + + `If you didn't sign it,' said the King, `that only makes the +matter worse. You MUST have meant some mischief, or else you'd +have signed your name like an honest man.' + + There was a general clapping of hands at this: it was the +first really clever thing the King had said that day. + + `That PROVES his guilt,' said the Queen. + + `It proves nothing of the sort!' said Alice. `Why, you don't +even know what they're about!' + + `Read them,' said the King. + + The White Rabbit put on his spectacles. `Where shall I begin, +please your Majesty?' he asked. + + `Begin at the beginning,' the King said gravely, `and go on +till you come to the end: then stop.' + + These were the verses the White Rabbit read:-- + + `They told me you had been to her, + And mentioned me to him: + She gave me a good character, + But said I could not swim. + + He sent them word I had not gone + (We know it to be true): + If she should push the matter on, + What would become of you? + + I gave her one, they gave him two, + You gave us three or more; + They all returned from him to you, + Though they were mine before. + + If I or she should chance to be + Involved in this affair, + He trusts to you to set them free, + Exactly as we were. + + My notion was that you had been + (Before she had this fit) + An obstacle that came between + Him, and ourselves, and it. + + Don't let him know she liked them best, + For this must ever be + A secret, kept from all the rest, + Between yourself and me.' + + `That's the most important piece of evidence we've heard yet,' +said the King, rubbing his hands; `so now let the jury--' + + `If any one of them can explain it,' said Alice, (she had +grown so large in the last few minutes that she wasn't a bit +afraid of interrupting him,) `I'll give him sixpence. _I_ don't +believe there's an atom of meaning in it.' + + The jury all wrote down on their slates, `SHE doesn't believe +there's an atom of meaning in it,' but none of them attempted to +explain the paper. + + `If there's no meaning in it,' said the King, `that saves a +world of trouble, you know, as we needn't try to find any. And +yet I don't know,' he went on, spreading out the verses on his +knee, and looking at them with one eye; `I seem to see some +meaning in them, after all. "--SAID I COULD NOT SWIM--" you +can't swim, can you?' he added, turning to the Knave. + + The Knave shook his head sadly. `Do I look like it?' he said. +(Which he certainly did NOT, being made entirely of cardboard.) + + `All right, so far,' said the King, and he went on muttering +over the verses to himself: `"WE KNOW IT TO BE TRUE--" that's +the jury, of course-- "I GAVE HER ONE, THEY GAVE HIM TWO--" why, +that must be what he did with the tarts, you know--' + + `But, it goes on "THEY ALL RETURNED FROM HIM TO YOU,"' said +Alice. + + `Why, there they are!' said the King triumphantly, pointing to +the tarts on the table. `Nothing can be clearer than THAT. +Then again--"BEFORE SHE HAD THIS FIT--" you never had fits, my +dear, I think?' he said to the Queen. + + `Never!' said the Queen furiously, throwing an inkstand at the +Lizard as she spoke. (The unfortunate little Bill had left off +writing on his slate with one finger, as he found it made no +mark; but he now hastily began again, using the ink, that was +trickling down his face, as long as it lasted.) + + `Then the words don't FIT you,' said the King, looking round +the court with a smile. There was a dead silence. + + `It's a pun!' the King added in an offended tone, and +everybody laughed, `Let the jury consider their verdict,' the +King said, for about the twentieth time that day. + + `No, no!' said the Queen. `Sentence first--verdict afterwards.' + + `Stuff and nonsense!' said Alice loudly. `The idea of having +the sentence first!' + + `Hold your tongue!' said the Queen, turning purple. + + `I won't!' said Alice. + + `Off with her head!' the Queen shouted at the top of her voice. +Nobody moved. + + `Who cares for you?' said Alice, (she had grown to her full +size by this time.) `You're nothing but a pack of cards!' + + At this the whole pack rose up into the air, and came flying +down upon her: she gave a little scream, half of fright and half +of anger, and tried to beat them off, and found herself lying on +the bank, with her head in the lap of her sister, who was gently +brushing away some dead leaves that had fluttered down from the +trees upon her face. + + `Wake up, Alice dear!' said her sister; `Why, what a long +sleep you've had!' + + `Oh, I've had such a curious dream!' said Alice, and she told +her sister, as well as she could remember them, all these strange +Adventures of hers that you have just been reading about; and +when she had finished, her sister kissed her, and said, `It WAS a +curious dream, dear, certainly: but now run in to your tea; it's +getting late.' So Alice got up and ran off, thinking while she +ran, as well she might, what a wonderful dream it had been. + + But her sister sat still just as she left her, leaning her +head on her hand, watching the setting sun, and thinking of +little Alice and all her wonderful Adventures, till she too began +dreaming after a fashion, and this was her dream:-- + + First, she dreamed of little Alice herself, and once again the +tiny hands were clasped upon her knee, and the bright eager eyes +were looking up into hers--she could hear the very tones of her +voice, and see that queer little toss of her head to keep back +the wandering hair that WOULD always get into her eyes--and +still as she listened, or seemed to listen, the whole place +around her became alive the strange creatures of her little +sister's dream. + + The long grass rustled at her feet as the White Rabbit hurried +by--the frightened Mouse splashed his way through the +neighbouring pool--she could hear the rattle of the teacups as +the March Hare and his friends shared their never-ending meal, +and the shrill voice of the Queen ordering off her unfortunate +guests to execution--once more the pig-baby was sneezing on the +Duchess's knee, while plates and dishes crashed around it--once +more the shriek of the Gryphon, the squeaking of the Lizard's +slate-pencil, and the choking of the suppressed guinea-pigs, +filled the air, mixed up with the distant sobs of the miserable +Mock Turtle. + + So she sat on, with closed eyes, and half believed herself in +Wonderland, though she knew she had but to open them again, and +all would change to dull reality--the grass would be only +rustling in the wind, and the pool rippling to the waving of the +reeds--the rattling teacups would change to tinkling sheep- +bells, and the Queen's shrill cries to the voice of the shepherd +boy--and the sneeze of the baby, the shriek of the Gryphon, and +all thy other queer noises, would change (she knew) to the +confused clamour of the busy farm-yard--while the lowing of the +cattle in the distance would take the place of the Mock Turtle's +heavy sobs. + + Lastly, she pictured to herself how this same little sister of +hers would, in the after-time, be herself a grown woman; and how +she would keep, through all her riper years, the simple and +loving heart of her childhood: and how she would gather about +her other little children, and make THEIR eyes bright and eager +with many a strange tale, perhaps even with the dream of +Wonderland of long ago: and how she would feel with all their +simple sorrows, and find a pleasure in all their simple joys, +remembering her own child-life, and the happy summer days. + + THE END + \ No newline at end of file diff --git a/ext/wasm3/test/wasi/brotli/alice29.txt.compressed b/ext/wasm3/test/wasi/brotli/alice29.txt.compressed new file mode 100644 index 0000000000000000000000000000000000000000..253d6ff48cc13e4314e729a7cd980d73e3eecd59 GIT binary patch literal 46487 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
      nKW>Kcqs~Kb(#!4JNL;q6|ty1|eP4h=zHoqy;ph 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�)Im*QqNEP< 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

      + +### Results + +```log + time(ms) +Node v13.0.1 (interpreter) 181527 +wasm-micro-runtime 78499 +wac (wax) - +wasm3 - +Wasmer 0.11.0 singlepass 1447 +wasmtime 0.7.0 (--optimize) 576 +Wasmer 0.11.0 cranelift 565 +wasmer-js (Node v13.0.1) 336 +Wasmer 0.11.0 llvm crash +WAVM 299 +Native (GCC 7.4.0, 32-bit) 249 +``` + +### Building + +```sh +wasicc -g0 -O3 c-ray-f.c -Dunix -o c-ray.wasm +``` + +### Running + +```sh +export ENGINES_PATH=/opt/wasm_engines + +# Wasm3 +cat scene | ../../../build/wasm3 c-ray.wasm -s 1024x768 > foo.ppm + +# wasm-micro-runtime +cat scene | $ENGINES_PATH/wasm-micro-runtime/core/iwasm/products/linux/build/iwasm c-ray.wasm -s 1024x768 > foo.ppm + +# wasmtime +cat scene | wasmtime --optimize c-ray.wasm -- -s 1024x768 > foo.ppm + +# Wasmer +cat scene | wasmer run c-ray.wasm -- -s 1024x768 > foo.ppm +cat scene | wasmer run --backend singlepass c-ray.wasm -- -s 1024x768 > foo.ppm +cat scene | wasmer run --backend llvm c-ray.wasm -- -s 1024x768 > foo.ppm + +# Wasmer-JS (V8) +cat scene | wasmer-js run c-ray.wasm -s 1024x768 > foo.ppm + +cat scene | node --wasm_interpret_all $(which wasmer-js) run c-ray.wasm -s 1024x768 > foo.ppm + +# WAVM +cat scene | $ENGINES_PATH/WAVM/Release/bin/wavm run c-ray.wasm -s 1024x768 > foo.ppm +``` diff --git a/ext/wasm3/test/wasi/c-ray/c-ray-f.c b/ext/wasm3/test/wasi/c-ray/c-ray-f.c new file mode 100644 index 0000000..9613245 --- /dev/null +++ b/ext/wasm3/test/wasi/c-ray/c-ray-f.c @@ -0,0 +1,583 @@ +/* c-ray-f - a simple raytracing filter. + * Copyright (C) 2006 John Tsiombikas + * + * You are free to use, modify and redistribute this program under the + * terms of the GNU General Public License v2 or (at your option) later. + * see "http://www.gnu.org/licenses/gpl.txt" for details. + * --------------------------------------------------------------------- + * Usage: + * compile: cc -o c-ray-f c-ray-f.c -lm + * run: cat scene | ./c-ray-f >foo.ppm + * enjoy: display foo.ppm (with imagemagick) + * or: imgview foo.ppm (on IRIX) + * --------------------------------------------------------------------- + * Scene file format: + * # sphere (many) + * s x y z rad r g b shininess reflectivity + * # light (many) + * l x y z + * # camera (one) + * c x y z fov tx ty tz + * --------------------------------------------------------------------- + */ +#include +#include +#include +#include +#include +#include + +/* find the appropriate way to define explicitly sized types */ +#if (__STDC_VERSION__ >= 199900) || defined(__GLIBC__) /* C99 or GNU libc */ +#include +#elif defined(__unix__) || defined(unix) +#include +#elif defined(_MSC_VER) /* the nameless one */ +typedef unsigned __int8 uint8_t; +typedef unsigned __int32 uint32_t; +#endif + +struct vec3 { + double x, y, z; +}; + +struct ray { + struct vec3 orig, dir; +}; + +struct material { + struct vec3 col; /* color */ + double spow; /* specular power */ + double refl; /* reflection intensity */ +}; + +struct sphere { + struct vec3 pos; + double rad; + struct material mat; + struct sphere *next; +}; + +struct spoint { + struct vec3 pos, normal, vref; /* position, normal and view reflection */ + double dist; /* parametric distance of intersection along the ray */ +}; + +struct camera { + struct vec3 pos, targ; + double fov; +}; + +void render(int xsz, int ysz, uint32_t *fb, int samples); +struct vec3 trace(struct ray ray, int depth); +struct vec3 shade(struct sphere *obj, struct spoint *sp, int depth); +struct vec3 reflect(struct vec3 v, struct vec3 n); +struct vec3 cross_product(struct vec3 v1, struct vec3 v2); +struct ray get_primary_ray(int x, int y, int sample); +struct vec3 get_sample_pos(int x, int y, int sample); +struct vec3 jitter(int x, int y, int s); +int ray_sphere(const struct sphere *sph, struct ray ray, struct spoint *sp); +void load_scene(FILE *fp); +unsigned long get_msec(void); + +#define MAX_LIGHTS 16 /* maximum number of lights */ +#define RAY_MAG 1000.0 /* trace rays of this magnitude */ +#define MAX_RAY_DEPTH 5 /* raytrace recursion limit */ +#define FOV 0.78539816 /* field of view in rads (pi/4) */ +#define HALF_FOV (FOV * 0.5) +#define ERR_MARGIN 1e-6 /* an arbitrary error margin to avoid surface acne */ + +/* bit-shift amount for packing each color into a 32bit uint */ +#ifdef LITTLE_ENDIAN +#define RSHIFT 16 +#define BSHIFT 0 +#else /* big endian */ +#define RSHIFT 0 +#define BSHIFT 16 +#endif /* endianness */ +#define GSHIFT 8 /* this is the same in both byte orders */ + +/* some helpful macros... */ +#define SQ(x) ((x) * (x)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define DOT(a, b) ((a).x * (b).x + (a).y * (b).y + (a).z * (b).z) +#define NORMALIZE(a) do {\ + double len = sqrt(DOT(a, a));\ + (a).x /= len; (a).y /= len; (a).z /= len;\ +} while(0); + +/* global state */ +int xres = 800; +int yres = 600; +double aspect = 1.333333; +struct sphere *obj_list; +struct vec3 lights[MAX_LIGHTS]; +int lnum = 0; +struct camera cam; + +#define NRAN 1024 +#define MASK (NRAN - 1) +struct vec3 urand[NRAN]; +int irand[NRAN]; + +const char *usage = { + "Usage: c-ray-f [options]\n" + " Reads a scene file from stdin, writes the image to stdout, and stats to stderr.\n\n" + "Options:\n" + " -s WxH where W is the width and H the height of the image\n" + " -r shoot rays per pixel (antialiasing)\n" + " -i read from instead of stdin\n" + " -o write to instead of stdout\n" + " -h this help screen\n\n" +}; + + + +int main(int argc, char **argv) { + int i; + unsigned long rend_time, start_time; + uint32_t *pixels; + int rays_per_pixel = 1; + FILE *infile = stdin, *outfile = stdout; + + for(i=1; i> RSHIFT) & 0xff, outfile); + fputc((pixels[i] >> GSHIFT) & 0xff, outfile); + fputc((pixels[i] >> BSHIFT) & 0xff, outfile); + } + fflush(outfile); + + if(infile != stdin) fclose(infile); + if(outfile != stdout) fclose(outfile); + return 0; +} + +/* render a frame of xsz/ysz dimensions into the provided framebuffer */ +void render(int xsz, int ysz, uint32_t *fb, int samples) { + int i, j, s; + double rcp_samples = 1.0 / (double)samples; + + /* for each subpixel, trace a ray through the scene, accumulate the + * colors of the subpixels of each pixel, then pack the color and + * put it into the framebuffer. + * XXX: assumes contiguous scanlines with NO padding, and 32bit pixels. + */ + for(j=0; jnext; + + /* if we reached the recursion limit, bail out */ + if(depth >= MAX_RAY_DEPTH) { + col.x = col.y = col.z = 0.0; + return col; + } + + /* find the nearest intersection ... */ + while(iter) { + if(ray_sphere(iter, ray, &sp)) { + if(!nearest_obj || sp.dist < nearest_sp.dist) { + nearest_obj = iter; + nearest_sp = sp; + } + } + iter = iter->next; + } + + /* and perform shading calculations as needed by calling shade() */ + if(nearest_obj) { + col = shade(nearest_obj, &nearest_sp, depth); + } else { + col.x = col.y = col.z = 0.0; + } + + return col; +} + +/* Calculates direct illumination with the phong reflectance model. + * Also handles reflections by calling trace again, if necessary. + */ +struct vec3 shade(struct sphere *obj, struct spoint *sp, int depth) { + int i; + struct vec3 col = {0, 0, 0}; + + /* for all lights ... */ + for(i=0; inext; + int in_shadow = 0; + + ldir.x = lights[i].x - sp->pos.x; + ldir.y = lights[i].y - sp->pos.y; + ldir.z = lights[i].z - sp->pos.z; + + shadow_ray.orig = sp->pos; + shadow_ray.dir = ldir; + + /* shoot shadow rays to determine if we have a line of sight with the light */ + while(iter) { + if(ray_sphere(iter, shadow_ray, 0)) { + in_shadow = 1; + break; + } + iter = iter->next; + } + + /* and if we're not in shadow, calculate direct illumination with the phong model. */ + if(!in_shadow) { + NORMALIZE(ldir); + + idiff = MAX(DOT(sp->normal, ldir), 0.0); + ispec = obj->mat.spow > 0.0 ? pow(MAX(DOT(sp->vref, ldir), 0.0), obj->mat.spow) : 0.0; + + col.x += idiff * obj->mat.col.x + ispec; + col.y += idiff * obj->mat.col.y + ispec; + col.z += idiff * obj->mat.col.z + ispec; + } + } + + /* Also, if the object is reflective, spawn a reflection ray, and call trace() + * to calculate the light arriving from the mirror direction. + */ + if(obj->mat.refl > 0.0) { + struct ray ray; + struct vec3 rcol; + + ray.orig = sp->pos; + ray.dir = sp->vref; + ray.dir.x *= RAY_MAG; + ray.dir.y *= RAY_MAG; + ray.dir.z *= RAY_MAG; + + rcol = trace(ray, depth + 1); + col.x += rcol.x * obj->mat.refl; + col.y += rcol.y * obj->mat.refl; + col.z += rcol.z * obj->mat.refl; + } + + return col; +} + +/* calculate reflection vector */ +struct vec3 reflect(struct vec3 v, struct vec3 n) { + struct vec3 res; + double dot = v.x * n.x + v.y * n.y + v.z * n.z; + res.x = -(2.0 * dot * n.x - v.x); + res.y = -(2.0 * dot * n.y - v.y); + res.z = -(2.0 * dot * n.z - v.z); + return res; +} + +struct vec3 cross_product(struct vec3 v1, struct vec3 v2) { + struct vec3 res; + res.x = v1.y * v2.z - v1.z * v2.y; + res.y = v1.z * v2.x - v1.x * v2.z; + res.z = v1.x * v2.y - v1.y * v2.x; + return res; +} + +/* determine the primary ray corresponding to the specified pixel (x, y) */ +struct ray get_primary_ray(int x, int y, int sample) { + struct ray ray; + float m[3][3]; + struct vec3 i, j = {0, 1, 0}, k, dir, orig, foo; + + k.x = cam.targ.x - cam.pos.x; + k.y = cam.targ.y - cam.pos.y; + k.z = cam.targ.z - cam.pos.z; + NORMALIZE(k); + + i = cross_product(j, k); + j = cross_product(k, i); + m[0][0] = i.x; m[0][1] = j.x; m[0][2] = k.x; + m[1][0] = i.y; m[1][1] = j.y; m[1][2] = k.y; + m[2][0] = i.z; m[2][1] = j.z; m[2][2] = k.z; + + ray.orig.x = ray.orig.y = ray.orig.z = 0.0; + ray.dir = get_sample_pos(x, y, sample); + ray.dir.z = 1.0 / HALF_FOV; + ray.dir.x *= RAY_MAG; + ray.dir.y *= RAY_MAG; + ray.dir.z *= RAY_MAG; + + dir.x = ray.dir.x + ray.orig.x; + dir.y = ray.dir.y + ray.orig.y; + dir.z = ray.dir.z + ray.orig.z; + foo.x = dir.x * m[0][0] + dir.y * m[0][1] + dir.z * m[0][2]; + foo.y = dir.x * m[1][0] + dir.y * m[1][1] + dir.z * m[1][2]; + foo.z = dir.x * m[2][0] + dir.y * m[2][1] + dir.z * m[2][2]; + + orig.x = ray.orig.x * m[0][0] + ray.orig.y * m[0][1] + ray.orig.z * m[0][2] + cam.pos.x; + orig.y = ray.orig.x * m[1][0] + ray.orig.y * m[1][1] + ray.orig.z * m[1][2] + cam.pos.y; + orig.z = ray.orig.x * m[2][0] + ray.orig.y * m[2][1] + ray.orig.z * m[2][2] + cam.pos.z; + + ray.orig = orig; + ray.dir.x = foo.x + orig.x; + ray.dir.y = foo.y + orig.y; + ray.dir.z = foo.z + orig.z; + + return ray; +} + + +struct vec3 get_sample_pos(int x, int y, int sample) { + struct vec3 pt; + double xsz = 2.0, ysz = xres / aspect; + static double sf = 0.0; + + if(sf == 0.0) { + sf = 2.0 / (double)xres; + } + + pt.x = ((double)x / (double)xres) - 0.5; + pt.y = -(((double)y / (double)yres) - 0.65) / aspect; + + if(sample) { + struct vec3 jt = jitter(x, y, sample); + pt.x += jt.x * sf; + pt.y += jt.y * sf / aspect; + } + return pt; +} + +/* jitter function taken from Graphics Gems I. */ +struct vec3 jitter(int x, int y, int s) { + struct vec3 pt; + pt.x = urand[(x + (y << 2) + irand[(x + s) & MASK]) & MASK].x; + pt.y = urand[(y + (x << 2) + irand[(y + s) & MASK]) & MASK].y; + return pt; +} + +/* Calculate ray-sphere intersection, and return {1, 0} to signify hit or no hit. + * Also the surface point parameters like position, normal, etc are returned through + * the sp pointer if it is not NULL. + */ +int ray_sphere(const struct sphere *sph, struct ray ray, struct spoint *sp) { + double a, b, c, d, sqrt_d, t1, t2; + + a = SQ(ray.dir.x) + SQ(ray.dir.y) + SQ(ray.dir.z); + b = 2.0 * ray.dir.x * (ray.orig.x - sph->pos.x) + + 2.0 * ray.dir.y * (ray.orig.y - sph->pos.y) + + 2.0 * ray.dir.z * (ray.orig.z - sph->pos.z); + c = SQ(sph->pos.x) + SQ(sph->pos.y) + SQ(sph->pos.z) + + SQ(ray.orig.x) + SQ(ray.orig.y) + SQ(ray.orig.z) + + 2.0 * (-sph->pos.x * ray.orig.x - sph->pos.y * ray.orig.y - sph->pos.z * ray.orig.z) - SQ(sph->rad); + + if((d = SQ(b) - 4.0 * a * c) < 0.0) return 0; + + sqrt_d = sqrt(d); + t1 = (-b + sqrt_d) / (2.0 * a); + t2 = (-b - sqrt_d) / (2.0 * a); + + if((t1 < ERR_MARGIN && t2 < ERR_MARGIN) || (t1 > 1.0 && t2 > 1.0)) return 0; + + if(sp) { + if(t1 < ERR_MARGIN) t1 = t2; + if(t2 < ERR_MARGIN) t2 = t1; + sp->dist = t1 < t2 ? t1 : t2; + + sp->pos.x = ray.orig.x + ray.dir.x * sp->dist; + sp->pos.y = ray.orig.y + ray.dir.y * sp->dist; + sp->pos.z = ray.orig.z + ray.dir.z * sp->dist; + + sp->normal.x = (sp->pos.x - sph->pos.x) / sph->rad; + sp->normal.y = (sp->pos.y - sph->pos.y) / sph->rad; + sp->normal.z = (sp->pos.z - sph->pos.z) / sph->rad; + + sp->vref = reflect(ray.dir, sp->normal); + NORMALIZE(sp->vref); + } + return 1; +} + +/* Load the scene from an extremely simple scene description file */ +#define DELIM " \t\n" +void load_scene(FILE *fp) { + char line[256], *ptr, type; + + obj_list = malloc(sizeof(struct sphere)); + obj_list->next = 0; + + while((ptr = fgets(line, 256, fp))) { + int i; + struct vec3 pos, col; + double rad, spow, refl; + + while(*ptr == ' ' || *ptr == '\t') ptr++; + if(*ptr == '#' || *ptr == '\n') continue; + + if(!(ptr = strtok(line, DELIM))) continue; + type = *ptr; + + for(i=0; i<3; i++) { + if(!(ptr = strtok(0, DELIM))) break; + *((double*)&pos.x + i) = atof(ptr); + } + + if(type == 'l') { + lights[lnum++] = pos; + continue; + } + + if(!(ptr = strtok(0, DELIM))) continue; + rad = atof(ptr); + + for(i=0; i<3; i++) { + if(!(ptr = strtok(0, DELIM))) break; + *((double*)&col.x + i) = atof(ptr); + } + + if(type == 'c') { + cam.pos = pos; + cam.targ = col; + cam.fov = rad; + continue; + } + + if(!(ptr = strtok(0, DELIM))) continue; + spow = atof(ptr); + + if(!(ptr = strtok(0, DELIM))) continue; + refl = atof(ptr); + + if(type == 's') { + struct sphere *sph = malloc(sizeof *sph); + sph->next = obj_list->next; + obj_list->next = sph; + + sph->pos = pos; + sph->rad = rad; + sph->mat.col = col; + sph->mat.spow = spow; + sph->mat.refl = refl; + } else { + fprintf(stderr, "unknown type: %c\n", type); + } + } +} + + +/* provide a millisecond-resolution timer for each system */ +#if defined(__unix__) || defined(unix) +#include +#include +unsigned long get_msec(void) { + static struct timeval timeval, first_timeval; + + gettimeofday(&timeval, 0); + if(first_timeval.tv_sec == 0) { + first_timeval = timeval; + return 0; + } + return (timeval.tv_sec - first_timeval.tv_sec) * 1000 + (timeval.tv_usec - first_timeval.tv_usec) / 1000; +} +#elif defined(__WIN32__) || defined(WIN32) +#include +unsigned long get_msec(void) { + return GetTickCount(); +} +#else +#error "I don't know how to measure time on your platform" +#endif diff --git a/ext/wasm3/test/wasi/c-ray/scene b/ext/wasm3/test/wasi/c-ray/scene new file mode 100644 index 0000000..082ef11 --- /dev/null +++ b/ext/wasm3/test/wasi/c-ray/scene @@ -0,0 +1,18 @@ +# spheres +# position radius color shininess reflectivity +s -1.5 -0.3 -1 0.7 1.0 0.2 0.05 50.0 0.3 +s 1.5 -0.4 0 0.6 0.1 0.85 1.0 50.0 0.4 + +# walls +s 0 -1000 2 999 0.1 0.2 0.6 80.0 0.8 + +# bouncing ball +s 0 0 2 1 1.0 0.5 0.1 60.0 0.7 + +# lights... +l -50 100 -50 +l 40 40 150 + +# camera (there can be only one!) +# position FOV target +c 0 6 -17 45 0 -1 0 diff --git a/ext/wasm3/test/wasi/c-ray/scene.jpg b/ext/wasm3/test/wasi/c-ray/scene.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1b939600c19674a69d0d022d44ec676e857da7d4 GIT binary patch literal 111827 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
      NfmMSj`I@hZ(ZR_m0{Ecco}=U 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 U?)n>Q!Egg$mD)q;>euxD0~;ntL;wH) literal 0 HcmV?d00001 diff --git a/ext/wasm3/test/wasi/c-ray/sphfract b/ext/wasm3/test/wasi/c-ray/sphfract new file mode 100644 index 0000000..72da260 --- /dev/null +++ b/ext/wasm3/test/wasi/c-ray/sphfract @@ -0,0 +1,192 @@ +s 0 0 0 1.0 0.25 0.25 0.25 50.0 0.65 +s 1.4 0 0 0.4 0.25 0.25 0.25 50.0 0.65 +s 1.96 0 0 0.16 0.25 0.25 0.25 50.0 0.65 +s 2.184 0 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.96 0.224 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.96 -0.224 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.96 0 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.96 0 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 0.56 0 0.16 0.25 0.25 0.25 50.0 0.65 +s 1.624 0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.176 0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 0.784 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 0.56 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 0.56 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 -0.56 0 0.16 0.25 0.25 0.25 50.0 0.65 +s 1.624 -0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.176 -0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 -0.784 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 -0.56 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 -0.56 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 0 0.56 0.16 0.25 0.25 0.25 50.0 0.65 +s 1.624 0 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.176 0 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 0.224 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 -0.224 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 0 0.784 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 0 -0.56 0.16 0.25 0.25 0.25 50.0 0.65 +s 1.624 0 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.176 0 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 0.224 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 -0.224 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 1.4 0 -0.784 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0 0 0.4 0.25 0.25 0.25 50.0 0.65 +s -1.96 0 0 0.16 0.25 0.25 0.25 50.0 0.65 +s -2.184 0 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.96 0.224 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.96 -0.224 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.96 0 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.96 0 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0.56 0 0.16 0.25 0.25 0.25 50.0 0.65 +s -1.176 0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.624 0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0.784 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0.56 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0.56 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 -0.56 0 0.16 0.25 0.25 0.25 50.0 0.65 +s -1.176 -0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.624 -0.56 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 -0.784 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 -0.56 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 -0.56 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0 0.56 0.16 0.25 0.25 0.25 50.0 0.65 +s -1.176 0 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.624 0 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0.224 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 -0.224 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0 0.784 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0 -0.56 0.16 0.25 0.25 0.25 50.0 0.65 +s -1.176 0 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.624 0 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0.224 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 -0.224 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -1.4 0 -0.784 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.4 0 0.4 0.25 0.25 0.25 50.0 0.65 +s 0.56 1.4 0 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.784 1.4 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 1.624 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 1.176 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 1.4 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 1.4 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 1.4 0 0.16 0.25 0.25 0.25 50.0 0.65 +s -0.784 1.4 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 1.624 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 1.176 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 1.4 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 1.4 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.96 0 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 1.96 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 1.96 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 2.184 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.96 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.96 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.4 0.56 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 1.4 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 1.4 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.624 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.176 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.4 0.784 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.4 -0.56 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 1.4 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 1.4 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.624 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.176 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 1.4 -0.784 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.4 0 0.4 0.25 0.25 0.25 50.0 0.65 +s 0.56 -1.4 0 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.784 -1.4 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 -1.176 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 -1.624 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 -1.4 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 -1.4 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 -1.4 0 0.16 0.25 0.25 0.25 50.0 0.65 +s -0.784 -1.4 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 -1.176 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 -1.624 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 -1.4 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 -1.4 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.96 0 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 -1.96 0 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 -1.96 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -2.184 0 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.96 0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.96 -0.224 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.4 0.56 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 -1.4 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 -1.4 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.176 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.624 0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.4 0.784 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.4 -0.56 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 -1.4 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 -1.4 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.176 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.624 -0.56 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -1.4 -0.784 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0 1.4 0.4 0.25 0.25 0.25 50.0 0.65 +s 0.56 0 1.4 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.784 0 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 0.224 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 -0.224 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 0 1.624 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 0 1.176 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 0 1.4 0.16 0.25 0.25 0.25 50.0 0.65 +s -0.784 0 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 0.224 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 -0.224 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 0 1.624 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 0 1.176 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0.56 1.4 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 0.56 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 0.56 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0.784 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0.56 1.624 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0.56 1.176 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -0.56 1.4 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 -0.56 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 -0.56 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -0.784 1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -0.56 1.624 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -0.56 1.176 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0 1.96 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 0 1.96 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 0 1.96 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0.224 1.96 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -0.224 1.96 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0 2.184 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0 -1.4 0.4 0.25 0.25 0.25 50.0 0.65 +s 0.56 0 -1.4 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.784 0 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 0.224 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 -0.224 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 0 -1.176 0.064 0.25 0.25 0.25 50.0 0.65 +s 0.56 0 -1.624 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 0 -1.4 0.16 0.25 0.25 0.25 50.0 0.65 +s -0.784 0 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 0.224 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 -0.224 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 0 -1.176 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.56 0 -1.624 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0.56 -1.4 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 0.56 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 0.56 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0.784 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0.56 -1.176 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0.56 -1.624 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -0.56 -1.4 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 -0.56 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 -0.56 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -0.784 -1.4 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -0.56 -1.176 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -0.56 -1.624 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0 -1.96 0.16 0.25 0.25 0.25 50.0 0.65 +s 0.224 0 -1.96 0.064 0.25 0.25 0.25 50.0 0.65 +s -0.224 0 -1.96 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0.224 -1.96 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -0.224 -1.96 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 0 -2.184 0.064 0.25 0.25 0.25 50.0 0.65 +s 0 -10002.25 0 10000 0.2 0.35 0.5 80.0 0.4 +s 0 10100.00 0 10000 0.5 0.2 0.1 40.0 0.0 +l -50 68 -50 +l 40 40 150 +c -7 6 -12 45 0 -0.65 0 diff --git a/ext/wasm3/test/wasi/c-ray/sphfract.jpg b/ext/wasm3/test/wasi/c-ray/sphfract.jpg new file mode 100644 index 0000000000000000000000000000000000000000..859f327fef3cb5cb90a13b234bf8f80c300bce5c GIT binary patch literal 192770 zcmb4qWmpyey7pQ$NViByOLs_jNq0+kH%LgzqFa&fM!Hp`LAp~~TIq&&7W&`&>~r>) zcRANwznL|&h7aEH+|M%)vkxmEOgSl8DG(S80)c^lpoayJI0zO7`ho6Yfe#!49Q1>P zfB=txjD&)MjD(Dgf{KBP@&x?}GBO$#8af6hCKe_NDmD%_CJwO1g#HK^dM7L#5^y8t z6XYkr+5gYa!&eX%5-bP~1PjIj!C--5vA_>qAQIs3goB0tx&QjW0DmDE9uWx{_*xSa z1OtYJ1H;0=BErBRz=NNHVSwMjf=9r9&W4C1N}+JfpsW7(eYchiBB)vSypkES@&?2hY8U^2iL#h2U#&P32pjhV4imFd7xm5CuGR3JYe zr~^)pCQy}$NF-Y!)i8mvC9^5|>fm(n10yL$vCMQ~7$Zfb;;oRzQD8X#td3D&_#uBb za5ye3IvoPBGAeKOQ)dzOwLtSw&>#vp1sC=e9m0EMG}i2A#vbwv5Z{nil6zKuDUL> z2PiTN6R6f_Z_Mjo?`?SavcM}Q{?b=Wepbw6zaF z&*4sW^cZ6`Nk~;*-;|dcSiy>O`nr;iwN+UZQ6haU*VC?#M|3?2u_#lYD6h1gR^*>hfCg#+Q=$JXEFxCes9W2B}w&8Iua-p! zUoy2xVx?Spv>v8ZvMiP$`C_B5@0&$Yo9D)^gb6HO_%elBuVla8QH5@9ki|AIh~7pXZ|>?WwX6K&;I0`gU{AA3Izp44;@V4 zKU>hMm;){W3XT)>!pH6FjWPl}e3UaTMMv)$a9=hQd#^igl(nJvV6@<^j_8^WA(_Zr zmILq!!%Lt~cxIDO@*I_c{loJHGCaCM8POvhJXzGfdJ}Uq9sG(&@<^!K020!|7(`X3 zB?+JjP$F@PfqFYYpztdt0NlhuRmbHIXyodkc#5FQrjVmUs)4{z0k{FsVulN+1OFE~ z37kP8SoyeA(d5~beRQHE-N=+p*@XX~=zl^e{ofD*v}XbZ-0&z#vjBudxFtag7-?WQ zPZ26g4me3h?G+HaY_YwhLC8lB$;^S?2?NevgpHYc1;sUW^ABzkk@GdCU11kyyv>xC zkg;M3+6bNZ-p5V99ze27BQ*FtjRfa{mX;5otIX>xZ%A@gjox)*W{`6Ozn$ozY$1p zt^{kyB@aQoK9WwHnx1crwhN!GdUT)1(6lsYvhv!Y#@}{s<)WzPu9H$}sULBueVjec zDk071K3eo_SujTXUVcedQo1hIGxW;Pe%Q5mx1;uK>Zs60v3;QZHg!I{sl_j&dyv-d zc|>~D-S3xWdAN;S<|>2cu3ELvrx@#hU4}8p%vG?O$iLH+ND%oNY8Hp zK9&>yD~DP0>d=*bjXy2^jpOm`Zf2uD7AG==siGWm}hwZ6V%@aqz!tX_Ro^g_ia zzXdiG=?ms6?WxA9A3!uaMa@rC=H}Zsm}m;B7D`iwnUeaR`upcakqIL-lz6Dyf9UtI zvC%k?OYj)DljVOV(=d*G&OmnrHZwE}8s~+p7Oq5j0L=<$1;ER3X0MaPFw?k{Fpe+Q z#vd~{P1Q#!C&F2TaGJb@N5+<(2NofPxClr?uu^Og!hMr4Q4vxrRJAV14Jvd10IB|gV_*+d%X&hzdx@SPpdo#FJxcg5U}iTde+-5H7P9!Si~lTG zg(mTZerkmaYAYk#BpFjZ4>fxfw7yaqyK|_xJ^y@0tty5gRr?}=$a%^P@_|TnNe^&> zfO?5yi$3BJs&3e#OHhq_)HE6XG814~-T{ahU=1Jf2-P>-|3oHZP+%lEU=snD0O|Kbe+iF?$tf4m_eaez0pf0Q`1i|l6YfD>E z3t=7G$A%IKqH7s2$Q9cvNmaB}8=D$k-R4mmY1hxZ3a7aEZ4asuvM&92G_CSG`^xQ? zo;^?fBnunYBg_yVwGy31h};r!O*9)b8tb;cYg=?Wn9*G@i?}24F)}`j*9mlU z^#J1fA~aZ9uW89mQlMn%#_l2Y0Md8>9V-Uh)8IUS?xu{6k^%0ys_J(+pf|dEleH4= zUe}n>!g@BIfy8e;WYe%Su^VIJ$DAXepU`We!Eiz*t=?a3ml?0B~YAA`-a_U_E( z@%5G8t+J^29pA{G&n01c`Rk|Xlko|rZ_iYu4R}mc3Dv#46cCbc(VFQ!XdJj54rs3{ zeoFl1_m)a%ypQwpo4XoBLo_>Mo8iPEh1rQ-l_DMU(n?nYTHR$Ii;NQSA{(EKd4uJ* zFH5Wun=_5|_Ve!oU_bXW#LuWyXd?F8qR-8D`eyEx-nl?^EV>ijhr z5byZuQ>0?Oyp_nd`7A1dV~X%}Yg|x>OI|D=-@tyn&ie?8U{hR>locaQARQ`}7$Z$c zC`cKZ@<5E64X~_qutVUWFE)T-B|yRc<5*2$f_ivIBMCclpm3*I{g;vbvj7CTI))-d zn|JhIz`rYIH2FuRnSnb*ogVQI$T~=w%(bjDvz!iV9;0|MY&TvMhX2XP3%J$L6C z)V@w7yhwOvtO_xcPPUnSA8$s+eX@3jQ1GO^`A8Hv9{~ z7KzzTK7CX$bX_dr>?;Oh!#YMdYSsmI2R?^_^mlFyd@T8fT0FJg77(2;{KMT|s8=Rm z{q~Yoy=YCL09Kf)tP|NJ8;zSK~>V%TllKJZg@8vD`vZ=q&nV#WL5 zl}k8hQWr_B-)mIsXp|SfzrYO2MX9A!9ju$?SWV~2(5&XYoif&Dk2{GEd@b64+w=e` zJ6eD0pe7gld!mHr1G9{JakYXPr2eX=-`W>%5=(!fj|yU@gOzkTASFsRNwgzXnxLx3 zkwwqM{Xx*4Wg}#Sq`ZRgxWlKswG(~2Vz==^GHse}pc=J_JpJlvkMI|bSG$e5Orb~> zI{Imy7fVUgEsWEjkC!7>o8HGAz?`V7Vtr7H^Dq(0MR}VU?a~?=qfk`3^QI|-`D#U1 zbL{j1^zC5Bv3R-8N7B7y`G7=dRJM3dw&>My8#Y43yME<^I3GgZAshMXGVcA)R!gz= z6S6M^%P$XO%$w@&j*15!K<_3rDPK_M`@S29y3M4@`b}?rE~#xb)vki)YlFx2WpboQ zS8zCz`mCRid{5pn>) z{hvAzI73Kg151dDj}C?1ecc~(3>1)v2crKJnt&~KJ#_bSodzI>BxFma0hEap`K4k+ z&?<2%fj({lgDc@hT<}`Wi@2`b@<;}XCZH(9R?+MV;tVcrp`qfFG{8q1M=#y3d5W!~ zCD9d0zFQ#@L01CDCke%tIDjpvqCOt{1)3~8_%F}^Z2imb0#+9aG?H!rYyTZ+K;ZJ9 zq6)1Ww*u{p5oVRq>On#LkD_`cqFGN;ye0o}i1d)ofo83*5tFgHXD}$oMJTzC7BQ}W zSRis;Sv%gOhLpWQ9#j_)NiMv-`3krI9C6Pu+L(?7=v@ znLh67o@=(pIe$O++0}AclwnbqES2<;#X~G zHlX0GH)L|;;|-A;D-VGe#Gxo6e*zEFNOumgrTWp;jzWL#8{12`%wlVM!}rbc1q;>P ze4G?@{6IIcr@TPOI@QsuJ4(1K+FWNX<0JNrJllqI#ZA0zF`kruX8QT#2ar6?+rq)3 zIg10WBeh1pru4Vx%Kjo`hf2$>UOp~G7_pvHE$jO(w!<8$9W}dKeNj`JFjlBoA~bX0W|da17$!!rQ@J!>7Tk4h<<>gwG#qPeawBdp@Au2irF7cF|=rf9&t~?+6mFY z9Wjb1%hG}{(qNsl4;>ZjW{qt#nuT^-K9*&8Vhd-ew?a!3Z5+z;4E&h$a})3( zeHZELm40WGZqnT3Ki@Oq={mHPYS^oWH>>?rYAno%=Kg}>KyU$JO?JN$%XqRp@K!=x zKu6J;0%ubZ!%+Ryg>`8EMwo=yU0^}hAr>p9Lmpm@Vamzk@|@w#7`87iysxvpLTmY= z-mY%Ng!T9W&cHc&TZkobFasuu6GxDA%m-htp#xMrfmh7SIVK%a7g zY)|=gJ(=u#FG)3t7i@W!eBl1Ba`Y}2&ta@!^Z`m@MoAIg{&1*up>>OIKXpu&z1?vr zHYXcB0W2@v+hum=JEi58y6uU)2T;rlqlD_A65Rr$+XTm<#kkI`at0g`swg5*HntQU zsxqPR2>?7gxOk{=!on#dKNgq&192cgSK)~MH|78c{)HV-kN(BxAB6s&J(AZFZvGmTq-^y9H}2317B=|~!2BPF1;P_Z-SRz|?d zKEiH*emhPg&JzF_V{R?^Upwjo=QLIpV5dnjSH);1syI)1g zpOgD~e`qGF~uZBnrXR_Nf*C2m*E{%L9K804|EHJHy zDEk7ZpQ4imjMpmN1@ny^TLb(7;^J-sL!cp$S4J&59+a$LcIosY=DFs_P-?4_^_l85 zVHH2NrG-T2#l3TQqPsif@z>_$rw_56UY>{KoZfW{r#|o{*!fDx<#W&U$8#lZ9PfgZ(WYIHoQeW2=pQPD{9CyMWC5p1Nt8 z0_1sJPB%k@6q-yQpF+XB>*mkgCn29R+-=Q4PR$RX_pEG_!Cx9&v&c%gW;#8lw0CIT z*RObIGrMDsG+#DMo|#%5)-bKN-2&n39np5E=~WvUV!?=!vtc+!Y~H)MxnoO&&)5|h z`*qBCEjDkT;zA`h4a^A^(Wy65&F;|b0aQTgV!p~K_eA7M?R2o? z-BVBy^12DXFMN24e6ujTYkk;0ss}yET8zfpK|u2>d&P0S2N0Ue11Q{OQEiDFkt&ck zeI-E=bnHLnk5m7tsW%0?cH@-m$S)Dn!8k?fK4c>&I3u$a0VNmgKk^P;N&dC#z#0ae zjV%hW%758_WDNFQHd{|1s}(A=*8RWRzbJ-I97_j~?M8r2WW>EoUc`l+=p^;ow`t0h ziaqO=dtqh`uZM&EhgjeNo~ePfP+?Kw0m2Stn7+TXQ~uu>2B4e&Ni2U@=5M(5H|c7E ziZ^s?hblMFvB7{gKL3QzDSzeL8sHQ_%uhtPr$E+i>Tgj2BkqU`Yme8~k<$`w$cGoV z!L}mv)d??^T9FXONiNWZ9UYG{lj-R<9kUPW22+>FszXc9+ae|wgRGW5_eRi_^CO;s z)_ccY4P6N$o&3J1W-OdfbV3}HW6lYX3R|~rE_G=4s$!ooIJ%G=# zq%55`l4IuZS@`w<;=jpk zJ*7RTny5Vd7~oS>++kawJ5Yfd!QrcgQqs|0kSxmf2^M|#3Hn_yuGfP7tfdnLI#d67>WuFU2KR4+Cbn`|#^8r+>yRd(jP+7#^V79xu-<)PED28U(Cs=%;Z~Edp zWlw-wa4h1=PZG;K!5*I3~5QkzXsnOjE*orwWky?9ocq*iQUr{;15$>l31vC8 zS&WQqL^}Eh{gp~z#74m&w%`mqbt}3Om4xOmK`At8(Gi-JYjqRPuXvs9@?NvGK z;6du*BSJ3Ycj{m&^&r9J{noh|AI+S68;S+hOmDvu6AzsV37f1gwO;W1{?ONpNqNMu z9cAGQ?mrb{-7)SO`AMSXaH^KoSKNTsiXf*@ng4G+g?>{kYeaotJz`Bmd>w~}wTbh#(GE@th_iN$>O$JZ|>hPIuV&ZvVW1)I&{S=DcYHI<_p z>ADq(DiOHRYq_f%b8Sof`VW?JESOTVR;rou52-M=2M5M%bu;_n%craxAh zt;R}Q<^t$Q>MOlSf)JF*if7>!z5;Q?0n|^y1ky9ZUymZlp_HK)#TQkEM)m;3#r`Y57YO>(i+)V@Mxj$3K2U~Zq(d+awEmMc zTxAp4{4Go#y;C363hGu)zodm({z45uLgIGJ+>l5090qSDbRF&@-?~Y*;kMD? z!})Q_px*CSu95uR6O255X>%Xx?2amjz3?gKyeIUL<-UzB#n*-+Ah7f?4XZ#_aiWfT z@=FFLuC1&47Jpo|X#H1-rN7SaPTQP!9Sbt|&Xs|h4Llw}ps?<%+Fja^#d#y}7b-FcHq??w&Nkp?YdCr_~9$43a z-FTEeazB3m<^1vnYp%o8Tue)k7}Wz=-H_IHtiD3nXkvZRZD(30|LOLnu;~LR>!M0W zs?JuLQ;AD8y=0IvqTZAh2pZnwaCN0{y9~j%EDln{Rd*RJs}}h5@UnmM;6+TO3lH?K zB(NV()@I;m`EupjI6IXmm6xdH>m$4b*~%%l_35b~O-dQp8F737Nhj>WXkXxxD@!FR~wc>8o8tUdL1A105= zT;|^H;>aM)AWN)&`6p2!4;HO`gr2lwLru_X`PzBKAX2W#%WprKveHxdgq>__!wPdS zLUoAKCDIFy931zo*@NNUOa|kEwfA8PS7ZrGfJmg;3Z5CJ253HlgV+EfqGyE3dyU(K z@-eUkNIbJ2lhS`om&$A0NqEVx>Wjb~g)9G?sSxJ_S?N%n@2p@W08Tr9EEHi64ZK{Z zLZPNCclK^gt zcnnV%>uuPe4Sr~0SNAs&l>i8e8jLRoLzVP@;u9h{7|tZw8wQ&r+53b!4Zht62*~j)uY9oTQ>6 zqleXiJX({D4umcj4DWh|Sz)MKbx%|RoA zel20Iy=P%J8C@4VGmS3bIcusEDM5^cu0;LC7?-WNc@0xV;snO)u)N%TczIuMk~0=F z|CiEH2piiK`*{fDJ;>zo6D!wveV(4o7K=QqCO+FoUkGmCgW#%sLc2~H+n_pcI6t};0z#ofU zfBNhPvCbA8XP}>z%UuE@PNP~~;d)BCx&n$|G(6*!`NywfUAXWXAoM_3kQQ6R(%hVi zil)fe_{MCwpDlHF-KS2Ly2E^iyJ#Ib8ytlst^8dzCw-|iTh1DpAKF3u{71r=x*~jH zNMd8J2=n{<$xyS)f~0)7c5sReN zd^GcQ*hy%%lACQJ*z#-W!Y|vRFSVqZJCa!!;Av%hkZni=Spv{20ceRgsDikV99R1>4t7u z_Ga|bQ7z!76_s@>-pm--d01J7ZBb_~iySo#e7dSqO-pDIIME!7EGBO_cmPTIsr(>% z)$)0ME-hr5t>>^Mq&RNAj6R5sv)g23vI+i^ix9hQR&3X*vBI~uiWxm1?h>LYkl2>G zbFcpH&hYaz)i42VFkk5xd~!wQ>BpR5hB~PZN1GSDTUb9)VBPQ~!PT4UrH;tfYmG{l zj(A%>*7PbK>2@=;wR&Zj!c2wR(890#Z_%f&4bKRZ`;{K_m!V!b0Ynz}4|_d& zCup$<6L^ydB)i7Y6V#)>RqkP;v;#JM5y)Y%k+z?dvB z0Fgtb1200+uL_tZF`03cK*@xBtb9CBG_?%0Hau2`;UC3XR1e|@D5>}{amq&(6am5} z)-!VJUC`ht8W(6#8I5NMXoF%`p5M2d=j$Cl8N$9tW8VMN_&H&2dfB816)9n|s%D>7_sQo2MM+bu26gNoO|_kCpbcrxSgXjkBX0GX3KeTmdiWRwuQKu>E?9 z=^2W|Y>W*N$E#G#q1S_0%)BSs+y=O^+Aoi^xwUf<7T3EuaN?pFdCL=7oymuj)6ChW zKDz@$(b4X`kZQbI9p|+g$ybw0UR-Gmc4J1_|bXfMIt@ zpZX&9QF&ceyt|cW;Iz1Devwz_WA19-!n`$cP}F2q6r^){c`)W+W+^hX3^OLEPY1_f;*#4^rgYtkJsTNM;@?fOH8*i}5ed`?ZXoqIU|t_mMZ@p}8F=U-E4* z#NN5aExHdcq7w*7H4FG27x(2G2{^7RL1eP`d{al95nt*2hl0!KR4Mi=gIW?y}e$F*E5PMZM61_&JB)kvit73YgSYE5{DVWTw z+9~=is4tolaq!(0}aqMl#N=}$a`tire@G_K?)u`rtZBt~`Te}|i zKDJEM?&~v?V@5kO?E2(Z&%@}yI%Ob(SrW?B^#vva&z1e)%qng2^nD!%*{hNoM zjk|_!l><`cp03f;lI%R_sbG1iGlG%|;v(dq@{36|ii#TA5o!eLFf;PY z5}^FD=_`0AWXt{mwSTK7LI>Xn&rO^{7T}HueBEXk%B!+mlfD|D6pNtN!<0;^l%kTQ z7exoAfuYVughE!85wJFqc2%deT7SU6H{_=p;Rw2JJRKHwT6AfX_hh}xt>y`%l$yT1^bt<| zF|yXmw>sl3u0hbqEL8UMym*^5$-%nb*S;!u1U;v6glDxo>J{$?7g3E=foIiMH8>>4 zAgyOF%edeg$4ElO)UBI;n0u~7S5>_{OAhVHsIFrup`PHh@+&rb5&E8i^&*h5`&Giz z4SIBNDr`2}YlWAN$a9}M;U8$PQGEOy09hYTEZOBJ19)%4}Ydmi2Dj?O)SEJEz4?(Ta!{nmh zH#K%(Qj?!PsN0kE3eQ@4cT8vMeD%)#I(!@>mWt(V+JbyrWRb6XKx2y(B-NdZ->A&* zU}J9Ct+-yk)qRo{gQcZ6sr<)>+8>Eoe3ewwo~{$)HtBYbn!NUF5(!&m-NQ0Li`8&} z;4MYo_+?fMa(}ihO|lhtdVZD?jHf=3XeRTXYwa4{{dWHckWAb3{%K@MIp;kYq**2+ zhSc)OP#bDym~GZFNz9J5Kedut<9Ra-{WgDEy=hYMZd0e`ca;Ke*XYUEr+R~yY>Rp? zhj3!)cU>^9@Y=)EOZw$#8J;3dM!xzb6#L5$e^11~nLFg=a>F($$D1%)`R9Z*vZ%06 zIQ)Ru57_9-Hp$}5w$EejO~~%N0>TxH$i$UuS_#k}K!;to`YD5xzCIkbJgR%JQq|+S zTe#7wN)g#&c zL14A|CsYEeyA&``#{I8L<%16;y%PV{X(dwF*i-T9VG972IndYK`S*; zWl^A7V+5)-U<6b>K`J3Th%<>Qni>gUGie{F8CnjEIi)h*7J(+@Ih5#hBAui0sX2dW zj7dx?Ed-4VnNFz4evc%;yP>SkoEr@-G`cQM-z-0osZGptgod8T$h$W_Oc@3}9ET+6 z{#BKqV&N0~-(`|{R8}`9GiZ5rTq8<#e2EvNEv7vExS!ViNuoGbXU=*!AnSwGyM^Og zhL#p2jcCu7yadrTs;uTui)j|IyNw-=eeH5Zsj8;^Gx-dE`_h)<#I#1drVb19eqT9u z|LRzx+M2&*&Y^z6kA{Y`mi-GUxXF-8vo*sC;49D5=kMvhTZ`Z;#=5teQK=b6#1 zHQO)i{qhq-cLyHIf)bxIe|aqSGKQw$MdRF;CZWY1e-CIkh_Rox{#{)WEUTh`G)@e! zyQMCz8#!95D?fTzzY)DHGrusn-cpi#**DukcQa*AASE?0uM)2z`wTPQbzawd(qa7_ z>IP&cjps$*Ic?tZ+urioUSD@i^{;#sWnrZ5n^yQH{8A|>Jej}Vj(Yyc<=_sqUu#dX zdahsoreEWJitCex6~mxOIj#Lz_eiVFP$u0Oi@pDPdm47rnu0N${Zs-U(`_J!r=E&b zs4S7*2Wh{lF{%6yWlf1A?lzL_7L{8{g45QxK*D2ovSbmj{=sX^4^KWCL9qJ^kLtm8 z)q%qBhoS|Y$R)WQZCK(8FfiFqfcShf*&rz|--Qyf%q^&G>GS7z1s0{p6Iub(TbKTB z40^xD4QP4}cYoL)(tZwm`qZS!>b>;KAg958m9K*S=7@*zDoO;E)mQh?rR|vqUL%{1 zt-N1rKaY8G6|{f5ajE$B;tF2plk+vEOl2jhjZ35+F|h)lnrc*?)v3_i68#J!-i`tXMihn2hmH|ZN$UN2^KuiAs>fIU4yl6hj^4L9h zEM9z~NjmGXe#fDvm?$yR^#Yek^G=DSv|$}KL$yR~F}2jxIg6`a5h2tj4WCSr2jfto z9W8vtVY8(zE2CAyr8M#|bt~P)^;UrOHR9{wKCD_J48CGTfvn8fb6ewT<)X~==4+dZ zbAI8HaK z1A2R33Nw43HH}?7oqj&$a4=N0s+Z1??3o~jqzs}Z92wbW`$A3!cvSIJK+Py3kph&5#gFU=O#Wm;Jzhd! zG&Pu1?yu8(%&=lkp{+w;cMgr&Q?rSDz(D`d23&ZR&7k*rM45YCV}j!1XM-XWa$-2| zNoK^h^B~#Gmr>0Wc5G$$7rz`T*6deli3f1zZ~gD#Jso@!32wP6b!~iTmYbVW=r(Fw zGY`ESUOx|$5S5L26+CNxG)sy1HQZ`SWt!=lWX{8nht^us%fN5gfM$D|wymX6{tB4h z>^6m9!_Z0~Qa&|2IZKQ>_4Z>>4`8l|Z1p&A)W3}sj*wH8)xG6ix^DIHj+wRAovx~o zZahuscZDH*`U*XW_;h|+w^v$GWDX0%A}ZUfpJ2b7+gkf&)6@^e_8$b8K5Q99D?gQj=A$qS zm}?}hd9;YZ%AIikw1Ui5&xpEZq@+$bqMZQoUR|;Oz}Gqm<+r)X#?M{jE_l?_;iyV` zwJu4frn3_Yqh9!eE~#ll(YQnxC+@LQJ+v=j9y|&$6E-U`rB&z^BqxsEhmGwAUE~nGZ=@Gv=JEWYDWl@JOxZ9+bxlbR z{^kbxs%)r|U1_0nUCkOv$`&utMJLsA=SaDd%`UC1u?ruVBAIuXWrf4x)`(xK zt82h6daF=+%}|M<3^U2R>hZA_)zwLQ;vm(er<22=i|;OkFLMzMFLd*8b*h5XmLT$o z=cJ&`USJSa?z_mwF&_$qBjLMV6qelH;C7JLuyrm)Y(t}H5Zh40XP)G`GG(P@13;wm~ z8oSn&FWjZ@=-Kmmzgt{fd+I^G^t7eKTkGbnHX}hs9gokyr|KEHYun%Jl|RpgEUn9E zy2xB#u^Cd~gAz|KGGi3%SC6bU!)={=C1F7` z@m&MhLb+VVV z2LYG=N6H6uF7SA$df=I1qZPis9$)D}llcU^jVSWS_>VO`BStgcnvy2;u78hr0u57W z1PHtY!MzN;8xKryv!`&dqzzD;>DX)sF(yNM5?T~UHC~U54p2MQ#J4!#h8`8{x}f)P(Sl5crs(mG2aTauQR$l!rAqW zdYtK7zhNY%X}A%d^+vOFA5Gviiww z@gU9Gdf-;TsCi3Rqx|%XUcLGvX`TZ^YyV30cg#g2nfOjhXLMEKw`9!73E7sAQztYJ zYDE@ZRUIXsWnkFtyy#lf-p#rZ&oNCv?F|IsRV7_xZAdvsm+K|9o)cWP3 z$=BX(9G-~)lRb<&Sm1M|iTFyTAUXztJb|}3(1xfO;fVgG`E8zyOI~8Y;c}E}s_wF~ zLM^$w){h~Mj{y^De|v0ix986SMdZlfLiQ9TDTyIB!oH27I5uMIa6ICyc`DB@3j#8Lt%3kB3q zOL&T!i!>}EqciRxbCdYi$kDHyStfAJ2c48c;ifAj3TVcwn`Jj43X7?Dvo}+U)VpSV zRct5PyeXxj;UbGlMZ*aU>k&88=^Z;A7aG1kQAdlbaK1r*x0eUhOy!nVaPJy)*OZh^`HD0E@G!ujxk-S9egB zB_m6|@oeSVjEu@CnIEid8_3L`@t9%n_QQlI|Kx>@xYHsrz1DQ6Yf&8-*qPBV{eV@M zpPxu(ZOdSy0NqjJ5zF#WqPBy?^V90hV^{(OpWGK)~bazyb5KFu2o{70s zAEmX1Xxg{X-sal%vr@oJ{@tvf#2po8^RGy`^6JDPwb1+4fFhH2!q@8wS z*!}qSdF^LZtFS{r@MY8O4>9VOoyTUhU%-R+DRu62i<>rd7E<;^UI?db{qeqUE} zt`@yE*9D%2Tt0AzSkv}O5O3U@DAK;-obUpjW?Ab_#Q-(>Dd3$5HlL%J)KOcvx$U9+ zA?DQlZhOHd?DCXR^0-P?Y4ZF_+F=0?X?F`6PWo|gN?R|Ni7MaZ)g>DZO>4t@p>|(P zH?$dN$-kjYnY4)>1rZ?Hn{kK;0nym@Fr475si7!56 zkxMK)EGUcysoU&Bf(1Ph6+L`V7&i*$>!``aj}er3@p0;$Fx6l&M&O-zF=+Ubp9t?i z+0-0`rK3NvMF(wCF*4%8Y12st1^u}IxaNOu`Eg$hy1zRYbazH8^n|fmJ7)vA4}4Hi zFEn#5eH{6LX3o&J5RinqfKh4SHTqItQNU=($p9mumIjZ zsCN^ejiiM%0AoKklSnR;K~za*?8J2v@zf?J}Q~GX!k87~<{F>ggjD%F<@zND+XuNOyO4OE=Tp z6v9X>95{QrwHbkrS~2WQL-th+#)P20AFR=QP9E7Mv`1YPXBkj@-o?+jq_iXp)rt;F z&`J4u^{K`F7tkr=&#&#;J45y7=)Ya3Zy8>8JQ!9+CcJ&a3C6R?NcRC^2R4{Us7{xb zx{V&{vBl%u3Uo~F}E0=R3$udkiH+<0g6+OdCxAAYaR{G#~^tU8tkyIkYee` zTkk^z*lGD#;;i0^=|~ZB)#(=5efs={J={`de5s5kRCJ(lHNOH64N8dl8d z>2LSfDv;W+IiruRBjXn0 z%ixJolFh*9)dv$CN~OksIqgEK*(_g0&# zUaVxLt3bUeQBTtK1_85WuriMz&I?My>MJAk_aDxAzyXr|9V$D&7rc=Uo{cqFNy%z|D+1nR0MtKIDQl*!J8We2Kt3K^ZA{lm>| zpO#A+>wRZjTjpe$(gmjg-SOYsF%agT(FguZ17G;UKg$YazZ}5_o0W*t_IXuS)H!GR0X@9>YCr&oa9=cd77fMZ!%9%-s{(>!YqAxg;XUWO{nh~ig=$;*;OA@ zhKfqjN;Q#~|5UPRA-&*R$PmQ(fmZbg%MgTtRh2J-I+GnWw@H{yEuSp0CCKMt9 zoA_2>Q!RvF{&@mI1j>xG(7k3vKRug6lYlg;D5HpSTxIo6HGT9@eszcjCZJHV=a&VO z4Fbuv2r9rK3SbCXOzs&FNe!VZktdfF5_xup0*LWN6d=lYmzFm)!?Y%P=nD$avwC+V$W2 zzAwT}-!TM`OwFXLSLX>^+-I~+wHqTk$%&tU2TORlYu~DuzvzhRsyhwf7HZsZH^P)N z#1`qC3Fqyp;UJ6bR4!i=(v`Z$@>bpUDLb@b z;jT^|6Et1!uGP|$dE-4aoUPMO6~C`=C4x10*@w!@K)QQ#?=zh)!TqQ*i;&6rAI_6>8M%s#jmhla?aWQKS0mBKsl&*H6eqJAje_9hDWkt*1DAlhdr4KF(Cq zB&7;`NJauqR$ptdf9%QbOB)*9*aAu^7(+&WtVrGz4up(!fwwX}j750yJd4mSl(#>c znrd9W{djrJI|w~H2$OLx*tf5q+qbL7X>U3W9eylCl_ufRMxDbb4~`A3kr^Vy+DbU4Dc_2}bQL-8`Q<)C2eosEaLZ;2@L=5!8*S*7f_ z2m>Lak^E~?%FhjcuQA4u8+(K}r4;g~>%r@Is&X8mJL|JjP1PKA%>JKZkm(bKySH?! z<~M{C5nubsDxc$$5~iDtMHZj?zH5(y!(A^3P2Xg!kP9LL*Q32YT>GdapspR}&Ohj) zyO!K1|Jz%r@bEiA)K@%0ZY`qiEr`trH+P`#db=#W^oWg#Mb%>KPEX_^XT7joVM zLyBC-vbA>YE273|gOA3pQ2fCARxnV`p;aJ>qUM@rodU7~qwm63*Y+bZEW$=t&W@ljP$`b|iU_U|PC?}f0osbx5 zTjOk1giQVGId&h>8yz074z9*MVQ5^uW@1#4ZH1-GXxN-JGl?>71iIE8O2Zfb6SC`{ z(RwW5AxbO>xOQuSnyooXjM$0ovvLSe2}O!OMEI6h4xKNn&vbP^QC)s*e{1V)-e_F! zhAV--7^I@_1&b$#v3W9^vfo>2h`0LY7qRi~RfHxC3-OJE=~71uW> zgGcr(y^4N|2_3Yp~@&#Pf6gX=fp%D;>NQ`tDusTO@#gT7 zGQbHAuvZm;!~bL4#99bhUI&hnkmx_I|9)TuP=;l%WyCN7bcmaOX%SI0!!UUNJov-A z0**CBz;F_I1u_OaCvL!54vX@u{JS|7iQcp?!kf%2Lx7D|d^OOM42nke$yYh7ga6{p z($J@0bQ622JzPqR>9$au#(#(5d?L?LR+6o~ugTGwF??H8Hziw6*R&h0wX#t{P{xWS z785f|?L~N7DsHoB$!Tt^4SD$GnZ^nHKmQmH9e&HX@iegNP+QIUbg-y-w-myo-Ij1F zXNs4Cn=2h33t9KwkqA(f{m1|khER1l>}cAa&Y7I_*DAGwuaYFkGLe1d5TL3rEr9h!7@{0HT4T??wMlE~JX=&S z-@ua)XTewJ?SbDaJgB@dsYRWK9QNW!%#+tIKyin(o4ZKRL{;gUUeqx=Ud1gPkNfj> zg4m+a^0_%@#p(xYVjNW7J8bR3rMW=*-W*PnjXZ>ChieD#|8*flXj9O3qAo{rkrPhLS;<{@+kY~kWyyoxl>xr6 zJuqTNh3{)neg_-^k&kUt=tvsY&6*nb00F`Nr3}xx=#6m#*BB^iy$=RrH%A#&(s74f zNytzAYdO?dGh0>anwpVkIlRa|uclYrAJ!}<_O=Q~+a9j!13a_+c4|Ionys_H$XM>3 zDsv$D2zN%Sc8swnR3pS>F{R68-=(s{+4h7bQe}&>(>YN7EawGjq|_^ZWCaoAO$8}T zH7yTsnc~})%RIaS)AsVQy|+;*vFu3~6|uRVnT<8D<93c`_I1GNi!tBKLI> zMvHKUOMMeF0wvb>poT{gCB+t)qhT;YprK z@r!kmgA!&%V~&vyJy{t%L~4D&{Bl5tOVl5bAJ8clnlt>^{!;H;#r<98R{0^Xq0zCm zZqI9f&%)*yHqAkt`s zQEx;R>zXRP#b#zE`sfGAd)c>0KWEU(QB%6`j!5*_xuYO6t~jqUlr<6|ThkiZ1V)v4 z4Vx4dO6O|(9BgbZDr1ztS%`mO$Cn1opa)sKJdGGd%Y6B>raGODj%e+OzTFPOyA%tG zuh8x{FJLaFRrj?V_GTSi#H9g0q16i_zfJ}=fm^8AaASh1J zMv|ZSw{u-0S3_|BuozQGZM}{yG;*}AE@NrjnW2xpwemZ?9($zWx0cq*-D3u}>L#(F z7Ln?zq*+FXpN&byWeUyhW5+H&M8Ynr9`5x|ZWuQiU*BjA8hYBiiG&Hyf3HRgEBGnK z|AxFMOI5)&jHA-cO;XeT0slA_+UZR+6MbDbGs}V8sE$r9iH9rx`qX1X=mBnw6wQ6! ztu`dbQlm^yX}1;V%k)@WW*yZL$)F5Z@W%!{7uUr10kQipz;nGmfG-A>|9Zq1W~3}% zsA^!5#>5W(4?qB;0suW>KxzyyGm0`Z8-^4$aw02346=XF{TIFfX!TzZ0|LaA|BEbv zofabL-ZI1AZ+(b!vYBnNqQK35ye-KXJz{zF(iT}6!v*Q5U}_Q zDvEzyjDK+j;FRE90YHgneR__N0Z&^N_u)-#@z}YX6Y6{8Bc@TytRG{gFj9<#5I}~J zREDdM-=+17BN42|x!mhkcK(1SR#jUm$LdD*>Q+;IPL!rj*e_7SC|PNx z-A8=t5grJ`Zz*;u`ldR#c{6$vEyOS+)wg&Oj-*>P=SziK!dUxCMuYj}C{`~?W{=Q9 z=Yanug%T|S{HPC{iv`MwQ-HucvC?ssRM3L6GQm{(Nj3>{c2Nb5u2@~J9MoB3KBR9g#J^@EdL+EYD2#xkZpMK z6LdGWE)!sX&3Hyij6HpXEXI&b`y&IV$U>sAXnUY9g@Q|5!r5I)zc=I3kLZ-P6t%Tv zD)^}VpM~D>N-1|wuM^EXV-Kfn21TY_UKUw5o_wFYa%bGyevuVWW_ZI@k4G61$531W z&j6eI1($VOwvGlyF^;>wZ~o`z{z%@!xFaLJKvvGuLMLC{&Zb5q6Z@TU zW&4i7Rz@<{*--|zx>Q08KNu;d%aVNBx9%$V`ciYN&Y>)mF#yvc^CRR12za_@)2F4} zN<*tPZ<;^Q)vV61SY9UhpeaC-ezMspv`izk9BtvDT5oD;ZO`--2O>=987mgvyF`<@ zOM2Bs%lyL*cXKL7(_#sz!wN#c4$7b0?aXXvZYj!0TD8DOO)(6m4m(31g^w)#7|1Lt zw6Ro`!AFNnMEEsgPJq6%5egC zHeuB1MWhr=nvVHSMXKU;e?SJ-ITiH^%~RmJ4a-H@ceVu5Km5>k5JtrJl|^17#ny@& zS*!H|K8{Q5Z67u6o8vI+nwod=%o~fdKeqZDTW2I&Tl&Sny=`Z7fT% zIAf>R@l_UEAa$*mSfI08sE7)xwQ6%ZSK_9q&|}dpm${;R31(wm>RFZO$JLj7`eD+9 zYo=>2qo))bT4Yw2(RcC$xo`B{e>$#P^1umS$W{lqE>mYK(bgXRM*O$R26#9^4gE(w z&;U}HB0l7mNY3huxxL9_T5u)nmCEBe&>T7G{8Q3$En(1as)`&&=wERpQUZ~ zE{;0yJ+PrLvfVah*pdXRCp!PwbDrl8d^Ifb=6Pa3#<);w_l^T%o!{7ic`EQBg-{(IvQcO`KdE#4^9)MZ`%6`XElk%Qj?~MP;DD|rH2ERq& zKp6OIBv>p!i{MaEutl757YUf^6OiKr=%bB1Y?k^njqH4}=;=ZXBLRyo15x0Ll`-(y z_$2cT6ZmyNZ%ckz2yzHrDbR}z#AQ;R9q&MHrV7A|XaAFE^caQ_;D17q0081IgY;J| zj|W8off@e4AwKz6C&1A09ho1<@d5HVP|%_We zj}BZm81hEEpCt}fa4EZdD)@laBdu=QIjgC{`7`pkHBDI*R7z*T0xfTeBk?;~MP26U z4P(V=Bn6|**>0qYw4G!3ZGy4`D^{)LOb?F@`&vT1YW-p&Z{m0deW(iMO3KQ;=f$?6 z_M)fu_zk>VgVnF2-J}|e>aMXR%^J6X28vt9m-0i625oEbTl$89{oy(8hd!-70S!rV z2%7yGWvzS}dCi|V?u}FFrRhSc%+;H5NMD>hzPNqxN?FOz3iPk*`L=Y}ujlA&Gt5gb zdiC}!Dy30bMhBZmhL>FvEcfZACqBEk;hod#!Xqj?jR9gxU(Jlu$i3}*KfE%U>ZS%e zP0m+KKi26)jx##o5k6mTRz|a=MOZ}iH>~t@k>)_lK1^NjR6BYsBt*}YkcYsJRe#R4 zJ5mmWgO3)z`N9?1cb217t>gPZe&z88lx|}^e*8Aj0>!KbhzibCTk7U{tQX(g=ieLp zVsflbm|BKe+A}pUP`ugpci^wqe{*grc@4IG^07R(WnL<9IVm~y;z!kR&N-CFnR0G` zytl{i3LhoM{NYH23Y44@O7_8lEsh4_CcJ$E&}!CIYVLoh{zm$_s8E$c2mPJ!ripa( zIH~F_DXc(7?_%*jk6pRc^=x2ZXx!e&>|OjZk0cW(I6Wf=P7ZBD6DQKG0fKCl^PX<= zfYCvcP~as)vgm^St?lJv!Jf^u+P88BZ`Z@6{p)jSzBJj<)agFEvaHo^7;nMYHPcr=Z^3lcw1c23~eHz@9mbDlfLYRF_!U?e_AxS|}SQmch+ur_xV^VO_W zeY>>fIKg}LPfwfqh)hg&5+ zZq0uSe$u>vY=W3Zlpl)k1tM#z1=wO3Mf4(IW}==ntG>ePB6%8 zG(`{JqH-HjHx3?F`}hYGqDx&jp}Br+*c^vm{V5c0LhvdcHLdc_J>U2J2%CNG(G6RE zfsQUOepZDmbshhMJ4I+;8sfGpVW21dcf!qIc5E}2TvMT8@uAzoxw+XHPrjnw4ap6c zJ-eoQqkL5z#d3&7yKqH_kx{US;-mNehQxwe6*>iCZ(246&RQdMdd5B)Ycw}1-Ew108K=FPu)W>iMIn~p`Ed041I9D2uPCH6F=#OU8`mE zjBc(T?XD)Ju_0(pVXgI+wsNB+GA_;y7B4^$`VXPclL=+G^7F9r7mHG&4gSkx3*@cX zWPU(cg#H)){DVc$`u7Jzz^#QJgs-jL`$oy$uH!*T*v8;*OrhfM)C2r_?;gN^`vvH^ z_)pL(6AaX80xKBE;IA~W`m9SRRmd9ARMMpSsz|_ABIJD*dq9cp^ORza2AFVJDTA5- z2W~Fd3MjP&5(?x4mgLXaLzw?1j0{-1000p_kjw;bir^(t0L1wl(=-Bu0Ou_bR{$oI zf6Q82&mj+zu4+eWw`3auhoq#_uN#RT&Qyf!o43r=7n1 z%xe)!y>Yo~)0?loq7L0|IYqVi6znGTCTsROMQT}1KyydPxx6^T<&iPvG}|cl70$`A zT3mju7-VPN+V6^e9NzC~{;sCn9_uW6LnS6xh>-OhWgH%vaHA3XfhW#Zp}$?ay>com zs%+K;B0Vx#jv`)*(wTc`C+$dmpkuHt)ly$wfEZT%uAxJu8B1Z@YQ5QpUe;17kZK~) z_0|6MVPMad6;BcIz2o$6kIlxMFuT43sDbx9sWDLfp0u1;h2VA({<$r7jvEhqvN+wT z>U0_0-d^s%Xqfq0p*;%g`ug&G)qZ=*IlZoOb^m>8HU(s33y&JY>tMGsw)Z3-xzt#- zo)rGMV^>(EVq}2FXItu?n;);NT7myGHl8IF-8sT^&4`%?6u77>$Ts~7RUNtL2r*FX4uo$_tU#u1J4&O z_WZVg54uqslw*c-){|1kF%n#`uEE`X*i13o+*EsN;DcKC-wL#ZmFUxm@gGa9yz{Zt znbkGvv6XiTY^|;N-LRk&nO^Qg+tL)>%GyiGERMdN{#m%e3UU^X(VtjVKS*-gGOQQ0 z3BB1+tT3;Q5hNMavi`A~3K?~h#)=94mJoQr;7(Id?kSHQ+Kz}ZhpnG$tTDz7N2Xbr z$8+`l%AH{P?(|ga-DOiQ?Ra5A^2EHGy%)h|R^6fl`}_Xa6flD+)usoddV==?mPLrv zr443|y9jR!e?h;0aACe`Fh!Taf?Kxr4C7)hy7cReHSQH@K~AHGuva=!U>(rdwD7c+ zTCEpz^F`>DwZ3!kURr0jd>Ql!b8*F!6NRWtAK^0wT(4*#o;&gvg`kfHwP)ZQKAtr9 ztAVHPTMx`gvX1k`-A!AEmw`@P&Zg+y*x_}-Hyi`&S}S5}_~-|MJH?Epa1Rzjf@(Ap z3x$Scvi9*!hdqBltUzs@ESu&@@3P0e)|TeZ%;ln%dbx3P@CO!p$Xle`Ga5XD_dbyK zo}((WC7}WI7Ww<<+)fn}C7dXkA?=Gw<{mBAVJMfV??7fOq(fi)9CCKQ`*xJ5s5fi; z`n)WyX5F@1#LxOWonrZ#fi>XRF;-GpUd<{%rZvK}xV<`{XX5LwdM`Tbt6U4ZlJEO9 z?xwD#9Cas_mR?~@gTUKLm_dk%yXDq_OS5*hQv#(OL4CU_+m=Z|Zy!gM&QyC?j+uqy z-|SQ}(>9*MFlGL`uOl@)EH<;S&(6+clw2y)o% ztNN7nmG{0mO7}E0TT|p%(iRtkCNjQdYb$f6_77rs#W-gb`V6_A_1Fl*r|<%t*zVw7zN;U{qnS@&Q*7&`1sZ7hc-Y;0YDmVECSbctQAY5Y0oxLAk zeK-8{=?^G2SkvSlz3f`G`&)oDk#c5Kx6DnCFTcTQk_zC;0bT-BP5_q9yLTO09IP4# zXN#SDj^^@g^dGL!%#oA$WIajiGaLIyojZFze@5gMz2Hsa(-Ft*D3e~QH%kqbIVtM} zFI}HW7mgGL7e{v>RsPH_ejza~22z0$A_6f4=%&Sw%6uzF)Z8wg9hE!&O}%t(O;o4+D8n0{wYE%Ft8dlbtoEwvh*Ao(fVkCPk-ihU1}68TId% z9YSU4;R?jV5a1x|m3JC)QCuCDMDemmfe@Ua!?6j&dQXvUW&|avpfGz%j+zBA84Eo>ytBV>GK8ASquhOUIUh4l= z?6FBZuwd;(|H}UVR(<|2yZ8JZzzXmh_eW8~6xYP25}}MtcPGNJ%!?t#u7GD}^FxF# zrJwL)UwcA$eVcyV+(CY7K$y+v{G{znx_)|*sVhYw%NGTvcun#y`3QkbPB)rdbnyPw~xz%#;ZqDQ=KDB^`@MT zQ$LqMBU*?2Ca%xBhi=~E!M!BQ(JR!)L___AAktUDw=pfAS8wh-dTx{@>ss*E^Cb03$0f4xyTW~yaKS3CVHGCCgv-3qPy z!RwBOm>!WS8jJ9&wmT<4fyQp-*=9|K+nkSZTBb(L?37q|grSrbm@U3jZOoKU*x)sj zfk?jbtTOcrAtY6_>#ZY#^`vxK-CC{RRig%zKG?%W^O(YAcQj7^WSpoPznb|2VscewswD{>cAhO1MFGApU;V4h!YSo)Vxn}O^5?5!o55L*(&K}4| z_n(qEmZ!YuFVEQ9Hk)*+Vmg1os6=~u#YYNP!bJ)yRR-o4aT1tsom{?$Dk$IPUR|j2 zC+>}w)jybE1(aQO3BCV#A77*Q@QcAf6;dr~-fhn*P}Z$tLwfRc%#uYSj7}CssgssK)v$AyvXHS*CsoD^z}rJjE0h ztb~Ncpn>kQ!X+w#m4|)bq~p4+Y4#AO<2Q=+wP+`NkY&60l#3@qehor$s^*)Mj=^G=){5kK$GO0iF`jt=S&HE0FJ)LiAbnOzekSn3qi%SKSu zMzlC;9l-A4?$Tx}^(bqw;)T5KtsrR8pHboc0QPXui^8P%V!oi@qi2}PdhjqV=(VUd zYHMza7q3Ss)0t*}tth5vFG#n$q7cdLZKDsT!mlq3YaQ&uC!IcFYozYiv;ZF(#j_52i>BL(zr}G7D{!i>TLR zvq^vTK`O;X`)PEiruNz+yED%QE8&B&D@qqzIs8xz$p$wH1ZmqoU<=h#72bK-xzIp6 zPC4Pwm$>d~ZbzjvcWdMJczt%!vEg2DA1CZUr7Xv>*j9#9I83hIGugN;*&ssU1LM$; z9S8)G6GCcop29IvBjio!rMY4gt5|3bJ(P~p^t)sHg+HSKm1_weSd!pl>qQyg4##|< zq}W2x`pEtJwP6rsyu5yD%(ttFuVS=7ytpk3rl#IalQ+oHtdqs?mB=Lo>PR2`ma3n2 zsFCR-gHrL*lBSkrw{P1Y5S6i%QXaO9BxhS1$=&gVy)}o8fALRSC#{k}jzq}!uqX9s z;?b9Q7pJdqdw57^EKvfwds_lCGvCeY`G)?KrmTHLuVo5ys}DrcbJUdp?24>xW`@2* z-XEg{yFU{T<>r;Pi76iAA6s9rCp7y?j$egI)SOP}NVEDgj=Zia+7bV;2Wtl!K}b{m zjf8c2F7;Y%R#z-tGoFEZ=kgu)H23;H)z(NblwSYrN&0t-Jm9E+!F#T}{%?vD7T6^S z6G{D_exbkdq5lq#{`)!%SSXmk(Zdz0ZQYU zHmL%}mnx~3=&W_(jWjQ@cLcZ3oJqV^)a_KK@7o9$>Z!WRWtjVaDoA~^<%x3jq`jl+ zg}CnA(h#U#0sSur_-xkc&6J*=!Y<6$_-5B1kL(kZXHggkX$LX??q+p=)TJ(?w;ulG z@#!UIBTY;@kDGX4pEr2;Sk1{jdo#V) zUS}%pF|w*La87&utf>rIi-vw@!}eBHtV?9>1c_(ZxJEqX+qyB5gjGGGJB7=gAwVGG zEuAKqIBfT_Qf;>8)+XC1;r)-_hq9^muHsTv5u)Z4dc>`5$Jd*CF*X{<$G=YCIcAR^ zHP)1M6~zdWoJMIIAS_XKboa9Su)PK}{&8BX(!bSoX_69N1~6KAA764jrTO%y`p>*x z4AbFRzuISSCWw%7gpbjDAB^na3Q^%kRgNd(V10!^UbtaS+XE(O(&iIzJ!Q)}Pe97^=Oi$Fy|L3I*x2=rCWre|w74t`E} z9MstJ;*57Ruc@a|AX#8xX-py|GCUe|jH|#@6Y8A^|0eC5?QvIHZ0x~%m2`=QLFdag z_ahmqmw7~)vms6vOW=>3!-!xWAl7q(QlfQ$GhY48DbxnZC@6ugE80GTA!cpO6f8!A zB8QD!t=ke-aT~I}or1hZu&A-3o1xo_o%?cuv%%Ls1G8@##MQVT=ZA~2IsvmG0<}9+ zED5S{;c;{OS#6b`WsBmeQ=_%pp24lqz>~AijZFB3r`K0-vT3(P`NT8z>}Ss+!PJsx z#0NO}K4YW%ERioC;KL)MyfNmuNc~_+O@o~&5l^iLIRj=jY{uMngYvb1V|o>W8Ze1E*GQeO!9WpK)} zC8u-KAaO7-+{%%x^aI= zKG+7%mb4b=q!~S3eKvmF4WH_G#6G^m5o%jbiP(~PF_V}tP2i-k&RFp9M!m(vdg7W@ zoukfnsoauhs_nqS-dt0(whPIR0_B@@kZydBxXigk2Y)6vb$}AnaqsMb?mnk2swTc; z>rD`=o}#MUd)O>v`9ExJbuXYn>pYd zqLH@;%8vSmX(%%IIqdAIQKeN|MG?$CxSbR%D)z~GjM#Se?)7PccQSKVh-?*>NDo*U z9IxMfln}_EML^h*LhYRn{~B$_;*75x=OA-;P^AmDUZG%=OrW61vI4{F%2K+Kuk~t;~k>HQQKcB*={y z7h3n_bNMR*`L;|RGL{ONb}QO_At*x&Eo94gJqD)k4wmxZJSkLq1=lOza0>qL(yWp3Tg|l&kF3@!oX;SGVx0G$N2*tdBoZlF z-nuK&++@)o4@nVFAg}l&H~o0G!+q1t#*T-G+>I6MQz~17kN9kex$_9_*ne_HnoXEd zYEZ<8Fwphsd%|OEsR4aNP7a#p^T|b||3BynbAt-VionjM3&n5(%vFoNqRJ{yU{PpN z6qrgTmO~Y?dO_7e=9dBfz9Oky48rV+6KhuJCNxUx-gx zSL5siS*wedEepx!@sDI7<1pFHTu1lfSw^?SNqltBt|u(x&qA^IXzcz~Psy9bgI$D?XQzW|?~aM8qo|O2wLn_lsmPkR^P3 z=`y=!SBZf~dEX>rplxlO`SP%lk@D+MU$+}QM3(*lNyRqa%5tMhzRuOM*&~ifXUYMZ zlp~yjx9E~$Qfcm*r&mNeKnd?O4tZZ%uy*Nt(#KUUK5v0-HV{5baCPMFGc$@b4n_F6 z?3wTyC96oIWx|ZN=X!=lHMlS+_UyDHS;K)9ty||02v4}Y8*%^S2ApVaVD`uw*|us> z?Oi7d{n6O6q~=gQ`;{mY8JpsO@*J)Tbm}1XioD{92$@$_akq1~_qSR9MkQ|CL=>|i zGqI0k%4?zx1d{XQ7tS-_LOVel7;8$=&yNs=zL@;d4+;WR=hVRnfzvGW`8#U!3%9rKY*ge26Ni@geG@1?3rNZfxsre>F+>M$Le%}z2$dRr!{?)KffE~p|NDb zm#4ise`$v%R+l5r{;sYkyksjw=jMV)gXuW=4+v);H^i?_-D?-Oib4Agh=H6q(@Uc7eU8l`T(ZU&6v8ncb*>RzqV1D zzYdN;;Lr{{giko+H>CXih4O0In1@w{wv6~CR!NW4g_l&oubpw|>Y_Nr5rS6J2uD)% zLvRr+W@!8)--0A)in%MHj==(#_BwhCQx*me4sXv%fPv|gHBlJO;CMa%gRTtiD(r+}=v3pKLtyc>q>JK~@ zq$L!kKRcELryCfz_(|k8P(~Be#)qg6oZf51KV}G6(l=Phr*D+CK+ok44CUTx%HL*= z0JKWzqOE7Tr9#ZwBJ4DkN%Ci^-$~KCuOZzPte`=hJ)?{R!$6ru-Bw>?hi<9au@(>S z>g%5S$&um*Kg+MkU#V;B>K~a=B|9BV9U>d(2L|jjI*n+=5x#V8sJSP%qqGa^&15hT z=%GH;#owLW-V<3$j9<1Q$OTD_9~sotes#;W4@WzYgUI!BQ(jA!9rM`b5k{+u<2%Mn zn#49!VQ54T$@{~bd<%JQM2LzJ{sdU{o@bW7`*{An1Pg{us`~A0|La1t7+v?Ew&++a z3tgeI-wqqlE`5j{$UumNCSE(PZ0Pv+e2J}$K%WJ^pVr)ujhUaLOLXv5i!q_tl#x{$ zA>7=IUDZa9C&b0GMf4N1WeDTE%z1?Tv}0lQ+A=p~#F^UnYUTa4;O1t@a?BOH)wy^h zgrNGR;I__(V`hv>s z<=S@#KK4YdNh6}Os^cTEnhf$N7LVMX3ZHe`2%-3IF7#j5KxZqm{dZ*i|G|^~kJlkA z@tlblzL%vHc>@evU2gyz{35!SswjXT#r@bEWNp&`lo)DYbFh$=V6sq1Sj+(%rNNrP zz|~%~SWNL;AYfUkBn=~bw#$o51GYv?B@OgvD+;9`^xxp|JaM5Q0>c)-fdYHE#vlL( z8bOu?jA4@aBEruT*w*s|1~?f1_Lu=P*IzT^bCucPSWI9RjI}A#Q9f-3?$1a$%8OhU zvGxOZ!fziSFV(+75QaaimeO{NoK&R5%?V!l zV-Hfaq-jXSh8MF!P;tM;?ppZXTd>3zb<~c2^x*M*(nDWQ$=!TAsH*&qb7f}cl1P}_ zsZr29=GGD?Dc;iE{pYzv04gqScu054Ia4qFtJS;(E-&XQj=cUW+s47JYZnUG45yTx z+TUqnCS>9jSVLBihP8**f2iMQOF<0qR40x0f79}V#%vej(Cl|?Hgl;6Kj{ru*uO*6NlkL=GcNCGtg2=_d+oWSUu~gmYkILKC<4~ zEpPXUcbUbJzt|TQiP7!I-Yk~CcJ4${4_Rc88Wf+6xZfNsbCsEi@~W@H{5%yYvYtp9 zFF1>Bj69W>Ld6v#mOV(3W0nE^g%USz`QWpuJW*C=weWf!d~!-e8J@#X#Q&ur1es-w zpS4Kmpty|4HT2qL{P3n-S1f|A6aC!W+1o?)H)hR4N12@M_X7{_fQTKa+v|hbx00}0 z`3kQhq#3PNH6ePb?<0ihVZg&(QnjY;p5_<8GQ!U)NDSiTyn=~n*QslRG`}wg52fO;gu5jB{*Xej-UE|M=+}x^fAsxPa#&F0l{ym8T-B zYV9mBNvuN#ti5Y%OVdZ`llc;lUy4mldkHD3M3i=IkJjC`7KtZiXmauZPVs#(QtiaV%u-FSsH)!#aT_BmpEs7x>^-AX;ldrrH`Lj zInlKOCGWK;_Vrmi$F297KC!5On`~kCvQnjJYK|@;cmR`qtL%NV1sCqu>c<0sX5F?7 z`zCcu1n!i*g~F$Kjl-tyA`Qcqng&p`qTP68`=x{+cIl~dZjH&2r!>af^0_9FLzgpu zA@6$P#P4B}D-$Au4g<2+Cttm=l!~8CYlLDnf z&O@Et!;F2$q`wTin!p%Tf&D3Xvd@N!MN%Nk94UJP%>035l8b_bgaTZR?X4Y?yIdog zVm)BWqqX>2wXWH^?xN%Z1F6;F~%I*!Dzt5&~I4wB0mStL+8CzOaLuYZcyWU0xGHUok@I*=+ zm{w(R`=yWqxc1lA$_p|_Lq^<;@(-pG+60&v?r>V0v+pe%YnypxdS((lyb>!PZtOGy z*3zQrq_R}Gw$y1EV#9A?8*N(l24v^UewEi}>REe?Wl6Q@mnRI2W+pPXIK>=t{J37nF&cp=)f*R8N+dX z;?Pb;iaCX?ZKY?P_Od`SRYOIx9x`4Snw4qRcyF%=|Be5|k<^poS&|(F6Z9mVrpp(Iy1GH zBWA2`z-mY1NrfPXmUi+x+)I+W?F-jfx;nVZ?KJJ~c;wNe0=XOTxwpH6$U??gRYQHC zj?|4-UBb=^T>@`va9F$(YJ30OhO+ z!vDV+P29h&>i_R`S|oOd-NfG|!L%Kfj6Mv{V5=CKitY)fvJR%MrnmYa2&OHnEa1Y1 zFc`UltrXzh@u8ulp*v8Cz-OF|25`0y;5;qJo(DM62(l6dz!@s>Y{04dD=LNnZXAHl z{O2a(pPPxlKLKtifR~-iV`Ko0NzWY=z!I%z|L5mtFAnet|BG=UD%&CPW<&jwhe_se z!p~*g0hQF3>lH$u!=2KLMlS>xT5fELro#2>9eRM&up3TprdF5}$IJMeNk7?oyNO4P=9s>B` zWgROU3p>t_9M&=0EFqF6Ari!EKYl27(QbVh{fIPH6690>(Nnpblu@}^vz_STsZfd{ zLAagOVP6cf_xl6VKRV8_&09KlbGGic8wLM@QXRD%V}U-}3Fnd*U^+~^G&$N9!!kF? z@DwRCl@w0NODQWaajs0Aui-zjbcZf!FPYsV2N;ZBe&t=#wjk5;XNP1^_!T#}+p!*D zvcDc&_?f2}$?hz>s_-d^Go~r_;U9YgRpGE*Q zlfaylzIHsT9kF-qj5|@Ync7=M?0P}xFI72pLzF)^OZ{?Eo=up_u9ubFid-=ye7(;K zf-uo|(sYT-Cw)wE&w{#?vOAlfl3_{kEy`rDtrN;Epr_Z?M9|zWezS#-7j)ZMXsXY`UksWS1a<&9uAQrkalOP;c7_epU>kHzcZ=iE zejF{R#cP-C*c6}KtP3i6j)k}6@iP!bjJ?#JlgDs_bK)~oAqj1F7Pa5Zi!e>N62@bOF)0CZUN~AC8Zf)Xc#)AyE~=3yZnyN^WJ;E zTI>8cF|0Men0KR`d0yYl+jf|3uioEYUGTC}S!#SaVKwJ`fEM<<7Ax9K zQTzvLDe~Z3G`b{^A$+$9iuhi?j=SKh=6B^14)dbe+Nx8_G^fI!?pBq=>5Bir zRoPH)WeZQkpjR355jK|h-)eQMy{OzUvEuy%;b+~?&d%0=QaLQ6WPu9LfI^X(>xJ5E z@!f|7oxI-1=Fc$~>h%Stg;YXmQ~bYqYvL_87#u|wyK*0q+96dej@AM1w`R-o{JIV} zgH1pt8mMI~F#|lkdlyQ^H~6V@DFsmi%t*tP4zVlSj{RB4VfX5O3O6I(s`B;`g9>&) z{X%VO+G2oBsJgqpL}Qd`&Bo=j@MFpBj$F)a%-m(IiZ{`O3oUQ18Af!$k!)4;r@KK^ zb0cL&&?IJx)|9i=P$#}-wm7h>-TSt~>NO}~)$T)qTpDG0PHgYU2YR|v^nS->a`o#a z%Uhf<7w0L{t~|P&tv$B5Yr`742GSfMR`%DM%|2Xn1;@)ru)2&bXq6bqe05pc%Nbwj zji~-xxUHLu75ENH%L2Mg5~){Sl$s!m>4=P{LD|(SO3~R|4B{@E8)2h&QQ# zRkj2kYGZ+gaxR@GSiM%5kCP=#Kgn41ypW?R)iWpKdlj3aWGW~aJuXl{3_--)5Stnv zKb!GY_BVMX^aS9Qn}I4)zUwc+Ddo!ZspBc@N#+W(zZOa_imOTWvByVCA<4#u0{(~k zg(G*830d)00A<;QCMa{V^S4^p$)=q_1e33p zj;gyRVR6z$QSL~uX5puN(3{j!GThfU55_c9S6T^e4n03^NFyepiw@mXZEdtZ|AAAA zJGSX>g7F`w5cm$Xj5CKDMQhDm>#IZtbZ;gt!R2ivxEsRvs=QK(7*10uTevbLDw?`= zoag88^x=Mz#+_Tjz5WzdU`1fk6GvzKgQ+apIq@3IhOkqIfhJZ2m|FtS1fUx0v{Ck1fx|ja{ zJ1_k3RhGV+C0^pUMjZ)PD^lsC#mP{6A-9_M(l=to9}6naa`;w+2<_ zv!33_Ld=m3c})P766>Oj1+anmEow5A4WYj(QtH{z5rs~u15r)mx54{D*T%ECt()`E z4&(dNrKY{qL^akWF--ah8nJ}1&7aJD{d)MF=w^c8GcEQ?x-xU?=~);_nblOMn=I>d z|NO&&4e8oKYpCm@o?5*Qom0*ioRiwO{G&Cj%-2EV$eN-1Z{og;p2d&M1 zp8M9lI2_10`A3DXc`ARIglbjIzHUv_Qj4P6K#Y^=&XAD$`ss}j91gL!dzp=t)Ypq; z^Wl4yeBC!0nMDl(alVF?jf*8X8>yJ3Lz7wS3vW%%4Lbr98b^OIQz%t*>m0et$Fv8j}t2Pze5C)NS3Vn5(Ur0 zL(aMNdZTf3oT6LXPGDj4?v3B~ZA3IJ3eri7Z%)16(6?RdT(vereOM)sO2c)jf~RLp z`cYIOaPURIG^0AkYNFNIvQ8tH(nlM!0YgXJ(_bBJSG8O=Hm1wmqS{&^Mix|OW(ToP zh*z;ig;kQTBR9^|9eXf*%PlALZm-TBKek46A3BiFPm|uL9z;CY-Z?Nm(2U0@`Y5!7 zye66Pvih{QW>YG*((t%)eWrCS%9)_nte4!fFT25qT*t7UeYp{2dC6M{p*cMk3 z4UK>-pSBKOSS?2EPuUzbTpl@|$d5bgeAclb84oVw2UcSwGvbmJsa$~yQU;;Xw|D*W zPH9C-CnO#=v#N7b<$MuTZU-gD_B!)sR$hz+0o0L-Vz?MpyQq#M$P=EUz0nmc(HE+; zd54Yr-Sx^_4bsysT#I|&Ft;WjBNay~_xTBC$#yPrRKYvnD@dq?oRSk3?p_Iw#S`xM zyHUb}N8c)%KX6DoAGTaMj2H&COYdnN7|L&b%mR&*Fh4gStYHlS%gF{$^jPExyTb!8 z1n3P=&YnxUlL05OJKYtJsN=-Hmi22BW8Y({sKHv)k~fXe51jN-i12HbC`bc!0i&c@ z-_Z~`tMU#4Ny3t2JH@YGoOuv;KiZxi0y^c0zsg5=!>JA8Zuv7y^niQ!#lBlMnAjq@ zr)nhKrY?>QZUs|pdnel_#<;jUFCF<1BVN9Ezoc>2G# z-0BeX-hji(D!h;M`<+hYkRJ*`O7nGH^F%S+ole$CTX^(*!Xw6;CZ5c;8NHPuS@7X_ z&-vB~7IXILSS{?`lEaMx3g`ofw!LpZ@eDJvn(^-H`8K>>a)g^?DNF5qW-zX>b(N

      8(?sQ}{wOtHX0lKsM88#PeVbYf=%k`*PU9jcu47KE)~C z{zC~jZ=DeXYj~A73=g-8VN9}bw*v?OK}b*pUzP{UzR%mO&30VKgdS)T^^@c>B>c)H znkCt72O+l`%#Ql(2;xk3UVq(di&44YuB}i=t{8ueo~`4T9r;eCd8qzao&w z9|^cD^#XK?x$0HaWOrEe@s(WTEA68t3!_Yer~l?TVy$f0r^ltm%|%f0L6n>FAz#P3 zJ{TjK`h!9L^mDO(`5>9R{jj_6Z%|GG#X+1wx9w4CrM`kZlS!~Oh z_6b`>k1VtnzDM6oFL8>bH)EyQQfPGR@w0=S2V2d6tFy&tH8WqD$g`~QaPNAJx*)@{ zbvVC99}YrfH3kPKaQmWuTKiz&!Yrp#Boi0kg5Ev-Mm|KwNj??$+o|_~(%INbU~IZI z@o#S(V(3_L)Hcn&jrv5Tf-<-1Uh6PM5$Ph|vAJMXd!;^g8!=8Ft<_AMB`=5@hp(?A zX%&PDN;;ORB{RQ5cs{h1sBsh@i*6qAejp!lORw2fx$^mh?Eh;#@TUXZQ;8Jg%8q!R z;fyYl5l~{=B%u&JajsTBVXFV#?Rc>r34EI6a>^HzelI(8M5|<(A>ne#S8j3b>;jR| z$ndf|g1WiLP-*$eB%g{zFq{`4emYA=rAk)%8ph2UZ7Z@F{ZKBUhb8eE{VFe>3!8b` zf$ey=8@47fTeEjPJveVAW^-&9E5Sg;V!pT&hk!sz!}Yv8lO(XvK9#IK3MAZLKFN0V zPDEQM-4$LMf7pyRp8*gz(MwgO*!Ekp$MC&^ys~I58D16@D!^x!7W}GSUtYbJ;GGdj z&=Tlt`2T<>xSuRSAncc1V=rF=)4_i~A+Uy(dS*cqS4s7#`VVIMD{cS^c^FM2U@}8| zoC4s}(v=29orG%%CRr4v3giV_=KfR=B>C+%HPj-^ZXL~HCbVJ}p0fFf zSSOx`_OE4Mf(F{I|G+7myJc=JFZN3LNUKGo92Uen;kqg;EHwM0`=L^+2f^_LBX4fr z=#r>6PC`;u2vgGdFYT3S$8TxHB>H`1Ijk34X09h|7(MsT*q>x(`g}1zN3~oV9I>4v z^6c#OrpHS3@h{=XZI3o}eJbzP@X9nJ1?#7H2-DcUIbM;-E_Hp*C|rKN_yd=xWBJ+& zCv9bU)*RH)$LDk8_4aV3;aK$kJmQsn2$> za}ER;%uUg8cf5m%6+lf8_3C|+-qyUAJl3E#pKoxmE;lww*+=|p*!tq^{5*rkt*_k5Iutv-ZSyiUNa()=b)Y(=utvhkfs3(`Xyt))fi#xLyo^yd-7JRQ1c}7V( zHmy{4&=&Gu;b&2KxT>)^40rnS8FUFOh_q^<*$!I9jA#)5P|HR)F+v|X*H1<*7O3*F z$c=Aj)%EV<$ZB zNrPnccLA(#clsT9dU*8braFr)#AQUOnamCcKRCK?s)9c=Sme#t|nQ@Z4?H$_zgxFG+J`zfFu6Sk;vmi2v zU(+XXZK@c&*HR}pyt->|b$t%OLuFR=zOr!`*E*6m^$`^vZ*$aIqTpz!ytN!K z`u0eaaK+hAY}6~>=(CxBN|SS-={ebKHLg(K5*S{$LZ=8`e(s2TpeMU^aZm@aKt>-)r`oPucG_IA5du zprq4fh$Zsq=y}8X(q8zqj#Oz7ic;ejY_ht%~`G(uV@E67nK2GR4grk`0`L*$-37*m-ZXFhX#z-uL zxo_h(H&$X5`Lc9Fk?pyt*tt;V@k{9YP^4cD@ykZK+QcgJ4l&#(0xatVPD$leEMKv_ z=QUcTxok;zap+N55E#>M&hCAhXR4Z(mR!TD=u?l!npW^Wl@|&=y>D;I$xIe%H*q@k zL?k69dg_@*F^wzK&5zTYzC1`%)}nuS#TZ&Q7p@+Du1b{a@cFROaQvicAg~6l<P0cn*gAFj{29 zXSEw2^iB+Wd1SbCM}r;@u3(E&gGA${mFc-fCS2zj;oA_dCN>D2r4{R3fP*DQw;pOp zz7!=cY#}7h5vIz?DoU||9!hM+CFn34G;O0)ynZ1zpQ>WMtSPm-&x<#s!KlILVv+oc zx!8oimv;05-3PhXm+$sWCz8|L9+JB=t1I!o^%c}&zk#?-Y)Msf;M>%L88ox zb5VXS_e2bqmFnBTuiq)z$+OwXkzD)HQN3P6-WmuY!$?QazMqs&3-=^W z#okiPbgivDx?WR-nFct)PRu4xup(nCmB#UVM_t$pzxT8-1S6=L;6wZ9(;Fjq(()-& zU%d-)d~Gu^p1yDdR&T!7+kewgbg1P6{ZzuHvFF%C9dF8&sq}d0M=z=NZF`;z&KLddTW&ev?5MOI6|dl@w4f#E-o~QM6D07L>srp$?dOG-Zn42`U97^FJX00 zlpa%$e3GR%=TiKBw*|&0Xfsi;wbJW&rWCvcibRgp&n#?b9N48@?b2RQ@*LC6^DK@{{(dqpZ;K z;R2JQ3N@kD!PZPcsKvC@lgj0?@wQ*qMAEm9uwD359+*5=TXUov*m-qIjL5v@O8XxjSuQIA`QqkBrzF(R z&IX|idpb(uR|2C6&&R)f#Gk&ka80o5NGmR7mXE$)ljb&w_TplsjK)`G>#7k8lDX1< z@D74)DZT=&sis#ZIsM}FCHQy~!`3Du*p(ljSK1)0b~G6JQK?<`r(Jyu!AeZw(egu) zZXP{$?6Ue|gjdq0e?|N!B6-LzQe5W?Lb7+@i9(I-)VA{79#D9_Ur2gsbIMkt&&I*U z@oN#QwjL{soPm(0wvERu>*9Ok>teSig(n5yWZk=8m>Ge6wZLVDGTJ(EF0qPmx z<9j&j*eeLNl(oqqa88thZnv@LC6IF$XUtb*L@{MM5I-{7IdbQ|?Q*275JskK{r0jt zpH?w7oj8@Q9L11qPg(6tQoeKtQWdj$KVtIzVh8Dus?Hp5BGqAS9n0g3xO|D~(>W9K z&l}H$db*apInVp&$5tueNb)VmqYiCcX}7GO#~#+j1b_9~3XQ6t@RQ=GC_~Gm(+452 z&egawEw1DISPQmz`QJa2q^jay!I2`9u{^P8FBRub%CTj8C}|!Tp}G)%lJk_-FuLv= zbQsvVzb&N}k#;si7x7}t-t((@e>`z1nk`J_+o8)}?q2MbbM@_v`xsI#4bkcMV0i(4 z14badJGY|7XL^qb!SjL+d*E@}UI-&r)kLM}qnX6SgYQZlrMywS`hW-uFIfq$pAD$O zfGAq)TmP+IP#~`$jyLm-s|j0|g|m(GGUlj6WPSxz7S$ubECG}dP8+HvYTrcq5)2DM z==W=YDTx5{t0a+$)JBEyZMW$&j;mTz6?aHX{+@&7r0&9=YhA%+W8c`X;$NQx<@*pe zo(DFi)G~k^V$YZ_vfK>+rzzLua);cLVY&^Gsa&`kapA}$Wb&q{#6bJ@wVR-24Ls4e zr5R;L)OzU0Grh>OH6Nm3#e{QY$+XlC1Q(b&q(~`ya9I98CYq*)&4rJ*?-)851CjY6 zGU~OOg&`_eGDwu-(CfjT^1>x9+{<9D0x80%ta;}?=w_H}h-U&^^T?y+^od!$gcDzk zma;!eGcmtbU1_oW$X86NV<43F-RHHLnE5hnHkv^GI3ARKDtHn!d)d!1*15hV z@!PW(8tvjuS5h`~DL#6I+o=Xq;@_8f2hy0WDn!^b*b(5nS#{a{U`WZ~d>qX$r5IGL zYVun{M>O}PDn24nAia6%Fnl1J`k|;A%X-zz50XHxtY|I*>yo&s)YeCqpY(I}qu7u? z%#p!@06y7+$`O-YVUahs7@jIXUAY7mU@)u1mG?&S{#pQeoou+SufnBqcK}ImONlW5 z>sA-51JZ_}5KRmjcX5rihl48u#}2*Uz0~V^k=JEjzH%~v)H}3}t-LQIcD^(vkZsHyp;}M>4llpHhX&1WjCd>=h;mcTuc!z{ug!}LXrGn|Lg3LCz z#*Ow#2S^%&%k1P?_3y5$kB6ZTUpyW5R6~6Vj-|z;%5aRqhLJCk@l85<`#A>sAS#Z} zD`uun?y0D09@f`dF4NI84?>=`d7iNw>@{27OK(s-vIU|y7A z`>9oRa&+@iyaXKdOF6c$zwlJi_H)#tXeo(6wRWST7i(?W3bf>kvTvGjP32)tGc{bgW!-hXg?P)1#Qrk;N$W-dBWGfe+wCbxPbAu+r_E7WX@ zT$fsu^X8V=qy0iBotn-$KRF9BP|iK2QOr6Tpo68@!!;HGh-{VN|IS$o+h=p4V%cYt z3xP;2-x(2!Aq7RDR7R540viATxAcD>@YlOp3A*ejpUARO0h;KqH;3wR2H=lqw)1i7 z*pI@8DXMsD)q!$|`G3Jp*bBZW)jZ+9uqO~W>wYWl3OtBB0`3urmj>X91L$T7V2=J} zjV%B60Q?8w{NHGY@82g4KPms~067UsI0^lSF9M>7KyS{Q{gptwr-$spGIKBM_L+!o z4*I>^>N?VH^LY}mE{A?;G>Dez`zTf>WB(DlF3DRf*5O&wJPO@qSB&zYEP4ap|N zj*2*1R8BM$M1>)KgttkvDHx*(Fya>qUG$2Yyn+I}ULGZTHgXDkE7`syq}AQ!Yb_ra zDpvO^KU3HMp~f8&I8&o2rD>r-oCW_g`!_O~|5E_{m)EgZyt+S3LtQ%opCYCcuSSZO|5b!&5qbnTq zNI}J{Bb*9qY{ReS`{(M9?4+(u1BwN992l>lH9sv1wERrUKt`Ah-ru7yx{^mfuf4^0 zwI7pZg6dGT+I5x>%ybPhB=Km%&b3!H&o&>DCltdyeB_e zV$Mv-zSS}AjrxXpie@acxFm%Tb_JI=`c*&5Ndyb+HNV9`njBlxnyrXMFJ0Bf!Nl5^ z8r8raLc`3lXm&ljEV6n~kFUcGuvBc}TIxh2@M>4Qt*y4|+prUBPtaCO!ZoSWy{clO zemNy#`f`r^)sv%*p!spkHO5%V!}& z8w;8}s|}p9*DysX$n<1(JcBWM-q&}NZ}~PcdGK*czLjXQ%03r7zX>65uv|EkgGx}= zwoVnA)CI0@%i@0s$fL{MA%4spO_-4jpM`#d=+3Y7Y@stUu=*@4!EBa;(6k7LeP4e3 z@J!rBk&nDw88mo#dv}tpX#z!^xyFsX_ui1Hx;_rvraWfpC*Ih%cH5xoandMI`LMLb z>1spR?AX({D^*p|p~x3Vx7#z5PB1MTEkDlSa zNhFWYJ&{gaB@c}TN6+3U#xYiI0_DP|g}#T`PR6&_t0FV%0G}KCgBGet=5)2cs7ItY&g65HU^#{i->6D(?@iX7lAg5H zdd5onr;CPuMvi52PCS^O?JR-wS)9#?+q=RP8Q( z_CH-M|5~-c#jBf@9M|2uiF=40h*}i)8i@7g!Ex5d$CpI3oQh08&RmMxR|+glg5F)+ zFXayw=;-Rmy$^GGvDjp|fNv`g?yG-6*;gj#^A<&LzW#W!V1J&vWYXEmQrWqhcei%_ zTb9{Ly8x8d?|z^3nP=$_Tx9tlxY1!>nU8loa)03L5zLE8J?`gCs2P` z19Ubob+S?5b7j5;nd~71+d({-`-oUkW*`yqQ8^3V_fMW_m%Kb_nHG7ojDD(jtL24%q1X!=Y%D)kym7fxLZZk!Hl1)j?`XN2nLkQt^$n<@4V?9Y>`;nN}N{H)Ry+ zNWJzPk)e~YZr>yK4iu$-uNHy%(tgurmLW(t6yCpRt?*T8`RZc1((r~utdpgJM@pq{ zZAEpJMd}PZex@kpHCWIfAzp|WJ?lkNjd@R`WAF0u6euGAw)rc5Np=CU7yxiW zppx(MEP)JZ9)Mq>gv8>CP$oFw{|DOqkL~z>=o^5o0WPAq|Bu697_Rd#e}nMG9Izlm zkD(U^RVSAv7MGV(c6OpV(8yor8=v+cah9h(QhDHh?y?)aRWvS~(285g$T@ZB2kY8x zx_Eu8-iU;FmW^q}ee|)bpEx0vOp{o=Nm+1);(-`)K3yM{VbmFG*N)<9JDJ+*M1T2u zaWP%_y_8QAqR`NCH4f+{t2vXtR}3V0_#8`<3I#2z5q6s`x{ZwDYbz@Sp5vbE{1TdN z(@Y-?<599%&!R!Mm|ZVK#0ZK^Y4TMR!EjjGmi8sOH8!Q?Is8aq`A&m;VoE~ZHhyFq z+fO4SVCMp6T^a1JmYlyZqul5=y%gx56xtgoiP=LL*4})`OnaxI(5yHcakkmaeZi+o zl2A73Wq-bXKi1Q9@TRRygn`kPU}1ozn^T23$ zUD->d#CbOL;cDHLxHg}ru+ei>hmbx>vg;3ARDGRT=DTAeUy`NG5K;xq!Qa3}?NJzk zZjaist{=MU^~PH3$^4>HREBtd_8IuduViPfQ#Ok1(WN zKODQ2s*4^~opw~Qa+N!*XZ%zly8!XO$u9`}9CI6*_4Nw)8o zl7g(FCpl;N>)?*s`X(4_Nh5Q(FkN8V)ht~{TVkN7x9Viaw8F5Fm}@feAcfz1Yoo=~ z%T%EyWa;`CY10p|iE^0j&`YT>LR4AacJ6K!0=BHHFz+*L2+&wYWnor7@w+}+N7yiv z*KU1~&=?X!#!ThjM`lbEC^2lKn5+9Wu__f5DT{@JjK05}iEjhrU+(va6k)PGu

      Nan2Qh3A198nm@x3ejx+>D`OF5v#5=E_G_rPf!+)J!J&B1JS833$ z^b|`mV`;G^H_>=2YOlVRyIG5&MkRw71wk&lMf^UT1N%M{yQ=8#=3o9CO|K6nG}c`# zZHQ{FEYG>Q>nCA%jaj3UzuqbX)IBhPGq;$%41U>2)}3Pmtp6ae59HdWT2H)h!L`B;m_$c8s1F}Moe01pH|*FSYIry%+KqO zy{X7OK|9$>h!`|6XEX@E|E0N(`@^DQfML-1T!U$3)S~joda+tyu>J3wxjo}o^@Ssa z`p=x(ind}+^cLYCWwAbeIHEw4XRtPuUL*CF@4hR>gkb((n`$^|~%j zZ|9S3nmXf-Qd0@G#+iqnraR(j;pbE7e%cY#mm6?g7b6V_>WlEq6X9hqk9S%5gHW>o zfj_`}-FHHDRUn3&2ue&pBAxG_ixRmBp^!zal!id~tV&4_HK9Bnt?6W9-UbJ2&&=*D zpZ*}^$7!F2*HudrE>(ELIG1&~!C&K@tnqR689~Z5b9}V!Y6oskBK5Iqt}cV0J`ju{ zoPb{}>x5l6IF9qnNyoQ^7wqXRqD~lC0viPrNgO-;z4szz<E3TyfdZRG-53}Z%1f9x6S*&GnQ}8h(wi~ywy2~o)?)L}&NzTP=CNqnM?6dBwiDd$vNt3z9YgX%=j!PIAA?<>W?o zlXj<#b82$&!(+c766fGbGnzU4gB1U;k-JZB@yWqes}K99>6|8BN7Q*HqSP>?gkK`- z3GrV|e~)2{0mqAdHtv3`~TX+VQD9oC>&2Ndsg?7fTc4z@ z%r&`Xg%)+B=A2scz3ZtaY^n{kET66kJk&M=ZWkt@V9rIFI{nz2I+4<{D15bba`Eeu z_i&x=qtA*K9lN(vtM1^;>g5E_2$p)tN}5oxYY2aVi`Kilpu30?7?Xys53HY z(;{9d4Z=8xJ$z%qxYEk5t>niFDC4kwp!S=MQIKo_ zY8{ks=Z4q1`qYbAMhuceby3swH>hX%@k)qxZ-XOae{TZA#b{6-D9DvOPewDGV9MkS z@@)8~P?4|vuJ=N7$0J9x+568Yp_(1FI+13QIAGUaS(t(Kv}5K}`?39AA)`D&{cU5& zYHz|#=~JOgjMiy6%_R4^t*vPjxPk1q58TBNC_^nRBh%6V4?xh02To1)VqwX&ez85j zZtqAMzqH#~c3ADUXX0k2!k~-hp;`K&q2E6+N*rU+@Z$%|c>a%NnQtQzVT<;!rbZYO&^iQ_q9H;CS=daFvt%4q#~04h9ikABtHtaEKQb0#w<7a@>47j%Vrxkl5?K&kYEHDxTBfQ;C=KtY2T3jf0QZ&)+6CVk zK!&#|q8gF_}i2bnX(p$%%vN~Pm%LwaA-LDl9(X2h4$*U-K z$vPb}`aWh&X-;gn9!CAoUu%ujooEvR5_GB~B5IiIw)1A>URWY0q#@FdqvhawbH5_- zFS55+s>@um6^_ey`(I?8bx>RVyX`}PqJ^TxrD)OOt}RfYxVw9ChXMr(MFNyy#a)9# zkYJ^_7l+{PPH^Z=-}iU!Ip^LP7&bfkV-GU3zU%osYe9iu%r_a|C6Q44q!Xkf@9z~c z1lyatxO6jhUK~^@y~q$}(WK_<-y}Y&I%L=Kpd3T)v9_|5k4hlGsXc2KL8kdGzWEa4 zAcj<{bBsZ$-PoZjbt=)$d@U>M(aCUHXra&7ktS_fYZJs|8u##^Bg>bi~M_GNelDew1W%AQ$qdn{HkluW4) zPNc-Z_%Y>(Q9y!Mk^p?%pkh<)p|x|KVA=@N6ENo4Y^69o5jV}^32`#`HZ>)wO+6@>??L3__W+S+gJGL z3veGiV?q&F_ydqQQr+$4YOz-99#kJpiWG-C%q_mP&UtJ7XlKr0>lvW0NALf^QS;nS^p-lZz2)YF{){XD2E(hVKlHs{y`i+Z1v9UKo_g_nnuFB&lX$&^zdA4s z$IlPZIMiWdv6h%)4UnBn>IOsux*L2p1xF?ZpQxaFBrGG~{_p86bId9<8aLM~I33|a#dL;n$5 z3(;k9^@vDE7;?N@Xz`j!2ix80Wli%LICmPc2-l90BGs+@bZY7BKZ}ZdClSn*9=^w& z>07lg@RFB!;IIXlN`IFmKNg18YHCw6esPM)fjJ)7=DALh`1FR=hm5>JMQeO{S+RM0 ziZ=q;^26qcxi2XX0ZzB9^x?qw+(NIPxU^)`cGv7vv5S5OeZS@ug;fJHJ=ZooC-_QE z^7QbgLva*_*1kP<`_RmEGZs}wZ4uX7ACu=^mk-O=7(PKz@+@`ePE?2E>n9;P^`0Ps zPNGou$ms@?%7t%|ti^jeGRM^D@jF6K9SbL#qlUy=r}Fz({DC=lBW;Bcu7gNsz31;U zYRTav4i4_-gMCP|jmY-yys`82Gj>V!I!v)A>Z6%9K35$Pe*md0T&P-d41y>&ICO%K zNav`!rHK7KWWKT~k3e3L`V#@CpR*oI@>e(0VTpUf^scFE>A~t+Q#g{;l)+hNY1`)h zj1@-?xAq<`nGkgQrHZk4t_Lb*_tDcvvq8`Wvxe_Z&uHtaYvNzWMWLR>F_B7?R`^_5 z=?*}ix4lTc>SjQFC34%+;hwn3da3U!Ru#v~lS!;{jjOYy98yZHI5a?>-V?YctST6URCY&@)U82eQ_9%CM!PUg4ou9$K>G@W0UNv0aKmDFH=9%Cs zXi~uzj#Y5I^aGCqbHd6T*q~SiAZ(Btb#ZGJWvNXPC`KMP+aMdCRZJ%zsS9`>?BM6o z_f2VNVPTkNgB-e+>AQi`wW#hUf0rUIV+&2)@ot{cY=PRp9OpnIUrr`Y{$xo*|AOhw zTM1gh=aOinfc_^_z&T-TFHSKcKwGRmOU(Ju_b`ADZFzF#U>5CX@ep|zUDxZi@u=#1 zyzPdte5+AcQ?mX2}pX|8rI#1y2goA`v90Wtf4T@cS?d4g!U=X2x&l zzhbfl*LHB0`16w*6VFW5a;dA6lDdg^zd;GiS%+ka;AGYXD20VqPM<%%XiqP<^J_Ie zP7OjG4AV9v59ufGquo-G%MTp~?@fnk`G_QrX6&^n>85Iv{NFj+zZZx+?P^s7GLKAQ z?}TkSwMbRTu0{S@@vqH9^H;(B)pP&vWjI32O(9$U{`e}Xri4a3&E#c)fue*HU)OuxdJw4TTDL`TQ(jb!Kv1SH<;a^Q zX(9zanQc5H(iYGB3qLWap|wreYQgo+;ST`y&Nb(*k+>pvpLikbd@uIPIldYl4JslC zdaL?pEZv^w;VV&3<_#@Y4PfA_jk1HCLWmbXc$GnKu)O$;)n$AoB{^mDB!FmC)yZq? z#|-_{F(-|uRcj6Z8bxHl^tA!gAa{7@0O}VK%om@OYk?hm2I3Vni~PK6vS&_pOP+y^ z2FLdNvgcD(Y;@D+u?{2py}MFu1+vx2QPPzab?`_ zQgR9HFsX>)8|_;508kRg->(s>y_E|zr>K`4GWjXmmvVI2pj@xd(9MYv~L!+`UF4roTuP66rw%g=J?hUTbFKJG&jHK3W9ghT)zdgmg z9#jK%s@8sgF8C-HN$<9fHkrK9B0N!6!8{M2+0L--O=z_WgsvJ$*c?&yiZz#;@W-%c zG^W_uxKccrEbE%eY%7ak8;xSnwR)~M_zPz#I30K?v-lR2k4Ey(EohuyUtOg#(Mavs zk=uy7$6pv6b2+fr^Eun3N7j^o0l7=kBXk*DlJSeYP!4|I`WFO5=Prq|s``@8kz8T+ z(}Kzj8*NMDr$_uspA5VKm84Gu;UsioWWNdpwPN+a`GT5B0%>b|J21tM+TgemDmy)GNj|+F2Y~w3g-Nx2KO7D>0s$#|{kCz|4mZgFwdP-#=`UVaFmR%0Ax}YId)1A6If8?U(QQ?-N`3 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 >] + ['>= >=] + ['+ +] + ['- -] + ['* *] + ['/ /] + ['time-ms time-ms] + + ['list list] + ['list? list?] + ['vector vector] + ['vector? vector?] + ['hash-map hash-map] + ['map? map?] + ['assoc assoc] + ['dissoc dissoc] + ['get get] + ['contains? contains?] + ['keys keys] + ['vals vals] + + ['sequential? sequential?] + ['cons cons] + ['concat concat] + ['vec vec] + ['nth nth] + ['first first] + ['rest rest] + ['empty? empty?] + ['count count] + ['apply apply] + ['map map] + + ['conj conj] + ['seq seq] + + ['with-meta with-meta] + ['meta meta] + ['atom atom] + ['atom? atom?] + ['deref deref] + ['reset! reset!] + ['swap! swap!]]) diff --git a/ext/wasm3/test/wasi/mal/env.mal b/ext/wasm3/test/wasi/mal/env.mal new file mode 100644 index 0000000..590110e --- /dev/null +++ b/ext/wasm3/test/wasi/mal/env.mal @@ -0,0 +1,34 @@ +(def! bind-env (fn* [env b e] + (if (empty? b) + env + (let* [b0 (first b)] + (if (= '& b0) + (assoc env (str (nth b 1)) e) + (bind-env (assoc env (str b0) (first e)) (rest b) (rest e))))))) + +(def! new-env (fn* [& args] + (if (<= (count args) 1) + (atom {:outer (first args)}) + (atom (apply bind-env {:outer (first args)} (rest args)))))) + +(def! env-find (fn* [env k] + (env-find-str env (str k)))) + +(def! env-find-str (fn* [env ks] + (if env + (let* [data @env] + (if (contains? data ks) + env + (env-find-str (get data :outer) ks)))))) + +(def! env-get (fn* [env k] + (let* [ks (str k) + e (env-find-str env ks)] + (if e + (get @e ks) + (throw (str "'" ks "' not found")))))) + +(def! env-set (fn* [env k v] + (do + (swap! env assoc (str k) v) + v))) diff --git a/ext/wasm3/test/wasi/mal/mal.mal b/ext/wasm3/test/wasi/mal/mal.mal new file mode 100644 index 0000000..82dc147 --- /dev/null +++ b/ext/wasm3/test/wasi/mal/mal.mal @@ -0,0 +1,152 @@ +(load-file "./env.mal") +(load-file "./core.mal") + +;; read +(def! READ read-string) + + +;; eval + +(def! qq-loop (fn* [elt acc] + (if (if (list? elt) (= (first elt) 'splice-unquote)) ; 2nd 'if' means 'and' + (list 'concat (nth elt 1) acc) + (list 'cons (QUASIQUOTE elt) acc)))) +(def! qq-foldr (fn* [xs] + (if (empty? xs) + (list) + (qq-loop (first xs) (qq-foldr (rest xs)))))) +(def! QUASIQUOTE (fn* [ast] + (cond + (vector? ast) (list 'vec (qq-foldr ast)) + (map? ast) (list 'quote ast) + (symbol? ast) (list 'quote ast) + (not (list? ast)) ast + (= (first ast) 'unquote) (nth ast 1) + "else" (qq-foldr ast)))) + +(def! MACROEXPAND (fn* [ast env] + (let* [a0 (if (list? ast) (first ast)) + e (if (symbol? a0) (env-find env a0)) + m (if e (env-get e a0))] + (if (_macro? m) + (MACROEXPAND (apply (get m :__MAL_MACRO__) (rest ast)) env) + ast)))) + +(def! eval-ast (fn* [ast env] + ;; (do (prn "eval-ast" ast "/" (keys env)) ) + (cond + (symbol? ast) (env-get env ast) + + (list? ast) (map (fn* [exp] (EVAL exp env)) ast) + + (vector? ast) (vec (map (fn* [exp] (EVAL exp env)) ast)) + + (map? ast) (apply hash-map + (apply concat + (map (fn* [k] [k (EVAL (get ast k) env)]) + (keys ast)))) + + "else" ast))) + +(def! LET (fn* [env binds form] + (if (empty? binds) + (EVAL form env) + (do + (env-set env (first binds) (EVAL (nth binds 1) env)) + (LET env (rest (rest binds)) form))))) + +(def! EVAL (fn* [ast env] + ;; (do (prn "EVAL" ast "/" (keys @env)) ) + (let* [ast (MACROEXPAND ast env)] + (if (not (list? ast)) + (eval-ast ast env) + + ;; apply list + (let* [a0 (first ast)] + (cond + (empty? ast) + ast + + (= 'def! a0) + (env-set env (nth ast 1) (EVAL (nth ast 2) env)) + + (= 'let* a0) + (LET (new-env env) (nth ast 1) (nth ast 2)) + + (= 'quote a0) + (nth ast 1) + + (= 'quasiquoteexpand a0) + (QUASIQUOTE (nth ast 1)) + + (= 'quasiquote a0) + (EVAL (QUASIQUOTE (nth ast 1)) env) + + (= 'defmacro! a0) + (env-set env (nth ast 1) (hash-map :__MAL_MACRO__ + (EVAL (nth ast 2) env))) + + (= 'macroexpand a0) + (MACROEXPAND (nth ast 1) env) + + (= 'try* a0) + (if (< (count ast) 3) + (EVAL (nth ast 1) env) + (try* + (EVAL (nth ast 1) env) + (catch* exc + (let* [a2 (nth ast 2)] + (EVAL (nth a2 2) (new-env env [(nth a2 1)] [exc])))))) + + (= 'do a0) + (let* [el (eval-ast (rest ast) env)] + (nth el (- (count el) 1))) + + (= 'if a0) + (if (EVAL (nth ast 1) env) + (EVAL (nth ast 2) env) + (if (> (count ast) 3) + (EVAL (nth ast 3) env))) + + (= 'fn* a0) + (fn* [& args] (EVAL (nth ast 2) (new-env env (nth ast 1) args))) + + "else" + (let* [el (eval-ast ast env)] + (apply (first el) (rest el))))))))) + + +;; print +(def! PRINT pr-str) + +;; repl +(def! repl-env (new-env)) +(def! rep (fn* [strng] + (PRINT (EVAL (READ strng) repl-env)))) + +;; core.mal: defined directly using mal +(map (fn* [data] (apply env-set repl-env data)) core_ns) +(env-set repl-env 'eval (fn* [ast] (EVAL ast repl-env))) +(env-set repl-env '*ARGV* (rest *ARGV*)) + +;; core.mal: defined using the new language itself +(rep (str "(def! *host-language* \"" *host-language* "-mal\")")) +(rep "(def! not (fn* [a] (if a false true)))") +(rep "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \"\nnil)\")))))") +(rep "(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))") + +;; repl loop +(def! repl-loop (fn* [line] + (if line + (do + (if (not (= "" line)) + (try* + (println (rep line)) + (catch* exc + (println "Uncaught exception:" exc)))) + (repl-loop (readline "mal-user> ")))))) + +;; main +(if (empty? *ARGV*) + (repl-loop "(println (str \"Mal [\" *host-language* \"]\"))") + (rep (str "(load-file \"" (first *ARGV*) "\")"))) diff --git a/ext/wasm3/test/wasi/mal/test-fib.mal b/ext/wasm3/test/wasi/mal/test-fib.mal new file mode 100644 index 0000000..d348652 --- /dev/null +++ b/ext/wasm3/test/wasi/mal/test-fib.mal @@ -0,0 +1,8 @@ +;; Compute a Fibonacci number with two recursions. +(def! fib + (fn* [n] ; non-negative number + (if (<= n 1) + n + (+ (fib (- n 1)) (fib (- n 2)))))) + +(println (fib (read-string (first *ARGV*)))) diff --git a/ext/wasm3/test/wasi/mandelbrot/README.md b/ext/wasm3/test/wasi/mandelbrot/README.md new file mode 100644 index 0000000..b236e18 --- /dev/null +++ b/ext/wasm3/test/wasi/mandelbrot/README.md @@ -0,0 +1,49 @@ +# mandelbrot + +Based on https://github.com/josch/mandelbrot + +

      + +### Results + +```log +TODO +``` + +### Building + +```sh +wasicc -g0 -O3 mandel_dd.c -o mandel_dd.wasm +wasicc -g0 -O3 mandel.c -o mandel.wasm +``` + +### Running + +```sh +export ENGINES_PATH=/opt/wasm_engines + +# Wasm3 +../../../build/wasm3 mandel_dd.wasm > image.ppm + +# WAC +$ENGINES_PATH/wac/wax mandel_dd.wasm > image.ppm + +# wasm-micro-runtime +$ENGINES_PATH/wasm-micro-runtime/core/iwasm/products/linux/build/iwasm mandel_dd.wasm > image.ppm + +# wasmtime +wasmtime --optimize mandel_dd.wasm > image.ppm + +# Wasmer +wasmer run mandel_dd.wasm > image.ppm +wasmer run --backend singlepass mandel_dd.wasm > image.ppm +wasmer run --backend llvm mandel_dd.wasm > image.ppm + +# Wasmer-JS (V8) +wasmer-js run mandel_dd.wasm > image.ppm + +node --wasm_interpret_all $(which wasmer-js) run mandel_dd.wasm > image.ppm + +# WAVM +$ENGINES_PATH/WAVM/Release/bin/wavm run mandel_dd.wasm > image.ppm +``` diff --git a/ext/wasm3/test/wasi/mandelbrot/colors.h b/ext/wasm3/test/wasi/mandelbrot/colors.h new file mode 100644 index 0000000..cd44393 --- /dev/null +++ b/ext/wasm3/test/wasi/mandelbrot/colors.h @@ -0,0 +1,836 @@ +#define GRADIENTLENGTH 4990 + +const unsigned char colors[GRADIENTLENGTH][3] = { + {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x52}, + {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x53}, {0x0e, 0x0b, 0x53}, + {0x0e, 0x0b, 0x53}, {0x0e, 0x0b, 0x53}, {0x0e, 0x0b, 0x53}, {0x0e, 0x0b, 0x53}, {0x0e, 0x0b, 0x53}, {0x0e, 0x0c, 0x53}, + {0x0e, 0x0c, 0x53}, {0x0e, 0x0c, 0x53}, {0x0e, 0x0c, 0x53}, {0x0e, 0x0c, 0x53}, {0x0e, 0x0c, 0x53}, {0x0e, 0x0c, 0x53}, + {0x0e, 0x0c, 0x53}, {0x0e, 0x0c, 0x53}, {0x0e, 0x0c, 0x53}, {0x0e, 0x0c, 0x53}, {0x0e, 0x0c, 0x53}, {0x0e, 0x0c, 0x54}, + {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, + {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, + {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, {0x0e, 0x0c, 0x54}, + {0x0e, 0x0c, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, + {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, + {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x55}, + {0x0e, 0x0d, 0x55}, {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, + {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, + {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, {0x0e, 0x0d, 0x56}, {0x0e, 0x0e, 0x56}, {0x0e, 0x0e, 0x56}, {0x0e, 0x0e, 0x56}, + {0x0e, 0x0e, 0x56}, {0x0e, 0x0e, 0x56}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, + {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, + {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, + {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x57}, {0x0e, 0x0e, 0x58}, {0x0e, 0x0e, 0x58}, {0x0e, 0x0e, 0x58}, + {0x0e, 0x0e, 0x58}, {0x0e, 0x0e, 0x58}, {0x0e, 0x0e, 0x58}, {0x0e, 0x0e, 0x58}, {0x0e, 0x0e, 0x58}, {0x0e, 0x0f, 0x58}, + {0x0e, 0x0f, 0x58}, {0x0e, 0x0f, 0x58}, {0x0e, 0x0f, 0x58}, {0x0e, 0x0f, 0x58}, {0x0e, 0x0f, 0x58}, {0x0e, 0x0f, 0x58}, + {0x0e, 0x0f, 0x58}, {0x0e, 0x0f, 0x58}, {0x0e, 0x0f, 0x58}, {0x0e, 0x0f, 0x58}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, + {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, + {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, + {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x59}, {0x0e, 0x0f, 0x5a}, + {0x0e, 0x0f, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, + {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, + {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, {0x0e, 0x10, 0x5a}, + {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, + {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, + {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x10, 0x5b}, {0x0e, 0x11, 0x5b}, {0x0e, 0x11, 0x5b}, + {0x0e, 0x11, 0x5b}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, + {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, + {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, + {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5c}, {0x0e, 0x11, 0x5d}, {0x0e, 0x11, 0x5d}, {0x0e, 0x11, 0x5d}, {0x0e, 0x11, 0x5d}, + {0x0e, 0x11, 0x5d}, {0x0e, 0x11, 0x5d}, {0x0e, 0x11, 0x5d}, {0x0e, 0x11, 0x5d}, {0x0e, 0x11, 0x5d}, {0x0e, 0x11, 0x5d}, + {0x0e, 0x12, 0x5d}, {0x0e, 0x12, 0x5d}, {0x0e, 0x12, 0x5d}, {0x0e, 0x12, 0x5d}, {0x0e, 0x12, 0x5d}, {0x0e, 0x12, 0x5d}, + {0x0e, 0x12, 0x5d}, {0x0e, 0x12, 0x5d}, {0x0e, 0x12, 0x5d}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, + {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, + {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, + {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5e}, {0x0e, 0x12, 0x5f}, {0x0e, 0x12, 0x5f}, + {0x0e, 0x12, 0x5f}, {0x0e, 0x12, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, + {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, + {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x5f}, {0x0e, 0x13, 0x60}, + {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, + {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, + {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x13, 0x60}, {0x0e, 0x14, 0x60}, {0x0e, 0x14, 0x60}, + {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, + {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, + {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x61}, + {0x0e, 0x14, 0x61}, {0x0e, 0x14, 0x62}, {0x0e, 0x14, 0x62}, {0x0e, 0x14, 0x62}, {0x0e, 0x14, 0x62}, {0x0e, 0x14, 0x62}, + {0x0e, 0x14, 0x62}, {0x0e, 0x14, 0x62}, {0x0e, 0x14, 0x62}, {0x0e, 0x14, 0x62}, {0x0e, 0x14, 0x62}, {0x0e, 0x14, 0x62}, + {0x0e, 0x15, 0x62}, {0x0e, 0x15, 0x62}, {0x0e, 0x15, 0x62}, {0x0e, 0x15, 0x62}, {0x0e, 0x15, 0x62}, {0x0e, 0x15, 0x62}, + {0x0e, 0x15, 0x62}, {0x0e, 0x15, 0x62}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, + {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, + {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, + {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x63}, {0x0e, 0x15, 0x64}, {0x0e, 0x15, 0x64}, {0x0e, 0x15, 0x64}, + {0x0e, 0x15, 0x64}, {0x0e, 0x15, 0x64}, {0x0e, 0x15, 0x64}, {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x64}, + {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x64}, + {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x64}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, + {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, + {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, + {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x16, 0x65}, {0x0e, 0x17, 0x66}, + {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, + {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, + {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, {0x0e, 0x17, 0x66}, + {0x0e, 0x17, 0x67}, {0x0e, 0x17, 0x67}, {0x0e, 0x17, 0x67}, {0x0e, 0x17, 0x67}, {0x0e, 0x17, 0x67}, {0x0e, 0x17, 0x67}, + {0x0e, 0x17, 0x67}, {0x0e, 0x17, 0x67}, {0x0e, 0x17, 0x67}, {0x0e, 0x17, 0x67}, {0x0e, 0x17, 0x67}, {0x0e, 0x17, 0x67}, + {0x0e, 0x17, 0x67}, {0x0e, 0x18, 0x67}, {0x0e, 0x18, 0x67}, {0x0e, 0x18, 0x67}, {0x0e, 0x18, 0x67}, {0x0e, 0x18, 0x67}, + {0x0e, 0x18, 0x67}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, + {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, + {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, + {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x68}, {0x0e, 0x18, 0x69}, {0x0e, 0x18, 0x69}, {0x0e, 0x18, 0x69}, {0x0e, 0x18, 0x69}, + {0x0e, 0x18, 0x69}, {0x0e, 0x18, 0x69}, {0x0e, 0x18, 0x69}, {0x0e, 0x19, 0x69}, {0x0e, 0x19, 0x69}, {0x0e, 0x19, 0x69}, + {0x0e, 0x19, 0x69}, {0x0e, 0x19, 0x69}, {0x0e, 0x19, 0x69}, {0x0e, 0x19, 0x69}, {0x0e, 0x19, 0x69}, {0x0e, 0x19, 0x69}, + {0x0e, 0x19, 0x69}, {0x0e, 0x19, 0x69}, {0x0e, 0x19, 0x69}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, + {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, + {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, + {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6a}, {0x0e, 0x19, 0x6b}, {0x0e, 0x1a, 0x6b}, + {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, + {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, + {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6b}, {0x0e, 0x1a, 0x6c}, + {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, + {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, + {0x0e, 0x1a, 0x6c}, {0x0e, 0x1a, 0x6c}, {0x0e, 0x1b, 0x6c}, {0x0e, 0x1b, 0x6c}, {0x0e, 0x1b, 0x6c}, {0x0e, 0x1b, 0x6c}, + {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, + {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, + {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6d}, + {0x0e, 0x1b, 0x6d}, {0x0e, 0x1b, 0x6e}, {0x0e, 0x1b, 0x6e}, {0x0e, 0x1b, 0x6e}, {0x0e, 0x1b, 0x6e}, {0x0e, 0x1b, 0x6e}, + {0x0e, 0x1b, 0x6e}, {0x0e, 0x1b, 0x6e}, {0x0e, 0x1b, 0x6e}, {0x0e, 0x1b, 0x6e}, {0x0e, 0x1c, 0x6e}, {0x0e, 0x1c, 0x6e}, + {0x0e, 0x1c, 0x6e}, {0x0e, 0x1c, 0x6e}, {0x0e, 0x1c, 0x6e}, {0x0e, 0x1c, 0x6e}, {0x0e, 0x1c, 0x6e}, {0x0e, 0x1c, 0x6e}, + {0x0e, 0x1c, 0x6e}, {0x0e, 0x1c, 0x6e}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, + {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, + {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, + {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x6f}, {0x0e, 0x1c, 0x70}, {0x0e, 0x1c, 0x70}, {0x0e, 0x1c, 0x70}, + {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, + {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, + {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x70}, {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, + {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, + {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, + {0x0e, 0x1d, 0x71}, {0x0e, 0x1d, 0x71}, {0x0e, 0x1e, 0x71}, {0x0e, 0x1e, 0x71}, {0x0e, 0x1e, 0x71}, {0x0e, 0x1e, 0x72}, + {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, + {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, + {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, {0x0e, 0x1e, 0x72}, + {0x0e, 0x1e, 0x73}, {0x0e, 0x1e, 0x73}, {0x0e, 0x1e, 0x73}, {0x0e, 0x1e, 0x73}, {0x0e, 0x1e, 0x73}, {0x0e, 0x1e, 0x73}, + {0x0e, 0x1e, 0x73}, {0x0e, 0x1e, 0x73}, {0x0e, 0x1e, 0x73}, {0x0e, 0x1e, 0x73}, {0x0e, 0x1f, 0x73}, {0x0e, 0x1f, 0x73}, + {0x0e, 0x1f, 0x73}, {0x0e, 0x1f, 0x73}, {0x0e, 0x1f, 0x73}, {0x0e, 0x1f, 0x73}, {0x0e, 0x1f, 0x73}, {0x0e, 0x1f, 0x73}, + {0x0e, 0x1f, 0x73}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, + {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, + {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, + {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x74}, {0x0e, 0x1f, 0x75}, {0x0e, 0x1f, 0x75}, {0x0e, 0x1f, 0x75}, {0x0e, 0x1f, 0x75}, + {0x0e, 0x1f, 0x75}, {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, + {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, + {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x75}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, + {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, + {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, + {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x20, 0x76}, {0x0e, 0x21, 0x76}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, + {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, + {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, + {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x77}, {0x0e, 0x21, 0x78}, + {0x0e, 0x21, 0x78}, {0x0e, 0x21, 0x78}, {0x0e, 0x21, 0x78}, {0x0e, 0x21, 0x78}, {0x0e, 0x21, 0x78}, {0x0e, 0x21, 0x78}, + {0x0e, 0x21, 0x78}, {0x0e, 0x21, 0x78}, {0x0e, 0x21, 0x78}, {0x0e, 0x21, 0x78}, {0x0e, 0x21, 0x78}, {0x0e, 0x22, 0x78}, + {0x0e, 0x22, 0x78}, {0x0e, 0x22, 0x78}, {0x0e, 0x22, 0x78}, {0x0e, 0x22, 0x78}, {0x0e, 0x22, 0x78}, {0x0e, 0x22, 0x78}, + {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, + {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, + {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x79}, + {0x0e, 0x22, 0x79}, {0x0e, 0x22, 0x7a}, {0x0e, 0x22, 0x7a}, {0x0e, 0x22, 0x7a}, {0x0e, 0x22, 0x7a}, {0x0e, 0x22, 0x7a}, + {0x0e, 0x22, 0x7a}, {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7a}, + {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7a}, + {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7a}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, + {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, + {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, + {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x23, 0x7b}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, + {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, + {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, + {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7c}, {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, + {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, + {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, {0x0e, 0x24, 0x7d}, + {0x0e, 0x25, 0x7d}, {0x0e, 0x25, 0x7d}, {0x0e, 0x25, 0x7d}, {0x0e, 0x25, 0x7d}, {0x0e, 0x25, 0x7d}, {0x0e, 0x25, 0x7e}, + {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, + {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, + {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, {0x0e, 0x25, 0x7e}, + {0x0e, 0x25, 0x7f}, {0x0e, 0x25, 0x7f}, {0x0e, 0x25, 0x7f}, {0x0e, 0x25, 0x7f}, {0x0e, 0x25, 0x7f}, {0x0e, 0x25, 0x7f}, + {0x0e, 0x25, 0x7f}, {0x0e, 0x25, 0x7f}, {0x0e, 0x26, 0x7f}, {0x0e, 0x26, 0x7f}, {0x0e, 0x26, 0x7f}, {0x0e, 0x26, 0x7f}, + {0x0e, 0x26, 0x7f}, {0x0e, 0x26, 0x7f}, {0x0e, 0x26, 0x7f}, {0x0e, 0x26, 0x7f}, {0x0e, 0x26, 0x7f}, {0x0e, 0x26, 0x7f}, + {0x0e, 0x26, 0x7f}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, + {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, + {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, + {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x80}, {0x0e, 0x26, 0x81}, {0x0e, 0x26, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, + {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, + {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, + {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x81}, {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, + {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, + {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, {0x0e, 0x27, 0x82}, + {0x0e, 0x28, 0x82}, {0x0e, 0x28, 0x82}, {0x0e, 0x28, 0x82}, {0x0e, 0x28, 0x82}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, + {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, + {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, + {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x83}, {0x0e, 0x28, 0x84}, + {0x0e, 0x28, 0x84}, {0x0e, 0x28, 0x84}, {0x0e, 0x28, 0x84}, {0x0e, 0x28, 0x84}, {0x0e, 0x28, 0x84}, {0x0e, 0x28, 0x84}, + {0x0e, 0x28, 0x84}, {0x0e, 0x28, 0x84}, {0x0e, 0x29, 0x84}, {0x0e, 0x29, 0x84}, {0x0e, 0x29, 0x84}, {0x0e, 0x29, 0x84}, + {0x0e, 0x29, 0x84}, {0x0e, 0x29, 0x84}, {0x0e, 0x29, 0x84}, {0x0e, 0x29, 0x84}, {0x0e, 0x29, 0x84}, {0x0e, 0x29, 0x84}, + {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, + {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, + {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x85}, + {0x0e, 0x29, 0x85}, {0x0e, 0x29, 0x86}, {0x0e, 0x29, 0x86}, {0x0e, 0x29, 0x86}, {0x0e, 0x29, 0x86}, {0x0e, 0x2a, 0x86}, + {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, + {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, + {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x86}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, + {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, + {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, {0x0e, 0x2a, 0x87}, + {0x0e, 0x2a, 0x87}, {0x0e, 0x2b, 0x87}, {0x0e, 0x2b, 0x87}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, + {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, + {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, + {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x88}, {0x0e, 0x2b, 0x89}, {0x0e, 0x2b, 0x89}, + {0x0e, 0x2b, 0x89}, {0x0e, 0x2b, 0x89}, {0x0e, 0x2b, 0x89}, {0x0e, 0x2b, 0x89}, {0x0e, 0x2b, 0x89}, {0x0e, 0x2b, 0x89}, + {0x0e, 0x2b, 0x89}, {0x0e, 0x2b, 0x89}, {0x0e, 0x2b, 0x89}, {0x0e, 0x2c, 0x89}, {0x0e, 0x2c, 0x89}, {0x0e, 0x2c, 0x89}, + {0x0e, 0x2c, 0x89}, {0x0e, 0x2c, 0x89}, {0x0e, 0x2c, 0x89}, {0x0e, 0x2c, 0x89}, {0x0e, 0x2c, 0x89}, {0x0e, 0x2c, 0x8a}, + {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, + {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, + {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, {0x0e, 0x2c, 0x8a}, + {0x0e, 0x2c, 0x8b}, {0x0e, 0x2c, 0x8b}, {0x0e, 0x2c, 0x8b}, {0x0e, 0x2c, 0x8b}, {0x0e, 0x2c, 0x8b}, {0x0e, 0x2d, 0x8b}, + {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8b}, + {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8b}, + {0x0e, 0x2d, 0x8b}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, + {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, + {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, {0x0e, 0x2d, 0x8c}, + {0x0e, 0x2d, 0x8c}, {0x0e, 0x2e, 0x8c}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, + {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, + {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, + {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8d}, {0x0e, 0x2e, 0x8e}, {0x0e, 0x2e, 0x8e}, {0x0e, 0x2e, 0x8e}, + {0x0e, 0x2e, 0x8e}, {0x0e, 0x2e, 0x8e}, {0x0e, 0x2e, 0x8e}, {0x0e, 0x2e, 0x8e}, {0x0e, 0x2e, 0x8e}, {0x0e, 0x2e, 0x8e}, + {0x0e, 0x2e, 0x8e}, {0x0e, 0x2e, 0x8e}, {0x0e, 0x2e, 0x8e}, {0x0e, 0x2f, 0x8e}, {0x0e, 0x2f, 0x8e}, {0x0e, 0x2f, 0x8e}, + {0x0e, 0x2f, 0x8e}, {0x0e, 0x2f, 0x8e}, {0x0e, 0x2f, 0x8e}, {0x0e, 0x2f, 0x8e}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, + {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, + {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, + {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x8f}, {0x0e, 0x2f, 0x90}, + {0x0e, 0x2f, 0x90}, {0x0e, 0x2f, 0x90}, {0x0e, 0x2f, 0x90}, {0x0e, 0x2f, 0x90}, {0x0e, 0x2f, 0x90}, {0x0e, 0x2f, 0x90}, + {0x0e, 0x30, 0x90}, {0x0e, 0x30, 0x90}, {0x0e, 0x30, 0x90}, {0x0e, 0x30, 0x90}, {0x0e, 0x30, 0x90}, {0x0e, 0x30, 0x90}, + {0x0e, 0x30, 0x90}, {0x0e, 0x30, 0x90}, {0x0e, 0x30, 0x90}, {0x0e, 0x30, 0x90}, {0x0e, 0x30, 0x90}, {0x0e, 0x30, 0x90}, + {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, + {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, + {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, + {0x0e, 0x30, 0x91}, {0x0e, 0x30, 0x91}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, + {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, + {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, + {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x92}, {0x0e, 0x31, 0x93}, {0x0e, 0x31, 0x93}, {0x0e, 0x31, 0x93}, + {0x0e, 0x31, 0x93}, {0x0e, 0x31, 0x93}, {0x0e, 0x31, 0x93}, {0x0e, 0x31, 0x93}, {0x0e, 0x31, 0x93}, {0x0e, 0x31, 0x93}, + {0x0e, 0x31, 0x93}, {0x0e, 0x31, 0x93}, {0x0e, 0x31, 0x93}, {0x0e, 0x31, 0x93}, {0x0e, 0x32, 0x93}, {0x0e, 0x32, 0x93}, + {0x0e, 0x32, 0x93}, {0x0e, 0x32, 0x93}, {0x0e, 0x32, 0x93}, {0x0e, 0x32, 0x93}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, + {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, + {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, + {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x94}, {0x0e, 0x32, 0x95}, + {0x0e, 0x32, 0x95}, {0x0e, 0x32, 0x95}, {0x0e, 0x32, 0x95}, {0x0e, 0x32, 0x95}, {0x0e, 0x32, 0x95}, {0x0e, 0x32, 0x95}, + {0x0e, 0x33, 0x95}, {0x0e, 0x33, 0x95}, {0x0e, 0x33, 0x95}, {0x0e, 0x33, 0x95}, {0x0e, 0x33, 0x95}, {0x0e, 0x33, 0x95}, + {0x0e, 0x33, 0x95}, {0x0e, 0x33, 0x95}, {0x0e, 0x33, 0x95}, {0x0e, 0x33, 0x95}, {0x0e, 0x33, 0x95}, {0x0e, 0x33, 0x95}, + {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, + {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, + {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x96}, + {0x0e, 0x33, 0x96}, {0x0e, 0x33, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, + {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, + {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, + {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x97}, {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, + {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, + {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, {0x0e, 0x34, 0x98}, {0x0e, 0x35, 0x98}, + {0x0e, 0x35, 0x98}, {0x0e, 0x35, 0x98}, {0x0e, 0x35, 0x98}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, + {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, + {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, + {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x99}, {0x0e, 0x35, 0x9a}, {0x0e, 0x35, 0x9a}, + {0x0e, 0x35, 0x9a}, {0x0e, 0x35, 0x9a}, {0x0e, 0x35, 0x9a}, {0x0e, 0x35, 0x9a}, {0x0e, 0x35, 0x9a}, {0x0e, 0x35, 0x9a}, + {0x0e, 0x35, 0x9a}, {0x0e, 0x36, 0x9a}, {0x0e, 0x36, 0x9a}, {0x0e, 0x36, 0x9a}, {0x0e, 0x36, 0x9a}, {0x0e, 0x36, 0x9a}, + {0x0e, 0x36, 0x9a}, {0x0e, 0x36, 0x9a}, {0x0e, 0x36, 0x9a}, {0x0e, 0x36, 0x9a}, {0x0e, 0x36, 0x9a}, {0x0e, 0x36, 0x9b}, + {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, + {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, + {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, {0x0e, 0x36, 0x9b}, + {0x0e, 0x36, 0x9c}, {0x0e, 0x36, 0x9c}, {0x0e, 0x36, 0x9c}, {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, + {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, + {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9c}, + {0x0e, 0x37, 0x9c}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, + {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, + {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x37, 0x9d}, {0x0e, 0x38, 0x9d}, + {0x0e, 0x38, 0x9d}, {0x0e, 0x38, 0x9d}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, + {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, + {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, + {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9e}, {0x0e, 0x38, 0x9f}, {0x0e, 0x38, 0x9f}, {0x0e, 0x38, 0x9f}, + {0x0e, 0x38, 0x9f}, {0x0e, 0x38, 0x9f}, {0x0e, 0x38, 0x9f}, {0x0e, 0x38, 0x9f}, {0x0e, 0x38, 0x9f}, {0x0e, 0x38, 0x9f}, + {0x0e, 0x38, 0x9f}, {0x0e, 0x39, 0x9f}, {0x0e, 0x39, 0x9f}, {0x0e, 0x39, 0x9f}, {0x0e, 0x39, 0x9f}, {0x0e, 0x39, 0x9f}, + {0x0e, 0x39, 0x9f}, {0x0e, 0x39, 0x9f}, {0x0e, 0x39, 0x9f}, {0x0e, 0x39, 0x9f}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, + {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, + {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, + {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa0}, {0x0e, 0x39, 0xa1}, + {0x0e, 0x39, 0xa1}, {0x0e, 0x39, 0xa1}, {0x0e, 0x39, 0xa1}, {0x0e, 0x39, 0xa1}, {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, + {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, + {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, {0x0e, 0x3a, 0xa1}, + {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, + {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, + {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, {0x0e, 0x3a, 0xa2}, + {0x0e, 0x3b, 0xa2}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, + {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, + {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, + {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa3}, {0x0e, 0x3b, 0xa4}, {0x0e, 0x3b, 0xa4}, {0x0e, 0x3b, 0xa4}, {0x0e, 0x3b, 0xa4}, + {0x0e, 0x3b, 0xa4}, {0x0e, 0x3b, 0xa4}, {0x0e, 0x3b, 0xa4}, {0x0e, 0x3b, 0xa4}, {0x0e, 0x3b, 0xa4}, {0x0e, 0x3b, 0xa4}, + {0x0e, 0x3b, 0xa4}, {0x0e, 0x3b, 0xa4}, {0x0e, 0x3c, 0xa4}, {0x0e, 0x3c, 0xa4}, {0x0e, 0x3c, 0xa4}, {0x0e, 0x3c, 0xa4}, + {0x0e, 0x3c, 0xa4}, {0x0e, 0x3c, 0xa4}, {0x0e, 0x3c, 0xa4}, {0x0e, 0x3c, 0xa5}, {0x0e, 0x3c, 0xa5}, {0x0e, 0x3c, 0xa5}, + {0x0e, 0x3c, 0xa5}, {0x0e, 0x3c, 0xa5}, {0x0e, 0x3c, 0xa5}, {0x0e, 0x3c, 0xa5}, {0x0e, 0x3c, 0xa5}, {0x0e, 0x3c, 0xa5}, + {0x0e, 0x3c, 0xa5}, {0x0e, 0x3c, 0xa5}, {0x0e, 0x3c, 0xa5}, {0x0e, 0x3c, 0xa5}, {0x0e, 0x3d, 0xa5}, {0x0f, 0x3d, 0xa5}, + {0x0f, 0x3d, 0xa6}, {0x0f, 0x3d, 0xa6}, {0x0f, 0x3d, 0xa6}, {0x0f, 0x3d, 0xa6}, {0x0f, 0x3d, 0xa6}, {0x0f, 0x3e, 0xa6}, + {0x0f, 0x3e, 0xa6}, {0x0f, 0x3e, 0xa6}, {0x0f, 0x3e, 0xa6}, {0x10, 0x3e, 0xa6}, {0x10, 0x3e, 0xa6}, {0x10, 0x3e, 0xa6}, + {0x10, 0x3f, 0xa7}, {0x10, 0x3f, 0xa7}, {0x10, 0x3f, 0xa7}, {0x10, 0x3f, 0xa7}, {0x10, 0x3f, 0xa7}, {0x10, 0x3f, 0xa7}, + {0x10, 0x40, 0xa7}, {0x10, 0x40, 0xa7}, {0x11, 0x40, 0xa7}, {0x11, 0x40, 0xa7}, {0x11, 0x40, 0xa7}, {0x11, 0x40, 0xa7}, + {0x11, 0x40, 0xa8}, {0x11, 0x41, 0xa8}, {0x11, 0x41, 0xa8}, {0x11, 0x41, 0xa8}, {0x11, 0x41, 0xa8}, {0x11, 0x41, 0xa8}, + {0x12, 0x41, 0xa8}, {0x12, 0x41, 0xa8}, {0x12, 0x42, 0xa8}, {0x12, 0x42, 0xa8}, {0x12, 0x42, 0xa8}, {0x12, 0x42, 0xa8}, + {0x12, 0x42, 0xa9}, {0x12, 0x42, 0xa9}, {0x12, 0x42, 0xa9}, {0x12, 0x43, 0xa9}, {0x13, 0x43, 0xa9}, {0x13, 0x43, 0xa9}, + {0x13, 0x43, 0xa9}, {0x13, 0x43, 0xa9}, {0x13, 0x43, 0xa9}, {0x13, 0x43, 0xa9}, {0x13, 0x44, 0xa9}, {0x13, 0x44, 0xa9}, + {0x13, 0x44, 0xaa}, {0x13, 0x44, 0xaa}, {0x14, 0x44, 0xaa}, {0x14, 0x44, 0xaa}, {0x14, 0x44, 0xaa}, {0x14, 0x45, 0xaa}, + {0x14, 0x45, 0xaa}, {0x14, 0x45, 0xaa}, {0x14, 0x45, 0xaa}, {0x14, 0x45, 0xaa}, {0x14, 0x45, 0xaa}, {0x14, 0x45, 0xaa}, + {0x14, 0x46, 0xab}, {0x15, 0x46, 0xab}, {0x15, 0x46, 0xab}, {0x15, 0x46, 0xab}, {0x15, 0x46, 0xab}, {0x15, 0x46, 0xab}, + {0x15, 0x46, 0xab}, {0x15, 0x47, 0xab}, {0x15, 0x47, 0xab}, {0x15, 0x47, 0xab}, {0x15, 0x47, 0xab}, {0x16, 0x47, 0xac}, + {0x16, 0x47, 0xac}, {0x16, 0x47, 0xac}, {0x16, 0x48, 0xac}, {0x16, 0x48, 0xac}, {0x16, 0x48, 0xac}, {0x16, 0x48, 0xac}, + {0x16, 0x48, 0xac}, {0x16, 0x48, 0xac}, {0x16, 0x48, 0xac}, {0x17, 0x49, 0xac}, {0x17, 0x49, 0xac}, {0x17, 0x49, 0xad}, + {0x17, 0x49, 0xad}, {0x17, 0x49, 0xad}, {0x17, 0x49, 0xad}, {0x17, 0x49, 0xad}, {0x17, 0x4a, 0xad}, {0x17, 0x4a, 0xad}, + {0x17, 0x4a, 0xad}, {0x18, 0x4a, 0xad}, {0x18, 0x4a, 0xad}, {0x18, 0x4a, 0xad}, {0x18, 0x4a, 0xad}, {0x18, 0x4b, 0xae}, + {0x18, 0x4b, 0xae}, {0x18, 0x4b, 0xae}, {0x18, 0x4b, 0xae}, {0x18, 0x4b, 0xae}, {0x18, 0x4b, 0xae}, {0x19, 0x4b, 0xae}, + {0x19, 0x4c, 0xae}, {0x19, 0x4c, 0xae}, {0x19, 0x4c, 0xae}, {0x19, 0x4c, 0xae}, {0x19, 0x4c, 0xae}, {0x19, 0x4c, 0xaf}, + {0x19, 0x4c, 0xaf}, {0x19, 0x4d, 0xaf}, {0x19, 0x4d, 0xaf}, {0x19, 0x4d, 0xaf}, {0x1a, 0x4d, 0xaf}, {0x1a, 0x4d, 0xaf}, + {0x1a, 0x4d, 0xaf}, {0x1a, 0x4d, 0xaf}, {0x1a, 0x4e, 0xaf}, {0x1a, 0x4e, 0xaf}, {0x1a, 0x4e, 0xaf}, {0x1a, 0x4e, 0xb0}, + {0x1a, 0x4e, 0xb0}, {0x1a, 0x4e, 0xb0}, {0x1b, 0x4e, 0xb0}, {0x1b, 0x4f, 0xb0}, {0x1b, 0x4f, 0xb0}, {0x1b, 0x4f, 0xb0}, + {0x1b, 0x4f, 0xb0}, {0x1b, 0x4f, 0xb0}, {0x1b, 0x4f, 0xb0}, {0x1b, 0x4f, 0xb0}, {0x1b, 0x50, 0xb0}, {0x1b, 0x50, 0xb1}, + {0x1c, 0x50, 0xb1}, {0x1c, 0x50, 0xb1}, {0x1c, 0x50, 0xb1}, {0x1c, 0x50, 0xb1}, {0x1c, 0x50, 0xb1}, {0x1c, 0x51, 0xb1}, + {0x1c, 0x51, 0xb1}, {0x1c, 0x51, 0xb1}, {0x1c, 0x51, 0xb1}, {0x1c, 0x51, 0xb1}, {0x1d, 0x51, 0xb1}, {0x1d, 0x51, 0xb2}, + {0x1d, 0x52, 0xb2}, {0x1d, 0x52, 0xb2}, {0x1d, 0x52, 0xb2}, {0x1d, 0x52, 0xb2}, {0x1d, 0x52, 0xb2}, {0x1d, 0x52, 0xb2}, + {0x1d, 0x52, 0xb2}, {0x1d, 0x53, 0xb2}, {0x1e, 0x53, 0xb2}, {0x1e, 0x53, 0xb2}, {0x1e, 0x53, 0xb2}, {0x1e, 0x53, 0xb3}, + {0x1e, 0x53, 0xb3}, {0x1e, 0x53, 0xb3}, {0x1e, 0x54, 0xb3}, {0x1e, 0x54, 0xb3}, {0x1e, 0x54, 0xb3}, {0x1e, 0x54, 0xb3}, + {0x1e, 0x54, 0xb3}, {0x1f, 0x54, 0xb3}, {0x1f, 0x55, 0xb3}, {0x1f, 0x55, 0xb3}, {0x1f, 0x55, 0xb4}, {0x1f, 0x55, 0xb4}, + {0x1f, 0x55, 0xb4}, {0x1f, 0x55, 0xb4}, {0x1f, 0x55, 0xb4}, {0x1f, 0x56, 0xb4}, {0x1f, 0x56, 0xb4}, {0x20, 0x56, 0xb4}, + {0x20, 0x56, 0xb4}, {0x20, 0x56, 0xb4}, {0x20, 0x56, 0xb4}, {0x20, 0x56, 0xb4}, {0x20, 0x57, 0xb5}, {0x20, 0x57, 0xb5}, + {0x20, 0x57, 0xb5}, {0x20, 0x57, 0xb5}, {0x20, 0x57, 0xb5}, {0x21, 0x57, 0xb5}, {0x21, 0x57, 0xb5}, {0x21, 0x58, 0xb5}, + {0x21, 0x58, 0xb5}, {0x21, 0x58, 0xb5}, {0x21, 0x58, 0xb5}, {0x21, 0x58, 0xb5}, {0x21, 0x58, 0xb6}, {0x21, 0x58, 0xb6}, + {0x21, 0x59, 0xb6}, {0x22, 0x59, 0xb6}, {0x22, 0x59, 0xb6}, {0x22, 0x59, 0xb6}, {0x22, 0x59, 0xb6}, {0x22, 0x59, 0xb6}, + {0x22, 0x59, 0xb6}, {0x22, 0x5a, 0xb6}, {0x22, 0x5a, 0xb6}, {0x22, 0x5a, 0xb6}, {0x22, 0x5a, 0xb7}, {0x23, 0x5a, 0xb7}, + {0x23, 0x5a, 0xb7}, {0x23, 0x5a, 0xb7}, {0x23, 0x5b, 0xb7}, {0x23, 0x5b, 0xb7}, {0x23, 0x5b, 0xb7}, {0x23, 0x5b, 0xb7}, + {0x23, 0x5b, 0xb7}, {0x23, 0x5b, 0xb7}, {0x23, 0x5b, 0xb7}, {0x23, 0x5c, 0xb7}, {0x24, 0x5c, 0xb8}, {0x24, 0x5c, 0xb8}, + {0x24, 0x5c, 0xb8}, {0x24, 0x5c, 0xb8}, {0x24, 0x5c, 0xb8}, {0x24, 0x5c, 0xb8}, {0x24, 0x5d, 0xb8}, {0x24, 0x5d, 0xb8}, + {0x24, 0x5d, 0xb8}, {0x24, 0x5d, 0xb8}, {0x25, 0x5d, 0xb8}, {0x25, 0x5d, 0xb8}, {0x25, 0x5d, 0xb9}, {0x25, 0x5e, 0xb9}, + {0x25, 0x5e, 0xb9}, {0x25, 0x5e, 0xb9}, {0x25, 0x5e, 0xb9}, {0x25, 0x5e, 0xb9}, {0x25, 0x5e, 0xb9}, {0x25, 0x5e, 0xb9}, + {0x26, 0x5f, 0xb9}, {0x26, 0x5f, 0xb9}, {0x26, 0x5f, 0xb9}, {0x26, 0x5f, 0xb9}, {0x26, 0x5f, 0xba}, {0x26, 0x5f, 0xba}, + {0x26, 0x5f, 0xba}, {0x26, 0x60, 0xba}, {0x26, 0x60, 0xba}, {0x26, 0x60, 0xba}, {0x27, 0x60, 0xba}, {0x27, 0x60, 0xba}, + {0x27, 0x60, 0xba}, {0x27, 0x60, 0xba}, {0x27, 0x61, 0xba}, {0x27, 0x61, 0xba}, {0x27, 0x61, 0xbb}, {0x27, 0x61, 0xbb}, + {0x27, 0x61, 0xbb}, {0x27, 0x61, 0xbb}, {0x27, 0x61, 0xbb}, {0x28, 0x62, 0xbb}, {0x28, 0x62, 0xbb}, {0x28, 0x62, 0xbb}, + {0x28, 0x62, 0xbb}, {0x28, 0x62, 0xbb}, {0x28, 0x62, 0xbb}, {0x28, 0x62, 0xbc}, {0x28, 0x63, 0xbc}, {0x28, 0x63, 0xbc}, + {0x28, 0x63, 0xbc}, {0x29, 0x63, 0xbc}, {0x29, 0x63, 0xbc}, {0x29, 0x63, 0xbc}, {0x29, 0x63, 0xbc}, {0x29, 0x64, 0xbc}, + {0x29, 0x64, 0xbc}, {0x29, 0x64, 0xbc}, {0x29, 0x64, 0xbc}, {0x29, 0x64, 0xbd}, {0x29, 0x64, 0xbd}, {0x2a, 0x64, 0xbd}, + {0x2a, 0x65, 0xbd}, {0x2a, 0x65, 0xbd}, {0x2a, 0x65, 0xbd}, {0x2a, 0x65, 0xbd}, {0x2a, 0x65, 0xbd}, {0x2a, 0x65, 0xbd}, + {0x2a, 0x65, 0xbd}, {0x2a, 0x66, 0xbd}, {0x2a, 0x66, 0xbd}, {0x2b, 0x66, 0xbe}, {0x2b, 0x66, 0xbe}, {0x2b, 0x66, 0xbe}, + {0x2b, 0x66, 0xbe}, {0x2b, 0x66, 0xbe}, {0x2b, 0x67, 0xbe}, {0x2b, 0x67, 0xbe}, {0x2b, 0x67, 0xbe}, {0x2b, 0x67, 0xbe}, + {0x2b, 0x67, 0xbe}, {0x2c, 0x67, 0xbe}, {0x2c, 0x67, 0xbe}, {0x2c, 0x68, 0xbf}, {0x2c, 0x68, 0xbf}, {0x2c, 0x68, 0xbf}, + {0x2c, 0x68, 0xbf}, {0x2c, 0x68, 0xbf}, {0x2c, 0x68, 0xbf}, {0x2c, 0x68, 0xbf}, {0x2c, 0x69, 0xbf}, {0x2c, 0x69, 0xbf}, + {0x2d, 0x69, 0xbf}, {0x2d, 0x69, 0xbf}, {0x2d, 0x69, 0xbf}, {0x2d, 0x69, 0xc0}, {0x2d, 0x6a, 0xc0}, {0x2d, 0x6a, 0xc0}, + {0x2d, 0x6a, 0xc0}, {0x2d, 0x6a, 0xc0}, {0x2d, 0x6a, 0xc0}, {0x2d, 0x6a, 0xc0}, {0x2e, 0x6a, 0xc0}, {0x2e, 0x6b, 0xc0}, + {0x2e, 0x6b, 0xc0}, {0x2e, 0x6b, 0xc0}, {0x2e, 0x6b, 0xc0}, {0x2e, 0x6b, 0xc1}, {0x2e, 0x6b, 0xc1}, {0x2e, 0x6b, 0xc1}, + {0x2e, 0x6c, 0xc1}, {0x2e, 0x6c, 0xc1}, {0x2f, 0x6c, 0xc1}, {0x2f, 0x6c, 0xc1}, {0x2f, 0x6c, 0xc1}, {0x2f, 0x6c, 0xc1}, + {0x2f, 0x6c, 0xc1}, {0x2f, 0x6d, 0xc1}, {0x2f, 0x6d, 0xc1}, {0x2f, 0x6d, 0xc2}, {0x2f, 0x6d, 0xc2}, {0x2f, 0x6d, 0xc2}, + {0x30, 0x6d, 0xc2}, {0x30, 0x6d, 0xc2}, {0x30, 0x6e, 0xc2}, {0x30, 0x6e, 0xc2}, {0x30, 0x6e, 0xc2}, {0x30, 0x6e, 0xc2}, + {0x30, 0x6e, 0xc2}, {0x30, 0x6e, 0xc2}, {0x30, 0x6e, 0xc2}, {0x30, 0x6f, 0xc3}, {0x31, 0x6f, 0xc3}, {0x31, 0x6f, 0xc3}, + {0x31, 0x6f, 0xc3}, {0x31, 0x6f, 0xc3}, {0x31, 0x6f, 0xc3}, {0x31, 0x6f, 0xc3}, {0x31, 0x70, 0xc3}, {0x31, 0x70, 0xc3}, + {0x31, 0x70, 0xc3}, {0x31, 0x70, 0xc3}, {0x31, 0x70, 0xc3}, {0x32, 0x70, 0xc4}, {0x32, 0x70, 0xc4}, {0x32, 0x71, 0xc4}, + {0x32, 0x71, 0xc4}, {0x32, 0x71, 0xc4}, {0x32, 0x71, 0xc4}, {0x32, 0x71, 0xc4}, {0x32, 0x71, 0xc4}, {0x32, 0x71, 0xc4}, + {0x32, 0x72, 0xc4}, {0x33, 0x72, 0xc4}, {0x33, 0x72, 0xc5}, {0x33, 0x72, 0xc5}, {0x33, 0x72, 0xc5}, {0x33, 0x72, 0xc5}, + {0x33, 0x72, 0xc5}, {0x33, 0x73, 0xc5}, {0x33, 0x73, 0xc5}, {0x33, 0x73, 0xc5}, {0x33, 0x73, 0xc5}, {0x34, 0x73, 0xc5}, + {0x34, 0x73, 0xc5}, {0x34, 0x73, 0xc5}, {0x34, 0x74, 0xc6}, {0x34, 0x74, 0xc6}, {0x34, 0x74, 0xc6}, {0x34, 0x74, 0xc6}, + {0x34, 0x74, 0xc6}, {0x34, 0x74, 0xc6}, {0x34, 0x74, 0xc6}, {0x35, 0x75, 0xc6}, {0x35, 0x75, 0xc6}, {0x35, 0x75, 0xc6}, + {0x35, 0x75, 0xc6}, {0x35, 0x75, 0xc6}, {0x35, 0x75, 0xc7}, {0x35, 0x75, 0xc7}, {0x35, 0x76, 0xc7}, {0x35, 0x76, 0xc7}, + {0x35, 0x76, 0xc7}, {0x36, 0x76, 0xc7}, {0x36, 0x76, 0xc7}, {0x36, 0x76, 0xc7}, {0x36, 0x76, 0xc7}, {0x36, 0x77, 0xc7}, + {0x36, 0x77, 0xc7}, {0x36, 0x77, 0xc7}, {0x36, 0x77, 0xc8}, {0x36, 0x77, 0xc8}, {0x36, 0x77, 0xc8}, {0x36, 0x77, 0xc8}, + {0x37, 0x78, 0xc8}, {0x37, 0x78, 0xc8}, {0x37, 0x78, 0xc8}, {0x37, 0x78, 0xc8}, {0x37, 0x78, 0xc8}, {0x37, 0x78, 0xc8}, + {0x37, 0x78, 0xc8}, {0x37, 0x79, 0xc8}, {0x37, 0x79, 0xc9}, {0x37, 0x79, 0xc9}, {0x38, 0x79, 0xc9}, {0x38, 0x79, 0xc9}, + {0x38, 0x79, 0xc9}, {0x38, 0x79, 0xc9}, {0x38, 0x7a, 0xc9}, {0x38, 0x7a, 0xc9}, {0x38, 0x7a, 0xc9}, {0x38, 0x7a, 0xc9}, + {0x38, 0x7a, 0xc9}, {0x38, 0x7a, 0xc9}, {0x39, 0x7a, 0xca}, {0x39, 0x7b, 0xca}, {0x39, 0x7b, 0xca}, {0x39, 0x7b, 0xca}, + {0x39, 0x7b, 0xca}, {0x39, 0x7b, 0xca}, {0x39, 0x7b, 0xca}, {0x39, 0x7b, 0xca}, {0x39, 0x7c, 0xca}, {0x39, 0x7c, 0xca}, + {0x3a, 0x7c, 0xca}, {0x3a, 0x7c, 0xca}, {0x3a, 0x7c, 0xcb}, {0x3a, 0x7c, 0xcb}, {0x3a, 0x7c, 0xcb}, {0x3a, 0x7d, 0xcb}, + {0x3a, 0x7d, 0xcb}, {0x3a, 0x7d, 0xcb}, {0x3a, 0x7d, 0xcb}, {0x3a, 0x7d, 0xcb}, {0x3a, 0x7d, 0xcb}, {0x3b, 0x7d, 0xcb}, + {0x3b, 0x7e, 0xcb}, {0x3b, 0x7e, 0xcb}, {0x3b, 0x7e, 0xcc}, {0x3b, 0x7e, 0xcc}, {0x3b, 0x7e, 0xcc}, {0x3b, 0x7e, 0xcc}, + {0x3b, 0x7f, 0xcc}, {0x3b, 0x7f, 0xcc}, {0x3b, 0x7f, 0xcc}, {0x3c, 0x7f, 0xcc}, {0x3c, 0x7f, 0xcc}, {0x3c, 0x7f, 0xcc}, + {0x3c, 0x7f, 0xcc}, {0x3c, 0x80, 0xcd}, {0x3c, 0x80, 0xcd}, {0x3c, 0x80, 0xcd}, {0x3c, 0x80, 0xcd}, {0x3c, 0x80, 0xcd}, + {0x3c, 0x80, 0xcd}, {0x3d, 0x80, 0xcd}, {0x3d, 0x81, 0xcd}, {0x3d, 0x81, 0xcd}, {0x3d, 0x81, 0xcd}, {0x3d, 0x81, 0xcd}, + {0x3d, 0x81, 0xcd}, {0x3d, 0x81, 0xce}, {0x3d, 0x81, 0xce}, {0x3d, 0x82, 0xce}, {0x3d, 0x82, 0xce}, {0x3e, 0x82, 0xce}, + {0x3e, 0x82, 0xce}, {0x3e, 0x82, 0xce}, {0x3e, 0x82, 0xce}, {0x3e, 0x82, 0xce}, {0x3e, 0x83, 0xce}, {0x3e, 0x83, 0xce}, + {0x3e, 0x83, 0xce}, {0x3e, 0x83, 0xcf}, {0x3e, 0x83, 0xcf}, {0x3f, 0x83, 0xcf}, {0x3f, 0x83, 0xcf}, {0x3f, 0x84, 0xcf}, + {0x3f, 0x84, 0xcf}, {0x3f, 0x84, 0xcf}, {0x3f, 0x84, 0xcf}, {0x3f, 0x84, 0xcf}, {0x3f, 0x84, 0xcf}, {0x3f, 0x84, 0xcf}, + {0x3f, 0x85, 0xcf}, {0x3f, 0x85, 0xd0}, {0x40, 0x85, 0xd0}, {0x40, 0x85, 0xd0}, {0x40, 0x85, 0xd0}, {0x40, 0x85, 0xd0}, + {0x40, 0x85, 0xd0}, {0x40, 0x86, 0xd0}, {0x40, 0x86, 0xd0}, {0x40, 0x86, 0xd0}, {0x40, 0x86, 0xd0}, {0x40, 0x86, 0xd0}, + {0x41, 0x86, 0xd0}, {0x41, 0x86, 0xd1}, {0x41, 0x87, 0xd1}, {0x41, 0x87, 0xd1}, {0x41, 0x87, 0xd1}, {0x41, 0x87, 0xd1}, + {0x41, 0x87, 0xd1}, {0x41, 0x87, 0xd1}, {0x41, 0x87, 0xd1}, {0x41, 0x88, 0xd1}, {0x42, 0x88, 0xd1}, {0x42, 0x88, 0xd1}, + {0x42, 0x88, 0xd1}, {0x42, 0x88, 0xd2}, {0x42, 0x88, 0xd2}, {0x42, 0x88, 0xd2}, {0x42, 0x89, 0xd2}, {0x42, 0x89, 0xd2}, + {0x42, 0x89, 0xd2}, {0x42, 0x89, 0xd2}, {0x43, 0x89, 0xd2}, {0x43, 0x89, 0xd2}, {0x43, 0x89, 0xd2}, {0x43, 0x8a, 0xd2}, + {0x43, 0x8a, 0xd2}, {0x43, 0x8a, 0xd3}, {0x43, 0x8a, 0xd3}, {0x43, 0x8a, 0xd3}, {0x43, 0x8a, 0xd3}, {0x43, 0x8a, 0xd3}, + {0x44, 0x8b, 0xd3}, {0x44, 0x8b, 0xd3}, {0x44, 0x8b, 0xd3}, {0x44, 0x8b, 0xd3}, {0x44, 0x8b, 0xd3}, {0x44, 0x8b, 0xd3}, + {0x44, 0x8b, 0xd3}, {0x44, 0x8c, 0xd4}, {0x44, 0x8c, 0xd4}, {0x44, 0x8c, 0xd4}, {0x44, 0x8c, 0xd4}, {0x45, 0x8c, 0xd4}, + {0x45, 0x8c, 0xd4}, {0x45, 0x8c, 0xd4}, {0x45, 0x8d, 0xd4}, {0x45, 0x8d, 0xd4}, {0x45, 0x8d, 0xd4}, {0x45, 0x8d, 0xd4}, + {0x45, 0x8d, 0xd4}, {0x45, 0x8d, 0xd5}, {0x45, 0x8d, 0xd5}, {0x46, 0x8e, 0xd5}, {0x46, 0x8e, 0xd5}, {0x46, 0x8e, 0xd5}, + {0x46, 0x8e, 0xd5}, {0x46, 0x8e, 0xd5}, {0x46, 0x8e, 0xd5}, {0x46, 0x8e, 0xd5}, {0x46, 0x8f, 0xd5}, {0x46, 0x8f, 0xd5}, + {0x46, 0x8f, 0xd6}, {0x47, 0x8f, 0xd6}, {0x47, 0x8f, 0xd6}, {0x47, 0x8f, 0xd6}, {0x47, 0x8f, 0xd6}, {0x47, 0x90, 0xd6}, + {0x47, 0x90, 0xd6}, {0x47, 0x90, 0xd6}, {0x47, 0x90, 0xd6}, {0x47, 0x90, 0xd6}, {0x47, 0x90, 0xd6}, {0x48, 0x90, 0xd6}, + {0x48, 0x91, 0xd7}, {0x48, 0x91, 0xd7}, {0x48, 0x91, 0xd7}, {0x48, 0x91, 0xd7}, {0x48, 0x91, 0xd7}, {0x48, 0x91, 0xd7}, + {0x48, 0x91, 0xd7}, {0x48, 0x92, 0xd7}, {0x48, 0x92, 0xd7}, {0x49, 0x92, 0xd7}, {0x49, 0x92, 0xd7}, {0x49, 0x92, 0xd7}, + {0x49, 0x92, 0xd8}, {0x49, 0x92, 0xd8}, {0x49, 0x93, 0xd8}, {0x49, 0x93, 0xd8}, {0x49, 0x93, 0xd8}, {0x49, 0x93, 0xd8}, + {0x49, 0x93, 0xd8}, {0x49, 0x93, 0xd8}, {0x4a, 0x94, 0xd8}, {0x4a, 0x94, 0xd8}, {0x4a, 0x94, 0xd8}, {0x4a, 0x94, 0xd8}, + {0x4a, 0x94, 0xd9}, {0x4a, 0x94, 0xd9}, {0x4a, 0x94, 0xd9}, {0x4a, 0x95, 0xd9}, {0x4a, 0x95, 0xd9}, {0x4a, 0x95, 0xd9}, + {0x4b, 0x95, 0xd9}, {0x4b, 0x95, 0xd9}, {0x4b, 0x95, 0xd9}, {0x4b, 0x95, 0xd9}, {0x4b, 0x96, 0xd9}, {0x4b, 0x96, 0xd9}, + {0x4b, 0x96, 0xda}, {0x4b, 0x96, 0xda}, {0x4b, 0x96, 0xda}, {0x4b, 0x96, 0xda}, {0x4c, 0x96, 0xda}, {0x4c, 0x97, 0xda}, + {0x4c, 0x97, 0xda}, {0x4c, 0x97, 0xda}, {0x4c, 0x97, 0xda}, {0x4c, 0x97, 0xda}, {0x4c, 0x97, 0xda}, {0x4c, 0x97, 0xda}, + {0x4c, 0x98, 0xdb}, {0x4c, 0x98, 0xdb}, {0x4d, 0x98, 0xdb}, {0x4d, 0x98, 0xdb}, {0x4d, 0x98, 0xdb}, {0x4d, 0x98, 0xdb}, + {0x4d, 0x98, 0xdb}, {0x4d, 0x99, 0xdb}, {0x4d, 0x99, 0xdb}, {0x4d, 0x99, 0xdb}, {0x4d, 0x99, 0xdb}, {0x4d, 0x99, 0xdb}, + {0x4d, 0x99, 0xdc}, {0x4e, 0x99, 0xdc}, {0x4e, 0x9a, 0xdc}, {0x4e, 0x9a, 0xdc}, {0x4e, 0x9a, 0xdc}, {0x4e, 0x9a, 0xdc}, + {0x4e, 0x9a, 0xdc}, {0x4e, 0x9a, 0xdc}, {0x4f, 0x9a, 0xdc}, {0x4f, 0x9b, 0xdc}, {0x4f, 0x9b, 0xdc}, {0x4f, 0x9b, 0xdc}, + {0x4f, 0x9b, 0xdc}, {0x50, 0x9b, 0xdd}, {0x50, 0x9b, 0xdd}, {0x50, 0x9b, 0xdd}, {0x50, 0x9c, 0xdd}, {0x50, 0x9c, 0xdd}, + {0x51, 0x9c, 0xdd}, {0x51, 0x9c, 0xdd}, {0x51, 0x9c, 0xdd}, {0x51, 0x9c, 0xdd}, {0x51, 0x9d, 0xdd}, {0x51, 0x9d, 0xdd}, + {0x52, 0x9d, 0xdd}, {0x52, 0x9d, 0xdd}, {0x52, 0x9d, 0xdd}, {0x52, 0x9d, 0xde}, {0x52, 0x9d, 0xde}, {0x53, 0x9e, 0xde}, + {0x53, 0x9e, 0xde}, {0x53, 0x9e, 0xde}, {0x53, 0x9e, 0xde}, {0x53, 0x9e, 0xde}, {0x54, 0x9e, 0xde}, {0x54, 0x9e, 0xde}, + {0x54, 0x9f, 0xde}, {0x54, 0x9f, 0xde}, {0x54, 0x9f, 0xde}, {0x55, 0x9f, 0xde}, {0x55, 0x9f, 0xde}, {0x55, 0x9f, 0xdf}, + {0x55, 0xa0, 0xdf}, {0x55, 0xa0, 0xdf}, {0x56, 0xa0, 0xdf}, {0x56, 0xa0, 0xdf}, {0x56, 0xa0, 0xdf}, {0x56, 0xa0, 0xdf}, + {0x56, 0xa0, 0xdf}, {0x57, 0xa1, 0xdf}, {0x57, 0xa1, 0xdf}, {0x57, 0xa1, 0xdf}, {0x57, 0xa1, 0xdf}, {0x57, 0xa1, 0xdf}, + {0x58, 0xa1, 0xdf}, {0x58, 0xa1, 0xdf}, {0x58, 0xa2, 0xe0}, {0x58, 0xa2, 0xe0}, {0x58, 0xa2, 0xe0}, {0x59, 0xa2, 0xe0}, + {0x59, 0xa2, 0xe0}, {0x59, 0xa2, 0xe0}, {0x59, 0xa3, 0xe0}, {0x59, 0xa3, 0xe0}, {0x5a, 0xa3, 0xe0}, {0x5a, 0xa3, 0xe0}, + {0x5a, 0xa3, 0xe0}, {0x5a, 0xa3, 0xe0}, {0x5a, 0xa3, 0xe0}, {0x5a, 0xa4, 0xe0}, {0x5b, 0xa4, 0xe1}, {0x5b, 0xa4, 0xe1}, + {0x5b, 0xa4, 0xe1}, {0x5b, 0xa4, 0xe1}, {0x5b, 0xa4, 0xe1}, {0x5c, 0xa4, 0xe1}, {0x5c, 0xa5, 0xe1}, {0x5c, 0xa5, 0xe1}, + {0x5c, 0xa5, 0xe1}, {0x5c, 0xa5, 0xe1}, {0x5d, 0xa5, 0xe1}, {0x5d, 0xa5, 0xe1}, {0x5d, 0xa5, 0xe1}, {0x5d, 0xa6, 0xe1}, + {0x5d, 0xa6, 0xe2}, {0x5e, 0xa6, 0xe2}, {0x5e, 0xa6, 0xe2}, {0x5e, 0xa6, 0xe2}, {0x5e, 0xa6, 0xe2}, {0x5e, 0xa7, 0xe2}, + {0x5f, 0xa7, 0xe2}, {0x5f, 0xa7, 0xe2}, {0x5f, 0xa7, 0xe2}, {0x5f, 0xa7, 0xe2}, {0x5f, 0xa7, 0xe2}, {0x60, 0xa7, 0xe2}, + {0x60, 0xa8, 0xe2}, {0x60, 0xa8, 0xe2}, {0x60, 0xa8, 0xe2}, {0x60, 0xa8, 0xe3}, {0x61, 0xa8, 0xe3}, {0x61, 0xa8, 0xe3}, + {0x61, 0xa8, 0xe3}, {0x61, 0xa9, 0xe3}, {0x61, 0xa9, 0xe3}, {0x62, 0xa9, 0xe3}, {0x62, 0xa9, 0xe3}, {0x62, 0xa9, 0xe3}, + {0x62, 0xa9, 0xe3}, {0x62, 0xaa, 0xe3}, {0x62, 0xaa, 0xe3}, {0x63, 0xaa, 0xe3}, {0x63, 0xaa, 0xe3}, {0x63, 0xaa, 0xe4}, + {0x63, 0xaa, 0xe4}, {0x63, 0xaa, 0xe4}, {0x64, 0xab, 0xe4}, {0x64, 0xab, 0xe4}, {0x64, 0xab, 0xe4}, {0x64, 0xab, 0xe4}, + {0x64, 0xab, 0xe4}, {0x65, 0xab, 0xe4}, {0x65, 0xab, 0xe4}, {0x65, 0xac, 0xe4}, {0x65, 0xac, 0xe4}, {0x65, 0xac, 0xe4}, + {0x66, 0xac, 0xe4}, {0x66, 0xac, 0xe5}, {0x66, 0xac, 0xe5}, {0x66, 0xad, 0xe5}, {0x66, 0xad, 0xe5}, {0x67, 0xad, 0xe5}, + {0x67, 0xad, 0xe5}, {0x67, 0xad, 0xe5}, {0x67, 0xad, 0xe5}, {0x67, 0xad, 0xe5}, {0x68, 0xae, 0xe5}, {0x68, 0xae, 0xe5}, + {0x68, 0xae, 0xe5}, {0x68, 0xae, 0xe5}, {0x68, 0xae, 0xe5}, {0x69, 0xae, 0xe5}, {0x69, 0xae, 0xe6}, {0x69, 0xaf, 0xe6}, + {0x69, 0xaf, 0xe6}, {0x69, 0xaf, 0xe6}, {0x6a, 0xaf, 0xe6}, {0x6a, 0xaf, 0xe6}, {0x6a, 0xaf, 0xe6}, {0x6a, 0xb0, 0xe6}, + {0x6a, 0xb0, 0xe6}, {0x6b, 0xb0, 0xe6}, {0x6b, 0xb0, 0xe6}, {0x6b, 0xb0, 0xe6}, {0x6b, 0xb0, 0xe6}, {0x6b, 0xb0, 0xe6}, + {0x6b, 0xb1, 0xe7}, {0x6c, 0xb1, 0xe7}, {0x6c, 0xb1, 0xe7}, {0x6c, 0xb1, 0xe7}, {0x6c, 0xb1, 0xe7}, {0x6c, 0xb1, 0xe7}, + {0x6d, 0xb1, 0xe7}, {0x6d, 0xb2, 0xe7}, {0x6d, 0xb2, 0xe7}, {0x6d, 0xb2, 0xe7}, {0x6d, 0xb2, 0xe7}, {0x6e, 0xb2, 0xe7}, + {0x6e, 0xb2, 0xe7}, {0x6e, 0xb3, 0xe7}, {0x6e, 0xb3, 0xe8}, {0x6e, 0xb3, 0xe8}, {0x6f, 0xb3, 0xe8}, {0x6f, 0xb3, 0xe8}, + {0x6f, 0xb3, 0xe8}, {0x6f, 0xb3, 0xe8}, {0x6f, 0xb4, 0xe8}, {0x70, 0xb4, 0xe8}, {0x70, 0xb4, 0xe8}, {0x70, 0xb4, 0xe8}, + {0x70, 0xb4, 0xe8}, {0x70, 0xb4, 0xe8}, {0x71, 0xb4, 0xe8}, {0x71, 0xb5, 0xe8}, {0x71, 0xb5, 0xe8}, {0x71, 0xb5, 0xe9}, + {0x71, 0xb5, 0xe9}, {0x72, 0xb5, 0xe9}, {0x72, 0xb5, 0xe9}, {0x72, 0xb5, 0xe9}, {0x72, 0xb6, 0xe9}, {0x72, 0xb6, 0xe9}, + {0x73, 0xb6, 0xe9}, {0x73, 0xb6, 0xe9}, {0x73, 0xb6, 0xe9}, {0x73, 0xb6, 0xe9}, {0x73, 0xb7, 0xe9}, {0x73, 0xb7, 0xe9}, + {0x74, 0xb7, 0xe9}, {0x74, 0xb7, 0xea}, {0x74, 0xb7, 0xea}, {0x74, 0xb7, 0xea}, {0x74, 0xb7, 0xea}, {0x75, 0xb8, 0xea}, + {0x75, 0xb8, 0xea}, {0x75, 0xb8, 0xea}, {0x75, 0xb8, 0xea}, {0x75, 0xb8, 0xea}, {0x76, 0xb8, 0xea}, {0x76, 0xb8, 0xea}, + {0x76, 0xb9, 0xea}, {0x76, 0xb9, 0xea}, {0x76, 0xb9, 0xea}, {0x77, 0xb9, 0xeb}, {0x77, 0xb9, 0xeb}, {0x77, 0xb9, 0xeb}, + {0x77, 0xba, 0xeb}, {0x77, 0xba, 0xeb}, {0x78, 0xba, 0xeb}, {0x78, 0xba, 0xeb}, {0x78, 0xba, 0xeb}, {0x78, 0xba, 0xeb}, + {0x78, 0xba, 0xeb}, {0x79, 0xbb, 0xeb}, {0x79, 0xbb, 0xeb}, {0x79, 0xbb, 0xeb}, {0x79, 0xbb, 0xeb}, {0x79, 0xbb, 0xeb}, + {0x7a, 0xbb, 0xec}, {0x7a, 0xbb, 0xec}, {0x7a, 0xbc, 0xec}, {0x7a, 0xbc, 0xec}, {0x7a, 0xbc, 0xec}, {0x7b, 0xbc, 0xec}, + {0x7b, 0xbc, 0xec}, {0x7b, 0xbc, 0xec}, {0x7b, 0xbd, 0xec}, {0x7b, 0xbd, 0xec}, {0x7c, 0xbd, 0xec}, {0x7c, 0xbd, 0xec}, + {0x7c, 0xbd, 0xec}, {0x7c, 0xbd, 0xec}, {0x7c, 0xbd, 0xed}, {0x7c, 0xbe, 0xed}, {0x7d, 0xbe, 0xed}, {0x7d, 0xbe, 0xed}, + {0x7d, 0xbe, 0xed}, {0x7d, 0xbe, 0xed}, {0x7d, 0xbe, 0xed}, {0x7e, 0xbe, 0xed}, {0x7e, 0xbf, 0xed}, {0x7e, 0xbf, 0xed}, + {0x7e, 0xbf, 0xed}, {0x7e, 0xbf, 0xed}, {0x7f, 0xbf, 0xed}, {0x7f, 0xbf, 0xed}, {0x7f, 0xc0, 0xee}, {0x7f, 0xc0, 0xee}, + {0x7f, 0xc0, 0xee}, {0x80, 0xc0, 0xee}, {0x80, 0xc0, 0xee}, {0x80, 0xc0, 0xee}, {0x80, 0xc0, 0xee}, {0x80, 0xc1, 0xee}, + {0x81, 0xc1, 0xee}, {0x81, 0xc1, 0xee}, {0x81, 0xc1, 0xee}, {0x81, 0xc1, 0xee}, {0x81, 0xc1, 0xee}, {0x82, 0xc1, 0xee}, + {0x82, 0xc2, 0xee}, {0x82, 0xc2, 0xef}, {0x82, 0xc2, 0xef}, {0x82, 0xc2, 0xef}, {0x83, 0xc2, 0xef}, {0x83, 0xc2, 0xef}, + {0x83, 0xc3, 0xef}, {0x83, 0xc3, 0xef}, {0x83, 0xc3, 0xef}, {0x84, 0xc3, 0xef}, {0x84, 0xc3, 0xef}, {0x84, 0xc3, 0xef}, + {0x84, 0xc3, 0xef}, {0x84, 0xc4, 0xef}, {0x84, 0xc4, 0xef}, {0x85, 0xc4, 0xf0}, {0x85, 0xc4, 0xf0}, {0x85, 0xc4, 0xf0}, + {0x85, 0xc4, 0xf0}, {0x85, 0xc4, 0xf0}, {0x86, 0xc5, 0xf0}, {0x86, 0xc5, 0xf0}, {0x86, 0xc5, 0xf0}, {0x86, 0xc5, 0xf0}, + {0x86, 0xc5, 0xf0}, {0x87, 0xc5, 0xf0}, {0x87, 0xc6, 0xf0}, {0x87, 0xc6, 0xf0}, {0x87, 0xc6, 0xf0}, {0x87, 0xc6, 0xf1}, + {0x88, 0xc6, 0xf1}, {0x88, 0xc6, 0xf1}, {0x88, 0xc6, 0xf1}, {0x88, 0xc7, 0xf1}, {0x88, 0xc7, 0xf1}, {0x89, 0xc7, 0xf1}, + {0x89, 0xc7, 0xf1}, {0x89, 0xc7, 0xf1}, {0x89, 0xc7, 0xf1}, {0x89, 0xc7, 0xf1}, {0x8a, 0xc8, 0xf1}, {0x8a, 0xc8, 0xf1}, + {0x8a, 0xc8, 0xf1}, {0x8a, 0xc8, 0xf1}, {0x8a, 0xc8, 0xf2}, {0x8b, 0xc8, 0xf2}, {0x8b, 0xc8, 0xf2}, {0x8b, 0xc9, 0xf2}, + {0x8b, 0xc9, 0xf2}, {0x8b, 0xc9, 0xf2}, {0x8c, 0xc9, 0xf2}, {0x8c, 0xc9, 0xf2}, {0x8c, 0xc9, 0xf2}, {0x8c, 0xca, 0xf2}, + {0x8c, 0xca, 0xf2}, {0x8d, 0xca, 0xf2}, {0x8d, 0xca, 0xf2}, {0x8d, 0xca, 0xf2}, {0x8d, 0xca, 0xf3}, {0x8d, 0xca, 0xf3}, + {0x8d, 0xcb, 0xf3}, {0x8e, 0xcb, 0xf3}, {0x8e, 0xcb, 0xf3}, {0x8e, 0xcb, 0xf3}, {0x8e, 0xcb, 0xf3}, {0x8e, 0xcb, 0xf3}, + {0x8f, 0xcb, 0xf3}, {0x8f, 0xcc, 0xf3}, {0x8f, 0xcc, 0xf3}, {0x8f, 0xcc, 0xf3}, {0x8f, 0xcc, 0xf3}, {0x90, 0xcc, 0xf3}, + {0x90, 0xcc, 0xf4}, {0x90, 0xcd, 0xf4}, {0x90, 0xcd, 0xf4}, {0x90, 0xcd, 0xf4}, {0x91, 0xcd, 0xf4}, {0x91, 0xcd, 0xf4}, + {0x91, 0xcd, 0xf4}, {0x91, 0xcd, 0xf4}, {0x91, 0xce, 0xf4}, {0x92, 0xce, 0xf4}, {0x92, 0xce, 0xf4}, {0x92, 0xce, 0xf4}, + {0x92, 0xce, 0xf4}, {0x92, 0xce, 0xf4}, {0x93, 0xce, 0xf4}, {0x93, 0xcf, 0xf5}, {0x93, 0xcf, 0xf5}, {0x93, 0xcf, 0xf5}, + {0x93, 0xcf, 0xf5}, {0x94, 0xcf, 0xf5}, {0x94, 0xcf, 0xf5}, {0x94, 0xd0, 0xf5}, {0x94, 0xd0, 0xf5}, {0x94, 0xd0, 0xf5}, + {0x95, 0xd0, 0xf5}, {0x95, 0xd0, 0xf5}, {0x95, 0xd0, 0xf5}, {0x95, 0xd0, 0xf5}, {0x95, 0xd1, 0xf5}, {0x96, 0xd1, 0xf6}, + {0x96, 0xd1, 0xf6}, {0x96, 0xd1, 0xf6}, {0x96, 0xd1, 0xf6}, {0x96, 0xd1, 0xf6}, {0x96, 0xd1, 0xf6}, {0x97, 0xd2, 0xf6}, + {0x97, 0xd2, 0xf6}, {0x97, 0xd2, 0xf6}, {0x97, 0xd2, 0xf6}, {0x97, 0xd2, 0xf6}, {0x98, 0xd2, 0xf6}, {0x98, 0xd3, 0xf6}, + {0x98, 0xd3, 0xf6}, {0x98, 0xd3, 0xf7}, {0x98, 0xd3, 0xf7}, {0x99, 0xd3, 0xf7}, {0x99, 0xd3, 0xf7}, {0x99, 0xd3, 0xf7}, + {0x99, 0xd4, 0xf7}, {0x99, 0xd4, 0xf7}, {0x9a, 0xd4, 0xf7}, {0x9a, 0xd4, 0xf7}, {0x9a, 0xd4, 0xf7}, {0x9a, 0xd4, 0xf7}, + {0x9a, 0xd4, 0xf7}, {0x9b, 0xd5, 0xf7}, {0x9b, 0xd5, 0xf7}, {0x9b, 0xd5, 0xf7}, {0x9b, 0xd5, 0xf8}, {0x9b, 0xd5, 0xf8}, + {0x9c, 0xd5, 0xf8}, {0x9c, 0xd6, 0xf8}, {0x9c, 0xd6, 0xf8}, {0x9c, 0xd6, 0xf8}, {0x9c, 0xd6, 0xf8}, {0x9d, 0xd6, 0xf8}, + {0x9d, 0xd6, 0xf8}, {0x9d, 0xd6, 0xf8}, {0x9d, 0xd7, 0xf8}, {0x9d, 0xd7, 0xf8}, {0x9e, 0xd7, 0xf8}, {0x9e, 0xd7, 0xf8}, + {0x9e, 0xd7, 0xf9}, {0x9e, 0xd7, 0xf9}, {0x9e, 0xd7, 0xf9}, {0x9e, 0xd8, 0xf9}, {0x9f, 0xd8, 0xf9}, {0x9f, 0xd8, 0xf9}, + {0x9f, 0xd8, 0xf9}, {0x9f, 0xd8, 0xf9}, {0x9f, 0xd8, 0xf9}, {0xa0, 0xd8, 0xf9}, {0xa0, 0xd9, 0xf9}, {0xa0, 0xd9, 0xf9}, + {0xa0, 0xd9, 0xf9}, {0xa0, 0xd9, 0xf9}, {0xa1, 0xd9, 0xfa}, {0xa1, 0xd9, 0xfa}, {0xa1, 0xda, 0xfa}, {0xa1, 0xda, 0xfa}, + {0xa1, 0xda, 0xfa}, {0xa2, 0xda, 0xfa}, {0xa2, 0xda, 0xfa}, {0xa2, 0xda, 0xfa}, {0xa2, 0xda, 0xfa}, {0xa2, 0xdb, 0xfa}, + {0xa3, 0xdb, 0xfa}, {0xa3, 0xdb, 0xfa}, {0xa3, 0xdb, 0xfa}, {0xa3, 0xdb, 0xfa}, {0xa3, 0xdb, 0xfa}, {0xa4, 0xdb, 0xfb}, + {0xa4, 0xdc, 0xfb}, {0xa4, 0xdc, 0xfb}, {0xa4, 0xdc, 0xfb}, {0xa4, 0xdc, 0xfb}, {0xa5, 0xdc, 0xfb}, {0xa5, 0xdc, 0xfb}, + {0xa5, 0xdd, 0xfb}, {0xa5, 0xdd, 0xfb}, {0xa5, 0xdd, 0xfb}, {0xa6, 0xdd, 0xfb}, {0xa6, 0xdd, 0xfb}, {0xa6, 0xdd, 0xfb}, + {0xa6, 0xdd, 0xfb}, {0xa6, 0xde, 0xfc}, {0xa7, 0xde, 0xfc}, {0xa7, 0xde, 0xfc}, {0xa7, 0xde, 0xfc}, {0xa7, 0xde, 0xfc}, + {0xa7, 0xde, 0xfc}, {0xa7, 0xde, 0xfc}, {0xa8, 0xdf, 0xfc}, {0xa8, 0xdf, 0xfc}, {0xa8, 0xdf, 0xfc}, {0xa8, 0xdf, 0xfc}, + {0xa8, 0xdf, 0xfc}, {0xa9, 0xdf, 0xfc}, {0xa9, 0xe0, 0xfc}, {0xa9, 0xe0, 0xfd}, {0xa9, 0xe0, 0xfd}, {0xa9, 0xe0, 0xfd}, + {0xaa, 0xe0, 0xfd}, {0xaa, 0xe0, 0xfd}, {0xaa, 0xe0, 0xfd}, {0xaa, 0xe1, 0xfd}, {0xaa, 0xe1, 0xfd}, {0xab, 0xe1, 0xfd}, + {0xab, 0xe1, 0xfd}, {0xab, 0xe1, 0xfd}, {0xab, 0xe1, 0xfd}, {0xab, 0xe1, 0xfd}, {0xac, 0xe2, 0xfd}, {0xac, 0xe2, 0xfd}, + {0xac, 0xe2, 0xfe}, {0xac, 0xe2, 0xfe}, {0xac, 0xe2, 0xfe}, {0xad, 0xe2, 0xfe}, {0xad, 0xe3, 0xfe}, {0xad, 0xe3, 0xfe}, + {0xad, 0xe3, 0xfe}, {0xad, 0xe3, 0xfe}, {0xae, 0xe3, 0xfe}, {0xae, 0xe3, 0xfe}, {0xae, 0xe3, 0xfe}, {0xae, 0xe4, 0xfe}, + {0xae, 0xe4, 0xfe}, {0xaf, 0xe4, 0xfe}, {0xaf, 0xe4, 0xff}, {0xaf, 0xe4, 0xff}, {0xaf, 0xe4, 0xff}, {0xaf, 0xe4, 0xff}, + {0xaf, 0xe5, 0xff}, {0xb0, 0xe5, 0xff}, {0xb0, 0xe5, 0xff}, {0xb0, 0xe5, 0xff}, {0xb0, 0xe5, 0xff}, {0xb0, 0xe5, 0xff}, + {0xb1, 0xe5, 0xff}, {0xb1, 0xe5, 0xff}, {0xb1, 0xe5, 0xff}, {0xb1, 0xe5, 0xff}, {0xb1, 0xe5, 0xff}, {0xb1, 0xe5, 0xff}, + {0xb2, 0xe6, 0xff}, {0xb2, 0xe6, 0xff}, {0xb2, 0xe6, 0xff}, {0xb2, 0xe6, 0xff}, {0xb2, 0xe6, 0xfe}, {0xb2, 0xe6, 0xfe}, + {0xb3, 0xe6, 0xfe}, {0xb3, 0xe6, 0xfe}, {0xb3, 0xe6, 0xfe}, {0xb3, 0xe6, 0xfe}, {0xb3, 0xe6, 0xfe}, {0xb4, 0xe6, 0xfe}, + {0xb4, 0xe6, 0xfe}, {0xb4, 0xe6, 0xfe}, {0xb4, 0xe6, 0xfe}, {0xb4, 0xe6, 0xfe}, {0xb4, 0xe6, 0xfe}, {0xb5, 0xe6, 0xfe}, + {0xb5, 0xe7, 0xfe}, {0xb5, 0xe7, 0xfe}, {0xb5, 0xe7, 0xfe}, {0xb5, 0xe7, 0xfe}, {0xb5, 0xe7, 0xfe}, {0xb6, 0xe7, 0xfe}, + {0xb6, 0xe7, 0xfe}, {0xb6, 0xe7, 0xfe}, {0xb6, 0xe7, 0xfe}, {0xb6, 0xe7, 0xfe}, {0xb6, 0xe7, 0xfe}, {0xb7, 0xe7, 0xfe}, + {0xb7, 0xe7, 0xfe}, {0xb7, 0xe7, 0xfd}, {0xb7, 0xe7, 0xfd}, {0xb7, 0xe7, 0xfd}, {0xb7, 0xe7, 0xfd}, {0xb8, 0xe8, 0xfd}, + {0xb8, 0xe8, 0xfd}, {0xb8, 0xe8, 0xfd}, {0xb8, 0xe8, 0xfd}, {0xb8, 0xe8, 0xfd}, {0xb9, 0xe8, 0xfd}, {0xb9, 0xe8, 0xfd}, + {0xb9, 0xe8, 0xfd}, {0xb9, 0xe8, 0xfd}, {0xb9, 0xe8, 0xfd}, {0xb9, 0xe8, 0xfd}, {0xba, 0xe8, 0xfd}, {0xba, 0xe8, 0xfd}, + {0xba, 0xe8, 0xfd}, {0xba, 0xe8, 0xfd}, {0xba, 0xe8, 0xfd}, {0xba, 0xe8, 0xfd}, {0xbb, 0xe8, 0xfd}, {0xbb, 0xe9, 0xfd}, + {0xbb, 0xe9, 0xfd}, {0xbb, 0xe9, 0xfd}, {0xbb, 0xe9, 0xfd}, {0xbb, 0xe9, 0xfc}, {0xbc, 0xe9, 0xfc}, {0xbc, 0xe9, 0xfc}, + {0xbc, 0xe9, 0xfc}, {0xbc, 0xe9, 0xfc}, {0xbc, 0xe9, 0xfc}, {0xbd, 0xe9, 0xfc}, {0xbd, 0xe9, 0xfc}, {0xbd, 0xe9, 0xfc}, + {0xbd, 0xe9, 0xfc}, {0xbd, 0xe9, 0xfc}, {0xbd, 0xe9, 0xfc}, {0xbe, 0xe9, 0xfc}, {0xbe, 0xea, 0xfc}, {0xbe, 0xea, 0xfc}, + {0xbe, 0xea, 0xfc}, {0xbe, 0xea, 0xfc}, {0xbe, 0xea, 0xfc}, {0xbf, 0xea, 0xfc}, {0xbf, 0xea, 0xfc}, {0xbf, 0xea, 0xfc}, + {0xbf, 0xea, 0xfc}, {0xbf, 0xea, 0xfc}, {0xbf, 0xea, 0xfc}, {0xc0, 0xea, 0xfc}, {0xc0, 0xea, 0xfc}, {0xc0, 0xea, 0xfc}, + {0xc0, 0xea, 0xfb}, {0xc0, 0xea, 0xfb}, {0xc0, 0xea, 0xfb}, {0xc1, 0xea, 0xfb}, {0xc1, 0xeb, 0xfb}, {0xc1, 0xeb, 0xfb}, + {0xc1, 0xeb, 0xfb}, {0xc1, 0xeb, 0xfb}, {0xc2, 0xeb, 0xfb}, {0xc2, 0xeb, 0xfb}, {0xc2, 0xeb, 0xfb}, {0xc2, 0xeb, 0xfb}, + {0xc2, 0xeb, 0xfb}, {0xc2, 0xeb, 0xfb}, {0xc3, 0xeb, 0xfb}, {0xc3, 0xeb, 0xfb}, {0xc3, 0xeb, 0xfb}, {0xc3, 0xeb, 0xfb}, + {0xc3, 0xeb, 0xfb}, {0xc3, 0xeb, 0xfb}, {0xc4, 0xeb, 0xfb}, {0xc4, 0xeb, 0xfb}, {0xc4, 0xec, 0xfb}, {0xc4, 0xec, 0xfb}, + {0xc4, 0xec, 0xfb}, {0xc4, 0xec, 0xfb}, {0xc5, 0xec, 0xfa}, {0xc5, 0xec, 0xfa}, {0xc5, 0xec, 0xfa}, {0xc5, 0xec, 0xfa}, + {0xc5, 0xec, 0xfa}, {0xc5, 0xec, 0xfa}, {0xc6, 0xec, 0xfa}, {0xc6, 0xec, 0xfa}, {0xc6, 0xec, 0xfa}, {0xc6, 0xec, 0xfa}, + {0xc6, 0xec, 0xfa}, {0xc7, 0xec, 0xfa}, {0xc7, 0xec, 0xfa}, {0xc7, 0xed, 0xfa}, {0xc7, 0xed, 0xfa}, {0xc7, 0xed, 0xfa}, + {0xc7, 0xed, 0xfa}, {0xc8, 0xed, 0xfa}, {0xc8, 0xed, 0xfa}, {0xc8, 0xed, 0xfa}, {0xc8, 0xed, 0xfa}, {0xc8, 0xed, 0xfa}, + {0xc8, 0xed, 0xfa}, {0xc9, 0xed, 0xfa}, {0xc9, 0xed, 0xfa}, {0xc9, 0xed, 0xfa}, {0xc9, 0xed, 0xf9}, {0xc9, 0xed, 0xf9}, + {0xc9, 0xed, 0xf9}, {0xca, 0xed, 0xf9}, {0xca, 0xed, 0xf9}, {0xca, 0xee, 0xf9}, {0xca, 0xee, 0xf9}, {0xca, 0xee, 0xf9}, + {0xca, 0xee, 0xf9}, {0xcb, 0xee, 0xf9}, {0xcb, 0xee, 0xf9}, {0xcb, 0xee, 0xf9}, {0xcb, 0xee, 0xf9}, {0xcb, 0xee, 0xf9}, + {0xcc, 0xee, 0xf9}, {0xcc, 0xee, 0xf9}, {0xcc, 0xee, 0xf9}, {0xcc, 0xee, 0xf9}, {0xcc, 0xee, 0xf9}, {0xcc, 0xee, 0xf9}, + {0xcd, 0xee, 0xf9}, {0xcd, 0xee, 0xf9}, {0xcd, 0xef, 0xf9}, {0xcd, 0xef, 0xf9}, {0xcd, 0xef, 0xf9}, {0xcd, 0xef, 0xf9}, + {0xce, 0xef, 0xf9}, {0xce, 0xef, 0xf8}, {0xce, 0xef, 0xf8}, {0xce, 0xef, 0xf8}, {0xce, 0xef, 0xf8}, {0xce, 0xef, 0xf8}, + {0xcf, 0xef, 0xf8}, {0xcf, 0xef, 0xf8}, {0xcf, 0xef, 0xf8}, {0xcf, 0xef, 0xf8}, {0xcf, 0xef, 0xf8}, {0xd0, 0xef, 0xf8}, + {0xd0, 0xef, 0xf8}, {0xd0, 0xef, 0xf8}, {0xd0, 0xf0, 0xf8}, {0xd0, 0xf0, 0xf8}, {0xd0, 0xf0, 0xf8}, {0xd1, 0xf0, 0xf8}, + {0xd1, 0xf0, 0xf8}, {0xd1, 0xf0, 0xf8}, {0xd1, 0xf0, 0xf8}, {0xd1, 0xf0, 0xf8}, {0xd1, 0xf0, 0xf8}, {0xd2, 0xf0, 0xf8}, + {0xd2, 0xf0, 0xf8}, {0xd2, 0xf0, 0xf8}, {0xd2, 0xf0, 0xf8}, {0xd2, 0xf0, 0xf7}, {0xd2, 0xf0, 0xf7}, {0xd3, 0xf0, 0xf7}, + {0xd3, 0xf0, 0xf7}, {0xd3, 0xf0, 0xf7}, {0xd3, 0xf1, 0xf7}, {0xd3, 0xf1, 0xf7}, {0xd3, 0xf1, 0xf7}, {0xd4, 0xf1, 0xf7}, + {0xd4, 0xf1, 0xf7}, {0xd4, 0xf1, 0xf7}, {0xd4, 0xf1, 0xf7}, {0xd4, 0xf1, 0xf7}, {0xd5, 0xf1, 0xf7}, {0xd5, 0xf1, 0xf7}, + {0xd5, 0xf1, 0xf7}, {0xd5, 0xf1, 0xf7}, {0xd5, 0xf1, 0xf7}, {0xd5, 0xf1, 0xf7}, {0xd6, 0xf1, 0xf7}, {0xd6, 0xf1, 0xf7}, + {0xd6, 0xf1, 0xf7}, {0xd6, 0xf2, 0xf7}, {0xd6, 0xf2, 0xf7}, {0xd6, 0xf2, 0xf7}, {0xd7, 0xf2, 0xf7}, {0xd7, 0xf2, 0xf7}, + {0xd7, 0xf2, 0xf6}, {0xd7, 0xf2, 0xf6}, {0xd7, 0xf2, 0xf6}, {0xd7, 0xf2, 0xf6}, {0xd8, 0xf2, 0xf6}, {0xd8, 0xf2, 0xf6}, + {0xd8, 0xf2, 0xf6}, {0xd8, 0xf2, 0xf6}, {0xd8, 0xf2, 0xf6}, {0xd8, 0xf2, 0xf6}, {0xd9, 0xf2, 0xf6}, {0xd9, 0xf2, 0xf6}, + {0xd9, 0xf2, 0xf6}, {0xd9, 0xf3, 0xf6}, {0xd9, 0xf3, 0xf6}, {0xda, 0xf3, 0xf6}, {0xda, 0xf3, 0xf6}, {0xda, 0xf3, 0xf6}, + {0xda, 0xf3, 0xf6}, {0xda, 0xf3, 0xf6}, {0xda, 0xf3, 0xf6}, {0xdb, 0xf3, 0xf6}, {0xdb, 0xf3, 0xf6}, {0xdb, 0xf3, 0xf6}, + {0xdb, 0xf3, 0xf6}, {0xdb, 0xf3, 0xf6}, {0xdb, 0xf3, 0xf5}, {0xdc, 0xf3, 0xf5}, {0xdc, 0xf3, 0xf5}, {0xdc, 0xf3, 0xf5}, + {0xdc, 0xf4, 0xf5}, {0xdc, 0xf4, 0xf5}, {0xdc, 0xf4, 0xf5}, {0xdd, 0xf4, 0xf5}, {0xdd, 0xf4, 0xf5}, {0xdd, 0xf4, 0xf5}, + {0xdd, 0xf4, 0xf5}, {0xdd, 0xf4, 0xf5}, {0xdd, 0xf4, 0xf5}, {0xde, 0xf4, 0xf5}, {0xde, 0xf4, 0xf5}, {0xde, 0xf4, 0xf5}, + {0xde, 0xf4, 0xf5}, {0xde, 0xf4, 0xf5}, {0xdf, 0xf4, 0xf5}, {0xdf, 0xf4, 0xf5}, {0xdf, 0xf4, 0xf5}, {0xdf, 0xf4, 0xf5}, + {0xdf, 0xf5, 0xf5}, {0xdf, 0xf5, 0xf5}, {0xe0, 0xf5, 0xf5}, {0xe0, 0xf5, 0xf5}, {0xe0, 0xf5, 0xf5}, {0xe0, 0xf5, 0xf4}, + {0xe0, 0xf5, 0xf4}, {0xe0, 0xf5, 0xf4}, {0xe1, 0xf5, 0xf4}, {0xe1, 0xf5, 0xf4}, {0xe1, 0xf5, 0xf4}, {0xe1, 0xf5, 0xf4}, + {0xe1, 0xf5, 0xf4}, {0xe1, 0xf5, 0xf4}, {0xe2, 0xf5, 0xf4}, {0xe2, 0xf5, 0xf4}, {0xe2, 0xf5, 0xf4}, {0xe2, 0xf5, 0xf4}, + {0xe2, 0xf6, 0xf4}, {0xe2, 0xf6, 0xf4}, {0xe3, 0xf6, 0xf4}, {0xe3, 0xf6, 0xf4}, {0xe3, 0xf6, 0xf4}, {0xe3, 0xf6, 0xf4}, + {0xe3, 0xf6, 0xf4}, {0xe4, 0xf6, 0xf4}, {0xe4, 0xf6, 0xf4}, {0xe4, 0xf6, 0xf4}, {0xe4, 0xf6, 0xf4}, {0xe4, 0xf6, 0xf4}, + {0xe4, 0xf6, 0xf4}, {0xe5, 0xf6, 0xf3}, {0xe5, 0xf6, 0xf3}, {0xe5, 0xf6, 0xf3}, {0xe5, 0xf6, 0xf3}, {0xe5, 0xf7, 0xf3}, + {0xe5, 0xf7, 0xf3}, {0xe6, 0xf7, 0xf3}, {0xe6, 0xf7, 0xf3}, {0xe6, 0xf7, 0xf3}, {0xe6, 0xf7, 0xf3}, {0xe6, 0xf7, 0xf3}, + {0xe6, 0xf7, 0xf3}, {0xe7, 0xf7, 0xf3}, {0xe7, 0xf7, 0xf3}, {0xe7, 0xf7, 0xf3}, {0xe7, 0xf7, 0xf3}, {0xe7, 0xf7, 0xf3}, + {0xe8, 0xf7, 0xf3}, {0xe8, 0xf7, 0xf3}, {0xe8, 0xf7, 0xf3}, {0xe8, 0xf7, 0xf3}, {0xe8, 0xf7, 0xf3}, {0xe8, 0xf8, 0xf3}, + {0xe9, 0xf8, 0xf3}, {0xe9, 0xf8, 0xf3}, {0xe9, 0xf8, 0xf3}, {0xe9, 0xf8, 0xf2}, {0xe9, 0xf8, 0xf2}, {0xe9, 0xf8, 0xf2}, + {0xea, 0xf8, 0xf2}, {0xea, 0xf8, 0xf2}, {0xea, 0xf8, 0xf2}, {0xea, 0xf8, 0xf2}, {0xea, 0xf8, 0xf2}, {0xea, 0xf8, 0xf2}, + {0xeb, 0xf8, 0xf2}, {0xeb, 0xf8, 0xf2}, {0xeb, 0xf8, 0xf2}, {0xeb, 0xf8, 0xf2}, {0xeb, 0xf8, 0xf2}, {0xeb, 0xf9, 0xf2}, + {0xec, 0xf9, 0xf2}, {0xec, 0xf9, 0xf2}, {0xec, 0xf9, 0xf2}, {0xec, 0xf9, 0xf2}, {0xec, 0xf9, 0xf2}, {0xed, 0xf9, 0xf2}, + {0xed, 0xf9, 0xf2}, {0xed, 0xf9, 0xf2}, {0xed, 0xf9, 0xf2}, {0xed, 0xf9, 0xf2}, {0xed, 0xf9, 0xf2}, {0xee, 0xf9, 0xf2}, + {0xee, 0xf9, 0xf1}, {0xee, 0xf9, 0xf1}, {0xee, 0xf9, 0xf1}, {0xee, 0xf9, 0xf1}, {0xee, 0xfa, 0xf1}, {0xef, 0xfa, 0xf1}, + {0xef, 0xfa, 0xf1}, {0xef, 0xfa, 0xf1}, {0xef, 0xfa, 0xf1}, {0xef, 0xfa, 0xf1}, {0xef, 0xfa, 0xf1}, {0xf0, 0xfa, 0xf1}, + {0xf0, 0xfa, 0xf1}, {0xf0, 0xfa, 0xf1}, {0xf0, 0xfa, 0xf1}, {0xf0, 0xfa, 0xf1}, {0xf0, 0xfa, 0xf1}, {0xf1, 0xfa, 0xf1}, + {0xf1, 0xfa, 0xf1}, {0xf1, 0xfa, 0xf1}, {0xf1, 0xfa, 0xf1}, {0xf1, 0xfa, 0xf1}, {0xf2, 0xfb, 0xf1}, {0xf2, 0xfb, 0xf1}, + {0xf2, 0xfb, 0xf1}, {0xf2, 0xfb, 0xf1}, {0xf2, 0xfb, 0xf0}, {0xf2, 0xfb, 0xf0}, {0xf3, 0xfb, 0xf0}, {0xf3, 0xfb, 0xf0}, + {0xf3, 0xfb, 0xf0}, {0xf3, 0xfb, 0xf0}, {0xf3, 0xfb, 0xf0}, {0xf3, 0xfb, 0xf0}, {0xf4, 0xfb, 0xf0}, {0xf4, 0xfb, 0xf0}, + {0xf4, 0xfb, 0xf0}, {0xf4, 0xfb, 0xf0}, {0xf4, 0xfb, 0xf0}, {0xf4, 0xfc, 0xf0}, {0xf5, 0xfc, 0xf0}, {0xf5, 0xfc, 0xf0}, + {0xf5, 0xfc, 0xf0}, {0xf5, 0xfc, 0xf0}, {0xf5, 0xfc, 0xf0}, {0xf5, 0xfc, 0xf0}, {0xf6, 0xfc, 0xf0}, {0xf6, 0xfc, 0xf0}, + {0xf6, 0xfc, 0xf0}, {0xf6, 0xfc, 0xf0}, {0xf6, 0xfc, 0xf0}, {0xf7, 0xfc, 0xf0}, {0xf7, 0xfc, 0xf0}, {0xf7, 0xfc, 0xef}, + {0xf7, 0xfc, 0xef}, {0xf7, 0xfc, 0xef}, {0xf7, 0xfc, 0xef}, {0xf8, 0xfd, 0xef}, {0xf8, 0xfd, 0xef}, {0xf8, 0xfd, 0xef}, + {0xf8, 0xfd, 0xef}, {0xf8, 0xfd, 0xef}, {0xf8, 0xfd, 0xef}, {0xf9, 0xfd, 0xef}, {0xf9, 0xfd, 0xef}, {0xf9, 0xfd, 0xef}, + {0xf9, 0xfd, 0xef}, {0xf9, 0xfd, 0xee}, {0xf9, 0xfd, 0xee}, {0xf9, 0xfd, 0xee}, {0xf9, 0xfd, 0xed}, {0xf9, 0xfd, 0xed}, + {0xf9, 0xfd, 0xec}, {0xf9, 0xfd, 0xec}, {0xf9, 0xfc, 0xec}, {0xf9, 0xfc, 0xeb}, {0xf9, 0xfc, 0xeb}, {0xf9, 0xfc, 0xeb}, + {0xf9, 0xfc, 0xea}, {0xf9, 0xfc, 0xea}, {0xf9, 0xfc, 0xe9}, {0xf9, 0xfc, 0xe9}, {0xf9, 0xfc, 0xe9}, {0xf9, 0xfc, 0xe8}, + {0xf9, 0xfc, 0xe8}, {0xf9, 0xfc, 0xe7}, {0xf9, 0xfc, 0xe7}, {0xf9, 0xfc, 0xe7}, {0xf9, 0xfc, 0xe6}, {0xf9, 0xfb, 0xe6}, + {0xf9, 0xfb, 0xe6}, {0xf9, 0xfb, 0xe5}, {0xf9, 0xfb, 0xe5}, {0xf9, 0xfb, 0xe4}, {0xf9, 0xfb, 0xe4}, {0xf9, 0xfb, 0xe4}, + {0xf9, 0xfb, 0xe3}, {0xf9, 0xfb, 0xe3}, {0xf9, 0xfb, 0xe2}, {0xf9, 0xfb, 0xe2}, {0xf9, 0xfb, 0xe2}, {0xf9, 0xfb, 0xe1}, + {0xf9, 0xfb, 0xe1}, {0xf9, 0xfb, 0xe1}, {0xf9, 0xfb, 0xe0}, {0xf9, 0xfa, 0xe0}, {0xf9, 0xfa, 0xdf}, {0xf9, 0xfa, 0xdf}, + {0xf9, 0xfa, 0xdf}, {0xf9, 0xfa, 0xde}, {0xf9, 0xfa, 0xde}, {0xf9, 0xfa, 0xdd}, {0xf9, 0xfa, 0xdd}, {0xf9, 0xfa, 0xdd}, + {0xf9, 0xfa, 0xdc}, {0xf9, 0xfa, 0xdc}, {0xf9, 0xfa, 0xdc}, {0xf9, 0xfa, 0xdb}, {0xf9, 0xfa, 0xdb}, {0xf9, 0xfa, 0xda}, + {0xf9, 0xf9, 0xda}, {0xf9, 0xf9, 0xda}, {0xf9, 0xf9, 0xd9}, {0xf9, 0xf9, 0xd9}, {0xf9, 0xf9, 0xd8}, {0xf9, 0xf9, 0xd8}, + {0xf9, 0xf9, 0xd8}, {0xf9, 0xf9, 0xd7}, {0xf9, 0xf9, 0xd7}, {0xf9, 0xf9, 0xd7}, {0xf9, 0xf9, 0xd6}, {0xf9, 0xf9, 0xd6}, + {0xf9, 0xf9, 0xd5}, {0xf9, 0xf9, 0xd5}, {0xf9, 0xf9, 0xd5}, {0xf9, 0xf9, 0xd4}, {0xf9, 0xf8, 0xd4}, {0xf9, 0xf8, 0xd3}, + {0xf9, 0xf8, 0xd3}, {0xf9, 0xf8, 0xd3}, {0xf9, 0xf8, 0xd2}, {0xf9, 0xf8, 0xd2}, {0xf9, 0xf8, 0xd2}, {0xf9, 0xf8, 0xd1}, + {0xf9, 0xf8, 0xd1}, {0xf9, 0xf8, 0xd0}, {0xf9, 0xf8, 0xd0}, {0xf9, 0xf8, 0xd0}, {0xf9, 0xf8, 0xcf}, {0xf9, 0xf8, 0xcf}, + {0xf9, 0xf8, 0xce}, {0xf9, 0xf7, 0xce}, {0xf9, 0xf7, 0xce}, {0xf9, 0xf7, 0xcd}, {0xf9, 0xf7, 0xcd}, {0xf9, 0xf7, 0xcd}, + {0xf9, 0xf7, 0xcc}, {0xf9, 0xf7, 0xcc}, {0xf9, 0xf7, 0xcb}, {0xf9, 0xf7, 0xcb}, {0xf9, 0xf7, 0xcb}, {0xf9, 0xf7, 0xca}, + {0xf9, 0xf7, 0xca}, {0xf9, 0xf7, 0xc9}, {0xf9, 0xf7, 0xc9}, {0xf9, 0xf7, 0xc9}, {0xf9, 0xf7, 0xc8}, {0xf9, 0xf6, 0xc8}, + {0xf9, 0xf6, 0xc8}, {0xf9, 0xf6, 0xc7}, {0xf9, 0xf6, 0xc7}, {0xf9, 0xf6, 0xc6}, {0xf9, 0xf6, 0xc6}, {0xf9, 0xf6, 0xc6}, + {0xf9, 0xf6, 0xc5}, {0xf9, 0xf6, 0xc5}, {0xf9, 0xf6, 0xc5}, {0xf9, 0xf6, 0xc4}, {0xf9, 0xf6, 0xc4}, {0xf9, 0xf6, 0xc3}, + {0xf9, 0xf6, 0xc3}, {0xf9, 0xf6, 0xc3}, {0xf9, 0xf5, 0xc2}, {0xf9, 0xf5, 0xc2}, {0xf9, 0xf5, 0xc1}, {0xf9, 0xf5, 0xc1}, + {0xf9, 0xf5, 0xc1}, {0xf9, 0xf5, 0xc0}, {0xf9, 0xf5, 0xc0}, {0xf9, 0xf5, 0xc0}, {0xf9, 0xf5, 0xbf}, {0xf9, 0xf5, 0xbf}, + {0xf9, 0xf5, 0xbe}, {0xf9, 0xf5, 0xbe}, {0xf9, 0xf5, 0xbe}, {0xf9, 0xf5, 0xbd}, {0xf9, 0xf5, 0xbd}, {0xf9, 0xf5, 0xbc}, + {0xf9, 0xf4, 0xbc}, {0xf9, 0xf4, 0xbc}, {0xf9, 0xf4, 0xbb}, {0xf9, 0xf4, 0xbb}, {0xf9, 0xf4, 0xbb}, {0xf9, 0xf4, 0xba}, + {0xf9, 0xf4, 0xba}, {0xf9, 0xf4, 0xb9}, {0xf9, 0xf4, 0xb9}, {0xf9, 0xf4, 0xb9}, {0xf9, 0xf4, 0xb8}, {0xf9, 0xf4, 0xb8}, + {0xf9, 0xf4, 0xb7}, {0xf9, 0xf4, 0xb7}, {0xf9, 0xf4, 0xb7}, {0xf9, 0xf3, 0xb6}, {0xf9, 0xf3, 0xb6}, {0xf9, 0xf3, 0xb6}, + {0xf9, 0xf3, 0xb5}, {0xf9, 0xf3, 0xb5}, {0xf9, 0xf3, 0xb4}, {0xf9, 0xf3, 0xb4}, {0xf9, 0xf3, 0xb4}, {0xf9, 0xf3, 0xb3}, + {0xf9, 0xf3, 0xb3}, {0xf9, 0xf3, 0xb2}, {0xf9, 0xf3, 0xb2}, {0xf9, 0xf3, 0xb2}, {0xf9, 0xf3, 0xb1}, {0xf9, 0xf3, 0xb1}, + {0xf9, 0xf3, 0xb1}, {0xf9, 0xf2, 0xb0}, {0xf9, 0xf2, 0xb0}, {0xf9, 0xf2, 0xaf}, {0xf9, 0xf2, 0xaf}, {0xf9, 0xf2, 0xaf}, + {0xf9, 0xf2, 0xae}, {0xf9, 0xf2, 0xae}, {0xf9, 0xf2, 0xad}, {0xf9, 0xf2, 0xad}, {0xf9, 0xf2, 0xad}, {0xf9, 0xf2, 0xac}, + {0xf9, 0xf2, 0xac}, {0xf9, 0xf2, 0xac}, {0xf9, 0xf2, 0xab}, {0xf9, 0xf2, 0xab}, {0xf9, 0xf1, 0xaa}, {0xf9, 0xf1, 0xaa}, + {0xf9, 0xf1, 0xaa}, {0xf9, 0xf1, 0xa9}, {0xf9, 0xf1, 0xa9}, {0xf9, 0xf1, 0xa8}, {0xf9, 0xf1, 0xa8}, {0xf9, 0xf1, 0xa8}, + {0xf9, 0xf1, 0xa7}, {0xf9, 0xf1, 0xa7}, {0xf9, 0xf1, 0xa7}, {0xf9, 0xf1, 0xa6}, {0xf9, 0xf1, 0xa6}, {0xf9, 0xf1, 0xa5}, + {0xf9, 0xf1, 0xa5}, {0xf9, 0xf1, 0xa5}, {0xf9, 0xf0, 0xa4}, {0xf9, 0xf0, 0xa4}, {0xf9, 0xf0, 0xa3}, {0xf9, 0xf0, 0xa3}, + {0xf9, 0xf0, 0xa3}, {0xf9, 0xf0, 0xa2}, {0xf9, 0xf0, 0xa2}, {0xf9, 0xf0, 0xa2}, {0xf9, 0xf0, 0xa1}, {0xf9, 0xf0, 0xa1}, + {0xf9, 0xf0, 0xa0}, {0xf9, 0xf0, 0xa0}, {0xf9, 0xf0, 0xa0}, {0xf9, 0xf0, 0x9f}, {0xf9, 0xf0, 0x9f}, {0xf9, 0xef, 0x9e}, + {0xf9, 0xef, 0x9e}, {0xf9, 0xef, 0x9e}, {0xf9, 0xef, 0x9d}, {0xf9, 0xef, 0x9d}, {0xf9, 0xef, 0x9d}, {0xf9, 0xef, 0x9c}, + {0xf9, 0xef, 0x9c}, {0xf9, 0xef, 0x9b}, {0xf9, 0xef, 0x9b}, {0xf9, 0xef, 0x9b}, {0xf9, 0xef, 0x9a}, {0xf9, 0xef, 0x9a}, + {0xf9, 0xef, 0x9a}, {0xf9, 0xef, 0x99}, {0xf9, 0xef, 0x99}, {0xf9, 0xee, 0x98}, {0xf9, 0xee, 0x98}, {0xf9, 0xee, 0x98}, + {0xf9, 0xee, 0x97}, {0xf9, 0xee, 0x97}, {0xf9, 0xee, 0x96}, {0xf9, 0xee, 0x96}, {0xf9, 0xee, 0x96}, {0xf9, 0xee, 0x95}, + {0xf9, 0xee, 0x95}, {0xf9, 0xee, 0x95}, {0xf9, 0xee, 0x94}, {0xf9, 0xee, 0x94}, {0xf9, 0xee, 0x93}, {0xf9, 0xee, 0x93}, + {0xf9, 0xed, 0x93}, {0xf9, 0xed, 0x92}, {0xf9, 0xed, 0x92}, {0xf9, 0xed, 0x91}, {0xf9, 0xed, 0x91}, {0xf9, 0xed, 0x91}, + {0xf9, 0xed, 0x90}, {0xf9, 0xed, 0x90}, {0xf9, 0xed, 0x90}, {0xf9, 0xed, 0x8f}, {0xf9, 0xed, 0x8f}, {0xf9, 0xed, 0x8e}, + {0xf9, 0xed, 0x8e}, {0xf9, 0xed, 0x8e}, {0xf9, 0xed, 0x8d}, {0xf9, 0xed, 0x8d}, {0xf9, 0xec, 0x8c}, {0xf9, 0xec, 0x8c}, + {0xf9, 0xec, 0x8c}, {0xf9, 0xec, 0x8b}, {0xf9, 0xec, 0x8b}, {0xf9, 0xec, 0x8b}, {0xf9, 0xec, 0x8a}, {0xf9, 0xec, 0x8a}, + {0xf9, 0xec, 0x89}, {0xf9, 0xec, 0x89}, {0xf9, 0xec, 0x89}, {0xf9, 0xec, 0x88}, {0xf9, 0xec, 0x88}, {0xf9, 0xec, 0x87}, + {0xf9, 0xec, 0x87}, {0xf9, 0xeb, 0x87}, {0xf9, 0xeb, 0x86}, {0xf9, 0xeb, 0x86}, {0xf9, 0xeb, 0x86}, {0xf9, 0xeb, 0x85}, + {0xf9, 0xeb, 0x85}, {0xf9, 0xeb, 0x84}, {0xf9, 0xeb, 0x84}, {0xf9, 0xeb, 0x84}, {0xf9, 0xeb, 0x83}, {0xf9, 0xeb, 0x83}, + {0xf9, 0xeb, 0x82}, {0xf9, 0xeb, 0x82}, {0xf9, 0xeb, 0x82}, {0xf9, 0xeb, 0x81}, {0xf9, 0xeb, 0x81}, {0xf9, 0xea, 0x81}, + {0xf9, 0xea, 0x80}, {0xf9, 0xea, 0x80}, {0xf9, 0xea, 0x7f}, {0xf9, 0xea, 0x7f}, {0xf9, 0xea, 0x7f}, {0xf9, 0xea, 0x7e}, + {0xf9, 0xea, 0x7e}, {0xf9, 0xea, 0x7d}, {0xf9, 0xea, 0x7d}, {0xf9, 0xea, 0x7d}, {0xf9, 0xea, 0x7c}, {0xf9, 0xea, 0x7c}, + {0xf9, 0xea, 0x7c}, {0xf9, 0xea, 0x7b}, {0xf9, 0xe9, 0x7b}, {0xf9, 0xe9, 0x7a}, {0xf9, 0xe9, 0x7a}, {0xf9, 0xe9, 0x7a}, + {0xf9, 0xe9, 0x79}, {0xf9, 0xe9, 0x79}, {0xf9, 0xe9, 0x78}, {0xf9, 0xe9, 0x78}, {0xf9, 0xe9, 0x78}, {0xf9, 0xe9, 0x77}, + {0xf9, 0xe9, 0x77}, {0xf9, 0xe9, 0x77}, {0xf9, 0xe9, 0x76}, {0xf9, 0xe9, 0x76}, {0xf9, 0xe9, 0x75}, {0xf9, 0xe9, 0x75}, + {0xf9, 0xe8, 0x75}, {0xf9, 0xe8, 0x74}, {0xf9, 0xe8, 0x74}, {0xf9, 0xe8, 0x73}, {0xf9, 0xe8, 0x73}, {0xf9, 0xe8, 0x73}, + {0xf9, 0xe8, 0x72}, {0xf9, 0xe8, 0x72}, {0xf9, 0xe8, 0x72}, {0xf9, 0xe8, 0x71}, {0xf9, 0xe8, 0x71}, {0xf9, 0xe8, 0x70}, + {0xf9, 0xe8, 0x70}, {0xf9, 0xe8, 0x70}, {0xf9, 0xe8, 0x6f}, {0xf9, 0xe7, 0x6f}, {0xf9, 0xe7, 0x6e}, {0xf9, 0xe7, 0x6e}, + {0xf9, 0xe7, 0x6e}, {0xf9, 0xe7, 0x6d}, {0xf9, 0xe7, 0x6d}, {0xf9, 0xe7, 0x6d}, {0xf9, 0xe7, 0x6c}, {0xf9, 0xe7, 0x6c}, + {0xf9, 0xe7, 0x6b}, {0xf9, 0xe7, 0x6b}, {0xf9, 0xe7, 0x6b}, {0xf9, 0xe7, 0x6a}, {0xf9, 0xe7, 0x6a}, {0xf9, 0xe7, 0x6a}, + {0xf9, 0xe7, 0x69}, {0xf9, 0xe6, 0x69}, {0xf9, 0xe6, 0x68}, {0xf9, 0xe6, 0x68}, {0xf9, 0xe6, 0x68}, {0xf9, 0xe6, 0x67}, + {0xf9, 0xe6, 0x67}, {0xf9, 0xe6, 0x66}, {0xf9, 0xe6, 0x66}, {0xf9, 0xe6, 0x66}, {0xf9, 0xe6, 0x65}, {0xf9, 0xe6, 0x65}, + {0xf9, 0xe6, 0x65}, {0xf9, 0xe6, 0x64}, {0xf9, 0xe6, 0x64}, {0xf9, 0xe6, 0x63}, {0xf9, 0xe5, 0x63}, {0xf9, 0xe5, 0x63}, + {0xf9, 0xe5, 0x62}, {0xf9, 0xe5, 0x62}, {0xf9, 0xe5, 0x61}, {0xf9, 0xe5, 0x61}, {0xf9, 0xe5, 0x61}, {0xf9, 0xe5, 0x60}, + {0xf9, 0xe5, 0x60}, {0xf9, 0xe5, 0x60}, {0xf9, 0xe5, 0x5f}, {0xf9, 0xe5, 0x5f}, {0xf9, 0xe4, 0x5f}, {0xf9, 0xe4, 0x5f}, + {0xf9, 0xe4, 0x5e}, {0xf9, 0xe4, 0x5e}, {0xf9, 0xe4, 0x5e}, {0xf9, 0xe4, 0x5e}, {0xf9, 0xe4, 0x5e}, {0xf9, 0xe3, 0x5d}, + {0xf9, 0xe3, 0x5d}, {0xf9, 0xe3, 0x5d}, {0xf9, 0xe3, 0x5d}, {0xf9, 0xe3, 0x5c}, {0xf9, 0xe3, 0x5c}, {0xf9, 0xe3, 0x5c}, + {0xf9, 0xe2, 0x5c}, {0xf9, 0xe2, 0x5b}, {0xf9, 0xe2, 0x5b}, {0xf9, 0xe2, 0x5b}, {0xf9, 0xe2, 0x5b}, {0xf9, 0xe2, 0x5a}, + {0xf9, 0xe2, 0x5a}, {0xf9, 0xe1, 0x5a}, {0xf9, 0xe1, 0x5a}, {0xf9, 0xe1, 0x59}, {0xf9, 0xe1, 0x59}, {0xf9, 0xe1, 0x59}, + {0xf9, 0xe1, 0x59}, {0xf9, 0xe1, 0x58}, {0xf9, 0xe0, 0x58}, {0xf9, 0xe0, 0x58}, {0xf9, 0xe0, 0x58}, {0xf9, 0xe0, 0x58}, + {0xf9, 0xe0, 0x57}, {0xf9, 0xe0, 0x57}, {0xf9, 0xe0, 0x57}, {0xf9, 0xdf, 0x57}, {0xf9, 0xdf, 0x56}, {0xf9, 0xdf, 0x56}, + {0xf9, 0xdf, 0x56}, {0xf9, 0xdf, 0x56}, {0xf9, 0xdf, 0x55}, {0xf9, 0xdf, 0x55}, {0xf9, 0xde, 0x55}, {0xf9, 0xde, 0x55}, + {0xf9, 0xde, 0x54}, {0xf9, 0xde, 0x54}, {0xf9, 0xde, 0x54}, {0xf9, 0xde, 0x54}, {0xf9, 0xde, 0x53}, {0xf9, 0xdd, 0x53}, + {0xf9, 0xdd, 0x53}, {0xf9, 0xdd, 0x53}, {0xf9, 0xdd, 0x52}, {0xf9, 0xdd, 0x52}, {0xf9, 0xdd, 0x52}, {0xf9, 0xdd, 0x52}, + {0xf9, 0xdc, 0x52}, {0xf9, 0xdc, 0x51}, {0xf9, 0xdc, 0x51}, {0xf9, 0xdc, 0x51}, {0xf9, 0xdc, 0x51}, {0xf9, 0xdc, 0x50}, + {0xf9, 0xdc, 0x50}, {0xf9, 0xdb, 0x50}, {0xf9, 0xdb, 0x50}, {0xf9, 0xdb, 0x4f}, {0xf9, 0xdb, 0x4f}, {0xf9, 0xdb, 0x4f}, + {0xf9, 0xdb, 0x4f}, {0xf9, 0xdb, 0x4e}, {0xf9, 0xda, 0x4e}, {0xf9, 0xda, 0x4e}, {0xf9, 0xda, 0x4e}, {0xf9, 0xda, 0x4d}, + {0xf9, 0xda, 0x4d}, {0xf9, 0xda, 0x4d}, {0xf9, 0xda, 0x4d}, {0xf9, 0xd9, 0x4c}, {0xf9, 0xd9, 0x4c}, {0xf9, 0xd9, 0x4c}, + {0xf9, 0xd9, 0x4c}, {0xf9, 0xd9, 0x4b}, {0xf9, 0xd9, 0x4b}, {0xf9, 0xd9, 0x4b}, {0xf9, 0xd8, 0x4b}, {0xf9, 0xd8, 0x4b}, + {0xf9, 0xd8, 0x4a}, {0xf9, 0xd8, 0x4a}, {0xf9, 0xd8, 0x4a}, {0xf9, 0xd8, 0x4a}, {0xf9, 0xd8, 0x49}, {0xf9, 0xd7, 0x49}, + {0xf9, 0xd7, 0x49}, {0xf9, 0xd7, 0x49}, {0xf9, 0xd7, 0x48}, {0xf9, 0xd7, 0x48}, {0xf9, 0xd7, 0x48}, {0xf9, 0xd7, 0x48}, + {0xf9, 0xd6, 0x47}, {0xf9, 0xd6, 0x47}, {0xf9, 0xd6, 0x47}, {0xf9, 0xd6, 0x47}, {0xf9, 0xd6, 0x46}, {0xf9, 0xd6, 0x46}, + {0xf9, 0xd6, 0x46}, {0xf9, 0xd5, 0x46}, {0xf9, 0xd5, 0x45}, {0xf9, 0xd5, 0x45}, {0xf9, 0xd5, 0x45}, {0xf9, 0xd5, 0x45}, + {0xf9, 0xd5, 0x45}, {0xf9, 0xd5, 0x44}, {0xf9, 0xd4, 0x44}, {0xf9, 0xd4, 0x44}, {0xf9, 0xd4, 0x44}, {0xf9, 0xd4, 0x43}, + {0xf9, 0xd4, 0x43}, {0xf9, 0xd4, 0x43}, {0xf9, 0xd4, 0x43}, {0xf9, 0xd3, 0x42}, {0xf9, 0xd3, 0x42}, {0xf9, 0xd3, 0x42}, + {0xf9, 0xd3, 0x42}, {0xf9, 0xd3, 0x41}, {0xf9, 0xd3, 0x41}, {0xf9, 0xd3, 0x41}, {0xf9, 0xd2, 0x41}, {0xf9, 0xd2, 0x40}, + {0xf9, 0xd2, 0x40}, {0xf9, 0xd2, 0x40}, {0xf9, 0xd2, 0x40}, {0xf9, 0xd2, 0x3f}, {0xf9, 0xd2, 0x3f}, {0xf9, 0xd1, 0x3f}, + {0xf9, 0xd1, 0x3f}, {0xf9, 0xd1, 0x3f}, {0xf9, 0xd1, 0x3e}, {0xf9, 0xd1, 0x3e}, {0xf9, 0xd1, 0x3e}, {0xf9, 0xd1, 0x3e}, + {0xf9, 0xd0, 0x3d}, {0xf9, 0xd0, 0x3d}, {0xf9, 0xd0, 0x3d}, {0xf9, 0xd0, 0x3d}, {0xf9, 0xd0, 0x3c}, {0xf9, 0xd0, 0x3c}, + {0xf9, 0xd0, 0x3c}, {0xf9, 0xcf, 0x3c}, {0xf9, 0xcf, 0x3b}, {0xf9, 0xcf, 0x3b}, {0xf9, 0xcf, 0x3b}, {0xf9, 0xcf, 0x3b}, + {0xf9, 0xcf, 0x3a}, {0xf9, 0xcf, 0x3a}, {0xf9, 0xce, 0x3a}, {0xf9, 0xce, 0x3a}, {0xf9, 0xce, 0x39}, {0xf9, 0xce, 0x39}, + {0xf9, 0xce, 0x39}, {0xf9, 0xce, 0x39}, {0xf9, 0xce, 0x38}, {0xf9, 0xcd, 0x38}, {0xf9, 0xcd, 0x38}, {0xf9, 0xcd, 0x38}, + {0xf9, 0xcd, 0x38}, {0xf9, 0xcd, 0x37}, {0xf9, 0xcd, 0x37}, {0xf9, 0xcd, 0x37}, {0xf9, 0xcc, 0x37}, {0xf9, 0xcc, 0x36}, + {0xf9, 0xcc, 0x36}, {0xf9, 0xcc, 0x36}, {0xf9, 0xcc, 0x36}, {0xf9, 0xcc, 0x35}, {0xf9, 0xcc, 0x35}, {0xf9, 0xcb, 0x35}, + {0xf9, 0xcb, 0x35}, {0xf9, 0xcb, 0x34}, {0xf9, 0xcb, 0x34}, {0xf9, 0xcb, 0x34}, {0xf9, 0xcb, 0x34}, {0xf9, 0xcb, 0x33}, + {0xf9, 0xca, 0x33}, {0xf9, 0xca, 0x33}, {0xf9, 0xca, 0x33}, {0xf9, 0xca, 0x32}, {0xf9, 0xca, 0x32}, {0xf9, 0xca, 0x32}, + {0xf9, 0xca, 0x32}, {0xf9, 0xc9, 0x32}, {0xf9, 0xc9, 0x31}, {0xf9, 0xc9, 0x31}, {0xf9, 0xc9, 0x31}, {0xf9, 0xc9, 0x31}, + {0xf9, 0xc9, 0x30}, {0xf9, 0xc9, 0x30}, {0xf9, 0xc8, 0x30}, {0xf9, 0xc8, 0x30}, {0xf9, 0xc8, 0x2f}, {0xf9, 0xc8, 0x2f}, + {0xf9, 0xc8, 0x2f}, {0xf9, 0xc8, 0x2f}, {0xf9, 0xc8, 0x2e}, {0xf9, 0xc7, 0x2e}, {0xf9, 0xc7, 0x2e}, {0xf9, 0xc7, 0x2e}, + {0xf9, 0xc7, 0x2d}, {0xf9, 0xc7, 0x2d}, {0xf9, 0xc7, 0x2d}, {0xf9, 0xc7, 0x2d}, {0xf9, 0xc6, 0x2c}, {0xf9, 0xc6, 0x2c}, + {0xf9, 0xc6, 0x2c}, {0xf9, 0xc6, 0x2c}, {0xf9, 0xc6, 0x2b}, {0xf9, 0xc6, 0x2b}, {0xf9, 0xc6, 0x2b}, {0xf9, 0xc5, 0x2b}, + {0xf9, 0xc5, 0x2b}, {0xf9, 0xc5, 0x2a}, {0xf9, 0xc5, 0x2a}, {0xf9, 0xc5, 0x2a}, {0xf9, 0xc5, 0x2a}, {0xf9, 0xc5, 0x29}, + {0xf9, 0xc4, 0x29}, {0xf9, 0xc4, 0x29}, {0xf9, 0xc4, 0x29}, {0xf9, 0xc4, 0x28}, {0xf9, 0xc4, 0x28}, {0xf9, 0xc4, 0x28}, + {0xf9, 0xc4, 0x28}, {0xf9, 0xc3, 0x27}, {0xf9, 0xc3, 0x27}, {0xf9, 0xc3, 0x27}, {0xf9, 0xc3, 0x27}, {0xf9, 0xc3, 0x26}, + {0xf9, 0xc3, 0x26}, {0xf9, 0xc3, 0x26}, {0xf9, 0xc2, 0x26}, {0xf9, 0xc2, 0x25}, {0xf9, 0xc2, 0x25}, {0xf9, 0xc2, 0x25}, + {0xf9, 0xc2, 0x25}, {0xf9, 0xc2, 0x25}, {0xf9, 0xc2, 0x24}, {0xf9, 0xc1, 0x24}, {0xf9, 0xc1, 0x24}, {0xf9, 0xc1, 0x24}, + {0xf9, 0xc1, 0x23}, {0xf9, 0xc1, 0x23}, {0xf9, 0xc1, 0x23}, {0xf9, 0xc1, 0x23}, {0xf9, 0xc0, 0x22}, {0xf9, 0xc0, 0x22}, + {0xf9, 0xc0, 0x22}, {0xf9, 0xc0, 0x22}, {0xf9, 0xc0, 0x21}, {0xf9, 0xc0, 0x21}, {0xf9, 0xc0, 0x21}, {0xf9, 0xbf, 0x21}, + {0xf9, 0xbf, 0x20}, {0xf9, 0xbf, 0x20}, {0xf9, 0xbf, 0x20}, {0xf9, 0xbf, 0x20}, {0xf9, 0xbf, 0x1f}, {0xf9, 0xbf, 0x1f}, + {0xf9, 0xbe, 0x1f}, {0xf9, 0xbe, 0x1f}, {0xf9, 0xbe, 0x1f}, {0xf9, 0xbe, 0x1e}, {0xf9, 0xbe, 0x1e}, {0xf9, 0xbe, 0x1e}, + {0xf9, 0xbe, 0x1e}, {0xf9, 0xbd, 0x1d}, {0xf9, 0xbd, 0x1d}, {0xf9, 0xbd, 0x1d}, {0xf9, 0xbd, 0x1d}, {0xf9, 0xbd, 0x1c}, + {0xf9, 0xbd, 0x1c}, {0xf9, 0xbd, 0x1c}, {0xf9, 0xbc, 0x1c}, {0xf9, 0xbc, 0x1b}, {0xf9, 0xbc, 0x1b}, {0xf9, 0xbc, 0x1b}, + {0xf9, 0xbc, 0x1b}, {0xf9, 0xbc, 0x1a}, {0xf9, 0xbc, 0x1a}, {0xf9, 0xbb, 0x1a}, {0xf9, 0xbb, 0x1a}, {0xf9, 0xbb, 0x19}, + {0xf9, 0xbb, 0x19}, {0xf9, 0xbb, 0x19}, {0xf9, 0xbb, 0x19}, {0xf9, 0xbb, 0x18}, {0xf9, 0xba, 0x18}, {0xf9, 0xba, 0x18}, + {0xf9, 0xba, 0x18}, {0xf9, 0xba, 0x18}, {0xf9, 0xba, 0x17}, {0xf9, 0xba, 0x17}, {0xf9, 0xba, 0x17}, {0xf9, 0xb9, 0x17}, + {0xf9, 0xb9, 0x16}, {0xf9, 0xb9, 0x16}, {0xf9, 0xb9, 0x16}, {0xf9, 0xb9, 0x16}, {0xf9, 0xb9, 0x15}, {0xf9, 0xb9, 0x15}, + {0xf9, 0xb8, 0x15}, {0xf9, 0xb8, 0x15}, {0xf9, 0xb8, 0x14}, {0xf9, 0xb8, 0x14}, {0xf9, 0xb8, 0x14}, {0xf9, 0xb8, 0x14}, + {0xf9, 0xb8, 0x13}, {0xf9, 0xb7, 0x13}, {0xf9, 0xb7, 0x13}, {0xf9, 0xb7, 0x13}, {0xf9, 0xb7, 0x12}, {0xf9, 0xb7, 0x12}, + {0xf9, 0xb7, 0x12}, {0xf9, 0xb7, 0x12}, {0xf9, 0xb6, 0x12}, {0xf9, 0xb6, 0x11}, {0xf9, 0xb6, 0x11}, {0xf9, 0xb6, 0x11}, + {0xf9, 0xb6, 0x11}, {0xf9, 0xb6, 0x10}, {0xf9, 0xb6, 0x10}, {0xf9, 0xb5, 0x10}, {0xf9, 0xb5, 0x10}, {0xf9, 0xb5, 0x0f}, + {0xf9, 0xb5, 0x0f}, {0xf9, 0xb5, 0x0f}, {0xf9, 0xb5, 0x0f}, {0xf9, 0xb4, 0x0f}, {0xf9, 0xb4, 0x0f}, {0xf9, 0xb4, 0x0f}, + {0xf8, 0xb4, 0x0f}, {0xf8, 0xb3, 0x0f}, {0xf8, 0xb3, 0x0f}, {0xf8, 0xb3, 0x0f}, {0xf8, 0xb3, 0x0f}, {0xf8, 0xb3, 0x0f}, + {0xf8, 0xb2, 0x0f}, {0xf8, 0xb2, 0x0f}, {0xf8, 0xb2, 0x0e}, {0xf7, 0xb2, 0x0e}, {0xf7, 0xb1, 0x0e}, {0xf7, 0xb1, 0x0e}, + {0xf7, 0xb1, 0x0e}, {0xf7, 0xb1, 0x0e}, {0xf7, 0xb0, 0x0e}, {0xf7, 0xb0, 0x0e}, {0xf7, 0xb0, 0x0e}, {0xf7, 0xb0, 0x0e}, + {0xf7, 0xaf, 0x0e}, {0xf6, 0xaf, 0x0e}, {0xf6, 0xaf, 0x0e}, {0xf6, 0xaf, 0x0e}, {0xf6, 0xaf, 0x0e}, {0xf6, 0xae, 0x0e}, + {0xf6, 0xae, 0x0e}, {0xf6, 0xae, 0x0e}, {0xf6, 0xae, 0x0e}, {0xf6, 0xad, 0x0e}, {0xf6, 0xad, 0x0e}, {0xf5, 0xad, 0x0e}, + {0xf5, 0xad, 0x0e}, {0xf5, 0xac, 0x0e}, {0xf5, 0xac, 0x0e}, {0xf5, 0xac, 0x0e}, {0xf5, 0xac, 0x0d}, {0xf5, 0xab, 0x0d}, + {0xf5, 0xab, 0x0d}, {0xf5, 0xab, 0x0d}, {0xf5, 0xab, 0x0d}, {0xf4, 0xaa, 0x0d}, {0xf4, 0xaa, 0x0d}, {0xf4, 0xaa, 0x0d}, + {0xf4, 0xaa, 0x0d}, {0xf4, 0xaa, 0x0d}, {0xf4, 0xa9, 0x0d}, {0xf4, 0xa9, 0x0d}, {0xf4, 0xa9, 0x0d}, {0xf4, 0xa9, 0x0d}, + {0xf3, 0xa8, 0x0d}, {0xf3, 0xa8, 0x0d}, {0xf3, 0xa8, 0x0d}, {0xf3, 0xa8, 0x0d}, {0xf3, 0xa7, 0x0d}, {0xf3, 0xa7, 0x0d}, + {0xf3, 0xa7, 0x0d}, {0xf3, 0xa7, 0x0d}, {0xf3, 0xa6, 0x0d}, {0xf3, 0xa6, 0x0d}, {0xf2, 0xa6, 0x0d}, {0xf2, 0xa6, 0x0c}, + {0xf2, 0xa6, 0x0c}, {0xf2, 0xa5, 0x0c}, {0xf2, 0xa5, 0x0c}, {0xf2, 0xa5, 0x0c}, {0xf2, 0xa5, 0x0c}, {0xf2, 0xa4, 0x0c}, + {0xf2, 0xa4, 0x0c}, {0xf2, 0xa4, 0x0c}, {0xf1, 0xa4, 0x0c}, {0xf1, 0xa3, 0x0c}, {0xf1, 0xa3, 0x0c}, {0xf1, 0xa3, 0x0c}, + {0xf1, 0xa3, 0x0c}, {0xf1, 0xa2, 0x0c}, {0xf1, 0xa2, 0x0c}, {0xf1, 0xa2, 0x0c}, {0xf1, 0xa2, 0x0c}, {0xf0, 0xa2, 0x0c}, + {0xf0, 0xa1, 0x0c}, {0xf0, 0xa1, 0x0c}, {0xf0, 0xa1, 0x0c}, {0xf0, 0xa1, 0x0c}, {0xf0, 0xa0, 0x0c}, {0xf0, 0xa0, 0x0c}, + {0xf0, 0xa0, 0x0c}, {0xf0, 0xa0, 0x0b}, {0xf0, 0x9f, 0x0b}, {0xef, 0x9f, 0x0b}, {0xef, 0x9f, 0x0b}, {0xef, 0x9f, 0x0b}, + {0xef, 0x9e, 0x0b}, {0xef, 0x9e, 0x0b}, {0xef, 0x9e, 0x0b}, {0xef, 0x9e, 0x0b}, {0xef, 0x9e, 0x0b}, {0xef, 0x9d, 0x0b}, + {0xef, 0x9d, 0x0b}, {0xee, 0x9d, 0x0b}, {0xee, 0x9d, 0x0b}, {0xee, 0x9c, 0x0b}, {0xee, 0x9c, 0x0b}, {0xee, 0x9c, 0x0b}, + {0xee, 0x9c, 0x0b}, {0xee, 0x9b, 0x0b}, {0xee, 0x9b, 0x0b}, {0xee, 0x9b, 0x0b}, {0xed, 0x9b, 0x0b}, {0xed, 0x9a, 0x0b}, + {0xed, 0x9a, 0x0b}, {0xed, 0x9a, 0x0b}, {0xed, 0x9a, 0x0b}, {0xed, 0x9a, 0x0a}, {0xed, 0x99, 0x0a}, {0xed, 0x99, 0x0a}, + {0xed, 0x99, 0x0a}, {0xed, 0x99, 0x0a}, {0xec, 0x98, 0x0a}, {0xec, 0x98, 0x0a}, {0xec, 0x98, 0x0a}, {0xec, 0x98, 0x0a}, + {0xec, 0x97, 0x0a}, {0xec, 0x97, 0x0a}, {0xec, 0x97, 0x0a}, {0xec, 0x97, 0x0a}, {0xec, 0x96, 0x0a}, {0xec, 0x96, 0x0a}, + {0xeb, 0x96, 0x0a}, {0xeb, 0x96, 0x0a}, {0xeb, 0x96, 0x0a}, {0xeb, 0x95, 0x0a}, {0xeb, 0x95, 0x0a}, {0xeb, 0x95, 0x0a}, + {0xeb, 0x95, 0x0a}, {0xeb, 0x94, 0x0a}, {0xeb, 0x94, 0x0a}, {0xea, 0x94, 0x0a}, {0xea, 0x94, 0x0a}, {0xea, 0x93, 0x09}, + {0xea, 0x93, 0x09}, {0xea, 0x93, 0x09}, {0xea, 0x93, 0x09}, {0xea, 0x92, 0x09}, {0xea, 0x92, 0x09}, {0xea, 0x92, 0x09}, + {0xea, 0x92, 0x09}, {0xe9, 0x92, 0x09}, {0xe9, 0x91, 0x09}, {0xe9, 0x91, 0x09}, {0xe9, 0x91, 0x09}, {0xe9, 0x91, 0x09}, + {0xe9, 0x90, 0x09}, {0xe9, 0x90, 0x09}, {0xe9, 0x90, 0x09}, {0xe9, 0x90, 0x09}, {0xe9, 0x8f, 0x09}, {0xe8, 0x8f, 0x09}, + {0xe8, 0x8f, 0x09}, {0xe8, 0x8f, 0x09}, {0xe8, 0x8e, 0x09}, {0xe8, 0x8e, 0x09}, {0xe8, 0x8e, 0x09}, {0xe8, 0x8e, 0x09}, + {0xe8, 0x8e, 0x09}, {0xe8, 0x8d, 0x08}, {0xe7, 0x8d, 0x08}, {0xe7, 0x8d, 0x08}, {0xe7, 0x8d, 0x08}, {0xe7, 0x8c, 0x08}, + {0xe7, 0x8c, 0x08}, {0xe7, 0x8c, 0x08}, {0xe7, 0x8c, 0x08}, {0xe7, 0x8b, 0x08}, {0xe7, 0x8b, 0x08}, {0xe7, 0x8b, 0x08}, + {0xe6, 0x8b, 0x08}, {0xe6, 0x8a, 0x08}, {0xe6, 0x8a, 0x08}, {0xe6, 0x8a, 0x08}, {0xe6, 0x8a, 0x08}, {0xe6, 0x89, 0x08}, + {0xe6, 0x89, 0x08}, {0xe6, 0x89, 0x08}, {0xe6, 0x89, 0x08}, {0xe6, 0x89, 0x08}, {0xe5, 0x88, 0x08}, {0xe5, 0x88, 0x08}, + {0xe5, 0x88, 0x08}, {0xe5, 0x88, 0x08}, {0xe5, 0x87, 0x07}, {0xe5, 0x87, 0x07}, {0xe5, 0x87, 0x07}, {0xe5, 0x87, 0x07}, + {0xe5, 0x86, 0x07}, {0xe4, 0x86, 0x07}, {0xe4, 0x86, 0x07}, {0xe4, 0x86, 0x07}, {0xe4, 0x85, 0x07}, {0xe4, 0x85, 0x07}, + {0xe4, 0x85, 0x07}, {0xe4, 0x85, 0x07}, {0xe4, 0x85, 0x07}, {0xe4, 0x84, 0x07}, {0xe4, 0x84, 0x07}, {0xe3, 0x84, 0x07}, + {0xe3, 0x84, 0x07}, {0xe3, 0x83, 0x07}, {0xe3, 0x83, 0x07}, {0xe3, 0x83, 0x07}, {0xe3, 0x83, 0x07}, {0xe3, 0x82, 0x07}, + {0xe3, 0x82, 0x07}, {0xe3, 0x82, 0x07}, {0xe3, 0x82, 0x07}, {0xe2, 0x81, 0x07}, {0xe2, 0x81, 0x06}, {0xe2, 0x81, 0x06}, + {0xe2, 0x81, 0x06}, {0xe2, 0x81, 0x06}, {0xe2, 0x80, 0x06}, {0xe2, 0x80, 0x06}, {0xe2, 0x80, 0x06}, {0xe2, 0x80, 0x06}, + {0xe1, 0x7f, 0x06}, {0xe1, 0x7f, 0x06}, {0xe1, 0x7f, 0x06}, {0xe1, 0x7f, 0x06}, {0xe1, 0x7e, 0x06}, {0xe1, 0x7e, 0x06}, + {0xe1, 0x7e, 0x06}, {0xe1, 0x7e, 0x06}, {0xe1, 0x7d, 0x06}, {0xe1, 0x7d, 0x06}, {0xe0, 0x7d, 0x06}, {0xe0, 0x7d, 0x06}, + {0xe0, 0x7d, 0x06}, {0xe0, 0x7c, 0x06}, {0xe0, 0x7c, 0x06}, {0xe0, 0x7c, 0x06}, {0xe0, 0x7c, 0x06}, {0xe0, 0x7b, 0x06}, + {0xe0, 0x7b, 0x05}, {0xe0, 0x7b, 0x05}, {0xdf, 0x7b, 0x05}, {0xdf, 0x7a, 0x05}, {0xdf, 0x7a, 0x05}, {0xdf, 0x7a, 0x05}, + {0xdf, 0x7a, 0x05}, {0xdf, 0x79, 0x05}, {0xdf, 0x79, 0x05}, {0xdf, 0x79, 0x05}, {0xdf, 0x79, 0x05}, {0xde, 0x79, 0x05}, + {0xde, 0x78, 0x05}, {0xde, 0x78, 0x05}, {0xde, 0x78, 0x05}, {0xde, 0x78, 0x05}, {0xde, 0x77, 0x05}, {0xde, 0x77, 0x05}, + {0xde, 0x77, 0x05}, {0xde, 0x77, 0x05}, {0xde, 0x76, 0x05}, {0xdd, 0x76, 0x05}, {0xdd, 0x76, 0x05}, {0xdd, 0x76, 0x05}, + {0xdd, 0x75, 0x05}, {0xdd, 0x75, 0x05}, {0xdd, 0x75, 0x04}, {0xdd, 0x75, 0x04}, {0xdd, 0x75, 0x04}, {0xdd, 0x74, 0x04}, + {0xdd, 0x74, 0x04}, {0xdc, 0x74, 0x04}, {0xdc, 0x74, 0x04}, {0xdc, 0x73, 0x04}, {0xdc, 0x73, 0x04}, {0xdc, 0x73, 0x04}, + {0xdc, 0x73, 0x04}, {0xdc, 0x72, 0x04}, {0xdc, 0x72, 0x04}, {0xdc, 0x72, 0x04}, {0xdb, 0x72, 0x04}, {0xdb, 0x71, 0x04}, + {0xdb, 0x71, 0x04}, {0xdb, 0x71, 0x04}, {0xdb, 0x71, 0x04}, {0xdb, 0x71, 0x04}, {0xdb, 0x70, 0x04}, {0xdb, 0x70, 0x04}, + {0xdb, 0x70, 0x04}, {0xdb, 0x70, 0x04}, {0xda, 0x6f, 0x04}, {0xda, 0x6f, 0x04}, {0xda, 0x6f, 0x03}, {0xda, 0x6f, 0x03}, + {0xda, 0x6e, 0x03}, {0xda, 0x6e, 0x03}, {0xda, 0x6e, 0x03}, {0xda, 0x6e, 0x03}, {0xda, 0x6d, 0x03}, {0xda, 0x6d, 0x03}, + {0xd9, 0x6d, 0x03}, {0xd9, 0x6d, 0x03}, {0xd9, 0x6c, 0x03}, {0xd9, 0x6c, 0x03}, {0xd9, 0x6c, 0x03}, {0xd9, 0x6c, 0x03}, + {0xd8, 0x6b, 0x03}, {0xd8, 0x6b, 0x03}, {0xd8, 0x6b, 0x03}, {0xd8, 0x6b, 0x03}, {0xd7, 0x6a, 0x03}, {0xd7, 0x6a, 0x03}, + {0xd7, 0x6a, 0x03}, {0xd6, 0x6a, 0x03}, {0xd6, 0x69, 0x03}, {0xd6, 0x69, 0x03}, {0xd6, 0x69, 0x03}, {0xd5, 0x69, 0x03}, + {0xd5, 0x68, 0x03}, {0xd5, 0x68, 0x04}, {0xd4, 0x68, 0x04}, {0xd4, 0x68, 0x04}, {0xd4, 0x67, 0x04}, {0xd4, 0x67, 0x04}, + {0xd3, 0x67, 0x04}, {0xd3, 0x66, 0x04}, {0xd3, 0x66, 0x04}, {0xd2, 0x66, 0x04}, {0xd2, 0x66, 0x04}, {0xd2, 0x65, 0x04}, + {0xd2, 0x65, 0x04}, {0xd1, 0x65, 0x04}, {0xd1, 0x65, 0x04}, {0xd1, 0x64, 0x04}, {0xd0, 0x64, 0x04}, {0xd0, 0x64, 0x04}, + {0xd0, 0x64, 0x04}, {0xd0, 0x63, 0x04}, {0xcf, 0x63, 0x04}, {0xcf, 0x63, 0x04}, {0xcf, 0x63, 0x04}, {0xce, 0x62, 0x04}, + {0xce, 0x62, 0x04}, {0xce, 0x62, 0x04}, {0xce, 0x61, 0x04}, {0xcd, 0x61, 0x04}, {0xcd, 0x61, 0x04}, {0xcd, 0x61, 0x04}, + {0xcc, 0x60, 0x05}, {0xcc, 0x60, 0x05}, {0xcc, 0x60, 0x05}, {0xcb, 0x60, 0x05}, {0xcb, 0x5f, 0x05}, {0xcb, 0x5f, 0x05}, + {0xcb, 0x5f, 0x05}, {0xca, 0x5f, 0x05}, {0xca, 0x5e, 0x05}, {0xca, 0x5e, 0x05}, {0xc9, 0x5e, 0x05}, {0xc9, 0x5e, 0x05}, + {0xc9, 0x5d, 0x05}, {0xc9, 0x5d, 0x05}, {0xc8, 0x5d, 0x05}, {0xc8, 0x5c, 0x05}, {0xc8, 0x5c, 0x05}, {0xc7, 0x5c, 0x05}, + {0xc7, 0x5c, 0x05}, {0xc7, 0x5b, 0x05}, {0xc7, 0x5b, 0x05}, {0xc6, 0x5b, 0x05}, {0xc6, 0x5b, 0x05}, {0xc6, 0x5a, 0x05}, + {0xc5, 0x5a, 0x05}, {0xc5, 0x5a, 0x05}, {0xc5, 0x5a, 0x05}, {0xc5, 0x59, 0x05}, {0xc4, 0x59, 0x05}, {0xc4, 0x59, 0x06}, + {0xc4, 0x59, 0x06}, {0xc3, 0x58, 0x06}, {0xc3, 0x58, 0x06}, {0xc3, 0x58, 0x06}, {0xc3, 0x57, 0x06}, {0xc2, 0x57, 0x06}, + {0xc2, 0x57, 0x06}, {0xc2, 0x57, 0x06}, {0xc1, 0x56, 0x06}, {0xc1, 0x56, 0x06}, {0xc1, 0x56, 0x06}, {0xc1, 0x56, 0x06}, + {0xc0, 0x55, 0x06}, {0xc0, 0x55, 0x06}, {0xc0, 0x55, 0x06}, {0xbf, 0x55, 0x06}, {0xbf, 0x54, 0x06}, {0xbf, 0x54, 0x06}, + {0xbf, 0x54, 0x06}, {0xbe, 0x54, 0x06}, {0xbe, 0x53, 0x06}, {0xbe, 0x53, 0x06}, {0xbd, 0x53, 0x06}, {0xbd, 0x52, 0x06}, + {0xbd, 0x52, 0x06}, {0xbd, 0x52, 0x06}, {0xbc, 0x52, 0x06}, {0xbc, 0x51, 0x07}, {0xbc, 0x51, 0x07}, {0xbb, 0x51, 0x07}, + {0xbb, 0x51, 0x07}, {0xbb, 0x50, 0x07}, {0xbb, 0x50, 0x07}, {0xba, 0x50, 0x07}, {0xba, 0x50, 0x07}, {0xba, 0x4f, 0x07}, + {0xb9, 0x4f, 0x07}, {0xb9, 0x4f, 0x07}, {0xb9, 0x4e, 0x07}, {0xb8, 0x4e, 0x07}, {0xb8, 0x4e, 0x07}, {0xb8, 0x4e, 0x07}, + {0xb8, 0x4d, 0x07}, {0xb7, 0x4d, 0x07}, {0xb7, 0x4d, 0x07}, {0xb7, 0x4d, 0x07}, {0xb6, 0x4c, 0x07}, {0xb6, 0x4c, 0x07}, + {0xb6, 0x4c, 0x07}, {0xb6, 0x4c, 0x07}, {0xb5, 0x4b, 0x07}, {0xb5, 0x4b, 0x07}, {0xb5, 0x4b, 0x07}, {0xb4, 0x4b, 0x07}, + {0xb4, 0x4a, 0x07}, {0xb4, 0x4a, 0x07}, {0xb4, 0x4a, 0x08}, {0xb3, 0x49, 0x08}, {0xb3, 0x49, 0x08}, {0xb3, 0x49, 0x08}, + {0xb2, 0x49, 0x08}, {0xb2, 0x48, 0x08}, {0xb2, 0x48, 0x08}, {0xb2, 0x48, 0x08}, {0xb1, 0x48, 0x08}, {0xb1, 0x47, 0x08}, + {0xb1, 0x47, 0x08}, {0xb0, 0x47, 0x08}, {0xb0, 0x47, 0x08}, {0xb0, 0x46, 0x08}, {0xb0, 0x46, 0x08}, {0xaf, 0x46, 0x08}, + {0xaf, 0x46, 0x08}, {0xaf, 0x45, 0x08}, {0xae, 0x45, 0x08}, {0xae, 0x45, 0x08}, {0xae, 0x44, 0x08}, {0xae, 0x44, 0x08}, + {0xad, 0x44, 0x08}, {0xad, 0x44, 0x08}, {0xad, 0x43, 0x08}, {0xac, 0x43, 0x08}, {0xac, 0x43, 0x08}, {0xac, 0x43, 0x08}, + {0xac, 0x42, 0x08}, {0xab, 0x42, 0x09}, {0xab, 0x42, 0x09}, {0xab, 0x42, 0x09}, {0xaa, 0x41, 0x09}, {0xaa, 0x41, 0x09}, + {0xaa, 0x41, 0x09}, {0xaa, 0x41, 0x09}, {0xa9, 0x40, 0x09}, {0xa9, 0x40, 0x09}, {0xa9, 0x40, 0x09}, {0xa8, 0x3f, 0x09}, + {0xa8, 0x3f, 0x09}, {0xa8, 0x3f, 0x09}, {0xa7, 0x3f, 0x09}, {0xa7, 0x3e, 0x09}, {0xa7, 0x3e, 0x09}, {0xa7, 0x3e, 0x09}, + {0xa6, 0x3e, 0x09}, {0xa6, 0x3d, 0x09}, {0xa6, 0x3d, 0x09}, {0xa5, 0x3d, 0x09}, {0xa5, 0x3d, 0x09}, {0xa5, 0x3c, 0x09}, + {0xa5, 0x3c, 0x09}, {0xa4, 0x3c, 0x09}, {0xa4, 0x3c, 0x09}, {0xa4, 0x3b, 0x09}, {0xa3, 0x3b, 0x09}, {0xa3, 0x3b, 0x09}, + {0xa3, 0x3a, 0x0a}, {0xa3, 0x3a, 0x0a}, {0xa2, 0x3a, 0x0a}, {0xa2, 0x3a, 0x0a}, {0xa2, 0x39, 0x0a}, {0xa1, 0x39, 0x0a}, + {0xa1, 0x39, 0x0a}, {0xa1, 0x39, 0x0a}, {0xa1, 0x38, 0x0a}, {0xa0, 0x38, 0x0a}, {0xa0, 0x38, 0x0a}, {0xa0, 0x38, 0x0a}, + {0x9f, 0x37, 0x0a}, {0x9f, 0x37, 0x0a}, {0x9f, 0x37, 0x0a}, {0x9f, 0x36, 0x0a}, {0x9e, 0x36, 0x0a}, {0x9e, 0x36, 0x0a}, + {0x9e, 0x36, 0x0a}, {0x9d, 0x35, 0x0a}, {0x9d, 0x35, 0x0a}, {0x9d, 0x35, 0x0a}, {0x9d, 0x35, 0x0a}, {0x9c, 0x34, 0x0a}, + {0x9c, 0x34, 0x0a}, {0x9c, 0x34, 0x0a}, {0x9b, 0x34, 0x0a}, {0x9b, 0x33, 0x0a}, {0x9b, 0x33, 0x0a}, {0x9b, 0x33, 0x0b}, + {0x9a, 0x33, 0x0b}, {0x9a, 0x32, 0x0b}, {0x9a, 0x32, 0x0b}, {0x99, 0x32, 0x0b}, {0x99, 0x31, 0x0b}, {0x99, 0x31, 0x0b}, + {0x99, 0x31, 0x0b}, {0x98, 0x31, 0x0b}, {0x98, 0x30, 0x0b}, {0x98, 0x30, 0x0b}, {0x97, 0x30, 0x0b}, {0x97, 0x30, 0x0b}, + {0x97, 0x2f, 0x0b}, {0x97, 0x2f, 0x0b}, {0x96, 0x2f, 0x0b}, {0x96, 0x2f, 0x0b}, {0x96, 0x2e, 0x0b}, {0x95, 0x2e, 0x0b}, + {0x95, 0x2e, 0x0b}, {0x95, 0x2e, 0x0b}, {0x94, 0x2d, 0x0b}, {0x94, 0x2d, 0x0b}, {0x94, 0x2d, 0x0b}, {0x94, 0x2c, 0x0b}, + {0x93, 0x2c, 0x0b}, {0x93, 0x2c, 0x0b}, {0x93, 0x2c, 0x0b}, {0x92, 0x2b, 0x0b}, {0x92, 0x2b, 0x0c}, {0x92, 0x2b, 0x0c}, + {0x92, 0x2b, 0x0c}, {0x91, 0x2a, 0x0c}, {0x91, 0x2a, 0x0c}, {0x91, 0x2a, 0x0c}, {0x90, 0x2a, 0x0c}, {0x90, 0x29, 0x0c}, + {0x90, 0x29, 0x0c}, {0x90, 0x29, 0x0c}, {0x8f, 0x29, 0x0c}, {0x8f, 0x28, 0x0c}, {0x8f, 0x28, 0x0c}, {0x8e, 0x28, 0x0c}, + {0x8e, 0x27, 0x0c}, {0x8e, 0x27, 0x0c}, {0x8e, 0x27, 0x0c}, {0x8d, 0x27, 0x0c}, {0x8d, 0x26, 0x0c}, {0x8d, 0x26, 0x0c}, + {0x8c, 0x26, 0x0c}, {0x8c, 0x26, 0x0c}, {0x8c, 0x25, 0x0c}, {0x8c, 0x25, 0x0c}, {0x8b, 0x25, 0x0c}, {0x8b, 0x25, 0x0c}, + {0x8b, 0x24, 0x0c}, {0x8a, 0x24, 0x0c}, {0x8a, 0x24, 0x0d}, {0x8a, 0x24, 0x0d}, {0x8a, 0x23, 0x0d}, {0x89, 0x23, 0x0d}, + {0x89, 0x23, 0x0d}, {0x89, 0x22, 0x0d}, {0x88, 0x22, 0x0d}, {0x88, 0x22, 0x0d}, {0x88, 0x22, 0x0d}, {0x88, 0x21, 0x0d}, + {0x87, 0x21, 0x0d}, {0x87, 0x21, 0x0d}, {0x87, 0x21, 0x0d}, {0x86, 0x20, 0x0d}, {0x86, 0x20, 0x0d}, {0x86, 0x20, 0x0d}, + {0x86, 0x20, 0x0d}, {0x85, 0x20, 0x0d}, {0x85, 0x20, 0x0d}, {0x85, 0x20, 0x0d}, {0x84, 0x1f, 0x0d}, {0x84, 0x1f, 0x0e}, + {0x84, 0x1f, 0x0e}, {0x84, 0x1f, 0x0e}, {0x83, 0x1f, 0x0e}, {0x83, 0x1f, 0x0e}, {0x83, 0x1f, 0x0e}, {0x82, 0x1f, 0x0e}, + {0x82, 0x1f, 0x0e}, {0x82, 0x1e, 0x0e}, {0x82, 0x1e, 0x0e}, {0x81, 0x1e, 0x0e}, {0x81, 0x1e, 0x0e}, {0x81, 0x1e, 0x0f}, + {0x80, 0x1e, 0x0f}, {0x80, 0x1e, 0x0f}, {0x80, 0x1e, 0x0f}, {0x80, 0x1e, 0x0f}, {0x7f, 0x1e, 0x0f}, {0x7f, 0x1d, 0x0f}, + {0x7f, 0x1d, 0x0f}, {0x7e, 0x1d, 0x0f}, {0x7e, 0x1d, 0x0f}, {0x7e, 0x1d, 0x0f}, {0x7e, 0x1d, 0x0f}, {0x7d, 0x1d, 0x0f}, + {0x7d, 0x1d, 0x10}, {0x7d, 0x1d, 0x10}, {0x7c, 0x1d, 0x10}, {0x7c, 0x1c, 0x10}, {0x7c, 0x1c, 0x10}, {0x7c, 0x1c, 0x10}, + {0x7b, 0x1c, 0x10}, {0x7b, 0x1c, 0x10}, {0x7b, 0x1c, 0x10}, {0x7a, 0x1c, 0x10}, {0x7a, 0x1c, 0x10}, {0x7a, 0x1c, 0x10}, + {0x7a, 0x1b, 0x11}, {0x79, 0x1b, 0x11}, {0x79, 0x1b, 0x11}, {0x79, 0x1b, 0x11}, {0x78, 0x1b, 0x11}, {0x78, 0x1b, 0x11}, + {0x78, 0x1b, 0x11}, {0x78, 0x1b, 0x11}, {0x77, 0x1b, 0x11}, {0x77, 0x1b, 0x11}, {0x77, 0x1a, 0x11}, {0x76, 0x1a, 0x11}, + {0x76, 0x1a, 0x12}, {0x76, 0x1a, 0x12}, {0x76, 0x1a, 0x12}, {0x75, 0x1a, 0x12}, {0x75, 0x1a, 0x12}, {0x75, 0x1a, 0x12}, + {0x74, 0x1a, 0x12}, {0x74, 0x1a, 0x12}, {0x74, 0x19, 0x12}, {0x74, 0x19, 0x12}, {0x73, 0x19, 0x12}, {0x73, 0x19, 0x12}, + {0x73, 0x19, 0x13}, {0x72, 0x19, 0x13}, {0x72, 0x19, 0x13}, {0x72, 0x19, 0x13}, {0x72, 0x19, 0x13}, {0x71, 0x18, 0x13}, + {0x71, 0x18, 0x13}, {0x71, 0x18, 0x13}, {0x70, 0x18, 0x13}, {0x70, 0x18, 0x13}, {0x70, 0x18, 0x13}, {0x70, 0x18, 0x13}, + {0x6f, 0x18, 0x13}, {0x6f, 0x18, 0x14}, {0x6f, 0x18, 0x14}, {0x6e, 0x17, 0x14}, {0x6e, 0x17, 0x14}, {0x6e, 0x17, 0x14}, + {0x6e, 0x17, 0x14}, {0x6d, 0x17, 0x14}, {0x6d, 0x17, 0x14}, {0x6d, 0x17, 0x14}, {0x6c, 0x17, 0x14}, {0x6c, 0x17, 0x14}, + {0x6c, 0x17, 0x14}, {0x6c, 0x16, 0x15}, {0x6b, 0x16, 0x15}, {0x6b, 0x16, 0x15}, {0x6b, 0x16, 0x15}, {0x6a, 0x16, 0x15}, + {0x6a, 0x16, 0x15}, {0x6a, 0x16, 0x15}, {0x6a, 0x16, 0x15}, {0x69, 0x16, 0x15}, {0x69, 0x15, 0x15}, {0x69, 0x15, 0x15}, + {0x69, 0x15, 0x15}, {0x68, 0x15, 0x16}, {0x68, 0x15, 0x16}, {0x68, 0x15, 0x16}, {0x67, 0x15, 0x16}, {0x67, 0x15, 0x16}, + {0x67, 0x15, 0x16}, {0x67, 0x15, 0x16}, {0x66, 0x14, 0x16}, {0x66, 0x14, 0x16}, {0x66, 0x14, 0x16}, {0x65, 0x14, 0x16}, + {0x65, 0x14, 0x16}, {0x65, 0x14, 0x16}, {0x65, 0x14, 0x17}, {0x64, 0x14, 0x17}, {0x64, 0x14, 0x17}, {0x64, 0x14, 0x17}, + {0x63, 0x13, 0x17}, {0x63, 0x13, 0x17}, {0x63, 0x13, 0x17}, {0x63, 0x13, 0x17}, {0x62, 0x13, 0x17}, {0x62, 0x13, 0x17}, + {0x62, 0x13, 0x17}, {0x61, 0x13, 0x17}, {0x61, 0x13, 0x18}, {0x61, 0x12, 0x18}, {0x61, 0x12, 0x18}, {0x60, 0x12, 0x18}, + {0x60, 0x12, 0x18}, {0x60, 0x12, 0x18}, {0x5f, 0x12, 0x18}, {0x5f, 0x12, 0x18}, {0x5f, 0x12, 0x18}, {0x5f, 0x12, 0x18}, + {0x5e, 0x12, 0x18}, {0x5e, 0x11, 0x18}, {0x5e, 0x11, 0x19}, {0x5d, 0x11, 0x19}, {0x5d, 0x11, 0x19}, {0x5d, 0x11, 0x19}, + {0x5d, 0x11, 0x19}, {0x5c, 0x11, 0x19}, {0x5c, 0x11, 0x19}, {0x5c, 0x11, 0x19}, {0x5b, 0x11, 0x19}, {0x5b, 0x10, 0x19}, + {0x5b, 0x10, 0x19}, {0x5b, 0x10, 0x19}, {0x5a, 0x10, 0x19}, {0x5a, 0x10, 0x1a}, {0x5a, 0x10, 0x1a}, {0x59, 0x10, 0x1a}, + {0x59, 0x10, 0x1a}, {0x59, 0x10, 0x1a}, {0x59, 0x0f, 0x1a}, {0x58, 0x0f, 0x1a}, {0x58, 0x0f, 0x1a}, {0x58, 0x0f, 0x1a}, + {0x57, 0x0f, 0x1a}, {0x57, 0x0f, 0x1a}, {0x57, 0x0f, 0x1a}, {0x57, 0x0f, 0x1b}, {0x56, 0x0f, 0x1b}, {0x56, 0x0f, 0x1b}, + {0x56, 0x0e, 0x1b}, {0x55, 0x0e, 0x1b}, {0x55, 0x0e, 0x1b}, {0x55, 0x0e, 0x1b}, {0x55, 0x0e, 0x1b}, {0x54, 0x0e, 0x1b}, + {0x54, 0x0e, 0x1b}, {0x54, 0x0e, 0x1b}, {0x53, 0x0e, 0x1b}, {0x53, 0x0e, 0x1c}, {0x53, 0x0d, 0x1c}, {0x53, 0x0d, 0x1c}, + {0x52, 0x0d, 0x1c}, {0x52, 0x0d, 0x1c}, {0x52, 0x0d, 0x1c}, {0x51, 0x0d, 0x1c}, {0x51, 0x0d, 0x1c}, {0x51, 0x0d, 0x1c}, + {0x51, 0x0d, 0x1c}, {0x50, 0x0c, 0x1c}, {0x50, 0x0c, 0x1c}, {0x50, 0x0c, 0x1c}, {0x4f, 0x0c, 0x1d}, {0x4f, 0x0c, 0x1d}, + {0x4f, 0x0c, 0x1d}, {0x4f, 0x0c, 0x1d}, {0x4e, 0x0c, 0x1d}, {0x4e, 0x0c, 0x1d}, {0x4e, 0x0c, 0x1d}, {0x4d, 0x0b, 0x1d}, + {0x4d, 0x0b, 0x1d}, {0x4d, 0x0b, 0x1d}, {0x4d, 0x0b, 0x1d}, {0x4c, 0x0b, 0x1d}, {0x4c, 0x0b, 0x1e}, {0x4c, 0x0b, 0x1e}, + {0x4b, 0x0b, 0x1e}, {0x4b, 0x0b, 0x1e}, {0x4b, 0x0b, 0x1e}, {0x4b, 0x0a, 0x1e}, {0x4a, 0x0a, 0x1e}, {0x4a, 0x0a, 0x1e}, + {0x4a, 0x0a, 0x1e}, {0x49, 0x0a, 0x1e}, {0x49, 0x0a, 0x1e}, {0x49, 0x0a, 0x1e}, {0x49, 0x0a, 0x1f}, {0x48, 0x0a, 0x1f}, + {0x48, 0x09, 0x1f}, {0x48, 0x09, 0x1f}, {0x48, 0x09, 0x1f}, {0x47, 0x09, 0x1f}, {0x47, 0x09, 0x1f}, {0x47, 0x09, 0x1f}, + {0x46, 0x09, 0x1f}, {0x46, 0x09, 0x1f}, {0x46, 0x09, 0x1f}, {0x46, 0x09, 0x1f}, {0x45, 0x08, 0x20}, {0x45, 0x08, 0x20}, + {0x45, 0x08, 0x20}, {0x44, 0x08, 0x20}, {0x44, 0x08, 0x20}, {0x44, 0x08, 0x20}, {0x44, 0x08, 0x20}, {0x43, 0x08, 0x20}, + {0x43, 0x08, 0x20}, {0x43, 0x08, 0x20}, {0x42, 0x07, 0x20}, {0x42, 0x07, 0x20}, {0x42, 0x07, 0x20}, {0x42, 0x07, 0x21}, + {0x41, 0x07, 0x21}, {0x41, 0x07, 0x21}, {0x41, 0x07, 0x21}, {0x40, 0x07, 0x21}, {0x40, 0x07, 0x21}, {0x40, 0x06, 0x21}, + {0x40, 0x06, 0x21}, {0x3f, 0x06, 0x21}, {0x3f, 0x06, 0x21}, {0x3f, 0x06, 0x21}, {0x3e, 0x06, 0x21}, {0x3e, 0x06, 0x22}, + {0x3e, 0x06, 0x22}, {0x3e, 0x06, 0x22}, {0x3d, 0x06, 0x22}, {0x3d, 0x05, 0x22}, {0x3d, 0x05, 0x22}, {0x3c, 0x05, 0x22}, + {0x3c, 0x05, 0x22}, {0x3c, 0x05, 0x22}, {0x3c, 0x05, 0x22}, {0x3b, 0x05, 0x22}, {0x3b, 0x05, 0x22}, {0x3b, 0x05, 0x23}, + {0x3a, 0x05, 0x23}, {0x3a, 0x04, 0x23}, {0x3a, 0x04, 0x23}, {0x3a, 0x04, 0x23}, {0x39, 0x04, 0x23}, {0x39, 0x04, 0x23}, + {0x39, 0x04, 0x23}, {0x39, 0x04, 0x23}, {0x38, 0x04, 0x24}, {0x38, 0x04, 0x24}, {0x38, 0x04, 0x24}, {0x38, 0x04, 0x24}, + {0x38, 0x04, 0x24}, {0x38, 0x04, 0x24}, {0x37, 0x04, 0x25}, {0x37, 0x04, 0x25}, {0x37, 0x04, 0x25}, {0x37, 0x04, 0x25}, + {0x37, 0x04, 0x25}, {0x37, 0x04, 0x26}, {0x36, 0x04, 0x26}, {0x36, 0x04, 0x26}, {0x36, 0x04, 0x26}, {0x36, 0x04, 0x26}, + {0x36, 0x05, 0x26}, {0x36, 0x05, 0x27}, {0x35, 0x05, 0x27}, {0x35, 0x05, 0x27}, {0x35, 0x05, 0x27}, {0x35, 0x05, 0x27}, + {0x35, 0x05, 0x28}, {0x35, 0x05, 0x28}, {0x34, 0x05, 0x28}, {0x34, 0x05, 0x28}, {0x34, 0x05, 0x28}, {0x34, 0x05, 0x29}, + {0x34, 0x05, 0x29}, {0x34, 0x05, 0x29}, {0x33, 0x05, 0x29}, {0x33, 0x05, 0x29}, {0x33, 0x05, 0x29}, {0x33, 0x05, 0x2a}, + {0x33, 0x05, 0x2a}, {0x33, 0x05, 0x2a}, {0x32, 0x05, 0x2a}, {0x32, 0x05, 0x2a}, {0x32, 0x05, 0x2b}, {0x32, 0x05, 0x2b}, + {0x32, 0x05, 0x2b}, {0x32, 0x05, 0x2b}, {0x31, 0x05, 0x2b}, {0x31, 0x05, 0x2b}, {0x31, 0x05, 0x2c}, {0x31, 0x05, 0x2c}, + {0x31, 0x05, 0x2c}, {0x31, 0x05, 0x2c}, {0x30, 0x05, 0x2c}, {0x30, 0x05, 0x2d}, {0x30, 0x05, 0x2d}, {0x30, 0x05, 0x2d}, + {0x30, 0x06, 0x2d}, {0x30, 0x06, 0x2d}, {0x2f, 0x06, 0x2d}, {0x2f, 0x06, 0x2e}, {0x2f, 0x06, 0x2e}, {0x2f, 0x06, 0x2e}, + {0x2f, 0x06, 0x2e}, {0x2f, 0x06, 0x2e}, {0x2e, 0x06, 0x2f}, {0x2e, 0x06, 0x2f}, {0x2e, 0x06, 0x2f}, {0x2e, 0x06, 0x2f}, + {0x2e, 0x06, 0x2f}, {0x2e, 0x06, 0x2f}, {0x2d, 0x06, 0x30}, {0x2d, 0x06, 0x30}, {0x2d, 0x06, 0x30}, {0x2d, 0x06, 0x30}, + {0x2d, 0x06, 0x30}, {0x2d, 0x06, 0x31}, {0x2c, 0x06, 0x31}, {0x2c, 0x06, 0x31}, {0x2c, 0x06, 0x31}, {0x2c, 0x06, 0x31}, + {0x2c, 0x06, 0x32}, {0x2c, 0x06, 0x32}, {0x2b, 0x06, 0x32}, {0x2b, 0x06, 0x32}, {0x2b, 0x06, 0x32}, {0x2b, 0x06, 0x32}, + {0x2b, 0x06, 0x33}, {0x2b, 0x06, 0x33}, {0x2a, 0x06, 0x33}, {0x2a, 0x06, 0x33}, {0x2a, 0x06, 0x33}, {0x2a, 0x06, 0x34}, + {0x2a, 0x06, 0x34}, {0x2a, 0x07, 0x34}, {0x29, 0x07, 0x34}, {0x29, 0x07, 0x34}, {0x29, 0x07, 0x34}, {0x29, 0x07, 0x35}, + {0x29, 0x07, 0x35}, {0x29, 0x07, 0x35}, {0x28, 0x07, 0x35}, {0x28, 0x07, 0x35}, {0x28, 0x07, 0x36}, {0x28, 0x07, 0x36}, + {0x28, 0x07, 0x36}, {0x28, 0x07, 0x36}, {0x27, 0x07, 0x36}, {0x27, 0x07, 0x36}, {0x27, 0x07, 0x37}, {0x27, 0x07, 0x37}, + {0x27, 0x07, 0x37}, {0x27, 0x07, 0x37}, {0x26, 0x07, 0x37}, {0x26, 0x07, 0x38}, {0x26, 0x07, 0x38}, {0x26, 0x07, 0x38}, + {0x26, 0x07, 0x38}, {0x26, 0x07, 0x38}, {0x25, 0x07, 0x38}, {0x25, 0x07, 0x39}, {0x25, 0x07, 0x39}, {0x25, 0x07, 0x39}, + {0x25, 0x07, 0x39}, {0x25, 0x07, 0x39}, {0x24, 0x07, 0x3a}, {0x24, 0x07, 0x3a}, {0x24, 0x07, 0x3a}, {0x24, 0x07, 0x3a}, + {0x24, 0x07, 0x3a}, {0x23, 0x08, 0x3b}, {0x23, 0x08, 0x3b}, {0x23, 0x08, 0x3b}, {0x23, 0x08, 0x3b}, {0x23, 0x08, 0x3b}, + {0x23, 0x08, 0x3b}, {0x22, 0x08, 0x3c}, {0x22, 0x08, 0x3c}, {0x22, 0x08, 0x3c}, {0x22, 0x08, 0x3c}, {0x22, 0x08, 0x3c}, + {0x22, 0x08, 0x3d}, {0x21, 0x08, 0x3d}, {0x21, 0x08, 0x3d}, {0x21, 0x08, 0x3d}, {0x21, 0x08, 0x3d}, {0x21, 0x08, 0x3d}, + {0x21, 0x08, 0x3e}, {0x20, 0x08, 0x3e}, {0x20, 0x08, 0x3e}, {0x20, 0x08, 0x3e}, {0x20, 0x08, 0x3e}, {0x20, 0x08, 0x3f}, + {0x20, 0x08, 0x3f}, {0x1f, 0x08, 0x3f}, {0x1f, 0x08, 0x3f}, {0x1f, 0x08, 0x3f}, {0x1f, 0x08, 0x3f}, {0x1f, 0x08, 0x40}, + {0x1f, 0x08, 0x40}, {0x1e, 0x08, 0x40}, {0x1e, 0x08, 0x40}, {0x1e, 0x08, 0x40}, {0x1e, 0x08, 0x41}, {0x1e, 0x08, 0x41}, + {0x1e, 0x08, 0x41}, {0x1d, 0x08, 0x41}, {0x1d, 0x09, 0x41}, {0x1d, 0x09, 0x41}, {0x1d, 0x09, 0x42}, {0x1d, 0x09, 0x42}, + {0x1d, 0x09, 0x42}, {0x1c, 0x09, 0x42}, {0x1c, 0x09, 0x42}, {0x1c, 0x09, 0x43}, {0x1c, 0x09, 0x43}, {0x1c, 0x09, 0x43}, + {0x1c, 0x09, 0x43}, {0x1b, 0x09, 0x43}, {0x1b, 0x09, 0x43}, {0x1b, 0x09, 0x44}, {0x1b, 0x09, 0x44}, {0x1b, 0x09, 0x44}, + {0x1b, 0x09, 0x44}, {0x1a, 0x09, 0x44}, {0x1a, 0x09, 0x45}, {0x1a, 0x09, 0x45}, {0x1a, 0x09, 0x45}, {0x1a, 0x09, 0x45}, + {0x1a, 0x09, 0x45}, {0x19, 0x09, 0x46}, {0x19, 0x09, 0x46}, {0x19, 0x09, 0x46}, {0x19, 0x09, 0x46}, {0x19, 0x09, 0x46}, + {0x19, 0x09, 0x46}, {0x18, 0x09, 0x47}, {0x18, 0x09, 0x47}, {0x18, 0x09, 0x47}, {0x18, 0x09, 0x47}, {0x18, 0x09, 0x47}, + {0x18, 0x09, 0x48}, {0x17, 0x09, 0x48}, {0x17, 0x09, 0x48}, {0x17, 0x0a, 0x48}, {0x17, 0x0a, 0x48}, {0x17, 0x0a, 0x48}, + {0x17, 0x0a, 0x49}, {0x16, 0x0a, 0x49}, {0x16, 0x0a, 0x49}, {0x16, 0x0a, 0x49}, {0x16, 0x0a, 0x49}, {0x16, 0x0a, 0x4a}, + {0x16, 0x0a, 0x4a}, {0x15, 0x0a, 0x4a}, {0x15, 0x0a, 0x4a}, {0x15, 0x0a, 0x4a}, {0x15, 0x0a, 0x4a}, {0x15, 0x0a, 0x4b}, + {0x15, 0x0a, 0x4b}, {0x14, 0x0a, 0x4b}, {0x14, 0x0a, 0x4b}, {0x14, 0x0a, 0x4b}, {0x14, 0x0a, 0x4c}, {0x14, 0x0a, 0x4c}, + {0x14, 0x0a, 0x4c}, {0x13, 0x0a, 0x4c}, {0x13, 0x0a, 0x4c}, {0x13, 0x0a, 0x4c}, {0x13, 0x0a, 0x4d}, {0x13, 0x0a, 0x4d}, + {0x13, 0x0a, 0x4d}, {0x12, 0x0a, 0x4d}, {0x12, 0x0a, 0x4d}, {0x12, 0x0a, 0x4e}, {0x12, 0x0a, 0x4e}, {0x12, 0x0a, 0x4e}, + {0x12, 0x0a, 0x4e}, {0x11, 0x0a, 0x4e}, {0x11, 0x0a, 0x4f}, {0x11, 0x0b, 0x4f}, {0x11, 0x0b, 0x4f}, {0x11, 0x0b, 0x4f}, + {0x11, 0x0b, 0x4f}, {0x10, 0x0b, 0x4f}, {0x10, 0x0b, 0x50}, {0x10, 0x0b, 0x50}, {0x10, 0x0b, 0x50}, {0x10, 0x0b, 0x50}, + {0x10, 0x0b, 0x50}, {0x0f, 0x0b, 0x51}, {0x0f, 0x0b, 0x51}, {0x0f, 0x0b, 0x51}, {0x0f, 0x0b, 0x51}, {0x0f, 0x0b, 0x51}, + {0x0f, 0x0b, 0x51}, {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x52}, {0x0e, 0x0b, 0x52} +}; diff --git a/ext/wasm3/test/wasi/mandelbrot/doubledouble.h b/ext/wasm3/test/wasi/mandelbrot/doubledouble.h new file mode 100644 index 0000000..54e7150 --- /dev/null +++ b/ext/wasm3/test/wasi/mandelbrot/doubledouble.h @@ -0,0 +1,147 @@ +#include + +typedef struct { + double hi; + double lo; +} DoubleDouble; + +static inline DoubleDouble dd_new(double hi, double lo) { + DoubleDouble num; + num.hi = hi; + num.lo = lo; + return num; +} + +unsigned int dd_get_ui(DoubleDouble num) { + return num.hi; +} + +static inline DoubleDouble dd_sqrt(DoubleDouble num) { + double a, b, c, d, e; + d = 1 / sqrt(num.hi); + e = num.hi * d; + a = 0x08000001 * e; + a += e - a; + b = e - a; + c = e * e; + b = ((a * a - c) + a * b * 2) + b * b; + a = num.hi - c; + c = num.hi - a; + c = (a + ((((num.hi - (c + a)) + (c - c)) + num.lo) - b)) * d * 0.5; + a = e + c; + b = e - a; + return dd_new(a, (e - (b + a)) + (b + c)); +} + +static inline DoubleDouble dd_div(DoubleDouble num1, DoubleDouble num2) { + double a, b, c, d, e, f, g; + f = num1.hi / num2.hi; + a = 0x08000001 * num2.hi; + a += num2.hi - a; + b = num2.hi - a; + c = 0x08000001 * f; + c += f - c; + d = f - c; + e = num2.hi * f; + c = (((a * c - e) + (a * d + b * c)) + b * d) + num2.lo * f; + b = num1.lo - c; + d = num1.lo - b; + a = num1.hi - e; + e = (num1.hi - ((num1.hi - a) + a)) + b; + g = a + e; + e += (a - g) + ((num1.lo - (d + b)) + (d - c)); + a = g + e; + b = a / num2.hi; + f += (e + (g - a)) / num2.hi; + a = f + b; + return dd_new(a, b + (f - a)); +} + +static inline DoubleDouble dd_ui_div(unsigned int num1, DoubleDouble num2) { + return dd_div(dd_new(num1, 0), num2); +} + +static inline DoubleDouble dd_div_ui(DoubleDouble num1, unsigned int num2) { + return dd_div(num1, dd_new(num2, 0)); +} + +static inline DoubleDouble dd_si_div(signed int num1, DoubleDouble num2) { + return dd_div(dd_new(num1, 0), num2); +} + +static inline DoubleDouble dd_div_si(DoubleDouble num1, signed int num2) { + return dd_div(num1, dd_new(num2, 0)); +} + +static inline DoubleDouble dd_add(DoubleDouble num1, DoubleDouble num2) { + double a, b, c, d, e, f; + e = num1.hi + num2.hi; + d = num1.hi - e; + a = num1.lo + num2.lo; + f = num1.lo - a; + d = ((num1.hi - (d + e)) + (d + num2.hi)) + a; + b = e + d; + c = ((num1.lo - (f + a)) + (f + num2.lo)) + (d + (e - b)); + a = b + c; + return dd_new(a, c + (b - a)); +} + +static inline DoubleDouble dd_mul(DoubleDouble num1, DoubleDouble num2) { + double a, b, c, d, e; + a = 0x08000001 * num1.hi; + a += num1.hi - a; + b = num1.hi - a; + c = 0x08000001 * num2.hi; + c += num2.hi - c; + d = num2.hi - c; + e = num1.hi * num2.hi; + c = (((a * c - e) + (a * d + b * c)) + b * d) + (num1.lo * num2.hi + num1.hi * num2.lo); + a = e + c; + return dd_new(a, c + (e - a)); +} + +static inline DoubleDouble dd_mul2(DoubleDouble num1, DoubleDouble num2) { + double a, b, c, d, e; + a = 0x08000001 * num1.hi; + a += num1.hi - a; + b = num1.hi - a; + c = 0x08000001 * num2.hi; + c += num2.hi - c; + d = num2.hi - c; + e = num1.hi * num2.hi; + c = 2*((((a * c - e) + (a * d + b * c)) + b * d) + (num1.lo * num2.hi + num1.hi * num2.lo)); + a = 2*e + c; + return dd_new(a, c + (2*e - a)); +} + +static inline DoubleDouble dd_mul_ui(DoubleDouble num1, unsigned int num2) { + return dd_mul(num1, dd_new(num2, 0)); +} + +static inline DoubleDouble dd_mul_d(DoubleDouble num1, double num2) { + return dd_mul(num1, dd_new(num2, 0)); +} + +static inline DoubleDouble dd_sub(DoubleDouble num1, DoubleDouble num2) { + double a, b, c, d, e, f, g; + g = num1.lo - num2.lo; + f = num1.lo - g; + e = num1.hi - num2.hi; + d = num1.hi - e; + d = ((num1.hi - (d + e)) + (d - num2.hi)) + g; + b = e + d; + c = (d + (e - b)) + ((num1.lo - (f + g)) + (f - num2.lo)); + a = b + c; + return dd_new(a, c + (b - a)); +} + +static inline DoubleDouble dd_sqr(DoubleDouble num) { + double a, b, c; + a = 0x08000001 * num.hi; + a += num.hi - a; + b = num.hi - a; + c = num.hi * num.hi; + b = ((((a * a - c) + a * b * 2) + b * b) + num.hi * num.lo * 2) + num.lo * num.lo; + a = b + c; + return dd_new(a, b + (c - a)); +} diff --git a/ext/wasm3/test/wasi/mandelbrot/image.png b/ext/wasm3/test/wasi/mandelbrot/image.png new file mode 100644 index 0000000000000000000000000000000000000000..4fb0c4ccdefdba04a43408d2987d049a7692951e GIT binary patch literal 485076 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

    1. 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≧5 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
    2. B1$o!d1PF`b44sdEX3tM|0L-;bJp22 zJ1Ln@kj-~hTn2^>kwGy_F;|!$$S9Jh#@TvD2##G*2pT&Dtt4Z|@64{DvTP4roB z)*R}$M!k0`YKG-!Vrz!y{4+D^jKsjH4%Ld9vH-z^B1&;YeA4dSmrpgS$A$t=-ajJI zpn3-vgl27o0DVA$zcMWi^C}@a5&`Bz6OJ%VB82-?0tnbVel0UR>p_=Jccf)S^bNWU zdNoC%c>^Gx0H2(iWJpi?)@#v8(-&j72`bk_L`cB$!192(;0{_Sg(QK%jHAP8%4Axy z;^ww)B*sN|+1(NaU@=u|hjdmPQnmoE^-(Yjh-RC>0Vx(bucr1IvP5DKO zlQObM|1sBi&yuC4V_(j${Z1~HREF5aBNqK zbv%Cr=mxuVbfY8WjoO;mw}V1e0s^3vK&hcWJ4I~amZHQ`(K)egag5P()D*W)>%3%? z+m2mjE7i4}*P0XE|M8iKWZQ?^pZu-z%U#{W0cQEC4PSI5UzRPKvCOvGVu;1CQ$2my#5r-rx8vhAAdeOGruc?G z?>XqG+*CH`*HIGme#eX;_+2iR`gebByn49TCy(o43p0{^k}=YSlq%b3dHSrTWQC$(Z?~$9iUCRxr4%8= zFgRuILVgq#B)c@#`<;vfF{|5sN-7(A3FL&!1 zzh}a)U7SC8vMp|8RPmG2gBB7$Gv#@E>=vVYkI@h|JI0fPt85}JIP1;1yg|pBO|F=Q;W-0l@-Zj9zp*Q zzE%C1x_TSr2w4CTfL*;t!^AWs?Y9+9y8}qA!U+L4dgH+efD;IEqCW%?O)56uKp}uw z3?pZIroxo}?2(aYUoX5R^z8d5DpI^3|LRla9b1!JPKGBCM_2BE3oy>`wRR0PR=EPw z15?f5w$(X(2;-s~Hx&Q?ivb!3l*dg`U6Yq>I&FQ8Ld-dEGMG@1!}AZ>tz>e1+`BtB zvvN_~y1#hs_M8IYp3}nh>*I7wm!i>&HBawax3txjx@tGu0} znTQ#fMUX{+fsmFa=9cE@GGbI(g}m&RepH=Tke0gRN4%V6VKU6H(Gq$i7;s(#ib06u zm{OyN_jTE?fA!JG%4Pb|Yv(PGt+y9#x_jl8oh-`%0Or>e-?B0N*ca#TT+#maE`uGV zR#dL;I{a7Lv_X@c5xn?e!}w$0`gR;U$?VvoI5DikvH5xKB4#Fp|9TYo*RuJ2pwK8j zBwCY)or+d-g55_bE!P`Mb!T3DI82CZ*XDRfF2_}F#@_$kCoSpL^QHO#rA{5bI+)k6 zj3{g(!!*qknUJo_Mqd@&+hbCf+TRg0?rbq$I->fQZ98Soo;l@|ev8$5TJUn40b+PQFL+6&2&FbRZ z?;g`8CxP7hvTgOeGwsmf4##jTbFj|BRhU^#6eb4%fUqDYWbf`|uD!YBme_&G+{zV| zq#!oT02ac?Za;E@#pe~m5x+AA!C=c}d~V+t2g7A+YlmEltl(L7JXXJ{AW zy0hl2>3*wGRxmOV3b?r37{0Eu3?pr6@u09R|ER15(`fMJ3`Cg|~n!w3sGTdouD9!t#@3~SiHk!!%?;C(h) zkwnj3ca_x%J0L!Mv0GVCoQ}W^S1m$Vl4S0=)-}Cdlk)DfcRvzjkO<&hfO8m(mz>7C zW1VBeDpX%Z=M?a0mYDC*5kNFey9ZA9Sg&-Ruq?UkOrPKuoW201;qjCbZH%^nVj;^y z5{Q5Cp06k&h&#F~t4SIOA;AGS2jCopaR5f3s7s5OANqs&c9_O-^7L07GS)cQI`hhb zj5Ve|OmNaq?;DH9JKo)kHQk!a=OBjR0gN|4-HQG>9O&PD(rgI{@96du#xs{DIoc-ns77)?R?-+*1YIVck zkQ?!Ys(UHGWtn+F{lcvY1BitfhN6E(bTio#-EKgIM#6wR=PvF?T`hxIOIBJa4C9JfhQVI?kmWeHwG%>AG~0CMDM4fgxG4E+hT<2duZ8uP*D&*uKfl#hzh&*9C*SKcx%~=3 ze0E)8$I1P3;rxxxFzv7fm;iNuMO)b|8#;#F1~w6}42w{dVI)>ec8w$o=HflWopapG zBtcl6hX6zoJ_v*nxJSh5jL*~VFbu>cCwoXB1CF!1PbG<*zx^5i-iIZzN>3Q)?K)O> zsm0qh&9lZ9BY@lax?wCMe(nSFm(2LbKe*G^6iMBafl!*^BY_K`WY>!>}zG0 z<5MvEWH_x}^8B9?+yQZ6s!1J7AQo|P^0`0o9ZvC)&&OJiQ9H}8lWuC{n(KhOY(`LG z@I#!;ybGR);#z z4GC%t!?rr*h~IqWt-b83H3cloy80^+taxw-=3Wxn^Cuo zr0Iwf24WylF}LKwP>)}KoBX6Wo}aI$0VEKde-~_Fr;Va-1Xutl9<;suTi54pHO~nD zG-Ktp`ERif&U&>ar>@gNm45FPK@Bm=;S650W)$bAGJwY-j75+^7=elV&hOp07S0-c z9+36PnbfQVW5=-k_+eLFHHjhimA5fs*^k>U&h`(Ie{?@9H1-adG$-0raiI%%^+VH8 zV|Q5GnLD%AFKz4dq3ninr(7GOEY+Cqs5TDEmJj)~hyHP3d+F7a*SH7I!TKb!^1fx3 zu9j4N=>wadDJak3DqF{pbS$uj(8D@xi@DGd*fd1(=@b4(l|5E*L@(H8Gslo^#K!@p+ zRN2~;?zV}<#zs9DIaHSwc>3|nNrLfnzKU^>6h8mP@b#fTAIWgK8F_jso>>3GD3}xg z48uf1uAe3fG6ms)@1EuCurnq-mXu&NS5SE4{n+o#Eclk`I4bQQOC`LCeXmWVC-QzNq zNV@y)pVw}C;@u~nEnL>f5lMxn%l1p>l|3Ikw%YdjP~No>(FW~#XY)JF=aBc}=Q2)s z!_K?%LMka+h|CLXJ0zMA$Ra|i^FYk&2fDf&VSw_C~f2g z{A6-bn3l=d8M~q;R;?hks_H7y>HphR%o%)Q{j?Qj27vgOyN0HjDBchP48uY$_y2n; zmnVv`I;YnB<|D7NkeLsik5+#S5D?%HVGv-EM}RPhAj_m?7nZGBe%E~^ckWCw&Nw<+ zZ0RX%drR2vfvGCe%+m{{tT4T}dReA<%+Nz-|ERIkn6zo=%;ozY`#r-V9`qruVD`k9 z%Wo^%y28DsZoC`TWUHrseWd2cjhBCSepBj_lHG3(CMa-ywwVcGCypUk{$od{@&aT1 zZa?S$b*)yYFoO-z%7idiMQHV7PPtO-@`rc>Mp?Q(c?5(T3OjP0-(I&wKLPK=&4j6zaF6G$u{OF%Q z((bBy%V-E+p2)q_;xEtQT*j8;hKX#R^WDK}v3rWoxMK75N5Lzrj+kcW4Tfb(ev+Z`} z`BuD9<{TNiHs~H1fBAm<%B*&AL8Un32eNn-9Sxg;TrP3!&0Vvi0v z7qT?S&ce{*opy8#&H}^$L<2S)@RFl8(b2!0KJ6$UhJ{9RsE>-}NF?ggDu2M~3!)Z> zKHb@)RZL~o-A1!q1_2g9gdm03rp>oYIOgta#&0HzUo1b;(jm6_d84sUzVuXw&4T^* zz8-PQ*B)AIn(-Gi1DBW*UP5xGsHx@ehc@N*dz0(uhrU8nTv&5|x(@Uk5?7^m@rrM!%e{g)>=fDA_FKM*V))`A-? z^?a<-_sVH*BCVl+RRu+-Hj(O_5T3klN}Uns9lGq>urA#nqMOH)9RZHEs32WrCqyyD z`B-~D=BN2is|!zR{2_o4!!fRyucC}=(uaP&LmV*A>9VtIr;pYz&&n3h_BmobevCzs zVF3i}qO-t%-t_*jKecEI#4;R3^8W88&61*Tds7HgXL*qz7fc`)3cLSqF?1YkDaR5D z$beDBbeabyB&!~+n0wJ3;>oqr6|3U%5;dM+$c806yV5m&<$_)oNYC(nyxYJ2iO1Xu zeGEO6t)i}c@Yd4!&R~2aD@}^yIWkI8I!~ObTea%Yf!^u!2THRsa?X?rFaEu+);wlJ zs^qXB=BqPs)2jGl;%suBG$+Y=;q6yTHr~4A_S=iAWm9JkWhPk~GhAaMf%jW#It`gp z+qB#7{=+XVL5mT}iwsDt6mi-5`w>Nn1U$BH_g9DgR|Ok7f|;cv+vZ2N2Be8+Iz%Nq zw(f5iSZGC*8VCS{mdodG`P?>O_~vtJYzTp!wZ^h)z!Nu798{nV*8$!f`1y2d%s?LFPem7&0y zqqg6Cn0s$c-;#ofS6{Q;s_(K>$tH6!&)+e@O(V6%WEhq;X6rJ9e6cXVjrWds>x90% z^x)chOss375r>HkNCAWxp=MfNKB&3a!~0PGS5)74t}iZKY9@rdXx#^RWbZ$ZRHS*B z`~F|)znyCsKi@AVf<`xC9UkVzNFLRFo}sqc3jUg;Q!)%d0B{KGl|SrBDAlc3UgpW- z?IG;^L2Gp_mx(MAZc2@a)_w7mY)sg8&9F3_<(Sgr=D*mtMd1RArj2Fy1#YMy^>Ue|(d*=8>;wQLfRcDOp)d z(JYH#L=J#hlvTgJ7QVjacKVIif?~|pp8N7<)z=!Gm<8BBcW;Q{lCA^igxOlhPktxZ z01j+uWLsMB*?>48NeBQzL8X3t)IkMEMO>`MU=<2*X}V&r-@yj0{lp-N8P^GRFl#ehI2_;7N=%E_;_I>nXqvv=Ww|g z1~G_m05}+sarwXBe*4lTb5frv=I+P1>Xpzbee*C|w^hfNLp?prqrvCRY*Ciq#Y>&L z*jlb=^_4x&2o?P7%GS@0r`BYqD0*WhxKUYEQJbEdF?aEr;*BpgPo*3pm{2=fA|7fE zYO+3CduVy$=-<9AM54H#EInN*9V`$JwNEC`VX>VKEyp=ixin+_65(dm1tva+k24;N zMabb7NT*L-lNUBs;9LoVAVQEu5CF_(Fiy;P-uU6sQ_lK zSJx}oZ;MS9FDo`P2nP`2kVasB@5(Y0v&77(hwqts`~~g3aeH%;*@<(b4qk$hRXXJP zVqrL^tYC0DlvtSG+coY0DsBJSC3)k^))!*Z92O9fdG!1_9y`=UjHX$008WrASk67I(0 zYa$NTHl+h|6JC;V#aH4S&J;@Rztr}FWloDX-Y(0f!W1(PNT*pq(mY zI2NhfhZ%J3{xzNJhWKTbO#j{&z;((&lC=NbEd+odCM_|VUPtFPT(>L8zZ1SBo6;| zv$`-ML5tP`H{sV7J&8Q90DuMDJj+I|29}k?#~YiEIYip=S?Kq%hJY&QCyTX?6V1jx zvl>rY_sn|Vn|JP5S*Dn_IVLe%_h{>A&zZwQE>)D$Me}c&vC}ZSL}@!7o0fmRPZ$U< za$xMR>TFa21`p) zF5l_^AeB$C6YiHc8-%iDc2-O)!R(zsj$=rcy5K~>svx3z2 z3j=kjp`LF(Dv$RaHRghFC<3tKOO*ksYTtOKic=mB*4IVTlC=I#V{!~9Gs!+Qia|0ckZ>dI`Q%uDLm&Ys z>^J*OCK60dzJ0bbC6SabD{@}Exc)aUNm4TjO-{s94d-(&_yj!o<>4z=g)T2RcG0hq zNIW5bUK-gq!s+Z3<>=iEivyPBfZ(gIFas0v&!+F5nGDx)TVD3SQC~{i zs92!ZCnO>!NXDgV++$N7esWH^aZ52LTkrqKzEI z3uzf({*g7ncz2LxSu~65H|5%d0;In4Zfw0fEU;#>U88kR)}z?&DS z^Crc=SSY;tIYK5o+diXAugvf}g3oT}f8MNc7Tq#I zWDx;7bN$mQrTzas`DWwxhWGw*E;m1Z`0F=$#kXbT3Z)q;t3x;6OYW z>-g$(b9Y-XW98teX=B{gzGKa6tN6uP66;)VHGS;IpVY3?8~A~-tYlf2HMZBGqQeZA zhhsPvLL8wcK94^=m-9esW(-dxJ@9#d27R1$`F?!Mcdve(6}x1`=$Mns=P&{}D@_=i z@&tS^t~f<33l+)Qt_7=tx{68B@)393q>);%h6F>jH!Q$d#vfuLE@wFJPJ}oYcZ^rb zr!Ky=>xVnjp5I$pnC76x$xO6Uh8BYhwY;rN&{VD}c;TLX+C-FExP>oML=-_h4(vYo zk9Q_knXk9`rrmFSs%cQPRWC2XaVA4<{_!6MOV_O)U@P6_Po<}+*57xVf^02al5A6~ zwLl3)(G0`bVFD|Z=q$(b?!J5U+!dT0DJXT4{UZTUhI?{ukW;9iJ2jP5hcMAn-N?G) z(K|N}1$c3(_JQ&^M-N`%n4`P{!yK)4+AHG(yywiRs~=u};8zEsp10v&ihzHp=Zuhkb}IT%sSVyZu)r3)m>}C3*;8SqLCV zi6?&ji<8IAIm5liPquZZFoP5aKYp4xia&H~_)T4r1Vb!KGhtugp`XdsS((p&qU-(g zLaG`(U2)0Bf`>LvKeBI|Wk$5*7D z%se(ZDn|#AQ9c{J834qxk!TPEkfC>YR=X0;j*3mkPkcREv0OVaLB;aW(KEA4n{oq4 z#Nk2?4rz9gVdzE>IKUymFpNWB<9#N{hROE3f71h%F$s z@pS+ph+%-kt0BK!aa)r%(2-D5$S0j;CCLMAQ$MZv_M)Q#F;oQD_D_~ExajbL7OO+i z_sE10hyr9-76AZQ7BMspBHT=b0E5`bnTTZ(i}08J^0V;iznQ!D&7GY++?jC|lrV|} zhbDj6r=7IOg`~mDa*iFD8jD@pBU(pHwN1H15Jc$p|4se>UXAO2tq!_5Jf<=eo065K zm`-)H_9U&@5*lmar{^W}Z0RbWf}Ip_0@wC+G}eo9K z*!j)ykU^vp+ih}t`i@b}ib)f)f_Te!pC*JZ_xsYbi->E@#`pF}d<@((Tjw=6gp?zp zy8Or$@bnJF%#@Aci4j*A7aqT3n|^xFn_ITzwYFL+wT^A~ly@5?pY4gIobFyTFDO)I zmg&bweX$7=p-?dBQ>+(XP2kRnHhyHbc)$Ed$F(`xgprBd!*5EefeV4p5gjKM=@(Lx zh1>~=PjHN99oi;0r zW>I8uxA5OR*?sQt$A`ocX=B`wN1?sqErnA(q0H599m>GN{sQ$hU_(FOcdH<)_|SB< zk~Q9$dUn$i^Ve7P-=5+&G-5CR$z53hNLfzA7m7!|)gcn`!4Fsda`TUx_8udUag-#z zq&nlkVe+oV$w$9gQB^N^;GtkBBstQN(3sSnm+O@c9SIvvWf|_81ZSHwRaubRIgWdw zD!V`;5b#Go`-tKYA)yu$VwZ8|(Xv62gto@44NMIt7L+h-)J4P2>uewZey`Jm2@@Kd zhR?O*9Ku0!0@9?RNeGhbKD=CDJkw)#f?S=~?7&|AOjNVuwswzR9HTtz$h}v4B2Q1+ z>{!c?a4M9dwzOaTa?Fu*i@qQ+#Bw7DOdJ3VA{-(d0!<8O^4ht5{pn-?k*x>UrB0lN z>t%7=FHGxyRX4v^j7mRQ!BTi8s6ILe?G@rMn zQFN&z_{>u=X*%ve^N=i2^7YAtw3YScYR`Gqi?}wgPrYIt&k!^MjkIeAKq2KoBc{`YQoxN&J_ z9$+DcK@K0601t%;AwbxC@QV;}%37F>#`GITA@x(Y5t54I%gqz== z3W(jx0ti@$V^}EIR2(1Q^(RqsY};9*Ue1_UMX>dtSy?&jQAD{5>_3l#Zc2;+=!QpZ zVNbL;lQ9aBkN%GNq!EN7a7hH_QOW=ygg@GpD3DqXpN+dVnb1j;<`!xOh4m>ZF-j3h zh5WIk*@H_S{Lz~0<36j&HZnoJaF?%jLgMq&i?-?i9T4Jwt^WU#9hs_SDpHx0EJ0Fw z%10N~SB4~i*k};WT=l1{XTmni$*V7S)eT*ni%m`apg+sONhrz|cI`hcj8QeF4|SdE z8?cs~K0du=Ez{O9+hR`Pa{T=3r2SHh}wBJtX z&JBtSP>VgaiDL1k;H%q{TDs*sGO{%_0fWRHoOv2wiR- z*RHBe5E{cCDntP-*APxEp@z;nlbU)Agx$$RWmi}vg$|46(#&UAU?7UB#&8T^c!p@M zaqDd<3Y1ZdoT<+caj6V~Oca0(`C&(hVMdSa&ZutGWuzA9KcmhSUG|kwQrBVfvuGh@jxh_E*%|v1e zqKyIq42w`m7%PzrJQoiiKV|bIRL5nf2PJ712Ze>z3^F(p zZB?c>t5Cai>8RW7O&dCsnZ-NUmBA1&aq7|=U&uEsw;{vi;bYF}VJkh>qt8;G@8XQJ zC8g=%aO-Jtc1nEBLm@&4F^nKdfq;O3#W8>ock2ep!M*(ocmD&GeO<8W!Q!Jwt|u+Y zHuuKUX*&Yh97t~N{Bs)j(&$CPgQ5s%MdqSZetum=zl1n2nYpBg*c@<;|NFlh><<4V#t)Ms_NsTeul zadEgvWfqQJ-1SPuQ$LvK=^=}1RNEg|rmK4@K!&5c)|B4+Lg;uhcc^M{3^%+3R^U$JHhGKxu(q9~eXqFNn<00VBYXF#OeWB~)_ zOBk9@1YrSSqrm-ig_D#eH)Xmm?7cMi`P)TX8wzwtjmtK_D$IyArzL5iOvU3ubowu& zS9;Q`i^B{D!!R6!90K#UHuJ(0JNDEvOz^;9=EV8wmD>GOOq$IhDyhk4fGRaLIcv!} zE{{tGLT#V?;#hZL#iKi|hM+=D63Nv;8l$6$SwKE_MNx*x*k{v9wMvM58*W>^bbW#S`sve0jh~tu#PLdO zs3lZ*e`$JP#v{_=Q?(WO)8nqeqkEE8u9Mo@E?n_R8&Z${15)Vax!XS(Zyf*Uq`=`akxQkJxs2qeqedXL)B^q>@CwhBky;IZf zFslE3hs?iw)23XJRz{c%!jwXjFe^;b6wOAs(=-(}({XlT22`oTVJ0e<2GM{W6fMjM zh}3xb9pb6uC?P*FDK<;v8}}w?&CObg>$w$YW&?@O{nAxaNz;JO!CA&1C?hVtbtUVI zx2BI@N@&=T3)AzP@l?e$DEizx*OkDyG>e!e!wKM-Xy3m?)`KEB5~B zcjw)c_#l>R81-Y2^TX`R8`FEHrnw(pOnc$>!EFUIoyJ%$P0vjR-=rR{=>FS9w9;${ zrxdBJlSWZaeR#H=KDCvWG|7}QE`f`&fN^keX$Aj|ozkLJ@)c>_m&cXa&JM8z^9C4i zTZi4o{H*d)jo!L{Aj>vr+qExl@4%8fGg<(}I(<0a(<)C%9vb#YxYYQd;oy1HeyUv~ zrEue@R!-cbKcy?uXjl9;At^2*j+`HkM^&YWWvgl`f-v^Z2Uefl^Vymu>`Sk~-m0xV)uN)eYw?e`+rM$=WN+GiGyn_F(FAyMvOE-sYH{U6&@~rp{hUd3Jb+ zD3^6f!6?7xAzv7~@VCFH{O<*Z##H$YIAFLq5%LD0{qi>_NnuH8NkK3+S+ITG%)UM7 znUYoo-|GsB00XRU;=|fcX$db(g+{rV>clV%1FgU3vb$neM>+1a{&H2X2g%F%0|m*> zTYtVYr|H4dN4iEYUH^RMj?xr?ASpjGja&#}U*M5o7#uW^D~k-`$>v0T%5!i2FcbvN zqp$InK0ITR%5s+~q%2P;b>(ahQHW;QXc%h5j1(2^L?a&2!aV?i8~L*f(S$5QEMOUC zGMwZ_k}j)KlG||9)09e%+r$kuNj>sV_vMyg?BoZ8wpb~m-hSe5>LhuH;ijakxSnw! z)({vJs4*SogS8ESc+k38X<_0{pZv2S0$z=GID)9$2f52&=@LrLlK5!T!d}pSjDQskTRZ^#+^OcFMnaxr6x{|d!tj>-VIr=k*<0yC z@x6Usz%q*v|KR(L4F6U2NB`-CMauvTvIZyW8KFsk2*V;<4rVqWn;0}5IBs6Ksbc!z zSH+&gsrj1I6FCjq3B7xCY}E9lKO2_T#7&sVxXj`oRdpY+mX+5e??1;pxRP91qnJIt zyVIM5GK%e^Q`$JmrY7p>-r>Wc4PfkAmeh~4o+~rj85_3$ayUnApAGU>#a(#)YX0zm zeQ7D&TF!I@Q_WKoZvL{RrL)0l%cW6?NSC=aZ|v}af#jmBBPTrK>6RtAE?#nuUsdqc zw+P7!t@qtMS9L|+-P4nS_YVhhogWCQ z?+%iPVHQGzk)X}fyG9fm1^@3Ty zIsOd8P)D0x`B*Pb@CIG7TW%F_MFNpR1t80^s3_I8>x(42PdMW#UVqP>x|*#aMDV1l zt#>RHXElU9BZ;{yp+Ziv0719_oSmmxL_hp~lCYg@?Uh_MCtHD1o~U4PX<_UTEG;{E znb$cWEsGhuC%x;d{v@t(Y|hEpYwj1}_V|)&(M%^yPZef2^q#tqTUeN1Qp+WXi^mV1 z{@}yX-3hJ}-*-U^*7utLt>=@a&PTr*;<8W}bp!XD5~IO{hdXp>5W}P8hb_tvNYXB-E%G-)vc)E~a=5Um)Z1 z1cQhF^zrVF1owMNvg2H{*D^6%Sxz1}LUem8uJqw(^*07*naR3jKFIyGV$#3BacR-!f$H5*$}X>o-N zqdi)xvwU6Erh6J(9bc#m?)&!8g;A92IddSH*K_9UwuCr@DKg{|qN+mHbH3FxF)dW8 z3j{NhgzDv6k6xU~UbP_yCy>)g^7+JYPxp?8_L>LmlKlKC?EFtRn6FGF^5Rlynxz>) z(QGKpaAGnhcK=?MR-2rb@Y>II@$Ee}d5Mpw!f{MW`x;$uz4!rlT2T1I`(i6gq%(az z-9+Q%{;(s!i{8?}BGKo(9c9srQ5h?Oivk9~&48erCq@5S{m~+}1b$0x`fbUrE$q_C z{&6B9Qx+$_-fEil%0Jy>s+F}1RzA_~OOWsxHWb1zagQzb>@~01=#9pf1N3i|p#PN& z6#Wk}(I{Dxfp9*HCQ2wo2Wqnv6O;nzV7$0DCI z4x*??W9ztAFOWv0Un!irw3n^xbL4kCxBWl(LmIP$dprJK@S-Rmc-bc7JZE$aF%|KQ|b1TWnz{ zC|Okp1hF)NEI>X=AX3I8<~FF3wKN-D8%8ES2;8(4!61;zWBiQgz1KSM;?-j=Q4mS6 zo)d5OtWm~^ez~K^HxBZp(;v2Fc4j|0=@)q=nSNHFNYsr^yEosQG4;&Au9k`9IVwe$ zS(skAb^ZMh_(EY6H338q@o>?a2LKrI*b7r%LQ-Yv*5tX{c!X4;*clOo40CKqdUQL}VPoPreVGW@)Z3i?$- zEO9Z458peb4zzR*1mZ+KZGAP2sSHk;4KqQRh&wyNoa@A81J_L_dA*tM+48g!Kh(Oj>?& z_sQz2!s?j*OXqBvin+ujdr=NI8*k=~p7(Oo#97Ow9Gp9T;O@L0ZeaG#&2Ew3Q^tT@)pKV0od<1QR*^L*jv5vg3<2<; zaS=D3EP7nD`Mn7mcO$X|{R_Ki(F^#;pKN>Vi~8|?0|D?^C(kuG)^C(pUAWND_Ru_=UNEe8NH?1}&I}7q$QJ-}m?bvHGKbXA=HzjAqeaNnzqU^E=P? zq5+HKN}rGlQ=vd`#z0M4F^iMeGfW19Xrkhm>no{%xTw`Eo|*}>RLC8GGY($c2;m}m z7CURTgn6X7#g(}2u{#J`pK#fuuYF>gnq_go001b&;bOGOi3xDfWz~@W;H-t2@~FCI z#e4S~40M7zO}94l`m9U!{ulNc8{aw5CuPGrjk~f~LM5(!;|S)khZz=oa`{Ae%9Dz; zvgy&8aWXEliHcT#972Ks7|!8Bg1|ON&#Md8#bm0I3me5E$K`WCQ?r_+5W_^1Bj*=l zAWYKo@+~e|QBA7PC(~)9Vy!-I#!h>4H{+$Z^DqWzv)q)BqF9e)G0K2GPfGnxkz!F3a84Olv)|PdYSvxW4f=cD?D?4)m-~Htx3qwdW4PHL^TEY5Pvs+zznb*sZzh(mRAy@216@e1^|a4v?zn`b z<-`Q}$DwU|CYJyGN6q`LrPgxW0m+`kw;J7It2nKv$DW;v97LjAEfvS783Gc|l~;zCgsNY&K^E5BMr05e)6{^)$tGiY>YIF?@aF+6xDkM z`yD}wz3rKi0Y_QzbekbDXt6?dOsv?tI)AR9TuLLNu7Rj73k?8iK$gE>^S`oN{o&xs zHML5vJdQz-L2zNT#V%e|!g)sh{GD#z*#-dwz5uv7G~N7_kv7{fi~Yc40n+8!>}*pd z4B>J|ScK*m=JOKhdAZI)fGv(CNx~8dC&&sD=|LA3g8&3<^aj8(07dx4EDDnVu#A_Rro(RTN z47~f2jI}Vdlq=!8NWu#w-n=_?WdC^Y97iWHpFQo?ts)>R5p(Rbs{%jV{*cqf+26lMZm??AO4d+7%mDFL*G++Zx)X(zJ1{L-l`kxvAnYK z+g3+W2^xZN8I;|uabB-hj^u2+&%jG<=?Zs^FvC;c6NaKu69+PpFFE?B)7k&H-TnWY z8vT!d6iL#}UHsBi&PRt4V4_w92oMHX009E9cA2g)#u`IS&jQKuW9~2=IZYv!qA(nb zWQno}uD`o9UF6gSuN|Z|`Ug+V4LU47E`;ojBus`Gp9xc8D)Lo_fQ5+RaETccb!miG z)=;Ok9NQLqVPuwDBk4<)jIFx6CZ=Tj-d=9=Neh7?oX=ld?7Qg8wRLylD$$HX5X~aO z0ER)x;U+gN=^>@2?8R>HO!1H_S{_@t& zn4AU=$ub;a6c_*?3l{8Ak=Zc>i!$66{E-+0GA{q~SD#Z_PL9Xl-KgsR;xz3ZooZTw z-*LZqNqvZh0^DgmA6UIgc+4rvm_rGCYAUg)aEa*jBZU{P8qa|owhj_9i-;2tf&uveTx5`y_S&hhuq0R2|vGB$?0!VWF$DfC|f%6 z#$!Y3WI2Kajp2{%Fb*G>BRw9ZFHEmmuUr1Km!!fph%ae~O)J;NiIsUxLNSkx4rv$q zVz@}n5Tyv7+L`C=PEIZi_gT^^UUj9#(_oNmlqkyw%DUqB;ym>t5gLZ8g zSMaWX%h$yEMR7V^qAEp~TOiGBMPdv}>El2DvHgk9S6w?bU{d8Eb!MEB-`6$%xv#{ z)qAg&tYTS`ZOOe?Of#W|Kp@nR5JEyoAtaCxN(d$NVgs(=-Yv`Oz4tDywrE$|ccFyD0}#>_gVUbSij}N1mz)f7#-XIgwgGfVkQIGAFab#lzBJM;0LO)=j6PYA+t$bmkGDi%;QVi=#K zCNLKGKDJmA-#F0PUvc9K6kig#tgK=G(URpVw^cVVNUmJTDJm(%rD-$u2Mj~KS86y{ zPE^NZt*VUWQQ?{}$;^g4cW;+|q|3Q|*G&EAgDjFxT^W7r@~R%Rw4fNjTqDR>wVlV+ zbe(#BR?kXZwLMn<@7!2(=ehQIew2+SFxNcMaa0^rER3#DnOjY&Wr#&cIiC11t$wVl z5VZ8P>7;Vmof&6b(HoQFS#k;Y@~|XcXtYxN1$#IMzfOh>c1IKd6~8tOgviI>;z}Fv zp;$Bw;OrTBT5c4joBYeC;z!rFnX$N=k{fdhBwKFEnC6vswa)g;u-y)iex86786;$V zqq+PbVCM%_e{@~l0RkG~wS6oOPJbh(5#`&&3dWp8{`4br)hwE!YQxHue^;7AQ z*4cSn;%xi)qH|9& z7vq!{tBOinFI3wcqK-i~1{oHMxUG_`9cIlz<+zFO2Uq+#WjMy;uadWA7Khu%=L*OE zO3v$4?u&(Gnd-2dgb2+me|W$C$c2=O)xM3Hk0R}pIQn+B6pd({=kZV^ML7tSKq01R zhN69t5$*rsK&=n1c6~)Z&;vjaCu9O|4-;e=BVdLarz&SonLFl*n5C6MK5G~Anjq)L z5HcclL~>Tf zwS2f|E;1u_%aWme89kcfgwhHjf;<3`L_k?*9NYi3zS$7fGOpgVESv~Wq!>s8K+}L^ z5L>K~$OJSKs{UQH*zj9VLO>8i>y=~nn%{5>OiQrC;yM#r{!;jAjK;a08OI$#mIqgNDwvy3Wh)XLSh9Z1Mo*<1%F#|>6?oLiijlAGK(#KgpFheqe~ z*<+iR4A9c}d4d}s#li*J!3i+i)T;@{$1nGr(l)I6(H|923fjM`2f^J23Uu^f3-`&i z{bnSAMvg&fo@jgP#rKOM%y&JcDOa={)^ClKm|Yn+lQ@eCu>ONi7y(yK4B|Koha8DU zJ@k>X_pP#*XfDEm2pwU8xy;KE{`oSO^iC&N`GuEgBaukGy!6m!C5S+Ant-8 zqg32)x^`;Ea=NYN%z<|Xf4%9*>m9prhcPa5sVez)n>eqtsq3jnW*aYeWaK9^m>?`l zqnmTMI*+a^(<#MR<3v=VwK`nmRq?D@d6Ju-j3%A7+iu%3Fm0a}Z!3&yi&Q90`hn-) z!Of$ikKN?HV#+m>ta4#T-cOz)Nl;j*{pyNc6t00Re$|2V+iu=G<+kQ#!pig^LKzmD zm1mNcOu3Xv#uH5D=GkepKhzfb-6;ZQMgFsY@azpiFc%Dc9UA&p35L6c@xB{*lgB|l3vJK9}8p+OYM&;gM#`VIxacd+-rvvQ;B+Yq21 zU?_z9K9&eA^2!4c0OW9Db_dxz$ewp14AI|iSBH?!#B@)vCXKusZ%F(2sF}b+V~^3- zm);Np0B8iCx?6(t=z~MKVJb3--C@psfX5a$5AoQM8I5f^T$%Rim(!#d0)Tj2LZ%=$ z7ezOj#DJ!Jq29ibdJMhdVoI zc``??WRRb8=Ih8IG8sT4KStyuCNm2tzfUM0ga-qJ;{}rOLiI-rTmlFJ-(mouD2k?O z#Q2P=5eA^~%89;yyW25Obse6sel{VNI((J$^e>kv67#3K+WH)VL^az^5;Ve?z)IO~ z$q=B8e+?lC335gfReXN=+P>y%Qrx^u)^^iQY4NQ$GX&?kXL_yYn{vwFxrT6Lkvj@= zU4Yr0Ge>Ylx~{(Bh;hfvhV(Lndd(j7p+ePIWTfiSnb}EiWI}qF-78s9f=_F=o=lJa?T^@F_l{3~X&CI{5Cs^ni_8@u z@Vih1a+&Zz50I-P)~`uhx?$=2f4OW^mfiTkZyN?2W_h;POEOGoQG@m<8$!Mi6=% z7to&BS;vl2=J=)IYlnKmAliRilF4eEAMRm9-cO(ZyE-|y@b;e#9D9Goo^>o)3Ir52 zRe!Mu4qxiqv3X)*1hvja4b(bigyoNQ+l?*bmC>W|>271k@%=|G9envqlvMJ?8((>$ z+{uVj*Oy&>>x)@sDQ%w@p?OJG$=DY!iCjb8)D>>PXJLS+iq5gWYn*mjV1|t6tg1y7 zH{aEG@$7o}rNf^#VJyBLDKOyAuf;GtCxtaNPe6bejE(t~2H!+q0#DS}dcbw~vEeU2 zu{?K0ilL{IL5@QQiCceBm=@!_#(gbQ*8Fi_yk*|iKgse7i2Xy>B1^g-j^14Ne)vBo z45ROAcHcTQFc2a;%?+IBzx{PF4D))C*^Z9a&=~Fc&fm5eui$7kS#qm}ZH$uf=AlMT zj|}vixZ%-fYfWW}p*K(S^+x}T+8pHCa%r-pzvFZp?e)5)k@saZ)lJA*0zQrbjzpA) zHyo~IXBWrtqto@>J$FB-U=5$j6xH;%Qtfr)TmSepCnk&Zqj1nyhM6Ean(?DLK^l)w z`Vo|sFbqHtfB@Cn_cihbJuD&%fZ(hEKyW^Q!6p$*BT};(M#!az(mvdq~kx98WM>(*w)g^Rp83vdoi-@9obZOzg- z-SpMou)LzkaUG9!^~5A4ayW_hPAq%Nees1WWMUSDpueU0-x*(87=QpU!KA5BZM)yc z2nxB(xvy$8@tC~-PE`j@Wsjl@1445^`*;g zyuo9yx*}H*Y?cQXEFAxX4H7~O0|bFdWg_#HqpaC$#}2o`(M!>#D-ZqQt09ZZFldxd z_9)`GnBAf(+Y5)Qt%6vu+w0qDEvCKz0DuKb>QA*N@TU(p#Sd~4r%Wg_7KgFP9Mbl| zaM^gx1yOE=Wg4(u{VEZ~mJ5INt4kLfp}nczJMDbk`8V6(*mil%m{T*}ZQK>rHXOb+ zTh&fQrpKyN@)OO2nNOCL$KdM7`I!N?Rk-iQ_%C~e9$d6a&?<;eqSLqb2rBGe76t*q zVimH_{qFH=CF|GS{^+AU2Jvk3`Oi;`-|+Aar=EF!)z2OurXs{rk=ai9>?!gRkfXbO zXSOvrW?IOYMy+aq=-@@cuPD`pc#-AhsGvBRGOyD{t-&0~31tP2i%qQBS3mo3e9Ni|?1a8@b965jCgUhGXrHVM zEL4pJTl5g*2l!8s{#pqEpcsn7jfXVHPAOHA; zV@F2MHUeS$!SVtk@6JcZsTHZ&c^}lWb}gaU7~R!1sZlVGe_Ha&pEt|1*ON3&0bc;& z!Xorr^pG%A>>aF+fTTfDS#bpJ>Y2mB!kv{X-hQHHS&h9=D5eCSxB@9KQ1!Hr+A18rfEH){qgZ;uszf^y zj`ir4ajY&oqXw-nS-pTyH0iHi~EpF<;jx|91;p_+R~B|4~wazWcl1JxL(+9ip=z6mbkN z91Kkn^G7M&d*$cvFPKUNOF8s^y}+am{s|V;Awf9_3K8I-piCEq0APrr=RAVjw15Bo z&jxHPwPl>dXC}w>ptYGECQ@}&>I(6NIk%S+xmpnw<2!RRp}dBWlVjl2?=K=g02BuR zVt#9DE@OWCPp{opUfXX@-gUd`$=^(lj9Fusq$cO&39XkOeF==t(4cUq+v$;ptEQ*t z&2~v%VanxZs~}7hAWa3Up?_SCl^VbL_eD?Nsls)ssjT{2mRq+x{-AK}9pOBkEU|z? zc`Gx?;+0FEe!9vrK1WI8|NQ!s9AyTD5XAr*VSe)>|JxE+`Gy9^hxC9@ZVUu~Mu@9Q zEUMU)zHDtq{*t_`Fw8!3dH;!f9@a4wUbc?;_?WtPHd-ijyHaj|e0F!$aPw61)(X3m zvwUXF8_x7?X|Z_PmY-RA&a8j%Hx^OM0KbSPNt*Vt!mIA-!%#p_f9w9G{a)42;FX?G_e`;Ihe7UenNf4@f7tOKeeb~^eP3fh z=(?g!fq}_ooSDW%SS0bM3TBGgK<%l4C#)V;lDknbe&wgH|23v~cU(@Em!#;$%*cS>-9kqHg~FJ5hJI#OM-#FSO0p&fG<-e_F8Io8B2kn2C#|L@LKkN;SfTA;H+ zibie^WdLfEBy*fm%c8@*r0-Dd_eVj@LVkwXEeuObzwp)Q9gpopqU0%Yb{)P7YyYe= zKiWlv@f9k@L0)|CS2tx{0nr(^{Nl$p2kJffzC+hcic)w&AxWc9Tnl~eQ3xgfzy*FJ zw%~AxNQPpwFn};NG56;`oXX}NSy#w-!;?4Od)v}Yk1XG?CAqM~&|0IW2GUYQ_dN5@ zXa3pGDZ8B%O4ZidSa)-OU)LwEHhg@Q5oZ-U84gAJQ$!I17_i8-7XiTGbH)yT5*ds0 zsh$maASv9KzNtc%x^jvgyTtqnAr2ErReT;XSN(z;>YQ#~QDtmgGV7Vg&X0Z@+)@^wEy#zM55)#Uz9KdH_$NDbIEe zo%%w2_en6_f!04_a&UZvw2)EBkN)Erw%+%H|%1!09dE>0}6vH6I1XydqXO6%zoRc>9DSLj{Ha3gX;QkeT^^$$; z>=lGuL*N*WLjuR54W}=);}fm*nx&hHHf4GBBgeiJ%|vZE_E{Sqkuc+uBt=-=+NDai zr)$`T+#YSDAgQpZqp`o;8rj?r{CsW<^EEIUvTiRkxAfxOZ~P^{GRJlKa9wRr{K%`D zvc~N8xVY?OEOGPsm)>SYCb36XfC_w9clq&cg9Vim>3 z^ZUQ@Ze!fe5dM8g-4DcAAh5_bZV~zjVL)6Ef&xK+#{$L42GzE5#u;B>s(Uv>I9f+$ z55P=|gW9r;_~i3Gqf_X6TT#$>`g-grEaisCT_jV7v zSTfk!Jv%VNW#bHi0WU=?vh;=k0N`QR1`{F}?|t{AIgh`-F0H$8CoD!H z;Ns0{$T1Xty+Q>LA&3_8k`_~j7P71XVgT~HDPnshM{zvmmA8lAelFp&YNi~VtF{!B z>?y@&EAbzY!AuMD6sWKe!&;;V?I90$D(rY2aW@Ok3+;^@%yhHw++;t z?kb^lO^?36E?#WWUpd?Bi5!dC!!6h_=1}OJn2+*AGl*swieeZBk>mpXiSeyTU_fh% z0AgsGEh^x(odj!oT^b`hmZoWMTOCDPGE!4de)w8{SM$zF8zqkxB`xES#;0%n+rc_n zcgu*xc6!#TQbkAkbg&_4_#)n3U@00X{Q-;{E*y9v1^|a(efGg8p3#d-Qau-Iqqg0j z^1EMmUp{lDV8bqg%`U4fJ$meP!$tkErun41p0qGrua}x5q6SS0n^6~@z4WndgU-n9 zQzma<3A$hs9IC2C2#R77$%*cdFQ~I~(rczO9YR%~Xe9}_+Sya8xZ-$?X6LG3RA21f zzHF{=bG%wBtoy39rd@i?yK0%N`Jp?MBiHoVKmLW+O9%GAAu=}zApla$e$VdT>1wOj zmcgIw9GvMG7_^6_Wu{;N;TUwxwEgYzH*+)X@4u&$rk9vFu^41%#?NO2KIq>^{lp=g zz}#l*?Ym-(J@xn8Ir^K5`pZ)ZT(P1}FS+aXOr`0>peMOf-Nw$nksp~dWpme$$r+kv zXn&nTOaK&tfJQJ{WSI+JU6QX-$V6r3f*Ez;w0xBZu~Q>3(0j(qi4=*sUU_PEPSi~g z-nBFysv<={{WFG5_Q&>}pf=vutK%i)r^kc~tyZrW!!^-bYGQDSr;3g(^(eEyyl6)N zMreS|%Vx14hGPiBZ(WY{o;uQB-}b;8FGg5Cj@k5!^M8JJUE;*Y&C74P>sD@bN!^Qg z)Hw20ktz>Q?jcd4`|8q?;;up4P;HYzQ-Wbkig@0oo6D=nFbxh`YQ8Ke%b7HiBw&Z8 z!ef3Lnc(mY&>{lqA|@#ewN(hz16)w@Wct>v4E4nB@KTrU4I5TL~v=YN6ipzHj`^=ZNWL-qfj7J|OlrUG3DRSAZMxe*xZnUjvr zu!sc<6ZCDk8vpSiNg0=A9XCn$_f# zh{CfyG@^Z)*ub2@EGRq!MLz^G_WcR{k(L01h;*3G{Av5ik({b2O}MkiFzxwyZsUus zW#T3I=Ub7&QiDZgco~9Rut@U9sVz{$19Au7%QFFxm_dM~Xrn5R^tc&>7@7eH;L#bn zPyT5bJslx%%pE->Nfe|ML~6Ol{r_scYOj>5SXN$aAvzVkY9C9ipaR#$e4C#+7P8L> zToeo$cl>u`plbi`U+hhiPpsXlC|b=1l=JOhHm$v7rz#_Nprs>H?(Jyq(iE-^ix8NF z$sV_dq7g|_9*z)%=giBJ>#2%qqtj0gW_%d9KLQ0U>~#=B(3?(}@B1BSPqaaQW(YAH5;zvCri~3XbszkFV`29lw|W0|F3H)^-|mS{O;NP4fKBeCgO?puob6hs~ z&QztLXxEyHgTl`C`IKnh&SLk96j#%f1jix4Wy#2?v4#N++alrUMxD#!oF7H4evpm& zrAqX#ciLmU=Z)5pY}jB;zCohWP8pmX&V*ugo$I_Wlt|`M(UrG>y7rL>otg1c5Fx+Q^nZ`%U#A7ob;^ma z3-te?)&Ga>074&o+Dk%+z5^v&#CJ@QndbyCNyN|um8?w$7xX!9zGT|2%8&6(YSuu8 z#v#yTFZHm(t6qBKna9XxePzyy;+|`#fAXBolem`lFh*s8I5wN2XoSE50XyJw9tgVt z7zS~IfB^Y4HPGvga`!m}VGsg>z!|HBhdU^Y2ScQS2mrt=Fk3>m!3;n!KnH?|o>s0K zF$=;9wrAu-S3dk`97dfzJGL|lH(onVX;(#*-4Ad`1B~`bMgv~|fk_qm;T;0vfT8Sm ziG+t32Ezd61A?G`Adrg04VT;chiqcX_~0WjC6#>Zu*zg|ax=@qz-WZCIyy1N$cmw; z5C&9;$QdmbyP<&g*mo{w7{7`rXnmpPQj~onqx?3?eM#jWext3zIWkmVKY#GNq~u+XhW;EEvd4GYMJci|8a5K&$xUH5kj9;=ql8^)bu zQ|x#(3u6uOJ#I!So$S5pQkL}Kxh`$C$L;ZtI5c1w;Py}yjcCg2gT5IiWMTs$Tm2wO z2>~lD!ef){Hqz$77{7Fuj#*JUTHmzm?t3~fe;OCZh}6>OE8q(7s-pUS-7BkfAz(Il581BesJ{2TM5)aR-{1h5?e57 zU)#h`%h)e>3^m0(J#gydLqo|p+TVNUL-CAsBC#^busAI}1+*9TrunEWAs(ClT09**{dM_VeaZ|>w8%99x(jpZu zO|jSkm^_}Q8N{0|6%-FP4Hw`1`-39=YaMUBQJBM?fl%Kt$nXsftv@_4i)kZ~&CN7R= z=-l!VXIKua!)nlr1Y*FGN~y_-^Ht*w7oPY-&XG5-RPMS>p%Aq`zxRM~`;L{ExxQ`v zZ=bc;XeN+u8qBli@VE?3`vz(pgOrDKRGp41$fW@b$D!KRcJbZMGnXXIjZP}09K)Zs z3DS!RRUBYw5uZdZD~WUc-d%}=8Fgq&0dHK37i>0VA;!NVPh9Rck5@`&wpqiZ1z~)+V~{IFgUgV1ObLB zu3WWoqh`-O(afdlyaMm&wc!HTARe5}>>`nC9ivecUk8m2V)Tkeia$>9zkYpeBEX5?p4G{g9_b^}KQ-~Izaz|byf zS%KzcZJlZD*7&5%2YK$;>DPX7!0jO9GJ$L7zdST_d6}T&8w^Ra!7+$q zfC?*Ezr8S5F_lxW=7#4S7#AQd&oMNP>qhR(Xt}w#KVswUC%cuSo-oAXFeL30f`Pya z0EDWMG0exl^2rM-vf(!IIY+|H&Vh!$l`qu|kY7$D9%z`z)nNJVX|wn8pcYV6Xb{2o)^GSf840fM2#)@9+!#VXuq%A)fO37K zz@lCJ*Ls8hQ^_#Mpl41u!oeB%X|?R>`_)yG@+j^M7;KF+o`?+h&P*_Erw+4bPHf9J zN)t9`Ro)_1$3k1*M;|nfwoX`OspLRyBDvokwwW&zGBo3lnzPJAvxZyV`8;ja5;uwC z5E2BIEHMlo_y=pQTRwXgb6MgOl^>n3#I*cr$r4RkG{47yfswNjTnj5IcjEcSa!b;6 zNa^E``q(l)lQuk&MS3Cdm zCzQL&%h`KMmsC_3(<8f;$=lI6Y!#R7aoD{y?JtD^*lI!0079!jLZNV0$du#1A`C)I zD2q^n)77v`wtDzVLzgKgXJgu)JJePzDk_byExsKm5QVTH6u!WQ3=}fx2ekkW&;r2a z$AS`njji=i3uj$FE)g+7tUrBL=C60uRN| zK2did;RA*4HomR;hd2ZWlpp?v=O;r2?lQn|+zYW8ZsAJr=YKe;sJOkd<;b~)2IjUs zSWJ3UY@{2}-t>x_aemHQGIP*60)qfzc)N1Wx1@x7r6V~p%F=02A&OyWe?$yeO#XqmZ_>mt3_=Xz7>02;SVy&HNg*d8 zx1Y6?=bSLS^K3>@^2i*Ywwqje`x2(Va#&3#KD(mHS(cm-fq6_kIT!Xdj(B1%vJAtF z=ghguIFV^7w_{0(TIY#vn_%hm6lF2gk7%FXFe;Wt%c-&KaGOV!|K;)KtKMZR$PY@l zZ_HY|*Ld;Ytz+7jKBje6>2$DexKT1TMs$ohVhUCu7Rx40=`{%R!PUvcTZ|MBVQic& zZ2kAE@@+5gsg#{~>mWBF%~JH>7*Vkyee}dhJ(8%oIQeAwdk6pYW_|srd&v!>&ghvr zAISm2prqQDbPpj0Aq8+83xOyhfB@pjH$FW^MtEt0q5a;lm~@w`(HoiKil5 zc|SSdV3 z&odkXF@U-wXB?Mk#W4wNVAIIi`Dx0zBd@3DKr0rNQm};dvH&F8ub#6`&Sdh&c$1y? z{D>t(~Zd2;>!NKf0khhGL1-7{{0)8n4VT;FGh_G_m6hui@4_bu2K zfdQJLqC9O12iMavTUn6PCumRQ1|7!TYjf{?=|bz2Y#BPa(~t*PFcIw z;-G;t*5M#2AI;wEU(LyM=DGkhiNFwA`82%w;W{2_2G>w;|Yk6>8 z|K48|@>yPiwQGi2osp&_*)lrB4K3)<8+__;2yhIsF<_pjBm(G9XaUd%{`giMI0m@< zu-c0?wKelCO^z3~p4)z-phwSp<6{CTq6_04kuecgk8NXApOKU9;mJsUnG4$BFWS;C zGV=h7bbLXJ;h@#NU)dKj?&26!2+S9IBlFARMkkq}LG#u<>gxWmjW=X{_}Hgzr@eU3 zvre~zG<9OaXv&v29x8(KVJsqT$*QHD=l8qYN4i;Q`q7E2m-{--UctF8)8JecegC67 ztoG$kP2p)QF2Mwk{{e?Q7#Lf9AuZW4>>~8qyMMY;vSh9gRLo3f9B87;Q>mPSw4#lh zP<&Z$Q@;_0x!gYO1M&lTK2aHl0l&kFzxrbshI848QT)}ck4CT7g=OUQb{TGtsq#i; zAM21iy%;4@@y%@;*2f$!&DrWqyJKqBXM=(7CT+`R&?-!q1T--FokHy-d4;|B;gds$c0{r@yb_axSL;UXq#s? z|K1)|?65jmB9V=qoWoq`09hg-D~7DUW-i|Mv+}yLBiWfOm)@+SWB_8m5!07`WjXb6D+*U8{Ie-fhWnliqt`lIh3OyD;p!st6MFfe(A>}dhSAZ6AUNLs|v z#mP~)YV93LdPu^8>iqPH=0R~n#M4h-x#8w;9J4+0$DYJ^<3qRWy9d|;1#f(8yy?)T z6}fJE_*x#H#pYwu=2v>JbR3#ke*D!#%WZ$vwM`O}XDSj$ihlCq__Yt;d~9mKR;Xbc zIquv@vFDJFm#2dTCYVgOJKwo7xM z&mh}zO9WpjJovF==T28=54)gp6NCKcWf6;bX#2fy3@$NE(UX^luC|J5>&8s+C4!uF zW-Ccj3`H@4_!=1EauIS@12hw~C`xG&A{6A#0svfIAe^~scgflh9!(VX-F$mFE|s+m zMVQ;_C-ly^ieK=;qbY>ZK4mNlSUm@EEr@UkOw(pk*E-qNd*$Od)-7Y#^?0JflmH+M z^KF3rpb$c2d3nx_dj(JYl!YXGXg4m+bgEfi0dlo;l4Jc{58j%pieTwXE{7z8qG_MP z%V*UTGU9-sOk=^qBPjg~-Zvlc1^mW_3j|`{hmk8RGkg-Ao_zTA^O%5s;znAs;;}IH z*mw{4@{%)Y&23K8)bAepyZy|oR+cP0eF+tefeh}15hQ8Emx(6Hs6@5l_=l|%7S0l0 z^I+9LRQb9CpXpO$Z0^1PwAlf{Wg{ktBm{A4p9BnI7-Zp?hGnx&j{o#|VtP>DHYMJE z>#b{U*!bgpg2pr5BaPj2(jvj+=P}`|W8*21q8Ntp`9K6Ue!lfO!6tBD*anW_I40+l zS^aPS?o-WU6*_`Nvs*uoQ9C^I@Z?zhoyol|j)+p(aGdSL2ug$;IW%^f_<4q|&RNCM zNt4{8O;1Y{ZO$9#XxO`dluQsByyWKh_K&e0GbRTcAmsHjb7r?q95FTJ>>Ol_BcqHw zc5TE^WfrIYLS5-C`%>&*bz_BHuJC7mo_gxqoYdHhv;}V;am}Czng)Q)#RxnpLO|BP zwY)sG>dhlkV|BKcqfJyEZ;nVJuZ;6@U0!roQY#5~Q)j=hMiw|RVWQz&OCR}WO(dA^ z+goHQE=puUZ>e^$S+Bt{05OOY7*C^p`{q7w=CayP&cN_kr;`C_!I~CN-}aCXrNbbw z=`0ePE;=vWOM58V@%c=NRz;tyXS{BY&rb#fydgu+v*4S=x9_a;@PDyA{-1kKeE09V z-r)P|?sE%0z(4nrG~8G&tLo!bf&AOJ?~a+JUq1D;A}hY9ekR3xNQ_TCb#k5f!V6a# z#&6puoT!;*7(>-HfhpzYoFwTyS8LH*=$USHdNGH`!g~+CbunS}jd`Qqa6`W}Q&Xi} z`$$&#Z6ZL4l*AW*Jxaz#JaxyX#rcCvmtp$m8Dws|<5AH&FZ9)2?k`k+b?jQyiu<3F zBxjs^`F)$)ZCB?}6d4R?1wm5zVm~AdgQbeW%6R8%ue1uwcQd0+vq+n{yGY>e;bv@> zgeQ_Tpn=~x0EKWRxg6Hn*I#M+=tRW&Rr&dfo^jPobI;W#JhpsCa%wV!e)2fOxVGIC zt1_LqZ(Y-D+w?WnPX!{%aPs}Awc8vX7#bsm07485R=p4#JFsA9heA>D1uX>v$d`NL z`$@G&jKO(y(ALy{{D(gDpTov6 zUGu94r(#^EPJA+|@4ld``l@*Q9su#sZ>4=1@K z*_~dhNV)%?TuXa<&6q{89MeSj_?H2%vmk602!#zHafJ}N76PCG6To7ttbnhJ0C%0G zTPFYjAOJ~3K~zeG2=!lHsvZ`}IOfFC9b&x{mE%%<@rClLzbB8fLbrg}5gh%I;B#Q_)%*nM?ZnY?Xh8`#=ik2jrebFma0 z3D-m7l!v4##=lbr0OEK_quYwg#%yAh6k{fnbDO?1*0)HxiGohcgG`Sp*Q&dLM@=_yz z$r~?MtuJRCuI2&K?I%Te$$2Z%S=eF)Z(AYr+E<*05izds81N>|44Y$%F&nf?6t~GOMBn_Lq}S8dX zvPzc6#plI3hA$Z`GF5DXOdAu{_~fS-c|A=dxiLV*u}|r+^cZhPTVM5=GdFFsm1gT% zgi0{paue`a zUKw4xc@2YT2qETQ3_vac<~rVK`0V}IBqBXuYQ$G;d+68mGZRyD9B0OTPK-S#%j4!$ zIJhd0oAPJCEvoDboB80Chg?ob<3=DPC=i5>@xH6}QkdIGc6oBGNvmyf8=zq*Em13W zcD?_~XB%%;iMifap01fQyW*+F#O;rGyfgza1_ecM{zZt-Dab{$JT!E=1TmZTz~a4P z4i&L>n}ZQLSZb2=X|*5&0wRJC)*6NZ96}7oJcMMq`trq(s@v-Z_N+p;{N@+E{d0$& zzelJPo;oqaF1|N%S%Gn$UX?LlJjSWjO33y)1y>tlzp)Ueo;^^yHOL_QIb5@Q|7C=w31bMnK@ z_Nej#R-LT!ZZSDL;Lzfbk+7Vl;Y0iX_Ql!DHbJ!ZM8DQeaWIGiZ#uv;wmC9g?`H=#I~CJbxef@>oSF zoE62d$(hctR8?0KSGuGdca=aqi~(F0$J=|gYRQT)-K8@Tr8fYsQkcEM)%f1+WiujE z_l6rq*6PbHKIf5_sqyOJ<;9jOO{}TIbutBizhUov{P$`mw6hbQC(EiIX!@mKYA{Pa zB@T0H`F*OGLP6;r&bfISXIWeX?e`o7L4Y-YtNCpwsMy>IPChF#bN3TJN?NwDu^F2m zZZ6EvBN8@3obY&Q8Z0o!0fIq8Z9*(L{`B)RHs$&o!)aQ{Vk-m!DUZho5CT9$;CcP` z2kv>E!KHYV;WqI^flhGBOBKygf|9y$5J_v{nsZpY0Nw#>+_Kf(7n;A*`^x1dgl!Iz) zD0&V+Zpz!%$+sg_X@;rp#Nf{#PWtGWnTBj1I_7q|Vep*=*iY|K9jQlS zcA+v%xh31xQrq=LdrHdywLa0{@PfW!8iQ!DJ{IASK@{mb)Z&mqI4eTpiq;S>)nz_- z2ewXfk(aZ!pI!9sej`rc1>ti)-b5*JS5Y<`={73j6I-ih=db>LST7Undj55Y0B1m$ zzn7Fma!Kfv=9$mGU#{voW?8+XLPd?%3=5ah3>rOuK~Z>1#ro3sUq8)?NE%Pt%aJQ` z9(mAz6{(IQ?98$-R5oSH7ryY!8d2RCNub=m z2L4xl0DdZixOnNK zpK2ex#q;{7+O2!se6J;k-P=7bIx?`zI`6jHVE6f!BidgK)C@)?M;&d9U{7`3o_hY1 z{UFCC7pHOHi`Svk!_yPR%5WCHzkmY~}OTC`~i4Pr#d7yRS1 z0R>E8{mTSb2QZjCj(mH>2|973j`!e4_VASxh z_mx8O`A0w6o;$U21tZqPoH#>98mif}bs+VZdAVr_VSc+b3?Srq_mzVNaba#6Hh8Y* zvkRieVHP4?uGNq0DXo{HX_}#!K>kml$S^Qqg z00z9&073{ejq>x>c}B-NFHJOb;wrJ-6_Nei3u={$>70%WPf5cG7D5cg00aVTs6b8t zgCOm5CZ`dN5JfXI?dL2p2nHKc$PEfS27Vt1fMFPi4H;Dil4tN`((yxYR-HUPGr{Am zc#5Zxo_gSZ=lGzsV3pQ(H4Y!k;Ph-B4G+=9LK99RiiRHJ2IRcY;f^UL zduv10=$`CRz9u%YbZO%3MNyb)!U*x4Jx{Q4fMZy|f&)09Z1;`Hvx7A=vSlNkGo5p4 zhNMt1Di8)Z8~{Sx@7>|cGhy>NkiZc|e`6GY0A3Fw1g~#a_<>*$g8vnK^n)BDuD=Ha zQ!_9Cp_^vshMR0az|cSwqYUGYo_zCayE8>6&QYeu4$OhQN9jY5_sLjaE;E3crRaT+$l2^7|F!N!8##Omw z=5!6KSfbZB`;IpW8u0>L6=~N`+a(FtYNsNyV#en96BB@%btH2~Sd%r9;w60jVEdW# z&D}0ow#VzCf@a|UNf$1XKlvVCwq>k9-e%}&;JLfk|7`nje|}zBx=lC7#lrH0GQR)e z51=IsfB-?RHjXb8eQ}~U%+zksP5kp;hQb2$k3U`J@Vv$u{Vg|KyL)}@`GJBW=JXhm zo)X0<1gtq;97Qv9!0<9CEcVrO2*G0WO}MaOgu$%xK;2{(K`FjQ;y=tmhycO}Jki?J zI>_gyrVq~w!ZGuYUMv?|h8jDRvCEcG3}S*4z=Gc{u#XR=%6i(HW;gDVLvA!rqHY|I zX_!cP;E}B)#lbM#$8Ckk%jeKpne;8I+ADH9Yo`l`%=@EbX*hNJosxTBS z7zFB-Z0oi7lKZU#7rXzoZ_vnz%w0+|zIh7L{^}nZFy~j~1!co%akz%RE?|M&7(77U z!61P_0*7LPseSdS*fi>=Kj&OMXprG}hpkHxv#bp&%xR-)N8lx z&=|rtx(4fF*6sVvs|L4|GTGT&4qCf5$9?g&s7P^wDtl96a*3w-7Z;qHOkOVK_J(wAhhI6Y;5Cam&9B9y16mwezr8BVtY?-fU7&W<5Bsh%E|L>_QHZi zfC@w>=L!P@O+EI?%>I9TCLMAYPt~^9#Xn^n91^DIk@lIW+=|{IdwO-H%k3G`0|Di~ z7^T#Ln>ayxhYf}33n3d#Ep;%!MX)}d$A7g+Jal52gSiisVj(x`<{z{jZ6g(Pk%aeodYmJ z5k!XwaS*4XJyVu+%aK+xcX7tlm?Mbju%ZG?NFvl z^ur(@xy>TVFlZ74D>&wt>|RF#4gu}-(Fnk@9P!mJz8>%*@?uF zZ+f#=E$5FN!**3B#XArAXFUFxEC^{FgCdcDI`(c=s{T+j&kzvHHQLE3=WGW73>zyj z3;`DV@w|Sak{2iOF!-|c-dAO686nabtN>v^87rn~B$Nx>b`ShMEevnv67WMv4!kw_ zDZEVp>bk};`Uh+Ux3J0P5`jqytXRY;i=ArpW)F|KY*79{g_9gQ`|pd%D^{m(S;l5V z=p;E>dBD~`LgMU>Uf0Wi@brv`_@fP-X2$DpO){NVIg}AH+1UIblss=;gZLM$$1yPIhdcw7 zpT2Qm^xU_ZD_8q`G!;Jfg0LluiKBO3{1C`9pRDfa9mO=sS^(HIU;>B%Kp~8Rw1+fb zUHp)q>NvY$iL<32ZT|f}F4ve-n7~`{^n}q1M2Q}Nyd*0~`9|2g!qKg>Ww4N@>3OZ( z5L{ah2qN@CRK(hwXYK>DDyTV@heMIE(`PgaDkoo)x_Vp2w)>T2=jxmmACr6J!e%5F1Rq2c-5Kq>++f_`Yb6Jn=#{n zqP%Xu*@=w|+YM&eJBsW!9|njiBed885K?pC*KCs0^*{Ku#p)XzqbA4QwSAmvJ0mZ_ zI_OI=%(%X%IKD0^NCND-x-Eie7{z(*%3f=0n)^zfa-8^CdlMv!*-Fekx0 z)+F3mP5K)T7NZN2cjC?t$)6qV`g|1Cxn1KRJVIQ%e?N ze?4?goxdqCcEF>m4iF@UAdX0`HiI!;QY?pUv*cEP`51p+rglLRGLOem?t<>r& zWLG_Li}|TpaT3a9cdlKb;L>(ltodx`6}b$E#r)2GU+_k71ELq+>JGT>*Wdpp5Z=nt zxILQTmU;+og_8(z00h9b5}!bo$l!uToqSb}t~%Y8J9BiIDzDuJMQYwyvokZ*u40V!?mPRzAuHYSxn{*Sck0I2j@Pv1D>CzPD2fKO zx1*_f-ETx3E|v<~Ivm;0vj2I=v&8B0Bvw~M@dLIAlO{KfAyYG%EX!c88&^`on2vsv z6^pqer@4nJxMQc(=VNw%{XfUgSW^>)Q_OfG5TGO70Ffnr0G3L+1?_u8aFn(XL%>}OoE`otc717LTjAq(!d2B&GH!$N&->F)%BfBUA zDdQ=AY#=}qA-fNtX0`6~>6D<74TXtB3_&)Ri#L4`tK=;kJ$g#ab?fd!OXH~E;GPkBLcD*cwo=&H!zNm#$i#?*t&)K7vI*5 z1(LIp0v;%^W$c)702fTgo^B=z@NKg%R=$2*bEjDU&M89fljw2vK7!DB( zCGh|VXh;Kkt}J2p$_0Zdh%wo0HjV+B$MSOmu4rJ~oO$l5XI*xh z0%s|hI0Hk#=d~}Zk8VYys30ehTG$Yj+rTk z0MQhHB&2CTQxJwW+`Qo2$Zqo+pYSjQ+yMpv5CMV?_}Yg#`Y9Je;5uZ>bq2>ADCq~x zhAaJ)&kwI(s2+Mbsw*^jv}Bw}uUKE{)GUPF=~HKI$UM1r0m@T5I0BAcHxtF@8Ed{X z_B9;%cRwc95DbdsNDM$ZY!$QnPabnE$yRt=s!|IkrD^DEzL>P>A>qh39p^^T=AY_- z#_jUZG{)eGu$a_M3s~R2dqyeF$fhX@$50f*uI_qkbcE5-(b5?x0se3Zb@27VAVk>X zRYOHF)@`el=Xq;O*)uwyN-5)7n=jw}VEKE4h026zviaB>`&dOWWA=c$Wq^Q?z8%-t z4R!$hKkR_(6s6r*u6kP}!L85%aQ-)k2tzPUWl_a)(}ac+jl<|sEmyZR9=_Uc*Vq-s z>FYP18<5WQ59vF)mscrIx3M>D^1S*6ea^Jx$=`3Jn!c>NiryI8wEV7$@6Nc26LFwU z*?%s8H~wqJ&Kxz^hI^-zw6@1L^!}*g+@^H~3l&o{oH#H=d1dLNtzELB3YIoAw<=S{ z4dlmJeTs72GifyY(o)&^-nOQhSf3#J?gz4ZE>1UpY1UEGN;4F)C@DMB*A@bNQPFhP+tMbiXHK}8xr zIUCB;Y)o~GTER-nas###@L^P(-yaBO*USM6^t?#x5aa^^h7g89%4TKxoGcE9uWy#7 z6rOnQ*^0`^XC?epuyECj`)3KV~1C7P(`u%N^N6Hs3@0ha)Qr(y`^6VUNjhE(`^>lI%EY#`c>#iU!3?7qy3(o78wzu%JM#AP!!=5N;9TdWcn#aD1$A|Xt1*Iv2O6Sr=i zpCOtw_*^7&J35$aE!*8dGf&-izG8$i)#LvP*N>M23PHonCd%D@4v)MNU*fmu8}vl)C@0JRq@yF zAO@*hP@Ljub z)w)Wd#fobzUv}zKru5$ZherFa_G3)uYV9ay8oQ%vMxMmXTvqkV7w(IS&S}>Zlt+h* zMoz3+iy-(mZW)|azPx1Q=EW?;dqLxb4 zDt1&1TPn!*o=Y5lWpQoqY7TFV9q^aFn9`?zwzrA-;FIz45Vd{+}v^=!_Cna6Eq0%z+s<3SP@U_EpW+F zg?0G+?*A~dV#anZ>U-xyDlN^PCF~WuM&2EG5gx7l;Ll_}3hSzKhdaf}fn7|L`()?%r({ql$&?KWm-7+q|((a7~ z=imCn=QF+#De0K9%(ML0A};`vlWJ5kMhC z0pd7fkO2v@OS}VZ)5*2(?moF+A23a(Czw9_m=sgyycIbI-uwJOovrDu-Gv#JC99br z;OV%an;>(3^s?y3NvEIvdvb~vXFH}QTqX&!42?=jm-GIG{Vh`(f(8^pUOTVp8%*%) z7X@B7D2%>dzbpVZ_X^QJOd{Gm%*o!ip1N_j({;F>cDoS(6auu{MNC`iF-A#o%!p@b z7-<(^Gqu{4_bVk%i(g2lEO_M`0Zoz?FWW<4j}+9K8%HrFck-*x63j;yJpLk2lkvM> z9T(V|y~;e7%QIqjsLV~++8_M^*JfK>hz5XxV+{MW(siy_4GxVaj(fnxiR2)}2LS*G zAq**0;sk$d<*KUaJY|eHDnV+ySZ|Mao@jNaWXjA!Uu%}g=fzZ6rMdUrBdQ&d4q62s zyC6i@9zLOe~!=hQeC?S!rIeo)Tm&-No|&iy+)e^|BnF`^bd0Y5h@_JAHDi> z#%Q~~p0%W#%56Mwh+n$S?_u0g-YT8AI^JVgqUg(%O)SiHRhHVi`P;}DJTcWLPrutb z(LqAdnak9gUq9_;s#(B^RsM{iNxvT~s!&^JTvWrJ2_hpolPFoAZS{#dPmP)!!gzh7 zATe!t%;V&1IV>ts<$Ge2_?5Q}>F}H@b;sfJGsY=*z@#g~+WgH|esT7W-#s5)xT;`i z5O!cNQu24E-(>sHB(4=B!`;7mFwya~FZ~&eDq!@JmV0dB;MJM$vQxyg`ywoR)L=jBCrbM3vB; zt3`kOh&NzOE?m0k*nv7HU&f;Xg)7QD1Pes`edzg2C=BiDaDy-ivh)B$5W^Y7NWDV; z**p8xdbg97CyjZcNeWGm!0M%eWNA$vE26EVRPn!tR)LQem}N-sjI$&3UqZ8ioWGa7eEnfXaW%&(dnraY{xJE z;P;V$1~`r*gh=Cn+|btE*xX(>#a2m&4ZM&n4nl-Mh%*?JbK{1TQc>%~0JPP;)6#3- zmUQ$~JGqqO^W!0g4-_m3oTqjWeGMGk(QlUMEr8ILu2`7{wIwgT zGtKrpVx*7(D7LY0)6bH2BsWm;OM8Z3mhV7UjXs^#IVmXi5s;$h8A<2#wc*fRtB+Y# zp3Jn?dCg;|_73zljmWs(g|VG|s7j)V4(G^6@CXszmZ8eVaHu^sn?E$`Ie^!eU4$!b zLaIT5M2uqytN*;vvv1iG&+?R+woC60jhR@E!P+)vQbN>+pE{zt&(&+5bar*kG+il^ z9xd6hyrMLB%;u*#Du=@}>$VE58XC|5Ae?!1k`tSgymnKucF{t6ZSVUHaaoxe=DmLn z#AIR|0YyVH2n5Y$EQe$;w4D%bEb})C?_RxiF@IoxRCZp|5SN#^?l;TZyaC`#TuL$7 z6vhk?gqvhi6iw1#Hqdx(`iIK=Lfdw>M-xR%eiUZFX9FNHgz(wy$B0kdY=_q@-9cY- z5tv&F5w`)1mE*o#q-a0&b!+AQ8^zmxS5&p2+W#AMy5{49Hevg*Cb<(o<1X-YMI>lY${c|x4(I0{U$~ICFiC7*sd&q&v1<;&#L$ZGO4q8!e^bvg3elz!X_>_h*+=>GxQfJTVc4Nmz<#@yv2 zqVF;I%EuI!%s9pQDxV7Pm#lvNwKv;R(iJwAC^L~~Hqn`P@AP2gKo@tR%GJ|-qVsgq z(v22BzP|e5ZEDKGovP9HAMIq7U~(s&wSGCyU>HyDPfsGvt<7337M+q-H>K&Yt4V?k z9y@|z8d_{v!lhPLYEGZ%PQ|AyD@IIL+Wz*X+SWhaOXL+hjv3<@#2Qch?NYj@U_+e7 zJ-YX+FB_E<;zd+h!kfuD;rB-Qb=Cm<-ibcqCxie(p^)Kn1rUbj?UmV001-(;1mQeC z$~F7o<`Mt5?FIWDv_+Br02&=M`F;NBQKN%miWL%`wfj&5x7U$;UKh9b46DnZI0wn445kXc90Voo&`aj)mU?xbNwGY4ix3cOg zK-vSOMa^$tR;a)9L@q*QAyO*O)viEl1PNBO4vXGFDVvFl31UB$icHZGJVO8@+lE@S(a zS9k4RR>2weDkzc&UjpE4vI0fYfGeI3$XD>L7(K}QvMSRQ5*-Q|C z1~5!ehe0ihrYL|g+Qd!|5R}Qs<9KIeYahg8vl-E`BXp`;oJ(L#f}}}m*47YO9xzMJc+P%OJTl z_tf+ERKSnN2F3*?n;xNf<#D>9tdEZ zD5)x59Th9;*HIHQq8#OffbZdY^%qCua^#jvoxtyh^Wc8^rqiFkIq-XnEweW%GP!Oe z`W$}(AwB=9GVdy=QZNc*roFQKK-*DNwxhqczJG-18}YxgVZhDd#K|~QGoB=#B@NXL z3|{Q`yv=2_bzXJLlfAlg7vJeipiNU43$yqo*z+r$4ErcoTXN#1XHM+ve(=s{_So?= zQNI`*8nt@4RJZ{aA&77ck4-5SO{PbaOUvXk^yP`&J#RJ^Q#?_hS84IGzvwGS)SdOk zq`6~?6^A!JF@Zh?zd`Cjb!A^qk@Ndbfc&@W1tZt9bN7r9T*z2w3}lar(_~qizq!CxlFjzE{;w5`knLQw0Jk*Q4|f}+z4=+tho!~ zK-xvBzJKr7FFv?%yUSP*$j0#ZU)A9FE(a>&%5)^nor%B&(LbhaA zM@{b{>I^!>JlGGlGedR7k%o5ykXOu)%+nS{sIbET(wDqaoqe)=Dmn+n}* zW@DK{i47rcgQ6&sq5=d(#um6-fk1#FNGgE16oXC7HCE21Sk75W>3J>QVGt#Zp(7ZU zJYfJwNGf6R25YDMBB6*AC1g<;M^^iy&xvyb<^V&0@uSkCtjTqM#zh(vE}vEXfO*M5 zkp{6y3@k_=Q!}h23niJh5dxJ2)PIy5PGMsLJAa(6Wn+E@%rvGh34&NZz zKCGuD89ZgI;O@lsMqhav=>EqyGy@Vi@PB@R8;2&5q5GmKQ$S2-=W2|H_kP!|8j4wK z)OmI+9Cs8yCp7l`e!o(gns&Lxh5cvWcgTE2z>BTiwnF8enVD`nU8lAWUIJi; z=%82^VGsg3mKwVAjwDarzb8f}_kTP&4V3z*++LRw@Kmu2@-V_T$S$soY8hiM?zYNe zr;qI!$~79@AuZeWom@W@0R#a6NF>CxTBhHJ`vc^)i8`Srfr9@PO1Qs&oaoj^XT>

      `=fb{zO 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


      <74_M#^2*h`~;{2ZQ`7XIYp@sH7H?PXc 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 +#include +#include +#include +#include + +#include "colors.h" + +double get_time() { + struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); + return ts.tv_sec * 1000.0 + ts.tv_nsec / 1000000.0; +} + +int main(int argc, char **argv) { + unsigned width, height; + double magn; + if (argc <= 1) { + width = 1024; + height = width; + magn = 4e5; + } else if (argc == 3) { + width = atoi(argv[1]); + height = width; + magn = strtod(argv[2], NULL); + } else { + fprintf(stderr, "usage: %s \n", argv[0]); + return 1; + } + double eps = 1e-17; + double Q1LOG2 = 1.44269504088896340735992468100189213742664595415299; + double LOG2 = 0.69314718055994530941723212145817656807550013436026; + + int x, y; + double centerx = -0.743643887037158704752191506114774; + double centery = 0.131825904205311970493132056385139; + double bailout = 128; + double logLogBailout = log(log(bailout)); + int foundperiods = 0; + long maxiter = width * sqrt(magn); + double x0d = 4 / magn / width; + double x2 = -2 / magn + centerx; + double y1d = -4 / magn / width; + double y2 = 2 / magn * height / width + centery; + + double tbeg = get_time(); + + // write out image header + printf("P6 %d %d 255\n", width, height); + + for (y = 0; y < height; y++) { + fprintf(stderr, "\r%.2f%%", (float)(y+1)/(height)*100); + for (x = 0; x < width; x++) { + double px = x*x0d + x2; + double py = y*y1d + y2; + // no Main bulb or Cardoid check to be faster + double zx = px; + double zy = py; + long i; + // Initial maximum period to detect. + int check = 3; + // Maximum period doubles every iterations: + int whenupdate = 10; + // Period history registers. + double hx = 0; + double hy = 0; + double xx, yy; + bool inside = true; + for (i = 1; i <= maxiter; i++) { + xx = zx * zx; + yy = zy * zy; + if (xx + yy > bailout) { + inside = false; + break; + } + // iterate + zy = 2 * zx * zy + py; + zx = xx - yy + px; + + // periodicity check + double d = zx - hx; + if (d > 0.0 ? d < eps : d > -eps) { + d = zy - hy; + if (d > 0.0 ? d < eps : d > -eps) { + // Period found. + foundperiods++; + break; + } + } + if ((i & check) == 0) { + if (--whenupdate == 0) { + whenupdate = 10; + check <<= 1; + check++; + } + // period = 0; + hx = zx; + hy = zy; + } + } + + if (inside) { + const char black[3] = {}; + fwrite(black, 1, 3, stdout); + } else { + double r = sqrtl(zx*zx + zy*zy); + double c = i - 1.28 + (logLogBailout - logl(logl(r))) * Q1LOG2; + int idx = fmodl((logl(c/64+1)/LOG2+0.45), 1)*(GRADIENTLENGTH-1) + 0.5; + fwrite(&colors[idx], 1, 3, stdout); + } + } + } + + double tend = get_time(); + + fprintf(stderr, "\nElapsed time: %.2f ms\n", tend-tbeg); + + //fprintf(stderr, "\n%d periods found\n", foundperiods); + + return 0; +} diff --git a/ext/wasm3/test/wasi/mandelbrot/mandel_dd.c b/ext/wasm3/test/wasi/mandelbrot/mandel_dd.c new file mode 100644 index 0000000..fd0d8c3 --- /dev/null +++ b/ext/wasm3/test/wasi/mandelbrot/mandel_dd.c @@ -0,0 +1,146 @@ +#include +#include +#include +#include +#include + +#include "colors.h" +#include "doubledouble.h" + +double get_time() { + struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); + return ts.tv_sec * 1000.0 + ts.tv_nsec / 1000000.0; +} + +int main(int argc, char **argv) { + unsigned width, height; + DoubleDouble magn; + if (argc <= 1) { + width = 1024; + height = width; + magn = dd_new(4e5, 0); + } else if (argc == 3) { + width = atoi(argv[1]); + height = width; + magn = dd_new(strtod(argv[2], NULL), 0); + } else { + fprintf(stderr, "usage: %s \n", argv[0]); + return 1; + } + DoubleDouble temp1; + double eps = 1e-17; + double Q1LOG2 = 1.44269504088896340735992468100189213742664595415299; + double LOG2 = 0.69314718055994530941723212145817656807550013436026; + unsigned int x, y; + DoubleDouble centerx, centery; + centerx = dd_new(-0.7436438870371587, -3.628952515063387E-17); + centery = dd_new(0.13182590420531198, -1.2892807754956678E-17); + double bailout = 128; // with a smaller value there are lines on magn=1 + double logLogBailout = log(log(bailout)); + int foundperiods = 0; + long maxiter = 50000; + /*// maxiter = width * sqrt(magn); + temp1 = dd_sqrt(magn); + unsigned long maxiter = width * dd_get_ui(temp1);*/ + DoubleDouble x2, y2, x0d, y1d; + // x0d = 4 / magn / width; + x0d = dd_ui_div(4, magn); + x0d = dd_div_ui(x0d, width); + // x2 = -2 / magn + centerx; + x2 = dd_si_div(-2, magn); + x2 = dd_add(x2, centerx); + // y1d = -4 / magn / width; + y1d = dd_si_div(-4, magn); + y1d = dd_div_ui(y1d, width); + // y2 = 2 / magn * height / width + centery; + y2 = dd_ui_div(2, magn); + temp1 = dd_new(height, 0); + temp1 = dd_div_ui(temp1, width); + y2 = dd_mul(y2, temp1); + y2 = dd_add(y2, centery); + DoubleDouble px, py, zx, zy, xx, yy; + double hx, hy, d; + + double tbeg = get_time(); + + // write out image header + printf("P6 %d %d 255\n", width, height); + + for (y = 0; y < height; y++) { + fprintf(stderr, "\r%.2f%%", (float)(y+1)/(height)*100); + for (x = 0; x < width; x++) { + //px = x*x0d + x2; + px = dd_mul_ui(x0d, x); + px = dd_add(px, x2); + //py = y*y1d + y2; + py = dd_mul_ui(y1d, y); + py = dd_add(py, y2); + // no Main bulb or Cardoid check to be faster + zx = dd_new(px.hi, px.lo); + zy = dd_new(py.hi, py.lo); + unsigned long i; + bool inside = true; + int check = 3; + int whenupdate = 10; + hx = 0; + hy = 0; + for (i = 1; i <= maxiter; i++) { + //xx = zx * zx; + xx = dd_sqr(zx); + //yy = zy * zy; + yy = dd_sqr(zy); + //if (xx + yy > bailout) { + if (xx.hi + yy.hi > bailout) { + inside = false; + break; + } + // iterate + //zy = 2 * zx * zy + py; + //zx = dd_mul_ui(zx, 2); + //zy = dd_mul(zx, zy); + zy = dd_add(dd_mul2(zx, zy), py); + //zx = xx - yy + px; + zx = dd_add(dd_sub(xx, yy), px); + + // period checking + d = zx.hi - hx; + if (d > 0.0 ? d < eps : d > -eps) { + d = zy.hi - hy; + if (d > 0.0 ? d < eps : d > -eps) { + // Period found. + foundperiods++; + break; + } + } + if ((i & check) == 0) { + if (--whenupdate == 0) { + whenupdate = 10; + check <<= 1; + check++; + } + // period = 0; + hx = zx.hi; + hy = zy.hi; + } + } + + if (inside) { + const char black[3] = {}; + fwrite(black, 1, 3, stdout); + } else { + double r = sqrt(zx.hi*zx.hi + zy.hi*zy.hi); + double c = i - 1.28 + (logLogBailout - log(log(r))) * Q1LOG2; + int idx = fmod((log(c/64+1)/LOG2+0.45), 1)*(GRADIENTLENGTH-1) + 0.5; + fwrite(&colors[idx], 1, 3, stdout); + } + } + } + + double tend = get_time(); + + fprintf(stderr, "\nElapsed time: %.2f ms\n", tend-tbeg); + + //fprintf(stderr, "\n%d periods found\n", foundperiods); + + return 0; +} diff --git a/ext/wasm3/test/wasi/raymarcher/raymarcher.cpp b/ext/wasm3/test/wasi/raymarcher/raymarcher.cpp new file mode 100644 index 0000000..b69e8cf --- /dev/null +++ b/ext/wasm3/test/wasi/raymarcher/raymarcher.cpp @@ -0,0 +1,164 @@ +/* + * Build: + * wasicc -g0 -O3 raymarcher.cpp -o raymarcher.wasm + */ +#include +#include +#include + +double t = 0.0; +#define WIDTH 80 +#define HEIGHT 40 +static char framebuffer[HEIGHT * WIDTH]; + +const char pixels[] = ".-::==+++%%%####@@@@"; +//const char pixels[] = ".-:=+%#@"; +//const char pixels[] = ".`:,;'_^\"><~+_-?][}{1)(|\\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$"; + +const int npixels = sizeof(pixels) - 1; + +struct vec3 { + float x; + float y; + float z; + + float length() { + return sqrt(x*x + y*y + z*z); + } + + void normalize() { + float l = length(); + x = x / l; y = y / l; z = z / l; + } + + struct vec3 operator*(float fac) { + struct vec3 r; + r.x = x * fac; r.y = y * fac; r.z = z * fac; + return r; + } + + struct vec3 operator+(struct vec3 other) { + struct vec3 r; + r.x = x +other.x; r.y = y +other.y; r.z = z + other.z; + return r; + } + struct vec3 operator-(struct vec3 other) { + struct vec3 r; + r.x = x - other.x; r.y = y - other.y; r.z = z - other.z; + return r; + } + +}; + +void raymarch(); +float sdf(struct vec3); +char shade(struct vec3); + + +void raymarch() { + for (int y = 0; y < HEIGHT; y++) { + for (int x = 0; x < WIDTH; x++) { + struct vec3 pos = {0.0, 0.0, -3.0}; + struct vec3 target = { + x / (float) WIDTH - 0.5f, + (y / (float) HEIGHT - 0.5f) * (HEIGHT / (float) WIDTH) * 1.5f, + -1.5f + }; + + struct vec3 ray = target - pos; + ray.normalize(); + char pxl = ' '; + float dist; + float max = 9999.0f; + for (int i = 0; i < 15000; i++) { + if (fabs(pos.x) > max + || fabs(pos.y) > max + || fabs(pos.z) > max) + break; + + dist = sdf(pos); + if (dist < 1e-6) { + pxl = shade(pos); + break; + } + + pos = pos + ray * dist; + } // end for (i) + + framebuffer[y * WIDTH + x] = pxl; + } // end for(x) + } // end for(y) +} // end raymarch() + +float sdf(struct vec3 pos) { + struct vec3 center = {0.0, 0.0, 0.0}; + + return (pos - center).length() - 0.6; +} + +char shade(struct vec3 pos) { + struct vec3 L = { + 50.0f * sinf(t), + 20.0f, + 50.0f * cosf(t) + }; + L.normalize(); + + float dt = 1e-6; + float current_val = sdf(pos); + + struct vec3 x = {pos.x + dt, pos.y, pos.z}; + float dx = sdf(x) - current_val; + + struct vec3 y = {pos.x, pos.y + dt, pos.z}; + float dy = sdf(y) - current_val; + + struct vec3 z = {pos.x, pos.y, pos.z + dt}; + float dz = sdf(z) - current_val; + + struct vec3 N; // N for normal + N.x = (dx - pos.x) / dt; + N.y = (dy - pos.y) / dt; + N.z = (dz - pos.z) / dt; + + if (N.length() < 1e-9) { + return pixels[0]; + } + + N.normalize(); + + float diffuse = L.x * N.x + L.y * N.y + L.z * N.z; + diffuse = (diffuse + 1.0) / 2.0 * npixels; + return pixels[(int) floor(diffuse) % npixels]; +} + +void cls() { + // Terminal clear sequence + write(0, "\33[2J\33[1;1H", 10); +} + +void printfb() { + char *fb = framebuffer; + char nl = '\n'; + cls(); + for (int y = 0; y < HEIGHT; y++) { + write(1, fb, WIDTH); + write(1, &nl, 1); + fb += WIDTH; + + } +} + +int main() { + for (int i = 0; i < WIDTH * HEIGHT; i++) { + framebuffer[i] = ' '; + } + + for (int i = 0; i < 100; i++) { + raymarch(); + printfb(); + usleep(20000); + t += 0.1; + } +} diff --git a/ext/wasm3/test/wasi/simple/0.txt b/ext/wasm3/test/wasi/simple/0.txt new file mode 100644 index 0000000..70c379b --- /dev/null +++ b/ext/wasm3/test/wasi/simple/0.txt @@ -0,0 +1 @@ +Hello world \ No newline at end of file diff --git a/ext/wasm3/test/wasi/simple/README.md b/ext/wasm3/test/wasi/simple/README.md new file mode 100644 index 0000000..56ae6c1 --- /dev/null +++ b/ext/wasm3/test/wasi/simple/README.md @@ -0,0 +1,23 @@ +## Compile + +```sh +wasicc -g -O0 -Wl,--stack-first test.c -o test.wasm +wasm-opt --strip-debug -Os test.wasm -o test-opt.wasm +``` + +## Run + +```sh +../../build/wasm3 test.wasm + +$ENGINES_PATH/wasm-micro-runtime/core/iwasm/products/linux/build/iwasm test.wasm + +$ENGINES_PATH/wac/wax test.wasm + +$ENGINES_PATH/WAVM/Release/bin/wavm run test.wasm + +wasmer run test.wasm + +wasmer-js run test.wasm +``` + diff --git a/ext/wasm3/test/wasi/simple/test.c b/ext/wasm3/test/wasi/simple/test.c new file mode 100644 index 0000000..dc3bd12 --- /dev/null +++ b/ext/wasm3/test/wasi/simple/test.c @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include + +#include "wasm_api.h" + +/* + * Helpers + */ + +static inline +struct timespec timespec_diff(struct timespec start, struct timespec end) +{ + struct timespec temp; + if ((end.tv_nsec-start.tv_nsec)<0) { + temp.tv_sec = end.tv_sec-start.tv_sec-1; + temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; + } else { + temp.tv_sec = end.tv_sec-start.tv_sec; + temp.tv_nsec = end.tv_nsec-start.tv_nsec; + } + return temp; +} + +static inline +int rand_range(int min, int max){ + return min + rand() / (RAND_MAX / (max - min + 1) + 1); +} + +WASM_EXPORT +uint32_t fib(uint32_t n) +{ + if(n < 2) { + return n; + } + return fib(n-1) + fib(n-2); +} + +/* + * Tests + */ + +static char gString[16]; + +__attribute__((constructor)) +void test_init_some_global() { + static const char data[] = "Constructor OK\n"; + memcpy(gString, data, sizeof(data)); +} + +void test_constructor() { + fwrite(gString, 1, sizeof(gString)-1, stdout); +} + +void test_write() { + fwrite("Hello world\n", 1, 12, stdout); +} + +void test_printf() { + printf("Hello %s!\n", "printf"); +} + +void test_args(int argc, char **argv) { + printf("Args: "); + for (int i = 0; i < argc; i++) { + printf("%s; ", argv[i]); + } + puts(""); +} + +void test_random() { + unsigned entropy; + getentropy(&entropy, sizeof(entropy)); + srand(entropy); + int x = rand_range(0, 10); + int y = rand_range(0, 10); + printf("%d + %d = %d\n", x, y, x+y); +} + +void test_gettime() { + struct timespec now; + clock_gettime(CLOCK_REALTIME, &now); + printf("Now: %lld sec, %ld ns\n", now.tv_sec, now.tv_nsec); +} + +void test_perf_fib(uint32_t n) { + struct timespec start, finish; + uint32_t result; + + printf("fib(%d) = ", n); + fflush(stdout); + + // Chew up some CPU time + clock_gettime(CLOCK_REALTIME, &start); + result = fib(n); + clock_gettime(CLOCK_REALTIME, &finish); + + struct timespec delta = timespec_diff(start, finish); + + //unsigned ms = (delta.tv_sec*1000) + (delta.tv_nsec/1000000); + //printf("%d [%u ms]\n", result, ms); + + double fms = (delta.tv_sec*1000.0) + (delta.tv_nsec/1000000.0); + printf("%d [%.3f ms]\n", result, fms); +} + +void test_cat(char* fn) { + int file = open(fn, O_RDONLY); + if (file >= 0) { + char c = 0; + while (read(file, &c, sizeof(c)) > 0) { + printf("%02x ", c); + } + close(file); + puts(""); + } else { + printf("Cannot open %s\n", fn); + } +} + +__attribute__((noinline)) void c() { __builtin_trap(); } +__attribute__((noinline)) void b() { c(); } +__attribute__((noinline)) void a() { b(); } +__attribute__((noinline)) void test_trap() { a(); } + +/* + * Main + */ + +int main(int argc, char **argv) +{ + test_write(); + test_constructor(); + test_printf(); + test_args(argc, argv); + test_gettime(); + test_random(); + if (0 == strcmp(argv[1], "trap")) { + test_trap(); + } + + test_perf_fib(20); + + if (0 == strcmp(argv[1], "cat")) { + test_cat(argv[2]); + } + + puts("=== done ==="); + return 0; +} diff --git a/ext/wasm3/test/wasi/simple/wasm_api.h b/ext/wasm3/test/wasi/simple/wasm_api.h new file mode 100644 index 0000000..7c430ff --- /dev/null +++ b/ext/wasm3/test/wasi/simple/wasm_api.h @@ -0,0 +1,10 @@ +#ifndef wasm_api_h +#define wasm_api_h + +#include + +#define WASM_EXPORT __attribute__((used)) __attribute__((visibility ("default"))) +#define WASM_EXPORT_AS(NAME) WASM_EXPORT __attribute__((export_name(NAME))) +#define WASM_IMPORT(MODULE,NAME) __attribute__((import_module(MODULE))) __attribute__((import_name(NAME))) + +#endif diff --git a/ext/wasm3/test/wasi/simple/wasm_api.syms b/ext/wasm3/test/wasi/simple/wasm_api.syms new file mode 100644 index 0000000..06ac8d4 --- /dev/null +++ b/ext/wasm3/test/wasi/simple/wasm_api.syms @@ -0,0 +1 @@ +wasm3_raw_sum diff --git a/ext/wasm3/test/wasi/smallpt/README.md b/ext/wasm3/test/wasi/smallpt/README.md new file mode 100644 index 0000000..066a2d4 --- /dev/null +++ b/ext/wasm3/test/wasi/smallpt/README.md @@ -0,0 +1,48 @@ +# smallpt + +Based on https://www.kevinbeason.com/smallpt/ + +

      + +### Results + +```log +TODO +``` + +### Building + +```sh +wasic++ -g0 -Oz -Wl,--stack-first -Wl,-z,stack-size=$[1024*1024] smallpt-ex.cpp -o smallpt-ex.wasm +``` + +### Running + +```sh +export ENGINES_PATH=/opt/wasm_engines + +# Wasm3 +../../../build/wasm3 smallpt-ex.wasm > image.ppm + +# WAC +$ENGINES_PATH/wac/wax smallpt-ex.wasm > image.ppm + +# wasm-micro-runtime +$ENGINES_PATH/wasm-micro-runtime/core/iwasm/products/linux/build/iwasm smallpt-ex.wasm > image.ppm + +# wasmtime +wasmtime --optimize smallpt-ex.wasm > image.ppm + +# Wasmer +wasmer run smallpt-ex.wasm > image.ppm +wasmer run --backend singlepass smallpt-ex.wasm > image.ppm +wasmer run --backend llvm smallpt-ex.wasm > image.ppm + +# Wasmer-JS (V8) +wasmer-js run smallpt-ex.wasm > image.ppm + +node --wasm_interpret_all $(which wasmer-js) run smallpt-ex.wasm > image.ppm + +# WAVM +$ENGINES_PATH/WAVM/Release/bin/wavm run smallpt-ex.wasm > image.ppm +``` diff --git a/ext/wasm3/test/wasi/smallpt/image.jpg b/ext/wasm3/test/wasi/smallpt/image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2461c7d615d6195f3c86ce5576fc77b833a74759 GIT binary patch literal 253688 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⁢M|P4-*8GJxo58>MSO+t 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 // smallpt, a Path Tracer by Kevin Beason, 2009 +#include // Make : g++ -O3 -fopenmp explicit.cpp -o explicit +#include // Remove "-fopenmp" for g++ version < 4.2 +#include +double get_time() { + struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); + return ts.tv_sec * 1000.0 + ts.tv_nsec / 1000000.0; +} +struct Vec { // Usage: time ./explicit 16 && xv image.ppm + double x, y, z; // position, also color (r,g,b) + Vec(double x_=0, double y_=0, double z_=0){ x=x_; y=y_; z=z_; } + Vec operator+(const Vec &b) const { return Vec(x+b.x,y+b.y,z+b.z); } + Vec operator-(const Vec &b) const { return Vec(x-b.x,y-b.y,z-b.z); } + Vec operator*(double b) const { return Vec(x*b,y*b,z*b); } + Vec mult(const Vec &b) const { return Vec(x*b.x,y*b.y,z*b.z); } + Vec& norm(){ return *this = *this * (1/sqrt(x*x+y*y+z*z)); } + double dot(const Vec &b) const { return x*b.x+y*b.y+z*b.z; } // cross: + Vec operator%(Vec&b){return Vec(y*b.z-z*b.y,z*b.x-x*b.z,x*b.y-y*b.x);} +}; +struct Ray { Vec o, d; Ray(Vec o_, Vec d_) : o(o_), d(d_) {} }; +enum Refl_t { DIFF, SPEC, REFR }; // material types, used in radiance() +struct Sphere { + double rad; // radius + Vec p, e, c; // position, emission, color + Refl_t refl; // reflection type (DIFFuse, SPECular, REFRactive) + Sphere(double rad_, Vec p_, Vec e_, Vec c_, Refl_t refl_): + rad(rad_), p(p_), e(e_), c(c_), refl(refl_) {} + double intersect(const Ray &r) const { // returns distance, 0 if nohit + Vec op = p-r.o; // Solve t^2*d.d + 2*t*(o-p).d + (o-p).(o-p)-R^2 = 0 + double t, eps=1e-4, b=op.dot(r.d), det=b*b-op.dot(op)+rad*rad; + if (det<0) return 0; else det=sqrt(det); + return (t=b-det)>eps ? t : ((t=b+det)>eps ? t : 0); + } +}; +Sphere spheres[] = {//Scene: radius, position, emission, color, material + Sphere(1e5, Vec( 1e5+1,40.8,81.6), Vec(),Vec(.75,.25,.25),DIFF),//Left + Sphere(1e5, Vec(-1e5+99,40.8,81.6),Vec(),Vec(.25,.25,.75),DIFF),//Rght + Sphere(1e5, Vec(50,40.8, 1e5), Vec(),Vec(.75,.75,.75),DIFF),//Back + Sphere(1e5, Vec(50,40.8,-1e5+170), Vec(),Vec(), DIFF),//Frnt + Sphere(1e5, Vec(50, 1e5, 81.6), Vec(),Vec(.75,.75,.75),DIFF),//Botm + Sphere(1e5, Vec(50,-1e5+81.6,81.6),Vec(),Vec(.75,.75,.75),DIFF),//Top + Sphere(16.5,Vec(27,16.5,47), Vec(),Vec(1,1,1)*.6, SPEC),//Mirr + Sphere(16.5,Vec(73,16.5,78), Vec(),Vec(.75,1.,.95), REFR),//Glas + Sphere(4.0, Vec(50,81.6-16.5,81.6),Vec(4,4,4)*12, Vec(), DIFF),//Lite +}; +int numSpheres = sizeof(spheres)/sizeof(Sphere); +inline double clamp(double x){ return x<0 ? 0 : x>1 ? 1 : x; } +inline int toInt(double x){ return int(pow(clamp(x),1/2.2)*255+.5); } +inline bool intersect(const Ray &r, double &t, int &id){ + double n=sizeof(spheres)/sizeof(Sphere), d, inf=t=1e20; + for(int i=int(n);i--;) if((d=spheres[i].intersect(r))&&df.y && f.x>f.z ? f.x : f.y>f.z ? f.y : f.z; // max refl + if (++depth>5||!p) if (erand48(Xi).1?Vec(0,1):Vec(1))%w).norm(), v=w%u; + Vec d = (u*cos(r1)*r2s + v*sin(r1)*r2s + w*sqrt(1-r2)).norm(); + + // Loop over any lights + Vec e; + for (int i=0; i.1?Vec(0,1):Vec(1))%sw).norm(), sv=sw%su; + double cos_a_max = sqrt(1-s.rad*s.rad/(x-s.p).dot(x-s.p)); + double eps1 = erand48(Xi), eps2 = erand48(Xi); + double cos_a = 1-eps1+eps1*cos_a_max; + double sin_a = sqrt(1-cos_a*cos_a); + double phi = 2*M_PI*eps2; + Vec l = su*cos(phi)*sin_a + sv*sin(phi)*sin_a + sw*cos_a; + l.norm(); + if (intersect(Ray(x,l), t, id) && id==i){ // shadow ray + double omega = 2*M_PI*(1-cos_a_max); + e = e + f.mult(s.e*l.dot(nl)*omega)*M_1_PI; // 1/pi for brdf + } + } + + return obj.e*E+e+f.mult(radiance(Ray(x,d),depth,Xi,0)); + } else if (obj.refl == SPEC) // Ideal SPECULAR reflection + return obj.e + f.mult(radiance(Ray(x,r.d-n*2*n.dot(r.d)),depth,Xi)); + Ray reflRay(x, r.d-n*2*n.dot(r.d)); // Ideal dielectric REFRACTION + bool into = n.dot(nl)>0; // Ray from outside going in? + double nc=1, nt=1.5, nnt=into?nc/nt:nt/nc, ddn=r.d.dot(nl), cos2t; + if ((cos2t=1-nnt*nnt*(1-ddn*ddn))<0) // Total internal reflection + return obj.e + f.mult(radiance(reflRay,depth,Xi)); + Vec tdir = (r.d*nnt - n*((into?1:-1)*(ddn*nnt+sqrt(cos2t)))).norm(); + double a=nt-nc, b=nt+nc, R0=a*a/(b*b), c = 1-(into?-ddn:tdir.dot(n)); + double Re=R0+(1-R0)*c*c*c*c*c,Tr=1-Re,P=.25+.5*Re,RP=Re/P,TP=Tr/(1-P); + return obj.e + f.mult(depth>2 ? (erand48(Xi)

      = 2) samps = atoi(argv[1])/4; + if (argc >= 3) w = h = atoi(argv[2]); + double tbeg = get_time(); + Ray cam(Vec(50,52,295.6), Vec(0,-0.042612,-1).norm()); // cam pos, dir + Vec cx=Vec(w*.5135/h), cy=(cx%cam.d).norm()*.5135, r, *c=new Vec[w*h]; +#pragma omp parallel for schedule(dynamic, 1) private(r) // OpenMP + for (int y=0; y // smallpt, a Path Tracer by Kevin Beason, 2008 +#include // Make : g++ -O3 -fopenmp smallpt.cpp -o smallpt +#include // Remove "-fopenmp" for g++ version < 4.2 +#include +double get_time() { + struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); + return ts.tv_sec * 1000.0 + ts.tv_nsec / 1000000.0; +} +struct Vec { // Usage: time ./smallpt 5000 && xv image.ppm + double x, y, z; // position, also color (r,g,b) + Vec(double x_=0, double y_=0, double z_=0){ x=x_; y=y_; z=z_; } + Vec operator+(const Vec &b) const { return Vec(x+b.x,y+b.y,z+b.z); } + Vec operator-(const Vec &b) const { return Vec(x-b.x,y-b.y,z-b.z); } + Vec operator*(double b) const { return Vec(x*b,y*b,z*b); } + Vec mult(const Vec &b) const { return Vec(x*b.x,y*b.y,z*b.z); } + Vec& norm(){ return *this = *this * (1/sqrt(x*x+y*y+z*z)); } + double dot(const Vec &b) const { return x*b.x+y*b.y+z*b.z; } // cross: + Vec operator%(Vec&b){return Vec(y*b.z-z*b.y,z*b.x-x*b.z,x*b.y-y*b.x);} +}; +struct Ray { Vec o, d; Ray(Vec o_, Vec d_) : o(o_), d(d_) {} }; +enum Refl_t { DIFF, SPEC, REFR }; // material types, used in radiance() +struct Sphere { + double rad; // radius + Vec p, e, c; // position, emission, color + Refl_t refl; // reflection type (DIFFuse, SPECular, REFRactive) + Sphere(double rad_, Vec p_, Vec e_, Vec c_, Refl_t refl_): + rad(rad_), p(p_), e(e_), c(c_), refl(refl_) {} + double intersect(const Ray &r) const { // returns distance, 0 if nohit + Vec op = p-r.o; // Solve t^2*d.d + 2*t*(o-p).d + (o-p).(o-p)-R^2 = 0 + double t, eps=1e-4, b=op.dot(r.d), det=b*b-op.dot(op)+rad*rad; + if (det<0) return 0; else det=sqrt(det); + return (t=b-det)>eps ? t : ((t=b+det)>eps ? t : 0); + } +}; +Sphere spheres[] = {//Scene: radius, position, emission, color, material + Sphere(1e5, Vec( 1e5+1,40.8,81.6), Vec(),Vec(.75,.25,.25),DIFF),//Left + Sphere(1e5, Vec(-1e5+99,40.8,81.6),Vec(),Vec(.25,.25,.75),DIFF),//Rght + Sphere(1e5, Vec(50,40.8, 1e5), Vec(),Vec(.75,.75,.75),DIFF),//Back + Sphere(1e5, Vec(50,40.8,-1e5+170), Vec(),Vec(), DIFF),//Frnt + Sphere(1e5, Vec(50, 1e5, 81.6), Vec(),Vec(.75,.75,.75),DIFF),//Botm + Sphere(1e5, Vec(50,-1e5+81.6,81.6),Vec(),Vec(.75,.75,.75),DIFF),//Top + Sphere(16.5,Vec(27,16.5,47), Vec(),Vec(1,1,1)*.6, SPEC),//Mirr + Sphere(16.5,Vec(73,16.5,78), Vec(),Vec(.75,1.,.95), REFR),//Glas + Sphere(4.0, Vec(50,81.6-16.5,81.6),Vec(4,4,4)*12, Vec(), DIFF),//Lite +}; +inline double clamp(double x){ return x<0 ? 0 : x>1 ? 1 : x; } +inline int toInt(double x){ return int(pow(clamp(x),1/2.2)*255+.5); } +inline bool intersect(const Ray &r, double &t, int &id){ + double n=sizeof(spheres)/sizeof(Sphere), d, inf=t=1e20; + for(int i=int(n);i--;) if((d=spheres[i].intersect(r))&&df.y && f.x>f.z ? f.x : f.y>f.z ? f.y : f.z; // max refl + if (++depth>5) if (erand48(Xi).1?Vec(0,1):Vec(1))%w).norm(), v=w%u; + Vec d = (u*cos(r1)*r2s + v*sin(r1)*r2s + w*sqrt(1-r2)).norm(); + return obj.e + f.mult(radiance(Ray(x,d),depth,Xi)); + } else if (obj.refl == SPEC) // Ideal SPECULAR reflection + return obj.e + f.mult(radiance(Ray(x,r.d-n*2*n.dot(r.d)),depth,Xi)); + Ray reflRay(x, r.d-n*2*n.dot(r.d)); // Ideal dielectric REFRACTION + bool into = n.dot(nl)>0; // Ray from outside going in? + double nc=1, nt=1.5, nnt=into?nc/nt:nt/nc, ddn=r.d.dot(nl), cos2t; + if ((cos2t=1-nnt*nnt*(1-ddn*ddn))<0) // Total internal reflection + return obj.e + f.mult(radiance(reflRay,depth,Xi)); + Vec tdir = (r.d*nnt - n*((into?1:-1)*(ddn*nnt+sqrt(cos2t)))).norm(); + double a=nt-nc, b=nt+nc, R0=a*a/(b*b), c = 1-(into?-ddn:tdir.dot(n)); + double Re=R0+(1-R0)*c*c*c*c*c,Tr=1-Re,P=.25+.5*Re,RP=Re/P,TP=Tr/(1-P); + return obj.e + f.mult(depth>2 ? (erand48(Xi)

      = 2) samps = atoi(argv[1])/4; + if (argc >= 3) w = h = atoi(argv[2]); + double tbeg = get_time(); + Ray cam(Vec(50,52,295.6), Vec(0,-0.042612,-1).norm()); // cam pos, dir + Vec cx=Vec(w*.5135/h), cy=(cx%cam.d).norm()*.5135, r, *c=new Vec[w*h]; +#pragma omp parallel for schedule(dynamic, 1) private(r) // OpenMP + for (int y=0; y +# include +# include +# include +# include +# include + +/*----------------------------------------------------------------------- + * INSTRUCTIONS: + * + * 1) STREAM requires different amounts of memory to run on different + * systems, depending on both the system cache size(s) and the + * granularity of the system timer. + * You should adjust the value of 'STREAM_ARRAY_SIZE' (below) + * to meet *both* of the following criteria: + * (a) Each array must be at least 4 times the size of the + * available cache memory. I don't worry about the difference + * between 10^6 and 2^20, so in practice the minimum array size + * is about 3.8 times the cache size. + * Example 1: One Xeon E3 with 8 MB L3 cache + * STREAM_ARRAY_SIZE should be >= 4 million, giving + * an array size of 30.5 MB and a total memory requirement + * of 91.5 MB. + * Example 2: Two Xeon E5's with 20 MB L3 cache each (using OpenMP) + * STREAM_ARRAY_SIZE should be >= 20 million, giving + * an array size of 153 MB and a total memory requirement + * of 458 MB. + * (b) The size should be large enough so that the 'timing calibration' + * output by the program is at least 20 clock-ticks. + * Example: most versions of Windows have a 10 millisecond timer + * granularity. 20 "ticks" at 10 ms/tic is 200 milliseconds. + * If the chip is capable of 10 GB/s, it moves 2 GB in 200 msec. + * This means the each array must be at least 1 GB, or 128M elements. + * + * Version 5.10 increases the default array size from 2 million + * elements to 10 million elements in response to the increasing + * size of L3 caches. The new default size is large enough for caches + * up to 20 MB. + * Version 5.10 changes the loop index variables from "register int" + * to "ssize_t", which allows array indices >2^32 (4 billion) + * on properly configured 64-bit systems. Additional compiler options + * (such as "-mcmodel=medium") may be required for large memory runs. + * + * Array size can be set at compile time without modifying the source + * code for the (many) compilers that support preprocessor definitions + * on the compile line. E.g., + * gcc -O -DSTREAM_ARRAY_SIZE=100000000 stream.c -o stream.100M + * will override the default size of 10M with a new size of 100M elements + * per array. + */ +#ifndef STREAM_ARRAY_SIZE +# define STREAM_ARRAY_SIZE 10000000 +#endif + +/* 2) STREAM runs each kernel "NTIMES" times and reports the *best* result + * for any iteration after the first, therefore the minimum value + * for NTIMES is 2. + * There are no rules on maximum allowable values for NTIMES, but + * values larger than the default are unlikely to noticeably + * increase the reported performance. + * NTIMES can also be set on the compile line without changing the source + * code using, for example, "-DNTIMES=7". + */ +#ifdef NTIMES +#if NTIMES<=1 +# define NTIMES 10 +#endif +#endif +#ifndef NTIMES +# define NTIMES 10 +#endif + +/* Users are allowed to modify the "OFFSET" variable, which *may* change the + * relative alignment of the arrays (though compilers may change the + * effective offset by making the arrays non-contiguous on some systems). + * Use of non-zero values for OFFSET can be especially helpful if the + * STREAM_ARRAY_SIZE is set to a value close to a large power of 2. + * OFFSET can also be set on the compile line without changing the source + * code using, for example, "-DOFFSET=56". + */ +#ifndef OFFSET +# define OFFSET 0 +#endif + +/* + * 3) Compile the code with optimization. Many compilers generate + * unreasonably bad code before the optimizer tightens things up. + * If the results are unreasonably good, on the other hand, the + * optimizer might be too smart for me! + * + * For a simple single-core version, try compiling with: + * cc -O stream.c -o stream + * This is known to work on many, many systems.... + * + * To use multiple cores, you need to tell the compiler to obey the OpenMP + * directives in the code. This varies by compiler, but a common example is + * gcc -O -fopenmp stream.c -o stream_omp + * The environment variable OMP_NUM_THREADS allows runtime control of the + * number of threads/cores used when the resulting "stream_omp" program + * is executed. + * + * To run with single-precision variables and arithmetic, simply add + * -DSTREAM_TYPE=float + * to the compile line. + * Note that this changes the minimum array sizes required --- see (1) above. + * + * The preprocessor directive "TUNED" does not do much -- it simply causes the + * code to call separate functions to execute each kernel. Trivial versions + * of these functions are provided, but they are *not* tuned -- they just + * provide predefined interfaces to be replaced with tuned code. + * + * + * 4) Optional: Mail the results to mccalpin@cs.virginia.edu + * Be sure to include info that will help me understand: + * a) the computer hardware configuration (e.g., processor model, memory type) + * b) the compiler name/version and compilation flags + * c) any run-time information (such as OMP_NUM_THREADS) + * d) all of the output from the test case. + * + * Thanks! + * + *-----------------------------------------------------------------------*/ + +# define HLINE "-------------------------------------------------------------\n" + +# ifndef MIN +# define MIN(x,y) ((x)<(y)?(x):(y)) +# endif +# ifndef MAX +# define MAX(x,y) ((x)>(y)?(x):(y)) +# endif + +#ifndef STREAM_TYPE +#define STREAM_TYPE double +#endif + +static STREAM_TYPE a[STREAM_ARRAY_SIZE+OFFSET], + b[STREAM_ARRAY_SIZE+OFFSET], + c[STREAM_ARRAY_SIZE+OFFSET]; + +static double avgtime[4] = {0}, maxtime[4] = {0}, + mintime[4] = {FLT_MAX,FLT_MAX,FLT_MAX,FLT_MAX}; + +static char *label[4] = {"Copy: ", "Scale: ", + "Add: ", "Triad: "}; + +static double bytes[4] = { + 2 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE, + 2 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE, + 3 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE, + 3 * sizeof(STREAM_TYPE) * STREAM_ARRAY_SIZE + }; + +extern double mysecond(); +extern void checkSTREAMresults(); +#ifdef TUNED +extern void tuned_STREAM_Copy(); +extern void tuned_STREAM_Scale(STREAM_TYPE scalar); +extern void tuned_STREAM_Add(); +extern void tuned_STREAM_Triad(STREAM_TYPE scalar); +#endif +#ifdef _OPENMP +extern int omp_get_num_threads(); +#endif +int +main() + { + int quantum, checktick(); + int BytesPerWord; + int k; + ssize_t j; + STREAM_TYPE scalar; + double t, times[4][NTIMES]; + + /* --- SETUP --- determine precision and check timing --- */ + + printf(HLINE); + printf("STREAM version $Revision: 5.10 $\n"); + printf(HLINE); + BytesPerWord = sizeof(STREAM_TYPE); + printf("This system uses %d bytes per array element.\n", + BytesPerWord); + + printf(HLINE); +#ifdef N + printf("***** WARNING: ******\n"); + printf(" It appears that you set the preprocessor variable N when compiling this code.\n"); + printf(" This version of the code uses the preprocessor variable STREAM_ARRAY_SIZE to control the array size\n"); + printf(" Reverting to default value of STREAM_ARRAY_SIZE=%llu\n",(unsigned long long) STREAM_ARRAY_SIZE); + printf("***** WARNING: ******\n"); +#endif + + printf("Array size = %llu (elements), Offset = %d (elements)\n" , (unsigned long long) STREAM_ARRAY_SIZE, OFFSET); + printf("Memory per array = %.1f MiB (= %.1f GiB).\n", + BytesPerWord * ( (double) STREAM_ARRAY_SIZE / 1024.0/1024.0), + BytesPerWord * ( (double) STREAM_ARRAY_SIZE / 1024.0/1024.0/1024.0)); + printf("Total memory required = %.1f MiB (= %.1f GiB).\n", + (3.0 * BytesPerWord) * ( (double) STREAM_ARRAY_SIZE / 1024.0/1024.), + (3.0 * BytesPerWord) * ( (double) STREAM_ARRAY_SIZE / 1024.0/1024./1024.)); + printf("Each kernel will be executed %d times.\n", NTIMES); + printf(" The *best* time for each kernel (excluding the first iteration)\n"); + printf(" will be used to compute the reported bandwidth.\n"); + +#ifdef _OPENMP + printf(HLINE); +#pragma omp parallel + { +#pragma omp master + { + k = omp_get_num_threads(); + printf ("Number of Threads requested = %i\n",k); + } + } +#endif + +#ifdef _OPENMP + k = 0; +#pragma omp parallel +#pragma omp atomic + k++; + printf ("Number of Threads counted = %i\n",k); +#endif + + /* Get initial value for system clock. */ +#pragma omp parallel for + for (j=0; j= 1) + printf("Your clock granularity/precision appears to be " + "%d microseconds.\n", quantum); + else { + printf("Your clock granularity appears to be " + "less than one microsecond.\n"); + quantum = 1; + } + + t = mysecond(); +#pragma omp parallel for + for (j = 0; j < STREAM_ARRAY_SIZE; j++) + a[j] = 2.0E0 * a[j]; + t = 1.0E6 * (mysecond() - t); + + printf("Each test below will take on the order" + " of %d microseconds.\n", (int) t ); + printf(" (= %d clock ticks)\n", (int) (t/quantum) ); + printf("Increase the size of the arrays if this shows that\n"); + printf("you are not getting at least 20 clock ticks per test.\n"); + + printf(HLINE); + + printf("WARNING -- The above is only a rough guideline.\n"); + printf("For best results, please be sure you know the\n"); + printf("precision of your system timer.\n"); + printf(HLINE); + + /* --- MAIN LOOP --- repeat test cases NTIMES times --- */ + + scalar = 3.0; + for (k=0; k + +double mysecond() +{ + struct timeval tp; + struct timezone tzp; + int i; + + i = gettimeofday(&tp,&tzp); + return ( (double) tp.tv_sec + (double) tp.tv_usec * 1.e-6 ); +} + +#ifndef abs +#define abs(a) ((a) >= 0 ? (a) : -(a)) +#endif +void checkSTREAMresults () +{ + STREAM_TYPE aj,bj,cj,scalar; + STREAM_TYPE aSumErr,bSumErr,cSumErr; + STREAM_TYPE aAvgErr,bAvgErr,cAvgErr; + double epsilon; + ssize_t j; + int k,ierr,err; + + /* reproduce initialization */ + aj = 1.0; + bj = 2.0; + cj = 0.0; + /* a[] is modified during timing check */ + aj = 2.0E0 * aj; + /* now execute timing loop */ + scalar = 3.0; + for (k=0; k epsilon) { + err++; + printf ("Failed Validation on array a[], AvgRelAbsErr > epsilon (%e)\n",epsilon); + printf (" Expected Value: %e, AvgAbsErr: %e, AvgRelAbsErr: %e\n",aj,aAvgErr,abs(aAvgErr)/aj); + ierr = 0; + for (j=0; j epsilon) { + ierr++; +#ifdef VERBOSE + if (ierr < 10) { + printf(" array a: index: %ld, expected: %e, observed: %e, relative error: %e\n", + j,aj,a[j],abs((aj-a[j])/aAvgErr)); + } +#endif + } + } + printf(" For array a[], %d errors were found.\n",ierr); + } + if (abs(bAvgErr/bj) > epsilon) { + err++; + printf ("Failed Validation on array b[], AvgRelAbsErr > epsilon (%e)\n",epsilon); + printf (" Expected Value: %e, AvgAbsErr: %e, AvgRelAbsErr: %e\n",bj,bAvgErr,abs(bAvgErr)/bj); + printf (" AvgRelAbsErr > Epsilon (%e)\n",epsilon); + ierr = 0; + for (j=0; j epsilon) { + ierr++; +#ifdef VERBOSE + if (ierr < 10) { + printf(" array b: index: %ld, expected: %e, observed: %e, relative error: %e\n", + j,bj,b[j],abs((bj-b[j])/bAvgErr)); + } +#endif + } + } + printf(" For array b[], %d errors were found.\n",ierr); + } + if (abs(cAvgErr/cj) > epsilon) { + err++; + printf ("Failed Validation on array c[], AvgRelAbsErr > epsilon (%e)\n",epsilon); + printf (" Expected Value: %e, AvgAbsErr: %e, AvgRelAbsErr: %e\n",cj,cAvgErr,abs(cAvgErr)/cj); + printf (" AvgRelAbsErr > Epsilon (%e)\n",epsilon); + ierr = 0; + for (j=0; j epsilon) { + ierr++; +#ifdef VERBOSE + if (ierr < 10) { + printf(" array c: index: %ld, expected: %e, observed: %e, relative error: %e\n", + j,cj,c[j],abs((cj-c[j])/cAvgErr)); + } +#endif + } + } + printf(" For array c[], %d errors were found.\n",ierr); + } + if (err == 0) { + printf ("Solution Validates: avg error less than %e on all three arrays\n",epsilon); + } +#ifdef VERBOSE + printf ("Results Validation Verbose Results: \n"); + printf (" Expected a(1), b(1), c(1): %f %f %f \n",aj,bj,cj); + printf (" Observed a(1), b(1), c(1): %f %f %f \n",a[1],b[1],c[1]); + printf (" Rel Errors on a, b, c: %e %e %e \n",abs(aAvgErr/aj),abs(bAvgErr/bj),abs(cAvgErr/cj)); +#endif +} + +#ifdef TUNED +/* stubs for "tuned" versions of the kernels */ +void tuned_STREAM_Copy() +{ + ssize_t j; +#pragma omp parallel for + for (j=0; j

      + +To run WasmBoy, you need a Gameboy ROM file. For example, you can download [`tobudx.gb` (Tobu Tobu Girl ROM)](https://tangramgames.itch.io/tobu-tobu-girl-deluxe/purchase?popup=1) + +`wasm3.wasm` is a normal WASI build of Wasm3. + +### Run with Webassembly.sh + +Drag'n'drop `wasm3.wasm`, `wasmerboy.wasm`, `tobudx.gb` to [Webassembly.sh](https://webassembly.sh) and run: + +```sh +wasm3 /tmp/wasmerboy.wasm /tmp/tobudx.gb +``` + +To speed it up (at your own risk, this disables security features): +```sh +chromium-browser --no-sandbox --js-flags="--wasm-opt --wasm-no-bounds-checks --wasm-no-stack-checks" "https://webassembly.sh" +``` + +### Run with Wasmer + +```sh +mkdir fs +cp wasmerboy.wasm tobudx.gb ./fs +wasmer run --dir=fs --enable-experimental-io-devices wasm3.wasm -- fs/wasmerboy.wasm fs/tobudx.gb +``` + +### Also + +Check out [Aaron Turner's article on Wasmer and WasmBoy](https://medium.com/wasmer/wasmer-io-devices-announcement-6f2a6fe23081). diff --git a/ext/wasm3/test/wasi/wasmboy/image.png b/ext/wasm3/test/wasi/wasmboy/image.png new file mode 100644 index 0000000000000000000000000000000000000000..2f579a686907d6a035294ded11e5e170c08cf352 GIT binary patch literal 51171 zcmX`T1y~$S(>6NzLU0Lg!QFzp26qjb5Zv7zLU4C?clSU71PJc#Zoz|}$@72j;TkS> zo8F%4>e9PvHcVOZ0}2uW5&!@wGSU*N007GY0MMTx(BR1Q4{Lhx52C%ajuQZ2I{*8H zS~Dee2LLiaMnY8GJ@X{X!y8+2X)vceJ3B4=3-u5z<}cXzSlGTefPMpdYbc+Yq?C*- zyY;dBxVmM_bA8aWvbw#Z`p$a>QAqvrxMzN{h2wBTTW zq4jZezS&s~rFr?{$NBLq^|*mzQxSAn(f=-d^#db9e=){0dM8B|4nEAi}$%^nAh&g!43#yM*t=PQ;INdEU{nyX`%l&=a*ezYGPRBpKwo; z!S3%QX0>@C_t23rsmPQ=QXlw#BBm8zlLv~5`264f$)rii1*^?46Yn2iuPWD1D=ZSb zpiqebe}^&N(g#YaA$#ZS!cEAw>Hm+W zpR&#-s;ly{1QK4dstS^V{!sqVoB7hwIp%4xCR}pxP&_F?yGb^>a!Wh_4s1}b2%Icj zFRA|?SFJAEWf;hABHzTb3j3BOoJit=Bv_L+^FiAP%H7>B79qZVM$2cP2mj2>kPoeL zYpZCiPAt54&@;H3wLBus)Zi>&m!e!k&0{$}i;B6JLG3J9!-T+E5$ZA7x{=Xh0V>!w z7Y;u{iy(=&b{~8S%A3b#7X)mbxfCyA$bRK1VVm?p$sSu2gleCLF;(w1H=ZG-pYYqX zsjz<)2_UKA#!HlByT&=SwSob3z4iQVmNzW(6X!Yz(3I2uWUHckEvL(p-rgF2=*ll@ zYH~IVF-KSXx-d$ekWWieGroPJD%Kheb6z@*2iyAvyN%BTC6Mfw(e$%gJneAdC>jnk zWY~x`?c~Q-&pS<4>Ks-&i!Hom;qJFfPXLf9ZXsw*UoxWDr1*Zw%ZisgQJE}JRZJHe zJvMF9-!Kq7u+>iyF$jR0RYtLVy6#HzUw1cM-G*hspV@_P+n1M+;e#|wXguBDuPyCe z+&@QuDjPdW7hyHW?q5J5`I~X_@qG@cL%__~nLh=vJL znv3N?9EMJ>k|-lWtsrzmnEaE9`X>z+huv~8S`>-;&(%>-%UhvM(pPOak zR>%4`)dNPX=I;qYOORz`<-e`E0}C3e!@T1o_(e&u(7jb1w}nN;$a47kHH)){06<Zhkr#!-^g( z>wYDJIFgx*NhZ;%bcdM0c|&agu>MGW%7d&*8f`k546=QyL7@a&08SJc$GbEXMiDV4 ztbF@?)4lsDaVGP#I!TA#J}Dzb6jZT!A>M9YkL>vt2gG6gWI!_7S^_9)fILYHWaYx zT`Fqp%9@*rlnskt!u#Em$ZrcT!)1LSnH6Pe=+cU^k$B71zu|!a_rvb+nLP0+RWdt849K|%^_>{jL6lQ!#au{VP!qd>{KH;;`B;`R6&FD>iBy12r3G}DAlEv zt+kGt&k{?uc|*6|QI<7$69b^=wTmUuPUfJ+#r`1!$YfQ+DMHZmt12L$bn-owAW&j} ze{klX14dBo!|*}9?y3McKA=-*>Qw*$RG4-{~bcUO2V6Yz_IZ#NNjCQ2gh}Go)U1O%K1gqV(jJT+zEKbYeEgd?t`uq&r zfM*i*85-;sW3uhL70;7zPG@(I(=O#fPG^>!JQZ*#WAr{Ycd8C<*kR5H zRy0<-c3`k<4HGbT?ZC3W__wQ3YS7>k0xLEo4MUV)#S1@vT(+Kb$5gE4!jH=Do!GmO zYAmy%(cXpbb*gG9r0B-8-Ku9%bw#>3Y;zP$)urL;4!vY zyLC7?ExiqgvLON;G`0Z2>P*ZQ2OHvw>0V}wAC0F;dr#VnuYfh1GI$W6zD_ znMHEG=K`-o!nmZ{eep!qXN4+JR=~dx8!*3e?-J^n-)C8=ldIT3gAJ-@BtXu*s*F3V zF5YX0*HZ8i_s;BRW7N25j2y@D03nW22@0l=@;`n$DYV+Y zL9SaqKGIhhWxD+dtEHA;gr2{bWo0@)$NlqA@dIb1t9$$hb+vcqmJTV&=UOdPLzPOl zP=Lz&zc9UH&qtt|isnAN#~HxeUokphm4y$20>0=>E}hJly2^cN@&(z1PKo5{Fy#dA zoryn{uy9LXE{L@$GMD67fp04S*S!Rf69o`WC2SNrR4$HY*}}~G%&PV!P@10T6Oe=6 z$PO2D(E42?t4mUJbps(JS~LrloHr;@3ZwOv+EsaCvWP{X9>@_defpH}O;>lI&6S&x zfgOOT1OA>`1uEDaQiV-gn%Xk=FYsE%M-$3tt%7X5*{K^h_gNaV9e2r5gjqK11ibq) zh|Ptt86UgN>=qX$7pV*4l;h1Cijl+KQ#;RYW+u>1d$@d~hMxEw-HUk7FMWcVn3)oWy6FPa@cDhp+MbAW;%tVMeu z7&jR)E$;_`S(%Ob^&^awG455y%|hH+p*n;-SXC#PU!oW;h)5)N)8SyZwAoGcomDxL zTWyI}6a^&k`s-M){!)re3jQBhqZ#yU^F5cUQv?K@%NtiAs)*meHWQ)kA@I8j{ZQ{@ z<3pf>r?;TCRSb*tDDR~GNvVvO(8Hg=Lbiv41x7wV!?dEsyqrI60968F0pBYJb$6~{}! z;Q6N^#_n7zPtAA@2X!AMrfy18ESV~37pKqNW)D_TX zEp2UsF~n48i(wz3?n)w3vibIe8Vhl=q$u)mRb;>|o0Y}Q?H47+e~xi=f~|!~{^vaP zIW>$BQ`~+ry-OAG?QrCidf%HntRYBdU2(BUKHPv=%l`K={i2UJ75Jn@U>N&TwzFT1 z&gRBlitnpcNU;AX!MUYnbWFoR$*2Nha(zW%Wvlc0#15s(`(H?)79!5MN6e6vG}hEx zwlZcYP`k()g3_8PS?IBvSt16pkg=6=s>|tNz?*k71nR?I-d-3#@~{b5c~jhiicmM zH}k(RF~d=}U}>oy%getqh$c+#+}tx*S#5(ZCPJs8m^i~I0vEPdM~y+ov|+I{Ipx%i ztEn-PB*`MKFqe_P!U}V1TaxVySDr-poVqzH-{KqvbwX-(a(hp`<^0-I-jEC^{thI_ z@c7$DJ5YkI*j3QTa>U@~t(9~?R?Je4-?TpS>EJ`XCje!$4&~+@32ZK(wk+=RmrnRP)T0_(J)Oq}3W=evFhFVKa zy{t;AC_3X?Iy!PuzeGX0y!!UJF>A#7zBL^@ zRV*?vN(_IeCR!`4syHWIKuaGk2GCnsnn=Ed4U&wnZ;%Sl{}mu-I-PnFd9?KKtTB5! zuwd=u^`r=Z>Rl+ItD%r(>FxOW^HObMX%&XpS4t|)`B^k2nK>i{DV6tlu=MBvOcA!U zNt0!>QCwl>ZwzXcleNe-gKlu9EVWwJh=#rzX`%_V(R+e~1WZq&0A@jIAb#k*sk*6# z&8m1+nMj-3St^>W>wdgV^AL&zQ#vxzU3s)UQHvT!}^MluzkUc z1lm<{1uYq9jNNv_u!n*lC$xf1TodZ^bMrIvN_ZR}(cAS7(7`Z?SK?dzmnoTi=akZH z&fpxjG@r&WEv`4Y5g6NE1V0q>j| zC$Pj7ikFB8{6cc$ijU``tqG+@%VT6^8~M!Yud^d#nrywx6=rPvAC2O&o&ssM2$H3Psw3tP z1nX0IDop9bI;&H_VhMtYXsj(6u^A!FLtB$`?g$JxabEteo^ncKs@vS%Ss`CvYe~Ed zaxlVHiwn{-IiVi_@wb&psC`eqsT16xYk>id-s7NGFp>wmIVMTWQs#Z!{9p*{-+iFIX*XEg5x%KHkkdea5~Tc6Y0c ze;)}Y3vN_8skU`X4U35V(@#~X^dI8##COPu*&a_dv8XX6lTd1LQ63r`QgKLdQf&w( zd^_CIA9SY9xK#Ws#X?|2v~zO*rPlX2m=TPJncA4-a@XmwJZ8id4yW2vYdm}ZK{)ge z=!Vd+t$SQh8VQYFDl-er(UW>00X=-5lc+Z1T@j>%D}sZOZqg|!rA26ruP;q=$5H;B z%gRJ14G{!DCxZp4Z(_t2gU}fLf!i_Qw82J^Qo)9`WW|#RVnv^$fM5pnr4l6u)xTp1 zA1B4Lc8V3xf|yK+qic19N>qsR?C1SqBF>W~N0Ujs?{KGOAOTkwRc~$X&VM_I^TMKd)s z!x86rWDosyqRFIL%x~Ovmpg-O;2eKVIuYTL3l7CcM}u%qu;rmf*k1bi1OdP*>EN}5 zIC1p2V-n>yqmP|)q_SkS>Raj7VK3Ai`R{J{;>Nt+sy;Xz;@ zi#YQ=^~BvuPRpPz0VQ|U9^XSGeA@Q#?eJfo^Hhn>u~bLu`sLJ<9kKwAF*3k&UMh2q zc##PMrGxm==sV4lfrK`E_}?CBnV71qxUDtu_zzpt;Cq3{<7djv-*>S>Dm7w>s^3fm zu?XQE$baR@269%f&8|2Zh_;|ZXF}2BNp?|Orf4K#9tFVU*&B6{BgFhdgNL#?Tpg>I zSglB*isZ94u`#j7(o`|8h zT_4d?sO5On7{DDza%g-Fw!~n1LzRd$4wd?@WA!Y^ed-^R^W?xEfK-a)WSBW$OHIZ?eIYh%#pdu0N)s18)tMOXtx6V2qavHYbXd+BtF?8t|{3 z4hAMon%xqqHossE@FEPf9;uUm)ajTm)L%y4()o{>c#&)ac<9iKJMUFEWM_2ItI=iY z$TL-xvuFhAuwXzF!CQzS8APTmdDyRB1q*?Zdbi!|i9j9ojo7QJ~7v|E!jWpu=}6b;lnlsF2YrqS`oLIk<#xTc*4vc9OfUm%yPy z#xs^r(aV=h+$RF?>_g}f80FnV^=P8&g8pd$8(H zhUqyA29FkYn^3{%@!4G7!x&f}c&6gxF`;tn>MVL19G?f6 zaFR6i_02scR8spAWAQd6T1wxcnWUkQ1+XCnV;~`iAOt=keY?qyx=Uy&G+r+shdn1m z!{IX!&gYk3va&p+;@g)AW>leQ75gmVl2j_ZwB62E9XKWD6o4Lp2~#9S%Yw|2uW;8qu3S`1!em`F z2lTlO-G=Vpz}YC=rGAoEVL_KiG-SsESLZPf_q6zQLnfWGgVs7sCa)d?r z0W?Dih=76by-Ca<7+|(L;|7u;KtX?pR~NA-gPm4@52$urhsyN|4dWBe5Q=6XYAy=H zcG>N>$HPUFOH}SdJSfK3eB6~kj2aJi5-Sr46A>lLgi#Sg;n)yC#DJBh+axM&w`YYz z4W`SinC|>1$Os@zH&Xp_RTy|tr!KTxxE)$jDDda6T6q4?H8{1N#bvWM)QMQR>g3_+ z24VqF`fr4OT-<#Dqtt1=PAWBQcN!O~2no&CIBedDz%6 zsr(3rf{>H?Tu*)=^(nNy54n|0Cc;#uSGO@&XRd|$#!}@q3BD_=rJA3E*0$8$i zz!x*Kp4XR0TzzK@^D#m|6kS3^9cJbsRT~r8v$Iz*#6XF)o)z!flTRZuck7tu%;PCx zO1s_0!s2k{+-U3L^Etw~hnran7fz4c`1820mXq>>*hBdI@u|jrfC#GW$(ykF8GmF( z!LN>ouI3(;fxFNAY~z-t)9BH!h$k{a6=<*nDT` zbC%a(JE=t|#JC$YpDnySvwoKsA?h(I;5m#?BS?CY?sX}HuowwRba7i!K>o5n$vUN z44F6dd&W1*bU1CAPfkw86vLK0)X@8A_Hj!;P4Q|ad)Rot1Wo@8@(G@>;f&6+2d zFPsN19hQW;o@NBWN)%^Pw0N?Vgl?Q)f}gI&b!TE$*~ZWm zwO>S!Az>laYe)*o09qNgM$I4ldVaJ~Dr5nHFncd_E$QUoCpyN?;ADF1&zb3RICb!{ z{{DTfm9$4VNMhqvv{dBB8l)Y!co7vcSHZ*Rmp9kpOp?nbN`jVOJUth?pDl;t5|98g zeg+CUw#nIr!ncZe{O|x5u8pu>CwqBXjL?m>i$a#B_WFc~Cvprb=1?`v=cXAs*PTxbQdAr9uVgLT2R2e1hN^-{ko9paIpLFUiA4 z2EtJ!n|RqA^lFbcpdz+k_ffri?79G{ZcB6@@4-WV9cQR9^xVYk;-@lGPd5Jh=Xq>c zn@?3d5Rn{~M-5wyt|-$%3JR}4B!JzB5_?V(k+f7Gp}oDmxVX4Xtpt@+sI#%L(Qv78 zcc-YY#H63uenDJvtcrgHP}b8X5@0t(#z{VByh`V|;&>>UPL8s={boAUX6mvSW@dIP zmjHo2JVXWDw?|u`M6hVe881A2hHeXe&tm=rB|9ZFPv!NE z;LH|Ay~L;RBU!{#l$JhhxX;sXV0oy50WEB11|+nU@&Hq0*x7Ayeky4U=tN90_ekQy z#d;S)U?*mrVYx+#iPzDwH@Rwga6gLI(y=#X{UsMXxQzLgDb;R2KhkzQN*>^(#vUw@ zqUK{5`rQ4{T7PDx)hA_h2wePvBwP@c)$8r&QB!3@vzYy*LC4VdYPD+Ft&~bU{uF}> zCRC8_Vu|6k#@nxd6-{st4R)sQhLGE(oG0}M|F@h0x#Y|YLHeugP?9@m45&|Wh0C_> z#b4|e{S15>#=8npF+_5t?MyXA-d$*vFsuLv_(KO|bhNDZIRH`rd)0w1I`fA>uriv0MF%<*5 zNs>dhEpiX~qBSGCm+&a@g0r?^2Tbj3y++E|{k3f1duEHd*;dh`FP-F#^Sh32K9=an z@S@oLcu3--oHOlRMzxZ}$aZp3BUZIb2?ZzOo*zVgUpyjkyD#>Z(|IPp49(D~DGE~U zbzUv-n2T!Sjk+A<4hV%bJLl;wed$H-=APo0Z@h24E<23`t+rE*J#%NVir7O4hKp_W z!j!yNGDcqj$Hpgp=u8JO9TE5e9uS9SRTeAoDF!3luI{U{vZ|WuvQg5MmaPUBC=qNF ztic$s<7YHD*%BhQ!w9?gChVpobHwE+rU{4FYJS3}r9(ed)vzTO)l?s*2+!4dDrV9t zrl-er?KKT-qbbt}^`dm$PCPf8TD*l`r>=0Lh&J8tdKj4XI?0@NAZ}L2Zm+smbB`lR z!X{&xSTRjBAXYWkb+<|Ls@tI1z{Jn6-3ezFH8i@HX}8$^Tr|I4W@lg4k(}N0i_Lps zdc4Pbaq8-7FlM#3?9aKvHyc^ppk=2ye{u`?=(zUeVKyds|8@C{ zX}QJk@IHcFipRkFIcp@vAU27u@A&Gq(e?*}UH9?L{e$TgNM{zS)qsazr)t$i4+X1Z z@b>6ka*p5GV%wq)SR_5Z&0^`gh(6lmvwP|ED9J(sY6S0;0PU7f(=aiDv(JPGn-~#U zFM<>s=*Yt!1x_p*`!>gg$(y;eCCGYc=;g)p9ZKN6%VfRj#RPW0 zPN%pxJ zw#o_dgk{wp9P2m=$G<&`qVu_1qp>p6&oq4M9sFeMIQDlN4!_^dQX!2)sdMLY+R>SB zu<14lL3lx((9-7UDPmtq@st)nkbkXbdollaQOh%(Ar|u*%4_$w$$nzbnvigd_-^tk zY0vEg8r50t>g~|}y7Q;*r7WnAT%Gs7{N^=0XVr$&TrQ^C+9sROF&WA$Byeb=qN3J) zUW4f69=M|!q{_=Ho`iaCtz2B1n)AjHIMNh;grW#943O7h#C@5%vgsHrnCex_zsd(f zCmh2+y-G`GHhyqsgWPM*m{%{%`=jkQVWEp{QBW517()&4(!d8e1(87)VXKqlgr6b} z7W5185a>4B3Y$K>mqj$T?rRljSZp*o<^sBRRvJdB3&zh$H>Ks|NHEawucZT4$ zU+<=ux{4mH=l({dFm_&)GrV|iR{TgqrTBsrpNwBZ~33!{|pl!{!S2 zb7LhzD^|R><2i2YHr)D6CtQXHHSuVK$&QcpR&$llCijCm2)jlzP9=#Du}8y-{MxN9 zuXWGYACmjOmuuT<-R%w!GF8m7e2*CHx^P|bFHS0dTh%;G59avk=;$Y8WHtTGY?%65 zwBq}^{%EO68*WA>MaIp4{LrI!yB;G98ophNAEElK?g5-aXJZJYaQ^3-HEaa^An{Ji zU1*O_-C(l;aK0BcO}Lmbt|*)nw`l!v{HlN18?FR)Su}8Pyk+6B`dgdlw(|O|dr)zi z$iGIX!`CpxX^~T_`{K-x8`s9ALl*^JTmlg|PeIdAk4{yut?4_gEI(>T;wFfif8DL$ z%>jEFyk1ed4CnsxlTM5=%bxQV)SvY{@9FpVzj~iZ=8SXS{2JocbGg5&>AYA>S-<}D zRM6EwIoO~S<@UkE<>vHG(EE;wd#&zdse{B@okfu`-g&Uz3M_fGtl!y_Zq=xRJXrII zpqCSiTEE#SaAWK^JJYp2&}g_V{8_pS)<%;U5lKm=&7``t(V;=0G?%#qf(a@=xV+cuM(Uvbn4hgB_W4_gr|s3H~L(mZ&-y6p02 zvNB`knwaHH$MRCpOlO-te=_@ozhepwE7#25D@4J959IDu;2JzF32t^0R`X4fH=X>w zzQQkzh{((Cwsm-P7&qt&Y0{7%BSdG|K zOv$Gl#rsm0sY-^g#avD=E^@_u5{nvYntJ4>=Je8Q7l&H+W-k}FLusnD#Rot3*Pm{0 zlCaLwQx;3OF)Th{(SW%Cray8lBVx_u8r4V&%X+6tM7Ko5$*cG7@V7L2YK2T5yR}Z3 zL)1f-b~h#G-7d?VB!(5p{;BS%gWdz&rZ@+Dg#k9FQe4BIr@nG##34))HT4$y3qbzdfR&0T*i^^|!W2vI*z&&s=)ke0yePRtPi|<<7<7GlGrNWHT=fNlI2yTZj9( zN&@xVEO+8*1q3z_mqmw%&F^Xam|GDq1)-fX!ARM_bsuJF6A`gljz!zLVJThrBPN!0 zSQw(+t6TrTs3f4=YEz;a1tV>GwVv~Let=05sI?h9EBl~GvT4uwJmOMSWdqdqhBs)U+Jm`>3U*KQoE@2ENY?EIm=a znnb|H1;W`>%JX44q1Ew`u=d4b;nRhd;l-ed+lt?;Ny=N> zwT1BqBV4H1H@KsuSqWWMN;0JKQ)al=j}VYb;q3eIB||Rg?{mZ*37A;8**;%;jUezQ zW+pEBL2rQDA=Sxy%(+2I+aEIHI`@mWqVvgUU^KQz7O@n5v|d^+5pvt5AATC1t{6t?Tt zVY0o;LKC1KVF#?~SE$oQ_jA0)=GR}rrmAb#C;ra<)o7aQm(f!UGmTLjQ2odMQ~!2; zQph1f1m$YoN&6SCDexb9I;gBSx?9_GT8=`CWDI)k!^Hdpz}(gyw*%g<>3)8C zvlU4fE=ETctUL_SBBn~jGzuIv7T`_^Cy*cLYl~g?xm&&59a;A}?-KO7 z6;aZfKC9c=F%jF&-XZ}0oG{V{MFtAU{QgBs!)eRn2n{5jGbU8E-O~Z+D;KA3yHkz# z5z(#-66gtoFPkT2n)B@%{7d_3vgyqmzoA1%-^mUcD|NctawXP$tdbmsbE{@{ERoO7 zh68SgrrAG@$7B$QJ$5n~=ro!YE=!_Q=~|lhMm{-X0N;;op@LR7Ys1JsT9>tbkS8?@ zU5Kn3*S0qmEmugi))^e*okBJE5!?Ve^A?%>QHN`bX<}vFy_q(+s)X@uVa^feuy{eM zf&7N6(WYa~)38jj5jH2!biGbrW4VL7y3)>GD@{lO zg7we0S#C;$Iyxe})lhG2*PV?Y7@*ckPQbK2s=>M%1cjU)AqbiZno2`s7VOzEc5G;x zqV(XY3I7YSW9doR1NH)(aec_$lr-I5;SL@!OBb_`$TrcDbzS z>Z;ukFmk>v?M}yjFhcnW0lpVANq#g;(wGg7mB?WFI4{`gAUJn^B))uZ*68wxTJ>zm zWeep$$y*@uh;`;@?Q&LDEr+@zE(y#Oz{=8+$9c)bh|ga=;!N^G;pK4er6}m`7%4O8 zHQeGhEEf8bdGWu*Z52FToVaWY_Rup_*nuz+s3ck3hE{ADOr}@hiwtX}_S3ac28If+ z`^7h1|GcKtNE8b5eAb=t)`k0ZhXBbq_;PB)aTOf5_@QcSF*>_|cSE1In_P-`p<;Fn z4crh?C#O6xM%MiadFOq)fu8L^;{MpK?QO)qLBSjaMm2|~cIUMwF;3sj_(yaV>rd(E zIJ;)iY8zK7)WkULvBe%5Ze)_qk_=gc&m|xYZxY(t(7(o== zlJl;L2K3$^H?IT5p#i1IbTPZ(-`*92$8hLQR~$z74^foF?(Wot~} z>US2u8y9DjpA07#m(5~596+s*o>=JgmztV-cX#(@f{;%h6|V8x?YYPPo7RCGk6!3; zHuL2lC8k0-w+gKGW_#f6ZESG765h6mn2JH2H^5^i!fU3d5QLWG04*Z+3Y+HGhp(m` z>i`xEA&HL44QgbSiJnm%RZWGBU{Kr%LbuZRd|#f6N6UMUxor79%^{Pq`ktg}2)|Tj z_17lm?Stiw-oFmFg%U1&#E|u8sP8Z_&sV93(|coSK6@((E$1uG!x`siD{7URAm9VF z8hM*}HP_7bykU<2_%+f++sv987Kv4-^D8NNiKjZn*_xCFcIvzjAU z8H>dxzYevY`Pqd;c4zaJg266>9N~rRkg5CU@Pk!zY{|)qm8pEY=DId~0BnwQk^fBU zXCvM2*+DVTa2GWg+)#cr=SA9nHd~@E-ml-t%+C6>gY^RM*W9dh=z_&D~nn&HSqa;J`*9#|M z-^@e~eX+j)dE43k2zBT4_& z%YL*(f9Ex9df3;f@EgNR^Bua6IP0=mG_-9kDsQJ2aK_jt8Z||Q@*_isJb~EDr4pY& z#4M86u&9GiljHou$lJ_a&Hva@>^J`F3p)WyzAJa8Q4^GiZpMc$LwK=kCYq(bdE>Q< z63r6hAt>Kcq?XfG&&AWD=5^99JN7S5bhp`*b##1=1<{_5FA$(MF0GP@zcE7jzjj_yJM+)i z4sPqa4*IYywcVyf$&Cr>8cyjXJ7-tPZSUU@ekMY>nG&G`@;0r$Hsd(%9A}51EL8Sl zaNQVN9p2+lrC**B7O~r@iuxXG_E4FL6>mNhOY);AN(=HTJ^z%6hmCa{PVy6KuUJ0H z)k1|fZ+SInLHJ(07Cc{RsE?XPW8fWb%g4OWT~odAcRIT*%`*Ngli5QbLrKo*Qk&%MAy1h!vbW*Z!=v*do9+&qYOK*)>>XYk!&B9SFU~8--eNiC5sFO zyC1kY^r6k^bt6rgTa)~*S$R}B4C|SvX ziQE0|$dRQPLs{A$13`aP(f1I`htJBNkkmfUiexS5wYt2dm5e^EHul-@HxB+;b~|-# zX$C_DNhr3 z=&)~m0QVC98!trH3z1%HMa20S6I#{4MWbWhAb>g-P`{x)BYS`&Fk^*{EByn zA$QT#P8gQ2L64}PEC1ce=J!Wy)zHD;FkH|WB}9oP04qWNT(d!^!x0zx&(Cp7O9B|n zS$?N?9O>GuzN=p+zI3QXr$PY!J8Y+o>SAiI&w=LHoRjW93%z}|)AuFzIl>ruW6?A+ z1{+!`J1Yu=ULTg#OmplPr{0`-{JrSzGF0(e2U##2mw?Rj#*!Hc`2Do1p0nOlQAoM< z{$|vb^X1_|FxqULAO?*5XHDi;U;zYLIY8u-U=0$U9B~p@M-ikdYFo?;jS;STq&kw< zOXtB)=2O?5`l2+n1{OgUK8SZoDI)>p3Bl%aPmW@JxX}}wUqmkD;j!5`gr_I8o2yq$ zM(KVbrz~AYJBuu~bDB7+o-IsR(tx&C)83ZR@-UwYSZwR+T=kf*ZTJaCmxhW6(9cym z$a)NBB?{YGXW#Oj{q(NrFn1ZenfNDva=646H@t4n^1Sh?ZxlOrPP~IEI#+Na*t&{b z&2&1r$2-i-P_&8D=4f&HGj%=`zkgf3tlnCtI-FrJ5%fNODu(AO#)%`hxf6O`i->iu zT7TVxx*DvH3EEwV0kn)OOXJVP@0rvbgjo%~KTNA)>8yY3^*I>R{u4wc+zvQixE_9i(n8$p)c@}Go|8rYm*PW8ietp)n z%4)on*txP&K&>EfSIOb{!9=o(=oyZceKjs2si+Innrq`vNksBO<(!|uvw+zXsgkgr zl6>cN;8kP6)64hW6up0-aSSQPUZa|?-&&g)7@@b9v^Jhoi{dWButB$D&SE(C_T785 zwHbfdcYPg@B=UVWWcJ&>FPZJW{wKZb9GC80T6&(7AVQzP%5{FNwwDPubuj6+oUf@t z6LHznzXzcz{d+&S?Lh^>&zA~XhH06JGYW<(au1v0v;8B7m7cf#S~R;cemiT+N_@6p zZNT=W6$~xCey{L07<1P+h0L$Lh{XT?mvWvL6LHe{^?`KrSPe|tb+za{dY#PvJ@z{t zalc(~w=+menguT(A#Z*sLUvgX`t2{Wlem>*A!ulgDk+qky}NMOuh`X2xY)GS8ck!CW791V{KH*xPU0>d ziRsET>-yVlZPKhq9Ttq)i&J3TeE;mBO|1--#kZJFhmv9sMPr%mN};_v5^+-)-^}Ou z?l-^vJu+S1XzhKmrWL_~%hK_=oJqTLuYtfyG@4@87EWu(?b!0W5GRg!D}1DyQkt4F zD>*j}P5#qCnc6gQ^p_67BNZR1Q6m8eQDby0#NB$knmRogx>QU{w=ckg>A>$O8d4*i ze=K+PQ`{W`YwG2IfjR;wTuMEx8bKk#JwRWkfVvgc#)9b$`fiHNObdwd-6uzNymbcq!&T z^VwZjDveR>^3AENeKXF_-D_%NW5uwh>$>cNHp}@Q0MPdLB(j}xsfr$N^}Vi$BXBca zKy$dg#aLBU)e&*`a$eH31ap~9GUo`iZk97#OM;c&C@@ei+%^-u{;P%(6$L2IPy9K@ zHEg>b9^ta3``F+rh_JRacN=4t-C=YQ_#1;lz~Fp-y~^`2%I(2AzT1A|Lv9xl(0so1 z{J>B8^b%}rrkK-gdiwC;_5R#;t@Rtc)$wsgdd7060jgdPab3mwxcMndMz?O$L!jgv zcBw+I&NVw^b1M^AJO^yIm59&B7 zgr~ftXqN8hZtL}z=~q^>izg2d9E+@5T6(ba{c9L`t~IlEr=hOrH=@7KBCyYrqW_sa z9ZbIkZm%2Gs~%MNdkvy`x_ue97b^z*II(TkFNTI|_Ob;C0oAXlGWdLj73mLf8^SM7 zBl*N#+7oJCPd|BSGGVATM-Wu}Fo9Eg7@)Acxq~USw6(`5 zhS$K37w6!!wYI$k1k%6F)UQvWDT=l|!gtA4zIO%V;ltu1&Ulq+9B=i7SjM51AI=0{ zFUPtB%%(?1TH3z=tP5ABOl|hI)v&$!T6P|JPv0u+bW`!Gj!6p}UR=9dpAON&8ztr9 z9Zi4txEo}n{Of4R*1Ea zmj2z(QM-|=v(7VZLXlA|KR@TkYX;Ngo>xWlC=9E;YbWN9u{G4Oun`8G7a>dAw&ppX z@xU$(r@Li->xSyCXL%-z+|5v$Gd+W|RIlm!1l6E^QlW=FdYdDbA-2Qo{s>dPpR~y$ zwSPi%v)xA9ZoXpiQ%z9>i5ojrG^5+~D1ZF;aLG^ue3!&E_~tWo8wG)Ci1=ialw=`*>N4|4hhIPaL_j zyq=6KDD{#-q*Pc5kn_pV#jwXrbmG$T6@}!X{8fWQ;OLd1>-(S`S<%&Zs$ryK7w)$u zOQ$uiH*TL3V@afo3=)qup{q~y-9NXM_Yug{N?0!6(@~2bycUVjeg8!eNz0l-j z5a^;{<$$j*h>5DQaH6@PMeK*1qIMA-{cqxDZ6mgFA)ep^&PEM1A53%a7OdrhMi?Tp zGEkaZ_11D}7f)3*<<8eq*S2gd%;Wk?iCs#Y57Rmftx|ngZAuRJ-`sNXbj6G776~0# zICON0ij#hY##evPPjmO_MiYJlTSJ-j7Gg%D)_JXQ?<-bw`6 z2>#0sYz}1X`qMeBn7wK|3O0INhG?yyoHpb&^bH52=MTr6B@KPT8=Xav7&1+1|Mduu zUbNHQ&lJ|YGgDd>&gFGYEJ!%5OR4LK+&ur(YN^D!eT|PXk}5rf`rMn}Z`yL5Ve%_a z5?L;=g(7X#XM(cp2>M>5&l7)q5Gt^qkwI1@P9a|ue8@r;k^DOyI?%^UgJdkKbBkc2 zqX~a>IBSPbqzZd)LossMz|wiStz^Z*>vsXxs8o(mnAaY+tn6%8yE%^5UUpmZLVM=G%^fl6ITRw0@uL@4)TYi$xU?e@Av%yNZv7VB(B8Q}=1*6~CrlD_S za*Sbzz~R7!uz<1v)VVy49ly8^LOv{=7n5*)4i?X%%+0HFc=g>^I`&;WuM{vx`>LGw zl#ck;?{eo&MwgMRyn%avCsE|YLzFnAHeiyP$RD%QP6Bu!N*p2o{snV*f`Zs}!}vL1 za}n3j2XyNQ%Sd4R8xGI@?ju7!^MWVqp_xfw^{qG(+iPIxYd54_zZT>E^g9&owJqW@ z9)7NA+&aO>`rjMr0bt)E^4rxaGe`f!lV9Xe!}04t-D^>~MgQ}f;4tQY-yDFNd6pPv zj*gm63_e?iA2g96tTFbema&2K|Gs_U8f%pS>$jL_><>Vkh4h{M|Hs&02gTJy-J|f} z5HvW!2^!qp-Ge&>cM0w;2`<51g1ZK{;I4zayZgW$^1ScwyMKK5)~%WE7MD zd#}}NccVZLLL4EW2m#(RJ;16+kc8WCK~obi_(dOl9#nR_4k5^~oltHxnm#f7yCFz6 zc{o_vhyxF`kOuq)_{<~CglL<~t7B8Rmu zaf~WXGypKYy5gxD1(+fHZ-a*EPBFi6E4J|XMdw&~@PC2x>q!+@nml}bcy;x{YSP0# z2BRUZi5P93CTB-bKdzS&!}h(`bBDxfwA}c!%-Zuek1FjSd2;Zi2$w!Sui+$vB!*E< z&?eltzu=a^djWLS3}iDcQ2rBqLKRZOEr^(~B`dKZ)lk8UxTRi#6HU^{sg}0rr@!gE zTNj+jiL>NG865k-MWeuin#T^lf#mXg{17!q>+%kiuU!C17(28B@>j5WxT6d1o7NsK zGZMZPaYoihXgpl8DW<&FbSe4~*w z{9v3xQ=13YPo_M5zDZyP%WwbWQD-_8~ULD;6%bN z@Q|cnkuNws5)v7NAtDG9uB7u`HgRFC9dXx0_xxXwL;zM(~}q(A1rPj{2Kef#_jV#EKW z8x>U8~%jw)E*a-ZdOkBM_{o$V#)do)F*esT)r@KQX)PtNu|vt4g# ztyFr5xgOWOm}CUaX1^_ajq`6`amqZGaDxpB1?@u_MjP;Lavv4R0_TqcULZ+O533^o zX?giC^21Tqi3}dwQgz=e8Y)hWzpkA1OENsA*|koHg<}p;r=roBmD&%@Ket0ud;X(2JhEE;v~W?U2a=Eesp9 zJCe*xOG{{J*|g?brk_+yPPLq@-{K6eA>d*fkW`oASu{=)G~6;0xXhwh zs+3`Pku~ZuoM`|0v~cWeQEqp`QJ7jhIlXS1<_P(simvzA9FXsJqNu@&D%MGxhGHGWEm0k3z8!hI6IFfN%5VT8D?xXVzKV z_G|MMI>0KOPWQ_#Tzt3l+h^PJ5iqkOmcmQoTpSMR1{5ww1 z?lcyot(qc2!TwVFT$9`3bIy|ro14I2zc@UXP7(8(!wBR=4-{m{{e@&Q}{> z8qV8b5V46fx7MCl2Z;STHDIrSjC>$gz(S0E+ruFFdF6eUyKVYofuNp`?gP_j|JIAu zPQlAH#^1N!#)bubht!g@W6h4X3XTvpDjyCah~1LZ)msdu)L)18^%{2EC5v4*Ba#KR z1mC)^BMn}j`>;BHsXxhEYDs1~%|%@!+Dz$OCs+Qt&%!zj969TFDrP8scO#MmR_=@o z7|7Z@q(-dwUfMUGM+QiV&8}h`9UJm^A&xP4Ocp#wOh`Dzpp*mnr>JZOB?|hr=c30; z5OEvdeTT8^SY7YDTN&`W%~iYVP|Wgmi^$-xTN+KxuQ)rUHSpX@q}N7~*k-H}xLl!H zUXji>Cvsa+%1`*z9Z6LVXs z-W6Zw$0GqYDobsC`M7u;FP*~wYIiuCt7>Ic6gZEk7>M~^<#7lWv-vjFMkHLFd)^P- zyNc}nnqh2yspZx>V^`F5I_wSE973*M~XsWu|H*own9>K!hq!Ms2^+Q4+DN2A-+agEi-~k^|62d?1OA<3EI&tldr57=} zaS`Y=*;SM~^e4eFMr%3DR4my`D#|&o-fuS2KTmvO|DsFDnHJM_6s|HY2JqiDmwP!k zo~Qsl9LImZt`)zqdwkeF?bxI;xZK~K1vyODpJ)4;?Ow$+MKynGn>9X{-Zsx7Q?sKk z|HR{aMl#$T1vqF{SzO|e{%tIQk%QW`q zzHXvn9h>01Snzg@SmPuxFwh~@EBP%0xZd0%WP6r@H}8?$(X`b%eO+72)2RBkYAbsV zn(`cHeQPPDjd{-tbSFKVuiMf@>ci$-4XEv zQntHu8s*2oO00;XBFAU8F5o5GR@0^lCaXQR)z^BD8Jsm{&6k4YW5HuIla{k)VPj?K6D&j=6%kWtqut>Lz zOs=Y+`ZVR(2&mg95Q)_mMLz4}qnhiW*;422EDhSY;hi_utiZ+wwGNsjL|WjZl5%a& zq8P6Fe6UW;OWnaN9#6BmNeH)1}JKLYaoZz3(I1H6PmVmQQ9pSXqLj)CRkDEHx z8Du6_7VC-^&b#?9}D+&u{kDd2Pa>MndJt2jV> zj;~GYPsgVbwaD{{udmmgpjE;$4Zo}Ttz*~etgJPlV#u$-$G=S@$v7{EK6io*Rr2-$ z2HAX|$5OaG@9?;|j|2lDXd;KOQNn;fyGc5=bb>cit@}&9*XqD95Gd3T3H9#nyKcZr zBCTNDD`NdJIh=&87S{L3 zZ}(QEXrTQy+nhHE2h;mBE==$~2MXZpb9EDg^6D;-`t!SsJ|U%jhezeHGLZkiGWEOi zq02{~)8&rzH2&;@ z#=)=6g~gx;M8SpnJKhEJKs0SJ#MIQtLJCE`JDk2gaYXl>lf+6g!4~hwAk_M%HD9XB z(*|Ck*SX$Hx8T|N;VC^eiGap!m-%@e4i47s&E0Em(fw^g(dT`?=U%8V%-y!JJ1Rk* zhi#86YZH^`rO($$W^0vqZZ4&IdYn%O^%i~_ zV(m-3F6?Ii$2jcPXCTnI-+kG2^FjVd(@HH%D;z_z-!-wVAIZFc`Ww4W z?Xs~27hA`q!<*@6pQ66k5m2uXCiWf#CN}n7k5@7yYWIQz18$3VGqIzrJv}ro$R&*# zs^jg-S!+bqv&D0!RkHHt=1$aC>HB7Ipx!`V?|XmIf3;I%$^0P^qnOk!S5<6wKH^3D zdBP9$v$r+7>SYlTzj_;*v|bb2CQI5=n>j&oU@869(q*agoA=AbsitSLNQ` zUUzpuQMSjPy_?Uz-|Ojm$7MgheSJIgggctZ!6z-Zw-)f=w+=eHKYUYOt-VT0OG|q` zH{g64?&=bnDT4qMml)RaI=m6T!dG8KD@I56e`;b}H?`TxnF}>aCyeVFaRM z<)+8Uh|3|U(&hM!@kuEe!Nh;LSPeHlii~JG2&bP776G3b|vVN@LkV=d&eUN;? zaW87?8ZzPY<sB?6~(yb{Yw5278!s*d;Va;(B^g}HsD3<`(Oy%6$Tuj65gDxKBEpy zn@{b#5w3u4Y7+K&czGv=yxauVrwxYr)LEq^B_6eP1jJBe<@b3QU0kxbUwfj>b@DJ; z)oV=(vlp7m&=uONul-q`qj7@KwBf;_pmoV_3WR&#Jv+c3iQX3Qc$N0LYXFh+YVRti zwg;qAq#7Pw&j@prw<^80Ed)AkJ+3m|vrL>X$7@?CdwA?$Q#}FC7MhNoh75u=^!>h@ z8v{el?`(fV06fPDtobg6X?{~#F*K_AxC}(oTeJGrN$~23T?)w-99#J^H=LF69?fvR z9ck$E`pOC59jbbHk#x?gH{9yn;*Y3IAU#ij$~T2(N}R0T=3aWHuhsH=mKK?QqGcyxJo!Zwoh&saq$=Q|I06?-r$BO%fyO;S@K~Gc46`n-=XXkv)I%-hS z!SmZV1i*VsVLu5x`f?%*%KM#(t~BhXXZzeQ)IbR`0RWDIH7!TS2G4c8@%c?xGMuk- z+kea6(D_`e>6KpQTT?ohYB$Gc4=Q^m?0k3Hvx%$|{2cXR0YTD!zcnWnaj*&+I~P(8*<4?LVh5qNq?6+WWu ziRWZ9ZI+|XHQ)UpR5pO-0>b4_ywm$dph99Q`G-iasr%mk=FG~sPPn}b=Ju((ez3tP zK}y2H-JEYvRpy-d`X1l6d&45KUYnAM73e-;eB_)XRLyk=x?lg4f&~CfCA4o4EO;(02Zc)Q!IP*}cb6xApwN5IUYP zkfw0^D;gW%|KrbYdQo`U7h2#ioV#pm9`~2Amru+WJ)$9ioR{LWV`TnD`Iz}i+Q_@& zxVt;4!zSM=xkS8{Xny^B?}B=>kwTZKic`8aN566J-^>kfj@|iCzJ-gfK%-4S ze+Q`WVMh!Y)o9Y8#J-SW$MhN3EJ)Ga;za(Hh+jvE0soOOs#zEul%mUeV8ND6BKjHi zcl$CfF3z1U3qI#O29*AGGST0cT4%FJV0ACCj2|HM%~^Z{EMnfxj}iC;I&66cHtSY$ zm)Eg8Oof4ZJz!`xu=nKkEQ;THM}kyvJ{`RsT#;awx0#j_8+7n-seXMJ>Y?G_mPT6t z#Q(A(sR#0C@^$R#&g0k91AW!h*5;cr4x{DIYzOVx$dG}j0IYN-h|Tpk&^jU_B1D%7 z%kIt&olfJZ2@AbWBOTSiuY@`}s>e>#A;IL`(XxqxM?v3IDOqp?mcfT5(#z z$$1p#xZG`icX#)j=k?g4DdkP*a9*$DNHZ;JawPyDZl@$myz7|5F{6@+uTauTK%q_t&Ts5y)!J zE;&}ei<02^cP!5%c43>}_BeJk|I;Kat8-@jXARnHFtHHdhUG`5b|&*|eF~c0Uc(8# z%tX@)nVr+RS?Oe-$A$vfteSYej7((ltvw#Z_%-q}cRWwQA?mrnMUQ00fbDsH%D9eW zu@F00)M!_-a(Ph~#YnL3{7u#@?Q5H%wOX#j(SkKd4L^bZi_FX={MVQ{g_J#BdHVSM zlhJjTo85}tp+cRe>ye(J!UT}qX@=x?lKP#M&evBj;ELB?6s!4~`?j)%1{rX2X7sgyS}6Bk!Y`T!e4+x?n|DP>UTTxz+XcXbK(E?s<;D{!wP|FR~FEzv$SR6@g|bCBrNQOEv74;kMSY zxr7|E(ek|X2G%2CcWXrcHNSGJ9Y=zUMTzXn7L{+eN`Tr+RW^n!a3bZ!p7n*ryAPL1 zSyAcX5CF0PQ!JbH(#$_k=d%s|su?;QQR3A`r$HPRhesz6U8B&es^DNo|Fpc)Rh`k5 z1ibTDWrBw(rQhR2qxmcFIw+|BDlpKV?-hsDwHybBenGj1_5&ht-GG~guQyK(1Omma zzoGy>APQcV@D{m4@_V_J>-%tcpP}-%*W2czG~cAsmd)>soKk)M+R#`h9=)R>px#_r zUwh*a@nUx4ln63ca0#@PRHFghIJ?}6zLo5A*n1nEfI#hlJ`gD1+7LS_$!w)Hd3qNB zmU07r?&R)gc(;}8>Y8hS7oqAqJDU)5xN3McNv|XCb=#jW&c?=&6Y(1bo*oL3cZWpP z<~hB~%Je<&HnAK=`V+xI?+@z67CuJ+I z=cTgHyaULmUHr!ixM{%m^mN%ffI{qNxPK|JtdYHZKPvhg0PYvtQCEddSDVRxu5I7l zoQy@sW}?K60|RUh5sQ-a^Cexkl^UM7j5fDRpYw?4N+(B_C|VGx^Ks(h;=+N9erP1!tZ}>C z=T6``F25>+f0>zyiOI(&{cSs0GP*?*s{0F7Ph8Dl^{KhUKKI$nD?hf8{rmZE zBLA&vBfy{O>B$F5RS&;uE}oL-73=L7la5m-9akSaS)Za8Z%|zo-?fq2ZbulpR$#Nc ztt|+#;pI2buUd!e<;5vc4X)7yYg+fl*$n9{uyUNp|7xgiZ`rC*m7Q4i`nQ z8ih3TGc(K1F9r}BcAok(3Q1#@rs>u>ZMCI0N6iUv3KHMwRn(9G-}DDmu}e<{t?ka~ zb)UbQZdLk;?}j!!f{LOW8Qx1Gj`OC8{@!Ksp0Es`aJ=duAW=e#(&ZL;DWWJ96j6+xbRZxV8d zRm2K;(+#$*RCW#|D4F3_ZhkIa2@%}L@VV&=Jty^l3gQ#2Gn2?|)@~C2VxJ50F+F0R zpSQbBJ#TdcfTz66-^kY)XxUAwEEv^lYS?#8gH-v}sc;GRYkM+PlML{;Y^HhICzOn4?fSd!D>~7%h?m#xvsK2XjN_9NKA@w}f=^qMLvOTX zQQCBUo|UY8$&-wzll?p0)$eIPep>N-)z2t+>4?)+-yrmFB=Df`Qiwp<4t4RlKhM@K z{yZ@Zj^ACRWJzqJ$G~WtHtxD|sp_S~$JWT?AHi{NQ2(;Oc+s`7;d9rJ&N=2opwYAP zBxl#!eskaXw#p`$*~>g;OqCR8TKt-*YtRm;4ml#X%ttX~n zm3}C7F=RF<#(tETUP<-Xr=<3Aali9>H8Fss^QQZ$zkMjgVNC6If`938baOx30s=s- zdp)=B`|yxz@68(TZteRzH%L1{Aeh3Z>^qfK<$M2VUjYNC!($-y6Xr@uL(;b}&hoU> zFoKIq6-^8B#($e;4S~yA1Kr}FCtR1L72OLoeLqst*c+xtx*di{T&ks@XAU@+6Z4bC zG%JP?q1K^f>N7-$3=)SY{nhYzR?jsKW_VWKhfBDqbAe|!H@WuWvxe(6FPzU{;;%tL zc3Kg55u*%7LJ6-oe%_Y7`6s=Ij(HHhxLKB@wLd+*z?;Bak=ML)5qWt!*kqM>;#FWu zXB#(d-HlObfTySDdaL`TB91eC`3W*Ivfli&x;8zK zlpgQ)IHBn6+UCLLL3c}MSUsP567y|{#ggzN+;p!XAkh=sJ2-xJf5 z3m*|2Qy-}vT#2?B-mMMHqATrOY7fs=x6?G&Yxg(z3(PM4$`KLUNJ35ImSbVNb!HYVgXQb4Iv zA)}JYzkZjRbPd!RHa5alVED%M7ei3mW)wVQyq@=2zK{H}(_wxGplyE$03{O`MD5Ux zFb7yJ)|wU)s6^9H&D3U?Ql791|5rA8ff*w>aA&hHOzmPj6g;C$u-pRXhk!NPcf|ff zY){ekf|T4w3gdl<+s~Vf4!4ME%Gtp=gOZu2AVLC#U z75MQMNre+~bjzmnbn5FDo!Vo2A*CWAXsW+*fWmZ>mv*zb*h!0r$TZ<6g*d#i_|wXN zh_E?At)2M4p84kmi|u)WoI*9&!G&bgNie50(>Xos*U(Xb<3|ZJ^2troKs~E0tJd9L z*c(%>skr>hON`Wy-1`Gn|BTPa#7%zD8%48r?6^^M^4RVO-)pLI|72s4AL|;~Ri8O0 zrh>vtUVk6=-2%?r>Ex`;8s`WhQ2I$MzrJch=^@j?o?bnPcJp&8pa1j#*>N9iXQJJC zzz91$2f~hdLUs42HJfSfS;d6ae2LeQF{oVMs-6L!Ti)(~A6@nv{OI-n9?d$Kc@ZAs zg6In0OgP^D(Z~x?l9sILv&lNfhZYz{M*c~rUizAf!f}P-?!v~ipMrI&vn=elUEtS{-+ z`r_~BMa8ZIXQ$x48S>kOsogS152RtBI^vT*{y_i6-Mwokz!vrjo4&D2P2c6YtZbUS7a#V56qmJBw_VngnY>;?3M{%Wx_&l7lt zeqj~$uZiE7CRgIt`c3CtP|7}8S+xT8YOUt`Cdm)d&_57Z$#-Urnx!W=aa*EO+J>pJ zm*;%R%~_d^D|cUf(uOmocHHAu$wtd1w6)4?%LJ!4`2jM0A|IQ1|t6AWA$MAr#LP_@4wMh^4 zAx6RVI>~PNr*JmwU;_TV;=`_8rI*@0D@)wi{7+WY&6ZyLfU2X+Rotds=b9*<5wD(&`=DT_K7^rJZUZAA3i^o^kO&THS|f zT`w`j>e9h5+_=v!@>Ej8GPs6QyDN))munW@NU{Yb7?SW0s|wSTs%lhHY4t~jKaE}4 zT#7go&l*}q0#EjpQD<%evUUQWV4TK;)%Ki+2+jBy$|~`orL__G=~^;)brM`?OBQi1 z5K+o*C=c9y?lxa}sZ-i%>v!mY+k2pM7bI`PDZ5 zjV#or^2i$Y-XDwt>ftNnphT3mx;K}|`W||?moIz99^wJyv^E>=N8i*#=ZyAE0%WKQ#x#Fkj?US|M5y}M zF`xQRsRuO1+X%sZ6$@hz*~4fu(1K2-7QH6&^3PST{K9A;%^VNuDtuEuK^96eJ^NL8 z|GG7k1QEqi?Qzwuip-KBXW1j$UdKvZk&QqdIfu|r$p~R_jK?xO&w_Uwp^#sokSpMd zb#_>7w@iJSA={_{F^`v9G1n%2f{_bJt2&`<_?!V;L0zGI?rc?iD1Ss>=A3}cUDhys z^^1(4Nz)jIrET66hZpE{*2K?`As~W% z4H|uPYgqswr$8Z|OF52ajBH_xXQd^zSJ7($Qug z6IVOwX;AF4g61im4r|2Xxr`>ee;!6mpRCo<{poU3Ya_C91_$`2jAIY{&RxQSjnPOLKOie z^q5ynqXdKQAGAY@5!^1(VqelZ6r8jbqe%d7uQ~v*pczo}iIj1DlG*ix{Uk{SADFiH zk=#wl%1Ge6CF>gyVvC`y)+9q&hPr>y&FSg6Q~)jJF9jU3i34`K?;b6{h3 zF0C@|Bne>+cjo+_Q5>5=K9?x8$dSEM8!D!dQea>auEGSqRV0tsBm8Wh$|IY{&}z)v zDgZon`K-t_a%i|+k3U<$9p8mGlXM+z_&91lZ=A$E9obwZbo{+G=Y;{7mM@Q7w+*~Y zrk8{7JVW zyjY%#u+5efAS^Z=v{B2^;lFH;jOG8=lgCw`Q=OX#S6hu)w~_HmvyHjjgz`0&lHANM z%NZ|UQuD^X_WU7ep@VU5ji8YhP*TT0Wf-x#&peoQp&&pShUi>B$H2AjSK{HLJ4X!2 zynYG_uk>?h+}$|S)_FR2f{L8QG4@kHL-x>9pxWMA5lGwu8SYB0o?xSJRNcF4DPMcF z5whZBk))Hj$dA0J!;zHF*B4c(^i`9mEy-vj0Me2ZorSwmgknwlOX@HF@;23HTWLS} z(_;flfK| z9NZ#MhwPfXsZY*psf=O7KDGG9FWl43C4~J46n80@{fem$5CzT{MOqyNtBe-?XP+@S zuP!M6N?6oWpT9#-sy*G;tjUV}euX2t<-PEa?E$fy4$U$ayyE_)!4O^Q=l6(_>~yuR z@l05ln3$S+9pCE&^WsEf_^ZPUGBZe?f<7H?v;{a=7^s6d@HWMkv~|+cQBGHDy1SoT z!m(y3VMog&uN~`&Zrm%^??|D^;hraOd*dyR#0tXy@=$GoJk6#SSHfc&M7M0ABU>{+ z!~56p9t&vQ&<1Dj1JfafHKS{eYIi0a$GhS!hHU5$tsTv@e9{*GGRZSbk8c7GN5AcU~(h=!K*kSWOLJPImLRLm0pLXt8x&%B%+;mhpW?eY0#5u?1_Y8 z%VIPZU(35RZRpNPYSWG4>oK)icx6Fp8A`6%d(J>n8HrEdeoqS^=>Z|iRr?_ZBY7YI znx*Z&F`}pr3i=!w`q^$A_#BpLC_-i#Jx19NiX)@{*qE=w52NIz7O>LHftnggm$FN` z-8HUEznDhL6_r%0r!z(jgCQM>Z-!pcHos{Ne+bVLQ&Gg8>DNx7br&#J!gms1&Fc4A zo*syHfrBC?gvWg=c5w`y>%PiZ9xE);#4bvpln9$Q&+R!il^#3K@||vro2#2H(IRBn z*ECj%41yFzC=7j6#P3zMII^HdoAo!EHqVAqwOI!KX?0as%w=5;P^cHBCV=??yBmvw z*~`=KYuDJCG5hBc4aYmaJPzsnyOS%t?3Rg&+$ejLIWKtao@3tRZzI?`w6d>h8O)(J zf@39BVLO9#@dUDVqgW>gGSGl22k`9U$Yji@g*zXYDw#AJE)X#9P2g64ibnO|(z=mg zCHpOdh9RXG9qIU+OLcy7dvhSMV4MAu_B*_?$Uw+%Zb7|lGoaA(73T(({#6d1BYjZF zP#4t?`-r}(%mJs?Q!2cWsX&Gq`wYm@K?#NrOMnIAk67Il+>PJV=vh^1mQwr0@@U+uBp!lb5A*Qm!#woKZ&SITRql>>CPc2Jn zOD(5f(a<1*#9bqK0Dxk-t&LD*%@VF$EU_9^sBX)VlTuN&LeyQ!V0yKGmlTyEpU6*s< zN6?V#LXt(8|G_yd;NaS;pj!B{LzQ>#?C#lP30{`S&okBsqROC#1yT}Uc!=|{9)ea{ z2~#}k{7mx$J$D`c=6eIs365D-!okD!e$v#_xAYo&3csCm@q+Y){Z$kF1JT#uD;)2+ z^-2;~FHxrjCmZg_$C1WI@@Q4%vhOa$yWH6_-=`Opfix<*Og<1(MY!b0h(wEZt-kji zpGi|yb`fIi3d{ZxA1v}KP(%y_K7T78JhF^W*yID}tcqO3u|2YPMjY?AI;!&^MMarn z+ma8HpbQ;&gp|+~`E>Z(EbbA@83!T#vE!kW(ag#fetr+b3@iBtCH6@(DPBw=zIj&3 zg<`|(A=JjaMBX=qR5`y3^jpsqs(+a3qz%XA|Rw4ojSf5k;UhRKtU#h zKEekAzKV^T;|webyE=Iv?Qt&Mk@p_N@7%$PtkvV*M|)Wj+a?sCG4kB_vyHTN{+^1T zX=Sb)N;OWooXL3fv~WZe(B6u-tqAks+cysKO(TK#rxv;=&2obF<~v6OA1PJr8-THx za{zz@jAGsT#?^$jGu$6&`}mCUQSq1v-<+ceR&z#Jf~Mv(k*wWU8Q`e6*eDM6aRpD! z_3~lN%KyjEjq(>M_52$+ud`;dc=8E3G=w zQ;Tw?AkDm>Wwl`B1F_Erzu>d#3{!^#^i&vcO#R|_7^d>J&oXVzBBBZrK7Srw>|?TZ z2IiL}gr&Hs#6-9l@fOtlTBMF=Qe~g!e>~Oe%W~_n6LFm6HS4sO=a|yVPRdw`a+4oN z>y6Cby8((`%}ioZuy`PkQDC9)BDA2}wL0+ELM&(1h4VIyd7Bl?=+7ad{tw{T>x6r` zN&UH~-n-<&onEm%MNqH~!{AEC8CGjc)gxf8nZwDZ+xxi5$=XI)XI8enzgb+JyqfOq zsG`1}_anMmNU-`q<3EB4yZePTL0ZD;_fLs5RQgFF%-~AWx{ChY9D?$6^B>hfdiuL4 z(kI-n>^@~o_u1OWY6(A1$EQX=cjn1dNXE=+iM5?r z?5^|rQfZ)yM@78;)tG)>vo)t_0r)2^Dcm-SYTQ*ndH~G-48RGx7wvA`-EIqrl++;US$O5WT4w*}R{nP!q9VGO%oRo_!S&XP7GKnS5iQL7)!v#!dKn2 z{q&b9C_emy$l)JO%YPNOo5tHe0ade5idWRDpyeX3CIZoHYl9;EPQ!qilBM*~Myuq^SrJK{x+UR7Wu@Lp z*LekhVcz4TgTG~=pKPq~lX(-%t6Y@-nh2)SJ87{~!SfBova}w>75Im-9+R8fsqIw-VHS=Pcwpdv0AIB&Ye{|10V#)Lu(ipt(gU2 zPC_BJez`P^B6^W|Dc`7M?K9lUJ5`Yep&nlwZYA_>0Tf3KNI7lW*>|o2okdTDU6F6! zM!2RT))NhH&Cl5EQwSy5Q0m;VnO2sZVZMVXL}G)E2;bzX0p$n_ZFlh~>e z_^c$p%jm*EGD&NQrV)iCdv_aq6^^F9P(#3io@*+pw1hH3kwz^XZoKo453vgK%-W%Q z{9yj1LRU?{Bi@J{<|ObyD_fqO@uANj)-|bWJY`%GFp|3BmnFVA8jxJvgtqzA6CFlFi$+Lpg{1rklfIyLzhy$NJ*i54fc zu&N>!m$6~|Eec9DYmj#_PthSijfL0dxi%7%S2b+b{*RraY*;XyhMrF2lWPJ$UBE!( zL}KAi!+ZV-ZTySu$>#XuelT=ysIKuZuSFU-^n_K>qxK<0E)OcyTJITC{weY7+zSBo zGCfJikILrBbe&&6zCf6|a?5Jz8Os(GLW?EMLk31D6p&+tmO~uwG@37|8{@aHQ(|ga zMM#K}_5nnYpO*5JD2fk+;%5&&!qacu)l+I0wl1C`e-dJ?47Vv=1d=~t<>>OUy2jX5 z?rHHB`!dI>Rf+sP#_okZyb5U;pQ$2RscX0MS^VQ{SXjs*qA$GRq3Cqvcp*(nDAmf! zeKFFHfMf~X{<5}nQFRbPDU4>yjf4raokDvA1;JS%Lw9XrZHD~RkB-?X)AH9p&!v%V zezCTM^4%ZNw6_Wg#&$91M)bkURpsiCLK-i8wDl4YqbNn005zowj&zs$wo>Y@1wvO= zu{<>7FsvZMwku)f8tBuwy=#J3MueGB89EDUPOL`m*3C z!-ICxLf*%QPRgwa#g=0r4f}7JvQdfNQwH@!6Y>%*4|uvZCl}r2Z*~LeS!PzS8qj>Q}beHjzoq!SIaZC8*&XfxN-mMyrpIt=F_Afj23b{q~%PpLQAax(77SnR0jv+?tj;CEcs`v zuj8WbD`ZAb_W1F1n$1^AwP|SS*nJ2k?*$rjGwNf;+p<`MQ{iaE3w_KBsnLaix8*7c z7U|S5$l+MH5mCE@V)H6;fG%aFR-gMU+ilLTk%P4#zR9N}u{NOh?~;(vUGl~h3cUXH zM4Z6m=X%EUb;y-rjUy)M%TQiuzB>iEv{hy_QU_B$61KwhQp z2kB*AZd9}dtHwneYsEJ<>M-XVFiO5dSaA2#R0=$cL|tV<^6xMUxDM^!yex`0bc(|K zMUkWonkg3puVI4S%Fbr-#2nq$=~{qt@LHg1y(7P&s%mH(nT6~)!KIr%ge`|4V`CGK zr99jV0+0uLxC6arNU>t{bqXo4AhQh&dWG#B8!8=`$`Q&(Xl*$QVihJCn!+IZ0AIdK zIEmBmOSzJxDWId%exoq6#4YtM=4Mu>DGg@-c3SS1O$Osqtu39#VRHXEithwQqrcRs z_E#xpa4hW>rdCLPskI)|bj$o2X^kOT?=%bsDL&QlS1K?me{0%62zDtGMf2dbfS_TT z$Bz|fe}>fW+(L&&K}x+JGZJubn)rNKyKxnwoe|GiYylhlD`D58-zvC$>mciV=5J0& z&lfH*wwDYwV*Fn%fX)IwhZNktEAOn(Lie<5zdp8I>m+dhUaDE(cNW64Dyp@APFE( zy+{Y0@bF_~g}*8Ef~pzhM`;IEff$w84DiWVxwNmbUT?bipLwScDBF{`nxir=FL2hB-$y<1!9~8Hj@08B@Kjy$K^k`q!HOi-;q)vg;xK`0m6Txg@2gxM8YZe_pnXb zcW!F9<2^jG6BpT(qkae>T!ivQ@#Y}AH#fz^nk^!_%dNywobhEta#adOgITGdU^eZbv(BP1q6+vo(zJ9kEY~k1lXW8 z>K}B9Bz^HhH;;+r?qnK0R$bvgoE6qnblP~0hvF@MUr!(;PXD)rA3TX{8s5+xuAVw5 ztU^Q=Fj~O*IzvpSKvtc%psI>=p7rw<5+I}>V0qg6WY_GM zH+FqhZ2L@bJ~nD3q4@o^;^A3iNWB` zl`1oer_i|db(IX<@q=H3p5HBy7DXO`@H-BnQK!waMarjZ{Dfm%L_=FFLru-; z;v6H$mNLdcweL7h9vSg22S{MS1aJ9OpWJU#=DH|N?_7T?vWF+tGbvKr$qwpD3jY+^ zXtgP1OM=Gpv~xm#tiHlsmztS3Hg9S^*Wd|1+Vd$d zc~PiKTBz#(tG%y|YOCw|OodXQg#x8mffC#)TD*l&+>2XrcL-Lbg#v*B#T^R8gS%7Q z-HHW@2lt?1!uveW%)EU&>zny=*7|_8LXvy#y?dX%_u2Bh`?TWW+&BqxvX7}ZC73Cg z(C+WQR(IXlk>zoQIQD(P0q^N?nET|CM2OB8U=c@tJw(Dc0}T>;+%2yg zTmd|Gq16;$3f-6yMK>ff(?n@TZ2j-A)D6yB<78KDlkVC7@>ss{z~_(#hYlm{`t~DE_>6B*_)?nn=715c}JMo4{PToB=+C~ zV7w{|$#8!DY4SvssD)$2zK%; z`%H{+2c%Am+xrVsIPOSqH^c(=_5P!RqQUDd?()7#U-`?FosxaGwH=?RNJqQ z$>`*|V0A`Z#tYHiHiYP2UV4sydJfXoeBG(Efo-ioUZl(ZD)2=8W-UqmCfl1{kW2H4 z7~uUyZyVpvW3dI~;IOU1271ntJJeAJCtLpD{o&L4zfLeE(jJWbFs@9jm=O;9ElOaO ziQ%pC57wa66D+)YfM}bebF@H8EbuMdU==Evh-J>T9<^y>fu8dpu!4GE-(=}QWE`cc zhztr=(5D`W&DK(OTAHT+bI8FvW{IY>>OKGBTR_MQLKKmn_w*4oMNT zUu)y9N~(QcW_*M+aPpa5b8gAHi#eR9Mdc7}e<4Gven^G%?BFna{#n=Ai50hweZ3DbA9xztGzujK!N7v!!J`Gpb? zL2(ZcANQ1MjC51NNV!l2*{qaLir1oy0a$XjFU@^Z49e^C*qlnSTOS6ujgVs~ z;8RDZH}PdIII02TJHY+7Sb)qY!n7$sZszwzY>1C*Sa zwptPB?0{w33VmWgHzxrzdd=OE)|I7LuV1j_RRH@_io3po_^b_T5Trt(qTTP>Bb~yM)(vy{9R>?;Gp>VE7%GZ%L$@ zud!){h1SJDeUW^SL86le20(0VOfPt|4*UH8{lCigtm4Mc>-rroso1g9paiccPAcAK zB<6>+@udB$2>EcneeG+)BO1GbqZd?_k|Lw)Hym-LE$8@Rfvawa7l7C2-`(q>W8p6$ z?n8H^IFr9HEXTV$<=Qq}Z*;>A031zQ33HxJHP$D25rge5<>rA~S^p}_uL#La*^qPJ z>A|4KdLp*Oe*X*U8R!W>WkpKmUnO=23P~rlKK_So>;>3ih5Nky8B|meizehwWh!67 z@2>p?%}Y;ef4-LRsM8Z25GqrJ+0qdqR!lpF2cVZuQ+xTy?;e0j z7GAviEP=yJuYW2=7!YD1u9fk%eg-snZm+dH+}s|ZwrYLpq;mL`v#RaH@Slph37?85 zYr#8@*#w5*`@<(Al=?@(Z`4)Ed^7Wo2YwE4$=%(^=bwxcjWpJR7(Ysk1*@b*JkZFi zKz;??JdAMwM3VRj{d;}9+T+<}o7LY1a#zLWkO7^)^e{ZDw%<2AkjjCcM>RI55nK;X zRb_tyaly{1qkS;S|F%0haF_c|ys|FQ!I9SUU^&;Uc_LUXs~I2jw=?a%E(7<$x{At_ zrXT%VPv@J7kgMV^nk%fG%9c1Q+pOnK>~|5!w1ymVo&g=_2F&U>8t&#<&YkFoRM2&V zO8IRFPih(Lp!lA?Wqds9yyMB^UP?0h0GBT*E!M7lc@E{;97f;pU;4KyNrv_VdrDV2 zbz1o0r7Hen!FQtlh&_8+OTzlob!aLx6uxm&bdlKzv}1VBvz}$n;1PA{jJZ{nmmgUh z$-SMyQ~hK>R)8H_`X%58))$wn*_^z8mHURfrn!v5)mFx>2cLtvACeW84!+rNb6J`9 zbZS0}>+`?~uh94ZG{L9u?ncb_)RViEXe!3d3}+6t(b-z>*^t1pxGT$LZ(2fKTdBZQ zLa$AUs2`Kx6WdUmQWog1SPQmrXYAIUQxlxHuFD@>{Ac+M9D%alD3AD_hC#mD3%Zdz zW1hlbVW*^4sT7fy8PiS_XMH+fjrOoxQnq4a5S_3_r|Hdv1^&+lXXkw{FQfXJx>>Az zY%`tQ0>JSTB}FH3l8237ddL$ORe!QuP7;K zDC&?jChdLsIZ?FZ^=P^>>nJ7H6M`~dji#B`#$3BS!WCer7V#z>72Zaj=+@JomtQwF z$$^ON*I@f9R(V_!cCXk^(t|yp^IDxjv^0gvRqA0p&on<~9wOr}{rXmsZnbl($oSR6 zOI%P>{pD`MQIo*RZkxO5+I%h5@vgv!^2yWwROPQMye0{zTD=Whjq$1b* zrDBbdf(~4bZNpn)J%M{L*Oi~mX+o!+6S3L|GVcm~*8bkkV<)!MSICR+X}coMSM`M0 zWT@SNLL1R3gk}Vi`g@yZ_CGIoVbiic-$_df-8wu9#6GnnedV@&wk75&7&V6PY-G6H z8Op0Cw}M6%MHf!qJbbf1-=!aCLu)RKnf$Yo?mEC@)!YafO6%8}{RGv^=gIufH$rtzVy>iUeB|M)bVj zuR-`_66{oYB5t5|&Nmm~%`BXD7d~TIO*LKKi&j-ZH56w~8YtvRMP&U>@6P%m)+EzUPQ$A89X( zxRcM<$nR{-?qrsB17_iZGd|1psD}ZWgw;G(ezpZ(hKpRl1H-*83~(c+p@i}c4re~m z4w);Ez;M{v#sP2G96gZZa(7Dtn><-trj*2`2012iaal|*06s(Qj};aa)IEVkhl8NF znEXH?D<{HxM_o)asU9J z(GeRV6x{)lYEW&Ek{a+AB$1IEk9jA}ksvpc+i$#w+S(9auOd3ahL7n>-Cx9J77%C(~`(vO^)U)2<6-wGBT5PfGZWW4yNtF={=2wMw25 z7uCW~Z5mPU3^sBIw{Ra@U#w{pV%rIpvK{Op6>PnNQ_vI{Xc&*<>Xq~D1zOXZFD?|uts6tpQ~dmJy8-08qgBkd88 z9H0G~b(oReg3(P6nY513%OxKK-%ScXosPjtjrZm+q*u8FMdRggDLzg}KP_8>_x9qi zz%(;A0bk{qq#9L2$`#i;8n}$4W}j3IwzpSY9)O|^9$VG5J?~5?c&`eP#l%ej zCsu z_h=%sy8!lLc9Hr6{J9ZDB75cBx}){Myph$yCF404m5x4At#jpGyQWF`w7)J#LdD^b zffpjfOal9iA0i{Dw#Uf*o(y#(zH27@Nn6=Fr-Y|kx;vK0u*Ixm_hMs&EKLEM*Syph zcYPte%t!A^3^oA(C{_=j2Dz5J+!!vjUibnt@k_m}y34eJb=ZSu4P!jjS;TA_T$Rj5 z8l)h9zqoOunL}sidvP^+&5*q8gPb(fzKdGGQIZ%)&zzTz&;|Ib^d{VrqT!M0=6kP` zW=&2%7``86_c(-9@~sCeGUPVH#%Ku%5ccs~S&7-DTwk@mTn)#DDYdz8I7 zZ0iDMGE*cZ7l38q?YQKN7wC4(nr!RTHRp2Mp6ohafbZutFMBm_wxHnF0JXf5ZsTh` zPuD={6o;EF2O%mTkPiJgy-j|v@pPvRd7f~d)2XTuE?p5UP{mMgXK0|Ss_6n{Cok{xVO)+8G$K6jQq`QbCjc(0;AJbF4ZA5ktA5K z=R&vrh-an#~iN7I6@#76B~uNs;qZA096~?}{n!<2RmW z%_rY~y=T09Vz5J5rRP#5Gd6%vO)#zmY?$r;U%^(qeswE9q;g#e5xcPFC$mv)n zWHqu}gcTTeG3OTnJI{TM+2!`?&=cqF?sS2%R!;Wnpyx@_0+u0yZ{Dun=R$V};=Bze z|C#0Vwy?cGfWnb~L3-~+M%4oTw9xYPd6Wmj#~BPume)uWUT-?Dh{fA1X}5?~?8!LJ z%G?cs)=0iF&cJh^Q6CLF>lcft=V5R~U4v$_NDJq_S=wnTvDVM}@`dx|YqhNkc{xi9 zl>;@Yl%q5^eo4ry`O~zkh-4v}YDAtSG?IMJE^?9(oGS?p-ac)<4!V)oU@?PXck0&j z(!PwSRd3Mn+$d>wOOtNe@HTpp^Yth8dib8|@`4lO)-XPKme4+a0gk}=G&0v*p94E? zPMbD?dTn6$dG%c$<@oib22pA6g?w;`JLW3Y!uUu_n z$B7ZzT_@3!6=NQY-u0ZyCHgNt1oKRyCVXDo#4LWM^E<+y3GHrusv|RD02wQ&iR@tl zk};AKBt-lKUov?XuJ~S#Ti{A8*({+vrFK_7SKCO4`aGT9FeebN8k-DUwP2LyHA|6F zAC0kva|+E<*;P-I2~6bOac*)fzDBo0Q)pxWYPHYI{PNlAdt=;u6eDy>sC7+8jy>nS z&UUKprHd5!PD$WYR}dB?8@5&Zt=P>oo`1c$R;0`;r_uYzP}rNQJ>>}a`+c1}^;?4? zSIEu*f%4!=5g=2%TPB6nprnEbov(vK2P*?+*E@~!L#$ibV=b%a^O1fqrXvfby@pLX z*H;i$8b2+NpaRHvW&#KtgD1IjxYpTrf3H5t3xcBS$s$Jkzn~ALR3QzUF=t(sR8)Yt zR-V;2^TjO2c_tFZ9b4=<-4<#ZJ@1r5y5$@qWJc%BI%ZW1hJsVDvuEBh168DOab4SQ zkmZqrybCQcnDXJ9FyV=5R;TlK@}e}LfIvczAFOGoO)r_pG}-psYZoKw26MrP+;K&F zDG=>(MXtsqsHb|TG@~d;vY~BrM`bV`A(E!xddWOOE+}MA`_ntHvcAiQmXp<_v9VDs zOYiYu61mv@_p9btg7>+iJJT|u?X>eHCqwiN<5v|t(FDhL35v|{a3$JPLWo8A^6SN< zII2}lXo=)3rEScS?r4T9rzGXbT=@KL|c^^ z$id?Ny&xxB9LP9RHw5XXi&`zK}5q8EAeyBnVUAxf)sS10FJq< zayT}c-@WPYvrZoV&)`ECsqVu`q<8i}S>LCSS0B55;784#?ILV66)3#&e)2B7ysFD@ zN*SnhlAyQRw3B9YEOHm+R(!L?q>748eG2KKVRhtN!GI5ogMg7ou86v#>5VL$1WseB zvIc(h>bHH-@AP`2G5Lf|^d__%A=>E6ZR zmmtY?p@`z`UKZ2t8z`j+EYEhU(t}rfzCJmXtmTIhtmojX5v!LLCx`c>kMy|yyxDy1 ztcZxBvZvd+sz_}ctX4(OQ_8RrtNL+3l|m&7Xu}wLay|uD{H!jJ==ELI z5KUnG9VA9){ENK2G;?-c{rIsP`>&pJC5WB!JO)h^>h2}SH)k`ATYc8DoHc+>_?UrG zp<8JUDP3N5?V@cW9~uWm*=4sKGzy!>s4Cfa;&7G_X(^ zR{$0!75+$$0y>`3wdX`Dou!1=u3kMjAYnm zk3a$J`V>4xk)#YE-*WPbbnYVxDl;aFtuUsEiolMa_3GZ}im_^R%xwzABY^tOrQO8E-5l6&V9$`;RZ>Bwe6p0dxe9xT5N;#Zn zqW7Ft3d_;Zfo4Du|i19hco{Aj-D4)S6xIrKRdW zXD1dsiAQ|)+^Huo+rz^h8N+YE3O_GawdxU+Ky~rS;k^vM*g4fj4A{U&%>3x&LtGi$ zmZbKMJPUW{!RyiFBFjP!@?NEEThsxl#!q={yJgM$CZ0tBLxMYYLdh6B`HF!wESfzu zS+o^FG*UMy$L(z``~LG|St|HWMsp|OVV)_7+1VTVGF=d@U&}HKCsM6qc6a`!xM}2i zO9WY!DetM!u_N-+#K&UlDny7Z*%Nk&oaV@mAcpR{y}$AtQ$~tuOQWyj3gwM+u^_vrbLI{q*;i6kFh%AQkH`R ztQs6pNVNIA@Ft?clgIk!llvbhu_!#(tDTy2?BGk&g0QRciVz`TlU;ltot;^`j;>E; z55|P}N^O}aJw7la@SEx49-q3!YV-ul(Hzn3q%Z_MHg%k0&-+X>BPNS7SB?@5`6q?9 zHq?FGrD!2PF}m9WT0CSKdhYkVj@!TsTuhK~j6Rr9q)|nn)H4&}nm_12Q#ZA1^H|R# zwdd0vfLw8Q%7gTK@{hnO!>XSwHEaKm@%P(qralean1aUHQvrlE9wM0BZPfEKHao@2J2Ypq4>EmhgV{1@j$1fpKU;&iIQ; z%deK-F#HQD9-_VmxV-(}V&or|O1&JLE41mtc$efXCemMF6b&$tkCf7($-mj_ zuR=;3?oO8&h&{Qlwbd_lG+VncR?YS2;5VL|2vEYowQv;=P%8=`(~FGA`-OQSB=vWw z8}xV1fCp96Leqx8F;Pc#Dl9QpeDYQpMa9jxi3H#+(*bJ{184yA2Tb(3cYXwy<3-hA zawGSoexvC&=a3r+6AL`rCFTdWOUey%VUorS7nMX7`U>OI(TLyxc_AmF-)`MoVPTYVS+;=Z zq!i38u;vqwhg(WUuv5abTP;v^Y4`j<#pMysTEk5;!n-k?VM<(hGRxMUnwlsCTFE<= zN8(;APMtsFvE$-38K44FNFAF9!&mJanCvpmr#QUjjEt7`{f1QjRh$&v8nWiD^QroR zf%+?zd%)Wjyu}|$Us=+YC{JJ&lV{+i3(7boO&ULWDa1`vN)BxlV^+@zC_B}6M33O! zQZ4X81~5&%J(fMCJHV5Eg3DBdCzMYE9HV-382M^zVy5a``q>GaR0Q_K3~gkukGY(V zxFb$!k;MEH!h}dGqc@HX-$#KAh+QOPc%T+_756WHl4rC~}rV*Z4~bm%#u%qS7-(!KP;g&;R;x_(gz=g3M*! zs#@WJ&y6HM)}XXT8vpj3cQ|r?_9NX4A;F#s)q=ARZt2Yc)#REV$6@>>*3is}ii0<(`h-Wq$y*N~c`P{mJ4H8>Q&*78AW3KFb@5F%%(2;f=V0;T-Tsl2$2>OF z%8UJjMfw*~u*MGVHSE3jlG+PkhSWOBfW5ws;o^-ehh3!97X;nkOToM>XwVpux+(m4 ztP!-;hV-N`7f3hE+FO)D{X&}EZr(=VO&)7lQC;-<-t^T*=MZ0qtY5*qGsIUhiZ(2i zM*M?<#tQLv@?D}P$nkM4Z15AF;^L~`ENSi)nvEGif*O4I?Zs#6)?^&UXZ#PN-k1iy zAZ|F1L)|a@g_Ha#Xdgxs0a;9hZoj+zFEcecR&p{X*tUvi`}WWKlGU?oDkV&E|0w4= znhuD!Q*LKFp{^$%NCV_J$`(1S3bQWb#{&ZM?)WGdXrJa5sB5`cSFcF3^F(_Nrk)iA zY5SF)pfu-)^0O^Yr2|hY*XK`gBZ5Fc>1;nAq?KKb{gaNR>@H_8Vc&7IWc|-D;{Z+O zS}~eH^Bu*i?iJ8vThC$}PG+G{^H+N*uYs6TFipmkZK-j8b7TqLJjX$H9c9rK1`CiQ zE6S`gs6Z-rGF}6yCi+21&02WAZ;XQGWI#LF261L&_K9hE3F4NQd~`&2@+HV^scuOj zd+f(ubr1)i(Wa5t;Evakg8fNxz^5MgabcA$O@_$x7;E*nmDXxjQz6viku5)GJ!H~i z++aRFMGM)pn>Cs@o8mX$KSg2dV93fgqoPp&bK-!D7xmc-20V4rYK`4lm_ieNG@nTc zc6P9935qK5Kzl85kp7UINK)#kvZ3)(PbHJ1lTM+-%9?F04^hLEk zg404gDg>3RXxrp}Z+D$|J+$Bu7+@@y6x4mvlT23=1q4P+9uFWM_$k;{)q&6UaDsyh zW^F2KF3ikC73y2n?*m9AX}ubdW9Vj)Ye@#XG2#Gtc z?gT5*JhmOFtu0D93LFX!>VF<)4YPJ}zAwU*)0X)LR&TmVe10^r8J)Q>SoCY0IO~ zC24ygsW6PfQ^eguvyD$Mffy$sEjnCi?ZcJ4l{x*xwbpMzlHf+z5DqW=H3PN}uw^ zQtb>cH9@=vgr&Jorq2P{UT7Sg2j#)~-l6Fqh&YmUtl0bM%Hk2FVV|`9cf& z1?4feVv}OHM$=}CA6vPGR~9K~w!x)gC4KT0((st8IE)>MaTYJ>&Z}@ilrDd_Fw-pt zffQ)PK?OlUK}o8MokFoJWy2PD>bmt4+wjHfen%iDKOb${#@D&9n8Q~>lXW~1C>^4B zjJAvIshdVZt{+5i3s>SGqwac^>UjO-1_nbdm@Fdc#{Cr9nU`A^Sy}2HcK|C44sUjW z9Gd(Rrvx%;43R;O`-|45^=_@IsRYqr0*{n9-5V{llc%xzw%+RVGpY+SN~8JN9x?W#;EsXNs| zqSN5~qHjUD6={158l;4{6ELe z(Z?V+F=TgqrF-~T+@UvEzP^yLbZWOw)B7YNt$%Ru@c3uK;ZB3%VG zKBir?S1JqGK?*1tRW!@;;y*p^c6zhacWOsg5qL94sBp7gh6*uO0L)0LK zydrjZp^>zdtSvL%W?Qkz{ZMV}SJnMCp>84{8vI|9q#~!6VJG*%64lobc`qBmv%oGt z(%ouXhDJOFA(njAPb*i!fq4cjNi0%uDk)vqq3@Vr6Lyp045$U!i#SBs(<=LWZvt4sG4KzaR~WljFk z=9>6~Y-?oPGkE;S!Fa~O_;>DQat_zm@X+Nh!T}ZrSx_E`f%p|ostYYe_92$u5-t`K zMdJFHVxB-cVNUiA<5+I+x~pm_Hchrm%xn>(`qGd*gTx~iOSCM1mdn73eFZVORi*bEWNvc{s zXHXon;X|&W>qlQu6YQFQDh#y>x!M%B16r58M~(SWV;Uwa?9p=RQ{**^?YSi;4H}Za zFLDzm!qISypCpypg&c2;-FZNP{OJkphj61XbCh{+0`n83RCBwnB`4&Tdg;sLms;U* z?vp3_du4Myi5!IGNI36F^Q(lnF2?%Z-zz1lt-?BZ<67R=Gm1mxijY_;JWj?yVDpC_ zk&{Tfx@WYyB0Jaf#F{UuKBDfZL`&6*gN2K|6%X}>t08y|RZQg~Ut438GT;!ab;nBR zc-*J!Uj+Ir^@3Y^2~}A&R`$Zw|I9d;{;r`ynN|$ymskZIj?UK_;!w{dNru^&dRQ*AHBhE->(eF1c74f8NQL)KUiv6YN;J zt4Y=8mtS>*taPt1r1KJ0Z{4IHj0B@*hnLMammxdXZ4}6o*qGZ4XNmM@GpEL@!@ke1 zyYuzcoqvD$a_~MXF+uO}TCx@n$7*|k7eaerCK8?ZHo_Wtk<-oQ89ZU^2p=2ruHZAx z98hzwXMAq&XuJ?nKu4~33_(+`JbQvWL%`TRcT4|oNC6233-xJBE-(AF5j?2U%IiMU z{ow)LIIG&7{Geg(`AdcD5Ee%`NxD*kkjGIav=j6P-kXjaMi%9>*MM9j#HP%r4@DFD zk`kIMOc<(>Cl>0aQ(kOYx)c2RR$0~1i*G}J0VqI!qZX2|0KSY&ynDHGT;X_x5T>{m z>L_LGl$5V3TOX=A-<{RzH+mRFT;oHa?h4G+SH0YB-y`{Hr81uWX+li;1_gRywb44! z{lW?2q*)bLr6{SW<)l?j-H%GytlB3DPxLKsyq2n}?!@8ES1C4mKm}Sv+w&>n!}imHect ze!o$OHMBNU?`oH_bvwcDxv?O!-e+wTlg;EP-LEELnG0L(k>$`{`cOm6!UCUi0LM<@ z@|BsjvsUXG$a@=SL~|(rD-{DJUj8dH)K$;|0F0|bEObNJy)5yyPy0(A$Fvh@C7>ux z-*%>YM>h6YJxuto6wyDZ6>C=1yuZ-L;;yt?XsQjxr!%+EApQfU1Eogwdrh9U%PT!m zPNb{yM==bP?|wz=(8(v$LqGg@^;>r7{~=>`#{@&yo;~VyjC)0UbiN~kElXI_$t)%s ztg0ajHeoELR7_8p-f~A+|16<=c(>4HE%kh7ZV#@V_!}j)sD#$*BlC*P?BUEZz67Z{ zOQlyOzgv)h$aX*p+4~MA2RA9rdz`_=wR%PU&s$<}*f1tuEL-|Y5C6N}DSaRa;3A&% zwZntl@8JUidyJ*d)y2zdgU##-Gzo++A**ZB1e(Q-XUe;MOy!K`j!x3nj`Zy$`?p$^ zc;|0$OZ=@wzXeH4Y4#4p^lqzdaW8YKII?K3Vl~FOg>mr_N&G>B%*j`2O;le(n7DQ} z+adTS1d*DsQu{ZZcvF@ICr|ZW@BDVFx2ZpXT1fADZ7+Q!n8t)wF{b93@h{}6Fs`}% zAH>(!G&be%-O{mI2Ud@Y`{=t<%P(2|tKx~z5($1Yf&Uvs2au?EKrk(nAdK20ijRoq zE_1+db8#zGie!-X40q`sA`dk1iO}h+A@@|XGzv`rLVTlPpX2d%t!PV zx*FtvxWtd(>TQPF*O<>p(0`-ub_IA}sqt7!KOwU~IaY^Ri6G=|@NXLX50dIu;e3N6 zfl8ej@E+qvbnCggxd?0*Qte1V=iKh^5TmYqRV|2kjKE^1{l#M4W446G$}d%PKo-J8 zpN8ShKUqqsx+bxXs=Fa1Hl;pBNf2TMuChE~OKn%J(XK@;H7xmc(mLWzb9042ny-@+ z#(&Vz_Y-+8tdnId0uZa^gJa@G&yp%B9TdAi(~K{a(ZLz3uYin0i;Q~A7P|!i&mB9RX zoXPgyluW23#)PV|Da&Dt8o?iC;q?H4)FW*gysogAGVR0R^qGnDk;ocf!QW=~?}fl9 z8Rg)y8%?WR$DXt=jXjRrKs7=XWe8yQbdxf`puv8ndHSw-Rk*am!Ax$v;k&#+`mzTNHC@Lj!aj z9j2vpK1*rRJX7603=#iY|C#SMDsIaWzV;B1$926ihsZSTks=KThSq9PhDL6Q|J$T0 zCijiuxwpUiwGsk1v$Mx6rPRP`wKDY2Fj+os7ylplPRjtD(<#Vbu~p5T`%>JGe4I2n zQNmHH=aQ5Ooy$ahkme-#pnP<5!f|Dr(loy98O#Smp7c{n|V_E0cZp8IdURSwQ^Hm6()dC83ZyGj1X zkpGRk{Kskd8|wJCt@?LI^q=a;e-Hh~j{RS<>6rjO699lNCk1-*4z-~9y8nN}?V*>t zDCbI1n}vnNWJg3mKszuaR!NJYBUZ!oAXv3AcQe1iu(IYbi%>i5f!cQ`klddFj(q&Y z;>aHF9_wgSkDwZDf)GX}gH3sYko?RF#{4C|XLf+qSp5}M?8bPL%3zb~iOp21O}~HF zfbiP|ahN{1Kj)p`7VVL_L8?M+7Qr)Bsg8V9*!+--_BUm{T@E!|@{`csb;#!Q;(yJ5 zCG-vwB@iQUqp?a-W!R@TXFqKcSvvXqI`Fr^cfCS6d1@(}rt5@*rrI~#H;m*ni<(cT zN(lPs9lj2g^;usr`C|ToRzN-#3X|Fp7|itYJg1}r7|2@cuk}<__px?qU0%b-^p@Yo zFpLqP3O{jp1Q&g}|3#VZ5n#C6)ULNH*yp+)ir*PQ~zC~yHFY4*N=5mk~wtI06%(P|F(#u;`7`@95#I( z)VHt2YLaDRFQ1~g|JsGV@CFfbGwY0Mas2pKN1WcH3f3(KaA-aXoDG8D5rCVOKhGwl z9PzB#(#K5mUc3An?2p^VTljE9VcmsvljwTPJEs^Gbq|%o=<8WoKo&O(T`Yuq6eV2- z4PF-=kw5Z0x(g_HAM%z~6R~ccbMMR7ZtAVK;4eVUH&SnEzDM_leMEt>6~9%QvjF+) zXQ`d28ebyh%#bgw*imjcOW!$E1y)|Mv43Xjt~>aWrj$6_!0x~V!ZWI3>KhQ_>Tw+lj+t#^!)Rxq95)8 z=%Z7Xlg^jbVfrnjZE`3Dd_VCpT&@g8=Xmi`48}F;v($?tOMMMEzyQ4e7@Pbtu zh`Sw6KglD&K+ZP2Hh7RMSp-sItS}IBLILmUHF3otz`;k$f2rD37VnJwSmiAJrU9 z@hmkjwba53jyt~D73Sv3YNF~t?{$1aS%+5t02(dFuGA+9fY&OFCb^K62kap(Ns@1( zGs@~DFpcmto&tRR`zy+xL`ceOaHLW8U!nuJ@;W@^TEF9Bgo}wb4|LHOJEHal?M`wO zre=>whETvc@A#UkN{hxZ&)eX6Ff|rpdPoPMy1Wv9hB9oHyb!-d_Yc^V`m-`j+5msu zlNBY8N;dZox(|55$i|M#u)&hB@Ua>XV6GQJ=e+8Y#4NA=M!>(+J?v6S5Iq3Etk zw#C=vcongajo(A;ei!v{5M~@_!cFQ_L?oP#5*3pr>h#Q`l8bae@n!t<>iYo27j}6a z$pY)>3G66=D|i+HPU?2_!|w@E5VgGrco8Yk=|xG)FlUVNOA8)kxh6e@;ls2e)4Ds7 zP#serrj%zn?dojs{TjFrQ1b&`)6(3hQ)VylA4Z)xpuiW@S| P8zM@H%Y%wU-+%faj`WxR literal 0 HcmV?d00001 diff --git a/ext/wasm3/test/wasi/wasmsynth/README.md b/ext/wasm3/test/wasi/wasmsynth/README.md new file mode 100644 index 0000000..c9eb9d7 --- /dev/null +++ b/ext/wasm3/test/wasi/wasmsynth/README.md @@ -0,0 +1,24 @@ +# Wasm Synth + +

      + +Here is some music created by [Peter Salomonsen](https://petersalomonsen.com/) in his [wasm music experiment](https://petersalomonsen.com/webassemblymusic/livecodev2/): + +- **Hondarribia (Wasm Summit opening track)**, `hondarribia.wasm` │ [SoundCloud](https://soundcloud.com/psalomo/hondarribia) +- **WASM song**, `wasm-song.wasm` │ [SoundCloud](https://soundcloud.com/psalomo/wasm-song) +- **Shuffle Chill**, `shuffle-chill.wasm` │ [SoundCloud](https://soundcloud.com/psalomo/shuffle-chill) +- **"WebChip" music**, `webchip-music.wasm` │ [SoundCloud](https://soundcloud.com/psalomo/webchip-music) + +Check out Peter's [excellent talk on WebAssembly Summit 2020](https://www.youtube.com/watch?v=WZp0sPDvWfw&t=18670). + +### Running + +Generate a `wav` file: +``` +wasm3 hondarribia.wasm | sox -S -t raw -b 32 -e float -r 44100 -c 2 - hondarribia.wav +``` + +Play live (choppy on most machines): +``` +wasm3 hondarribia.wasm | sox -S -t raw -b 32 -e float -r 44100 -c 2 - -d +``` diff --git a/ext/wasm3/test/wasi/wasmsynth/image.png b/ext/wasm3/test/wasi/wasmsynth/image.png new file mode 100644 index 0000000000000000000000000000000000000000..992c4c458c65013aa9bc2369a2a7317a1fd90bd3 GIT binary patch literal 158769 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�YLu6Y+tPt@xbKJ!+m; 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

      IZ|+uZ?IRTFO7pxO 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

      jQ?|FLRMR6O&fr4f7Aqs9Ia4g`G?( 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 frameSize.x) + { + velocity.x = -10; + } + if(ball.x <= 0) + { + velocity.x = +10; + } + if(ball.y + ball.h >= frameSize.y) + { + velocity.y = -10; + } + + if(ball.y <= paddle.y + paddle.h + && ball.x+ball.w >= paddle.x + && ball.x <= paddle.x + paddle.w + && velocity.y < 0) + { + velocity.y *= -1; + ball.y = paddle.y + paddle.h; + } + + if(ball.y <= 0) + { + ball.x = frameSize.x/2. - ball.w; + ball.y = frameSize.y/2. - ball.h; + } + + draw_rect(paddle, paddleColor); + draw_rect(ball, ballColor); +} diff --git a/scripts/bindgen.py b/scripts/bindgen.py new file mode 100755 index 0000000..348e108 --- /dev/null +++ b/scripts/bindgen.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 +import sys + +if len(sys.argv) < 2: + print("bindgen require an api name\n") + exit(-1); + +apiName = sys.argv[1] +cdir = '' + +if len(sys.argv) > 2: + cdir = sys.argv[2] + +inPath = cdir + '/bindgen_' + apiName + '_api.txt' +outPath = cdir + '/bindgen_' + apiName + '_api.c' + +inFile = open(inPath, 'r') +outFile = open(outPath, 'w') + +stubs = [] +links = [] + +def gen_stub(name, sig): + src = 'const void* ' + name + '_stub(IM3Runtime runtime, IM3ImportContext _ctx, uint64_t * _sp, void * _mem)\n' + src += '{\n' + spIndex = 0 + + parsingRet = True + retCount = 0 + argCount = 0 + retString = '' + argString = '' + + for index, c in enumerate(sig): + if parsingRet: + if retCount > 1: + print('unsupported multiple return types\n') + break + if c == '(': + parsingRet = False + continue + elif c == ')': + print('unexpected ) while parsing return type\n') + break; + elif c == 'v': + continue + elif c == 'i': + retString = '*((i32*)&_sp[0]) = ' + elif c == 'I': + retString = '*((i64*)&_sp[0]) = ' + elif c == 'f': + retString = '*((f32*)&_sp[0]) = ' + elif c == 'd': + retString = '*((f64*)&_sp[0]) = ' + elif c == 'p': + print('returning pointers is not supported yet\n') + break + else: + print('unrecognized type ' + c + ' in procedure signature\n') + break + retCount += 1 + else: + argIndex = argCount + retCount + if c == ')': + break + elif c == 'v': + break + elif c == 'i': + argString += '*(i32*)&_sp[' + str(argIndex) + ']' + elif c == 'I': + argString += '*(i64*)&_sp[' + str(argIndex) + ']' + elif c == 'f': + argString += '*(f32*)&_sp[' + str(argIndex) + ']' + elif c == 'd': + argString += '*(f64*)&_sp[' + str(argIndex) + ']' + elif c == 'p': + argString += '(void*)((char*)_mem + *(i32*)&_sp[' + str(argIndex) + '])' + else: + print('unrecognized type ' + c + ' in procedure signature\n') + break + + if index+2 < len(sig): + argString += ', ' + argCount += 1 + + src += '\t' + retString + name + '(' + argString + ');\n' + src += '\treturn(0);\n' + src += '}\n' + stubs.append(src) + +def gen_link(name, sig): + m3_Sig = '' + for c in sig: + if c == 'p': + m3_Sig += 'i' + else: + m3_Sig += c + + src = '\tres = m3_LinkRawFunction(module, "*", "' + name + '", "' + m3_Sig + '", ' + name + '_stub);\n' + src += '\tif(res != m3Err_none && res != m3Err_functionLookupFailed) { LOG_ERROR("error: %s\\n", res); return(-1); }\n\n' + links.append(src) + +for line in inFile: + if line.isspace(): + continue + desc = line.split() + gen_stub(desc[0], desc[1]) + gen_link(desc[0], desc[1]) + +linkProc = 'int bindgen_link_' + apiName + '_api(IM3Module module)\n' +linkProc += '{\n' +linkProc += '\tM3Result res;\n' + +for link in links: + linkProc += link + +linkProc += '\treturn(0);\n' +linkProc += '}\n' + +for stub in stubs: + outFile.write(stub) + +outFile.write('\n') +outFile.write(linkProc) + +inFile.close() +outFile.close() diff --git a/scripts/mkapp.py b/scripts/mkapp.py new file mode 100644 index 0000000..fc6e781 --- /dev/null +++ b/scripts/mkapp.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python3 + +import os +import shutil +import subprocess +from argparse import ArgumentParser + +#--------------------------------------------------------------------------------------------- +# NOTE: get args +# +# mkapp.py [options] module +# +# -n, --name the name of the app +# -r, --res-file copies a file to the app bundle's resource directory +# -R, --res-dir copies the contents of a directory to the bundle's resource directory +# -i, --icon icon file +# -D, --out-dir output directory +#---------------------------------------------------------------------------------------------- + +parser = ArgumentParser(prog='mkapp') +parser.add_argument("-r", "--res-file", nargs='+', action='append', dest='res_files') +parser.add_argument("-R", "--res-dir", nargs='+', action='append', dest='res_dirs') +parser.add_argument("-i", "--icon") +parser.add_argument("-D", "--out-dir", default=os.getcwd()) +parser.add_argument("-n", "--name", default='out') +parser.add_argument("-O", "--orca-dir", default='.') +parser.add_argument("--version", default='0.0.0') +parser.add_argument("module") + +args = parser.parse_args() + +#----------------------------------------------------------- +#NOTE: make bundle directory structure +#----------------------------------------------------------- +app_name = args.name +bundle_name = app_name + '.app' +bundle_path = args.out_dir + '/' + bundle_name +contents_dir = bundle_path + '/Contents' +exe_dir = contents_dir + '/MacOS' +res_dir = contents_dir + '/resources' +wasm_dir = contents_dir + '/wasm' + +if os.path.exists(bundle_path): + shutil.rmtree(bundle_path) +os.mkdir(bundle_path) +os.mkdir(contents_dir) +os.mkdir(exe_dir) +os.mkdir(res_dir) +os.mkdir(wasm_dir) + +#----------------------------------------------------------- +#NOTE: copy orca runtime executable and libraries +#----------------------------------------------------------- +orca_exe = args.orca_dir + '/bin/orca' +milepost_lib = args.orca_dir + '/bin/libmilepost.dylib' +gles_lib = args.orca_dir + '/bin/libGLESv2.dylib' +egl_lib = args.orca_dir + '/bin/libEGL.dylib' +renderer_lib = args.orca_dir + '/bin/mtl_renderer.metallib' + +shutil.copy(orca_exe, exe_dir) +shutil.copy(milepost_lib, exe_dir) +shutil.copy(gles_lib, exe_dir) +shutil.copy(egl_lib, exe_dir) +shutil.copy(renderer_lib, exe_dir) + +#----------------------------------------------------------- +#NOTE: copy wasm module and resources +#----------------------------------------------------------- +shutil.copy(args.module, wasm_dir + '/module.wasm') + +if args.res_files != None: + for res in args.res_files: + shutil.copy(res, res_dir) + +if args.res_dirs != None: + for res in args.res_dirs: + shutil.copytree(res, res_dir) + +#----------------------------------------------------------- +#NOTE make icon +#----------------------------------------------------------- +src_image=args.icon + +#if src_image == None: +# src_image = orca_dir + '/resources/default_app_icon.png' + +if src_image != None: + iconset = os.path.splitext(src_image)[0] + '.iconset' + + if os.path.exists(iconset): + shutil.rmtree(iconset) + + os.mkdir(iconset) + + size = 16 + for i in range(0, 7): + size_str = str(size) + icon = 'icon_' + size_str + 'x' + size_str + '.png' + subprocess.run(['sips', '-z', size_str, size_str, src_image, '--out', iconset + '/' + icon], + stdout = subprocess.DEVNULL, + stderr = subprocess.DEVNULL) + + size_str_retina = str(size*2) + icon = 'icon_' + size_str + 'x' + size_str + '@2x.png' + subprocess.run(['sips', '-z', size_str_retina, size_str_retina, src_image, '--out', iconset + '/' + icon], + stdout = subprocess.DEVNULL, + stderr = subprocess.DEVNULL) + + size = size*2 + + subprocess.run(['iconutil', '-c', 'icns', '-o', res_dir + '/icon.icns', iconset]) + shutil.rmtree(iconset) + +#----------------------------------------------------------- +#NOTE: write plist file +#----------------------------------------------------------- +version = args.version +bundle_sig = "????" +icon_file = '' + +plist_contents = """ + + + + + CFBundleName + {app_name} + CFBundleDisplayName + {app_name} + CFBundleIdentifier + {app_name} + CFBundleVersion + {version} + CFBundlePackageType + APPL + CFBundleSignature + {bundle_sig} + CFBundleExecutable + orca + CFBundleIconFile + icon.icns + NSHighResolutionCapable + True + + +""".format(app_name=app_name, version=version, bundle_sig=bundle_sig, icon_file=icon_file) + +plist_file = open(contents_dir + '/Info.plist', 'w') +print(plist_contents, file=plist_file) diff --git a/sdk/GLES3/gl3.h b/sdk/GLES3/gl3.h new file mode 100644 index 0000000..3db2579 --- /dev/null +++ b/sdk/GLES3/gl3.h @@ -0,0 +1,1192 @@ +#ifndef __gles2_gl3_h_ +#define __gles2_gl3_h_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright 2013-2020 The Khronos Group Inc. +** SPDX-License-Identifier: MIT +** +** This header is generated from the Khronos OpenGL / OpenGL ES XML +** API Registry. The current version of the Registry, generator scripts +** used to make the header, and the header can be found at +** https://github.com/KhronosGroup/OpenGL-Registry +*/ + +#include + +#ifndef GL_APIENTRYP +#define GL_APIENTRYP GL_APIENTRY* +#endif + +#ifndef GL_GLES_PROTOTYPES +#define GL_GLES_PROTOTYPES 1 +#endif + +/* Generated on date 20211115 */ + +/* Generated C header for: + * API: gles2 + * Profile: common + * Versions considered: 2\.[0-9]|3\.0 + * Versions emitted: .* + * Default extensions included: None + * Additional extensions included: _nomatch_^ + * Extensions removed: _nomatch_^ + */ + +#ifndef GL_ES_VERSION_2_0 +#define GL_ES_VERSION_2_0 1 +#include +typedef khronos_int8_t GLbyte; +typedef khronos_float_t GLclampf; +typedef khronos_int32_t GLfixed; +typedef khronos_int16_t GLshort; +typedef khronos_uint16_t GLushort; +typedef void GLvoid; +typedef struct __GLsync *GLsync; +typedef khronos_int64_t GLint64; +typedef khronos_uint64_t GLuint64; +typedef unsigned int GLenum; +typedef unsigned int GLuint; +typedef char GLchar; +typedef khronos_float_t GLfloat; +typedef khronos_ssize_t GLsizeiptr; +typedef khronos_intptr_t GLintptr; +typedef unsigned int GLbitfield; +typedef int GLint; +typedef unsigned char GLboolean; +typedef int GLsizei; +typedef khronos_uint8_t GLubyte; +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_FALSE 0 +#define GL_TRUE 1 +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_FUNC_ADD 0x8006 +#define GL_BLEND_EQUATION 0x8009 +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_STREAM_DRAW 0x88E0 +#define GL_STATIC_DRAW 0x88E4 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_CULL_FACE 0x0B44 +#define GL_BLEND 0x0BE2 +#define GL_DITHER 0x0BD0 +#define GL_STENCIL_TEST 0x0B90 +#define GL_DEPTH_TEST 0x0B71 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_CW 0x0900 +#define GL_CCW 0x0901 +#define GL_LINE_WIDTH 0x0B21 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#define GL_VIEWPORT 0x0BA2 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_RED_BITS 0x0D52 +#define GL_GREEN_BITS 0x0D53 +#define GL_BLUE_BITS 0x0D54 +#define GL_ALPHA_BITS 0x0D55 +#define GL_DEPTH_BITS 0x0D56 +#define GL_STENCIL_BITS 0x0D57 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_FIXED 0x140C +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#define GL_SHADER_TYPE 0x8B4F +#define GL_DELETE_STATUS 0x8B80 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_INVERT 0x150A +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_TEXTURE 0x1702 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_REPEAT 0x2901 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B +#define GL_COMPILE_STATUS 0x8B81 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_SHADER_COMPILER 0x8DFA +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 +#define GL_LOW_FLOAT 0x8DF0 +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_LOW_INT 0x8DF3 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_HIGH_INT 0x8DF5 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGB565 0x8D62 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_NONE 0 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +typedef void (GL_APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture); +typedef void (GL_APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (GL_APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name); +typedef void (GL_APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); +typedef void (GL_APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer); +typedef void (GL_APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer); +typedef void (GL_APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture); +typedef void (GL_APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode); +typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha); +typedef void (GL_APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor); +typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +typedef void (GL_APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage); +typedef void (GL_APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); +typedef GLenum (GL_APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target); +typedef void (GL_APIENTRYP PFNGLCLEARPROC) (GLbitfield mask); +typedef void (GL_APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (GL_APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d); +typedef void (GL_APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s); +typedef void (GL_APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +typedef void (GL_APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); +typedef void (GL_APIENTRYP PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef GLuint (GL_APIENTRYP PFNGLCREATEPROGRAMPROC) (void); +typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROC) (GLenum type); +typedef void (GL_APIENTRYP PFNGLCULLFACEPROC) (GLenum mode); +typedef void (GL_APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers); +typedef void (GL_APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers); +typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program); +typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers); +typedef void (GL_APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader); +typedef void (GL_APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures); +typedef void (GL_APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func); +typedef void (GL_APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag); +typedef void (GL_APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f); +typedef void (GL_APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (GL_APIENTRYP PFNGLDISABLEPROC) (GLenum cap); +typedef void (GL_APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index); +typedef void (GL_APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices); +typedef void (GL_APIENTRYP PFNGLENABLEPROC) (GLenum cap); +typedef void (GL_APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index); +typedef void (GL_APIENTRYP PFNGLFINISHPROC) (void); +typedef void (GL_APIENTRYP PFNGLFLUSHPROC) (void); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GL_APIENTRYP PFNGLFRONTFACEPROC) (GLenum mode); +typedef void (GL_APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); +typedef void (GL_APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target); +typedef void (GL_APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers); +typedef void (GL_APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers); +typedef void (GL_APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures); +typedef void (GL_APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +typedef void (GL_APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders); +typedef GLint (GL_APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (GL_APIENTRYP PFNGLGETBOOLEANVPROC) (GLenum pname, GLboolean *data); +typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef GLenum (GL_APIENTRYP PFNGLGETERRORPROC) (void); +typedef void (GL_APIENTRYP PFNGLGETFLOATVPROC) (GLenum pname, GLfloat *data); +typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (GL_APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision); +typedef void (GL_APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); +typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name); +typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params); +typedef void (GL_APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params); +typedef GLint (GL_APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params); +typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer); +typedef void (GL_APIENTRYP PFNGLHINTPROC) (GLenum target, GLenum mode); +typedef GLboolean (GL_APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer); +typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDPROC) (GLenum cap); +typedef GLboolean (GL_APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer); +typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPROC) (GLuint program); +typedef GLboolean (GL_APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer); +typedef GLboolean (GL_APIENTRYP PFNGLISSHADERPROC) (GLuint shader); +typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREPROC) (GLuint texture); +typedef void (GL_APIENTRYP PFNGLLINEWIDTHPROC) (GLfloat width); +typedef void (GL_APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program); +typedef void (GL_APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param); +typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat units); +typedef void (GL_APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); +typedef void (GL_APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void); +typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert); +typedef void (GL_APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryFormat, const void *binary, GLsizei length); +typedef void (GL_APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); +typedef void (GL_APIENTRYP PFNGLSTENCILFUNCPROC) (GLenum func, GLint ref, GLuint mask); +typedef void (GL_APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask); +typedef void (GL_APIENTRYP PFNGLSTENCILMASKPROC) (GLuint mask); +typedef void (GL_APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask); +typedef void (GL_APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass); +typedef void (GL_APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +typedef void (GL_APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param); +typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param); +typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +typedef void (GL_APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0); +typedef void (GL_APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0); +typedef void (GL_APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1); +typedef void (GL_APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1); +typedef void (GL_APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GL_APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GL_APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GL_APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GL_APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program); +typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); +typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height); +#if GL_GLES_PROTOTYPES +GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture); +GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader); +GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name); +GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer); +GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer); +GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer); +GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture); +GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode); +GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha); +GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); +GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage); +GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); +GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target); +GL_APICALL void GL_APIENTRY glClear (GLbitfield mask); +GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat d); +GL_APICALL void GL_APIENTRY glClearStencil (GLint s); +GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader); +GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); +GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); +GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL GLuint GL_APIENTRY glCreateProgram (void); +GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type); +GL_APICALL void GL_APIENTRY glCullFace (GLenum mode); +GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers); +GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers); +GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program); +GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers); +GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader); +GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures); +GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func); +GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag); +GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f); +GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader); +GL_APICALL void GL_APIENTRY glDisable (GLenum cap); +GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index); +GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); +GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices); +GL_APICALL void GL_APIENTRY glEnable (GLenum cap); +GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index); +GL_APICALL void GL_APIENTRY glFinish (void); +GL_APICALL void GL_APIENTRY glFlush (void); +GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode); +GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers); +GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target); +GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers); +GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers); +GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures); +GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders); +GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar *name); +GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *data); +GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params); +GL_APICALL GLenum GL_APIENTRY glGetError (void); +GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data); +GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data); +GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision); +GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); +GL_APICALL const GLubyte *GL_APIENTRY glGetString (GLenum name); +GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params); +GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params); +GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params); +GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar *name); +GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params); +GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer); +GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode); +GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer); +GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap); +GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer); +GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program); +GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer); +GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader); +GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture); +GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width); +GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program); +GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); +GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); +GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void); +GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert); +GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryFormat, const void *binary, GLsizei length); +GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); +GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask); +GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); +GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); +GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params); +GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params); +GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat v0); +GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint v0); +GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1); +GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint v0, GLint v1); +GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2); +GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUseProgram (GLuint program); +GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program); +GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint index, GLfloat x); +GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v); +GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y); +GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v); +GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z); +GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v); +GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v); +GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); +GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); +#endif +#endif /* GL_ES_VERSION_2_0 */ + +#ifndef GL_ES_VERSION_3_0 +#define GL_ES_VERSION_3_0 1 +typedef khronos_uint16_t GLhalf; +#define GL_READ_BUFFER 0x0C02 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_RED 0x1903 +#define GL_RGB8 0x8051 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_COLOR_ATTACHMENT16 0x8CF0 +#define GL_COLOR_ATTACHMENT17 0x8CF1 +#define GL_COLOR_ATTACHMENT18 0x8CF2 +#define GL_COLOR_ATTACHMENT19 0x8CF3 +#define GL_COLOR_ATTACHMENT20 0x8CF4 +#define GL_COLOR_ATTACHMENT21 0x8CF5 +#define GL_COLOR_ATTACHMENT22 0x8CF6 +#define GL_COLOR_ATTACHMENT23 0x8CF7 +#define GL_COLOR_ATTACHMENT24 0x8CF8 +#define GL_COLOR_ATTACHMENT25 0x8CF9 +#define GL_COLOR_ATTACHMENT26 0x8CFA +#define GL_COLOR_ATTACHMENT27 0x8CFB +#define GL_COLOR_ATTACHMENT28 0x8CFC +#define GL_COLOR_ATTACHMENT29 0x8CFD +#define GL_COLOR_ATTACHMENT30 0x8CFE +#define GL_COLOR_ATTACHMENT31 0x8CFF +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_HALF_FLOAT 0x140B +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_RG 0x8227 +#define GL_RG_INTEGER 0x8228 +#define GL_R8 0x8229 +#define GL_RG8 0x822B +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#define GL_VERTEX_ARRAY_BINDING 0x85B5 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_COPY_READ_BUFFER_BINDING 0x8F36 +#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37 +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_INVALID_INDEX 0xFFFFFFFFu +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A +#define GL_SAMPLER_BINDING 0x8919 +#define GL_RGB10_A2UI 0x906F +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_INT_2_10_10_10_REV 0x8D9F +#define GL_TRANSFORM_FEEDBACK 0x8E22 +#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23 +#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 +#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_PROGRAM_BINARY_FORMATS 0x87FF +#define GL_COMPRESSED_R11_EAC 0x9270 +#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271 +#define GL_COMPRESSED_RG11_EAC 0x9272 +#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 +#define GL_COMPRESSED_RGB8_ETC2 0x9274 +#define GL_COMPRESSED_SRGB8_ETC2 0x9275 +#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 +#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 +#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 +#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F +#define GL_MAX_ELEMENT_INDEX 0x8D6B +#define GL_NUM_SAMPLE_COUNTS 0x9380 +#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF +typedef void (GL_APIENTRYP PFNGLREADBUFFERPROC) (GLenum src); +typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); +typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); +typedef void (GL_APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids); +typedef void (GL_APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids); +typedef GLboolean (GL_APIENTRYP PFNGLISQUERYPROC) (GLuint id); +typedef void (GL_APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id); +typedef void (GL_APIENTRYP PFNGLENDQUERYPROC) (GLenum target); +typedef void (GL_APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params); +typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target); +typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, void **params); +typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void *(GL_APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length); +typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array); +typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays); +typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays); +typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array); +typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data); +typedef void (GL_APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode); +typedef void (GL_APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void); +typedef void (GL_APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GL_APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer); +typedef void (GL_APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode); +typedef void (GL_APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v); +typedef void (GL_APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params); +typedef GLint (GL_APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (GL_APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0); +typedef void (GL_APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1); +typedef void (GL_APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GL_APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GL_APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value); +typedef void (GL_APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index); +typedef void (GL_APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +typedef void (GL_APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices); +typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params); +typedef GLuint (GL_APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName); +typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName); +typedef void (GL_APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount); +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount); +typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags); +typedef GLboolean (GL_APIENTRYP PFNGLISSYNCPROC) (GLsync sync); +typedef void (GL_APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync); +typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (GL_APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (GL_APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data); +typedef void (GL_APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei count, GLsizei *length, GLint *values); +typedef void (GL_APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data); +typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params); +typedef void (GL_APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers); +typedef void (GL_APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers); +typedef GLboolean (GL_APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler); +typedef void (GL_APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param); +typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor); +typedef void (GL_APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id); +typedef void (GL_APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids); +typedef void (GL_APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids); +typedef GLboolean (GL_APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id); +typedef void (GL_APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC) (void); +typedef void (GL_APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC) (void); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); +typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length); +typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value); +typedef void (GL_APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments); +typedef void (GL_APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei count, GLint *params); +#if GL_GLES_PROTOTYPES +GL_APICALL void GL_APIENTRY glReadBuffer (GLenum src); +GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); +GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +GL_APICALL void GL_APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); +GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); +GL_APICALL void GL_APIENTRY glGenQueries (GLsizei n, GLuint *ids); +GL_APICALL void GL_APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids); +GL_APICALL GLboolean GL_APIENTRY glIsQuery (GLuint id); +GL_APICALL void GL_APIENTRY glBeginQuery (GLenum target, GLuint id); +GL_APICALL void GL_APIENTRY glEndQuery (GLenum target); +GL_APICALL void GL_APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params); +GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer (GLenum target); +GL_APICALL void GL_APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, void **params); +GL_APICALL void GL_APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs); +GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +GL_APICALL void *GL_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +GL_APICALL void GL_APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length); +GL_APICALL void GL_APIENTRY glBindVertexArray (GLuint array); +GL_APICALL void GL_APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays); +GL_APICALL void GL_APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays); +GL_APICALL GLboolean GL_APIENTRY glIsVertexArray (GLuint array); +GL_APICALL void GL_APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data); +GL_APICALL void GL_APIENTRY glBeginTransformFeedback (GLenum primitiveMode); +GL_APICALL void GL_APIENTRY glEndTransformFeedback (void); +GL_APICALL void GL_APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +GL_APICALL void GL_APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer); +GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode); +GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +GL_APICALL void GL_APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +GL_APICALL void GL_APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params); +GL_APICALL void GL_APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w); +GL_APICALL void GL_APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +GL_APICALL void GL_APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v); +GL_APICALL void GL_APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v); +GL_APICALL void GL_APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params); +GL_APICALL GLint GL_APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name); +GL_APICALL void GL_APIENTRY glUniform1ui (GLint location, GLuint v0); +GL_APICALL void GL_APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1); +GL_APICALL void GL_APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2); +GL_APICALL void GL_APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +GL_APICALL void GL_APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value); +GL_APICALL void GL_APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value); +GL_APICALL void GL_APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value); +GL_APICALL void GL_APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +GL_APICALL const GLubyte *GL_APIENTRY glGetStringi (GLenum name, GLuint index); +GL_APICALL void GL_APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +GL_APICALL void GL_APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices); +GL_APICALL void GL_APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params); +GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName); +GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName); +GL_APICALL void GL_APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +GL_APICALL void GL_APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instancecount); +GL_APICALL void GL_APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount); +GL_APICALL GLsync GL_APIENTRY glFenceSync (GLenum condition, GLbitfield flags); +GL_APICALL GLboolean GL_APIENTRY glIsSync (GLsync sync); +GL_APICALL void GL_APIENTRY glDeleteSync (GLsync sync); +GL_APICALL GLenum GL_APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); +GL_APICALL void GL_APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); +GL_APICALL void GL_APIENTRY glGetInteger64v (GLenum pname, GLint64 *data); +GL_APICALL void GL_APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei count, GLsizei *length, GLint *values); +GL_APICALL void GL_APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data); +GL_APICALL void GL_APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params); +GL_APICALL void GL_APIENTRY glGenSamplers (GLsizei count, GLuint *samplers); +GL_APICALL void GL_APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers); +GL_APICALL GLboolean GL_APIENTRY glIsSampler (GLuint sampler); +GL_APICALL void GL_APIENTRY glBindSampler (GLuint unit, GLuint sampler); +GL_APICALL void GL_APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param); +GL_APICALL void GL_APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param); +GL_APICALL void GL_APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param); +GL_APICALL void GL_APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params); +GL_APICALL void GL_APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor); +GL_APICALL void GL_APIENTRY glBindTransformFeedback (GLenum target, GLuint id); +GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids); +GL_APICALL void GL_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids); +GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback (GLuint id); +GL_APICALL void GL_APIENTRY glPauseTransformFeedback (void); +GL_APICALL void GL_APIENTRY glResumeTransformFeedback (void); +GL_APICALL void GL_APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); +GL_APICALL void GL_APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length); +GL_APICALL void GL_APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value); +GL_APICALL void GL_APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments); +GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +GL_APICALL void GL_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei count, GLint *params); +#endif +#endif /* GL_ES_VERSION_3_0 */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sdk/GLES3/gl31.h b/sdk/GLES3/gl31.h new file mode 100644 index 0000000..502d6fe --- /dev/null +++ b/sdk/GLES3/gl31.h @@ -0,0 +1,1507 @@ +#ifndef __gles2_gl31_h_ +#define __gles2_gl31_h_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright 2013-2020 The Khronos Group Inc. +** SPDX-License-Identifier: MIT +** +** This header is generated from the Khronos OpenGL / OpenGL ES XML +** API Registry. The current version of the Registry, generator scripts +** used to make the header, and the header can be found at +** https://github.com/KhronosGroup/OpenGL-Registry +*/ + +#include + +#ifndef GL_APIENTRYP +#define GL_APIENTRYP GL_APIENTRY* +#endif + +#ifndef GL_GLES_PROTOTYPES +#define GL_GLES_PROTOTYPES 1 +#endif + +/* Generated on date 20191013 */ + +/* Generated C header for: + * API: gles2 + * Profile: common + * Versions considered: 2\.[0-9]|3\.[01] + * Versions emitted: .* + * Default extensions included: None + * Additional extensions included: _nomatch_^ + * Extensions removed: _nomatch_^ + */ + +#ifndef GL_ES_VERSION_2_0 +#define GL_ES_VERSION_2_0 1 +#include +typedef khronos_int8_t GLbyte; +typedef khronos_float_t GLclampf; +typedef khronos_int32_t GLfixed; +typedef khronos_int16_t GLshort; +typedef khronos_uint16_t GLushort; +typedef void GLvoid; +typedef struct __GLsync *GLsync; +typedef khronos_int64_t GLint64; +typedef khronos_uint64_t GLuint64; +typedef unsigned int GLenum; +typedef unsigned int GLuint; +typedef char GLchar; +typedef khronos_float_t GLfloat; +typedef khronos_ssize_t GLsizeiptr; +typedef khronos_intptr_t GLintptr; +typedef unsigned int GLbitfield; +typedef int GLint; +typedef unsigned char GLboolean; +typedef int GLsizei; +typedef khronos_uint8_t GLubyte; +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_FALSE 0 +#define GL_TRUE 1 +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_FUNC_ADD 0x8006 +#define GL_BLEND_EQUATION 0x8009 +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_STREAM_DRAW 0x88E0 +#define GL_STATIC_DRAW 0x88E4 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_CULL_FACE 0x0B44 +#define GL_BLEND 0x0BE2 +#define GL_DITHER 0x0BD0 +#define GL_STENCIL_TEST 0x0B90 +#define GL_DEPTH_TEST 0x0B71 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_CW 0x0900 +#define GL_CCW 0x0901 +#define GL_LINE_WIDTH 0x0B21 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#define GL_VIEWPORT 0x0BA2 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_RED_BITS 0x0D52 +#define GL_GREEN_BITS 0x0D53 +#define GL_BLUE_BITS 0x0D54 +#define GL_ALPHA_BITS 0x0D55 +#define GL_DEPTH_BITS 0x0D56 +#define GL_STENCIL_BITS 0x0D57 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_FIXED 0x140C +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#define GL_SHADER_TYPE 0x8B4F +#define GL_DELETE_STATUS 0x8B80 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_INVERT 0x150A +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_TEXTURE 0x1702 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_REPEAT 0x2901 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B +#define GL_COMPILE_STATUS 0x8B81 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_SHADER_COMPILER 0x8DFA +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 +#define GL_LOW_FLOAT 0x8DF0 +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_LOW_INT 0x8DF3 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_HIGH_INT 0x8DF5 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGB565 0x8D62 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_NONE 0 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +typedef void (GL_APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture); +typedef void (GL_APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (GL_APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name); +typedef void (GL_APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); +typedef void (GL_APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer); +typedef void (GL_APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer); +typedef void (GL_APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture); +typedef void (GL_APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode); +typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha); +typedef void (GL_APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor); +typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +typedef void (GL_APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage); +typedef void (GL_APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); +typedef GLenum (GL_APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target); +typedef void (GL_APIENTRYP PFNGLCLEARPROC) (GLbitfield mask); +typedef void (GL_APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (GL_APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d); +typedef void (GL_APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s); +typedef void (GL_APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +typedef void (GL_APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); +typedef void (GL_APIENTRYP PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef GLuint (GL_APIENTRYP PFNGLCREATEPROGRAMPROC) (void); +typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROC) (GLenum type); +typedef void (GL_APIENTRYP PFNGLCULLFACEPROC) (GLenum mode); +typedef void (GL_APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers); +typedef void (GL_APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers); +typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program); +typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers); +typedef void (GL_APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader); +typedef void (GL_APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures); +typedef void (GL_APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func); +typedef void (GL_APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag); +typedef void (GL_APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f); +typedef void (GL_APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (GL_APIENTRYP PFNGLDISABLEPROC) (GLenum cap); +typedef void (GL_APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index); +typedef void (GL_APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices); +typedef void (GL_APIENTRYP PFNGLENABLEPROC) (GLenum cap); +typedef void (GL_APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index); +typedef void (GL_APIENTRYP PFNGLFINISHPROC) (void); +typedef void (GL_APIENTRYP PFNGLFLUSHPROC) (void); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GL_APIENTRYP PFNGLFRONTFACEPROC) (GLenum mode); +typedef void (GL_APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); +typedef void (GL_APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target); +typedef void (GL_APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers); +typedef void (GL_APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers); +typedef void (GL_APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures); +typedef void (GL_APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +typedef void (GL_APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders); +typedef GLint (GL_APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (GL_APIENTRYP PFNGLGETBOOLEANVPROC) (GLenum pname, GLboolean *data); +typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef GLenum (GL_APIENTRYP PFNGLGETERRORPROC) (void); +typedef void (GL_APIENTRYP PFNGLGETFLOATVPROC) (GLenum pname, GLfloat *data); +typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (GL_APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision); +typedef void (GL_APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); +typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name); +typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params); +typedef void (GL_APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params); +typedef GLint (GL_APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params); +typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer); +typedef void (GL_APIENTRYP PFNGLHINTPROC) (GLenum target, GLenum mode); +typedef GLboolean (GL_APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer); +typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDPROC) (GLenum cap); +typedef GLboolean (GL_APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer); +typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPROC) (GLuint program); +typedef GLboolean (GL_APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer); +typedef GLboolean (GL_APIENTRYP PFNGLISSHADERPROC) (GLuint shader); +typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREPROC) (GLuint texture); +typedef void (GL_APIENTRYP PFNGLLINEWIDTHPROC) (GLfloat width); +typedef void (GL_APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program); +typedef void (GL_APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param); +typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat units); +typedef void (GL_APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); +typedef void (GL_APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void); +typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert); +typedef void (GL_APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length); +typedef void (GL_APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); +typedef void (GL_APIENTRYP PFNGLSTENCILFUNCPROC) (GLenum func, GLint ref, GLuint mask); +typedef void (GL_APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask); +typedef void (GL_APIENTRYP PFNGLSTENCILMASKPROC) (GLuint mask); +typedef void (GL_APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask); +typedef void (GL_APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass); +typedef void (GL_APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +typedef void (GL_APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param); +typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param); +typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +typedef void (GL_APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0); +typedef void (GL_APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0); +typedef void (GL_APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1); +typedef void (GL_APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1); +typedef void (GL_APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GL_APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GL_APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GL_APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GL_APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program); +typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); +typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height); +#if GL_GLES_PROTOTYPES +GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture); +GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader); +GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name); +GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer); +GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer); +GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer); +GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture); +GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode); +GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha); +GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); +GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage); +GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); +GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target); +GL_APICALL void GL_APIENTRY glClear (GLbitfield mask); +GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat d); +GL_APICALL void GL_APIENTRY glClearStencil (GLint s); +GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader); +GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); +GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); +GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL GLuint GL_APIENTRY glCreateProgram (void); +GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type); +GL_APICALL void GL_APIENTRY glCullFace (GLenum mode); +GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers); +GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers); +GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program); +GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers); +GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader); +GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures); +GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func); +GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag); +GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f); +GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader); +GL_APICALL void GL_APIENTRY glDisable (GLenum cap); +GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index); +GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); +GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices); +GL_APICALL void GL_APIENTRY glEnable (GLenum cap); +GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index); +GL_APICALL void GL_APIENTRY glFinish (void); +GL_APICALL void GL_APIENTRY glFlush (void); +GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode); +GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers); +GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target); +GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers); +GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers); +GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures); +GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders); +GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar *name); +GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *data); +GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params); +GL_APICALL GLenum GL_APIENTRY glGetError (void); +GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data); +GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data); +GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision); +GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); +GL_APICALL const GLubyte *GL_APIENTRY glGetString (GLenum name); +GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params); +GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params); +GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params); +GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar *name); +GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params); +GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer); +GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode); +GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer); +GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap); +GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer); +GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program); +GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer); +GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader); +GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture); +GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width); +GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program); +GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); +GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); +GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void); +GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert); +GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length); +GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); +GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask); +GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); +GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); +GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params); +GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params); +GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat v0); +GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint v0); +GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1); +GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint v0, GLint v1); +GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2); +GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUseProgram (GLuint program); +GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program); +GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint index, GLfloat x); +GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v); +GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y); +GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v); +GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z); +GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v); +GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v); +GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); +GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); +#endif +#endif /* GL_ES_VERSION_2_0 */ + +#ifndef GL_ES_VERSION_3_0 +#define GL_ES_VERSION_3_0 1 +typedef khronos_uint16_t GLhalf; +#define GL_READ_BUFFER 0x0C02 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_RED 0x1903 +#define GL_RGB8 0x8051 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_COLOR_ATTACHMENT16 0x8CF0 +#define GL_COLOR_ATTACHMENT17 0x8CF1 +#define GL_COLOR_ATTACHMENT18 0x8CF2 +#define GL_COLOR_ATTACHMENT19 0x8CF3 +#define GL_COLOR_ATTACHMENT20 0x8CF4 +#define GL_COLOR_ATTACHMENT21 0x8CF5 +#define GL_COLOR_ATTACHMENT22 0x8CF6 +#define GL_COLOR_ATTACHMENT23 0x8CF7 +#define GL_COLOR_ATTACHMENT24 0x8CF8 +#define GL_COLOR_ATTACHMENT25 0x8CF9 +#define GL_COLOR_ATTACHMENT26 0x8CFA +#define GL_COLOR_ATTACHMENT27 0x8CFB +#define GL_COLOR_ATTACHMENT28 0x8CFC +#define GL_COLOR_ATTACHMENT29 0x8CFD +#define GL_COLOR_ATTACHMENT30 0x8CFE +#define GL_COLOR_ATTACHMENT31 0x8CFF +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_HALF_FLOAT 0x140B +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_RG 0x8227 +#define GL_RG_INTEGER 0x8228 +#define GL_R8 0x8229 +#define GL_RG8 0x822B +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#define GL_VERTEX_ARRAY_BINDING 0x85B5 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_COPY_READ_BUFFER_BINDING 0x8F36 +#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37 +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_INVALID_INDEX 0xFFFFFFFFu +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A +#define GL_SAMPLER_BINDING 0x8919 +#define GL_RGB10_A2UI 0x906F +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_INT_2_10_10_10_REV 0x8D9F +#define GL_TRANSFORM_FEEDBACK 0x8E22 +#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23 +#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 +#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_PROGRAM_BINARY_FORMATS 0x87FF +#define GL_COMPRESSED_R11_EAC 0x9270 +#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271 +#define GL_COMPRESSED_RG11_EAC 0x9272 +#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 +#define GL_COMPRESSED_RGB8_ETC2 0x9274 +#define GL_COMPRESSED_SRGB8_ETC2 0x9275 +#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 +#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 +#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 +#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F +#define GL_MAX_ELEMENT_INDEX 0x8D6B +#define GL_NUM_SAMPLE_COUNTS 0x9380 +#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF +typedef void (GL_APIENTRYP PFNGLREADBUFFERPROC) (GLenum src); +typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); +typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); +typedef void (GL_APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids); +typedef void (GL_APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids); +typedef GLboolean (GL_APIENTRYP PFNGLISQUERYPROC) (GLuint id); +typedef void (GL_APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id); +typedef void (GL_APIENTRYP PFNGLENDQUERYPROC) (GLenum target); +typedef void (GL_APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params); +typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target); +typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, void **params); +typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void *(GL_APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length); +typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array); +typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays); +typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays); +typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array); +typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data); +typedef void (GL_APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode); +typedef void (GL_APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void); +typedef void (GL_APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GL_APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer); +typedef void (GL_APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode); +typedef void (GL_APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v); +typedef void (GL_APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params); +typedef GLint (GL_APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (GL_APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0); +typedef void (GL_APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1); +typedef void (GL_APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GL_APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GL_APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value); +typedef void (GL_APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index); +typedef void (GL_APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +typedef void (GL_APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices); +typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params); +typedef GLuint (GL_APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName); +typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName); +typedef void (GL_APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount); +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount); +typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags); +typedef GLboolean (GL_APIENTRYP PFNGLISSYNCPROC) (GLsync sync); +typedef void (GL_APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync); +typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (GL_APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (GL_APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data); +typedef void (GL_APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); +typedef void (GL_APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data); +typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params); +typedef void (GL_APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers); +typedef void (GL_APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers); +typedef GLboolean (GL_APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler); +typedef void (GL_APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param); +typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor); +typedef void (GL_APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id); +typedef void (GL_APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids); +typedef void (GL_APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids); +typedef GLboolean (GL_APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id); +typedef void (GL_APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC) (void); +typedef void (GL_APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC) (void); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); +typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length); +typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value); +typedef void (GL_APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments); +typedef void (GL_APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params); +#if GL_GLES_PROTOTYPES +GL_APICALL void GL_APIENTRY glReadBuffer (GLenum src); +GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); +GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +GL_APICALL void GL_APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); +GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); +GL_APICALL void GL_APIENTRY glGenQueries (GLsizei n, GLuint *ids); +GL_APICALL void GL_APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids); +GL_APICALL GLboolean GL_APIENTRY glIsQuery (GLuint id); +GL_APICALL void GL_APIENTRY glBeginQuery (GLenum target, GLuint id); +GL_APICALL void GL_APIENTRY glEndQuery (GLenum target); +GL_APICALL void GL_APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params); +GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer (GLenum target); +GL_APICALL void GL_APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, void **params); +GL_APICALL void GL_APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs); +GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +GL_APICALL void *GL_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +GL_APICALL void GL_APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length); +GL_APICALL void GL_APIENTRY glBindVertexArray (GLuint array); +GL_APICALL void GL_APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays); +GL_APICALL void GL_APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays); +GL_APICALL GLboolean GL_APIENTRY glIsVertexArray (GLuint array); +GL_APICALL void GL_APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data); +GL_APICALL void GL_APIENTRY glBeginTransformFeedback (GLenum primitiveMode); +GL_APICALL void GL_APIENTRY glEndTransformFeedback (void); +GL_APICALL void GL_APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +GL_APICALL void GL_APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer); +GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode); +GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +GL_APICALL void GL_APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +GL_APICALL void GL_APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params); +GL_APICALL void GL_APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w); +GL_APICALL void GL_APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +GL_APICALL void GL_APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v); +GL_APICALL void GL_APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v); +GL_APICALL void GL_APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params); +GL_APICALL GLint GL_APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name); +GL_APICALL void GL_APIENTRY glUniform1ui (GLint location, GLuint v0); +GL_APICALL void GL_APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1); +GL_APICALL void GL_APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2); +GL_APICALL void GL_APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +GL_APICALL void GL_APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value); +GL_APICALL void GL_APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value); +GL_APICALL void GL_APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value); +GL_APICALL void GL_APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +GL_APICALL const GLubyte *GL_APIENTRY glGetStringi (GLenum name, GLuint index); +GL_APICALL void GL_APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +GL_APICALL void GL_APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices); +GL_APICALL void GL_APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params); +GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName); +GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName); +GL_APICALL void GL_APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +GL_APICALL void GL_APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instancecount); +GL_APICALL void GL_APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount); +GL_APICALL GLsync GL_APIENTRY glFenceSync (GLenum condition, GLbitfield flags); +GL_APICALL GLboolean GL_APIENTRY glIsSync (GLsync sync); +GL_APICALL void GL_APIENTRY glDeleteSync (GLsync sync); +GL_APICALL GLenum GL_APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); +GL_APICALL void GL_APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); +GL_APICALL void GL_APIENTRY glGetInteger64v (GLenum pname, GLint64 *data); +GL_APICALL void GL_APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); +GL_APICALL void GL_APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data); +GL_APICALL void GL_APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params); +GL_APICALL void GL_APIENTRY glGenSamplers (GLsizei count, GLuint *samplers); +GL_APICALL void GL_APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers); +GL_APICALL GLboolean GL_APIENTRY glIsSampler (GLuint sampler); +GL_APICALL void GL_APIENTRY glBindSampler (GLuint unit, GLuint sampler); +GL_APICALL void GL_APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param); +GL_APICALL void GL_APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param); +GL_APICALL void GL_APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param); +GL_APICALL void GL_APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params); +GL_APICALL void GL_APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor); +GL_APICALL void GL_APIENTRY glBindTransformFeedback (GLenum target, GLuint id); +GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids); +GL_APICALL void GL_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids); +GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback (GLuint id); +GL_APICALL void GL_APIENTRY glPauseTransformFeedback (void); +GL_APICALL void GL_APIENTRY glResumeTransformFeedback (void); +GL_APICALL void GL_APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); +GL_APICALL void GL_APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length); +GL_APICALL void GL_APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value); +GL_APICALL void GL_APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments); +GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +GL_APICALL void GL_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params); +#endif +#endif /* GL_ES_VERSION_3_0 */ + +#ifndef GL_ES_VERSION_3_1 +#define GL_ES_VERSION_3_1 1 +#define GL_COMPUTE_SHADER 0x91B9 +#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB +#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC +#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD +#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262 +#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263 +#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264 +#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265 +#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266 +#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB +#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE +#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF +#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267 +#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE +#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF +#define GL_COMPUTE_SHADER_BIT 0x00000020 +#define GL_DRAW_INDIRECT_BUFFER 0x8F3F +#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43 +#define GL_MAX_UNIFORM_LOCATIONS 0x826E +#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310 +#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311 +#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313 +#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314 +#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315 +#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316 +#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318 +#define GL_UNIFORM 0x92E1 +#define GL_UNIFORM_BLOCK 0x92E2 +#define GL_PROGRAM_INPUT 0x92E3 +#define GL_PROGRAM_OUTPUT 0x92E4 +#define GL_BUFFER_VARIABLE 0x92E5 +#define GL_SHADER_STORAGE_BLOCK 0x92E6 +#define GL_ATOMIC_COUNTER_BUFFER 0x92C0 +#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4 +#define GL_ACTIVE_RESOURCES 0x92F5 +#define GL_MAX_NAME_LENGTH 0x92F6 +#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7 +#define GL_NAME_LENGTH 0x92F9 +#define GL_TYPE 0x92FA +#define GL_ARRAY_SIZE 0x92FB +#define GL_OFFSET 0x92FC +#define GL_BLOCK_INDEX 0x92FD +#define GL_ARRAY_STRIDE 0x92FE +#define GL_MATRIX_STRIDE 0x92FF +#define GL_IS_ROW_MAJOR 0x9300 +#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301 +#define GL_BUFFER_BINDING 0x9302 +#define GL_BUFFER_DATA_SIZE 0x9303 +#define GL_NUM_ACTIVE_VARIABLES 0x9304 +#define GL_ACTIVE_VARIABLES 0x9305 +#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306 +#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A +#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B +#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C +#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D +#define GL_LOCATION 0x930E +#define GL_VERTEX_SHADER_BIT 0x00000001 +#define GL_FRAGMENT_SHADER_BIT 0x00000002 +#define GL_ALL_SHADER_BITS 0xFFFFFFFF +#define GL_PROGRAM_SEPARABLE 0x8258 +#define GL_ACTIVE_PROGRAM 0x8259 +#define GL_PROGRAM_PIPELINE_BINDING 0x825A +#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1 +#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2 +#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3 +#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC +#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0 +#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1 +#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2 +#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6 +#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7 +#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8 +#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC +#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9 +#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB +#define GL_MAX_IMAGE_UNITS 0x8F38 +#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA +#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE +#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF +#define GL_IMAGE_BINDING_NAME 0x8F3A +#define GL_IMAGE_BINDING_LEVEL 0x8F3B +#define GL_IMAGE_BINDING_LAYERED 0x8F3C +#define GL_IMAGE_BINDING_LAYER 0x8F3D +#define GL_IMAGE_BINDING_ACCESS 0x8F3E +#define GL_IMAGE_BINDING_FORMAT 0x906E +#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001 +#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002 +#define GL_UNIFORM_BARRIER_BIT 0x00000004 +#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008 +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020 +#define GL_COMMAND_BARRIER_BIT 0x00000040 +#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080 +#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100 +#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200 +#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400 +#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800 +#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000 +#define GL_ALL_BARRIER_BITS 0xFFFFFFFF +#define GL_IMAGE_2D 0x904D +#define GL_IMAGE_3D 0x904E +#define GL_IMAGE_CUBE 0x9050 +#define GL_IMAGE_2D_ARRAY 0x9053 +#define GL_INT_IMAGE_2D 0x9058 +#define GL_INT_IMAGE_3D 0x9059 +#define GL_INT_IMAGE_CUBE 0x905B +#define GL_INT_IMAGE_2D_ARRAY 0x905E +#define GL_UNSIGNED_INT_IMAGE_2D 0x9063 +#define GL_UNSIGNED_INT_IMAGE_3D 0x9064 +#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069 +#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7 +#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8 +#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9 +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA +#define GL_SHADER_STORAGE_BUFFER 0x90D2 +#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3 +#define GL_SHADER_STORAGE_BUFFER_START 0x90D4 +#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5 +#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6 +#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA +#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB +#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC +#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD +#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE +#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF +#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000 +#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39 +#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA +#define GL_STENCIL_INDEX 0x1901 +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F +#define GL_SAMPLE_POSITION 0x8E50 +#define GL_SAMPLE_MASK 0x8E51 +#define GL_SAMPLE_MASK_VALUE 0x8E52 +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 +#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E +#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F +#define GL_MAX_INTEGER_SAMPLES 0x9110 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 +#define GL_TEXTURE_SAMPLES 0x9106 +#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_ALPHA_SIZE 0x805F +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_TEXTURE_STENCIL_SIZE 0x88F1 +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE 0x8C13 +#define GL_TEXTURE_DEPTH_TYPE 0x8C16 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A +#define GL_VERTEX_ATTRIB_BINDING 0x82D4 +#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5 +#define GL_VERTEX_BINDING_DIVISOR 0x82D6 +#define GL_VERTEX_BINDING_OFFSET 0x82D7 +#define GL_VERTEX_BINDING_STRIDE 0x82D8 +#define GL_VERTEX_BINDING_BUFFER 0x8F4F +#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9 +#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA +#define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5 +typedef void (GL_APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); +typedef void (GL_APIENTRYP PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect); +typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect); +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param); +typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint *params); +typedef GLuint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params); +typedef GLint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const GLchar *name); +typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program); +typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program); +typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar *const*strings); +typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline); +typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint *pipelines); +typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines); +typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint v0); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint v0, GLint v1); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint v0); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat v0); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (GL_APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); +typedef void (GL_APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data); +typedef void (GL_APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers); +typedef void (GL_APIENTRYP PFNGLMEMORYBARRIERBYREGIONPROC) (GLbitfield barriers); +typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (GL_APIENTRYP PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat *val); +typedef void (GL_APIENTRYP PFNGLSAMPLEMASKIPROC) (GLuint maskNumber, GLbitfield mask); +typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERIVPROC) (GLenum target, GLint level, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERFVPROC) (GLenum target, GLint level, GLenum pname, GLfloat *params); +typedef void (GL_APIENTRYP PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex); +typedef void (GL_APIENTRYP PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor); +#if GL_GLES_PROTOTYPES +GL_APICALL void GL_APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); +GL_APICALL void GL_APIENTRY glDispatchComputeIndirect (GLintptr indirect); +GL_APICALL void GL_APIENTRY glDrawArraysIndirect (GLenum mode, const void *indirect); +GL_APICALL void GL_APIENTRY glDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect); +GL_APICALL void GL_APIENTRY glFramebufferParameteri (GLenum target, GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glGetFramebufferParameteriv (GLenum target, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetProgramInterfaceiv (GLuint program, GLenum programInterface, GLenum pname, GLint *params); +GL_APICALL GLuint GL_APIENTRY glGetProgramResourceIndex (GLuint program, GLenum programInterface, const GLchar *name); +GL_APICALL void GL_APIENTRY glGetProgramResourceName (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); +GL_APICALL void GL_APIENTRY glGetProgramResourceiv (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params); +GL_APICALL GLint GL_APIENTRY glGetProgramResourceLocation (GLuint program, GLenum programInterface, const GLchar *name); +GL_APICALL void GL_APIENTRY glUseProgramStages (GLuint pipeline, GLbitfield stages, GLuint program); +GL_APICALL void GL_APIENTRY glActiveShaderProgram (GLuint pipeline, GLuint program); +GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramv (GLenum type, GLsizei count, const GLchar *const*strings); +GL_APICALL void GL_APIENTRY glBindProgramPipeline (GLuint pipeline); +GL_APICALL void GL_APIENTRY glDeleteProgramPipelines (GLsizei n, const GLuint *pipelines); +GL_APICALL void GL_APIENTRY glGenProgramPipelines (GLsizei n, GLuint *pipelines); +GL_APICALL GLboolean GL_APIENTRY glIsProgramPipeline (GLuint pipeline); +GL_APICALL void GL_APIENTRY glGetProgramPipelineiv (GLuint pipeline, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glProgramUniform1i (GLuint program, GLint location, GLint v0); +GL_APICALL void GL_APIENTRY glProgramUniform2i (GLuint program, GLint location, GLint v0, GLint v1); +GL_APICALL void GL_APIENTRY glProgramUniform3i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +GL_APICALL void GL_APIENTRY glProgramUniform4i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +GL_APICALL void GL_APIENTRY glProgramUniform1ui (GLuint program, GLint location, GLuint v0); +GL_APICALL void GL_APIENTRY glProgramUniform2ui (GLuint program, GLint location, GLuint v0, GLuint v1); +GL_APICALL void GL_APIENTRY glProgramUniform3ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +GL_APICALL void GL_APIENTRY glProgramUniform4ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +GL_APICALL void GL_APIENTRY glProgramUniform1f (GLuint program, GLint location, GLfloat v0); +GL_APICALL void GL_APIENTRY glProgramUniform2f (GLuint program, GLint location, GLfloat v0, GLfloat v1); +GL_APICALL void GL_APIENTRY glProgramUniform3f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +GL_APICALL void GL_APIENTRY glProgramUniform4f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +GL_APICALL void GL_APIENTRY glProgramUniform1iv (GLuint program, GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glProgramUniform2iv (GLuint program, GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glProgramUniform3iv (GLuint program, GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glProgramUniform4iv (GLuint program, GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glProgramUniform1uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glProgramUniform2uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glProgramUniform3uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glProgramUniform4uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glProgramUniform1fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniform2fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniform3fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniform4fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glValidateProgramPipeline (GLuint pipeline); +GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLog (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +GL_APICALL void GL_APIENTRY glBindImageTexture (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); +GL_APICALL void GL_APIENTRY glGetBooleani_v (GLenum target, GLuint index, GLboolean *data); +GL_APICALL void GL_APIENTRY glMemoryBarrier (GLbitfield barriers); +GL_APICALL void GL_APIENTRY glMemoryBarrierByRegion (GLbitfield barriers); +GL_APICALL void GL_APIENTRY glTexStorage2DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +GL_APICALL void GL_APIENTRY glGetMultisamplefv (GLenum pname, GLuint index, GLfloat *val); +GL_APICALL void GL_APIENTRY glSampleMaski (GLuint maskNumber, GLbitfield mask); +GL_APICALL void GL_APIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params); +GL_APICALL void GL_APIENTRY glBindVertexBuffer (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +GL_APICALL void GL_APIENTRY glVertexAttribFormat (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +GL_APICALL void GL_APIENTRY glVertexAttribIFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +GL_APICALL void GL_APIENTRY glVertexAttribBinding (GLuint attribindex, GLuint bindingindex); +GL_APICALL void GL_APIENTRY glVertexBindingDivisor (GLuint bindingindex, GLuint divisor); +#endif +#endif /* GL_ES_VERSION_3_1 */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sdk/GLES3/gl32.h b/sdk/GLES3/gl32.h new file mode 100644 index 0000000..ae56b0e --- /dev/null +++ b/sdk/GLES3/gl32.h @@ -0,0 +1,1808 @@ +#ifndef __gles2_gl32_h_ +#define __gles2_gl32_h_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright 2013-2020 The Khronos Group Inc. +** SPDX-License-Identifier: MIT +** +** This header is generated from the Khronos OpenGL / OpenGL ES XML +** API Registry. The current version of the Registry, generator scripts +** used to make the header, and the header can be found at +** https://github.com/KhronosGroup/OpenGL-Registry +*/ + +#include + +#ifndef GL_APIENTRYP +#define GL_APIENTRYP GL_APIENTRY* +#endif + +#ifndef GL_GLES_PROTOTYPES +#define GL_GLES_PROTOTYPES 1 +#endif + +/* Generated on date 20191013 */ + +/* Generated C header for: + * API: gles2 + * Profile: common + * Versions considered: 2\.[0-9]|3\.[012] + * Versions emitted: .* + * Default extensions included: None + * Additional extensions included: _nomatch_^ + * Extensions removed: _nomatch_^ + */ + +#ifndef GL_ES_VERSION_2_0 +#define GL_ES_VERSION_2_0 1 +#include +typedef khronos_int8_t GLbyte; +typedef khronos_float_t GLclampf; +typedef khronos_int32_t GLfixed; +typedef khronos_int16_t GLshort; +typedef khronos_uint16_t GLushort; +typedef void GLvoid; +typedef struct __GLsync *GLsync; +typedef khronos_int64_t GLint64; +typedef khronos_uint64_t GLuint64; +typedef unsigned int GLenum; +typedef unsigned int GLuint; +typedef char GLchar; +typedef khronos_float_t GLfloat; +typedef khronos_ssize_t GLsizeiptr; +typedef khronos_intptr_t GLintptr; +typedef unsigned int GLbitfield; +typedef int GLint; +typedef unsigned char GLboolean; +typedef int GLsizei; +typedef khronos_uint8_t GLubyte; +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_FALSE 0 +#define GL_TRUE 1 +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_FUNC_ADD 0x8006 +#define GL_BLEND_EQUATION 0x8009 +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_STREAM_DRAW 0x88E0 +#define GL_STATIC_DRAW 0x88E4 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_CULL_FACE 0x0B44 +#define GL_BLEND 0x0BE2 +#define GL_DITHER 0x0BD0 +#define GL_STENCIL_TEST 0x0B90 +#define GL_DEPTH_TEST 0x0B71 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_CW 0x0900 +#define GL_CCW 0x0901 +#define GL_LINE_WIDTH 0x0B21 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#define GL_VIEWPORT 0x0BA2 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_RED_BITS 0x0D52 +#define GL_GREEN_BITS 0x0D53 +#define GL_BLUE_BITS 0x0D54 +#define GL_ALPHA_BITS 0x0D55 +#define GL_DEPTH_BITS 0x0D56 +#define GL_STENCIL_BITS 0x0D57 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_FIXED 0x140C +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#define GL_SHADER_TYPE 0x8B4F +#define GL_DELETE_STATUS 0x8B80 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_INVERT 0x150A +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_TEXTURE 0x1702 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_REPEAT 0x2901 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B +#define GL_COMPILE_STATUS 0x8B81 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_SHADER_COMPILER 0x8DFA +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 +#define GL_LOW_FLOAT 0x8DF0 +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_LOW_INT 0x8DF3 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_HIGH_INT 0x8DF5 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGB565 0x8D62 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_NONE 0 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +typedef void (GL_APIENTRYP PFNGLACTIVETEXTUREPROC) (GLenum texture); +typedef void (GL_APIENTRYP PFNGLATTACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (GL_APIENTRYP PFNGLBINDATTRIBLOCATIONPROC) (GLuint program, GLuint index, const GLchar *name); +typedef void (GL_APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer); +typedef void (GL_APIENTRYP PFNGLBINDFRAMEBUFFERPROC) (GLenum target, GLuint framebuffer); +typedef void (GL_APIENTRYP PFNGLBINDRENDERBUFFERPROC) (GLenum target, GLuint renderbuffer); +typedef void (GL_APIENTRYP PFNGLBINDTEXTUREPROC) (GLenum target, GLuint texture); +typedef void (GL_APIENTRYP PFNGLBLENDCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONPROC) (GLenum mode); +typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha); +typedef void (GL_APIENTRYP PFNGLBLENDFUNCPROC) (GLenum sfactor, GLenum dfactor); +typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +typedef void (GL_APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage); +typedef void (GL_APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); +typedef GLenum (GL_APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC) (GLenum target); +typedef void (GL_APIENTRYP PFNGLCLEARPROC) (GLbitfield mask); +typedef void (GL_APIENTRYP PFNGLCLEARCOLORPROC) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (GL_APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d); +typedef void (GL_APIENTRYP PFNGLCLEARSTENCILPROC) (GLint s); +typedef void (GL_APIENTRYP PFNGLCOLORMASKPROC) (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +typedef void (GL_APIENTRYP PFNGLCOMPILESHADERPROC) (GLuint shader); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); +typedef void (GL_APIENTRYP PFNGLCOPYTEXIMAGE2DPROC) (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef GLuint (GL_APIENTRYP PFNGLCREATEPROGRAMPROC) (void); +typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROC) (GLenum type); +typedef void (GL_APIENTRYP PFNGLCULLFACEPROC) (GLenum mode); +typedef void (GL_APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers); +typedef void (GL_APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC) (GLsizei n, const GLuint *framebuffers); +typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPROC) (GLuint program); +typedef void (GL_APIENTRYP PFNGLDELETERENDERBUFFERSPROC) (GLsizei n, const GLuint *renderbuffers); +typedef void (GL_APIENTRYP PFNGLDELETESHADERPROC) (GLuint shader); +typedef void (GL_APIENTRYP PFNGLDELETETEXTURESPROC) (GLsizei n, const GLuint *textures); +typedef void (GL_APIENTRYP PFNGLDEPTHFUNCPROC) (GLenum func); +typedef void (GL_APIENTRYP PFNGLDEPTHMASKPROC) (GLboolean flag); +typedef void (GL_APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f); +typedef void (GL_APIENTRYP PFNGLDETACHSHADERPROC) (GLuint program, GLuint shader); +typedef void (GL_APIENTRYP PFNGLDISABLEPROC) (GLenum cap); +typedef void (GL_APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC) (GLuint index); +typedef void (GL_APIENTRYP PFNGLDRAWARRAYSPROC) (GLenum mode, GLint first, GLsizei count); +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices); +typedef void (GL_APIENTRYP PFNGLENABLEPROC) (GLenum cap); +typedef void (GL_APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC) (GLuint index); +typedef void (GL_APIENTRYP PFNGLFINISHPROC) (void); +typedef void (GL_APIENTRYP PFNGLFLUSHPROC) (void); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GL_APIENTRYP PFNGLFRONTFACEPROC) (GLenum mode); +typedef void (GL_APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers); +typedef void (GL_APIENTRYP PFNGLGENERATEMIPMAPPROC) (GLenum target); +typedef void (GL_APIENTRYP PFNGLGENFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers); +typedef void (GL_APIENTRYP PFNGLGENRENDERBUFFERSPROC) (GLsizei n, GLuint *renderbuffers); +typedef void (GL_APIENTRYP PFNGLGENTEXTURESPROC) (GLsizei n, GLuint *textures); +typedef void (GL_APIENTRYP PFNGLGETACTIVEATTRIBPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +typedef void (GL_APIENTRYP PFNGLGETATTACHEDSHADERSPROC) (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders); +typedef GLint (GL_APIENTRYP PFNGLGETATTRIBLOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (GL_APIENTRYP PFNGLGETBOOLEANVPROC) (GLenum pname, GLboolean *data); +typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef GLenum (GL_APIENTRYP PFNGLGETERRORPROC) (void); +typedef void (GL_APIENTRYP PFNGLGETFLOATVPROC) (GLenum pname, GLfloat *data); +typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) (GLenum target, GLenum attachment, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETINTEGERVPROC) (GLenum pname, GLint *data); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMIVPROC) (GLuint program, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMINFOLOGPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (GL_APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETSHADERIVPROC) (GLuint shader, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETSHADERINFOLOGPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (GL_APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision); +typedef void (GL_APIENTRYP PFNGLGETSHADERSOURCEPROC) (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); +typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGPROC) (GLenum name); +typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERFVPROC) (GLenum target, GLenum pname, GLfloat *params); +typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETUNIFORMFVPROC) (GLuint program, GLint location, GLfloat *params); +typedef void (GL_APIENTRYP PFNGLGETUNIFORMIVPROC) (GLuint program, GLint location, GLint *params); +typedef GLint (GL_APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBFVPROC) (GLuint index, GLenum pname, GLfloat *params); +typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIVPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC) (GLuint index, GLenum pname, void **pointer); +typedef void (GL_APIENTRYP PFNGLHINTPROC) (GLenum target, GLenum mode); +typedef GLboolean (GL_APIENTRYP PFNGLISBUFFERPROC) (GLuint buffer); +typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDPROC) (GLenum cap); +typedef GLboolean (GL_APIENTRYP PFNGLISFRAMEBUFFERPROC) (GLuint framebuffer); +typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPROC) (GLuint program); +typedef GLboolean (GL_APIENTRYP PFNGLISRENDERBUFFERPROC) (GLuint renderbuffer); +typedef GLboolean (GL_APIENTRYP PFNGLISSHADERPROC) (GLuint shader); +typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREPROC) (GLuint texture); +typedef void (GL_APIENTRYP PFNGLLINEWIDTHPROC) (GLfloat width); +typedef void (GL_APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program); +typedef void (GL_APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param); +typedef void (GL_APIENTRYP PFNGLPOLYGONOFFSETPROC) (GLfloat factor, GLfloat units); +typedef void (GL_APIENTRYP PFNGLREADPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); +typedef void (GL_APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void); +typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLSAMPLECOVERAGEPROC) (GLfloat value, GLboolean invert); +typedef void (GL_APIENTRYP PFNGLSCISSORPROC) (GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length); +typedef void (GL_APIENTRYP PFNGLSHADERSOURCEPROC) (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); +typedef void (GL_APIENTRYP PFNGLSTENCILFUNCPROC) (GLenum func, GLint ref, GLuint mask); +typedef void (GL_APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC) (GLenum face, GLenum func, GLint ref, GLuint mask); +typedef void (GL_APIENTRYP PFNGLSTENCILMASKPROC) (GLuint mask); +typedef void (GL_APIENTRYP PFNGLSTENCILMASKSEPARATEPROC) (GLenum face, GLuint mask); +typedef void (GL_APIENTRYP PFNGLSTENCILOPPROC) (GLenum fail, GLenum zfail, GLenum zpass); +typedef void (GL_APIENTRYP PFNGLSTENCILOPSEPARATEPROC) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +typedef void (GL_APIENTRYP PFNGLTEXIMAGE2DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFPROC) (GLenum target, GLenum pname, GLfloat param); +typedef void (GL_APIENTRYP PFNGLTEXPARAMETERFVPROC) (GLenum target, GLenum pname, const GLfloat *params); +typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIPROC) (GLenum target, GLenum pname, GLint param); +typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE2DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +typedef void (GL_APIENTRYP PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0); +typedef void (GL_APIENTRYP PFNGLUNIFORM1FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM1IPROC) (GLint location, GLint v0); +typedef void (GL_APIENTRYP PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1); +typedef void (GL_APIENTRYP PFNGLUNIFORM2FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM2IPROC) (GLint location, GLint v0, GLint v1); +typedef void (GL_APIENTRYP PFNGLUNIFORM2IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM3FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GL_APIENTRYP PFNGLUNIFORM3FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM3IPROC) (GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GL_APIENTRYP PFNGLUNIFORM3IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GL_APIENTRYP PFNGLUNIFORM4FVPROC) (GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM4IPROC) (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GL_APIENTRYP PFNGLUNIFORM4IVPROC) (GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUSEPROGRAMPROC) (GLuint program); +typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FPROC) (GLuint index, GLfloat x); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB1FVPROC) (GLuint index, const GLfloat *v); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FPROC) (GLuint index, GLfloat x, GLfloat y); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB2FVPROC) (GLuint index, const GLfloat *v); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB3FVPROC) (GLuint index, const GLfloat *v); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); +typedef void (GL_APIENTRYP PFNGLVIEWPORTPROC) (GLint x, GLint y, GLsizei width, GLsizei height); +#if GL_GLES_PROTOTYPES +GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture); +GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader); +GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name); +GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer); +GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer); +GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer); +GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture); +GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode); +GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha); +GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); +GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage); +GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); +GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target); +GL_APICALL void GL_APIENTRY glClear (GLbitfield mask); +GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat d); +GL_APICALL void GL_APIENTRY glClearStencil (GLint s); +GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader); +GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); +GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); +GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL GLuint GL_APIENTRY glCreateProgram (void); +GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type); +GL_APICALL void GL_APIENTRY glCullFace (GLenum mode); +GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers); +GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers); +GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program); +GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers); +GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader); +GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures); +GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func); +GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag); +GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f); +GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader); +GL_APICALL void GL_APIENTRY glDisable (GLenum cap); +GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index); +GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); +GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices); +GL_APICALL void GL_APIENTRY glEnable (GLenum cap); +GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index); +GL_APICALL void GL_APIENTRY glFinish (void); +GL_APICALL void GL_APIENTRY glFlush (void); +GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode); +GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers); +GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target); +GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers); +GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers); +GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures); +GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders); +GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar *name); +GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *data); +GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params); +GL_APICALL GLenum GL_APIENTRY glGetError (void); +GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data); +GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data); +GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision); +GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); +GL_APICALL const GLubyte *GL_APIENTRY glGetString (GLenum name); +GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params); +GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params); +GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params); +GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar *name); +GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params); +GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer); +GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode); +GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer); +GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap); +GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer); +GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program); +GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer); +GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader); +GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture); +GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width); +GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program); +GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); +GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); +GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void); +GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert); +GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length); +GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); +GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask); +GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); +GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); +GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params); +GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params); +GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat v0); +GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint v0); +GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1); +GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint v0, GLint v1); +GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2); +GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUseProgram (GLuint program); +GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program); +GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint index, GLfloat x); +GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v); +GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y); +GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v); +GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z); +GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v); +GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v); +GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); +GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); +#endif +#endif /* GL_ES_VERSION_2_0 */ + +#ifndef GL_ES_VERSION_3_0 +#define GL_ES_VERSION_3_0 1 +typedef khronos_uint16_t GLhalf; +#define GL_READ_BUFFER 0x0C02 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_RED 0x1903 +#define GL_RGB8 0x8051 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_COLOR_ATTACHMENT16 0x8CF0 +#define GL_COLOR_ATTACHMENT17 0x8CF1 +#define GL_COLOR_ATTACHMENT18 0x8CF2 +#define GL_COLOR_ATTACHMENT19 0x8CF3 +#define GL_COLOR_ATTACHMENT20 0x8CF4 +#define GL_COLOR_ATTACHMENT21 0x8CF5 +#define GL_COLOR_ATTACHMENT22 0x8CF6 +#define GL_COLOR_ATTACHMENT23 0x8CF7 +#define GL_COLOR_ATTACHMENT24 0x8CF8 +#define GL_COLOR_ATTACHMENT25 0x8CF9 +#define GL_COLOR_ATTACHMENT26 0x8CFA +#define GL_COLOR_ATTACHMENT27 0x8CFB +#define GL_COLOR_ATTACHMENT28 0x8CFC +#define GL_COLOR_ATTACHMENT29 0x8CFD +#define GL_COLOR_ATTACHMENT30 0x8CFE +#define GL_COLOR_ATTACHMENT31 0x8CFF +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_HALF_FLOAT 0x140B +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_RG 0x8227 +#define GL_RG_INTEGER 0x8228 +#define GL_R8 0x8229 +#define GL_RG8 0x822B +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#define GL_VERTEX_ARRAY_BINDING 0x85B5 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_COPY_READ_BUFFER_BINDING 0x8F36 +#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37 +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_INVALID_INDEX 0xFFFFFFFFu +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A +#define GL_SAMPLER_BINDING 0x8919 +#define GL_RGB10_A2UI 0x906F +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_INT_2_10_10_10_REV 0x8D9F +#define GL_TRANSFORM_FEEDBACK 0x8E22 +#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23 +#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 +#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_PROGRAM_BINARY_FORMATS 0x87FF +#define GL_COMPRESSED_R11_EAC 0x9270 +#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271 +#define GL_COMPRESSED_RG11_EAC 0x9272 +#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 +#define GL_COMPRESSED_RGB8_ETC2 0x9274 +#define GL_COMPRESSED_SRGB8_ETC2 0x9275 +#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 +#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 +#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 +#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F +#define GL_MAX_ELEMENT_INDEX 0x8D6B +#define GL_NUM_SAMPLE_COUNTS 0x9380 +#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF +typedef void (GL_APIENTRYP PFNGLREADBUFFERPROC) (GLenum src); +typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); +typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); +typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); +typedef void (GL_APIENTRYP PFNGLGENQUERIESPROC) (GLsizei n, GLuint *ids); +typedef void (GL_APIENTRYP PFNGLDELETEQUERIESPROC) (GLsizei n, const GLuint *ids); +typedef GLboolean (GL_APIENTRYP PFNGLISQUERYPROC) (GLuint id); +typedef void (GL_APIENTRYP PFNGLBEGINQUERYPROC) (GLenum target, GLuint id); +typedef void (GL_APIENTRYP PFNGLENDQUERYPROC) (GLenum target); +typedef void (GL_APIENTRYP PFNGLGETQUERYIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVPROC) (GLuint id, GLenum pname, GLuint *params); +typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target); +typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVPROC) (GLenum target, GLenum pname, void **params); +typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSPROC) (GLsizei n, const GLenum *bufs); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void *(GL_APIENTRYP PFNGLMAPBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC) (GLenum target, GLintptr offset, GLsizeiptr length); +typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYPROC) (GLuint array); +typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *arrays); +typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays); +typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYPROC) (GLuint array); +typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VPROC) (GLenum target, GLuint index, GLint *data); +typedef void (GL_APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC) (GLenum primitiveMode); +typedef void (GL_APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC) (void); +typedef void (GL_APIENTRYP PFNGLBINDBUFFERRANGEPROC) (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GL_APIENTRYP PFNGLBINDBUFFERBASEPROC) (GLenum target, GLuint index, GLuint buffer); +typedef void (GL_APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC) (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode); +typedef void (GL_APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC) (GLuint index, GLenum pname, GLuint *params); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4IVPROC) (GLuint index, const GLint *v); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC) (GLuint index, const GLuint *v); +typedef void (GL_APIENTRYP PFNGLGETUNIFORMUIVPROC) (GLuint program, GLint location, GLuint *params); +typedef GLint (GL_APIENTRYP PFNGLGETFRAGDATALOCATIONPROC) (GLuint program, const GLchar *name); +typedef void (GL_APIENTRYP PFNGLUNIFORM1UIPROC) (GLint location, GLuint v0); +typedef void (GL_APIENTRYP PFNGLUNIFORM2UIPROC) (GLint location, GLuint v0, GLuint v1); +typedef void (GL_APIENTRYP PFNGLUNIFORM3UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GL_APIENTRYP PFNGLUNIFORM4UIPROC) (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GL_APIENTRYP PFNGLUNIFORM1UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM2UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM3UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLUNIFORM4UIVPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLCLEARBUFFERIVPROC) (GLenum buffer, GLint drawbuffer, const GLint *value); +typedef void (GL_APIENTRYP PFNGLCLEARBUFFERUIVPROC) (GLenum buffer, GLint drawbuffer, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFVPROC) (GLenum buffer, GLint drawbuffer, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLCLEARBUFFERFIPROC) (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +typedef const GLubyte *(GL_APIENTRYP PFNGLGETSTRINGIPROC) (GLenum name, GLuint index); +typedef void (GL_APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +typedef void (GL_APIENTRYP PFNGLGETUNIFORMINDICESPROC) (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices); +typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC) (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params); +typedef GLuint (GL_APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC) (GLuint program, const GLchar *uniformBlockName); +typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC) (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName); +typedef void (GL_APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC) (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount); +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount); +typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags); +typedef GLboolean (GL_APIENTRYP PFNGLISSYNCPROC) (GLsync sync); +typedef void (GL_APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync); +typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (GL_APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (GL_APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data); +typedef void (GL_APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); +typedef void (GL_APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data); +typedef void (GL_APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params); +typedef void (GL_APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers); +typedef void (GL_APIENTRYP PFNGLDELETESAMPLERSPROC) (GLsizei count, const GLuint *samplers); +typedef GLboolean (GL_APIENTRYP PFNGLISSAMPLERPROC) (GLuint sampler); +typedef void (GL_APIENTRYP PFNGLBINDSAMPLERPROC) (GLuint unit, GLuint sampler); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIPROC) (GLuint sampler, GLenum pname, GLint param); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, const GLint *param); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFPROC) (GLuint sampler, GLenum pname, GLfloat param); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, const GLfloat *param); +typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC) (GLuint sampler, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC) (GLuint sampler, GLenum pname, GLfloat *params); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor); +typedef void (GL_APIENTRYP PFNGLBINDTRANSFORMFEEDBACKPROC) (GLenum target, GLuint id); +typedef void (GL_APIENTRYP PFNGLDELETETRANSFORMFEEDBACKSPROC) (GLsizei n, const GLuint *ids); +typedef void (GL_APIENTRYP PFNGLGENTRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids); +typedef GLboolean (GL_APIENTRYP PFNGLISTRANSFORMFEEDBACKPROC) (GLuint id); +typedef void (GL_APIENTRYP PFNGLPAUSETRANSFORMFEEDBACKPROC) (void); +typedef void (GL_APIENTRYP PFNGLRESUMETRANSFORMFEEDBACKPROC) (void); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); +typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length); +typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIPROC) (GLuint program, GLenum pname, GLint value); +typedef void (GL_APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments); +typedef void (GL_APIENTRYP PFNGLINVALIDATESUBFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params); +#if GL_GLES_PROTOTYPES +GL_APICALL void GL_APIENTRY glReadBuffer (GLenum src); +GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); +GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +GL_APICALL void GL_APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); +GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); +GL_APICALL void GL_APIENTRY glGenQueries (GLsizei n, GLuint *ids); +GL_APICALL void GL_APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids); +GL_APICALL GLboolean GL_APIENTRY glIsQuery (GLuint id); +GL_APICALL void GL_APIENTRY glBeginQuery (GLenum target, GLuint id); +GL_APICALL void GL_APIENTRY glEndQuery (GLenum target); +GL_APICALL void GL_APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params); +GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer (GLenum target); +GL_APICALL void GL_APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, void **params); +GL_APICALL void GL_APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs); +GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +GL_APICALL void *GL_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +GL_APICALL void GL_APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length); +GL_APICALL void GL_APIENTRY glBindVertexArray (GLuint array); +GL_APICALL void GL_APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays); +GL_APICALL void GL_APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays); +GL_APICALL GLboolean GL_APIENTRY glIsVertexArray (GLuint array); +GL_APICALL void GL_APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data); +GL_APICALL void GL_APIENTRY glBeginTransformFeedback (GLenum primitiveMode); +GL_APICALL void GL_APIENTRY glEndTransformFeedback (void); +GL_APICALL void GL_APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +GL_APICALL void GL_APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer); +GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode); +GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +GL_APICALL void GL_APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +GL_APICALL void GL_APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params); +GL_APICALL void GL_APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w); +GL_APICALL void GL_APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +GL_APICALL void GL_APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v); +GL_APICALL void GL_APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v); +GL_APICALL void GL_APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params); +GL_APICALL GLint GL_APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name); +GL_APICALL void GL_APIENTRY glUniform1ui (GLint location, GLuint v0); +GL_APICALL void GL_APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1); +GL_APICALL void GL_APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2); +GL_APICALL void GL_APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +GL_APICALL void GL_APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value); +GL_APICALL void GL_APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value); +GL_APICALL void GL_APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value); +GL_APICALL void GL_APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +GL_APICALL const GLubyte *GL_APIENTRY glGetStringi (GLenum name, GLuint index); +GL_APICALL void GL_APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +GL_APICALL void GL_APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices); +GL_APICALL void GL_APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params); +GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName); +GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName); +GL_APICALL void GL_APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +GL_APICALL void GL_APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instancecount); +GL_APICALL void GL_APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount); +GL_APICALL GLsync GL_APIENTRY glFenceSync (GLenum condition, GLbitfield flags); +GL_APICALL GLboolean GL_APIENTRY glIsSync (GLsync sync); +GL_APICALL void GL_APIENTRY glDeleteSync (GLsync sync); +GL_APICALL GLenum GL_APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); +GL_APICALL void GL_APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); +GL_APICALL void GL_APIENTRY glGetInteger64v (GLenum pname, GLint64 *data); +GL_APICALL void GL_APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); +GL_APICALL void GL_APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data); +GL_APICALL void GL_APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params); +GL_APICALL void GL_APIENTRY glGenSamplers (GLsizei count, GLuint *samplers); +GL_APICALL void GL_APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers); +GL_APICALL GLboolean GL_APIENTRY glIsSampler (GLuint sampler); +GL_APICALL void GL_APIENTRY glBindSampler (GLuint unit, GLuint sampler); +GL_APICALL void GL_APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param); +GL_APICALL void GL_APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param); +GL_APICALL void GL_APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param); +GL_APICALL void GL_APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params); +GL_APICALL void GL_APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor); +GL_APICALL void GL_APIENTRY glBindTransformFeedback (GLenum target, GLuint id); +GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids); +GL_APICALL void GL_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids); +GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback (GLuint id); +GL_APICALL void GL_APIENTRY glPauseTransformFeedback (void); +GL_APICALL void GL_APIENTRY glResumeTransformFeedback (void); +GL_APICALL void GL_APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); +GL_APICALL void GL_APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length); +GL_APICALL void GL_APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value); +GL_APICALL void GL_APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments); +GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +GL_APICALL void GL_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params); +#endif +#endif /* GL_ES_VERSION_3_0 */ + +#ifndef GL_ES_VERSION_3_1 +#define GL_ES_VERSION_3_1 1 +#define GL_COMPUTE_SHADER 0x91B9 +#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB +#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC +#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD +#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262 +#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263 +#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264 +#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265 +#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266 +#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB +#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE +#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF +#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267 +#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE +#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF +#define GL_COMPUTE_SHADER_BIT 0x00000020 +#define GL_DRAW_INDIRECT_BUFFER 0x8F3F +#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43 +#define GL_MAX_UNIFORM_LOCATIONS 0x826E +#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310 +#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311 +#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313 +#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314 +#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315 +#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316 +#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318 +#define GL_UNIFORM 0x92E1 +#define GL_UNIFORM_BLOCK 0x92E2 +#define GL_PROGRAM_INPUT 0x92E3 +#define GL_PROGRAM_OUTPUT 0x92E4 +#define GL_BUFFER_VARIABLE 0x92E5 +#define GL_SHADER_STORAGE_BLOCK 0x92E6 +#define GL_ATOMIC_COUNTER_BUFFER 0x92C0 +#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4 +#define GL_ACTIVE_RESOURCES 0x92F5 +#define GL_MAX_NAME_LENGTH 0x92F6 +#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7 +#define GL_NAME_LENGTH 0x92F9 +#define GL_TYPE 0x92FA +#define GL_ARRAY_SIZE 0x92FB +#define GL_OFFSET 0x92FC +#define GL_BLOCK_INDEX 0x92FD +#define GL_ARRAY_STRIDE 0x92FE +#define GL_MATRIX_STRIDE 0x92FF +#define GL_IS_ROW_MAJOR 0x9300 +#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301 +#define GL_BUFFER_BINDING 0x9302 +#define GL_BUFFER_DATA_SIZE 0x9303 +#define GL_NUM_ACTIVE_VARIABLES 0x9304 +#define GL_ACTIVE_VARIABLES 0x9305 +#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306 +#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A +#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B +#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C +#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D +#define GL_LOCATION 0x930E +#define GL_VERTEX_SHADER_BIT 0x00000001 +#define GL_FRAGMENT_SHADER_BIT 0x00000002 +#define GL_ALL_SHADER_BITS 0xFFFFFFFF +#define GL_PROGRAM_SEPARABLE 0x8258 +#define GL_ACTIVE_PROGRAM 0x8259 +#define GL_PROGRAM_PIPELINE_BINDING 0x825A +#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1 +#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2 +#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3 +#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC +#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0 +#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1 +#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2 +#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6 +#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7 +#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8 +#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC +#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9 +#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB +#define GL_MAX_IMAGE_UNITS 0x8F38 +#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA +#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE +#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF +#define GL_IMAGE_BINDING_NAME 0x8F3A +#define GL_IMAGE_BINDING_LEVEL 0x8F3B +#define GL_IMAGE_BINDING_LAYERED 0x8F3C +#define GL_IMAGE_BINDING_LAYER 0x8F3D +#define GL_IMAGE_BINDING_ACCESS 0x8F3E +#define GL_IMAGE_BINDING_FORMAT 0x906E +#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001 +#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002 +#define GL_UNIFORM_BARRIER_BIT 0x00000004 +#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008 +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020 +#define GL_COMMAND_BARRIER_BIT 0x00000040 +#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080 +#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100 +#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200 +#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400 +#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800 +#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000 +#define GL_ALL_BARRIER_BITS 0xFFFFFFFF +#define GL_IMAGE_2D 0x904D +#define GL_IMAGE_3D 0x904E +#define GL_IMAGE_CUBE 0x9050 +#define GL_IMAGE_2D_ARRAY 0x9053 +#define GL_INT_IMAGE_2D 0x9058 +#define GL_INT_IMAGE_3D 0x9059 +#define GL_INT_IMAGE_CUBE 0x905B +#define GL_INT_IMAGE_2D_ARRAY 0x905E +#define GL_UNSIGNED_INT_IMAGE_2D 0x9063 +#define GL_UNSIGNED_INT_IMAGE_3D 0x9064 +#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069 +#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7 +#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8 +#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9 +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA +#define GL_SHADER_STORAGE_BUFFER 0x90D2 +#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3 +#define GL_SHADER_STORAGE_BUFFER_START 0x90D4 +#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5 +#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6 +#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA +#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB +#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC +#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD +#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE +#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF +#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000 +#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39 +#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA +#define GL_STENCIL_INDEX 0x1901 +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F +#define GL_SAMPLE_POSITION 0x8E50 +#define GL_SAMPLE_MASK 0x8E51 +#define GL_SAMPLE_MASK_VALUE 0x8E52 +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 +#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E +#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F +#define GL_MAX_INTEGER_SAMPLES 0x9110 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 +#define GL_TEXTURE_SAMPLES 0x9106 +#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_ALPHA_SIZE 0x805F +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_TEXTURE_STENCIL_SIZE 0x88F1 +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE 0x8C13 +#define GL_TEXTURE_DEPTH_TYPE 0x8C16 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A +#define GL_VERTEX_ATTRIB_BINDING 0x82D4 +#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5 +#define GL_VERTEX_BINDING_DIVISOR 0x82D6 +#define GL_VERTEX_BINDING_OFFSET 0x82D7 +#define GL_VERTEX_BINDING_STRIDE 0x82D8 +#define GL_VERTEX_BINDING_BUFFER 0x8F4F +#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9 +#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA +#define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5 +typedef void (GL_APIENTRYP PFNGLDISPATCHCOMPUTEPROC) (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); +typedef void (GL_APIENTRYP PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect); +typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect); +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param); +typedef void (GL_APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint *params); +typedef GLuint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params); +typedef GLint (GL_APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const GLchar *name); +typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESPROC) (GLuint pipeline, GLbitfield stages, GLuint program); +typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMPROC) (GLuint pipeline, GLuint program); +typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVPROC) (GLenum type, GLsizei count, const GLchar *const*strings); +typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEPROC) (GLuint pipeline); +typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESPROC) (GLsizei n, const GLuint *pipelines); +typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESPROC) (GLsizei n, GLuint *pipelines); +typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEPROC) (GLuint pipeline); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVPROC) (GLuint pipeline, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IPROC) (GLuint program, GLint location, GLint v0); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IPROC) (GLuint program, GLint location, GLint v0, GLint v1); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIPROC) (GLuint program, GLint location, GLuint v0); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FPROC) (GLuint program, GLint location, GLfloat v0); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIVPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEPROC) (GLuint pipeline); +typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +typedef void (GL_APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); +typedef void (GL_APIENTRYP PFNGLGETBOOLEANI_VPROC) (GLenum target, GLuint index, GLboolean *data); +typedef void (GL_APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers); +typedef void (GL_APIENTRYP PFNGLMEMORYBARRIERBYREGIONPROC) (GLbitfield barriers); +typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (GL_APIENTRYP PFNGLGETMULTISAMPLEFVPROC) (GLenum pname, GLuint index, GLfloat *val); +typedef void (GL_APIENTRYP PFNGLSAMPLEMASKIPROC) (GLuint maskNumber, GLbitfield mask); +typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERIVPROC) (GLenum target, GLint level, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERFVPROC) (GLenum target, GLint level, GLenum pname, GLfloat *params); +typedef void (GL_APIENTRYP PFNGLBINDVERTEXBUFFERPROC) (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBIFORMATPROC) (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBBINDINGPROC) (GLuint attribindex, GLuint bindingindex); +typedef void (GL_APIENTRYP PFNGLVERTEXBINDINGDIVISORPROC) (GLuint bindingindex, GLuint divisor); +#if GL_GLES_PROTOTYPES +GL_APICALL void GL_APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); +GL_APICALL void GL_APIENTRY glDispatchComputeIndirect (GLintptr indirect); +GL_APICALL void GL_APIENTRY glDrawArraysIndirect (GLenum mode, const void *indirect); +GL_APICALL void GL_APIENTRY glDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect); +GL_APICALL void GL_APIENTRY glFramebufferParameteri (GLenum target, GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glGetFramebufferParameteriv (GLenum target, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetProgramInterfaceiv (GLuint program, GLenum programInterface, GLenum pname, GLint *params); +GL_APICALL GLuint GL_APIENTRY glGetProgramResourceIndex (GLuint program, GLenum programInterface, const GLchar *name); +GL_APICALL void GL_APIENTRY glGetProgramResourceName (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); +GL_APICALL void GL_APIENTRY glGetProgramResourceiv (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params); +GL_APICALL GLint GL_APIENTRY glGetProgramResourceLocation (GLuint program, GLenum programInterface, const GLchar *name); +GL_APICALL void GL_APIENTRY glUseProgramStages (GLuint pipeline, GLbitfield stages, GLuint program); +GL_APICALL void GL_APIENTRY glActiveShaderProgram (GLuint pipeline, GLuint program); +GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramv (GLenum type, GLsizei count, const GLchar *const*strings); +GL_APICALL void GL_APIENTRY glBindProgramPipeline (GLuint pipeline); +GL_APICALL void GL_APIENTRY glDeleteProgramPipelines (GLsizei n, const GLuint *pipelines); +GL_APICALL void GL_APIENTRY glGenProgramPipelines (GLsizei n, GLuint *pipelines); +GL_APICALL GLboolean GL_APIENTRY glIsProgramPipeline (GLuint pipeline); +GL_APICALL void GL_APIENTRY glGetProgramPipelineiv (GLuint pipeline, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glProgramUniform1i (GLuint program, GLint location, GLint v0); +GL_APICALL void GL_APIENTRY glProgramUniform2i (GLuint program, GLint location, GLint v0, GLint v1); +GL_APICALL void GL_APIENTRY glProgramUniform3i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +GL_APICALL void GL_APIENTRY glProgramUniform4i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +GL_APICALL void GL_APIENTRY glProgramUniform1ui (GLuint program, GLint location, GLuint v0); +GL_APICALL void GL_APIENTRY glProgramUniform2ui (GLuint program, GLint location, GLuint v0, GLuint v1); +GL_APICALL void GL_APIENTRY glProgramUniform3ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +GL_APICALL void GL_APIENTRY glProgramUniform4ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +GL_APICALL void GL_APIENTRY glProgramUniform1f (GLuint program, GLint location, GLfloat v0); +GL_APICALL void GL_APIENTRY glProgramUniform2f (GLuint program, GLint location, GLfloat v0, GLfloat v1); +GL_APICALL void GL_APIENTRY glProgramUniform3f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +GL_APICALL void GL_APIENTRY glProgramUniform4f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +GL_APICALL void GL_APIENTRY glProgramUniform1iv (GLuint program, GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glProgramUniform2iv (GLuint program, GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glProgramUniform3iv (GLuint program, GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glProgramUniform4iv (GLuint program, GLint location, GLsizei count, const GLint *value); +GL_APICALL void GL_APIENTRY glProgramUniform1uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glProgramUniform2uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glProgramUniform3uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glProgramUniform4uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); +GL_APICALL void GL_APIENTRY glProgramUniform1fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniform2fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniform3fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniform4fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GL_APICALL void GL_APIENTRY glValidateProgramPipeline (GLuint pipeline); +GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLog (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +GL_APICALL void GL_APIENTRY glBindImageTexture (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); +GL_APICALL void GL_APIENTRY glGetBooleani_v (GLenum target, GLuint index, GLboolean *data); +GL_APICALL void GL_APIENTRY glMemoryBarrier (GLbitfield barriers); +GL_APICALL void GL_APIENTRY glMemoryBarrierByRegion (GLbitfield barriers); +GL_APICALL void GL_APIENTRY glTexStorage2DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +GL_APICALL void GL_APIENTRY glGetMultisamplefv (GLenum pname, GLuint index, GLfloat *val); +GL_APICALL void GL_APIENTRY glSampleMaski (GLuint maskNumber, GLbitfield mask); +GL_APICALL void GL_APIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params); +GL_APICALL void GL_APIENTRY glBindVertexBuffer (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +GL_APICALL void GL_APIENTRY glVertexAttribFormat (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +GL_APICALL void GL_APIENTRY glVertexAttribIFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +GL_APICALL void GL_APIENTRY glVertexAttribBinding (GLuint attribindex, GLuint bindingindex); +GL_APICALL void GL_APIENTRY glVertexBindingDivisor (GLuint bindingindex, GLuint divisor); +#endif +#endif /* GL_ES_VERSION_3_1 */ + +#ifndef GL_ES_VERSION_3_2 +#define GL_ES_VERSION_3_2 1 +typedef void (GL_APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +#define GL_MULTISAMPLE_LINE_WIDTH_RANGE 0x9381 +#define GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY 0x9382 +#define GL_MULTIPLY 0x9294 +#define GL_SCREEN 0x9295 +#define GL_OVERLAY 0x9296 +#define GL_DARKEN 0x9297 +#define GL_LIGHTEN 0x9298 +#define GL_COLORDODGE 0x9299 +#define GL_COLORBURN 0x929A +#define GL_HARDLIGHT 0x929B +#define GL_SOFTLIGHT 0x929C +#define GL_DIFFERENCE 0x929E +#define GL_EXCLUSION 0x92A0 +#define GL_HSL_HUE 0x92AD +#define GL_HSL_SATURATION 0x92AE +#define GL_HSL_COLOR 0x92AF +#define GL_HSL_LUMINOSITY 0x92B0 +#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243 +#define GL_DEBUG_CALLBACK_FUNCTION 0x8244 +#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245 +#define GL_DEBUG_SOURCE_API 0x8246 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247 +#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249 +#define GL_DEBUG_SOURCE_APPLICATION 0x824A +#define GL_DEBUG_SOURCE_OTHER 0x824B +#define GL_DEBUG_TYPE_ERROR 0x824C +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E +#define GL_DEBUG_TYPE_PORTABILITY 0x824F +#define GL_DEBUG_TYPE_PERFORMANCE 0x8250 +#define GL_DEBUG_TYPE_OTHER 0x8251 +#define GL_DEBUG_TYPE_MARKER 0x8268 +#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269 +#define GL_DEBUG_TYPE_POP_GROUP 0x826A +#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B +#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C +#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D +#define GL_BUFFER 0x82E0 +#define GL_SHADER 0x82E1 +#define GL_PROGRAM 0x82E2 +#define GL_VERTEX_ARRAY 0x8074 +#define GL_QUERY 0x82E3 +#define GL_PROGRAM_PIPELINE 0x82E4 +#define GL_SAMPLER 0x82E6 +#define GL_MAX_LABEL_LENGTH 0x82E8 +#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143 +#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144 +#define GL_DEBUG_LOGGED_MESSAGES 0x9145 +#define GL_DEBUG_SEVERITY_HIGH 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM 0x9147 +#define GL_DEBUG_SEVERITY_LOW 0x9148 +#define GL_DEBUG_OUTPUT 0x92E0 +#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002 +#define GL_STACK_OVERFLOW 0x0503 +#define GL_STACK_UNDERFLOW 0x0504 +#define GL_GEOMETRY_SHADER 0x8DD9 +#define GL_GEOMETRY_SHADER_BIT 0x00000004 +#define GL_GEOMETRY_VERTICES_OUT 0x8916 +#define GL_GEOMETRY_INPUT_TYPE 0x8917 +#define GL_GEOMETRY_OUTPUT_TYPE 0x8918 +#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F +#define GL_LAYER_PROVOKING_VERTEX 0x825E +#define GL_LINES_ADJACENCY 0x000A +#define GL_LINE_STRIP_ADJACENCY 0x000B +#define GL_TRIANGLES_ADJACENCY 0x000C +#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF +#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C +#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32 +#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123 +#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124 +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 +#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29 +#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF +#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS 0x92D5 +#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD +#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7 +#define GL_FIRST_VERTEX_CONVENTION 0x8E4D +#define GL_LAST_VERTEX_CONVENTION 0x8E4E +#define GL_UNDEFINED_VERTEX 0x8260 +#define GL_PRIMITIVES_GENERATED 0x8C87 +#define GL_FRAMEBUFFER_DEFAULT_LAYERS 0x9312 +#define GL_MAX_FRAMEBUFFER_LAYERS 0x9317 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7 +#define GL_REFERENCED_BY_GEOMETRY_SHADER 0x9309 +#define GL_PRIMITIVE_BOUNDING_BOX 0x92BE +#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004 +#define GL_CONTEXT_FLAGS 0x821E +#define GL_LOSE_CONTEXT_ON_RESET 0x8252 +#define GL_GUILTY_CONTEXT_RESET 0x8253 +#define GL_INNOCENT_CONTEXT_RESET 0x8254 +#define GL_UNKNOWN_CONTEXT_RESET 0x8255 +#define GL_RESET_NOTIFICATION_STRATEGY 0x8256 +#define GL_NO_RESET_NOTIFICATION 0x8261 +#define GL_CONTEXT_LOST 0x0507 +#define GL_SAMPLE_SHADING 0x8C36 +#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37 +#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B +#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C +#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D +#define GL_PATCHES 0x000E +#define GL_PATCH_VERTICES 0x8E72 +#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75 +#define GL_TESS_GEN_MODE 0x8E76 +#define GL_TESS_GEN_SPACING 0x8E77 +#define GL_TESS_GEN_VERTEX_ORDER 0x8E78 +#define GL_TESS_GEN_POINT_MODE 0x8E79 +#define GL_ISOLINES 0x8E7A +#define GL_QUADS 0x0007 +#define GL_FRACTIONAL_ODD 0x8E7B +#define GL_FRACTIONAL_EVEN 0x8E7C +#define GL_MAX_PATCH_VERTICES 0x8E7D +#define GL_MAX_TESS_GEN_LEVEL 0x8E7E +#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F +#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80 +#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81 +#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82 +#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83 +#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84 +#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85 +#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86 +#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89 +#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A +#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C +#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D +#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E +#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F +#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD +#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE +#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3 +#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4 +#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB +#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC +#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8 +#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9 +#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221 +#define GL_IS_PER_PATCH 0x92E7 +#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307 +#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308 +#define GL_TESS_CONTROL_SHADER 0x8E88 +#define GL_TESS_EVALUATION_SHADER 0x8E87 +#define GL_TESS_CONTROL_SHADER_BIT 0x00000008 +#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010 +#define GL_TEXTURE_BORDER_COLOR 0x1004 +#define GL_CLAMP_TO_BORDER 0x812D +#define GL_TEXTURE_BUFFER 0x8C2A +#define GL_TEXTURE_BUFFER_BINDING 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D +#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 +#define GL_IMAGE_BUFFER 0x9051 +#define GL_INT_IMAGE_BUFFER 0x905C +#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067 +#define GL_TEXTURE_BUFFER_OFFSET 0x919D +#define GL_TEXTURE_BUFFER_SIZE 0x919E +#define GL_COMPRESSED_RGBA_ASTC_4x4 0x93B0 +#define GL_COMPRESSED_RGBA_ASTC_5x4 0x93B1 +#define GL_COMPRESSED_RGBA_ASTC_5x5 0x93B2 +#define GL_COMPRESSED_RGBA_ASTC_6x5 0x93B3 +#define GL_COMPRESSED_RGBA_ASTC_6x6 0x93B4 +#define GL_COMPRESSED_RGBA_ASTC_8x5 0x93B5 +#define GL_COMPRESSED_RGBA_ASTC_8x6 0x93B6 +#define GL_COMPRESSED_RGBA_ASTC_8x8 0x93B7 +#define GL_COMPRESSED_RGBA_ASTC_10x5 0x93B8 +#define GL_COMPRESSED_RGBA_ASTC_10x6 0x93B9 +#define GL_COMPRESSED_RGBA_ASTC_10x8 0x93BA +#define GL_COMPRESSED_RGBA_ASTC_10x10 0x93BB +#define GL_COMPRESSED_RGBA_ASTC_12x10 0x93BC +#define GL_COMPRESSED_RGBA_ASTC_12x12 0x93BD +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4 0x93D0 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4 0x93D1 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5 0x93D2 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5 0x93D3 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6 0x93D4 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5 0x93D5 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6 0x93D6 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8 0x93D7 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5 0x93D8 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6 0x93D9 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8 0x93DA +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10 0x93DB +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10 0x93DC +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12 0x93DD +#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A +#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F +#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054 +#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105 +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +typedef void (GL_APIENTRYP PFNGLBLENDBARRIERPROC) (void); +typedef void (GL_APIENTRYP PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); +typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam); +typedef GLuint (GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); +typedef void (GL_APIENTRYP PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message); +typedef void (GL_APIENTRYP PFNGLPOPDEBUGGROUPPROC) (void); +typedef void (GL_APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); +typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); +typedef void (GL_APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label); +typedef void (GL_APIENTRYP PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); +typedef void (GL_APIENTRYP PFNGLGETPOINTERVPROC) (GLenum pname, void **params); +typedef void (GL_APIENTRYP PFNGLENABLEIPROC) (GLenum target, GLuint index); +typedef void (GL_APIENTRYP PFNGLDISABLEIPROC) (GLenum target, GLuint index); +typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONIPROC) (GLuint buf, GLenum mode); +typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEIPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (GL_APIENTRYP PFNGLBLENDFUNCIPROC) (GLuint buf, GLenum src, GLenum dst); +typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEIPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +typedef void (GL_APIENTRYP PFNGLCOLORMASKIPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDIPROC) (GLenum target, GLuint index); +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); +typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (GL_APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW); +typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSPROC) (void); +typedef void (GL_APIENTRYP PFNGLREADNPIXELSPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); +typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); +typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETNUNIFORMUIVPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params); +typedef void (GL_APIENTRYP PFNGLMINSAMPLESHADINGPROC) (GLfloat value); +typedef void (GL_APIENTRYP PFNGLPATCHPARAMETERIPROC) (GLenum pname, GLint value); +typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, const GLint *params); +typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, const GLuint *params); +typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIIVPROC) (GLenum target, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC) (GLenum target, GLenum pname, GLuint *params); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, const GLint *param); +typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, const GLuint *param); +typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIIVPROC) (GLuint sampler, GLenum pname, GLint *params); +typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVPROC) (GLuint sampler, GLenum pname, GLuint *params); +typedef void (GL_APIENTRYP PFNGLTEXBUFFERPROC) (GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GL_APIENTRYP PFNGLTEXBUFFERRANGEPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DMULTISAMPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +#if GL_GLES_PROTOTYPES +GL_APICALL void GL_APIENTRY glBlendBarrier (void); +GL_APICALL void GL_APIENTRY glCopyImageSubData (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +GL_APICALL void GL_APIENTRY glDebugMessageControl (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +GL_APICALL void GL_APIENTRY glDebugMessageInsert (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); +GL_APICALL void GL_APIENTRY glDebugMessageCallback (GLDEBUGPROC callback, const void *userParam); +GL_APICALL GLuint GL_APIENTRY glGetDebugMessageLog (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); +GL_APICALL void GL_APIENTRY glPushDebugGroup (GLenum source, GLuint id, GLsizei length, const GLchar *message); +GL_APICALL void GL_APIENTRY glPopDebugGroup (void); +GL_APICALL void GL_APIENTRY glObjectLabel (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); +GL_APICALL void GL_APIENTRY glGetObjectLabel (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); +GL_APICALL void GL_APIENTRY glObjectPtrLabel (const void *ptr, GLsizei length, const GLchar *label); +GL_APICALL void GL_APIENTRY glGetObjectPtrLabel (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); +GL_APICALL void GL_APIENTRY glGetPointerv (GLenum pname, void **params); +GL_APICALL void GL_APIENTRY glEnablei (GLenum target, GLuint index); +GL_APICALL void GL_APIENTRY glDisablei (GLenum target, GLuint index); +GL_APICALL void GL_APIENTRY glBlendEquationi (GLuint buf, GLenum mode); +GL_APICALL void GL_APIENTRY glBlendEquationSeparatei (GLuint buf, GLenum modeRGB, GLenum modeAlpha); +GL_APICALL void GL_APIENTRY glBlendFunci (GLuint buf, GLenum src, GLenum dst); +GL_APICALL void GL_APIENTRY glBlendFuncSeparatei (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +GL_APICALL void GL_APIENTRY glColorMaski (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +GL_APICALL GLboolean GL_APIENTRY glIsEnabledi (GLenum target, GLuint index); +GL_APICALL void GL_APIENTRY glDrawElementsBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); +GL_APICALL void GL_APIENTRY glDrawRangeElementsBaseVertex (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); +GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertex (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex); +GL_APICALL void GL_APIENTRY glFramebufferTexture (GLenum target, GLenum attachment, GLuint texture, GLint level); +GL_APICALL void GL_APIENTRY glPrimitiveBoundingBox (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW); +GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatus (void); +GL_APICALL void GL_APIENTRY glReadnPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); +GL_APICALL void GL_APIENTRY glGetnUniformfv (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); +GL_APICALL void GL_APIENTRY glGetnUniformiv (GLuint program, GLint location, GLsizei bufSize, GLint *params); +GL_APICALL void GL_APIENTRY glGetnUniformuiv (GLuint program, GLint location, GLsizei bufSize, GLuint *params); +GL_APICALL void GL_APIENTRY glMinSampleShading (GLfloat value); +GL_APICALL void GL_APIENTRY glPatchParameteri (GLenum pname, GLint value); +GL_APICALL void GL_APIENTRY glTexParameterIiv (GLenum target, GLenum pname, const GLint *params); +GL_APICALL void GL_APIENTRY glTexParameterIuiv (GLenum target, GLenum pname, const GLuint *params); +GL_APICALL void GL_APIENTRY glGetTexParameterIiv (GLenum target, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetTexParameterIuiv (GLenum target, GLenum pname, GLuint *params); +GL_APICALL void GL_APIENTRY glSamplerParameterIiv (GLuint sampler, GLenum pname, const GLint *param); +GL_APICALL void GL_APIENTRY glSamplerParameterIuiv (GLuint sampler, GLenum pname, const GLuint *param); +GL_APICALL void GL_APIENTRY glGetSamplerParameterIiv (GLuint sampler, GLenum pname, GLint *params); +GL_APICALL void GL_APIENTRY glGetSamplerParameterIuiv (GLuint sampler, GLenum pname, GLuint *params); +GL_APICALL void GL_APIENTRY glTexBuffer (GLenum target, GLenum internalformat, GLuint buffer); +GL_APICALL void GL_APIENTRY glTexBufferRange (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +GL_APICALL void GL_APIENTRY glTexStorage3DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +#endif +#endif /* GL_ES_VERSION_3_2 */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sdk/GLES3/gl3platform.h b/sdk/GLES3/gl3platform.h new file mode 100644 index 0000000..8699212 --- /dev/null +++ b/sdk/GLES3/gl3platform.h @@ -0,0 +1,27 @@ +#ifndef __gl3platform_h_ +#define __gl3platform_h_ + +/* +** Copyright 2017-2020 The Khronos Group Inc. +** SPDX-License-Identifier: Apache-2.0 +*/ + +/* Platform-specific types and definitions for OpenGL ES 3.X gl3.h + * + * Adopters may modify khrplatform.h and this file to suit their platform. + * Please contribute modifications back to Khronos as pull requests on the + * public github repository: + * https://github.com/KhronosGroup/OpenGL-Registry + */ + +#include + +#ifndef GL_APICALL +#define GL_APICALL KHRONOS_APICALL +#endif + +#ifndef GL_APIENTRY +#define GL_APIENTRY KHRONOS_APIENTRY +#endif + +#endif /* __gl3platform_h_ */ diff --git a/sdk/KHR/khrplatform.h b/sdk/KHR/khrplatform.h new file mode 100644 index 0000000..ba47c26 --- /dev/null +++ b/sdk/KHR/khrplatform.h @@ -0,0 +1,292 @@ +#ifndef __khrplatform_h_ +#define __khrplatform_h_ + +/* +** Copyright (c) 2008-2018 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are 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 Materials. +** +** THE MATERIALS ARE 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 +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +/* Khronos platform-specific types and definitions. + * + * The master copy of khrplatform.h is maintained in the Khronos EGL + * Registry repository at https://github.com/KhronosGroup/EGL-Registry + * The last semantic modification to khrplatform.h was at commit ID: + * 67a3e0864c2d75ea5287b9f3d2eb74a745936692 + * + * Adopters may modify this file to suit their platform. Adopters are + * encouraged to submit platform specific modifications to the Khronos + * group so that they can be included in future versions of this file. + * Please submit changes by filing pull requests or issues on + * the EGL Registry repository linked above. + * + * + * See the Implementer's Guidelines for information about where this file + * should be located on your system and for more details of its use: + * http://www.khronos.org/registry/implementers_guide.pdf + * + * This file should be included as + * #include + * by Khronos client API header files that use its types and defines. + * + * The types in khrplatform.h should only be used to define API-specific types. + * + * Types defined in khrplatform.h: + * khronos_int8_t signed 8 bit + * khronos_uint8_t unsigned 8 bit + * khronos_int16_t signed 16 bit + * khronos_uint16_t unsigned 16 bit + * khronos_int32_t signed 32 bit + * khronos_uint32_t unsigned 32 bit + * khronos_int64_t signed 64 bit + * khronos_uint64_t unsigned 64 bit + * khronos_intptr_t signed same number of bits as a pointer + * khronos_uintptr_t unsigned same number of bits as a pointer + * khronos_ssize_t signed size + * khronos_usize_t unsigned size + * khronos_float_t signed 32 bit floating point + * khronos_time_ns_t unsigned 64 bit time in nanoseconds + * khronos_utime_nanoseconds_t unsigned time interval or absolute time in + * nanoseconds + * khronos_stime_nanoseconds_t signed time interval in nanoseconds + * khronos_boolean_enum_t enumerated boolean type. This should + * only be used as a base type when a client API's boolean type is + * an enum. Client APIs which use an integer or other type for + * booleans cannot use this as the base type for their boolean. + * + * Tokens defined in khrplatform.h: + * + * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. + * + * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. + * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. + * + * Calling convention macros defined in this file: + * KHRONOS_APICALL + * KHRONOS_APIENTRY + * KHRONOS_APIATTRIBUTES + * + * These may be used in function prototypes as: + * + * KHRONOS_APICALL void KHRONOS_APIENTRY funcname( + * int arg1, + * int arg2) KHRONOS_APIATTRIBUTES; + */ + +#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC) +# define KHRONOS_STATIC 1 +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APICALL + *------------------------------------------------------------------------- + * This precedes the return type of the function in the function prototype. + */ +#if defined(KHRONOS_STATIC) + /* If the preprocessor constant KHRONOS_STATIC is defined, make the + * header compatible with static linking. */ +# define KHRONOS_APICALL +#elif defined(_WIN32) +# define KHRONOS_APICALL __declspec(dllimport) +#elif defined (__SYMBIAN32__) +# define KHRONOS_APICALL IMPORT_C +#elif (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303) \ + || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) +/* KHRONOS_APIATTRIBUTES is not used by the client API headers yet */ +# define KHRONOS_APICALL __attribute__((visibility("default"))) +#else +# define KHRONOS_APICALL +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIENTRY + *------------------------------------------------------------------------- + * This follows the return type of the function and precedes the function + * name in the function prototype. + */ +#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(KHRONOS_STATIC) + /* Win32 but not WinCE */ +# define KHRONOS_APIENTRY __stdcall +#else +# define KHRONOS_APIENTRY +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIATTRIBUTES + *------------------------------------------------------------------------- + * This follows the closing parenthesis of the function prototype arguments. + */ +#if defined (__ARMCC_2__) +#define KHRONOS_APIATTRIBUTES __softfp +#else +#define KHRONOS_APIATTRIBUTES +#endif + +/*------------------------------------------------------------------------- + * basic type definitions + *-----------------------------------------------------------------------*/ +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) + + +/* + * Using + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(__VMS ) || defined(__sgi) + +/* + * Using + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(_WIN32) && !defined(__SCITECH_SNAP__) + +/* + * Win32 + */ +typedef __int32 khronos_int32_t; +typedef unsigned __int32 khronos_uint32_t; +typedef __int64 khronos_int64_t; +typedef unsigned __int64 khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(__sun__) || defined(__digital__) + +/* + * Sun or Digital + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#if defined(__arch64__) || defined(_LP64) +typedef long int khronos_int64_t; +typedef unsigned long int khronos_uint64_t; +#else +typedef long long int khronos_int64_t; +typedef unsigned long long int khronos_uint64_t; +#endif /* __arch64__ */ +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif 0 + +/* + * Hypothetical platform with no float or int64 support + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#define KHRONOS_SUPPORT_INT64 0 +#define KHRONOS_SUPPORT_FLOAT 0 + +#else + +/* + * Generic fallback + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#endif + + +/* + * Types that are (so far) the same on all platforms + */ +typedef signed char khronos_int8_t; +typedef unsigned char khronos_uint8_t; +typedef signed short int khronos_int16_t; +typedef unsigned short int khronos_uint16_t; + +/* + * Types that differ between LLP64 and LP64 architectures - in LLP64, + * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears + * to be the only LLP64 architecture in current use. + */ +#ifdef _WIN64 +typedef signed long long int khronos_intptr_t; +typedef unsigned long long int khronos_uintptr_t; +typedef signed long long int khronos_ssize_t; +typedef unsigned long long int khronos_usize_t; +#else +typedef signed long int khronos_intptr_t; +typedef unsigned long int khronos_uintptr_t; +typedef signed long int khronos_ssize_t; +typedef unsigned long int khronos_usize_t; +#endif + +#if KHRONOS_SUPPORT_FLOAT +/* + * Float type + */ +typedef float khronos_float_t; +#endif + +#if KHRONOS_SUPPORT_INT64 +/* Time types + * + * These types can be used to represent a time interval in nanoseconds or + * an absolute Unadjusted System Time. Unadjusted System Time is the number + * of nanoseconds since some arbitrary system event (e.g. since the last + * time the system booted). The Unadjusted System Time is an unsigned + * 64 bit value that wraps back to 0 every 584 years. Time intervals + * may be either signed or unsigned. + */ +typedef khronos_uint64_t khronos_utime_nanoseconds_t; +typedef khronos_int64_t khronos_stime_nanoseconds_t; +#endif + +/* + * Dummy value used to pad enum types to 32 bits. + */ +#ifndef KHRONOS_MAX_ENUM +#define KHRONOS_MAX_ENUM 0x7FFFFFFF +#endif + +/* + * Enumerated boolean type + * + * Values other than zero should be considered to be true. Therefore + * comparisons should not be made against KHRONOS_TRUE. + */ +typedef enum { + KHRONOS_FALSE = 0, + KHRONOS_TRUE = 1, + KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM +} khronos_boolean_enum_t; + +#endif /* __khrplatform_h_ */ diff --git a/sdk/keys.h b/sdk/keys.h new file mode 100644 index 0000000..3d254a7 --- /dev/null +++ b/sdk/keys.h @@ -0,0 +1,140 @@ +/************************************************************//** +* +* @file: keys.h +* @author: Martin Fouilleul +* @date: 26/08/2022 +* @revision: +* +*****************************************************************/ +#ifndef __KEYS_H_ +#define __KEYS_H_ + +#include"typedefs.h" + +typedef i32 key_code; +static const key_code KEY_UNKNOWN = -1, + KEY_SPACE = 32, + KEY_APOSTROPHE = 39, // ' + KEY_COMMA = 44, // , + KEY_MINUS = 45, // - + KEY_PERIOD = 46, // . + KEY_SLASH = 47, // / + KEY_0 = 48, + KEY_1 = 49, + KEY_2 = 50, + KEY_3 = 51, + KEY_4 = 52, + KEY_5 = 53, + KEY_6 = 54, + KEY_7 = 55, + KEY_8 = 56, + KEY_9 = 57, + KEY_SEMICOLON = 59, // ; + KEY_EQUAL = 61, // = + KEY_A = 65, + KEY_B = 66, + KEY_C = 67, + KEY_D = 68, + KEY_E = 69, + KEY_F = 70, + KEY_G = 71, + KEY_H = 72, + KEY_I = 73, + KEY_J = 74, + KEY_K = 75, + KEY_L = 76, + KEY_M = 77, + KEY_N = 78, + KEY_O = 79, + KEY_P = 80, + KEY_Q = 81, + KEY_R = 82, + KEY_S = 83, + KEY_T = 84, + KEY_U = 85, + KEY_V = 86, + KEY_W = 87, + KEY_X = 88, + KEY_Y = 89, + KEY_Z = 90, + KEY_LEFT_BRACKET = 91, // [ + KEY_BACKSLASH = 92, // \ */ + KEY_RIGHT_BRACKET = 93, // ] + KEY_GRAVE_ACCENT = 96, // ` + KEY_WORLD_1 = 161, // non-US #1 + KEY_WORLD_2 = 162, // non-US #2 + KEY_ESCAPE = 256, + KEY_ENTER = 257, + KEY_TAB = 258, + KEY_BACKSPACE = 259, + KEY_INSERT = 260, + KEY_DELETE = 261, + KEY_RIGHT = 262, + KEY_LEFT = 263, + KEY_DOWN = 264, + KEY_UP = 265, + KEY_PAGE_UP = 266, + KEY_PAGE_DOWN = 267, + KEY_HOME = 268, + KEY_END = 269, + KEY_CAPS_LOCK = 280, + KEY_SCROLL_LOCK = 281, + KEY_NUM_LOCK = 282, + KEY_PRINT_SCREEN = 283, + KEY_PAUSE = 284, + KEY_F1 = 290, + KEY_F2 = 291, + KEY_F3 = 292, + KEY_F4 = 293, + KEY_F5 = 294, + KEY_F6 = 295, + KEY_F7 = 296, + KEY_F8 = 297, + KEY_F9 = 298, + KEY_F10 = 299, + KEY_F11 = 300, + KEY_F12 = 301, + KEY_F13 = 302, + KEY_F14 = 303, + KEY_F15 = 304, + KEY_F16 = 305, + KEY_F17 = 306, + KEY_F18 = 307, + KEY_F19 = 308, + KEY_F20 = 309, + KEY_F21 = 310, + KEY_F22 = 311, + KEY_F23 = 312, + KEY_F24 = 313, + KEY_F25 = 314, + KEY_KP_0 = 320, + KEY_KP_1 = 321, + KEY_KP_2 = 322, + KEY_KP_3 = 323, + KEY_KP_4 = 324, + KEY_KP_5 = 325, + KEY_KP_6 = 326, + KEY_KP_7 = 327, + KEY_KP_8 = 328, + KEY_KP_9 = 329, + KEY_KP_DECIMAL = 330, + KEY_KP_DIVIDE = 331, + KEY_KP_MULTIPLY = 332, + KEY_KP_SUBTRACT = 333, + KEY_KP_ADD = 334, + KEY_KP_ENTER = 335, + KEY_KP_EQUAL = 336, + KEY_LEFT_SHIFT = 340, + KEY_LEFT_CONTROL = 341, + KEY_LEFT_ALT = 342, + KEY_LEFT_SUPER = 343, + KEY_RIGHT_SHIFT = 344, + KEY_RIGHT_CONTROL = 345, + KEY_RIGHT_ALT = 346, + KEY_RIGHT_SUPER = 347, + KEY_MENU = 348; + +static const key_code KEY_MAX = KEY_MENU; + + +#endif //__KEYS_H_ diff --git a/sdk/macro_helpers.h b/sdk/macro_helpers.h new file mode 100644 index 0000000..a38c0b3 --- /dev/null +++ b/sdk/macro_helpers.h @@ -0,0 +1,129 @@ +/************************************************************//** +* +* @file: macro_helpers.h +* @author: Martin Fouilleul +* @date: 27/03/2020 +* @revision: +* +*****************************************************************/ +#ifndef __MACRO_HELPERS_H_ +#define __MACRO_HELPERS_H_ + +//NOTE(martin): macro concatenation +#define _cat2_(a, b) a##b +#define _cat3_(a, b, c) a##b##c + + +//NOTE(martin): inline, but still generate code +// (eg. use the inline version inside a library, but still exports the function for client code) +//TODO(martin): this is a compiler-specific attribute, recognized by clang and gcc. See if there's a more portable approach +//#define INLINE_GEN __attribute__((used)) static inline + + +//NOTE(martin): typed and array mallocs +#define malloc_type(type) ((type*)malloc(sizeof(type))) +#define malloc_array(type, count) ((type*)malloc(sizeof(type)*count)) + +//NOTE(martin): 'hygienic' templates, to replace macros and avoid multiple evaluation problems. +#ifdef __cplusplus + //NOTE(martin): in C++ we use templates and decltype/declval + // (overloaded functions would be ambiguous because of the + // overload resolution and conversion/promotion rules) + + #include + + template + inline decltype(std::declval()+std::declval()) minimum_safe(Ta a, Tb b) + { + return(a < b ? a : b); + } + + template + inline decltype(std::declval()+std::declval()) maximum_safe(Ta a, Tb b) + { + return(a > b ? a : b); + } + + template + inline T square_safe(T a) {return(a*a);} + + template + inline T cube_safe(T a) {return(a*a*a);} + +#else // (__cplusplus not defined) + + //NOTE(martin): Type generic arithmetic functions helpers + // this macros helps generate variants of a generic 'template' for all arithmetic types. + // the def parameter must be a macro that take a type, and optional arguments + #define tga_generate_variants(def, ...) \ + def(u8, ##__VA_ARGS__) def(i8, ##__VA_ARGS__ ) def(u16, ##__VA_ARGS__) def(i16, ##__VA_ARGS__) \ + def(u32, ##__VA_ARGS__) def(i32, ##__VA_ARGS__) def(u64, ##__VA_ARGS__) def(i64, ##__VA_ARGS__) \ + def(f32, ##__VA_ARGS__) def(f64, ##__VA_ARGS__) + + // This macro generates the name of a typed variant + #define tga_variant_name(name, type) _cat3_(name, _, type) + + // This macro generates a _Generic association between a type and its variant + #define tga_variant_association(type, name) , type: tga_variant_name(name, type) + + // This macros selects the appropriate variant for a 2 parameters functions + #define tga_select_binary(name, a, b) \ + _Generic((a+b) tga_generate_variants(tga_variant_association, name))(a, b) + + // This macros selects the appropriate variant for a 1 parameters functions + #define tga_select_unary(name, a) \ + _Generic((a) tga_generate_variants(tga_variant_association, name))(a) + + //NOTE(martin): type generic templates + #define minimum_def(type) static inline type tga_variant_name(minimum_safe, type)(type a, type b) {return(a < b ? a : b);} + #define maximum_def(type) static inline type tga_variant_name(maximum_safe, type)(type a, type b) {return(a > b ? a : b);} + #define square_def(type) static inline type tga_variant_name(square_safe, type)(type a) {return(a*a);} + #define cube_def(type) static inline type tga_variant_name(cube_safe, type)(type a) {return(a*a*a);} + + //NOTE(martin): instantiante our templates for all arithmetic types + tga_generate_variants(minimum_def) + tga_generate_variants(maximum_def) + tga_generate_variants(square_def) + tga_generate_variants(cube_def) + + //NOTE(martin): select the correct variant according to the argument types + #define minimum_safe(a, b) tga_select_binary(minimum_safe, a, b) + #define maximum_safe(a, b) tga_select_binary(maximum_safe, a, b) + #define square_safe(a) tga_select_unary(square_safe, a) + #define cube_safe(a) tga_select_unary(cube_safe, a) + +#endif // __cplusplus else branch + + +//NOTE(martin): these macros are calling the safe functions defined above, so they don't evaluate their +// arguments twice + +#define minimum(a, b) minimum_safe(a, b) +#define maximum(a, b) maximum_safe(a, b) + +#define ClampLowBound(a, low) (maximum((a), (low))) +#define ClampHighBound(a, high) (minimum((a), (high))) +#define Clamp(a, low, high) (ClampLowBound(ClampHighBound((a), (high)), (low))) + +#define Square(a) square_safe(a) +#define Cube(a) cube_safe(a) + +#define AlignUpOnPow2(x, a) (((x) + (a) - 1) & ~((a)-1)) +#define AlignDownOnPow2(x, a) ((x) & ~((a)-1)) + +static inline u64 next_pow2_u64(u64 x) +{ + x--; + x |= x>>1; + x |= x>>2; + x |= x>>4; + x |= x>>8; + x |= x>>16; + x |= x>>32; + x++; + return(x); +} + +#define defer_loop(begin, end) begin; for(int __i__=0; __i__<1; __i__++, end) + +#endif //__MACRO_HELPERS_H_ diff --git a/sdk/typedefs.h b/sdk/typedefs.h new file mode 100644 index 0000000..e0f7e10 --- /dev/null +++ b/sdk/typedefs.h @@ -0,0 +1,69 @@ +//***************************************************************** +// +// $file: typedefs.h $ +// $author: Martin Fouilleul $ +// $date: 23/36/2015 $ +// $revision: $ +// +//***************************************************************** +#ifndef __TYPEDEFS_H_ +#define __TYPEDEFS_H_ + +#include +#include //FLT_MAX/MIN etc... + +#ifndef __cplusplus +#include +#endif //__cplusplus + +typedef uint8_t byte; +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; + +typedef float f32; +typedef double f64; + +typedef union +{ + struct + { + f32 x; + f32 y; + }; + f32 c[2]; +} vec2; + +typedef union +{ + struct + { + f32 x; + f32 y; + f32 z; + f32 w; + }; + f32 c[4]; +} vec4; + +#define vec4_expand_xyz(v) (v).x, (v).y, (v).z + +typedef union +{ + struct + { + f32 x; + f32 y; + f32 w; + f32 h; + }; + f32 c[4]; +} mp_rect; + +#endif //__TYPEDEFS_H_ diff --git a/src/bindgen_core_api.txt b/src/bindgen_core_api.txt new file mode 100644 index 0000000..90a369d --- /dev/null +++ b/src/bindgen_core_api.txt @@ -0,0 +1,6 @@ +log_string_flat v(Ip) +log_int v(i) +cosf f(f) +sinf f(f) +floorf f(f) +sqrtf f(f) \ No newline at end of file diff --git a/src/bindgen_gles_api.txt b/src/bindgen_gles_api.txt new file mode 100644 index 0000000..03c8df4 --- /dev/null +++ b/src/bindgen_gles_api.txt @@ -0,0 +1,44 @@ +glCreateProgram i(v) +glCreateShader i(i) +glCompileShader v(i) +glAttachShader v(ii) +glLinkProgram v(i) +glUseProgram v(i) +glGetError i(v) +glClearColor v(ffff) +glClear v(i) +glViewport v(iiii) + +glGetShaderiv v(iip) +glGetShaderInfoLog v(iipp) + +glBindFramebuffer v(ii) +glBindTexture v(ii) +glActiveTexture v(i) + +glGenBuffers v(ip) +glGenTextures v(ip) +glGenFramebuffers v(ip) + +glFramebufferTexture2D v(iiiii) +glCheckFramebufferStatus i(i) + +glTexImage2D v(iiiiiiiip) +glTexParameteri v(iii) + +glBindBuffer v(ii) +glBufferData v(iipi) + +glUniform1i v(ii) +glUniform2i v(iii) +glUniform1f v(if) +glUniform2f v(iff) +glUniform3f v(ifff) +glUniformMatrix4fv v(iiip) + +glGetAttribLocation i(ip) +glGetUniformLocation i(ip) + +glVertexAttribPointer v(iiiiip) +glEnableVertexAttribArray v(i) +glDrawArrays v(iii) diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..4200d32 --- /dev/null +++ b/src/main.c @@ -0,0 +1,454 @@ +/************************************************************//** +* +* @file: main.c +* @author: Martin Fouilleul +* @date: 11/04/2023 +* +*****************************************************************/ +#include +#include +#include + +#include"wasm3.h" +#include"m3_env.h" +#include"m3_compile.h" + +#define MG_INCLUDE_GL_API +#include"milepost.h" + +#define LOG_SUBSYSTEM "Orca" + + +void log_string_flat(u64 len, char* ptr) +{ + LOG_MESSAGE("%.*s", (int)len, ptr); +} + +void log_int(int i) +{ + printf("%i ", i); +} + +#include"bindgen_core_api.c" +#include"bindgen_gles_api.c" +#include"manual_gles_api.c" + +typedef struct orca_app +{ + mp_window window; + mg_surface surface; + mg_canvas canvas; + +} orca_app; + +#define G_EVENTS(X) \ + X(G_EVENT_START, "OnInit", "", "") \ + X(G_EVENT_MOUSE_DOWN, "OnMouseDown", "", "i") \ + X(G_EVENT_MOUSE_UP, "OnMouseUp", "", "i") \ + X(G_EVENT_MOUSE_ENTER, "OnMouseEnter", "", "") \ + X(G_EVENT_MOUSE_LEAVE, "OnMouseLeave", "", "") \ + X(G_EVENT_MOUSE_MOVE, "OnMouseMove", "", "ffff") \ + X(G_EVENT_MOUSE_WHEEL, "OnMouseWheel", "", "ff") \ + X(G_EVENT_KEY_DOWN, "OnKeyDown", "", "i") \ + X(G_EVENT_KEY_UP, "OnKeyUp", "", "i") \ + X(G_EVENT_FRAME_REFRESH, "OnFrameRefresh", "", "") \ + X(G_EVENT_FRAME_RESIZE, "OnFrameResize", "", "ii") + +typedef enum { + #define G_EVENT_KIND(kind, ...) kind, + G_EVENTS(G_EVENT_KIND) + G_EVENT_COUNT +} guest_event_kind; + + +typedef struct g_event_handler_desc +{ + str8 name; + str8 retTags; + str8 argTags; +} g_event_handler_desc; + +const g_event_handler_desc G_EVENT_HANDLER_DESC[] = { + #define G_EVENT_HANDLER_DESC_ENTRY(kind, name, rets, args) {STR8(name), STR8(rets), STR8(args)}, + G_EVENTS(G_EVENT_HANDLER_DESC_ENTRY) +}; + +char m3_type_to_tag(M3ValueType type) +{ + switch(type) + { + case c_m3Type_none: + return('v'); + case c_m3Type_i32: + return('i'); + case c_m3Type_i64: + return('I'); + case c_m3Type_f32: + return('f'); + case c_m3Type_f64: + return('d'); + + case c_m3Type_unknown: + return('!'); + } +} + +typedef struct host_memory +{ + char* ptr; + u32 reserved; + u32 committed; + +} host_memory; + +void host_memory_init(host_memory* memory) +{ + mem_base_allocator* allocator = mem_base_allocator_default(); + memory->committed = 0; + memory->reserved = 4<<20; + memory->ptr = mem_base_reserve(allocator, memory->reserved); +} + +void* host_memory_resize_callback(void* p, unsigned long size, void* userData) +{ + host_memory* memory = (host_memory*)userData; + + if(memory->committed >= size) + { + return(memory->ptr); + } + else if(memory->committed < memory->reserved) + { + u32 commitSize = size - memory->committed; + + mem_base_allocator* allocator = mem_base_allocator_default(); + mem_base_commit(allocator, memory->ptr + memory->committed, commitSize); + memory->committed += commitSize; + return(memory->ptr); + } + else + { + DEBUG_ASSERT(0, "Out of memory"); + return(0); + } +} + +void host_memory_free_callback(void* p, void* userData) +{ + host_memory* memory = (host_memory*)userData; + + mem_base_allocator* allocator = mem_base_allocator_default(); + mem_base_release(allocator, memory->ptr, memory->reserved); + memset(memory, 0, sizeof(host_memory)); +} + +void* orca_runloop(void* user) +{ + orca_app* app = (orca_app*)user; + mem_arena_init(mem_scratch()); + + //NOTE: loads wasm module + const char* bundleNameCString = "module"; + str8 modulePath = mp_app_get_resource_path(mem_scratch(), "../wasm/module.wasm"); + const char* modulePathCString = str8_to_cstring(mem_scratch(), modulePath); + + FILE* file = fopen(modulePathCString, "rb"); + if(!file) + { + LOG_ERROR("Couldn't load wasm module at %s\n", modulePathCString); + return((void*)-1); + } + + fseek(file, 0, SEEK_END); + u64 wasmSize = ftell(file); + rewind(file); + + u8* wasmBytes = malloc_array(u8, wasmSize); + fread(wasmBytes, 1, wasmSize, file); + fclose(file); + + u32 stackSize = 65536; + IM3Environment env = m3_NewEnvironment(); + + host_memory hostMemory = {}; + host_memory_init(&hostMemory); + + IM3Runtime runtime = m3_NewRuntime(env, stackSize, NULL); + m3_RuntimeSetMemoryCallbacks(runtime, host_memory_resize_callback, host_memory_free_callback, &hostMemory); + //NOTE: host memory will be freed when runtime is freed. + + IM3Module module = 0; + + //TODO check errors + m3_ParseModule(env, &module, wasmBytes, wasmSize); + m3_LoadModule(runtime, module); + m3_SetModuleName(module, bundleNameCString); + + mem_scratch_clear(); + + //NOTE: bind orca APIs + bindgen_link_core_api(module); + bindgen_link_gles_api(module); + manual_link_gles_api(module); + + //NOTE: compile + M3Result res = m3_CompileModule(module); + if(res) + { + M3ErrorInfo errInfo = {}; + m3_GetErrorInfo(runtime, &errInfo); + + LOG_ERROR("wasm error: %s\n", errInfo.message); + } + + //NOTE: Find heap base + u32 heapBase = 0; + { + IM3Global global = m3_FindGlobal(module, "__heap_base"); + if(global) + { + M3TaggedValue val; + M3Result res = m3_GetGlobal(global, &val); + if(!res && val.type == c_m3Type_i32) + { + heapBase = val.value.i32; + } + else + { + LOG_ERROR("couldn't get value of __heap_base\n"); + return((void*)-1); + } + } + else + { + LOG_ERROR("couldn't locate __heap_base\n"); + return((void*)-1); + } + } + //NOTE: align heap base on 16Bytes + heapBase = AlignUpOnPow2(heapBase, 16); + LOG_MESSAGE("mem_size = %u, __heap_base = %u\n", m3_GetMemorySize(runtime), heapBase); + + //NOTE: Find and type check event handlers. + IM3Function eventHandlers[G_EVENT_COUNT] = {0}; + for(int i=0; iname.ptr); + + if(handler) + { + bool checked = false; + + //NOTE: check function signature + int retCount = m3_GetRetCount(handler); + int argCount = m3_GetArgCount(handler); + if(retCount == desc->retTags.len && argCount == desc->argTags.len) + { + checked = true; + for(int retIndex = 0; retIndex < retCount; retIndex++) + { + M3ValueType m3Type = m3_GetRetType(handler, retIndex); + char tag = m3_type_to_tag(m3Type); + + if(tag != desc->retTags.ptr[retIndex]) + { + checked = false; + break; + } + } + if(checked) + { + for(int argIndex = 0; argIndex < argCount; argIndex++) + { + M3ValueType m3Type = m3_GetArgType(handler, argIndex); + char tag = m3_type_to_tag(m3Type); + + if(tag != desc->argTags.ptr[argIndex]) + { + checked = false; + break; + } + } + } + } + + if(checked) + { + eventHandlers[i] = handler; + } + else + { + LOG_ERROR("type mismatch for event handler %.*s\n", (int)desc->name.len, desc->name.ptr); + } + } + } + + //mg_canvas_prepare(app->canvas); + + //NOTE: prepare GL surface + mg_surface_prepare(app->surface); + + //NOTE: call init handler + if(eventHandlers[G_EVENT_START]) + { + m3_Call(eventHandlers[G_EVENT_START], 0, 0); + } + + if(eventHandlers[G_EVENT_FRAME_RESIZE]) + { + mp_rect frame = mg_surface_get_frame(app->surface); + u32 width = (u32)frame.w; + u32 height = (u32)frame.h; + const void* args[2] = {&width, &height}; + m3_Call(eventHandlers[G_EVENT_FRAME_RESIZE], 2, args); + } + + while(!mp_should_quit()) + { + mp_event event = {0}; + while(mp_next_event(&event)) + { + switch(event.type) + { + case MP_EVENT_WINDOW_CLOSE: + { + mp_request_quit(); + } break; + + case MP_EVENT_WINDOW_RESIZE: + { + //TODO: resize surface! + if(eventHandlers[G_EVENT_FRAME_RESIZE]) + { + u32 width = (u32)event.frame.rect.w; + u32 height = (u32)event.frame.rect.h; + const void* args[2] = {&width, &height}; + m3_Call(eventHandlers[G_EVENT_FRAME_RESIZE], 2, args); + } + } break; + + case MP_EVENT_MOUSE_BUTTON: + { + if(event.key.action == MP_KEY_PRESS) + { + if(eventHandlers[G_EVENT_MOUSE_DOWN]) + { + int key = event.key.code; + const void* args[1] = {&key}; + m3_Call(eventHandlers[G_EVENT_MOUSE_DOWN], 1, args); + } + } + else + { + if(eventHandlers[G_EVENT_MOUSE_UP]) + { + int key = event.key.code; + const void* args[1] = {&key}; + m3_Call(eventHandlers[G_EVENT_MOUSE_UP], 1, args); + } + } + } break; + + case MP_EVENT_MOUSE_MOVE: + { + if(eventHandlers[G_EVENT_MOUSE_MOVE]) + { + const void* args[4] = {&event.move.x, &event.move.y, &event.move.deltaX, &event.move.deltaY}; + m3_Call(eventHandlers[G_EVENT_MOUSE_MOVE], 4, args); + } + } break; + + case MP_EVENT_KEYBOARD_KEY: + { + if(event.key.action == MP_KEY_PRESS) + { + if(eventHandlers[G_EVENT_KEY_DOWN]) + { + const void* args[1] = {&event.key.code}; + m3_Call(eventHandlers[G_EVENT_KEY_DOWN], 1, args); + } + } + else if(event.key.action == MP_KEY_RELEASE) + { + if(eventHandlers[G_EVENT_KEY_UP]) + { + const void* args[1] = {&event.key.code}; + m3_Call(eventHandlers[G_EVENT_KEY_UP], 1, args); + } + } + } break; + + default: + break; + } + } + + mg_surface_prepare(app->surface); + glClearColor(1, 0, 1, 1); + glClear(GL_COLOR_BUFFER_BIT); + + if(eventHandlers[G_EVENT_FRAME_REFRESH]) + { + m3_Call(eventHandlers[G_EVENT_FRAME_REFRESH], 0, 0); + } + + mg_surface_present(app->surface); + //TODO: update and render + mem_scratch_clear(); + } + + return(0); +} + +int main(int argc, char** argv) +{ + LogLevel(LOG_LEVEL_DEBUG); + + mp_init(); + mp_clock_init(); + + mp_rect windowRect = {.x = 100, .y = 100, .w = 810, .h = 610}; + mp_window window = mp_window_create(windowRect, "orca", 0); + + //NOTE: create surface and canvas + mg_surface surface = mg_surface_create_for_window(window, MG_BACKEND_GLES); + mg_surface_swap_interval(surface, 1); +/* mg_canvas canvas = mg_canvas_create(surface); + + if(mg_canvas_is_nil(canvas)) + { + printf("Error: couldn't create canvas\n"); + return(-1); + } +*/ + //NOTE: show window and start runloop + mp_window_bring_to_front(window); + mp_window_focus(window); + + orca_app app = {.window = window, + .surface = surface}; +// .canvas = canvas}; + + pthread_t runloopThread; + pthread_create(&runloopThread, 0, orca_runloop, &app); + + while(!mp_should_quit()) + { + mp_pump_events(0); + //TODO: what to do with mem scratch here? + } + + void* res; + pthread_join(runloopThread, &res); + +// mg_canvas_destroy(canvas); +// mg_surface_destroy(surface); + mp_window_destroy(window); + + mp_terminate(); + return(0); +} + +#undef LOG_SUBSYSTEM diff --git a/src/manual_gles_api.c b/src/manual_gles_api.c new file mode 100644 index 0000000..765ceba --- /dev/null +++ b/src/manual_gles_api.c @@ -0,0 +1,29 @@ + +const void* glShaderSource_stub(IM3Runtime runtime, IM3ImportContext _ctx, uint64_t * _sp, void * _mem) +{ + i32 shader = *(i32*)&_sp[0]; + i32 count = *(i32*)&_sp[1]; + i32 stringArrayOffset = *(i32*)&_sp[2]; + i32 lengthArrayOffset = *(i32*)&_sp[3]; + + int* stringOffsetArray = (int*)((char*)_mem + stringArrayOffset); + const char** stringArray = (const char**)mem_arena_alloc_array(mem_scratch(), char*, count); + for(int i=0; i

      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�~!dwvt{3 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

    3. gXTQ@^k(+M)m*#%Mm}SX($5WYH6@223pYP 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

      Q zAQw{fQgjar6v8JX#hFda7YwuZ=mvHEPJZn3EDM?8409>emHB~}TB$?`Y2W0F2P!5v zhQCbaOvMJ5=&*{FZO9ha%tn�UdV~rD+NexQ*BwR!;+0!!1YM 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