Merge branch 'master' into issue-30961
This commit is contained in:
commit
cbb88faad7
663 changed files with 15343 additions and 8698 deletions
|
@ -7,6 +7,7 @@ services:
|
||||||
# our configure script, so disable auto submodule management.
|
# our configure script, so disable auto submodule management.
|
||||||
git:
|
git:
|
||||||
submodules: false
|
submodules: false
|
||||||
|
depth: 1
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- docker build -t rust -f src/etc/Dockerfile src/etc
|
- docker build -t rust -f src/etc/Dockerfile src/etc
|
||||||
|
|
12
configure
vendored
12
configure
vendored
|
@ -609,7 +609,7 @@ opt dist-host-only 0 "only install bins for the host architecture"
|
||||||
opt inject-std-version 1 "inject the current compiler version of libstd into programs"
|
opt inject-std-version 1 "inject the current compiler version of libstd into programs"
|
||||||
opt llvm-version-check 1 "check if the LLVM version is supported, build anyway"
|
opt llvm-version-check 1 "check if the LLVM version is supported, build anyway"
|
||||||
opt rustbuild 0 "use the rust and cargo based build system"
|
opt rustbuild 0 "use the rust and cargo based build system"
|
||||||
opt orbit 0 "get MIR where it belongs - everywhere; most importantly, in orbit"
|
opt orbit 1 "get MIR where it belongs - everywhere; most importantly, in orbit"
|
||||||
opt codegen-tests 1 "run the src/test/codegen tests"
|
opt codegen-tests 1 "run the src/test/codegen tests"
|
||||||
opt option-checking 1 "complain about unrecognized options in this configure script"
|
opt option-checking 1 "complain about unrecognized options in this configure script"
|
||||||
opt ninja 0 "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)"
|
opt ninja 0 "build LLVM using the Ninja generator (for MSVC, requires building in the correct environment)"
|
||||||
|
@ -733,7 +733,7 @@ if [ -n "$CFG_ENABLE_DEBUG_ASSERTIONS" ]; then putvar CFG_ENABLE_DEBUG_ASSERTION
|
||||||
if [ -n "$CFG_ENABLE_DEBUGINFO" ]; then putvar CFG_ENABLE_DEBUGINFO; fi
|
if [ -n "$CFG_ENABLE_DEBUGINFO" ]; then putvar CFG_ENABLE_DEBUGINFO; fi
|
||||||
if [ -n "$CFG_ENABLE_DEBUG_JEMALLOC" ]; then putvar CFG_ENABLE_DEBUG_JEMALLOC; fi
|
if [ -n "$CFG_ENABLE_DEBUG_JEMALLOC" ]; then putvar CFG_ENABLE_DEBUG_JEMALLOC; fi
|
||||||
|
|
||||||
if [ -n "$CFG_ENABLE_ORBIT" ]; then putvar CFG_ENABLE_ORBIT; fi
|
if [ -n "$CFG_DISABLE_ORBIT" ]; then putvar CFG_DISABLE_ORBIT; fi
|
||||||
|
|
||||||
step_msg "looking for build programs"
|
step_msg "looking for build programs"
|
||||||
|
|
||||||
|
@ -1020,6 +1020,12 @@ then
|
||||||
err "bad LLVM version: $LLVM_VERSION, need >=3.7"
|
err "bad LLVM version: $LLVM_VERSION, need >=3.7"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
if "$CFG_LLVM_ROOT/bin/llvm-mc" -help | grep -- "-relocation-model"; then
|
||||||
|
msg "found older llvm-mc"
|
||||||
|
CFG_LLVM_MC_HAS_RELOCATION_MODEL=1
|
||||||
|
putvar CFG_LLVM_MC_HAS_RELOCATION_MODEL
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Even when the user overrides the choice of CC, still try to detect
|
# Even when the user overrides the choice of CC, still try to detect
|
||||||
|
@ -1192,7 +1198,7 @@ do
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
|
||||||
x86_64-*-musl)
|
x86_64-*-musl | arm-*-musleabi)
|
||||||
if [ ! -f $CFG_MUSL_ROOT/lib/libc.a ]
|
if [ ! -f $CFG_MUSL_ROOT/lib/libc.a ]
|
||||||
then
|
then
|
||||||
err "musl libc $CFG_MUSL_ROOT/lib/libc.a not found"
|
err "musl libc $CFG_MUSL_ROOT/lib/libc.a not found"
|
||||||
|
|
|
@ -17,7 +17,7 @@ CFG_STATIC_LIB_NAME_aarch64-apple-ios=lib$(1).a
|
||||||
CFG_LIB_DSYM_GLOB_aarch64-apple-ios = lib$(1)-*.a.dSYM
|
CFG_LIB_DSYM_GLOB_aarch64-apple-ios = lib$(1)-*.a.dSYM
|
||||||
CFG_CFLAGS_aarch64-apple-ios := $(CFG_IOS_SDK_FLAGS_aarch64-apple-ios)
|
CFG_CFLAGS_aarch64-apple-ios := $(CFG_IOS_SDK_FLAGS_aarch64-apple-ios)
|
||||||
CFG_JEMALLOC_CFLAGS_aarch64-apple-ios := $(CFG_IOS_SDK_FLAGS_aarch64-apple-ios)
|
CFG_JEMALLOC_CFLAGS_aarch64-apple-ios := $(CFG_IOS_SDK_FLAGS_aarch64-apple-ios)
|
||||||
CFG_GCCISH_CFLAGS_aarch64-apple-ios := -Wall -Werror -fPIC $(CFG_IOS_SDK_FLAGS_aarch64-apple-ios)
|
CFG_GCCISH_CFLAGS_aarch64-apple-ios := -fPIC $(CFG_IOS_SDK_FLAGS_aarch64-apple-ios)
|
||||||
CFG_GCCISH_CXXFLAGS_aarch64-apple-ios := -fno-rtti $(CFG_IOS_SDK_FLAGS_aarch64-apple-ios) -I$(CFG_IOS_SDK_aarch64-apple-ios)/usr/include/c++/4.2.1
|
CFG_GCCISH_CXXFLAGS_aarch64-apple-ios := -fno-rtti $(CFG_IOS_SDK_FLAGS_aarch64-apple-ios) -I$(CFG_IOS_SDK_aarch64-apple-ios)/usr/include/c++/4.2.1
|
||||||
CFG_GCCISH_LINK_FLAGS_aarch64-apple-ios := -lpthread -syslibroot $(CFG_IOS_SDK_aarch64-apple-ios) -Wl,-no_compact_unwind
|
CFG_GCCISH_LINK_FLAGS_aarch64-apple-ios := -lpthread -syslibroot $(CFG_IOS_SDK_aarch64-apple-ios) -Wl,-no_compact_unwind
|
||||||
CFG_GCCISH_DEF_FLAG_aarch64-apple-ios := -Wl,-exported_symbols_list,
|
CFG_GCCISH_DEF_FLAG_aarch64-apple-ios := -Wl,-exported_symbols_list,
|
||||||
|
|
3
mk/cfg/arm-unknown-linux-musleabi.mk
Normal file
3
mk/cfg/arm-unknown-linux-musleabi.mk
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# This file is intentially left empty to indicate that, while this target is
|
||||||
|
# supported, it's not supported using plain GNU Make builds. Use a --rustbuild
|
||||||
|
# instead.
|
3
mk/cfg/arm-unknown-linux-musleabihf.mk
Normal file
3
mk/cfg/arm-unknown-linux-musleabihf.mk
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# This file is intentially left empty to indicate that, while this target is
|
||||||
|
# supported, it's not supported using plain GNU Make builds. Use a --rustbuild
|
||||||
|
# instead.
|
|
@ -15,7 +15,7 @@ CFG_INSTALL_ONLY_RLIB_armv7-apple-ios = 1
|
||||||
CFG_STATIC_LIB_NAME_armv7-apple-ios=lib$(1).a
|
CFG_STATIC_LIB_NAME_armv7-apple-ios=lib$(1).a
|
||||||
CFG_LIB_DSYM_GLOB_armv7-apple-ios = lib$(1)-*.a.dSYM
|
CFG_LIB_DSYM_GLOB_armv7-apple-ios = lib$(1)-*.a.dSYM
|
||||||
CFG_JEMALLOC_CFLAGS_armv7-apple-ios := -arch armv7 -mfpu=vfp3 $(CFG_IOS_SDK_FLAGS_armv7-apple-ios)
|
CFG_JEMALLOC_CFLAGS_armv7-apple-ios := -arch armv7 -mfpu=vfp3 $(CFG_IOS_SDK_FLAGS_armv7-apple-ios)
|
||||||
CFG_GCCISH_CFLAGS_armv7-apple-ios := -Wall -Werror -g -fPIC $(CFG_IOS_SDK_FLAGS_armv7-apple-ios) -mfpu=vfp3 -arch armv7
|
CFG_GCCISH_CFLAGS_armv7-apple-ios := -g -fPIC $(CFG_IOS_SDK_FLAGS_armv7-apple-ios) -mfpu=vfp3 -arch armv7
|
||||||
CFG_GCCISH_CXXFLAGS_armv7-apple-ios := -fno-rtti $(CFG_IOS_SDK_FLAGS_armv7-apple-ios) -I$(CFG_IOS_SDK_armv7-apple-ios)/usr/include/c++/4.2.1
|
CFG_GCCISH_CXXFLAGS_armv7-apple-ios := -fno-rtti $(CFG_IOS_SDK_FLAGS_armv7-apple-ios) -I$(CFG_IOS_SDK_armv7-apple-ios)/usr/include/c++/4.2.1
|
||||||
CFG_GCCISH_LINK_FLAGS_armv7-apple-ios := -lpthread -syslibroot $(CFG_IOS_SDK_armv7-apple-ios) -Wl,-no_compact_unwind
|
CFG_GCCISH_LINK_FLAGS_armv7-apple-ios := -lpthread -syslibroot $(CFG_IOS_SDK_armv7-apple-ios) -Wl,-no_compact_unwind
|
||||||
CFG_GCCISH_DEF_FLAG_armv7-apple-ios := -Wl,-exported_symbols_list,
|
CFG_GCCISH_DEF_FLAG_armv7-apple-ios := -Wl,-exported_symbols_list,
|
||||||
|
|
3
mk/cfg/armv7-unknown-linux-musleabihf.mk
Normal file
3
mk/cfg/armv7-unknown-linux-musleabihf.mk
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# This file is intentially left empty to indicate that, while this target is
|
||||||
|
# supported, it's not supported using plain GNU Make builds. Use a --rustbuild
|
||||||
|
# instead.
|
|
@ -15,7 +15,7 @@ CFG_INSTALL_ONLY_RLIB_armv7s-apple-ios = 1
|
||||||
CFG_STATIC_LIB_NAME_armv7s-apple-ios=lib$(1).a
|
CFG_STATIC_LIB_NAME_armv7s-apple-ios=lib$(1).a
|
||||||
CFG_LIB_DSYM_GLOB_armv7s-apple-ios = lib$(1)-*.a.dSYM
|
CFG_LIB_DSYM_GLOB_armv7s-apple-ios = lib$(1)-*.a.dSYM
|
||||||
CFG_JEMALLOC_CFLAGS_armv7s-apple-ios := -arch armv7s $(CFG_IOS_SDK_FLAGS_armv7s-apple-ios)
|
CFG_JEMALLOC_CFLAGS_armv7s-apple-ios := -arch armv7s $(CFG_IOS_SDK_FLAGS_armv7s-apple-ios)
|
||||||
CFG_GCCISH_CFLAGS_armv7s-apple-ios := -Wall -Werror -g -fPIC $(CFG_IOS_SDK_FLAGS_armv7s-apple-ios) -arch armv7s
|
CFG_GCCISH_CFLAGS_armv7s-apple-ios := -g -fPIC $(CFG_IOS_SDK_FLAGS_armv7s-apple-ios) -arch armv7s
|
||||||
CFG_GCCISH_CXXFLAGS_armv7s-apple-ios := -fno-rtti $(CFG_IOS_SDK_FLAGS_armv7s-apple-ios) -I$(CFG_IOS_SDK_armv7s-apple-ios)/usr/include/c++/4.2.1
|
CFG_GCCISH_CXXFLAGS_armv7s-apple-ios := -fno-rtti $(CFG_IOS_SDK_FLAGS_armv7s-apple-ios) -I$(CFG_IOS_SDK_armv7s-apple-ios)/usr/include/c++/4.2.1
|
||||||
CFG_GCCISH_LINK_FLAGS_armv7s-apple-ios := -lpthread -syslibroot $(CFG_IOS_SDK_armv7s-apple-ios) -Wl,-no_compact_unwind
|
CFG_GCCISH_LINK_FLAGS_armv7s-apple-ios := -lpthread -syslibroot $(CFG_IOS_SDK_armv7s-apple-ios) -Wl,-no_compact_unwind
|
||||||
CFG_GCCISH_DEF_FLAG_armv7s-apple-ios := -Wl,-exported_symbols_list,
|
CFG_GCCISH_DEF_FLAG_armv7s-apple-ios := -Wl,-exported_symbols_list,
|
||||||
|
|
|
@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_asmjs-unknown-emscripten=lib$(1).a
|
||||||
CFG_LIB_GLOB_asmjs-unknown-emscripten=lib$(1)-*.so
|
CFG_LIB_GLOB_asmjs-unknown-emscripten=lib$(1)-*.so
|
||||||
CFG_LIB_DSYM_GLOB_asmjs-unknown-emscripten=lib$(1)-*.dylib.dSYM
|
CFG_LIB_DSYM_GLOB_asmjs-unknown-emscripten=lib$(1)-*.dylib.dSYM
|
||||||
CFG_JEMALLOC_CFLAGS_asmjs-unknown-emscripten := -m32 $(CFLAGS)
|
CFG_JEMALLOC_CFLAGS_asmjs-unknown-emscripten := -m32 $(CFLAGS)
|
||||||
CFG_GCCISH_CFLAGS_asmjs-unknown-emscripten := -Wall -Werror -g -fPIC -m32 $(CFLAGS)
|
CFG_GCCISH_CFLAGS_asmjs-unknown-emscripten := -g -fPIC -m32 $(CFLAGS)
|
||||||
CFG_GCCISH_CXXFLAGS_asmjs-unknown-emscripten := -fno-rtti $(CXXFLAGS)
|
CFG_GCCISH_CXXFLAGS_asmjs-unknown-emscripten := -fno-rtti $(CXXFLAGS)
|
||||||
CFG_GCCISH_LINK_FLAGS_asmjs-unknown-emscripten := -shared -fPIC -ldl -pthread -lrt -g -m32
|
CFG_GCCISH_LINK_FLAGS_asmjs-unknown-emscripten := -shared -fPIC -ldl -pthread -lrt -g -m32
|
||||||
CFG_GCCISH_DEF_FLAG_asmjs-unknown-emscripten := -Wl,--export-dynamic,--dynamic-list=
|
CFG_GCCISH_DEF_FLAG_asmjs-unknown-emscripten := -Wl,--export-dynamic,--dynamic-list=
|
||||||
|
|
|
@ -14,7 +14,7 @@ CFG_LIB_GLOB_i386-apple-ios = lib$(1)-*.dylib
|
||||||
CFG_INSTALL_ONLY_RLIB_i386-apple-ios = 1
|
CFG_INSTALL_ONLY_RLIB_i386-apple-ios = 1
|
||||||
CFG_STATIC_LIB_NAME_i386-apple-ios=lib$(1).a
|
CFG_STATIC_LIB_NAME_i386-apple-ios=lib$(1).a
|
||||||
CFG_LIB_DSYM_GLOB_i386-apple-ios = lib$(1)-*.dylib.dSYM
|
CFG_LIB_DSYM_GLOB_i386-apple-ios = lib$(1)-*.dylib.dSYM
|
||||||
CFG_GCCISH_CFLAGS_i386-apple-ios := -Wall -Werror -g -fPIC -m32 $(CFG_IOSSIM_FLAGS_i386-apple-ios)
|
CFG_GCCISH_CFLAGS_i386-apple-ios := -g -fPIC -m32 $(CFG_IOSSIM_FLAGS_i386-apple-ios)
|
||||||
CFG_GCCISH_CXXFLAGS_i386-apple-ios := -fno-rtti $(CFG_IOSSIM_FLAGS_i386-apple-ios) -I$(CFG_IOSSIM_SDK_i386-apple-ios)/usr/include/c++/4.2.1
|
CFG_GCCISH_CXXFLAGS_i386-apple-ios := -fno-rtti $(CFG_IOSSIM_FLAGS_i386-apple-ios) -I$(CFG_IOSSIM_SDK_i386-apple-ios)/usr/include/c++/4.2.1
|
||||||
CFG_GCCISH_LINK_FLAGS_i386-apple-ios := -lpthread -m32 -Wl,-no_compact_unwind -m32 -Wl,-syslibroot $(CFG_IOSSIM_SDK_i386-apple-ios)
|
CFG_GCCISH_LINK_FLAGS_i386-apple-ios := -lpthread -m32 -Wl,-no_compact_unwind -m32 -Wl,-syslibroot $(CFG_IOSSIM_SDK_i386-apple-ios)
|
||||||
CFG_GCCISH_DEF_FLAG_i386-apple-ios := -Wl,-exported_symbols_list,
|
CFG_GCCISH_DEF_FLAG_i386-apple-ios := -Wl,-exported_symbols_list,
|
||||||
|
|
|
@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_i586-unknown-linux-gnu=lib$(1).a
|
||||||
CFG_LIB_GLOB_i586-unknown-linux-gnu=lib$(1)-*.so
|
CFG_LIB_GLOB_i586-unknown-linux-gnu=lib$(1)-*.so
|
||||||
CFG_LIB_DSYM_GLOB_i586-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
|
CFG_LIB_DSYM_GLOB_i586-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
|
||||||
CFG_JEMALLOC_CFLAGS_i586-unknown-linux-gnu := -m32 $(CFLAGS) -march=pentium
|
CFG_JEMALLOC_CFLAGS_i586-unknown-linux-gnu := -m32 $(CFLAGS) -march=pentium
|
||||||
CFG_GCCISH_CFLAGS_i586-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32 $(CFLAGS) -march=pentium
|
CFG_GCCISH_CFLAGS_i586-unknown-linux-gnu := -g -fPIC -m32 $(CFLAGS) -march=pentium
|
||||||
CFG_GCCISH_CXXFLAGS_i586-unknown-linux-gnu := -fno-rtti $(CXXFLAGS) -march=pentium
|
CFG_GCCISH_CXXFLAGS_i586-unknown-linux-gnu := -fno-rtti $(CXXFLAGS) -march=pentium
|
||||||
CFG_GCCISH_LINK_FLAGS_i586-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m32
|
CFG_GCCISH_LINK_FLAGS_i586-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m32
|
||||||
CFG_GCCISH_DEF_FLAG_i586-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
|
CFG_GCCISH_DEF_FLAG_i586-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
|
||||||
|
|
|
@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_i686-apple-darwin=lib$(1).a
|
||||||
CFG_LIB_GLOB_i686-apple-darwin=lib$(1)-*.dylib
|
CFG_LIB_GLOB_i686-apple-darwin=lib$(1)-*.dylib
|
||||||
CFG_LIB_DSYM_GLOB_i686-apple-darwin=lib$(1)-*.dylib.dSYM
|
CFG_LIB_DSYM_GLOB_i686-apple-darwin=lib$(1)-*.dylib.dSYM
|
||||||
CFG_JEMALLOC_CFLAGS_i686-apple-darwin := -m32 -arch i386 $(CFLAGS)
|
CFG_JEMALLOC_CFLAGS_i686-apple-darwin := -m32 -arch i386 $(CFLAGS)
|
||||||
CFG_GCCISH_CFLAGS_i686-apple-darwin := -Wall -Werror -g -fPIC -m32 -arch i386 $(CFLAGS)
|
CFG_GCCISH_CFLAGS_i686-apple-darwin := -g -fPIC -m32 -arch i386 $(CFLAGS)
|
||||||
CFG_GCCISH_CXXFLAGS_i686-apple-darwin := -fno-rtti $(CXXFLAGS)
|
CFG_GCCISH_CXXFLAGS_i686-apple-darwin := -fno-rtti $(CXXFLAGS)
|
||||||
CFG_GCCISH_LINK_FLAGS_i686-apple-darwin := -dynamiclib -pthread -framework CoreServices -m32
|
CFG_GCCISH_LINK_FLAGS_i686-apple-darwin := -dynamiclib -pthread -framework CoreServices -m32
|
||||||
CFG_GCCISH_DEF_FLAG_i686-apple-darwin := -Wl,-exported_symbols_list,
|
CFG_GCCISH_DEF_FLAG_i686-apple-darwin := -Wl,-exported_symbols_list,
|
||||||
|
|
|
@ -9,7 +9,7 @@ CFG_STATIC_LIB_NAME_i686-pc-windows-gnu=$(1).lib
|
||||||
CFG_LIB_GLOB_i686-pc-windows-gnu=$(1)-*.dll
|
CFG_LIB_GLOB_i686-pc-windows-gnu=$(1)-*.dll
|
||||||
CFG_LIB_DSYM_GLOB_i686-pc-windows-gnu=$(1)-*.dylib.dSYM
|
CFG_LIB_DSYM_GLOB_i686-pc-windows-gnu=$(1)-*.dylib.dSYM
|
||||||
CFG_JEMALLOC_CFLAGS_i686-pc-windows-gnu := -march=i686 -m32 -D_WIN32_WINNT=0x0600 -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS)
|
CFG_JEMALLOC_CFLAGS_i686-pc-windows-gnu := -march=i686 -m32 -D_WIN32_WINNT=0x0600 -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS)
|
||||||
CFG_GCCISH_CFLAGS_i686-pc-windows-gnu := -Wall -Werror -g -m32 -D_WIN32_WINNT=0x0600 -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS)
|
CFG_GCCISH_CFLAGS_i686-pc-windows-gnu := -g -m32 -D_WIN32_WINNT=0x0600 -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS)
|
||||||
CFG_GCCISH_CXXFLAGS_i686-pc-windows-gnu := -fno-rtti $(CXXFLAGS)
|
CFG_GCCISH_CXXFLAGS_i686-pc-windows-gnu := -fno-rtti $(CXXFLAGS)
|
||||||
CFG_GCCISH_LINK_FLAGS_i686-pc-windows-gnu := -shared -g -m32
|
CFG_GCCISH_LINK_FLAGS_i686-pc-windows-gnu := -shared -g -m32
|
||||||
CFG_GCCISH_DEF_FLAG_i686-pc-windows-gnu :=
|
CFG_GCCISH_DEF_FLAG_i686-pc-windows-gnu :=
|
||||||
|
|
|
@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_i686-unknown-freebsd=lib$(1).a
|
||||||
CFG_LIB_GLOB_i686-unknown-freebsd=lib$(1)-*.so
|
CFG_LIB_GLOB_i686-unknown-freebsd=lib$(1)-*.so
|
||||||
CFG_LIB_DSYM_GLOB_i686-unknown-freebsd=$(1)-*.dylib.dSYM
|
CFG_LIB_DSYM_GLOB_i686-unknown-freebsd=$(1)-*.dylib.dSYM
|
||||||
CFG_JEMALLOC_CFLAGS_i686-unknown-freebsd := -m32 -I/usr/local/include $(CFLAGS)
|
CFG_JEMALLOC_CFLAGS_i686-unknown-freebsd := -m32 -I/usr/local/include $(CFLAGS)
|
||||||
CFG_GCCISH_CFLAGS_i686-unknown-freebsd := -Wall -Werror -g -fPIC -m32 -arch i386 -I/usr/local/include $(CFLAGS)
|
CFG_GCCISH_CFLAGS_i686-unknown-freebsd := -g -fPIC -m32 -arch i386 -I/usr/local/include $(CFLAGS)
|
||||||
CFG_GCCISH_LINK_FLAGS_i686-unknown-freebsd := -m32 -shared -fPIC -g -pthread -lrt
|
CFG_GCCISH_LINK_FLAGS_i686-unknown-freebsd := -m32 -shared -fPIC -g -pthread -lrt
|
||||||
CFG_GCCISH_DEF_FLAG_i686-unknown-freebsd := -Wl,--export-dynamic,--dynamic-list=
|
CFG_GCCISH_DEF_FLAG_i686-unknown-freebsd := -Wl,--export-dynamic,--dynamic-list=
|
||||||
CFG_LLC_FLAGS_i686-unknown-freebsd :=
|
CFG_LLC_FLAGS_i686-unknown-freebsd :=
|
||||||
|
|
|
@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_i686-unknown-linux-gnu=lib$(1).a
|
||||||
CFG_LIB_GLOB_i686-unknown-linux-gnu=lib$(1)-*.so
|
CFG_LIB_GLOB_i686-unknown-linux-gnu=lib$(1)-*.so
|
||||||
CFG_LIB_DSYM_GLOB_i686-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
|
CFG_LIB_DSYM_GLOB_i686-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
|
||||||
CFG_JEMALLOC_CFLAGS_i686-unknown-linux-gnu := -m32 $(CFLAGS)
|
CFG_JEMALLOC_CFLAGS_i686-unknown-linux-gnu := -m32 $(CFLAGS)
|
||||||
CFG_GCCISH_CFLAGS_i686-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32 $(CFLAGS) -march=i686
|
CFG_GCCISH_CFLAGS_i686-unknown-linux-gnu := -g -fPIC -m32 $(CFLAGS) -march=i686
|
||||||
CFG_GCCISH_CXXFLAGS_i686-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
|
CFG_GCCISH_CXXFLAGS_i686-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
|
||||||
CFG_GCCISH_LINK_FLAGS_i686-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m32
|
CFG_GCCISH_LINK_FLAGS_i686-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m32
|
||||||
CFG_GCCISH_DEF_FLAG_i686-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
|
CFG_GCCISH_DEF_FLAG_i686-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
|
||||||
|
|
|
@ -8,7 +8,7 @@ CFG_LIB_NAME_i686-unknown-linux-musl=lib$(1).so
|
||||||
CFG_STATIC_LIB_NAME_i686-unknown-linux-musl=lib$(1).a
|
CFG_STATIC_LIB_NAME_i686-unknown-linux-musl=lib$(1).a
|
||||||
CFG_LIB_GLOB_i686-unknown-linux-musl=lib$(1)-*.so
|
CFG_LIB_GLOB_i686-unknown-linux-musl=lib$(1)-*.so
|
||||||
CFG_JEMALLOC_CFLAGS_i686-unknown-linux-musl := -m32 -Wl,-melf_i386
|
CFG_JEMALLOC_CFLAGS_i686-unknown-linux-musl := -m32 -Wl,-melf_i386
|
||||||
CFG_GCCISH_CFLAGS_i686-unknown-linux-musl := -Wall -Werror -g -fPIC -m32 -Wl,-melf_i386
|
CFG_GCCISH_CFLAGS_i686-unknown-linux-musl := -g -fPIC -m32 -Wl,-melf_i386
|
||||||
CFG_GCCISH_CXXFLAGS_i686-unknown-linux-musl :=
|
CFG_GCCISH_CXXFLAGS_i686-unknown-linux-musl :=
|
||||||
CFG_GCCISH_LINK_FLAGS_i686-unknown-linux-musl :=
|
CFG_GCCISH_LINK_FLAGS_i686-unknown-linux-musl :=
|
||||||
CFG_GCCISH_DEF_FLAG_i686-unknown-linux-musl :=
|
CFG_GCCISH_DEF_FLAG_i686-unknown-linux-musl :=
|
||||||
|
|
|
@ -9,7 +9,7 @@ CFG_STATIC_LIB_NAME_powerpc-unknown-linux-gnu=lib$(1).a
|
||||||
CFG_LIB_GLOB_powerpc-unknown-linux-gnu=lib$(1)-*.so
|
CFG_LIB_GLOB_powerpc-unknown-linux-gnu=lib$(1)-*.so
|
||||||
CFG_LIB_DSYM_GLOB_powerpc-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
|
CFG_LIB_DSYM_GLOB_powerpc-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
|
||||||
CFG_CFLAGS_powerpc-unknown-linux-gnu := -m32 $(CFLAGS)
|
CFG_CFLAGS_powerpc-unknown-linux-gnu := -m32 $(CFLAGS)
|
||||||
CFG_GCCISH_CFLAGS_powerpc-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32 $(CFLAGS)
|
CFG_GCCISH_CFLAGS_powerpc-unknown-linux-gnu := -g -fPIC -m32 $(CFLAGS)
|
||||||
CFG_GCCISH_CXXFLAGS_powerpc-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
|
CFG_GCCISH_CXXFLAGS_powerpc-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
|
||||||
CFG_GCCISH_LINK_FLAGS_powerpc-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m32
|
CFG_GCCISH_LINK_FLAGS_powerpc-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m32
|
||||||
CFG_GCCISH_DEF_FLAG_powerpc-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
|
CFG_GCCISH_DEF_FLAG_powerpc-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
|
||||||
|
|
|
@ -10,7 +10,7 @@ CFG_LIB_GLOB_powerpc64-unknown-linux-gnu=lib$(1)-*.so
|
||||||
CFG_LIB_DSYM_GLOB_powerpc64-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
|
CFG_LIB_DSYM_GLOB_powerpc64-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
|
||||||
CFG_JEMALLOC_CFLAGS_powerpc64-unknown-linux-gnu := -m64
|
CFG_JEMALLOC_CFLAGS_powerpc64-unknown-linux-gnu := -m64
|
||||||
CFG_CFLAGS_powerpc64-unknown-linux-gnu := -m64 $(CFLAGS)
|
CFG_CFLAGS_powerpc64-unknown-linux-gnu := -m64 $(CFLAGS)
|
||||||
CFG_GCCISH_CFLAGS_powerpc64-unknown-linux-gnu := -Wall -Werror -g -fPIC -m64 $(CFLAGS)
|
CFG_GCCISH_CFLAGS_powerpc64-unknown-linux-gnu := -g -fPIC -m64 $(CFLAGS)
|
||||||
CFG_GCCISH_CXXFLAGS_powerpc64-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
|
CFG_GCCISH_CXXFLAGS_powerpc64-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
|
||||||
CFG_GCCISH_LINK_FLAGS_powerpc64-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m64
|
CFG_GCCISH_LINK_FLAGS_powerpc64-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m64
|
||||||
CFG_GCCISH_DEF_FLAG_powerpc64-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
|
CFG_GCCISH_DEF_FLAG_powerpc64-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
|
||||||
|
|
|
@ -9,7 +9,7 @@ CFG_STATIC_LIB_NAME_powerpc64le-unknown-linux-gnu=lib$(1).a
|
||||||
CFG_LIB_GLOB_powerpc64le-unknown-linux-gnu=lib$(1)-*.so
|
CFG_LIB_GLOB_powerpc64le-unknown-linux-gnu=lib$(1)-*.so
|
||||||
CFG_LIB_DSYM_GLOB_powerpc64le-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
|
CFG_LIB_DSYM_GLOB_powerpc64le-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
|
||||||
CFG_CFLAGS_powerpc64le-unknown-linux-gnu := -m64 $(CFLAGS)
|
CFG_CFLAGS_powerpc64le-unknown-linux-gnu := -m64 $(CFLAGS)
|
||||||
CFG_GCCISH_CFLAGS_powerpc64le-unknown-linux-gnu := -Wall -Werror -g -fPIC -m64 $(CFLAGS)
|
CFG_GCCISH_CFLAGS_powerpc64le-unknown-linux-gnu := -g -fPIC -m64 $(CFLAGS)
|
||||||
CFG_GCCISH_CXXFLAGS_powerpc64le-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
|
CFG_GCCISH_CXXFLAGS_powerpc64le-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
|
||||||
CFG_GCCISH_LINK_FLAGS_powerpc64le-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m64
|
CFG_GCCISH_LINK_FLAGS_powerpc64le-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m64
|
||||||
CFG_GCCISH_DEF_FLAG_powerpc64le-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
|
CFG_GCCISH_DEF_FLAG_powerpc64le-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
|
||||||
|
|
|
@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_x86_64-apple-darwin=lib$(1).a
|
||||||
CFG_LIB_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib
|
CFG_LIB_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib
|
||||||
CFG_LIB_DSYM_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib.dSYM
|
CFG_LIB_DSYM_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib.dSYM
|
||||||
CFG_JEMALLOC_CFLAGS_x86_64-apple-darwin := -m64 -arch x86_64 $(CFLAGS)
|
CFG_JEMALLOC_CFLAGS_x86_64-apple-darwin := -m64 -arch x86_64 $(CFLAGS)
|
||||||
CFG_GCCISH_CFLAGS_x86_64-apple-darwin := -Wall -Werror -g -fPIC -m64 -arch x86_64 $(CFLAGS)
|
CFG_GCCISH_CFLAGS_x86_64-apple-darwin := -g -fPIC -m64 -arch x86_64 $(CFLAGS)
|
||||||
CFG_GCCISH_CXXFLAGS_x86_64-apple-darwin := -fno-rtti $(CXXFLAGS)
|
CFG_GCCISH_CXXFLAGS_x86_64-apple-darwin := -fno-rtti $(CXXFLAGS)
|
||||||
CFG_GCCISH_LINK_FLAGS_x86_64-apple-darwin := -dynamiclib -pthread -framework CoreServices -m64
|
CFG_GCCISH_LINK_FLAGS_x86_64-apple-darwin := -dynamiclib -pthread -framework CoreServices -m64
|
||||||
CFG_GCCISH_DEF_FLAG_x86_64-apple-darwin := -Wl,-exported_symbols_list,
|
CFG_GCCISH_DEF_FLAG_x86_64-apple-darwin := -Wl,-exported_symbols_list,
|
||||||
|
|
|
@ -16,7 +16,7 @@ CFG_STATIC_LIB_NAME_x86_64-apple-ios=lib$(1).a
|
||||||
CFG_LIB_DSYM_GLOB_x86_64-apple-ios = lib$(1)-*.a.dSYM
|
CFG_LIB_DSYM_GLOB_x86_64-apple-ios = lib$(1)-*.a.dSYM
|
||||||
CFG_CFLAGS_x86_64-apple-ios := $(CFG_IOSSIM_FLAGS_x86_64-apple-ios)
|
CFG_CFLAGS_x86_64-apple-ios := $(CFG_IOSSIM_FLAGS_x86_64-apple-ios)
|
||||||
CFG_JEMALLOC_CFLAGS_x86_64-apple-ios := $(CFG_IOSSIM_FLAGS_x86_64-apple-ios)
|
CFG_JEMALLOC_CFLAGS_x86_64-apple-ios := $(CFG_IOSSIM_FLAGS_x86_64-apple-ios)
|
||||||
CFG_GCCISH_CFLAGS_x86_64-apple-ios := -Wall -Werror -fPIC $(CFG_IOSSIM_FLAGS_x86_64-apple-ios)
|
CFG_GCCISH_CFLAGS_x86_64-apple-ios := -fPIC $(CFG_IOSSIM_FLAGS_x86_64-apple-ios)
|
||||||
CFG_GCCISH_CXXFLAGS_x86_64-apple-ios := -fno-rtti $(CFG_IOSSIM_FLAGS_x86_64-apple-ios) -I$(CFG_IOSSIM_SDK_x86_64-apple-ios)/usr/include/c++/4.2.1
|
CFG_GCCISH_CXXFLAGS_x86_64-apple-ios := -fno-rtti $(CFG_IOSSIM_FLAGS_x86_64-apple-ios) -I$(CFG_IOSSIM_SDK_x86_64-apple-ios)/usr/include/c++/4.2.1
|
||||||
CFG_GCCISH_LINK_FLAGS_x86_64-apple-ios := -lpthread -Wl,-no_compact_unwind -m64 -Wl,-syslibroot $(CFG_IOSSIM_SDK_x86_64-apple-ios)
|
CFG_GCCISH_LINK_FLAGS_x86_64-apple-ios := -lpthread -Wl,-no_compact_unwind -m64 -Wl,-syslibroot $(CFG_IOSSIM_SDK_x86_64-apple-ios)
|
||||||
CFG_GCCISH_DEF_FLAG_x86_64-apple-ios := -Wl,-exported_symbols_list,
|
CFG_GCCISH_DEF_FLAG_x86_64-apple-ios := -Wl,-exported_symbols_list,
|
||||||
|
|
|
@ -9,7 +9,7 @@ CFG_STATIC_LIB_NAME_x86_64-pc-windows-gnu=$(1).lib
|
||||||
CFG_LIB_GLOB_x86_64-pc-windows-gnu=$(1)-*.dll
|
CFG_LIB_GLOB_x86_64-pc-windows-gnu=$(1)-*.dll
|
||||||
CFG_LIB_DSYM_GLOB_x86_64-pc-windows-gnu=$(1)-*.dylib.dSYM
|
CFG_LIB_DSYM_GLOB_x86_64-pc-windows-gnu=$(1)-*.dylib.dSYM
|
||||||
CFG_JEMALLOC_CFLAGS_x86_64-pc-windows-gnu := -m64 -D_WIN32_WINNT=0x0600 -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS)
|
CFG_JEMALLOC_CFLAGS_x86_64-pc-windows-gnu := -m64 -D_WIN32_WINNT=0x0600 -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS)
|
||||||
CFG_GCCISH_CFLAGS_x86_64-pc-windows-gnu := -Wall -Werror -g -m64 -D_WIN32_WINNT=0x0600 -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS)
|
CFG_GCCISH_CFLAGS_x86_64-pc-windows-gnu := -g -m64 -D_WIN32_WINNT=0x0600 -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS)
|
||||||
CFG_GCCISH_CXXFLAGS_x86_64-pc-windows-gnu := -fno-rtti $(CXXFLAGS)
|
CFG_GCCISH_CXXFLAGS_x86_64-pc-windows-gnu := -fno-rtti $(CXXFLAGS)
|
||||||
CFG_GCCISH_LINK_FLAGS_x86_64-pc-windows-gnu := -shared -g -m64
|
CFG_GCCISH_LINK_FLAGS_x86_64-pc-windows-gnu := -shared -g -m64
|
||||||
CFG_GCCISH_DEF_FLAG_x86_64-pc-windows-gnu :=
|
CFG_GCCISH_DEF_FLAG_x86_64-pc-windows-gnu :=
|
||||||
|
|
|
@ -9,7 +9,7 @@ CFG_LIB_NAME_x86_64-rumprun-netbsd=lib$(1).so
|
||||||
CFG_STATIC_LIB_NAME_x86_64-rumprun-netbsd=lib$(1).a
|
CFG_STATIC_LIB_NAME_x86_64-rumprun-netbsd=lib$(1).a
|
||||||
CFG_LIB_GLOB_x86_64-rumprun-netbsd=lib$(1)-*.so
|
CFG_LIB_GLOB_x86_64-rumprun-netbsd=lib$(1)-*.so
|
||||||
CFG_JEMALLOC_CFLAGS_x86_64-rumprun-netbsd := -m64
|
CFG_JEMALLOC_CFLAGS_x86_64-rumprun-netbsd := -m64
|
||||||
CFG_GCCISH_CFLAGS_x86_64-rumprun-netbsd := -Wall -Werror -g -fPIC -m64
|
CFG_GCCISH_CFLAGS_x86_64-rumprun-netbsd := -g -fPIC -m64
|
||||||
CFG_GCCISH_CXXFLAGS_x86_64-rumprun-netbsd :=
|
CFG_GCCISH_CXXFLAGS_x86_64-rumprun-netbsd :=
|
||||||
CFG_GCCISH_LINK_FLAGS_x86_64-rumprun-netbsd :=
|
CFG_GCCISH_LINK_FLAGS_x86_64-rumprun-netbsd :=
|
||||||
CFG_GCCISH_DEF_FLAG_x86_64-rumprun-netbsd :=
|
CFG_GCCISH_DEF_FLAG_x86_64-rumprun-netbsd :=
|
||||||
|
|
|
@ -9,7 +9,7 @@ CFG_STATIC_LIB_NAME_x86_64-sun-solaris=lib$(1).a
|
||||||
CFG_LIB_GLOB_x86_64-sun-solaris=lib$(1)-*.so
|
CFG_LIB_GLOB_x86_64-sun-solaris=lib$(1)-*.so
|
||||||
CFG_LIB_DSYM_GLOB_x86_64-sun-solaris=$(1)-*.dylib.dSYM
|
CFG_LIB_DSYM_GLOB_x86_64-sun-solaris=$(1)-*.dylib.dSYM
|
||||||
CFG_JEMALLOC_CFLAGS_x86_64-sun-solaris := -I/usr/local/include $(CFLAGS)
|
CFG_JEMALLOC_CFLAGS_x86_64-sun-solaris := -I/usr/local/include $(CFLAGS)
|
||||||
CFG_GCCISH_CFLAGS_x86_64-sun-solaris := -Wall -Werror -g -D_POSIX_PTHREAD_SEMANTICS -fPIC -I/usr/local/include $(CFLAGS)
|
CFG_GCCISH_CFLAGS_x86_64-sun-solaris := -g -D_POSIX_PTHREAD_SEMANTICS -fPIC -I/usr/local/include $(CFLAGS)
|
||||||
CFG_GCCISH_LINK_FLAGS_x86_64-sun-solaris := -shared -fPIC -g -pthread -lrt
|
CFG_GCCISH_LINK_FLAGS_x86_64-sun-solaris := -shared -fPIC -g -pthread -lrt
|
||||||
CFG_GCCISH_DEF_FLAG_x86_64-sun-solaris := -Wl,--export-dynamic,--dynamic-list=
|
CFG_GCCISH_DEF_FLAG_x86_64-sun-solaris := -Wl,--export-dynamic,--dynamic-list=
|
||||||
CFG_LLC_FLAGS_x86_64-sun-solaris :=
|
CFG_LLC_FLAGS_x86_64-sun-solaris :=
|
||||||
|
|
|
@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_x86_64-unknown-bitrig=lib$(1).a
|
||||||
CFG_LIB_GLOB_x86_64-unknown-bitrig=lib$(1)-*.so
|
CFG_LIB_GLOB_x86_64-unknown-bitrig=lib$(1)-*.so
|
||||||
CFG_LIB_DSYM_GLOB_x86_64-unknown-bitrig=$(1)-*.dylib.dSYM
|
CFG_LIB_DSYM_GLOB_x86_64-unknown-bitrig=$(1)-*.dylib.dSYM
|
||||||
CFG_JEMALLOC_CFLAGS_x86_64-unknown-bitrig := -m64 -I/usr/include $(CFLAGS)
|
CFG_JEMALLOC_CFLAGS_x86_64-unknown-bitrig := -m64 -I/usr/include $(CFLAGS)
|
||||||
CFG_GCCISH_CFLAGS_x86_64-unknown-bitrig := -Wall -Werror -fPIE -fPIC -m64 -I/usr/include $(CFLAGS)
|
CFG_GCCISH_CFLAGS_x86_64-unknown-bitrig := -fPIE -fPIC -m64 -I/usr/include $(CFLAGS)
|
||||||
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-bitrig := -shared -pic -pthread -m64 $(LDFLAGS)
|
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-bitrig := -shared -pic -pthread -m64 $(LDFLAGS)
|
||||||
CFG_GCCISH_DEF_FLAG_x86_64-unknown-bitrig := -Wl,--export-dynamic,--dynamic-list=
|
CFG_GCCISH_DEF_FLAG_x86_64-unknown-bitrig := -Wl,--export-dynamic,--dynamic-list=
|
||||||
CFG_LLC_FLAGS_x86_64-unknown-bitrig :=
|
CFG_LLC_FLAGS_x86_64-unknown-bitrig :=
|
||||||
|
|
|
@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_x86_64-unknown-dragonfly=lib$(1).a
|
||||||
CFG_LIB_GLOB_x86_64-unknown-dragonfly=lib$(1)-*.so
|
CFG_LIB_GLOB_x86_64-unknown-dragonfly=lib$(1)-*.so
|
||||||
CFG_LIB_DSYM_GLOB_x86_64-unknown-dragonfly=$(1)-*.dylib.dSYM
|
CFG_LIB_DSYM_GLOB_x86_64-unknown-dragonfly=$(1)-*.dylib.dSYM
|
||||||
CFG_JEMALLOC_CFLAGS_x86_64-unknown-dragonfly := -m64 -I/usr/include -I/usr/local/include $(CFLAGS)
|
CFG_JEMALLOC_CFLAGS_x86_64-unknown-dragonfly := -m64 -I/usr/include -I/usr/local/include $(CFLAGS)
|
||||||
CFG_GCCISH_CFLAGS_x86_64-unknown-dragonfly := -Wall -Werror -g -fPIC -m64 -I/usr/include -I/usr/local/include $(CFLAGS)
|
CFG_GCCISH_CFLAGS_x86_64-unknown-dragonfly := -g -fPIC -m64 -I/usr/include -I/usr/local/include $(CFLAGS)
|
||||||
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-dragonfly := -shared -fPIC -g -pthread -lrt -m64
|
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-dragonfly := -shared -fPIC -g -pthread -lrt -m64
|
||||||
CFG_GCCISH_DEF_FLAG_x86_64-unknown-dragonfly := -Wl,--export-dynamic,--dynamic-list=
|
CFG_GCCISH_DEF_FLAG_x86_64-unknown-dragonfly := -Wl,--export-dynamic,--dynamic-list=
|
||||||
CFG_LLC_FLAGS_x86_64-unknown-dragonfly :=
|
CFG_LLC_FLAGS_x86_64-unknown-dragonfly :=
|
||||||
|
|
|
@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_x86_64-unknown-freebsd=lib$(1).a
|
||||||
CFG_LIB_GLOB_x86_64-unknown-freebsd=lib$(1)-*.so
|
CFG_LIB_GLOB_x86_64-unknown-freebsd=lib$(1)-*.so
|
||||||
CFG_LIB_DSYM_GLOB_x86_64-unknown-freebsd=$(1)-*.dylib.dSYM
|
CFG_LIB_DSYM_GLOB_x86_64-unknown-freebsd=$(1)-*.dylib.dSYM
|
||||||
CFG_JEMALLOC_CFLAGS_x86_64-unknown-freebsd := -I/usr/local/include $(CFLAGS)
|
CFG_JEMALLOC_CFLAGS_x86_64-unknown-freebsd := -I/usr/local/include $(CFLAGS)
|
||||||
CFG_GCCISH_CFLAGS_x86_64-unknown-freebsd := -Wall -Werror -g -fPIC -I/usr/local/include $(CFLAGS)
|
CFG_GCCISH_CFLAGS_x86_64-unknown-freebsd := -g -fPIC -I/usr/local/include $(CFLAGS)
|
||||||
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-freebsd := -shared -fPIC -g -pthread -lrt
|
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-freebsd := -shared -fPIC -g -pthread -lrt
|
||||||
CFG_GCCISH_DEF_FLAG_x86_64-unknown-freebsd := -Wl,--export-dynamic,--dynamic-list=
|
CFG_GCCISH_DEF_FLAG_x86_64-unknown-freebsd := -Wl,--export-dynamic,--dynamic-list=
|
||||||
CFG_LLC_FLAGS_x86_64-unknown-freebsd :=
|
CFG_LLC_FLAGS_x86_64-unknown-freebsd :=
|
||||||
|
|
|
@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_x86_64-unknown-linux-gnu=lib$(1).a
|
||||||
CFG_LIB_GLOB_x86_64-unknown-linux-gnu=lib$(1)-*.so
|
CFG_LIB_GLOB_x86_64-unknown-linux-gnu=lib$(1)-*.so
|
||||||
CFG_LIB_DSYM_GLOB_x86_64-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
|
CFG_LIB_DSYM_GLOB_x86_64-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
|
||||||
CFG_JEMALLOC_CFLAGS_x86_64-unknown-linux-gnu := -m64
|
CFG_JEMALLOC_CFLAGS_x86_64-unknown-linux-gnu := -m64
|
||||||
CFG_GCCISH_CFLAGS_x86_64-unknown-linux-gnu := -Wall -Werror -g -fPIC -m64
|
CFG_GCCISH_CFLAGS_x86_64-unknown-linux-gnu := -g -fPIC -m64
|
||||||
CFG_GCCISH_CXXFLAGS_x86_64-unknown-linux-gnu := -fno-rtti
|
CFG_GCCISH_CXXFLAGS_x86_64-unknown-linux-gnu := -fno-rtti
|
||||||
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m64
|
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m64
|
||||||
CFG_GCCISH_DEF_FLAG_x86_64-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
|
CFG_GCCISH_DEF_FLAG_x86_64-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
|
||||||
|
|
|
@ -7,8 +7,8 @@ CFG_INSTALL_ONLY_RLIB_x86_64-unknown-linux-musl = 1
|
||||||
CFG_LIB_NAME_x86_64-unknown-linux-musl=lib$(1).so
|
CFG_LIB_NAME_x86_64-unknown-linux-musl=lib$(1).so
|
||||||
CFG_STATIC_LIB_NAME_x86_64-unknown-linux-musl=lib$(1).a
|
CFG_STATIC_LIB_NAME_x86_64-unknown-linux-musl=lib$(1).a
|
||||||
CFG_LIB_GLOB_x86_64-unknown-linux-musl=lib$(1)-*.so
|
CFG_LIB_GLOB_x86_64-unknown-linux-musl=lib$(1)-*.so
|
||||||
CFG_JEMALLOC_CFLAGS_x86_64-unknown-linux-musl := -m64
|
CFG_JEMALLOC_CFLAGS_x86_64-unknown-linux-musl := -m64 -Wa,-mrelax-relocations=no
|
||||||
CFG_GCCISH_CFLAGS_x86_64-unknown-linux-musl := -Wall -Werror -g -fPIC -m64
|
CFG_GCCISH_CFLAGS_x86_64-unknown-linux-musl := -g -fPIC -m64 -Wa,-mrelax-relocations=no
|
||||||
CFG_GCCISH_CXXFLAGS_x86_64-unknown-linux-musl :=
|
CFG_GCCISH_CXXFLAGS_x86_64-unknown-linux-musl :=
|
||||||
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-linux-musl :=
|
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-linux-musl :=
|
||||||
CFG_GCCISH_DEF_FLAG_x86_64-unknown-linux-musl :=
|
CFG_GCCISH_DEF_FLAG_x86_64-unknown-linux-musl :=
|
||||||
|
|
|
@ -9,7 +9,7 @@ CFG_STATIC_LIB_NAME_x86_64-unknown-netbsd=lib$(1).a
|
||||||
CFG_LIB_GLOB_x86_64-unknown-netbsd=lib$(1)-*.so
|
CFG_LIB_GLOB_x86_64-unknown-netbsd=lib$(1)-*.so
|
||||||
CFG_LIB_DSYM_GLOB_x86_64-unknown-netbsd=$(1)-*.dylib.dSYM
|
CFG_LIB_DSYM_GLOB_x86_64-unknown-netbsd=$(1)-*.dylib.dSYM
|
||||||
CFG_JEMALLOC_CFLAGS_x86_64-unknown-netbsd := -I/usr/local/include $(CFLAGS)
|
CFG_JEMALLOC_CFLAGS_x86_64-unknown-netbsd := -I/usr/local/include $(CFLAGS)
|
||||||
CFG_GCCISH_CFLAGS_x86_64-unknown-netbsd := -Wall -Werror -g -fPIC -I/usr/local/include $(CFLAGS)
|
CFG_GCCISH_CFLAGS_x86_64-unknown-netbsd := -g -fPIC -I/usr/local/include $(CFLAGS)
|
||||||
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-netbsd := -shared -fPIC -g -pthread -lrt
|
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-netbsd := -shared -fPIC -g -pthread -lrt
|
||||||
CFG_GCCISH_DEF_FLAG_x86_64-unknown-netbsd := -Wl,--export-dynamic,--dynamic-list=
|
CFG_GCCISH_DEF_FLAG_x86_64-unknown-netbsd := -Wl,--export-dynamic,--dynamic-list=
|
||||||
CFG_LLC_FLAGS_x86_64-unknown-netbsd :=
|
CFG_LLC_FLAGS_x86_64-unknown-netbsd :=
|
||||||
|
|
|
@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_x86_64-unknown-openbsd=lib$(1).a
|
||||||
CFG_LIB_GLOB_x86_64-unknown-openbsd=lib$(1)-*.so
|
CFG_LIB_GLOB_x86_64-unknown-openbsd=lib$(1)-*.so
|
||||||
CFG_LIB_DSYM_GLOB_x86_64-unknown-openbsd=$(1)-*.dylib.dSYM
|
CFG_LIB_DSYM_GLOB_x86_64-unknown-openbsd=$(1)-*.dylib.dSYM
|
||||||
CFG_JEMALLOC_CFLAGS_x86_64-unknown-openbsd := -m64 -I/usr/include $(CFLAGS)
|
CFG_JEMALLOC_CFLAGS_x86_64-unknown-openbsd := -m64 -I/usr/include $(CFLAGS)
|
||||||
CFG_GCCISH_CFLAGS_x86_64-unknown-openbsd := -Wall -Werror -g -fPIC -m64 -I/usr/include $(CFLAGS)
|
CFG_GCCISH_CFLAGS_x86_64-unknown-openbsd := -g -fPIC -m64 -I/usr/include $(CFLAGS)
|
||||||
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-openbsd := -shared -fPIC -g -pthread -m64
|
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-openbsd := -shared -fPIC -g -pthread -m64
|
||||||
CFG_GCCISH_DEF_FLAG_x86_64-unknown-openbsd := -Wl,--export-dynamic,--dynamic-list=
|
CFG_GCCISH_DEF_FLAG_x86_64-unknown-openbsd := -Wl,--export-dynamic,--dynamic-list=
|
||||||
CFG_LLC_FLAGS_x86_64-unknown-openbsd :=
|
CFG_LLC_FLAGS_x86_64-unknown-openbsd :=
|
||||||
|
|
|
@ -162,9 +162,10 @@ ifdef CFG_ENABLE_DEBUGINFO
|
||||||
CFG_RUSTC_FLAGS += -g
|
CFG_RUSTC_FLAGS += -g
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef CFG_ENABLE_ORBIT
|
ifdef CFG_DISABLE_ORBIT
|
||||||
$(info cfg: launching MIR (CFG_ENABLE_ORBIT))
|
$(info cfg: HOLD HOLD HOLD (CFG_DISABLE_ORBIT))
|
||||||
CFG_RUSTC_FLAGS += -Z orbit
|
RUSTFLAGS_STAGE1 += -Z orbit=off
|
||||||
|
RUSTFLAGS_STAGE2 += -Z orbit=off
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef SAVE_TEMPS
|
ifdef SAVE_TEMPS
|
||||||
|
|
|
@ -221,12 +221,19 @@ define CFG_MAKE_TOOLCHAIN
|
||||||
LLVM_MC_RELOCATION_MODEL="default"
|
LLVM_MC_RELOCATION_MODEL="default"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# LLVM changed this flag in 3.9
|
||||||
|
ifdef CFG_LLVM_MC_HAS_RELOCATION_MODEL
|
||||||
|
LLVM_MC_RELOC_FLAG := -relocation-model=$$(LLVM_MC_RELOCATION_MODEL)
|
||||||
|
else
|
||||||
|
LLVM_MC_RELOC_FLAG := -position-independent
|
||||||
|
endif
|
||||||
|
|
||||||
# We're using llvm-mc as our assembler because it supports
|
# We're using llvm-mc as our assembler because it supports
|
||||||
# .cfi pseudo-ops on mac
|
# .cfi pseudo-ops on mac
|
||||||
CFG_ASSEMBLE_$(1)=$$(CPP_$(1)) -E $$(2) | \
|
CFG_ASSEMBLE_$(1)=$$(CPP_$(1)) -E $$(2) | \
|
||||||
$$(LLVM_MC_$$(CFG_BUILD)) \
|
$$(LLVM_MC_$$(CFG_BUILD)) \
|
||||||
-assemble \
|
-assemble \
|
||||||
-relocation-model=$$(LLVM_MC_RELOCATION_MODEL) \
|
$$(LLVM_MC_RELOC_FLAG) \
|
||||||
-filetype=obj \
|
-filetype=obj \
|
||||||
-triple=$(1) \
|
-triple=$(1) \
|
||||||
-o=$$(1)
|
-o=$$(1)
|
||||||
|
|
480
mk/rt.mk
480
mk/rt.mk
|
@ -223,147 +223,377 @@ endif
|
||||||
# compiler-rt
|
# compiler-rt
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
ifdef CFG_ENABLE_FAST_MAKE
|
# Everything below is a manual compilation of compiler-rt, disregarding its
|
||||||
COMPRT_DEPS := $(S)/.gitmodules
|
# build system. See comments in `src/bootstrap/native.rs` for more information.
|
||||||
else
|
|
||||||
COMPRT_DEPS := $(wildcard \
|
|
||||||
$(S)src/compiler-rt/* \
|
|
||||||
$(S)src/compiler-rt/*/* \
|
|
||||||
$(S)src/compiler-rt/*/*/* \
|
|
||||||
$(S)src/compiler-rt/*/*/*/*)
|
|
||||||
endif
|
|
||||||
|
|
||||||
# compiler-rt's build system is a godawful mess. Here we figure out
|
|
||||||
# the ridiculous platform-specific values and paths necessary to get
|
|
||||||
# useful artifacts out of it.
|
|
||||||
|
|
||||||
COMPRT_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt)
|
COMPRT_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt)
|
||||||
COMPRT_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(COMPRT_NAME_$(1))
|
COMPRT_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(COMPRT_NAME_$(1))
|
||||||
COMPRT_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/compiler-rt
|
COMPRT_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/compiler-rt
|
||||||
|
|
||||||
COMPRT_ARCH_$(1) := $$(word 1,$$(subst -, ,$(1)))
|
# GENERIC_SOURCES in CMakeLists.txt
|
||||||
|
COMPRT_OBJS_$(1) := \
|
||||||
# All this is to figure out the path to the compiler-rt bin
|
absvdi2.o \
|
||||||
ifeq ($$(findstring windows-msvc,$(1)),windows-msvc)
|
absvsi2.o \
|
||||||
COMPRT_DIR_$(1) := windows/Release
|
adddf3.o \
|
||||||
COMPRT_LIB_NAME_$(1) := clang_rt.builtins-$$(patsubst i%86,i386,$$(COMPRT_ARCH_$(1)))
|
addsf3.o \
|
||||||
endif
|
addvdi3.o \
|
||||||
|
addvsi3.o \
|
||||||
ifeq ($$(findstring windows-gnu,$(1)),windows-gnu)
|
apple_versioning.o \
|
||||||
COMPRT_DIR_$(1) := windows
|
ashldi3.o \
|
||||||
COMPRT_LIB_NAME_$(1) := clang_rt.builtins-$$(COMPRT_ARCH_$(1))
|
ashrdi3.o \
|
||||||
endif
|
clear_cache.o \
|
||||||
|
clzdi2.o \
|
||||||
ifeq ($$(findstring darwin,$(1)),darwin)
|
clzsi2.o \
|
||||||
COMPRT_DIR_$(1) := builtins
|
cmpdi2.o \
|
||||||
COMPRT_LIB_NAME_$(1) := clang_rt.builtins_$$(patsubst i686,i386,$$(COMPRT_ARCH_$(1)))_osx
|
comparedf2.o \
|
||||||
endif
|
comparesf2.o \
|
||||||
|
ctzdi2.o \
|
||||||
ifeq ($$(findstring ios,$(1)),ios)
|
ctzsi2.o \
|
||||||
COMPRT_DIR_$(1) := builtins
|
divdc3.o \
|
||||||
COMPRT_ARCH_$(1) := $$(patsubst armv7s,armv7em,$$(COMPRT_ARCH_$(1)))
|
divdf3.o \
|
||||||
COMPRT_LIB_NAME_$(1) := clang_rt.hard_pic_$$(COMPRT_ARCH_$(1))_macho_embedded
|
divdi3.o \
|
||||||
ifeq ($$(COMPRT_ARCH_$(1)),aarch64)
|
divmoddi4.o \
|
||||||
COMPRT_LIB_NAME_$(1) := clang_rt.builtins_arm64_ios
|
divmodsi4.o \
|
||||||
endif
|
divsc3.o \
|
||||||
COMPRT_DEFINES_$(1) := -DCOMPILER_RT_ENABLE_IOS=ON
|
divsf3.o \
|
||||||
endif
|
divsi3.o \
|
||||||
|
divxc3.o \
|
||||||
ifndef COMPRT_DIR_$(1)
|
extendsfdf2.o \
|
||||||
# NB: FreeBSD and NetBSD output to "linux"...
|
extendhfsf2.o \
|
||||||
COMPRT_DIR_$(1) := linux
|
ffsdi2.o \
|
||||||
COMPRT_ARCH_$(1) := $$(patsubst i586,i386,$$(COMPRT_ARCH_$(1)))
|
fixdfdi.o \
|
||||||
|
fixdfsi.o \
|
||||||
ifeq ($$(findstring android,$(1)),android)
|
fixsfdi.o \
|
||||||
ifeq ($$(findstring arm,$$(COMPRT_ARCH_$(1))),arm)
|
fixsfsi.o \
|
||||||
COMPRT_ARCH_$(1) := armhf
|
fixunsdfdi.o \
|
||||||
endif
|
fixunsdfsi.o \
|
||||||
endif
|
fixunssfdi.o \
|
||||||
|
fixunssfsi.o \
|
||||||
ifeq ($$(findstring eabihf,$(1)),eabihf)
|
fixunsxfdi.o \
|
||||||
ifeq ($$(findstring armv7,$(1)),)
|
fixunsxfsi.o \
|
||||||
COMPRT_LIB_NAME_$(1) := clang_rt.builtins-armhf
|
fixxfdi.o \
|
||||||
endif
|
floatdidf.o \
|
||||||
endif
|
floatdisf.o \
|
||||||
|
floatdixf.o \
|
||||||
ifndef COMPRT_LIB_NAME_$(1)
|
floatsidf.o \
|
||||||
COMPRT_LIB_NAME_$(1) := clang_rt.builtins-$$(COMPRT_ARCH_$(1))
|
floatsisf.o \
|
||||||
endif
|
floatundidf.o \
|
||||||
endif
|
floatundisf.o \
|
||||||
|
floatundixf.o \
|
||||||
|
floatunsidf.o \
|
||||||
ifeq ($$(findstring windows-gnu,$(1)),windows-gnu)
|
floatunsisf.o \
|
||||||
COMPRT_LIB_FILE_$(1) := lib$$(COMPRT_LIB_NAME_$(1)).a
|
int_util.o \
|
||||||
endif
|
lshrdi3.o \
|
||||||
|
moddi3.o \
|
||||||
ifeq ($$(findstring android,$(1)),android)
|
modsi3.o \
|
||||||
ifeq ($$(findstring arm,$(1)),arm)
|
muldc3.o \
|
||||||
COMPRT_LIB_FILE_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),$$(COMPRT_LIB_NAME_$(1))-android)
|
muldf3.o \
|
||||||
endif
|
muldi3.o \
|
||||||
endif
|
mulodi4.o \
|
||||||
|
mulosi4.o \
|
||||||
ifndef COMPRT_LIB_FILE_$(1)
|
muloti4.o \
|
||||||
COMPRT_LIB_FILE_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),$$(COMPRT_LIB_NAME_$(1)))
|
mulsc3.o \
|
||||||
endif
|
mulsf3.o \
|
||||||
|
mulvdi3.o \
|
||||||
COMPRT_OUTPUT_$(1) := $$(COMPRT_BUILD_DIR_$(1))/lib/$$(COMPRT_DIR_$(1))/$$(COMPRT_LIB_FILE_$(1))
|
mulvsi3.o \
|
||||||
|
mulxc3.o \
|
||||||
ifeq ($$(findstring windows-msvc,$(1)),windows-msvc)
|
negdf2.o \
|
||||||
COMPRT_BUILD_ARGS_$(1) := //v:m //nologo
|
negdi2.o \
|
||||||
COMPRT_BUILD_TARGET_$(1) := lib/builtins/builtins
|
negsf2.o \
|
||||||
COMPRT_BUILD_CC_$(1) :=
|
negvdi2.o \
|
||||||
else
|
negvsi2.o \
|
||||||
COMPRT_BUILD_ARGS_$(1) :=
|
paritydi2.o \
|
||||||
ifndef COMPRT_BUILD_TARGET_$(1)
|
paritysi2.o \
|
||||||
COMPRT_BUILD_TARGET_$(1) := $$(COMPRT_LIB_NAME_$(1))
|
popcountdi2.o \
|
||||||
endif
|
popcountsi2.o \
|
||||||
COMPRT_BUILD_CC_$(1) := -DCMAKE_C_COMPILER=$$(call FIND_COMPILER,$$(CC_$(1))) \
|
powidf2.o \
|
||||||
-DCMAKE_CXX_COMPILER=$$(call FIND_COMPILER,$$(CXX_$(1)))
|
powisf2.o \
|
||||||
|
powixf2.o \
|
||||||
|
subdf3.o \
|
||||||
|
subsf3.o \
|
||||||
|
subvdi3.o \
|
||||||
|
subvsi3.o \
|
||||||
|
truncdfhf2.o \
|
||||||
|
truncdfsf2.o \
|
||||||
|
truncsfhf2.o \
|
||||||
|
ucmpdi2.o \
|
||||||
|
udivdi3.o \
|
||||||
|
udivmoddi4.o \
|
||||||
|
udivmodsi4.o \
|
||||||
|
udivsi3.o \
|
||||||
|
umoddi3.o \
|
||||||
|
umodsi3.o
|
||||||
|
|
||||||
ifeq ($$(findstring ios,$(1)),)
|
ifeq ($$(findstring ios,$(1)),)
|
||||||
COMPRT_BUILD_CC_$(1) := $$(COMPRT_BUILD_CC_$(1)) \
|
COMPRT_OBJS_$(1) += \
|
||||||
-DCMAKE_C_FLAGS="$$(CFG_GCCISH_CFLAGS_$(1)) -Wno-error"
|
absvti2.o \
|
||||||
|
addtf3.o \
|
||||||
|
addvti3.o \
|
||||||
|
ashlti3.o \
|
||||||
|
ashrti3.o \
|
||||||
|
clzti2.o \
|
||||||
|
cmpti2.o \
|
||||||
|
ctzti2.o \
|
||||||
|
divtf3.o \
|
||||||
|
divti3.o \
|
||||||
|
ffsti2.o \
|
||||||
|
fixdfti.o \
|
||||||
|
fixsfti.o \
|
||||||
|
fixunsdfti.o \
|
||||||
|
fixunssfti.o \
|
||||||
|
fixunsxfti.o \
|
||||||
|
fixxfti.o \
|
||||||
|
floattidf.o \
|
||||||
|
floattisf.o \
|
||||||
|
floattixf.o \
|
||||||
|
floatuntidf.o \
|
||||||
|
floatuntisf.o \
|
||||||
|
floatuntixf.o \
|
||||||
|
lshrti3.o \
|
||||||
|
modti3.o \
|
||||||
|
multf3.o \
|
||||||
|
multi3.o \
|
||||||
|
mulvti3.o \
|
||||||
|
negti2.o \
|
||||||
|
negvti2.o \
|
||||||
|
parityti2.o \
|
||||||
|
popcountti2.o \
|
||||||
|
powitf2.o \
|
||||||
|
subtf3.o \
|
||||||
|
subvti3.o \
|
||||||
|
trampoline_setup.o \
|
||||||
|
ucmpti2.o \
|
||||||
|
udivmodti4.o \
|
||||||
|
udivti3.o \
|
||||||
|
umodti3.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($$(findstring apple,$(1)),apple)
|
||||||
|
COMPRT_OBJS_$(1) += \
|
||||||
|
atomic_flag_clear.o \
|
||||||
|
atomic_flag_clear_explicit.o \
|
||||||
|
atomic_flag_test_and_set.o \
|
||||||
|
atomic_flag_test_and_set_explicit.o \
|
||||||
|
atomic_signal_fence.o \
|
||||||
|
atomic_thread_fence.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
ifeq ($$(findstring windows,$(1)),)
|
||||||
|
COMPRT_OBJS_$(1) += emutls.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($$(findstring msvc,$(1)),)
|
||||||
|
|
||||||
|
ifeq ($$(findstring freebsd,$(1)),)
|
||||||
|
COMPRT_OBJS_$(1) += gcc_personality_v0.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
COMPRT_OBJS_$(1) += emutls.o
|
||||||
|
|
||||||
|
ifeq ($$(findstring x86_64,$(1)),x86_64)
|
||||||
|
COMPRT_OBJS_$(1) += \
|
||||||
|
x86_64/chkstk.o \
|
||||||
|
x86_64/chkstk2.o \
|
||||||
|
x86_64/floatdidf.o \
|
||||||
|
x86_64/floatdisf.o \
|
||||||
|
x86_64/floatdixf.o \
|
||||||
|
x86_64/floatundidf.o \
|
||||||
|
x86_64/floatundisf.o \
|
||||||
|
x86_64/floatundixf.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($$(findstring i686,$$(patsubts i%86,i686,$(1))),i686)
|
||||||
|
COMPRT_OBJS_$(1) += \
|
||||||
|
i386/ashldi3.o \
|
||||||
|
i386/ashrdi3.o \
|
||||||
|
i386/chkstk.o \
|
||||||
|
i386/chkstk2.o \
|
||||||
|
i386/divdi3.o \
|
||||||
|
i386/floatdidf.o \
|
||||||
|
i386/floatdisf.o \
|
||||||
|
i386/floatdixf.o \
|
||||||
|
i386/floatundidf.o \
|
||||||
|
i386/floatundisf.o \
|
||||||
|
i386/floatundixf.o \
|
||||||
|
i386/lshrdi3.o \
|
||||||
|
i386/moddi3.o \
|
||||||
|
i386/muldi3.o \
|
||||||
|
i386/udivdi3.o \
|
||||||
|
i386/umoddi3.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
ifeq ($$(findstring x86_64,$(1)),x86_64)
|
||||||
|
COMPRT_OBJS_$(1) += \
|
||||||
|
x86_64/floatdidf.o \
|
||||||
|
x86_64/floatdisf.o \
|
||||||
|
x86_64/floatdixf.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Generic ARM sources, nothing compiles on iOS though
|
||||||
|
ifeq ($$(findstring arm,$(1)),arm)
|
||||||
|
ifeq ($$(findstring ios,$(1)),)
|
||||||
|
COMPRT_OBJS_$(1) += \
|
||||||
|
arm/aeabi_cdcmp.o \
|
||||||
|
arm/aeabi_cdcmpeq_check_nan.o \
|
||||||
|
arm/aeabi_cfcmp.o \
|
||||||
|
arm/aeabi_cfcmpeq_check_nan.o \
|
||||||
|
arm/aeabi_dcmp.o \
|
||||||
|
arm/aeabi_div0.o \
|
||||||
|
arm/aeabi_drsub.o \
|
||||||
|
arm/aeabi_fcmp.o \
|
||||||
|
arm/aeabi_frsub.o \
|
||||||
|
arm/aeabi_idivmod.o \
|
||||||
|
arm/aeabi_ldivmod.o \
|
||||||
|
arm/aeabi_memcmp.o \
|
||||||
|
arm/aeabi_memcpy.o \
|
||||||
|
arm/aeabi_memmove.o \
|
||||||
|
arm/aeabi_memset.o \
|
||||||
|
arm/aeabi_uidivmod.o \
|
||||||
|
arm/aeabi_uldivmod.o \
|
||||||
|
arm/bswapdi2.o \
|
||||||
|
arm/bswapsi2.o \
|
||||||
|
arm/clzdi2.o \
|
||||||
|
arm/clzsi2.o \
|
||||||
|
arm/comparesf2.o \
|
||||||
|
arm/divmodsi4.o \
|
||||||
|
arm/divsi3.o \
|
||||||
|
arm/modsi3.o \
|
||||||
|
arm/switch16.o \
|
||||||
|
arm/switch32.o \
|
||||||
|
arm/switch8.o \
|
||||||
|
arm/switchu8.o \
|
||||||
|
arm/sync_synchronize.o \
|
||||||
|
arm/udivmodsi4.o \
|
||||||
|
arm/udivsi3.o \
|
||||||
|
arm/umodsi3.o
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Thumb sources
|
||||||
|
ifeq ($$(findstring armv7,$(1)),armv7)
|
||||||
|
COMPRT_OBJS_$(1) += \
|
||||||
|
arm/sync_fetch_and_add_4.o \
|
||||||
|
arm/sync_fetch_and_add_8.o \
|
||||||
|
arm/sync_fetch_and_and_4.o \
|
||||||
|
arm/sync_fetch_and_and_8.o \
|
||||||
|
arm/sync_fetch_and_max_4.o \
|
||||||
|
arm/sync_fetch_and_max_8.o \
|
||||||
|
arm/sync_fetch_and_min_4.o \
|
||||||
|
arm/sync_fetch_and_min_8.o \
|
||||||
|
arm/sync_fetch_and_nand_4.o \
|
||||||
|
arm/sync_fetch_and_nand_8.o \
|
||||||
|
arm/sync_fetch_and_or_4.o \
|
||||||
|
arm/sync_fetch_and_or_8.o \
|
||||||
|
arm/sync_fetch_and_sub_4.o \
|
||||||
|
arm/sync_fetch_and_sub_8.o \
|
||||||
|
arm/sync_fetch_and_umax_4.o \
|
||||||
|
arm/sync_fetch_and_umax_8.o \
|
||||||
|
arm/sync_fetch_and_umin_4.o \
|
||||||
|
arm/sync_fetch_and_umin_8.o \
|
||||||
|
arm/sync_fetch_and_xor_4.o \
|
||||||
|
arm/sync_fetch_and_xor_8.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
# VFP sources
|
||||||
|
ifeq ($$(findstring eabihf,$(1)),eabihf)
|
||||||
|
COMPRT_OBJS_$(1) += \
|
||||||
|
arm/adddf3vfp.o \
|
||||||
|
arm/addsf3vfp.o \
|
||||||
|
arm/divdf3vfp.o \
|
||||||
|
arm/divsf3vfp.o \
|
||||||
|
arm/eqdf2vfp.o \
|
||||||
|
arm/eqsf2vfp.o \
|
||||||
|
arm/extendsfdf2vfp.o \
|
||||||
|
arm/fixdfsivfp.o \
|
||||||
|
arm/fixsfsivfp.o \
|
||||||
|
arm/fixunsdfsivfp.o \
|
||||||
|
arm/fixunssfsivfp.o \
|
||||||
|
arm/floatsidfvfp.o \
|
||||||
|
arm/floatsisfvfp.o \
|
||||||
|
arm/floatunssidfvfp.o \
|
||||||
|
arm/floatunssisfvfp.o \
|
||||||
|
arm/gedf2vfp.o \
|
||||||
|
arm/gesf2vfp.o \
|
||||||
|
arm/gtdf2vfp.o \
|
||||||
|
arm/gtsf2vfp.o \
|
||||||
|
arm/ledf2vfp.o \
|
||||||
|
arm/lesf2vfp.o \
|
||||||
|
arm/ltdf2vfp.o \
|
||||||
|
arm/ltsf2vfp.o \
|
||||||
|
arm/muldf3vfp.o \
|
||||||
|
arm/mulsf3vfp.o \
|
||||||
|
arm/negdf2vfp.o \
|
||||||
|
arm/negsf2vfp.o \
|
||||||
|
arm/nedf2vfp.o \
|
||||||
|
arm/nesf2vfp.o \
|
||||||
|
arm/restore_vfp_d8_d15_regs.o \
|
||||||
|
arm/save_vfp_d8_d15_regs.o \
|
||||||
|
arm/subdf3vfp.o \
|
||||||
|
arm/subsf3vfp.o \
|
||||||
|
arm/truncdfsf2vfp.o \
|
||||||
|
arm/unorddf2vfp.o \
|
||||||
|
arm/unordsf2vfp.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($$(findstring aarch64,$(1)),aarch64)
|
||||||
|
COMPRT_OBJS_$(1) += \
|
||||||
|
comparetf2.o \
|
||||||
|
extenddftf2.o \
|
||||||
|
extendsftf2.o \
|
||||||
|
fixtfdi.o \
|
||||||
|
fixtfsi.o \
|
||||||
|
fixtfti.o \
|
||||||
|
fixunstfdi.o \
|
||||||
|
fixunstfsi.o \
|
||||||
|
fixunstfti.o \
|
||||||
|
floatditf.o \
|
||||||
|
floatsitf.o \
|
||||||
|
floatunditf.o \
|
||||||
|
floatunsitf.o \
|
||||||
|
multc3.o \
|
||||||
|
trunctfdf2.o \
|
||||||
|
trunctfsf2.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($$(findstring msvc,$(1)),msvc)
|
||||||
|
$$(COMPRT_BUILD_DIR_$(1))/%.o: CFLAGS += -Zl -D__func__=__FUNCTION__
|
||||||
|
else
|
||||||
|
$$(COMPRT_BUILD_DIR_$(1))/%.o: CFLAGS += -fno-builtin -fvisibility=hidden \
|
||||||
|
-fomit-frame-pointer -ffreestanding
|
||||||
|
endif
|
||||||
|
|
||||||
|
COMPRT_OBJS_$(1) := $$(COMPRT_OBJS_$(1):%=$$(COMPRT_BUILD_DIR_$(1))/%)
|
||||||
|
|
||||||
|
$$(COMPRT_BUILD_DIR_$(1))/%.o: $(S)src/compiler-rt/lib/builtins/%.c
|
||||||
|
@mkdir -p $$(@D)
|
||||||
|
@$$(call E, compile: $$@)
|
||||||
|
$$(Q)$$(call CFG_COMPILE_C_$(1),$$@,$$<)
|
||||||
|
|
||||||
|
$$(COMPRT_BUILD_DIR_$(1))/%.o: $(S)src/compiler-rt/lib/builtins/%.S \
|
||||||
|
$$(LLVM_CONFIG_$$(CFG_BUILD))
|
||||||
|
@mkdir -p $$(@D)
|
||||||
|
@$$(call E, compile: $$@)
|
||||||
|
$$(Q)$$(call CFG_ASSEMBLE_$(1),$$@,$$<)
|
||||||
|
|
||||||
|
ifeq ($$(findstring msvc,$(1)),msvc)
|
||||||
|
$$(COMPRT_BUILD_DIR_$(1))/%.o: \
|
||||||
|
export INCLUDE := $$(CFG_MSVC_INCLUDE_PATH_$$(HOST_$(1)))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($$(findstring emscripten,$(1)),emscripten)
|
ifeq ($$(findstring emscripten,$(1)),emscripten)
|
||||||
|
|
||||||
# FIXME: emscripten doesn't use compiler-rt and can't build it without
|
# FIXME: emscripten doesn't use compiler-rt and can't build it without
|
||||||
# further hacks
|
# further hacks
|
||||||
$$(COMPRT_LIB_$(1)):
|
COMPRT_OBJS_$(1) :=
|
||||||
touch $$@
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
$$(COMPRT_LIB_$(1)): $$(COMPRT_DEPS) $$(MKFILE_DEPS) $$(LLVM_CONFIG_$$(CFG_BUILD))
|
|
||||||
@$$(call E, cmake: compiler-rt)
|
|
||||||
$$(Q)rm -rf $$(COMPRT_BUILD_DIR_$(1))
|
|
||||||
$$(Q)mkdir $$(COMPRT_BUILD_DIR_$(1))
|
|
||||||
$$(Q)cd "$$(COMPRT_BUILD_DIR_$(1))"; \
|
|
||||||
$$(CFG_CMAKE) "$(S)src/compiler-rt" \
|
|
||||||
-DCMAKE_BUILD_TYPE=$$(LLVM_BUILD_CONFIG_MODE) \
|
|
||||||
-DLLVM_CONFIG_PATH=$$(LLVM_CONFIG_$$(CFG_BUILD)) \
|
|
||||||
-DCOMPILER_RT_DEFAULT_TARGET_TRIPLE=$(1) \
|
|
||||||
-DCOMPILER_RT_BUILD_SANITIZERS=OFF \
|
|
||||||
-DCOMPILER_RT_BUILD_EMUTLS=OFF \
|
|
||||||
$$(COMPRT_DEFINES_$(1)) \
|
|
||||||
$$(COMPRT_BUILD_CC_$(1)) \
|
|
||||||
-G"$$(CFG_CMAKE_GENERATOR)"
|
|
||||||
ifneq ($$(CFG_NINJA),)
|
|
||||||
$$(CFG_CMAKE) --build "$$(COMPRT_BUILD_DIR_$(1))" \
|
|
||||||
--target $$(COMPRT_BUILD_TARGET_$(1)) \
|
|
||||||
--config $$(LLVM_BUILD_CONFIG_MODE) \
|
|
||||||
-- $$(COMPRT_BUILD_ARGS_$(1))
|
|
||||||
else
|
|
||||||
$$(Q)$$(CFG_CMAKE) --build "$$(COMPRT_BUILD_DIR_$(1))" \
|
|
||||||
--target $$(COMPRT_BUILD_TARGET_$(1)) \
|
|
||||||
--config $$(LLVM_BUILD_CONFIG_MODE) \
|
|
||||||
-- $$(COMPRT_BUILD_ARGS_$(1)) $$(MFLAGS)
|
|
||||||
endif
|
endif
|
||||||
$$(Q)cp "$$(COMPRT_OUTPUT_$(1))" $$@
|
|
||||||
|
|
||||||
endif
|
$$(COMPRT_LIB_$(1)): $$(COMPRT_OBJS_$(1))
|
||||||
|
@$$(call E, link: $$@)
|
||||||
|
$$(Q)$$(call CFG_CREATE_ARCHIVE_$(1),$$@) $$^
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# libbacktrace
|
# libbacktrace
|
||||||
|
|
|
@ -24,7 +24,7 @@ LLVM_EXTRA_INCDIRS_$(1)= $$(call CFG_CC_INCLUDE_$(1),$(S)src/llvm/include) \
|
||||||
endif
|
endif
|
||||||
|
|
||||||
RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, \
|
RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, \
|
||||||
ExecutionEngineWrapper.cpp RustWrapper.cpp PassWrapper.cpp \
|
RustWrapper.cpp PassWrapper.cpp \
|
||||||
ArchiveWrapper.cpp)
|
ArchiveWrapper.cpp)
|
||||||
|
|
||||||
RUSTLLVM_INCS_$(1) = $$(LLVM_EXTRA_INCDIRS_$(1)) \
|
RUSTLLVM_INCS_$(1) = $$(LLVM_EXTRA_INCDIRS_$(1)) \
|
||||||
|
|
14
mk/tests.mk
14
mk/tests.mk
|
@ -277,7 +277,8 @@ check-stage$(1)-T-$(2)-H-$(3)-exec: \
|
||||||
check-stage$(1)-T-$(2)-H-$(3)-ui-exec \
|
check-stage$(1)-T-$(2)-H-$(3)-ui-exec \
|
||||||
check-stage$(1)-T-$(2)-H-$(3)-doc-exec \
|
check-stage$(1)-T-$(2)-H-$(3)-doc-exec \
|
||||||
check-stage$(1)-T-$(2)-H-$(3)-doc-error-index-exec \
|
check-stage$(1)-T-$(2)-H-$(3)-doc-error-index-exec \
|
||||||
check-stage$(1)-T-$(2)-H-$(3)-pretty-exec
|
check-stage$(1)-T-$(2)-H-$(3)-pretty-exec \
|
||||||
|
check-stage$(1)-T-$(2)-H-$(3)-mir-opt-exec
|
||||||
|
|
||||||
ifndef CFG_DISABLE_CODEGEN_TESTS
|
ifndef CFG_DISABLE_CODEGEN_TESTS
|
||||||
check-stage$(1)-T-$(2)-H-$(3)-exec: \
|
check-stage$(1)-T-$(2)-H-$(3)-exec: \
|
||||||
|
@ -458,6 +459,7 @@ UI_RS := $(call rwildcard,$(S)src/test/ui/,*.rs) \
|
||||||
$(call rwildcard,$(S)src/test/ui/,*.stdout) \
|
$(call rwildcard,$(S)src/test/ui/,*.stdout) \
|
||||||
$(call rwildcard,$(S)src/test/ui/,*.stderr)
|
$(call rwildcard,$(S)src/test/ui/,*.stderr)
|
||||||
RUSTDOCCK_RS := $(call rwildcard,$(S)src/test/rustdoc/,*.rs)
|
RUSTDOCCK_RS := $(call rwildcard,$(S)src/test/rustdoc/,*.rs)
|
||||||
|
MIR_OPT_RS := $(call rwildcard,$(S)src/test/mir-opt/,*.rs)
|
||||||
|
|
||||||
RPASS_TESTS := $(RPASS_RS)
|
RPASS_TESTS := $(RPASS_RS)
|
||||||
RPASS_VALGRIND_TESTS := $(RPASS_VALGRIND_RS)
|
RPASS_VALGRIND_TESTS := $(RPASS_VALGRIND_RS)
|
||||||
|
@ -475,6 +477,7 @@ CODEGEN_UNITS_TESTS := $(CODEGEN_UNITS_RS)
|
||||||
INCREMENTAL_TESTS := $(INCREMENTAL_RS)
|
INCREMENTAL_TESTS := $(INCREMENTAL_RS)
|
||||||
RMAKE_TESTS := $(RMAKE_RS)
|
RMAKE_TESTS := $(RMAKE_RS)
|
||||||
UI_TESTS := $(UI_RS)
|
UI_TESTS := $(UI_RS)
|
||||||
|
MIR_OPT_TESTS := $(MIR_OPT_RS)
|
||||||
RUSTDOCCK_TESTS := $(RUSTDOCCK_RS)
|
RUSTDOCCK_TESTS := $(RUSTDOCCK_RS)
|
||||||
|
|
||||||
CTEST_SRC_BASE_rpass = run-pass
|
CTEST_SRC_BASE_rpass = run-pass
|
||||||
|
@ -552,6 +555,11 @@ CTEST_BUILD_BASE_ui = ui
|
||||||
CTEST_MODE_ui = ui
|
CTEST_MODE_ui = ui
|
||||||
CTEST_RUNTOOL_ui = $(CTEST_RUNTOOL)
|
CTEST_RUNTOOL_ui = $(CTEST_RUNTOOL)
|
||||||
|
|
||||||
|
CTEST_SRC_BASE_mir-opt = mir-opt
|
||||||
|
CTEST_BUILD_BASE_mir-opt = mir-opt
|
||||||
|
CTEST_MODE_mir-opt = mir-opt
|
||||||
|
CTEST_RUNTOOL_mir-opt = $(CTEST_RUNTOOL)
|
||||||
|
|
||||||
CTEST_SRC_BASE_rustdocck = rustdoc
|
CTEST_SRC_BASE_rustdocck = rustdoc
|
||||||
CTEST_BUILD_BASE_rustdocck = rustdoc
|
CTEST_BUILD_BASE_rustdocck = rustdoc
|
||||||
CTEST_MODE_rustdocck = rustdoc
|
CTEST_MODE_rustdocck = rustdoc
|
||||||
|
@ -684,6 +692,7 @@ CTEST_DEPS_incremental_$(1)-T-$(2)-H-$(3) = $$(INCREMENTAL_TESTS)
|
||||||
CTEST_DEPS_rmake_$(1)-T-$(2)-H-$(3) = $$(RMAKE_TESTS) \
|
CTEST_DEPS_rmake_$(1)-T-$(2)-H-$(3) = $$(RMAKE_TESTS) \
|
||||||
$$(CSREQ$(1)_T_$(3)_H_$(3)) $$(SREQ$(1)_T_$(2)_H_$(3))
|
$$(CSREQ$(1)_T_$(3)_H_$(3)) $$(SREQ$(1)_T_$(2)_H_$(3))
|
||||||
CTEST_DEPS_ui_$(1)-T-$(2)-H-$(3) = $$(UI_TESTS)
|
CTEST_DEPS_ui_$(1)-T-$(2)-H-$(3) = $$(UI_TESTS)
|
||||||
|
CTEST_DEPS_mir-opt_$(1)-T-$(2)-H-$(3) = $$(MIR_OPT_TESTS)
|
||||||
CTEST_DEPS_rustdocck_$(1)-T-$(2)-H-$(3) = $$(RUSTDOCCK_TESTS) \
|
CTEST_DEPS_rustdocck_$(1)-T-$(2)-H-$(3) = $$(RUSTDOCCK_TESTS) \
|
||||||
$$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
|
$$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
|
||||||
$(S)src/etc/htmldocck.py
|
$(S)src/etc/htmldocck.py
|
||||||
|
@ -755,7 +764,7 @@ endef
|
||||||
|
|
||||||
CTEST_NAMES = rpass rpass-valgrind rpass-full rfail-full cfail-full rfail cfail pfail \
|
CTEST_NAMES = rpass rpass-valgrind rpass-full rfail-full cfail-full rfail cfail pfail \
|
||||||
debuginfo-gdb debuginfo-lldb codegen codegen-units rustdocck incremental \
|
debuginfo-gdb debuginfo-lldb codegen codegen-units rustdocck incremental \
|
||||||
rmake ui
|
rmake ui mir-opt
|
||||||
|
|
||||||
$(foreach host,$(CFG_HOST), \
|
$(foreach host,$(CFG_HOST), \
|
||||||
$(eval $(foreach target,$(CFG_TARGET), \
|
$(eval $(foreach target,$(CFG_TARGET), \
|
||||||
|
@ -964,6 +973,7 @@ TEST_GROUPS = \
|
||||||
pretty-rfail-full \
|
pretty-rfail-full \
|
||||||
pretty-rfail \
|
pretty-rfail \
|
||||||
pretty-pretty \
|
pretty-pretty \
|
||||||
|
mir-opt \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
define DEF_CHECK_FOR_STAGE_AND_TARGET_AND_HOST
|
define DEF_CHECK_FOR_STAGE_AND_TARGET_AND_HOST
|
||||||
|
|
23
src/bootstrap/Cargo.lock
generated
23
src/bootstrap/Cargo.lock
generated
|
@ -5,10 +5,10 @@ dependencies = [
|
||||||
"build_helper 0.1.0",
|
"build_helper 0.1.0",
|
||||||
"cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"gcc 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gcc 0.3.31 (git+https://github.com/alexcrichton/gcc-rs)",
|
||||||
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"md5 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"md5 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
"num_cpus 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -25,7 +25,7 @@ name = "cmake"
|
||||||
version = "0.1.17"
|
version = "0.1.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gcc 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
"gcc 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -33,12 +33,17 @@ name = "filetime"
|
||||||
version = "0.1.10"
|
version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gcc"
|
name = "gcc"
|
||||||
version = "0.3.26"
|
version = "0.3.31"
|
||||||
|
source = "git+https://github.com/alexcrichton/gcc-rs#b8e2400883f1a2749b323354dad372cdd1c838c7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gcc"
|
||||||
|
version = "0.3.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -48,7 +53,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kernel32-sys"
|
name = "kernel32-sys"
|
||||||
version = "0.2.1"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -57,7 +62,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.9"
|
version = "0.2.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -70,7 +75,7 @@ name = "num_cpus"
|
||||||
version = "0.2.11"
|
version = "0.2.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -29,6 +29,6 @@ getopts = "0.2"
|
||||||
rustc-serialize = "0.3"
|
rustc-serialize = "0.3"
|
||||||
winapi = "0.2"
|
winapi = "0.2"
|
||||||
kernel32-sys = "0.2"
|
kernel32-sys = "0.2"
|
||||||
gcc = "0.3.17"
|
gcc = { git = "https://github.com/alexcrichton/gcc-rs" }
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
md5 = "0.1"
|
md5 = "0.1"
|
||||||
|
|
|
@ -92,8 +92,7 @@ pub fn std_link(build: &Build,
|
||||||
}
|
}
|
||||||
add_to_sysroot(&out_dir, &libdir);
|
add_to_sysroot(&out_dir, &libdir);
|
||||||
|
|
||||||
if target.contains("musl") &&
|
if target.contains("musl") && !target.contains("mips") {
|
||||||
(target.contains("x86_64") || target.contains("i686")) {
|
|
||||||
copy_third_party_objects(build, target, &libdir);
|
copy_third_party_objects(build, target, &libdir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,7 @@ pub struct Config {
|
||||||
// libstd features
|
// libstd features
|
||||||
pub debug_jemalloc: bool,
|
pub debug_jemalloc: bool,
|
||||||
pub use_jemalloc: bool,
|
pub use_jemalloc: bool,
|
||||||
|
pub backtrace: bool, // support for RUST_BACKTRACE
|
||||||
|
|
||||||
// misc
|
// misc
|
||||||
pub channel: String,
|
pub channel: String,
|
||||||
|
@ -134,6 +135,7 @@ struct Rust {
|
||||||
debuginfo: Option<bool>,
|
debuginfo: Option<bool>,
|
||||||
debug_jemalloc: Option<bool>,
|
debug_jemalloc: Option<bool>,
|
||||||
use_jemalloc: Option<bool>,
|
use_jemalloc: Option<bool>,
|
||||||
|
backtrace: Option<bool>,
|
||||||
default_linker: Option<String>,
|
default_linker: Option<String>,
|
||||||
default_ar: Option<String>,
|
default_ar: Option<String>,
|
||||||
channel: Option<String>,
|
channel: Option<String>,
|
||||||
|
@ -158,6 +160,7 @@ impl Config {
|
||||||
let mut config = Config::default();
|
let mut config = Config::default();
|
||||||
config.llvm_optimize = true;
|
config.llvm_optimize = true;
|
||||||
config.use_jemalloc = true;
|
config.use_jemalloc = true;
|
||||||
|
config.backtrace = true;
|
||||||
config.rust_optimize = true;
|
config.rust_optimize = true;
|
||||||
config.rust_optimize_tests = true;
|
config.rust_optimize_tests = true;
|
||||||
config.submodules = true;
|
config.submodules = true;
|
||||||
|
@ -230,6 +233,7 @@ impl Config {
|
||||||
set(&mut config.rust_rpath, rust.rpath);
|
set(&mut config.rust_rpath, rust.rpath);
|
||||||
set(&mut config.debug_jemalloc, rust.debug_jemalloc);
|
set(&mut config.debug_jemalloc, rust.debug_jemalloc);
|
||||||
set(&mut config.use_jemalloc, rust.use_jemalloc);
|
set(&mut config.use_jemalloc, rust.use_jemalloc);
|
||||||
|
set(&mut config.backtrace, rust.backtrace);
|
||||||
set(&mut config.channel, rust.channel.clone());
|
set(&mut config.channel, rust.channel.clone());
|
||||||
config.rustc_default_linker = rust.default_linker.clone();
|
config.rustc_default_linker = rust.default_linker.clone();
|
||||||
config.rustc_default_ar = rust.default_ar.clone();
|
config.rustc_default_ar = rust.default_ar.clone();
|
||||||
|
|
|
@ -99,6 +99,9 @@
|
||||||
# Whether or not jemalloc is built with its debug option set
|
# Whether or not jemalloc is built with its debug option set
|
||||||
#debug-jemalloc = false
|
#debug-jemalloc = false
|
||||||
|
|
||||||
|
# Whether or not `panic!`s generate backtraces (RUST_BACKTRACE)
|
||||||
|
#backtrace = true
|
||||||
|
|
||||||
# The default linker that will be used by the generated compiler. Note that this
|
# The default linker that will be used by the generated compiler. Note that this
|
||||||
# is not the linker used to link said compiler.
|
# is not the linker used to link said compiler.
|
||||||
#default-linker = "cc"
|
#default-linker = "cc"
|
||||||
|
|
|
@ -388,6 +388,10 @@ impl Build {
|
||||||
check::compiletest(self, &compiler, target.target,
|
check::compiletest(self, &compiler, target.target,
|
||||||
"pretty", "run-pass-valgrind");
|
"pretty", "run-pass-valgrind");
|
||||||
}
|
}
|
||||||
|
CheckMirOpt { compiler } => {
|
||||||
|
check::compiletest(self, &compiler, target.target,
|
||||||
|
"mir-opt", "mir-opt");
|
||||||
|
}
|
||||||
CheckCodegen { compiler } => {
|
CheckCodegen { compiler } => {
|
||||||
check::compiletest(self, &compiler, target.target,
|
check::compiletest(self, &compiler, target.target,
|
||||||
"codegen", "codegen");
|
"codegen", "codegen");
|
||||||
|
@ -648,6 +652,9 @@ impl Build {
|
||||||
if self.config.use_jemalloc {
|
if self.config.use_jemalloc {
|
||||||
features.push_str(" jemalloc");
|
features.push_str(" jemalloc");
|
||||||
}
|
}
|
||||||
|
if self.config.backtrace {
|
||||||
|
features.push_str(" backtrace");
|
||||||
|
}
|
||||||
return features
|
return features
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -848,6 +855,12 @@ impl Build {
|
||||||
base.push("-stdlib=libc++".into());
|
base.push("-stdlib=libc++".into());
|
||||||
base.push("-mmacosx-version-min=10.7".into());
|
base.push("-mmacosx-version-min=10.7".into());
|
||||||
}
|
}
|
||||||
|
// This is a hack, because newer binutils broke things on some vms/distros
|
||||||
|
// (i.e., linking against unknown relocs disabled by the following flag)
|
||||||
|
// See: https://github.com/rust-lang/rust/issues/34978
|
||||||
|
if target == "x86_64-unknown-linux-musl" {
|
||||||
|
base.push("-Wa,-mrelax-relocations=no".into());
|
||||||
|
}
|
||||||
return base
|
return base
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -133,86 +133,397 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) {
|
||||||
|
|
||||||
/// Compiles the `compiler-rt` library, or at least the builtins part of it.
|
/// Compiles the `compiler-rt` library, or at least the builtins part of it.
|
||||||
///
|
///
|
||||||
/// This uses the CMake build system and an existing LLVM build directory to
|
/// Note that while compiler-rt has a build system associated with it, we
|
||||||
/// compile the project.
|
/// specifically don't use it here. The compiler-rt build system, written in
|
||||||
|
/// CMake, is actually *very* difficult to work with in terms of getting it to
|
||||||
|
/// compile on all the relevant platforms we want it to compile on. In the end
|
||||||
|
/// it became so much pain to work with local patches, work around the oddities
|
||||||
|
/// of the build system, etc, that we're just building everything by hand now.
|
||||||
|
///
|
||||||
|
/// In general compiler-rt is just a bunch of intrinsics that are in practice
|
||||||
|
/// *very* stable. We just need to make sure that all the relevant functions and
|
||||||
|
/// such are compiled somewhere and placed in an object file somewhere.
|
||||||
|
/// Eventually, these should all be written in Rust!
|
||||||
|
///
|
||||||
|
/// So below you'll find a listing of every single file in the compiler-rt repo
|
||||||
|
/// that we're compiling. We just reach in and compile with the `gcc` crate
|
||||||
|
/// which should have all the relevant flags and such already configured.
|
||||||
|
///
|
||||||
|
/// The risk here is that if we update compiler-rt we may need to compile some
|
||||||
|
/// new intrinsics, but to be honest we surely don't use all of the intrinsics
|
||||||
|
/// listed below today so the likelihood of us actually needing a new intrinsic
|
||||||
|
/// is quite low. The failure case is also just that someone reports a link
|
||||||
|
/// error (if any) and then we just add it to the list. Overall, that cost is
|
||||||
|
/// far far less than working with compiler-rt's build system over time.
|
||||||
pub fn compiler_rt(build: &Build, target: &str) {
|
pub fn compiler_rt(build: &Build, target: &str) {
|
||||||
let dst = build.compiler_rt_out(target);
|
let build_dir = build.compiler_rt_out(target);
|
||||||
let arch = target.split('-').next().unwrap();
|
let output = build_dir.join(staticlib("compiler-rt", target));
|
||||||
let mode = if build.config.rust_optimize {"Release"} else {"Debug"};
|
|
||||||
|
|
||||||
let build_llvm_config = build.llvm_config(&build.config.build);
|
|
||||||
let mut cfg = cmake::Config::new(build.src.join("src/compiler-rt"));
|
|
||||||
cfg.target(target)
|
|
||||||
.host(&build.config.build)
|
|
||||||
.out_dir(&dst)
|
|
||||||
.profile(mode)
|
|
||||||
.define("LLVM_CONFIG_PATH", build_llvm_config)
|
|
||||||
.define("COMPILER_RT_DEFAULT_TARGET_TRIPLE", target)
|
|
||||||
.define("COMPILER_RT_BUILD_SANITIZERS", "OFF")
|
|
||||||
.define("COMPILER_RT_BUILD_EMUTLS", "OFF")
|
|
||||||
// inform about c/c++ compilers, the c++ compiler isn't actually used but
|
|
||||||
// it's needed to get the initial configure to work on all platforms.
|
|
||||||
.define("CMAKE_C_COMPILER", build.cc(target))
|
|
||||||
.define("CMAKE_CXX_COMPILER", build.cc(target));
|
|
||||||
|
|
||||||
let (dir, build_target, libname) = if target.contains("linux") ||
|
|
||||||
target.contains("freebsd") ||
|
|
||||||
target.contains("netbsd") {
|
|
||||||
let os_extra = if target.contains("android") && target.contains("arm") {
|
|
||||||
"-android"
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
};
|
|
||||||
let builtins_arch = match arch {
|
|
||||||
"i586" => "i386",
|
|
||||||
"arm" | "armv7" if target.contains("android") => "armhf",
|
|
||||||
"arm" if target.contains("eabihf") => "armhf",
|
|
||||||
_ => arch,
|
|
||||||
};
|
|
||||||
let target = format!("clang_rt.builtins-{}", builtins_arch);
|
|
||||||
("linux".to_string(),
|
|
||||||
target.clone(),
|
|
||||||
format!("{}{}", target, os_extra))
|
|
||||||
} else if target.contains("apple-darwin") {
|
|
||||||
let builtins_arch = match arch {
|
|
||||||
"i686" => "i386",
|
|
||||||
_ => arch,
|
|
||||||
};
|
|
||||||
let target = format!("clang_rt.builtins_{}_osx", builtins_arch);
|
|
||||||
("builtins".to_string(), target.clone(), target)
|
|
||||||
} else if target.contains("apple-ios") {
|
|
||||||
cfg.define("COMPILER_RT_ENABLE_IOS", "ON");
|
|
||||||
let target = match arch {
|
|
||||||
"armv7s" => "hard_pic_armv7em_macho_embedded".to_string(),
|
|
||||||
"aarch64" => "builtins_arm64_ios".to_string(),
|
|
||||||
_ => format!("hard_pic_{}_macho_embedded", arch),
|
|
||||||
};
|
|
||||||
("builtins".to_string(), target.clone(), target)
|
|
||||||
} else if target.contains("windows-gnu") {
|
|
||||||
let target = format!("clang_rt.builtins-{}", arch);
|
|
||||||
("windows".to_string(), target.clone(), target)
|
|
||||||
} else if target.contains("windows-msvc") {
|
|
||||||
let builtins_arch = match arch {
|
|
||||||
"i586" | "i686" => "i386",
|
|
||||||
_ => arch,
|
|
||||||
};
|
|
||||||
(format!("windows/{}", mode),
|
|
||||||
"lib/builtins/builtins".to_string(),
|
|
||||||
format!("clang_rt.builtins-{}", builtins_arch))
|
|
||||||
} else {
|
|
||||||
panic!("can't get os from target: {}", target)
|
|
||||||
};
|
|
||||||
let output = dst.join("build/lib").join(dir)
|
|
||||||
.join(staticlib(&libname, target));
|
|
||||||
build.compiler_rt_built.borrow_mut().insert(target.to_string(),
|
build.compiler_rt_built.borrow_mut().insert(target.to_string(),
|
||||||
output.clone());
|
output.clone());
|
||||||
if fs::metadata(&output).is_ok() {
|
t!(fs::create_dir_all(&build_dir));
|
||||||
|
|
||||||
|
let mut cfg = gcc::Config::new();
|
||||||
|
cfg.cargo_metadata(false)
|
||||||
|
.out_dir(&build_dir)
|
||||||
|
.target(target)
|
||||||
|
.host(&build.config.build)
|
||||||
|
.opt_level(2)
|
||||||
|
.debug(false);
|
||||||
|
|
||||||
|
if target.contains("msvc") {
|
||||||
|
// Don't pull in extra libraries on MSVC
|
||||||
|
cfg.flag("/Zl");
|
||||||
|
|
||||||
|
// Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP
|
||||||
|
cfg.define("__func__", Some("__FUNCTION__"));
|
||||||
|
} else {
|
||||||
|
// Turn off various features of gcc and such, mostly copying
|
||||||
|
// compiler-rt's build system already
|
||||||
|
cfg.flag("-fno-builtin");
|
||||||
|
cfg.flag("-fvisibility=hidden");
|
||||||
|
cfg.flag("-fomit-frame-pointer");
|
||||||
|
cfg.flag("-ffreestanding");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut sources = vec![
|
||||||
|
"absvdi2.c",
|
||||||
|
"absvsi2.c",
|
||||||
|
"adddf3.c",
|
||||||
|
"addsf3.c",
|
||||||
|
"addvdi3.c",
|
||||||
|
"addvsi3.c",
|
||||||
|
"apple_versioning.c",
|
||||||
|
"ashldi3.c",
|
||||||
|
"ashrdi3.c",
|
||||||
|
"clear_cache.c",
|
||||||
|
"clzdi2.c",
|
||||||
|
"clzsi2.c",
|
||||||
|
"cmpdi2.c",
|
||||||
|
"comparedf2.c",
|
||||||
|
"comparesf2.c",
|
||||||
|
"ctzdi2.c",
|
||||||
|
"ctzsi2.c",
|
||||||
|
"divdc3.c",
|
||||||
|
"divdf3.c",
|
||||||
|
"divdi3.c",
|
||||||
|
"divmoddi4.c",
|
||||||
|
"divmodsi4.c",
|
||||||
|
"divsc3.c",
|
||||||
|
"divsf3.c",
|
||||||
|
"divsi3.c",
|
||||||
|
"divxc3.c",
|
||||||
|
"extendsfdf2.c",
|
||||||
|
"extendhfsf2.c",
|
||||||
|
"ffsdi2.c",
|
||||||
|
"fixdfdi.c",
|
||||||
|
"fixdfsi.c",
|
||||||
|
"fixsfdi.c",
|
||||||
|
"fixsfsi.c",
|
||||||
|
"fixunsdfdi.c",
|
||||||
|
"fixunsdfsi.c",
|
||||||
|
"fixunssfdi.c",
|
||||||
|
"fixunssfsi.c",
|
||||||
|
"fixunsxfdi.c",
|
||||||
|
"fixunsxfsi.c",
|
||||||
|
"fixxfdi.c",
|
||||||
|
"floatdidf.c",
|
||||||
|
"floatdisf.c",
|
||||||
|
"floatdixf.c",
|
||||||
|
"floatsidf.c",
|
||||||
|
"floatsisf.c",
|
||||||
|
"floatundidf.c",
|
||||||
|
"floatundisf.c",
|
||||||
|
"floatundixf.c",
|
||||||
|
"floatunsidf.c",
|
||||||
|
"floatunsisf.c",
|
||||||
|
"int_util.c",
|
||||||
|
"lshrdi3.c",
|
||||||
|
"moddi3.c",
|
||||||
|
"modsi3.c",
|
||||||
|
"muldc3.c",
|
||||||
|
"muldf3.c",
|
||||||
|
"muldi3.c",
|
||||||
|
"mulodi4.c",
|
||||||
|
"mulosi4.c",
|
||||||
|
"muloti4.c",
|
||||||
|
"mulsc3.c",
|
||||||
|
"mulsf3.c",
|
||||||
|
"mulvdi3.c",
|
||||||
|
"mulvsi3.c",
|
||||||
|
"mulxc3.c",
|
||||||
|
"negdf2.c",
|
||||||
|
"negdi2.c",
|
||||||
|
"negsf2.c",
|
||||||
|
"negvdi2.c",
|
||||||
|
"negvsi2.c",
|
||||||
|
"paritydi2.c",
|
||||||
|
"paritysi2.c",
|
||||||
|
"popcountdi2.c",
|
||||||
|
"popcountsi2.c",
|
||||||
|
"powidf2.c",
|
||||||
|
"powisf2.c",
|
||||||
|
"powixf2.c",
|
||||||
|
"subdf3.c",
|
||||||
|
"subsf3.c",
|
||||||
|
"subvdi3.c",
|
||||||
|
"subvsi3.c",
|
||||||
|
"truncdfhf2.c",
|
||||||
|
"truncdfsf2.c",
|
||||||
|
"truncsfhf2.c",
|
||||||
|
"ucmpdi2.c",
|
||||||
|
"udivdi3.c",
|
||||||
|
"udivmoddi4.c",
|
||||||
|
"udivmodsi4.c",
|
||||||
|
"udivsi3.c",
|
||||||
|
"umoddi3.c",
|
||||||
|
"umodsi3.c",
|
||||||
|
];
|
||||||
|
|
||||||
|
if !target.contains("ios") {
|
||||||
|
sources.extend(vec![
|
||||||
|
"absvti2.c",
|
||||||
|
"addtf3.c",
|
||||||
|
"addvti3.c",
|
||||||
|
"ashlti3.c",
|
||||||
|
"ashrti3.c",
|
||||||
|
"clzti2.c",
|
||||||
|
"cmpti2.c",
|
||||||
|
"ctzti2.c",
|
||||||
|
"divtf3.c",
|
||||||
|
"divti3.c",
|
||||||
|
"ffsti2.c",
|
||||||
|
"fixdfti.c",
|
||||||
|
"fixsfti.c",
|
||||||
|
"fixunsdfti.c",
|
||||||
|
"fixunssfti.c",
|
||||||
|
"fixunsxfti.c",
|
||||||
|
"fixxfti.c",
|
||||||
|
"floattidf.c",
|
||||||
|
"floattisf.c",
|
||||||
|
"floattixf.c",
|
||||||
|
"floatuntidf.c",
|
||||||
|
"floatuntisf.c",
|
||||||
|
"floatuntixf.c",
|
||||||
|
"lshrti3.c",
|
||||||
|
"modti3.c",
|
||||||
|
"multf3.c",
|
||||||
|
"multi3.c",
|
||||||
|
"mulvti3.c",
|
||||||
|
"negti2.c",
|
||||||
|
"negvti2.c",
|
||||||
|
"parityti2.c",
|
||||||
|
"popcountti2.c",
|
||||||
|
"powitf2.c",
|
||||||
|
"subtf3.c",
|
||||||
|
"subvti3.c",
|
||||||
|
"trampoline_setup.c",
|
||||||
|
"ucmpti2.c",
|
||||||
|
"udivmodti4.c",
|
||||||
|
"udivti3.c",
|
||||||
|
"umodti3.c",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if target.contains("apple") {
|
||||||
|
sources.extend(vec![
|
||||||
|
"atomic_flag_clear.c",
|
||||||
|
"atomic_flag_clear_explicit.c",
|
||||||
|
"atomic_flag_test_and_set.c",
|
||||||
|
"atomic_flag_test_and_set_explicit.c",
|
||||||
|
"atomic_signal_fence.c",
|
||||||
|
"atomic_thread_fence.c",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !target.contains("windows") {
|
||||||
|
sources.push("emutls.c");
|
||||||
|
}
|
||||||
|
|
||||||
|
if target.contains("msvc") {
|
||||||
|
if target.contains("x86_64") {
|
||||||
|
sources.extend(vec![
|
||||||
|
"x86_64/floatdidf.c",
|
||||||
|
"x86_64/floatdisf.c",
|
||||||
|
"x86_64/floatdixf.c",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !target.contains("freebsd") {
|
||||||
|
sources.push("gcc_personality_v0.c");
|
||||||
|
}
|
||||||
|
|
||||||
|
if target.contains("x86_64") {
|
||||||
|
sources.extend(vec![
|
||||||
|
"x86_64/chkstk.S",
|
||||||
|
"x86_64/chkstk2.S",
|
||||||
|
"x86_64/floatdidf.c",
|
||||||
|
"x86_64/floatdisf.c",
|
||||||
|
"x86_64/floatdixf.c",
|
||||||
|
"x86_64/floatundidf.S",
|
||||||
|
"x86_64/floatundisf.S",
|
||||||
|
"x86_64/floatundixf.S",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if target.contains("i386") ||
|
||||||
|
target.contains("i586") ||
|
||||||
|
target.contains("i686") {
|
||||||
|
sources.extend(vec![
|
||||||
|
"i386/ashldi3.S",
|
||||||
|
"i386/ashrdi3.S",
|
||||||
|
"i386/chkstk.S",
|
||||||
|
"i386/chkstk2.S",
|
||||||
|
"i386/divdi3.S",
|
||||||
|
"i386/floatdidf.S",
|
||||||
|
"i386/floatdisf.S",
|
||||||
|
"i386/floatdixf.S",
|
||||||
|
"i386/floatundidf.S",
|
||||||
|
"i386/floatundisf.S",
|
||||||
|
"i386/floatundixf.S",
|
||||||
|
"i386/lshrdi3.S",
|
||||||
|
"i386/moddi3.S",
|
||||||
|
"i386/muldi3.S",
|
||||||
|
"i386/udivdi3.S",
|
||||||
|
"i386/umoddi3.S",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if target.contains("arm") && !target.contains("ios") {
|
||||||
|
sources.extend(vec![
|
||||||
|
"arm/aeabi_cdcmp.S",
|
||||||
|
"arm/aeabi_cdcmpeq_check_nan.c",
|
||||||
|
"arm/aeabi_cfcmp.S",
|
||||||
|
"arm/aeabi_cfcmpeq_check_nan.c",
|
||||||
|
"arm/aeabi_dcmp.S",
|
||||||
|
"arm/aeabi_div0.c",
|
||||||
|
"arm/aeabi_drsub.c",
|
||||||
|
"arm/aeabi_fcmp.S",
|
||||||
|
"arm/aeabi_frsub.c",
|
||||||
|
"arm/aeabi_idivmod.S",
|
||||||
|
"arm/aeabi_ldivmod.S",
|
||||||
|
"arm/aeabi_memcmp.S",
|
||||||
|
"arm/aeabi_memcpy.S",
|
||||||
|
"arm/aeabi_memmove.S",
|
||||||
|
"arm/aeabi_memset.S",
|
||||||
|
"arm/aeabi_uidivmod.S",
|
||||||
|
"arm/aeabi_uldivmod.S",
|
||||||
|
"arm/bswapdi2.S",
|
||||||
|
"arm/bswapsi2.S",
|
||||||
|
"arm/clzdi2.S",
|
||||||
|
"arm/clzsi2.S",
|
||||||
|
"arm/comparesf2.S",
|
||||||
|
"arm/divmodsi4.S",
|
||||||
|
"arm/divsi3.S",
|
||||||
|
"arm/modsi3.S",
|
||||||
|
"arm/switch16.S",
|
||||||
|
"arm/switch32.S",
|
||||||
|
"arm/switch8.S",
|
||||||
|
"arm/switchu8.S",
|
||||||
|
"arm/sync_synchronize.S",
|
||||||
|
"arm/udivmodsi4.S",
|
||||||
|
"arm/udivsi3.S",
|
||||||
|
"arm/umodsi3.S",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if target.contains("armv7") {
|
||||||
|
sources.extend(vec![
|
||||||
|
"arm/sync_fetch_and_add_4.S",
|
||||||
|
"arm/sync_fetch_and_add_8.S",
|
||||||
|
"arm/sync_fetch_and_and_4.S",
|
||||||
|
"arm/sync_fetch_and_and_8.S",
|
||||||
|
"arm/sync_fetch_and_max_4.S",
|
||||||
|
"arm/sync_fetch_and_max_8.S",
|
||||||
|
"arm/sync_fetch_and_min_4.S",
|
||||||
|
"arm/sync_fetch_and_min_8.S",
|
||||||
|
"arm/sync_fetch_and_nand_4.S",
|
||||||
|
"arm/sync_fetch_and_nand_8.S",
|
||||||
|
"arm/sync_fetch_and_or_4.S",
|
||||||
|
"arm/sync_fetch_and_or_8.S",
|
||||||
|
"arm/sync_fetch_and_sub_4.S",
|
||||||
|
"arm/sync_fetch_and_sub_8.S",
|
||||||
|
"arm/sync_fetch_and_umax_4.S",
|
||||||
|
"arm/sync_fetch_and_umax_8.S",
|
||||||
|
"arm/sync_fetch_and_umin_4.S",
|
||||||
|
"arm/sync_fetch_and_umin_8.S",
|
||||||
|
"arm/sync_fetch_and_xor_4.S",
|
||||||
|
"arm/sync_fetch_and_xor_8.S",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if target.contains("eabihf") {
|
||||||
|
sources.extend(vec![
|
||||||
|
"arm/adddf3vfp.S",
|
||||||
|
"arm/addsf3vfp.S",
|
||||||
|
"arm/divdf3vfp.S",
|
||||||
|
"arm/divsf3vfp.S",
|
||||||
|
"arm/eqdf2vfp.S",
|
||||||
|
"arm/eqsf2vfp.S",
|
||||||
|
"arm/extendsfdf2vfp.S",
|
||||||
|
"arm/fixdfsivfp.S",
|
||||||
|
"arm/fixsfsivfp.S",
|
||||||
|
"arm/fixunsdfsivfp.S",
|
||||||
|
"arm/fixunssfsivfp.S",
|
||||||
|
"arm/floatsidfvfp.S",
|
||||||
|
"arm/floatsisfvfp.S",
|
||||||
|
"arm/floatunssidfvfp.S",
|
||||||
|
"arm/floatunssisfvfp.S",
|
||||||
|
"arm/gedf2vfp.S",
|
||||||
|
"arm/gesf2vfp.S",
|
||||||
|
"arm/gtdf2vfp.S",
|
||||||
|
"arm/gtsf2vfp.S",
|
||||||
|
"arm/ledf2vfp.S",
|
||||||
|
"arm/lesf2vfp.S",
|
||||||
|
"arm/ltdf2vfp.S",
|
||||||
|
"arm/ltsf2vfp.S",
|
||||||
|
"arm/muldf3vfp.S",
|
||||||
|
"arm/mulsf3vfp.S",
|
||||||
|
"arm/negdf2vfp.S",
|
||||||
|
"arm/negsf2vfp.S",
|
||||||
|
"arm/nedf2vfp.S",
|
||||||
|
"arm/nesf2vfp.S",
|
||||||
|
"arm/restore_vfp_d8_d15_regs.S",
|
||||||
|
"arm/save_vfp_d8_d15_regs.S",
|
||||||
|
"arm/subdf3vfp.S",
|
||||||
|
"arm/subsf3vfp.S",
|
||||||
|
"arm/truncdfsf2vfp.S",
|
||||||
|
"arm/unorddf2vfp.S",
|
||||||
|
"arm/unordsf2vfp.S",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if target.contains("aarch64") {
|
||||||
|
sources.extend(vec![
|
||||||
|
"comparetf2.c",
|
||||||
|
"extenddftf2.c",
|
||||||
|
"extendsftf2.c",
|
||||||
|
"fixtfdi.c",
|
||||||
|
"fixtfsi.c",
|
||||||
|
"fixtfti.c",
|
||||||
|
"fixunstfdi.c",
|
||||||
|
"fixunstfsi.c",
|
||||||
|
"fixunstfti.c",
|
||||||
|
"floatditf.c",
|
||||||
|
"floatsitf.c",
|
||||||
|
"floatunditf.c",
|
||||||
|
"floatunsitf.c",
|
||||||
|
"multc3.c",
|
||||||
|
"trunctfdf2.c",
|
||||||
|
"trunctfsf2.c",
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut out_of_date = false;
|
||||||
|
for src in sources {
|
||||||
|
let src = build.src.join("src/compiler-rt/lib/builtins").join(src);
|
||||||
|
out_of_date = out_of_date || !up_to_date(&src, &output);
|
||||||
|
cfg.file(src);
|
||||||
|
}
|
||||||
|
if !out_of_date {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let _ = fs::remove_dir_all(&dst);
|
cfg.compile("libcompiler-rt.a");
|
||||||
t!(fs::create_dir_all(&dst));
|
|
||||||
cfg.build_target(&build_target);
|
|
||||||
cfg.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compiles the `rust_test_helpers.c` library which we used in various
|
/// Compiles the `rust_test_helpers.c` library which we used in various
|
||||||
|
|
|
@ -31,6 +31,15 @@ use Build;
|
||||||
pub fn check(build: &mut Build) {
|
pub fn check(build: &mut Build) {
|
||||||
let mut checked = HashSet::new();
|
let mut checked = HashSet::new();
|
||||||
let path = env::var_os("PATH").unwrap_or(OsString::new());
|
let path = env::var_os("PATH").unwrap_or(OsString::new());
|
||||||
|
// On Windows, quotes are invalid characters for filename paths, and if
|
||||||
|
// one is present as part of the PATH then that can lead to the system
|
||||||
|
// being unable to identify the files properly. See
|
||||||
|
// https://github.com/rust-lang/rust/issues/34959 for more details.
|
||||||
|
if cfg!(windows) {
|
||||||
|
if path.to_string_lossy().contains("\"") {
|
||||||
|
panic!("PATH contains invalid character '\"'");
|
||||||
|
}
|
||||||
|
}
|
||||||
let mut need_cmd = |cmd: &OsStr| {
|
let mut need_cmd = |cmd: &OsStr| {
|
||||||
if !checked.insert(cmd.to_owned()) {
|
if !checked.insert(cmd.to_owned()) {
|
||||||
return
|
return
|
||||||
|
@ -100,7 +109,7 @@ pub fn check(build: &mut Build) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure musl-root is valid if specified
|
// Make sure musl-root is valid if specified
|
||||||
if target.contains("musl") && (target.contains("x86_64") || target.contains("i686")) {
|
if target.contains("musl") && !target.contains("mips") {
|
||||||
match build.config.musl_root {
|
match build.config.musl_root {
|
||||||
Some(ref root) => {
|
Some(ref root) => {
|
||||||
if fs::metadata(root.join("lib/libc.a")).is_err() {
|
if fs::metadata(root.join("lib/libc.a")).is_err() {
|
||||||
|
|
|
@ -124,6 +124,7 @@ macro_rules! targets {
|
||||||
(check_codegen_units, CheckCodegenUnits { compiler: Compiler<'a> }),
|
(check_codegen_units, CheckCodegenUnits { compiler: Compiler<'a> }),
|
||||||
(check_incremental, CheckIncremental { compiler: Compiler<'a> }),
|
(check_incremental, CheckIncremental { compiler: Compiler<'a> }),
|
||||||
(check_ui, CheckUi { compiler: Compiler<'a> }),
|
(check_ui, CheckUi { compiler: Compiler<'a> }),
|
||||||
|
(check_mir_opt, CheckMirOpt { compiler: Compiler<'a> }),
|
||||||
(check_debuginfo, CheckDebuginfo { compiler: Compiler<'a> }),
|
(check_debuginfo, CheckDebuginfo { compiler: Compiler<'a> }),
|
||||||
(check_rustdoc, CheckRustdoc { compiler: Compiler<'a> }),
|
(check_rustdoc, CheckRustdoc { compiler: Compiler<'a> }),
|
||||||
(check_docs, CheckDocs { compiler: Compiler<'a> }),
|
(check_docs, CheckDocs { compiler: Compiler<'a> }),
|
||||||
|
@ -347,9 +348,7 @@ impl<'a> Step<'a> {
|
||||||
vec![self.libstd(compiler),
|
vec![self.libstd(compiler),
|
||||||
self.target(host).rustc(compiler.stage)]
|
self.target(host).rustc(compiler.stage)]
|
||||||
}
|
}
|
||||||
Source::CompilerRt { _dummy } => {
|
Source::CompilerRt { _dummy } => Vec::new(),
|
||||||
vec![self.llvm(()).target(&build.config.build)]
|
|
||||||
}
|
|
||||||
Source::Llvm { _dummy } => Vec::new(),
|
Source::Llvm { _dummy } => Vec::new(),
|
||||||
Source::TestHelpers { _dummy } => Vec::new(),
|
Source::TestHelpers { _dummy } => Vec::new(),
|
||||||
Source::DebuggerScripts { stage: _ } => Vec::new(),
|
Source::DebuggerScripts { stage: _ } => Vec::new(),
|
||||||
|
@ -452,6 +451,7 @@ impl<'a> Step<'a> {
|
||||||
self.check_pretty_rfail_full(compiler),
|
self.check_pretty_rfail_full(compiler),
|
||||||
self.check_rpass_valgrind(compiler),
|
self.check_rpass_valgrind(compiler),
|
||||||
self.check_rmake(compiler),
|
self.check_rmake(compiler),
|
||||||
|
self.check_mir_opt(compiler),
|
||||||
|
|
||||||
// crates
|
// crates
|
||||||
self.check_crate_rustc(compiler),
|
self.check_crate_rustc(compiler),
|
||||||
|
@ -479,6 +479,7 @@ impl<'a> Step<'a> {
|
||||||
Source::CheckTidy { stage } => {
|
Source::CheckTidy { stage } => {
|
||||||
vec![self.tool_tidy(stage)]
|
vec![self.tool_tidy(stage)]
|
||||||
}
|
}
|
||||||
|
Source::CheckMirOpt { compiler} |
|
||||||
Source::CheckPrettyRPass { compiler } |
|
Source::CheckPrettyRPass { compiler } |
|
||||||
Source::CheckPrettyRFail { compiler } |
|
Source::CheckPrettyRFail { compiler } |
|
||||||
Source::CheckRFail { compiler } |
|
Source::CheckRFail { compiler } |
|
||||||
|
|
|
@ -103,7 +103,10 @@ pub fn add_lib_path(path: Vec<PathBuf>, cmd: &mut Command) {
|
||||||
/// Uses last-modified time checks to verify this.
|
/// Uses last-modified time checks to verify this.
|
||||||
pub fn up_to_date(src: &Path, dst: &Path) -> bool {
|
pub fn up_to_date(src: &Path, dst: &Path) -> bool {
|
||||||
let threshold = mtime(dst);
|
let threshold = mtime(dst);
|
||||||
let meta = t!(fs::metadata(src));
|
let meta = match fs::metadata(src) {
|
||||||
|
Ok(meta) => meta,
|
||||||
|
Err(e) => panic!("source {:?} failed to get metadata: {}", src, e),
|
||||||
|
};
|
||||||
if meta.is_dir() {
|
if meta.is_dir() {
|
||||||
dir_up_to_date(src, &threshold)
|
dir_up_to_date(src, &threshold)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit ac3d1cda612edccb6f1da53cbf7716e248405f3b
|
Subproject commit 8598065bd965d9713bfafb6c1e766d63a7b17b89
|
|
@ -223,6 +223,7 @@ trait system to overload operators. Calling functions is no different. We have
|
||||||
three separate traits to overload with:
|
three separate traits to overload with:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
# #![feature(unboxed_closures)]
|
||||||
# mod foo {
|
# mod foo {
|
||||||
pub trait Fn<Args> : FnMut<Args> {
|
pub trait Fn<Args> : FnMut<Args> {
|
||||||
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
|
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
|
||||||
|
@ -291,9 +292,9 @@ isn’t interesting. The next part is:
|
||||||
# some_closure(1) }
|
# some_closure(1) }
|
||||||
```
|
```
|
||||||
|
|
||||||
Because `Fn` is a trait, we can bound our generic with it. In this case, our
|
Because `Fn` is a trait, we can use it as a bound for our generic type. In
|
||||||
closure takes a `i32` as an argument and returns an `i32`, and so the generic
|
this case, our closure takes a `i32` as an argument and returns an `i32`, and
|
||||||
bound we use is `Fn(i32) -> i32`.
|
so the generic bound we use is `Fn(i32) -> i32`.
|
||||||
|
|
||||||
There’s one other key point here: because we’re bounding a generic with a
|
There’s one other key point here: because we’re bounding a generic with a
|
||||||
trait, this will get monomorphized, and therefore, we’ll be doing static
|
trait, this will get monomorphized, and therefore, we’ll be doing static
|
||||||
|
|
|
@ -575,16 +575,69 @@ against `libc` and `libm` by default.
|
||||||
|
|
||||||
# The "nullable pointer optimization"
|
# The "nullable pointer optimization"
|
||||||
|
|
||||||
Certain types are defined to not be NULL. This includes references (`&T`,
|
Certain Rust types are defined to never be `null`. This includes references (`&T`,
|
||||||
`&mut T`), boxes (`Box<T>`), and function pointers (`extern "abi" fn()`).
|
`&mut T`), boxes (`Box<T>`), and function pointers (`extern "abi" fn()`). When
|
||||||
When interfacing with C, pointers that might be NULL are often used.
|
interfacing with C, pointers that might be `null` are often used, which would seem to
|
||||||
As a special case, a generic `enum` that contains exactly two variants, one of
|
require some messy `transmute`s and/or unsafe code to handle conversions to/from Rust types.
|
||||||
which contains no data and the other containing a single field, is eligible
|
However, the language provides a workaround.
|
||||||
for the "nullable pointer optimization". When such an enum is instantiated
|
|
||||||
with one of the non-nullable types, it is represented as a single pointer,
|
As a special case, an `enum` is eligible for the "nullable pointer optimization" if it contains
|
||||||
and the non-data variant is represented as the NULL pointer. So
|
exactly two variants, one of which contains no data and the other contains a field of one of the
|
||||||
`Option<extern "C" fn(c_int) -> c_int>` is how one represents a nullable
|
non-nullable types listed above. This means no extra space is required for a discriminant; rather,
|
||||||
function pointer using the C ABI.
|
the empty variant is represented by putting a `null` value into the non-nullable field. This is
|
||||||
|
called an "optimization", but unlike other optimizations it is guaranteed to apply to eligible
|
||||||
|
types.
|
||||||
|
|
||||||
|
The most common type that takes advantage of the nullable pointer optimization is `Option<T>`,
|
||||||
|
where `None` corresponds to `null`. So `Option<extern "C" fn(c_int) -> c_int>` is a correct way
|
||||||
|
to represent a nullable function pointer using the C ABI (corresponding to the C type
|
||||||
|
`int (*)(int)`).
|
||||||
|
|
||||||
|
Here is a contrived example. Let's say some C library has a facility for registering a
|
||||||
|
callback, which gets called in certain situations. The callback is passed a function pointer
|
||||||
|
and an integer and it is supposed to run the function with the integer as a parameter. So
|
||||||
|
we have function pointers flying across the FFI boundary in both directions.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
# #![feature(libc)]
|
||||||
|
extern crate libc;
|
||||||
|
use libc::c_int;
|
||||||
|
|
||||||
|
# #[cfg(hidden)]
|
||||||
|
extern "C" {
|
||||||
|
/// Register the callback.
|
||||||
|
fn register(cb: Option<extern "C" fn(Option<extern "C" fn(c_int) -> c_int>, c_int) -> c_int>);
|
||||||
|
}
|
||||||
|
# unsafe fn register(_: Option<extern "C" fn(Option<extern "C" fn(c_int) -> c_int>,
|
||||||
|
# c_int) -> c_int>)
|
||||||
|
# {}
|
||||||
|
|
||||||
|
/// This fairly useless function receives a function pointer and an integer
|
||||||
|
/// from C, and returns the result of calling the function with the integer.
|
||||||
|
/// In case no function is provided, it squares the integer by default.
|
||||||
|
extern "C" fn apply(process: Option<extern "C" fn(c_int) -> c_int>, int: c_int) -> c_int {
|
||||||
|
match process {
|
||||||
|
Some(f) => f(int),
|
||||||
|
None => int * int
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
unsafe {
|
||||||
|
register(Some(apply));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
And the code on the C side looks like this:
|
||||||
|
|
||||||
|
```c
|
||||||
|
void register(void (*f)(void (*)(int), int)) {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
No `transmute` required!
|
||||||
|
|
||||||
# Calling Rust code from C
|
# Calling Rust code from C
|
||||||
|
|
||||||
|
|
|
@ -365,7 +365,7 @@ numbers. A bare number like above is actually shorthand for `^0.3.0`,
|
||||||
meaning "anything compatible with 0.3.0".
|
meaning "anything compatible with 0.3.0".
|
||||||
If we wanted to use only `0.3.0` exactly, we could say `rand="=0.3.0"`
|
If we wanted to use only `0.3.0` exactly, we could say `rand="=0.3.0"`
|
||||||
(note the two equal signs).
|
(note the two equal signs).
|
||||||
And if we wanted to use the latest version we could use `*`.
|
And if we wanted to use the latest version we could use `rand="*"`.
|
||||||
We could also use a range of versions.
|
We could also use a range of versions.
|
||||||
[Cargo’s documentation][cargodoc] contains more details.
|
[Cargo’s documentation][cargodoc] contains more details.
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,8 @@ asm!("xor %eax, %eax"
|
||||||
: "eax"
|
: "eax"
|
||||||
);
|
);
|
||||||
# } }
|
# } }
|
||||||
|
# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
|
||||||
|
# fn main() {}
|
||||||
```
|
```
|
||||||
|
|
||||||
Whitespace also doesn't matter:
|
Whitespace also doesn't matter:
|
||||||
|
@ -70,6 +72,8 @@ Whitespace also doesn't matter:
|
||||||
# fn main() { unsafe {
|
# fn main() { unsafe {
|
||||||
asm!("xor %eax, %eax" ::: "eax");
|
asm!("xor %eax, %eax" ::: "eax");
|
||||||
# } }
|
# } }
|
||||||
|
# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
|
||||||
|
# fn main() {}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Operands
|
## Operands
|
||||||
|
@ -129,6 +133,8 @@ stay valid.
|
||||||
// Put the value 0x200 in eax
|
// Put the value 0x200 in eax
|
||||||
asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "eax");
|
asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "eax");
|
||||||
# } }
|
# } }
|
||||||
|
# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
|
||||||
|
# fn main() {}
|
||||||
```
|
```
|
||||||
|
|
||||||
Input and output registers need not be listed since that information
|
Input and output registers need not be listed since that information
|
||||||
|
@ -164,6 +170,8 @@ unsafe {
|
||||||
}
|
}
|
||||||
println!("eax is currently {}", result);
|
println!("eax is currently {}", result);
|
||||||
# }
|
# }
|
||||||
|
# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
|
||||||
|
# fn main() {}
|
||||||
```
|
```
|
||||||
|
|
||||||
## More Information
|
## More Information
|
||||||
|
|
|
@ -15,7 +15,7 @@ For example, `Box` pointers require two lang items, one for allocation
|
||||||
and one for deallocation. A freestanding program that uses the `Box`
|
and one for deallocation. A freestanding program that uses the `Box`
|
||||||
sugar for dynamic allocations via `malloc` and `free`:
|
sugar for dynamic allocations via `malloc` and `free`:
|
||||||
|
|
||||||
```rust
|
```rust,ignore
|
||||||
#![feature(lang_items, box_syntax, start, libc)]
|
#![feature(lang_items, box_syntax, start, libc)]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
|
|
|
@ -105,19 +105,19 @@ When you need to keep track of how many times you already looped, you can use th
|
||||||
#### On ranges:
|
#### On ranges:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
for (i, j) in (5..10).enumerate() {
|
for (index, value) in (5..10).enumerate() {
|
||||||
println!("i = {} and j = {}", i, j);
|
println!("index = {} and value = {}", index, value);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Outputs:
|
Outputs:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
i = 0 and j = 5
|
index = 0 and value = 5
|
||||||
i = 1 and j = 6
|
index = 1 and value = 6
|
||||||
i = 2 and j = 7
|
index = 2 and value = 7
|
||||||
i = 3 and j = 8
|
index = 3 and value = 8
|
||||||
i = 4 and j = 9
|
index = 4 and value = 9
|
||||||
```
|
```
|
||||||
|
|
||||||
Don't forget to add the parentheses around the range.
|
Don't forget to add the parentheses around the range.
|
||||||
|
|
|
@ -94,7 +94,7 @@
|
||||||
* `|` (`|…| expr`): closures. See [Closures].
|
* `|` (`|…| expr`): closures. See [Closures].
|
||||||
* `|=` (`var |= expr`): bitwise or & assignment. Overloadable (`BitOrAssign`).
|
* `|=` (`var |= expr`): bitwise or & assignment. Overloadable (`BitOrAssign`).
|
||||||
* `||` (`expr || expr`): logical or.
|
* `||` (`expr || expr`): logical or.
|
||||||
* `_`: "ignored" pattern binding. See [Patterns (Ignoring bindings)].
|
* `_`: "ignored" pattern binding (see [Patterns (Ignoring bindings)]). Also used to make integer-literals readable (see [Reference (Integer literals)]).
|
||||||
|
|
||||||
## Other Syntax
|
## Other Syntax
|
||||||
|
|
||||||
|
@ -231,6 +231,7 @@
|
||||||
[Primitive Types (Tuples)]: primitive-types.html#tuples
|
[Primitive Types (Tuples)]: primitive-types.html#tuples
|
||||||
[Raw Pointers]: raw-pointers.html
|
[Raw Pointers]: raw-pointers.html
|
||||||
[Reference (Byte String Literals)]: ../reference.html#byte-string-literals
|
[Reference (Byte String Literals)]: ../reference.html#byte-string-literals
|
||||||
|
[Reference (Integer literals)]: ../reference.html#integer-literals
|
||||||
[Reference (Raw Byte String Literals)]: ../reference.html#raw-byte-string-literals
|
[Reference (Raw Byte String Literals)]: ../reference.html#raw-byte-string-literals
|
||||||
[Reference (Raw String Literals)]: ../reference.html#raw-string-literals
|
[Reference (Raw String Literals)]: ../reference.html#raw-string-literals
|
||||||
[References and Borrowing]: references-and-borrowing.html
|
[References and Borrowing]: references-and-borrowing.html
|
||||||
|
|
|
@ -26,6 +26,8 @@ The stack is very fast, and is where memory is allocated in Rust by default.
|
||||||
But the allocation is local to a function call, and is limited in size. The
|
But the allocation is local to a function call, and is limited in size. The
|
||||||
heap, on the other hand, is slower, and is explicitly allocated by your
|
heap, on the other hand, is slower, and is explicitly allocated by your
|
||||||
program. But it’s effectively unlimited in size, and is globally accessible.
|
program. But it’s effectively unlimited in size, and is globally accessible.
|
||||||
|
Note this meaning of heap, which allocates arbitrary-sized blocks of memory in arbitrary
|
||||||
|
order, is quite different from the heap data structure.
|
||||||
|
|
||||||
# The Stack
|
# The Stack
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,6 @@ dispatch with trait objects by casting:
|
||||||
# trait Foo { fn method(&self) -> String; }
|
# trait Foo { fn method(&self) -> String; }
|
||||||
# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
|
# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
|
||||||
# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }
|
# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }
|
||||||
|
|
||||||
fn do_something(x: &Foo) {
|
fn do_something(x: &Foo) {
|
||||||
x.method();
|
x.method();
|
||||||
}
|
}
|
||||||
|
@ -140,7 +139,6 @@ or by coercing:
|
||||||
# trait Foo { fn method(&self) -> String; }
|
# trait Foo { fn method(&self) -> String; }
|
||||||
# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
|
# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
|
||||||
# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }
|
# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }
|
||||||
|
|
||||||
fn do_something(x: &Foo) {
|
fn do_something(x: &Foo) {
|
||||||
x.method();
|
x.method();
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ struct Vec<T> {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Unlike the previous example it *appears* that everything is exactly as we
|
Unlike the previous example, it *appears* that everything is exactly as we
|
||||||
want. Every generic argument to Vec shows up in at least one field.
|
want. Every generic argument to Vec shows up in at least one field.
|
||||||
Good to go!
|
Good to go!
|
||||||
|
|
||||||
|
@ -84,4 +84,3 @@ standard library made a utility for itself called `Unique<T>` which:
|
||||||
* includes a `PhantomData<T>`
|
* includes a `PhantomData<T>`
|
||||||
* auto-derives Send/Sync as if T was contained
|
* auto-derives Send/Sync as if T was contained
|
||||||
* marks the pointer as NonZero for the null-pointer optimization
|
* marks the pointer as NonZero for the null-pointer optimization
|
||||||
|
|
||||||
|
|
|
@ -1653,14 +1653,43 @@ the Rust ABI and the foreign ABI.
|
||||||
A number of [attributes](#ffi-attributes) control the behavior of external blocks.
|
A number of [attributes](#ffi-attributes) control the behavior of external blocks.
|
||||||
|
|
||||||
By default external blocks assume that the library they are calling uses the
|
By default external blocks assume that the library they are calling uses the
|
||||||
standard C "cdecl" ABI. Other ABIs may be specified using an `abi` string, as
|
standard C ABI on the specific platform. Other ABIs may be specified using an
|
||||||
shown here:
|
`abi` string, as shown here:
|
||||||
|
|
||||||
```ignore
|
```ignore
|
||||||
// Interface to the Windows API
|
// Interface to the Windows API
|
||||||
extern "stdcall" { }
|
extern "stdcall" { }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
There are three ABI strings which are cross-platform, and which all compilers
|
||||||
|
are guaranteed to support:
|
||||||
|
|
||||||
|
* `extern "Rust"` -- The default ABI when you write a normal `fn foo()` in any
|
||||||
|
Rust code.
|
||||||
|
* `extern "C"` -- This is the same as `extern fn foo()`; whatever the default
|
||||||
|
your C compiler supports.
|
||||||
|
* `extern "system"` -- Usually the same as `extern "C"`, except on Win32, in
|
||||||
|
which case it's `"stdcall"`, or what you should use to link to the Windows API
|
||||||
|
itself
|
||||||
|
|
||||||
|
There are also some platform-specific ABI strings:
|
||||||
|
|
||||||
|
* `extern "cdecl"` -- The default for x86\_32 C code.
|
||||||
|
* `extern "stdcall"` -- The default for the Win32 API on x86\_32.
|
||||||
|
* `extern "win64"` -- The default for C code on x86\_64 Windows.
|
||||||
|
* `extern "aapcs"` -- The default for ARM.
|
||||||
|
* `extern "fastcall"` -- The `fastcall` ABI -- corresponds to MSVC's
|
||||||
|
`__fastcall` and GCC and clang's `__attribute__((fastcall))`
|
||||||
|
* `extern "vectorcall"` -- The `vectorcall` ABI -- corresponds to MSVC's
|
||||||
|
`__vectorcall` and clang's `__attribute__((vectorcall))`
|
||||||
|
|
||||||
|
Finally, there are some rustc-specific ABI strings:
|
||||||
|
|
||||||
|
* `extern "rust-intrinsic"` -- The ABI of rustc intrinsics.
|
||||||
|
* `extern "rust-call"` -- The ABI of the Fn::call trait functions.
|
||||||
|
* `extern "platform-intrinsic"` -- Specific platform intrinsics -- like, for
|
||||||
|
example, `sqrt` -- have this ABI. You should never have to deal with it.
|
||||||
|
|
||||||
The `link` attribute allows the name of the library to be specified. When
|
The `link` attribute allows the name of the library to be specified. When
|
||||||
specified the compiler will attempt to link against the native library of the
|
specified the compiler will attempt to link against the native library of the
|
||||||
specified name.
|
specified name.
|
||||||
|
@ -3020,7 +3049,8 @@ as
|
||||||
== != < > <= >=
|
== != < > <= >=
|
||||||
&&
|
&&
|
||||||
||
|
||
|
||||||
= ..
|
.. ...
|
||||||
|
=
|
||||||
```
|
```
|
||||||
|
|
||||||
Operators at the same precedence level are evaluated left-to-right. [Unary
|
Operators at the same precedence level are evaluated left-to-right. [Unary
|
||||||
|
|
|
@ -23,11 +23,5 @@ RUN apt-get update && apt-get -y install \
|
||||||
libedit-dev zlib1g-dev \
|
libedit-dev zlib1g-dev \
|
||||||
llvm-3.7-tools cmake
|
llvm-3.7-tools cmake
|
||||||
|
|
||||||
# When we compile compiler-rt we pass it the llvm-config we just installed on
|
|
||||||
# the system, but unfortunately it doesn't infer correctly where
|
|
||||||
# LLVMConfig.cmake is so we need to coerce it a bit...
|
|
||||||
RUN mkdir -p /usr/lib/llvm-3.7/build/share/llvm
|
|
||||||
RUN ln -s /usr/share/llvm-3.7/cmake /usr/lib/llvm-3.7/build/share/llvm/cmake
|
|
||||||
|
|
||||||
RUN mkdir /build
|
RUN mkdir /build
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
|
|
154
src/etc/char_private.py
Normal file
154
src/etc/char_private.py
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
#
|
||||||
|
# Copyright 2011-2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
# file at the top-level directory of this distribution and at
|
||||||
|
# http://rust-lang.org/COPYRIGHT.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
# option. This file may not be copied, modified, or distributed
|
||||||
|
# except according to those terms.
|
||||||
|
|
||||||
|
# This script uses the following Unicode tables:
|
||||||
|
# - Categories.txt
|
||||||
|
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
def to_ranges(iter):
|
||||||
|
current = None
|
||||||
|
for i in iter:
|
||||||
|
if current is None or i != current[1] or i in (0x10000, 0x20000):
|
||||||
|
if current is not None:
|
||||||
|
yield tuple(current)
|
||||||
|
current = [i, i + 1]
|
||||||
|
else:
|
||||||
|
current[1] += 1
|
||||||
|
if current is not None:
|
||||||
|
yield tuple(current)
|
||||||
|
|
||||||
|
def get_escaped(dictionary):
|
||||||
|
for i in range(0x110000):
|
||||||
|
if dictionary.get(i, "Cn") in "Cc Cf Cs Co Cn Zl Zp Zs".split() and i != ord(' '):
|
||||||
|
yield i
|
||||||
|
|
||||||
|
def get_file(f):
|
||||||
|
try:
|
||||||
|
return open(os.path.basename(f))
|
||||||
|
except FileNotFoundError:
|
||||||
|
subprocess.run(["curl", "-O", f], check=True)
|
||||||
|
return open(os.path.basename(f))
|
||||||
|
|
||||||
|
def main():
|
||||||
|
file = get_file("http://www.unicode.org/notes/tn36/Categories.txt")
|
||||||
|
|
||||||
|
dictionary = {int(line.split()[0], 16): line.split()[1] for line in file}
|
||||||
|
|
||||||
|
CUTOFF=0x10000
|
||||||
|
singletons0 = []
|
||||||
|
singletons1 = []
|
||||||
|
normal0 = []
|
||||||
|
normal1 = []
|
||||||
|
extra = []
|
||||||
|
|
||||||
|
for a, b in to_ranges(get_escaped(dictionary)):
|
||||||
|
if a > 2 * CUTOFF:
|
||||||
|
extra.append((a, b - a))
|
||||||
|
elif a == b - 1:
|
||||||
|
if a & CUTOFF:
|
||||||
|
singletons1.append(a & ~CUTOFF)
|
||||||
|
else:
|
||||||
|
singletons0.append(a)
|
||||||
|
elif a == b - 2:
|
||||||
|
if a & CUTOFF:
|
||||||
|
singletons1.append(a & ~CUTOFF)
|
||||||
|
singletons1.append((a + 1) & ~CUTOFF)
|
||||||
|
else:
|
||||||
|
singletons0.append(a)
|
||||||
|
singletons0.append(a + 1)
|
||||||
|
else:
|
||||||
|
if a >= 2 * CUTOFF:
|
||||||
|
extra.append((a, b - a))
|
||||||
|
elif a & CUTOFF:
|
||||||
|
normal1.append((a & ~CUTOFF, b - a))
|
||||||
|
else:
|
||||||
|
normal0.append((a, b - a))
|
||||||
|
|
||||||
|
print("""\
|
||||||
|
// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// NOTE: The following code was generated by "src/etc/char_private.py",
|
||||||
|
// do not edit directly!
|
||||||
|
|
||||||
|
use slice::SliceExt;
|
||||||
|
|
||||||
|
fn check(x: u16, singletons: &[u16], normal: &[u16]) -> bool {
|
||||||
|
for &s in singletons {
|
||||||
|
if x == s {
|
||||||
|
return false;
|
||||||
|
} else if x < s {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for w in normal.chunks(2) {
|
||||||
|
let start = w[0];
|
||||||
|
let len = w[1];
|
||||||
|
let difference = (x as i32) - (start as i32);
|
||||||
|
if 0 <= difference {
|
||||||
|
if difference < len as i32 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_printable(x: char) -> bool {
|
||||||
|
let x = x as u32;
|
||||||
|
let lower = x as u16;
|
||||||
|
if x < 0x10000 {
|
||||||
|
check(lower, SINGLETONS0, NORMAL0)
|
||||||
|
} else if x < 0x20000 {
|
||||||
|
check(lower, SINGLETONS1, NORMAL1)
|
||||||
|
} else {\
|
||||||
|
""")
|
||||||
|
for a, b in extra:
|
||||||
|
print(" if 0x{:x} <= x && x < 0x{:x} {{".format(a, a + b))
|
||||||
|
print(" return false;")
|
||||||
|
print(" }")
|
||||||
|
print("""\
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}\
|
||||||
|
""")
|
||||||
|
print()
|
||||||
|
print("const SINGLETONS0: &'static [u16] = &[")
|
||||||
|
for s in singletons0:
|
||||||
|
print(" 0x{:x},".format(s))
|
||||||
|
print("];")
|
||||||
|
print("const SINGLETONS1: &'static [u16] = &[")
|
||||||
|
for s in singletons1:
|
||||||
|
print(" 0x{:x},".format(s))
|
||||||
|
print("];")
|
||||||
|
print("const NORMAL0: &'static [u16] = &[")
|
||||||
|
for a, b in normal0:
|
||||||
|
print(" 0x{:x}, 0x{:x},".format(a, b))
|
||||||
|
print("];")
|
||||||
|
print("const NORMAL1: &'static [u16] = &[")
|
||||||
|
for a, b in normal1:
|
||||||
|
print(" 0x{:x}, 0x{:x},".format(a, b))
|
||||||
|
print("];")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
|
@ -58,6 +58,7 @@ case "$TARG_DIR" in
|
||||||
|
|
||||||
cp ${PREFIX}/bin/rustc${BIN_SUF} ${TARG_DIR}/stage0/bin/
|
cp ${PREFIX}/bin/rustc${BIN_SUF} ${TARG_DIR}/stage0/bin/
|
||||||
cp ${PREFIX}/${LIB_DIR}/${RUSTLIBDIR}/${TARG_DIR}/${LIB_DIR}/* ${TARG_DIR}/stage0/${LIB_DIR}/
|
cp ${PREFIX}/${LIB_DIR}/${RUSTLIBDIR}/${TARG_DIR}/${LIB_DIR}/* ${TARG_DIR}/stage0/${LIB_DIR}/
|
||||||
|
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}arena*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
|
||||||
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}extra*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
|
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}extra*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
|
||||||
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}rust*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
|
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}rust*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
|
||||||
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}std*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
|
cp ${PREFIX}/${LIB_DIR}/${LIB_PREFIX}std*${LIB_SUF} ${TARG_DIR}/stage0/${LIB_DIR}/
|
||||||
|
|
|
@ -77,6 +77,13 @@ for lib in out.strip().replace("\n", ' ').split(' '):
|
||||||
lib = lib.strip()[2:]
|
lib = lib.strip()[2:]
|
||||||
elif lib[0] == '-':
|
elif lib[0] == '-':
|
||||||
lib = lib.strip()[1:]
|
lib = lib.strip()[1:]
|
||||||
|
# If this actually points at a literal file then we're on MSVC which now
|
||||||
|
# prints full paths, so get just the name of the library and strip off the
|
||||||
|
# trailing ".lib"
|
||||||
|
elif os.path.exists(lib):
|
||||||
|
lib = os.path.basename(lib)[:-4]
|
||||||
|
elif lib[-4:] == '.lib':
|
||||||
|
lib = lib[:-4]
|
||||||
f.write("#[link(name = \"" + lib + "\"")
|
f.write("#[link(name = \"" + lib + "\"")
|
||||||
if not llvm_shared and 'LLVM' in lib:
|
if not llvm_shared and 'LLVM' in lib:
|
||||||
f.write(", kind = \"static\"")
|
f.write(", kind = \"static\"")
|
||||||
|
|
|
@ -21,6 +21,10 @@
|
||||||
//!
|
//!
|
||||||
//! Sharing some immutable data between threads:
|
//! Sharing some immutable data between threads:
|
||||||
//!
|
//!
|
||||||
|
// Note that we **do not** run these tests here. The windows builders get super
|
||||||
|
// unhappy of a thread outlives the main thread and then exits at the same time
|
||||||
|
// (something deadlocks) so we just avoid this entirely by not running these
|
||||||
|
// tests.
|
||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use std::sync::Arc;
|
//! use std::sync::Arc;
|
||||||
//! use std::thread;
|
//! use std::thread;
|
||||||
|
@ -97,7 +101,8 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
|
||||||
/// by putting it inside `Mutex` and then share `Mutex` immutably
|
/// by putting it inside `Mutex` and then share `Mutex` immutably
|
||||||
/// with `Arc<T>` as shown below.
|
/// with `Arc<T>` as shown below.
|
||||||
///
|
///
|
||||||
/// ```
|
// See comment at the top of this file for why the test is no_run
|
||||||
|
/// ```no_run
|
||||||
/// use std::sync::{Arc, Mutex};
|
/// use std::sync::{Arc, Mutex};
|
||||||
/// use std::thread;
|
/// use std::thread;
|
||||||
///
|
///
|
||||||
|
|
|
@ -16,7 +16,7 @@ libc = { path = "../rustc/libc_shim" }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
build_helper = { path = "../build_helper" }
|
build_helper = { path = "../build_helper" }
|
||||||
gcc = "0.3.17"
|
gcc = "0.3.27"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
debug = []
|
debug = []
|
||||||
|
|
|
@ -73,7 +73,16 @@ fn main() {
|
||||||
.replace("\\", "/"))
|
.replace("\\", "/"))
|
||||||
.current_dir(&build_dir)
|
.current_dir(&build_dir)
|
||||||
.env("CC", compiler.path())
|
.env("CC", compiler.path())
|
||||||
.env("EXTRA_CFLAGS", cflags)
|
.env("EXTRA_CFLAGS", cflags.clone())
|
||||||
|
// jemalloc generates Makefile deps using GCC's "-MM" flag. This means
|
||||||
|
// that GCC will run the preprocessor, and only the preprocessor, over
|
||||||
|
// jemalloc's source files. If we don't specify CPPFLAGS, then at least
|
||||||
|
// on ARM that step fails with a "Missing implementation for 32-bit
|
||||||
|
// atomic operations" error. This is because no "-march" flag will be
|
||||||
|
// passed to GCC, and then GCC won't define the
|
||||||
|
// "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4" macro that jemalloc needs to
|
||||||
|
// select an atomic operation implementation.
|
||||||
|
.env("CPPFLAGS", cflags.clone())
|
||||||
.env("AR", &ar)
|
.env("AR", &ar)
|
||||||
.env("RANLIB", format!("{} s", ar.display()));
|
.env("RANLIB", format!("{} s", ar.display()));
|
||||||
|
|
||||||
|
|
|
@ -313,6 +313,10 @@ pub struct RangeMut<'a, K: 'a, V: 'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A view into a single entry in a map, which may either be vacant or occupied.
|
/// A view into a single entry in a map, which may either be vacant or occupied.
|
||||||
|
/// This enum is constructed from the [`entry`] method on [`BTreeMap`].
|
||||||
|
///
|
||||||
|
/// [`BTreeMap`]: struct.BTreeMap.html
|
||||||
|
/// [`entry`]: struct.BTreeMap.html#method.entry
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub enum Entry<'a, K: 'a, V: 'a> {
|
pub enum Entry<'a, K: 'a, V: 'a> {
|
||||||
/// A vacant Entry
|
/// A vacant Entry
|
||||||
|
@ -326,7 +330,23 @@ pub enum Entry<'a, K: 'a, V: 'a> {
|
||||||
OccupiedEntry<'a, K, V>),
|
OccupiedEntry<'a, K, V>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A vacant Entry.
|
#[stable(feature= "debug_btree_map", since = "1.12.0")]
|
||||||
|
impl<'a, K: 'a + Debug + Ord, V: 'a + Debug> Debug for Entry<'a, K, V> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
Vacant(ref v) => f.debug_tuple("Entry")
|
||||||
|
.field(v)
|
||||||
|
.finish(),
|
||||||
|
Occupied(ref o) => f.debug_tuple("Entry")
|
||||||
|
.field(o)
|
||||||
|
.finish(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A vacant Entry. It is part of the [`Entry`] enum.
|
||||||
|
///
|
||||||
|
/// [`Entry`]: enum.Entry.html
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct VacantEntry<'a, K: 'a, V: 'a> {
|
pub struct VacantEntry<'a, K: 'a, V: 'a> {
|
||||||
key: K,
|
key: K,
|
||||||
|
@ -337,7 +357,18 @@ pub struct VacantEntry<'a, K: 'a, V: 'a> {
|
||||||
_marker: PhantomData<&'a mut (K, V)>,
|
_marker: PhantomData<&'a mut (K, V)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An occupied Entry.
|
#[stable(feature= "debug_btree_map", since = "1.12.0")]
|
||||||
|
impl<'a, K: 'a + Debug + Ord, V: 'a> Debug for VacantEntry<'a, K, V> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_tuple("VacantEntry")
|
||||||
|
.field(self.key())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An occupied Entry. It is part of the [`Entry`] enum.
|
||||||
|
///
|
||||||
|
/// [`Entry`]: enum.Entry.html
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
|
pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
|
||||||
handle: Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::KV>,
|
handle: Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::KV>,
|
||||||
|
@ -348,6 +379,16 @@ pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
|
||||||
_marker: PhantomData<&'a mut (K, V)>,
|
_marker: PhantomData<&'a mut (K, V)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature= "debug_btree_map", since = "1.12.0")]
|
||||||
|
impl<'a, K: 'a + Debug + Ord, V: 'a + Debug> Debug for OccupiedEntry<'a, K, V> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.debug_struct("OccupiedEntry")
|
||||||
|
.field("key", self.key())
|
||||||
|
.field("value", self.get())
|
||||||
|
.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// An iterator for merging two sorted sequences into one
|
// An iterator for merging two sorted sequences into one
|
||||||
struct MergeIter<K, V, I: Iterator<Item = (K, V)>> {
|
struct MergeIter<K, V, I: Iterator<Item = (K, V)>> {
|
||||||
left: Peekable<I>,
|
left: Peekable<I>,
|
||||||
|
@ -1857,6 +1898,17 @@ impl<K, V> BTreeMap<K, V> {
|
||||||
impl<'a, K: Ord, V> Entry<'a, K, V> {
|
impl<'a, K: Ord, V> Entry<'a, K, V> {
|
||||||
/// Ensures a value is in the entry by inserting the default if empty, and returns
|
/// Ensures a value is in the entry by inserting the default if empty, and returns
|
||||||
/// a mutable reference to the value in the entry.
|
/// a mutable reference to the value in the entry.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::collections::BTreeMap;
|
||||||
|
///
|
||||||
|
/// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
|
||||||
|
/// map.entry("poneyland").or_insert(12);
|
||||||
|
///
|
||||||
|
/// assert_eq!(map["poneyland"], 12);
|
||||||
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn or_insert(self, default: V) -> &'a mut V {
|
pub fn or_insert(self, default: V) -> &'a mut V {
|
||||||
match self {
|
match self {
|
||||||
|
@ -1867,6 +1919,19 @@ impl<'a, K: Ord, V> Entry<'a, K, V> {
|
||||||
|
|
||||||
/// Ensures a value is in the entry by inserting the result of the default function if empty,
|
/// Ensures a value is in the entry by inserting the result of the default function if empty,
|
||||||
/// and returns a mutable reference to the value in the entry.
|
/// and returns a mutable reference to the value in the entry.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::collections::BTreeMap;
|
||||||
|
///
|
||||||
|
/// let mut map: BTreeMap<&str, String> = BTreeMap::new();
|
||||||
|
/// let s = "hoho".to_owned();
|
||||||
|
///
|
||||||
|
/// map.entry("poneyland").or_insert_with(|| s);
|
||||||
|
///
|
||||||
|
/// assert_eq!(map["poneyland"], "hoho".to_owned());
|
||||||
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
|
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
|
||||||
match self {
|
match self {
|
||||||
|
@ -1876,6 +1941,15 @@ impl<'a, K: Ord, V> Entry<'a, K, V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a reference to this entry's key.
|
/// Returns a reference to this entry's key.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::collections::BTreeMap;
|
||||||
|
///
|
||||||
|
/// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
|
||||||
|
/// assert_eq!(map.entry("poneyland").key(), &"poneyland");
|
||||||
|
/// ```
|
||||||
#[stable(feature = "map_entry_keys", since = "1.10.0")]
|
#[stable(feature = "map_entry_keys", since = "1.10.0")]
|
||||||
pub fn key(&self) -> &K {
|
pub fn key(&self) -> &K {
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -1888,12 +1962,36 @@ impl<'a, K: Ord, V> Entry<'a, K, V> {
|
||||||
impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
|
impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
|
||||||
/// Gets a reference to the key that would be used when inserting a value
|
/// Gets a reference to the key that would be used when inserting a value
|
||||||
/// through the VacantEntry.
|
/// through the VacantEntry.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::collections::BTreeMap;
|
||||||
|
///
|
||||||
|
/// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
|
||||||
|
/// assert_eq!(map.entry("poneyland").key(), &"poneyland");
|
||||||
|
/// ```
|
||||||
#[stable(feature = "map_entry_keys", since = "1.10.0")]
|
#[stable(feature = "map_entry_keys", since = "1.10.0")]
|
||||||
pub fn key(&self) -> &K {
|
pub fn key(&self) -> &K {
|
||||||
&self.key
|
&self.key
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Take ownership of the key.
|
/// Take ownership of the key.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(map_entry_recover_keys)]
|
||||||
|
///
|
||||||
|
/// use std::collections::BTreeMap;
|
||||||
|
/// use std::collections::btree_map::Entry;
|
||||||
|
///
|
||||||
|
/// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
|
||||||
|
///
|
||||||
|
/// if let Entry::Vacant(v) = map.entry("poneyland") {
|
||||||
|
/// v.into_key();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
#[unstable(feature = "map_entry_recover_keys", issue = "34285")]
|
#[unstable(feature = "map_entry_recover_keys", issue = "34285")]
|
||||||
pub fn into_key(self) -> K {
|
pub fn into_key(self) -> K {
|
||||||
self.key
|
self.key
|
||||||
|
@ -1901,6 +1999,21 @@ impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
|
||||||
|
|
||||||
/// Sets the value of the entry with the VacantEntry's key,
|
/// Sets the value of the entry with the VacantEntry's key,
|
||||||
/// and returns a mutable reference to it.
|
/// and returns a mutable reference to it.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::collections::BTreeMap;
|
||||||
|
///
|
||||||
|
/// let mut count: BTreeMap<&str, usize> = BTreeMap::new();
|
||||||
|
///
|
||||||
|
/// // count the number of occurrences of letters in the vec
|
||||||
|
/// for x in vec!["a","b","a","c","a","b"] {
|
||||||
|
/// *count.entry(x).or_insert(0) += 1;
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// assert_eq!(count["a"], 3);
|
||||||
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn insert(self, value: V) -> &'a mut V {
|
pub fn insert(self, value: V) -> &'a mut V {
|
||||||
*self.length += 1;
|
*self.length += 1;
|
||||||
|
@ -1946,30 +2059,106 @@ impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
|
||||||
|
|
||||||
impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
|
impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
|
||||||
/// Gets a reference to the key in the entry.
|
/// Gets a reference to the key in the entry.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::collections::BTreeMap;
|
||||||
|
///
|
||||||
|
/// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
|
||||||
|
/// map.entry("poneyland").or_insert(12);
|
||||||
|
/// assert_eq!(map.entry("poneyland").key(), &"poneyland");
|
||||||
|
/// ```
|
||||||
#[stable(feature = "map_entry_keys", since = "1.10.0")]
|
#[stable(feature = "map_entry_keys", since = "1.10.0")]
|
||||||
pub fn key(&self) -> &K {
|
pub fn key(&self) -> &K {
|
||||||
self.handle.reborrow().into_kv().0
|
self.handle.reborrow().into_kv().0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Take ownership of the key and value from the map.
|
/// Take ownership of the key and value from the map.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(map_entry_recover_keys)]
|
||||||
|
///
|
||||||
|
/// use std::collections::BTreeMap;
|
||||||
|
/// use std::collections::btree_map::Entry;
|
||||||
|
///
|
||||||
|
/// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
|
||||||
|
/// map.entry("poneyland").or_insert(12);
|
||||||
|
///
|
||||||
|
/// if let Entry::Occupied(o) = map.entry("poneyland") {
|
||||||
|
/// // We delete the entry from the map.
|
||||||
|
/// o.remove_pair();
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // If now try to get the value, it will panic:
|
||||||
|
/// // println!("{}", map["poneyland"]);
|
||||||
|
/// ```
|
||||||
#[unstable(feature = "map_entry_recover_keys", issue = "34285")]
|
#[unstable(feature = "map_entry_recover_keys", issue = "34285")]
|
||||||
pub fn remove_pair(self) -> (K, V) {
|
pub fn remove_pair(self) -> (K, V) {
|
||||||
self.remove_kv()
|
self.remove_kv()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a reference to the value in the entry.
|
/// Gets a reference to the value in the entry.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::collections::BTreeMap;
|
||||||
|
/// use std::collections::btree_map::Entry;
|
||||||
|
///
|
||||||
|
/// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
|
||||||
|
/// map.entry("poneyland").or_insert(12);
|
||||||
|
///
|
||||||
|
/// if let Entry::Occupied(o) = map.entry("poneyland") {
|
||||||
|
/// assert_eq!(o.get(), &12);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn get(&self) -> &V {
|
pub fn get(&self) -> &V {
|
||||||
self.handle.reborrow().into_kv().1
|
self.handle.reborrow().into_kv().1
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a mutable reference to the value in the entry.
|
/// Gets a mutable reference to the value in the entry.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::collections::BTreeMap;
|
||||||
|
/// use std::collections::btree_map::Entry;
|
||||||
|
///
|
||||||
|
/// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
|
||||||
|
/// map.entry("poneyland").or_insert(12);
|
||||||
|
///
|
||||||
|
/// assert_eq!(map["poneyland"], 12);
|
||||||
|
/// if let Entry::Occupied(mut o) = map.entry("poneyland") {
|
||||||
|
/// *o.get_mut() += 10;
|
||||||
|
/// }
|
||||||
|
/// assert_eq!(map["poneyland"], 22);
|
||||||
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn get_mut(&mut self) -> &mut V {
|
pub fn get_mut(&mut self) -> &mut V {
|
||||||
self.handle.kv_mut().1
|
self.handle.kv_mut().1
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the entry into a mutable reference to its value.
|
/// Converts the entry into a mutable reference to its value.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::collections::BTreeMap;
|
||||||
|
/// use std::collections::btree_map::Entry;
|
||||||
|
///
|
||||||
|
/// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
|
||||||
|
/// map.entry("poneyland").or_insert(12);
|
||||||
|
///
|
||||||
|
/// assert_eq!(map["poneyland"], 12);
|
||||||
|
/// if let Entry::Occupied(o) = map.entry("poneyland") {
|
||||||
|
/// *o.into_mut() += 10;
|
||||||
|
/// }
|
||||||
|
/// assert_eq!(map["poneyland"], 22);
|
||||||
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn into_mut(self) -> &'a mut V {
|
pub fn into_mut(self) -> &'a mut V {
|
||||||
self.handle.into_kv_mut().1
|
self.handle.into_kv_mut().1
|
||||||
|
@ -1977,12 +2166,43 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
|
||||||
|
|
||||||
/// Sets the value of the entry with the OccupiedEntry's key,
|
/// Sets the value of the entry with the OccupiedEntry's key,
|
||||||
/// and returns the entry's old value.
|
/// and returns the entry's old value.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::collections::BTreeMap;
|
||||||
|
/// use std::collections::btree_map::Entry;
|
||||||
|
///
|
||||||
|
/// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
|
||||||
|
/// map.entry("poneyland").or_insert(12);
|
||||||
|
///
|
||||||
|
/// if let Entry::Occupied(mut o) = map.entry("poneyland") {
|
||||||
|
/// assert_eq!(o.insert(15), 12);
|
||||||
|
/// }
|
||||||
|
/// assert_eq!(map["poneyland"], 15);
|
||||||
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn insert(&mut self, value: V) -> V {
|
pub fn insert(&mut self, value: V) -> V {
|
||||||
mem::replace(self.get_mut(), value)
|
mem::replace(self.get_mut(), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Takes the value of the entry out of the map, and returns it.
|
/// Takes the value of the entry out of the map, and returns it.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::collections::BTreeMap;
|
||||||
|
/// use std::collections::btree_map::Entry;
|
||||||
|
///
|
||||||
|
/// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
|
||||||
|
/// map.entry("poneyland").or_insert(12);
|
||||||
|
///
|
||||||
|
/// if let Entry::Occupied(o) = map.entry("poneyland") {
|
||||||
|
/// assert_eq!(o.remove(), 12);
|
||||||
|
/// }
|
||||||
|
/// // If we try to get "poneyland"'s value, it'll panic:
|
||||||
|
/// // println!("{}", map["poneyland"]);
|
||||||
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn remove(self) -> V {
|
pub fn remove(self) -> V {
|
||||||
self.remove_kv().1
|
self.remove_kv().1
|
||||||
|
|
|
@ -409,8 +409,8 @@
|
||||||
//! ## Precision
|
//! ## Precision
|
||||||
//!
|
//!
|
||||||
//! For non-numeric types, this can be considered a "maximum width". If the resulting string is
|
//! For non-numeric types, this can be considered a "maximum width". If the resulting string is
|
||||||
//! longer than this width, then it is truncated down to this many characters and only those are
|
//! longer than this width, then it is truncated down to this many characters and that truncated
|
||||||
//! emitted.
|
//! value is emitted with proper `fill`, `alignment` and `width` if those parameters are set.
|
||||||
//!
|
//!
|
||||||
//! For integral types, this is ignored.
|
//! For integral types, this is ignored.
|
||||||
//!
|
//!
|
||||||
|
@ -434,42 +434,37 @@
|
||||||
//! in this case, if one uses the format string `{<arg>:<spec>.*}`, then the `<arg>` part refers
|
//! in this case, if one uses the format string `{<arg>:<spec>.*}`, then the `<arg>` part refers
|
||||||
//! to the *value* to print, and the `precision` must come in the input preceding `<arg>`.
|
//! to the *value* to print, and the `precision` must come in the input preceding `<arg>`.
|
||||||
//!
|
//!
|
||||||
//! For example, these:
|
//! For example, the following calls all print the same thing `Hello x is 0.01000`:
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! // Hello {arg 0 (x)} is {arg 1 (0.01) with precision specified inline (5)}
|
//! // Hello {arg 0 ("x")} is {arg 1 (0.01) with precision specified inline (5)}
|
||||||
//! println!("Hello {0} is {1:.5}", "x", 0.01);
|
//! println!("Hello {0} is {1:.5}", "x", 0.01);
|
||||||
//!
|
//!
|
||||||
//! // Hello {arg 1 (x)} is {arg 2 (0.01) with precision specified in arg 0 (5)}
|
//! // Hello {arg 1 ("x")} is {arg 2 (0.01) with precision specified in arg 0 (5)}
|
||||||
//! println!("Hello {1} is {2:.0$}", 5, "x", 0.01);
|
//! println!("Hello {1} is {2:.0$}", 5, "x", 0.01);
|
||||||
//!
|
//!
|
||||||
//! // Hello {arg 0 (x)} is {arg 2 (0.01) with precision specified in arg 1 (5)}
|
//! // Hello {arg 0 ("x")} is {arg 2 (0.01) with precision specified in arg 1 (5)}
|
||||||
//! println!("Hello {0} is {2:.1$}", "x", 5, 0.01);
|
//! println!("Hello {0} is {2:.1$}", "x", 5, 0.01);
|
||||||
//!
|
//!
|
||||||
//! // Hello {next arg (x)} is {second of next two args (0.01) with precision
|
//! // Hello {next arg ("x")} is {second of next two args (0.01) with precision
|
||||||
//! // specified in first of next two args (5)}
|
//! // specified in first of next two args (5)}
|
||||||
//! println!("Hello {} is {:.*}", "x", 5, 0.01);
|
//! println!("Hello {} is {:.*}", "x", 5, 0.01);
|
||||||
//!
|
//!
|
||||||
//! // Hello {next arg (x)} is {arg 2 (0.01) with precision
|
//! // Hello {next arg ("x")} is {arg 2 (0.01) with precision
|
||||||
//! // specified in its predecessor (5)}
|
//! // specified in its predecessor (5)}
|
||||||
//! println!("Hello {} is {2:.*}", "x", 5, 0.01);
|
//! println!("Hello {} is {2:.*}", "x", 5, 0.01);
|
||||||
//!
|
//!
|
||||||
//! // Hello {next arg (x)} is {arg "number" (0.01) with precision specified
|
//! // Hello {next arg ("x")} is {arg "number" (0.01) with precision specified
|
||||||
//! // in arg "prec" (5)}
|
//! // in arg "prec" (5)}
|
||||||
//! println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01);
|
//! println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01);
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! All print the same thing:
|
|
||||||
//!
|
|
||||||
//! ```text
|
|
||||||
//! Hello x is 0.01000
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! While these:
|
//! While these:
|
||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! println!("{}, `{name:.*}` has 3 fractional digits", "Hello", 3, name=1234.56);
|
//! println!("{}, `{name:.*}` has 3 fractional digits", "Hello", 3, name=1234.56);
|
||||||
//! println!("{}, `{name:.*}` has 3 characters", "Hello", 3, name="1234.56");
|
//! println!("{}, `{name:.*}` has 3 characters", "Hello", 3, name="1234.56");
|
||||||
|
//! println!("{}, `{name:>8.*}` has 3 right-aligned characters", "Hello", 3, name="1234.56");
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! print two significantly different things:
|
//! print two significantly different things:
|
||||||
|
@ -477,6 +472,7 @@
|
||||||
//! ```text
|
//! ```text
|
||||||
//! Hello, `1234.560` has 3 fractional digits
|
//! Hello, `1234.560` has 3 fractional digits
|
||||||
//! Hello, `123` has 3 characters
|
//! Hello, `123` has 3 characters
|
||||||
|
//! Hello, ` 123` has 3 right-aligned characters
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! # Escaping
|
//! # Escaping
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#![feature(allow_internal_unstable)]
|
#![feature(allow_internal_unstable)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
|
#![cfg_attr(not(test), feature(char_escape_debug))]
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
#![feature(dropck_parametricity)]
|
#![feature(dropck_parametricity)]
|
||||||
#![feature(fmt_internals)]
|
#![feature(fmt_internals)]
|
||||||
|
@ -48,7 +49,6 @@
|
||||||
#![feature(specialization)]
|
#![feature(specialization)]
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
#![feature(step_by)]
|
#![feature(step_by)]
|
||||||
#![feature(unboxed_closures)]
|
|
||||||
#![feature(unicode)]
|
#![feature(unicode)]
|
||||||
#![feature(unique)]
|
#![feature(unique)]
|
||||||
#![feature(unsafe_no_drop_flag)]
|
#![feature(unsafe_no_drop_flag)]
|
||||||
|
|
|
@ -172,6 +172,14 @@ impl<T> Default for LinkedList<T> {
|
||||||
|
|
||||||
impl<T> LinkedList<T> {
|
impl<T> LinkedList<T> {
|
||||||
/// Creates an empty `LinkedList`.
|
/// Creates an empty `LinkedList`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::collections::LinkedList;
|
||||||
|
///
|
||||||
|
/// let list: LinkedList<u32> = LinkedList::new();
|
||||||
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
|
@ -195,19 +203,22 @@ impl<T> LinkedList<T> {
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::LinkedList;
|
/// use std::collections::LinkedList;
|
||||||
///
|
///
|
||||||
/// let mut a = LinkedList::new();
|
/// let mut list1 = LinkedList::new();
|
||||||
/// let mut b = LinkedList::new();
|
/// list1.push_back('a');
|
||||||
/// a.push_back(1);
|
|
||||||
/// a.push_back(2);
|
|
||||||
/// b.push_back(3);
|
|
||||||
/// b.push_back(4);
|
|
||||||
///
|
///
|
||||||
/// a.append(&mut b);
|
/// let mut list2 = LinkedList::new();
|
||||||
|
/// list2.push_back('b');
|
||||||
|
/// list2.push_back('c');
|
||||||
///
|
///
|
||||||
/// for e in &a {
|
/// list1.append(&mut list2);
|
||||||
/// println!("{}", e); // prints 1, then 2, then 3, then 4
|
///
|
||||||
/// }
|
/// let mut iter = list1.iter();
|
||||||
/// println!("{}", b.len()); // prints 0
|
/// assert_eq!(iter.next(), Some(&'a'));
|
||||||
|
/// assert_eq!(iter.next(), Some(&'b'));
|
||||||
|
/// assert_eq!(iter.next(), Some(&'c'));
|
||||||
|
/// assert!(iter.next().is_none());
|
||||||
|
///
|
||||||
|
/// assert!(list2.is_empty());
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn append(&mut self, other: &mut Self) {
|
pub fn append(&mut self, other: &mut Self) {
|
||||||
|
@ -226,6 +237,24 @@ impl<T> LinkedList<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provides a forward iterator.
|
/// Provides a forward iterator.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::collections::LinkedList;
|
||||||
|
///
|
||||||
|
/// let mut list: LinkedList<u32> = LinkedList::new();
|
||||||
|
///
|
||||||
|
/// list.push_back(0);
|
||||||
|
/// list.push_back(1);
|
||||||
|
/// list.push_back(2);
|
||||||
|
///
|
||||||
|
/// let mut iter = list.iter();
|
||||||
|
/// assert_eq!(iter.next(), Some(&0));
|
||||||
|
/// assert_eq!(iter.next(), Some(&1));
|
||||||
|
/// assert_eq!(iter.next(), Some(&2));
|
||||||
|
/// assert_eq!(iter.next(), None);
|
||||||
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn iter(&self) -> Iter<T> {
|
pub fn iter(&self) -> Iter<T> {
|
||||||
|
@ -238,6 +267,28 @@ impl<T> LinkedList<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provides a forward iterator with mutable references.
|
/// Provides a forward iterator with mutable references.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::collections::LinkedList;
|
||||||
|
///
|
||||||
|
/// let mut list: LinkedList<u32> = LinkedList::new();
|
||||||
|
///
|
||||||
|
/// list.push_back(0);
|
||||||
|
/// list.push_back(1);
|
||||||
|
/// list.push_back(2);
|
||||||
|
///
|
||||||
|
/// for element in list.iter_mut() {
|
||||||
|
/// *element += 10;
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// let mut iter = list.iter();
|
||||||
|
/// assert_eq!(iter.next(), Some(&10));
|
||||||
|
/// assert_eq!(iter.next(), Some(&11));
|
||||||
|
/// assert_eq!(iter.next(), Some(&12));
|
||||||
|
/// assert_eq!(iter.next(), None);
|
||||||
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn iter_mut(&mut self) -> IterMut<T> {
|
pub fn iter_mut(&mut self) -> IterMut<T> {
|
||||||
|
@ -289,7 +340,6 @@ impl<T> LinkedList<T> {
|
||||||
///
|
///
|
||||||
/// dl.push_back(3);
|
/// dl.push_back(3);
|
||||||
/// assert_eq!(dl.len(), 3);
|
/// assert_eq!(dl.len(), 3);
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -316,7 +366,6 @@ impl<T> LinkedList<T> {
|
||||||
/// dl.clear();
|
/// dl.clear();
|
||||||
/// assert_eq!(dl.len(), 0);
|
/// assert_eq!(dl.len(), 0);
|
||||||
/// assert_eq!(dl.front(), None);
|
/// assert_eq!(dl.front(), None);
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -326,6 +375,23 @@ impl<T> LinkedList<T> {
|
||||||
|
|
||||||
/// Returns `true` if the `LinkedList` contains an element equal to the
|
/// Returns `true` if the `LinkedList` contains an element equal to the
|
||||||
/// given value.
|
/// given value.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(linked_list_contains)]
|
||||||
|
///
|
||||||
|
/// use std::collections::LinkedList;
|
||||||
|
///
|
||||||
|
/// let mut list: LinkedList<u32> = LinkedList::new();
|
||||||
|
///
|
||||||
|
/// list.push_back(0);
|
||||||
|
/// list.push_back(1);
|
||||||
|
/// list.push_back(2);
|
||||||
|
///
|
||||||
|
/// assert_eq!(list.contains(&0), true);
|
||||||
|
/// assert_eq!(list.contains(&10), false);
|
||||||
|
/// ```
|
||||||
#[unstable(feature = "linked_list_contains", reason = "recently added",
|
#[unstable(feature = "linked_list_contains", reason = "recently added",
|
||||||
issue = "32630")]
|
issue = "32630")]
|
||||||
pub fn contains(&self, x: &T) -> bool
|
pub fn contains(&self, x: &T) -> bool
|
||||||
|
@ -347,7 +413,6 @@ impl<T> LinkedList<T> {
|
||||||
///
|
///
|
||||||
/// dl.push_front(1);
|
/// dl.push_front(1);
|
||||||
/// assert_eq!(dl.front(), Some(&1));
|
/// assert_eq!(dl.front(), Some(&1));
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -374,7 +439,6 @@ impl<T> LinkedList<T> {
|
||||||
/// Some(x) => *x = 5,
|
/// Some(x) => *x = 5,
|
||||||
/// }
|
/// }
|
||||||
/// assert_eq!(dl.front(), Some(&5));
|
/// assert_eq!(dl.front(), Some(&5));
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -395,7 +459,6 @@ impl<T> LinkedList<T> {
|
||||||
///
|
///
|
||||||
/// dl.push_back(1);
|
/// dl.push_back(1);
|
||||||
/// assert_eq!(dl.back(), Some(&1));
|
/// assert_eq!(dl.back(), Some(&1));
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -422,7 +485,6 @@ impl<T> LinkedList<T> {
|
||||||
/// Some(x) => *x = 5,
|
/// Some(x) => *x = 5,
|
||||||
/// }
|
/// }
|
||||||
/// assert_eq!(dl.back(), Some(&5));
|
/// assert_eq!(dl.back(), Some(&5));
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
@ -446,7 +508,6 @@ impl<T> LinkedList<T> {
|
||||||
///
|
///
|
||||||
/// dl.push_front(1);
|
/// dl.push_front(1);
|
||||||
/// assert_eq!(dl.front().unwrap(), &1);
|
/// assert_eq!(dl.front().unwrap(), &1);
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn push_front(&mut self, elt: T) {
|
pub fn push_front(&mut self, elt: T) {
|
||||||
|
@ -471,9 +532,7 @@ impl<T> LinkedList<T> {
|
||||||
/// assert_eq!(d.pop_front(), Some(3));
|
/// assert_eq!(d.pop_front(), Some(3));
|
||||||
/// assert_eq!(d.pop_front(), Some(1));
|
/// assert_eq!(d.pop_front(), Some(1));
|
||||||
/// assert_eq!(d.pop_front(), None);
|
/// assert_eq!(d.pop_front(), None);
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn pop_front(&mut self) -> Option<T> {
|
pub fn pop_front(&mut self) -> Option<T> {
|
||||||
self.pop_front_node().map(Node::into_element)
|
self.pop_front_node().map(Node::into_element)
|
||||||
|
|
|
@ -23,6 +23,22 @@ pub trait RangeArgument<T> {
|
||||||
/// Start index (inclusive)
|
/// Start index (inclusive)
|
||||||
///
|
///
|
||||||
/// Return start value if present, else `None`.
|
/// Return start value if present, else `None`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(collections)]
|
||||||
|
/// #![feature(collections_range)]
|
||||||
|
///
|
||||||
|
/// extern crate collections;
|
||||||
|
///
|
||||||
|
/// # fn main() {
|
||||||
|
/// use collections::range::RangeArgument;
|
||||||
|
///
|
||||||
|
/// assert_eq!((..10).start(), None);
|
||||||
|
/// assert_eq!((3..10).start(), Some(&3));
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
fn start(&self) -> Option<&T> {
|
fn start(&self) -> Option<&T> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -30,6 +46,22 @@ pub trait RangeArgument<T> {
|
||||||
/// End index (exclusive)
|
/// End index (exclusive)
|
||||||
///
|
///
|
||||||
/// Return end value if present, else `None`.
|
/// Return end value if present, else `None`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(collections)]
|
||||||
|
/// #![feature(collections_range)]
|
||||||
|
///
|
||||||
|
/// extern crate collections;
|
||||||
|
///
|
||||||
|
/// # fn main() {
|
||||||
|
/// use collections::range::RangeArgument;
|
||||||
|
///
|
||||||
|
/// assert_eq!((3..).end(), None);
|
||||||
|
/// assert_eq!((3..10).end(), Some(&10));
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
fn end(&self) -> Option<&T> {
|
fn end(&self) -> Option<&T> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -544,14 +544,21 @@ impl<T> [T] {
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// Print the adjacent pairs of a slice (i.e. `[1,2]`, `[2,3]`,
|
/// ```
|
||||||
/// `[3,4]`):
|
/// let slice = ['r', 'u', 's', 't'];
|
||||||
|
/// let mut iter = slice.windows(2);
|
||||||
|
/// assert_eq!(iter.next().unwrap(), &['r', 'u']);
|
||||||
|
/// assert_eq!(iter.next().unwrap(), &['u', 's']);
|
||||||
|
/// assert_eq!(iter.next().unwrap(), &['s', 't']);
|
||||||
|
/// assert!(iter.next().is_none());
|
||||||
|
/// ```
|
||||||
///
|
///
|
||||||
/// ```rust
|
/// If the slice is shorter than `size`:
|
||||||
/// let v = &[1, 2, 3, 4];
|
///
|
||||||
/// for win in v.windows(2) {
|
/// ```
|
||||||
/// println!("{:?}", win);
|
/// let slice = ['f', 'o', 'o'];
|
||||||
/// }
|
/// let mut iter = slice.windows(4);
|
||||||
|
/// assert!(iter.next().is_none());
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -570,15 +577,13 @@ impl<T> [T] {
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// Print the slice two elements at a time (i.e. `[1,2]`,
|
/// ```
|
||||||
/// `[3,4]`, `[5]`):
|
/// let slice = ['l', 'o', 'r', 'e', 'm'];
|
||||||
///
|
/// let mut iter = slice.chunks(2);
|
||||||
/// ```rust
|
/// assert_eq!(iter.next().unwrap(), &['l', 'o']);
|
||||||
/// let v = &[1, 2, 3, 4, 5];
|
/// assert_eq!(iter.next().unwrap(), &['r', 'e']);
|
||||||
///
|
/// assert_eq!(iter.next().unwrap(), &['m']);
|
||||||
/// for chunk in v.chunks(2) {
|
/// assert!(iter.next().is_none());
|
||||||
/// println!("{:?}", chunk);
|
|
||||||
/// }
|
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -684,15 +689,40 @@ impl<T> [T] {
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Print the slice split by numbers divisible by 3 (i.e. `[10, 40]`,
|
/// ```
|
||||||
/// `[20]`, `[50]`):
|
/// let slice = [10, 40, 33, 20];
|
||||||
|
/// let mut iter = slice.split(|num| num % 3 == 0);
|
||||||
|
///
|
||||||
|
/// assert_eq!(iter.next().unwrap(), &[10, 40]);
|
||||||
|
/// assert_eq!(iter.next().unwrap(), &[20]);
|
||||||
|
/// assert!(iter.next().is_none());
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// If the first element is matched, an empty slice will be the first item
|
||||||
|
/// returned by the iterator. Similarly, if the last element in the slice
|
||||||
|
/// is matched, an empty slice will be the last item returned by the
|
||||||
|
/// iterator:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let v = [10, 40, 30, 20, 60, 50];
|
/// let slice = [10, 40, 33];
|
||||||
|
/// let mut iter = slice.split(|num| num % 3 == 0);
|
||||||
///
|
///
|
||||||
/// for group in v.split(|num| *num % 3 == 0) {
|
/// assert_eq!(iter.next().unwrap(), &[10, 40]);
|
||||||
/// println!("{:?}", group);
|
/// assert_eq!(iter.next().unwrap(), &[]);
|
||||||
/// }
|
/// assert!(iter.next().is_none());
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// If two matched elements are directly adjacent, an empty slice will be
|
||||||
|
/// present between them:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let slice = [10, 6, 33, 20];
|
||||||
|
/// let mut iter = slice.split(|num| num % 3 == 0);
|
||||||
|
///
|
||||||
|
/// assert_eq!(iter.next().unwrap(), &[10]);
|
||||||
|
/// assert_eq!(iter.next().unwrap(), &[]);
|
||||||
|
/// assert_eq!(iter.next().unwrap(), &[20]);
|
||||||
|
/// assert!(iter.next().is_none());
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -1697,6 +1697,14 @@ impl str {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Escapes each char in `s` with `char::escape_debug`.
|
||||||
|
#[unstable(feature = "str_escape",
|
||||||
|
reason = "return type may change to be an iterator",
|
||||||
|
issue = "27791")]
|
||||||
|
pub fn escape_debug(&self) -> String {
|
||||||
|
self.chars().flat_map(|c| c.escape_debug()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
/// Escapes each char in `s` with `char::escape_default`.
|
/// Escapes each char in `s` with `char::escape_default`.
|
||||||
#[unstable(feature = "str_escape",
|
#[unstable(feature = "str_escape",
|
||||||
reason = "return type may change to be an iterator",
|
reason = "return type may change to be an iterator",
|
||||||
|
|
|
@ -59,7 +59,7 @@ use core::fmt;
|
||||||
use core::hash;
|
use core::hash;
|
||||||
use core::iter::FromIterator;
|
use core::iter::FromIterator;
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use core::ops::{self, Add, Index, IndexMut};
|
use core::ops::{self, Add, AddAssign, Index, IndexMut};
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
use core::str::pattern::Pattern;
|
use core::str::pattern::Pattern;
|
||||||
use rustc_unicode::char::{decode_utf16, REPLACEMENT_CHARACTER};
|
use rustc_unicode::char::{decode_utf16, REPLACEMENT_CHARACTER};
|
||||||
|
@ -701,6 +701,12 @@ impl String {
|
||||||
/// Violating these may cause problems like corrupting the allocator's
|
/// Violating these may cause problems like corrupting the allocator's
|
||||||
/// internal datastructures.
|
/// internal datastructures.
|
||||||
///
|
///
|
||||||
|
/// The ownership of `ptr` is effectively transferred to the
|
||||||
|
/// `String` which may then deallocate, reallocate or change the
|
||||||
|
/// contents of memory pointed to by the pointer at will. Ensure
|
||||||
|
/// that nothing else uses the pointer after calling this
|
||||||
|
/// function.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Basic usage:
|
/// Basic usage:
|
||||||
|
@ -1126,18 +1132,62 @@ impl String {
|
||||||
assert!(idx <= len);
|
assert!(idx <= len);
|
||||||
assert!(self.is_char_boundary(idx));
|
assert!(self.is_char_boundary(idx));
|
||||||
let bits = ch.encode_utf8();
|
let bits = ch.encode_utf8();
|
||||||
let bits = bits.as_slice();
|
|
||||||
let amt = bits.len();
|
|
||||||
self.vec.reserve(amt);
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
ptr::copy(self.vec.as_ptr().offset(idx as isize),
|
self.insert_bytes(idx, bits.as_slice());
|
||||||
self.vec.as_mut_ptr().offset((idx + amt) as isize),
|
}
|
||||||
len - idx);
|
}
|
||||||
ptr::copy(bits.as_ptr(),
|
|
||||||
self.vec.as_mut_ptr().offset(idx as isize),
|
unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) {
|
||||||
amt);
|
let len = self.len();
|
||||||
self.vec.set_len(len + amt);
|
let amt = bytes.len();
|
||||||
|
self.vec.reserve(amt);
|
||||||
|
|
||||||
|
ptr::copy(self.vec.as_ptr().offset(idx as isize),
|
||||||
|
self.vec.as_mut_ptr().offset((idx + amt) as isize),
|
||||||
|
len - idx);
|
||||||
|
ptr::copy(bytes.as_ptr(),
|
||||||
|
self.vec.as_mut_ptr().offset(idx as isize),
|
||||||
|
amt);
|
||||||
|
self.vec.set_len(len + amt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inserts a string into this `String` at a byte position.
|
||||||
|
///
|
||||||
|
/// This is an `O(n)` operation as it requires copying every element in the
|
||||||
|
/// buffer.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
///
|
||||||
|
/// Panics if `idx` is larger than the `String`'s length, or if it does not
|
||||||
|
/// lie on a [`char`] boundary.
|
||||||
|
///
|
||||||
|
/// [`char`]: ../../std/primitive.char.html
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(insert_str)]
|
||||||
|
///
|
||||||
|
/// let mut s = String::from("bar");
|
||||||
|
///
|
||||||
|
/// s.insert_str(0, "foo");
|
||||||
|
///
|
||||||
|
/// assert_eq!("foobar", s);
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
#[unstable(feature = "insert_str",
|
||||||
|
reason = "recent addition",
|
||||||
|
issue = "0")]
|
||||||
|
pub fn insert_str(&mut self, idx: usize, string: &str) {
|
||||||
|
let len = self.len();
|
||||||
|
assert!(idx <= len);
|
||||||
|
assert!(self.is_char_boundary(idx));
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
self.insert_bytes(idx, string.as_bytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1559,6 +1609,14 @@ impl<'a> Add<&'a str> for String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "stringaddassign", since = "1.12.0")]
|
||||||
|
impl<'a> AddAssign<&'a str> for String {
|
||||||
|
#[inline]
|
||||||
|
fn add_assign(&mut self, other: &str) {
|
||||||
|
self.push_str(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl ops::Index<ops::Range<usize>> for String {
|
impl ops::Index<ops::Range<usize>> for String {
|
||||||
type Output = str;
|
type Output = str;
|
||||||
|
@ -1823,6 +1881,26 @@ impl Into<Vec<u8>> for String {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "stringfromchars", since = "1.12.0")]
|
||||||
|
impl<'a> From<&'a [char]> for String {
|
||||||
|
#[inline]
|
||||||
|
fn from(v: &'a [char]) -> String {
|
||||||
|
let mut s = String::with_capacity(v.len());
|
||||||
|
for c in v {
|
||||||
|
s.push(*c);
|
||||||
|
}
|
||||||
|
s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "stringfromchars", since = "1.12.0")]
|
||||||
|
impl From<Vec<char>> for String {
|
||||||
|
#[inline]
|
||||||
|
fn from(v: Vec<char>) -> String {
|
||||||
|
String::from(v.as_slice())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl fmt::Write for String {
|
impl fmt::Write for String {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -73,6 +73,7 @@ use core::mem;
|
||||||
use core::ops::{Index, IndexMut};
|
use core::ops::{Index, IndexMut};
|
||||||
use core::ops;
|
use core::ops;
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
|
use core::ptr::Shared;
|
||||||
use core::slice;
|
use core::slice;
|
||||||
|
|
||||||
use super::SpecExtend;
|
use super::SpecExtend;
|
||||||
|
@ -342,12 +343,18 @@ impl<T> Vec<T> {
|
||||||
///
|
///
|
||||||
/// * `ptr` needs to have been previously allocated via `String`/`Vec<T>`
|
/// * `ptr` needs to have been previously allocated via `String`/`Vec<T>`
|
||||||
/// (at least, it's highly likely to be incorrect if it wasn't).
|
/// (at least, it's highly likely to be incorrect if it wasn't).
|
||||||
/// * `length` needs to be the length that less than or equal to `capacity`.
|
/// * `length` needs to be less than or equal to `capacity`.
|
||||||
/// * `capacity` needs to be the capacity that the pointer was allocated with.
|
/// * `capacity` needs to be the capacity that the pointer was allocated with.
|
||||||
///
|
///
|
||||||
/// Violating these may cause problems like corrupting the allocator's
|
/// Violating these may cause problems like corrupting the allocator's
|
||||||
/// internal datastructures.
|
/// internal datastructures.
|
||||||
///
|
///
|
||||||
|
/// The ownership of `ptr` is effectively transferred to the
|
||||||
|
/// `Vec<T>` which may then deallocate, reallocate or change the
|
||||||
|
/// contents of memory pointed to by the pointer at will. Ensure
|
||||||
|
/// that nothing else uses the pointer after calling this
|
||||||
|
/// function.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -469,6 +476,25 @@ impl<T> Vec<T> {
|
||||||
/// Note that this will drop any excess capacity. Calling this and
|
/// Note that this will drop any excess capacity. Calling this and
|
||||||
/// converting back to a vector with `into_vec()` is equivalent to calling
|
/// converting back to a vector with `into_vec()` is equivalent to calling
|
||||||
/// `shrink_to_fit()`.
|
/// `shrink_to_fit()`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let v = vec![1, 2, 3];
|
||||||
|
///
|
||||||
|
/// let slice = v.into_boxed_slice();
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Any excess capacity is removed:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let mut vec = Vec::with_capacity(10);
|
||||||
|
/// vec.extend([1, 2, 3].iter().cloned());
|
||||||
|
///
|
||||||
|
/// assert_eq!(vec.capacity(), 10);
|
||||||
|
/// let slice = vec.into_boxed_slice();
|
||||||
|
/// assert_eq!(slice.into_vec().capacity(), 3);
|
||||||
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn into_boxed_slice(mut self) -> Box<[T]> {
|
pub fn into_boxed_slice(mut self) -> Box<[T]> {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -479,18 +505,45 @@ impl<T> Vec<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shorten a vector to be `len` elements long, dropping excess elements.
|
/// Shortens the vector, keeping the first `len` elements and dropping
|
||||||
|
/// the rest.
|
||||||
///
|
///
|
||||||
/// If `len` is greater than the vector's current length, this has no
|
/// If `len` is greater than the vector's current length, this has no
|
||||||
/// effect.
|
/// effect.
|
||||||
///
|
///
|
||||||
|
/// The [`drain`] method can emulate `truncate`, but causes the excess
|
||||||
|
/// elements to be returned instead of dropped.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
/// Truncating a five element vector to two elements:
|
||||||
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let mut vec = vec![1, 2, 3, 4, 5];
|
/// let mut vec = vec![1, 2, 3, 4, 5];
|
||||||
/// vec.truncate(2);
|
/// vec.truncate(2);
|
||||||
/// assert_eq!(vec, [1, 2]);
|
/// assert_eq!(vec, [1, 2]);
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// No truncation occurs when `len` is greater than the vector's current
|
||||||
|
/// length:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let mut vec = vec![1, 2, 3];
|
||||||
|
/// vec.truncate(8);
|
||||||
|
/// assert_eq!(vec, [1, 2, 3]);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Truncating when `len == 0` is equivalent to calling the [`clear`]
|
||||||
|
/// method.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let mut vec = vec![1, 2, 3];
|
||||||
|
/// vec.truncate(0);
|
||||||
|
/// assert_eq!(vec, []);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [`clear`]: #method.clear
|
||||||
|
/// [`drain`]: #method.drain
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn truncate(&mut self, len: usize) {
|
pub fn truncate(&mut self, len: usize) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -508,6 +561,14 @@ impl<T> Vec<T> {
|
||||||
/// Extracts a slice containing the entire vector.
|
/// Extracts a slice containing the entire vector.
|
||||||
///
|
///
|
||||||
/// Equivalent to `&s[..]`.
|
/// Equivalent to `&s[..]`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::io::{self, Write};
|
||||||
|
/// let buffer = vec![1, 2, 3, 5, 8];
|
||||||
|
/// io::sink().write(buffer.as_slice()).unwrap();
|
||||||
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "vec_as_slice", since = "1.7.0")]
|
#[stable(feature = "vec_as_slice", since = "1.7.0")]
|
||||||
pub fn as_slice(&self) -> &[T] {
|
pub fn as_slice(&self) -> &[T] {
|
||||||
|
@ -517,6 +578,14 @@ impl<T> Vec<T> {
|
||||||
/// Extracts a mutable slice of the entire vector.
|
/// Extracts a mutable slice of the entire vector.
|
||||||
///
|
///
|
||||||
/// Equivalent to `&mut s[..]`.
|
/// Equivalent to `&mut s[..]`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::io::{self, Read};
|
||||||
|
/// let mut buffer = vec![0; 3];
|
||||||
|
/// io::repeat(0b101).read_exact(buffer.as_mut_slice()).unwrap();
|
||||||
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "vec_as_slice", since = "1.7.0")]
|
#[stable(feature = "vec_as_slice", since = "1.7.0")]
|
||||||
pub fn as_mut_slice(&mut self) -> &mut [T] {
|
pub fn as_mut_slice(&mut self) -> &mut [T] {
|
||||||
|
@ -532,9 +601,38 @@ impl<T> Vec<T> {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let mut v = vec![1, 2, 3, 4];
|
/// use std::ptr;
|
||||||
|
///
|
||||||
|
/// let mut vec = vec!['r', 'u', 's', 't'];
|
||||||
|
///
|
||||||
/// unsafe {
|
/// unsafe {
|
||||||
/// v.set_len(1);
|
/// ptr::drop_in_place(&mut vec[3]);
|
||||||
|
/// vec.set_len(3);
|
||||||
|
/// }
|
||||||
|
/// assert_eq!(vec, ['r', 'u', 's']);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// In this example, there is a memory leak since the memory locations
|
||||||
|
/// owned by the inner vectors were not freed prior to the `set_len` call:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let mut vec = vec![vec![1, 0, 0],
|
||||||
|
/// vec![0, 1, 0],
|
||||||
|
/// vec![0, 0, 1]];
|
||||||
|
/// unsafe {
|
||||||
|
/// vec.set_len(0);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// In this example, the vector gets expanded from zero to four items
|
||||||
|
/// without any memory allocations occurring, resulting in vector
|
||||||
|
/// values of unallocated memory:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let mut vec: Vec<char> = Vec::new();
|
||||||
|
///
|
||||||
|
/// unsafe {
|
||||||
|
/// vec.set_len(4);
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -821,8 +919,8 @@ impl<T> Vec<T> {
|
||||||
Drain {
|
Drain {
|
||||||
tail_start: end,
|
tail_start: end,
|
||||||
tail_len: len - end,
|
tail_len: len - end,
|
||||||
iter: range_slice.iter_mut(),
|
iter: range_slice.iter(),
|
||||||
vec: self as *mut _,
|
vec: Shared::new(self as *mut _),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1728,8 +1826,8 @@ pub struct Drain<'a, T: 'a> {
|
||||||
/// Length of tail
|
/// Length of tail
|
||||||
tail_len: usize,
|
tail_len: usize,
|
||||||
/// Current remaining range to remove
|
/// Current remaining range to remove
|
||||||
iter: slice::IterMut<'a, T>,
|
iter: slice::Iter<'a, T>,
|
||||||
vec: *mut Vec<T>,
|
vec: Shared<Vec<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "drain", since = "1.6.0")]
|
#[stable(feature = "drain", since = "1.6.0")]
|
||||||
|
@ -1767,7 +1865,7 @@ impl<'a, T> Drop for Drain<'a, T> {
|
||||||
|
|
||||||
if self.tail_len > 0 {
|
if self.tail_len > 0 {
|
||||||
unsafe {
|
unsafe {
|
||||||
let source_vec = &mut *self.vec;
|
let source_vec = &mut **self.vec;
|
||||||
// memmove back untouched tail, update to new length
|
// memmove back untouched tail, update to new length
|
||||||
let start = source_vec.len();
|
let start = source_vec.len();
|
||||||
let tail = self.tail_start;
|
let tail = self.tail_start;
|
||||||
|
|
|
@ -365,12 +365,28 @@ impl<T> VecDeque<T> {
|
||||||
|
|
||||||
impl<T> VecDeque<T> {
|
impl<T> VecDeque<T> {
|
||||||
/// Creates an empty `VecDeque`.
|
/// Creates an empty `VecDeque`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::collections::VecDeque;
|
||||||
|
///
|
||||||
|
/// let vector: VecDeque<u32> = VecDeque::new();
|
||||||
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn new() -> VecDeque<T> {
|
pub fn new() -> VecDeque<T> {
|
||||||
VecDeque::with_capacity(INITIAL_CAPACITY)
|
VecDeque::with_capacity(INITIAL_CAPACITY)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an empty `VecDeque` with space for at least `n` elements.
|
/// Creates an empty `VecDeque` with space for at least `n` elements.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::collections::VecDeque;
|
||||||
|
///
|
||||||
|
/// let vector: VecDeque<u32> = VecDeque::with_capacity(10);
|
||||||
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn with_capacity(n: usize) -> VecDeque<T> {
|
pub fn with_capacity(n: usize) -> VecDeque<T> {
|
||||||
// +1 since the ringbuffer always leaves one space empty
|
// +1 since the ringbuffer always leaves one space empty
|
||||||
|
@ -386,6 +402,8 @@ impl<T> VecDeque<T> {
|
||||||
|
|
||||||
/// Retrieves an element in the `VecDeque` by index.
|
/// Retrieves an element in the `VecDeque` by index.
|
||||||
///
|
///
|
||||||
|
/// Element at index 0 is the front of the queue.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -409,6 +427,8 @@ impl<T> VecDeque<T> {
|
||||||
|
|
||||||
/// Retrieves an element in the `VecDeque` mutably by index.
|
/// Retrieves an element in the `VecDeque` mutably by index.
|
||||||
///
|
///
|
||||||
|
/// Element at index 0 is the front of the queue.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -440,6 +460,8 @@ impl<T> VecDeque<T> {
|
||||||
///
|
///
|
||||||
/// Fails if there is no element with either index.
|
/// Fails if there is no element with either index.
|
||||||
///
|
///
|
||||||
|
/// Element at index 0 is the front of the queue.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -696,6 +718,25 @@ impl<T> VecDeque<T> {
|
||||||
|
|
||||||
/// Returns a pair of slices which contain, in order, the contents of the
|
/// Returns a pair of slices which contain, in order, the contents of the
|
||||||
/// `VecDeque`.
|
/// `VecDeque`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::collections::VecDeque;
|
||||||
|
///
|
||||||
|
/// let mut vector: VecDeque<u32> = VecDeque::new();
|
||||||
|
///
|
||||||
|
/// vector.push_back(0);
|
||||||
|
/// vector.push_back(1);
|
||||||
|
/// vector.push_back(2);
|
||||||
|
///
|
||||||
|
/// assert_eq!(vector.as_slices(), (&[0u32, 1, 2] as &[u32], &[] as &[u32]));
|
||||||
|
///
|
||||||
|
/// vector.push_front(10);
|
||||||
|
/// vector.push_front(9);
|
||||||
|
///
|
||||||
|
/// assert_eq!(vector.as_slices(), (&[9u32, 10] as &[u32], &[0u32, 1, 2] as &[u32]));
|
||||||
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "deque_extras_15", since = "1.5.0")]
|
#[stable(feature = "deque_extras_15", since = "1.5.0")]
|
||||||
pub fn as_slices(&self) -> (&[T], &[T]) {
|
pub fn as_slices(&self) -> (&[T], &[T]) {
|
||||||
|
@ -715,6 +756,24 @@ impl<T> VecDeque<T> {
|
||||||
|
|
||||||
/// Returns a pair of slices which contain, in order, the contents of the
|
/// Returns a pair of slices which contain, in order, the contents of the
|
||||||
/// `VecDeque`.
|
/// `VecDeque`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::collections::VecDeque;
|
||||||
|
///
|
||||||
|
/// let mut vector: VecDeque<u32> = VecDeque::new();
|
||||||
|
///
|
||||||
|
/// vector.push_back(0);
|
||||||
|
/// vector.push_back(1);
|
||||||
|
///
|
||||||
|
/// vector.push_front(10);
|
||||||
|
/// vector.push_front(9);
|
||||||
|
///
|
||||||
|
/// vector.as_mut_slices().0[0] = 42;
|
||||||
|
/// vector.as_mut_slices().1[0] = 24;
|
||||||
|
/// assert_eq!(vector.as_slices(), (&[42u32, 10] as &[u32], &[24u32, 1] as &[u32]));
|
||||||
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "deque_extras_15", since = "1.5.0")]
|
#[stable(feature = "deque_extras_15", since = "1.5.0")]
|
||||||
pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
|
pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
|
||||||
|
@ -789,7 +848,7 @@ impl<T> VecDeque<T> {
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::VecDeque;
|
/// use std::collections::VecDeque;
|
||||||
|
///
|
||||||
/// let mut v: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
|
/// let mut v: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
|
||||||
/// assert_eq!(vec![3].into_iter().collect::<VecDeque<_>>(), v.drain(2..).collect());
|
/// assert_eq!(vec![3].into_iter().collect::<VecDeque<_>>(), v.drain(2..).collect());
|
||||||
/// assert_eq!(vec![1, 2].into_iter().collect::<VecDeque<_>>(), v);
|
/// assert_eq!(vec![1, 2].into_iter().collect::<VecDeque<_>>(), v);
|
||||||
|
@ -875,6 +934,22 @@ impl<T> VecDeque<T> {
|
||||||
|
|
||||||
/// Returns `true` if the `VecDeque` contains an element equal to the
|
/// Returns `true` if the `VecDeque` contains an element equal to the
|
||||||
/// given value.
|
/// given value.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #![feature(vec_deque_contains)]
|
||||||
|
///
|
||||||
|
/// use std::collections::VecDeque;
|
||||||
|
///
|
||||||
|
/// let mut vector: VecDeque<u32> = VecDeque::new();
|
||||||
|
///
|
||||||
|
/// vector.push_back(0);
|
||||||
|
/// vector.push_back(1);
|
||||||
|
///
|
||||||
|
/// assert_eq!(vector.contains(&1), true);
|
||||||
|
/// assert_eq!(vector.contains(&10), false);
|
||||||
|
/// ```
|
||||||
#[unstable(feature = "vec_deque_contains", reason = "recently added",
|
#[unstable(feature = "vec_deque_contains", reason = "recently added",
|
||||||
issue = "32630")]
|
issue = "32630")]
|
||||||
pub fn contains(&self, x: &T) -> bool
|
pub fn contains(&self, x: &T) -> bool
|
||||||
|
@ -1111,6 +1186,8 @@ impl<T> VecDeque<T> {
|
||||||
///
|
///
|
||||||
/// Returns `None` if `index` is out of bounds.
|
/// Returns `None` if `index` is out of bounds.
|
||||||
///
|
///
|
||||||
|
/// Element at index 0 is the front of the queue.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -1145,6 +1222,8 @@ impl<T> VecDeque<T> {
|
||||||
///
|
///
|
||||||
/// Returns `None` if `index` is out of bounds.
|
/// Returns `None` if `index` is out of bounds.
|
||||||
///
|
///
|
||||||
|
/// Element at index 0 is the front of the queue.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -1176,6 +1255,8 @@ impl<T> VecDeque<T> {
|
||||||
/// end is closer to the insertion point will be moved to make room,
|
/// end is closer to the insertion point will be moved to make room,
|
||||||
/// and all the affected elements will be moved to new positions.
|
/// and all the affected elements will be moved to new positions.
|
||||||
///
|
///
|
||||||
|
/// Element at index 0 is the front of the queue.
|
||||||
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if `index` is greater than `VecDeque`'s length
|
/// Panics if `index` is greater than `VecDeque`'s length
|
||||||
|
@ -1403,7 +1484,10 @@ impl<T> VecDeque<T> {
|
||||||
/// room, and all the affected elements will be moved to new positions.
|
/// room, and all the affected elements will be moved to new positions.
|
||||||
/// Returns `None` if `index` is out of bounds.
|
/// Returns `None` if `index` is out of bounds.
|
||||||
///
|
///
|
||||||
|
/// Element at index 0 is the front of the queue.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::VecDeque;
|
/// use std::collections::VecDeque;
|
||||||
///
|
///
|
||||||
|
@ -1581,6 +1665,8 @@ impl<T> VecDeque<T> {
|
||||||
///
|
///
|
||||||
/// Note that the capacity of `self` does not change.
|
/// Note that the capacity of `self` does not change.
|
||||||
///
|
///
|
||||||
|
/// Element at index 0 is the front of the queue.
|
||||||
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if `at > len`
|
/// Panics if `at > len`
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::collections::BinaryHeap;
|
use std::collections::BinaryHeap;
|
||||||
|
use std::collections::binary_heap::Drain;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_iterator() {
|
fn test_iterator() {
|
||||||
|
@ -292,3 +293,8 @@ fn test_extend_specialization() {
|
||||||
|
|
||||||
assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]);
|
assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn assert_covariance() {
|
||||||
|
fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { d }
|
||||||
|
}
|
||||||
|
|
|
@ -703,16 +703,32 @@ fn test_escape_unicode() {
|
||||||
assert_eq!("\u{1d4ea}\r".escape_unicode(), "\\u{1d4ea}\\u{d}");
|
assert_eq!("\u{1d4ea}\r".escape_unicode(), "\\u{1d4ea}\\u{d}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_escape_debug() {
|
||||||
|
assert_eq!("abc".escape_debug(), "abc");
|
||||||
|
assert_eq!("a c".escape_debug(), "a c");
|
||||||
|
assert_eq!("éèê".escape_debug(), "éèê");
|
||||||
|
assert_eq!("\r\n\t".escape_debug(), "\\r\\n\\t");
|
||||||
|
assert_eq!("'\"\\".escape_debug(), "\\'\\\"\\\\");
|
||||||
|
assert_eq!("\u{7f}\u{ff}".escape_debug(), "\\u{7f}\u{ff}");
|
||||||
|
assert_eq!("\u{100}\u{ffff}".escape_debug(), "\u{100}\\u{ffff}");
|
||||||
|
assert_eq!("\u{10000}\u{10ffff}".escape_debug(), "\u{10000}\\u{10ffff}");
|
||||||
|
assert_eq!("ab\u{200b}".escape_debug(), "ab\\u{200b}");
|
||||||
|
assert_eq!("\u{10d4ea}\r".escape_debug(), "\\u{10d4ea}\\r");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_escape_default() {
|
fn test_escape_default() {
|
||||||
assert_eq!("abc".escape_default(), "abc");
|
assert_eq!("abc".escape_default(), "abc");
|
||||||
assert_eq!("a c".escape_default(), "a c");
|
assert_eq!("a c".escape_default(), "a c");
|
||||||
|
assert_eq!("éèê".escape_default(), "\\u{e9}\\u{e8}\\u{ea}");
|
||||||
assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t");
|
assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t");
|
||||||
assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\");
|
assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\");
|
||||||
|
assert_eq!("\u{7f}\u{ff}".escape_default(), "\\u{7f}\\u{ff}");
|
||||||
assert_eq!("\u{100}\u{ffff}".escape_default(), "\\u{100}\\u{ffff}");
|
assert_eq!("\u{100}\u{ffff}".escape_default(), "\\u{100}\\u{ffff}");
|
||||||
assert_eq!("\u{10000}\u{10ffff}".escape_default(), "\\u{10000}\\u{10ffff}");
|
assert_eq!("\u{10000}\u{10ffff}".escape_default(), "\\u{10000}\\u{10ffff}");
|
||||||
assert_eq!("ab\u{fb00}".escape_default(), "ab\\u{fb00}");
|
assert_eq!("ab\u{200b}".escape_default(), "ab\\u{200b}");
|
||||||
assert_eq!("\u{1d4ea}\r".escape_default(), "\\u{1d4ea}\\r");
|
assert_eq!("\u{10d4ea}\r".escape_default(), "\\u{10d4ea}\\r");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -192,6 +192,17 @@ fn test_push_str() {
|
||||||
assert_eq!(&s[0..], "abcประเทศไทย中华Việt Nam");
|
assert_eq!(&s[0..], "abcประเทศไทย中华Việt Nam");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_add_assign() {
|
||||||
|
let mut s = String::new();
|
||||||
|
s += "";
|
||||||
|
assert_eq!(s.as_str(), "");
|
||||||
|
s += "abc";
|
||||||
|
assert_eq!(s.as_str(), "abc");
|
||||||
|
s += "ประเทศไทย中华Việt Nam";
|
||||||
|
assert_eq!(s.as_str(), "abcประเทศไทย中华Việt Nam");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_push() {
|
fn test_push() {
|
||||||
let mut data = String::from("ประเทศไทย中");
|
let mut data = String::from("ประเทศไทย中");
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::iter::{FromIterator, repeat};
|
use std::iter::{FromIterator, repeat};
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
|
use std::vec::Drain;
|
||||||
|
|
||||||
use test::Bencher;
|
use test::Bencher;
|
||||||
|
|
||||||
|
@ -510,6 +511,11 @@ fn test_cow_from() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
fn assert_covariance() {
|
||||||
|
fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { d }
|
||||||
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_new(b: &mut Bencher) {
|
fn bench_new(b: &mut Bencher) {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
|
|
|
@ -847,6 +847,20 @@ impl<'b, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<RefMut<'b, U>> for RefM
|
||||||
/// The `UnsafeCell<T>` type is the only legal way to obtain aliasable data that is considered
|
/// The `UnsafeCell<T>` type is the only legal way to obtain aliasable data that is considered
|
||||||
/// mutable. In general, transmuting an `&T` type into an `&mut T` is considered undefined behavior.
|
/// mutable. In general, transmuting an `&T` type into an `&mut T` is considered undefined behavior.
|
||||||
///
|
///
|
||||||
|
/// The compiler makes optimizations based on the knowledge that `&T` is not mutably aliased or
|
||||||
|
/// mutated, and that `&mut T` is unique. When building abstractions like `Cell`, `RefCell`,
|
||||||
|
/// `Mutex`, etc, you need to turn these optimizations off. `UnsafeCell` is the only legal way
|
||||||
|
/// to do this. When `UnsafeCell<T>` is immutably aliased, it is still safe to obtain a mutable
|
||||||
|
/// reference to its interior and/or to mutate it. However, it is up to the abstraction designer
|
||||||
|
/// to ensure that no two mutable references obtained this way are active at the same time, and
|
||||||
|
/// that there are no active mutable references or mutations when an immutable reference is obtained
|
||||||
|
/// from the cell. This is often done via runtime checks.
|
||||||
|
///
|
||||||
|
/// Note that while mutating or mutably aliasing the contents of an `& UnsafeCell<T>` is
|
||||||
|
/// okay (provided you enforce the invariants some other way); it is still undefined behavior
|
||||||
|
/// to have multiple `&mut UnsafeCell<T>` aliases.
|
||||||
|
///
|
||||||
|
///
|
||||||
/// Types like `Cell<T>` and `RefCell<T>` use this type to wrap their internal data.
|
/// Types like `Cell<T>` and `RefCell<T>` use this type to wrap their internal data.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
@ -916,6 +930,11 @@ impl<T> UnsafeCell<T> {
|
||||||
impl<T: ?Sized> UnsafeCell<T> {
|
impl<T: ?Sized> UnsafeCell<T> {
|
||||||
/// Gets a mutable pointer to the wrapped value.
|
/// Gets a mutable pointer to the wrapped value.
|
||||||
///
|
///
|
||||||
|
/// This can be cast to a pointer of any kind.
|
||||||
|
/// Ensure that the access is unique when casting to
|
||||||
|
/// `&mut T`, and ensure that there are no mutations or mutable
|
||||||
|
/// aliases going on when casting to `&T`
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
use prelude::v1::*;
|
use prelude::v1::*;
|
||||||
|
|
||||||
|
use char_private::is_printable;
|
||||||
use mem::transmute;
|
use mem::transmute;
|
||||||
|
|
||||||
// UTF-8 ranges and tags for encoding characters
|
// UTF-8 ranges and tags for encoding characters
|
||||||
|
@ -263,6 +264,8 @@ pub trait CharExt {
|
||||||
fn escape_unicode(self) -> EscapeUnicode;
|
fn escape_unicode(self) -> EscapeUnicode;
|
||||||
#[stable(feature = "core", since = "1.6.0")]
|
#[stable(feature = "core", since = "1.6.0")]
|
||||||
fn escape_default(self) -> EscapeDefault;
|
fn escape_default(self) -> EscapeDefault;
|
||||||
|
#[unstable(feature = "char_escape_debug", issue = "35068")]
|
||||||
|
fn escape_debug(self) -> EscapeDebug;
|
||||||
#[stable(feature = "core", since = "1.6.0")]
|
#[stable(feature = "core", since = "1.6.0")]
|
||||||
fn len_utf8(self) -> usize;
|
fn len_utf8(self) -> usize;
|
||||||
#[stable(feature = "core", since = "1.6.0")]
|
#[stable(feature = "core", since = "1.6.0")]
|
||||||
|
@ -326,6 +329,19 @@ impl CharExt for char {
|
||||||
EscapeDefault { state: init_state }
|
EscapeDefault { state: init_state }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn escape_debug(self) -> EscapeDebug {
|
||||||
|
let init_state = match self {
|
||||||
|
'\t' => EscapeDefaultState::Backslash('t'),
|
||||||
|
'\r' => EscapeDefaultState::Backslash('r'),
|
||||||
|
'\n' => EscapeDefaultState::Backslash('n'),
|
||||||
|
'\\' | '\'' | '"' => EscapeDefaultState::Backslash(self),
|
||||||
|
c if is_printable(c) => EscapeDefaultState::Char(c),
|
||||||
|
c => EscapeDefaultState::Unicode(c.escape_unicode()),
|
||||||
|
};
|
||||||
|
EscapeDebug(EscapeDefault { state: init_state })
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn len_utf8(self) -> usize {
|
fn len_utf8(self) -> usize {
|
||||||
let code = self as u32;
|
let code = self as u32;
|
||||||
|
@ -600,6 +616,27 @@ impl ExactSizeIterator for EscapeDefault {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An iterator that yields the literal escape code of a `char`.
|
||||||
|
///
|
||||||
|
/// This `struct` is created by the [`escape_debug()`] method on [`char`]. See its
|
||||||
|
/// documentation for more.
|
||||||
|
///
|
||||||
|
/// [`escape_debug()`]: ../../std/primitive.char.html#method.escape_debug
|
||||||
|
/// [`char`]: ../../std/primitive.char.html
|
||||||
|
#[unstable(feature = "char_escape_debug", issue = "35068")]
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct EscapeDebug(EscapeDefault);
|
||||||
|
|
||||||
|
#[unstable(feature = "char_escape_debug", issue = "35068")]
|
||||||
|
impl Iterator for EscapeDebug {
|
||||||
|
type Item = char;
|
||||||
|
fn next(&mut self) -> Option<char> { self.0.next() }
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) { self.0.size_hint() }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unstable(feature = "char_escape_debug", issue = "35068")]
|
||||||
|
impl ExactSizeIterator for EscapeDebug { }
|
||||||
|
|
||||||
/// An iterator over `u8` entries represending the UTF-8 encoding of a `char`
|
/// An iterator over `u8` entries represending the UTF-8 encoding of a `char`
|
||||||
/// value.
|
/// value.
|
||||||
///
|
///
|
||||||
|
|
695
src/libcore/char_private.rs
Normal file
695
src/libcore/char_private.rs
Normal file
|
@ -0,0 +1,695 @@
|
||||||
|
// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
// NOTE: The following code was generated by "src/etc/char_private.py",
|
||||||
|
// do not edit directly!
|
||||||
|
|
||||||
|
use slice::SliceExt;
|
||||||
|
|
||||||
|
fn check(x: u16, singletons: &[u16], normal: &[u16]) -> bool {
|
||||||
|
for &s in singletons {
|
||||||
|
if x == s {
|
||||||
|
return false;
|
||||||
|
} else if x < s {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for w in normal.chunks(2) {
|
||||||
|
let start = w[0];
|
||||||
|
let len = w[1];
|
||||||
|
let difference = (x as i32) - (start as i32);
|
||||||
|
if 0 <= difference {
|
||||||
|
if difference < len as i32 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_printable(x: char) -> bool {
|
||||||
|
let x = x as u32;
|
||||||
|
let lower = x as u16;
|
||||||
|
if x < 0x10000 {
|
||||||
|
check(lower, SINGLETONS0, NORMAL0)
|
||||||
|
} else if x < 0x20000 {
|
||||||
|
check(lower, SINGLETONS1, NORMAL1)
|
||||||
|
} else {
|
||||||
|
if 0x20000 <= x && x < 0x2f800 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if 0x2fa1e <= x && x < 0xe0100 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if 0xe01f0 <= x && x < 0x110000 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const SINGLETONS0: &'static [u16] = &[
|
||||||
|
0xad,
|
||||||
|
0x378,
|
||||||
|
0x379,
|
||||||
|
0x38b,
|
||||||
|
0x38d,
|
||||||
|
0x3a2,
|
||||||
|
0x557,
|
||||||
|
0x558,
|
||||||
|
0x560,
|
||||||
|
0x588,
|
||||||
|
0x590,
|
||||||
|
0x61c,
|
||||||
|
0x61d,
|
||||||
|
0x6dd,
|
||||||
|
0x70e,
|
||||||
|
0x70f,
|
||||||
|
0x74b,
|
||||||
|
0x74c,
|
||||||
|
0x82e,
|
||||||
|
0x82f,
|
||||||
|
0x83f,
|
||||||
|
0x85c,
|
||||||
|
0x85d,
|
||||||
|
0x8a1,
|
||||||
|
0x8ff,
|
||||||
|
0x978,
|
||||||
|
0x980,
|
||||||
|
0x984,
|
||||||
|
0x98d,
|
||||||
|
0x98e,
|
||||||
|
0x991,
|
||||||
|
0x992,
|
||||||
|
0x9a9,
|
||||||
|
0x9b1,
|
||||||
|
0x9ba,
|
||||||
|
0x9bb,
|
||||||
|
0x9c5,
|
||||||
|
0x9c6,
|
||||||
|
0x9c9,
|
||||||
|
0x9ca,
|
||||||
|
0x9de,
|
||||||
|
0x9e4,
|
||||||
|
0x9e5,
|
||||||
|
0xa04,
|
||||||
|
0xa11,
|
||||||
|
0xa12,
|
||||||
|
0xa29,
|
||||||
|
0xa31,
|
||||||
|
0xa34,
|
||||||
|
0xa37,
|
||||||
|
0xa3a,
|
||||||
|
0xa3b,
|
||||||
|
0xa3d,
|
||||||
|
0xa49,
|
||||||
|
0xa4a,
|
||||||
|
0xa5d,
|
||||||
|
0xa84,
|
||||||
|
0xa8e,
|
||||||
|
0xa92,
|
||||||
|
0xaa9,
|
||||||
|
0xab1,
|
||||||
|
0xab4,
|
||||||
|
0xaba,
|
||||||
|
0xabb,
|
||||||
|
0xac6,
|
||||||
|
0xaca,
|
||||||
|
0xace,
|
||||||
|
0xacf,
|
||||||
|
0xae4,
|
||||||
|
0xae5,
|
||||||
|
0xb04,
|
||||||
|
0xb0d,
|
||||||
|
0xb0e,
|
||||||
|
0xb11,
|
||||||
|
0xb12,
|
||||||
|
0xb29,
|
||||||
|
0xb31,
|
||||||
|
0xb34,
|
||||||
|
0xb3a,
|
||||||
|
0xb3b,
|
||||||
|
0xb45,
|
||||||
|
0xb46,
|
||||||
|
0xb49,
|
||||||
|
0xb4a,
|
||||||
|
0xb5e,
|
||||||
|
0xb64,
|
||||||
|
0xb65,
|
||||||
|
0xb84,
|
||||||
|
0xb91,
|
||||||
|
0xb9b,
|
||||||
|
0xb9d,
|
||||||
|
0xbc9,
|
||||||
|
0xbce,
|
||||||
|
0xbcf,
|
||||||
|
0xc04,
|
||||||
|
0xc0d,
|
||||||
|
0xc11,
|
||||||
|
0xc29,
|
||||||
|
0xc34,
|
||||||
|
0xc45,
|
||||||
|
0xc49,
|
||||||
|
0xc57,
|
||||||
|
0xc64,
|
||||||
|
0xc65,
|
||||||
|
0xc80,
|
||||||
|
0xc81,
|
||||||
|
0xc84,
|
||||||
|
0xc8d,
|
||||||
|
0xc91,
|
||||||
|
0xca9,
|
||||||
|
0xcb4,
|
||||||
|
0xcba,
|
||||||
|
0xcbb,
|
||||||
|
0xcc5,
|
||||||
|
0xcc9,
|
||||||
|
0xcdf,
|
||||||
|
0xce4,
|
||||||
|
0xce5,
|
||||||
|
0xcf0,
|
||||||
|
0xd04,
|
||||||
|
0xd0d,
|
||||||
|
0xd11,
|
||||||
|
0xd3b,
|
||||||
|
0xd3c,
|
||||||
|
0xd45,
|
||||||
|
0xd49,
|
||||||
|
0xd64,
|
||||||
|
0xd65,
|
||||||
|
0xd80,
|
||||||
|
0xd81,
|
||||||
|
0xd84,
|
||||||
|
0xdb2,
|
||||||
|
0xdbc,
|
||||||
|
0xdbe,
|
||||||
|
0xdbf,
|
||||||
|
0xdd5,
|
||||||
|
0xdd7,
|
||||||
|
0xe83,
|
||||||
|
0xe85,
|
||||||
|
0xe86,
|
||||||
|
0xe89,
|
||||||
|
0xe8b,
|
||||||
|
0xe8c,
|
||||||
|
0xe98,
|
||||||
|
0xea0,
|
||||||
|
0xea4,
|
||||||
|
0xea6,
|
||||||
|
0xea8,
|
||||||
|
0xea9,
|
||||||
|
0xeac,
|
||||||
|
0xeba,
|
||||||
|
0xebe,
|
||||||
|
0xebf,
|
||||||
|
0xec5,
|
||||||
|
0xec7,
|
||||||
|
0xece,
|
||||||
|
0xecf,
|
||||||
|
0xeda,
|
||||||
|
0xedb,
|
||||||
|
0xf48,
|
||||||
|
0xf98,
|
||||||
|
0xfbd,
|
||||||
|
0xfcd,
|
||||||
|
0x10c6,
|
||||||
|
0x10ce,
|
||||||
|
0x10cf,
|
||||||
|
0x1249,
|
||||||
|
0x124e,
|
||||||
|
0x124f,
|
||||||
|
0x1257,
|
||||||
|
0x1259,
|
||||||
|
0x125e,
|
||||||
|
0x125f,
|
||||||
|
0x1289,
|
||||||
|
0x128e,
|
||||||
|
0x128f,
|
||||||
|
0x12b1,
|
||||||
|
0x12b6,
|
||||||
|
0x12b7,
|
||||||
|
0x12bf,
|
||||||
|
0x12c1,
|
||||||
|
0x12c6,
|
||||||
|
0x12c7,
|
||||||
|
0x12d7,
|
||||||
|
0x1311,
|
||||||
|
0x1316,
|
||||||
|
0x1317,
|
||||||
|
0x135b,
|
||||||
|
0x135c,
|
||||||
|
0x1680,
|
||||||
|
0x170d,
|
||||||
|
0x176d,
|
||||||
|
0x1771,
|
||||||
|
0x17de,
|
||||||
|
0x17df,
|
||||||
|
0x180e,
|
||||||
|
0x180f,
|
||||||
|
0x196e,
|
||||||
|
0x196f,
|
||||||
|
0x1a1c,
|
||||||
|
0x1a1d,
|
||||||
|
0x1a5f,
|
||||||
|
0x1a7d,
|
||||||
|
0x1a7e,
|
||||||
|
0x1f16,
|
||||||
|
0x1f17,
|
||||||
|
0x1f1e,
|
||||||
|
0x1f1f,
|
||||||
|
0x1f46,
|
||||||
|
0x1f47,
|
||||||
|
0x1f4e,
|
||||||
|
0x1f4f,
|
||||||
|
0x1f58,
|
||||||
|
0x1f5a,
|
||||||
|
0x1f5c,
|
||||||
|
0x1f5e,
|
||||||
|
0x1f7e,
|
||||||
|
0x1f7f,
|
||||||
|
0x1fb5,
|
||||||
|
0x1fc5,
|
||||||
|
0x1fd4,
|
||||||
|
0x1fd5,
|
||||||
|
0x1fdc,
|
||||||
|
0x1ff0,
|
||||||
|
0x1ff1,
|
||||||
|
0x1ff5,
|
||||||
|
0x2072,
|
||||||
|
0x2073,
|
||||||
|
0x208f,
|
||||||
|
0x2700,
|
||||||
|
0x2c2f,
|
||||||
|
0x2c5f,
|
||||||
|
0x2d26,
|
||||||
|
0x2d2e,
|
||||||
|
0x2d2f,
|
||||||
|
0x2da7,
|
||||||
|
0x2daf,
|
||||||
|
0x2db7,
|
||||||
|
0x2dbf,
|
||||||
|
0x2dc7,
|
||||||
|
0x2dcf,
|
||||||
|
0x2dd7,
|
||||||
|
0x2ddf,
|
||||||
|
0x2e9a,
|
||||||
|
0x3040,
|
||||||
|
0x3097,
|
||||||
|
0x3098,
|
||||||
|
0x318f,
|
||||||
|
0x321f,
|
||||||
|
0x32ff,
|
||||||
|
0xa78f,
|
||||||
|
0xa9ce,
|
||||||
|
0xaa4e,
|
||||||
|
0xaa4f,
|
||||||
|
0xaa5a,
|
||||||
|
0xaa5b,
|
||||||
|
0xab07,
|
||||||
|
0xab08,
|
||||||
|
0xab0f,
|
||||||
|
0xab10,
|
||||||
|
0xab27,
|
||||||
|
0xabee,
|
||||||
|
0xabef,
|
||||||
|
0xfa6e,
|
||||||
|
0xfa6f,
|
||||||
|
0xfb37,
|
||||||
|
0xfb3d,
|
||||||
|
0xfb3f,
|
||||||
|
0xfb42,
|
||||||
|
0xfb45,
|
||||||
|
0xfd90,
|
||||||
|
0xfd91,
|
||||||
|
0xfdfe,
|
||||||
|
0xfdff,
|
||||||
|
0xfe53,
|
||||||
|
0xfe67,
|
||||||
|
0xfe75,
|
||||||
|
0xffc8,
|
||||||
|
0xffc9,
|
||||||
|
0xffd0,
|
||||||
|
0xffd1,
|
||||||
|
0xffd8,
|
||||||
|
0xffd9,
|
||||||
|
0xffe7,
|
||||||
|
0xfffe,
|
||||||
|
0xffff,
|
||||||
|
];
|
||||||
|
const SINGLETONS1: &'static [u16] = &[
|
||||||
|
0xc,
|
||||||
|
0x27,
|
||||||
|
0x3b,
|
||||||
|
0x3e,
|
||||||
|
0x4e,
|
||||||
|
0x4f,
|
||||||
|
0x31f,
|
||||||
|
0x39e,
|
||||||
|
0x49e,
|
||||||
|
0x49f,
|
||||||
|
0x806,
|
||||||
|
0x807,
|
||||||
|
0x809,
|
||||||
|
0x836,
|
||||||
|
0x83d,
|
||||||
|
0x83e,
|
||||||
|
0x856,
|
||||||
|
0xa04,
|
||||||
|
0xa14,
|
||||||
|
0xa18,
|
||||||
|
0xb56,
|
||||||
|
0xb57,
|
||||||
|
0x10bd,
|
||||||
|
0x1135,
|
||||||
|
0xd127,
|
||||||
|
0xd128,
|
||||||
|
0xd455,
|
||||||
|
0xd49d,
|
||||||
|
0xd4a0,
|
||||||
|
0xd4a1,
|
||||||
|
0xd4a3,
|
||||||
|
0xd4a4,
|
||||||
|
0xd4a7,
|
||||||
|
0xd4a8,
|
||||||
|
0xd4ad,
|
||||||
|
0xd4ba,
|
||||||
|
0xd4bc,
|
||||||
|
0xd4c4,
|
||||||
|
0xd506,
|
||||||
|
0xd50b,
|
||||||
|
0xd50c,
|
||||||
|
0xd515,
|
||||||
|
0xd51d,
|
||||||
|
0xd53a,
|
||||||
|
0xd53f,
|
||||||
|
0xd545,
|
||||||
|
0xd551,
|
||||||
|
0xd6a6,
|
||||||
|
0xd6a7,
|
||||||
|
0xd7cc,
|
||||||
|
0xd7cd,
|
||||||
|
0xee04,
|
||||||
|
0xee20,
|
||||||
|
0xee23,
|
||||||
|
0xee25,
|
||||||
|
0xee26,
|
||||||
|
0xee28,
|
||||||
|
0xee33,
|
||||||
|
0xee38,
|
||||||
|
0xee3a,
|
||||||
|
0xee48,
|
||||||
|
0xee4a,
|
||||||
|
0xee4c,
|
||||||
|
0xee50,
|
||||||
|
0xee53,
|
||||||
|
0xee55,
|
||||||
|
0xee56,
|
||||||
|
0xee58,
|
||||||
|
0xee5a,
|
||||||
|
0xee5c,
|
||||||
|
0xee5e,
|
||||||
|
0xee60,
|
||||||
|
0xee63,
|
||||||
|
0xee65,
|
||||||
|
0xee66,
|
||||||
|
0xee6b,
|
||||||
|
0xee73,
|
||||||
|
0xee78,
|
||||||
|
0xee7d,
|
||||||
|
0xee7f,
|
||||||
|
0xee8a,
|
||||||
|
0xeea4,
|
||||||
|
0xeeaa,
|
||||||
|
0xf0af,
|
||||||
|
0xf0b0,
|
||||||
|
0xf0bf,
|
||||||
|
0xf0c0,
|
||||||
|
0xf0d0,
|
||||||
|
0xf12f,
|
||||||
|
0xf336,
|
||||||
|
0xf3c5,
|
||||||
|
0xf43f,
|
||||||
|
0xf441,
|
||||||
|
0xf4f8,
|
||||||
|
0xf53e,
|
||||||
|
0xf53f,
|
||||||
|
];
|
||||||
|
const NORMAL0: &'static [u16] = &[
|
||||||
|
0x0, 0x20,
|
||||||
|
0x7f, 0x22,
|
||||||
|
0x37f, 0x5,
|
||||||
|
0x528, 0x9,
|
||||||
|
0x58b, 0x4,
|
||||||
|
0x5c8, 0x8,
|
||||||
|
0x5eb, 0x5,
|
||||||
|
0x5f5, 0x11,
|
||||||
|
0x7b2, 0xe,
|
||||||
|
0x7fb, 0x5,
|
||||||
|
0x85f, 0x41,
|
||||||
|
0x8ad, 0x37,
|
||||||
|
0x9b3, 0x3,
|
||||||
|
0x9cf, 0x8,
|
||||||
|
0x9d8, 0x4,
|
||||||
|
0x9fc, 0x5,
|
||||||
|
0xa0b, 0x4,
|
||||||
|
0xa43, 0x4,
|
||||||
|
0xa4e, 0x3,
|
||||||
|
0xa52, 0x7,
|
||||||
|
0xa5f, 0x7,
|
||||||
|
0xa76, 0xb,
|
||||||
|
0xad1, 0xf,
|
||||||
|
0xaf2, 0xf,
|
||||||
|
0xb4e, 0x8,
|
||||||
|
0xb58, 0x4,
|
||||||
|
0xb78, 0xa,
|
||||||
|
0xb8b, 0x3,
|
||||||
|
0xb96, 0x3,
|
||||||
|
0xba0, 0x3,
|
||||||
|
0xba5, 0x3,
|
||||||
|
0xbab, 0x3,
|
||||||
|
0xbba, 0x4,
|
||||||
|
0xbc3, 0x3,
|
||||||
|
0xbd1, 0x6,
|
||||||
|
0xbd8, 0xe,
|
||||||
|
0xbfb, 0x6,
|
||||||
|
0xc3a, 0x3,
|
||||||
|
0xc4e, 0x7,
|
||||||
|
0xc5a, 0x6,
|
||||||
|
0xc70, 0x8,
|
||||||
|
0xcce, 0x7,
|
||||||
|
0xcd7, 0x7,
|
||||||
|
0xcf3, 0xf,
|
||||||
|
0xd4f, 0x8,
|
||||||
|
0xd58, 0x8,
|
||||||
|
0xd76, 0x3,
|
||||||
|
0xd97, 0x3,
|
||||||
|
0xdc7, 0x3,
|
||||||
|
0xdcb, 0x4,
|
||||||
|
0xde0, 0x12,
|
||||||
|
0xdf5, 0xc,
|
||||||
|
0xe3b, 0x4,
|
||||||
|
0xe5c, 0x25,
|
||||||
|
0xe8e, 0x6,
|
||||||
|
0xee0, 0x20,
|
||||||
|
0xf6d, 0x4,
|
||||||
|
0xfdb, 0x25,
|
||||||
|
0x10c8, 0x5,
|
||||||
|
0x137d, 0x3,
|
||||||
|
0x139a, 0x6,
|
||||||
|
0x13f5, 0xb,
|
||||||
|
0x169d, 0x3,
|
||||||
|
0x16f1, 0xf,
|
||||||
|
0x1715, 0xb,
|
||||||
|
0x1737, 0x9,
|
||||||
|
0x1754, 0xc,
|
||||||
|
0x1774, 0xc,
|
||||||
|
0x17ea, 0x6,
|
||||||
|
0x17fa, 0x6,
|
||||||
|
0x181a, 0x6,
|
||||||
|
0x1878, 0x8,
|
||||||
|
0x18ab, 0x5,
|
||||||
|
0x18f6, 0xa,
|
||||||
|
0x191d, 0x3,
|
||||||
|
0x192c, 0x4,
|
||||||
|
0x193c, 0x4,
|
||||||
|
0x1941, 0x3,
|
||||||
|
0x1975, 0xb,
|
||||||
|
0x19ac, 0x4,
|
||||||
|
0x19ca, 0x6,
|
||||||
|
0x19db, 0x3,
|
||||||
|
0x1a8a, 0x6,
|
||||||
|
0x1a9a, 0x6,
|
||||||
|
0x1aae, 0x52,
|
||||||
|
0x1b4c, 0x4,
|
||||||
|
0x1b7d, 0x3,
|
||||||
|
0x1bf4, 0x8,
|
||||||
|
0x1c38, 0x3,
|
||||||
|
0x1c4a, 0x3,
|
||||||
|
0x1c80, 0x40,
|
||||||
|
0x1cc8, 0x8,
|
||||||
|
0x1cf7, 0x9,
|
||||||
|
0x1de7, 0x15,
|
||||||
|
0x1fff, 0x11,
|
||||||
|
0x2028, 0x8,
|
||||||
|
0x205f, 0x11,
|
||||||
|
0x209d, 0x3,
|
||||||
|
0x20ba, 0x16,
|
||||||
|
0x20f1, 0xf,
|
||||||
|
0x218a, 0x6,
|
||||||
|
0x23f4, 0xc,
|
||||||
|
0x2427, 0x19,
|
||||||
|
0x244b, 0x15,
|
||||||
|
0x2b4d, 0x3,
|
||||||
|
0x2b5a, 0xa6,
|
||||||
|
0x2cf4, 0x5,
|
||||||
|
0x2d28, 0x5,
|
||||||
|
0x2d68, 0x7,
|
||||||
|
0x2d71, 0xe,
|
||||||
|
0x2d97, 0x9,
|
||||||
|
0x2e3c, 0x44,
|
||||||
|
0x2ef4, 0xc,
|
||||||
|
0x2fd6, 0x1a,
|
||||||
|
0x2ffc, 0x5,
|
||||||
|
0x3100, 0x5,
|
||||||
|
0x312e, 0x3,
|
||||||
|
0x31bb, 0x5,
|
||||||
|
0x31e4, 0xc,
|
||||||
|
0x3400, 0x19c0,
|
||||||
|
0x4e00, 0x5200,
|
||||||
|
0xa48d, 0x3,
|
||||||
|
0xa4c7, 0x9,
|
||||||
|
0xa62c, 0x14,
|
||||||
|
0xa698, 0x7,
|
||||||
|
0xa6f8, 0x8,
|
||||||
|
0xa794, 0xc,
|
||||||
|
0xa7ab, 0x4d,
|
||||||
|
0xa82c, 0x4,
|
||||||
|
0xa83a, 0x6,
|
||||||
|
0xa878, 0x8,
|
||||||
|
0xa8c5, 0x9,
|
||||||
|
0xa8da, 0x6,
|
||||||
|
0xa8fc, 0x4,
|
||||||
|
0xa954, 0xb,
|
||||||
|
0xa97d, 0x3,
|
||||||
|
0xa9da, 0x4,
|
||||||
|
0xa9e0, 0x20,
|
||||||
|
0xaa37, 0x9,
|
||||||
|
0xaa7c, 0x4,
|
||||||
|
0xaac3, 0x18,
|
||||||
|
0xaaf7, 0xa,
|
||||||
|
0xab17, 0x9,
|
||||||
|
0xab2f, 0x91,
|
||||||
|
0xabfa, 0x2bb6,
|
||||||
|
0xd7c7, 0x4,
|
||||||
|
0xd7fc, 0x2104,
|
||||||
|
0xfada, 0x26,
|
||||||
|
0xfb07, 0xc,
|
||||||
|
0xfb18, 0x5,
|
||||||
|
0xfbc2, 0x11,
|
||||||
|
0xfd40, 0x10,
|
||||||
|
0xfdc8, 0x28,
|
||||||
|
0xfe1a, 0x6,
|
||||||
|
0xfe27, 0x9,
|
||||||
|
0xfe6c, 0x4,
|
||||||
|
0xfefd, 0x4,
|
||||||
|
0xffbf, 0x3,
|
||||||
|
0xffdd, 0x3,
|
||||||
|
0xffef, 0xd,
|
||||||
|
];
|
||||||
|
const NORMAL1: &'static [u16] = &[
|
||||||
|
0x5e, 0x22,
|
||||||
|
0xfb, 0x5,
|
||||||
|
0x103, 0x4,
|
||||||
|
0x134, 0x3,
|
||||||
|
0x18b, 0x5,
|
||||||
|
0x19c, 0x34,
|
||||||
|
0x1fe, 0x82,
|
||||||
|
0x29d, 0x3,
|
||||||
|
0x2d1, 0x2f,
|
||||||
|
0x324, 0xc,
|
||||||
|
0x34b, 0x35,
|
||||||
|
0x3c4, 0x4,
|
||||||
|
0x3d6, 0x2a,
|
||||||
|
0x4aa, 0x356,
|
||||||
|
0x839, 0x3,
|
||||||
|
0x860, 0xa0,
|
||||||
|
0x91c, 0x3,
|
||||||
|
0x93a, 0x5,
|
||||||
|
0x940, 0x40,
|
||||||
|
0x9b8, 0x6,
|
||||||
|
0x9c0, 0x40,
|
||||||
|
0xa07, 0x5,
|
||||||
|
0xa34, 0x4,
|
||||||
|
0xa3b, 0x4,
|
||||||
|
0xa48, 0x8,
|
||||||
|
0xa59, 0x7,
|
||||||
|
0xa80, 0x80,
|
||||||
|
0xb36, 0x3,
|
||||||
|
0xb73, 0x5,
|
||||||
|
0xb80, 0x80,
|
||||||
|
0xc49, 0x217,
|
||||||
|
0xe7f, 0x181,
|
||||||
|
0x104e, 0x4,
|
||||||
|
0x1070, 0x10,
|
||||||
|
0x10c2, 0xe,
|
||||||
|
0x10e9, 0x7,
|
||||||
|
0x10fa, 0x6,
|
||||||
|
0x1144, 0x3c,
|
||||||
|
0x11c9, 0x7,
|
||||||
|
0x11da, 0x4a6,
|
||||||
|
0x16b8, 0x8,
|
||||||
|
0x16ca, 0x936,
|
||||||
|
0x236f, 0x91,
|
||||||
|
0x2463, 0xd,
|
||||||
|
0x2474, 0xb8c,
|
||||||
|
0x342f, 0x33d1,
|
||||||
|
0x6a39, 0x4c7,
|
||||||
|
0x6f45, 0xb,
|
||||||
|
0x6f7f, 0x10,
|
||||||
|
0x6fa0, 0x4060,
|
||||||
|
0xb002, 0x1ffe,
|
||||||
|
0xd0f6, 0xa,
|
||||||
|
0xd173, 0x8,
|
||||||
|
0xd1de, 0x22,
|
||||||
|
0xd246, 0xba,
|
||||||
|
0xd357, 0x9,
|
||||||
|
0xd372, 0x8e,
|
||||||
|
0xd547, 0x3,
|
||||||
|
0xd800, 0x1600,
|
||||||
|
0xee3c, 0x6,
|
||||||
|
0xee43, 0x4,
|
||||||
|
0xee9c, 0x5,
|
||||||
|
0xeebc, 0x34,
|
||||||
|
0xeef2, 0x10e,
|
||||||
|
0xf02c, 0x4,
|
||||||
|
0xf094, 0xc,
|
||||||
|
0xf0e0, 0x20,
|
||||||
|
0xf10b, 0x5,
|
||||||
|
0xf16c, 0x4,
|
||||||
|
0xf19b, 0x4b,
|
||||||
|
0xf203, 0xd,
|
||||||
|
0xf23b, 0x5,
|
||||||
|
0xf249, 0x7,
|
||||||
|
0xf252, 0xae,
|
||||||
|
0xf321, 0xf,
|
||||||
|
0xf37d, 0x3,
|
||||||
|
0xf394, 0xc,
|
||||||
|
0xf3cb, 0x15,
|
||||||
|
0xf3f1, 0xf,
|
||||||
|
0xf4fd, 0x3,
|
||||||
|
0xf544, 0xc,
|
||||||
|
0xf568, 0x93,
|
||||||
|
0xf641, 0x4,
|
||||||
|
0xf650, 0x30,
|
||||||
|
0xf6c6, 0x3a,
|
||||||
|
0xf774, 0x88c,
|
||||||
|
];
|
|
@ -980,15 +980,19 @@ impl<'a> Formatter<'a> {
|
||||||
return self.buf.write_str(s);
|
return self.buf.write_str(s);
|
||||||
}
|
}
|
||||||
// The `precision` field can be interpreted as a `max-width` for the
|
// The `precision` field can be interpreted as a `max-width` for the
|
||||||
// string being formatted
|
// string being formatted.
|
||||||
if let Some(max) = self.precision {
|
let s = if let Some(max) = self.precision {
|
||||||
// If there's a maximum width and our string is longer than
|
// If our string is longer that the precision, then we must have
|
||||||
// that, then we must always have truncation. This is the only
|
// truncation. However other flags like `fill`, `width` and `align`
|
||||||
// case where the maximum length will matter.
|
// must act as always.
|
||||||
if let Some((i, _)) = s.char_indices().skip(max).next() {
|
if let Some((i, _)) = s.char_indices().skip(max).next() {
|
||||||
return self.buf.write_str(&s[..i])
|
&s[..i]
|
||||||
|
} else {
|
||||||
|
&s
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
&s
|
||||||
|
};
|
||||||
// The `width` field is more of a `min-width` parameter at this point.
|
// The `width` field is more of a `min-width` parameter at this point.
|
||||||
match self.width {
|
match self.width {
|
||||||
// If we're under the maximum length, and there's no minimum length
|
// If we're under the maximum length, and there's no minimum length
|
||||||
|
@ -1379,7 +1383,7 @@ impl Debug for str {
|
||||||
f.write_char('"')?;
|
f.write_char('"')?;
|
||||||
let mut from = 0;
|
let mut from = 0;
|
||||||
for (i, c) in self.char_indices() {
|
for (i, c) in self.char_indices() {
|
||||||
let esc = c.escape_default();
|
let esc = c.escape_debug();
|
||||||
// If char needs escaping, flush backlog so far and write, else skip
|
// If char needs escaping, flush backlog so far and write, else skip
|
||||||
if esc.len() != 1 {
|
if esc.len() != 1 {
|
||||||
f.write_str(&self[from..i])?;
|
f.write_str(&self[from..i])?;
|
||||||
|
@ -1405,7 +1409,7 @@ impl Display for str {
|
||||||
impl Debug for char {
|
impl Debug for char {
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||||
f.write_char('\'')?;
|
f.write_char('\'')?;
|
||||||
for c in self.escape_default() {
|
for c in self.escape_debug() {
|
||||||
f.write_char(c)?
|
f.write_char(c)?
|
||||||
}
|
}
|
||||||
f.write_char('\'')
|
f.write_char('\'')
|
||||||
|
|
|
@ -234,6 +234,16 @@ pub trait BuildHasher {
|
||||||
type Hasher: Hasher;
|
type Hasher: Hasher;
|
||||||
|
|
||||||
/// Creates a new hasher.
|
/// Creates a new hasher.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::collections::hash_map::RandomState;
|
||||||
|
/// use std::hash::BuildHasher;
|
||||||
|
///
|
||||||
|
/// let s = RandomState::new();
|
||||||
|
/// let new_s = s.build_hasher();
|
||||||
|
/// ```
|
||||||
#[stable(since = "1.7.0", feature = "build_hasher")]
|
#[stable(since = "1.7.0", feature = "build_hasher")]
|
||||||
fn build_hasher(&self) -> Self::Hasher;
|
fn build_hasher(&self) -> Self::Hasher;
|
||||||
}
|
}
|
||||||
|
|
|
@ -277,17 +277,200 @@ extern "rust-intrinsic" {
|
||||||
/// Moves a value out of scope without running drop glue.
|
/// Moves a value out of scope without running drop glue.
|
||||||
pub fn forget<T>(_: T) -> ();
|
pub fn forget<T>(_: T) -> ();
|
||||||
|
|
||||||
/// Unsafely transforms a value of one type into a value of another type.
|
/// Reinterprets the bits of a value of one type as another type; both types
|
||||||
|
/// must have the same size. Neither the original, nor the result, may be an
|
||||||
|
/// [invalid value] (../../nomicon/meet-safe-and-unsafe.html).
|
||||||
///
|
///
|
||||||
/// Both types must have the same size.
|
/// `transmute` is semantically equivalent to a bitwise move of one type
|
||||||
|
/// into another. It copies the bits from the destination type into the
|
||||||
|
/// source type, then forgets the original. It's equivalent to C's `memcpy`
|
||||||
|
/// under the hood, just like `transmute_copy`.
|
||||||
|
///
|
||||||
|
/// `transmute` is incredibly unsafe. There are a vast number of ways to
|
||||||
|
/// cause undefined behavior with this function. `transmute` should be
|
||||||
|
/// the absolute last resort.
|
||||||
|
///
|
||||||
|
/// The [nomicon](../../nomicon/transmutes.html) has additional
|
||||||
|
/// documentation.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// There are a few things that `transmute` is really useful for.
|
||||||
/// use std::mem;
|
|
||||||
///
|
///
|
||||||
/// let array: &[u8] = unsafe { mem::transmute("Rust") };
|
/// Getting the bitpattern of a floating point type (or, more generally,
|
||||||
/// assert_eq!(array, [82, 117, 115, 116]);
|
/// type punning, when `T` and `U` aren't pointers):
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let bitpattern = unsafe {
|
||||||
|
/// std::mem::transmute::<f32, u32>(1.0)
|
||||||
|
/// };
|
||||||
|
/// assert_eq!(bitpattern, 0x3F800000);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Turning a pointer into a function pointer:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// fn foo() -> i32 {
|
||||||
|
/// 0
|
||||||
|
/// }
|
||||||
|
/// let pointer = foo as *const ();
|
||||||
|
/// let function = unsafe {
|
||||||
|
/// std::mem::transmute::<*const (), fn() -> i32>(pointer)
|
||||||
|
/// };
|
||||||
|
/// assert_eq!(function(), 0);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Extending a lifetime, or shortening an invariant lifetime; this is
|
||||||
|
/// advanced, very unsafe rust:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// struct R<'a>(&'a i32);
|
||||||
|
/// unsafe fn extend_lifetime<'b>(r: R<'b>) -> R<'static> {
|
||||||
|
/// std::mem::transmute::<R<'b>, R<'static>>(r)
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// unsafe fn shorten_invariant_lifetime<'b, 'c>(r: &'b mut R<'static>)
|
||||||
|
/// -> &'b mut R<'c> {
|
||||||
|
/// std::mem::transmute::<&'b mut R<'static>, &'b mut R<'c>>(r)
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Alternatives
|
||||||
|
///
|
||||||
|
/// However, many uses of `transmute` can be achieved through other means.
|
||||||
|
/// `transmute` can transform any type into any other, with just the caveat
|
||||||
|
/// that they're the same size, and often interesting results occur. Below
|
||||||
|
/// are common applications of `transmute` which can be replaced with safe
|
||||||
|
/// applications of `as`:
|
||||||
|
///
|
||||||
|
/// Turning a pointer into a `usize`:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let ptr = &0;
|
||||||
|
/// let ptr_num_transmute = unsafe {
|
||||||
|
/// std::mem::transmute::<&i32, usize>(ptr)
|
||||||
|
/// };
|
||||||
|
/// // Use an `as` cast instead
|
||||||
|
/// let ptr_num_cast = ptr as *const i32 as usize;
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Turning a `*mut T` into an `&mut T`:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let ptr: *mut i32 = &mut 0;
|
||||||
|
/// let ref_transmuted = unsafe {
|
||||||
|
/// std::mem::transmute::<*mut i32, &mut i32>(ptr)
|
||||||
|
/// };
|
||||||
|
/// // Use a reborrow instead
|
||||||
|
/// let ref_casted = unsafe { &mut *ptr };
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Turning an `&mut T` into an `&mut U`:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let ptr = &mut 0;
|
||||||
|
/// let val_transmuted = unsafe {
|
||||||
|
/// std::mem::transmute::<&mut i32, &mut u32>(ptr)
|
||||||
|
/// };
|
||||||
|
/// // Now, put together `as` and reborrowing - note the chaining of `as`
|
||||||
|
/// // `as` is not transitive
|
||||||
|
/// let val_casts = unsafe { &mut *(ptr as *mut i32 as *mut u32) };
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Turning an `&str` into an `&[u8]`:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// // this is not a good way to do this.
|
||||||
|
/// let slice = unsafe { std::mem::transmute::<&str, &[u8]>("Rust") };
|
||||||
|
/// assert_eq!(slice, &[82, 117, 115, 116]);
|
||||||
|
/// // You could use `str::as_bytes`
|
||||||
|
/// let slice = "Rust".as_bytes();
|
||||||
|
/// assert_eq!(slice, &[82, 117, 115, 116]);
|
||||||
|
/// // Or, just use a byte string, if you have control over the string
|
||||||
|
/// // literal
|
||||||
|
/// assert_eq!(b"Rust", &[82, 117, 115, 116]);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Turning a `Vec<&T>` into a `Vec<Option<&T>>`:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let store = [0, 1, 2, 3];
|
||||||
|
/// let mut v_orig = store.iter().collect::<Vec<&i32>>();
|
||||||
|
/// // Using transmute: this is Undefined Behavior, and a bad idea.
|
||||||
|
/// // However, it is no-copy.
|
||||||
|
/// let v_transmuted = unsafe {
|
||||||
|
/// std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(
|
||||||
|
/// v_orig.clone())
|
||||||
|
/// };
|
||||||
|
/// // This is the suggested, safe way.
|
||||||
|
/// // It does copy the entire Vector, though, into a new array.
|
||||||
|
/// let v_collected = v_orig.clone()
|
||||||
|
/// .into_iter()
|
||||||
|
/// .map(|r| Some(r))
|
||||||
|
/// .collect::<Vec<Option<&i32>>>();
|
||||||
|
/// // The no-copy, unsafe way, still using transmute, but not UB.
|
||||||
|
/// // This is equivalent to the original, but safer, and reuses the
|
||||||
|
/// // same Vec internals. Therefore the new inner type must have the
|
||||||
|
/// // exact same size, and the same or lesser alignment, as the old
|
||||||
|
/// // type. The same caveats exist for this method as transmute, for
|
||||||
|
/// // the original inner type (`&i32`) to the converted inner type
|
||||||
|
/// // (`Option<&i32>`), so read the nomicon pages linked above.
|
||||||
|
/// let v_from_raw = unsafe {
|
||||||
|
/// Vec::from_raw_parts(v_orig.as_mut_ptr(),
|
||||||
|
/// v_orig.len(),
|
||||||
|
/// v_orig.capacity())
|
||||||
|
/// };
|
||||||
|
/// std::mem::forget(v_orig);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Implementing `split_at_mut`:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use std::{slice, mem};
|
||||||
|
/// // There are multiple ways to do this; and there are multiple problems
|
||||||
|
/// // with the following, transmute, way.
|
||||||
|
/// fn split_at_mut_transmute<T>(slice: &mut [T], mid: usize)
|
||||||
|
/// -> (&mut [T], &mut [T]) {
|
||||||
|
/// let len = slice.len();
|
||||||
|
/// assert!(mid <= len);
|
||||||
|
/// unsafe {
|
||||||
|
/// let slice2 = mem::transmute::<&mut [T], &mut [T]>(slice);
|
||||||
|
/// // first: transmute is not typesafe; all it checks is that T and
|
||||||
|
/// // U are of the same size. Second, right here, you have two
|
||||||
|
/// // mutable references pointing to the same memory.
|
||||||
|
/// (&mut slice[0..mid], &mut slice2[mid..len])
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// // This gets rid of the typesafety problems; `&mut *` will *only* give
|
||||||
|
/// // you an `&mut T` from an `&mut T` or `*mut T`.
|
||||||
|
/// fn split_at_mut_casts<T>(slice: &mut [T], mid: usize)
|
||||||
|
/// -> (&mut [T], &mut [T]) {
|
||||||
|
/// let len = slice.len();
|
||||||
|
/// assert!(mid <= len);
|
||||||
|
/// unsafe {
|
||||||
|
/// let slice2 = &mut *(slice as *mut [T]);
|
||||||
|
/// // however, you still have two mutable references pointing to
|
||||||
|
/// // the same memory.
|
||||||
|
/// (&mut slice[0..mid], &mut slice2[mid..len])
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// // This is how the standard library does it. This is the best method, if
|
||||||
|
/// // you need to do something like this
|
||||||
|
/// fn split_at_stdlib<T>(slice: &mut [T], mid: usize)
|
||||||
|
/// -> (&mut [T], &mut [T]) {
|
||||||
|
/// let len = slice.len();
|
||||||
|
/// assert!(mid <= len);
|
||||||
|
/// unsafe {
|
||||||
|
/// let ptr = slice.as_mut_ptr();
|
||||||
|
/// // This now has three mutable references pointing at the same
|
||||||
|
/// // memory. `slice`, the rvalue ret.0, and the rvalue ret.1.
|
||||||
|
/// // `slice` is never used after `let ptr = ...`, and so one can
|
||||||
|
/// // treat it as "dead", and therefore, you only have two real
|
||||||
|
/// // mutable slices.
|
||||||
|
/// (slice::from_raw_parts_mut(ptr, mid),
|
||||||
|
/// slice::from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn transmute<T, U>(e: T) -> U;
|
pub fn transmute<T, U>(e: T) -> U;
|
||||||
|
|
|
@ -386,10 +386,11 @@ pub trait Extend<A> {
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub trait DoubleEndedIterator: Iterator {
|
pub trait DoubleEndedIterator: Iterator {
|
||||||
/// An iterator able to yield elements from both ends.
|
/// Removes and returns an element from the end of the iterator.
|
||||||
///
|
///
|
||||||
/// As this is the only method for this trait, the [trait-level] docs
|
/// Returns `None` when there are no more elements.
|
||||||
/// contain more details.
|
///
|
||||||
|
/// The [trait-level] docs contain more details.
|
||||||
///
|
///
|
||||||
/// [trait-level]: trait.DoubleEndedIterator.html
|
/// [trait-level]: trait.DoubleEndedIterator.html
|
||||||
///
|
///
|
||||||
|
|
|
@ -103,17 +103,17 @@ mod int_macros;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod uint_macros;
|
mod uint_macros;
|
||||||
|
|
||||||
#[path = "num/isize.rs"] pub mod isize;
|
#[path = "num/isize.rs"] pub mod isize;
|
||||||
#[path = "num/i8.rs"] pub mod i8;
|
#[path = "num/i8.rs"] pub mod i8;
|
||||||
#[path = "num/i16.rs"] pub mod i16;
|
#[path = "num/i16.rs"] pub mod i16;
|
||||||
#[path = "num/i32.rs"] pub mod i32;
|
#[path = "num/i32.rs"] pub mod i32;
|
||||||
#[path = "num/i64.rs"] pub mod i64;
|
#[path = "num/i64.rs"] pub mod i64;
|
||||||
|
|
||||||
#[path = "num/usize.rs"] pub mod usize;
|
#[path = "num/usize.rs"] pub mod usize;
|
||||||
#[path = "num/u8.rs"] pub mod u8;
|
#[path = "num/u8.rs"] pub mod u8;
|
||||||
#[path = "num/u16.rs"] pub mod u16;
|
#[path = "num/u16.rs"] pub mod u16;
|
||||||
#[path = "num/u32.rs"] pub mod u32;
|
#[path = "num/u32.rs"] pub mod u32;
|
||||||
#[path = "num/u64.rs"] pub mod u64;
|
#[path = "num/u64.rs"] pub mod u64;
|
||||||
|
|
||||||
#[path = "num/f32.rs"] pub mod f32;
|
#[path = "num/f32.rs"] pub mod f32;
|
||||||
#[path = "num/f64.rs"] pub mod f64;
|
#[path = "num/f64.rs"] pub mod f64;
|
||||||
|
@ -161,5 +161,6 @@ pub mod hash;
|
||||||
pub mod fmt;
|
pub mod fmt;
|
||||||
|
|
||||||
// note: does not need to be public
|
// note: does not need to be public
|
||||||
|
mod char_private;
|
||||||
mod iter_private;
|
mod iter_private;
|
||||||
mod tuple;
|
mod tuple;
|
||||||
|
|
|
@ -35,6 +35,17 @@ macro_rules! panic {
|
||||||
/// This will invoke the `panic!` macro if the provided expression cannot be
|
/// This will invoke the `panic!` macro if the provided expression cannot be
|
||||||
/// evaluated to `true` at runtime.
|
/// evaluated to `true` at runtime.
|
||||||
///
|
///
|
||||||
|
/// Assertions are always checked in both debug and release builds, and cannot
|
||||||
|
/// be disabled. See `debug_assert!` for assertions that are not enabled in
|
||||||
|
/// release builds by default.
|
||||||
|
///
|
||||||
|
/// Unsafe code relies on `assert!` to enforce run-time invariants that, if
|
||||||
|
/// violated could lead to unsafety.
|
||||||
|
///
|
||||||
|
/// Other use-cases of `assert!` include
|
||||||
|
/// [testing](https://doc.rust-lang.org/book/testing.html) and enforcing
|
||||||
|
/// run-time invariants in safe code (whose violation cannot result in unsafety).
|
||||||
|
///
|
||||||
/// This macro has a second version, where a custom panic message can be provided.
|
/// This macro has a second version, where a custom panic message can be provided.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
@ -123,6 +134,13 @@ macro_rules! assert_eq {
|
||||||
/// expensive to be present in a release build but may be helpful during
|
/// expensive to be present in a release build but may be helpful during
|
||||||
/// development.
|
/// development.
|
||||||
///
|
///
|
||||||
|
/// An unchecked assertion allows a program in an inconsistent state to keep
|
||||||
|
/// running, which might have unexpected consequences but does not introduce
|
||||||
|
/// unsafety as long as this only happens in safe code. The performance cost
|
||||||
|
/// of assertions, is however, not measurable in general. Replacing `assert!`
|
||||||
|
/// with `debug_assert!` is thus only encouraged after thorough profiling, and
|
||||||
|
/// more importantly, only in safe code!
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -144,6 +144,12 @@ pub trait Unsize<T: ?Sized> {
|
||||||
/// Generalizing the latter case, any type implementing `Drop` can't be `Copy`, because it's
|
/// Generalizing the latter case, any type implementing `Drop` can't be `Copy`, because it's
|
||||||
/// managing some resource besides its own `size_of::<T>()` bytes.
|
/// managing some resource besides its own `size_of::<T>()` bytes.
|
||||||
///
|
///
|
||||||
|
/// ## What if I derive `Copy` on a type that can't?
|
||||||
|
///
|
||||||
|
/// If you try to derive `Copy` on a struct or enum, you will get a compile-time error.
|
||||||
|
/// Specifically, with structs you'll get [E0204](https://doc.rust-lang.org/error-index.html#E0204)
|
||||||
|
/// and with enums you'll get [E0205](https://doc.rust-lang.org/error-index.html#E0205).
|
||||||
|
///
|
||||||
/// ## When should my type be `Copy`?
|
/// ## When should my type be `Copy`?
|
||||||
///
|
///
|
||||||
/// Generally speaking, if your type _can_ implement `Copy`, it should. There's one important thing
|
/// Generally speaking, if your type _can_ implement `Copy`, it should. There's one important thing
|
||||||
|
|
|
@ -611,6 +611,31 @@ macro_rules! int_impl {
|
||||||
if b {None} else {Some(a)}
|
if b {None} else {Some(a)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checked absolute value. Computes `self.abs()`, returning `None` if
|
||||||
|
/// `self == MIN`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # #![feature(no_panic_abs)]
|
||||||
|
///
|
||||||
|
/// use std::i32;
|
||||||
|
///
|
||||||
|
/// assert_eq!((-5i32).checked_abs(), Some(5));
|
||||||
|
/// assert_eq!(i32::MIN.checked_abs(), None);
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "no_panic_abs", issue = "35057")]
|
||||||
|
#[inline]
|
||||||
|
pub fn checked_abs(self) -> Option<Self> {
|
||||||
|
if self.is_negative() {
|
||||||
|
self.checked_neg()
|
||||||
|
} else {
|
||||||
|
Some(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Saturating integer addition. Computes `self + other`, saturating at
|
/// Saturating integer addition. Computes `self + other`, saturating at
|
||||||
/// the numeric bounds instead of overflowing.
|
/// the numeric bounds instead of overflowing.
|
||||||
///
|
///
|
||||||
|
@ -863,6 +888,36 @@ macro_rules! int_impl {
|
||||||
self.overflowing_shr(rhs).0
|
self.overflowing_shr(rhs).0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Wrapping (modular) absolute value. Computes `self.abs()`,
|
||||||
|
/// wrapping around at the boundary of the type.
|
||||||
|
///
|
||||||
|
/// The only case where such wrapping can occur is when one takes
|
||||||
|
/// the absolute value of the negative minimal value for the type
|
||||||
|
/// this is a positive value that is too large to represent in the
|
||||||
|
/// type. In such a case, this function returns `MIN` itself.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # #![feature(no_panic_abs)]
|
||||||
|
///
|
||||||
|
/// assert_eq!(100i8.wrapping_abs(), 100);
|
||||||
|
/// assert_eq!((-100i8).wrapping_abs(), 100);
|
||||||
|
/// assert_eq!((-128i8).wrapping_abs(), -128);
|
||||||
|
/// assert_eq!((-128i8).wrapping_abs() as u8, 128);
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "no_panic_abs", issue = "35057")]
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn wrapping_abs(self) -> Self {
|
||||||
|
if self.is_negative() {
|
||||||
|
self.wrapping_neg()
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Calculates `self` + `rhs`
|
/// Calculates `self` + `rhs`
|
||||||
///
|
///
|
||||||
/// Returns a tuple of the addition along with a boolean indicating
|
/// Returns a tuple of the addition along with a boolean indicating
|
||||||
|
@ -1071,6 +1126,35 @@ macro_rules! int_impl {
|
||||||
(self >> (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
|
(self >> (rhs & ($BITS - 1)), (rhs > ($BITS - 1)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Computes the absolute value of `self`.
|
||||||
|
///
|
||||||
|
/// Returns a tuple of the absolute version of self along with a
|
||||||
|
/// boolean indicating whether an overflow happened. If self is the
|
||||||
|
/// minimum value (e.g. i32::MIN for values of type i32), then the
|
||||||
|
/// minimum value will be returned again and true will be returned for
|
||||||
|
/// an overflow happening.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Basic usage:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # #![feature(no_panic_abs)]
|
||||||
|
///
|
||||||
|
/// assert_eq!(10i8.overflowing_abs(), (10,false));
|
||||||
|
/// assert_eq!((-10i8).overflowing_abs(), (10,false));
|
||||||
|
/// assert_eq!((-128i8).overflowing_abs(), (-128,true));
|
||||||
|
/// ```
|
||||||
|
#[unstable(feature = "no_panic_abs", issue = "35057")]
|
||||||
|
#[inline]
|
||||||
|
pub fn overflowing_abs(self) -> (Self, bool) {
|
||||||
|
if self.is_negative() {
|
||||||
|
self.overflowing_neg()
|
||||||
|
} else {
|
||||||
|
(self, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Raises self to the power of `exp`, using exponentiation by squaring.
|
/// Raises self to the power of `exp`, using exponentiation by squaring.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
|
|
@ -142,6 +142,7 @@
|
||||||
use self::Option::*;
|
use self::Option::*;
|
||||||
|
|
||||||
use clone::Clone;
|
use clone::Clone;
|
||||||
|
use convert::From;
|
||||||
use default::Default;
|
use default::Default;
|
||||||
use iter::ExactSizeIterator;
|
use iter::ExactSizeIterator;
|
||||||
use iter::{Iterator, DoubleEndedIterator, FromIterator, IntoIterator};
|
use iter::{Iterator, DoubleEndedIterator, FromIterator, IntoIterator};
|
||||||
|
@ -754,6 +755,13 @@ impl<'a, T> IntoIterator for &'a mut Option<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(since = "1.12.0", feature = "option_from")]
|
||||||
|
impl<T> From<T> for Option<T> {
|
||||||
|
fn from(val: T) -> Option<T> {
|
||||||
|
Some(val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
// The Option Iterators
|
// The Option Iterators
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -902,6 +902,8 @@ macro_rules! make_mut_slice {
|
||||||
|
|
||||||
/// Immutable slice iterator
|
/// Immutable slice iterator
|
||||||
///
|
///
|
||||||
|
/// This struct is created by the [`iter`] method on [slices].
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Basic usage:
|
/// Basic usage:
|
||||||
|
@ -915,6 +917,9 @@ macro_rules! make_mut_slice {
|
||||||
/// println!("{}", element);
|
/// println!("{}", element);
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// [`iter`]: ../../std/primitive.slice.html#method.iter
|
||||||
|
/// [slices]: ../../std/primitive.slice.html
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct Iter<'a, T: 'a> {
|
pub struct Iter<'a, T: 'a> {
|
||||||
ptr: *const T,
|
ptr: *const T,
|
||||||
|
@ -993,6 +998,8 @@ impl<'a, T> Clone for Iter<'a, T> {
|
||||||
|
|
||||||
/// Mutable slice iterator.
|
/// Mutable slice iterator.
|
||||||
///
|
///
|
||||||
|
/// This struct is created by the [`iter_mut`] method on [slices].
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Basic usage:
|
/// Basic usage:
|
||||||
|
@ -1010,6 +1017,9 @@ impl<'a, T> Clone for Iter<'a, T> {
|
||||||
/// // We now have "[2, 3, 4]":
|
/// // We now have "[2, 3, 4]":
|
||||||
/// println!("{:?}", slice);
|
/// println!("{:?}", slice);
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// [`iter_mut`]: ../../std/primitive.slice.html#method.iter_mut
|
||||||
|
/// [slices]: ../../std/primitive.slice.html
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct IterMut<'a, T: 'a> {
|
pub struct IterMut<'a, T: 'a> {
|
||||||
ptr: *mut T,
|
ptr: *mut T,
|
||||||
|
|
|
@ -459,6 +459,19 @@ impl<'a> Chars<'a> {
|
||||||
///
|
///
|
||||||
/// This has the same lifetime as the original slice, and so the
|
/// This has the same lifetime as the original slice, and so the
|
||||||
/// iterator can continue to be used while this exists.
|
/// iterator can continue to be used while this exists.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// let mut chars = "abc".chars();
|
||||||
|
///
|
||||||
|
/// assert_eq!(chars.as_str(), "abc");
|
||||||
|
/// chars.next();
|
||||||
|
/// assert_eq!(chars.as_str(), "bc");
|
||||||
|
/// chars.next();
|
||||||
|
/// chars.next();
|
||||||
|
/// assert_eq!(chars.as_str(), "");
|
||||||
|
/// ```
|
||||||
#[stable(feature = "iter_to_slice", since = "1.4.0")]
|
#[stable(feature = "iter_to_slice", since = "1.4.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_str(&self) -> &'a str {
|
pub fn as_str(&self) -> &'a str {
|
||||||
|
|
|
@ -74,6 +74,8 @@
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
#![stable(feature = "rust1", since = "1.0.0")]
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#![cfg_attr(not(target_has_atomic = "8"), allow(dead_code))]
|
||||||
|
#![cfg_attr(not(target_has_atomic = "8"), allow(unused_imports))]
|
||||||
|
|
||||||
use self::Ordering::*;
|
use self::Ordering::*;
|
||||||
|
|
||||||
|
|
|
@ -123,6 +123,49 @@ fn test_is_digit() {
|
||||||
assert!(!'Q'.is_numeric());
|
assert!(!'Q'.is_numeric());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_escape_debug() {
|
||||||
|
fn string(c: char) -> String {
|
||||||
|
c.escape_debug().collect()
|
||||||
|
}
|
||||||
|
let s = string('\n');
|
||||||
|
assert_eq!(s, "\\n");
|
||||||
|
let s = string('\r');
|
||||||
|
assert_eq!(s, "\\r");
|
||||||
|
let s = string('\'');
|
||||||
|
assert_eq!(s, "\\'");
|
||||||
|
let s = string('"');
|
||||||
|
assert_eq!(s, "\\\"");
|
||||||
|
let s = string(' ');
|
||||||
|
assert_eq!(s, " ");
|
||||||
|
let s = string('a');
|
||||||
|
assert_eq!(s, "a");
|
||||||
|
let s = string('~');
|
||||||
|
assert_eq!(s, "~");
|
||||||
|
let s = string('é');
|
||||||
|
assert_eq!(s, "é");
|
||||||
|
let s = string('\x00');
|
||||||
|
assert_eq!(s, "\\u{0}");
|
||||||
|
let s = string('\x1f');
|
||||||
|
assert_eq!(s, "\\u{1f}");
|
||||||
|
let s = string('\x7f');
|
||||||
|
assert_eq!(s, "\\u{7f}");
|
||||||
|
let s = string('\u{80}');
|
||||||
|
assert_eq!(s, "\\u{80}");
|
||||||
|
let s = string('\u{ff}');
|
||||||
|
assert_eq!(s, "\u{ff}");
|
||||||
|
let s = string('\u{11b}');
|
||||||
|
assert_eq!(s, "\u{11b}");
|
||||||
|
let s = string('\u{1d4b6}');
|
||||||
|
assert_eq!(s, "\u{1d4b6}");
|
||||||
|
let s = string('\u{200b}'); // zero width space
|
||||||
|
assert_eq!(s, "\\u{200b}");
|
||||||
|
let s = string('\u{e000}'); // private use 1
|
||||||
|
assert_eq!(s, "\\u{e000}");
|
||||||
|
let s = string('\u{100000}'); // private use 2
|
||||||
|
assert_eq!(s, "\\u{100000}");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_escape_default() {
|
fn test_escape_default() {
|
||||||
fn string(c: char) -> String {
|
fn string(c: char) -> String {
|
||||||
|
@ -142,18 +185,28 @@ fn test_escape_default() {
|
||||||
assert_eq!(s, "a");
|
assert_eq!(s, "a");
|
||||||
let s = string('~');
|
let s = string('~');
|
||||||
assert_eq!(s, "~");
|
assert_eq!(s, "~");
|
||||||
|
let s = string('é');
|
||||||
|
assert_eq!(s, "\\u{e9}");
|
||||||
let s = string('\x00');
|
let s = string('\x00');
|
||||||
assert_eq!(s, "\\u{0}");
|
assert_eq!(s, "\\u{0}");
|
||||||
let s = string('\x1f');
|
let s = string('\x1f');
|
||||||
assert_eq!(s, "\\u{1f}");
|
assert_eq!(s, "\\u{1f}");
|
||||||
let s = string('\x7f');
|
let s = string('\x7f');
|
||||||
assert_eq!(s, "\\u{7f}");
|
assert_eq!(s, "\\u{7f}");
|
||||||
|
let s = string('\u{80}');
|
||||||
|
assert_eq!(s, "\\u{80}");
|
||||||
let s = string('\u{ff}');
|
let s = string('\u{ff}');
|
||||||
assert_eq!(s, "\\u{ff}");
|
assert_eq!(s, "\\u{ff}");
|
||||||
let s = string('\u{11b}');
|
let s = string('\u{11b}');
|
||||||
assert_eq!(s, "\\u{11b}");
|
assert_eq!(s, "\\u{11b}");
|
||||||
let s = string('\u{1d4b6}');
|
let s = string('\u{1d4b6}');
|
||||||
assert_eq!(s, "\\u{1d4b6}");
|
assert_eq!(s, "\\u{1d4b6}");
|
||||||
|
let s = string('\u{200b}'); // zero width space
|
||||||
|
assert_eq!(s, "\\u{200b}");
|
||||||
|
let s = string('\u{e000}'); // private use 1
|
||||||
|
assert_eq!(s, "\\u{e000}");
|
||||||
|
let s = string('\u{100000}'); // private use 2
|
||||||
|
assert_eq!(s, "\\u{100000}");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#![feature(borrow_state)]
|
#![feature(borrow_state)]
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
#![feature(cell_extras)]
|
#![feature(cell_extras)]
|
||||||
|
#![feature(char_escape_debug)]
|
||||||
#![feature(const_fn)]
|
#![feature(const_fn)]
|
||||||
#![feature(core_private_bignum)]
|
#![feature(core_private_bignum)]
|
||||||
#![feature(core_private_diy_float)]
|
#![feature(core_private_diy_float)]
|
||||||
|
@ -29,10 +30,9 @@
|
||||||
#![feature(slice_patterns)]
|
#![feature(slice_patterns)]
|
||||||
#![feature(step_by)]
|
#![feature(step_by)]
|
||||||
#![feature(test)]
|
#![feature(test)]
|
||||||
#![feature(unboxed_closures)]
|
#![feature(try_from)]
|
||||||
#![feature(unicode)]
|
#![feature(unicode)]
|
||||||
#![feature(unique)]
|
#![feature(unique)]
|
||||||
#![feature(try_from)]
|
|
||||||
|
|
||||||
extern crate core;
|
extern crate core;
|
||||||
extern crate test;
|
extern crate test;
|
||||||
|
|
|
@ -11,4 +11,4 @@ crate-type = ["dylib"]
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
build_helper = { path = "../build_helper" }
|
build_helper = { path = "../build_helper" }
|
||||||
gcc = "0.3"
|
gcc = "0.3.27"
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit b0d62534d48b711c8978d1bbe8cca0558ae7b1cb
|
Subproject commit 5066b7dcab7e700844b0e2ba71b8af9dc627a59b
|
|
@ -45,16 +45,25 @@ pub const DW_EH_PE_aligned: u8 = 0x50;
|
||||||
pub const DW_EH_PE_indirect: u8 = 0x80;
|
pub const DW_EH_PE_indirect: u8 = 0x80;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct EHContext {
|
pub struct EHContext<'a> {
|
||||||
pub ip: usize, // Current instruction pointer
|
pub ip: usize, // Current instruction pointer
|
||||||
pub func_start: usize, // Address of the current function
|
pub func_start: usize, // Address of the current function
|
||||||
pub text_start: usize, // Address of the code section
|
pub get_text_start: &'a Fn() -> usize, // Get address of the code section
|
||||||
pub data_start: usize, // Address of the data section
|
pub get_data_start: &'a Fn() -> usize, // Get address of the data section
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn find_landing_pad(lsda: *const u8, context: &EHContext) -> Option<usize> {
|
pub enum EHAction {
|
||||||
|
None,
|
||||||
|
Cleanup(usize),
|
||||||
|
Catch(usize),
|
||||||
|
Terminate,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const USING_SJLJ_EXCEPTIONS: bool = cfg!(all(target_os = "ios", target_arch = "arm"));
|
||||||
|
|
||||||
|
pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) -> EHAction {
|
||||||
if lsda.is_null() {
|
if lsda.is_null() {
|
||||||
return None;
|
return EHAction::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let func_start = context.func_start;
|
let func_start = context.func_start;
|
||||||
|
@ -77,32 +86,61 @@ pub unsafe fn find_landing_pad(lsda: *const u8, context: &EHContext) -> Option<u
|
||||||
let call_site_encoding = reader.read::<u8>();
|
let call_site_encoding = reader.read::<u8>();
|
||||||
let call_site_table_length = reader.read_uleb128();
|
let call_site_table_length = reader.read_uleb128();
|
||||||
let action_table = reader.ptr.offset(call_site_table_length as isize);
|
let action_table = reader.ptr.offset(call_site_table_length as isize);
|
||||||
// Return addresses point 1 byte past the call instruction, which could
|
let ip = context.ip;
|
||||||
// be in the next IP range.
|
|
||||||
let ip = context.ip - 1;
|
|
||||||
|
|
||||||
while reader.ptr < action_table {
|
if !USING_SJLJ_EXCEPTIONS {
|
||||||
let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding);
|
while reader.ptr < action_table {
|
||||||
let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding);
|
let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding);
|
||||||
let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding);
|
let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding);
|
||||||
let cs_action = reader.read_uleb128();
|
let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding);
|
||||||
// Callsite table is sorted by cs_start, so if we've passed the ip, we
|
let cs_action = reader.read_uleb128();
|
||||||
// may stop searching.
|
// Callsite table is sorted by cs_start, so if we've passed the ip, we
|
||||||
if ip < func_start + cs_start {
|
// may stop searching.
|
||||||
break;
|
if ip < func_start + cs_start {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ip < func_start + cs_start + cs_len {
|
||||||
|
if cs_lpad == 0 {
|
||||||
|
return EHAction::None;
|
||||||
|
} else {
|
||||||
|
let lpad = lpad_base + cs_lpad;
|
||||||
|
return interpret_cs_action(cs_action, lpad);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ip < func_start + cs_start + cs_len {
|
// Ip is not present in the table. This should not happen... but it does: issue #35011.
|
||||||
if cs_lpad != 0 {
|
// So rather than returning EHAction::Terminate, we do this.
|
||||||
return Some(lpad_base + cs_lpad);
|
EHAction::None
|
||||||
} else {
|
} else {
|
||||||
return None;
|
// SjLj version:
|
||||||
|
// The "IP" is an index into the call-site table, with two exceptions:
|
||||||
|
// -1 means 'no-action', and 0 means 'terminate'.
|
||||||
|
match ip as isize {
|
||||||
|
-1 => return EHAction::None,
|
||||||
|
0 => return EHAction::Terminate,
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
let mut idx = ip;
|
||||||
|
loop {
|
||||||
|
let cs_lpad = reader.read_uleb128();
|
||||||
|
let cs_action = reader.read_uleb128();
|
||||||
|
idx -= 1;
|
||||||
|
if idx == 0 {
|
||||||
|
// Can never have null landing pad for sjlj -- that would have
|
||||||
|
// been indicated by a -1 call site index.
|
||||||
|
let lpad = (cs_lpad + 1) as usize;
|
||||||
|
return interpret_cs_action(cs_action, lpad);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// IP range not found: gcc's C++ personality calls terminate() here,
|
}
|
||||||
// however the rest of the languages treat this the same as cs_lpad == 0.
|
|
||||||
// We follow this suit.
|
fn interpret_cs_action(cs_action: u64, lpad: usize) -> EHAction {
|
||||||
None
|
if cs_action == 0 {
|
||||||
|
EHAction::Cleanup(lpad)
|
||||||
|
} else {
|
||||||
|
EHAction::Catch(lpad)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -140,18 +178,16 @@ unsafe fn read_encoded_pointer(reader: &mut DwarfReader,
|
||||||
DW_EH_PE_absptr => 0,
|
DW_EH_PE_absptr => 0,
|
||||||
// relative to address of the encoded value, despite the name
|
// relative to address of the encoded value, despite the name
|
||||||
DW_EH_PE_pcrel => reader.ptr as usize,
|
DW_EH_PE_pcrel => reader.ptr as usize,
|
||||||
DW_EH_PE_textrel => {
|
|
||||||
assert!(context.text_start != 0);
|
|
||||||
context.text_start
|
|
||||||
}
|
|
||||||
DW_EH_PE_datarel => {
|
|
||||||
assert!(context.data_start != 0);
|
|
||||||
context.data_start
|
|
||||||
}
|
|
||||||
DW_EH_PE_funcrel => {
|
DW_EH_PE_funcrel => {
|
||||||
assert!(context.func_start != 0);
|
assert!(context.func_start != 0);
|
||||||
context.func_start
|
context.func_start
|
||||||
}
|
}
|
||||||
|
DW_EH_PE_textrel => {
|
||||||
|
(*context.get_text_start)()
|
||||||
|
}
|
||||||
|
DW_EH_PE_datarel => {
|
||||||
|
(*context.get_data_start)()
|
||||||
|
}
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,8 @@ use core::ptr;
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
|
|
||||||
use unwind as uw;
|
use unwind as uw;
|
||||||
|
use libc::{c_int, uintptr_t};
|
||||||
|
use dwarf::eh::{self, EHContext, EHAction};
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct Exception {
|
struct Exception {
|
||||||
|
@ -106,160 +108,184 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class {
|
||||||
0x4d4f5a_00_52555354
|
0x4d4f5a_00_52555354
|
||||||
}
|
}
|
||||||
|
|
||||||
// We could implement our personality routine in Rust, however exception
|
|
||||||
// info decoding is tedious. More importantly, personality routines have to
|
|
||||||
// handle various platform quirks, which are not fun to maintain. For this
|
|
||||||
// reason, we attempt to reuse personality routine of the C language:
|
|
||||||
// __gcc_personality_v0.
|
|
||||||
//
|
|
||||||
// Since C does not support exception catching, __gcc_personality_v0 simply
|
|
||||||
// always returns _URC_CONTINUE_UNWIND in search phase, and always returns
|
|
||||||
// _URC_INSTALL_CONTEXT (i.e. "invoke cleanup code") in cleanup phase.
|
|
||||||
//
|
|
||||||
// This is pretty close to Rust's exception handling approach, except that Rust
|
|
||||||
// does have a single "catch-all" handler at the bottom of each thread's stack.
|
|
||||||
// So we have two versions of the personality routine:
|
|
||||||
// - rust_eh_personality, used by all cleanup landing pads, which never catches,
|
|
||||||
// so the behavior of __gcc_personality_v0 is perfectly adequate there, and
|
|
||||||
// - rust_eh_personality_catch, used only by rust_try(), which always catches.
|
|
||||||
//
|
|
||||||
// See also: rustc_trans::trans::intrinsic::trans_gnu_try
|
|
||||||
|
|
||||||
#[cfg(all(not(target_arch = "arm"),
|
// Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister()
|
||||||
not(all(windows, target_arch = "x86_64"))))]
|
// and TargetLowering::getExceptionSelectorRegister() for each architecture,
|
||||||
pub mod eabi {
|
// then mapped to DWARF register numbers via register definition tables
|
||||||
use unwind as uw;
|
// (typically <arch>RegisterInfo.td, search for "DwarfRegNum").
|
||||||
use libc::c_int;
|
// See also http://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register.
|
||||||
|
|
||||||
extern "C" {
|
#[cfg(target_arch = "x86")]
|
||||||
fn __gcc_personality_v0(version: c_int,
|
const UNWIND_DATA_REG: (i32, i32) = (0, 2); // EAX, EDX
|
||||||
actions: uw::_Unwind_Action,
|
|
||||||
exception_class: uw::_Unwind_Exception_Class,
|
#[cfg(target_arch = "x86_64")]
|
||||||
ue_header: *mut uw::_Unwind_Exception,
|
const UNWIND_DATA_REG: (i32, i32) = (0, 1); // RAX, RDX
|
||||||
context: *mut uw::_Unwind_Context)
|
|
||||||
-> uw::_Unwind_Reason_Code;
|
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
|
||||||
|
const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 / X0, X1
|
||||||
|
|
||||||
|
#[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
|
||||||
|
const UNWIND_DATA_REG: (i32, i32) = (4, 5); // A0, A1
|
||||||
|
|
||||||
|
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
|
||||||
|
const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 / X3, X4
|
||||||
|
|
||||||
|
// The following code is based on GCC's C and C++ personality routines. For reference, see:
|
||||||
|
// https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
|
||||||
|
// https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
|
||||||
|
|
||||||
|
// The personality routine for most of our targets, except ARM, which has a slightly different ABI
|
||||||
|
// (however, iOS goes here as it uses SjLj unwinding). Also, the 64-bit Windows implementation
|
||||||
|
// lives in seh64_gnu.rs
|
||||||
|
#[cfg(all(any(target_os = "ios", not(target_arch = "arm"))))]
|
||||||
|
#[lang = "eh_personality"]
|
||||||
|
#[no_mangle]
|
||||||
|
#[allow(unused)]
|
||||||
|
unsafe extern "C" fn rust_eh_personality(version: c_int,
|
||||||
|
actions: uw::_Unwind_Action,
|
||||||
|
exception_class: uw::_Unwind_Exception_Class,
|
||||||
|
exception_object: *mut uw::_Unwind_Exception,
|
||||||
|
context: *mut uw::_Unwind_Context)
|
||||||
|
-> uw::_Unwind_Reason_Code {
|
||||||
|
if version != 1 {
|
||||||
|
return uw::_URC_FATAL_PHASE1_ERROR;
|
||||||
}
|
}
|
||||||
|
let eh_action = find_eh_action(context);
|
||||||
#[lang = "eh_personality"]
|
if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 {
|
||||||
#[no_mangle]
|
match eh_action {
|
||||||
extern "C" fn rust_eh_personality(version: c_int,
|
EHAction::None | EHAction::Cleanup(_) => return uw::_URC_CONTINUE_UNWIND,
|
||||||
actions: uw::_Unwind_Action,
|
EHAction::Catch(_) => return uw::_URC_HANDLER_FOUND,
|
||||||
exception_class: uw::_Unwind_Exception_Class,
|
EHAction::Terminate => return uw::_URC_FATAL_PHASE1_ERROR,
|
||||||
ue_header: *mut uw::_Unwind_Exception,
|
}
|
||||||
context: *mut uw::_Unwind_Context)
|
} else {
|
||||||
-> uw::_Unwind_Reason_Code {
|
match eh_action {
|
||||||
unsafe { __gcc_personality_v0(version, actions, exception_class, ue_header, context) }
|
EHAction::None => return uw::_URC_CONTINUE_UNWIND,
|
||||||
}
|
EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => {
|
||||||
|
uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0, exception_object as uintptr_t);
|
||||||
#[lang = "eh_personality_catch"]
|
uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
|
||||||
#[no_mangle]
|
uw::_Unwind_SetIP(context, lpad);
|
||||||
pub extern "C" fn rust_eh_personality_catch(version: c_int,
|
return uw::_URC_INSTALL_CONTEXT;
|
||||||
actions: uw::_Unwind_Action,
|
}
|
||||||
exception_class: uw::_Unwind_Exception_Class,
|
EHAction::Terminate => return uw::_URC_FATAL_PHASE2_ERROR,
|
||||||
ue_header: *mut uw::_Unwind_Exception,
|
|
||||||
context: *mut uw::_Unwind_Context)
|
|
||||||
-> uw::_Unwind_Reason_Code {
|
|
||||||
|
|
||||||
if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 {
|
|
||||||
// search phase
|
|
||||||
uw::_URC_HANDLER_FOUND // catch!
|
|
||||||
} else {
|
|
||||||
// cleanup phase
|
|
||||||
unsafe { __gcc_personality_v0(version, actions, exception_class, ue_header, context) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// iOS on armv7 is using SjLj exceptions and therefore requires to use
|
// ARM EHABI personality routine.
|
||||||
// a specialized personality routine: __gcc_personality_sj0
|
// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
|
||||||
|
|
||||||
#[cfg(all(target_os = "ios", target_arch = "arm"))]
|
|
||||||
pub mod eabi {
|
|
||||||
use unwind as uw;
|
|
||||||
use libc::c_int;
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
fn __gcc_personality_sj0(version: c_int,
|
|
||||||
actions: uw::_Unwind_Action,
|
|
||||||
exception_class: uw::_Unwind_Exception_Class,
|
|
||||||
ue_header: *mut uw::_Unwind_Exception,
|
|
||||||
context: *mut uw::_Unwind_Context)
|
|
||||||
-> uw::_Unwind_Reason_Code;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[lang = "eh_personality"]
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn rust_eh_personality(version: c_int,
|
|
||||||
actions: uw::_Unwind_Action,
|
|
||||||
exception_class: uw::_Unwind_Exception_Class,
|
|
||||||
ue_header: *mut uw::_Unwind_Exception,
|
|
||||||
context: *mut uw::_Unwind_Context)
|
|
||||||
-> uw::_Unwind_Reason_Code {
|
|
||||||
unsafe { __gcc_personality_sj0(version, actions, exception_class, ue_header, context) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[lang = "eh_personality_catch"]
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn rust_eh_personality_catch(version: c_int,
|
|
||||||
actions: uw::_Unwind_Action,
|
|
||||||
exception_class: uw::_Unwind_Exception_Class,
|
|
||||||
ue_header: *mut uw::_Unwind_Exception,
|
|
||||||
context: *mut uw::_Unwind_Context)
|
|
||||||
-> uw::_Unwind_Reason_Code {
|
|
||||||
if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 {
|
|
||||||
// search phase
|
|
||||||
uw::_URC_HANDLER_FOUND // catch!
|
|
||||||
} else {
|
|
||||||
// cleanup phase
|
|
||||||
unsafe { __gcc_personality_sj0(version, actions, exception_class, ue_header, context) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ARM EHABI uses a slightly different personality routine signature,
|
|
||||||
// but otherwise works the same.
|
|
||||||
#[cfg(all(target_arch = "arm", not(target_os = "ios")))]
|
#[cfg(all(target_arch = "arm", not(target_os = "ios")))]
|
||||||
pub mod eabi {
|
#[lang = "eh_personality"]
|
||||||
use unwind as uw;
|
#[no_mangle]
|
||||||
use libc::c_int;
|
unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State,
|
||||||
|
exception_object: *mut uw::_Unwind_Exception,
|
||||||
extern "C" {
|
context: *mut uw::_Unwind_Context)
|
||||||
fn __gcc_personality_v0(state: uw::_Unwind_State,
|
-> uw::_Unwind_Reason_Code {
|
||||||
ue_header: *mut uw::_Unwind_Exception,
|
let state = state as c_int;
|
||||||
context: *mut uw::_Unwind_Context)
|
let action = state & uw::_US_ACTION_MASK as c_int;
|
||||||
-> uw::_Unwind_Reason_Code;
|
let search_phase = if action == uw::_US_VIRTUAL_UNWIND_FRAME as c_int {
|
||||||
}
|
|
||||||
|
|
||||||
#[lang = "eh_personality"]
|
|
||||||
#[no_mangle]
|
|
||||||
extern "C" fn rust_eh_personality(state: uw::_Unwind_State,
|
|
||||||
ue_header: *mut uw::_Unwind_Exception,
|
|
||||||
context: *mut uw::_Unwind_Context)
|
|
||||||
-> uw::_Unwind_Reason_Code {
|
|
||||||
unsafe { __gcc_personality_v0(state, ue_header, context) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[lang = "eh_personality_catch"]
|
|
||||||
#[no_mangle]
|
|
||||||
pub extern "C" fn rust_eh_personality_catch(state: uw::_Unwind_State,
|
|
||||||
ue_header: *mut uw::_Unwind_Exception,
|
|
||||||
context: *mut uw::_Unwind_Context)
|
|
||||||
-> uw::_Unwind_Reason_Code {
|
|
||||||
// Backtraces on ARM will call the personality routine with
|
// Backtraces on ARM will call the personality routine with
|
||||||
// state == _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND. In those cases
|
// state == _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND. In those cases
|
||||||
// we want to continue unwinding the stack, otherwise all our backtraces
|
// we want to continue unwinding the stack, otherwise all our backtraces
|
||||||
// would end at __rust_try.
|
// would end at __rust_try
|
||||||
if (state as c_int & uw::_US_ACTION_MASK as c_int) ==
|
if state & uw::_US_FORCE_UNWIND as c_int != 0 {
|
||||||
uw::_US_VIRTUAL_UNWIND_FRAME as c_int &&
|
return continue_unwind(exception_object, context)
|
||||||
(state as c_int & uw::_US_FORCE_UNWIND as c_int) == 0 {
|
}
|
||||||
// search phase
|
true
|
||||||
uw::_URC_HANDLER_FOUND // catch!
|
} else if action == uw::_US_UNWIND_FRAME_STARTING as c_int {
|
||||||
} else {
|
false
|
||||||
// cleanup phase
|
} else if action == uw::_US_UNWIND_FRAME_RESUME as c_int {
|
||||||
unsafe { __gcc_personality_v0(state, ue_header, context) }
|
return continue_unwind(exception_object, context);
|
||||||
|
} else {
|
||||||
|
return uw::_URC_FAILURE;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The DWARF unwinder assumes that _Unwind_Context holds things like the function
|
||||||
|
// and LSDA pointers, however ARM EHABI places them into the exception object.
|
||||||
|
// To preserve signatures of functions like _Unwind_GetLanguageSpecificData(), which
|
||||||
|
// take only the context pointer, GCC personality routines stash a pointer to exception_object
|
||||||
|
// in the context, using location reserved for ARM's "scratch register" (r12).
|
||||||
|
uw::_Unwind_SetGR(context, uw::UNWIND_POINTER_REG, exception_object as uw::_Unwind_Ptr);
|
||||||
|
// ...A more principled approach would be to provide the full definition of ARM's
|
||||||
|
// _Unwind_Context in our libunwind bindings and fetch the required data from there directly,
|
||||||
|
// bypassing DWARF compatibility functions.
|
||||||
|
|
||||||
|
let eh_action = find_eh_action(context);
|
||||||
|
if search_phase {
|
||||||
|
match eh_action {
|
||||||
|
EHAction::None |
|
||||||
|
EHAction::Cleanup(_) => return continue_unwind(exception_object, context),
|
||||||
|
EHAction::Catch(_) => return uw::_URC_HANDLER_FOUND,
|
||||||
|
EHAction::Terminate => return uw::_URC_FAILURE,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match eh_action {
|
||||||
|
EHAction::None => return continue_unwind(exception_object, context),
|
||||||
|
EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => {
|
||||||
|
uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0, exception_object as uintptr_t);
|
||||||
|
uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
|
||||||
|
uw::_Unwind_SetIP(context, lpad);
|
||||||
|
return uw::_URC_INSTALL_CONTEXT;
|
||||||
|
}
|
||||||
|
EHAction::Terminate => return uw::_URC_FAILURE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// On ARM EHABI the personality routine is responsible for actually
|
||||||
|
// unwinding a single stack frame before returning (ARM EHABI Sec. 6.1).
|
||||||
|
unsafe fn continue_unwind(exception_object: *mut uw::_Unwind_Exception,
|
||||||
|
context: *mut uw::_Unwind_Context)
|
||||||
|
-> uw::_Unwind_Reason_Code {
|
||||||
|
if __gnu_unwind_frame(exception_object, context) == uw::_URC_NO_REASON {
|
||||||
|
uw::_URC_CONTINUE_UNWIND
|
||||||
|
} else {
|
||||||
|
uw::_URC_FAILURE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// defined in libgcc
|
||||||
|
extern "C" {
|
||||||
|
fn __gnu_unwind_frame(exception_object: *mut uw::_Unwind_Exception,
|
||||||
|
context: *mut uw::_Unwind_Context)
|
||||||
|
-> uw::_Unwind_Reason_Code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn find_eh_action(context: *mut uw::_Unwind_Context) -> EHAction {
|
||||||
|
let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8;
|
||||||
|
let mut ip_before_instr: c_int = 0;
|
||||||
|
let ip = uw::_Unwind_GetIPInfo(context, &mut ip_before_instr);
|
||||||
|
let eh_context = EHContext {
|
||||||
|
// The return address points 1 byte past the call instruction,
|
||||||
|
// which could be in the next IP range in LSDA range table.
|
||||||
|
ip: if ip_before_instr != 0 { ip } else { ip - 1 },
|
||||||
|
func_start: uw::_Unwind_GetRegionStart(context),
|
||||||
|
get_text_start: &|| uw::_Unwind_GetTextRelBase(context),
|
||||||
|
get_data_start: &|| uw::_Unwind_GetDataRelBase(context),
|
||||||
|
};
|
||||||
|
eh::find_eh_action(lsda, &eh_context)
|
||||||
|
}
|
||||||
|
|
||||||
|
// *** Delete after a new snapshot ***
|
||||||
|
#[cfg(all(stage0, any(target_os = "ios", not(target_arch = "arm"))))]
|
||||||
|
#[lang = "eh_personality_catch"]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn rust_eh_personality_catch(version: c_int,
|
||||||
|
actions: uw::_Unwind_Action,
|
||||||
|
exception_class: uw::_Unwind_Exception_Class,
|
||||||
|
ue_header: *mut uw::_Unwind_Exception,
|
||||||
|
context: *mut uw::_Unwind_Context)
|
||||||
|
-> uw::_Unwind_Reason_Code {
|
||||||
|
rust_eh_personality(version, actions, exception_class, ue_header, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
// *** Delete after a new snapshot ***
|
||||||
|
#[cfg(all(stage0, target_arch = "arm", not(target_os = "ios")))]
|
||||||
|
#[lang = "eh_personality_catch"]
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn rust_eh_personality_catch(state: uw::_Unwind_State,
|
||||||
|
ue_header: *mut uw::_Unwind_Exception,
|
||||||
|
context: *mut uw::_Unwind_Context)
|
||||||
|
-> uw::_Unwind_Reason_Code {
|
||||||
|
rust_eh_personality(state, ue_header, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
// See docs in the `unwind` module.
|
// See docs in the `unwind` module.
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue