From 982db0281cf6ac3f9c52dbb4238b9ed3f06a01df Mon Sep 17 00:00:00 2001 From: Syrus Date: Sat, 15 Dec 2018 22:43:10 -0800 Subject: [PATCH 1/5] Added support for 0 or 2 params in main emscripten function --- emtests/printf.c | 2 +- emtests/printf.wasm | Bin 46714 -> 46706 bytes rustfmt.toml | 1 + src/webassembly/mod.rs | 26 +++++++++++++++++++++----- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/emtests/printf.c b/emtests/printf.c index 3f2ad8b71..55abc0ad5 100644 --- a/emtests/printf.c +++ b/emtests/printf.c @@ -8,7 +8,7 @@ #include #include -int main( int argc, char * argv [] ) { +int main() { int x; printf("ab%gc%nd\n", 1.23f, &x); printf("n=%d\n", x); diff --git a/emtests/printf.wasm b/emtests/printf.wasm index 0d4197a24a39c24322e8b7a0bf5e4adfb76a4b39..bd5c1ebf4b04041778c8b30ee9b84665fa0e8a9a 100644 GIT binary patch delta 1000 zcmZ9KyK59-6vgMYkC}bVK9X!Unc4GYH`&c=ldz&#nJXzQM6~jMn99~_7A#b>5YkxM ziA_+_Xd`Q71Pif{AP5F5L?ei4B#qv?GdqN>&fat8ckaix-|4aO=h%3D-O!Ew8^!}& zf4%#~ycxdB=;y+gqxvm}o)|&fX*sRjHEWv(*UX_$_l!VQSqH2Y*1vk7T-HO@66;IW zBI{$;0_%WPxZhf!9M-R_HtPr0Eb9SlhIPoALfEHnpe&vds4`1EPCi)7(lQ-s z?6X>dn!*%?Z)B#=9?Fti^r|GeCHXX_>CvZ7H1n<*%v{c2;LVmCuZ}ud!v6AL37d-9 zl(4gyrMI^vzUw0;aVCy45;xF@;*g&C$Vi@z^Q`1^n2U0@dGkExlQbVF4_;jU-bYqo zJC1FEefTkK3*1CANf`zZ!#{o4q0mm8J3=d{n0AC-z(SHT-9js-cbjko&e6BgmF5I) zqn(TlFJdtn8D7FtGV%>}(4lYy)3Ax0lofWKe!tTDr|fO{hYNCmF1iyYqsv&HF!|lA zVCAeyKbj~=X>sfhrL-uet5}W9P}#A|t!r4D_>^1Mv3}O1`#@1zOJjF*)RMIJ&>Neh z(vrNB4Q!0f_)9L`#Aak(jrP+Epd_s>rR2T2a+zD$B1fLk5#UN#p;O3w0#szK(&+Kt OQK-t;-`BIZ_x=M2{o6eN delta 1004 zcmZ9KyKmEA6vb^PX&mSMPSZL$U!6ATD}6U&A{TXFs1Qv24<0K114m*21OrkQMmEG! zfx5sJ7RbN=45&gvqKE-Ok$^6!3*4JH5z6%QJ;&!<>+|>f)Hpvio?JEb;L$bXuCBlA zehggq-iGyE&#_d?vFM@U)-1FqHi@LJSxmB}+)m1mS(m13k^Wuc|Q{CJNShe%Tf zG!=lZf(Y+vn%2o3o?W~U&=4lmRV9=V+BG!l+X$!HWrP}rrlw$FO4N5YELQ2*MoQc~ zooK8hzfVC|O=Fr~$V?w>@v!9|9yQp^R5}pT#B`LvniiBi&+Xv_J`g5 z70P-xYgQ61VW^C|#iH|8n@<%eHa5R-7+ zx8o9?!yI{o-K=xkfit!_T|>=Jf3F}e>4a}5Bt4ILe|18_3s@Mt9Im78hr3lIB%Gu# zgELG@xPiuS^jPQgA{NIsrtX?COzJ~b<) zo7fzQ-e6T$ZpIe2MymfRw{By5B+8rg6v#?zj^z3>_%L^{Lzdj26CfvMfzBcG8Bmb9 bNQ2vYQ=uqht7egwjD9}Q`{q&5JUILZQDon` diff --git a/rustfmt.toml b/rustfmt.toml index dc26521c0..4a3e0232a 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,3 +1,4 @@ ignore = [ "src/spectests", + "src/emtests", ] diff --git a/src/webassembly/mod.rs b/src/webassembly/mod.rs index 5c679ba48..d91ac003f 100644 --- a/src/webassembly/mod.rs +++ b/src/webassembly/mod.rs @@ -11,6 +11,7 @@ use cranelift_codegen::{ isa, settings::{self, Configurable}, }; +use cranelift_wasm::ModuleEnvironment; use std::panic; use std::str::FromStr; use target_lexicon; @@ -226,11 +227,26 @@ pub fn start_instance( _ => panic!("_main emscripten function not found"), }; - let main: extern "C" fn(u32, u32, &Instance) = get_instance_function!(instance, func_index); - - let (argc, argv) = store_module_arguments(path, args, instance); - - call_protected!(main(argc, argv, &instance)).map_err(|err| format!("{}", err)) + let sig_index = module.get_func_type(func_index); + let signature = module.get_signature(sig_index); + let num_params = signature.params.len(); + match num_params { + 2 => { + let main: extern "C" fn(u32, u32, &Instance) = + get_instance_function!(instance, func_index); + let (argc, argv) = store_module_arguments(path, args, instance); + call_protected!(main(argc, argv, &instance)) + } + 0 => { + let main: extern "C" fn(&Instance) = get_instance_function!(instance, func_index); + call_protected!(main(&instance)) + } + _ => panic!( + "The emscripten main function has received an incorrect number of params {}", + num_params + ), + } + .map_err(|err| format!("{}", err)) // TODO: We should implement emscripten __ATEXIT__ } else { let func_index = From 4b33b101ed32792489ff640788430eabd18f641c Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 16 Dec 2018 10:43:35 -0600 Subject: [PATCH 2/5] Add a debug messages for mocked missing globals and tables --- src/webassembly/instance.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/webassembly/instance.rs b/src/webassembly/instance.rs index fdcdeefd7..84a464d2d 100644 --- a/src/webassembly/instance.rs +++ b/src/webassembly/instance.rs @@ -394,6 +394,10 @@ impl Instance { Some(ImportValue::Global(value)) => *value, None => { if options.mock_missing_globals { + debug!( + "The Imported global {}.{} is not provided, therefore will be mocked.", + module_name, field_name + ); 0 } else { panic!( @@ -430,6 +434,10 @@ impl Instance { Some(ImportValue::Table(t)) => t.to_vec(), None => { if options.mock_missing_tables { + debug!( + "The Imported table {}.{} is not provided, therefore will be mocked.", + module_name, field_name + ); let len = table.entity.size; let mut v = Vec::with_capacity(len); v.resize(len, 0); From 755f3ae69090e00900f1000575db10b6c9770239 Mon Sep 17 00:00:00 2001 From: Mackenzie Clark Date: Sun, 16 Dec 2018 11:27:45 -0800 Subject: [PATCH 3/5] upgrade to wabt-rs 0.7.2 includes a fix for windows builds, this brings wamer one step closer to windows support --- Cargo.lock | 19 +++++++++++++------ Cargo.toml | 5 ++--- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0960fe670..8b2705003 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -306,6 +306,11 @@ name = "gcc" version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "indicatif" version = "0.10.3" @@ -838,22 +843,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wabt" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.79 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", - "wabt-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt-sys 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wabt-sys" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -880,7 +886,7 @@ dependencies = [ "structopt 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "wabt 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "wabt 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "wasmparser 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -943,6 +949,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)" = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2" +"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum indicatif 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "40ecd1e2ee08e6c255ce890f5a99d17000850e664e7acf119fb03b25b0575bfe" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" @@ -1010,8 +1017,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum wabt 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5b24b2494bd6077dff717f41523f6e3e0161d58f578198589a6a6c8b314cb763" -"checksum wabt-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "122aefe1d22c067cce1dc5d20d89d1ca47ce0eb10120246a3e2340863f9e6ddd" +"checksum wabt 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff1f0f87e467255240c1faf5cf13a04410723407840d7733e75967224e191a5" +"checksum wabt-sys 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cc8982bfe0a923f152e96d991e50a6f97fe73ca4af6d9d84d76634f03051fa2" "checksum wasmparser 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2a75e0c3fe9a4d4fd91901348a5be05ba4791e29dda89e8596bfe87900ba7edc" "checksum wasmparser 0.21.10 (registry+https://github.com/rust-lang/crates.io-index)" = "48b8ebfeb364ff50e0ff043f491c270f58a7563aa3dc97402a0e813bfeb6df6f" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" diff --git a/Cargo.toml b/Cargo.toml index be1aa895e..af292988b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,7 @@ tempdir = "0.3.7" error-chain = "0.12.0" errno = "0.2.4" structopt = "0.2.11" -wabt = "0.7.1" +wabt = "0.7.2" wasmparser = "0.20.0" winapi = "0.3.6" region = "0.3.0" @@ -51,8 +51,7 @@ indicatif = "0.10" console = "0.7.1" [build-dependencies] -wabt = "0.7.1" - +wabt = "0.7.2" # [dev-dependencies] # libffi = "0.6.4" # maplit = "1.0.1" From de85ab943acdddb6f10ea1a9aac59070ec0fb190 Mon Sep 17 00:00:00 2001 From: Brandon Fish Date: Sun, 16 Dec 2018 13:50:54 -0600 Subject: [PATCH 4/5] Add Emscripten globals for Infinity and NaN to fix printf for these values --- emtests/printf.c | 26 +++++++++++++------------- emtests/printf.output | 12 ++++++++++++ emtests/printf.wasm | Bin 46706 -> 46179 bytes src/apis/emscripten/mod.rs | 10 ++++++++++ 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/emtests/printf.c b/emtests/printf.c index 55abc0ad5..603ad5feb 100644 --- a/emtests/printf.c +++ b/emtests/printf.c @@ -27,19 +27,19 @@ int main() { printf("Width trick: %*d\n", 5, 10); printf("%s %%\n", "A string"); printf("Null string: %7s\n", NULL); -// printf("Null pointer: %p\n", NULL); -// printf("%lf\n", INFINITY); -// printf("%lF\n", INFINITY); -// printf("%lf\n", -INFINITY); -// printf("%lF\n", -INFINITY); -// printf("%lf\n", NAN); -// printf("%lF\n", NAN); -// printf("%10f\n", NAN); -// printf("%-10f\n", NAN); -// printf("%010.2f\n", NAN); -// printf("%-010.2f\n", NAN); -// printf("%10.f\n", INFINITY); -// printf("%-10.f\n", -INFINITY); +// printf("Null pointer: %p\n", NULL); + printf("%lf\n", INFINITY); + printf("%lF\n", INFINITY); + printf("%lf\n", -INFINITY); + printf("%lF\n", -INFINITY); + printf("%lf\n", NAN); + printf("%lF\n", NAN); + printf("%10f\n", NAN); + printf("%-10f\n", NAN); + printf("%010.2f\n", NAN); + printf("%-010.2f\n", NAN); + printf("%10.f\n", INFINITY); + printf("%-10.f\n", -INFINITY); // printf("--rest--\n"); // printf("in%%3.5valid\n", 0); // printf("%.f\n", 0.0f); diff --git a/emtests/printf.output b/emtests/printf.output index 5136a9d2b..ac02f590a 100644 --- a/emtests/printf.output +++ b/emtests/printf.output @@ -15,3 +15,15 @@ Force sign or space: 3.14 -3.14 3.14 -3.14 Width trick: 10 A string % Null string: (null) +inf +INF +-inf +-INF +nan +NAN + nan +nan + nan +nan + inf +-inf diff --git a/emtests/printf.wasm b/emtests/printf.wasm index bd5c1ebf4b04041778c8b30ee9b84665fa0e8a9a..69cc16f2b7743d206fabe9cad0fb1a9891f35518 100644 GIT binary patch literal 46179 zcma&P2b@(!()WMQIrrRqnL98;62(BZfH`1T*GGV`yeWY8AJz0cK2OZ zf|xO9OrR*Js2Bkw!K^6eteA7o`ThRt+!@ek-_QR)H20j-p}M-dy1Tl&y1Fo8>|s%% zP>2p}+%FkFeta~3zeqm?e<|!2yBEKO{R)NsQewD=q89c`j?P1mR*F2VuwQBXQME|X zQPI)+#Yc^gj@qx7d&RFLt0W^wkL$AIpLff49lFEbyYDf4kG=Oy#uwzQrGrNuzW<0($!;TdOO9&) zstg@{(4nIbZTlx)p2x`1qehH5c;v1l4?BF!KMS#AbMVNvy$^32F=|E6UL*EDd`#Q! zqjwlFdi3FKgU1~H_Z36CdFWnkBMxZUecZ?~2aP)X?}bFLs-uq_HLB^z(FY7a^w8X= z^9nxge&ylAhmSh^fRP$)X)EBbAb`_(V^ z``zZbS9Q5pEm9|ZjvT!_yOoBIJZ$U%V-7u{ZRF_ThmAb!fFu4neE&laE;xNkctDsq znh;NL;-qaOsE_D~sIE>})aBuWMvNWVUI!kb-DBYPQJkb{630;z!&p(w8<<7>@Gma$ zQm#amPIYxrwOHS|OP4|%7mLM`;uagCLg}#X{tbMM_BiYz782P z^6!OibwE0xC3Aeb)cePtKtFuU$U3r{Y?WPh39I(rWtUy* zZn-bsew`>9-?u(Qee12z+^@cGeb&&N9nq?{zMXd~4zxmJQnjd|nil%jH&janEA*?c z*7?Jtex0k`3Vpj|g(k)9*9D)3Y9477rC6n*x~x+)P&sT5=n08u;eh!N^&+~b%!t->VEAu>o zXD^-;c&^0r+o(D8;Q1WS?mXx5?8ftao?UrP;Mu_Q(?WCT!gCqV&ODd$tmpXvPvO0Q zXD6QPG>0+|YYshmtlS(Lc{DbMI@>-Zynaf)FnB0fBF>%AIcToM7WLy?@{j6VBRN9NHR#w_hwX~g-w!ihy?mt4obF0=# z!PQ!DRl#f7TD9Qkt5#KTeJ!|N!E4*vc`)8&ypFBY5nA6I*0ptOiGQqGy%Kk>1$S2B z^=!Rb;?7FEzOCO8O5zP{gIeMX>#egAcc}$;QQ{44!&>4lO1zP6)DcSJjcwyv;>GpW zMTr}-H=UjhN<6>@bbOL{6WgTYlf;|arX8QqZ!_C0|I9wEw+6xLy5r1uhivpq=rmBZ z+g15*Zkzwcla#-+-~GlDp4q~-SkW_^+S$4aXt#FX1p?YlK)19lf8zRMY<_3!CZOHheI3*80=kWD)9&dxbr+9pYumPa)?xzm_xAgCPsPk$>ulWxv`3bT z)q04Mf3QDfb>f~gx>yedu9RKfMc+W_5732)%CeX{`puJTSK3H^3SKcSRZ{B z^Us&MSW%y8{`poHOZ8dG5&5KxmGoJuW&Cv)tLS_Ce)U;1JhK75ic%a=IsjtkcL&MFnp3UL%#4b;=f3$`(i*|Ed9G^9&c4n~} zCZ;wq&6089(=_`wsAG7wWVlb$apBRjJzCC^*6?5UUv$4=f7^d2;NlmxhQsWzEE*gB zVgDd*b2uilW1=i-3#Ufev^9<2xUD%{5ZMKh>V8IKGrZfmKCX)h20X{EwKo&Ahrc@7L5rH%f}w}*tbOt z9Jf{a)my2dnoU?!5ub^nojnr|3$MlYTAY&xI(-=1hjC6RXww$HiL=;WCM8+HCM7N5 zl!S+!0&3?c_DyW(L*y9>oI&9A2@ks-uiFy4Ey>0=hkFydH_7V9g{6rtO|r(;@S=R| zMJn#?#NJLas_V1FKBL2L4L>G^dlBfz7YXBITsW&}XBD$}T)3oYmlU&NYq+Xt1YcDg z6K+-*Z{xzJ0drD#tRYnj4$8y7w(+6Nx%>!N+lOKX^v8o`s& zG2xVyFy6+6^HbyFe0byX)GklO8`q`c4SvNN^HZCjiZ|{_?VeQhd@Qxc+~_JTn1ym7oU>+vP{x+LB>v!tp$vlJdHE1fvx;*#O!d(S~u zZ~4osicu9>@X4%_;U=an;U+!AF?W@O3S9AE$#8c$Sn!)jah@vKO(pTivXVVjQlt+` zhFj*5JhVA{T{7HF?)6Np)-$ne6U%T#HpQ7|N*T^k!#l5R=h33t!ewPqhhI_WTD57fyNAFH9sn{hIVSQ=EF0Fv|#56Rfu=*vHmas3swr^|rv;A3Y{@?cBV)DP(U&P{n zwg0xijthUYzlpp5$NopWJ=})dU&n;~>~A)FTo_>^#M1}Z0pjQbZ9hA3Oc-e+?7(s1 zAUjB$e6SrXK0d@o+96}Yp>~iRGA=Y*v%*@eMcg~e4z*EZ!f0!@QRBklHrftv4o76O z`q>d)7p>MR(v7h(s_d~gR$pz_rtb7eJJLC49DxjHf49FY@SpZi75VClU0qQQdwQtt z>EQm4{U62om;Fm|j|f#NWFS5H(aQ4Q_HU&aZ{wBagvfAW z*NHqLYZw|PMK&oaj^``2hH8lOucK4zTn!O0z-)44lfAz^HnL+QT1Cq8wsB&_%ZUs_Cq;IW z64gsuJvp+I9p)5*#Yd+^c8YtP78$O-DV!cr*wgbAJ(|Ngk)7ia&W-F`$KpJiLmo_F z&X4ST51ty?R1dx|vI_}D2L4@rlH!SkczzVtsivgo{T#hJMc2-Ne^F!?Ie?2JyVwC- z64@n@I_--U{UV~*$5n((a=SFLOFi5)w*H<4nRqF*ZLq61>63wvva-=(=^ zdPZbtc;Yi7JJW}(vm(Qt=0nzLJ{F!G8Sc!QPxu{hrg%P=i7J;lTJ_m#^rVqp?!c~y z#Gd@BuedU@E8Tads6UgDbXH`uL@Yvnr-u1E)%UcDO``#35$W2(Rgqog!|T-)96p6h zuZglBgIyyu>JtbD4wQa&WV0RmwUOcK2Zvb|o8^qNS02Uoax|`s47WVLIg!l~krImY zJF&qHk>RFzF(t%=8zZ~XLEjYFOzZjB75Jm5H0Nubp*LG3*f*&`}eZTMIc$)Dll(a0Wk!RxU|!w0`& ziKTeq-xi*5;pqu#_sPhfbOJpU*;6VlLe&!>@w5w7PkY`ZWB6#YrBNtbQ`jx#O+L?% zn-}xh$evZ$Gf~*BYP;DIPv&F8bCKb4k0qY!`N(iSz~Di%e<3p5Ql;_X!{v2Gj}zS| zZ!a%K_Tmb%mS`9nt8k+~Q>59u#}5lHNA@yh$i_34&?jC6v#pdDN(aue)*+5EW8!jTk`EAUm{NU zdHd$@c4TkUHpYc_BYT&kwubiv#omM9???7N(U$c=EQss_kM?0?A5zb);iJfK??LsC z6^)O!@JVE!kYGYXbNDo}Pd&kBk$px*wuUbvBjy(*_%h16*q31bmEz;o7QT+`>nLj& z7ru!M-)~^dZzKEGx#2s1DL04jVSvcKXSDkvvL6UTK8y_a9YBAM?B^(iYE`{SaL)N9 zvR}NaC&V_vId5W2Co~c97Se3a|1ItHC~TE&9p+b367^{clVYCaa7>)7V#mZSVKO6- zCK)t=$#FFt8w-bH7q9-_HJjSP@v$B6a`=g{ofxY|Pl^qv zT01#5T%Vy~N^DakaG&fLo)X(B`m*qQU~SKHQ1%DVt4~wjHy~En5Dr?6*FL>^@b9NWc?PuCUTuhQ_3btuPoF3csSYp{_v0WBRFuOdq z%VUXVGvs445WTL5?TT3P*_E+f8LKJGj14z~JZCA4k8$DZ*sg}Ejs7KHZI&4+l?OUrr2)cr8V3d8^N~{ zYp%k08yDuq#)sDN=Eq`gepRWr#de!l>g|w##fRJDkfpXIZ<~j#YMF?7M{IY9F59wV zu~pbE<>mLhY;ReOtr#|_jXzKu;#%O$uh<~5?wzsS>Co?r?Jj5CyJN$Nbr;5l+kR+R z6x$-&24Ac|R#|@ZuR*E(z8VGshjDLlY>OSvJ+a;6b#+z6u5vco+hf??UYdJjyVv90 z7u$Uv@BY~C7w!YWy%@F=Qw;?BBG}&-x1*m6Y}=@;55)FBI}fBt^y)Vsj14E8ABt@| zdng_n9*OM{McW4N=CCB@WeMJo#`dTtx{zS`Z)4TK8?n9Nk>8B% zO^^ImY;Td9DEg+Nzai)@@(svEzKz4yDMe+pd@8o5Jn_@9Jx#-D4$sDhd%{-|o}iU9 zhv#C$Jzet&Tfm2xwetu_fBl@ILLRMoB0(tzZctk?)$!K(_DL+k?-NJnlbBpx`~x2- z@hM9ep2ugg;kFqZW>##b^WvX`G9Bih9GTB!!!6JCi`c&CD25AxTZ=Kij19Nc^V&uk zd==YQp263#eeERpHnwlQUba^Fcd_BV_5_3j;``We%Bc!c~8W48;05Hr$U6h*$vnB{rO+?8MeQW;+Rl6A~(6LINSTbB>>w*u+F4;V}t0($Xg< zhC3z^jkh7JIUJkVv5A6?OYFEr?dbT#j!z`!ogg1OL6Kdu0M3auI432BJJI26r?@94 zv@C&{k{Iq}523+r$AFa>ZaZbUog}~0_+ZCjXgEEw(}nA4NF)dHD-Jm`VQoOj zoJANB+QQk1ot4WdhDciQ(2#3_OT(abmbLm6e*_b{PWM zC5c_)XkD7vrJ$7+Lcf%tTppX2*fe?ektgw79-E%nbXLX2h07AV%$LBf5D>e9@?M$P zl|+*~HZ!rA9&J`)v#2Z9z!Jkmd29~LbvGzJUTxvV#BNL^kKL3QzBj=YHz#(p*UByaf;@IBwPv?ceRC6=OHgZ= zml*CAV9rl$eiHiS;#fbgz}uZ4=mG9X4A-wlJKDvaiQVZ8cUNL}K`@2j;fvmp^=k`v zC$=!LyQ%2~i7jxFE=p{XYTEtBgvE*4{bH|a&!`5Srg2YVxZ7*&r@Fc?G2DvPd4FO! z_fhTL?hNq&NJ=JrP*2A4hZ1DMhoIBLi9ML)GU3BXH9R6ZJOb6003ut{tUV2-8n=1GT&&1PnM6y>TfiC(qCq815rQmgtdl?v(rqPKx_Ud)!YG!+qj_LFWwsf1cRq4(E%+zHq{Rnb?<(&sXxX zuN1qg%%J|)iG95SU8>pSHPtPC!}2?&8y3Dz>|2#pUoGLggmC*#0J76P;`fQ+Aj1y{ zKK6rSLNrSMQ^KbT^mAgkpFGHm`il}NWJ1w!zjz2f;4`sk6N}61shTbAFMKAkc3xDU zd`!`fDZ-`C_0J}l(0Ho-<)!}FczGTq~Q|{*cY5Ro9MVnk?gFPHuv}23eb5}oo zbvia2SG0ZXINy(5+Q0TP!NSSKluVTOP#ek@yTI9i=5Ruh=f=(9#G;*Cv=b@AN#MnM zOPEr$lZrNl?(>wQ;h^5BMLV_lTR||J<6uuK+G$>-(~EYxN1EmSXA}*03Xsn(8t#nZ zuHhViJFPe@oLe+L&Ml4!*H!E~NiQqPnAPlNhjCuf&hyQT^NV)AXL3Q2k^2HsF0Z$# zMVsmY7b@UF1$?cBpJwy=hdS?X>QwlPiiVp?&KDQ$Vxehus<}&xc4<)&rg?;Ecug-F zPEju_+GRkb^J5QPwR(BcF8A0oiZ;Wuy`pGWbYxmzOz{qNc}D{gzoB2et7tfpb3xG- z6gAHMQXU!>7HuI3@o5|q78T90T-=V$Jw@aF9o5KA? zyFX7KHc5dJb|4_^m>nOf*DN6<^SP-4Hp_k%MXD^yhfU}wpc6gU*Xp^l0-0Y~v@0Ft z%%aT%q@tyGg;_+5= zhMR@o4Mn@Qn2!!Ouq}CG(QsmpG|SoLrlO^G6CStd1)jT=XFIXx7LCuj%C};(#VtAS z%`4hG$6|ib=6j`*`X(6dwxaPik2<`)Xnfobquo@on{r0mq&}raQ_6lv(QsEn-8+kR zr|6kNNXp(p$dm}sG5ud;tkLo3oQ}3xOL(AYn`Yw&hX;#n?ANOK;iBOl1oL?nqtR_P zEId*)+&rez*H`TNidd0kP2t(1JzFEc<~y5#$fg~5q*a#G@^-vL?N#|bS~T1eX!e*$ zzXUQbE!ty6TS|717wz#5W_zM&PdIsg4V2E{ak1Z%MSIdY;HjcLB_ce4Z*TEIJ(E}< zZN?H|(Vh{LEk~&cO6?8xxuQKsLmd;IFVb}Fd38g!N%%u{tk_YUS9^u-FyFC}hRstt z@OzTipzLi%)ihiqRa zeW0(j-xuxsV)&tGKNK^zKz}USk6yf=_{Fa!{9Lr3J?NLB{Z#8fexU=IkW&5$?A9KW z8o(x`EJ~&txsTEQuSWODdf`_?_^~Pe>h6zA4R@>uk#aHsj!*4)4?7{X6VhxQC12+C zbYhyF&EmBp`*5<74<{?BM?5J-9|d?Pr*?8Gk146)HwAd73bRw$(mstP!<70s!+T`p z*p*b`(^EU$Q=F0788nQha3+&3;)zOUq+z8FDfJ9*BrA#NXQg(QCptT|v)Mvta+lgU zp88xiz(@_hfWYqIyi{*H4hY*TAg66zN!iBP*JwTsel zacUQ*s*FpRfO!^|@{1p9hpA2Tpy{byn&!Rv^t2i-^Gq+J@H5E6E+gs{sR8#2ysq?W znNiEou5{YtNwv&mxOCFbN)0#Dg8*?Q$*xN6Di6ClwX1(sE!TLpT%*YKMajK+)0i!~ z&rXMiYuOYR-P_v%-jw@#uflb`3fEP!=cIT&eZNq!(FM}<&?iWwYweM0#(XgPBYgyo z+~?!ea34~rPg46tg<^vV6`9Xd``lGzzGzqM`Z6`#7qs}VG!drDUgg-+S|)(cyBajA`;Q~TMA`%7xSIPE5s4EKZ6?gyvcL^O#?ghFEc!xjht z-+5y?tz@SuqnuAz*g3sqr#miZl(bR7ug24}N_Lj}o?U{Tc6NzPrxGMRN0cIP3jy9j zRIT}nl3n32t}NM=4r6A?X4dGqh3fyR zlHsm&D8vBD)g{9@6tzivmzH`>iHA4!*(JNCgi`qIQs||M<@L!l^r~7#`CVJGYdyc~ zN_Jf-I~rMBK6bss@1+i54%_G6&~GRiZjOi0A@pKsC>gGo3e-z0wKwzOE48=sqv z%_Rv?x0WP8@v91-EB!UKi+O|*p)JfW**p~2sI=SIUGYNSUb5Sj-u=gfJ6z}O4$qnN zu;vh(TME5xNZ5s8#eME9*_~dJyGwSr!tN}EU8=TAt#j+G&SXK!aCvV>nSisfWVqfc z0UktIR5ILLWhK__rIp&nC0p!h-6PJt2gGQst3rX=TJ60hyH}ol!m3I`TwkrduVnX? zv|4+A$?gZo*6@G;*#ngMp^`mBG_BS?T(XBf+9M@<1SV(=OJGe!8xtN?G(OtGV<_s8 zK&!P&OSaS#JYKTLA!=)QqGZH;f&@>NSgn1s)DoUne7xGiGbMYbq}AGIONQ^WCB~JK zJ?Ay^yuYwo`vNs*FOV4I=@K(v*EZJLB``aaZ+v)ob>aVJH_a779 z^)~#jSG(s}%Lbl*uVlDaYP_h5d%tA373=oHlHuG()$)pS$46kRW!sPSWZCwU63e!q zK(J3s_Hii}tEk<4QL--_-j^l&vZT@NtCHb* zHHB|V_KmnICwXn(<@>5 zE~;i{p_3D~lX`{Y%ZB@?I4qn{wiBdBYJQ61#Il{}=$+&dPJ(AoE*nl!Pbu3eD2h_c zoUl+XrP3>{RbD}O(v4qT#$T*^P1$f)dk`tF0>JFD&GxYC%646O#i`%* zWljCA_sEokb}lY37sP+=uu7JnLT2pU7gC(N`AhjY_~Y0TvQIX$}7w*8!vMq z$b4ZdzPhb!x0N-%-7X)y-LskRl)1xek)qvMHrySx!rJ`yIE-v}mHG6c?e4POEmZCz zZChAS*3ibUhPH)LP*!G(2qQvUxTkE3%61Rzb#K}3^=iGZZ1*X>`=c}GO3n9sR-~uY zgKc4%Lsf&rFeWta^FY}i@IpLTwg(mVKsgMn+AxYLV)an>_fXkzxko;WeYkA69*Thn zQ64E9ZlSWGNvb@IZA;3w#PM2Mwx!_3$kvmtpT@3L*|I%L4Y!8p%7%NY%=AUk_-G3+mhD9nXkdG( zY%h6&m&^7tByA0^l#Q6Lkl@ua1KX?A=rYB}t1Y}%w%5uU*j_IizOTc`Z+pSN21d3I%7*J%BOij-hh_T^ zO37nt{;Ua|AE~x`wuO<DFg=>`%(}i4*m+vVEq?cKiV*5xD{*ktFqzTM-}+K^TgL6sR8X9JsHrxEi<5f3!%O%+c&k|;yZea@0}3e zL$@Ex_G6i2dS91AcW-{()vkXk+fNSg=d%4=)`<2?*>LmAO<_XCCRE^p=h}y~ZW_`i zR!m2mY+}VJH>qOX)Fh6n*rbYD!Q_ffc8&OBD|W1sqfx1iOxB<(WIwqQx_1m|&-y?F zh>r3?ljAFf>s})g9DD*x$16mkv7A^jT#Y0?q&?@5{2Ik{pdSJVWip!eSn zfY6T2fOJa5a3@!m=XPqvaP8TH&uJAqjRFzF=K-)yK4CwzVmOxS&#Ks26x6?3!r2w| z!DkC%Z8`Itis6uw&aJ4QKG!oN8r}1G6+TrD=T{7Oo(K8T!39dBkf{~JUEm@3fb)eF zyYN?oY2)hQ;)-2NS(WLEJ4rKFji$yrST!|9kCf?D59?7J*ihx;A3D`kTRcKkPuKZ5L)Z8QPURhJs^bt%B^L8VC5XuF*lH z$^Jqrg+QU6n%ew>hgK{m>v#b;Wum`p^$R7`^E2_+71BAEhwFr+o!^uzX2blE{e$s9 z8q=Dw-YaEfMZ8aEx$Iu3dB5u?=UUUhE{D|o1syeN+#FX$p5vOwC{yF6y3eoEuqOdZ zFfH2E4?9XIRy&SpR4;K4*QmCvDLfWYeUIg(f;pd#3|(mm_G@iu)uih_Q~IYJ07}o# zyGpU^J5$C2rzV(eKOb?J_vwiJKUT8zjuv%YzJ$?9Q&?AhR^earqi?`{S!&Lb^_NQwc7E!y8hA7Th=ed;-53|KE}hwS3=( z)M!q#02bLh0zrtYxa)MclxokRt-uj)(p~1N)vyHG)cFL-)v4`$SOR5g#)}XCcl8#b zEJ#8g*R)ois88dv!P1#M-_=FCej4_xW*N;NiU*g%IEWl z^N7j^P3*dG-*IAkV$)AqC$5`1` zCZl{kcNJSj+4NQ~rX>tgQEox&txQ(U^H|MR%O~iNq_>XyukMlaVlvFHVQUCVAC;Pp zF6gPAZcRFcHDM6wMldJdMYVqVq#51;6=C$ANUv(~CMPFE9QYx(F9H9p(fcHmhE4eF)-faQU$Lp|KHEpOZK=E6`_ z%(uO5uVe#_*iB)O4N~7UkZ9Y7di6|IvHT9UgCgz7G>%9+8FADn?MSp8faX&a4mGPj zs-eM)MNv7&u2h^{7a2H!ZksB`rXm9;&+~Idn+8ljaD*PXP1dB$p$YxYU>mH&L$rW8 z#G5tBEb`fz2)1)m7-qwWJk;EDL4(q}hQ8O%khZX^?W)mdw^~oLI|n0oYYls-m)S$L zqkd(8%JxV5qrmQIdjfcHI4?$}U$S#|4@T}&m$H}bwL(UF+ur#CDV6}JzCYQYY=BAz z<^bHs_7T8+ZC@e9IYG`OER$$@sD_2IMDa7WVaMmB|m>>zJc9z;#` z37sJX?EoR+V57@8SP)!JJ0u5tC`Ty|sez^9IA>`tmsLoK4F=j#3lBA;Q8tQ_wn#D_ zt-0c8C*9$-_HhKGKucR_wIi&x)lXhhOio^s1fMaXO%10_867SLX|%&xJ82AE)BKxL znIg|Pj#8HF$k4TFUGr|HB=CaNyDnU>joGuTE*wLQ;-Y z)~0|Q%7i$5wu-5j#PSv&L4`(XZj0Mzq2Ci%n8JC;cOi{6!)H^)0Uh+923sfam#@Ai&|2CPWwEL zaH)-*uQQkC>-tPa{cL|(eZqx0d6_ro3-V{J65<{i^8l})%OVa$wnw1qFV~Ss|7JJaN8%aes+r%F zdQ!}p5i`G;&}o*=N#^TSv!bd_Kz8N~WLvm8va2H$J!V9q=zSfUDy#=Z9EB7Y`2k2x z{I2x_ke!>tbvo%t91P=X~C7SnLADI@tWNJXYzzq@JK)+F^9tG#7UmbEJ`2%@! z_K}tQP2`?;ju*rPH9;IeET_aRei+hMHk=T*`ccSQIE0w1laL-?g9$JmbQr#KKTk&> zg~NOuj#L}CP39MJ=mai@a)+OeoWGpjcj|1U)v~2R?()--%hxZn^Ih@eZXJ-63fO`O zA6wu6c&D-#>aZlmUC=+oX+u7m#6l)A4_~Aw1z4<;llfS&I0~`T0$8qj(!iHb)1vI% z{teaLBR7WeA8lc1;#bIik3k&sBF7dt8uTrh)GxCVb~beCrr5YzNKFPE!0Eg++Fp~u z4C5LDnmY^=Wdmef!{xkf5qG!Y6%#yb0G{@MjTseUbHs$r#jdWlyai#j35G9)Y24bp zg;98m{E&g`0oPfbo8ut?^}v|vW_WCC*G{ceWp1%n)~7A&bEL!?qpegtus<7| zRrXGM+j=b!+}Ev{<60t{I-Ok3VeUe7gdAlc=_YAGpxMwi76rY~1FREfakkCJ$ZZuH z>BKfs__pE_L=YcRROoFfG=dL>-pu;iW=)bF@*+#qvO=NzQs_<;db7|wZ(9X*U8}Ok z;qu42`Gd1`f?p6)h=m!a@K?8jtu9a0o0<>;`vA8P$`oHHF@aayV6lakuqJ2q${Jvy zwwi4r+dyWYx+_W#z6Qu_Q%`-ZWIb#pnTm2WkXiFh!gcfI$Sw0n3^2=J%yL6@P82nY zF}uN-wgO|C7_%Gv(oO7^=4=CNE0eONR0zq1z8_$QpYjsAt)woTbN1%xNAVl1As?ds zL^dpxTZNj!ndQa`HQfp7!m?r(c$LzjQ~+R3-a=yE1y3xY=dx~KTx_Ur7L|ms+Teu! zh6P%mC}#yYf>jvWUEU1GhX||#oQK`7Ui8YONgCG(#LQ&%ipJYeZHN;2$BljDzd|1{ zp@JNkcL=cpZjYj_irM`?k*Pb4$ZZW(fZb09wP3=I`c~N%6k1g{byoFO?=?vO(a{Pk zFmprR3f+hkM9R*Zv(At^%U|eSz&_$8g>@xQ4c;Vw`D6INfr8YFbLJW1YWh+c}%`sMcXbSOCyQU zZ$j0?8#tqntc=BaG+KjzcC|)5x>?s6>~8I_=@;@>!7d~IvB3!oQ-E&3?i$!!KxGH$ z4I%NCM3<5M!kAv6w0d^3igjuct29(Q)v9KBCCP@-OHtHIwjuBZMayMF8H)xl)Pmt2eI?Hszly>DbrWTy+Uae}OP`}ow)fhWkhWFeRQ1!;) zeKqXR{zXFtf3+bDmKj!))F0Ddh}N~0L#WVQ{X;@MdY!|_&ck;m(RwP~1`wPi^caG} zd{AgI9|X;~vA@p)@nG=4!=sRY=$xfteGo?SO0B=Xm@U7?y-tt*>&S=`*!tGyfb$TTf>o`jO3zbNVS&&KZ@dXk|i zia=81A&_M@?!6yv8rINiLPH45iOg*iQJvCxpfeLR29z4Kx+atjdgtSLuNu>kGZ@nS z3d7YL!-W2}14B*1lcAb=gTv||OD51+9WK&T3w7+}$BrFUY9LbtnL3W`8t zVWqK&!AP0WM{73Umw9(zF-b{Z40MupB?0Ui)v5NVO4S!#nwJ6C=c>;xkS;cV?%vGaL|Oy8?>sh~Nn;U=pSUHt3{7 zK9UA_(BiFItLDi>tG7ZP2);Bn{Okl15F;k@{UG z&mk;dq_%Pk%N2vDx0TVZtWuwPXJA{UN-byYC@|_ni!!|8ix=3I(=tqfqrwvOvFWFB zu@K|s+7xffy*c5VdpJUg!ZE++;ab|D+*?uZEhQUnYFiIQwA{+JY1I)N>Zf2^$}k=) zATotlFvcQ8Jrx__XL+#)+CY%q7T%YZdJ-yX1^F?KU;m=h)KKjgrDDcXJA)S*ccM%j z$g@IfMcE9B8>+{r(N>DJ4YAazuVr2?F^X&x!sVOg%+6|!ZPpsLiU-TmzsxS@j5==#D8y4{C1Z(3M_vYidZ9B;le6E@ck(yFbl*>%1rJO6nrnm-Fl? zePI1rr{pNj)>%otZJPIGdAYC_SSv*D_CnBwDHeTiMHWcb$|g>lTp2}|R>_iKVRZnl z?%{QW*Lw@{VMT3YwXqr;vR{7s;qPi4eX{;N4PcTL0yr6Ql!+muUSmhXOEs%HS)E(!=q2j4&Xy8Z$-|r&RTb2Qo_sV)axzGC zP9$q+t<6#I{HqqnB5JKBegDcjLxct_NTgaZp%yn_6sHzfYAa0*L?*Z|NQ0$R99 zW^Po?vZe_mc5zmwIW<(fw$Juvt<_k{=B(9F?XrRoMq=NIqqW7UbPJ+U1&V7c^-Cx7 za>98FUOlb((=9h{s3AVAUTs{T&c3RKN!t;KT=HYkQSpn6J|!=FF?$4Ar9&3%qEQk- z1=1B8`)RNZz18k|SCNAlp%GdHvm0N`5$Rp^)zi9J&tdsEO0tb$=w1@AU}&FGNZ@BW z)}*dgGGno^ufT29F;vnx6-*CHDE*KKsX1LalyX8gZb0?oS#WG?a}T&p*urfBS|DFD z3y~y%0=SFe0NUR}*0lb_S<_)O_SK6j2N`@~yj*Idd|;vybtWgu2O;#;Xq~mqOWBo= zhIkse0=o0XKSZYXA-;E>e#K#jsYHZ+G$$MKU)p?a8pV)H}AS}uMTvUPk`tyG9_v>91n>d2m=*Ce`JJY+3c;sE5;gPPO>e&9i^=Azx=Vzi-n zZDVE^%c2!#Vap;-!#2*og+o^5Df7K+*~T==jk6PI3hUZhgIo(pi}~$ujU8_*cf48c z&1t)#t!f*3{tOYT+B&vY;{YG<7_+>|<#VsRsxel(4kd*Ys%ps~s_A}`K*HK$%(W@8 zV!-toeTvF2;TvvOtL_lKvuKFKTvFF%!&|A?LT$O(r>`9{Wmj=b-h=xrw}ZiZ*t(*e zbA@(qYF}`Sc-_Amp^xIM>vUQSYoiGxHNYPEym;1n$t&^rE=Na4!AY;juoBbU zR81fO@vx^W8&^v4bs?y|D6uD1Z`Q-6zA-u+FDTiqy z?K|HQu^;RMOgu3Er>*E(s+KNm$p-xY=U*Y#p#644&&dzlshyNZu|6rV(VvH`tdO6h z`lOy6*Fu#hjqNTPC%f$s@kO7;zvy`D05piP&Hi?z;feIG#aSnYNs$a1zJ`etPy3nd zbE*C0yS_Qn{hOo$@}=+nu0r4bxn~OpATDz*P8-Ec#Iz$!zF&L3UptU*v?E+AIY7RZ z=`I@LS1Q%l9i>X;v9dfUOfKX=@s-1OPRj4Kb6 zUt-MwFaHoR8m&j$#QYcW)?_}%sDSzhnEoV%5*6+jnF7o43KL>k1KXo!+$O7oQZncR zI1*8+iBdIDBJ@Kh!M0xcY=NRTLWBg1DKVD8XgZT&pP!;CVz)js*db`X&R_hrxW*cc_18lJwfo$XgMBbHI4C&bj_3BC#y zjEK?*I6l_)HWq_kiM?vsJz?f_lI)CSCqB-$jPH4iYQEV`DUIIc1u%5?P7O zIskj%uf(Dn+uxvdnxl1^qlG;&cEX(!ft~O(Vxh$j_?fZL!Y1)qBHyVoSe@=zo#|Me zCahBV_mTe)U@FI&SPK{SQ6Yv1`}4G;Kcq(N^*S^td`}W(D%l`YmE@WaIU*OxT$t+7 zO%kadpNw-OOl)LQkElUS^+cEsyKsei#D3UCLYFhh#B0NJi<=RX1@2ldm&mqqt+>-- zo94Mpk1et3F;;eKX2jM_3b{$4nX)EEp0LIYnH39bWD%2|88L>M(ySM44ROF9YJ|OL zgn0w>&EG3zSqxr=G3uqyB!>5~^KRMO!WJ0=1j2)xt&$n%hpD0#nbpEd*OBR+S>SJu7VlFL4`YOW1D1NZG77w_m0q<{CF-2Iz$dLblLr`x@b{-Su;G+!>*k ze^NoP#j73>?;$dLhRDC5Aj4-G#9CzbY_?j)wbXi_Dr2~RUB}lNnvs^nhKTJOu^XSs zM%9h@pBOi8S~HRc#5uByR-=VC4k5ZT7Su@ChlB%2xHIXh*hUjO+#qvlHKy69Dcq#? zag*xyMrY((Wc6C{FspWJdpwwHt}Lpl|Hz~LRpt7ts^78s8xQ5Xi~S8Tb(b(q{RuH4 z_B`2P6Ttbg&2Q(B+hmAMeE3Xk&&1-xCuATi2MxSe!P` z`S30`wdQ=7=fdWFjSKg{q%Ar85f=QTb0FLH;y<_PHIr?6@S`gCR!R0&N%jKuy+K_T zOEa~8HtYWrmo12~5FYl)napjkg?nX+O+0i@jG2vlDE5El!ProHD9&xFDcB9JiN)@Z z?Z2?q=C+Tu*DvDz1^dS!v`DQpT+Hp*?O}sad5A~ieHer+5nuTzJhk6&RGplaja?6Zw z#am+QU&+LVyQvPD4XCF;s%mB-b~9?2Ze^2>Zlx9{9~83?K>iM72BJAdP(7$oq)jum z!PtFn%NkmxVZdYsje;ZX@2%m57+<94e`0`+2K~>}+N#WoHd1?U4X74~r~bwFFTeb& z70b{6BGN{w9aRk*x645Pf1j-DE-bWk*{XBTYR|@oE> z&}_~6N=^96W1_K{7?}M*EZgtpvy(azEWIWJO|ae>>cJ|CTtsnWD{+_;CK%FZbX*>4Q}vq!tJKC?Ot zb{n&*{azeCinGN&3Fy{=;n}ee!G7WU@u0$9xiU#{;GhEE|CTjF+Uo~SK+ISPUN=6u zU?E$S!%0DV0tQJhl8%Y+zE}mJjxUwXZh1_LY?_ol9_^N9OS`d2h9(NgGJ|`JuM)8* zl74!Gnu*%=b1`-q1%Rz~)-_6G`2LC+RtxowzoOwAF-5JRhE2#0)Ea&j>*Lryj%Rvv zyDq}O{B`0v8yz+w@un)*W=!3-KmuyAqr%|&E_q@mUnrGa?^_Uaq~YASrPN7oj6&b+ zekVZZj$G7qY8obk!_6|IO(}0;@OX}5-Xh(RjzskxiA4KPVk|$-lnv~w7+ZZ>!kkfE zE405#0}g%lj=W)>n0+HL80_V%U$>1Lx1w-8vZs_p#&>tL zT{}Qj>+1v~`qe)e_Uw3lQ2H#kf{aaW2-9uMB{kcGXCf&}|E8U=msLZAx#X`YNp?+e z-C!26fJ#p(mTCP-Sa7BZpj_3sIT}@b3@ZFl8dU?;98Pt8DhhX+ z47Q_EH6~z`bgis-BpOy!Tf2r8W=fsIP_?SER_~vMG>fZj?o5%f{Owp5_ydhW7JmoQ z7~Wmp7*e6PD7O+M{618R+#*~iJttB&l2XlRwOTX!@HZ*%U!JlrR9~%ez1&E;s${NI zgaZ0KeWm!rb3RS^Ha?BDyW6ENlsDVkzvkq&xAM6@X;vWV`mE${pEIZ9`|$Ey zKaB#5Xn_@*u&xUqz9e|J>jQzqg2)zVHrtcMz;!Xs&zR5h#obZk*12MkWa32;`&gWT zSRA1#WQ(I=IuL;8Ja360D0k zi-^2yX*I8BFM>=T)Tx1*jKL<8v#oU(+p=5<;t%Nzfiq194^z~B6muOfrt8Q&tWyMv z{fNx7lXv%aj<2tHK_6B@m*{ALu|V^vRP3$$&Kxbs4;K6?dOrz&OCxw63N2yk?vas< zrJE1zrDTs+SVx;4HKaOL0^oEPX%;W9nJpzwT^`v^xx6t$nsQY5461miDhq-i!RveK zYzF!-gQYHqy8@CwAG4@GOI`mg_ysk&D{;->Kd<+W*nMx%~Flq(q=O(Tr1T$ zU~if7S!HwUc?m#UVOp7;i2S2-YWr5T#>h@tf3}m>&ig!cjhn1440g79YB}=s>kA5F zb>JqinI2fLr)oB|9y^Dp+=Bgh+c32r)%;w>Z~F#GZd-(BBilrWGk88nQJ#<3RDGV6 z&KG2e9t59<6iwB@Mu7I(UWx$!62ULKb@}nUr?z30-7ulB4WBj`6biN(I!Bw>U{o}V zW5X-La6lgXicr*770_6zQshl|&10)Pujb`(V6Q6nHowKZW8vvp5d&y&*Rsf#i35T@ zUW@FtoH6UuEDD=DHx@15Yw@f*AL?1K$b<4cGrdHF3J$}nOf4C6&*zN14K zS>2HQ=mojG190U~&nB$eO)aBAKL7tf#_g5Shi=>+ygrI-kl?&8yY}tVCR*0}4)i@8 zk^<=aQ5cj1t*v3DwjNsHRM+b@9%mhZY~%ZXK~VC}_K&SQFQ!2f`dsswK=ZS?=~0&8h@zPV8EFk(hptLK0xK*EM^cRE7!_ zmn$v{oYv0snG~ENaB#7}nf;aJOEu7&EtCuDlGCH{<)dRQ{UT{a zSr0aY;(@jjRQj#t-TqCiPAy&PT=Yir=IYBTDO}iP12nMGt=c>tR3KF1|MdhlfWSF5wXx+<5dM$F09 zr!pN%rbCr!=W8X|BHDPS)%s2~0m4f<&;|zfDYenW6gg$^)1X2ThL& zKxbZ=9)NDx0j<6h$Of2Xi*uxP1CX7`b?2P0=Xic~9aAIE5B1Q{EiVgGY0aty_Fy&( znPW2s33DdPQk7SL=GWxc%ple5iW}M`S0Q_`T|(4BWH(6J$^HhDBX$?F#&hutFTho>T>gz(G+%X$; z0!Ys9pXbC(RaY&koJU!IW0QTYJYbU4_G^0l1WwRQQ;3YWwQPJV!r9u|hZiF2**ZdG zClJ|5h^*&`(1%^C2~&Xyl29mhOf4M+lsm%uM}k)ntrj-3X;6@9n2^sXkKa8H+1zby6a3j*iKq; zsmmsHx4LGH+3K2U=T2gJc8kY&$1KGalsdE|MfYQ=W?Eeb6;IHH%XcTIR+Zp$hr|kC@?*cH7aW&O<)ObWruZXw2ul8oZi4enX_YAuJ=rJA`D<% zrOw-f7pU$EZB59`QvWQ5l5`CcUdo<*lGPoN!S$3<8LL`E@jAM95RfQUCj^K#TG8tD zRvUTIDJiM=sQU6+t`(mP71ydM4L1%95d+^H@LWyNATdBSW*X5Os*gmunr}~bPbb7H z?4C}DwGrPFiWLzX*}oB05J^yGwq)m=DmtX40^!plY5*ZuAsBBg4NQo&@{VFOI)j6` z6O}RztJRq&sDn#NUj71OKlyE9m>oLW3+!=oS%3m|(6+9fF|~n><|Pb82B~)BdiF!k zS+89qs~}YABXZFMK7#~>#_d$*!15*RF?T@ncrw1>=pYH=nS|ocDXvibIYkv8^X4?T zOJ(O=hVA*BLRaJ#=w&^g?+JV#hLQVxdVg4c7Ak7oHashv=vsgAo(>{KQ*+bUvii+x zbM|Vtu)5lm)>`P!Spov(%QzRJ`G5=m@?eHJ53xF120`EQ)s@R6WtYt?L$a%>uZeN2PN=Cq~iJ8j{E$m{UI|2^%=KZ6NHihayM+sZ)ETcr*;@CpB}JM4!~cMX<2gsUC6=0Olr?its`4p%4M60cDdTI_7y>cE{1c`wCu z?_oMOt@h-%JW#jX@^Ev)KI=ybM(Vv9K2EOYURDh~*C*Ke!6Ku#p&T#*=Jv&UXR04agtvQ!DSCE`OOg0 zSoMn`pwV&du?vL}+^k?={!oHpG~GX8OL%)E;Z6l20%icaiCN4^uY|8`BjtV@zGy}& zu(~3w{R6i@+^%#3DD`ngO5M?mQK5r%*Tn23+(muqR*3;&LBfR+j^aYyFv0y3En!i@ zwGyK5;)E+DEE%FZBuID>5$}ODX-4Rn3$bjXz1kr#X*(np}ef zyt0iG)RiSh{=>%23*2hJ)dyeF^tjgGs~o41OO}As*SgbSg}x2(7_|QZ(60rwqYA-c zXNk}R?t`HEkFdUt3`aR%AC;{>gdHhuL>-l8t5=bK*OzuFdR?~8(11itqIJSHsr~y} z-GI@<*ZF#RTAzEcTXSvgCXDBj<8%W?uWNNVF)uGBM+L66c!@6i>KRm%3T3He<^9uZzy4+6Dq|3xQ9L!cpAa#N1$8CIx&Q)V?f09jr|qtVbOjRAqY= z{y=~}MT6L`*(%s*^EKyAhe>#1&G|G$ajdhUSQKY(Yut&LZ49#YnCu+H1X@MQG>LA} z%EFl}8Vt$L^-`l}vijets_Ez;S$t*^crLkQI_%q4JGM)Y$-ar#55D8rKFOrKI;ggk z>n9vt|BLMv-&Em4@uq24#k%?V+;!PH5xv=Rxi}gXE{|+oG4G6sl}6=zg%%Jg-Q^LG zXJ|#XMhY7w!e6O%M-hG|cq$<)k257U%%au@Nh-VCgRjz(BVa0snmdM}7!*+CtF`!h zx#zEdtD`WK9?k(X=R4n1GV^l4QzPbI0G^rymWrf0d2@d8{TS$l6bAAPDvsyP zAT=cTmJG$IqcZEM%$p->6AVJe=MEjrvNqrAg&ojGupNeKWq+T1RiBiZ7WL2Ni+r`^5} zm9?g=sb=(y_M9mGnxQY0%9mL;7o}KD?yE)_SdZ<*O&hufiFnUOVKb2_guZ&;+^Lk3 zbh9cKuBt9riN(mmUS%ZGXS)JwOSEJ%lI~M$J;121IQSA-Woe5L&*!z`belzPb>iD(VTay-y zS>S#HXiIg;d*03RO z#&RYkZt=#@qG91f%unRAB;NKMsMC9HFvc53=fcLuG$}EU5Ez$Ic5FA%?r^G zzLbio8p796Zj0m_*B+&Te_PWV)f(&95zO*OF$-^hfCsntvTZN+{Vw9%I2eBKhKRm{ z34V~KC|D`w_qCMbWZwUPT4~t6*5HL#2Ol!D4p9&MBRq>{>9AaHlpf$mQtqHlm7P(o zsLfp@QIW|0~+s4#1&^yKL+RXa*ZnpQ%0cFv> zvw!U@3rM^khXU3U`F&#f0t)6(cGEn91z>?aL6_08esDq@*xE`Z-kw;Cf&S--3Ob1( zoz`FiF-5o13fFe6(fz>3i*xD6N4LKX7OfiX~ zX>P6?D!~HH(7)vBpWgH4`kyeIYkrF1a*a=VUNk)~P$oRLYms_78s~+b!?f6@Y1i-4 z*oT1K*&5t^NPc-NzL0NsZ462!Wh>NC3gHl08v@4O81aw>sDRCg(Et^&E2QB`vKcwB zJpi@`R}o2rGY7VZHWmeJ>vmvLLzl;vfx9f?a0qgM*UF)m;=3!ptg*wj1MLv5mXL<0 zhND?h@D!t5mo0&P-kakrMjDXPC0P-=k=OM`V#2vn zxy*bvJU5meCCTQIY`!Z}lFYRzNk%AoWc+T}UekiaO~-p{-t4-R8JwQ$QZjFLElQuG z-i4NhvU0^)F0IuxaV-y7pb+?dq4ZqQcT~v2SjvfDu?Q>{D*z%ah6q*qf0z>GN8CUr zdQyi(XQbJWMIOk^E^eQE#kH9oI|j=qcK0iIfF^#rz?R9G6Mneu!>+zxQS0K_@G6_7 zHz!(lc~Fns%-OE;L%5{7p8Q%}a zO~G}|`FyxW=ZE9aAB(R1!al^gnPK8F-DT@Zf-4OB#P@N}dH_1`S}!C)zL(f2Vm={N zR!`clT>S*$Tp$71jtcTTs%(X$0ZTcafuhes1?!K7HH6tqeXDCDi3rc@a@>3(^jsYF z^49DO+$5#L7hEqFJ0RUNSNJE{UxrFkg=V(1G$?p|iTZz8I`0%@U>J;+Q~0yf>(8Rs zD^g>>HoW0?13JBy#pnQf8D5LgP$AW_m~$)a(t7dVs1^SWFFrvH4$P1Ky{S8MJ?UHd zrMZ0S03yF#I*Lz{E>-r>5wzZpQTU_j4EE{DJ0e0CuDgW@e-;tY&lxO%@BLV+Iuz^! zd34$tT`QEq(3jy}b=_$Til}N0mTt|TQ@u8IWHvA~Rjo;UgCdp~?PJb$Xptbb;mQIX zsQp0TFWjIJSJ_5Hv3%!TO&y>)!=a9Jh>RPo*&S(dbNb|u@wCWiFlY+|g)SqIrM#KvCB5s{N9 zAr8cZK$xBFmByN#S>{)#UW6^m4cA) z`*ruu>^iOr#SKa-snxINb@%J{UVlvYo7d374|ugLqKoEQTa~jV`BdU*dGD= z4PIFfHoSp(frktSF;Zf~>rD)U#w_P8Y9whu(pwz*aCoYRMt-d}uzU6P0N&fgdlR%` zItwHwf}iOtfVKO9poGKsKRB?Z_(r)jT`WFV;IR@i|E7vvxN>PflX#9meiSNac+5~P zy+7rYo*Vh$E2L+&%c5blnTz7c$};cdUybrStv}HPLD=EI z4hMEPu)~2J4(xE?|BM3#{UP?iN{Gt}EZq7j?=AdNA1ZOdv0v(~GOn}msyGU}jcGXw z_cann4|uJH;WVr;xTy!joXP%|+^__i?3?>nepRKzgO9Nqftg6-8g_LZ-=0Wf9YzYQG*#9V({xnj!kJh7Sumr=}{y_1Zb|Y=fj~d(9 z8sqo==Op&;utRVR3nreUV)F@SoQ7%ahuM%jlE?sqp|&t zqrJjqK`yRg!xQ7Wn8 zf*-HmShUF!-_Z+=v+Ha($j|Me%5qYcSrsgK_>O>5f9)(`b%)5gbsETEK@9SyWkpWM z_?GoPP37bUxz+e1N}|UOR=3|&H-qZ-o9aLld_1sLdWK@Ha1Et#Zv`&iG7iCCz^xf+ z^n*ntdM9Clx8Wm?+en&|k+zKuKq)28eBTvIRcy0sVx~8$+?jt5d1=|lyfs729U!J= zDgebW$0ISY$kX+}xsAp>YKWPYcgUj#7lgxo265@EhBUzsjmE757mM`ca#rfy7tK?8 zKq3+>+%(d>JTB)+_y`H7_~^Vk7a#m0K+CY=zR`{0jquNlg&Arg+))?@w2fcvm3S+~ z5}aG-Sc2>NXxjy~(uQ1+;|yMcpj8k(MFeAUiU>P~f7x4g=xbrLfy-je$*J`#I|Emi z;N%FEQ~UZLZgH2+0aGKL0Tj<@H%WX41U)kn-ZAw1pmvEwzfAVKK)MOUJ}hme;f943 zjrAR5!PlX2vxthIrl`}}z0s2*+;NgJy@f$V+^21**l#BB5;R#kPvtF__8Q-hBM@z& zawq$FxpdZAOu_!CGGP8xq4m=!QM6Bt#{1gyC|-7uw^+Fwop03m;BZ6%MuU(obO+5q zWUQy-l{5xWF~FDx4s67Fe88()kuQtJr$PY*f;fy+x^RwO(3EvF!&wJ!HKUk-H*JWg zcn*2B6+g59#1tS-s-Et!?5W@$N~AHRad(UE|Ew7--W6+>@33QeC@T(`z$uP%P`fKA zVdP2%j}acr;Yq@iISkjt@I9Tw`v~vL;RA#Z7%n za=1>op2PEm=X3ZJ;Zr$$n(*lyhQE|5na2O-{ok-#j?h`0VfQe9G&(v`f42a>Ti2|M zXK_QW0m-0>!j%jzl8RyuJA|DaM)4#ntEFU#8XY1kD-IGTIt6bw@t_%hEn>p}>VcsW z)0pn-)QaCy=S*qPDC|TGwlY^ETg;H+U^0X%K#w7C9Ue&I%zSZ3oklZVvN33pjX{5G z44PwO&>0(pw%8c-#Kxc@HU{0WF=&O2K_6@knqXtl0ULw#Z47d^F)eZ3zMDzfB2fTl zFtJF^5a&O^C|O)9m)e@+un%i=*Q?^N9x%W&3DrW!ZitH*JPHr2O9xx~F}&auaZhFi z2Cn7O;c>mrsK8DZI3pMFkZXsLb9lhRzCIp?wsNTgS+lo8dRL|j@PWFI2{0%{;%@7f z6Yf$`Kn0_+juk36V1Vbfj}8_@V|%Q0{h;_C{;BN!?}-0kM2KAjSqlU4!DtbHgTK?P z2YLEGH{efjLD+xxpZsV2ZnL)H)xy?<2+!0IPKbq7H+H>L#mQG>&BO16xS%}0;|5G< z$y&fa20(u_R-S74;flQKr>n9VxZxVnj@R)V!6z`DQE^0sy2fBQAr_<9Q!?>aLOhs7 zM*Vk^k&{D@WfaS#>v{@!5|8yC@g(ssp#T|es5tgp3ZHWH5m}lvfyUK^UWz(Ow)}Qm z#VSl??6&+(WgECDYmuxS#=pbSglGqmoASy0v3uGe=~!LC`xRPn3NYBFR@~IzQ1Vmo z@|)Ln1NU8Ci_`}Ti! zY-ab7+dp$)eBzc{Z>t@C;o1-GI68a!%vaAYeC^`Hm%sJox1ajXcc1>A>$OyS#lNx^ z#7VmK%=e!aOF@866UgRPif*sgdn)vlxDa(*Ka}XcQ7j%)NiRrc7@=#bZmbe?Qnwi> zv5XW~rs0kz zyp=ua#*wFzL@W|RZTd-?h;O<act?BkFN*Yxa^Yu@qudjeA|tB$KTqRUPTML6Bo1r5nX=><3%27rGm+ALvFe zg&S_*Ba>2VVgUnaGS^b9P6mFshWu`8E((!Jx6l+VF7#Wexq*_wvxO)O(R8wiJWU}2 z@JYo3tV{h4$cuXEFmk(>fRhhINh$s_{zRyiawby}OiH41Un`oYvc!crw(pIM#1-_@5EQ2WOYW)aZ%p4igIEYC$> z4Un|h3ymT%zu)Nwio7(^>OcitbQyF6w45?Don{FgHTBy*ijC1hHh_J>$eM+?oXnKl zVMBCB%QQ*c$|Vz&DtRo`H!#cimMtY+>Gc4El=Bk`H2E??spk)TXCY i3&f!*7&rZ12U6~ZE%AgFyG`oP7&K#Rw{xbHto;&X{w~Y59Ktde0fy{qFZXAGUM)?ND7^U0vN>UEN*UXTpI|sZ@&o z(7JarY0{)<(%zB&l-yI=JN6*{mi8`{_RdJ*0ZLlhJ2|w7Jybc0xYFL`Nr%)EMTbO( z?j0X8DLQ2DvM8qnk3I0u zJ05f}iGR`ERS&H0wtK$A7!uaM`}p@>KhJ+dKzaXh2kpDhxMY`oc1aFtd{sw{|KkDU z59t0ILBgtB;1owaagR4y=J-T^j+&a1?Y52LB+KF`ft{i_;{P;>qEcE)<1)XcN;RtX zX=;jUX>;Fx{Yr71rfFGe)0U`I-mm|pXtlV;pG1FB{mJ-~m;U|FA<=5(8hTV!yWLB_Dk5JaFs;k?nv9e{#m%?a%w{H@4Kj)^+gsUmP@{ zd$+OO6H0j%XuJQZYwTZ21DZ&^Uq|j`_G|W!UjgBuuCb-oKK{AeJ`=~5TKcp`rPZQZ z)5v8Xm91H^{qxsKg!7xWhe0+dzg?gC z3oBcHMW^`+N&FXnGnouB8lejXw4ZWTB|6zk!_SWiF;l%YgOcc{Cm^)7iI(WJur8^Jv`VzeQvUPQ(kJRy*@s=ud2R$ zUzN_>x>R3oRad^R8h&e~{HthGcrc2G+k=thKwcXaZjANY9xh7kq9p%oXE-gj8{>3R z-kRBIX)PR?*^ybEOblOV`J#2y!`>J|Gg%%YdmCOWD7my zp~!G&M{VKR$eso9T%fwc>yf=4<&!3ak0K%T5oLZGfunsZsgRK=hxZPT4R^MJD1ksc zHKCGphvQ;9F3yv#aC)plq5k=?;ZBzTA%xiWa9M1Z#frNrwwq!R;GWp-iSwu{JgyLX z+*2=%LIjytZ;}ko-*rm86hk|EDIOEviS3=ZAPsc-Jhso{f>O|?JNy*qv3sT^dC8_F z9pR*eA3F)u&Pwd3*v^8;7c25&BCkpKv1A)QG+; z?Fu(44&TIZcWQU1c{DLRmfB+^?+h=(E~&jps<#z~Z({f?wa+}&kE#8Lr!!2;jOb}u zS2!sn4&TIZR%U#h1#euG*+rRn$_LJ!Da4i#+6m z%y745ZQ+~DzR8?7E`p+mmF=*yc;i@S)?>@?by>V|T3JndS~)yjQC4xtd1b@h=3S7Y zK5)-lN>LM9@X4iR!yTD*gd6lDj=8HWRN#t7%Z9tl!GhnBROf}V-B1>Pyj`{z%1ZQE z*>G<+5?xwu4?mU-cY_DL6sz|fS+OH4a7F&5GtY??I7c1t%!-{!kLnKdDxwa5MV+e% zBD_1?TCt}qc59_G++VT#D}uDBVv8zpn}>IW4=Sqp2Nl(vY*2I;ei@*53BSqeAzxSQ z>xyVRxoVTE#C=@}zp2@8>_pGjBtlKE8m$#w63#!8U(yCor1?wZT&?ke{7gRgK@A+%L?+km{USjjTZErF8KDLio zd|%t!_MI5^v;D-~f3QD@x5wI8+qWzH(e|^k6T|+tzj*opJ3t)WZhy4)uFzroTl>T? z&c=z853~ct$K$QT#&?B-Y@Cgs82)U3R$QlbihH~4AnWQ1-S%henivkYZacU=Ow4Dj zYZJXK{$hU->HcbeRb&6n{-&?L+utQl|6%`d&N;;X%CzRMOn(ju)nqs_xU6yFf9!vh zc#=&L33?*ykz_9C%e05dkxh01cvxhIMT$N=vcrjPjxz$n5m7C(N&2xPTzE~1Y>H=? z8rjrHg&!H29E>|HGF)|3I6AVUqjVBqnN@3HVYT=?g3n4V+))J{u`KIO4Bg)mtVQ)tlmArtZFQzB zYlStOw5y7KXVO0$&{>h4<$&fyHb>>GD$1V|**PA4Ze-_r^m&n;N3_U$Zp4h|oG7eG z8E46Vru?=VWvm(2aH6c?{5q*S!6g` z?sA5}NVL2nvdhIam%=7jM76M|?YUHWS4MWF2$xWuZN(HD3yRG7{j|_LMXCNLBH$;Y0o!~#AaARaQI*6MhyU9V^9NEov5X9dS8SW+r zK|COCjSS}?K&+a#jtaL$cALmmb&kG0vfG&mbcH*pt-9`=k>Tzr@FuQ3+!fhf-ns6M z>~1gqp2+TDBGVP_RfyfI#Kjz`E8JIybAM#G`y5VHX&+GEQ3(%6hI_zc=uNQABaz{% zYP@0`cr>y{Rjv9s@K{tI2Of{?ai2jw;WH@yiY1;Ti16<4RAjif80nsl>}e;^Gm$-` z+Io0bc+O`>&w1HoqwHPn$%qxxuHip3d_5tB1cB z8LkL;%yYd2j*&0B2v(ApBf~wZJU$MndKw0f@sOgwyb{?fOHGLUy<8zDAKg=F4?jgz z#(rYh`e$VSB(5_ojtuuBKzm~AiNngZnxx6f&N-7~o9y%1!(uzkXCPBzgwPb`sgPzH z{{NZ16@}sXcH!P?My4Tc;fR=DN|+kw%iGkrBODpq5n3&%3&gcBEfx;b;_h%15Lq_^ zU`3#_kUc66s}N)^pjT2~I6AhY9f4zFJ0{k6H9a<*TJ6}_a4U`q$H#WOX3obthBIQD zp|6#~j=&np?-JM=;fRukDVO1g;QhW0q*vts+1e$R*v z?-?-0)m6J%!W_zXhuIWqv!VN$F+X-DXr0CCAcp@t!`ZBJ9Hlw2%@Hc<2F>LfSF=7GmPw2)u@Sw1RF^6a-^6fvY?rfQni#H#?Fy22hAU$u`btt= zr8s;O!_~1}?WwL|Ifkb*TpJtF*OKZw#o?P6u8)n6>sguI5Q~}lt2Vqjwwt{TZ-E41 zd%GnLqcZy$zHP#&nvD`sZ;kC%(PjHE!iI;o49|{uM%t(b8x_rQyQ|4|3_IA!u(OQ` zqn&3*i)U|(?KUrFVQdSXXK#-UC!W0{Hr&pm!kw|*NvGf|vz=?<_G!)T9dg2FSdq9crtWufV ztD#MN#>Wo&*qKCObirUYLREh#wuc%lk=2){566ZR=8weIW{|Vyyd2xhp5T?(UUBSS zjqTMU8cHmRZIMU61~wl3dTg%~O+)6I@x2y@O-T~Apl81#|I6~*reR~-B5dZ3v$1IQ z2K~SRy&2n^4(P4e-cmUmi{fv`_O?gA8{4}c{a$SE5v>{DyK&fr=&(6uyea=1@}q~` z*ftNF`HXL~V#c>|$TKR=VEJ5Z&pE*787F;cd?7a6Gp-SMhEBs^85{2TdPvCOu&2E2 z_eG=kh1?raxQAMf(7f-1*gkNOA3AgMSIqrUY#({($B@@PMl5|2+b7CPOs=Uzu13D1 zYF8BVz7LVWpT_nny?jFWOya>lqt|^AYu@*TBlAT}sXqGyAE@(XY+rgAU&V%_6~B&! zDs=q@?S%OGOX&0sqVK=#zm_WX+t|MCt%lD5bFs;HvEiQbvPP(Y?_>Mk3-}?nADjd~ z#`dG@L2||aGdA20o`HBkERGGQ`qiKgi1Z}ZlW4@BoY>?Mp>GMy35nrmcnrO*jfF&F zxHh5RCI!GuK2X7r3MVIavT&VAY2D$JMCt(kibGCK>e{)}h$BIFI6bk`5<49&(X7N~ zIkC=2>6!FCJ3&hRPZ%*4+0N}iqA*@`zdQV>9ra}&dzs-l_^VQo3{vGWo;&(S(RvGYMIFNGl)QN?uZ zg2XOR;1C6p&ZlD+CUzm(Ee5B==DI3to`Bdq>U&9Imyk@;vH6M3_hbtaTR>ZNhD#H} z&7(msQ!+lf!{v!xP6kcKu1M?(&v0d8S3=Ova8+WYyowB0Crrn#M(uX3(i7Aju1oB? zMANbB6C?C`xZ;MyZtzyQ(LGGZZlcxfCYtZ&#BL_4Gu)CG?nYqVn%J#L7*fo}hIj+s z=KO#JxIHo4kUH(?7k4Cfhcn!riQNgo6hnY(fg>Bj%pi73~OM5|e=yZ+y6T{tBXFs*o1Bv05ZqA1i!+D5W?>1+MhZB3)(Rw7YM?B=w z#2$4O@?#{X_HE&Db+5;T$iqokK4U+EIph=6PIG}L6XuXlLfEGgdm<_3kWVGG@U#f` zG-Q4@v1b!@TgbbD3;DsCySftFj}?3jrGzE)fM%~JhFhUdL`e2V zVz{MA_GV(Zf@E42FRyO#R$^~C0&gewHtO2;@J?d5A|tU&LwGka+}lev%zKI9mS56# z?W}6Mw^hb%|`iu%6C-!k7wSzu8!Y4_6+4*T= z_*=$=&l3Agq#>YBd-z=O_PMZm$0ySBc?@)O{ph zzfJ(C#NQ@{`&x-LFDcmi%i@=;O8Z?S?e~e{zFQjb4~hNYaDGheN2l#iD9jz7e=5ZO zsnj(UMguHPZ1Ga$spTK~`mrZ9T%R#va%z)P>Z-4faCl0*9qwCw-+IC+so@~Q5o!MI zI(CGjNTAwJP5D%Xj!X?V)uX(s)09auN2P|F<}rkT&(WzJoi1svT7La{8r_ab?U+=f z+w|0?gHOJ2y}ZXafo^Vi?piOOMB({;_1}lqD=0U+__g1L<5D{=WrsK%pW5+h{@le+ zUz|+{Gg8X18D6Iz3p3LU;41T1_A9<>Y$$HXm_#M>4H$`1o0-~);C>SL;O_`0r*=|m zCnHl&Neu_pPEGC9R0@mI(p5Rl!Olu;mRIGB)XwlkGdz5DYPeH?d}eC6+3C;2S?-&a zjtOU{#>d%gDqK^wYc!=<8gwn6?J(w~Hph1=&PnYYFXY@5d2_BPR^HZDesTZWSz>B>!wM%;om0VenhO7`N5U~ex-j^CqB{$lBDN(AWKG*fP`K z{~#j#JU>BHU}?xMSsJ!d#Mb#Vh1Jl!hb@s4(2Ip>PsGYJFH!jAsa@_MuSo3*)rn*o zLE*|YzuBAPs?@F`1Q(GRh;s@)ygjws z9g{m!yTcop{I|e#cczB#cG~l<)cCjyrn|ms*B4B;WphUB-d%+N_oRlq91`D~+Pxy` z-Brj51$xPukpgNG{_oVRlXF@@PTRU8Jek^7`J|o0Q>ks;K>q2}a8H5!EmflrZapSE zlN#<8R^K;Q?dGaDlWc9_wbWj#w}MtkTZ73~y@+Hrv~ESWepcOAM$ z+*5?jTU3UhcT&R#Ip0m~9rwJK8vgghURB}<9TnbB4R-^?ytPU|_&~YBhpFND5Q2Op zv9~trywvc13{QNL+9xn1pPB7c3-?s*R`j_O!fk@7cKB2Y6mn(N@LyT&3ZJKjyA9us zRlCuf>>hCnMb$Zl?xl*I;M`E~^%tq({)53Yh12az7tk}kUwxJGXXOeud0w zc;*kquaJ2S&(%ZmE9CNq=jNgK6>@#UbJtM(3R&3jJTw%)LhfsLo*If@A&)gYFAc@7 zkmnknH;3X^$fAbl!=d;U@@~WPKwD z48KBVG(5A1;aA9M4bS<*@GE3a!!v&veud0yc&;9XUm=$_JU0)+uaN5-p1X$OSIEMK z=b>Tv6>?w0^VBf>3VE#Id1)Aag*?~ryg3ZNLKZbV9}dH>karuNFNfh*$fpg@kHhdQ zEAEBAfg1&_<}AJ?(tl-8#Xtv+>V)y&}dtgzdek=YC% zolnS&uoJ-NL?L!!))r=FHZ!BEv1!Su%etgh6+St$lRd{NnVsTQJ(X2A>7>a!B@3;^ zL;*oD%O#+j2c4$kSU8-X+3B8nR%Wx9eRPI1*co*wvoo6w6k+iV1KgRy;v1yL*_q+a z%sRtORlA9<50a8NbJ#}BY)+k6s?#}{;fOj{AcX6AtiiKzerD%;3tW)d1zy&LYMk?- z_}t9qdepqkF041sJR0X>L9mOV#wF~kX81b7d~cmg>IK?-Zvp~oodua);!SXAX1E0& z1%Pt_a9L)TdEDj9JN~74uJGo$LW!GGt#JzJccp56Wi~2Yg_VQo-w<^KQ@LxrDcAO< zTwB$?HZ$BcG}v{SU8fA^HX3Yg5#jpGu6LT>kl77h{Tnm8vEE=eWMS>z20PaqY;85v zO_|-~nQqSPW^brlGP}id-NcCA_2DiJmtL zcV%{$6Z~!z!w&8qwZ&b~_ukCz^{D%pkks4aKHB1b(c^w7`Jig48a>4PFAEQ6_OPda zB(p~x)T09RFrXgG>@kmeJhMmZpdJU*6M|q*0P9J14zuu7W)EiJnauD!L%wJAt%cHa znc-(K^*n#In0rAns_BcF;a+I8@RN}JrHtY0B@w<@m%W@B?s-aiB~w3sMTyn3pYvP< z!ZNS2T6ci2vCPfvRYhg>MeOUD;RO1P%-#^-!Z7Pibi4)Nx3uWAw;V7F+X66w0Dijx z_?^sfZ+n^4=PmGg7lpBW;y5%SPdWncW%i!8-TRrnkCjko_%O2%fz=j1%IqUGHNk9i zeO$y(44=41s=ZHD^-q-qShUP%m`ORT&xOAj>5I(1@Q^Pv!+lPrzRK(?Rf|HfKdkHBb{(mEk1yNt4roT%W;mb| z%65X_uOqeciDf&{qfaW^Ngh43Y%_`0boHb%=A$Q;!+Ml4L;mCCx1p4=URc+){_Fa} z+SUo%dF5%FDP^1D5RWL^5oJ+wYT0m;-NtEhS?zZuhGL3^K?o1qG2>h8UF+nso$Q4> z*P!n^rEI4-v{TF4&f>51xu=)ybPt_XHk=52h6sFy>P6&s0=%7wd3n_?*CZ1@gb_|H zvq@OC*>3!HX1TsWepcCVXJQ+0wu01*(mtF6h837nTjT*qI8(1^V2w&2{MW$~Mm%;G(i!R0d^o z5PxymaPyp0!~^4!vf)(48d)VQ=9g{0!&p$Z1rFn~vRziE<95RH^0MI;I22L<<%+W5 z9ExadAJcEIEc4?M<*Kq>Sq|uP%b~v-7Vq;}=wCC}CS6^&tG&Ey%63gTKa{OVh1j(Y zzrV!8b>+I;xxQ?;>pTYW&>vHkvf=uxiTX={e-j_Bz`wa{H>&|}DoZhWOIZqh{;I)m zE!P$Jw-HBz?ywM}#Ih}<(QYr>?Oy3Su*_0^5AO>c%va0ys<+G{_n^do zjh3_5$`ixuWqX~d&hSRraEpNXX4&2>hh+;T{<7YP?>JA;soyOdZrM8hVDk6M_MUU{ z`(=9{qA7*|SK=2&EFY-dm&L54Y#)^ELz?{~jGCRkAH%h3b`S3gpLies#GBnqtQP~% ze_A%&J9S=E!+l;h+|q6PMcHs3qGox=x#P>Sed+jpRkp7@up!7DdZtx7$~jVVwKCsGQ|XqLVD=|&5o)VZkaj}A=%Lt!}TViI~-Fn zTtPBv^9QPrOt08jV$XmxgW z#m@HTnZsYgI>I>>JIABWt=ODO(f;RFYT-OVu=Bv+d=)Q&e?i6YUr-qpF09yvq$Qle zg~W3!HrI>0$UQX9#g$@}cuA#LCC;zd{7P6*u?1e(r4_r>@wiNQEC7$oD|Wd@T~V>i z>UdlM=qmwWSAxdX6$99nB)z7hx#ZPq6U{EK@x~z#;eKs}a1A`yRSb8nNBx|PtO6=_ zy+_?pu^TE&uM%&pXq9-Qr==R?zNun2Rq_?p#urs+yLIBy7KOjs&L>S=g#15sFZ0$T zqq1LI3Aa?d;cs!sH&^Uts;MXfV3pe{hC3CaF09x>asSQAlF^vno{;vNv@P6TvD=+b z=2pTT3JP~t49}g=<1S&VN!{HQySt)6?;eHNJzmURPMCYW5vkgJ6~o>#>SG=B@g8#U59F z5AO<3D33kiMUkIc|H2-wa02ZYVRzOr9`a zhbWYUKH9xpv6nG{WtgehD?sTCuL_F2N{wHu*lQ%yX!m->UiV~gRO}5}xHG(2G2E+_ zuJD$U@zEXLuGrgT&}jEg#oqA@?^f(xNZJ|Rs~9QYBg6X@M!WZE(GQiLpziQd#XhQN zwEMVXgnkSoe^Rkeyj?zZ4;t{ylRJ6 z#p+Y4Hl?b;;|MI@t5m-&Osz7^O|62-Vb#!_S&N3bBdh!}%uTB@%uVBD!cmwIV-2Wb z?kMc&k5*ngy4oF%soF8sP*di<-eGGR=T53}tW6e&Rj1s{s?GHBkFVPCe){3$s+~-k z8t0hDcZXv=f{u1v)sFL|GpaVjQ9XgpfdbVNIgTMjj|Wi=bjPY-KKd4Yo>F>A0@+Tf z8m{jWCO-|6#if$apH8nDuAmxodTUlEn^m=0j=>pKJEN-JF}rHG0yeR|g^>8ns^QLX zd*-5T&Z-)&c}eq~UA42RGXc`o6ifYcs)l1X=e(+&rz+{IBb;BAWIo@`hl?$}3#x`g zvv6Tm()&U$h-3)uxm7+TcIQ2Q%UDdys;;V$wRLcsTus$KFgLu~5`VLn#! z)Dr~h;Y&u}uUCxb#X4h$MIjO|SEd6|UG4N-M8F{!1;{E{JXTl-!(*87 za(3c7EbFGkG8m?Rxp}K#&5}9TteBcl_e`rO0V)KJJSuuq+f+p{$gR?WO(S5oZx5qw z6^FKmjkf1F+PAmu?TLy5L>-)H8Qm5p+C+d(aa*I~bl^=W&5#|fz`JQ|p0owbT~Bmd ztkI!rdxSnVI-C}(=Zv;J*#3>NN`!thW7|WdKH2j#LYxvyf3k-f7vQJ3Q4onvb`QA} z1BF)6GH7zduaq5rW(1^0s{#BJh;TYDA^_&Pv~dgp`+wYds88;a6+V(xCt?^VWFRj^ z2UhOIkwiCi$LPH?JgXpkHWEVrS`##wZkqnQEZhOC6gRl_x|_Na`+w(Q(+ZsEI&ShV zBr$V$B;CMW0dB=EI=>pxfHGAl0h1ie&fjv2|F>l@u9R+euC}aOniH?!!o-|lH!=4? zWjQU)--|d6{Z@p;Mg1iI+wxm8XR})BlBG$a7K8K;98h784xo=B4nu;6&VdHENLM*- zk*?w~GyjZesXsoAkQbjsp&w;@DE|lYTa7aMg}y#-=vzqfrm$Q_#b_@#zZbyQBExu| z276rxF|p+r{a$g3z9~C=VvCTl9FpWEH@$Zgc#&u+CKFu75I2bzTX5GL{e zS7WEp03;z9hV(yqnQlj~GBKhj3S#$Qk*ISpKSde#^fevVUJ8rJvZ(*J+DSD6j_}Z7 zGP4Jcm#lIQ*U?nf_y`%%s~S^djOup+!g7kowjOtccO~KhF)cQns$CW#`OP&1P1ZKzA&#p+5sNz0FQMud#B^lO`=m6(<9pGJIsgVJ57rPEZwKjd$EW= zRY<~&g;e46?CFjJM(by|-8QD_vQ%%AnfjSfgrr0;M>$Kz>WVm9#^^LyA=KSq9cXRg z99gInUW^Lo%1~Xx9xHXmf%Am9q`u2o_WxjUNA{oF&jHvfp5MiGQN*sc zt0I13zbFLNu3QkY3+s1wMDUHlXZ?Y>4C{LxP%O^GTWc8Xm89asZMfj%7)C>s5jMgV zfhZh_+rf4yY=O56gURgYE`DjhRKJ5lh$3vElzBJFq1{{z?QXj(~T-`H=|R(sZkkIbd_>x2;+;6 za1h61$152fVOYD)&YJK179FgUj@a488QL!IUmnH!Xc(F^b}VBpGbbQFY=R*45!mhm z?7_xK+d5eK5r=H8kEbCgIw!i+U-?mw;>0aA{i~+Uf0s)2@7`wrsCSh^Xq3NpbJF$@ z`=3tTN1$qQ;Fc_ebcG(DGW57y{)hNudHYAG*z#e8%>4T>oxc@{4%hixq7I8N3^i`< z5IU~;nWCe&#kbEYkBAKC3lyI)Pt}QB`v>U}56fyTd8Cf!3X^F%nd`j=4g0e7rQ}h% z;()**fk4vvQu1gW-PKa^7(Y$OQt~)I-+LVOK3=D8i>2fY9XVC96CzICYAJc5PNs4k zlhgM~#)qz9&>alElss9-RF&ZrolcdQK2>K_IakZg2s(^*deos~xnwz&oM-sCT$Ylv zbyAn3xlHgc)iD7 z&DEEj*JP5fa5!Sy96p0FAKp;e$-uPV-7z`@vv)3-$c^5QZ-09#K0M_jJsubu%tm9xSX5$9mld#=>kS24#` zI`gWPq zceqK1S=p5!Z{~tC(K_;u$h4_qcNEj3J9S`HrQfQvuB!FjI+a?iBNMgA%^m@wx9EJV zlHR5>utIcUWH=DLUFTpy^H$K*GV*4X%SYW*kwTWx>K+|`HQ(NG&c0ViU>os}>OR&> z#kU^?aRuZ3Iu5I%AJEZP3FHSO!#PwUmk|0Pzw4to9_!#A_Vco?y78uZM5krzYsb82 zsDM7Ev#7E=8z@V#s+p2 zVqZN2%dMPRYP&{$v&#Q^u}U?RS?z7hHAUt%j4f_m5$csqcE@>{JBVr_<(i=7LuR@i zBx|XikwwF`j2yvDEgQD?-r$sPsGC|w=r*Kn`GNblu@M{bHt` zZwun+91Qu2(^$W02gCaowsnz&nl)LIIYCwt*_qlGr*yYA&d)U$nD@25%HGdb;ZCP* z3MJS!0vXmejef?#M4w+FO15e3!|2;erTSa5H0}f7^a04LgtJk3Oof}N?kdox ze^}9}zG7Y)sk@H~&dhAZj<7l%fl|0DNX4(oOnS{RVJ!kFY;9YMA#iQ_OpOWXTKSOf ze8|Dfs8So+&a_mKYqFhMV|KNo4eNm5eFTK7d@RxBJ$-CFk-%?7>YZV2U`YoPto3a} z#d)PSvOY|*wk>8%+X|iSZF}2T@!JZI;l^2UzH%zPEtO^#Mx{4nez;j%U=CJPS$(ET zrB|oYeW>(iVZ}lLQ&KDH4ky=y)s5P>EWS!YSQk237dJJPiW47PsnQnA47jCGk;nig z=CDe;s>QZyM_{5FDjI@wmhE)fQogP(=^Cgc%kZ_K-)^O^Wo;Q-R+m>f8r)h{ELE0a zfLo_HMzCe^69dpjz?_wq+T~HyD&`yjbJ|kOX=2U+@XP?QTvo6S?5%<-meDB9#dy~& zl;NqOmaahRXZ;E$Y!(x?SWD64n?)VisJO2Sl}2-GmDcV9g<)GU4E#zBF=|i~Op*-E zR9<39z#Me|7^f|@O`@_8RzK|7drY7Qih5RpE70Z8_lmAKDMVl$BEKZ9IdVk~E6w%M zXcix_F*x58Mg0YB;Qv}j@UZyjVqZx5@2 zdP~v6T0|x)pPw|(`=?(e)t|jGmm8aNF;tUq7bI$}DOo9hu%xTe*xKKk%kXOO3}^0J zmxKHRi?*{U6Ygr9U${idn?{KqQZzxc7MQYL?Wb03sXZ1&gOq$(E3I29fp(;yX0RXJ zoew@3-Jk#N4EpsTA)~hJ+oj9bK&crNYaz=Fp$To1`Z&dmphcysf-M5t-&*xEfUV&I z_J9U#Bt+pA?21*4ja8T#*aLvwKd^s+#T(FDLgIZ&w)TsuPZiqew-3`x6onAKrPin3 zkV~30=Q5^6Q8ZZf91K|=fPxT2$cRN98E=KfAS>#(c7f#phdhw}HV{e|txJWayw}BX zV9Et?-Xe$yZzN{|wJ2>>@80T`z5T;wcokHAO6XD><|)2(6OVUW7)RXQjL4>&^dk^f zQ*Y6}1o8k%EF)==(DKeDu(WgYgGscmYPdc`Cksnq!O^X2pvp28RO8lF8>&Rsr382q za0q?#EUX98jP{wWiR4|o2&%;_Q}awB#t(sVcbcHq40h-ccN-eVel$P$c^Wzd{H!$n zp`4hrKU;-)+}_`tegJLBc601pOcSdOL{x7Bb@oBUn7phFvSqu%x)i^zi$OXzoFQ#Q zOITH`)?hP+eA?8Qz;WlE!0B$i0$fv@R5Qh3Uw6e*D3 zy7psr8)mDEZOZy$5QP5lc1!J7QIpz|hE?m)Z5?lx_ddT!2`<=7c$N`vkf(JGbsgp{ zRDwM48RH}C{aAx%pO)G&Su{#8#}urr0qNWqK6w_4hqYibibu~Na2oK}YF(2Ba!G=k z#lJ#X{ClW`9^3^)g=%7i*81y^!tppEGT zfg?k1!xdc+E<>eqeUE;54e#rN&iY<0?i^ILP$7A> zHX@j6Z$kVg9?u?v;y1I+JYFg!s=Wo(-n@fJ(D$U+g$3R&21yi zMN77gW~SS!)|w3V)|x332yX53F*HHUTSPBEN%XIOxyh%cwt6v0l?(nxP_&MqN;+N+ z$8!7=dD>Fz-x#Q7uHRbDXER9mTPmcvrS?u7ttFNg1B>Nj=4sIIu@zNAx|jk{<2hMZ z&g$W?ZtFVYTrNUsT?^KAc}o{l>SDZJS)&=V3tKsqeKbq+he}J0;QjJRqa~A}PTCqI z@K6&_UGxFI@yQq>3CJQ%pwB$#Jxt2(4Kp6F)Ffjr#IM{UC(CS{V~s$7uWn zhR=)`LlrTQFaD!vH{|FFMScl>%4RgBg)}o`<$ylO|4O%0Ol%Q!G>!nJ076dH=YKBt z;4{;9vE*!d$uyv(13bMWX^A-*^U5W~Q*{Y3W-+%HsE@c#f}^r% zOOaq}SXNUG1b`H@+CD>Y=B1tKV*uD$n{>8GXV@|xZd-y`k$N*yb0ux)u$9Ia6a|{v_tD~Z85<~asZiZcOKHoAhC7RiY&kT+wgmtN zQq(fKDQO@iTLuaZ4*eP5w}MH;Cz=4K;8Nl43=gM`w<^YXH64c&VJR;jB}3TCPXTU~ zm(?1X5MRDtrxiHQ?A^aH;MRv*^Q~;;5UomnX@j${A&P)fjmgO5!=_Zn!Nk=(85359 zNbH^x-(-!Q@+LL42HKS-h->r3KmG8R_F(vW$cx4zz_RY00K=|o*11$y7mxSV4*IZP-$~GmX|0D{jE@WKp!#@@!G0_1OmbV?bY?-#PrQu5X0bn%qCMmaRUb zv_(>~)#*nKUu&;#aIeqmKJVu1F|ukQO&5;vu4${ct|u~T&?*QrDbU7+)S>2U(|(!( zBXyYiQfbKBUmW$c0Ucoq)M(BiF&P#a(oyHQI`;WpTkE%7%{yDKXp306se`l{G>n3rVt?PYRLjVbfUm@+v&7XzvoPayF!+Ifa#Y&+vQChpKK^A75i zgmRl(D@Qh_$6`m{Yc73RkriBw4*JoFY3F5ZqRU`DV5XWAEy; zdLms1eR?bvif?F#Y_HGc9|}C<0|Z~@RY7~f`D^lN2SYZNP} zKa@MFbORijzjO?_2JT8n>?+;#R!8h=-StLWU*p%nQS`OC`3+jENPptEqj&1-bPb%E z`FdRjrxv^+)?IMD&3t35d(4L`6{PU%;gsr@n5*IH1>LIq;MC5y#VoaM100LTg|RMn zYmyYb+2P(EbHQ6Z#~r%jO*!t2joWzG*eAzbF*mublazF6)RD>DaF3&waIQiZg@@%~ zpAEU$EqqP$sS0oo9eTyy4$W}d7Vgu1Z*){xtSqxDbs?`PcS1cDhx=&*&1hcL#cAOc zzekPDBd%M!U-yl1YfnAF8@dB6ysit>auU22>q<2?qZjGEI4)7^5Qgws&< zusj0IC2zXsO%;DQ#yCa1b~tN=g5HnBTo5NpJ}RpfDy4zq(2=MOR>*r6 zmb$`DjEu{7u+-m?acZZ`R;cNEGkvsWwtOvo7~6+2vy%^ErY9RRiT;{P>(suj8))4v zSiTN*lJp|7o$XAX709wSS+?VvI~%QrW#w6K{Po+yn0UC2fr6ujF;)gjfR#Z#0c?nY zfutgs>#TcG=0W_3BHPF) z(Ou94+XC*2ZTBY!wi<)|K=+b<#0B2%T-goeg9X`hViH-;iBW;){A=D*WmUEHxOV$% zyRPn50bJef>%Bwl5Y5)PsypWbZ43x##Y4d6;LzD?UjL5*pa|@y12zj$qCn<}w&FHt@{y%_SH(^R95zKF$M&$?(7q5#H##ytNOP34+@DN8Q-T^?A(c zJ+F9m2Q@6KP00@;4?*j@VV$Rk+wd?o%D3nhKb!Z8A4!^n8jv;U93`e_}LV_ilj2P?~R?Kf`k7q%MBC!#j5+FY$q1dC|46mh-Lp}A6zUTr=vLeybkhJpLZn^{1t zx!gzvl~4xExC3`e#MXx6wMujPFL<4<+t`=j zwQ_S~{t8}P&{&i<%WXgY*^Ado#k7{mh_GBy0GpSsgB_e##}rm0wB}$AHq~T0!VR1# ze=!^RwiFC25*F)Rvc7SCr_aU*DQ_fNHW53R$amx3$br51swea$TncHsv~DbG5kc*2 zn2WT9dAb5!#vyxR8`2@$kil4ojK&m1Mj}WC>^?{{AFC8MJ9Y#y2C3%NDAq>e+ zma^=VnDshHY))xhD4E~ycn;{r^8%j&OipZaGNQCwVM3A)A5r4_e{@YH9rCb5y%m#6 zLF9x$!c~>LiA0}l9*_z39&X^p(B$$+JpmIFf@rxbWn!WbH!)#Bd2-0|Q-c)5SEz$z zS$+y%pZcw)lL2v!zo9~(yw-192LxAueufH)3qdJ&^3vtjO3khRLeB4F>RiY0d*%TR z3|sys)e#BTX3q7#ac5-v*_~o1+b^)k9fqoU7>J>hnh~K`-ZN~|+^@*Z^6f6!a%*I8 zOO@75!#%Pn2`lFhJ0be^7Na!x$(lq}zh5RKRQ+r!eIL#9fGkORGd1^S5<^VYC7yF- z{J}Ey313;U^pq5(4Q|pHgmm64f85K1&3tj@yF}Q7$PUCxxfz>h(7%;SU)c|PQE9bV zRL@pxZc@JJU;c~L@rQxHw8Zp`3;L45fZ(~LEy9Po1)QG29$39V)=W!?1>`MAS`Z7( zE1;Mn-dXAuzy)_Lj?JV2IE#C|W7`F5s@9EUYPC2XQTk<=6QPZS`_KKC2MsX4;w}Sa z!5{5&Ma$J+BzP~WKddWHjaMf&|XX2YO2pR;0eq4Tm*?)bd zEmA+d1nKACQlDa=>IEt0cFwYF%8F%CctgTh>o?~w#lJ;e7e%%x3c8GaRj=zR>S?b< z*y}6X>$2ttkLCv3H&?yJuc^jw=uC^P+8*9?3;*WP#W{z6Pwv)9Z%6b3NcBe4y1tGB zus!%LB2BR0rg(z1ox7x%hDrhU_XX1ZORCEyhofaEw|Ox$xIwQ)(Ec~j;+xmPd)TET zbAKhlVlauYb@;zEBSVj=zEcJg8cH(C~U zcL?};T)+Z1fx0Fv>oYN`>ER~-!ZK%<8n-EPl`?wJAz`Q?@OaY+HhZt$iJi?}Tv7!| z_l2biI_^<4RbNhc&{S($-_iA>AF^q(zATb-q61l>Df>D)&9M#VIXZNVXbTPnjVz9I zfYZlRe~VgpKjs=~*+qRC0qs)~e6EKBNbo5M)~tmMyu=Oov@IzSEu#&kNw&oLGo7Gw z7bsTEqrVVF`T`)wk4m0;9lS+y;s0fUzbF4v$v4n^5hZ1-t;Sx(CSj!|I;&Syec-`W zU+EkNADBXMv9!)|6jRlVVPak9!j!#Gt-rs~`3`a9w||K7+=?zNy0l=^KR|j3iIJ9YA z6zXtgMrT}K-wZ%a&T5ger6JYbQBuO~(?Pf2W&iWX?)!82pK5GKk( zLzBaf;OR}tjA&Bj&{*nYX0RNLVQ({Ls?74^|1~!!RiBQ2O+HIzlFS358snV&>|8O& za_t67bUzaSw~s-iJqEkSB7&8-7U5cL>SzFK&0TCA+r>BFwC$#5+>FLUvgVLB*I-|= z&G>2V+uRu9y|it34`A~GDC>4#!UObIwz>TZ0u>P~)P3bn1nYQ}wufc5M<KJ$SyBG9?x;B6OeLRg>d@4XjjC%8z=0*SroA4&&Lo8jpcU z5rKN3c$~09hZ2NCr>$U}ow69x7Q1j*89@b%9l&7+;jnUn1N~@$jN?nJpj0|ns4h)$ zY3>*-;V4vkmw8SA>@&g|MM)?sTxUT^hu9j%J}6UK!97fB1)av6%wX6d zy+n_nmSg;}Nu4Ox*3urI5E*J~E5lA8vXc-Q>WCoF7H}{C6i#;(%DoFnM*%A$X8+E2 zt}xIZ&J-`{@Q9)3a3l~`FXAY)14l*00SF;dXceHy)X3K5yhJAx$Mv*3syX$n$ktb$ zHgIVZE-3Ayt!RU+cYW%mW0?{*D8NtGaa(C2j`7mbOKiXa3eH#+(KB>TqJD6K(vS1E zt|8=fknu!7(!BME9OgV_4&U+f-hukYZvsX&MsqEf@bju49(l?G;xP;;@A z)81{x#azB&7m)pJN$Ow~mD)TanWlkAa2O?kQw^^5*S0&Rt@TplmfEy9UT#t* z-D%wNYmsCwecU%}Wl2y!*0B7DrXKCDj%YfR9=N=%_&@4|1wIY=971 z-a(!n{aRuJG*$rIKn!;pbLAE0%0?n!zNrn{L3kkkQpRzzbl_Y~91=VgCqR-njn83z zjed-$?2}qkhmXRPzob)jpuPglDeaIC(Rf)c??+X~la9gt$CiYFGO5R0a<3B|08)p)SJDPeU?YE}x!S zxG4#DdgyFI_twJ>zToG%$aY4WsCCQY8B}RzQ0G#MXjXAkJ270Ee`FfCMxKq;{K5e5 zaEJc;bXiD_HpQis&}XQ{YLClr{LxwhE|wOFHS=614)cSo^JZ$=UC#20_~MfPH2)WM z%)-bPB8ob7?SDjp-2G37cpK9vUSXxg8rS)c=qdhvySQ|Cac%xmA;09vd(69@5f#WZ zsa&L`oR&QA>wPj%xdBvep>SsPel`BSJC^GIdOiDgX)5cfZzuKLq&|wLSA_Xdw9FS# z4YtD2$ahe6>oU67vze~u2G6mndbU=WCBse^1}WKqJmFW|$?D+ZrP5ujbTi|y7Z*Y4 z>5SH`ii_O52kb1(Osbar@hJIO^8<~G&0_}_H{59Hu zCE4fN=5unOHvK79Q?V1bY|f!U-cdP{rzMPA$xcjadJ1Atj$ECkIe87GWRhdZ)4@w9 zJcFWqXX=F%-Z;^_yYXf9Cu9D;xz~;P0)I`})%>O2XSK19PMePp{yv z^d$7jk-WeHd!g65Mvoq=m9F*vzMS52=t*6C_oNr|DvQR_>)_k#^(KqxTfE95;5Yg+ z%6fa{W`B-FVLZmd);?G7@yp9BLg~8XI$lAr9=&^Tj@~*rIbEt@PvNfkB;2OwQh14_ zqyGGI)D~_}c(Vl>ozh5MD($0pTfqE|g!_#AnV84$`4cH51k9Q`lpnKuthZqD^;P;^ zgt7;u$lB7d_AMTEA>W$Jj!#Lcb*}_=g4~0yk;TJ3;E*pL-c7RnP)G1yJp*IE=Tu(8 z>o1m!4EO7~7XWqWnU|{)JseGwaT9E!CterF%>MQ#qJQsD4eS5d@H9+L5xskI3$ds8Z%GJ({yXehvpog9ORp5ofvOWY^gM}=%qG;dDi6UX zr{S=IXAes+VXHC}XPkrP*_?O2K1@k@kK3leen;p@5of=#4?he}Q}wJ!ogGU^%i?C2 zg8@2KKzmuDKdTS$7_A41saJpWum@wQx@Y*i_m#irE06Re)06D)S-x_Oea?+#C8=r6 zkWpGPkZDL*pVQ9^0; zdS-s`QqseFF+2)Wd>pD5Vt7sF3-&|&iI}-;mA079c9CYT)*&szLvvs7n5^|lAw2ss z{ppDs7h?A?;GwJ0BBp`p5anZaf$MR7|KSl=#nxUySP*#XFD+QCGJfremf*-DXu?7oH}aB3voF@LwNPku7sZQUzkkJhfI{i8$c4Oqn= zI@Q91W|*#Z2oTn%A-1L=j)}tGGrm^gYa@OAS1-i=1RhM_p5ec0C<)*tRwKtM^Ye5% zE`#z#N}mHYRb{7?Bj3m`7BcU|`Pj zrgPkCMFJ+{lch-fCcC&y2=}^9T{ApReQAD)$0*B~`uiP<0a&te1~~n3&+bD0nr_(o-&X#p2ig;m+DSoF8f55YMI1__D|@!>sP$ zVhfMOrT3G|(7dUL7}AXoWo$*0hgS3B=q?dV=jy+#&0c+lsi zgm!(IxV$F`>pfm9ffW^FJXPnOPFkxFpz@TUCzPp(9U-&OcUCB{G9pSFxI^~ zVO~E0ya#)Sx{vC6(!{>t)S7|Q%uITd@*w~wgUL)szAF&=-|kE1`#EaDOEA%SRr zvBjgluh?^6$v2Z8qi1-RdfcB_?!g4)3EeTp=Ak#-lO7D%r*zbujUo)MBA!;xt0Rj& zAizGuoe5=i!3ggsPcr1plMSNYs4!PZb1%I)Ip05)2Wtm|+~u?wUZ zv~gtX_g~0Z@KYwTLZ$U+c&1k-)>(Er}4VV66lMz=b3@D7EVu@f>ZW8GFXKir>B7zyG~8R zKk2f|uFItDU2PIAnH0Z=WMa}gEhXtJy`l9UKzT)rw-Nw1tNwiy->38K&rAv8EJ3V^ zW-mjt4@4^az&jT2g8h`tDc;`Vd9Z!MhuWJ36%wt(TbrKrBTxDfM>tMm92=v}myeYO zdTt0Uck*W5P~*rasEdllCcd4x$z6{ltVXDXzV$m)O`b;d-tOZA{oHBT?7@-;NEQ5i%Qq%#Jng+xc3(y#8wRH{Q#? z_5BmL_PeM!$oIWAO{B8;L3<^jxBhp?qW-XGxs zc1F1Ws>u0MJ*Rp-{!K~1i>V-|b0$mk9b@G7V$+`3hO_0uGi!cN)+GFy4X^1%zY!?X zUrEsI?-G8YlNlrF-n&w@UtsrTBRjM+v#b4L4EBhO<%eswwrlv6Bl;_m`3PN;C7Mpv z1zKXSBW2dCvHVxzmw6O+(|ArQKupmsRzw^ThhJs-`%6Z(-Fj)dYw_({@OP`K_t0l1 z1b^gEOZRD*#w9i_rq}7^K^r+*2GAq(e~j)mf#wDFga-`C>uRg%m~6TtO}7V87wn+1 zf3E4NYW5hJsxz!Nk{quK`iMK8I2{3F)l*nOQzgHu51_m8|1VYR6Ln>uYK<-QNnUHW zbY>Lq6E@>+`#5jT+p3{4e#UZ|>mLOOJ7~{_$=oc5 z>Q>McdU}jr__R1|OIM5iO~SmU1B z^&N7Wss4+)54+A(|AsHvw5HWx_RX}4`g407_Lu!fJiC8F%vThHx?8|B=xN3Lg|9Ot z)Z#Cx1;}aq4+=GXH9xEHSGpA2oWTOUg*yK+9Z!bWt_ty-Pw#NJ>7-kdVkt_K$*(C| zvq_@Arlly$_+>MNVS0NRw*8n}uIM(;7XmF7frJM54A2=bYyB^Qp$=*bmUj#4X5SDJ z`}4Jb4h+9v_mKdg*#(Fe+@08PjexKF3pIX*3peV_2P#~2!+c_Dbm07Xxz z#roUX?kl$NIS}1ip(Uzpi!Y0xulitcZPIV*-f6Obm3Zz~A=`nBY#Cg8FDx!C`CFI@ zJeLznKy;ZHFK8ULz+Lgd!pPke>+k&9f?JvToUifjX*c+Mi-8HfTo8Pm-={aZwUs+t zHL!a1zpm8*25^vtPQEClIbGtSpyxQhgKm6RP;@BIa9o)DFWIJC5+{LWd=E}?@h88Q zli$}x-L`Q+l>j20!wcjSIE&@W4|2Zz!19GCcbd|kjQpX+KZvD&ugkMZ`a|NmS;epE zvL!o4DK}s&Z`TayM}nQxtw0wu0Rs2rvBB{V;?5;;=O2B@7?FMq1j07#H3f`cto=my zY3J8y1N@+zAN#Znh}0$C%|4fw^b0$~eIMpAsnqLE319c?Z2wjnl$TY+Klu#e&zg5~ zeT!eIeK#=6Tpzm#lpYQ~dl9fHNO;htn_$ks{ZNq8&!1|r;f?UGx=33>`8Rtg>)&x( zCIQZLnhQ4U4BNHKwab>}m&Nkk0Nmo|Yd_WfsQ?vF-VY0^h;w0ZiT2NObp_)E!sWw( z&Lv+q%iQe}_`G)YM%%B~#Pb0>!v)I#*k8~k*;M6sS>Jj&FfWVj`GDI~SZwJli4EXz zsg>|YbsM)-Xul)EnlrunmB73b=+0l-FvrEe>Hzy|v$h4Z(tis%v>8}{AL)NPsLk>U zS6Mj}Lnx1ru^h``q=2b-U@n@E2h6~ALpL1%I4_5b72VVAnG;;ptp*Ut=3l_!03`EC zdrh~5@hRQbEouCoF6ZWo?# z-n4*M0agJQ+4TTwvN%~e==;x>w9$s5eW}J`-el!A1!)sSWt6Iq)a(w^>r+96ExCP) zm=G=dR_9MWuZ@28+Jq$5*4NLpCE3St7!1g2!@UlOdbjHR501UvBDuwZTO7E>fmF%pj;AWsN4JE?sowy*uEiA9imx?&bRQtI3C);G^|PB6 z8MX_N>|lt20>v6I&8m{oCXu z<1)(Wc30dHio4wvN1ZTCq*7&IO{IdAw6w>d<bK^TwBXGrxGj$j zVuM;CD^zr(c7%xqa|1*#(`c^}V_{ynYWwT^6m8A?xLNy=`iQpVN2HfXk_>K4)R-)Q zZxb!kh$Gg{kAef{Rik!Z733H^Yura>h1}_R@)$#(DH-dEZhc@JY!~&BO(LdZQc;M| zP|6&4AV5Li%6)rOsNG?U8&h`y%4iN$&q`+}D~BAfMv!Q!dR*OmvT`;@iB0RqisR+! z@^od17F31!8WoAP9$Np#oyv_l4r%@B3HskClOWJ@fmZ@OiAd33nt)@hXWi8-!NUwj z5o6YKbStsLg62|m36FwQ6*4@4X>Mgt<`yH5sU?~bY{FN|EHq}5Su0%d&ym)iZ9w?Y zmyn{g$o5lpP&h}9!n8WvJY4&bI{|RRThDn8{^imjI}*{h(`*2sZO@Ryhz?IX|Csz^ zg?~c+iNcRHXsmY^{=@PgF8oL3KU(;Y$$zZy8~N>FZCBoL`HvUz_sD-w;Xfh&iNZf8 z|6JieCI6|y|FHZI7yd`(f3)ype1>jQs_Va-#yfVKkqiF`e=Irur@!8UmE3jLu@J`I zR6~-Xh|)6yzpq;Og+Gu#DEwrvN)1Y>j6ANW3q2*H6%lpZMDC^`uU`y=)hk zR(wS|=W;`%SVbOgWuZoSHhUBYJw+AJV+3xWN3&!A+1#T}_I!ucrQC%UKsz_LU9GN{cRbre!tN@_11n$obonnNR462O7)>W#q zwvRd5zqzC2VPc^2)jOuVvNts~IdqoRj?ro72A@j-dNS2{FaA$)w4N5vae znmnbY%pXH3%SuW9p6`t-SjRz%oQD%x_ry?$b=$|d3+Cw@Lqr4Tn+7h=JAivc4{zKB z^Bj&JBE?x9@=nTaALA~VC%*>?J$O*hoB!;Ix6Hda-5_+pAwpnI{;(Xf>=}+9B(jcS z4p_H+?BUSd{SQ2N>Y>wT9{!d3`T576Sa_;-*BuA21u*rFV-wYp%9{_q<*jSocw=+L z>>HgtbojPA$8O($&+#Ki$IEZ}gXE`b@#oqk3RPHv-7`t@$%JozvsR0`}OyK z;5WiXGg`gYdS<NXcsi{t zBYY_~X|J(nR$J}J#EEIPlBkiz$<82VBZ(VPntBVOh_+j4mU_PywtJDu;@Gsqp-mM!{!^KrB{u$R=a8XDk-8qd#rj6G_ojLT97KK*f(6lK>wPkh~@3|xJTx3 zqtQ#eD_KYfbbYK5Z_#h&D$eAJmcr90qoQfn z>bl`2mj?ys8hSZza3PyPnb#B4#5UiKAbD{(b*&_rKZr(sk*Ehm&x{wF^P7 z^j23<2RD`$0?%8_P}6WjR>1|;stBA9yS9~4mu|Ak_-Y)7O}f_0>@Zcl6~Z>^)!dPg zHc~Jk2Vc%^O?}j5rVfRXWicgRHL&^q}25-u}4j*s8-#7KCF;c|6fxfJjr6Tsf zcd7jU%Rm2e`~R-?;mXXl#!RJ@O*6yT zIn&kyat6uZ)Iy{r5!Q~Lw5fh@jQNx;)4;dZV2Wqg`Q<^A=c+X+Pc;yVwQyV z@3b7J_eAT%#r6{D4AJ&abVhVn$iQd_Pg;y-1)*{??qO+drdML#V9k~~9^() -> ImportObject<&'a str, &'b str> { "DYNAMICTOP_PTR", ImportValue::Global(dynamictop_ptr(STATIC_BUMP) as _), ); + import_object.set( + "global", + "Infinity", + ImportValue::Global(std::f64::INFINITY.to_bits() as _), + ); + import_object.set( + "global", + "NaN", + ImportValue::Global(std::f64::NAN.to_bits() as _), + ); import_object.set("env", "tableBase", ImportValue::Global(0)); // Print functions import_object.set("env", "printf", ImportValue::Func(io::printf as _)); From 93f8cdfc81cd3546462abf6b657742d982cb9cf6 Mon Sep 17 00:00:00 2001 From: Lachlan Sneff Date: Mon, 17 Dec 2018 21:30:27 -0500 Subject: [PATCH 5/5] Update cranelift to 0.26.0. (#64) * Initial additional modules * Update to cranelift 0.26.0 * Fixed formatting --- Cargo.lock | 69 ++++++++++------ Cargo.toml | 16 ++-- src/webassembly/instance.rs | 14 ++-- src/webassembly/mod.rs | 4 +- src/webassembly/module.rs | 33 ++++---- src/webassembly/vmcontext.rs | 151 +++++++++++++++++++++++++++++++++++ src/webassembly/vmoffsets.rs | 9 +++ 7 files changed, 238 insertions(+), 58 deletions(-) create mode 100644 src/webassembly/vmcontext.rs create mode 100644 src/webassembly/vmoffsets.rs diff --git a/Cargo.lock b/Cargo.lock index 8b2705003..547737a60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,6 +63,11 @@ name = "byteorder" version = "1.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "cast" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cc" version = "1.0.25" @@ -132,18 +137,20 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.23.0" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cranelift-entity 0.23.0", + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cranelift-codegen" -version = "0.23.0" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cranelift-bforest 0.23.0", - "cranelift-codegen-meta 0.23.0", - "cranelift-entity 0.23.0", + "cranelift-bforest 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen-meta 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -152,44 +159,50 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.23.0" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cranelift-entity 0.23.0", + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cranelift-entity" -version = "0.23.0" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cranelift-frontend" -version = "0.23.0" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cranelift-codegen 0.23.0", + "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cranelift-native" -version = "0.23.0" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cranelift-codegen 0.23.0", + "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "raw-cpuid 6.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "target-lexicon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cranelift-wasm" -version = "0.23.0" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cranelift-codegen 0.23.0", - "cranelift-entity 0.23.0", - "cranelift-frontend 0.23.0", + "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-frontend 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "wasmparser 0.21.10 (registry+https://github.com/rust-lang/crates.io-index)", + "wasmparser 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -868,10 +881,10 @@ version = "0.1.3" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "console 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cranelift-codegen 0.23.0", - "cranelift-entity 0.23.0", - "cranelift-native 0.23.0", - "cranelift-wasm 0.23.0", + "cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)", "docopt 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "errno 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -898,7 +911,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wasmparser" -version = "0.21.10" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -929,6 +942,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" +"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" "checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" "checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" @@ -936,6 +950,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum cmake 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "6ec65ee4f9c9d16f335091d23693457ed4928657ba4982289d7fafee03bc614a" "checksum console 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ba5561f4d4d89e0f246d4dd83846d96f617e886b96c7aee36e68791c98f89ce" +"checksum cranelift-bforest 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "40f8ff24e9a6c89b8a846b14df9a34d2cac17cea7bdb5c81ed6b4744ee0e38bf" +"checksum cranelift-codegen 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "42f5b809bd885c368e01aeec8fe04f21dcb07569834b907d75b4a7bed8d067eb" +"checksum cranelift-codegen-meta 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "014c23ed3ebdc8377d41540af638245207dd169f421df042dfccc867465734ed" +"checksum cranelift-entity 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4df40e26c0cf7b4d86919cb995bb412ee3001cc18e4f3c83a903f30b7007d8b" +"checksum cranelift-frontend 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "789907218eeebebcea8122c2053d71affac91c96ce72cea35ebfdbbf547e82af" +"checksum cranelift-native 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474bee81d620a473bf43411a3d6f10ffbf7965141dc5e5b76d8d2151dde3285d" +"checksum cranelift-wasm 0.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49723365dab9a48b354bdc24cb6d9d5719bc1d3b858ffd2ea179d0d7d885804a" "checksum crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f739f8c5363aca78cfb059edf753d8f0d36908c348f3d8d1503f03d8b75d9cf3" "checksum crossbeam-epoch 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "927121f5407de9956180ff5e936fe3cf4324279280001cd56b669d28ee7e9150" "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" @@ -1020,7 +1041,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum wabt 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff1f0f87e467255240c1faf5cf13a04410723407840d7733e75967224e191a5" "checksum wabt-sys 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cc8982bfe0a923f152e96d991e50a6f97fe73ca4af6d9d84d76634f03051fa2" "checksum wasmparser 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2a75e0c3fe9a4d4fd91901348a5be05ba4791e29dda89e8596bfe87900ba7edc" -"checksum wasmparser 0.21.10 (registry+https://github.com/rust-lang/crates.io-index)" = "48b8ebfeb364ff50e0ff043f491c270f58a7563aa3dc97402a0e813bfeb6df6f" +"checksum wasmparser 0.22.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46e666ecb4a406483a59a49f9d0c17f327e70da53a128eccddae2eadb95865c" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index af292988b..2a61b1524 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,14 +20,14 @@ include = [ ] [dependencies] -# cranelift-native = "0.23.0" -cranelift-native = { path = "cranelift/lib/native" } -# cranelift-codegen = "0.23.0" -cranelift-codegen = { path = "cranelift/lib/codegen" } -# cranelift-entity = "0.23.0" -cranelift-entity = { path = "cranelift/lib/entity" } -# cranelift-wasm = "0.23.0" -cranelift-wasm = { path = "cranelift/lib/wasm" } +cranelift-native = "0.26.0" +# cranelift-native = { path = "cranelift/lib/native" } +cranelift-codegen = "0.26.0" +# cranelift-codegen = { path = "cranelift/lib/codegen" } +cranelift-entity = "0.26.0" +# cranelift-entity = { path = "cranelift/lib/entity" } +cranelift-wasm = "0.26.0" +# cranelift-wasm = { path = "cranelift/lib/wasm" } docopt = "1.0.0" serde = "1.0.55" serde_derive = "1.0.55" diff --git a/src/webassembly/instance.rs b/src/webassembly/instance.rs index 84a464d2d..b7f17e1bc 100644 --- a/src/webassembly/instance.rs +++ b/src/webassembly/instance.rs @@ -383,8 +383,8 @@ impl Instance { GlobalInit::I64Const(n) => n, GlobalInit::F32Const(f) => f as _, // unsafe { mem::transmute(f as f64) }, GlobalInit::F64Const(f) => f as _, // unsafe { mem::transmute(f) }, - GlobalInit::GlobalRef(global_index) => globals_data[global_index.index()], - GlobalInit::Import() => { + GlobalInit::GetGlobal(global_index) => globals_data[global_index.index()], + GlobalInit::Import => { let (module_name, field_name) = import_name .as_ref() .expect("Expected a import name for the global import"); @@ -438,7 +438,7 @@ impl Instance { "The Imported table {}.{} is not provided, therefore will be mocked.", module_name, field_name ); - let len = table.entity.size; + let len = table.entity.minimum as usize; let mut v = Vec::with_capacity(len); v.resize(len, 0); v @@ -456,7 +456,7 @@ impl Instance { } } None => { - let len = table.entity.size; + let len = table.entity.minimum as usize; let mut v = Vec::with_capacity(len); v.resize(len, 0); v @@ -498,15 +498,15 @@ impl Instance { // If we use emscripten, we set a fixed initial and maximum debug!( "Instance - init memory ({}, {:?})", - memory.pages_count, memory.maximum + memory.minimum, memory.maximum ); let memory = if options.abi == InstanceABI::Emscripten { // We use MAX_PAGES, so at the end the result is: // (initial * LinearMemory::PAGE_SIZE) == LinearMemory::DEFAULT_HEAP_SIZE // However, it should be: (initial * LinearMemory::PAGE_SIZE) == 16777216 - LinearMemory::new(LinearMemory::MAX_PAGES as u32, None) + LinearMemory::new(LinearMemory::MAX_PAGES, None) } else { - LinearMemory::new(memory.pages_count as u32, memory.maximum.map(|m| m as u32)) + LinearMemory::new(memory.minimum, memory.maximum.map(|m| m as u32)) }; memories.push(memory); } diff --git a/src/webassembly/mod.rs b/src/webassembly/mod.rs index d91ac003f..d46d74030 100644 --- a/src/webassembly/mod.rs +++ b/src/webassembly/mod.rs @@ -6,6 +6,8 @@ pub mod memory; pub mod module; pub mod relocation; pub mod utils; +pub mod vmcontext; +pub mod vmoffsets; use cranelift_codegen::{ isa, @@ -132,7 +134,7 @@ pub fn validate_or_error(bytes: &[u8]) -> Result<(), ErrorKind> { return Err(ErrorKind::CompileError(format!( "Validation error: {}", err.message - ))) + ))); } _ => (), } diff --git a/src/webassembly/module.rs b/src/webassembly/module.rs index 75a9f10bd..5a1b9f951 100644 --- a/src/webassembly/module.rs +++ b/src/webassembly/module.rs @@ -6,7 +6,7 @@ use std::string::String; use std::vec::Vec; use cranelift_codegen::cursor::FuncCursor; -use cranelift_codegen::ir::immediates::{Imm64, Offset32}; +use cranelift_codegen::ir::immediates::{Imm64, Offset32, Uimm64}; use cranelift_codegen::ir::types::*; use cranelift_codegen::ir::{ self, AbiParam, ArgumentPurpose, ExtFuncData, ExternalName, FuncRef, InstBuilder, Signature, @@ -392,9 +392,9 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> { // Create table based on the data above func.create_table(ir::TableData { base_gv, - min_size: Imm64::new(0), + min_size: Uimm64::new(0), bound_gv, - element_size: Imm64::new(i64::from(self.pointer_bytes())), + element_size: Uimm64::new(u64::from(self.pointer_bytes())), index_type: I64, }) } @@ -434,9 +434,9 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> { func.create_heap(ir::HeapData { base: heap_base, min_size: 0.into(), - guard_size: (LinearMemory::DEFAULT_GUARD_SIZE as i64).into(), + offset_guard_size: Uimm64::new(LinearMemory::DEFAULT_GUARD_SIZE as u64), style: ir::HeapStyle::Static { - bound: (LinearMemory::DEFAULT_HEAP_SIZE as i64).into(), + bound: Uimm64::new(LinearMemory::DEFAULT_HEAP_SIZE as u64), }, index_type: I32, }) @@ -458,15 +458,16 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> { readonly: false, }); - let offset = global_index.index() as i64 * ptr_size as i64; - let iadd = func.create_global_value(ir::GlobalValueData::IAddImm { - base: globals_base_addr, - offset: Imm64::new(offset), - global_type: native_pointer_type(), - }); + let offset = global_index.index() * ptr_size as usize; + // let iadd = func.create_global_value(ir::GlobalValueData::IAddImm { + // base: globals_base_addr, + // offset: Imm64::new(offset), + // global_type: native_pointer_type(), + // }); GlobalVariable::Memory { - gv: iadd, + gv: globals_base_addr, + offset: (offset as i32).into(), ty: self.mod_info.globals[global_index.index()].entity.ty, } } @@ -664,12 +665,8 @@ impl<'environment> FuncEnvironmentTrait for FuncEnvironment<'environment> { } impl<'data> ModuleEnvironment<'data> for Module { - fn target_config(&self) -> &TargetFrontendConfig { - &self.info.config - } - - fn get_func_name(&self, func_index: FuncIndex) -> ir::ExternalName { - get_func_name(func_index) + fn target_config(&self) -> TargetFrontendConfig { + self.info.config } fn declare_signature(&mut self, sig: &ir::Signature) { diff --git a/src/webassembly/vmcontext.rs b/src/webassembly/vmcontext.rs new file mode 100644 index 000000000..cb5e97a2a --- /dev/null +++ b/src/webassembly/vmcontext.rs @@ -0,0 +1,151 @@ +use crate::webassembly::vmoffsets::VMOffsets; +use cranelift_wasm::{ + DefinedFuncIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, FuncIndex, + GlobalIndex, MemoryIndex, SignatureIndex, TableIndex, +}; + +#[repr(C)] +pub struct VMContext { + /// A pointer to an array of imported functions, indexed by `FuncIndex`. + imported_functions: *const *const VMFunctionBody, + + /// A pointer to an array of imported tables, indexed by `TableIndex`. + imported_tables: *mut VMTableImport, + + /// A pointer to an array of imported memories, indexed by `MemoryIndex, + imported_memories: *mut VMMemoryImport, + + /// A pointer to an array of imported globals, indexed by `GlobalIndex`. + imported_globals: *mut VMGlobalImport, + + /// A pointer to an array of locally-defined tables, indexed by `DefinedTableIndex`. + tables: *mut VMTableDefinition, + + /// A pointer to an array of locally-defined memories, indexed by `DefinedMemoryIndex`. + memories: *mut VMMemoryDefinition, + + /// A pointer to an array of locally-defined globals, indexed by ``DefinedGlobalIndex`. + globals: *mut VMGlobalDefinition, + + /// Signature identifiers for signature-checked indirect calls. + signature_ids: *mut VMSharedSigIndex, +} + +/// Used to provide type safety for passing around function pointers. +/// The typesystem ensures this cannot be dereferenced. +pub enum VMFunctionBody {} + +/// Definition of a table used by the VM. (obviously) +#[repr(C)] +pub struct VMTableDefinition { + /// pointer to the elements in the table. + pub base: *mut u8, + /// Number of elements in the table (NOT necessarily the size of the table in bytes!). + pub current_elements: usize, +} + +impl VMTableDefinition { + pub fn offset_base(offsets: &VMOffsets) -> u8 { + 0 * offsets.ptr_size + } + + pub fn offset_current_elements(offsets: &VMOffsets) -> u8 { + 1 * offsets.ptr_size + } +} + +#[repr(C)] +pub struct VMTableImport { + /// A pointer to the table definition. + pub table: *mut VMTableDefinition, + /// A pointer to the vmcontext that owns this table definition. + pub vmctx: *mut VMContext, +} + +impl VMTableImport { + pub fn offset_table(offsets: &VMOffsets) -> u8 { + 0 * offsets.ptr_size + } + + pub fn offset_vmctx(offsets: &VMOffsets) -> u8 { + 1 * offsets.ptr_size + } +} + +/// Definition of a memory used by the VM. +#[repr(C)] +pub struct VMMemoryDefinition { + /// Pointer to the bottom of linear memory. + pub base: *mut u8, + /// Current logical size of this linear memory in bytes. + pub size: usize, +} + +impl VMMemoryDefinition { + pub fn offset_base(offsets: &VMOffsets) -> u8 { + 0 * offsets.ptr_size + } + + pub fn offset_size(offsets: &VMOffsets) -> u8 { + 1 * offsets.ptr_size + } +} + +#[repr(C)] +pub struct VMMemoryImport { + /// A pointer to the memory definition. + pub memory: *mut VMMemoryDefinition, + /// A pointer to the vmcontext that owns this memory definition. + pub vmctx: *mut VMContext, +} + +impl VMMemoryImport { + pub fn offset_memory(offsets: &VMOffsets) -> u8 { + 0 * offsets.ptr_size + } + + pub fn offset_vmctx(offsets: &VMOffsets) -> u8 { + 1 * offsets.ptr_size + } +} + +/// Definition of a global used by the VM. +#[repr(C, align(8))] +pub struct VMGlobalDefinition { + pub data: [u8; 8], +} + +#[repr(C)] +pub struct VMGlobalImport { + pub globals: *mut VMGlobalDefinition, +} + +impl VMGlobalImport { + pub fn offset_globals(offsets: &VMOffsets) -> u8 { + 0 * offsets.ptr_size + } +} + +#[repr(C)] +pub struct VMSharedSigIndex(u32); + +#[repr(C)] +pub struct VMCallerCheckedAnyfunc { + pub func: *const VMFunctionBody, + pub type_index: VMSharedSigIndex, + pub vmctx: *mut VMContext, +} + +impl VMCallerCheckedAnyfunc { + pub fn offset_func(offsets: &VMOffsets) -> u8 { + 0 * offsets.ptr_size + } + + pub fn offset_type_index(offsets: &VMOffsets) -> u8 { + 1 * offsets.ptr_size + } + + pub fn offset_vmctx(offsets: &VMOffsets) -> u8 { + 2 * offsets.ptr_size + } +} diff --git a/src/webassembly/vmoffsets.rs b/src/webassembly/vmoffsets.rs new file mode 100644 index 000000000..267787142 --- /dev/null +++ b/src/webassembly/vmoffsets.rs @@ -0,0 +1,9 @@ +pub struct VMOffsets { + pub(in crate::webassembly) ptr_size: u8, +} + +impl VMOffsets { + pub fn new(ptr_size: u8) -> Self { + Self { ptr_size } + } +}