From 8a915186331f1c99b4b0875ab1927b47d35fd760 Mon Sep 17 00:00:00 2001 From: Justine Tunney Date: Sat, 10 Apr 2021 16:22:35 -0700 Subject: [PATCH] Fix issues revealed by ECMAScript test262 Cosmopolitan's QuickJS is now equally conformant and performant, with the exception of Atomics, which have been disabled since Cosmopolitan currently doesn't support pthreads. QuickJS memory usage -- BigNum 2021-03-27 version, 64-bit, malloc limit: -1 NAME COUNT SIZE memory allocated 937 131764 (140.6 per block) memory used 938 116103 (8 overhead, 16.7 average slack) atoms 513 21408 (41.7 per atom) objects 170 12279 (72.2 per object) properties 864 15531 (5.1 per object) shapes 58 12995 (224.1 per shape) bytecode functions 13 1512 bytecode 13 867 (66.7 per function) C functions 99 arrays 1 fast arrays 1 elements 1 16 (1.0 per fast array) Result: 35/74740 errors, 1279 excluded, 485 skipped, 19 new, 2 fixed real 2m40.828s user 2m29.764s sys 0m10.939s --- build/bootstrap/compile.com | Bin 77824 -> 77824 bytes build/config.mk | 5 +- examples/walk.c | 52 +++++++++ libc/runtime/fesetround.c | 2 - libc/runtime/fltrounds.c | 14 ++- libc/testlib/formatfloat.c | 7 +- libc/tinymath/atanh.c | 2 +- libc/tinymath/atanhf.c | 2 +- libc/tinymath/atanhl.c | 2 +- libc/tinymath/expm1l.S | 12 +- libc/tinymath/powl.c | 6 +- libc/tinymath/sinh.c | 1 + libc/tinymath/sinhf.c | 1 + libc/tinymath/sinhl.c | 1 + libc/tinymath/tanh.c | 1 + libc/tinymath/tanhf.c | 1 + libc/tinymath/tanhl.c | 1 + test/libc/tinymath/atan2_test.c | 5 + test/libc/tinymath/atanh_test.c | 3 + test/libc/tinymath/expm1_test.c | 40 +++++-- test/libc/tinymath/powl_test.c | 15 +++ test/libc/tinymath/sinh_test.c | 3 + test/libc/tinymath/strtod_test.c | 57 +++++++++ test/libc/tinymath/tanh_test.c | 3 + test/libc/tinymath/test.mk | 3 +- third_party/gdtoa/gdtoa.internal.h | 3 + third_party/gdtoa/gdtoa.mk | 7 -- third_party/gdtoa/strtod.c | 2 +- third_party/lua/lua.mk | 2 +- third_party/musl/ftw.c | 6 + third_party/musl/nftw.c | 19 ++- third_party/quickjs/README.cosmo | 7 +- third_party/quickjs/quickjs-libc.c | 57 +-------- third_party/quickjs/quickjs.c | 20 ++-- third_party/quickjs/quickjs.mk | 182 ++++++++++++++++++++--------- third_party/quickjs/run-test262.c | 7 +- third_party/quickjs/test262.conf | 23 ++-- tool/build/compile.c | 5 + 38 files changed, 395 insertions(+), 184 deletions(-) create mode 100644 examples/walk.c create mode 100644 test/libc/tinymath/strtod_test.c diff --git a/build/bootstrap/compile.com b/build/bootstrap/compile.com index 347df93b0e84d2fba538d85bc2a070fa1dd6fed3..0073592d8e727a6fbc51b8837b3640316e662a4b 100755 GIT binary patch delta 25837 zcmc(|d3;mF_cwlT+S`qm8=!@F3tviT*Kv66RZQ4Rx_5!j93I$Ydj0>Q)l`YTv++5J-^ZR{Yzt{8o=jlr_Gv}N+ zGjrz5nVB;)S7&Xgvo>^HmX2%m@_?m$(#yp!cUY3FD1m9p4}nr=vT`x-$2$L=-Jx6w z7y466nlGFX$4o-8pWf(;I_@I9G3q=28#^r7n_ zXNrj?j_b>P!QKnaZSqSfhd({Xr8hy?l#6D(5FdV_k<#ama*`zpPd1j5{Sl=bll>v3 zu4H8^dqo%$x;|N%#x4ne#BNCzle{xyLO9Mj(^Y$0Z14T~2Ky$lD3$IHU0NjxVD2k~1ae1zYex$NyGkF^=JCWn)@ z70-QM4SrrvfmK$dZF?r&U~QVV)eW1(vYI}W{R(70J7=Qg7CvgsbIOa9Oq#GKa6vnkEGwRkRuR@AI{BS{umAD$aGR(YHqZI&1_{Vwv$7ftf-%73!h-_80szWO_d zE9KF3ig_Ey`Ex3TO307*zlRpaOyEH+ECRsKkiI)!O;4q?OLAxbinJ16%t4+*l6lVe zbRZDO2q?E)94F-omw+`H6npDZ9oX;L0<9{c(v<6(k+kq%2 z7JPw(X?6CqR7OF-rnkzDYl{33#}#3yU(Un472lT2hi;ycdU0m{nFMN85aSRjZ4QufnUD#D96+q(fy`wYxM0>Tr^vL7Np5Kn=1o5R1Br1hn!0^6$pi72m*`9ik?e$=` zZ-I4X_YGz{f<&dTM9t=<*760Ru&-Wf-pVhE&DpOm0iL3!agQYa96nYbN zrO;8$G>BQDf(t0bmEA8%727c+d}UOuU(3)b zSj%XP_x=v#@O?tqfQF3v0J0;K-MGWq6fd{m5EW`5$p+hf}R=gGy+eP&e;I36M$qlFUGkLxpS$LYkBqG?uTc0J})! z?`1-TvVri2P;vv380o%Cw*vvml|37+&#w738?D` zFi}Pmy9E>*hM1%DLyG1gs#K%O=#A#EtR0D0VZbhw%49Ly0qxB0ud>N^X7{3q-BwDY zToH)hK4NmaH&L}vsS=#o%~Yz`QW~?$CE!XciR!dU^;=@FN)8&dN;zTA5w=*xp3$&m z3zQEC`70scP?38yB#jzn6(MgEa=D6pRYTI)Q05S_83zOYn2KDkBBM&l7ATJZlo4X%fJHUZ61q)UE9tCclm69!ZEuRRVJd3nDw0wz|jpu(RhF#PUb|2{4Xu#enKM+a_QK^xr&DowiE-2qxjAh)n22)aWcTM#rO2)aw4$AX|ogP?mc4!|A> z!UhImfhaVpzY2=$hCrRYmA>zBSj)W8iswSb!ds}i)t&MoRyHLcMh2zT=Qv4PEVxL` zny8BKCkS9?A2iLKxeTPGj{%BGKZ!Unuc;VE_5>sW9fm-8#;taGYvdS2Ic5f>IG;!% z!i&%epn6aacXmAGcp|7KdbB)(z_QQ;fqybIiqa*|sAXPK_NvvhHIk}?@6agvljMY> zZKi-nr!^|uGHUEX(97kh-W?1p6!Hmx87I{)6p9g7GhORy4&rE4j*2%KQ7n*>wKpef3Xo}`9G`8%WQ z2M3HxBC>L}p{Pe $C?J;YsArpQ`*C*?dUsOmFGW`{b6G8hKd-7$4AbzhV2Vp(<*ajTr`RSJ;ZVJ!X_Bci}-6-^aZ*<7uhO`}0~ zKzWjwZ&z^`J%5a|x^ulI`Lb31**MnfHdmK!gP712GpJm-(!UVJtox^!>^1j`X$wZd zQcUu-e-*T|1_e3fN@b>2VjVdBtHhC1qE)^@C8Bhccu+0T==#N}Tqn~aSB{tD`iaUH zr_tS*{{bmiIus%F%s6L~YbO~e8>bkj8mCREfb4$gg2@a-+!*v-9TFh_(O?{ly^MSp z`xtw>jFTC4rO%Jc;h=}7K(K@s?GbB*3dEK77OTT*JK|91;x6o|#I6n(QVUxk{Q@FZ z`RXHbw_2;5`2C=lz?=V@a#ju7zW%P04vnZ zn|#M2|7DTSSmfi%x7P!K;!W6j?JjD;#w8_2@P7mX8g|Hi~mZ8KS+PC;_IdR6%3}YY3U z{d$7!N?wT*pZ0OBec6?a3 zvjdyiaV+0~?dzD4mD&L;-1{PkECKO7;0q&h($-96Od1l1JJJxWLJ1`$&ptg-zf!}x zbjs9iaIwcaC1$yfka^4S7G4kwAI50PIJn1&=|l2-S$r3ZDbKzg2$c8R)4VGdB!j~0 z`QRd8CFdg8-cIdxv0t*4H@+z4Z_Gm<)s%cfX z&r5{;*u~Dt(Nl7Ol}AK?`+C+mwN)C4FXIBLufGSPMt1^%;8@heN{v$fqGh5XVQ&T- zlWI@RO@itcZUMqCC`m`rQTskYB4BIbRwHuZ`;_TbC;KCHV6&o>98}F~(*D%rzFD%8 zb?=t0Gd;_ucT3@)V=s2=g4%r6ZKUq|KUiqmc%HE-X(_q`f3SiyBQTX|+40}qRN3V~ z9`+`*JPT<9<-S^_Tv8{IeP?tHy-WseVe-OsyOkBrB{2WIAQzG1D{ z#*8Vt+rP59j4VEa_3GJO_iYQ7*RxZv)Oc|AcpA`A8Fk<+d0x4WxUvUuD3~(01%=m? z83;4H=(nu>Y+ui=vmj#Uz#jJ5@TVB%GfE*w1?tus?duT7LLs02ai1Wt^+4onieyQi zg^|Q*Vvsb<>dEWk?*eEuf|~w;cK62uO8yU}`yMu;S99Hzy=+#mH*|OWOz557=Hp+2 z!ax_3empI??OUw!Em{e@$VT>V&5vYrduJGy`c<+Ks8$EXT8{NVykbURbR7%i7XE5$ zN6i}@2Y3qtQU9xI@+>>sdz>z34olDM*x9!aOyqkex$qe%YQ{;ETotIP6s}uO!hP&mX7^5$5MS6?no|)kg$QGjaP{SE&D=SmQlYSthdjdN zOUfphb?7rdzpEJvaqk;}5>OE(kv-d|o#T7VrKCYC_E`ZBfg0LMH6rCHWN@o+DW~r_}6qiMx7gBTxs(CE2GXhTJnrJXOZuaH!)tSGM@v_fHF2#-3#{1IGAzLD*r|j z9}JLOQRvOI(e^Lnf|8`th_7IZx1S3VUQ^lvNS4elC?%z8J>%8V*_wyq=VoK=~0FV%iavH8ND%58HGyA6_I6e_%K1L4J^$PK>^R5IFHk=bopK3L^wV`L zn`qTECAell@0>P{w#a`<9=msxB;S_g<0!wcQVQ!Lxf@wMxqHpB@~Bn5G9p;7qgT~> zr9(b~+q~Bwr@W0Csj@Y?8s^#rW#?|SBxRD(@lQeH$gOHw*-#){gP*D1RT&-&yxs#mE6r}V(2Ql7dAi>BssTQu|R1g>I9?Y&aJlaRg&xP zfGtGg%cTAx3!*K71K6nQa}B@Q%dB#PKdChoI9_s9MbOIcANBOr45W9(jHtOwosU{ETy~=$7R2aUbE|sfg`p?@+JO)G6WR< z8hBZ|W4u-euz}E2vNfooxd)W(UorQe@jn>Ychc@l~}Mi~IjB{e!i zdRutG)(z{L_Dsxa-lh@O2bj)lF~3<2b@oL6Ah4#C@>diy<}`14xgI-|j2|RJr425S z{u-_F&{p6OT>?5&(OaaU13suiKwcc}%FMO)2|=j4cTXPBQw z(i|_DpMuV;t+9RNc)%c@37wh6I5=j-6->j=NqOg`4hdV>YsPkb82j3osQW3BeP>J* zzr3jGSrXXCDCu9as6hk6ANq_YT_YPYD9yTz@a`|G(LE>?{hY4MP<8f8FF+PgzFrxF z^sv0m`)UBd^5RBEc$wwzq&XMjCHM335y~c&Uih{nJ2)uC@jng)9mdxG>rik8tN36j z2uj!&Aoa|E>i-{W{=EMW)t~TxruzSr<~O~s`87j3=mrK@6H^?ouui4~^9SDr1&)FHGI| zPuOKsQsgX<_#+hK=Pb%RO1I9zrkQ)?%*S%VxZcv35uq3xF+!Ru?Ap)GVa- zpmPWb&F0N5y+&89&Im`0zZ=$n5<6+m$X3^``>sQWXLIsJ z&ebr&uD2GZ`EH0h`6;C8iVcZalcoW#Z+3>YX&=Aj^yTwi~}!e27A zyDT4S6n6?}+T!ytQrJaX$NAGGPbmC<_e|{7p>1_{+p%3kvvvRZi?l=+`W=gwS|;p2N8E#Z zoq-S+_EELSDq%G-avK{Y_2K8TrP8PlI^ZOCehoI4k|d8Bp+Im1@B)Bc{ix|mE&E*> z&412JmW+wtdTcTk=Bz_1(%-^-|{R)Csb{7-rh;h(*qzR!Z35gLp8psoK;&` z+=AmWaf0=`U(&afCKr!Z@(D^u{8t(lJBU{|29^J2SVr{dh#>xcH4guqK|ao&V0`{U^_THmCmqxrK9-YySOQZlQ+K)9$D5XCcWw5bFUV$+}PC7WSPM0qFJ* z;7j(Bb)@dvHg?$>H$46mj(cdtIU&`W@3czp#hN|;rw!1-Q3!_2uUy2p#y)48eP&M^36&cDMp=Zb489Q(N@Ij6mTE@GxPf*}_ zhL_~b5{j1n6rvpJK&ZI?P+AtYtHI=&hKZAC2*Tz5Aj^-mYQx&lo&B6jlsSh2VzDyF zViKhbFJQZGR0)Jf)d0*KR=3ax39(>3Bu7?a&j;jx#LlVC_Ne5srSn#-YIA~oLe*>+ zQ5zj%m7)41)Z=#r8QpQ$Deye61N{|c&btH?z5&eQF@>U8LN((4MerFCzw7O(u!~lC z`W2vdQPvRQBMN}*fy`DuWfNr>g4L&va+FdIcbrS55eg{q3aY zxJeXs$4ypP(TF(5b01=zoxKLJXa0p&x71mz z_sEux_sLsrkE#+jA%ZB*0A&?K-uY(`bN0o|1&zh+fH*p*s1jxpo&a)<#Xb5o?hDlB zLxa?251<_V((Ij))+sY?i>a{y-#3kVxP>dJl@znm@E z*}tDHad$Cn0_1;_c31A~JlNQhqX5Cr{gDn;DjtX$_*UY_xrFZr4_lScpR(gmW%`VN zI)yek5;8ji;UD4_x+4sDb7g@5M#KK)dTEozZ8`w43L!+(0bG8=2?e#BYSGb^eGf@) z_i2=DTjQHcYqBcgutpLPzHh}^jOyNECKQ9#_0wpLk|$gQ9$N4=n>?yjYv1c+%4{(v z8BUXc@*!Br@b3qdHHqxyQSmz6IJRxn_P9e!f^&p&s4W@{trV1~8a97)3&(i?U^E0p zIZmr%bHl+3XZ9N{Q7!vqXZFi##5$&QAM7TkUuFAfQj;pMu*H?slVRQT8r1-IHfDm> z-_$LMxrppYPc z1Ncut0UNv(zE1_#d(68n-?+@t0azX?>CW7aMCl!>iQy6U`?GX>;qtkjW&5fkWD4sKLew(=is16!ahVD zo9lu{a_@tqn)a%NDI1V>XUmthA^at=Q3{ctOmQKq6CC2(2L*S99m$h{VzNMn!5;RM z+8eFV%>ywU(9P%A?Xj&prv6tcE!9#Qqo!(ZwUDS8ENfhP?AIHi%TeLfT~*4ESFwV= z6ULn5k_Mif4%H7y4yo?Gj{G!iUl@FE3 z4=7!LAT4bx?lK23UkzGh>R~xy5OL5SBYBi~pIeo|NnO;bV?N9&_~egj*uDBWoh`%|I9^rwJY+<}1uEBkaiS&fEI5XqE<)Rpt$fixL{#&)`q zszOQch5|~lkuwUFzXam%hzd6z@?)qWz62ye%;jX!xL!k~xgxXpY$Tk4Kx+*jD z41y6|j{MCbwx0fxfKVM=`Kvg`lU3#|lqe0>swfz&qQE~^BXpZrsb~}5Ae*-YyoFxb zTqF)}@Ml(;p>xz4m0@X9HNFLP3sjklf&u9l=WhfavctSZu0mFm{N@utqAOof&G2F5 zLrr;;TZM~n7cK;vS_{#tB&0L8X3l*C=ZcA=Xfkh-&6`~LMUBN*y{4pExlAk=hDi|8 zTt3qzH<;vG>a^vm70Ygg8pS==A{^9H2dJkOwuC<2bX^f|ic>QuLJ`y%4HdHQC@#Wz z79BO#mGic+o8km6P<7&#JtrEjYs&ek|F0TA7ocPj6j2CbdS_6wi8KY-7WRL2Zclcx6c8L0Kzkr{N zx|`5ru!$yS6EJed$K3dct)JRyWDTqc9`cqOZ{6bo<|O2aDQCFFrkWs%c5;6}|9j52*n)_v|o@DLKd(`@Lpt`6!2 z<8BfcHT@C^I|5^ELQAt;ZgG`GoVaE86Xv|R09T#Nx2W(-7>D12Ps~AVKG1=eC2=U) zI=PmR=g_RfsPPf;#fhqN>0@43$$A_XUz7mBim%w@S;|*(8Is2_p7#w1SGoKG4hk|J z6<5+pwtTLux!6!CzQmwq#1sE2Zi?N!QUF00#pO+3H5j@(`2dM$QHk$r7@10H?Sv!h z*cQkAK#fg7>Bv`uOg{(7yYGK4L^NFoBbTE*ebuOd;krGQNSkTxL9bi|*ZtzkMyg0B ze~Z+)MKL}n%Ak4#y#7zgwC!-4kHG#k7S~3B5cAq9az0t|s%T7uW3<{cOT$Q0mNy3g zN`)$l<1QecvgQL^!}Oa8DHdK2Dp1U-56Bz-D+~zA%-tcnz6Zj013#!Q1YhA9K~-MX zTRz`)OtE21k*z0cv>)Ao7EV2ZmX@QXh)+O#a=BXZ187iLpxVDrEGUN-`S;T(U#`c< zc3^wF10dDTcLbRi8Oj#7K|y8W>Q{jg3)kUy3vZ9`twh8~^WixOM_7SsXJ3OI>mGBl z{dXLS6dMCom3;a=IB8Udn>bsl&_>WUl7F*xr1kB#2wGUw zVdV)niW}^(%%Dp~mr;pa`8R(fT6PqI3iFd%vN8ljF4eqqmY(tfTNC$}WZY@-I#s1R zu$m0oW?p=&99xQra@%0%J~H&2tzT84jX580?&tz7-XWDKNn1It)?sTMFmDJ{00}B6 z0OyYi#u2?=l&X@p1f$y=8>p5x8Qsqp#w!z{PdLCTP6C}N)f-~o;HpiuwcbPN)N9z(lgkW`vy!> zPdV$A?vbRZOAU1FS+B0kFq1c-|l7HW$$hQs{Ne zbelK3XxnwyK8dWLJr(7`>i~LAp@%9c0bUX6joqjWa#sxUK(s4hVPksAHkh)jvSh=gli2TOw)PN`Q( ze?k*wvtxsjri!;r?N*~}sh+drF#i~G-~!w#p(B|x%)bIilW1mRMfzZr!~VnB~Br7UN#A$Kj0$I3k%VJyGg zst)96;$zEE$MAwe@A5v>v!sSfPv{q#rH+nD~9+=U#0isH0OcQOt<~z zkGNkdjZ_@Dsz*j0By~k0l5A{|BrgS<3&`=BLi3P6gp62`s3w7;XS z3VEj`w}-Y3M$b^bG6dU`d?zRKws2I%Dakl@G#6uwy$Xc?oJLoSab`bvh4NxkGJ2GJ z8}+Xez6T`dVIyuGO+}1%-Hvo5NO`9ucj)QbVc5uH7a9ehBwo5i1Hk@#vUi#jgpyn) zt?*GssqAkYj31I#+)6^VabSnjayff4XmE+eQ7+}#awd_Ir4_aT0PU^b3L&xvwP4Tv^Cc=><+H8DBW>AL9?}T zb5}!@qh~2bJ|>s)jJnh+`R`LduQ zWSk^Sgwg$I1K2jWlt#9GrAgo-m&s>RtBj{|?$hEf%8F`YXDO=%yKfhP-LrS(vQt-x zS>zcD*fstai6ydTrbV3RWtMqKx)&PQoOuSm6Z>GEq`TO_exGNa{MO%rK-py>wM=eA z{#dJAt)2d6cvr{bl2K^*s@QNG&J~=rLrc6BV~U~8)YqdjE{ybyXkoaO9~P+Kz5YMo z2bx_EcMxtYctau6m3P?E`Qw}J1q^rCI^IDq(hcgCci7eWhjpWFvmMXa9dtn`km6T= zf5or5wN>5q%7_=Bww~$O++S0^rMVS4(->Arb&Ow8IyqD={O2afUvv}X8}js*;?4<_ z7xzHkp?q=(vf9Ipt|I~eA|tj9$>4&!O4zqMN{AFI>}t3?ll8C`=adVJXe!wcCxY!L z9XV{meF7=3PRgcPd9kRB*6Pv?jQyP?* zesQH%zAkwl(YtC{*n)1lk7{@JUhoRf>vtYnIGE?Vu*UWxUF+}J4!be#N(x#6M`sI* zJ0DWNXyxmbZ&=u(jeHh+YtiGe4G@WYI4W+0b&&LaoImI6j9q*oBpO0o5vWC9i7WfE zd(Xu?emYD2_N`Rr3z4s%QnrNH9 z$eG>M8d&6|(9Yp{Pw%5(3$uGel5a{poG{;7Tz@An*2^bc2SebdLcM&Cq6U(DUgB|k z`4F74BOVR>mUCbKFFDJZ-z}FI!yE}UkqI4sEQX1^O z+)#h6U4yvSi#3Hi`oOudID&UuAlzz;>v98HBDqH<(Y2x0Y`&uf`|vSbCrB?x zr28M0+`R!~n^vrF=mC@r=NCL7xrH_qmrqFOXislFZhs{%N}(%j)IV~}Pc^{0j??+v z9~70JgJv}LO{b<-3Ht$3TSp3AB^HtnTq#Jco+m;ENcHC|?Qqn2(uS)YF`G`Y zt1qPJ5^l06SGq26oMpLE$9;oWDb|pb7|PN=r7;C^N&xZ`UmT<^J5p{T;lndxDqt#6 zgY&c?XRG0==t@;laTh>#zogQWY_F@$(A*njyer8`s#P2|24q&g7T#w!WsrsE5iANv zWEo-HFO>kAs-rFsFhUDli5%w!v8HUR~{5X{vGi~#dJO1%1Kh9bETBFVfB84UAebu4ZehlU&e z77J%%7`n43onYe&6Jy$|g$=2SxbK&_bzy z<|BY%ixwiJ1xW{}q-CIPbCiiMj?$GLVNbkR5UpCJUc=-pvPyrx*hv?4ge9z;+U~={ z7+Sr9)}{AfLF-aQ)&tzQ~)zHXOKcPd^$*J%rtiVkbzL^IhIgTYC;ZV;rkGAEAN#I z*?(8DTz7Zf)+(0oUimbaA{}iEQpTh5!!?LxkrL z!TQ*(1~?iMo}!pK-;Il~8qVTjXqE67VDyLRfcw$@!Zbw17k`13n1EZRr6kcQzTpbp zv^;}jln|jgv68bpsR8j8Dp{&0NB8vsHpk=or>5Vdrnfwubm0eBhnEKHD)+NlFZE7X zwf}z*<9r}k&C*uv)JvAe(MVW5mWMG_QP*}^+b;h53TUsKb(AV(mB*?5-Ww^Fx7MyN z0MZ^aQLXKyDZT=xtR0W5!^U;7ViUTZE-0tht79#c&0Loh>G>Jji`niJW9wG)%URo( zAMV!kN5DLT_1ad3R%JIOS3tiQR=3`_4tj)}>uLeM73{T_JG7lfpcVIMLR%EBJo_?S z`!V>~1U=l0R9dj}FDL7qqt~x*t`mGLetk;hV^e7u)hpZBkoBW=Pk7np^#l0sJ1?xS z)A7gH$yZD*&UqnOY)16xk!p&MH*#M~<5}9P-6CH>+8?f5Si>HFb*RqlW!qjIqn8)t zkj17)9acH5wv_2N#_O(ZWL-A4O2>04X~k{&UIk7HUH*tbGym`SP{CEqw`RX{5v9lu-b)+@7a(fCQ+Cm_BZ1`>d9k=;TSwoboHY8Au%YTa_Ok#<% z8gAZ$CfW(88@`cs!l!TIT-%>#PaK{pND0{txjitOl zc-L|RHr!YbvtKuMVTqe2>0VjDp5K(w88BPPBH zS3XZCrxos)UpBKxUdz+1+{|{qma6luVi#Xa(9L~=-F;0;S^FQll~|n}z_QkHt&|?O zSv&>FbaaCuS6B+y&-6)b_Uq$XH3OweR?OiIoFoo6S4;Fr@%E?e!s{K|#;&5hXQi(S zSSc?cm0i;t~)s-#z5Vb*V*(pM(C*_$`CX|z0=Ti0`tDnNjG36^S$xV z_zzx0lQWe*U_uh@iW^C}P!`TCiku`$5MxfmN6-4Xgy;Krjj3CPg_-bMw5pxBv}XzZ8bb;?BXk z(d&B}y*LIabp8nANad|=?7PiR>1K~+L*Go(g^ps2-t6Sag&{S{-_VCxdnGxdJ_DE4@S^1l|Xe!BLc9;y8<=nmE+6Z7wGF)Z#%3qj! z+_`%tII-jkES(MJYMb6@xU?{aZfKhgPlQD*9}_riGTgR5Vlwy~`A?b*k4G<;q!szq zPKeDOrTkP72&msLpj%b-#=ucyV83#X=Cr(uK!ucdLA~pZyVYj->9A`k=v!kDHRww-NDk*wrHFuRso*fN;3`vN;ZZb@daCF3P^zx*-5yD|2#C_d%DAhj% zMWJ%?^axaWQHsAeg2g@Rgb!7sI5=6n9PQ%FUirL9zK7}sYD}rOgHg{Y9-rO$?XA9i zDeLt1T9~-6-tI4U#0j~-CpN|=Irj)2yzoVH^j~2=Y=P?%%gX&p%F-?D`J!RET{Bp9 zQGV-(W}u-k8;Nxsj~DWWln*eMTE)RBZysXP-)R~90+JR_XdB!=kiAb`l&Hyein6?~ZS3Ur%ytDanV_7cI)% zp)CBpcB4k+l5$^DhGGjvU!1V=e)Z}29;7jOUZs0^Jv5pQL7Mh}mBhdSq|zu&g4p|} z-glQRd#}UzYr|1bxCX+N=`ia4$1zqVPYy3-H-Ilpd_RI(@w`O+$PAw0Dt`?P=4h(c zkNj>|gAiL<$+WvUYAw52SlxRmv3jfo>IBQnq%ti^zn}}8Jy?(TTk2X5Wy9X@q`NtU zEqwol$UZO*{_wA(BH6w7Te6lPv~f&dhc#NW#D(kW%60nRp9WmQ5*+=RsM;XW~fY67e|@Z z{bf4xkw>IXnagu**9Q;ja^l$UADA2`aKw*S(Tc4D$3<39p|jPPQT`r&K)pIbgRcdQ zQ>Rqa360iLYX#p{3@o1jQ;pgb9l$CF)q^m8c`1n2wFc;-ClII;zSTfI!PmC~a8fLI zE`DhMb4Q)9N5$h-pZcK1oiGR7lvS~+DYOs99gm3s!0fk1$#8e}kL!tuy^EYM2ylOU zEuZp&o8}(x4&I12GEF4yS<3KtNrK`lUNnZv!_-h1SQ@6hw+z=`>VyFXwQyLao4)<+ zQ4CCY|LmJyj$06>j363mP5=)?vabPzxAGCbVK9!+=I#60z>iE0uZNl&t~`aj{>C)@ z2IB0CL5cw?3zM+o!BB8zk3j@u<44$wfkc_+%kN=R8V|tZ zw&rk3w_C7?LOftW|JNuqR8PIX;ui&3-3h{eE|pW-H&bVnbjazi3KY^mZWrog!<2~V zVMOf_a>9iQ)^$r3?8~ezNsb?Iu%Y$V4n(Olm$n0F0(wiG@YN?!dFN@@{7bx?d(Pxe zlZdr!uaWb=Q#L25YXIowv^rrPIPmWL?jy+uBW3qh&?Bg1xPaW$8a(T-ly7O0 z*a8qqqAUrL!28n1TboClkjaww9rn_LN?7{VSTPv@$aT&slor>igpJy2(6w>1m$tTU zIT=TT&_3ULI_Pa6()OD*FJSGT-FFQu-MD|g$%FqvvTa?3KA2qg1(H!pH7ei>hxWK`>unFaZnIB6en$6nJxkn{#;;+y+b%Ti zk2Mdree@)y#jw24eR$p3?~_*a$aCx`87-IFF%-mc-VCqUB)mdyaMe1bywE~mi$2NZ zT|3WwazaP6Teo+`{Q~U6o#1Ab&nkPvJ2qh%7BjJS(Kw!t3USYT zifZ-nb6sAhQ_m+1jK2C5TIg z2C?9M6fC*n$iSU72=b}DCP$u%tFq-v?!oXLm}``+So$M!4q6$uga*cb+Jv=|4CQzS zkGGjLQ)Z&V{zPRN)*?8{GL&P@0}M?s4@Xmt6`ocpcnNoZmWByl2XjdR`5P3z#~d_c z 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 T%l{7>__CrSH>epa=9>K<63aVV diff --git a/build/config.mk b/build/config.mk index e04ca5584..141977aef 100644 --- a/build/config.mk +++ b/build/config.mk @@ -69,6 +69,9 @@ CONFIG_CCFLAGS += \ $(BACKTRACES) \ -O2 +TARGET_ARCH ?= \ + -msse3 + endif # Debug Mode @@ -88,7 +91,7 @@ CONFIG_CPPFLAGS += \ CONFIG_CCFLAGS += \ $(BACKTRACES) \ $(FTRACE) \ - -O2 + -Og CONFIG_COPTS += \ $(SECURITY_BLANKETS) \ diff --git a/examples/walk.c b/examples/walk.c new file mode 100644 index 000000000..31f5fc405 --- /dev/null +++ b/examples/walk.c @@ -0,0 +1,52 @@ +#if 0 +/*─────────────────────────────────────────────────────────────────╗ +│ To the extent possible under law, Justine Tunney has waived │ +│ all copyright and related or neighboring rights to this file, │ +│ as it is written in the following disclaimers: │ +│ • http://unlicense.org/ │ +│ • http://creativecommons.org/publicdomain/zero/1.0/ │ +╚─────────────────────────────────────────────────────────────────*/ +#endif +#include "libc/calls/calls.h" +#include "libc/calls/struct/stat.h" +#include "libc/log/log.h" +#include "libc/runtime/runtime.h" +#include "libc/sysv/consts/exit.h" +#include "third_party/musl/ftw.h" + +/** + * @fileoverview Directory walker example. + * Copied from IEEE Std 1003.1-2017 + */ + +static int display_info(const char *fpath, const struct stat *sb, int tflag, + struct FTW *ftwbuf) { + printf("%-3s %2d %7jd %-40s %d %s\n", + (tflag == FTW_D) ? "d" + : (tflag == FTW_DNR) ? "dnr" + : (tflag == FTW_DP) ? "dp" + : (tflag == FTW_F) ? (S_ISBLK(sb->st_mode) ? "f b" + : S_ISCHR(sb->st_mode) ? "f c" + : S_ISFIFO(sb->st_mode) ? "f p" + : S_ISREG(sb->st_mode) ? "f r" + : S_ISSOCK(sb->st_mode) ? "f s" + : "f ?") + : (tflag == FTW_NS) ? "ns" + : (tflag == FTW_SL) ? "sl" + : (tflag == FTW_SLN) ? "sln" + : "?", + ftwbuf->level, (intmax_t)sb->st_size, fpath, ftwbuf->base, + fpath + ftwbuf->base); + return 0; /* To tell nftw() to continue */ +} + +int main(int argc, char *argv[]) { + int flags = 0; + if (argc > 2 && strchr(argv[2], 'd') != NULL) flags |= FTW_DEPTH; + if (argc > 2 && strchr(argv[2], 'p') != NULL) flags |= FTW_PHYS; + if (nftw((argc < 2) ? "." : argv[1], display_info, 20, flags) == -1) { + perror("nftw"); + exit(EXIT_FAILURE); + } + exit(EXIT_SUCCESS); +} diff --git a/libc/runtime/fesetround.c b/libc/runtime/fesetround.c index f55465f35..3b8896c4e 100644 --- a/libc/runtime/fesetround.c +++ b/libc/runtime/fesetround.c @@ -18,8 +18,6 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/runtime/fenv.h" -/* TODO(jart): This needs tests. */ - /** * Sets rounding mode. * diff --git a/libc/runtime/fltrounds.c b/libc/runtime/fltrounds.c index 3b90c0f41..c3a8920b8 100644 --- a/libc/runtime/fltrounds.c +++ b/libc/runtime/fltrounds.c @@ -19,16 +19,18 @@ #include "libc/runtime/fenv.h" int __flt_rounds(void) { - switch (fegetround()) { - case FE_TOWARDZERO: + int x87cw; + asm("fnstcw\t%0" : "=m"(x87cw)); + switch ((x87cw & 0x0c00) >> 10) { + case FE_TOWARDZERO >> 10: return 0; - case FE_TONEAREST: + case FE_TONEAREST >> 10: return 1; - case FE_UPWARD: + case FE_UPWARD >> 10: return 2; - case FE_DOWNWARD: + case FE_DOWNWARD >> 10: return 3; default: - return -1; + unreachable; } } diff --git a/libc/testlib/formatfloat.c b/libc/testlib/formatfloat.c index d515c66ba..0056a8ded 100644 --- a/libc/testlib/formatfloat.c +++ b/libc/testlib/formatfloat.c @@ -19,12 +19,9 @@ #include "libc/fmt/fmt.h" #include "libc/mem/mem.h" #include "libc/testlib/testlib.h" +#include "libc/x/x.h" #include "third_party/gdtoa/gdtoa.h" testonly char *testlib_formatfloat(long double x) { - char buf[32]; - char *str = malloc(256); - g_xfmt_p(buf, &x, 15, sizeof(buf), 0); - sprintf(str, "%Lf (%s)", x, buf); - return str; + return xasprintf("%.15Lg", x); } diff --git a/libc/tinymath/atanh.c b/libc/tinymath/atanh.c index 7927aa709..3548943d4 100644 --- a/libc/tinymath/atanh.c +++ b/libc/tinymath/atanh.c @@ -22,5 +22,5 @@ * Returns inverse hyperbolic tangent of 𝑥. */ double atanh(double x) { - return log((1 + x) / (1 - x)) / 2; + return x ? log((1 + x) / (1 - x)) / 2 : x; } diff --git a/libc/tinymath/atanhf.c b/libc/tinymath/atanhf.c index 702a4ae34..ef27074bf 100644 --- a/libc/tinymath/atanhf.c +++ b/libc/tinymath/atanhf.c @@ -22,5 +22,5 @@ * Returns inverse hyperbolic tangent of 𝑥. */ float atanhf(float x) { - return logf((1 + x) / (1 - x)) / 2; + return x ? logf((1 + x) / (1 - x)) / 2 : x; } diff --git a/libc/tinymath/atanhl.c b/libc/tinymath/atanhl.c index 54baf9bc4..a88347d18 100644 --- a/libc/tinymath/atanhl.c +++ b/libc/tinymath/atanhl.c @@ -22,5 +22,5 @@ * Returns inverse hyperbolic tangent of 𝑥. */ long double atanhl(long double x) { - return logl((1 + x) / (1 - x)) / 2; + return x ? logl((1 + x) / (1 - x)) / 2 : x; } diff --git a/libc/tinymath/expm1l.S b/libc/tinymath/expm1l.S index d12f779d6..f5852d861 100644 --- a/libc/tinymath/expm1l.S +++ b/libc/tinymath/expm1l.S @@ -19,7 +19,7 @@ #include "libc/runtime/pc.internal.h" #include "libc/macros.internal.h" -// Returns 𝑒^x-1. +// Returns 𝑒^𝑥-𝟷. // // @param 𝑥 is an 80-bit long double passed on stack in 16-bytes // @return result of exponentiation on FPU stack in %st @@ -27,11 +27,13 @@ expm1l: push %rbp mov %rsp,%rbp .profilable fldt 16(%rbp) - fxam # isinf(x) + fxam fstsw %ax mov %ah,%al - and $0x45,%ah - cmp $5,%ah + and $(FPU_C3|FPU_C2|FPU_C0)>>8,%ah + cmp $(FPU_C3)>>8,%ah # !x + je 0f + cmp $(FPU_C2|FPU_C0)>>8,%ah # isinf(x) je 1f fldl2e fmulp %st,%st(1) @@ -50,7 +52,7 @@ expm1l: push %rbp faddp %st,%st(1) 0: pop %rbp ret -1: test $2,%al # signbit(x) +1: test $FPU_C1>>8,%al # signbit(x) jz 0b fstp %st fld1 diff --git a/libc/tinymath/powl.c b/libc/tinymath/powl.c index 9ecdc23dd..e2a58a23b 100644 --- a/libc/tinymath/powl.c +++ b/libc/tinymath/powl.c @@ -46,7 +46,11 @@ long double powl(long double x, long double y) { return 1; } } else if (y > 0) { - return y == 1 ? x : 0; + if (signbit(x) && y == truncl(y) && ((int64_t)y & 1)) { + return -0.; + } else { + return 0; + } } else if (!y) { return 1; } else { diff --git a/libc/tinymath/sinh.c b/libc/tinymath/sinh.c index 6cab29aa8..f0e998b7e 100644 --- a/libc/tinymath/sinh.c +++ b/libc/tinymath/sinh.c @@ -22,5 +22,6 @@ * Returns hyperbolic sine of 𝑥. */ double sinh(double x) { + if (!x) return x; return (exp(x) - exp(-x)) / 2; } diff --git a/libc/tinymath/sinhf.c b/libc/tinymath/sinhf.c index db7088279..73a013c22 100644 --- a/libc/tinymath/sinhf.c +++ b/libc/tinymath/sinhf.c @@ -22,5 +22,6 @@ * Returns hyperbolic sine of 𝑥. */ float sinhf(float x) { + if (!x) return x; return (expf(x) - expf(-x)) / 2; } diff --git a/libc/tinymath/sinhl.c b/libc/tinymath/sinhl.c index 16c79e330..c2a09d892 100644 --- a/libc/tinymath/sinhl.c +++ b/libc/tinymath/sinhl.c @@ -22,5 +22,6 @@ * Returns hyperbolic sine of 𝑥. */ long double sinhl(long double x) { + if (!x) return x; return (expl(x) - expl(-x)) / 2; } diff --git a/libc/tinymath/tanh.c b/libc/tinymath/tanh.c index 8139d00f0..5ae19c19f 100644 --- a/libc/tinymath/tanh.c +++ b/libc/tinymath/tanh.c @@ -22,6 +22,7 @@ * Returns hyperbolic tangent of 𝑥. */ double tanh(double x) { + if (!x) return x; if (isinf(x)) return copysign(1, x); return sinh(x) / cosh(x); } diff --git a/libc/tinymath/tanhf.c b/libc/tinymath/tanhf.c index aef44313f..d9f491de7 100644 --- a/libc/tinymath/tanhf.c +++ b/libc/tinymath/tanhf.c @@ -22,6 +22,7 @@ * Returns hyperbolic tangent of 𝑥. */ float tanhf(float x) { + if (!x) return x; if (isinf(x)) return copysignf(1, x); return sinhf(x) / coshf(x); } diff --git a/libc/tinymath/tanhl.c b/libc/tinymath/tanhl.c index 3c76761bf..7d0a41e01 100644 --- a/libc/tinymath/tanhl.c +++ b/libc/tinymath/tanhl.c @@ -22,6 +22,7 @@ * Returns hyperbolic tangent of 𝑥. */ long double tanhl(long double x) { + if (!x) return x; if (isinf(x)) return copysignl(1, x); return sinhl(x) / coshl(x); } diff --git a/test/libc/tinymath/atan2_test.c b/test/libc/tinymath/atan2_test.c index 82350d494..976ff5f2f 100644 --- a/test/libc/tinymath/atan2_test.c +++ b/test/libc/tinymath/atan2_test.c @@ -282,6 +282,11 @@ TEST(atan2, test) { gc(xasprintf("%.15g", atan2(__DBL_MAX__, __DBL_MIN__)))); EXPECT_STREQ("0.785398163397448", gc(xasprintf("%.15g", atan2(__DBL_MAX__, __DBL_MAX__)))); + EXPECT_STREQ("-0", + gc(xasprintf("%.15g", atan2(-0.000000000000001, INFINITY)))); + EXPECT_STREQ("-0", gc(xasprintf("%.15g", atan2(-1, INFINITY)))); + EXPECT_STREQ( + "-0", gc(xasprintf("%.15g", atan2(-1.7976931348623157e308, INFINITY)))); } BENCH(atan2, bench) { diff --git a/test/libc/tinymath/atanh_test.c b/test/libc/tinymath/atanh_test.c index 2f7de8c53..f096cc212 100644 --- a/test/libc/tinymath/atanh_test.c +++ b/test/libc/tinymath/atanh_test.c @@ -27,6 +27,7 @@ TEST(atanh, test) { EXPECT_STREQ("0", gc(xdtoa(atanh(0)))); + EXPECT_STREQ("-0", gc(xdtoa(atanh(-0.)))); EXPECT_STREQ(".549306144334055", gc(xdtoa(atanh(.5)))); EXPECT_STREQ("-.549306144334055", gc(xdtoa(atanh(-.5)))); EXPECT_STREQ("INFINITY", gc(xdtoa(atanh(+1)))); @@ -37,6 +38,7 @@ TEST(atanh, test) { TEST(atanhl, test) { EXPECT_STREQ("0", gc(xdtoal(atanhl(0)))); + EXPECT_STREQ("-0", gc(xdtoal(atanhl(-0.)))); EXPECT_STREQ(".5493061443340548", gc(xdtoal(atanhl(.5)))); EXPECT_STREQ("-.5493061443340548", gc(xdtoal(atanhl(-.5)))); EXPECT_STREQ("INFINITY", gc(xdtoal(atanhl(+1)))); @@ -47,6 +49,7 @@ TEST(atanhl, test) { TEST(atanhf, test) { EXPECT_STREQ("0", gc(xdtoaf(atanhf(0)))); + EXPECT_STREQ("-0", gc(xdtoaf(atanhf(-0.)))); EXPECT_STREQ(".549306", gc(xdtoaf(atanhf(.5)))); EXPECT_STREQ("-.549306", gc(xdtoaf(atanhf(-.5)))); EXPECT_STREQ("INFINITY", gc(xdtoaf(atanhf(+1)))); diff --git a/test/libc/tinymath/expm1_test.c b/test/libc/tinymath/expm1_test.c index 2da3221c6..2d218a26f 100644 --- a/test/libc/tinymath/expm1_test.c +++ b/test/libc/tinymath/expm1_test.c @@ -25,11 +25,37 @@ #define expm1(x) expm1(VEIL("x", (double)(x))) #define expm1f(x) expm1f(VEIL("x", (float)(x))) +TEST(expm1, test) { + EXPECT_STREQ("0", gc(xdtoa(expm1(0)))); + EXPECT_STREQ("-0", gc(xdtoa(expm1(-0.)))); + EXPECT_STREQ("NAN", gc(xdtoa(expm1(NAN)))); + EXPECT_STREQ("-1", gc(xdtoa(expm1(-INFINITY)))); + EXPECT_STREQ("INFINITY", gc(xdtoa(expm1(INFINITY)))); + /* EXPECT_STREQ("-INFINITY", gc(xdtoa(expm1(-132098844872390)))); */ + /* EXPECT_STREQ("INFINITY", gc(xdtoa(expm1(132098844872390)))); */ + EXPECT_STREQ("0", gc(xasprintf("%.15g", expm1(0.)))); + EXPECT_STREQ("-0", gc(xasprintf("%.15g", expm1(-0.)))); + EXPECT_STREQ("0.648721270700128", gc(xasprintf("%.15g", expm1(.5)))); + EXPECT_STREQ("-0.393469340287367", gc(xasprintf("%.15g", expm1(-.5)))); + EXPECT_STREQ("1.71828182845905", gc(xasprintf("%.15g", expm1(1.)))); + EXPECT_STREQ("-0.632120558828558", gc(xasprintf("%.15g", expm1(-1.)))); + EXPECT_STREQ("3.48168907033806", gc(xasprintf("%.15g", expm1(1.5)))); + EXPECT_STREQ("-0.77686983985157", gc(xasprintf("%.15g", expm1(-1.5)))); + EXPECT_STREQ("6.38905609893065", gc(xasprintf("%.15g", expm1(2.)))); + EXPECT_TRUE(isnan(expm1(NAN))); + EXPECT_TRUE(isnan(expm1(-NAN))); + EXPECT_STREQ("inf", gc(xasprintf("%.15g", expm1(INFINITY)))); + EXPECT_STREQ("-1", gc(xasprintf("%.15g", expm1(-INFINITY)))); + EXPECT_STREQ("2.2250738585072e-308", + gc(xasprintf("%.15g", expm1(__DBL_MIN__)))); + EXPECT_STREQ("inf", gc(xasprintf("%.15g", expm1(__DBL_MAX__)))); +} + TEST(expm1l, test) { EXPECT_STREQ("1.718281828459045", gc(xdtoal(expm1l(1)))); EXPECT_STREQ("1.718281828459045", gc(xdtoal(expl(1) - 1))); EXPECT_STREQ("0", gc(xdtoal(expm1l(0)))); - EXPECT_STREQ("0", gc(xdtoal(expm1l(-0.)))); + EXPECT_STREQ("-0", gc(xdtoal(expm1l(-0.)))); EXPECT_STREQ("NAN", gc(xdtoal(expm1l(NAN)))); EXPECT_STREQ("-1", gc(xdtoal(expm1l(-INFINITY)))); EXPECT_STREQ("INFINITY", gc(xdtoal(expm1l(INFINITY)))); @@ -37,19 +63,9 @@ TEST(expm1l, test) { /* EXPECT_STREQ("INFINITY", gc(xdtoal(expm1l(132098844872390)))); */ } -TEST(expm1, test) { - EXPECT_STREQ("0", gc(xdtoa(expm1(0)))); - EXPECT_STREQ("0", gc(xdtoa(expm1(-0.)))); - EXPECT_STREQ("NAN", gc(xdtoa(expm1(NAN)))); - EXPECT_STREQ("-1", gc(xdtoa(expm1(-INFINITY)))); - EXPECT_STREQ("INFINITY", gc(xdtoa(expm1(INFINITY)))); - /* EXPECT_STREQ("-INFINITY", gc(xdtoa(expm1(-132098844872390)))); */ - /* EXPECT_STREQ("INFINITY", gc(xdtoa(expm1(132098844872390)))); */ -} - TEST(expm1f, test) { EXPECT_STREQ("0", gc(xdtoaf(expm1f(0)))); - EXPECT_STREQ("0", gc(xdtoaf(expm1f(-0.)))); + EXPECT_STREQ("-0", gc(xdtoaf(expm1f(-0.)))); EXPECT_STREQ("NAN", gc(xdtoaf(expm1f(NAN)))); EXPECT_STREQ("-1", gc(xdtoaf(expm1f(-INFINITY)))); EXPECT_STREQ("INFINITY", gc(xdtoaf(expm1f(INFINITY)))); diff --git a/test/libc/tinymath/powl_test.c b/test/libc/tinymath/powl_test.c index 971ecf22b..2922692f0 100644 --- a/test/libc/tinymath/powl_test.c +++ b/test/libc/tinymath/powl_test.c @@ -100,6 +100,8 @@ TEST(powl, test) { EXPECT_TRUE(isnan(powl(-3, -(1. / MAX(rando, 2))))); EXPECT_STREQ("-.3333333333333333", gc(xdtoal(powl(-3, -1)))); EXPECT_STREQ(".1111111111111111", gc(xdtoal(powl(-3, -2)))); + EXPECT_STREQ("-0", gc(xdtoal(powl(-0., MAX(1, rando) | 1)))); + EXPECT_STREQ("0", gc(xdtoal(powl(-0., MAX(1, rando) & ~1)))); } TEST(pow, test) { @@ -150,6 +152,8 @@ TEST(pow, test) { EXPECT_STREQ("inf", fmtd(pow(-0., -(rando & -2)))); EXPECT_STREQ("-0.333333333333333", fmtd(pow(-3, -1))); EXPECT_STREQ("0.111111111111111", fmtd(pow(-3, -2))); + EXPECT_STREQ("-0", gc(xdtoa(pow(-0., MAX(1, rando) | 1)))); + EXPECT_STREQ("0", gc(xdtoa(pow(-0., MAX(1, rando) & ~1)))); } TEST(powf, test) { @@ -200,6 +204,8 @@ TEST(powf, test) { EXPECT_STREQ("inf", fmtf(powf(-0., -(rando & -2)))); EXPECT_STREQ("-0.333333", fmtf(powf(-3, -1))); EXPECT_STREQ("0.111111", fmtf(powf(-3, -2))); + EXPECT_STREQ("-0", gc(xdtoaf(powf(-0., MAX(1, rando) | 1)))); + EXPECT_STREQ("0", gc(xdtoaf(powf(-0., MAX(1, rando) & ~1)))); } TEST(powl, errors) { @@ -537,6 +543,15 @@ TEST(powl, errors) { errno = 0; EXPECT_STREQ("inf", fmtd(pow(__DBL_MAX__, __DBL_MAX__))); /* EXPECT_EQ(ERANGE, errno); */ + EXPECT_STREQ("1", gc(xasprintf("%.15g", pow(0., 0)))); + EXPECT_STREQ("1", gc(xasprintf("%.15g", pow(-0., 0)))); + EXPECT_STREQ("-0", gc(xasprintf("%.15g", pow(-0., 1)))); + EXPECT_STREQ("-0", gc(xasprintf("%.15g", pow(-0., 11)))); + EXPECT_STREQ("-0", gc(xasprintf("%.15g", pow(-0., 111)))); + EXPECT_STREQ("0", gc(xasprintf("%.15g", pow(-0., 2)))); + EXPECT_STREQ("0", gc(xasprintf("%.15g", pow(-0., 22)))); + EXPECT_STREQ("0", gc(xasprintf("%.15g", pow(-0., 222)))); + EXPECT_STREQ("0", gc(xasprintf("%.15g", pow(-0., 2.5)))); } BENCH(powl, bench) { diff --git a/test/libc/tinymath/sinh_test.c b/test/libc/tinymath/sinh_test.c index 6cdbe9845..653bb560b 100644 --- a/test/libc/tinymath/sinh_test.c +++ b/test/libc/tinymath/sinh_test.c @@ -31,6 +31,7 @@ TEST(sinh, test) { EXPECT_STREQ("INFINITY", gc(xdtoa(sinh(30000)))); EXPECT_STREQ("-INFINITY", gc(xdtoa(sinh(-30000)))); EXPECT_STREQ("0", gc(xdtoa(sinh(0)))); + EXPECT_STREQ("-0", gc(xdtoa(sinh(-0.)))); EXPECT_STREQ("NAN", gc(xdtoa(sinh(NAN)))); EXPECT_STREQ("INFINITY", gc(xdtoa(sinh(INFINITY)))); EXPECT_STREQ("-INFINITY", gc(xdtoa(sinh(-INFINITY)))); @@ -42,6 +43,7 @@ TEST(sinhl, test) { EXPECT_STREQ("INFINITY", gc(xdtoal(sinhl(30000)))); EXPECT_STREQ("-INFINITY", gc(xdtoal(sinhl(-30000)))); EXPECT_STREQ("0", gc(xdtoal(sinhl(0)))); + EXPECT_STREQ("-0", gc(xdtoal(sinhl(-0.)))); EXPECT_STREQ("NAN", gc(xdtoal(sinhl(NAN)))); EXPECT_STREQ("INFINITY", gc(xdtoal(sinhl(INFINITY)))); EXPECT_STREQ("-INFINITY", gc(xdtoal(sinhl(-INFINITY)))); @@ -53,6 +55,7 @@ TEST(sinhf, test) { EXPECT_STREQ("INFINITY", gc(xdtoaf(sinhf(30000)))); EXPECT_STREQ("-INFINITY", gc(xdtoaf(sinhf(-30000)))); EXPECT_STREQ("0", gc(xdtoaf(sinhf(0)))); + EXPECT_STREQ("-0", gc(xdtoaf(sinhf(-0.)))); EXPECT_STREQ("NAN", gc(xdtoaf(sinhf(NAN)))); EXPECT_STREQ("INFINITY", gc(xdtoaf(sinhf(INFINITY)))); EXPECT_STREQ("-INFINITY", gc(xdtoaf(sinhf(-INFINITY)))); diff --git a/test/libc/tinymath/strtod_test.c b/test/libc/tinymath/strtod_test.c new file mode 100644 index 000000000..f6ee4fdc8 --- /dev/null +++ b/test/libc/tinymath/strtod_test.c @@ -0,0 +1,57 @@ +/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ +│ │ +│ 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. │ +╚─────────────────────────────────────────────────────────────────────────────*/ +#include "libc/runtime/fenv.h" +#include "libc/runtime/gc.internal.h" +#include "libc/testlib/testlib.h" +#include "libc/x/x.h" +#include "third_party/gdtoa/gdtoa.h" + +int oldround; + +void SetUp(void) { + oldround = fegetround(); +} + +void TearDown(void) { + fesetround(oldround); +} + +TEST(strtod, testNearest) { + fesetround(FE_TONEAREST); + EXPECT_STREQ("-1.79769313486231e+308", + gc(xasprintf("%.15g", strtod("-1.79769313486231e+308", NULL)))); +} + +TEST(strtod, testDownward) { + fesetround(FE_DOWNWARD); + EXPECT_STREQ("-1.79769313486232e+308", + gc(xasprintf("%.15g", strtod("-1.79769313486231e+308", NULL)))); +} + +TEST(strtod, testUpward) { + fesetround(FE_UPWARD); + EXPECT_STREQ("-1.7976931348623e+308", + gc(xasprintf("%.15g", strtod("-1.79769313486231e+308", NULL)))); +} + +TEST(strtod, testTowardzero) { + fesetround(FE_TOWARDZERO); + EXPECT_STREQ("-1.7976931348623e+308", + gc(xasprintf("%.15g", strtod("-1.79769313486231e+308", NULL)))); +} diff --git a/test/libc/tinymath/tanh_test.c b/test/libc/tinymath/tanh_test.c index b1a59544d..65f922d0f 100644 --- a/test/libc/tinymath/tanh_test.c +++ b/test/libc/tinymath/tanh_test.c @@ -29,6 +29,7 @@ TEST(tanhl, test) { EXPECT_STREQ(".09966799462495582", gc(xdtoal(tanhl(+.1)))); EXPECT_STREQ("-.09966799462495582", gc(xdtoal(tanhl(-.1)))); EXPECT_STREQ("0", gc(xdtoal(tanhl(0)))); + EXPECT_STREQ("-0", gc(xdtoal(tanhl(-0.)))); EXPECT_TRUE(isnan(tanhl(NAN))); EXPECT_STREQ("1", gc(xdtoal(tanhl(INFINITY)))); EXPECT_STREQ("-1", gc(xdtoal(tanhl(-INFINITY)))); @@ -38,6 +39,7 @@ TEST(tanh, test) { EXPECT_STREQ(".0996679946249559", gc(xdtoa(tanh(+.1)))); EXPECT_STREQ("-.0996679946249559", gc(xdtoa(tanh(-.1)))); EXPECT_STREQ("0", gc(xdtoa(tanh(0)))); + EXPECT_STREQ("-0", gc(xdtoa(tanh(-0.)))); EXPECT_TRUE(isnan(tanh(NAN))); EXPECT_STREQ("1", gc(xdtoa(tanh(INFINITY)))); EXPECT_STREQ("-1", gc(xdtoa(tanh(-INFINITY)))); @@ -47,6 +49,7 @@ TEST(tanhf, test) { EXPECT_STREQ(".099668", gc(xdtoaf(tanhf(+.1)))); EXPECT_STREQ("-.099668", gc(xdtoaf(tanhf(-.1)))); EXPECT_STREQ("0", gc(xdtoaf(tanhf(0)))); + EXPECT_STREQ("-0", gc(xdtoaf(tanhf(-0.)))); EXPECT_TRUE(isnan(tanhf(NAN))); EXPECT_STREQ("1", gc(xdtoaf(tanhf(INFINITY)))); EXPECT_STREQ("-1", gc(xdtoaf(tanhf(-INFINITY)))); diff --git a/test/libc/tinymath/test.mk b/test/libc/tinymath/test.mk index 641693130..4feea7a30 100644 --- a/test/libc/tinymath/test.mk +++ b/test/libc/tinymath/test.mk @@ -37,7 +37,8 @@ TEST_LIBC_TINYMATH_DIRECTDEPS = \ LIBC_TESTLIB \ LIBC_TINYMATH \ LIBC_UNICODE \ - LIBC_X + LIBC_X \ + THIRD_PARTY_GDTOA TEST_LIBC_TINYMATH_DEPS := \ $(call uniq,$(foreach x,$(TEST_LIBC_TINYMATH_DIRECTDEPS),$($(x)))) diff --git a/third_party/gdtoa/gdtoa.internal.h b/third_party/gdtoa/gdtoa.internal.h index 0a74b0556..970015a47 100644 --- a/third_party/gdtoa/gdtoa.internal.h +++ b/third_party/gdtoa/gdtoa.internal.h @@ -18,6 +18,9 @@ asm(".include \"libc/disclaimer.inc\""); #define d_QNAN0 0x7ff80000 #define d_QNAN1 0x0 +#define Check_FLT_ROUNDS 1 +#define Trust_FLT_ROUNDS 1 + /**************************************************************** The author of this software is David M. Gay. diff --git a/third_party/gdtoa/gdtoa.mk b/third_party/gdtoa/gdtoa.mk index d9e15e57b..c253ef9a6 100644 --- a/third_party/gdtoa/gdtoa.mk +++ b/third_party/gdtoa/gdtoa.mk @@ -46,13 +46,6 @@ $(THIRD_PARTY_GDTOA_A).pkg: \ $(THIRD_PARTY_GDTOA_A_OBJS) \ $(foreach x,$(THIRD_PARTY_GDTOA_A_DIRECTDEPS),$($(x)_A).pkg) -$(THIRD_PARTY_GDTOA_A_OBJS): \ - OVERRIDE_CFLAGS += \ - $(OLD_CODE) \ - $(IEEE_MATH) \ - -ffunction-sections \ - -fdata-sections - THIRD_PARTY_GDTOA_LIBS = $(foreach x,$(THIRD_PARTY_GDTOA_ARTIFACTS),$($(x))) THIRD_PARTY_GDTOA_SRCS = $(foreach x,$(THIRD_PARTY_GDTOA_ARTIFACTS),$($(x)_SRCS)) THIRD_PARTY_GDTOA_HDRS = $(foreach x,$(THIRD_PARTY_GDTOA_ARTIFACTS),$($(x)_HDRS)) diff --git a/third_party/gdtoa/strtod.c b/third_party/gdtoa/strtod.c index 1080b6b34..19f2de989 100644 --- a/third_party/gdtoa/strtod.c +++ b/third_party/gdtoa/strtod.c @@ -729,7 +729,7 @@ strtod(CONST char *s00, char **se) } #endif /*Sudden_Underflow*/ #endif /*Avoid_Underflow*/ - dval(&adj) *= ulp(&rv); + dval(&adj) *= ulp(&rv); /* XXX */ if (dsign) { if (word0(&rv) == Big0 && word1(&rv) == Big1) goto ovfl; diff --git a/third_party/lua/lua.mk b/third_party/lua/lua.mk index b2628de9b..50a78b0ec 100644 --- a/third_party/lua/lua.mk +++ b/third_party/lua/lua.mk @@ -41,7 +41,7 @@ THIRD_PARTY_LUA_DEPS := \ $(THIRD_PARTY_LUA_A): \ third_party/lua/ \ $(THIRD_PARTY_LUA_A).pkg \ - $(filter-out %/lua.c,$(THIRD_PARTY_LUA_OBJS)) + $(filter-out %/lua.o,$(THIRD_PARTY_LUA_OBJS)) $(THIRD_PARTY_LUA_A).pkg: \ $(THIRD_PARTY_LUA_OBJS) \ diff --git a/third_party/musl/ftw.c b/third_party/musl/ftw.c index ee4c54b22..51622cb51 100644 --- a/third_party/musl/ftw.c +++ b/third_party/musl/ftw.c @@ -34,6 +34,12 @@ asm(".include \"libc/disclaimer.inc\""); /* clang-format off */ +/** + * Walks file tree. + * + * @see examples/walk.c for example + * @see nftw() + */ int ftw(const char *path, int (*fn)(const char *, const struct stat *, int), int fd_limit) { /* The following cast assumes that calling a function with one diff --git a/third_party/musl/nftw.c b/third_party/musl/nftw.c index 15a491df8..21d31ff51 100644 --- a/third_party/musl/nftw.c +++ b/third_party/musl/nftw.c @@ -38,7 +38,13 @@ Musl libc (MIT License)\\n\ Copyright 2005-2014 Rich Felker, et. al.\""); asm(".include \"libc/disclaimer.inc\""); -#define pthread_setcancelstate(...) /* no cosmo pthreads support atm */ +/* no reason to impose windows limit + small enough to fit in stack frame + should be changed to use realloc */ +#define PATH_MAX2 2048 + +/* no cosmo pthreads support atm */ +#define pthread_setcancelstate(...) /* clang-format off */ @@ -123,7 +129,7 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, && (!de->d_name[1] || (de->d_name[1]=='.' && !de->d_name[2]))) continue; - if (strlen(de->d_name) >= PATH_MAX-l) { + if (strlen(de->d_name) >= PATH_MAX2-l) { errno = ENAMETOOLONG; closedir(d); return -1; @@ -149,16 +155,21 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, return 0; } +/** + * Walks file tree. + * + * @see examples/walk.c for example + */ int nftw(const char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int fd_limit, int flags) { int r, cs; size_t l; - char pathbuf[PATH_MAX+1]; + char pathbuf[PATH_MAX2+1]; if (fd_limit <= 0) return 0; l = strlen(path); - if (l > PATH_MAX) { + if (l > PATH_MAX2) { errno = ENAMETOOLONG; return -1; } diff --git a/third_party/quickjs/README.cosmo b/third_party/quickjs/README.cosmo index 072d819e9..c8f7ab916 100644 --- a/third_party/quickjs/README.cosmo +++ b/third_party/quickjs/README.cosmo @@ -1,2 +1,7 @@ Source: -https://bellard.org/quickjs/quickjs-2021-03-27.tar.xz +- https://bellard.org/quickjs/quickjs-2021-03-27.tar.xz + +Local Changes: +- Replace snprintf with xasprintf in find_unique_cname +- Squash uninitialized read of harnessbuf in run-test262.c +- Change run-test262.c to not rebase configured paths diff --git a/third_party/quickjs/quickjs-libc.c b/third_party/quickjs/quickjs-libc.c index 32dcc53f8..cea3b1bad 100644 --- a/third_party/quickjs/quickjs-libc.c +++ b/third_party/quickjs/quickjs-libc.c @@ -2764,61 +2764,6 @@ static char **build_envp(JSContext *ctx, JSValueConst obj) goto done; } -/* execvpe is not available on non GNU systems */ -static int my_execvpe(const char *filename, char **argv, char **envp) -{ - char *path, *p, *p_next, *p1; - char buf[PATH_MAX]; - size_t filename_len, path_len; - BOOL eacces_error; - - filename_len = strlen(filename); - if (filename_len == 0) { - errno = ENOENT; - return -1; - } - if (strchr(filename, '/')) - return execve(filename, argv, envp); - - path = getenv("PATH"); - if (!path) - path = (char *)"/bin:/usr/bin"; - eacces_error = FALSE; - p = path; - for(p = path; p != NULL; p = p_next) { - p1 = strchr(p, ':'); - if (!p1) { - p_next = NULL; - path_len = strlen(p); - } else { - p_next = p1 + 1; - path_len = p1 - p; - } - /* path too long */ - if ((path_len + 1 + filename_len + 1) > PATH_MAX) - continue; - memcpy(buf, p, path_len); - buf[path_len] = '/'; - memcpy(buf + path_len + 1, filename, filename_len); - buf[path_len + 1 + filename_len] = '\0'; - - execve(buf, argv, envp); - - if (errno == EACCES) { - eacces_error = TRUE; - } else if (errno == ENOENT) { - /* do nothing */ - } else if (errno == ENOTDIR) { - /* do nothing */ - } else { - return -1; - } - } - if (eacces_error) - errno = EACCES; - return -1; -} - /* exec(args[, options]) -> exitcode */ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) @@ -2973,7 +2918,7 @@ static JSValue js_os_exec(JSContext *ctx, JSValueConst this_val, if (!file) file = exec_argv[0]; if (use_path) - ret = my_execvpe(file, (char **)exec_argv, envp); + ret = execvpe(file, (char **)exec_argv, envp); else ret = execve(file, (char **)exec_argv, envp); _exit(127); diff --git a/third_party/quickjs/quickjs.c b/third_party/quickjs/quickjs.c index bcec9cc48..1935e0cec 100644 --- a/third_party/quickjs/quickjs.c +++ b/third_party/quickjs/quickjs.c @@ -11296,11 +11296,11 @@ static char *i64toa(char *buf_end, int64_t n, unsigned int base) static void js_ecvt1(double d, int n_digits, int *decpt, int *sign, char *buf, int rounding_mode, char *buf1, int buf1_size) { - /* if (rounding_mode != FE_TONEAREST) */ - /* fesetround(rounding_mode); */ + if (rounding_mode != FE_TONEAREST) + fesetround(rounding_mode); snprintf(buf1, buf1_size, "%+.*e", n_digits - 1, d); - /* if (rounding_mode != FE_TONEAREST) */ - /* fesetround(FE_TONEAREST); */ + if (rounding_mode != FE_TONEAREST) + fesetround(FE_TONEAREST); *sign = (buf1[0] == '-'); /* mantissa */ buf[0] = buf1[1]; @@ -53608,12 +53608,12 @@ static JSValue js_atomics_op(JSContext *ctx, a = func_name((_Atomic(uint32_t) *)ptr, v); \ break; #endif - /* OP(ADD, atomic_fetch_add) */ - /* OP(AND, atomic_fetch_and) */ - /* OP(OR, atomic_fetch_or) */ - /* OP(SUB, atomic_fetch_sub) */ - /* OP(XOR, atomic_fetch_xor) */ - /* OP(EXCHANGE, atomic_exchange) */ + OP(ADD, atomic_fetch_add) + OP(AND, atomic_fetch_and) + OP(OR, atomic_fetch_or) + OP(SUB, atomic_fetch_sub) + OP(XOR, atomic_fetch_xor) + OP(EXCHANGE, atomic_exchange) #undef OP case ATOMICS_OP_LOAD | (0 << 3): diff --git a/third_party/quickjs/quickjs.mk b/third_party/quickjs/quickjs.mk index 494e1d93f..f278b6eb5 100644 --- a/third_party/quickjs/quickjs.mk +++ b/third_party/quickjs/quickjs.mk @@ -3,83 +3,151 @@ PKGS += THIRD_PARTY_QUICKJS -THIRD_PARTY_QUICKJS_FILES := $(wildcard third_party/quickjs/*) -THIRD_PARTY_QUICKJS_SRCS = $(filter %.c,$(THIRD_PARTY_QUICKJS_FILES)) -THIRD_PARTY_QUICKJS_HDRS = $(filter %.h,$(THIRD_PARTY_QUICKJS_FILES)) +THIRD_PARTY_QUICKJS_ARTIFACTS += THIRD_PARTY_QUICKJS_A THIRD_PARTY_QUICKJS_BINS = $(THIRD_PARTY_QUICKJS_COMS) $(THIRD_PARTY_QUICKJS_COMS:%=%.dbg) -THIRD_PARTY_QUICKJS = $(THIRD_PARTY_QUICKJS_DEPS) $(THIRD_PARTY_QUICKJS_A) +THIRD_PARTY_QUICKJS = $(THIRD_PARTY_QUICKJS_A_DEPS) $(THIRD_PARTY_QUICKJS_A) THIRD_PARTY_QUICKJS_A = o/$(MODE)/third_party/quickjs/quickjs.a +THIRD_PARTY_QUICKJS_HDRS = $(foreach x,$(THIRD_PARTY_QUICKJS_ARTIFACTS),$($(x)_HDRS)) -THIRD_PARTY_QUICKJS_OBJS = \ - $(THIRD_PARTY_QUICKJS_SRCS:%.c=o/$(MODE)/%.o) +THIRD_PARTY_QUICKJS_A_SRCS = \ + third_party/quickjs/cutils.c \ + third_party/quickjs/libbf.c \ + third_party/quickjs/libregexp.c \ + third_party/quickjs/libunicode.c \ + third_party/quickjs/quickjs-libc.c \ + third_party/quickjs/quickjs.c \ + third_party/quickjs/wut.c -THIRD_PARTY_QUICKJS_COMS = \ - o/$(MODE)/third_party/quickjs/qjs.com +THIRD_PARTY_QUICKJS_A_HDRS = \ + third_party/quickjs/cutils.h \ + third_party/quickjs/libbf.h \ + third_party/quickjs/libregexp.h \ + third_party/quickjs/libunicode.h \ + third_party/quickjs/list.h \ + third_party/quickjs/quickjs-libc.h \ + third_party/quickjs/quickjs.h -THIRD_PARTY_QUICKJS_CHECKS = \ - $(THIRD_PARTY_QUICKJS_A).pkg \ - $(THIRD_PARTY_QUICKJS_HDRS:%=o/$(MODE)/%.ok) +THIRD_PARTY_QUICKJS_A_OBJS = \ + o/$(MODE)/third_party/quickjs/cutils.o \ + o/$(MODE)/third_party/quickjs/libbf.o \ + o/$(MODE)/third_party/quickjs/libregexp.o \ + o/$(MODE)/third_party/quickjs/libunicode.o \ + o/$(MODE)/third_party/quickjs/quickjs-libc.o \ + o/$(MODE)/third_party/quickjs/quickjs.o \ + o/$(MODE)/third_party/quickjs/wut.o -THIRD_PARTY_QUICKJS_DIRECTDEPS = \ - LIBC_ALG \ - LIBC_CALLS \ - LIBC_FMT \ - LIBC_INTRIN \ - LIBC_LOG \ - LIBC_MEM \ - LIBC_NEXGEN32E \ - LIBC_RUNTIME \ - LIBC_SOCK \ - LIBC_STDIO \ - LIBC_STR \ - LIBC_SYSV \ - LIBC_SYSV_CALLS \ - LIBC_TIME \ - LIBC_TINYMATH \ - LIBC_UNICODE \ - LIBC_X \ - THIRD_PARTY_COMPILER_RT \ - THIRD_PARTY_GDTOA \ - THIRD_PARTY_GETOPT \ +THIRD_PARTY_QUICKJS_A_DIRECTDEPS = \ + LIBC_ALG \ + LIBC_CALLS \ + LIBC_FMT \ + LIBC_INTRIN \ + LIBC_LOG \ + LIBC_MEM \ + LIBC_NEXGEN32E \ + LIBC_RUNTIME \ + LIBC_SOCK \ + LIBC_STDIO \ + LIBC_STR \ + LIBC_SYSV \ + LIBC_SYSV_CALLS \ + LIBC_TIME \ + LIBC_TINYMATH \ + LIBC_UNICODE \ + LIBC_X \ + THIRD_PARTY_COMPILER_RT \ + THIRD_PARTY_GDTOA \ + THIRD_PARTY_GETOPT \ THIRD_PARTY_MUSL -THIRD_PARTY_QUICKJS_DEPS := \ - $(call uniq,$(foreach x,$(THIRD_PARTY_QUICKJS_DIRECTDEPS),$($(x)))) +THIRD_PARTY_QUICKJS_A_DEPS := \ + $(call uniq,$(foreach x,$(THIRD_PARTY_QUICKJS_A_DIRECTDEPS),$($(x)))) -$(THIRD_PARTY_QUICKJS_A): \ - third_party/quickjs/ \ - $(THIRD_PARTY_QUICKJS_A).pkg \ - $(filter-out %/quickjs.c,$(THIRD_PARTY_QUICKJS_OBJS)) +$(THIRD_PARTY_QUICKJS_A): \ + third_party/quickjs/ \ + $(THIRD_PARTY_QUICKJS_A).pkg \ + $(THIRD_PARTY_QUICKJS_A_OBJS) -$(THIRD_PARTY_QUICKJS_A).pkg: \ - $(THIRD_PARTY_QUICKJS_OBJS) \ - $(foreach x,$(THIRD_PARTY_QUICKJS_DIRECTDEPS),$($(x)_A).pkg) +$(THIRD_PARTY_QUICKJS_A).pkg: \ + $(THIRD_PARTY_QUICKJS_A_OBJS) \ + $(foreach x,$(THIRD_PARTY_QUICKJS_A_DIRECTDEPS),$($(x)_A).pkg) -o/$(MODE)/third_party/quickjs/qjs.com.dbg: \ - $(THIRD_PARTY_QUICKJS_DEPS) \ - $(THIRD_PARTY_QUICKJS_A) \ - $(THIRD_PARTY_QUICKJS_A).pkg \ - o/$(MODE)/third_party/quickjs/qjs.o \ - $(CRT) \ +THIRD_PARTY_QUICKJS_SRCS = \ + third_party/quickjs/qjs.c \ + third_party/quickjs/qjsc.c \ + third_party/quickjs/run-test262.c \ + $(foreach x,$(THIRD_PARTY_QUICKJS_ARTIFACTS),$($(x)_SRCS)) + +THIRD_PARTY_QUICKJS_OBJS = \ + o/$(MODE)/third_party/quickjs/qjs.o \ + o/$(MODE)/third_party/quickjs/qjsc.o \ + o/$(MODE)/third_party/quickjs/run-test262.o \ + $(THIRD_PARTY_QUICKJS_A_OBJS) + +THIRD_PARTY_QUICKJS_COMS = \ + o/$(MODE)/third_party/quickjs/qjs.com \ + o/$(MODE)/third_party/quickjs/qjsc.com \ + o/$(MODE)/third_party/quickjs/run-test262.com \ + o/$(MODE)/third_party/quickjs/unicode_gen.com + +THIRD_PARTY_QUICKJS_CHECKS = \ + $(THIRD_PARTY_QUICKJS_A).pkg \ + $(THIRD_PARTY_QUICKJS_A_HDRS:%=o/$(MODE)/%.ok) + +o/$(MODE)/third_party/quickjs/qjs.com.dbg: \ + $(THIRD_PARTY_QUICKJS_A_DEPS) \ + $(THIRD_PARTY_QUICKJS_A) \ + $(THIRD_PARTY_QUICKJS_A).pkg \ + o/$(MODE)/third_party/quickjs/qjs.o \ + $(CRT) \ $(APE) -@$(APELINK) -$(THIRD_PARTY_QUICKJS_OBJS): \ - OVERRIDE_CPPFLAGS += \ - -DCONFIG_BIGNUM \ +o/$(MODE)/third_party/quickjs/qjsc.com.dbg: \ + $(THIRD_PARTY_QUICKJS_A_DEPS) \ + $(THIRD_PARTY_QUICKJS_A) \ + $(THIRD_PARTY_QUICKJS_A).pkg \ + o/$(MODE)/third_party/quickjs/qjsc.o \ + $(CRT) \ + $(APE) + -@$(APELINK) + +# git clone git@github.com:tc39/test262 /opt/test262 +# make -j8 MODE=dbg o/dbg/third_party/quickjs/run-test262.com +# o/dbg/third_party/quickjs/run-test262.com -m -c third_party/quickjs/test262.conf -a +o/$(MODE)/third_party/quickjs/run-test262.com.dbg: \ + $(THIRD_PARTY_QUICKJS_A_DEPS) \ + $(THIRD_PARTY_QUICKJS_A) \ + $(THIRD_PARTY_QUICKJS_A).pkg \ + o/$(MODE)/third_party/quickjs/run-test262.o \ + $(CRT) \ + $(APE) + -@$(APELINK) + +o/$(MODE)/third_party/quickjs/unicode_gen.com.dbg: \ + $(THIRD_PARTY_QUICKJS_A_DEPS) \ + $(THIRD_PARTY_QUICKJS_A) \ + $(THIRD_PARTY_QUICKJS_A).pkg \ + o/$(MODE)/third_party/quickjs/unicode_gen.o \ + $(CRT) \ + $(APE) + -@$(APELINK) + +$(THIRD_PARTY_QUICKJS_OBJS): \ + OVERRIDE_CPPFLAGS += \ + -DCONFIG_BIGNUM \ -DCONFIG_VERSION=\"$(shell cat third_party/quickjs/VERSION)\" -o/$(MODE)/third_party/quickjs/unicode_gen.o: \ - OVERRIDE_CPPFLAGS += \ +o/$(MODE)/third_party/quickjs/unicode_gen.o: \ + OVERRIDE_CPPFLAGS += \ -DSTACK_FRAME_UNLIMITED # TODO(jart): Replace alloca() calls with malloc(). -o/$(MODE)/third_party/quickjs/libregexp.o \ -o/$(MODE)/third_party/quickjs/quickjs.o: \ - OVERRIDE_CPPFLAGS += \ +o/$(MODE)/third_party/quickjs/libregexp.o \ +o/$(MODE)/third_party/quickjs/quickjs.o: \ + OVERRIDE_CPPFLAGS += \ -DSTACK_FRAME_UNLIMITED .PHONY: o/$(MODE)/third_party/quickjs -o/$(MODE)/third_party/quickjs: \ - $(THIRD_PARTY_QUICKJS_BINS) \ +o/$(MODE)/third_party/quickjs: \ + $(THIRD_PARTY_QUICKJS_BINS) \ $(THIRD_PARTY_QUICKJS_CHECKS) diff --git a/third_party/quickjs/run-test262.c b/third_party/quickjs/run-test262.c index f69a28f48..756d43aa8 100644 --- a/third_party/quickjs/run-test262.c +++ b/third_party/quickjs/run-test262.c @@ -931,7 +931,8 @@ void load_config(const char *filename) if (!f) { perror_exit(1, filename); } - base_name = get_basename(filename); + /* base_name = get_basename(filename); */ + base_name = strdup(""); while (fgets(buf, sizeof(buf), f) != NULL) { char *p, *q; @@ -1672,6 +1673,8 @@ int run_test(const char *filename, int index) if (p) { snprintf(harnessbuf, sizeof(harnessbuf), "%.*s%s", (int)(p - filename), filename, "test/harness"); + } else { + strcpy(harnessbuf, ""); /* XXX */ } harness = harnessbuf; } @@ -1947,6 +1950,8 @@ int main(int argc, char **argv) BOOL is_test262_harness = FALSE; BOOL is_module = FALSE; + showcrashreports(); + #if !defined(_WIN32) /* Date tests assume California local time */ setenv("TZ", "America/Los_Angeles", 1); diff --git a/third_party/quickjs/test262.conf b/third_party/quickjs/test262.conf index 6fbb5793a..0a181ef30 100644 --- a/third_party/quickjs/test262.conf +++ b/third_party/quickjs/test262.conf @@ -26,22 +26,22 @@ module=yes verbose=yes # load harness files from this directory -harnessdir=test262/harness +harnessdir=/opt/test262/harness # names of harness include files to skip #harnessexclude= # name of the error file for known errors -errorfile=test262_errors.txt +errorfile=third_party/quickjs/test262_errors.txt # exclude tests enumerated in this file (see also [exclude] section) #excludefile=test262_exclude.txt # report test results to this file -reportfile=test262_report.txt +reportfile=o/test262_report.txt # enumerate tests from this directory -testdir=test262/test +testdir=/opt/test262/test [features] # Standard language features and proposed extensions @@ -184,16 +184,19 @@ __setter__ # list excluded tests and directories here # intl not supported -test262/test/intl402/ +/opt/test262/test/intl402/ # incompatible with the "caller" feature -test262/test/built-ins/Function/prototype/restricted-property-caller.js -test262/test/built-ins/Function/prototype/restricted-property-arguments.js -test262/test/built-ins/ThrowTypeError/unique-per-realm-function-proto.js +/opt/test262/test/built-ins/Function/prototype/restricted-property-caller.js +/opt/test262/test/built-ins/Function/prototype/restricted-property-arguments.js +/opt/test262/test/built-ins/ThrowTypeError/unique-per-realm-function-proto.js # slow tests -#test262/test/built-ins/RegExp/CharacterClassEscapes/ -#test262/test/built-ins/RegExp/property-escapes/ +#/opt/test262/test/built-ins/RegExp/CharacterClassEscapes/ +#/opt/test262/test/built-ins/RegExp/property-escapes/ + +# No threads in Cosmopolitan ATM +/opt/test262/test/built-ins/Atomics/ [tests] # list test files or use config.testdir diff --git a/tool/build/compile.c b/tool/build/compile.c index 647396df4..b52435c5f 100644 --- a/tool/build/compile.c +++ b/tool/build/compile.c @@ -421,6 +421,11 @@ int main(int argc, char *argv[]) { } else if (isclang && startswith(argv[i], "--debug-prefix-map")) { /* llvm doesn't provide a gas interface so simulate w/ clang */ AddArg(xasprintf("-f%s", argv[i] + 2)); + } else if (isgcc && (!strcmp(argv[i], "-Os") || !strcmp(argv[i], "-O2") || + !strcmp(argv[i], "-O3"))) { + /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97623 */ + AddArg(argv[i]); + AddArg("-fno-code-hoisting"); } else { AddArg(argv[i]); }