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.
|
||||
git:
|
||||
submodules: false
|
||||
depth: 1
|
||||
|
||||
before_install:
|
||||
- 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 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 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 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)"
|
||||
|
@ -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_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"
|
||||
|
||||
|
@ -1020,6 +1020,12 @@ then
|
|||
err "bad LLVM version: $LLVM_VERSION, need >=3.7"
|
||||
;;
|
||||
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
|
||||
|
||||
# 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 ]
|
||||
then
|
||||
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_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_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,
|
||||
|
|
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_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_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_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,
|
||||
|
|
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_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_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_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,
|
||||
|
|
|
@ -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_DSYM_GLOB_asmjs-unknown-emscripten=lib$(1)-*.dylib.dSYM
|
||||
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_LINK_FLAGS_asmjs-unknown-emscripten := -shared -fPIC -ldl -pthread -lrt -g -m32
|
||||
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_STATIC_LIB_NAME_i386-apple-ios=lib$(1).a
|
||||
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_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,
|
||||
|
|
|
@ -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_DSYM_GLOB_i586-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
|
||||
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_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=
|
||||
|
|
|
@ -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_DSYM_GLOB_i686-apple-darwin=lib$(1)-*.dylib.dSYM
|
||||
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_LINK_FLAGS_i686-apple-darwin := -dynamiclib -pthread -framework CoreServices -m32
|
||||
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_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_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_LINK_FLAGS_i686-pc-windows-gnu := -shared -g -m32
|
||||
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_DSYM_GLOB_i686-unknown-freebsd=$(1)-*.dylib.dSYM
|
||||
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_DEF_FLAG_i686-unknown-freebsd := -Wl,--export-dynamic,--dynamic-list=
|
||||
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_DSYM_GLOB_i686-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
|
||||
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_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=
|
||||
|
|
|
@ -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_LIB_GLOB_i686-unknown-linux-musl=lib$(1)-*.so
|
||||
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_LINK_FLAGS_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_DSYM_GLOB_powerpc-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
|
||||
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_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=
|
||||
|
|
|
@ -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_JEMALLOC_CFLAGS_powerpc64-unknown-linux-gnu := -m64
|
||||
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_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=
|
||||
|
|
|
@ -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_DSYM_GLOB_powerpc64le-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
|
||||
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_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=
|
||||
|
|
|
@ -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_DSYM_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib.dSYM
|
||||
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_LINK_FLAGS_x86_64-apple-darwin := -dynamiclib -pthread -framework CoreServices -m64
|
||||
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_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_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,
|
||||
|
|
|
@ -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_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_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_LINK_FLAGS_x86_64-pc-windows-gnu := -shared -g -m64
|
||||
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_LIB_GLOB_x86_64-rumprun-netbsd=lib$(1)-*.so
|
||||
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_LINK_FLAGS_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_DSYM_GLOB_x86_64-sun-solaris=$(1)-*.dylib.dSYM
|
||||
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_DEF_FLAG_x86_64-sun-solaris := -Wl,--export-dynamic,--dynamic-list=
|
||||
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_DSYM_GLOB_x86_64-unknown-bitrig=$(1)-*.dylib.dSYM
|
||||
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_DEF_FLAG_x86_64-unknown-bitrig := -Wl,--export-dynamic,--dynamic-list=
|
||||
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_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_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_DEF_FLAG_x86_64-unknown-dragonfly := -Wl,--export-dynamic,--dynamic-list=
|
||||
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_DSYM_GLOB_x86_64-unknown-freebsd=$(1)-*.dylib.dSYM
|
||||
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_DEF_FLAG_x86_64-unknown-freebsd := -Wl,--export-dynamic,--dynamic-list=
|
||||
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_DSYM_GLOB_x86_64-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
|
||||
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_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=
|
||||
|
|
|
@ -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_STATIC_LIB_NAME_x86_64-unknown-linux-musl=lib$(1).a
|
||||
CFG_LIB_GLOB_x86_64-unknown-linux-musl=lib$(1)-*.so
|
||||
CFG_JEMALLOC_CFLAGS_x86_64-unknown-linux-musl := -m64
|
||||
CFG_GCCISH_CFLAGS_x86_64-unknown-linux-musl := -Wall -Werror -g -fPIC -m64
|
||||
CFG_JEMALLOC_CFLAGS_x86_64-unknown-linux-musl := -m64 -Wa,-mrelax-relocations=no
|
||||
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_LINK_FLAGS_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_DSYM_GLOB_x86_64-unknown-netbsd=$(1)-*.dylib.dSYM
|
||||
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_DEF_FLAG_x86_64-unknown-netbsd := -Wl,--export-dynamic,--dynamic-list=
|
||||
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_DSYM_GLOB_x86_64-unknown-openbsd=$(1)-*.dylib.dSYM
|
||||
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_DEF_FLAG_x86_64-unknown-openbsd := -Wl,--export-dynamic,--dynamic-list=
|
||||
CFG_LLC_FLAGS_x86_64-unknown-openbsd :=
|
||||
|
|
|
@ -162,9 +162,10 @@ ifdef CFG_ENABLE_DEBUGINFO
|
|||
CFG_RUSTC_FLAGS += -g
|
||||
endif
|
||||
|
||||
ifdef CFG_ENABLE_ORBIT
|
||||
$(info cfg: launching MIR (CFG_ENABLE_ORBIT))
|
||||
CFG_RUSTC_FLAGS += -Z orbit
|
||||
ifdef CFG_DISABLE_ORBIT
|
||||
$(info cfg: HOLD HOLD HOLD (CFG_DISABLE_ORBIT))
|
||||
RUSTFLAGS_STAGE1 += -Z orbit=off
|
||||
RUSTFLAGS_STAGE2 += -Z orbit=off
|
||||
endif
|
||||
|
||||
ifdef SAVE_TEMPS
|
||||
|
|
|
@ -221,12 +221,19 @@ define CFG_MAKE_TOOLCHAIN
|
|||
LLVM_MC_RELOCATION_MODEL="default"
|
||||
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
|
||||
# .cfi pseudo-ops on mac
|
||||
CFG_ASSEMBLE_$(1)=$$(CPP_$(1)) -E $$(2) | \
|
||||
$$(LLVM_MC_$$(CFG_BUILD)) \
|
||||
-assemble \
|
||||
-relocation-model=$$(LLVM_MC_RELOCATION_MODEL) \
|
||||
$$(LLVM_MC_RELOC_FLAG) \
|
||||
-filetype=obj \
|
||||
-triple=$(1) \
|
||||
-o=$$(1)
|
||||
|
|
480
mk/rt.mk
480
mk/rt.mk
|
@ -223,147 +223,377 @@ endif
|
|||
# compiler-rt
|
||||
################################################################################
|
||||
|
||||
ifdef CFG_ENABLE_FAST_MAKE
|
||||
COMPRT_DEPS := $(S)/.gitmodules
|
||||
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.
|
||||
# Everything below is a manual compilation of compiler-rt, disregarding its
|
||||
# build system. See comments in `src/bootstrap/native.rs` for more information.
|
||||
|
||||
COMPRT_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt)
|
||||
COMPRT_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(COMPRT_NAME_$(1))
|
||||
COMPRT_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/compiler-rt
|
||||
|
||||
COMPRT_ARCH_$(1) := $$(word 1,$$(subst -, ,$(1)))
|
||||
|
||||
# All this is to figure out the path to the compiler-rt bin
|
||||
ifeq ($$(findstring windows-msvc,$(1)),windows-msvc)
|
||||
COMPRT_DIR_$(1) := windows/Release
|
||||
COMPRT_LIB_NAME_$(1) := clang_rt.builtins-$$(patsubst i%86,i386,$$(COMPRT_ARCH_$(1)))
|
||||
endif
|
||||
|
||||
ifeq ($$(findstring windows-gnu,$(1)),windows-gnu)
|
||||
COMPRT_DIR_$(1) := windows
|
||||
COMPRT_LIB_NAME_$(1) := clang_rt.builtins-$$(COMPRT_ARCH_$(1))
|
||||
endif
|
||||
|
||||
ifeq ($$(findstring darwin,$(1)),darwin)
|
||||
COMPRT_DIR_$(1) := builtins
|
||||
COMPRT_LIB_NAME_$(1) := clang_rt.builtins_$$(patsubst i686,i386,$$(COMPRT_ARCH_$(1)))_osx
|
||||
endif
|
||||
|
||||
ifeq ($$(findstring ios,$(1)),ios)
|
||||
COMPRT_DIR_$(1) := builtins
|
||||
COMPRT_ARCH_$(1) := $$(patsubst armv7s,armv7em,$$(COMPRT_ARCH_$(1)))
|
||||
COMPRT_LIB_NAME_$(1) := clang_rt.hard_pic_$$(COMPRT_ARCH_$(1))_macho_embedded
|
||||
ifeq ($$(COMPRT_ARCH_$(1)),aarch64)
|
||||
COMPRT_LIB_NAME_$(1) := clang_rt.builtins_arm64_ios
|
||||
endif
|
||||
COMPRT_DEFINES_$(1) := -DCOMPILER_RT_ENABLE_IOS=ON
|
||||
endif
|
||||
|
||||
ifndef COMPRT_DIR_$(1)
|
||||
# NB: FreeBSD and NetBSD output to "linux"...
|
||||
COMPRT_DIR_$(1) := linux
|
||||
COMPRT_ARCH_$(1) := $$(patsubst i586,i386,$$(COMPRT_ARCH_$(1)))
|
||||
|
||||
ifeq ($$(findstring android,$(1)),android)
|
||||
ifeq ($$(findstring arm,$$(COMPRT_ARCH_$(1))),arm)
|
||||
COMPRT_ARCH_$(1) := armhf
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($$(findstring eabihf,$(1)),eabihf)
|
||||
ifeq ($$(findstring armv7,$(1)),)
|
||||
COMPRT_LIB_NAME_$(1) := clang_rt.builtins-armhf
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef COMPRT_LIB_NAME_$(1)
|
||||
COMPRT_LIB_NAME_$(1) := clang_rt.builtins-$$(COMPRT_ARCH_$(1))
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($$(findstring windows-gnu,$(1)),windows-gnu)
|
||||
COMPRT_LIB_FILE_$(1) := lib$$(COMPRT_LIB_NAME_$(1)).a
|
||||
endif
|
||||
|
||||
ifeq ($$(findstring android,$(1)),android)
|
||||
ifeq ($$(findstring arm,$(1)),arm)
|
||||
COMPRT_LIB_FILE_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),$$(COMPRT_LIB_NAME_$(1))-android)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef COMPRT_LIB_FILE_$(1)
|
||||
COMPRT_LIB_FILE_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),$$(COMPRT_LIB_NAME_$(1)))
|
||||
endif
|
||||
|
||||
COMPRT_OUTPUT_$(1) := $$(COMPRT_BUILD_DIR_$(1))/lib/$$(COMPRT_DIR_$(1))/$$(COMPRT_LIB_FILE_$(1))
|
||||
|
||||
ifeq ($$(findstring windows-msvc,$(1)),windows-msvc)
|
||||
COMPRT_BUILD_ARGS_$(1) := //v:m //nologo
|
||||
COMPRT_BUILD_TARGET_$(1) := lib/builtins/builtins
|
||||
COMPRT_BUILD_CC_$(1) :=
|
||||
else
|
||||
COMPRT_BUILD_ARGS_$(1) :=
|
||||
ifndef COMPRT_BUILD_TARGET_$(1)
|
||||
COMPRT_BUILD_TARGET_$(1) := $$(COMPRT_LIB_NAME_$(1))
|
||||
endif
|
||||
COMPRT_BUILD_CC_$(1) := -DCMAKE_C_COMPILER=$$(call FIND_COMPILER,$$(CC_$(1))) \
|
||||
-DCMAKE_CXX_COMPILER=$$(call FIND_COMPILER,$$(CXX_$(1)))
|
||||
# GENERIC_SOURCES in CMakeLists.txt
|
||||
COMPRT_OBJS_$(1) := \
|
||||
absvdi2.o \
|
||||
absvsi2.o \
|
||||
adddf3.o \
|
||||
addsf3.o \
|
||||
addvdi3.o \
|
||||
addvsi3.o \
|
||||
apple_versioning.o \
|
||||
ashldi3.o \
|
||||
ashrdi3.o \
|
||||
clear_cache.o \
|
||||
clzdi2.o \
|
||||
clzsi2.o \
|
||||
cmpdi2.o \
|
||||
comparedf2.o \
|
||||
comparesf2.o \
|
||||
ctzdi2.o \
|
||||
ctzsi2.o \
|
||||
divdc3.o \
|
||||
divdf3.o \
|
||||
divdi3.o \
|
||||
divmoddi4.o \
|
||||
divmodsi4.o \
|
||||
divsc3.o \
|
||||
divsf3.o \
|
||||
divsi3.o \
|
||||
divxc3.o \
|
||||
extendsfdf2.o \
|
||||
extendhfsf2.o \
|
||||
ffsdi2.o \
|
||||
fixdfdi.o \
|
||||
fixdfsi.o \
|
||||
fixsfdi.o \
|
||||
fixsfsi.o \
|
||||
fixunsdfdi.o \
|
||||
fixunsdfsi.o \
|
||||
fixunssfdi.o \
|
||||
fixunssfsi.o \
|
||||
fixunsxfdi.o \
|
||||
fixunsxfsi.o \
|
||||
fixxfdi.o \
|
||||
floatdidf.o \
|
||||
floatdisf.o \
|
||||
floatdixf.o \
|
||||
floatsidf.o \
|
||||
floatsisf.o \
|
||||
floatundidf.o \
|
||||
floatundisf.o \
|
||||
floatundixf.o \
|
||||
floatunsidf.o \
|
||||
floatunsisf.o \
|
||||
int_util.o \
|
||||
lshrdi3.o \
|
||||
moddi3.o \
|
||||
modsi3.o \
|
||||
muldc3.o \
|
||||
muldf3.o \
|
||||
muldi3.o \
|
||||
mulodi4.o \
|
||||
mulosi4.o \
|
||||
muloti4.o \
|
||||
mulsc3.o \
|
||||
mulsf3.o \
|
||||
mulvdi3.o \
|
||||
mulvsi3.o \
|
||||
mulxc3.o \
|
||||
negdf2.o \
|
||||
negdi2.o \
|
||||
negsf2.o \
|
||||
negvdi2.o \
|
||||
negvsi2.o \
|
||||
paritydi2.o \
|
||||
paritysi2.o \
|
||||
popcountdi2.o \
|
||||
popcountsi2.o \
|
||||
powidf2.o \
|
||||
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)),)
|
||||
COMPRT_BUILD_CC_$(1) := $$(COMPRT_BUILD_CC_$(1)) \
|
||||
-DCMAKE_C_FLAGS="$$(CFG_GCCISH_CFLAGS_$(1)) -Wno-error"
|
||||
COMPRT_OBJS_$(1) += \
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
ifeq ($$(findstring emscripten,$(1)),emscripten)
|
||||
|
||||
# FIXME: emscripten doesn't use compiler-rt and can't build it without
|
||||
# further hacks
|
||||
$$(COMPRT_LIB_$(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)
|
||||
COMPRT_OBJS_$(1) :=
|
||||
endif
|
||||
$$(Q)cp "$$(COMPRT_OUTPUT_$(1))" $$@
|
||||
|
||||
endif
|
||||
$$(COMPRT_LIB_$(1)): $$(COMPRT_OBJS_$(1))
|
||||
@$$(call E, link: $$@)
|
||||
$$(Q)$$(call CFG_CREATE_ARCHIVE_$(1),$$@) $$^
|
||||
|
||||
################################################################################
|
||||
# libbacktrace
|
||||
|
|
|
@ -24,7 +24,7 @@ LLVM_EXTRA_INCDIRS_$(1)= $$(call CFG_CC_INCLUDE_$(1),$(S)src/llvm/include) \
|
|||
endif
|
||||
|
||||
RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, \
|
||||
ExecutionEngineWrapper.cpp RustWrapper.cpp PassWrapper.cpp \
|
||||
RustWrapper.cpp PassWrapper.cpp \
|
||||
ArchiveWrapper.cpp)
|
||||
|
||||
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)-doc-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
|
||||
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/,*.stderr)
|
||||
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_VALGRIND_TESTS := $(RPASS_VALGRIND_RS)
|
||||
|
@ -475,6 +477,7 @@ CODEGEN_UNITS_TESTS := $(CODEGEN_UNITS_RS)
|
|||
INCREMENTAL_TESTS := $(INCREMENTAL_RS)
|
||||
RMAKE_TESTS := $(RMAKE_RS)
|
||||
UI_TESTS := $(UI_RS)
|
||||
MIR_OPT_TESTS := $(MIR_OPT_RS)
|
||||
RUSTDOCCK_TESTS := $(RUSTDOCCK_RS)
|
||||
|
||||
CTEST_SRC_BASE_rpass = run-pass
|
||||
|
@ -552,6 +555,11 @@ CTEST_BUILD_BASE_ui = ui
|
|||
CTEST_MODE_ui = ui
|
||||
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_BUILD_BASE_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) \
|
||||
$$(CSREQ$(1)_T_$(3)_H_$(3)) $$(SREQ$(1)_T_$(2)_H_$(3))
|
||||
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) \
|
||||
$$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
|
||||
$(S)src/etc/htmldocck.py
|
||||
|
@ -755,7 +764,7 @@ endef
|
|||
|
||||
CTEST_NAMES = rpass rpass-valgrind rpass-full rfail-full cfail-full rfail cfail pfail \
|
||||
debuginfo-gdb debuginfo-lldb codegen codegen-units rustdocck incremental \
|
||||
rmake ui
|
||||
rmake ui mir-opt
|
||||
|
||||
$(foreach host,$(CFG_HOST), \
|
||||
$(eval $(foreach target,$(CFG_TARGET), \
|
||||
|
@ -964,6 +973,7 @@ TEST_GROUPS = \
|
|||
pretty-rfail-full \
|
||||
pretty-rfail \
|
||||
pretty-pretty \
|
||||
mir-opt \
|
||||
$(NULL)
|
||||
|
||||
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",
|
||||
"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)",
|
||||
"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)",
|
||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.9 (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.10 (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)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -25,7 +25,7 @@ name = "cmake"
|
|||
version = "0.1.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
|
@ -33,12 +33,17 @@ name = "filetime"
|
|||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
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"
|
||||
|
||||
[[package]]
|
||||
|
@ -48,7 +53,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.1"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -57,7 +62,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.9"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -70,7 +75,7 @@ name = "num_cpus"
|
|||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
|
|
|
@ -29,6 +29,6 @@ getopts = "0.2"
|
|||
rustc-serialize = "0.3"
|
||||
winapi = "0.2"
|
||||
kernel32-sys = "0.2"
|
||||
gcc = "0.3.17"
|
||||
gcc = { git = "https://github.com/alexcrichton/gcc-rs" }
|
||||
libc = "0.2"
|
||||
md5 = "0.1"
|
||||
|
|
|
@ -92,8 +92,7 @@ pub fn std_link(build: &Build,
|
|||
}
|
||||
add_to_sysroot(&out_dir, &libdir);
|
||||
|
||||
if target.contains("musl") &&
|
||||
(target.contains("x86_64") || target.contains("i686")) {
|
||||
if target.contains("musl") && !target.contains("mips") {
|
||||
copy_third_party_objects(build, target, &libdir);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,6 +72,7 @@ pub struct Config {
|
|||
// libstd features
|
||||
pub debug_jemalloc: bool,
|
||||
pub use_jemalloc: bool,
|
||||
pub backtrace: bool, // support for RUST_BACKTRACE
|
||||
|
||||
// misc
|
||||
pub channel: String,
|
||||
|
@ -134,6 +135,7 @@ struct Rust {
|
|||
debuginfo: Option<bool>,
|
||||
debug_jemalloc: Option<bool>,
|
||||
use_jemalloc: Option<bool>,
|
||||
backtrace: Option<bool>,
|
||||
default_linker: Option<String>,
|
||||
default_ar: Option<String>,
|
||||
channel: Option<String>,
|
||||
|
@ -158,6 +160,7 @@ impl Config {
|
|||
let mut config = Config::default();
|
||||
config.llvm_optimize = true;
|
||||
config.use_jemalloc = true;
|
||||
config.backtrace = true;
|
||||
config.rust_optimize = true;
|
||||
config.rust_optimize_tests = true;
|
||||
config.submodules = true;
|
||||
|
@ -230,6 +233,7 @@ impl Config {
|
|||
set(&mut config.rust_rpath, rust.rpath);
|
||||
set(&mut config.debug_jemalloc, rust.debug_jemalloc);
|
||||
set(&mut config.use_jemalloc, rust.use_jemalloc);
|
||||
set(&mut config.backtrace, rust.backtrace);
|
||||
set(&mut config.channel, rust.channel.clone());
|
||||
config.rustc_default_linker = rust.default_linker.clone();
|
||||
config.rustc_default_ar = rust.default_ar.clone();
|
||||
|
|
|
@ -99,6 +99,9 @@
|
|||
# Whether or not jemalloc is built with its debug option set
|
||||
#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
|
||||
# is not the linker used to link said compiler.
|
||||
#default-linker = "cc"
|
||||
|
|
|
@ -388,6 +388,10 @@ impl Build {
|
|||
check::compiletest(self, &compiler, target.target,
|
||||
"pretty", "run-pass-valgrind");
|
||||
}
|
||||
CheckMirOpt { compiler } => {
|
||||
check::compiletest(self, &compiler, target.target,
|
||||
"mir-opt", "mir-opt");
|
||||
}
|
||||
CheckCodegen { compiler } => {
|
||||
check::compiletest(self, &compiler, target.target,
|
||||
"codegen", "codegen");
|
||||
|
@ -648,6 +652,9 @@ impl Build {
|
|||
if self.config.use_jemalloc {
|
||||
features.push_str(" jemalloc");
|
||||
}
|
||||
if self.config.backtrace {
|
||||
features.push_str(" backtrace");
|
||||
}
|
||||
return features
|
||||
}
|
||||
|
||||
|
@ -848,6 +855,12 @@ impl Build {
|
|||
base.push("-stdlib=libc++".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
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
/// This uses the CMake build system and an existing LLVM build directory to
|
||||
/// compile the project.
|
||||
/// Note that while compiler-rt has a build system associated with it, we
|
||||
/// 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) {
|
||||
let dst = build.compiler_rt_out(target);
|
||||
let arch = target.split('-').next().unwrap();
|
||||
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));
|
||||
let build_dir = build.compiler_rt_out(target);
|
||||
let output = build_dir.join(staticlib("compiler-rt", target));
|
||||
build.compiler_rt_built.borrow_mut().insert(target.to_string(),
|
||||
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
|
||||
}
|
||||
let _ = fs::remove_dir_all(&dst);
|
||||
t!(fs::create_dir_all(&dst));
|
||||
cfg.build_target(&build_target);
|
||||
cfg.build();
|
||||
cfg.compile("libcompiler-rt.a");
|
||||
}
|
||||
|
||||
/// Compiles the `rust_test_helpers.c` library which we used in various
|
||||
|
|
|
@ -31,6 +31,15 @@ use Build;
|
|||
pub fn check(build: &mut Build) {
|
||||
let mut checked = HashSet::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| {
|
||||
if !checked.insert(cmd.to_owned()) {
|
||||
return
|
||||
|
@ -100,7 +109,7 @@ pub fn check(build: &mut Build) {
|
|||
}
|
||||
|
||||
// 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 {
|
||||
Some(ref root) => {
|
||||
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_incremental, CheckIncremental { compiler: Compiler<'a> }),
|
||||
(check_ui, CheckUi { compiler: Compiler<'a> }),
|
||||
(check_mir_opt, CheckMirOpt { compiler: Compiler<'a> }),
|
||||
(check_debuginfo, CheckDebuginfo { compiler: Compiler<'a> }),
|
||||
(check_rustdoc, CheckRustdoc { compiler: Compiler<'a> }),
|
||||
(check_docs, CheckDocs { compiler: Compiler<'a> }),
|
||||
|
@ -347,9 +348,7 @@ impl<'a> Step<'a> {
|
|||
vec![self.libstd(compiler),
|
||||
self.target(host).rustc(compiler.stage)]
|
||||
}
|
||||
Source::CompilerRt { _dummy } => {
|
||||
vec![self.llvm(()).target(&build.config.build)]
|
||||
}
|
||||
Source::CompilerRt { _dummy } => Vec::new(),
|
||||
Source::Llvm { _dummy } => Vec::new(),
|
||||
Source::TestHelpers { _dummy } => Vec::new(),
|
||||
Source::DebuggerScripts { stage: _ } => Vec::new(),
|
||||
|
@ -452,6 +451,7 @@ impl<'a> Step<'a> {
|
|||
self.check_pretty_rfail_full(compiler),
|
||||
self.check_rpass_valgrind(compiler),
|
||||
self.check_rmake(compiler),
|
||||
self.check_mir_opt(compiler),
|
||||
|
||||
// crates
|
||||
self.check_crate_rustc(compiler),
|
||||
|
@ -479,6 +479,7 @@ impl<'a> Step<'a> {
|
|||
Source::CheckTidy { stage } => {
|
||||
vec![self.tool_tidy(stage)]
|
||||
}
|
||||
Source::CheckMirOpt { compiler} |
|
||||
Source::CheckPrettyRPass { compiler } |
|
||||
Source::CheckPrettyRFail { 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.
|
||||
pub fn up_to_date(src: &Path, dst: &Path) -> bool {
|
||||
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() {
|
||||
dir_up_to_date(src, &threshold)
|
||||
} 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:
|
||||
|
||||
```rust
|
||||
# #![feature(unboxed_closures)]
|
||||
# mod foo {
|
||||
pub trait Fn<Args> : FnMut<Args> {
|
||||
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
|
||||
|
@ -291,9 +292,9 @@ isn’t interesting. The next part is:
|
|||
# some_closure(1) }
|
||||
```
|
||||
|
||||
Because `Fn` is a trait, we can bound our generic with it. In this case, our
|
||||
closure takes a `i32` as an argument and returns an `i32`, and so the generic
|
||||
bound we use is `Fn(i32) -> i32`.
|
||||
Because `Fn` is a trait, we can use it as a bound for our generic type. In
|
||||
this case, our closure takes a `i32` as an argument and returns an `i32`, and
|
||||
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
|
||||
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"
|
||||
|
||||
Certain types are defined to not be NULL. This includes references (`&T`,
|
||||
`&mut T`), boxes (`Box<T>`), and function pointers (`extern "abi" fn()`).
|
||||
When interfacing with C, pointers that might be NULL are often used.
|
||||
As a special case, a generic `enum` that contains exactly two variants, one of
|
||||
which contains no data and the other containing a single field, is eligible
|
||||
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,
|
||||
and the non-data variant is represented as the NULL pointer. So
|
||||
`Option<extern "C" fn(c_int) -> c_int>` is how one represents a nullable
|
||||
function pointer using the C ABI.
|
||||
Certain Rust types are defined to never be `null`. This includes references (`&T`,
|
||||
`&mut T`), boxes (`Box<T>`), and function pointers (`extern "abi" fn()`). When
|
||||
interfacing with C, pointers that might be `null` are often used, which would seem to
|
||||
require some messy `transmute`s and/or unsafe code to handle conversions to/from Rust types.
|
||||
However, the language provides a workaround.
|
||||
|
||||
As a special case, an `enum` is eligible for the "nullable pointer optimization" if it contains
|
||||
exactly two variants, one of which contains no data and the other contains a field of one of the
|
||||
non-nullable types listed above. This means no extra space is required for a discriminant; rather,
|
||||
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
|
||||
|
||||
|
|
|
@ -365,7 +365,7 @@ numbers. A bare number like above is actually shorthand for `^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"`
|
||||
(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.
|
||||
[Cargo’s documentation][cargodoc] contains more details.
|
||||
|
||||
|
|
|
@ -60,6 +60,8 @@ asm!("xor %eax, %eax"
|
|||
: "eax"
|
||||
);
|
||||
# } }
|
||||
# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
Whitespace also doesn't matter:
|
||||
|
@ -70,6 +72,8 @@ Whitespace also doesn't matter:
|
|||
# fn main() { unsafe {
|
||||
asm!("xor %eax, %eax" ::: "eax");
|
||||
# } }
|
||||
# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
## Operands
|
||||
|
@ -129,6 +133,8 @@ stay valid.
|
|||
// Put the value 0x200 in 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
|
||||
|
@ -164,6 +170,8 @@ unsafe {
|
|||
}
|
||||
println!("eax is currently {}", result);
|
||||
# }
|
||||
# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
## 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`
|
||||
sugar for dynamic allocations via `malloc` and `free`:
|
||||
|
||||
```rust
|
||||
```rust,ignore
|
||||
#![feature(lang_items, box_syntax, start, libc)]
|
||||
#![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:
|
||||
|
||||
```rust
|
||||
for (i, j) in (5..10).enumerate() {
|
||||
println!("i = {} and j = {}", i, j);
|
||||
for (index, value) in (5..10).enumerate() {
|
||||
println!("index = {} and value = {}", index, value);
|
||||
}
|
||||
```
|
||||
|
||||
Outputs:
|
||||
|
||||
```text
|
||||
i = 0 and j = 5
|
||||
i = 1 and j = 6
|
||||
i = 2 and j = 7
|
||||
i = 3 and j = 8
|
||||
i = 4 and j = 9
|
||||
index = 0 and value = 5
|
||||
index = 1 and value = 6
|
||||
index = 2 and value = 7
|
||||
index = 3 and value = 8
|
||||
index = 4 and value = 9
|
||||
```
|
||||
|
||||
Don't forget to add the parentheses around the range.
|
||||
|
|
|
@ -94,7 +94,7 @@
|
|||
* `|` (`|…| expr`): closures. See [Closures].
|
||||
* `|=` (`var |= expr`): bitwise or & assignment. Overloadable (`BitOrAssign`).
|
||||
* `||` (`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
|
||||
|
||||
|
@ -231,6 +231,7 @@
|
|||
[Primitive Types (Tuples)]: primitive-types.html#tuples
|
||||
[Raw Pointers]: raw-pointers.html
|
||||
[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 String Literals)]: ../reference.html#raw-string-literals
|
||||
[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
|
||||
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.
|
||||
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
|
||||
|
||||
|
|
|
@ -123,7 +123,6 @@ dispatch with trait objects by casting:
|
|||
# trait Foo { fn method(&self) -> String; }
|
||||
# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
|
||||
# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }
|
||||
|
||||
fn do_something(x: &Foo) {
|
||||
x.method();
|
||||
}
|
||||
|
@ -140,7 +139,6 @@ or by coercing:
|
|||
# trait Foo { fn method(&self) -> String; }
|
||||
# impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
|
||||
# impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }
|
||||
|
||||
fn do_something(x: &Foo) {
|
||||
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.
|
||||
Good to go!
|
||||
|
||||
|
@ -84,4 +84,3 @@ standard library made a utility for itself called `Unique<T>` which:
|
|||
* includes a `PhantomData<T>`
|
||||
* auto-derives Send/Sync as if T was contained
|
||||
* 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.
|
||||
|
||||
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
|
||||
shown here:
|
||||
standard C ABI on the specific platform. Other ABIs may be specified using an
|
||||
`abi` string, as shown here:
|
||||
|
||||
```ignore
|
||||
// Interface to the Windows API
|
||||
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
|
||||
specified the compiler will attempt to link against the native library of the
|
||||
specified name.
|
||||
|
@ -3020,7 +3049,8 @@ as
|
|||
== != < > <= >=
|
||||
&&
|
||||
||
|
||||
= ..
|
||||
.. ...
|
||||
=
|
||||
```
|
||||
|
||||
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 \
|
||||
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
|
||||
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}/${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}rust*${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:]
|
||||
elif lib[0] == '-':
|
||||
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 + "\"")
|
||||
if not llvm_shared and 'LLVM' in lib:
|
||||
f.write(", kind = \"static\"")
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
//!
|
||||
//! 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
|
||||
//! use std::sync::Arc;
|
||||
//! 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
|
||||
/// 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::thread;
|
||||
///
|
||||
|
|
|
@ -16,7 +16,7 @@ libc = { path = "../rustc/libc_shim" }
|
|||
|
||||
[build-dependencies]
|
||||
build_helper = { path = "../build_helper" }
|
||||
gcc = "0.3.17"
|
||||
gcc = "0.3.27"
|
||||
|
||||
[features]
|
||||
debug = []
|
||||
|
|
|
@ -73,7 +73,16 @@ fn main() {
|
|||
.replace("\\", "/"))
|
||||
.current_dir(&build_dir)
|
||||
.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("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.
|
||||
/// 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")]
|
||||
pub enum Entry<'a, K: 'a, V: 'a> {
|
||||
/// A vacant Entry
|
||||
|
@ -326,7 +330,23 @@ pub enum Entry<'a, K: 'a, V: 'a> {
|
|||
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")]
|
||||
pub struct VacantEntry<'a, K: 'a, V: 'a> {
|
||||
key: K,
|
||||
|
@ -337,7 +357,18 @@ pub struct VacantEntry<'a, K: 'a, V: 'a> {
|
|||
_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")]
|
||||
pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
|
||||
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)>,
|
||||
}
|
||||
|
||||
#[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
|
||||
struct MergeIter<K, V, I: Iterator<Item = (K, V)>> {
|
||||
left: Peekable<I>,
|
||||
|
@ -1857,6 +1898,17 @@ impl<K, V> BTreeMap<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
|
||||
/// 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")]
|
||||
pub fn or_insert(self, default: V) -> &'a mut V {
|
||||
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,
|
||||
/// 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")]
|
||||
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
|
||||
match self {
|
||||
|
@ -1876,6 +1941,15 @@ impl<'a, K: Ord, V> Entry<'a, K, V> {
|
|||
}
|
||||
|
||||
/// 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")]
|
||||
pub fn key(&self) -> &K {
|
||||
match *self {
|
||||
|
@ -1888,12 +1962,36 @@ impl<'a, K: Ord, V> Entry<'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
|
||||
/// 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")]
|
||||
pub fn key(&self) -> &K {
|
||||
&self.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")]
|
||||
pub fn into_key(self) -> K {
|
||||
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,
|
||||
/// 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")]
|
||||
pub fn insert(self, value: V) -> &'a mut V {
|
||||
*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> {
|
||||
/// 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")]
|
||||
pub fn key(&self) -> &K {
|
||||
self.handle.reborrow().into_kv().0
|
||||
}
|
||||
|
||||
/// 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")]
|
||||
pub fn remove_pair(self) -> (K, V) {
|
||||
self.remove_kv()
|
||||
}
|
||||
|
||||
/// 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")]
|
||||
pub fn get(&self) -> &V {
|
||||
self.handle.reborrow().into_kv().1
|
||||
}
|
||||
|
||||
/// 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")]
|
||||
pub fn get_mut(&mut self) -> &mut V {
|
||||
self.handle.kv_mut().1
|
||||
}
|
||||
|
||||
/// 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")]
|
||||
pub fn into_mut(self) -> &'a mut V {
|
||||
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,
|
||||
/// 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")]
|
||||
pub fn insert(&mut self, value: V) -> V {
|
||||
mem::replace(self.get_mut(), value)
|
||||
}
|
||||
|
||||
/// 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")]
|
||||
pub fn remove(self) -> V {
|
||||
self.remove_kv().1
|
||||
|
|
|
@ -409,8 +409,8 @@
|
|||
//! ## Precision
|
||||
//!
|
||||
//! 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
|
||||
//! emitted.
|
||||
//! longer than this width, then it is truncated down to this many characters and that truncated
|
||||
//! value is emitted with proper `fill`, `alignment` and `width` if those parameters are set.
|
||||
//!
|
||||
//! 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
|
||||
//! 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);
|
||||
//!
|
||||
//! // 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);
|
||||
//!
|
||||
//! // 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);
|
||||
//!
|
||||
//! // 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)}
|
||||
//! 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)}
|
||||
//! 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)}
|
||||
//! println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01);
|
||||
//! ```
|
||||
//!
|
||||
//! All print the same thing:
|
||||
//!
|
||||
//! ```text
|
||||
//! Hello x is 0.01000
|
||||
//! ```
|
||||
//!
|
||||
//! While these:
|
||||
//!
|
||||
//! ```
|
||||
//! println!("{}, `{name:.*}` has 3 fractional digits", "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:
|
||||
|
@ -477,6 +472,7 @@
|
|||
//! ```text
|
||||
//! Hello, `1234.560` has 3 fractional digits
|
||||
//! Hello, `123` has 3 characters
|
||||
//! Hello, ` 123` has 3 right-aligned characters
|
||||
//! ```
|
||||
//!
|
||||
//! # Escaping
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#![feature(allow_internal_unstable)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![cfg_attr(not(test), feature(char_escape_debug))]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(dropck_parametricity)]
|
||||
#![feature(fmt_internals)]
|
||||
|
@ -48,7 +49,6 @@
|
|||
#![feature(specialization)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(step_by)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(unicode)]
|
||||
#![feature(unique)]
|
||||
#![feature(unsafe_no_drop_flag)]
|
||||
|
|
|
@ -172,6 +172,14 @@ impl<T> Default for LinkedList<T> {
|
|||
|
||||
impl<T> LinkedList<T> {
|
||||
/// Creates an empty `LinkedList`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::LinkedList;
|
||||
///
|
||||
/// let list: LinkedList<u32> = LinkedList::new();
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn new() -> Self {
|
||||
|
@ -195,19 +203,22 @@ impl<T> LinkedList<T> {
|
|||
/// ```
|
||||
/// use std::collections::LinkedList;
|
||||
///
|
||||
/// let mut a = LinkedList::new();
|
||||
/// let mut b = LinkedList::new();
|
||||
/// a.push_back(1);
|
||||
/// a.push_back(2);
|
||||
/// b.push_back(3);
|
||||
/// b.push_back(4);
|
||||
/// let mut list1 = LinkedList::new();
|
||||
/// list1.push_back('a');
|
||||
///
|
||||
/// a.append(&mut b);
|
||||
/// let mut list2 = LinkedList::new();
|
||||
/// list2.push_back('b');
|
||||
/// list2.push_back('c');
|
||||
///
|
||||
/// for e in &a {
|
||||
/// println!("{}", e); // prints 1, then 2, then 3, then 4
|
||||
/// }
|
||||
/// println!("{}", b.len()); // prints 0
|
||||
/// list1.append(&mut list2);
|
||||
///
|
||||
/// let mut iter = list1.iter();
|
||||
/// 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")]
|
||||
pub fn append(&mut self, other: &mut Self) {
|
||||
|
@ -226,6 +237,24 @@ impl<T> LinkedList<T> {
|
|||
}
|
||||
|
||||
/// 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]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn iter(&self) -> Iter<T> {
|
||||
|
@ -238,6 +267,28 @@ impl<T> LinkedList<T> {
|
|||
}
|
||||
|
||||
/// 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]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn iter_mut(&mut self) -> IterMut<T> {
|
||||
|
@ -289,7 +340,6 @@ impl<T> LinkedList<T> {
|
|||
///
|
||||
/// dl.push_back(3);
|
||||
/// assert_eq!(dl.len(), 3);
|
||||
///
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -316,7 +366,6 @@ impl<T> LinkedList<T> {
|
|||
/// dl.clear();
|
||||
/// assert_eq!(dl.len(), 0);
|
||||
/// assert_eq!(dl.front(), None);
|
||||
///
|
||||
/// ```
|
||||
#[inline]
|
||||
#[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
|
||||
/// 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",
|
||||
issue = "32630")]
|
||||
pub fn contains(&self, x: &T) -> bool
|
||||
|
@ -347,7 +413,6 @@ impl<T> LinkedList<T> {
|
|||
///
|
||||
/// dl.push_front(1);
|
||||
/// assert_eq!(dl.front(), Some(&1));
|
||||
///
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -374,7 +439,6 @@ impl<T> LinkedList<T> {
|
|||
/// Some(x) => *x = 5,
|
||||
/// }
|
||||
/// assert_eq!(dl.front(), Some(&5));
|
||||
///
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -395,7 +459,6 @@ impl<T> LinkedList<T> {
|
|||
///
|
||||
/// dl.push_back(1);
|
||||
/// assert_eq!(dl.back(), Some(&1));
|
||||
///
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -422,7 +485,6 @@ impl<T> LinkedList<T> {
|
|||
/// Some(x) => *x = 5,
|
||||
/// }
|
||||
/// assert_eq!(dl.back(), Some(&5));
|
||||
///
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -446,7 +508,6 @@ impl<T> LinkedList<T> {
|
|||
///
|
||||
/// dl.push_front(1);
|
||||
/// assert_eq!(dl.front().unwrap(), &1);
|
||||
///
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
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(1));
|
||||
/// assert_eq!(d.pop_front(), None);
|
||||
///
|
||||
/// ```
|
||||
///
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn pop_front(&mut self) -> Option<T> {
|
||||
self.pop_front_node().map(Node::into_element)
|
||||
|
|
|
@ -23,6 +23,22 @@ pub trait RangeArgument<T> {
|
|||
/// Start index (inclusive)
|
||||
///
|
||||
/// 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> {
|
||||
None
|
||||
}
|
||||
|
@ -30,6 +46,22 @@ pub trait RangeArgument<T> {
|
|||
/// End index (exclusive)
|
||||
///
|
||||
/// 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> {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -544,14 +544,21 @@ impl<T> [T] {
|
|||
///
|
||||
/// # 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
|
||||
/// let v = &[1, 2, 3, 4];
|
||||
/// for win in v.windows(2) {
|
||||
/// println!("{:?}", win);
|
||||
/// }
|
||||
/// If the slice is shorter than `size`:
|
||||
///
|
||||
/// ```
|
||||
/// let slice = ['f', 'o', 'o'];
|
||||
/// let mut iter = slice.windows(4);
|
||||
/// assert!(iter.next().is_none());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
|
@ -570,15 +577,13 @@ impl<T> [T] {
|
|||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Print the slice two elements at a time (i.e. `[1,2]`,
|
||||
/// `[3,4]`, `[5]`):
|
||||
///
|
||||
/// ```rust
|
||||
/// let v = &[1, 2, 3, 4, 5];
|
||||
///
|
||||
/// for chunk in v.chunks(2) {
|
||||
/// println!("{:?}", chunk);
|
||||
/// }
|
||||
/// ```
|
||||
/// let slice = ['l', 'o', 'r', 'e', 'm'];
|
||||
/// let mut iter = slice.chunks(2);
|
||||
/// assert_eq!(iter.next().unwrap(), &['l', 'o']);
|
||||
/// assert_eq!(iter.next().unwrap(), &['r', 'e']);
|
||||
/// assert_eq!(iter.next().unwrap(), &['m']);
|
||||
/// assert!(iter.next().is_none());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
|
@ -684,15 +689,40 @@ impl<T> [T] {
|
|||
///
|
||||
/// # 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) {
|
||||
/// println!("{:?}", group);
|
||||
/// }
|
||||
/// assert_eq!(iter.next().unwrap(), &[10, 40]);
|
||||
/// 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")]
|
||||
#[inline]
|
||||
|
|
|
@ -1697,6 +1697,14 @@ impl str {
|
|||
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`.
|
||||
#[unstable(feature = "str_escape",
|
||||
reason = "return type may change to be an iterator",
|
||||
|
|
|
@ -59,7 +59,7 @@ use core::fmt;
|
|||
use core::hash;
|
||||
use core::iter::FromIterator;
|
||||
use core::mem;
|
||||
use core::ops::{self, Add, Index, IndexMut};
|
||||
use core::ops::{self, Add, AddAssign, Index, IndexMut};
|
||||
use core::ptr;
|
||||
use core::str::pattern::Pattern;
|
||||
use rustc_unicode::char::{decode_utf16, REPLACEMENT_CHARACTER};
|
||||
|
@ -701,6 +701,12 @@ impl String {
|
|||
/// Violating these may cause problems like corrupting the allocator's
|
||||
/// 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
|
||||
///
|
||||
/// Basic usage:
|
||||
|
@ -1126,18 +1132,62 @@ impl String {
|
|||
assert!(idx <= len);
|
||||
assert!(self.is_char_boundary(idx));
|
||||
let bits = ch.encode_utf8();
|
||||
let bits = bits.as_slice();
|
||||
let amt = bits.len();
|
||||
self.vec.reserve(amt);
|
||||
|
||||
unsafe {
|
||||
ptr::copy(self.vec.as_ptr().offset(idx as isize),
|
||||
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),
|
||||
amt);
|
||||
self.vec.set_len(len + amt);
|
||||
self.insert_bytes(idx, bits.as_slice());
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) {
|
||||
let len = self.len();
|
||||
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")]
|
||||
impl ops::Index<ops::Range<usize>> for String {
|
||||
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")]
|
||||
impl fmt::Write for String {
|
||||
#[inline]
|
||||
|
|
|
@ -73,6 +73,7 @@ use core::mem;
|
|||
use core::ops::{Index, IndexMut};
|
||||
use core::ops;
|
||||
use core::ptr;
|
||||
use core::ptr::Shared;
|
||||
use core::slice;
|
||||
|
||||
use super::SpecExtend;
|
||||
|
@ -342,12 +343,18 @@ impl<T> 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).
|
||||
/// * `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.
|
||||
///
|
||||
/// Violating these may cause problems like corrupting the allocator's
|
||||
/// 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
|
||||
///
|
||||
/// ```
|
||||
|
@ -469,6 +476,25 @@ impl<T> Vec<T> {
|
|||
/// Note that this will drop any excess capacity. Calling this and
|
||||
/// converting back to a vector with `into_vec()` is equivalent to calling
|
||||
/// `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")]
|
||||
pub fn into_boxed_slice(mut self) -> Box<[T]> {
|
||||
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
|
||||
/// effect.
|
||||
///
|
||||
/// The [`drain`] method can emulate `truncate`, but causes the excess
|
||||
/// elements to be returned instead of dropped.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Truncating a five element vector to two elements:
|
||||
///
|
||||
/// ```
|
||||
/// let mut vec = vec![1, 2, 3, 4, 5];
|
||||
/// vec.truncate(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")]
|
||||
pub fn truncate(&mut self, len: usize) {
|
||||
unsafe {
|
||||
|
@ -508,6 +561,14 @@ impl<T> Vec<T> {
|
|||
/// Extracts a slice containing the entire vector.
|
||||
///
|
||||
/// 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]
|
||||
#[stable(feature = "vec_as_slice", since = "1.7.0")]
|
||||
pub fn as_slice(&self) -> &[T] {
|
||||
|
@ -517,6 +578,14 @@ impl<T> Vec<T> {
|
|||
/// Extracts a mutable slice of the entire vector.
|
||||
///
|
||||
/// 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]
|
||||
#[stable(feature = "vec_as_slice", since = "1.7.0")]
|
||||
pub fn as_mut_slice(&mut self) -> &mut [T] {
|
||||
|
@ -532,9 +601,38 @@ impl<T> Vec<T> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let mut v = vec![1, 2, 3, 4];
|
||||
/// use std::ptr;
|
||||
///
|
||||
/// let mut vec = vec!['r', 'u', 's', 't'];
|
||||
///
|
||||
/// 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]
|
||||
|
@ -821,8 +919,8 @@ impl<T> Vec<T> {
|
|||
Drain {
|
||||
tail_start: end,
|
||||
tail_len: len - end,
|
||||
iter: range_slice.iter_mut(),
|
||||
vec: self as *mut _,
|
||||
iter: range_slice.iter(),
|
||||
vec: Shared::new(self as *mut _),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1728,8 +1826,8 @@ pub struct Drain<'a, T: 'a> {
|
|||
/// Length of tail
|
||||
tail_len: usize,
|
||||
/// Current remaining range to remove
|
||||
iter: slice::IterMut<'a, T>,
|
||||
vec: *mut Vec<T>,
|
||||
iter: slice::Iter<'a, T>,
|
||||
vec: Shared<Vec<T>>,
|
||||
}
|
||||
|
||||
#[stable(feature = "drain", since = "1.6.0")]
|
||||
|
@ -1767,7 +1865,7 @@ impl<'a, T> Drop for Drain<'a, T> {
|
|||
|
||||
if self.tail_len > 0 {
|
||||
unsafe {
|
||||
let source_vec = &mut *self.vec;
|
||||
let source_vec = &mut **self.vec;
|
||||
// memmove back untouched tail, update to new length
|
||||
let start = source_vec.len();
|
||||
let tail = self.tail_start;
|
||||
|
|
|
@ -365,12 +365,28 @@ impl<T> VecDeque<T> {
|
|||
|
||||
impl<T> VecDeque<T> {
|
||||
/// Creates an empty `VecDeque`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::VecDeque;
|
||||
///
|
||||
/// let vector: VecDeque<u32> = VecDeque::new();
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn new() -> VecDeque<T> {
|
||||
VecDeque::with_capacity(INITIAL_CAPACITY)
|
||||
}
|
||||
|
||||
/// 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")]
|
||||
pub fn with_capacity(n: usize) -> VecDeque<T> {
|
||||
// +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.
|
||||
///
|
||||
/// Element at index 0 is the front of the queue.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
@ -409,6 +427,8 @@ impl<T> VecDeque<T> {
|
|||
|
||||
/// Retrieves an element in the `VecDeque` mutably by index.
|
||||
///
|
||||
/// Element at index 0 is the front of the queue.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
@ -440,6 +460,8 @@ impl<T> VecDeque<T> {
|
|||
///
|
||||
/// Fails if there is no element with either index.
|
||||
///
|
||||
/// Element at index 0 is the front of the queue.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
@ -696,6 +718,25 @@ impl<T> VecDeque<T> {
|
|||
|
||||
/// Returns a pair of slices which contain, in order, the contents of the
|
||||
/// `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]
|
||||
#[stable(feature = "deque_extras_15", since = "1.5.0")]
|
||||
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
|
||||
/// `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]
|
||||
#[stable(feature = "deque_extras_15", since = "1.5.0")]
|
||||
pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
|
||||
|
@ -789,7 +848,7 @@ impl<T> VecDeque<T> {
|
|||
///
|
||||
/// ```
|
||||
/// use std::collections::VecDeque;
|
||||
|
||||
///
|
||||
/// 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![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
|
||||
/// 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",
|
||||
issue = "32630")]
|
||||
pub fn contains(&self, x: &T) -> bool
|
||||
|
@ -1111,6 +1186,8 @@ impl<T> VecDeque<T> {
|
|||
///
|
||||
/// Returns `None` if `index` is out of bounds.
|
||||
///
|
||||
/// Element at index 0 is the front of the queue.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
@ -1145,6 +1222,8 @@ impl<T> VecDeque<T> {
|
|||
///
|
||||
/// Returns `None` if `index` is out of bounds.
|
||||
///
|
||||
/// Element at index 0 is the front of the queue.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
@ -1176,6 +1255,8 @@ impl<T> VecDeque<T> {
|
|||
/// end is closer to the insertion point will be moved to make room,
|
||||
/// and all the affected elements will be moved to new positions.
|
||||
///
|
||||
/// Element at index 0 is the front of the queue.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// 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.
|
||||
/// Returns `None` if `index` is out of bounds.
|
||||
///
|
||||
/// Element at index 0 is the front of the queue.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::VecDeque;
|
||||
///
|
||||
|
@ -1581,6 +1665,8 @@ impl<T> VecDeque<T> {
|
|||
///
|
||||
/// Note that the capacity of `self` does not change.
|
||||
///
|
||||
/// Element at index 0 is the front of the queue.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `at > len`
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
use std::collections::BinaryHeap;
|
||||
use std::collections::binary_heap::Drain;
|
||||
|
||||
#[test]
|
||||
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]);
|
||||
}
|
||||
|
||||
#[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}");
|
||||
}
|
||||
|
||||
#[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]
|
||||
fn test_escape_default() {
|
||||
assert_eq!("abc".escape_default(), "abc");
|
||||
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!("'\"\\".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{10000}\u{10ffff}".escape_default(), "\\u{10000}\\u{10ffff}");
|
||||
assert_eq!("ab\u{fb00}".escape_default(), "ab\\u{fb00}");
|
||||
assert_eq!("\u{1d4ea}\r".escape_default(), "\\u{1d4ea}\\r");
|
||||
assert_eq!("ab\u{200b}".escape_default(), "ab\\u{200b}");
|
||||
assert_eq!("\u{10d4ea}\r".escape_default(), "\\u{10d4ea}\\r");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -192,6 +192,17 @@ fn test_push_str() {
|
|||
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]
|
||||
fn test_push() {
|
||||
let mut data = String::from("ประเทศไทย中");
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
use std::borrow::Cow;
|
||||
use std::iter::{FromIterator, repeat};
|
||||
use std::mem::size_of;
|
||||
use std::vec::Drain;
|
||||
|
||||
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]
|
||||
fn bench_new(b: &mut Bencher) {
|
||||
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
|
||||
/// 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.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -916,6 +930,11 @@ impl<T> UnsafeCell<T> {
|
|||
impl<T: ?Sized> UnsafeCell<T> {
|
||||
/// 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
|
||||
///
|
||||
/// ```
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
use prelude::v1::*;
|
||||
|
||||
use char_private::is_printable;
|
||||
use mem::transmute;
|
||||
|
||||
// UTF-8 ranges and tags for encoding characters
|
||||
|
@ -263,6 +264,8 @@ pub trait CharExt {
|
|||
fn escape_unicode(self) -> EscapeUnicode;
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
fn escape_default(self) -> EscapeDefault;
|
||||
#[unstable(feature = "char_escape_debug", issue = "35068")]
|
||||
fn escape_debug(self) -> EscapeDebug;
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
fn len_utf8(self) -> usize;
|
||||
#[stable(feature = "core", since = "1.6.0")]
|
||||
|
@ -326,6 +329,19 @@ impl CharExt for char {
|
|||
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]
|
||||
fn len_utf8(self) -> usize {
|
||||
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`
|
||||
/// 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);
|
||||
}
|
||||
// The `precision` field can be interpreted as a `max-width` for the
|
||||
// string being formatted
|
||||
if let Some(max) = self.precision {
|
||||
// If there's a maximum width and our string is longer than
|
||||
// that, then we must always have truncation. This is the only
|
||||
// case where the maximum length will matter.
|
||||
// string being formatted.
|
||||
let s = if let Some(max) = self.precision {
|
||||
// If our string is longer that the precision, then we must have
|
||||
// truncation. However other flags like `fill`, `width` and `align`
|
||||
// must act as always.
|
||||
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.
|
||||
match self.width {
|
||||
// If we're under the maximum length, and there's no minimum length
|
||||
|
@ -1379,7 +1383,7 @@ impl Debug for str {
|
|||
f.write_char('"')?;
|
||||
let mut from = 0;
|
||||
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 esc.len() != 1 {
|
||||
f.write_str(&self[from..i])?;
|
||||
|
@ -1405,7 +1409,7 @@ impl Display for str {
|
|||
impl Debug for char {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
f.write_char('\'')?;
|
||||
for c in self.escape_default() {
|
||||
for c in self.escape_debug() {
|
||||
f.write_char(c)?
|
||||
}
|
||||
f.write_char('\'')
|
||||
|
|
|
@ -234,6 +234,16 @@ pub trait BuildHasher {
|
|||
type Hasher: 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")]
|
||||
fn build_hasher(&self) -> Self::Hasher;
|
||||
}
|
||||
|
|
|
@ -277,17 +277,200 @@ extern "rust-intrinsic" {
|
|||
/// Moves a value out of scope without running drop glue.
|
||||
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
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem;
|
||||
/// There are a few things that `transmute` is really useful for.
|
||||
///
|
||||
/// let array: &[u8] = unsafe { mem::transmute("Rust") };
|
||||
/// assert_eq!(array, [82, 117, 115, 116]);
|
||||
/// Getting the bitpattern of a floating point type (or, more generally,
|
||||
/// 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")]
|
||||
pub fn transmute<T, U>(e: T) -> U;
|
||||
|
|
|
@ -386,10 +386,11 @@ pub trait Extend<A> {
|
|||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
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
|
||||
/// contain more details.
|
||||
/// Returns `None` when there are no more elements.
|
||||
///
|
||||
/// The [trait-level] docs contain more details.
|
||||
///
|
||||
/// [trait-level]: trait.DoubleEndedIterator.html
|
||||
///
|
||||
|
|
|
@ -103,17 +103,17 @@ mod int_macros;
|
|||
#[macro_use]
|
||||
mod uint_macros;
|
||||
|
||||
#[path = "num/isize.rs"] pub mod isize;
|
||||
#[path = "num/i8.rs"] pub mod i8;
|
||||
#[path = "num/i16.rs"] pub mod i16;
|
||||
#[path = "num/i32.rs"] pub mod i32;
|
||||
#[path = "num/i64.rs"] pub mod i64;
|
||||
#[path = "num/isize.rs"] pub mod isize;
|
||||
#[path = "num/i8.rs"] pub mod i8;
|
||||
#[path = "num/i16.rs"] pub mod i16;
|
||||
#[path = "num/i32.rs"] pub mod i32;
|
||||
#[path = "num/i64.rs"] pub mod i64;
|
||||
|
||||
#[path = "num/usize.rs"] pub mod usize;
|
||||
#[path = "num/u8.rs"] pub mod u8;
|
||||
#[path = "num/u16.rs"] pub mod u16;
|
||||
#[path = "num/u32.rs"] pub mod u32;
|
||||
#[path = "num/u64.rs"] pub mod u64;
|
||||
#[path = "num/u8.rs"] pub mod u8;
|
||||
#[path = "num/u16.rs"] pub mod u16;
|
||||
#[path = "num/u32.rs"] pub mod u32;
|
||||
#[path = "num/u64.rs"] pub mod u64;
|
||||
|
||||
#[path = "num/f32.rs"] pub mod f32;
|
||||
#[path = "num/f64.rs"] pub mod f64;
|
||||
|
@ -161,5 +161,6 @@ pub mod hash;
|
|||
pub mod fmt;
|
||||
|
||||
// note: does not need to be public
|
||||
mod char_private;
|
||||
mod iter_private;
|
||||
mod tuple;
|
||||
|
|
|
@ -35,6 +35,17 @@ macro_rules! panic {
|
|||
/// This will invoke the `panic!` macro if the provided expression cannot be
|
||||
/// 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.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -123,6 +134,13 @@ macro_rules! assert_eq {
|
|||
/// expensive to be present in a release build but may be helpful during
|
||||
/// 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
|
||||
///
|
||||
/// ```
|
||||
|
|
|
@ -144,6 +144,12 @@ pub trait Unsize<T: ?Sized> {
|
|||
/// 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.
|
||||
///
|
||||
/// ## 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`?
|
||||
///
|
||||
/// 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)}
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// the numeric bounds instead of overflowing.
|
||||
///
|
||||
|
@ -863,6 +888,36 @@ macro_rules! int_impl {
|
|||
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`
|
||||
///
|
||||
/// 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)))
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// # Examples
|
||||
|
|
|
@ -142,6 +142,7 @@
|
|||
use self::Option::*;
|
||||
|
||||
use clone::Clone;
|
||||
use convert::From;
|
||||
use default::Default;
|
||||
use iter::ExactSizeIterator;
|
||||
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
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -902,6 +902,8 @@ macro_rules! make_mut_slice {
|
|||
|
||||
/// Immutable slice iterator
|
||||
///
|
||||
/// This struct is created by the [`iter`] method on [slices].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
|
@ -915,6 +917,9 @@ macro_rules! make_mut_slice {
|
|||
/// println!("{}", element);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`iter`]: ../../std/primitive.slice.html#method.iter
|
||||
/// [slices]: ../../std/primitive.slice.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Iter<'a, T: 'a> {
|
||||
ptr: *const T,
|
||||
|
@ -993,6 +998,8 @@ impl<'a, T> Clone for Iter<'a, T> {
|
|||
|
||||
/// Mutable slice iterator.
|
||||
///
|
||||
/// This struct is created by the [`iter_mut`] method on [slices].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
|
@ -1010,6 +1017,9 @@ impl<'a, T> Clone for Iter<'a, T> {
|
|||
/// // We now have "[2, 3, 4]":
|
||||
/// println!("{:?}", slice);
|
||||
/// ```
|
||||
///
|
||||
/// [`iter_mut`]: ../../std/primitive.slice.html#method.iter_mut
|
||||
/// [slices]: ../../std/primitive.slice.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct IterMut<'a, T: 'a> {
|
||||
ptr: *mut T,
|
||||
|
|
|
@ -459,6 +459,19 @@ impl<'a> Chars<'a> {
|
|||
///
|
||||
/// This has the same lifetime as the original slice, and so the
|
||||
/// 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")]
|
||||
#[inline]
|
||||
pub fn as_str(&self) -> &'a str {
|
||||
|
|
|
@ -74,6 +74,8 @@
|
|||
//! ```
|
||||
|
||||
#![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::*;
|
||||
|
||||
|
|
|
@ -123,6 +123,49 @@ fn test_is_digit() {
|
|||
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]
|
||||
fn test_escape_default() {
|
||||
fn string(c: char) -> String {
|
||||
|
@ -142,18 +185,28 @@ fn test_escape_default() {
|
|||
assert_eq!(s, "a");
|
||||
let s = string('~');
|
||||
assert_eq!(s, "~");
|
||||
let s = string('é');
|
||||
assert_eq!(s, "\\u{e9}");
|
||||
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]
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#![feature(borrow_state)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(cell_extras)]
|
||||
#![feature(char_escape_debug)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(core_private_bignum)]
|
||||
#![feature(core_private_diy_float)]
|
||||
|
@ -29,10 +30,9 @@
|
|||
#![feature(slice_patterns)]
|
||||
#![feature(step_by)]
|
||||
#![feature(test)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(try_from)]
|
||||
#![feature(unicode)]
|
||||
#![feature(unique)]
|
||||
#![feature(try_from)]
|
||||
|
||||
extern crate core;
|
||||
extern crate test;
|
||||
|
|
|
@ -11,4 +11,4 @@ crate-type = ["dylib"]
|
|||
|
||||
[build-dependencies]
|
||||
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;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct EHContext {
|
||||
pub struct EHContext<'a> {
|
||||
pub ip: usize, // Current instruction pointer
|
||||
pub func_start: usize, // Address of the current function
|
||||
pub text_start: usize, // Address of the code section
|
||||
pub data_start: usize, // Address of the data section
|
||||
pub get_text_start: &'a Fn() -> usize, // Get address of the code 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() {
|
||||
return None;
|
||||
return EHAction::None;
|
||||
}
|
||||
|
||||
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_table_length = reader.read_uleb128();
|
||||
let action_table = reader.ptr.offset(call_site_table_length as isize);
|
||||
// Return addresses point 1 byte past the call instruction, which could
|
||||
// be in the next IP range.
|
||||
let ip = context.ip - 1;
|
||||
let ip = context.ip;
|
||||
|
||||
while reader.ptr < action_table {
|
||||
let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding);
|
||||
let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding);
|
||||
let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding);
|
||||
let cs_action = reader.read_uleb128();
|
||||
// Callsite table is sorted by cs_start, so if we've passed the ip, we
|
||||
// may stop searching.
|
||||
if ip < func_start + cs_start {
|
||||
break;
|
||||
if !USING_SJLJ_EXCEPTIONS {
|
||||
while reader.ptr < action_table {
|
||||
let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding);
|
||||
let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding);
|
||||
let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding);
|
||||
let cs_action = reader.read_uleb128();
|
||||
// Callsite table is sorted by cs_start, so if we've passed the ip, we
|
||||
// may stop searching.
|
||||
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 {
|
||||
if cs_lpad != 0 {
|
||||
return Some(lpad_base + cs_lpad);
|
||||
} else {
|
||||
return None;
|
||||
// Ip is not present in the table. This should not happen... but it does: issue #35011.
|
||||
// So rather than returning EHAction::Terminate, we do this.
|
||||
EHAction::None
|
||||
} else {
|
||||
// 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.
|
||||
None
|
||||
}
|
||||
|
||||
fn interpret_cs_action(cs_action: u64, lpad: usize) -> EHAction {
|
||||
if cs_action == 0 {
|
||||
EHAction::Cleanup(lpad)
|
||||
} else {
|
||||
EHAction::Catch(lpad)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -140,18 +178,16 @@ unsafe fn read_encoded_pointer(reader: &mut DwarfReader,
|
|||
DW_EH_PE_absptr => 0,
|
||||
// relative to address of the encoded value, despite the name
|
||||
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 => {
|
||||
assert!(context.func_start != 0);
|
||||
context.func_start
|
||||
}
|
||||
DW_EH_PE_textrel => {
|
||||
(*context.get_text_start)()
|
||||
}
|
||||
DW_EH_PE_datarel => {
|
||||
(*context.get_data_start)()
|
||||
}
|
||||
_ => panic!(),
|
||||
};
|
||||
|
||||
|
|
|
@ -61,6 +61,8 @@ use core::ptr;
|
|||
use alloc::boxed::Box;
|
||||
|
||||
use unwind as uw;
|
||||
use libc::{c_int, uintptr_t};
|
||||
use dwarf::eh::{self, EHContext, EHAction};
|
||||
|
||||
#[repr(C)]
|
||||
struct Exception {
|
||||
|
@ -106,160 +108,184 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class {
|
|||
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"),
|
||||
not(all(windows, target_arch = "x86_64"))))]
|
||||
pub mod eabi {
|
||||
use unwind as uw;
|
||||
use libc::c_int;
|
||||
// Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister()
|
||||
// and TargetLowering::getExceptionSelectorRegister() for each architecture,
|
||||
// then mapped to DWARF register numbers via register definition tables
|
||||
// (typically <arch>RegisterInfo.td, search for "DwarfRegNum").
|
||||
// See also http://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register.
|
||||
|
||||
extern "C" {
|
||||
fn __gcc_personality_v0(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;
|
||||
#[cfg(target_arch = "x86")]
|
||||
const UNWIND_DATA_REG: (i32, i32) = (0, 2); // EAX, EDX
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
const UNWIND_DATA_REG: (i32, i32) = (0, 1); // RAX, RDX
|
||||
|
||||
#[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;
|
||||
}
|
||||
|
||||
#[lang = "eh_personality"]
|
||||
#[no_mangle]
|
||||
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_v0(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_v0(version, actions, exception_class, ue_header, context) }
|
||||
let eh_action = find_eh_action(context);
|
||||
if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 {
|
||||
match eh_action {
|
||||
EHAction::None | EHAction::Cleanup(_) => return uw::_URC_CONTINUE_UNWIND,
|
||||
EHAction::Catch(_) => return uw::_URC_HANDLER_FOUND,
|
||||
EHAction::Terminate => return uw::_URC_FATAL_PHASE1_ERROR,
|
||||
}
|
||||
} else {
|
||||
match eh_action {
|
||||
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);
|
||||
uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
|
||||
uw::_Unwind_SetIP(context, lpad);
|
||||
return uw::_URC_INSTALL_CONTEXT;
|
||||
}
|
||||
EHAction::Terminate => return uw::_URC_FATAL_PHASE2_ERROR,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// iOS on armv7 is using SjLj exceptions and therefore requires to use
|
||||
// a specialized personality routine: __gcc_personality_sj0
|
||||
|
||||
#[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.
|
||||
// ARM EHABI personality routine.
|
||||
// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
|
||||
#[cfg(all(target_arch = "arm", not(target_os = "ios")))]
|
||||
pub mod eabi {
|
||||
use unwind as uw;
|
||||
use libc::c_int;
|
||||
|
||||
extern "C" {
|
||||
fn __gcc_personality_v0(state: uw::_Unwind_State,
|
||||
ue_header: *mut uw::_Unwind_Exception,
|
||||
context: *mut uw::_Unwind_Context)
|
||||
-> uw::_Unwind_Reason_Code;
|
||||
}
|
||||
|
||||
#[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 {
|
||||
#[lang = "eh_personality"]
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State,
|
||||
exception_object: *mut uw::_Unwind_Exception,
|
||||
context: *mut uw::_Unwind_Context)
|
||||
-> uw::_Unwind_Reason_Code {
|
||||
let state = state as c_int;
|
||||
let action = state & uw::_US_ACTION_MASK as c_int;
|
||||
let search_phase = if action == uw::_US_VIRTUAL_UNWIND_FRAME as c_int {
|
||||
// Backtraces on ARM will call the personality routine with
|
||||
// state == _US_VIRTUAL_UNWIND_FRAME | _US_FORCE_UNWIND. In those cases
|
||||
// we want to continue unwinding the stack, otherwise all our backtraces
|
||||
// would end at __rust_try.
|
||||
if (state as c_int & uw::_US_ACTION_MASK as c_int) ==
|
||||
uw::_US_VIRTUAL_UNWIND_FRAME as c_int &&
|
||||
(state as c_int & uw::_US_FORCE_UNWIND as c_int) == 0 {
|
||||
// search phase
|
||||
uw::_URC_HANDLER_FOUND // catch!
|
||||
} else {
|
||||
// cleanup phase
|
||||
unsafe { __gcc_personality_v0(state, ue_header, context) }
|
||||
// would end at __rust_try
|
||||
if state & uw::_US_FORCE_UNWIND as c_int != 0 {
|
||||
return continue_unwind(exception_object, context)
|
||||
}
|
||||
true
|
||||
} else if action == uw::_US_UNWIND_FRAME_STARTING as c_int {
|
||||
false
|
||||
} else if action == uw::_US_UNWIND_FRAME_RESUME as c_int {
|
||||
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.
|
||||
|
|
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