From 9ece0510b14e6baad0d2c9511dab86919a5379e1 Mon Sep 17 00:00:00 2001 From: Valerii Hiora Date: Fri, 6 Jun 2014 17:34:48 +0300 Subject: [PATCH 01/10] Updated deps --- src/compiler-rt | 2 +- src/jemalloc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler-rt b/src/compiler-rt index ed112ca1e42..c10fb863096 160000 --- a/src/compiler-rt +++ b/src/compiler-rt @@ -1 +1 @@ -Subproject commit ed112ca1e4275e1c5707a898f2bf6164707ba378 +Subproject commit c10fb8630963e858513fbebe86db3648a2246d73 diff --git a/src/jemalloc b/src/jemalloc index 6a96910f2ea..024c67ad651 160000 --- a/src/jemalloc +++ b/src/jemalloc @@ -1 +1 @@ -Subproject commit 6a96910f2eaea6d2c705bb12379b23576b30d7d5 +Subproject commit 024c67ad651e1a3ca228936c4cfb13a37329baf2 From 9e90a5e72c760cee268b714aced54ed30d04fa3c Mon Sep 17 00:00:00 2001 From: Valerii Hiora Date: Mon, 5 May 2014 10:05:11 +0300 Subject: [PATCH 02/10] Platform configuration FIXME: avoid using Xcode build and switch to a patched libuv --- mk/platform.mk | 96 +++++++++++++++++++++++++++++++++++--------------- mk/rt.mk | 49 ++++++++++++++++++++++---- 2 files changed, 111 insertions(+), 34 deletions(-) diff --git a/mk/platform.mk b/mk/platform.mk index 3ab55ce4b7b..1efa1cc5b6d 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -155,36 +155,76 @@ CFG_LDPATH_i686-unknown-linux-gnu := CFG_RUN_i686-unknown-linux-gnu=$(2) CFG_RUN_TARG_i686-unknown-linux-gnu=$(call CFG_RUN_i686-unknown-linux-gnu,,$(2)) -# arm-apple-darwin configuration -ifeq ($(CFG_OSTYPE),apple-darwin) +# arm-apple-ios configuration +CFG_SDK_NAME_arm-apple-ios = iphoneos +CFG_SDK_ARCHS_arm-apple-ios = armv7 +ifneq ($(findstring darwin,$(CFG_OSTYPE)),) CFG_IOS_SDK = $(shell xcrun --show-sdk-path -sdk iphoneos 2>/dev/null) -CFG_IOS_FLAGS = -target arm-apple-darwin -isysroot $(CFG_IOS_SDK) -I$(CFG_IOS_SDK)/usr/include -I$(CFG_IOS_SDK)/usr/include/c++/4.2.1 -CC_arm-apple-darwin = $(shell xcrun -find -sdk iphoneos clang) -CXX_arm-apple-darwin = $(shell xcrun -find -sdk iphoneos clang++) -CPP_arm-apple-darwin = $(shell xcrun -find -sdk iphoneos clang++) -AR_arm-apple-darwin = $(shell xcrun -find -sdk iphoneos ar) -CFG_LIB_NAME_arm-apple-darwin = lib$(1).dylib -CFG_LIB_GLOB_arm-apple-darwin = lib$(1)-*.dylib -CFG_LIB_DSYM_GLOB_arm-apple-darwin = lib$(1)-*.dylib.dSYM -CFG_CFLAGS_arm-apple-darwin := $(CFG_IOS_FLAGS) $(CFLAGS) -CFG_GCCISH_CFLAGS_arm-apple-darwin := -Wall -Werror -g -fPIC $(CFG_IOS_FLAGS) $(CFLAGS) -CFG_GCCISH_CXXFLAGS_arm-apple-darwin := -fno-rtti $(CFG_IOS_FLAGS) $(CXXFLAGS) -CFG_GCCISH_LINK_FLAGS_arm-apple-darwin := -dynamiclib -lpthread -framework CoreServices -Wl,-no_compact_unwind -CFG_GCCISH_DEF_FLAG_arm-apple-darwin := -Wl,-exported_symbols_list, -CFG_GCCISH_PRE_LIB_FLAGS_arm-apple-darwin := -CFG_GCCISH_POST_LIB_FLAGS_arm-apple-darwin := -CFG_DEF_SUFFIX_arm-apple-darwin := .darwin.def -CFG_LLC_FLAGS_arm-apple-darwin := -CFG_INSTALL_NAME_arm-apple-darwin = -Wl,-install_name,@rpath/$(1) -CFG_LIBUV_LINK_FLAGS_arm-apple-darwin = -CFG_EXE_SUFFIX_arm-apple-darwin := -CFG_WINDOWSY_arm-apple-darwin := -CFG_UNIXY_arm-apple-darwin := 1 -CFG_PATH_MUNGE_arm-apple-darwin := true -CFG_LDPATH_arm-apple-darwin := -CFG_RUN_arm-apple-darwin = $(2) -CFG_RUN_TARG_arm-apple-darwin = $(call CFG_RUN_arm-apple-darwin,,$(2)) +CFG_IOS_FLAGS = -target armv7-apple-darwin -isysroot $(CFG_IOS_SDK) -mios-version-min=7.0 +CC_arm-apple-ios = $(shell xcrun -find -sdk iphoneos clang) +CXX_arm-apple-ios = $(shell xcrun -find -sdk iphoneos clang++) +CPP_arm-apple-ios = $(shell xcrun -find -sdk iphoneos clang++) +AR_arm-apple-ios = $(shell xcrun -find -sdk iphoneos ar) endif +CFG_LIB_NAME_arm-apple-ios = lib$(1).a +CFG_LIB_GLOB_arm-apple-ios = lib$(1)-*.a +CFG_STATIC_LIB_NAME_arm-apple-ios=lib$(1).a +CFG_LIB_DSYM_GLOB_arm-apple-ios = lib$(1)-*.a.dSYM +CFG_CFLAGS_arm-apple-ios := -arch armv7 -mfpu=vfp3 $(CFG_IOS_FLAGS) +CFG_GCCISH_CFLAGS_arm-apple-ios := -Wall -Werror -g -fPIC $(CFG_IOS_FLAGS) -mfpu=vfp3 -arch armv7 +CFG_GCCISH_CXXFLAGS_arm-apple-ios := -fno-rtti $(CFG_IOS_FLAGS) -I$(CFG_IOS_SDK)/usr/include/c++/4.2.1 +CFG_GCCISH_LINK_FLAGS_arm-apple-ios := -lpthread -syslibroot $(CFG_IOS_SDK) -Wl,-no_compact_unwind +CFG_GCCISH_DEF_FLAG_arm-apple-ios := -Wl,-exported_symbols_list, +CFG_GCCISH_PRE_LIB_FLAGS_arm-apple-ios := +CFG_GCCISH_POST_LIB_FLAGS_arm-apple-ios := +CFG_DEF_SUFFIX_arm-apple-ios := .darwin.def +CFG_LLC_FLAGS_arm-apple-ios := -mattr=+vfp3,+v7,+thumb2,+neon -march=arm +CFG_INSTALL_NAME_arm-apple-ios = -Wl,-install_name,@rpath/$(1) +CFG_LIBUV_LINK_FLAGS_arm-apple-ios = +CFG_EXE_SUFFIX_arm-apple-ios := +CFG_WINDOWSY_arm-apple-ios := +CFG_UNIXY_arm-apple-ios := 1 +CFG_PATH_MUNGE_arm-apple-ios := true +CFG_LDPATH_arm-apple-ios := +CFG_RUN_arm-apple-ios = $(2) +CFG_RUN_TARG_arm-apple-ios = $(call CFG_RUN_arm-apple-ios,,$(2)) +RUSTC_FLAGS_arm-apple-ios := -C relocation_model=pic +RUSTC_CROSS_FLAGS_arm-apple-ios :=-C relocation_model=pic + +# i386-apple-ios configuration +CFG_SDK_NAME_i386-apple-ios = iphonesimulator +CFG_SDK_ARCHS_i386-apple-ios = i386 +ifneq ($(findstring darwin,$(CFG_OSTYPE)),) +CFG_IOSSIM_SDK = $(shell xcrun --show-sdk-path -sdk iphonesimulator 2>/dev/null) +CFG_IOSSIM_FLAGS = -target i386-apple-ios -isysroot $(CFG_IOSSIM_SDK) -mios-simulator-version-min=7.0 +CC_i386-apple-ios = $(shell xcrun -find -sdk iphonesimulator clang) +CXX_i386-apple-ios = $(shell xcrun -find -sdk iphonesimulator clang++) +CPP_i386-apple-ios = $(shell xcrun -find -sdk iphonesimulator clang++) +AR_i386-apple-ios = $(shell xcrun -find -sdk iphonesimulator ar) +endif +CFG_LIB_NAME_i386-apple-ios = lib$(1).a +CFG_LIB_GLOB_i386-apple-ios = lib$(1)-*.dylib +CFG_STATIC_LIB_NAME_i386-apple-ios=lib$(1).a +CFG_LIB_DSYM_GLOB_i386-apple-ios = lib$(1)-*.dylib.dSYM +CFG_CFLAGS_i386-apple-ios = $(CFG_IOSSIM_FLAGS) +CFG_GCCISH_CFLAGS_i386-apple-ios = -Wall -Werror -g -fPIC -m32 $(CFG_IOSSIM_FLAGS) +CFG_GCCISH_CXXFLAGS_i386-apple-ios = -fno-rtti $(CFG_IOSSIM_FLAGS) -I$(CFG_IOSSIM_SDK)/usr/include/c++/4.2.1 +CFG_GCCISH_LINK_FLAGS_i386-apple-ios = -lpthread -Wl,-no_compact_unwind -m32 -Wl,-syslibroot $(CFG_IOSSIM_SDK) +CFG_GCCISH_DEF_FLAG_i386-apple-ios = -Wl,-exported_symbols_list, +CFG_GCCISH_PRE_LIB_FLAGS_i386-apple-ios = +CFG_GCCISH_POST_LIB_FLAGS_i386-apple-ios = +CFG_DEF_SUFFIX_i386-apple-ios = .darwin.def +CFG_LLC_FLAGS_i386-apple-ios = +CFG_INSTALL_NAME_i386-apple-ios = -Wl,-install_name,@rpath/$(1) +CFG_LIBUV_LINK_FLAGS_i386-apple-ios = +CFG_EXE_SUFFIX_i386-apple-ios = +CFG_WINDOWSY_i386-apple-ios = +CFG_UNIXY_i386-apple-ios = 1 +CFG_PATH_MUNGE_i386-apple-ios = true +CFG_LDPATH_i386-apple-ios = +CFG_RUN_i386-apple-ios = $(2) +CFG_RUN_TARG_i386-apple-ios = $(call CFG_RUN_i386-apple-ios,,$(2)) +CFG_JEMALLOC_CFLAGS_i386-apple-ios = -target i386-apple-ios -Wl,-syslibroot $(CFG_IOSSIM_SDK) -Wl,-no_compact_unwind # x86_64-apple-darwin configuration CC_x86_64-apple-darwin=$(CC) diff --git a/mk/rt.mk b/mk/rt.mk index 1c4efd641f0..cb6c0fc7e5e 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -166,6 +166,9 @@ ifeq ($$(CFG_WINDOWSY_$(1)), 1) JEMALLOC_ARGS_$(1) := --enable-lazy-lock else ifeq ($(OSTYPE_$(1)), apple-darwin) LIBUV_OSTYPE_$(1) := mac +else ifeq ($(OSTYPE_$(1)), apple-ios) + LIBUV_OSTYPE_$(1) := ios + JEMALLOC_ARGS_$(1) := --disable-tls else ifeq ($(OSTYPE_$(1)), unknown-freebsd) LIBUV_OSTYPE_$(1) := freebsd else ifeq ($(OSTYPE_$(1)), linux-androideabi) @@ -181,6 +184,8 @@ LIBUV_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/libuv LIBUV_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(LIBUV_NAME_$(1)) LIBUV_MAKEFILE_$(1) := $$(CFG_BUILD_DIR)$$(RT_OUTPUT_DIR_$(1))/libuv/Makefile +LIBUV_BUILD_DIR_$(1) := $$(CFG_BUILD_DIR)$$(RT_OUTPUT_DIR_$(1))/libuv +LIBUV_XCODEPROJ_$(1) := $$(LIBUV_BUILD_DIR_$(1))/uv.xcodeproj LIBUV_STAMP_$(1) = $$(LIBUV_DIR_$(1))/libuv-auto-clean-stamp @@ -212,6 +217,31 @@ $$(LIBUV_LOCAL_$(1)): $$(LIBUV_DEPS) $$(MKFILE_DEPS) CXX="$$(CXX_$(1))" \ AR="$$(AR_$(1))" \ V=$$(VERBOSE) + $$(Q)cp $$(S)src/libuv/libuv.a $$@ +else ifeq ($(OSTYPE_$(1)), apple-ios) # iOS +$$(LIBUV_XCODEPROJ_$(1)): $$(LIBUV_DEPS) $$(MKFILE_DEPS) $$(LIBUV_STAMP_$(1)) + cp -rf $(S)src/libuv/ $$(LIBUV_BUILD_DIR_$(1)) + (cd $$(LIBUV_BUILD_DIR_$(1)) && \ + $$(CFG_PYTHON) ./gyp_uv.py -f xcode \ + -D ninja \ + -R libuv) + touch $$@ + +LIBUV_XCODE_OUT_LIB_$(1) := $$(LIBUV_BUILD_DIR_$(1))/build/Release-$$(CFG_SDK_NAME_$(1))/libuv.a + +$$(LIBUV_LIB_$(1)): $$(LIBUV_XCODE_OUT_LIB_$(1)) $$(MKFILE_DEPS) + $$(Q)cp $$< $$@ +$$(LIBUV_XCODE_OUT_LIB_$(1)): $$(LIBUV_DEPS) $$(LIBUV_XCODEPROJ_$(1)) \ + $$(MKFILE_DEPS) + $$(Q)xcodebuild -project $$(LIBUV_BUILD_DIR_$(1))/uv.xcodeproj \ + CFLAGS="$$(LIBUV_CFLAGS_$(1)) $$(SNAP_DEFINES)" \ + LDFLAGS="$$(CFG_GCCISH_LINK_FLAGS_$(1))" \ + $$(LIBUV_ARGS_$(1)) \ + V=$$(VERBOSE) \ + -configuration Release \ + -sdk "$$(CFG_SDK_NAME_$(1))" \ + ARCHS="$$(CFG_SDK_ARCHS_$(1))" + $$(Q)touch $$@ else LIBUV_LOCAL_$(1) := $$(LIBUV_DIR_$(1))/Release/libuv.a $$(LIBUV_LOCAL_$(1)): $$(LIBUV_DEPS) $$(LIBUV_MAKEFILE_$(1)) $$(MKFILE_DEPS) @@ -226,7 +256,6 @@ $$(LIBUV_LOCAL_$(1)): $$(LIBUV_DEPS) $$(LIBUV_MAKEFILE_$(1)) $$(MKFILE_DEPS) NO_LOAD="$$(LIBUV_NO_LOAD)" \ V=$$(VERBOSE) $$(Q)touch $$@ - endif ifeq ($(1),$$(CFG_BUILD)) @@ -269,13 +298,13 @@ JEMALLOC_LOCAL_$(1) := $$(JEMALLOC_BUILD_DIR_$(1))/lib/$$(JEMALLOC_REAL_NAME_$(1 $$(JEMALLOC_LOCAL_$(1)): $$(JEMALLOC_DEPS) $$(MKFILE_DEPS) @$$(call E, make: jemalloc) cd "$$(JEMALLOC_BUILD_DIR_$(1))"; "$(S)src/jemalloc/configure" \ - $$(JEMALLOC_ARGS_$(1)) --enable-cc-silence --with-jemalloc-prefix=je_ \ - --disable-experimental --build=$(CFG_BUILD) --host=$(1) \ + $$(JEMALLOC_ARGS_$(1)) --with-jemalloc-prefix=je_ \ + --build=$(CFG_BUILD) --host=$(1) \ CC="$$(CC_$(1))" \ AR="$$(AR_$(1))" \ RANLIB="$$(AR_$(1)) s" \ CPPFLAGS="-I $(S)src/rt/" \ - EXTRA_CFLAGS="$$(CFG_CFLAGS_$(1)) -g1" + EXTRA_CFLAGS="$$(CFG_CFLAGS_$(1)) $$(CFG_JEMALLOC_CFLAGS_$(1)) -g1" $$(Q)$$(MAKE) -C "$$(JEMALLOC_BUILD_DIR_$(1))" build_lib_static ifeq ($(1),$$(CFG_BUILD)) @@ -335,15 +364,22 @@ BACKTRACE_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),backtrace) BACKTRACE_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(BACKTRACE_NAME_$(1)) BACKTRACE_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/libbacktrace -ifeq ($$(findstring darwin,$$(OSTYPE_$(1))),darwin) - # We don't use this on platforms that aren't linux-based, so just make the file # available, the compilation of libstd won't actually build it. +ifeq ($$(findstring darwin,$$(OSTYPE_$(1))),darwin) +# See comment above $$(BACKTRACE_LIB_$(1)): touch $$@ else +ifeq ($$(findstring ios,$$(OSTYPE_$(1))),ios) +# See comment above +$$(BACKTRACE_LIB_$(1)): + touch $$@ +else + ifeq ($$(CFG_WINDOWSY_$(1)),1) +# See comment above $$(BACKTRACE_LIB_$(1)): touch $$@ else @@ -388,6 +424,7 @@ $$(BACKTRACE_LIB_$(1)): $$(BACKTRACE_BUILD_DIR_$(1))/Makefile $$(MKFILE_DEPS) $$(Q)cp $$(BACKTRACE_BUILD_DIR_$(1))/.libs/libbacktrace.a $$@ endif # endif for windowsy +endif # endif for ios endif # endif for darwin endef From d730ae2fb0c455775fb1962454537c79e54f817e Mon Sep 17 00:00:00 2001 From: Valerii Hiora Date: Mon, 5 May 2014 10:08:34 +0300 Subject: [PATCH 03/10] Runtime support for arm on iOS --- src/librustrt/stack.rs | 39 +++++++++++++++++++++-- src/rt/arch/arm/_context.S | 24 +++++++++----- src/rt/arch/arm/morestack.S | 62 +++++++++++++++++++++++++++---------- src/rt/arch/arm/record_sp.S | 22 +++++++------ 4 files changed, 111 insertions(+), 36 deletions(-) diff --git a/src/librustrt/stack.rs b/src/librustrt/stack.rs index 148d93adc84..aac773f6f85 100644 --- a/src/librustrt/stack.rs +++ b/src/librustrt/stack.rs @@ -24,6 +24,28 @@ //! detection is not guaranteed to continue in the future. Usage of this module //! is discouraged unless absolutely necessary. +// iOS related notes +// +// It is possible to implement it using idea from +// http://www.opensource.apple.com/source/Libc/Libc-825.40.1/pthreads/pthread_machdep.h +// +// In short: _pthread_{get,set}_specific_direct allows extremely fast +// access, exactly what is required for segmented stack +// There is a pool of reserved slots for Apple internal use (0..119) +// First dynamic allocated pthread key starts with 257 (on iOS7) +// So using slot 149 should be pretty safe ASSUMING space is reserved +// for every key < first dynamic key +// +// There is also an opportunity to steal keys reserved for Garbage Collection +// ranges 80..89 and 110..119, especially considering the fact Garbage Collection +// never supposed to work on iOS. But as everybody knows it - there is a chance +// that those slots will be re-used, like it happened with key 95 (moved from +// JavaScriptCore to CoreText) +// +// Unfortunately Apple rejected patch to LLVM which generated +// corresponding prolog, decision was taken to disable segmented +// stack support on iOS. + pub static RED_ZONE: uint = 20 * 1024; /// This function is invoked from rust's current __morestack function. Segmented @@ -193,7 +215,7 @@ pub unsafe fn record_sp_limit(limit: uint) { // mips, arm - Some brave soul can port these to inline asm, but it's over // my head personally #[cfg(target_arch = "mips")] - #[cfg(target_arch = "arm")] #[inline(always)] + #[cfg(target_arch = "arm", not(target_os = "ios"))] #[inline(always)] unsafe fn target_record_sp_limit(limit: uint) { use libc::c_void; return record_sp_limit(limit as *c_void); @@ -201,6 +223,11 @@ pub unsafe fn record_sp_limit(limit: uint) { fn record_sp_limit(limit: *c_void); } } + + // iOS segmented stack is disabled for now, see related notes + #[cfg(target_arch = "arm", target_os = "ios")] #[inline(always)] + unsafe fn target_record_sp_limit(_: uint) { + } } /// The counterpart of the function above, this function will fetch the current @@ -267,7 +294,7 @@ pub unsafe fn get_sp_limit() -> uint { // mips, arm - Some brave soul can port these to inline asm, but it's over // my head personally #[cfg(target_arch = "mips")] - #[cfg(target_arch = "arm")] #[inline(always)] + #[cfg(target_arch = "arm", not(target_os = "ios"))] #[inline(always)] unsafe fn target_get_sp_limit() -> uint { use libc::c_void; return get_sp_limit() as uint; @@ -275,4 +302,12 @@ pub unsafe fn get_sp_limit() -> uint { fn get_sp_limit() -> *c_void; } } + + // iOS doesn't support segmented stacks yet. This function might + // be called by runtime though so it is unsafe to mark it as + // unreachable, let's return a fixed constant. + #[cfg(target_arch = "arm", target_os = "ios")] #[inline(always)] + unsafe fn target_get_sp_limit() -> uint { + 1024 + } } diff --git a/src/rt/arch/arm/_context.S b/src/rt/arch/arm/_context.S index fb6db57414a..38fc4827f58 100644 --- a/src/rt/arch/arm/_context.S +++ b/src/rt/arch/arm/_context.S @@ -12,8 +12,16 @@ .align #endif -.globl rust_swap_registers -rust_swap_registers: +#if defined(__APPLE__) + #define SWAP_REGISTERS _rust_swap_registers + #define BOOTSTRAP_TASK _rust_bootstrap_green_task +#else + #define SWAP_REGISTERS rust_swap_registers + #define BOOTSTRAP_TASK rust_bootstrap_green_task +#endif + +.globl SWAP_REGISTERS +SWAP_REGISTERS: str r0, [r0, #0] str r3, [r0, #12] str r4, [r0, #16] @@ -53,9 +61,9 @@ rust_swap_registers: mov pc, lr // For reasons of this existence, see the comments in x86_64/_context.S -.globl rust_bootstrap_green_task -rust_bootstrap_green_task: - mov r0, r0 - mov r1, r3 - mov r2, r4 - mov pc, r5 +.globl BOOTSTRAP_TASK +BOOTSTRAP_TASK: + mov r0, r0 + mov r1, r3 + mov r2, r4 + mov pc, r5 diff --git a/src/rt/arch/arm/morestack.S b/src/rt/arch/arm/morestack.S index 219f0962d77..0b9012cc2a8 100644 --- a/src/rt/arch/arm/morestack.S +++ b/src/rt/arch/arm/morestack.S @@ -8,33 +8,63 @@ .text .code 32 .arm +#if defined(__APPLE__) +.align 2 +#else .align +#endif -.global rust_stack_exhausted -.global __morestack -.hidden __morestack +#if defined(__APPLE__) +#define MORESTACK ___morestack +#define STACK_EXHAUSTED _rust_stack_exhausted +#else +#define MORESTACK __morestack +#define STACK_EXHAUSTED rust_stack_exhausted +#endif + +.global STACK_EXHAUSTED +.global MORESTACK + +// Unfortunately LLVM yet doesn't support emitting correct debug +// DWARF information for non-ELF targets so to make it compile +// on iOS all that directives are simply commented out +#if defined(__APPLE__) +#define UNWIND @ +#else +#define UNWIND +#endif + +#if defined(__APPLE__) +.private_extern MORESTACK +#else +.hidden MORESTACK +#endif + +#if !defined(__APPLE__) + .type MORESTACK,%function +#endif // r4 and r5 are scratch registers for __morestack due to llvm // ARMFrameLowering::adjustForSegmentedStacks() implementation. - .type __morestack,%function -__morestack: - .fnstart - // Save frame pointer and return address - .save {r4, r5} - .save {lr} - .save {r6, fp, lr} +MORESTACK: + UNWIND .fnstart + + // Save frame pointer and return address + UNWIND .save {r4, r5} + UNWIND .save {lr} + UNWIND .save {r6, fp, lr} push {r6, fp, lr} - .movsp r6 - mov r6, sp - .setfp fp, sp, #4 - add fp, sp, #4 + UNWIND .movsp r6 + mov r6, sp + UNWIND .setfp fp, sp, #4 + add fp, sp, #4 // Save argument registers of the original function push {r0, r1, r2, r3, lr} // Create new stack - bl rust_stack_exhausted@plt + bl STACK_EXHAUSTED@plt // the above function ensures that it never returns - .fnend + UNWIND .fnend diff --git a/src/rt/arch/arm/record_sp.S b/src/rt/arch/arm/record_sp.S index cce14ed5a3e..94cfcff039e 100644 --- a/src/rt/arch/arm/record_sp.S +++ b/src/rt/arch/arm/record_sp.S @@ -1,3 +1,5 @@ +// Do not compile anything here for iOS +#if !defined(__APPLE__) // Mark stack as non-executable #if defined(__linux__) && defined(__ELF__) .section .note.GNU-stack, "", %progbits @@ -6,16 +8,15 @@ .text .code 32 .arm -#if defined(__APPLE__) -.align 2 -#else .align -#endif -.globl record_sp_limit -.globl get_sp_limit +#define RECORD_SP_LIMIT record_sp_limit +#define GET_SP_LIMIT get_sp_limit -record_sp_limit: +.globl RECORD_SP_LIMIT +.globl GET_SP_LIMIT + +RECORD_SP_LIMIT: // First, try to read TLS address from coprocessor mrc p15, #0, r3, c13, c0, #3 cmp r3, #0 @@ -27,12 +28,12 @@ record_sp_limit: add r3, r3, #252 #elif __linux__ add r3, r3, #4 -#endif +#endif // ANDROID str r0, [r3] mov pc, lr -get_sp_limit: +GET_SP_LIMIT: // First, try to read TLS address from coprocessor mrc p15, #0, r3, c13, c0, #3 cmp r3, #0 @@ -44,7 +45,8 @@ get_sp_limit: add r3, r3, #252 #elif __linux__ add r3, r3, #4 -#endif +#endif // __ANDROID__ ldr r0, [r3] mov pc, lr +#endif From 0c10c686824bf37084af87af84f338bcd2a7551a Mon Sep 17 00:00:00 2001 From: Valerii Hiora Date: Mon, 12 May 2014 20:03:34 +0300 Subject: [PATCH 04/10] Disable generating split-stack code Allows to compile for archs which do not have (or have limited) segmented stack support like embedded. --- src/librustc/middle/trans/base.rs | 21 ++++++++++++--------- src/librustc/middle/trans/context.rs | 20 ++++++++++++++++---- src/librustc/middle/trans/glue.rs | 2 +- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 9cebc79171f..594a62ea9b2 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -172,12 +172,12 @@ impl<'a> Drop for StatRecorder<'a> { } // only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions -fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv, +fn decl_fn(ccx: &CrateContext, name: &str, cc: lib::llvm::CallConv, ty: Type, output: ty::t) -> ValueRef { let llfn: ValueRef = name.with_c_str(|buf| { unsafe { - llvm::LLVMGetOrInsertFunction(llmod, buf, ty.to_ref()) + llvm::LLVMGetOrInsertFunction(ccx.llmod, buf, ty.to_ref()) } }); @@ -196,17 +196,20 @@ fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv, lib::llvm::SetFunctionCallConv(llfn, cc); // Function addresses in Rust are never significant, allowing functions to be merged. lib::llvm::SetUnnamedAddr(llfn, true); - set_split_stack(llfn); + + if ccx.is_split_stack_supported() { + set_split_stack(llfn); + } llfn } // only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions -pub fn decl_cdecl_fn(llmod: ModuleRef, +pub fn decl_cdecl_fn(ccx: &CrateContext, name: &str, ty: Type, output: ty::t) -> ValueRef { - decl_fn(llmod, name, lib::llvm::CCallConv, ty, output) + decl_fn(ccx, name, lib::llvm::CCallConv, ty, output) } // only use this for foreign function ABIs and glue, use `get_extern_rust_fn` for Rust functions @@ -221,7 +224,7 @@ pub fn get_extern_fn(ccx: &CrateContext, Some(n) => return *n, None => {} } - let f = decl_fn(ccx.llmod, name, cc, ty, output); + let f = decl_fn(ccx, name, cc, ty, output); externs.insert(name.to_string(), f); f } @@ -250,7 +253,7 @@ pub fn decl_rust_fn(ccx: &CrateContext, fn_ty: ty::t, name: &str) -> ValueRef { }; let llfty = type_of_rust_fn(ccx, has_env, inputs.as_slice(), output); - let llfn = decl_fn(ccx.llmod, name, lib::llvm::CCallConv, llfty, output); + let llfn = decl_fn(ccx, name, lib::llvm::CCallConv, llfty, output); let attrs = get_fn_llvm_attributes(ccx, fn_ty); for &(idx, attr) in attrs.iter() { unsafe { @@ -1877,7 +1880,7 @@ pub fn register_fn_llvmty(ccx: &CrateContext, llfty: Type) -> ValueRef { debug!("register_fn_llvmty id={} sym={}", node_id, sym); - let llfn = decl_fn(ccx.llmod, sym.as_slice(), cc, llfty, ty::mk_nil()); + let llfn = decl_fn(ccx, sym.as_slice(), cc, llfty, ty::mk_nil()); finish_register_fn(ccx, sp, sym, node_id, llfn); llfn } @@ -1909,7 +1912,7 @@ pub fn create_entry_wrapper(ccx: &CrateContext, let llfty = Type::func([ccx.int_type, Type::i8p(ccx).ptr_to()], &ccx.int_type); - let llfn = decl_cdecl_fn(ccx.llmod, "main", llfty, ty::mk_nil()); + let llfn = decl_cdecl_fn(ccx, "main", llfty, ty::mk_nil()); let llbb = "top".with_c_str(|buf| { unsafe { llvm::LLVMAppendBasicBlockInContext(ccx.llcx, llfn, buf) diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index a80ae9e2596..68c6f1752bd 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - use driver::config::NoDebugInfo; use driver::session::Session; use lib::llvm::{ContextRef, ModuleRef, ValueRef}; @@ -32,6 +31,7 @@ use std::c_str::ToCStr; use std::ptr; use std::rc::Rc; use std::collections::{HashMap, HashSet}; +use syntax::abi; use syntax::ast; use syntax::parse::token::InternedString; @@ -273,20 +273,32 @@ impl CrateContext { None => fail!() } } + + // Although there is an experimental implementation of LLVM which + // supports SS on armv7 it wasn't approved by Apple, see: + // http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20140505/216350.html + // It looks like it might be never accepted to upstream LLVM. + // + // So far the decision was to disable them in default builds + // but it could be enabled (with patched LLVM) + pub fn is_split_stack_supported(&self) -> bool { + let ref cfg = self.sess().targ_cfg; + cfg.os != abi::OsiOS || cfg.arch != abi::Arm + } } fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option { macro_rules! ifn ( ($name:expr fn() -> $ret:expr) => ( if *key == $name { - let f = base::decl_cdecl_fn(ccx.llmod, $name, Type::func([], &$ret), ty::mk_nil()); + let f = base::decl_cdecl_fn(ccx, $name, Type::func([], &$ret), ty::mk_nil()); ccx.intrinsics.borrow_mut().insert($name, f.clone()); return Some(f); } ); ($name:expr fn($($arg:expr),*) -> $ret:expr) => ( if *key == $name { - let f = base::decl_cdecl_fn(ccx.llmod, $name, + let f = base::decl_cdecl_fn(ccx, $name, Type::func([$($arg),*], &$ret), ty::mk_nil()); ccx.intrinsics.borrow_mut().insert($name, f.clone()); return Some(f); @@ -418,7 +430,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option $ret); } else if *key == $name { - let f = base::decl_cdecl_fn(ccx.llmod, stringify!($cname), + let f = base::decl_cdecl_fn(ccx, stringify!($cname), Type::func([$($arg),*], &$ret), ty::mk_nil()); ccx.intrinsics.borrow_mut().insert($name, f.clone()); diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 96aa7267d23..ef9bf4eebe2 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -462,7 +462,7 @@ fn declare_generic_glue(ccx: &CrateContext, t: ty::t, llfnty: Type, t, format!("glue_{}", name).as_slice()); debug!("{} is for type {}", fn_nm, ppaux::ty_to_str(ccx.tcx(), t)); - let llfn = decl_cdecl_fn(ccx.llmod, fn_nm.as_slice(), llfnty, ty::mk_nil()); + let llfn = decl_cdecl_fn(ccx, fn_nm.as_slice(), llfnty, ty::mk_nil()); note_unique_llvm_symbol(ccx, fn_nm); return llfn; } From a49b765f9a5b5926e338da30fcaae59ff1ae5c02 Mon Sep 17 00:00:00 2001 From: Valerii Hiora Date: Mon, 5 May 2014 10:07:49 +0300 Subject: [PATCH 05/10] Basic iOS support --- src/liblibc/lib.rs | 13 +++++ src/libnative/io/c_unix.rs | 7 +++ src/libnative/io/file_unix.rs | 3 +- src/libnative/io/mod.rs | 1 + src/libnative/io/net.rs | 3 +- src/libnative/io/process.rs | 1 + src/libnative/io/timer_unix.rs | 19 +++++- src/librustc/back/arm.rs | 8 +++ src/librustc/back/link.rs | 70 +++++++++++++++------- src/librustc/back/mips.rs | 8 +++ src/librustc/back/rpath.rs | 2 +- src/librustc/back/x86.rs | 8 +++ src/librustc/back/x86_64.rs | 6 ++ src/librustc/driver/config.rs | 7 ++- src/librustc/driver/session.rs | 1 - src/librustc/metadata/creader.rs | 3 +- src/librustc/metadata/loader.rs | 9 ++- src/librustc/middle/trans/cabi_x86.rs | 4 +- src/librustc/middle/trans/cleanup.rs | 2 +- src/librustc/middle/trans/debuginfo.rs | 3 +- src/librustdoc/flock.rs | 1 + src/librustrt/args.rs | 1 + src/librustrt/lib.rs | 2 +- src/librustrt/libunwind.rs | 25 +++++++- src/librustrt/local_ptr.rs | 5 +- src/librustrt/mutex.rs | 5 ++ src/librustrt/stack.rs | 12 ++-- src/librustrt/thread.rs | 2 - src/librustrt/thread_local_storage.rs | 3 +- src/librustrt/unwind.rs | 64 +++++++++++++++++++- src/libstd/dynamic_lib.rs | 3 +- src/libstd/os.rs | 81 ++++++++++++++++++++++++++ src/libstd/rand/os.rs | 69 +++++++++++++++++++++- src/libstd/rt/backtrace.rs | 60 ++++++++++++++++--- src/libstd/rtdeps.rs | 4 ++ src/libsyntax/abi.rs | 2 +- src/libtime/lib.rs | 9 ++- 37 files changed, 461 insertions(+), 65 deletions(-) diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index ff87b7fb007..9ed0d50a03e 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -278,10 +278,13 @@ pub use consts::os::extra::{MAP_STACK}; pub use consts::os::bsd44::{TCP_KEEPIDLE}; #[cfg(target_os = "macos")] +#[cfg(target_os = "ios")] pub use consts::os::bsd44::{TCP_KEEPALIVE}; #[cfg(target_os = "macos")] +#[cfg(target_os = "ios")] pub use consts::os::extra::{F_FULLFSYNC}; #[cfg(target_os = "macos")] +#[cfg(target_os = "ios")] pub use types::os::arch::extra::{mach_timebase_info}; @@ -1286,6 +1289,7 @@ pub mod types { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] pub mod os { pub mod common { pub mod posix01 { @@ -3106,6 +3110,7 @@ pub mod consts { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] pub mod os { pub mod c95 { use types::os::arch::c95::{c_int, c_uint}; @@ -3769,6 +3774,7 @@ pub mod funcs { #[cfg(target_os = "linux")] #[cfg(target_os = "android")] #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] #[cfg(target_os = "freebsd")] pub mod posix88 { pub mod stat_ { @@ -3783,6 +3789,7 @@ pub mod funcs { #[cfg(target_os = "linux")] #[cfg(target_os = "freebsd")] #[cfg(target_os = "android")] + #[cfg(target_os = "ios")] pub fn fstat(fildes: c_int, buf: *mut stat) -> c_int; #[cfg(target_os = "macos")] @@ -3795,6 +3802,7 @@ pub mod funcs { #[cfg(target_os = "linux")] #[cfg(target_os = "freebsd")] #[cfg(target_os = "android")] + #[cfg(target_os = "ios")] pub fn stat(path: *c_char, buf: *mut stat) -> c_int; #[cfg(target_os = "macos")] @@ -3967,6 +3975,7 @@ pub mod funcs { #[cfg(target_os = "linux")] #[cfg(target_os = "android")] #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] #[cfg(target_os = "freebsd")] pub mod posix01 { pub mod stat_ { @@ -3977,6 +3986,7 @@ pub mod funcs { #[cfg(target_os = "linux")] #[cfg(target_os = "freebsd")] #[cfg(target_os = "android")] + #[cfg(target_os = "ios")] pub fn lstat(path: *c_char, buf: *mut stat) -> c_int; #[cfg(target_os = "macos")] @@ -4076,6 +4086,7 @@ pub mod funcs { #[cfg(target_os = "linux")] #[cfg(target_os = "android")] #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] #[cfg(target_os = "freebsd")] pub mod posix08 { pub mod unistd { @@ -4156,6 +4167,7 @@ pub mod funcs { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] #[cfg(target_os = "freebsd")] pub mod bsd44 { use types::common::c95::{c_void}; @@ -4209,6 +4221,7 @@ pub mod funcs { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] pub mod extra { use types::os::arch::c95::{c_char, c_int}; diff --git a/src/libnative/io/c_unix.rs b/src/libnative/io/c_unix.rs index e6cb5cb76f1..70fd6310070 100644 --- a/src/libnative/io/c_unix.rs +++ b/src/libnative/io/c_unix.rs @@ -20,6 +20,7 @@ pub use self::signal::{SA_NODEFER, SA_NOCLDWAIT, SA_SIGINFO, SIGCHLD}; use libc; #[cfg(target_os = "macos")] +#[cfg(target_os = "ios")] #[cfg(target_os = "freebsd")] pub static FIONBIO: libc::c_ulong = 0x8004667e; #[cfg(target_os = "linux", not(target_arch = "mips"))] @@ -29,6 +30,7 @@ pub static FIONBIO: libc::c_ulong = 0x5421; pub static FIONBIO: libc::c_ulong = 0x667e; #[cfg(target_os = "macos")] +#[cfg(target_os = "ios")] #[cfg(target_os = "freebsd")] pub static FIOCLEX: libc::c_ulong = 0x20006601; #[cfg(target_os = "linux", not(target_arch = "mips"))] @@ -38,6 +40,7 @@ pub static FIOCLEX: libc::c_ulong = 0x5451; pub static FIOCLEX: libc::c_ulong = 0x6601; #[cfg(target_os = "macos")] +#[cfg(target_os = "ios")] #[cfg(target_os = "freebsd")] pub static MSG_DONTWAIT: libc::c_int = 0x80; #[cfg(target_os = "linux")] @@ -75,6 +78,7 @@ extern { } #[cfg(target_os = "macos")] +#[cfg(target_os = "ios")] mod select { pub static FD_SETSIZE: uint = 1024; @@ -187,6 +191,7 @@ mod signal { } #[cfg(target_os = "macos")] +#[cfg(target_os = "ios")] #[cfg(target_os = "freebsd")] mod signal { use libc; @@ -201,6 +206,7 @@ mod signal { pub static SIGCHLD: libc::c_int = 20; #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] pub type sigset_t = u32; #[cfg(target_os = "freebsd")] pub struct sigset_t { @@ -219,6 +225,7 @@ mod signal { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] pub struct sigaction { pub sa_handler: extern fn(libc::c_int), sa_tramp: *mut libc::c_void, diff --git a/src/libnative/io/file_unix.rs b/src/libnative/io/file_unix.rs index fda9b7b1932..f521934c0f9 100644 --- a/src/libnative/io/file_unix.rs +++ b/src/libnative/io/file_unix.rs @@ -133,6 +133,7 @@ impl rtio::RtioFileStream for FileDesc { return super::mkerr_libc(os_datasync(self.fd())); #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] fn os_datasync(fd: c_int) -> c_int { unsafe { libc::fcntl(fd, libc::F_FULLFSYNC) } } @@ -140,7 +141,7 @@ impl rtio::RtioFileStream for FileDesc { fn os_datasync(fd: c_int) -> c_int { retry(|| unsafe { libc::fdatasync(fd) }) } - #[cfg(not(target_os = "macos"), not(target_os = "linux"))] + #[cfg(not(target_os = "macos"), not(target_os = "ios"), not(target_os = "linux"))] fn os_datasync(fd: c_int) -> c_int { retry(|| unsafe { libc::fsync(fd) }) } diff --git a/src/libnative/io/mod.rs b/src/libnative/io/mod.rs index 4158db7bb8e..6dc2482ab0c 100644 --- a/src/libnative/io/mod.rs +++ b/src/libnative/io/mod.rs @@ -50,6 +50,7 @@ pub mod file; pub mod file; #[cfg(target_os = "macos")] +#[cfg(target_os = "ios")] #[cfg(target_os = "freebsd")] #[cfg(target_os = "android")] #[cfg(target_os = "linux")] diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index e7effbd6bdb..30ea80a1296 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -320,6 +320,7 @@ impl TcpStream { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] fn set_tcp_keepalive(&mut self, seconds: uint) -> IoResult<()> { setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPALIVE, seconds as libc::c_int) @@ -329,7 +330,7 @@ impl TcpStream { setsockopt(self.fd(), libc::IPPROTO_TCP, libc::TCP_KEEPIDLE, seconds as libc::c_int) } - #[cfg(not(target_os = "macos"), not(target_os = "freebsd"))] + #[cfg(not(target_os = "macos"), not(target_os = "ios"), not(target_os = "freebsd"))] fn set_tcp_keepalive(&mut self, _seconds: uint) -> IoResult<()> { Ok(()) } diff --git a/src/libnative/io/process.rs b/src/libnative/io/process.rs index d8486cb9f09..f26d87ba1b5 100644 --- a/src/libnative/io/process.rs +++ b/src/libnative/io/process.rs @@ -769,6 +769,7 @@ fn translate_status(status: c_int) -> rtio::ProcessExit { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] #[cfg(target_os = "freebsd")] mod imp { pub fn WIFEXITED(status: i32) -> bool { (status & 0x7f) == 0 } diff --git a/src/libnative/io/timer_unix.rs b/src/libnative/io/timer_unix.rs index 11f9c4b3d8c..ca0a810890c 100644 --- a/src/libnative/io/timer_unix.rs +++ b/src/libnative/io/timer_unix.rs @@ -93,7 +93,20 @@ pub fn now() -> u64 { } } -fn helper(input: libc::c_int, messages: Receiver, _: ()) { + +// Note: although the last parameter isn't used there is no way now to +// convert it to unit type, because LLVM dies in SjLj preparation +// step (unfortunately iOS uses SjLJ exceptions) +// +// It's definitely a temporary workaround just to get it working. +// So far it looks like an LLVM issue and it was reported: +// http://llvm.org/bugs/show_bug.cgi?id=19855 +// Actually this issue is pretty common while compiling for armv7 iOS +// and in most cases it is simply solved by using --opt-level=2 (or -O) +// +// For this specific case unfortunately turning optimizations wasn't +// enough. +fn helper(input: libc::c_int, messages: Receiver, _: int) { let mut set: c::fd_set = unsafe { mem::zeroed() }; let mut fd = FileDesc::new(input, true); @@ -202,7 +215,9 @@ fn helper(input: libc::c_int, messages: Receiver, _: ()) { impl Timer { pub fn new() -> IoResult { - unsafe { HELPER.boot(|| {}, helper); } + // See notes above regarding using int return value + // instead of () + unsafe { HELPER.boot(|| {0}, helper); } static mut ID: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT; let id = unsafe { ID.fetch_add(1, atomics::Relaxed) }; diff --git a/src/librustc/back/arm.rs b/src/librustc/back/arm.rs index e5e8126ace1..7a944fd5abe 100644 --- a/src/librustc/back/arm.rs +++ b/src/librustc/back/arm.rs @@ -34,6 +34,14 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs -a0:0:64-n32".to_string() } + abi::OsiOS => { + "e-p:32:32:32\ + -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\ + -f32:32:32-f64:64:64\ + -v64:64:64-v128:64:128\ + -a0:0:64-n32".to_string() + } + abi::OsWin32 => { "e-p:32:32:32\ -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\ diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 55998f254ed..ab4eda33d75 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -114,6 +114,13 @@ pub mod write { // which are *far* more efficient. This is obviously undesirable in some // cases, so if any sort of target feature is specified we don't append v7 // to the feature list. + // + // On iOS only armv7 and newer are supported. So it is useful to + // get all hardware potential via VFP3 (hardware floating point) + // and NEON (SIMD) instructions supported by LLVM. + // Note that without those flags various linking errors might + // arise as some of intrinsicts are converted into function calls + // and nobody provides implementations those functions fn target_feature<'a>(sess: &'a Session) -> &'a str { match sess.targ_cfg.os { abi::OsAndroid => { @@ -122,7 +129,10 @@ pub mod write { } else { sess.opts.cg.target_feature.as_slice() } - } + }, + abi::OsiOS if sess.targ_cfg.arch == abi::Arm => { + "+v7,+thumb2,+vfp3,+neon" + }, _ => sess.opts.cg.target_feature.as_slice() } } @@ -827,15 +837,23 @@ pub fn filename_for_input(sess: &Session, crate_type: config::CrateType, out_filename.with_filename(format!("lib{}.rlib", libname)) } config::CrateTypeDylib => { - let (prefix, suffix) = match sess.targ_cfg.os { - abi::OsWin32 => (loader::WIN32_DLL_PREFIX, loader::WIN32_DLL_SUFFIX), - abi::OsMacos => (loader::MACOS_DLL_PREFIX, loader::MACOS_DLL_SUFFIX), - abi::OsLinux => (loader::LINUX_DLL_PREFIX, loader::LINUX_DLL_SUFFIX), - abi::OsAndroid => (loader::ANDROID_DLL_PREFIX, loader::ANDROID_DLL_SUFFIX), - abi::OsFreebsd => (loader::FREEBSD_DLL_PREFIX, loader::FREEBSD_DLL_SUFFIX), - }; - out_filename.with_filename(format!("{}{}{}", prefix, libname, - suffix)) + // There is no support of DyLibs on iOS + if sess.targ_cfg.os == abi::OsiOS { + out_filename.with_filename(format!("lib{}.a", libname)) + } else { + let (prefix, suffix) = match sess.targ_cfg.os { + abi::OsWin32 => (loader::WIN32_DLL_PREFIX, loader::WIN32_DLL_SUFFIX), + abi::OsMacos => (loader::MACOS_DLL_PREFIX, loader::MACOS_DLL_SUFFIX), + abi::OsLinux => (loader::LINUX_DLL_PREFIX, loader::LINUX_DLL_SUFFIX), + abi::OsAndroid => (loader::ANDROID_DLL_PREFIX, loader::ANDROID_DLL_SUFFIX), + abi::OsFreebsd => (loader::FREEBSD_DLL_PREFIX, loader::FREEBSD_DLL_SUFFIX), + abi::OsiOS => unreachable!(), + }; + out_filename.with_filename(format!("{}{}{}", + prefix, + libname, + suffix)) + } } config::CrateTypeStaticlib => { out_filename.with_filename(format!("lib{}.a", libname)) @@ -886,7 +904,14 @@ fn link_binary_output(sess: &Session, link_natively(sess, trans, false, &obj_filename, &out_filename); } config::CrateTypeDylib => { - link_natively(sess, trans, true, &obj_filename, &out_filename); + if sess.targ_cfg.os == abi::OsiOS { + sess.warn(format!("No dylib for iOS -> saving static library {} to {}", + obj_filename.display(), out_filename.display()).as_slice()); + link_staticlib(sess, &obj_filename, &out_filename); + } + else { + link_natively(sess, trans, true, &obj_filename, &out_filename); + } } } @@ -991,7 +1016,7 @@ fn link_rlib<'a>(sess: &'a Session, // symbol table of the archive. This currently dies on OSX (see // #11162), and isn't necessary there anyway match sess.targ_cfg.os { - abi::OsMacos => {} + abi::OsMacos | abi::OsiOS => {} _ => { a.update_symbols(); } } } @@ -1104,15 +1129,16 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool, // On OSX, debuggers need this utility to get run to do some munging of // the symbols - if sess.targ_cfg.os == abi::OsMacos && (sess.opts.debuginfo != NoDebugInfo) { - match Command::new("dsymutil").arg(out_filename).status() { - Ok(..) => {} - Err(e) => { - sess.err(format!("failed to run dsymutil: {}", e).as_slice()); - sess.abort_if_errors(); + if (sess.targ_cfg.os == abi::OsMacos || sess.targ_cfg.os == abi::OsiOS) + && (sess.opts.debuginfo != NoDebugInfo) { + match Command::new("dsymutil").arg(out_filename).status() { + Ok(..) => {} + Err(e) => { + sess.err(format!("failed to run dsymutil: {}", e).as_slice()); + sess.abort_if_errors(); + } } } - } } fn link_args(cmd: &mut Command, @@ -1169,7 +1195,7 @@ fn link_args(cmd: &mut Command, // already done the best it can do, and we also don't want to eliminate the // metadata. If we're building an executable, however, --gc-sections drops // the size of hello world from 1.8MB to 597K, a 67% reduction. - if !dylib && sess.targ_cfg.os != abi::OsMacos { + if !dylib && sess.targ_cfg.os != abi::OsMacos && sess.targ_cfg.os != abi::OsiOS { cmd.arg("-Wl,--gc-sections"); } @@ -1185,7 +1211,7 @@ fn link_args(cmd: &mut Command, sess.opts.optimize == config::Aggressive { cmd.arg("-Wl,-O1"); } - } else if sess.targ_cfg.os == abi::OsMacos { + } else if sess.targ_cfg.os == abi::OsMacos || sess.targ_cfg.os == abi::OsiOS { // The dead_strip option to the linker specifies that functions and data // unreachable by the entry point will be removed. This is quite useful // with Rust's compilation model of compiling libraries at a time into @@ -1348,7 +1374,7 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) { // For those that support this, we ensure we pass the option if the library // was flagged "static" (most defaults are dynamic) to ensure that if // libfoo.a and libfoo.so both exist that the right one is chosen. - let takes_hints = sess.targ_cfg.os != abi::OsMacos; + let takes_hints = sess.targ_cfg.os != abi::OsMacos && sess.targ_cfg.os != abi::OsiOS; for &(ref l, kind) in sess.cstore.get_used_libraries().borrow().iter() { match kind { diff --git a/src/librustc/back/mips.rs b/src/librustc/back/mips.rs index 9f640a2c9cb..ea9879dbf49 100644 --- a/src/librustc/back/mips.rs +++ b/src/librustc/back/mips.rs @@ -29,6 +29,14 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs -a0:0:64-n32".to_string() } + abi::OsiOS => { + "E-p:32:32:32\ + -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\ + -f32:32:32-f64:64:64\ + -v64:64:64-v128:64:128\ + -a0:0:64-n32".to_string() + } + abi::OsWin32 => { "E-p:32:32:32\ -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\ diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs index cdf49304f9a..a458cf22a5b 100644 --- a/src/librustc/back/rpath.rs +++ b/src/librustc/back/rpath.rs @@ -122,7 +122,7 @@ pub fn get_rpath_relative_to_output(os: abi::Os, abi::OsAndroid | abi::OsLinux | abi::OsFreebsd => "$ORIGIN", abi::OsMacos => "@loader_path", - abi::OsWin32 => unreachable!() + abi::OsWin32 | abi::OsiOS => unreachable!() }; let mut lib = fs::realpath(&os::make_absolute(lib)).unwrap(); diff --git a/src/librustc/back/x86.rs b/src/librustc/back/x86.rs index 3ef013d47c9..90106e9e030 100644 --- a/src/librustc/back/x86.rs +++ b/src/librustc/back/x86.rs @@ -31,6 +31,14 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -n8:16:32".to_string() } + abi::OsiOS => { + "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16\ + -i32:32:32-i64:32:64\ + -f32:32:32-f64:32:64-v64:64:64\ + -v128:128:128-a0:0:64-f80:128:128\ + -n8:16:32".to_string() + } + abi::OsWin32 => { "e-p:32:32-f64:64:64-i64:64:64-f80:32:32-n8:16:32".to_string() } diff --git a/src/librustc/back/x86_64.rs b/src/librustc/back/x86_64.rs index 80dd2b2c516..55b0eca7be7 100644 --- a/src/librustc/back/x86_64.rs +++ b/src/librustc/back/x86_64.rs @@ -28,6 +28,12 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs s0:64:64-f80:128:128-n8:16:32:64".to_string() } + abi::OsiOS => { + "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\ + f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\ + s0:64:64-f80:128:128-n8:16:32:64".to_string() + } + abi::OsWin32 => { // FIXME: Test this. Copied from linux (#2398) "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\ diff --git a/src/librustc/driver/config.rs b/src/librustc/driver/config.rs index 186db839e33..2f7dc136ef2 100644 --- a/src/librustc/driver/config.rs +++ b/src/librustc/driver/config.rs @@ -362,7 +362,8 @@ pub fn cfg_os_to_meta_os(os: abi::Os) -> metadata::loader::Os { abi::OsLinux => loader::OsLinux, abi::OsAndroid => loader::OsAndroid, abi::OsMacos => loader::OsMacos, - abi::OsFreebsd => loader::OsFreebsd + abi::OsFreebsd => loader::OsFreebsd, + abi::OsiOS => loader::OsiOS, } } @@ -373,6 +374,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig { abi::OsLinux => InternedString::new("linux"), abi::OsAndroid => InternedString::new("android"), abi::OsFreebsd => InternedString::new("freebsd"), + abi::OsiOS => InternedString::new("ios"), }; // ARM is bi-endian, however using NDK seems to default @@ -438,7 +440,8 @@ static os_names : &'static [(&'static str, abi::Os)] = &'static [ ("darwin", abi::OsMacos), ("android", abi::OsAndroid), ("linux", abi::OsLinux), - ("freebsd", abi::OsFreebsd)]; + ("freebsd", abi::OsFreebsd), + ("ios", abi::OsiOS)]; pub fn get_arch(triple: &str) -> Option { for &(arch, abi) in architecture_abis.iter() { diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 773b9e6e0aa..bc22b3ca7e2 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -249,4 +249,3 @@ pub fn expect(sess: &Session, opt: Option, msg: || -> String) -> T { diagnostic::expect(sess.diagnostic(), opt, msg) } - diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 4df21fbc974..63b177b0eb7 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -215,7 +215,8 @@ fn visit_item(e: &Env, i: &ast::Item) { Some(k) => { if k.equiv(&("static")) { cstore::NativeStatic - } else if e.sess.targ_cfg.os == abi::OsMacos && + } else if (e.sess.targ_cfg.os == abi::OsMacos || + e.sess.targ_cfg.os == abi::OsiOS) && k.equiv(&("framework")) { cstore::NativeFramework } else if k.equiv(&("framework")) { diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index cfda97ad26f..a674b6cf5a9 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -39,6 +39,9 @@ use time; pub static MACOS_DLL_PREFIX: &'static str = "lib"; pub static MACOS_DLL_SUFFIX: &'static str = ".dylib"; +pub static IOS_DLL_PREFIX: &'static str = "lib"; +pub static IOS_DLL_SUFFIX: &'static str = ".dylib"; + pub static WIN32_DLL_PREFIX: &'static str = ""; pub static WIN32_DLL_SUFFIX: &'static str = ".dll"; @@ -56,7 +59,8 @@ pub enum Os { OsWin32, OsLinux, OsAndroid, - OsFreebsd + OsFreebsd, + OsiOS } pub struct CrateMismatch { @@ -455,6 +459,7 @@ impl<'a> Context<'a> { OsLinux => (LINUX_DLL_PREFIX, LINUX_DLL_SUFFIX), OsAndroid => (ANDROID_DLL_PREFIX, ANDROID_DLL_SUFFIX), OsFreebsd => (FREEBSD_DLL_PREFIX, FREEBSD_DLL_SUFFIX), + OsiOS => (IOS_DLL_PREFIX, IOS_DLL_SUFFIX), } } @@ -593,6 +598,7 @@ fn get_metadata_section_imp(os: Os, filename: &Path) -> Result &'static str { match os { OsMacos => "__DATA,__note.rustc", + OsiOS => "__DATA,__note.rustc", OsWin32 => ".note.rustc", OsLinux => ".note.rustc", OsAndroid => ".note.rustc", @@ -603,6 +609,7 @@ pub fn meta_section_name(os: Os) -> &'static str { pub fn read_meta_section_name(os: Os) -> &'static str { match os { OsMacos => "__note.rustc", + OsiOS => "__note.rustc", OsWin32 => ".note.rustc", OsLinux => ".note.rustc", OsAndroid => ".note.rustc", diff --git a/src/librustc/middle/trans/cabi_x86.rs b/src/librustc/middle/trans/cabi_x86.rs index 93b6fdd8988..d10f6b72820 100644 --- a/src/librustc/middle/trans/cabi_x86.rs +++ b/src/librustc/middle/trans/cabi_x86.rs @@ -9,7 +9,7 @@ // except according to those terms. -use syntax::abi::{OsWin32, OsMacos}; +use syntax::abi::{OsWin32, OsMacos, OsiOS}; use lib::llvm::*; use super::cabi::*; use super::common::*; @@ -36,7 +36,7 @@ pub fn compute_abi_info(ccx: &CrateContext, enum Strategy { RetValue(Type), RetPointer } let strategy = match ccx.sess().targ_cfg.os { - OsWin32 | OsMacos => { + OsWin32 | OsMacos | OsiOS => { match llsize_of_alloc(ccx, rty) { 1 => RetValue(Type::i8(ccx)), 2 => RetValue(Type::i16(ccx)), diff --git a/src/librustc/middle/trans/cleanup.rs b/src/librustc/middle/trans/cleanup.rs index b28db3d378b..24f30bae75a 100644 --- a/src/librustc/middle/trans/cleanup.rs +++ b/src/librustc/middle/trans/cleanup.rs @@ -680,7 +680,7 @@ impl<'a> CleanupHelperMethods<'a> for FunctionContext<'a> { Some(llpersonality) => llpersonality, None => { let fty = Type::variadic_func(&[], &Type::i32(self.ccx)); - let f = base::decl_cdecl_fn(self.ccx.llmod, + let f = base::decl_cdecl_fn(self.ccx, "rust_eh_personality", fty, ty::mk_i32()); diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index db17000abb3..c50badac531 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -277,7 +277,8 @@ pub fn finalize(cx: &CrateContext) { // instruct LLVM to emit an older version of dwarf, however, // for OS X to understand. For more info see #11352 // This can be overridden using --llvm-opts -dwarf-version,N. - if cx.sess().targ_cfg.os == abi::OsMacos { + if cx.sess().targ_cfg.os == abi::OsMacos || + cx.sess().targ_cfg.os == abi::OsiOS { "Dwarf Version".with_c_str( |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s, 2)); } else { diff --git a/src/librustdoc/flock.rs b/src/librustdoc/flock.rs index 8ad10a686e6..800e7f065f1 100644 --- a/src/librustdoc/flock.rs +++ b/src/librustdoc/flock.rs @@ -64,6 +64,7 @@ mod imp { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] mod os { use libc; diff --git a/src/librustrt/args.rs b/src/librustrt/args.rs index 0789bf7f906..d6d4b18051b 100644 --- a/src/librustrt/args.rs +++ b/src/librustrt/args.rs @@ -145,6 +145,7 @@ mod imp { } #[cfg(target_os = "macos")] +#[cfg(target_os = "ios")] #[cfg(target_os = "win32")] mod imp { use core::prelude::*; diff --git a/src/librustrt/lib.rs b/src/librustrt/lib.rs index 76cbeef443e..e17a43322ba 100644 --- a/src/librustrt/lib.rs +++ b/src/librustrt/lib.rs @@ -164,7 +164,7 @@ pub unsafe fn cleanup() { pub mod shouldnt_be_public { #[cfg(not(test))] pub use super::local_ptr::native::maybe_tls_key; - #[cfg(not(windows), not(target_os = "android"))] + #[cfg(not(windows), not(target_os = "android"), not(target_os = "ios"))] pub use super::local_ptr::compiled::RT_TLS_PTR; } diff --git a/src/librustrt/libunwind.rs b/src/librustrt/libunwind.rs index 846ec248805..50c2aba2b5c 100644 --- a/src/librustrt/libunwind.rs +++ b/src/librustrt/libunwind.rs @@ -17,6 +17,7 @@ use libc; #[cfg(not(target_arch = "arm"))] +#[cfg(target_os = "ios")] #[repr(C)] pub enum _Unwind_Action { _UA_SEARCH_PHASE = 1, @@ -61,9 +62,12 @@ pub static unwinder_private_data_size: int = 5; #[cfg(target_arch = "x86_64")] pub static unwinder_private_data_size: int = 2; -#[cfg(target_arch = "arm")] +#[cfg(target_arch = "arm", not(target_os = "ios"))] pub static unwinder_private_data_size: int = 20; +#[cfg(target_arch = "arm", target_os = "ios")] +pub static unwinder_private_data_size: int = 5; + #[cfg(target_arch = "mips")] pub static unwinder_private_data_size: int = 2; @@ -89,8 +93,27 @@ extern {} #[link(name = "gcc")] extern {} + extern "C" { + // iOS on armv7 uses SjLj exceptions and requires to link + // agains corresponding routine (..._SjLj_...) + // So here we just skip linking for iOS + #[cfg(not(target_os = "ios", target_arch = "arm"))] pub fn _Unwind_RaiseException(exception: *_Unwind_Exception) -> _Unwind_Reason_Code; pub fn _Unwind_DeleteException(exception: *_Unwind_Exception); } + +// ... and now we just providing access to SjLj counterspart +// through a standard name to hide those details from others +// (see also comment above regarding _Unwind_RaiseException) +#[cfg(target_os = "ios", target_arch = "arm")] +#[inline(always)] +pub unsafe fn _Unwind_RaiseException(exc: *_Unwind_Exception) + -> _Unwind_Reason_Code { + extern "C" { + fn _Unwind_SjLj_RaiseException(e: *_Unwind_Exception) + -> _Unwind_Reason_Code; } + + _Unwind_SjLj_RaiseException(exc) +} diff --git a/src/librustrt/local_ptr.rs b/src/librustrt/local_ptr.rs index 91e3409892e..b6858be32b7 100644 --- a/src/librustrt/local_ptr.rs +++ b/src/librustrt/local_ptr.rs @@ -24,10 +24,11 @@ use alloc::owned::Box; #[cfg(windows)] // mingw-w32 doesn't like thread_local things #[cfg(target_os = "android")] // see #10686 +#[cfg(target_os = "ios")] pub use self::native::{init, cleanup, put, take, try_take, unsafe_take, exists, unsafe_borrow, try_unsafe_borrow}; -#[cfg(not(windows), not(target_os = "android"))] +#[cfg(not(windows), not(target_os = "android"), not(target_os = "ios"))] pub use self::compiled::{init, cleanup, put, take, try_take, unsafe_take, exists, unsafe_borrow, try_unsafe_borrow}; @@ -81,7 +82,7 @@ pub unsafe fn borrow() -> Borrowed { /// implemented using LLVM's thread_local attribute which isn't necessarily /// working on all platforms. This implementation is faster, however, so we use /// it wherever possible. -#[cfg(not(windows), not(target_os = "android"))] +#[cfg(not(windows), not(target_os = "android"), not(target_os = "ios"))] pub mod compiled { use core::prelude::*; diff --git a/src/librustrt/mutex.rs b/src/librustrt/mutex.rs index eec19e9d5db..26359ff7f6e 100644 --- a/src/librustrt/mutex.rs +++ b/src/librustrt/mutex.rs @@ -283,6 +283,7 @@ mod imp { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] mod os { use libc; @@ -294,6 +295,10 @@ mod imp { static __PTHREAD_MUTEX_SIZE__: uint = 40; #[cfg(target_arch = "x86")] static __PTHREAD_COND_SIZE__: uint = 24; + #[cfg(target_arch = "arm")] + static __PTHREAD_MUTEX_SIZE__: uint = 40; + #[cfg(target_arch = "arm")] + static __PTHREAD_COND_SIZE__: uint = 24; static _PTHREAD_MUTEX_SIG_init: libc::c_long = 0x32AAABA7; static _PTHREAD_COND_SIG_init: libc::c_long = 0x3CB0B1BB; diff --git a/src/librustrt/stack.rs b/src/librustrt/stack.rs index aac773f6f85..e6fa845bedc 100644 --- a/src/librustrt/stack.rs +++ b/src/librustrt/stack.rs @@ -173,7 +173,8 @@ pub unsafe fn record_sp_limit(limit: uint) { return target_record_sp_limit(limit); // x86-64 - #[cfg(target_arch = "x86_64", target_os = "macos")] #[inline(always)] + #[cfg(target_arch = "x86_64", target_os = "macos")] + #[cfg(target_arch = "x86_64", target_os = "ios")] #[inline(always)] unsafe fn target_record_sp_limit(limit: uint) { asm!("movq $$0x60+90*8, %rsi movq $0, %gs:(%rsi)" :: "r"(limit) : "rsi" : "volatile") @@ -195,7 +196,8 @@ pub unsafe fn record_sp_limit(limit: uint) { } // x86 - #[cfg(target_arch = "x86", target_os = "macos")] #[inline(always)] + #[cfg(target_arch = "x86", target_os = "macos")] + #[cfg(target_arch = "x86", target_os = "ios")] #[inline(always)] unsafe fn target_record_sp_limit(limit: uint) { asm!("movl $$0x48+90*4, %eax movl $0, %gs:(%eax)" :: "r"(limit) : "eax" : "volatile") @@ -243,7 +245,8 @@ pub unsafe fn get_sp_limit() -> uint { return target_get_sp_limit(); // x86-64 - #[cfg(target_arch = "x86_64", target_os = "macos")] #[inline(always)] + #[cfg(target_arch = "x86_64", target_os = "macos")] + #[cfg(target_arch = "x86_64", target_os = "ios")] #[inline(always)] unsafe fn target_get_sp_limit() -> uint { let limit; asm!("movq $$0x60+90*8, %rsi @@ -270,7 +273,8 @@ pub unsafe fn get_sp_limit() -> uint { } // x86 - #[cfg(target_arch = "x86", target_os = "macos")] #[inline(always)] + #[cfg(target_arch = "x86", target_os = "macos")] + #[cfg(target_arch = "x86", target_os = "ios")] #[inline(always)] unsafe fn target_get_sp_limit() -> uint { let limit; asm!("movl $$0x48+90*4, %eax diff --git a/src/librustrt/thread.rs b/src/librustrt/thread.rs index 4ef2cec19db..3dcd1c4a6f0 100644 --- a/src/librustrt/thread.rs +++ b/src/librustrt/thread.rs @@ -276,7 +276,6 @@ mod imp { } pub unsafe fn yield_now() { assert_eq!(sched_yield(), 0); } - // glibc >= 2.15 has a __pthread_get_minstack() function that returns // PTHREAD_STACK_MIN plus however many bytes are needed for thread-local // storage. We need that information to avoid blowing up when a small stack @@ -345,4 +344,3 @@ mod tests { assert_eq!(42, Thread::start_stack(1, proc () 42).join()); } } - diff --git a/src/librustrt/thread_local_storage.rs b/src/librustrt/thread_local_storage.rs index 2cdeb21fb83..4a7be39e6b8 100644 --- a/src/librustrt/thread_local_storage.rs +++ b/src/librustrt/thread_local_storage.rs @@ -37,13 +37,14 @@ pub unsafe fn destroy(key: Key) { assert!(pthread_key_delete(key) == 0); } -#[cfg(target_os="macos")] +#[cfg(target_os = "macos")] #[allow(non_camel_case_types)] // foreign type type pthread_key_t = ::libc::c_ulong; #[cfg(target_os="linux")] #[cfg(target_os="freebsd")] #[cfg(target_os="android")] +#[cfg(target_os = "ios")] #[allow(non_camel_case_types)] // foreign type type pthread_key_t = ::libc::c_uint; diff --git a/src/librustrt/unwind.rs b/src/librustrt/unwind.rs index f7475db1552..e60c50f0adb 100644 --- a/src/librustrt/unwind.rs +++ b/src/librustrt/unwind.rs @@ -285,16 +285,74 @@ pub mod eabi { } else { // cleanup phase unsafe { - __gcc_personality_v0(version, actions, exception_class, ue_header, + __gcc_personality_v0(version, actions, exception_class, ue_header, + context) + } + } + } +} + +// iOS on armv7 is using SjLj exceptions and therefore requires to use +// a specialized personality routine: __gcc_personality_sj0 + +#[cfg(target_os = "ios", target_arch = "arm", not(test))] +#[doc(hidden)] +#[allow(visible_private_types)] +pub mod eabi { + use uw = libunwind; + use libc::c_int; + + extern "C" { + #[cfg(target_os = "ios", target_arch = "arm")] + fn __gcc_personality_sj0(version: c_int, + actions: uw::_Unwind_Action, + exception_class: uw::_Unwind_Exception_Class, + ue_header: *uw::_Unwind_Exception, + context: *uw::_Unwind_Context) + -> uw::_Unwind_Reason_Code; + } + + #[lang="eh_personality"] + #[no_mangle] // so we can reference it by name from middle/trans/base.rs + pub extern "C" fn rust_eh_personality( + version: c_int, + actions: uw::_Unwind_Action, + exception_class: uw::_Unwind_Exception_Class, + ue_header: *uw::_Unwind_Exception, + context: *uw::_Unwind_Context + ) -> uw::_Unwind_Reason_Code + { + unsafe { + __gcc_personality_sj0(version, actions, exception_class, ue_header, + context) + } + } + + #[no_mangle] // referenced from rust_try.ll + pub extern "C" fn rust_eh_personality_catch( + version: c_int, + actions: uw::_Unwind_Action, + exception_class: uw::_Unwind_Exception_Class, + ue_header: *uw::_Unwind_Exception, + context: *uw::_Unwind_Context + ) -> uw::_Unwind_Reason_Code + { + if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 { // search phase + uw::_URC_HANDLER_FOUND // catch! + } + else { // cleanup phase + unsafe { + __gcc_personality_sj0(version, actions, exception_class, ue_header, context) } } } } + // ARM EHABI uses a slightly different personality routine signature, // but otherwise works the same. -#[cfg(target_arch = "arm", not(test))] +#[cfg(target_arch = "arm", not(test), not(target_os = "ios"))] #[allow(visible_private_types)] pub mod eabi { use uw = libunwind; @@ -332,7 +390,7 @@ pub mod eabi { } else { // cleanup phase unsafe { - __gcc_personality_v0(state, ue_header, context) + __gcc_personality_v0(state, ue_header, context) } } } diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index fa6efc8a4b1..5dbed6844c3 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -153,7 +153,7 @@ impl DynamicLibrary { } } -#[cfg(test)] +#[cfg(test, not(target_os = "ios"))] mod test { use super::*; use prelude::*; @@ -205,6 +205,7 @@ mod test { #[cfg(target_os = "linux")] #[cfg(target_os = "android")] #[cfg(target_os = "macos")] +#[cfg(target_os = "ios")] #[cfg(target_os = "freebsd")] pub mod dl { use prelude::*; diff --git a/src/libstd/os.rs b/src/libstd/os.rs index cc76cde7baf..f6b1c04dd34 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -552,6 +552,7 @@ pub fn pipe() -> Pipe { /// Returns the proper dll filename for the given basename of a file /// as a String. +#[cfg(not(target_os="ios"))] pub fn dll_filename(base: &str) -> String { format!("{}{}{}", consts::DLL_PREFIX, base, consts::DLL_SUFFIX) } @@ -608,6 +609,7 @@ pub fn self_exe_name() -> Option { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] fn load_self() -> Option> { unsafe { use libc::funcs::extra::_NSGetExecutablePath; @@ -802,6 +804,7 @@ pub fn change_dir(p: &Path) -> bool { /// Returns the platform-specific value of errno pub fn errno() -> int { #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] #[cfg(target_os = "freebsd")] fn errno_location() -> *c_int { extern { @@ -850,6 +853,7 @@ pub fn error_string(errnum: uint) -> String { #[cfg(unix)] fn strerror(errnum: uint) -> String { #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] #[cfg(target_os = "android")] #[cfg(target_os = "freebsd")] fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: libc::size_t) @@ -995,6 +999,64 @@ fn real_args_as_bytes() -> Vec> { } } +// As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs +// and use underscores in their names - they're most probably +// are considered private and therefore should be avoided +// Here is another way to get arguments using Objective C +// runtime +// +// In general it looks like: +// res = Vec::new() +// let args = [[NSProcessInfo processInfo] arguments] +// for i in range(0, [args count]) +// res.push([args objectAtIndex:i]) +// res +#[cfg(target_os = "ios")] +fn real_args_as_bytes() -> Vec> { + use c_str::CString; + use iter::range; + use mem; + + #[link(name = "objc")] + extern { + fn sel_registerName(name: *libc::c_uchar) -> Sel; + fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId; + fn objc_getClass(class_name: *libc::c_uchar) -> NsId; + } + + #[link(name = "Foundation", kind = "framework")] + extern {} + + type Sel = *libc::c_void; + type NsId = *libc::c_void; + + let mut res = Vec::new(); + + unsafe { + let processInfoSel = sel_registerName("processInfo\0".as_ptr()); + let argumentsSel = sel_registerName("arguments\0".as_ptr()); + let utf8Sel = sel_registerName("UTF8String\0".as_ptr()); + let countSel = sel_registerName("count\0".as_ptr()); + let objectAtSel = sel_registerName("objectAtIndex:\0".as_ptr()); + + let klass = objc_getClass("NSProcessInfo\0".as_ptr()); + let info = objc_msgSend(klass, processInfoSel); + let args = objc_msgSend(info, argumentsSel); + + let cnt: int = mem::transmute(objc_msgSend(args, countSel)); + for i in range(0, cnt) { + let tmp = objc_msgSend(args, objectAtSel, i); + let utf_c_str: *libc::c_char = mem::transmute(objc_msgSend(tmp, utf8Sel)); + let s = CString::new(utf_c_str, false); + if s.is_not_null() { + res.push(Vec::from_slice(s.as_bytes_no_nul())) + } + } + } + + res +} + #[cfg(target_os = "linux")] #[cfg(target_os = "android")] #[cfg(target_os = "freebsd")] @@ -1532,6 +1594,25 @@ pub mod consts { pub static EXE_EXTENSION: &'static str = ""; } +#[cfg(target_os = "ios")] +pub mod consts { + pub use os::arch_consts::ARCH; + + pub static FAMILY: &'static str = "unix"; + + /// A string describing the specific operating system in use: in this + /// case, `ios`. + pub static SYSNAME: &'static str = "ios"; + + /// Specifies the filename suffix used for executable binaries on this + /// platform: in this case, the empty string. + pub static EXE_SUFFIX: &'static str = ""; + + /// Specifies the file extension, if any, used for executable binaries + /// on this platform: in this case, the empty string. + pub static EXE_EXTENSION: &'static str = ""; +} + #[cfg(target_os = "freebsd")] pub mod consts { pub use os::arch_consts::ARCH; diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs index 2654b7a1acc..f507011c2b9 100644 --- a/src/libstd/rand/os.rs +++ b/src/libstd/rand/os.rs @@ -13,7 +13,7 @@ pub use self::imp::OsRng; -#[cfg(unix)] +#[cfg(unix, not(target_os = "ios"))] mod imp { use io::{IoResult, File}; use path::Path; @@ -28,7 +28,7 @@ mod imp { /// `/dev/urandom`. /// - Windows: calls `CryptGenRandom`, using the default cryptographic /// service provider with the `PROV_RSA_FULL` type. - /// + /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed /// This does not block. #[cfg(unix)] pub struct OsRng { @@ -58,6 +58,71 @@ mod imp { } } +#[cfg(target_os = "ios")] +mod imp { + extern crate libc; + + use collections::Collection; + use io::{IoResult}; + use kinds::marker; + use mem; + use os; + use rand::Rng; + use result::{Ok}; + use self::libc::{c_int, size_t}; + use slice::MutableVector; + + /// A random number generator that retrieves randomness straight from + /// the operating system. Platform sources: + /// + /// - Unix-like systems (Linux, Android, Mac OSX): read directly from + /// `/dev/urandom`. + /// - Windows: calls `CryptGenRandom`, using the default cryptographic + /// service provider with the `PROV_RSA_FULL` type. + /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed + /// This does not block. + pub struct OsRng { + marker: marker::NoCopy + } + + struct SecRandom; + + static kSecRandomDefault: *SecRandom = 0 as *SecRandom; + + #[link(name = "Security", kind = "framework")] + extern "C" { + fn SecRandomCopyBytes(rnd: *SecRandom, count: size_t, bytes: *mut u8) -> c_int; + } + + impl OsRng { + /// Create a new `OsRng`. + pub fn new() -> IoResult { + Ok(OsRng {marker: marker::NoCopy} ) + } + } + + impl Rng for OsRng { + fn next_u32(&mut self) -> u32 { + let mut v = [0u8, .. 4]; + self.fill_bytes(v); + unsafe { mem::transmute(v) } + } + fn next_u64(&mut self) -> u64 { + let mut v = [0u8, .. 8]; + self.fill_bytes(v); + unsafe { mem::transmute(v) } + } + fn fill_bytes(&mut self, v: &mut [u8]) { + let ret = unsafe { + SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr()) + }; + if ret == -1 { + fail!("couldn't generate random bytes: {}", os::last_os_error()); + } + } + } +} + #[cfg(windows)] mod imp { extern crate libc; diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index a1372b51d47..16b598b3ae7 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -237,22 +237,58 @@ fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> { #[cfg(unix)] mod imp { use c_str::CString; - use io::{IoResult, IoError, Writer}; + use io::{IoResult, Writer}; use libc; use mem; use option::{Some, None, Option}; use result::{Ok, Err}; use rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT}; - struct Context<'a> { - idx: int, - writer: &'a mut Writer, - last_error: Option, + /// As always - iOS on arm uses SjLj exceptions and + /// _Unwind_Backtrace is even not available there. Still, + /// backtraces could be extracted using a backtrace function, + /// which thanks god is public + #[cfg(target_os = "ios", target_arch = "arm")] + #[inline(never)] + pub fn write(w: &mut Writer) -> IoResult<()> { + use iter::{Iterator, range}; + use result; + use slice::{MutableVector}; + + extern { + fn backtrace(buf: *mut *libc::c_void, sz: libc::c_int) -> libc::c_int; + } + + // while it doesn't requires lock for work as everything is + // local, it still displays much nicier backtraces when a + // couple of tasks fail simultaneously + static mut LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT; + let _g = unsafe { LOCK.lock() }; + + try!(writeln!(w, "stack backtrace:")); + // 100 lines should be enough + static size: libc::c_int = 100; + let mut buf: [*libc::c_void, ..size] = unsafe {mem::zeroed()}; + let cnt = unsafe { backtrace(buf.as_mut_ptr(), size) as uint}; + + // skipping the first one as it is write itself + result::fold_(range(1, cnt).map(|i| { + print(w, i as int, buf[i]) + })) } + #[cfg(not(target_os = "ios", target_arch = "arm"))] #[inline(never)] // if we know this is a function call, we can skip it when // tracing pub fn write(w: &mut Writer) -> IoResult<()> { + use io::IoError; + + struct Context<'a> { + idx: int, + writer: &'a mut Writer, + last_error: Option, + } + // When using libbacktrace, we use some necessary global state, so we // need to prevent more than one thread from entering this block. This // is semi-reasonable in terms of printing anyway, and we know that all @@ -291,7 +327,7 @@ mod imp { // instructions after it. This means that the return instruction // pointer points *outside* of the calling function, and by // unwinding it we go back to the original function. - let ip = if cfg!(target_os = "macos") { + let ip = if cfg!(target_os = "macos") || cfg!(target_os = "ios") { ip } else { unsafe { uw::_Unwind_FindEnclosingFunction(ip) } @@ -323,6 +359,7 @@ mod imp { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] fn print(w: &mut Writer, idx: int, addr: *libc::c_void) -> IoResult<()> { use intrinsics; #[repr(C)] @@ -347,7 +384,7 @@ mod imp { } } - #[cfg(not(target_os = "macos"))] + #[cfg(not(target_os = "macos"), not(target_os = "ios"))] fn print(w: &mut Writer, idx: int, addr: *libc::c_void) -> IoResult<()> { use collections::Collection; use iter::Iterator; @@ -487,9 +524,14 @@ mod imp { /// Unwind library interface used for backtraces /// - /// Note that the native libraries come from librustrt, not this module. + /// Note that the native libraries come from librustrt, not this + /// module. + /// Note that dead code is allowed as here are just bindings + /// iOS doesn't use all of them it but adding more + /// platform-specific configs pollutes the code too much #[allow(non_camel_case_types)] #[allow(non_snake_case_functions)] + #[allow(dead_code)] mod uw { use libc; @@ -514,6 +556,8 @@ mod imp { arg: *libc::c_void) -> _Unwind_Reason_Code; extern { + // No native _Unwind_Backtrace on iOS + #[cfg(not(target_os = "ios", target_arch = "arm"))] pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn, trace_argument: *libc::c_void) -> _Unwind_Reason_Code; diff --git a/src/libstd/rtdeps.rs b/src/libstd/rtdeps.rs index c804918ae4b..f8bfde52261 100644 --- a/src/libstd/rtdeps.rs +++ b/src/libstd/rtdeps.rs @@ -39,3 +39,7 @@ extern {} #[cfg(target_os = "macos")] #[link(name = "System")] extern {} + +#[cfg(target_os = "ios")] +#[link(name = "System")] +extern {} diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index cfe85995df6..ec54a033e71 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -11,7 +11,7 @@ use std::fmt; #[deriving(PartialEq)] -pub enum Os { OsWin32, OsMacos, OsLinux, OsAndroid, OsFreebsd, } +pub enum Os { OsWin32, OsMacos, OsLinux, OsAndroid, OsFreebsd, OsiOS, } #[deriving(PartialEq, Eq, Hash, Encodable, Decodable, Clone)] pub enum Abi { diff --git a/src/libtime/lib.rs b/src/libtime/lib.rs index 63523cd3a6f..b4a2e92cc12 100644 --- a/src/libtime/lib.rs +++ b/src/libtime/lib.rs @@ -48,7 +48,7 @@ mod rustrt { } } -#[cfg(unix, not(target_os = "macos"))] +#[cfg(unix, not(target_os = "macos"), not(target_os = "ios"))] mod imp { use libc::{c_int, timespec}; @@ -63,6 +63,7 @@ mod imp { } #[cfg(target_os = "macos")] +#[cfg(target_os = "ios")] mod imp { use libc::{timeval, timezone, c_int, mach_timebase_info}; @@ -123,6 +124,7 @@ pub fn get_time() -> Timespec { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] unsafe fn os_get_time() -> (i64, i32) { use std::ptr; let mut tv = libc::timeval { tv_sec: 0, tv_usec: 0 }; @@ -130,7 +132,7 @@ pub fn get_time() -> Timespec { (tv.tv_sec as i64, tv.tv_usec * 1000) } - #[cfg(not(target_os = "macos"), not(windows))] + #[cfg(not(target_os = "macos"), not(target_os = "ios"), not(windows))] unsafe fn os_get_time() -> (i64, i32) { let mut tv = libc::timespec { tv_sec: 0, tv_nsec: 0 }; imp::clock_gettime(libc::CLOCK_REALTIME, &mut tv); @@ -162,6 +164,7 @@ pub fn precise_time_ns() -> u64 { } #[cfg(target_os = "macos")] + #[cfg(target_os = "ios")] fn os_precise_time_ns() -> u64 { static mut TIMEBASE: libc::mach_timebase_info = libc::mach_timebase_info { numer: 0, denom: 0 }; @@ -175,7 +178,7 @@ pub fn precise_time_ns() -> u64 { } } - #[cfg(not(windows), not(target_os = "macos"))] + #[cfg(not(windows), not(target_os = "macos"), not(target_os = "ios"))] fn os_precise_time_ns() -> u64 { let mut ts = libc::timespec { tv_sec: 0, tv_nsec: 0 }; unsafe { From 70a79a9e0527fab74d8c2d2b49886b41bdd878f5 Mon Sep 17 00:00:00 2001 From: Valerii Hiora Date: Wed, 11 Jun 2014 10:48:17 +0300 Subject: [PATCH 06/10] Better dylib skipping based on Alex Crichton code --- src/librustc/back/arm.rs | 5 -- src/librustc/back/link.rs | 68 ++++++++++++++++---------- src/librustc/back/mips.rs | 5 -- src/librustc/back/target_strs.rs | 1 - src/librustc/back/x86.rs | 5 -- src/librustc/back/x86_64.rs | 5 -- src/librustc/driver/config.rs | 25 +++++----- src/librustc/driver/driver.rs | 19 ++++++-- src/librustc/driver/mod.rs | 3 +- src/librustc/metadata/creader.rs | 6 +-- src/librustc/metadata/loader.rs | 81 ++++++++++++++----------------- src/librustc/middle/trans/base.rs | 10 ++-- src/libsyntax/abi.rs | 13 +++++ 13 files changed, 125 insertions(+), 121 deletions(-) diff --git a/src/librustc/back/arm.rs b/src/librustc/back/arm.rs index 7a944fd5abe..7a7d248a4cb 100644 --- a/src/librustc/back/arm.rs +++ b/src/librustc/back/arm.rs @@ -9,8 +9,6 @@ // except according to those terms. use back::target_strs; -use driver::config::cfg_os_to_meta_os; -use metadata::loader::meta_section_name; use syntax::abi; pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs::t { @@ -22,9 +20,6 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs return target_strs::t { module_asm: "".to_string(), - meta_sect_name: - meta_section_name(cfg_os_to_meta_os(target_os)).to_string(), - data_layout: match target_os { abi::OsMacos => { "e-p:32:32:32\ diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index ab4eda33d75..d644a0cc353 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -806,6 +806,10 @@ pub fn link_binary(sess: &Session, id: &CrateId) -> Vec { let mut out_filenames = Vec::new(); for &crate_type in sess.crate_types.borrow().iter() { + if invalid_output_for_target(sess, crate_type) { + sess.bug(format!("invalid output type `{}` for target os `{}`", + crate_type, sess.targ_cfg.os).as_slice()); + } let out_file = link_binary_output(sess, trans, crate_type, outputs, id); out_filenames.push(out_file); } @@ -822,6 +826,32 @@ pub fn link_binary(sess: &Session, out_filenames } + +/// Returns default crate type for target +/// +/// Default crate type is used when crate type isn't provided neither +/// through cmd line arguments nor through crate attributes +/// +/// It is CrateTypeExecutable for all platforms but iOS as there is no +/// way to run iOS binaries anyway without jailbreaking and +/// interaction with Rust code through static library is the only +/// option for now +pub fn default_output_for_target(sess: &Session) -> config::CrateType { + match sess.targ_cfg.os { + abi::OsiOS => config::CrateTypeStaticlib, + _ => config::CrateTypeExecutable + } +} + +/// Checks if target supports crate_type as output +pub fn invalid_output_for_target(sess: &Session, + crate_type: config::CrateType) -> bool { + match (sess.targ_cfg.os, crate_type) { + (abi::OsiOS, config::CrateTypeDylib) => true, + _ => false + } +} + fn is_writeable(p: &Path) -> bool { match p.stat() { Err(..) => true, @@ -837,23 +867,18 @@ pub fn filename_for_input(sess: &Session, crate_type: config::CrateType, out_filename.with_filename(format!("lib{}.rlib", libname)) } config::CrateTypeDylib => { - // There is no support of DyLibs on iOS - if sess.targ_cfg.os == abi::OsiOS { - out_filename.with_filename(format!("lib{}.a", libname)) - } else { - let (prefix, suffix) = match sess.targ_cfg.os { - abi::OsWin32 => (loader::WIN32_DLL_PREFIX, loader::WIN32_DLL_SUFFIX), - abi::OsMacos => (loader::MACOS_DLL_PREFIX, loader::MACOS_DLL_SUFFIX), - abi::OsLinux => (loader::LINUX_DLL_PREFIX, loader::LINUX_DLL_SUFFIX), - abi::OsAndroid => (loader::ANDROID_DLL_PREFIX, loader::ANDROID_DLL_SUFFIX), - abi::OsFreebsd => (loader::FREEBSD_DLL_PREFIX, loader::FREEBSD_DLL_SUFFIX), - abi::OsiOS => unreachable!(), - }; - out_filename.with_filename(format!("{}{}{}", - prefix, - libname, - suffix)) - } + let (prefix, suffix) = match sess.targ_cfg.os { + abi::OsWin32 => (loader::WIN32_DLL_PREFIX, loader::WIN32_DLL_SUFFIX), + abi::OsMacos => (loader::MACOS_DLL_PREFIX, loader::MACOS_DLL_SUFFIX), + abi::OsLinux => (loader::LINUX_DLL_PREFIX, loader::LINUX_DLL_SUFFIX), + abi::OsAndroid => (loader::ANDROID_DLL_PREFIX, loader::ANDROID_DLL_SUFFIX), + abi::OsFreebsd => (loader::FREEBSD_DLL_PREFIX, loader::FREEBSD_DLL_SUFFIX), + abi::OsiOS => unreachable!(), + }; + out_filename.with_filename(format!("{}{}{}", + prefix, + libname, + suffix)) } config::CrateTypeStaticlib => { out_filename.with_filename(format!("lib{}.a", libname)) @@ -904,14 +929,7 @@ fn link_binary_output(sess: &Session, link_natively(sess, trans, false, &obj_filename, &out_filename); } config::CrateTypeDylib => { - if sess.targ_cfg.os == abi::OsiOS { - sess.warn(format!("No dylib for iOS -> saving static library {} to {}", - obj_filename.display(), out_filename.display()).as_slice()); - link_staticlib(sess, &obj_filename, &out_filename); - } - else { - link_natively(sess, trans, true, &obj_filename, &out_filename); - } + link_natively(sess, trans, true, &obj_filename, &out_filename); } } diff --git a/src/librustc/back/mips.rs b/src/librustc/back/mips.rs index ea9879dbf49..8f3da03e825 100644 --- a/src/librustc/back/mips.rs +++ b/src/librustc/back/mips.rs @@ -9,17 +9,12 @@ // except according to those terms. use back::target_strs; -use driver::config::cfg_os_to_meta_os; -use metadata::loader::meta_section_name; use syntax::abi; pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs::t { return target_strs::t { module_asm: "".to_string(), - meta_sect_name: - meta_section_name(cfg_os_to_meta_os(target_os)).to_string(), - data_layout: match target_os { abi::OsMacos => { "E-p:32:32:32\ diff --git a/src/librustc/back/target_strs.rs b/src/librustc/back/target_strs.rs index ed5976ad508..7928f3d8db0 100644 --- a/src/librustc/back/target_strs.rs +++ b/src/librustc/back/target_strs.rs @@ -12,7 +12,6 @@ pub struct t { pub module_asm: String, - pub meta_sect_name: String, pub data_layout: String, pub target_triple: String, pub cc_args: Vec , diff --git a/src/librustc/back/x86.rs b/src/librustc/back/x86.rs index 90106e9e030..d2dac03267d 100644 --- a/src/librustc/back/x86.rs +++ b/src/librustc/back/x86.rs @@ -10,8 +10,6 @@ use back::target_strs; -use driver::config::cfg_os_to_meta_os; -use metadata::loader::meta_section_name; use syntax::abi; pub fn get_target_strs(target_triple: String, target_os: abi::Os) @@ -19,9 +17,6 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) return target_strs::t { module_asm: "".to_string(), - meta_sect_name: - meta_section_name(cfg_os_to_meta_os(target_os)).to_string(), - data_layout: match target_os { abi::OsMacos => { "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16\ diff --git a/src/librustc/back/x86_64.rs b/src/librustc/back/x86_64.rs index 55b0eca7be7..c2eae18737b 100644 --- a/src/librustc/back/x86_64.rs +++ b/src/librustc/back/x86_64.rs @@ -10,17 +10,12 @@ use back::target_strs; -use driver::config::cfg_os_to_meta_os; -use metadata::loader::meta_section_name; use syntax::abi; pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs::t { return target_strs::t { module_asm: "".to_string(), - meta_sect_name: - meta_section_name(cfg_os_to_meta_os(target_os)).to_string(), - data_layout: match target_os { abi::OsMacos => { "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\ diff --git a/src/librustc/driver/config.rs b/src/librustc/driver/config.rs index 2f7dc136ef2..fd21951f287 100644 --- a/src/librustc/driver/config.rs +++ b/src/librustc/driver/config.rs @@ -19,7 +19,6 @@ use back; use back::link; use back::target_strs; use back::{arm, x86, x86_64, mips}; -use metadata; use middle::lint; use syntax::abi; @@ -36,6 +35,7 @@ use getopts::{optopt, optmulti, optflag, optflagopt}; use getopts; use lib::llvm::llvm; use std::cell::{RefCell}; +use std::fmt; pub struct Config { @@ -354,19 +354,6 @@ pub fn default_lib_output() -> CrateType { CrateTypeRlib } -pub fn cfg_os_to_meta_os(os: abi::Os) -> metadata::loader::Os { - use metadata::loader; - - match os { - abi::OsWin32 => loader::OsWin32, - abi::OsLinux => loader::OsLinux, - abi::OsAndroid => loader::OsAndroid, - abi::OsMacos => loader::OsMacos, - abi::OsFreebsd => loader::OsFreebsd, - abi::OsiOS => loader::OsiOS, - } -} - pub fn default_configuration(sess: &Session) -> ast::CrateConfig { let tos = match sess.targ_cfg.os { abi::OsWin32 => InternedString::new("win32"), @@ -775,6 +762,16 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { } } +impl fmt::Show for CrateType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + CrateTypeExecutable => "bin".fmt(f), + CrateTypeDylib => "dylib".fmt(f), + CrateTypeRlib => "rlib".fmt(f), + CrateTypeStaticlib => "staticlib".fmt(f) + } + } +} #[cfg(test)] mod test { diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index d703ece307f..7bc698bfbd3 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -779,17 +779,26 @@ pub fn collect_crate_types(session: &Session, // command line, then reuse the empty `base` Vec to hold the types that // will be found in crate attributes. let mut base = session.opts.crate_types.clone(); - if base.len() > 0 { - return base - } else { + if base.len() == 0 { base.extend(attr_types.move_iter()); if base.len() == 0 { - base.push(config::CrateTypeExecutable); + base.push(link::default_output_for_target(session)); } base.as_mut_slice().sort(); base.dedup(); - return base; } + + base.move_iter().filter(|crate_type| { + let res = !link::invalid_output_for_target(session, *crate_type); + + if !res { + session.warn(format!("dropping unsupported crate type `{}` \ + for target os `{}`", + *crate_type, session.targ_cfg.os).as_slice()); + } + + res + }).collect() } pub struct OutputFilenames { diff --git a/src/librustc/driver/mod.rs b/src/librustc/driver/mod.rs index b6205d8d54e..952e8afcbec 100644 --- a/src/librustc/driver/mod.rs +++ b/src/librustc/driver/mod.rs @@ -349,8 +349,7 @@ pub fn early_error(msg: &str) -> ! { pub fn list_metadata(sess: &Session, path: &Path, out: &mut io::Writer) -> io::IoResult<()> { - metadata::loader::list_file_metadata( - config::cfg_os_to_meta_os(sess.targ_cfg.os), path, out) + metadata::loader::list_file_metadata(sess.targ_cfg.os, path, out) } /// Run a procedure which will detect failures in the compiler and print nicer diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 63b177b0eb7..efe28614b8f 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -346,7 +346,7 @@ fn resolve_crate<'a>(e: &mut Env, id_hash: id_hash.as_slice(), hash: hash.map(|a| &*a), filesearch: e.sess.target_filesearch(), - os: config::cfg_os_to_meta_os(e.sess.targ_cfg.os), + os: e.sess.targ_cfg.os, triple: e.sess.targ_cfg.target_strs.target_triple.as_slice(), root: root, rejected_via_hash: vec!(), @@ -410,7 +410,7 @@ impl<'a> PluginMetadataReader<'a> { hash: None, filesearch: self.env.sess.host_filesearch(), triple: driver::host_triple(), - os: config::cfg_os_to_meta_os(os), + os: os, root: &None, rejected_via_hash: vec!(), rejected_via_triple: vec!(), @@ -421,7 +421,7 @@ impl<'a> PluginMetadataReader<'a> { // try loading from target crates (only valid if there are // no syntax extensions) load_ctxt.triple = target_triple; - load_ctxt.os = config::cfg_os_to_meta_os(self.env.sess.targ_cfg.os); + load_ctxt.os = self.env.sess.targ_cfg.os; load_ctxt.filesearch = self.env.sess.target_filesearch(); let lib = load_ctxt.load_library_crate(); if decoder::get_plugin_registrar_fn(lib.metadata.as_slice()).is_some() { diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index a674b6cf5a9..c1f29d7596b 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -18,6 +18,7 @@ use metadata::cstore::{MetadataBlob, MetadataVec, MetadataArchive}; use metadata::decoder; use metadata::encoder; use metadata::filesearch::{FileSearch, FileMatches, FileDoesntMatch}; +use syntax::abi; use syntax::codemap::Span; use syntax::diagnostic::SpanHandler; use syntax::crateid::CrateId; @@ -39,9 +40,6 @@ use time; pub static MACOS_DLL_PREFIX: &'static str = "lib"; pub static MACOS_DLL_SUFFIX: &'static str = ".dylib"; -pub static IOS_DLL_PREFIX: &'static str = "lib"; -pub static IOS_DLL_SUFFIX: &'static str = ".dylib"; - pub static WIN32_DLL_PREFIX: &'static str = ""; pub static WIN32_DLL_SUFFIX: &'static str = ".dll"; @@ -54,15 +52,6 @@ pub static FREEBSD_DLL_SUFFIX: &'static str = ".so"; pub static ANDROID_DLL_PREFIX: &'static str = "lib"; pub static ANDROID_DLL_SUFFIX: &'static str = ".so"; -pub enum Os { - OsMacos, - OsWin32, - OsLinux, - OsAndroid, - OsFreebsd, - OsiOS -} - pub struct CrateMismatch { path: Path, got: String, @@ -76,7 +65,7 @@ pub struct Context<'a> { pub id_hash: &'a str, pub hash: Option<&'a Svh>, pub triple: &'a str, - pub os: Os, + pub os: abi::Os, pub filesearch: FileSearch<'a>, pub root: &'a Option, pub rejected_via_hash: Vec, @@ -178,10 +167,12 @@ impl<'a> Context<'a> { } fn find_library_crate(&mut self) -> Option { - let (dyprefix, dysuffix) = self.dylibname(); + let dypair = self.dylibname(); // want: crate_name.dir_part() + prefix + crate_name.file_part + "-" - let dylib_prefix = format!("{}{}-", dyprefix, self.crate_id.name); + let dylib_prefix = dypair.map(|(prefix, _)| { + format!("{}{}-", prefix, self.crate_id.name) + }); let rlib_prefix = format!("lib{}-", self.crate_id.name); let mut candidates = HashMap::new(); @@ -222,12 +213,14 @@ impl<'a> Context<'a> { FileDoesntMatch } } - } else if file.starts_with(dylib_prefix.as_slice()) && - file.ends_with(dysuffix){ + } else if dypair.map_or(false, |(_, suffix)| { + file.starts_with(dylib_prefix.get_ref().as_slice()) && + file.ends_with(suffix) + }) { + let (_, suffix) = dypair.unwrap(); + let dylib_prefix = dylib_prefix.get_ref().as_slice(); info!("dylib candidate: {}", path.display()); - match self.try_match(file, - dylib_prefix.as_slice(), - dysuffix) { + match self.try_match(file, dylib_prefix, suffix) { Some(hash) => { info!("dylib accepted, hash: {}", hash); let slot = candidates.find_or_insert_with(hash, |_| { @@ -452,14 +445,14 @@ impl<'a> Context<'a> { // Returns the corresponding (prefix, suffix) that files need to have for // dynamic libraries - fn dylibname(&self) -> (&'static str, &'static str) { + fn dylibname(&self) -> Option<(&'static str, &'static str)> { match self.os { - OsWin32 => (WIN32_DLL_PREFIX, WIN32_DLL_SUFFIX), - OsMacos => (MACOS_DLL_PREFIX, MACOS_DLL_SUFFIX), - OsLinux => (LINUX_DLL_PREFIX, LINUX_DLL_SUFFIX), - OsAndroid => (ANDROID_DLL_PREFIX, ANDROID_DLL_SUFFIX), - OsFreebsd => (FREEBSD_DLL_PREFIX, FREEBSD_DLL_SUFFIX), - OsiOS => (IOS_DLL_PREFIX, IOS_DLL_SUFFIX), + abi::OsWin32 => Some((WIN32_DLL_PREFIX, WIN32_DLL_SUFFIX)), + abi::OsMacos => Some((MACOS_DLL_PREFIX, MACOS_DLL_SUFFIX)), + abi::OsLinux => Some((LINUX_DLL_PREFIX, LINUX_DLL_SUFFIX)), + abi::OsAndroid => Some((ANDROID_DLL_PREFIX, ANDROID_DLL_SUFFIX)), + abi::OsFreebsd => Some((FREEBSD_DLL_PREFIX, FREEBSD_DLL_SUFFIX)), + abi::OsiOS => None, } } @@ -501,7 +494,7 @@ impl ArchiveMetadata { } // Just a small wrapper to time how long reading metadata takes. -fn get_metadata_section(os: Os, filename: &Path) -> Result { +fn get_metadata_section(os: abi::Os, filename: &Path) -> Result { let start = time::precise_time_ns(); let ret = get_metadata_section_imp(os, filename); info!("reading {} => {}ms", filename.filename_display(), @@ -509,7 +502,7 @@ fn get_metadata_section(os: Os, filename: &Path) -> Result return ret; } -fn get_metadata_section_imp(os: Os, filename: &Path) -> Result { +fn get_metadata_section_imp(os: abi::Os, filename: &Path) -> Result { if !filename.exists() { return Err(format!("no such file: '{}'", filename.display())); } @@ -595,30 +588,30 @@ fn get_metadata_section_imp(os: Os, filename: &Path) -> Result &'static str { +pub fn meta_section_name(os: abi::Os) -> Option<&'static str> { match os { - OsMacos => "__DATA,__note.rustc", - OsiOS => "__DATA,__note.rustc", - OsWin32 => ".note.rustc", - OsLinux => ".note.rustc", - OsAndroid => ".note.rustc", - OsFreebsd => ".note.rustc" + abi::OsMacos => Some("__DATA,__note.rustc"), + abi::OsiOS => Some("__DATA,__note.rustc"), + abi::OsWin32 => Some(".note.rustc"), + abi::OsLinux => Some(".note.rustc"), + abi::OsAndroid => Some(".note.rustc"), + abi::OsFreebsd => Some(".note.rustc") } } -pub fn read_meta_section_name(os: Os) -> &'static str { +pub fn read_meta_section_name(os: abi::Os) -> &'static str { match os { - OsMacos => "__note.rustc", - OsiOS => "__note.rustc", - OsWin32 => ".note.rustc", - OsLinux => ".note.rustc", - OsAndroid => ".note.rustc", - OsFreebsd => ".note.rustc" + abi::OsMacos => "__note.rustc", + abi::OsiOS => "__note.rustc", + abi::OsWin32 => ".note.rustc", + abi::OsLinux => ".note.rustc", + abi::OsAndroid => ".note.rustc", + abi::OsFreebsd => ".note.rustc" } } // A diagnostic function for dumping crate metadata to an output stream -pub fn list_file_metadata(os: Os, path: &Path, +pub fn list_file_metadata(os: abi::Os, path: &Path, out: &mut io::Writer) -> io::IoResult<()> { match get_metadata_section(os, path) { Ok(bytes) => decoder::list_crate_metadata(bytes.as_slice(), out), diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 594a62ea9b2..3fec3cbd1bb 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -35,7 +35,7 @@ use driver::driver::{CrateAnalysis, CrateTranslation}; use lib::llvm::{ModuleRef, ValueRef, BasicBlockRef}; use lib::llvm::{llvm, Vector}; use lib; -use metadata::{csearch, encoder}; +use metadata::{csearch, encoder, loader}; use middle::lint; use middle::astencode; use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem}; @@ -2281,12 +2281,8 @@ pub fn write_metadata(cx: &CrateContext, krate: &ast::Crate) -> Vec { }); unsafe { llvm::LLVMSetInitializer(llglobal, llconst); - cx.sess() - .targ_cfg - .target_strs - .meta_sect_name - .as_slice() - .with_c_str(|buf| { + let name = loader::meta_section_name(cx.sess().targ_cfg.os); + name.unwrap_or("rust_metadata").with_c_str(|buf| { llvm::LLVMSetSection(llglobal, buf) }); } diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index ec54a033e71..7ff020d6818 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -159,6 +159,19 @@ impl fmt::Show for Abi { } } +impl fmt::Show for Os { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + OsLinux => "linux".fmt(f), + OsWin32 => "win32".fmt(f), + OsMacos => "macos".fmt(f), + OsiOS => "ios".fmt(f), + OsAndroid => "android".fmt(f), + OsFreebsd => "freebsd".fmt(f) + } + } +} + #[allow(non_snake_case_functions)] #[test] fn lookup_Rust() { From ebc6474668ec60cc793af0f48143bf33d984deb4 Mon Sep 17 00:00:00 2001 From: Valerii Hiora Date: Fri, 13 Jun 2014 10:18:12 +0300 Subject: [PATCH 07/10] Cosmetic fixes & comments --- src/librustrt/libunwind.rs | 12 ++++++------ src/librustrt/unwind.rs | 1 - src/libstd/rt/backtrace.rs | 11 ++++++++--- src/rt/arch/arm/record_sp.S | 6 +++++- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/librustrt/libunwind.rs b/src/librustrt/libunwind.rs index 50c2aba2b5c..2d58c1bee15 100644 --- a/src/librustrt/libunwind.rs +++ b/src/librustrt/libunwind.rs @@ -97,10 +97,14 @@ extern {} extern "C" { // iOS on armv7 uses SjLj exceptions and requires to link // agains corresponding routine (..._SjLj_...) - // So here we just skip linking for iOS #[cfg(not(target_os = "ios", target_arch = "arm"))] pub fn _Unwind_RaiseException(exception: *_Unwind_Exception) - -> _Unwind_Reason_Code; + -> _Unwind_Reason_Code; + + #[cfg(target_os = "ios", target_arch = "arm")] + fn _Unwind_SjLj_RaiseException(e: *_Unwind_Exception) + -> _Unwind_Reason_Code; + pub fn _Unwind_DeleteException(exception: *_Unwind_Exception); } @@ -111,9 +115,5 @@ extern "C" { #[inline(always)] pub unsafe fn _Unwind_RaiseException(exc: *_Unwind_Exception) -> _Unwind_Reason_Code { - extern "C" { - fn _Unwind_SjLj_RaiseException(e: *_Unwind_Exception) - -> _Unwind_Reason_Code; } - _Unwind_SjLj_RaiseException(exc) } diff --git a/src/librustrt/unwind.rs b/src/librustrt/unwind.rs index e60c50f0adb..5b941c9d5aa 100644 --- a/src/librustrt/unwind.rs +++ b/src/librustrt/unwind.rs @@ -303,7 +303,6 @@ pub mod eabi { use libc::c_int; extern "C" { - #[cfg(target_os = "ios", target_arch = "arm")] fn __gcc_personality_sj0(version: c_int, actions: uw::_Unwind_Action, exception_class: uw::_Unwind_Exception_Class, diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index 16b598b3ae7..0e3e7cc796a 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -248,6 +248,11 @@ mod imp { /// _Unwind_Backtrace is even not available there. Still, /// backtraces could be extracted using a backtrace function, /// which thanks god is public + /// + /// As mentioned in a huge comment block above, backtrace doesn't + /// play well with green threads, so while it is extremely nice + /// and simple to use it should be used only on iOS devices as the + /// only viable option. #[cfg(target_os = "ios", target_arch = "arm")] #[inline(never)] pub fn write(w: &mut Writer) -> IoResult<()> { @@ -267,9 +272,9 @@ mod imp { try!(writeln!(w, "stack backtrace:")); // 100 lines should be enough - static size: libc::c_int = 100; - let mut buf: [*libc::c_void, ..size] = unsafe {mem::zeroed()}; - let cnt = unsafe { backtrace(buf.as_mut_ptr(), size) as uint}; + static SIZE: libc::c_int = 100; + let mut buf: [*libc::c_void, ..SIZE] = unsafe {mem::zeroed()}; + let cnt = unsafe { backtrace(buf.as_mut_ptr(), SIZE) as uint}; // skipping the first one as it is write itself result::fold_(range(1, cnt).map(|i| { diff --git a/src/rt/arch/arm/record_sp.S b/src/rt/arch/arm/record_sp.S index 94cfcff039e..d0e9b81b95a 100644 --- a/src/rt/arch/arm/record_sp.S +++ b/src/rt/arch/arm/record_sp.S @@ -1,4 +1,8 @@ -// Do not compile anything here for iOS +// Do not compile anything here for iOS because split stacks +// are disabled at all and do not need any runtime support. +// +// See also comments in librustrt/stack.rs about why it was +// disabled and how it could be implemented in case of need. #if !defined(__APPLE__) // Mark stack as non-executable #if defined(__linux__) && defined(__ELF__) From 41522aaf7275b1282df866bdbaeac3bd1f3a0958 Mon Sep 17 00:00:00 2001 From: Valerii Hiora Date: Fri, 13 Jun 2014 11:41:00 +0300 Subject: [PATCH 08/10] There should be no metadata to read on iOS --- src/librustc/metadata/loader.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index c1f29d7596b..978246b2436 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -602,7 +602,7 @@ pub fn meta_section_name(os: abi::Os) -> Option<&'static str> { pub fn read_meta_section_name(os: abi::Os) -> &'static str { match os { abi::OsMacos => "__note.rustc", - abi::OsiOS => "__note.rustc", + abi::OsiOS => unreachable!(), abi::OsWin32 => ".note.rustc", abi::OsLinux => ".note.rustc", abi::OsAndroid => ".note.rustc", From 3446f2887962460840ca105d1fa469987d39d86b Mon Sep 17 00:00:00 2001 From: Valerii Hiora Date: Sat, 14 Jun 2014 18:00:28 +0300 Subject: [PATCH 09/10] Updated compiler-rt Previous update unfortunately included changes which broke Android compilation. This update fixes it and should allow correct compilation of SjLj for iOS and all builtins for Android. --- src/compiler-rt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler-rt b/src/compiler-rt index c10fb863096..7b97b8468f0 160000 --- a/src/compiler-rt +++ b/src/compiler-rt @@ -1 +1 @@ -Subproject commit c10fb8630963e858513fbebe86db3648a2246d73 +Subproject commit 7b97b8468f0614072cf3299fa8c51e85f609316f From 2ec323e4c30c265f35314c0a77f5df5a655cec2f Mon Sep 17 00:00:00 2001 From: Valerii Hiora Date: Mon, 16 Jun 2014 08:48:59 +0300 Subject: [PATCH 10/10] Potential fix for Win32 build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It seems in one of rebases I’ve resolved conflicts wrong and left one redundant line, it is absent in current master and it might cause compilation failure by copying file into itself. --- mk/rt.mk | 1 - 1 file changed, 1 deletion(-) diff --git a/mk/rt.mk b/mk/rt.mk index cb6c0fc7e5e..7fc82ef6269 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -217,7 +217,6 @@ $$(LIBUV_LOCAL_$(1)): $$(LIBUV_DEPS) $$(MKFILE_DEPS) CXX="$$(CXX_$(1))" \ AR="$$(AR_$(1))" \ V=$$(VERBOSE) - $$(Q)cp $$(S)src/libuv/libuv.a $$@ else ifeq ($(OSTYPE_$(1)), apple-ios) # iOS $$(LIBUV_XCODEPROJ_$(1)): $$(LIBUV_DEPS) $$(MKFILE_DEPS) $$(LIBUV_STAMP_$(1)) cp -rf $(S)src/libuv/ $$(LIBUV_BUILD_DIR_$(1))