diff --git a/configure b/configure index 59e51356c6c..9eccc2f6e40 100755 --- a/configure +++ b/configure @@ -291,6 +291,22 @@ envopt() { fi } +to_llvm_triple() { + case $1 in + i686-w64-mingw32) echo i686-pc-windows-gnu ;; + x86_64-w64-mingw32) echo x86_64-pc-windows-gnu ;; + *) echo $1 ;; + esac +} + +to_gnu_triple() { + case $1 in + i686-pc-windows-gnu) echo i686-w64-mingw32 ;; + x86_64-pc-windows-gnu) echo x86_64-w64-mingw32 ;; + *) echo $1 ;; + esac +} + msg "looking for configure programs" need_cmd cmp need_cmd mkdir @@ -350,37 +366,40 @@ case $CFG_OSTYPE in # instead, msys defines $MSYSTEM which is MINGW32 on i686 and # MINGW64 on x86_64. CFG_CPUTYPE=i686 - CFG_OSTYPE=w64-mingw32 + CFG_OSTYPE=pc-windows-gnu if [ "$MSYSTEM" = MINGW64 ] then CFG_CPUTYPE=x86_64 - CFG_OSTYPE=w64-mingw32 fi ;; + MSYS*) + CFG_OSTYPE=pc-windows-gnu + ;; + # Thad's Cygwin identifers below # Vista 32 bit CYGWIN_NT-6.0) - CFG_OSTYPE=pc-mingw32 + CFG_OSTYPE=pc-windows-gnu CFG_CPUTYPE=i686 ;; # Vista 64 bit CYGWIN_NT-6.0-WOW64) - CFG_OSTYPE=w64-mingw32 + CFG_OSTYPE=pc-windows-gnu CFG_CPUTYPE=x86_64 ;; # Win 7 32 bit CYGWIN_NT-6.1) - CFG_OSTYPE=pc-mingw32 + CFG_OSTYPE=pc-windows-gnu CFG_CPUTYPE=i686 ;; # Win 7 64 bit CYGWIN_NT-6.1-WOW64) - CFG_OSTYPE=w64-mingw32 + CFG_OSTYPE=pc-windows-gnu CFG_CPUTYPE=x86_64 ;; @@ -466,7 +485,6 @@ opt llvm-assertions 1 "build LLVM with assertions" opt debug 1 "build with extra debug fun" opt ratchet-bench 0 "ratchet benchmarks" opt fast-make 0 "use .gitmodules as timestamp for submodule deps" -opt mingw-cross 0 "cross-compile for win32 using mingw" opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds" opt local-rust 0 "use an installed rustc rather than downloading a snapshot" opt llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM" @@ -487,7 +505,6 @@ valopt llvm-root "" "set LLVM root" valopt jemalloc-root "" "set directory where libjemalloc_pic.a is located" valopt build "${DEFAULT_BUILD}" "GNUs ./configure syntax LLVM build triple" valopt android-cross-path "/opt/ndk_standalone" "Android NDK standalone path" -valopt mingw32-cross-path "" "MinGW32 cross compiler path" # Many of these are saved below during the "writing configuration" step # (others are conditionally saved). @@ -501,12 +518,18 @@ valopt_nosave target "${CFG_HOST}" "GNUs ./configure syntax LLVM target triples" valopt_nosave mandir "${CFG_PREFIX}/share/man" "install man pages in PATH" valopt_nosave release-channel "dev" "the name of the release channel to build" +# Temporarily support old triples until buildbots get updated +CFG_BUILD=$(to_llvm_triple $CFG_BUILD) +putvar CFG_BUILD # Yes, this creates a duplicate entry, but the last one wins. +CFG_HOST=$(to_llvm_triple $CFG_HOST) +CFG_TARGET=$(to_llvm_triple $CFG_TARGET) + # On windows we just store the libraries in the bin directory because # there's no rpath. This is where the build system itself puts libraries; # --libdir is used to configure the installation directory. # FIXME: This needs to parameterized over target triples. Do it in platform.mk CFG_LIBDIR_RELATIVE=lib -if [ "$CFG_OSTYPE" = "pc-mingw32" ] || [ "$CFG_OSTYPE" = "w64-mingw32" ] +if [ "$CFG_OSTYPE" = "pc-windows-gnu" ] then CFG_LIBDIR_RELATIVE=bin fi @@ -632,7 +655,7 @@ then fi BIN_SUF= -if [ "$CFG_OSTYPE" = "pc-mingw32" ] || [ "$CFG_OSTYPE" = "w64-mingw32" ] +if [ "$CFG_OSTYPE" = "pc-windows-gnu" ] then BIN_SUF=.exe fi @@ -1100,12 +1123,15 @@ do if [ ${do_reconfigure} -ne 0 ] then - msg "configuring LLVM for $t" + # LLVM's configure doesn't recognize the new Windows triples yet + gnu_t=$(to_gnu_triple $t) + + msg "configuring LLVM for $gnu_t" LLVM_TARGETS="--enable-targets=x86,x86_64,arm,mips" - LLVM_BUILD="--build=$t" - LLVM_HOST="--host=$t" - LLVM_TARGET="--target=$t" + LLVM_BUILD="--build=$gnu_t" + LLVM_HOST="--host=$gnu_t" + LLVM_TARGET="--target=$gnu_t" # Disable unused LLVM features LLVM_OPTS="$LLVM_DBG_OPTS $LLVM_ASSERTION_OPTS --disable-docs --enable-bindings=none" @@ -1119,7 +1145,7 @@ do # (llvm's configure tries to find pthread first, so we have to disable it explicitly.) # Also note that pthreads works badly on mingw-w64 systems: #8996 case "$CFG_BUILD" in - (*-mingw32) + (*-windows-*) LLVM_OPTS="$LLVM_OPTS --disable-pthreads" ;; esac @@ -1269,6 +1295,7 @@ putvar CFG_HOST putvar CFG_TARGET putvar CFG_LIBDIR_RELATIVE putvar CFG_DISABLE_MANAGE_SUBMODULES +putvar CFG_ANDROID_CROSS_PATH putvar CFG_MANDIR # Avoid spurious warnings from clang by feeding it original source on diff --git a/mk/cfg/arm-apple-ios b/mk/cfg/arm-apple-ios index b2ce37ad460..6a66ff46a36 100644 --- a/mk/cfg/arm-apple-ios +++ b/mk/cfg/arm-apple-ios @@ -3,7 +3,7 @@ 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 armv7-apple-darwin -isysroot $(CFG_IOS_SDK) -mios-version-min=7.0 +CFG_IOS_FLAGS = -target armv7-apple-ios -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++) @@ -32,3 +32,4 @@ 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 +CFG_GNU_TRIPLE_arm-apple-ios := arm-apple-ios diff --git a/mk/cfg/arm-linux-androideabi b/mk/cfg/arm-linux-androideabi index bf7ec39b654..e24a805b416 100644 --- a/mk/cfg/arm-linux-androideabi +++ b/mk/cfg/arm-linux-androideabi @@ -26,3 +26,4 @@ CFG_RUN_arm-linux-androideabi= CFG_RUN_TARG_arm-linux-androideabi= RUSTC_FLAGS_arm-linux-androideabi := RUSTC_CROSS_FLAGS_arm-linux-androideabi := +CFG_GNU_TRIPLE_arm-linux-androideabi := arm-linux-androideabi diff --git a/mk/cfg/arm-unknown-linux-gnueabi b/mk/cfg/arm-unknown-linux-gnueabi index e76ce27ac96..4b7b9ad87ca 100644 --- a/mk/cfg/arm-unknown-linux-gnueabi +++ b/mk/cfg/arm-unknown-linux-gnueabi @@ -27,3 +27,4 @@ CFG_RUN_arm-unknown-linux-gnueabi=$(2) CFG_RUN_TARG_arm-unknown-linux-gnueabi=$(call CFG_RUN_arm-unknown-linux-gnueabi,,$(2)) RUSTC_FLAGS_arm-unknown-linux-gnueabi := RUSTC_CROSS_FLAGS_arm-unknown-linux-gnueabi := +CFG_GNU_TRIPLE_arm-unknown-linux-gnueabi := arm-unknown-linux-gnueabi diff --git a/mk/cfg/arm-unknown-linux-gnueabihf b/mk/cfg/arm-unknown-linux-gnueabihf index 22bfc2574ca..535dce6b9f3 100644 --- a/mk/cfg/arm-unknown-linux-gnueabihf +++ b/mk/cfg/arm-unknown-linux-gnueabihf @@ -27,3 +27,4 @@ CFG_RUN_arm-unknown-linux-gnueabihf=$(2) CFG_RUN_TARG_arm-unknown-linux-gnueabihf=$(call CFG_RUN_arm-unknown-linux-gnueabihf,,$(2)) RUSTC_FLAGS_arm-unknown-linux-gnueabihf := -C target-feature=+v6,+vfp2 RUSTC_CROSS_FLAGS_arm-unknown-linux-gnueabihf := +CFG_GNU_TRIPLE_arm-unknown-linux-gnueabihf := arm-unknown-linux-gnueabihf diff --git a/mk/cfg/i386-apple-ios b/mk/cfg/i386-apple-ios index c71d664db34..0e0d2724ddb 100644 --- a/mk/cfg/i386-apple-ios +++ b/mk/cfg/i386-apple-ios @@ -31,3 +31,4 @@ 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 +CFG_GNU_TRIPLE_i386-apple-ios := i386-apple-ios diff --git a/mk/cfg/i586-mingw32msvc b/mk/cfg/i586-mingw32msvc deleted file mode 100644 index 30ebbb34d4f..00000000000 --- a/mk/cfg/i586-mingw32msvc +++ /dev/null @@ -1,29 +0,0 @@ -# i586-mingw32msvc configuration -CC_i586-mingw32msvc=$(CFG_MINGW32_CROSS_PATH)/bin/i586-mingw32msvc-gcc -CXX_i586-mingw32msvc=$(CFG_MINGW32_CROSS_PATH)/bin/i586-mingw32msvc-g++ -CPP_i586-mingw32msvc=$(CFG_MINGW32_CROSS_PATH)/bin/i586-mingw32msvc-cpp -AR_i586-mingw32msvc=$(CFG_MINGW32_CROSS_PATH)/bin/i586-mingw32msvc-ar -CFG_LIB_NAME_i586-mingw32msvc=$(1).dll -CFG_STATIC_LIB_NAME_i586-mingw32msvc=$(1).lib -CFG_LIB_GLOB_i586-mingw32msvc=$(1)-*.dll -CFG_LIB_DSYM_GLOB_i586-mingw32msvc=$(1)-*.dylib.dSYM -CFG_CFLAGS_i586-mingw32msvc := -march=i586 -m32 $(CFLAGS) -CFG_GCCISH_CFLAGS_i586-mingw32msvc := -Wall -Werror -g -march=i586 -m32 $(CFLAGS) -CFG_GCCISH_CXXFLAGS_i586-mingw32msvc := -fno-rtti $(CXXFLAGS) -CFG_GCCISH_LINK_FLAGS_i586-mingw32msvc := -shared -g -m32 -CFG_GCCISH_DEF_FLAG_i586-mingw32msvc := -CFG_GCCISH_PRE_LIB_FLAGS_i586-mingw32msvc := -CFG_GCCISH_POST_LIB_FLAGS_i586-mingw32msvc := -CFG_DEF_SUFFIX_i586-mingw32msvc := .mingw32.def -CFG_LLC_FLAGS_i586-mingw32msvc := -CFG_INSTALL_NAME_i586-mingw32msvc = -CFG_EXE_SUFFIX_i586-mingw32msvc := .exe -CFG_WINDOWSY_i586-mingw32msvc := 1 -CFG_UNIXY_i586-mingw32msvc := -CFG_PATH_MUNGE_i586-mingw32msvc := $(strip perl -i.bak -p \ - -e 's@\\(\S)@/\1@go;' \ - -e 's@^/([a-zA-Z])/@\1:/@o;') -CFG_LDPATH_i586-mingw32msvc := -CFG_RUN_i586-mingw32msvc= -CFG_RUN_TARG_i586-mingw32msvc= - diff --git a/mk/cfg/i686-apple-darwin b/mk/cfg/i686-apple-darwin index 0f8a7732834..97ab0b31f63 100644 --- a/mk/cfg/i686-apple-darwin +++ b/mk/cfg/i686-apple-darwin @@ -24,4 +24,4 @@ CFG_PATH_MUNGE_i686-apple-darwin := true CFG_LDPATH_i686-apple-darwin := CFG_RUN_i686-apple-darwin=$(2) CFG_RUN_TARG_i686-apple-darwin=$(call CFG_RUN_i686-apple-darwin,,$(2)) - +CFG_GNU_TRIPLE_i686-apple-darwin := i686-apple-darwin diff --git a/mk/cfg/i686-pc-windows-gnu b/mk/cfg/i686-pc-windows-gnu new file mode 100644 index 00000000000..f24d8312f3c --- /dev/null +++ b/mk/cfg/i686-pc-windows-gnu @@ -0,0 +1,28 @@ +# i686-pc-windows-gnu configuration +CROSS_PREFIX_i686-pc-windows-gnu=i686-pc-windows-gnu- +CC_i686-pc-windows-gnu=gcc +CXX_i686-pc-windows-gnu=g++ +CPP_i686-pc-windows-gnu=gcc -E +AR_i686-pc-windows-gnu=ar +CFG_LIB_NAME_i686-pc-windows-gnu=$(1).dll +CFG_STATIC_LIB_NAME_i686-pc-windows-gnu=$(1).lib +CFG_LIB_GLOB_i686-pc-windows-gnu=$(1)-*.dll +CFG_LIB_DSYM_GLOB_i686-pc-windows-gnu=$(1)-*.dylib.dSYM +CFG_CFLAGS_i686-pc-windows-gnu := -march=i686 -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS) +CFG_GCCISH_CFLAGS_i686-pc-windows-gnu := -Wall -Werror -g -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS) +CFG_GCCISH_CXXFLAGS_i686-pc-windows-gnu := -fno-rtti $(CXXFLAGS) +CFG_GCCISH_LINK_FLAGS_i686-pc-windows-gnu := -shared -g -m32 +CFG_GCCISH_DEF_FLAG_i686-pc-windows-gnu := +CFG_GCCISH_PRE_LIB_FLAGS_i686-pc-windows-gnu := +CFG_GCCISH_POST_LIB_FLAGS_i686-pc-windows-gnu := +CFG_DEF_SUFFIX_i686-pc-windows-gnu := .windows.def +CFG_LLC_FLAGS_i686-pc-windows-gnu := +CFG_INSTALL_NAME_i686-pc-windows-gnu = +CFG_EXE_SUFFIX_i686-pc-windows-gnu := .exe +CFG_WINDOWSY_i686-pc-windows-gnu := 1 +CFG_UNIXY_i686-pc-windows-gnu := +CFG_PATH_MUNGE_i686-pc-windows-gnu := +CFG_LDPATH_i686-pc-windows-gnu :=$(CFG_LDPATH_i686-pc-windows-gnu):$(PATH) +CFG_RUN_i686-pc-windows-gnu=PATH="$(CFG_LDPATH_i686-pc-windows-gnu):$(1)" $(2) +CFG_RUN_TARG_i686-pc-windows-gnu=$(call CFG_RUN_i686-pc-windows-gnu,$(HLIB$(1)_H_$(CFG_BUILD)),$(2)) +CFG_GNU_TRIPLE_i686-pc-windows-gnu := i686-w64-mingw32 diff --git a/mk/cfg/i686-unknown-linux-gnu b/mk/cfg/i686-unknown-linux-gnu index 0b34e0feee7..76ed56d145b 100644 --- a/mk/cfg/i686-unknown-linux-gnu +++ b/mk/cfg/i686-unknown-linux-gnu @@ -24,4 +24,4 @@ CFG_PATH_MUNGE_i686-unknown-linux-gnu := true 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)) - +CFG_GNU_TRIPLE_i686-unknown-linux-gnu := i686-unknown-linux-gnu diff --git a/mk/cfg/i686-w64-mingw32 b/mk/cfg/i686-w64-mingw32 deleted file mode 100644 index b62b805a4fb..00000000000 --- a/mk/cfg/i686-w64-mingw32 +++ /dev/null @@ -1,31 +0,0 @@ -# i686-w64-mingw32 configuration -CROSS_PREFIX_i686-w64-mingw32=i686-w64-mingw32- -CC_i686-w64-mingw32=gcc -CXX_i686-w64-mingw32=g++ -CPP_i686-w64-mingw32=gcc -E -AR_i686-w64-mingw32=ar -CFG_LIB_NAME_i686-w64-mingw32=$(1).dll -CFG_STATIC_LIB_NAME_i686-w64-mingw32=$(1).lib -CFG_LIB_GLOB_i686-w64-mingw32=$(1)-*.dll -CFG_LIB_DSYM_GLOB_i686-w64-mingw32=$(1)-*.dylib.dSYM -CFG_CFLAGS_i686-w64-mingw32 := -march=i686 -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS) -CFG_GCCISH_CFLAGS_i686-w64-mingw32 := -Wall -Werror -g -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS) -CFG_GCCISH_CXXFLAGS_i686-w64-mingw32 := -fno-rtti $(CXXFLAGS) -CFG_GCCISH_LINK_FLAGS_i686-w64-mingw32 := -shared -g -m32 -CFG_GCCISH_DEF_FLAG_i686-w64-mingw32 := -CFG_GCCISH_PRE_LIB_FLAGS_i686-w64-mingw32 := -CFG_GCCISH_POST_LIB_FLAGS_i686-w64-mingw32 := -CFG_DEF_SUFFIX_i686-w64-mingw32 := .mingw32.def -CFG_LLC_FLAGS_i686-w64-mingw32 := -CFG_INSTALL_NAME_i686-w64-mingw32 = -CFG_EXE_SUFFIX_i686-w64-mingw32 := .exe -CFG_WINDOWSY_i686-w64-mingw32 := 1 -CFG_UNIXY_i686-w64-mingw32 := -CFG_PATH_MUNGE_i686-w64-mingw32 := -CFG_LDPATH_i686-w64-mingw32 :=$(CFG_LDPATH_i686-w64-mingw32):$(PATH) -CFG_RUN_i686-w64-mingw32=PATH="$(CFG_LDPATH_i686-w64-mingw32):$(1)" $(2) -CFG_RUN_TARG_i686-w64-mingw32=$(call CFG_RUN_i686-w64-mingw32,$(HLIB$(1)_H_$(CFG_BUILD)),$(2)) -# Stop rustc from OOMing when building itself (I think) -RUSTC_FLAGS_i686-w64-mingw32=-C link-args="-Wl,--large-address-aware" -RUSTC_CROSS_FLAGS_i686-w64-mingw32 := - diff --git a/mk/cfg/mips-unknown-linux-gnu b/mk/cfg/mips-unknown-linux-gnu index c01fdf00f66..1caecec93d1 100644 --- a/mk/cfg/mips-unknown-linux-gnu +++ b/mk/cfg/mips-unknown-linux-gnu @@ -25,3 +25,4 @@ CFG_LDPATH_mips-unknown-linux-gnu := CFG_RUN_mips-unknown-linux-gnu= CFG_RUN_TARG_mips-unknown-linux-gnu= RUSTC_FLAGS_mips-unknown-linux-gnu := -C target-cpu=mips32r2 -C target-feature="+mips32r2,+o32" -C soft-float +CFG_GNU_TRIPLE_mips-unknown-linux-gnu := mips-unknown-linux-gnu diff --git a/mk/cfg/mipsel-linux b/mk/cfg/mipsel-linux deleted file mode 100644 index 963965cbd6c..00000000000 --- a/mk/cfg/mipsel-linux +++ /dev/null @@ -1,27 +0,0 @@ -# mipsel-linux configuration -CC_mipsel-linux=mipsel-linux-gcc -CXX_mipsel-linux=mipsel-linux-g++ -CPP_mipsel-linux=mipsel-linux-gcc -AR_mipsel-linux=mipsel-linux-ar -CFG_LIB_NAME_mipsel-linux=lib$(1).so -CFG_STATIC_LIB_NAME_mipsel-linux=lib$(1).a -CFG_LIB_GLOB_mipsel-linux=lib$(1)-*.so -CFG_LIB_DSYM_GLOB_mipsel-linux=lib$(1)-*.dylib.dSYM -CFG_CFLAGS_mipsel-linux := -mips32 -mabi=32 $(CFLAGS) -CFG_GCCISH_CFLAGS_mipsel-linux := -Wall -g -fPIC -mips32 -mabi=32 $(CFLAGS) -CFG_GCCISH_CXXFLAGS_mipsel-linux := -fno-rtti $(CXXFLAGS) -CFG_GCCISH_LINK_FLAGS_mipsel-linux := -shared -fPIC -g -mips32 -CFG_GCCISH_DEF_FLAG_mipsel-linux := -Wl,--export-dynamic,--dynamic-list= -CFG_GCCISH_PRE_LIB_FLAGS_mipsel-linux := -Wl,-whole-archive -CFG_GCCISH_POST_LIB_FLAGS_mipsel-linux := -Wl,-no-whole-archive -CFG_DEF_SUFFIX_mipsel-linux := .linux.def -CFG_LLC_FLAGS_mipsel-linux := -CFG_INSTALL_NAME_mipsel-linux = -CFG_EXE_SUFFIX_mipsel-linux := -CFG_WINDOWSY_mipsel-linux := -CFG_UNIXY_mipsel-linux := 1 -CFG_PATH_MUNGE_mipsel-linux := true -CFG_LDPATH_mipsel-linux := -CFG_RUN_mipsel-linux= -CFG_RUN_TARG_mipsel-linux= -RUSTC_FLAGS_mipsel-linux := -C target-cpu=mips32 -C target-feature="+mips32,+o32" diff --git a/mk/cfg/mipsel-unknown-linux-gnu b/mk/cfg/mipsel-unknown-linux-gnu new file mode 100644 index 00000000000..d761d5dd090 --- /dev/null +++ b/mk/cfg/mipsel-unknown-linux-gnu @@ -0,0 +1,28 @@ +# mipsel-unknown-linux-gnu configuration +CC_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-gcc +CXX_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-g++ +CPP_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-gcc +AR_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-ar +CFG_LIB_NAME_mipsel-unknown-linux-gnu=lib$(1).so +CFG_STATIC_LIB_NAME_mipsel-unknown-linux-gnu=lib$(1).a +CFG_LIB_GLOB_mipsel-unknown-linux-gnu=lib$(1)-*.so +CFG_LIB_DSYM_GLOB_mipsel-unknown-linux-gnu=lib$(1)-*.dylib.dSYM +CFG_CFLAGS_mipsel-unknown-linux-gnu := -mips32 -mabi=32 $(CFLAGS) +CFG_GCCISH_CFLAGS_mipsel-unknown-linux-gnu := -Wall -g -fPIC -mips32 -mabi=32 $(CFLAGS) +CFG_GCCISH_CXXFLAGS_mipsel-unknown-linux-gnu := -fno-rtti $(CXXFLAGS) +CFG_GCCISH_LINK_FLAGS_mipsel-unknown-linux-gnu := -shared -fPIC -g -mips32 +CFG_GCCISH_DEF_FLAG_mipsel-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list= +CFG_GCCISH_PRE_LIB_FLAGS_mipsel-unknown-linux-gnu := -Wl,-whole-archive +CFG_GCCISH_POST_LIB_FLAGS_mipsel-unknown-linux-gnu := -Wl,-no-whole-archive +CFG_DEF_SUFFIX_mipsel-unknown-linux-gnu := .linux.def +CFG_LLC_FLAGS_mipsel-unknown-linux-gnu := +CFG_INSTALL_NAME_mipsel-unknown-linux-gnu = +CFG_EXE_SUFFIX_mipsel-unknown-linux-gnu := +CFG_WINDOWSY_mipsel-unknown-linux-gnu := +CFG_UNIXY_mipsel-unknown-linux-gnu := 1 +CFG_PATH_MUNGE_mipsel-unknown-linux-gnu := true +CFG_LDPATH_mipsel-unknown-linux-gnu := +CFG_RUN_mipsel-unknown-linux-gnu= +CFG_RUN_TARG_mipsel-unknown-linux-gnu= +RUSTC_FLAGS_mipsel-unknown-linux-gnu := -C target-cpu=mips32 -C target-feature="+mips32,+o32" +CFG_GNU_TRIPLE_mipsel-unknown-linux-gnu := mipsel-unknown-linux-gnu diff --git a/mk/cfg/x86_64-apple-darwin b/mk/cfg/x86_64-apple-darwin index 67b32a6930c..5da7c928da9 100644 --- a/mk/cfg/x86_64-apple-darwin +++ b/mk/cfg/x86_64-apple-darwin @@ -24,3 +24,4 @@ CFG_PATH_MUNGE_x86_64-apple-darwin := true CFG_LDPATH_x86_64-apple-darwin := CFG_RUN_x86_64-apple-darwin=$(2) CFG_RUN_TARG_x86_64-apple-darwin=$(call CFG_RUN_x86_64-apple-darwin,,$(2)) +CFG_GNU_TRIPLE_x86_64-apple-darwin := x86_64-apple-darwin diff --git a/mk/cfg/x86_64-pc-windows-gnu b/mk/cfg/x86_64-pc-windows-gnu new file mode 100644 index 00000000000..fbe2e832f40 --- /dev/null +++ b/mk/cfg/x86_64-pc-windows-gnu @@ -0,0 +1,28 @@ +# x86_64-pc-windows-gnu configuration +CROSS_PREFIX_x86_64-pc-windows-gnu=x86_64-pc-windows-gnu- +CC_x86_64-pc-windows-gnu=gcc +CXX_x86_64-pc-windows-gnu=g++ +CPP_x86_64-pc-windows-gnu=gcc -E +AR_x86_64-pc-windows-gnu=ar +CFG_LIB_NAME_x86_64-pc-windows-gnu=$(1).dll +CFG_STATIC_LIB_NAME_x86_64-pc-windows-gnu=$(1).lib +CFG_LIB_GLOB_x86_64-pc-windows-gnu=$(1)-*.dll +CFG_LIB_DSYM_GLOB_x86_64-pc-windows-gnu=$(1)-*.dylib.dSYM +CFG_CFLAGS_x86_64-pc-windows-gnu := -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS) +CFG_GCCISH_CFLAGS_x86_64-pc-windows-gnu := -Wall -Werror -g -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS) +CFG_GCCISH_CXXFLAGS_x86_64-pc-windows-gnu := -fno-rtti $(CXXFLAGS) +CFG_GCCISH_LINK_FLAGS_x86_64-pc-windows-gnu := -shared -g -m64 +CFG_GCCISH_DEF_FLAG_x86_64-pc-windows-gnu := +CFG_GCCISH_PRE_LIB_FLAGS_x86_64-pc-windows-gnu := +CFG_GCCISH_POST_LIB_FLAGS_x86_64-pc-windows-gnu := +CFG_DEF_SUFFIX_x86_64-pc-windows-gnu := .windows.def +CFG_LLC_FLAGS_x86_64-pc-windows-gnu := +CFG_INSTALL_NAME_x86_64-pc-windows-gnu = +CFG_EXE_SUFFIX_x86_64-pc-windows-gnu := .exe +CFG_WINDOWSY_x86_64-pc-windows-gnu := 1 +CFG_UNIXY_x86_64-pc-windows-gnu := +CFG_PATH_MUNGE_x86_64-pc-windows-gnu := +CFG_LDPATH_x86_64-pc-windows-gnu :=$(CFG_LDPATH_x86_64-pc-windows-gnu):$(PATH) +CFG_RUN_x86_64-pc-windows-gnu=PATH="$(CFG_LDPATH_x86_64-pc-windows-gnu):$(1)" $(2) +CFG_RUN_TARG_x86_64-pc-windows-gnu=$(call CFG_RUN_x86_64-pc-windows-gnu,$(HLIB$(1)_H_$(CFG_BUILD)),$(2)) +CFG_GNU_TRIPLE_x86_64-pc-windows-gnu := x86_64-w64-mingw32 diff --git a/mk/cfg/x86_64-unknown-dragonfly b/mk/cfg/x86_64-unknown-dragonfly index 48e872c5ed3..50928d3c20e 100644 --- a/mk/cfg/x86_64-unknown-dragonfly +++ b/mk/cfg/x86_64-unknown-dragonfly @@ -23,3 +23,4 @@ CFG_PATH_MUNGE_x86_64-unknown-dragonfly := CFG_LDPATH_x86_64-unknown-dragonfly := CFG_RUN_x86_64-unknown-dragonfly=$(2) CFG_RUN_TARG_x86_64-unknown-dragonfly=$(call CFG_RUN_x86_64-unknown-dragonfly,,$(2)) +CFG_GNU_TRIPLE_x86_64-unknown-dragonfly := x86_64-unknown-dragonfly diff --git a/mk/cfg/x86_64-unknown-freebsd b/mk/cfg/x86_64-unknown-freebsd index 8ad42d25642..1926c9873b7 100644 --- a/mk/cfg/x86_64-unknown-freebsd +++ b/mk/cfg/x86_64-unknown-freebsd @@ -23,3 +23,4 @@ CFG_PATH_MUNGE_x86_64-unknown-freebsd := CFG_LDPATH_x86_64-unknown-freebsd := CFG_RUN_x86_64-unknown-freebsd=$(2) CFG_RUN_TARG_x86_64-unknown-freebsd=$(call CFG_RUN_x86_64-unknown-freebsd,,$(2)) +CFG_GNU_TRIPLE_x86_64-unknown-freebsd := x86_64-unknown-freebsd diff --git a/mk/cfg/x86_64-unknown-linux-gnu b/mk/cfg/x86_64-unknown-linux-gnu index d6d0fd7677f..5f165ade3a7 100644 --- a/mk/cfg/x86_64-unknown-linux-gnu +++ b/mk/cfg/x86_64-unknown-linux-gnu @@ -24,3 +24,5 @@ CFG_PATH_MUNGE_x86_64-unknown-linux-gnu := true CFG_LDPATH_x86_64-unknown-linux-gnu := CFG_RUN_x86_64-unknown-linux-gnu=$(2) CFG_RUN_TARG_x86_64-unknown-linux-gnu=$(call CFG_RUN_x86_64-unknown-linux-gnu,,$(2)) +CFG_GNU_TRIPLE_x86_64-unknown-linux-gnu := x86_64-unknown-linux-gnu + diff --git a/mk/cfg/x86_64-w64-mingw32 b/mk/cfg/x86_64-w64-mingw32 deleted file mode 100644 index b292a83bbb4..00000000000 --- a/mk/cfg/x86_64-w64-mingw32 +++ /dev/null @@ -1,28 +0,0 @@ -# x86_64-w64-mingw32 configuration -CROSS_PREFIX_x86_64-w64-mingw32=x86_64-w64-mingw32- -CC_x86_64-w64-mingw32=gcc -CXX_x86_64-w64-mingw32=g++ -CPP_x86_64-w64-mingw32=gcc -E -AR_x86_64-w64-mingw32=ar -CFG_LIB_NAME_x86_64-w64-mingw32=$(1).dll -CFG_STATIC_LIB_NAME_x86_64-w64-mingw32=$(1).lib -CFG_LIB_GLOB_x86_64-w64-mingw32=$(1)-*.dll -CFG_LIB_DSYM_GLOB_x86_64-w64-mingw32=$(1)-*.dylib.dSYM -CFG_CFLAGS_x86_64-w64-mingw32 := -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS) -CFG_GCCISH_CFLAGS_x86_64-w64-mingw32 := -Wall -Werror -g -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS) -CFG_GCCISH_CXXFLAGS_x86_64-w64-mingw32 := -fno-rtti $(CXXFLAGS) -CFG_GCCISH_LINK_FLAGS_x86_64-w64-mingw32 := -shared -g -m64 -CFG_GCCISH_DEF_FLAG_x86_64-w64-mingw32 := -CFG_GCCISH_PRE_LIB_FLAGS_x86_64-w64-mingw32 := -CFG_GCCISH_POST_LIB_FLAGS_x86_64-w64-mingw32 := -CFG_DEF_SUFFIX_x86_64-w64-mingw32 := .mingw32.def -CFG_LLC_FLAGS_x86_64-w64-mingw32 := -CFG_INSTALL_NAME_x86_64-w64-mingw32 = -CFG_EXE_SUFFIX_x86_64-w64-mingw32 := .exe -CFG_WINDOWSY_x86_64-w64-mingw32 := 1 -CFG_UNIXY_x86_64-w64-mingw32 := -CFG_PATH_MUNGE_x86_64-w64-mingw32 := -CFG_LDPATH_x86_64-w64-mingw32 :=$(CFG_LDPATH_x86_64-w64-mingw32):$(PATH) -CFG_RUN_x86_64-w64-mingw32=PATH="$(CFG_LDPATH_x86_64-w64-mingw32):$(1)" $(2) -CFG_RUN_TARG_x86_64-w64-mingw32=$(call CFG_RUN_x86_64-w64-mingw32,$(HLIB$(1)_H_$(CFG_BUILD)),$(2)) -RUSTC_CROSS_FLAGS_x86_64-w64-mingw32 := diff --git a/mk/main.mk b/mk/main.mk index 181bca69462..e10fb4c7f75 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -311,7 +311,6 @@ export CFG_RELEASE export CFG_PACKAGE_NAME export CFG_BUILD export CFG_LLVM_ROOT -export CFG_ENABLE_MINGW_CROSS export CFG_PREFIX export CFG_LIBDIR export CFG_LIBDIR_RELATIVE diff --git a/mk/rt.mk b/mk/rt.mk index 3e050123274..7204808c30a 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -176,7 +176,7 @@ $$(JEMALLOC_LOCAL_$(1)): $$(JEMALLOC_DEPS) $$(MKFILE_DEPS) @$$(call E, make: jemalloc) cd "$$(JEMALLOC_BUILD_DIR_$(1))"; "$(S)src/jemalloc/configure" \ $$(JEMALLOC_ARGS_$(1)) --with-jemalloc-prefix=je_ $(CFG_JEMALLOC_FLAGS) \ - --build=$(CFG_BUILD) --host=$(1) \ + --build=$$(CFG_GNU_TRIPLE_$(CFG_BUILD)) --host=$$(CFG_GNU_TRIPLE_$(1)) \ CC="$$(CC_$(1))" \ AR="$$(AR_$(1))" \ RANLIB="$$(AR_$(1)) s" \ diff --git a/src/etc/snapshot.py b/src/etc/snapshot.py index 268b82bdca3..e0610bfbdfe 100644 --- a/src/etc/snapshot.py +++ b/src/etc/snapshot.py @@ -75,9 +75,8 @@ def full_snapshot_name(date, rev, platform, hsh): def get_kernel(triple): - os_name = triple.split('-')[-1] - #scrub(os.getenv("CFG_ENABLE_MINGW_CROSS")): - if os_name == "nt" or os_name == "mingw32": + os_name = triple.split('-')[2] + if os_name == "windows": return "winnt" if os_name == "darwin": return "macos" diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index d47ca892b13..81f856c29d5 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -19,7 +19,7 @@ use driver::config::NoDebugInfo; use driver::session::Session; use driver::config; use metadata::common::LinkMeta; -use metadata::{encoder, cstore, filesearch, csearch, loader, creader}; +use metadata::{encoder, cstore, filesearch, csearch, creader}; use middle::trans::context::CrateContext; use middle::trans::common::gensym_name; use middle::ty; @@ -36,7 +36,6 @@ use std::str; use std::string::String; use flate; use serialize::hex::ToHex; -use syntax::abi; use syntax::ast; use syntax::ast_map::{PathElem, PathElems, PathName}; use syntax::ast_map; @@ -363,17 +362,8 @@ pub fn mangle_internal_name_by_path_and_seq(path: PathElems, flav: &str) -> Stri pub fn get_cc_prog(sess: &Session) -> String { match sess.opts.cg.linker { Some(ref linker) => return linker.to_string(), - None => {} + None => sess.target.target.options.linker.clone(), } - - // In the future, FreeBSD will use clang as default compiler. - // It would be flexible to use cc (system's default C compiler) - // instead of hard-coded gcc. - // For Windows, there is no cc command, so we add a condition to make it use gcc. - match sess.targ_cfg.os { - abi::OsWindows => "gcc", - _ => "cc", - }.to_string() } pub fn remove(sess: &Session, path: &Path) { @@ -397,7 +387,7 @@ pub fn link_binary(sess: &Session, 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()); + crate_type, sess.opts.target_triple).as_slice()); } let out_file = link_binary_output(sess, trans, crate_type, outputs, crate_name); @@ -427,17 +417,20 @@ pub fn link_binary(sess: &Session, /// 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 + if !sess.target.target.options.executables { + config::CrateTypeStaticlib + } else { + 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, + match (sess.target.target.options.dynamic_linking, + sess.target.target.options.executables, crate_type) { + (false, _, config::CrateTypeDylib) => true, + (_, false, config::CrateTypeExecutable) => true, _ => false } } @@ -459,15 +452,8 @@ pub fn filename_for_input(sess: &Session, out_filename.with_filename(format!("lib{}.rlib", libname)) } config::CrateTypeDylib => { - let (prefix, suffix) = match sess.targ_cfg.os { - abi::OsWindows => (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::OsDragonfly => (loader::DRAGONFLY_DLL_PREFIX, loader::DRAGONFLY_DLL_SUFFIX), - abi::OsiOS => unreachable!(), - }; + let (prefix, suffix) = (sess.target.target.options.dll_prefix.as_slice(), + sess.target.target.options.dll_suffix.as_slice()); out_filename.with_filename(format!("{}{}{}", prefix, libname, @@ -477,15 +463,8 @@ pub fn filename_for_input(sess: &Session, out_filename.with_filename(format!("lib{}.a", libname)) } config::CrateTypeExecutable => { - match sess.targ_cfg.os { - abi::OsWindows => out_filename.with_extension("exe"), - abi::OsMacos | - abi::OsLinux | - abi::OsAndroid | - abi::OsFreebsd | - abi::OsDragonfly | - abi::OsiOS => out_filename.clone(), - } + let suffix = sess.target.target.options.exe_suffix.as_slice(); + out_filename.with_filename(format!("{}{}", libname, suffix)) } } } @@ -562,7 +541,8 @@ fn link_rlib<'a>(sess: &'a Session, handler: handler, dst: out_filename.clone(), lib_search_paths: archive_search_paths(sess), - os: sess.targ_cfg.os, + slib_prefix: sess.target.target.options.staticlib_prefix.clone(), + slib_suffix: sess.target.target.options.staticlib_suffix.clone(), maybe_ar_prog: sess.opts.cg.ar.clone() }; let mut ab = ArchiveBuilder::create(config); @@ -581,12 +561,12 @@ fn link_rlib<'a>(sess: &'a Session, // symbol table of the archive. ab.update_symbols(); - let mut ab = match sess.targ_cfg.os { + let mut ab = match sess.target.target.options.is_like_osx { // For OSX/iOS, we must be careful to update symbols only when adding // object files. We're about to start adding non-object files, so run // `ar` now to process the object files. - abi::OsMacos | abi::OsiOS => ab.build().extend(), - _ => ab, + true => ab.build().extend(), + false => ab, }; // Note that it is important that we add all of our non-object "magical @@ -686,6 +666,13 @@ fn link_rlib<'a>(sess: &'a Session, remove(sess, &bc_filename); } } + + // After adding all files to the archive, we need to update the + // symbol table of the archive. This currently dies on OSX (see + // #11162), and isn't necessary there anyway + if !sess.target.target.options.is_like_osx { + ab.update_symbols(); + } } None => {} @@ -734,11 +721,13 @@ fn write_rlib_bytecode_object_v1(writer: &mut T, // metadata file). fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) { let ab = link_rlib(sess, None, obj_filename, out_filename); - let mut ab = match sess.targ_cfg.os { - abi::OsMacos | abi::OsiOS => ab.build().extend(), - _ => ab, + let mut ab = match sess.target.target.options.is_like_osx { + true => ab.build().extend(), + false => ab, }; - ab.add_native_library("morestack").unwrap(); + if sess.target.target.options.morestack { + ab.add_native_library("morestack").unwrap(); + } ab.add_native_library("compiler-rt").unwrap(); let crates = sess.cstore.get_used_crates(cstore::RequireStatic); @@ -791,9 +780,13 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool, let pname = get_cc_prog(sess); let mut cmd = Command::new(pname.as_slice()); - cmd.args(sess.targ_cfg.target_strs.cc_args.as_slice()); + cmd.args(sess.target.target.options.pre_link_args.as_slice()); link_args(&mut cmd, sess, dylib, tmpdir.path(), trans, obj_filename, out_filename); + cmd.args(sess.target.target.options.post_link_args.as_slice()); + if !sess.target.target.options.no_compiler_rt { + cmd.arg("-lcompiler-rt"); + } if (sess.opts.debugging_opts & config::PRINT_LINK_ARGS) != 0 { println!("{}", &cmd); @@ -831,16 +824,15 @@ 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.targ_cfg.os == abi::OsiOS) - && (sess.opts.debuginfo != NoDebugInfo) { - match Command::new("dsymutil").arg(out_filename).output() { - Ok(..) => {} - Err(e) => { - sess.err(format!("failed to run dsymutil: {}", e).as_slice()); - sess.abort_if_errors(); - } + if sess.target.target.options.is_like_osx && sess.opts.debuginfo != NoDebugInfo { + match Command::new("dsymutil").arg(out_filename).output() { + Ok(..) => {} + Err(e) => { + sess.err(format!("failed to run dsymutil: {}", e).as_slice()); + sess.abort_if_errors(); } } + } } fn link_args(cmd: &mut Command, @@ -854,10 +846,15 @@ fn link_args(cmd: &mut Command, // The default library location, we need this to find the runtime. // The location of crates will be determined as needed. let lib_path = sess.target_filesearch().get_lib_path(); + + // target descriptor + let t = &sess.target.target; + cmd.arg("-L").arg(&lib_path); cmd.arg("-o").arg(out_filename).arg(obj_filename); + // Stack growth requires statically linking a __morestack function. Note // that this is listed *before* all other libraries. Due to the usage of the // --as-needed flag below, the standard library may only be useful for its @@ -874,17 +871,15 @@ fn link_args(cmd: &mut Command, // all contents of this library. This way we're guaranteed that the linker // will include the __morestack symbol 100% of the time, always resolving // references to it even if the object above didn't use it. - match sess.targ_cfg.os { - abi::OsMacos | abi::OsiOS => { + if t.options.morestack { + if t.options.is_like_osx { let morestack = lib_path.join("libmorestack.a"); let mut v = b"-Wl,-force_load,".to_vec(); v.push_all(morestack.as_vec()); cmd.arg(v.as_slice()); - } - _ => { - cmd.args(["-Wl,--whole-archive", "-lmorestack", - "-Wl,--no-whole-archive"]); + } else { + cmd.args(["-Wl,--whole-archive", "-lmorestack", "-Wl,--no-whole-archive"]); } } @@ -895,60 +890,10 @@ fn link_args(cmd: &mut Command, cmd.arg(obj_filename.with_extension("metadata.o")); } - // We want to prevent the compiler from accidentally leaking in any system - // libraries, so we explicitly ask gcc to not link to any libraries by - // default. Note that this does not happen for windows because windows pulls - // in some large number of libraries and I couldn't quite figure out which - // subset we wanted. - // - // FIXME(#11937) we should invoke the system linker directly - if sess.targ_cfg.os != abi::OsWindows { - cmd.arg("-nodefaultlibs"); - } - // Rust does its' own LTO cmd.arg("-fno-lto"); - // clang fails hard if -fno-use-linker-plugin is passed - if sess.targ_cfg.os == abi::OsWindows { - cmd.arg("-fno-use-linker-plugin"); - } - - // If we're building a dylib, we don't use --gc-sections because LLVM has - // 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 && sess.targ_cfg.os != abi::OsiOS { - cmd.arg("-Wl,--gc-sections"); - } - - let used_link_args = sess.cstore.get_used_link_args().borrow(); - - // Dynamically linked executables can be compiled as position independent if the default - // relocation model of position independent code is not changed. This is a requirement to take - // advantage of ASLR, as otherwise the functions in the executable are not randomized and can - // be used during an exploit of a vulnerability in any code. - if sess.targ_cfg.os == abi::OsLinux { - let mut args = sess.opts.cg.link_args.iter().chain(used_link_args.iter()); - if !dylib && sess.opts.cg.relocation_model.as_slice() == "pic" && - !args.any(|x| x.as_slice() == "-static") { - cmd.arg("-pie"); - } - } - - if sess.targ_cfg.os == abi::OsLinux || sess.targ_cfg.os == abi::OsDragonfly { - // GNU-style linkers will use this to omit linking to libraries which - // don't actually fulfill any relocations, but only for libraries which - // follow this flag. Thus, use it before specifying libraries to link to. - cmd.arg("-Wl,--as-needed"); - - // GNU-style linkers support optimization with -O. GNU ld doesn't need a - // numeric argument, but other linkers do. - if sess.opts.optimize == config::Default || - sess.opts.optimize == config::Aggressive { - cmd.arg("-Wl,-O1"); - } - } else if sess.targ_cfg.os == abi::OsMacos || sess.targ_cfg.os == abi::OsiOS { + if t.options.is_like_osx { // 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 @@ -959,67 +904,58 @@ fn link_args(cmd: &mut Command, // won't get much benefit from dylibs because LLVM will have already // stripped away as much as it could. This has not been seen to impact // link times negatively. + // + // -dead_strip can't be part of the pre_link_args because it's also used for partial + // linking when using multiple codegen units (-r). So we insert it here. cmd.arg("-Wl,-dead_strip"); } - if sess.targ_cfg.os == abi::OsWindows { - if sess.targ_cfg.arch == abi::X86 { - // Make sure that we link to the dynamic libgcc, otherwise cross-module - // DWARF stack unwinding will not work. - // This behavior may be overridden by -Clink-args="-static-libgcc" - cmd.arg("-shared-libgcc"); - } else { - // On Win64 unwinding is handled by the OS, so we can link libgcc statically. - cmd.arg("-static-libgcc"); - } + // If we're building a dylib, we don't use --gc-sections because LLVM has + // 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 && !t.options.is_like_osx { + cmd.arg("-Wl,--gc-sections"); + } - // And here, we see obscure linker flags #45. On windows, it has been - // found to be necessary to have this flag to compile liblibc. - // - // First a bit of background. On Windows, the file format is not ELF, - // but COFF (at least according to LLVM). COFF doesn't officially allow - // for section names over 8 characters, apparently. Our metadata - // section, ".note.rustc", you'll note is over 8 characters. - // - // On more recent versions of gcc on mingw, apparently the section name - // is *not* truncated, but rather stored elsewhere in a separate lookup - // table. On older versions of gcc, they apparently always truncated the - // section names (at least in some cases). Truncating the section name - // actually creates "invalid" objects [1] [2], but only for some - // introspection tools, not in terms of whether it can be loaded. - // - // Long story short, passing this flag forces the linker to *not* - // truncate section names (so we can find the metadata section after - // it's compiled). The real kicker is that rust compiled just fine on - // windows for quite a long time *without* this flag, so I have no idea - // why it suddenly started failing for liblibc. Regardless, we - // definitely don't want section name truncation, so we're keeping this - // flag for windows. - // - // [1] - https://sourceware.org/bugzilla/show_bug.cgi?id=13130 - // [2] - https://code.google.com/p/go/issues/detail?id=2139 - cmd.arg("-Wl,--enable-long-section-names"); + let used_link_args = sess.cstore.get_used_link_args().borrow(); - // Always enable DEP (NX bit) when it is available - cmd.arg("-Wl,--nxcompat"); - - // Mark all dynamic libraries and executables as compatible with ASLR - // FIXME #16514: ASLR is disabled on Windows due to MinGW-w64 bugs: - // FIXME #17098: ASLR breaks gdb on Windows - // FIXME #17684: ASLR breaks thread-local storage on Windows - //cmd.arg("-Wl,--dynamicbase"); - - // Mark all dynamic libraries and executables as compatible with the larger 4GiB address - // space available to x86 Windows binaries on x86_64. - if sess.targ_cfg.arch == abi::X86 { - cmd.arg("-Wl,--large-address-aware"); + if t.options.position_independant_executables { + let empty_vec = Vec::new(); + let empty_str = String::new(); + let args = sess.opts.cg.link_args.as_ref().unwrap_or(&empty_vec); + let mut args = args.iter().chain(used_link_args.iter()); + if !dylib + && (t.options.relocation_model.as_slice() == "pic" + || sess.opts.cg.relocation_model.as_ref() + .unwrap_or(&empty_str).as_slice() == "pic") + && !args.any(|x| x.as_slice() == "-static") { + cmd.arg("-pie"); } } - if sess.targ_cfg.os == abi::OsAndroid { - // Many of the symbols defined in compiler-rt are also defined in libgcc. - // Android linker doesn't like that by default. - cmd.arg("-Wl,--allow-multiple-definition"); + if t.options.linker_is_gnu { + // GNU-style linkers support optimization with -O. GNU ld doesn't need a + // numeric argument, but other linkers do. + if sess.opts.optimize == config::Default || + sess.opts.optimize == config::Aggressive { + cmd.arg("-Wl,-O1"); + } + } + + // We want to prevent the compiler from accidentally leaking in any system + // libraries, so we explicitly ask gcc to not link to any libraries by + // default. Note that this does not happen for windows because windows pulls + // in some large number of libraries and I couldn't quite figure out which + // subset we wanted. + if !t.options.is_like_windows { + cmd.arg("-nodefaultlibs"); + } + + // Mark all dynamic libraries and executables as compatible with ASLR + // FIXME #17098: ASLR breaks gdb + if t.options.is_like_windows && sess.opts.debuginfo == NoDebugInfo { + // cmd.arg("-Wl,--dynamicbase"); } // Take careful note of the ordering of the arguments we pass to the linker @@ -1063,7 +999,7 @@ fn link_args(cmd: &mut Command, if dylib { // On mac we need to tell the linker to let this library be rpathed - if sess.targ_cfg.os == abi::OsMacos { + if sess.target.target.options.is_like_osx { cmd.args(["-dynamiclib", "-Wl,-dylib"]); if sess.opts.cg.rpath { @@ -1076,18 +1012,6 @@ fn link_args(cmd: &mut Command, } } - if sess.targ_cfg.os == abi::OsFreebsd { - cmd.args(["-L/usr/local/lib", - "-L/usr/local/lib/gcc46", - "-L/usr/local/lib/gcc44"]); - } - else if sess.targ_cfg.os == abi::OsDragonfly { - cmd.args(["-L/usr/local/lib", - "-L/usr/lib/gcc47", - "-L/usr/lib/gcc44"]); - } - - // FIXME (#2397): At some point we want to rpath our guesses as to // where extern libraries might live, based on the // addl_lib_search_paths @@ -1103,27 +1027,20 @@ fn link_args(cmd: &mut Command, path }; let rpath_config = RPathConfig { - os: sess.targ_cfg.os, used_crates: sess.cstore.get_used_crates(cstore::RequireDynamic), out_filename: out_filename.clone(), + has_rpath: sess.target.target.options.has_rpath, + is_like_osx: sess.target.target.options.is_like_osx, get_install_prefix_lib_path: get_install_prefix_lib_path, realpath: ::util::fs::realpath }; cmd.args(rpath::get_rpath_flags(rpath_config).as_slice()); } - // compiler-rt contains implementations of low-level LLVM helpers. This is - // used to resolve symbols from the object file we just created, as well as - // any system static libraries that may be expecting gcc instead. Most - // symbols in libgcc also appear in compiler-rt. - // - // This is the end of the command line, so this library is used to resolve - // *all* undefined symbols in all other libraries, and this is intentional. - cmd.arg("-lcompiler-rt"); - // Finally add all the linker arguments provided on the command line along // with any #[link_args] attributes found inside the crate - cmd.args(sess.opts.cg.link_args.as_slice()); + let empty = Vec::new(); + cmd.args(sess.opts.cg.link_args.as_ref().unwrap_or(&empty).as_slice()); cmd.args(used_link_args.as_slice()); } @@ -1152,8 +1069,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 && - sess.targ_cfg.os != abi::OsiOS; + let takes_hints = !sess.target.target.options.is_like_osx; let libs = sess.cstore.get_used_libraries(); let libs = libs.borrow(); @@ -1184,7 +1100,8 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) { // -force_load is the OSX equivalent of --whole-archive, but it // involves passing the full path to the library to link. let lib = archive::find_library(l.as_slice(), - sess.targ_cfg.os, + sess.target.target.options.staticlib_prefix.as_slice(), + sess.target.target.options.staticlib_suffix.as_slice(), search_path.as_slice(), &sess.diagnostic().handler); let mut v = b"-Wl,-force_load,".to_vec(); @@ -1257,7 +1174,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session, // Converts a library file-stem into a cc -l argument fn unlib<'a>(config: &config::Config, stem: &'a [u8]) -> &'a [u8] { - if stem.starts_with("lib".as_bytes()) && config.os != abi::OsWindows { + if stem.starts_with("lib".as_bytes()) && !config.target.options.is_like_windows { stem[3..] } else { stem @@ -1315,7 +1232,8 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session, handler: handler, dst: dst.clone(), lib_search_paths: archive_search_paths(sess), - os: sess.targ_cfg.os, + slib_prefix: sess.target.target.options.staticlib_prefix.clone(), + slib_suffix: sess.target.target.options.staticlib_suffix.clone(), maybe_ar_prog: sess.opts.cg.ar.clone() }; let mut archive = Archive::open(config); @@ -1342,7 +1260,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session, if !dir.is_empty() { cmd.arg("-L").arg(dir); } let mut v = "-l".as_bytes().to_vec(); - v.push_all(unlib(&sess.targ_cfg, cratepath.filestem().unwrap())); + v.push_all(unlib(&sess.target, cratepath.filestem().unwrap())); cmd.arg(v.as_slice()); } } diff --git a/src/librustc/back/write.rs b/src/librustc/back/write.rs index 031fc731f41..a869db9eb6b 100644 --- a/src/librustc/back/write.rs +++ b/src/librustc/back/write.rs @@ -18,7 +18,6 @@ use llvm; use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, ContextRef}; use llvm::SMDiagnosticRef; use util::common::time; -use syntax::abi; use syntax::codemap; use syntax::diagnostic; use syntax::diagnostic::{Emitter, Handler, Level, mk_handler}; @@ -150,20 +149,8 @@ impl Emitter for SharedEmitter { // Note that without those flags various linking errors might // arise as some of intrinsics 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 => { - if "" == sess.opts.cg.target_feature.as_slice() { - "+v7" - } 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() - } +fn target_feature(sess: &Session) -> String { + format!("{},{}", sess.target.target.options.features, sess.opts.cg.target_feature) } fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel { @@ -176,7 +163,11 @@ fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel { } fn create_target_machine(sess: &Session) -> TargetMachineRef { - let reloc_model = match sess.opts.cg.relocation_model.as_slice() { + let reloc_model_arg = match sess.opts.cg.relocation_model { + Some(ref s) => s.as_slice(), + None => sess.target.target.options.relocation_model.as_slice() + }; + let reloc_model = match reloc_model_arg { "pic" => llvm::RelocPIC, "static" => llvm::RelocStatic, "default" => llvm::RelocDefault, @@ -195,22 +186,22 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef { let use_softfp = sess.opts.cg.soft_float; // FIXME: #11906: Omitting frame pointers breaks retrieving the value of a parameter. - // FIXME: #11954: mac64 unwinding may not work with fp elim let no_fp_elim = (sess.opts.debuginfo != NoDebugInfo) || - (sess.targ_cfg.os == abi::OsMacos && - sess.targ_cfg.arch == abi::X86_64); + !sess.target.target.options.eliminate_frame_pointer; let any_library = sess.crate_types.borrow().iter().any(|ty| { *ty != config::CrateTypeExecutable }); - // OSX has -dead_strip, which doesn't rely on ffunction_sections - // FIXME(#13846) this should be enabled for windows - let ffunction_sections = sess.targ_cfg.os != abi::OsMacos && - sess.targ_cfg.os != abi::OsWindows; + let ffunction_sections = sess.target.target.options.function_sections; let fdata_sections = ffunction_sections; - let code_model = match sess.opts.cg.code_model.as_slice() { + let code_model_arg = match sess.opts.cg.code_model { + Some(ref s) => s.as_slice(), + None => sess.target.target.options.code_model.as_slice() + }; + + let code_model = match code_model_arg { "default" => llvm::CodeModelDefault, "small" => llvm::CodeModelSmall, "kernel" => llvm::CodeModelKernel, @@ -226,11 +217,15 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef { } }; - let triple = sess.targ_cfg.target_strs.target_triple.as_slice(); + let triple = sess.target.target.llvm_target.as_slice(); let tm = unsafe { - triple.with_c_str(|t| { - sess.opts.cg.target_cpu.as_slice().with_c_str(|cpu| { + triple.with_c_str(|t| { + let cpu = match sess.opts.cg.target_cpu { + Some(ref s) => s.as_slice(), + None => sess.target.target.options.cpu.as_slice() + }; + cpu.with_c_str(|cpu| { target_feature(sess).with_c_str(|features| { llvm::LLVMRustCreateTargetMachine( t, cpu, features, @@ -692,7 +687,7 @@ pub fn run_passes(sess: &Session, // the desired path. This will give the correct behavior whether or // not GCC adds --force-exe-suffix. let windows_output_path = - if sess.targ_cfg.os == abi::OsWindows { + if sess.target.target.options.is_like_windows { Some(output_path.with_extension("o.exe")) } else { None @@ -701,7 +696,7 @@ pub fn run_passes(sess: &Session, let pname = get_cc_prog(sess); let mut cmd = Command::new(pname.as_slice()); - cmd.args(sess.targ_cfg.target_strs.cc_args.as_slice()); + cmd.args(sess.target.target.options.pre_link_args.as_slice()); cmd.arg("-nostdlib"); for index in range(0, trans.modules.len()) { @@ -712,6 +707,8 @@ pub fn run_passes(sess: &Session, .arg("-o") .arg(windows_output_path.as_ref().unwrap_or(output_path)); + cmd.args(sess.target.target.options.post_link_args.as_slice()); + if (sess.opts.debugging_opts & config::PRINT_LINK_ARGS) != 0 { println!("{}", &cmd); } diff --git a/src/librustc/driver/config.rs b/src/librustc/driver/config.rs index 10c40a32da6..8c1d7c839ac 100644 --- a/src/librustc/driver/config.rs +++ b/src/librustc/driver/config.rs @@ -17,17 +17,15 @@ use driver::session::Session; use back; use back::write; -use back::target_strs; -use back::{arm, x86, x86_64, mips, mipsel}; +use rustc_back::target::Target; use lint; use metadata::cstore; -use syntax::abi; use syntax::ast; use syntax::ast::{IntTy, UintTy}; use syntax::attr; use syntax::attr::AttrMetaMethods; -use syntax::diagnostic::{ColorConfig, Auto, Always, Never}; +use syntax::diagnostic::{ColorConfig, Auto, Always, Never, SpanHandler}; use syntax::parse; use syntax::parse::token::InternedString; @@ -41,9 +39,7 @@ use std::fmt; use llvm; pub struct Config { - pub os: abi::Os, - pub arch: abi::Architecture, - pub target_strs: target_strs::t, + pub target: Target, pub int_type: IntTy, pub uint_type: UintTy, } @@ -291,6 +287,13 @@ macro_rules! cgoptions( } } + fn parse_opt_bool(slot: &mut Option, v: Option<&str>) -> bool { + match v { + Some(..) => false, + None => { *slot = Some(true); true } + } + } + fn parse_opt_string(slot: &mut Option, v: Option<&str>) -> bool { match v { Some(s) => { *slot = Some(s.to_string()); true }, @@ -318,6 +321,18 @@ macro_rules! cgoptions( } } + fn parse_opt_list(slot: &mut Option>, v: Option<&str>) + -> bool { + match v { + Some(s) => { + let v = s.words().map(|s| s.to_string()).collect(); + *slot = Some(v); + true + }, + None => false, + } + } + fn parse_uint(slot: &mut uint, v: Option<&str>) -> bool { use std::from_str::FromStr; match v.and_then(FromStr::from_str) { @@ -351,11 +366,11 @@ cgoptions!( "tool to assemble archives with"), linker: Option = (None, parse_opt_string, "system linker to link outputs with"), - link_args: Vec = (Vec::new(), parse_list, + link_args: Option> = (None, parse_opt_list, "extra arguments to pass to the linker (space separated)"), lto: bool = (false, parse_bool, "perform LLVM link-time optimizations"), - target_cpu: String = ("generic".to_string(), parse_string, + target_cpu: Option = (None, parse_opt_string, "select target processor (llc -mcpu=help for details)"), target_feature: String = ("".to_string(), parse_string, "target specific attributes (llc -mattr=help for details)"), @@ -379,11 +394,11 @@ cgoptions!( "prefer dynamic linking to static linking"), no_integrated_as: bool = (false, parse_bool, "use an external assembler rather than LLVM's integrated one"), - no_redzone: bool = (false, parse_bool, + no_redzone: Option = (None, parse_opt_bool, "disable the use of the redzone"), - relocation_model: String = ("pic".to_string(), parse_string, + relocation_model: Option = (None, parse_opt_string, "choose the relocation model to use (llc -relocation-model for details)"), - code_model: String = ("default".to_string(), parse_string, + code_model: Option = (None, parse_opt_string, "choose the code model to use (llc -code-model for details)"), metadata: Vec = (Vec::new(), parse_list, "metadata to mangle symbol names with"), @@ -437,40 +452,27 @@ pub fn default_lib_output() -> CrateType { } pub fn default_configuration(sess: &Session) -> ast::CrateConfig { - let tos = match sess.targ_cfg.os { - abi::OsWindows => InternedString::new("windows"), - abi::OsMacos => InternedString::new("macos"), - abi::OsLinux => InternedString::new("linux"), - abi::OsAndroid => InternedString::new("android"), - abi::OsFreebsd => InternedString::new("freebsd"), - abi::OsDragonfly => InternedString::new("dragonfly"), - abi::OsiOS => InternedString::new("ios"), - }; + use syntax::parse::token::intern_and_get_ident as intern; - // ARM is bi-endian, however using NDK seems to default - // to little-endian unless a flag is provided. - let (end,arch,wordsz) = match sess.targ_cfg.arch { - abi::X86 => ("little", "x86", "32"), - abi::X86_64 => ("little", "x86_64", "64"), - abi::Arm => ("little", "arm", "32"), - abi::Mips => ("big", "mips", "32"), - abi::Mipsel => ("little", "mipsel", "32") - }; + let end = sess.target.target.target_endian.as_slice(); + let arch = sess.target.target.arch.as_slice(); + let wordsz = sess.target.target.target_word_size.as_slice(); + let os = sess.target.target.target_os.as_slice(); - let fam = match sess.targ_cfg.os { - abi::OsWindows => InternedString::new("windows"), - _ => InternedString::new("unix") + let fam = match sess.target.target.options.is_like_windows { + true => InternedString::new("windows"), + false => InternedString::new("unix") }; let mk = attr::mk_name_value_item_str; return vec!(// Target bindings. attr::mk_word_item(fam.clone()), - mk(InternedString::new("target_os"), tos), + mk(InternedString::new("target_os"), intern(os)), mk(InternedString::new("target_family"), fam), - mk(InternedString::new("target_arch"), InternedString::new(arch)), - mk(InternedString::new("target_endian"), InternedString::new(end)), + mk(InternedString::new("target_arch"), intern(arch)), + mk(InternedString::new("target_endian"), intern(end)), mk(InternedString::new("target_word_size"), - InternedString::new(wordsz)) + intern(wordsz)) ); } @@ -495,78 +497,23 @@ pub fn build_configuration(sess: &Session) -> ast::CrateConfig { v } -pub fn get_os(triple: &str) -> Option { - for &(name, os) in os_names.iter() { - if triple.contains(name) { return Some(os) } +pub fn build_target_config(opts: &Options, sp: &SpanHandler) -> Config { + let target = match Target::search(opts.target_triple.as_slice()) { + Ok(t) => t, + Err(e) => { + sp.handler().fatal((format!("Error loading target specification: {}", e)).as_slice()); } - None -} -#[allow(non_upper_case_globals)] -static os_names : &'static [(&'static str, abi::Os)] = &[ - ("mingw32", abi::OsWindows), - ("win32", abi::OsWindows), - ("windows", abi::OsWindows), - ("darwin", abi::OsMacos), - ("android", abi::OsAndroid), - ("linux", abi::OsLinux), - ("freebsd", abi::OsFreebsd), - ("dragonfly", abi::OsDragonfly), - ("ios", abi::OsiOS)]; - -pub fn get_arch(triple: &str) -> Option { - for &(arch, abi) in architecture_abis.iter() { - if triple.contains(arch) { return Some(abi) } - } - None -} -#[allow(non_upper_case_globals)] -static architecture_abis : &'static [(&'static str, abi::Architecture)] = &[ - ("i386", abi::X86), - ("i486", abi::X86), - ("i586", abi::X86), - ("i686", abi::X86), - ("i786", abi::X86), - - ("x86_64", abi::X86_64), - - ("arm", abi::Arm), - ("xscale", abi::Arm), - ("thumb", abi::Arm), - - ("mipsel", abi::Mipsel), - ("mips", abi::Mips)]; - -pub fn build_target_config(sopts: &Options) -> Config { - let os = match get_os(sopts.target_triple.as_slice()) { - Some(os) => os, - None => early_error("unknown operating system") }; - let arch = match get_arch(sopts.target_triple.as_slice()) { - Some(arch) => arch, - None => { - early_error(format!("unknown architecture: {}", - sopts.target_triple.as_slice()).as_slice()) - } - }; - let (int_type, uint_type) = match arch { - abi::X86 => (ast::TyI32, ast::TyU32), - abi::X86_64 => (ast::TyI64, ast::TyU64), - abi::Arm => (ast::TyI32, ast::TyU32), - abi::Mips => (ast::TyI32, ast::TyU32), - abi::Mipsel => (ast::TyI32, ast::TyU32) - }; - let target_triple = sopts.target_triple.clone(); - let target_strs = match arch { - abi::X86 => x86::get_target_strs(target_triple, os), - abi::X86_64 => x86_64::get_target_strs(target_triple, os), - abi::Arm => arm::get_target_strs(target_triple, os), - abi::Mips => mips::get_target_strs(target_triple, os), - abi::Mipsel => mipsel::get_target_strs(target_triple, os) + + let (int_type, uint_type) = match target.target_word_size.as_slice() { + "32" => (ast::TyI32, ast::TyU32), + "64" => (ast::TyI64, ast::TyU64), + w => sp.handler().fatal((format!("target specification was invalid: unrecognized \ + target-word-size {}", w)).as_slice()) }; + Config { - os: os, - arch: arch, - target_strs: target_strs, + target: target, int_type: int_type, uint_type: uint_type, } diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index d3ed0dbd99e..d347f113af3 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -749,8 +749,8 @@ pub fn collect_crate_types(session: &Session, if !res { session.warn(format!("dropping unsupported crate type `{}` \ - for target os `{}`", - *crate_type, session.targ_cfg.os).as_slice()); + for target `{}`", + *crate_type, session.opts.target_triple).as_slice()); } res diff --git a/src/librustc/driver/mod.rs b/src/librustc/driver/mod.rs index 028d0ec607a..7715f0e10f5 100644 --- a/src/librustc/driver/mod.rs +++ b/src/librustc/driver/mod.rs @@ -435,7 +435,7 @@ pub fn early_warn(msg: &str) { pub fn list_metadata(sess: &Session, path: &Path, out: &mut io::Writer) -> io::IoResult<()> { - metadata::loader::list_file_metadata(sess.targ_cfg.os, path, out) + metadata::loader::list_file_metadata(sess.target.target.options.is_like_osx, path, out) } /// Run a procedure which will detect failures in the compiler and print nicer diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index f8e778ce15f..57c65ccebc5 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -32,7 +32,7 @@ use std::cell::{Cell, RefCell}; // Represents the data associated with a compilation // session for a single crate. pub struct Session { - pub targ_cfg: config::Config, + pub target: config::Config, pub opts: config::Options, pub cstore: CStore, pub parse_sess: ParseSess, @@ -219,7 +219,7 @@ pub fn build_session_(sopts: config::Options, local_crate_source_file: Option, span_diagnostic: diagnostic::SpanHandler) -> Session { - let target_cfg = config::build_target_config(&sopts); + let target_cfg = config::build_target_config(&sopts, &span_diagnostic); let p_s = parse::new_parse_sess_special_handler(span_diagnostic); let default_sysroot = match sopts.maybe_sysroot { Some(_) => None, @@ -236,7 +236,7 @@ pub fn build_session_(sopts: config::Options, ); let sess = Session { - targ_cfg: target_cfg, + target: target_cfg, opts: sopts, cstore: CStore::new(token::get_ident_interner()), parse_sess: p_s, diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 0c26981c2a0..c00551b220d 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -210,7 +210,7 @@ impl LintPass for TypeLimits { ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) | ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => { let int_type = if t == ast::TyI { - cx.sess().targ_cfg.int_type + cx.sess().target.int_type } else { t }; let (min, max) = int_ty_range(int_type); let negative = self.negated_expr_id == e.id; @@ -227,7 +227,7 @@ impl LintPass for TypeLimits { }, ty::ty_uint(t) => { let uint_type = if t == ast::TyU { - cx.sess().targ_cfg.uint_type + cx.sess().target.uint_type } else { t }; let (min, max) = uint_ty_range(uint_type); let lit_val: u64 = match lit.node { diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 797bc5814fc..91d7eeaf8f2 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -14,7 +14,7 @@ use back::svh::Svh; use driver::session::Session; -use driver::{driver, config}; +use driver::driver; use metadata::cstore; use metadata::cstore::{CStore, CrateSource}; use metadata::decoder; @@ -237,6 +237,9 @@ fn visit_item(e: &Env, i: &ast::Item) { Some(k) => { if k.equiv(&("static")) { cstore::NativeStatic + } else if e.sess.target.target.options.is_like_osx + && k.equiv(&("framework")) { + cstore::NativeFramework } else if k.equiv(&("framework")) { cstore::NativeFramework } else { @@ -285,8 +288,7 @@ fn register_native_lib(sess: &Session, span: Option, name: String, } return } - let is_osx = sess.targ_cfg.os == abi::OsMacos || - sess.targ_cfg.os == abi::OsiOS; + let is_osx = sess.target.target.options.is_like_osx; if kind == cstore::NativeFramework && !is_osx { let msg = "native frameworks are only available on OSX targets"; match span { @@ -400,8 +402,7 @@ fn resolve_crate<'a>(e: &mut Env, crate_name: name, hash: hash.map(|a| &*a), filesearch: e.sess.target_filesearch(), - os: e.sess.targ_cfg.os, - triple: e.sess.targ_cfg.target_strs.target_triple.as_slice(), + triple: e.sess.opts.target_triple.as_slice(), root: root, rejected_via_hash: vec!(), rejected_via_triple: vec!(), @@ -451,10 +452,9 @@ impl<'a> PluginMetadataReader<'a> { pub fn read_plugin_metadata(&mut self, krate: &ast::ViewItem) -> PluginMetadata { let info = extract_crate_info(&self.env, krate).unwrap(); - let target_triple = self.env.sess.targ_cfg.target_strs.target_triple.as_slice(); + let target_triple = self.env.sess.opts.target_triple.as_slice(); let is_cross = target_triple != driver::host_triple(); let mut should_link = info.should_link && !is_cross; - let os = config::get_os(driver::host_triple()).unwrap(); let mut load_ctxt = loader::Context { sess: self.env.sess, span: krate.span, @@ -463,7 +463,6 @@ impl<'a> PluginMetadataReader<'a> { hash: None, filesearch: self.env.sess.host_filesearch(), triple: driver::host_triple(), - os: os, root: &None, rejected_via_hash: vec!(), rejected_via_triple: vec!(), @@ -475,7 +474,6 @@ 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 = 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/encoder.rs b/src/librustc/metadata/encoder.rs index fd389c1f314..da7e78d272f 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -2071,8 +2071,7 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter, parms: EncodeParams, krate: encode_crate_name(&mut rbml_w, ecx.link_meta.crate_name.as_slice()); encode_crate_triple(&mut rbml_w, tcx.sess - .targ_cfg - .target_strs + .opts .target_triple .as_slice()); encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash); diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 738eeaae6a5..f46af9088d8 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -222,7 +222,6 @@ 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 util::fs; @@ -240,24 +239,6 @@ use std::collections::hash_map::{Occupied, Vacant}; use flate; use time; -pub const MACOS_DLL_PREFIX: &'static str = "lib"; -pub const MACOS_DLL_SUFFIX: &'static str = ".dylib"; - -pub const WIN32_DLL_PREFIX: &'static str = ""; -pub const WIN32_DLL_SUFFIX: &'static str = ".dll"; - -pub const LINUX_DLL_PREFIX: &'static str = "lib"; -pub const LINUX_DLL_SUFFIX: &'static str = ".so"; - -pub const FREEBSD_DLL_PREFIX: &'static str = "lib"; -pub const FREEBSD_DLL_SUFFIX: &'static str = ".so"; - -pub const DRAGONFLY_DLL_PREFIX: &'static str = "lib"; -pub const DRAGONFLY_DLL_SUFFIX: &'static str = ".so"; - -pub const ANDROID_DLL_PREFIX: &'static str = "lib"; -pub const ANDROID_DLL_SUFFIX: &'static str = ".so"; - pub struct CrateMismatch { path: Path, got: String, @@ -270,7 +251,6 @@ pub struct Context<'a> { pub crate_name: &'a str, pub hash: Option<&'a Svh>, pub triple: &'a str, - pub os: abi::Os, pub filesearch: FileSearch<'a>, pub root: &'a Option, pub rejected_via_hash: Vec, @@ -387,9 +367,7 @@ impl<'a> Context<'a> { let dypair = self.dylibname(); // want: crate_name.dir_part() + prefix + crate_name.file_part + "-" - let dylib_prefix = dypair.map(|(prefix, _)| { - format!("{}{}", prefix, self.crate_name) - }); + let dylib_prefix = format!("{}{}", dypair.ref0(), self.crate_name); let rlib_prefix = format!("lib{}", self.crate_name); let mut candidates = HashMap::new(); @@ -416,13 +394,9 @@ impl<'a> Context<'a> { file.ends_with(".rlib") { (file.slice(rlib_prefix.len(), file.len() - ".rlib".len()), true) - } else if dypair.map_or(false, |(_, suffix)| { - file.starts_with(dylib_prefix.as_ref().unwrap().as_slice()) && - file.ends_with(suffix) - }) { - let (_, suffix) = dypair.unwrap(); - let dylib_prefix = dylib_prefix.as_ref().unwrap().as_slice(); - (file.slice(dylib_prefix.len(), file.len() - suffix.len()), + } else if file.starts_with(dylib_prefix.as_slice()) && + file.ends_with(dypair.ref1().as_slice()) { + (file.slice(dylib_prefix.len(), file.len() - dypair.ref1().len()), false) } else { return FileDoesntMatch @@ -530,7 +504,8 @@ impl<'a> Context<'a> { for lib in m.into_iter() { info!("{} reading metadata from: {}", flavor, lib.display()); - let metadata = match get_metadata_section(self.os, &lib) { + let metadata = match get_metadata_section(self.sess.target.target.options.is_like_osx, + &lib) { Ok(blob) => { if self.crate_matches(blob.as_slice(), &lib) { blob @@ -617,16 +592,9 @@ impl<'a> Context<'a> { // Returns the corresponding (prefix, suffix) that files need to have for // dynamic libraries - fn dylibname(&self) -> Option<(&'static str, &'static str)> { - match self.os { - abi::OsWindows => 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::OsDragonfly => Some((DRAGONFLY_DLL_PREFIX, DRAGONFLY_DLL_SUFFIX)), - abi::OsiOS => None, - } + fn dylibname(&self) -> (String, String) { + let t = &self.sess.target.target; + (t.options.dll_prefix.clone(), t.options.dll_suffix.clone()) } fn find_commandline_library(&mut self) -> Option { @@ -660,13 +628,9 @@ impl<'a> Context<'a> { if file.starts_with("lib") && file.ends_with(".rlib") { return true } else { - match dylibname { - Some((prefix, suffix)) => { - if file.starts_with(prefix) && file.ends_with(suffix) { - return true - } - } - None => {} + let (ref prefix, ref suffix) = dylibname; + if file.starts_with(prefix.as_slice()) && file.ends_with(suffix.as_slice()) { + return true } } sess.err(format!("extern location for {} is of an unknown type: {}", @@ -726,15 +690,15 @@ impl ArchiveMetadata { } // Just a small wrapper to time how long reading metadata takes. -fn get_metadata_section(os: abi::Os, filename: &Path) -> Result { +fn get_metadata_section(is_osx: bool, filename: &Path) -> Result { let start = time::precise_time_ns(); - let ret = get_metadata_section_imp(os, filename); + let ret = get_metadata_section_imp(is_osx, filename); info!("reading {} => {}ms", filename.filename_display(), (time::precise_time_ns() - start) / 1000000); return ret; } -fn get_metadata_section_imp(os: abi::Os, filename: &Path) -> Result { +fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result { if !filename.exists() { return Err(format!("no such file: '{}'", filename.display())); } @@ -780,7 +744,7 @@ fn get_metadata_section_imp(os: abi::Os, filename: &Path) -> Result Result Option<&'static str> { - match os { - abi::OsMacos => Some("__DATA,__note.rustc"), - abi::OsiOS => Some("__DATA,__note.rustc"), - abi::OsWindows => Some(".note.rustc"), - abi::OsLinux => Some(".note.rustc"), - abi::OsAndroid => Some(".note.rustc"), - abi::OsFreebsd => Some(".note.rustc"), - abi::OsDragonfly => Some(".note.rustc"), +pub fn meta_section_name(is_osx: bool) -> &'static str { + if is_osx { + "__DATA,__note.rustc" + } else { + ".note.rustc" } } -pub fn read_meta_section_name(os: abi::Os) -> &'static str { - match os { - abi::OsMacos => "__note.rustc", - abi::OsiOS => unreachable!(), - abi::OsWindows => ".note.rustc", - abi::OsLinux => ".note.rustc", - abi::OsAndroid => ".note.rustc", - abi::OsFreebsd => ".note.rustc", - abi::OsDragonfly => ".note.rustc" +pub fn read_meta_section_name(is_osx: bool) -> &'static str { + if is_osx { + "__note.rustc" + } else { + ".note.rustc" } } // A diagnostic function for dumping crate metadata to an output stream -pub fn list_file_metadata(os: abi::Os, path: &Path, +pub fn list_file_metadata(is_osx: bool, path: &Path, out: &mut io::Writer) -> io::IoResult<()> { - match get_metadata_section(os, path) { + match get_metadata_section(is_osx, path) { Ok(bytes) => decoder::list_crate_metadata(bytes.as_slice(), out), Err(msg) => { write!(out, "{}\n", msg) diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index 15ca00f6a7f..0a28c93a34e 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -135,13 +135,13 @@ fn calculate_type(sess: &session::Session, sess.cstore.iter_crate_data(|cnum, data| { let src = sess.cstore.get_used_crate_source(cnum).unwrap(); if src.dylib.is_some() { - add_library(sess, cnum, cstore::RequireDynamic, &mut formats); debug!("adding dylib: {}", data.name); + add_library(sess, cnum, cstore::RequireDynamic, &mut formats); let deps = csearch::get_dylib_dependency_formats(&sess.cstore, cnum); for &(depnum, style) in deps.iter() { - add_library(sess, depnum, style, &mut formats); debug!("adding {}: {}", style, sess.cstore.get_crate_data(depnum).name.clone()); + add_library(sess, depnum, style, &mut formats); } } }); @@ -160,9 +160,9 @@ fn calculate_type(sess: &session::Session, let src = sess.cstore.get_used_crate_source(cnum).unwrap(); if src.dylib.is_none() && !formats.contains_key(&cnum) { assert!(src.rlib.is_some()); + debug!("adding staticlib: {}", data.name); add_library(sess, cnum, cstore::RequireStatic, &mut formats); ret[cnum as uint - 1] = Some(cstore::RequireStatic); - debug!("adding staticlib: {}", data.name); } }); diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs index 7dbddd3f5df..d3658e89a2a 100644 --- a/src/librustc/middle/trans/adt.rs +++ b/src/librustc/middle/trans/adt.rs @@ -62,7 +62,6 @@ use middle::trans::type_::Type; use middle::trans::type_of; use middle::ty; use middle::ty::Disr; -use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel}; use syntax::ast; use syntax::attr; use syntax::attr::IntType; @@ -410,14 +409,12 @@ fn range_to_inttype(cx: &CrateContext, hint: Hint, bounds: &IntBounds) -> IntTyp return ity; } attr::ReprExtern => { - attempts = match cx.sess().targ_cfg.arch { - X86 | X86_64 => at_least_32, + attempts = match cx.sess().target.target.arch.as_slice() { // WARNING: the ARM EABI has two variants; the one corresponding to `at_least_32` // appears to be used on Linux and NetBSD, but some systems may use the variant // corresponding to `choose_shortest`. However, we don't run on those yet...? - Arm => at_least_32, - Mips => at_least_32, - Mipsel => at_least_32, + "arm" => at_least_32, + _ => at_least_32, } } attr::ReprAny => { diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 5c9546bf212..b80425e7ac8 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -87,8 +87,7 @@ use std::cell::{Cell, RefCell}; use std::collections::HashSet; use std::rc::Rc; use std::{i8, i16, i32, i64}; -use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel, Rust, RustCall}; -use syntax::abi::{RustIntrinsic, Abi, OsWindows}; +use syntax::abi::{Rust, RustCall, RustIntrinsic, Abi}; use syntax::ast_util::local_def; use syntax::attr::AttrMetaMethods; use syntax::attr; @@ -193,7 +192,8 @@ pub fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv, llvm::SetFunctionAttribute(llfn, llvm::NoReturnAttribute); } - if ccx.tcx().sess.opts.cg.no_redzone { + if ccx.tcx().sess.opts.cg.no_redzone + .unwrap_or(ccx.tcx().sess.target.target.options.disable_redzone) { llvm::SetFunctionAttribute(llfn, llvm::NoRedZoneAttribute) } @@ -934,17 +934,16 @@ pub fn trans_external_path(ccx: &CrateContext, did: ast::DefId, t: ty::t) -> Val let name = csearch::get_symbol(&ccx.sess().cstore, did); match ty::get(t).sty { ty::ty_bare_fn(ref fn_ty) => { - match fn_ty.abi.for_target(ccx.sess().targ_cfg.os, - ccx.sess().targ_cfg.arch) { - Some(Rust) | Some(RustCall) => { + match ccx.sess().target.target.adjust_abi(fn_ty.abi) { + Rust | RustCall => { get_extern_rust_fn(ccx, t, name.as_slice(), did) } - Some(RustIntrinsic) => { + RustIntrinsic => { ccx.sess().bug("unexpected intrinsic in trans_external_path") } - Some(..) | None => { + _ => { foreign::register_foreign_item_fn(ccx, fn_ty.abi, t, - name.as_slice(), None) + name.as_slice()) } } } @@ -1143,9 +1142,10 @@ pub fn call_lifetime_end(cx: Block, ptr: ValueRef) { pub fn call_memcpy(cx: Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) { let _icx = push_ctxt("call_memcpy"); let ccx = cx.ccx(); - let key = match ccx.sess().targ_cfg.arch { - X86 | Arm | Mips | Mipsel => "llvm.memcpy.p0i8.p0i8.i32", - X86_64 => "llvm.memcpy.p0i8.p0i8.i64" + let key = match ccx.sess().target.target.target_word_size.as_slice() { + "32" => "llvm.memcpy.p0i8.p0i8.i32", + "64" => "llvm.memcpy.p0i8.p0i8.i64", + tws => panic!("Unsupported target word size for memcpy: {}", tws), }; let memcpy = ccx.get_intrinsic(&key); let src_ptr = PointerCast(cx, src, Type::i8p(ccx)); @@ -1187,9 +1187,10 @@ fn memzero(b: &Builder, llptr: ValueRef, ty: ty::t) { let llty = type_of::type_of(ccx, ty); - let intrinsic_key = match ccx.sess().targ_cfg.arch { - X86 | Arm | Mips | Mipsel => "llvm.memset.p0i8.i32", - X86_64 => "llvm.memset.p0i8.i64" + let intrinsic_key = match ccx.sess().target.target.target_word_size.as_slice() { + "32" => "llvm.memset.p0i8.i32", + "64" => "llvm.memset.p0i8.i64", + tws => panic!("Unsupported target word size for memset: {}", tws), }; let llintrinsicfn = ccx.get_intrinsic(&intrinsic_key); @@ -2583,7 +2584,7 @@ pub fn create_entry_wrapper(ccx: &CrateContext, // FIXME: #16581: Marking a symbol in the executable with `dllexport` // linkage forces MinGW's linker to output a `.reloc` section for ASLR - if ccx.sess().targ_cfg.os == OsWindows { + if ccx.sess().target.target.options.is_like_windows { unsafe { llvm::LLVMRustSetDLLExportStorageClass(llfn) } } @@ -2803,9 +2804,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { let abi = ccx.tcx().map.get_foreign_abi(id); let ty = ty::node_id_to_type(ccx.tcx(), ni.id); let name = foreign::link_name(&*ni); - foreign::register_foreign_item_fn(ccx, abi, ty, - name.get().as_slice(), - Some(ni.span)) + foreign::register_foreign_item_fn(ccx, abi, ty, name.get().as_slice()) } ast::ForeignItemStatic(..) => { foreign::register_static(ccx, &*ni) @@ -2946,8 +2945,8 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec { }); unsafe { llvm::LLVMSetInitializer(llglobal, llconst); - let name = loader::meta_section_name(cx.sess().targ_cfg.os); - name.unwrap_or("rust_metadata").with_c_str(|buf| { + let name = loader::meta_section_name(cx.sess().target.target.options.is_like_osx); + name.with_c_str(|buf| { llvm::LLVMSetSection(llglobal, buf) }); } diff --git a/src/librustc/middle/trans/cabi.rs b/src/librustc/middle/trans/cabi.rs index d419a56ec14..940964ce9af 100644 --- a/src/librustc/middle/trans/cabi.rs +++ b/src/librustc/middle/trans/cabi.rs @@ -17,8 +17,6 @@ use middle::trans::cabi_x86_win64; use middle::trans::cabi_arm; use middle::trans::cabi_mips; use middle::trans::type_::Type; -use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel}; -use syntax::abi::{OsWindows}; #[deriving(Clone, PartialEq)] pub enum ArgKind { @@ -107,16 +105,16 @@ pub fn compute_abi_info(ccx: &CrateContext, atys: &[Type], rty: Type, ret_def: bool) -> FnType { - match ccx.sess().targ_cfg.arch { - X86 => cabi_x86::compute_abi_info(ccx, atys, rty, ret_def), - X86_64 => - if ccx.sess().targ_cfg.os == OsWindows { - cabi_x86_win64::compute_abi_info(ccx, atys, rty, ret_def) - } else { - cabi_x86_64::compute_abi_info(ccx, atys, rty, ret_def) - }, - Arm => cabi_arm::compute_abi_info(ccx, atys, rty, ret_def), - Mips => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def), - Mipsel => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def), + match ccx.sess().target.target.arch.as_slice() { + "x86" => cabi_x86::compute_abi_info(ccx, atys, rty, ret_def), + "x86_64" => if ccx.sess().target.target.options.is_like_windows { + cabi_x86_win64::compute_abi_info(ccx, atys, rty, ret_def) + } else { + cabi_x86_64::compute_abi_info(ccx, atys, rty, ret_def) + }, + "arm" => cabi_arm::compute_abi_info(ccx, atys, rty, ret_def), + "mips" => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def), + a => ccx.sess().fatal((format!("unrecognized arch \"{}\" in target specification", a)) + .as_slice()), } } diff --git a/src/librustc/middle/trans/cabi_x86.rs b/src/librustc/middle/trans/cabi_x86.rs index b5de0ae29d4..6f8651c3e44 100644 --- a/src/librustc/middle/trans/cabi_x86.rs +++ b/src/librustc/middle/trans/cabi_x86.rs @@ -13,7 +13,6 @@ use middle::trans::cabi::{ArgType, FnType}; use middle::trans::type_::Type; use super::common::*; use super::machine::*; -use syntax::abi::{OsWindows, OsMacos, OsiOS}; pub fn compute_abi_info(ccx: &CrateContext, atys: &[Type], @@ -34,19 +33,17 @@ pub fn compute_abi_info(ccx: &CrateContext, // Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp enum Strategy { RetValue(Type), RetPointer } - let strategy = match ccx.sess().targ_cfg.os { - OsWindows | OsMacos | OsiOS => { - match llsize_of_alloc(ccx, rty) { - 1 => RetValue(Type::i8(ccx)), - 2 => RetValue(Type::i16(ccx)), - 4 => RetValue(Type::i32(ccx)), - 8 => RetValue(Type::i64(ccx)), - _ => RetPointer - } - } - _ => { - RetPointer + let t = &ccx.sess().target.target; + let strategy = if t.options.is_like_osx || t.options.is_like_windows { + match llsize_of_alloc(ccx, rty) { + 1 => RetValue(Type::i8(ccx)), + 2 => RetValue(Type::i16(ccx)), + 4 => RetValue(Type::i32(ccx)), + 8 => RetValue(Type::i64(ccx)), + _ => RetPointer } + } else { + RetPointer }; match strategy { diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index 955fcbfab84..7d2460093fe 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -34,7 +34,6 @@ 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; @@ -220,16 +219,16 @@ unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextR let llmod = mod_name.with_c_str(|buf| { llvm::LLVMModuleCreateWithNameInContext(buf, llcx) }); - sess.targ_cfg - .target_strs + sess.target + .target .data_layout .as_slice() .with_c_str(|buf| { llvm::LLVMSetDataLayout(llmod, buf); }); - sess.targ_cfg - .target_strs - .target_triple + sess.target + .target + .llvm_target .as_slice() .with_c_str(|buf| { llvm::LLVMRustSetNormalizedTarget(llmod, buf); @@ -378,8 +377,8 @@ impl LocalCrateContext { let td = mk_target_data(shared.tcx .sess - .targ_cfg - .target_strs + .target + .target .data_layout .as_slice()); @@ -531,16 +530,8 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { } } - // 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) && cfg.os != abi::OsWindows + self.sess().target.target.options.morestack } diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 3d76d1f5d4d..ea7f28796f0 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -211,7 +211,7 @@ use std::ptr; use std::rc::{Rc, Weak}; use syntax::util::interner::Interner; use syntax::codemap::{Span, Pos}; -use syntax::{abi, ast, codemap, ast_util, ast_map}; +use syntax::{ast, codemap, ast_util, ast_map}; use syntax::ast_util::PostExpansionMethod; use syntax::parse::token; use syntax::parse::token::special_idents; @@ -750,8 +750,7 @@ 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 || - cx.sess().targ_cfg.os == abi::OsiOS { + if cx.sess().target.target.options.is_like_osx { "Dwarf Version".with_c_str( |s| llvm::LLVMRustAddModuleFlag(cx.llmod(), s, 2)); } diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index d979024c160..bed45a28691 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -34,7 +34,7 @@ use syntax::parse::token::{InternedString, special_idents}; use syntax::parse::token; use syntax::{ast}; use syntax::{attr, ast_map}; -use util::ppaux::{Repr, UserString}; +use util::ppaux::Repr; /////////////////////////////////////////////////////////////////////////// // Type definitions @@ -70,39 +70,35 @@ struct LlvmSignature { // Calls to external functions pub fn llvm_calling_convention(ccx: &CrateContext, - abi: Abi) -> Option { - let os = ccx.sess().targ_cfg.os; - let arch = ccx.sess().targ_cfg.arch; - abi.for_target(os, arch).map(|abi| { - match abi { - RustIntrinsic => { - // Intrinsics are emitted at the call site - ccx.sess().bug("asked to register intrinsic fn"); - } - - Rust => { - // FIXME(#3678) Implement linking to foreign fns with Rust ABI - ccx.sess().unimpl("foreign functions with Rust ABI"); - } - - RustCall => { - // FIXME(#3678) Implement linking to foreign fns with Rust ABI - ccx.sess().unimpl("foreign functions with RustCall ABI"); - } - - // It's the ABI's job to select this, not us. - System => ccx.sess().bug("system abi should be selected elsewhere"), - - Stdcall => llvm::X86StdcallCallConv, - Fastcall => llvm::X86FastcallCallConv, - C => llvm::CCallConv, - Win64 => llvm::X86_64_Win64, - - // These API constants ought to be more specific... - Cdecl => llvm::CCallConv, - Aapcs => llvm::CCallConv, + abi: Abi) -> CallConv { + match ccx.sess().target.target.adjust_abi(abi) { + RustIntrinsic => { + // Intrinsics are emitted at the call site + ccx.sess().bug("asked to register intrinsic fn"); } - }) + + Rust => { + // FIXME(#3678) Implement linking to foreign fns with Rust ABI + ccx.sess().unimpl("foreign functions with Rust ABI"); + } + + RustCall => { + // FIXME(#3678) Implement linking to foreign fns with Rust ABI + ccx.sess().unimpl("foreign functions with RustCall ABI"); + } + + // It's the ABI's job to select this, not us. + System => ccx.sess().bug("system abi should be selected elsewhere"), + + Stdcall => llvm::X86StdcallCallConv, + Fastcall => llvm::X86FastcallCallConv, + C => llvm::CCallConv, + Win64 => llvm::X86_64_Win64, + + // These API constants ought to be more specific... + Cdecl => llvm::CCallConv, + Aapcs => llvm::CCallConv, + } } pub fn llvm_linkage_by_name(name: &str) -> Option { @@ -191,7 +187,7 @@ pub fn register_static(ccx: &CrateContext, } pub fn register_foreign_item_fn(ccx: &CrateContext, abi: Abi, fty: ty::t, - name: &str, span: Option) -> ValueRef { + name: &str) -> ValueRef { /*! * Registers a foreign function found in a library. * Just adds a LLVM global. @@ -204,25 +200,7 @@ pub fn register_foreign_item_fn(ccx: &CrateContext, abi: Abi, fty: ty::t, fty.repr(ccx.tcx()), name); - let cc = match llvm_calling_convention(ccx, abi) { - Some(cc) => cc, - None => { - match span { - Some(s) => { - ccx.sess().span_fatal(s, - format!("ABI `{}` has no suitable calling convention \ - for target architecture", - abi.user_string(ccx.tcx())).as_slice()) - } - None => { - ccx.sess().fatal( - format!("ABI `{}` has no suitable calling convention \ - for target architecture", - abi.user_string(ccx.tcx())).as_slice()) - } - } - } - }; + let cc = llvm_calling_convention(ccx, abi); // Register the function as a C extern fn let tys = foreign_types_for_fn_ty(ccx, fty); @@ -375,16 +353,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, llargs_foreign.push(llarg_foreign); } - let cc = match llvm_calling_convention(ccx, fn_abi) { - Some(cc) => cc, - None => { - // FIXME(#8357) We really ought to report a span here - ccx.sess().fatal( - format!("ABI string `{}` has no suitable ABI \ - for target architecture", - fn_abi.user_string(ccx.tcx())).as_slice()); - } - }; + let cc = llvm_calling_convention(ccx, fn_abi); // A function pointer is called without the declaration available, so we have to apply // any attributes with ABI implications directly to the call instruction. @@ -498,8 +467,7 @@ pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &ast::ForeignMod) { abi => { let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id); register_foreign_item_fn(ccx, abi, ty, - lname.get().as_slice(), - Some(foreign_item.span)); + lname.get().as_slice()); // Unlike for other items, we shouldn't call // `base::update_linkage` here. Foreign items have // special linkage requirements, which are handled @@ -548,8 +516,7 @@ pub fn decl_rust_fn_with_foreign_abi(ccx: &CrateContext, let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys); let cconv = match ty::get(t).sty { ty::ty_bare_fn(ref fn_ty) => { - let c = llvm_calling_convention(ccx, fn_ty.abi); - c.unwrap_or(llvm::CCallConv) + llvm_calling_convention(ccx, fn_ty.abi) } _ => panic!("expected bare fn in decl_rust_fn_with_foreign_abi") }; @@ -572,8 +539,7 @@ pub fn register_rust_fn_with_foreign_abi(ccx: &CrateContext, let t = ty::node_id_to_type(ccx.tcx(), node_id); let cconv = match ty::get(t).sty { ty::ty_bare_fn(ref fn_ty) => { - let c = llvm_calling_convention(ccx, fn_ty.abi); - c.unwrap_or(llvm::CCallConv) + llvm_calling_convention(ccx, fn_ty.abi) } _ => panic!("expected bare fn in register_rust_fn_with_foreign_abi") }; diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs index 1746f785311..7b8eb4e02b2 100644 --- a/src/librustc/middle/trans/type_.rs +++ b/src/librustc/middle/trans/type_.rs @@ -17,7 +17,6 @@ use llvm::{Float, Double, X86_FP80, PPC_FP128, FP128}; use middle::trans::context::CrateContext; use syntax::ast; -use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel}; use std::c_str::ToCStr; use std::mem; @@ -105,9 +104,10 @@ impl Type { } pub fn int(ccx: &CrateContext) -> Type { - match ccx.tcx().sess.targ_cfg.arch { - X86 | Arm | Mips | Mipsel => Type::i32(ccx), - X86_64 => Type::i64(ccx) + match ccx.tcx().sess.target.target.target_word_size.as_slice() { + "32" => Type::i32(ccx), + "64" => Type::i64(ccx), + tws => panic!("Unsupported target word size for int: {}", tws), } } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 92b5b696e52..0c7de4b3ac4 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -4840,7 +4840,7 @@ pub fn check_enum_variants(ccx: &CrateCtxt, ast::TyU16 => disr as u16 as Disr == disr, ast::TyU32 => disr as u32 as Disr == disr, ast::TyU64 => disr as u64 as Disr == disr, - ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr) + ast::TyU => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr) } } fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool { @@ -4849,7 +4849,7 @@ pub fn check_enum_variants(ccx: &CrateCtxt, ast::TyI16 => disr as i16 as Disr == disr, ast::TyI32 => disr as i32 as Disr == disr, ast::TyI64 => disr as i64 as Disr == disr, - ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr) + ast::TyI => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr) } } match ty { diff --git a/src/librustc_back/archive.rs b/src/librustc_back/archive.rs index 2e58a8dab3b..db2f291e5e7 100644 --- a/src/librustc_back/archive.rs +++ b/src/librustc_back/archive.rs @@ -16,7 +16,6 @@ use std::io::{fs, TempDir}; use std::io; use std::os; use std::str; -use syntax::abi; use syntax::diagnostic::Handler as ErrorHandler; pub static METADATA_FILENAME: &'static str = "rust.metadata.bin"; @@ -25,7 +24,8 @@ pub struct ArchiveConfig<'a> { pub handler: &'a ErrorHandler, pub dst: Path, pub lib_search_paths: Vec, - pub os: abi::Os, + pub slib_prefix: String, + pub slib_suffix: String, pub maybe_ar_prog: Option } @@ -33,7 +33,8 @@ pub struct Archive<'a> { handler: &'a ErrorHandler, dst: Path, lib_search_paths: Vec, - os: abi::Os, + slib_prefix: String, + slib_suffix: String, maybe_ar_prog: Option } @@ -96,14 +97,11 @@ fn run_ar(handler: &ErrorHandler, maybe_ar_prog: &Option, } } -pub fn find_library(name: &str, os: abi::Os, search_paths: &[Path], - handler: &ErrorHandler) -> Path { - let (osprefix, osext) = match os { - abi::OsWindows => ("", "lib"), _ => ("lib", "a"), - }; +pub fn find_library(name: &str, osprefix: &str, ossuffix: &str, + search_paths: &[Path], handler: &ErrorHandler) -> Path { // On Windows, static libraries sometimes show up as libfoo.a and other // times show up as foo.lib - let oslibname = format!("{}{}.{}", osprefix, name, osext); + let oslibname = format!("{}{}{}", osprefix, name, ossuffix); let unixlibname = format!("lib{}.a", name); for path in search_paths.iter() { @@ -122,12 +120,14 @@ pub fn find_library(name: &str, os: abi::Os, search_paths: &[Path], impl<'a> Archive<'a> { fn new(config: ArchiveConfig<'a>) -> Archive<'a> { - let ArchiveConfig { handler, dst, lib_search_paths, os, maybe_ar_prog } = config; + let ArchiveConfig { handler, dst, lib_search_paths, slib_prefix, slib_suffix, + maybe_ar_prog } = config; Archive { handler: handler, dst: dst, lib_search_paths: lib_search_paths, - os: os, + slib_prefix: slib_prefix, + slib_suffix: slib_suffix, maybe_ar_prog: maybe_ar_prog } } @@ -178,7 +178,9 @@ impl<'a> ArchiveBuilder<'a> { /// Adds all of the contents of a native library to this archive. This will /// search in the relevant locations for a library named `name`. pub fn add_native_library(&mut self, name: &str) -> io::IoResult<()> { - let location = find_library(name, self.archive.os, + let location = find_library(name, + self.archive.slib_prefix.as_slice(), + self.archive.slib_suffix.as_slice(), self.archive.lib_search_paths.as_slice(), self.archive.handler); self.add_archive(&location, name, []) diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs index c11eb3ab603..97d94437acd 100644 --- a/src/librustc_back/lib.rs +++ b/src/librustc_back/lib.rs @@ -51,3 +51,4 @@ pub mod svh; pub mod target_strs; pub mod x86; pub mod x86_64; +pub mod target; diff --git a/src/librustc_back/rpath.rs b/src/librustc_back/rpath.rs index 4c62ba54ac4..e7ac1bbcf84 100644 --- a/src/librustc_back/rpath.rs +++ b/src/librustc_back/rpath.rs @@ -12,13 +12,13 @@ use std::collections::HashSet; use std::os; use std::io::IoError; -use syntax::abi; use syntax::ast; pub struct RPathConfig<'a> { - pub os: abi::Os, pub used_crates: Vec<(ast::CrateNum, Option)>, pub out_filename: Path, + pub is_like_osx: bool, + pub has_rpath: bool, pub get_install_prefix_lib_path: ||:'a -> Path, pub realpath: |&Path|:'a -> Result } @@ -26,24 +26,12 @@ pub struct RPathConfig<'a> { pub fn get_rpath_flags(config: RPathConfig) -> Vec { // No rpath on windows - if config.os == abi::OsWindows { + if !config.has_rpath { return Vec::new(); } let mut flags = Vec::new(); - if config.os == abi::OsFreebsd { - flags.push_all(["-Wl,-rpath,/usr/local/lib/gcc46".to_string(), - "-Wl,-rpath,/usr/local/lib/gcc44".to_string(), - "-Wl,-z,origin".to_string()]); - } - else if config.os == abi::OsDragonfly { - flags.push_all(["-Wl,-rpath,/usr/lib/gcc47".to_string(), - "-Wl,-rpath,/usr/lib/gcc44".to_string(), - "-Wl,-z,origin".to_string()]); - } - - debug!("preparing the RPATH!"); let libs = config.used_crates.clone(); @@ -107,14 +95,11 @@ fn get_rpath_relative_to_output(config: &mut RPathConfig, lib: &Path) -> String { use std::os; - assert!(config.os != abi::OsWindows); - // Mac doesn't appear to support $ORIGIN - let prefix = match config.os { - abi::OsAndroid | abi::OsLinux | abi::OsFreebsd | abi::OsDragonfly - => "$ORIGIN", - abi::OsMacos => "@loader_path", - abi::OsWindows | abi::OsiOS => unreachable!() + let prefix = if config.is_like_osx { + "@loader_path" + } else { + "$ORIGIN" }; let mut lib = (config.realpath)(&os::make_absolute(lib)).unwrap(); @@ -203,10 +188,11 @@ mod test { #[cfg(any(target_os = "linux", target_os = "android"))] fn test_rpath_relative() { let config = &mut RPathConfig { - os: abi::OsLinux, used_crates: Vec::new(), out_filename: Path::new("bin/rustc"), get_install_prefix_lib_path: || panic!(), + has_rpath: true, + is_like_osx: false, realpath: |p| Ok(p.clone()) }; let res = get_rpath_relative_to_output(config, &Path::new("lib/libstd.so")); @@ -217,8 +203,9 @@ mod test { #[cfg(target_os = "freebsd")] fn test_rpath_relative() { let config = &mut RPathConfig { - os: abi::OsFreebsd, used_crates: Vec::new(), + has_rpath: true, + is_like_osx: false, out_filename: Path::new("bin/rustc"), get_install_prefix_lib_path: || panic!(), realpath: |p| Ok(p.clone()) @@ -231,8 +218,9 @@ mod test { #[cfg(target_os = "dragonfly")] fn test_rpath_relative() { let config = &mut RPathConfig { - os: abi::OsDragonfly, used_crates: Vec::new(), + has_rpath: true, + is_like_osx: false, out_filename: Path::new("bin/rustc"), get_install_prefix_lib_path: || panic!(), realpath: |p| Ok(p.clone()) @@ -245,8 +233,9 @@ mod test { #[cfg(target_os = "macos")] fn test_rpath_relative() { let config = &mut RPathConfig { - os: abi::OsMacos, used_crates: Vec::new(), + has_rpath: true, + is_like_osx: true, out_filename: Path::new("bin/rustc"), get_install_prefix_lib_path: || panic!(), realpath: |p| Ok(p.clone()) diff --git a/src/librustc_back/target/apple_base.rs b/src/librustc_back/target/apple_base.rs new file mode 100644 index 00000000000..795a2c18bc6 --- /dev/null +++ b/src/librustc_back/target/apple_base.rs @@ -0,0 +1,29 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::TargetOptions; +use std::default::Default; + +pub fn opts() -> TargetOptions { + TargetOptions { + // OSX has -dead_strip, which doesn't rely on ffunction_sections + function_sections: false, + linker: "cc".to_string(), + dynamic_linking: true, + executables: true, + is_like_osx: true, + morestack: true, + has_rpath: true, + dll_prefix: "lib".to_string(), + dll_suffix: ".dylib".to_string(), + pre_link_args: Vec::new(), + .. Default::default() + } +} diff --git a/src/librustc_back/target/arm_apple_ios.rs b/src/librustc_back/target/arm_apple_ios.rs new file mode 100644 index 00000000000..8be98a51775 --- /dev/null +++ b/src/librustc_back/target/arm_apple_ios.rs @@ -0,0 +1,37 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::{Target, TargetOptions}; + +pub fn target() -> Target { + Target { + data_layout: "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(), + llvm_target: "arm-apple-ios".to_string(), + target_endian: "little".to_string(), + target_word_size: "32".to_string(), + arch: "arm".to_string(), + target_os: "ios".to_string(), + options: TargetOptions { + features: "+v7,+thumb2,+vfp3,+neon".to_string(), + executables: false, + dynamic_linking: false, + // 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. + morestack: false, + .. super::apple_base::opts() + } + } +} diff --git a/src/librustc_back/target/arm_linux_androideabi.rs b/src/librustc_back/target/arm_linux_androideabi.rs new file mode 100644 index 00000000000..c7622720731 --- /dev/null +++ b/src/librustc_back/target/arm_linux_androideabi.rs @@ -0,0 +1,33 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::Target; + +pub fn target() -> Target { + let mut base = super::linux_base::opts(); + base.features = "+v7".to_string(); + // Many of the symbols defined in compiler-rt are also defined in libgcc. Android + // linker doesn't like that by default. + base.pre_link_args.push("-Wl,--allow-multiple-definition".to_string()); + + Target { + data_layout: "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(), + llvm_target: "arm-linux-androideabi".to_string(), + target_endian: "little".to_string(), + target_word_size: "32".to_string(), + arch: "arm".to_string(), + target_os: "android".to_string(), + options: base, + } +} diff --git a/src/librustc_back/target/arm_unknown_linux_gnueabi.rs b/src/librustc_back/target/arm_unknown_linux_gnueabi.rs new file mode 100644 index 00000000000..aecab188264 --- /dev/null +++ b/src/librustc_back/target/arm_unknown_linux_gnueabi.rs @@ -0,0 +1,32 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::{Target, TargetOptions}; + +pub fn target() -> Target { + let base = super::linux_base::opts(); + Target { + data_layout: "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(), + llvm_target: "arm-unknown-linux-gnueabi".to_string(), + target_endian: "little".to_string(), + target_word_size: "32".to_string(), + arch: "arm".to_string(), + target_os: "linux".to_string(), + + options: TargetOptions { + features: "+v6".to_string(), + .. base + }, + } +} diff --git a/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs b/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs new file mode 100644 index 00000000000..32d183d6254 --- /dev/null +++ b/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs @@ -0,0 +1,32 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::{Target, TargetOptions}; + +pub fn target() -> Target { + let base = super::linux_base::opts(); + Target { + data_layout: "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(), + llvm_target: "arm-unknown-linux-gnueabi".to_string(), + target_endian: "little".to_string(), + target_word_size: "32".to_string(), + arch: "arm".to_string(), + target_os: "linux".to_string(), + + options: TargetOptions { + features: "+v6,+vfp2".to_string(), + .. base + } + } +} diff --git a/src/librustc_back/target/dragonfly_base.rs b/src/librustc_back/target/dragonfly_base.rs new file mode 100644 index 00000000000..4e982b2b76e --- /dev/null +++ b/src/librustc_back/target/dragonfly_base.rs @@ -0,0 +1,30 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::TargetOptions; +use std::default::Default; + +pub fn opts() -> TargetOptions { + TargetOptions { + linker: "cc".to_string(), + dynamic_linking: true, + executables: true, + morestack: true, + has_rpath: true, + pre_link_args: vec!( + "-L/usr/local/lib".to_string(), + "-L/usr/local/lib/gcc47".to_string(), + "-L/usr/local/lib/gcc44".to_string(), + ), + + .. Default::default() + } +} + diff --git a/src/librustc_back/target/freebsd_base.rs b/src/librustc_back/target/freebsd_base.rs new file mode 100644 index 00000000000..ab8398fc605 --- /dev/null +++ b/src/librustc_back/target/freebsd_base.rs @@ -0,0 +1,30 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::TargetOptions; +use std::default::Default; + +pub fn opts() -> TargetOptions { + TargetOptions { + linker: "cc".to_string(), + dynamic_linking: true, + executables: true, + morestack: true, + has_rpath: true, + pre_link_args: vec!( + "-L/usr/local/lib".to_string(), + "-L/usr/local/lib/gcc46".to_string(), + "-L/usr/local/lib/gcc44".to_string(), + ), + + .. Default::default() + } +} + diff --git a/src/librustc_back/target/i386_apple_ios.rs b/src/librustc_back/target/i386_apple_ios.rs new file mode 100644 index 00000000000..fe336601a81 --- /dev/null +++ b/src/librustc_back/target/i386_apple_ios.rs @@ -0,0 +1,28 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::Target; + +pub fn target() -> Target { + Target { + data_layout: "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(), + llvm_target: "i386-apple-ios".to_string(), + target_endian: "little".to_string(), + target_word_size: "32".to_string(), + arch: "x86".to_string(), + target_os: "ios".to_string(), + + options: super::apple_base::opts() + } +} diff --git a/src/librustc_back/target/i686_apple_darwin.rs b/src/librustc_back/target/i686_apple_darwin.rs new file mode 100644 index 00000000000..eb1dbd2da63 --- /dev/null +++ b/src/librustc_back/target/i686_apple_darwin.rs @@ -0,0 +1,28 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::Target; + +pub fn target() -> Target { + Target { + data_layout: "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(), + llvm_target: "i686-apple-darwin".to_string(), + target_endian: "little".to_string(), + target_word_size: "32".to_string(), + arch: "x86".to_string(), + target_os: "macos".to_string(), + + options: super::apple_base::opts() + } +} diff --git a/src/librustc_back/target/i686_pc_windows_gnu.rs b/src/librustc_back/target/i686_pc_windows_gnu.rs new file mode 100644 index 00000000000..4d75590e664 --- /dev/null +++ b/src/librustc_back/target/i686_pc_windows_gnu.rs @@ -0,0 +1,34 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::Target; + +pub fn target() -> Target { + let mut options = super::windows_base::opts(); + + // Mark all dynamic libraries and executables as compatible with the larger 4GiB address + // space available to x86 Windows binaries on x86_64. + options.pre_link_args.push("-Wl,--large-address-aware".to_string()); + + // Make sure that we link to the dynamic libgcc, otherwise cross-module + // DWARF stack unwinding will not work. + // This behavior may be overridden by -Clink-args="-static-libgcc" + options.pre_link_args.push("-shared-libgcc".to_string()); + + Target { + data_layout: "e-p:32:32-f64:64:64-i64:64:64-f80:32:32-n8:16:32".to_string(), + llvm_target: "i686-pc-windows-gnu".to_string(), + target_endian: "little".to_string(), + target_word_size: "32".to_string(), + arch: "x86".to_string(), + target_os: "windows".to_string(), + options: options, + } +} diff --git a/src/librustc_back/target/i686_unknown_dragonfly.rs b/src/librustc_back/target/i686_unknown_dragonfly.rs new file mode 100644 index 00000000000..5229c443001 --- /dev/null +++ b/src/librustc_back/target/i686_unknown_dragonfly.rs @@ -0,0 +1,23 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::Target; + +pub fn target() -> Target { + Target { + data_layout: "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string(), + llvm_target: "i686-unknown-dragonfly".to_string(), + target_endian: "little".to_string(), + target_word_size: "32".to_string(), + arch: "x86".to_string(), + target_os: "dragonfly".to_string(), + options: super::dragonfly_base::opts() + } +} diff --git a/src/librustc_back/target/i686_unknown_linux_gnu.rs b/src/librustc_back/target/i686_unknown_linux_gnu.rs new file mode 100644 index 00000000000..a7ee1b71bd8 --- /dev/null +++ b/src/librustc_back/target/i686_unknown_linux_gnu.rs @@ -0,0 +1,23 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::Target; + +pub fn target() -> Target { + Target { + data_layout: "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string(), + llvm_target: "i686-unknown-linux-gnu".to_string(), + target_endian: "little".to_string(), + target_word_size: "32".to_string(), + arch: "x86".to_string(), + target_os: "linux".to_string(), + options: super::linux_base::opts() + } +} diff --git a/src/librustc_back/target/linux_base.rs b/src/librustc_back/target/linux_base.rs new file mode 100644 index 00000000000..51b817a6175 --- /dev/null +++ b/src/librustc_back/target/linux_base.rs @@ -0,0 +1,31 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::TargetOptions; +use std::default::Default; + +pub fn opts() -> TargetOptions { + TargetOptions { + linker: "cc".to_string(), + dynamic_linking: true, + executables: true, + morestack: true, + linker_is_gnu: true, + has_rpath: true, + pre_link_args: vec!( + // GNU-style linkers will use this to omit linking to libraries which + // don't actually fulfill any relocations, but only for libraries which + // follow this flag. Thus, use it before specifying libraries to link to. + "-Wl,--as-needed".to_string(), + ), + position_independant_executables: true, + .. Default::default() + } +} diff --git a/src/librustc_back/target/mips_unknown_linux_gnu.rs b/src/librustc_back/target/mips_unknown_linux_gnu.rs new file mode 100644 index 00000000000..45e02ecb98c --- /dev/null +++ b/src/librustc_back/target/mips_unknown_linux_gnu.rs @@ -0,0 +1,27 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::Target; + +pub fn target() -> Target { + Target { + data_layout: "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(), + llvm_target: "mips-unknown-linux-gnu".to_string(), + target_endian: "big".to_string(), + target_word_size: "32".to_string(), + arch: "mips".to_string(), + target_os: "linux".to_string(), + options: super::linux_base::opts() + } +} diff --git a/src/librustc_back/target/mipsel_unknown_linux_gnu.rs b/src/librustc_back/target/mipsel_unknown_linux_gnu.rs new file mode 100644 index 00000000000..1ba99b167c3 --- /dev/null +++ b/src/librustc_back/target/mipsel_unknown_linux_gnu.rs @@ -0,0 +1,28 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::Target; + +pub fn target() -> Target { + Target { + data_layout: "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(), + llvm_target: "mipsel-unknown-linux-gnu".to_string(), + target_endian: "little".to_string(), + target_word_size: "32".to_string(), + arch: "mips".to_string(), + target_os: "linux".to_string(), + + options: super::linux_base::opts() + } +} diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs new file mode 100644 index 00000000000..7013a890e79 --- /dev/null +++ b/src/librustc_back/target/mod.rs @@ -0,0 +1,379 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! [Flexible target specification.](https://github.com/rust-lang/rfcs/pull/131) +//! +//! Rust targets a wide variety of usecases, and in the interest of flexibility, +//! allows new target triples to be defined in configuration files. Most users +//! will not need to care about these, but this is invaluable when porting Rust +//! to a new platform, and allows for an unprecedented level of control over how +//! the compiler works. +//! +//! # Using custom targets +//! +//! A target triple, as passed via `rustc --target=TRIPLE`, will first be +//! compared against the list of built-in targets. This is to ease distributing +//! rustc (no need for configuration files) and also to hold these built-in +//! targets as immutable and sacred. If `TRIPLE` is not one of the built-in +//! targets, rustc will check if a file named `TRIPLE` exists. If it does, it +//! will be loaded as the target configuration. If the file does not exist, +//! rustc will search each directory in the environment variable +//! `RUST_TARGET_PATH` for a file named `TRIPLE.json`. The first one found will +//! be loaded. If no file is found in any of those directories, a fatal error +//! will be given. `RUST_TARGET_PATH` includes `/etc/rustc` as its last entry, +//! to be searched by default. +//! +//! Projects defining their own targets should use +//! `--target=path/to/my-awesome-platform.json` instead of adding to +//! `RUST_TARGET_PATH`. +//! +//! # Defining a new target +//! +//! Targets are defined using [JSON](http://json.org/). The `Target` struct in +//! this module defines the format the JSON file should take, though each +//! underscore in the field names should be replaced with a hyphen (`-`) in the +//! JSON file. Some fields are required in every target specification, such as +//! `data-layout`, `llvm-target`, `target-endian`, `target-word-size`, and +//! `arch`. In general, options passed to rustc with `-C` override the target's +//! settings, though `target-feature` and `link-args` will *add* to the list +//! specified by the target, rather than replace. + +use serialize::json::Json; +use syntax::{diagnostic, abi}; +use std::default::Default; +use std::io::fs::PathExtensions; + +mod windows_base; +mod linux_base; +mod apple_base; +mod freebsd_base; +mod dragonfly_base; + +mod arm_apple_ios; +mod arm_linux_androideabi; +mod arm_unknown_linux_gnueabi; +mod arm_unknown_linux_gnueabihf; +mod i686_apple_darwin; +mod i386_apple_ios; +mod i686_pc_windows_gnu; +mod i686_unknown_linux_gnu; +mod mips_unknown_linux_gnu; +mod mipsel_unknown_linux_gnu; +mod x86_64_apple_darwin; +mod x86_64_pc_windows_gnu; +mod x86_64_unknown_freebsd; +mod x86_64_unknown_dragonfly; +mod x86_64_unknown_linux_gnu; + +/// Everything `rustc` knows about how to compile for a specific target. +/// +/// Every field here must be specified, and has no default value. +#[deriving(Clone, Show)] +pub struct Target { + /// [Data layout](http://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM. + pub data_layout: String, + /// Target triple to pass to LLVM. + pub llvm_target: String, + /// String to use as the `target_endian` `cfg` variable. + pub target_endian: String, + /// String to use as the `target_word_size` `cfg` variable. + pub target_word_size: String, + /// OS name to use for conditional compilation. + pub target_os: String, + /// Architecture to use for ABI considerations. Valid options: "x86", "x86_64", "arm", and + /// "mips". "mips" includes "mipsel". + pub arch: String, + /// Optional settings with defaults. + pub options: TargetOptions, +} + +/// Optional aspects of a target specification. +/// +/// This has an implementation of `Default`, see each field for what the default is. In general, +/// these try to take "minimal defaults" that don't assume anything about the runtime they run in. +#[deriving(Clone, Show)] +pub struct TargetOptions { + /// Linker to invoke. Defaults to "cc". + pub linker: String, + /// Linker arguments that are unconditionally passed *before* any user-defined libraries. + pub pre_link_args: Vec, + /// Linker arguments that are unconditionally passed *after* any user-defined libraries. + pub post_link_args: Vec, + /// Default CPU to pass to LLVM. Corresponds to `llc -mcpu=$cpu`. Defaults to "default". + pub cpu: String, + /// Default target features to pass to LLVM. These features will *always* be passed, and cannot + /// be disabled even via `-C`. Corresponds to `llc -mattr=$features`. + pub features: String, + /// Whether dynamic linking is available on this target. Defaults to false. + pub dynamic_linking: bool, + /// Whether executables are available on this target. iOS, for example, only allows static + /// libraries. Defaults to false. + pub executables: bool, + /// Whether LLVM's segmented stack prelude is supported by whatever runtime is available. + /// Will emit stack checks and calls to __morestack. Defaults to false. + pub morestack: bool, + /// Relocation model to use in object file. Corresponds to `llc + /// -relocation-model=$relocation_model`. Defaults to "pic". + pub relocation_model: String, + /// Code model to use. Corresponds to `llc -code-model=$code_model`. Defaults to "default". + pub code_model: String, + /// Do not emit code that uses the "red zone", if the ABI has one. Defaults to false. + pub disable_redzone: bool, + /// Eliminate frame pointers from stack frames if possible. Defaults to true. + pub eliminate_frame_pointer: bool, + /// Emit each function in its own section. Defaults to true. + pub function_sections: bool, + /// String to prepend to the name of every dynamic library. Defaults to "lib". + pub dll_prefix: String, + /// String to append to the name of every dynamic library. Defaults to ".so". + pub dll_suffix: String, + /// String to append to the name of every executable. + pub exe_suffix: String, + /// String to prepend to the name of every static library. Defaults to "lib". + pub staticlib_prefix: String, + /// String to append to the name of every static library. Defaults to ".a". + pub staticlib_suffix: String, + /// Whether the target toolchain is like OSX's. Only useful for compiling against iOS/OS X, in + /// particular running dsymutil and some other stuff like `-dead_strip`. Defaults to false. + pub is_like_osx: bool, + /// Whether the target toolchain is like Windows'. Only useful for compiling against Windows, + /// only realy used for figuring out how to find libraries, since Windows uses its own + /// library naming convention. Defaults to false. + pub is_like_windows: bool, + /// Whether the linker support GNU-like arguments such as -O. Defaults to false. + pub linker_is_gnu: bool, + /// Whether the linker support rpaths or not. Defaults to false. + pub has_rpath: bool, + /// Whether to disable linking to compiler-rt. Defaults to false, as LLVM will emit references + /// to the functions that compiler-rt provides. + pub no_compiler_rt: bool, + /// Dynamically linked executables can be compiled as position independent if the default + /// relocation model of position independent code is not changed. This is a requirement to take + /// advantage of ASLR, as otherwise the functions in the executable are not randomized and can + /// be used during an exploit of a vulnerability in any code. + pub position_independant_executables: bool, +} + +impl Default for TargetOptions { + /// Create a set of "sane defaults" for any target. This is still incomplete, and if used for + /// compilation, will certainly not work. + fn default() -> TargetOptions { + TargetOptions { + linker: "cc".to_string(), + pre_link_args: Vec::new(), + post_link_args: Vec::new(), + cpu: "generic".to_string(), + features: "".to_string(), + dynamic_linking: false, + executables: false, + morestack: false, + relocation_model: "pic".to_string(), + code_model: "default".to_string(), + disable_redzone: false, + eliminate_frame_pointer: true, + function_sections: true, + dll_prefix: "lib".to_string(), + dll_suffix: ".so".to_string(), + exe_suffix: "".to_string(), + staticlib_prefix: "lib".to_string(), + staticlib_suffix: ".a".to_string(), + is_like_osx: false, + is_like_windows: false, + linker_is_gnu: false, + has_rpath: false, + no_compiler_rt: false, + position_independant_executables: false, + } + } +} + +impl Target { + /// Given a function ABI, turn "System" into the correct ABI for this target. + pub fn adjust_abi(&self, abi: abi::Abi) -> abi::Abi { + match abi { + abi::System => { + if self.options.is_like_windows && self.arch.as_slice() == "x86" { + abi::Stdcall + } else { + abi::C + } + }, + abi => abi + } + } + + /// Load a target descriptor from a JSON object. + pub fn from_json(obj: Json) -> Target { + // this is 1. ugly, 2. error prone. + + + let handler = diagnostic::default_handler(diagnostic::Auto, None); + + let get_req_field = |name: &str| { + match obj.find(&name.to_string()) + .map(|s| s.as_string()) + .and_then(|os| os.map(|s| s.to_string())) { + Some(val) => val, + None => + handler.fatal((format!("Field {} in target specification is required", name)) + .as_slice()) + } + }; + + let mut base = Target { + data_layout: get_req_field("data-layout"), + llvm_target: get_req_field("llvm-target"), + target_endian: get_req_field("target-endian"), + target_word_size: get_req_field("target-word-size"), + arch: get_req_field("arch"), + target_os: get_req_field("os"), + options: Default::default(), + }; + + macro_rules! key ( + ($key_name:ident) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.find(&name).map(|o| o.as_string() + .map(|s| base.options.$key_name = s.to_string())); + } ); + ($key_name:ident, bool) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.find(&name).map(|o| o.as_boolean().map(|s| base.options.$key_name = s)); + } ); + ($key_name:ident, list) => ( { + let name = (stringify!($key_name)).replace("_", "-"); + obj.find(&name).map(|o| o.as_list() + .map(|v| base.options.$key_name = v.iter() + .map(|a| a.as_string().unwrap().to_string()).collect() + ) + ); + } ); + ) + + key!(cpu); + key!(linker); + key!(relocation_model); + key!(code_model); + key!(dll_prefix); + key!(dll_suffix); + key!(exe_suffix); + key!(staticlib_prefix); + key!(staticlib_suffix); + key!(features); + key!(dynamic_linking, bool); + key!(executables, bool); + key!(morestack, bool); + key!(disable_redzone, bool); + key!(eliminate_frame_pointer, bool); + key!(function_sections, bool); + key!(is_like_osx, bool); + key!(is_like_windows, bool); + key!(linker_is_gnu, bool); + key!(has_rpath, bool); + key!(no_compiler_rt, bool); + key!(pre_link_args, list); + key!(post_link_args, list); + + base + } + + /// Search RUST_TARGET_PATH for a JSON file specifying the given target triple. Note that it + /// could also just be a bare filename already, so also check for that. If one of the hardcoded + /// targets we know about, just return it directly. + /// + /// The error string could come from any of the APIs called, including filesystem access and + /// JSON decoding. + pub fn search(target: &str) -> Result { + use std::os; + use std::io::File; + use std::path::Path; + use serialize::json; + + fn load_file(path: &Path) -> Result { + let mut f = try!(File::open(path).map_err(|e| e.to_string())); + let obj = try!(json::from_reader(&mut f).map_err(|e| e.to_string())); + Ok(Target::from_json(obj)) + } + + // this would use a match if stringify! were allowed in pattern position + macro_rules! load_specific ( + ( $($name:ident),+ ) => ( + { + let target = target.replace("-", "_"); + let target = target.as_slice(); + if false { } + $( + else if target == stringify!($name) { + let t = $name::target(); + debug!("Got builtin target: {}", t); + return Ok(t); + } + )* + else if target == "x86_64-w64-mingw32" { + let t = x86_64_pc_windows_gnu::target(); + return Ok(t); + } else if target == "i686-w64-mingw32" { + let t = i686_pc_windows_gnu::target(); + return Ok(t); + } + } + ) + ) + + load_specific!( + x86_64_unknown_linux_gnu, + i686_unknown_linux_gnu, + mips_unknown_linux_gnu, + mipsel_unknown_linux_gnu, + arm_linux_androideabi, + arm_unknown_linux_gnueabi, + arm_unknown_linux_gnueabihf, + + x86_64_unknown_freebsd, + + x86_64_unknown_dragonfly, + + x86_64_apple_darwin, + i686_apple_darwin, + i386_apple_ios, + arm_apple_ios, + + x86_64_pc_windows_gnu, + i686_pc_windows_gnu + ) + + + let path = Path::new(target); + + if path.is_file() { + return load_file(&path); + } + + let path = { + let mut target = target.to_string(); + target.push_str(".json"); + Path::new(target) + }; + + let target_path = os::getenv("RUST_TARGET_PATH").unwrap_or(String::new()); + + let paths = os::split_paths(target_path.as_slice()); + // FIXME 16351: add a sane default search path? + + for dir in paths.iter() { + let p = dir.join(path.clone()); + if p.is_file() { + return load_file(&p); + } + } + + Err(format!("Could not find specification for target {}", target)) + } +} diff --git a/src/librustc_back/target/windows_base.rs b/src/librustc_back/target/windows_base.rs new file mode 100644 index 00000000000..148be8cab76 --- /dev/null +++ b/src/librustc_back/target/windows_base.rs @@ -0,0 +1,66 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::TargetOptions; +use std::default::Default; + +pub fn opts() -> TargetOptions { + TargetOptions { + // FIXME(#13846) this should be enabled for windows + function_sections: false, + linker: "gcc".to_string(), + dynamic_linking: true, + executables: true, + dll_prefix: "".to_string(), + dll_suffix: ".dll".to_string(), + exe_suffix: ".exe".to_string(), + staticlib_prefix: "".to_string(), + staticlib_suffix: ".lib".to_string(), + morestack: false, + is_like_windows: true, + pre_link_args: vec!( + // And here, we see obscure linker flags #45. On windows, it has been + // found to be necessary to have this flag to compile liblibc. + // + // First a bit of background. On Windows, the file format is not ELF, + // but COFF (at least according to LLVM). COFF doesn't officially allow + // for section names over 8 characters, apparently. Our metadata + // section, ".note.rustc", you'll note is over 8 characters. + // + // On more recent versions of gcc on mingw, apparently the section name + // is *not* truncated, but rather stored elsewhere in a separate lookup + // table. On older versions of gcc, they apparently always truncated th + // section names (at least in some cases). Truncating the section name + // actually creates "invalid" objects [1] [2], but only for some + // introspection tools, not in terms of whether it can be loaded. + // + // Long story short, passing this flag forces the linker to *not* + // truncate section names (so we can find the metadata section after + // it's compiled). The real kicker is that rust compiled just fine on + // windows for quite a long time *without* this flag, so I have no idea + // why it suddenly started failing for liblibc. Regardless, we + // definitely don't want section name truncation, so we're keeping this + // flag for windows. + // + // [1] - https://sourceware.org/bugzilla/show_bug.cgi?id=13130 + // [2] - https://code.google.com/p/go/issues/detail?id=2139 + "-Wl,--enable-long-section-names".to_string(), + + // Tell GCC to avoid linker plugins, because we are not bundling + // them with Windows installer, and Rust does its own LTO anyways. + "-fno-use-linker-plugin".to_string(), + + // Always enable DEP (NX bit) when it is available + "-Wl,--nxcompat".to_string(), + ), + + .. Default::default() + } +} diff --git a/src/librustc_back/target/x86_64_apple_darwin.rs b/src/librustc_back/target/x86_64_apple_darwin.rs new file mode 100644 index 00000000000..4e958d73a39 --- /dev/null +++ b/src/librustc_back/target/x86_64_apple_darwin.rs @@ -0,0 +1,29 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::Target; + +pub fn target() -> Target { + let mut base = super::apple_base::opts(); + base.eliminate_frame_pointer = false; + base.pre_link_args.push("-m64".to_string()); + + Target { + data_layout: "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(), + llvm_target: "x86_64-apple-darwin".to_string(), + target_endian: "little".to_string(), + target_word_size: "64".to_string(), + arch: "x86_64".to_string(), + target_os: "macos".to_string(), + options: base, + } +} diff --git a/src/librustc_back/target/x86_64_pc_windows_gnu.rs b/src/librustc_back/target/x86_64_pc_windows_gnu.rs new file mode 100644 index 00000000000..9247e1da0a5 --- /dev/null +++ b/src/librustc_back/target/x86_64_pc_windows_gnu.rs @@ -0,0 +1,31 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::Target; + +pub fn target() -> Target { + let mut base = super::windows_base::opts(); + // On Win64 unwinding is handled by the OS, so we can link libgcc statically. + base.pre_link_args.push("-static-libgcc".to_string()); + base.pre_link_args.push("-m64".to_string()); + + Target { + // FIXME: Test this. Copied from linux (#2398) + data_layout: "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-S128".to_string(), + llvm_target: "x86_64-pc-windows-gnu".to_string(), + target_endian: "little".to_string(), + target_word_size: "64".to_string(), + arch: "x86_64".to_string(), + target_os: "windows".to_string(), + options: base, + } +} diff --git a/src/librustc_back/target/x86_64_unknown_dragonfly.rs b/src/librustc_back/target/x86_64_unknown_dragonfly.rs new file mode 100644 index 00000000000..79f09a3b00b --- /dev/null +++ b/src/librustc_back/target/x86_64_unknown_dragonfly.rs @@ -0,0 +1,23 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::Target; + +pub fn target() -> Target { + Target { + data_layout: "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string(), + llvm_target: "x86_64-unknown-dragonfly".to_string(), + target_endian: "little".to_string(), + target_word_size: "32".to_string(), + arch: "x86_64".to_string(), + target_os: "dragonfly".to_string(), + options: super::dragonfly_base::opts() + } +} diff --git a/src/librustc_back/target/x86_64_unknown_freebsd.rs b/src/librustc_back/target/x86_64_unknown_freebsd.rs new file mode 100644 index 00000000000..37801f3bf25 --- /dev/null +++ b/src/librustc_back/target/x86_64_unknown_freebsd.rs @@ -0,0 +1,28 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::Target; + +pub fn target() -> Target { + let mut base = super::freebsd_base::opts(); + base.pre_link_args.push("-m64".to_string()); + + Target { + data_layout: "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-S128".to_string(), + llvm_target: "x86_64-unknown-freebsd".to_string(), + target_endian: "little".to_string(), + target_word_size: "64".to_string(), + arch: "x86_64".to_string(), + target_os: "freebsd".to_string(), + options: base, + } +} diff --git a/src/librustc_back/target/x86_64_unknown_linux_gnu.rs b/src/librustc_back/target/x86_64_unknown_linux_gnu.rs new file mode 100644 index 00000000000..ac04e6e14ba --- /dev/null +++ b/src/librustc_back/target/x86_64_unknown_linux_gnu.rs @@ -0,0 +1,28 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::Target; + +pub fn target() -> Target { + let mut base = super::linux_base::opts(); + base.pre_link_args.push("-m64".to_string()); + + Target { + data_layout: "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-S128".to_string(), + llvm_target: "x86_64-unknown-linux-gnu".to_string(), + target_endian: "little".to_string(), + target_word_size: "64".to_string(), + arch: "x86_64".to_string(), + target_os: "linux".to_string(), + options: base, + } +} diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 3e8ebc00579..93662b3b63e 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -183,7 +183,7 @@ fn runtest(test: &str, cratename: &str, libs: Vec, externs: core::Externs, // environment to ensure that the target loads the right libraries at // runtime. It would be a sad day if the *host* libraries were loaded as a // mistake. - let mut cmd = Command::new(outdir.path().join("rust_out")); + let mut cmd = Command::new(outdir.path().join("rust-out")); let newpath = { let mut path = DynamicLibrary::search_path(); path.insert(0, libdir.clone()); diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index dc41f3d9279..912755d0ea0 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -37,9 +37,6 @@ pub enum Abi { #[allow(non_camel_case_types)] #[deriving(PartialEq)] pub enum Architecture { - // NB. You cannot change the ordering of these - // constants without adjusting IntelBits below. - // (This is ensured by the test indices_are_correct().) X86, X86_64, Arm, @@ -47,20 +44,11 @@ pub enum Architecture { Mipsel } -#[allow(non_upper_case_globals)] -const IntelBits: u32 = (1 << (X86 as uint)) | (1 << (X86_64 as uint)); -#[allow(non_upper_case_globals)] -const ArmBits: u32 = (1 << (Arm as uint)); - pub struct AbiData { abi: Abi, // Name of this ABI as we like it called. name: &'static str, - - // Is it specific to a platform? If so, which one? Also, what is - // the name that LLVM gives it (in case we disagree) - abi_arch: AbiArchitecture } pub enum AbiArchitecture { @@ -75,22 +63,21 @@ pub enum AbiArchitecture { #[allow(non_upper_case_globals)] static AbiDatas: &'static [AbiData] = &[ // Platform-specific ABIs - AbiData {abi: Cdecl, name: "cdecl", abi_arch: Archs(IntelBits)}, - AbiData {abi: Stdcall, name: "stdcall", abi_arch: Archs(IntelBits)}, - AbiData {abi: Fastcall, name:"fastcall", abi_arch: Archs(IntelBits)}, - AbiData {abi: Aapcs, name: "aapcs", abi_arch: Archs(ArmBits)}, - AbiData {abi: Win64, name: "win64", - abi_arch: Archs(1 << (X86_64 as uint))}, + AbiData {abi: Cdecl, name: "cdecl" }, + AbiData {abi: Stdcall, name: "stdcall" }, + AbiData {abi: Fastcall, name:"fastcall" }, + AbiData {abi: Aapcs, name: "aapcs" }, + AbiData {abi: Win64, name: "win64" }, // Cross-platform ABIs // // NB: Do not adjust this ordering without // adjusting the indices below. - AbiData {abi: Rust, name: "Rust", abi_arch: RustArch}, - AbiData {abi: C, name: "C", abi_arch: AllArch}, - AbiData {abi: System, name: "system", abi_arch: AllArch}, - AbiData {abi: RustIntrinsic, name: "rust-intrinsic", abi_arch: RustArch}, - AbiData {abi: RustCall, name: "rust-call", abi_arch: RustArch}, + AbiData {abi: Rust, name: "Rust" }, + AbiData {abi: C, name: "C" }, + AbiData {abi: System, name: "system" }, + AbiData {abi: RustIntrinsic, name: "rust-intrinsic" }, + AbiData {abi: RustCall, name: "rust-call" }, ]; /// Returns the ABI with the given name (if any). @@ -116,28 +103,6 @@ impl Abi { pub fn name(&self) -> &'static str { self.data().name } - - pub fn for_target(&self, os: Os, arch: Architecture) -> Option { - // If this ABI isn't actually for the specified architecture, then we - // short circuit early - match self.data().abi_arch { - Archs(a) if a & arch.bit() == 0 => return None, - Archs(_) | RustArch | AllArch => {} - } - // Transform this ABI as appropriate for the requested os/arch - // combination. - Some(match (*self, os, arch) { - (System, OsWindows, X86) => Stdcall, - (System, _, _) => C, - (me, _, _) => me, - }) - } -} - -impl Architecture { - fn bit(&self) -> u32 { - 1 << (*self as uint) - } } impl fmt::Show for Abi { @@ -184,23 +149,4 @@ fn indices_are_correct() { for (i, abi_data) in AbiDatas.iter().enumerate() { assert_eq!(i, abi_data.abi.index()); } - - let bits = 1 << (X86 as uint); - let bits = bits | 1 << (X86_64 as uint); - assert_eq!(IntelBits, bits); - - let bits = 1 << (Arm as uint); - assert_eq!(ArmBits, bits); -} - -#[test] -fn pick_uniplatform() { - assert_eq!(Stdcall.for_target(OsLinux, X86), Some(Stdcall)); - assert_eq!(Stdcall.for_target(OsLinux, Arm), None); - assert_eq!(System.for_target(OsLinux, X86), Some(C)); - assert_eq!(System.for_target(OsWindows, X86), Some(Stdcall)); - assert_eq!(System.for_target(OsWindows, X86_64), Some(C)); - assert_eq!(System.for_target(OsWindows, Arm), Some(C)); - assert_eq!(Stdcall.for_target(OsWindows, X86), Some(Stdcall)); - assert_eq!(Stdcall.for_target(OsWindows, X86_64), Some(Stdcall)); } diff --git a/src/test/run-make/rustdoc-hidden-line/Makefile b/src/test/run-make/rustdoc-hidden-line/Makefile index b08c6625f17..bc7e4e5863e 100644 --- a/src/test/run-make/rustdoc-hidden-line/Makefile +++ b/src/test/run-make/rustdoc-hidden-line/Makefile @@ -4,6 +4,7 @@ ifndef IS_WINDOWS all: + @echo $(RUSTDOC) $(HOST_RPATH_ENV) $(RUSTDOC) --test foo.rs $(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc foo.rs cp verify.sh $(TMPDIR) diff --git a/src/test/run-make/target-specs/Makefile b/src/test/run-make/target-specs/Makefile new file mode 100644 index 00000000000..746870d201f --- /dev/null +++ b/src/test/run-make/target-specs/Makefile @@ -0,0 +1,11 @@ +-include ../tools.mk +all: + $(RUSTC) foo.rs --target=my-awesome-platform.json --crate-type=lib --emit=asm + grep --quiet --invert-match morestack < $(TMPDIR)/foo.s + $(RUSTC) foo.rs --target=my-invalid-platform.json 2>&1 | grep --quiet --invert-match "Error loading taget specification" + $(RUSTC) foo.rs --target=my-incomplete-platform.json 2>&1 | grep 'Field llvm-target' + RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=my-awesome-platform --crate-type=lib --emit=asm + RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=x86_64-unknown-linux-gnu --crate-type=lib --emit=asm + # The built-in target *should* override the one we have here, and thus we + # should have morestack + grep --quiet morestack < $(TMPDIR)/foo.s diff --git a/src/test/run-make/target-specs/foo.rs b/src/test/run-make/target-specs/foo.rs new file mode 100644 index 00000000000..eeddd5e19a8 --- /dev/null +++ b/src/test/run-make/target-specs/foo.rs @@ -0,0 +1,26 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(lang_items)] +#![no_std] + +#[lang="sized"] +trait Sized { } + +#[lang="start"] +fn start(_main: *const u8, _argc: int, _argv: *const *const u8) -> int { 0 } + +extern { + fn _foo() -> [u8, ..16]; +} + +fn _main() { + let _a = unsafe { _foo() }; +} diff --git a/src/test/run-make/target-specs/my-awesome-platform.json b/src/test/run-make/target-specs/my-awesome-platform.json new file mode 100644 index 00000000000..f5f622bbcda --- /dev/null +++ b/src/test/run-make/target-specs/my-awesome-platform.json @@ -0,0 +1,9 @@ +{ + "data-layout": "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32", + "llvm-target": "i686-unknown-linux-gnu", + "target-endian": "little", + "target-word-size": "32", + "arch": "x86", + "os": "linux", + "morestack": false +} diff --git a/src/test/run-make/target-specs/my-incomplete-platform.json b/src/test/run-make/target-specs/my-incomplete-platform.json new file mode 100644 index 00000000000..5005a9ff839 --- /dev/null +++ b/src/test/run-make/target-specs/my-incomplete-platform.json @@ -0,0 +1,8 @@ +{ + "data-layout": "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32", + "target-endian": "little", + "target-word-size": "32", + "arch": "x86", + "os": "foo", + "morestack": false +} diff --git a/src/test/run-make/target-specs/my-invalid-platform.json b/src/test/run-make/target-specs/my-invalid-platform.json new file mode 100644 index 00000000000..3feac45b7d6 --- /dev/null +++ b/src/test/run-make/target-specs/my-invalid-platform.json @@ -0,0 +1 @@ +wow this json is really broke! diff --git a/src/test/run-make/target-specs/x86_64-unknown-linux-gnu.json b/src/test/run-make/target-specs/x86_64-unknown-linux-gnu.json new file mode 100644 index 00000000000..f5f622bbcda --- /dev/null +++ b/src/test/run-make/target-specs/x86_64-unknown-linux-gnu.json @@ -0,0 +1,9 @@ +{ + "data-layout": "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32", + "llvm-target": "i686-unknown-linux-gnu", + "target-endian": "little", + "target-word-size": "32", + "arch": "x86", + "os": "linux", + "morestack": false +}