about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-04-26 16:00:48 +0000
committerbors <bors@rust-lang.org>2018-04-26 16:00:48 +0000
commit949010d23e9f7037a8e6f323588873b3d2438fb1 (patch)
tree5fc47e5862bd70b8728e6eb204c815f007c8dcad
parent88cd36714c6d62393f18d8efa2ea2724e1ec4a9d (diff)
parenta131c518ad640ccd12711ccd63d8b98cafa55ee9 (diff)
downloadrust-949010d23e9f7037a8e6f323588873b3d2438fb1.tar.gz
rust-949010d23e9f7037a8e6f323588873b3d2438fb1.zip
Auto merge of #50228 - irinagpopa:backstory-v2, r=nikomatsakis
Rename rustc_back to rustc_target and move ABI code to it.

Fixes #45226.
-rw-r--r--src/Cargo.lock44
-rw-r--r--src/librustc/Cargo.toml2
-rw-r--r--src/librustc/hir/intravisit.rs2
-rw-r--r--src/librustc/hir/map/blocks.rs2
-rw-r--r--src/librustc/hir/map/mod.rs2
-rw-r--r--src/librustc/hir/mod.rs2
-rw-r--r--src/librustc/hir/print.rs2
-rw-r--r--src/librustc/ich/impls_misc.rs2
-rw-r--r--src/librustc/ich/impls_syntax.rs2
-rw-r--r--src/librustc/lib.rs2
-rw-r--r--src/librustc/lint/context.rs3
-rw-r--r--src/librustc/middle/cstore.rs2
-rw-r--r--src/librustc/middle/dependency_format.rs2
-rw-r--r--src/librustc/middle/intrinsicck.rs2
-rw-r--r--src/librustc/middle/reachable.rs2
-rw-r--r--src/librustc/middle/weak_lang_items.rs2
-rw-r--r--src/librustc/session/config.rs13
-rw-r--r--src/librustc/session/mod.rs4
-rw-r--r--src/librustc/traits/error_reporting.rs4
-rw-r--r--src/librustc/traits/select.rs2
-rw-r--r--src/librustc/ty/context.rs6
-rw-r--r--src/librustc/ty/error.rs2
-rw-r--r--src/librustc/ty/instance.rs2
-rw-r--r--src/librustc/ty/layout.rs913
-rw-r--r--src/librustc/ty/maps/mod.rs2
-rw-r--r--src/librustc/ty/relate.rs2
-rw-r--r--src/librustc/ty/structural_impls.rs2
-rw-r--r--src/librustc/ty/sty.rs2
-rw-r--r--src/librustc/ty/util.rs2
-rw-r--r--src/librustc/util/ppaux.rs2
-rw-r--r--src/librustc_allocator/Cargo.toml1
-rw-r--r--src/librustc_allocator/expand.rs2
-rw-r--r--src/librustc_allocator/lib.rs1
-rw-r--r--src/librustc_back/README.md6
-rw-r--r--src/librustc_back/lib.rs170
-rw-r--r--src/librustc_cratesio_shim/Cargo.toml1
-rw-r--r--src/librustc_cratesio_shim/src/lib.rs1
-rw-r--r--src/librustc_data_structures/Cargo.toml1
-rw-r--r--src/librustc_data_structures/lib.rs4
-rw-r--r--src/librustc_driver/Cargo.toml2
-rw-r--r--src/librustc_driver/lib.rs4
-rw-r--r--src/librustc_driver/test.rs2
-rw-r--r--src/librustc_lint/Cargo.toml1
-rw-r--r--src/librustc_lint/bad_style.rs2
-rw-r--r--src/librustc_lint/builtin.rs2
-rw-r--r--src/librustc_lint/lib.rs1
-rw-r--r--src/librustc_lint/types.rs4
-rw-r--r--src/librustc_metadata/Cargo.toml2
-rw-r--r--src/librustc_metadata/creader.rs3
-rw-r--r--src/librustc_metadata/cstore.rs2
-rw-r--r--src/librustc_metadata/lib.rs2
-rw-r--r--src/librustc_metadata/link_args.rs2
-rw-r--r--src/librustc_metadata/locator.rs2
-rw-r--r--src/librustc_metadata/native_libs.rs2
-rw-r--r--src/librustc_metadata/schema.rs3
-rw-r--r--src/librustc_mir/Cargo.toml2
-rw-r--r--src/librustc_mir/build/expr/into.rs2
-rw-r--r--src/librustc_mir/build/mod.rs4
-rw-r--r--src/librustc_mir/hair/cx/mod.rs1
-rw-r--r--src/librustc_mir/interpret/eval_context.rs8
-rw-r--r--src/librustc_mir/interpret/terminator/mod.rs2
-rw-r--r--src/librustc_mir/lib.rs2
-rw-r--r--src/librustc_mir/monomorphize/item.rs2
-rw-r--r--src/librustc_mir/shim.rs2
-rw-r--r--src/librustc_mir/transform/const_prop.rs3
-rw-r--r--src/librustc_mir/transform/inline.rs2
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs2
-rw-r--r--src/librustc_mir/transform/rustc_peek.rs2
-rw-r--r--src/librustc_save_analysis/Cargo.toml1
-rw-r--r--src/librustc_save_analysis/lib.rs1
-rw-r--r--src/librustc_save_analysis/sig.rs6
-rw-r--r--src/librustc_target/Cargo.toml (renamed from src/librustc_back/Cargo.toml)10
-rw-r--r--src/librustc_target/README.md6
-rw-r--r--src/librustc_target/abi/call/aarch64.rs (renamed from src/librustc_trans/cabi_aarch64.rs)26
-rw-r--r--src/librustc_target/abi/call/arm.rs (renamed from src/librustc_trans/cabi_arm.rs)32
-rw-r--r--src/librustc_target/abi/call/asmjs.rs (renamed from src/librustc_trans/cabi_asmjs.rs)16
-rw-r--r--src/librustc_target/abi/call/hexagon.rs (renamed from src/librustc_trans/cabi_hexagon.rs)8
-rw-r--r--src/librustc_target/abi/call/mips.rs (renamed from src/librustc_trans/cabi_mips.rs)24
-rw-r--r--src/librustc_target/abi/call/mips64.rs (renamed from src/librustc_trans/cabi_mips64.rs)51
-rw-r--r--src/librustc_target/abi/call/mod.rs511
-rw-r--r--src/librustc_target/abi/call/msp430.rs (renamed from src/librustc_trans/cabi_msp430.rs)8
-rw-r--r--src/librustc_target/abi/call/nvptx.rs (renamed from src/librustc_trans/cabi_nvptx.rs)8
-rw-r--r--src/librustc_target/abi/call/nvptx64.rs (renamed from src/librustc_trans/cabi_nvptx64.rs)8
-rw-r--r--src/librustc_target/abi/call/powerpc.rs (renamed from src/librustc_trans/cabi_powerpc.rs)24
-rw-r--r--src/librustc_target/abi/call/powerpc64.rs (renamed from src/librustc_trans/cabi_powerpc64.rs)38
-rw-r--r--src/librustc_target/abi/call/s390x.rs (renamed from src/librustc_trans/cabi_s390x.rs)32
-rw-r--r--src/librustc_target/abi/call/sparc.rs (renamed from src/librustc_trans/cabi_sparc.rs)24
-rw-r--r--src/librustc_target/abi/call/sparc64.rs (renamed from src/librustc_trans/cabi_sparc64.rs)26
-rw-r--r--src/librustc_target/abi/call/wasm32.rs (renamed from src/librustc_trans/cabi_wasm32.rs)11
-rw-r--r--src/librustc_target/abi/call/x86.rs (renamed from src/librustc_trans/cabi_x86.rs)30
-rw-r--r--src/librustc_target/abi/call/x86_64.rs (renamed from src/librustc_trans/cabi_x86_64.rs)56
-rw-r--r--src/librustc_target/abi/call/x86_win64.rs (renamed from src/librustc_trans/cabi_x86_win64.rs)19
-rw-r--r--src/librustc_target/abi/mod.rs823
-rw-r--r--src/librustc_target/build.rs (renamed from src/librustc_back/build.rs)0
-rw-r--r--src/librustc_target/lib.rs46
-rw-r--r--src/librustc_target/spec/aarch64_apple_ios.rs (renamed from src/librustc_back/target/aarch64_apple_ios.rs)3
-rw-r--r--src/librustc_target/spec/aarch64_linux_android.rs (renamed from src/librustc_back/target/aarch64_linux_android.rs)3
-rw-r--r--src/librustc_target/spec/aarch64_unknown_cloudabi.rs (renamed from src/librustc_back/target/aarch64_unknown_cloudabi.rs)3
-rw-r--r--src/librustc_target/spec/aarch64_unknown_freebsd.rs (renamed from src/librustc_back/target/aarch64_unknown_freebsd.rs)3
-rw-r--r--src/librustc_target/spec/aarch64_unknown_fuchsia.rs (renamed from src/librustc_back/target/aarch64_unknown_fuchsia.rs)3
-rw-r--r--src/librustc_target/spec/aarch64_unknown_linux_gnu.rs (renamed from src/librustc_back/target/aarch64_unknown_linux_gnu.rs)3
-rw-r--r--src/librustc_target/spec/aarch64_unknown_linux_musl.rs (renamed from src/librustc_back/target/aarch64_unknown_linux_musl.rs)3
-rw-r--r--src/librustc_target/spec/abi.rs (renamed from src/libsyntax/abi.rs)0
-rw-r--r--src/librustc_target/spec/android_base.rs (renamed from src/librustc_back/target/android_base.rs)3
-rw-r--r--src/librustc_target/spec/apple_base.rs (renamed from src/librustc_back/target/apple_base.rs)2
-rw-r--r--src/librustc_target/spec/apple_ios_base.rs (renamed from src/librustc_back/target/apple_ios_base.rs)3
-rw-r--r--src/librustc_target/spec/arm_base.rs (renamed from src/librustc_back/target/arm_base.rs)2
-rw-r--r--src/librustc_target/spec/arm_linux_androideabi.rs (renamed from src/librustc_back/target/arm_linux_androideabi.rs)3
-rw-r--r--src/librustc_target/spec/arm_unknown_linux_gnueabi.rs (renamed from src/librustc_back/target/arm_unknown_linux_gnueabi.rs)3
-rw-r--r--src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs (renamed from src/librustc_back/target/arm_unknown_linux_gnueabihf.rs)3
-rw-r--r--src/librustc_target/spec/arm_unknown_linux_musleabi.rs (renamed from src/librustc_back/target/arm_unknown_linux_musleabi.rs)3
-rw-r--r--src/librustc_target/spec/arm_unknown_linux_musleabihf.rs (renamed from src/librustc_back/target/arm_unknown_linux_musleabihf.rs)3
-rw-r--r--src/librustc_target/spec/armv4t_unknown_linux_gnueabi.rs (renamed from src/librustc_back/target/armv4t_unknown_linux_gnueabi.rs)3
-rw-r--r--src/librustc_target/spec/armv5te_unknown_linux_gnueabi.rs (renamed from src/librustc_back/target/armv5te_unknown_linux_gnueabi.rs)3
-rw-r--r--src/librustc_target/spec/armv7_apple_ios.rs (renamed from src/librustc_back/target/armv7_apple_ios.rs)3
-rw-r--r--src/librustc_target/spec/armv7_linux_androideabi.rs (renamed from src/librustc_back/target/armv7_linux_androideabi.rs)3
-rw-r--r--src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs (renamed from src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs)3
-rw-r--r--src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs (renamed from src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs)3
-rw-r--r--src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs (renamed from src/librustc_back/target/armv7_unknown_linux_musleabihf.rs)3
-rw-r--r--src/librustc_target/spec/armv7s_apple_ios.rs (renamed from src/librustc_back/target/armv7s_apple_ios.rs)3
-rw-r--r--src/librustc_target/spec/asmjs_unknown_emscripten.rs (renamed from src/librustc_back/target/asmjs_unknown_emscripten.rs)3
-rw-r--r--src/librustc_target/spec/bitrig_base.rs (renamed from src/librustc_back/target/bitrig_base.rs)2
-rw-r--r--src/librustc_target/spec/cloudabi_base.rs (renamed from src/librustc_back/target/cloudabi_base.rs)4
-rw-r--r--src/librustc_target/spec/dragonfly_base.rs (renamed from src/librustc_back/target/dragonfly_base.rs)3
-rw-r--r--src/librustc_target/spec/freebsd_base.rs (renamed from src/librustc_back/target/freebsd_base.rs)3
-rw-r--r--src/librustc_target/spec/fuchsia_base.rs (renamed from src/librustc_back/target/fuchsia_base.rs)3
-rw-r--r--src/librustc_target/spec/haiku_base.rs (renamed from src/librustc_back/target/haiku_base.rs)2
-rw-r--r--src/librustc_target/spec/i386_apple_ios.rs (renamed from src/librustc_back/target/i386_apple_ios.rs)3
-rw-r--r--src/librustc_target/spec/i586_pc_windows_msvc.rs (renamed from src/librustc_back/target/i586_pc_windows_msvc.rs)2
-rw-r--r--src/librustc_target/spec/i586_unknown_linux_gnu.rs (renamed from src/librustc_back/target/i586_unknown_linux_gnu.rs)2
-rw-r--r--src/librustc_target/spec/i586_unknown_linux_musl.rs (renamed from src/librustc_back/target/i586_unknown_linux_musl.rs)2
-rw-r--r--src/librustc_target/spec/i686_apple_darwin.rs (renamed from src/librustc_back/target/i686_apple_darwin.rs)3
-rw-r--r--src/librustc_target/spec/i686_linux_android.rs (renamed from src/librustc_back/target/i686_linux_android.rs)3
-rw-r--r--src/librustc_target/spec/i686_pc_windows_gnu.rs (renamed from src/librustc_back/target/i686_pc_windows_gnu.rs)3
-rw-r--r--src/librustc_target/spec/i686_pc_windows_msvc.rs (renamed from src/librustc_back/target/i686_pc_windows_msvc.rs)3
-rw-r--r--src/librustc_target/spec/i686_unknown_cloudabi.rs (renamed from src/librustc_back/target/i686_unknown_cloudabi.rs)3
-rw-r--r--src/librustc_target/spec/i686_unknown_dragonfly.rs (renamed from src/librustc_back/target/i686_unknown_dragonfly.rs)3
-rw-r--r--src/librustc_target/spec/i686_unknown_freebsd.rs (renamed from src/librustc_back/target/i686_unknown_freebsd.rs)3
-rw-r--r--src/librustc_target/spec/i686_unknown_haiku.rs (renamed from src/librustc_back/target/i686_unknown_haiku.rs)3
-rw-r--r--src/librustc_target/spec/i686_unknown_linux_gnu.rs (renamed from src/librustc_back/target/i686_unknown_linux_gnu.rs)3
-rw-r--r--src/librustc_target/spec/i686_unknown_linux_musl.rs (renamed from src/librustc_back/target/i686_unknown_linux_musl.rs)3
-rw-r--r--src/librustc_target/spec/i686_unknown_netbsd.rs (renamed from src/librustc_back/target/i686_unknown_netbsd.rs)3
-rw-r--r--src/librustc_target/spec/i686_unknown_openbsd.rs (renamed from src/librustc_back/target/i686_unknown_openbsd.rs)3
-rw-r--r--src/librustc_target/spec/l4re_base.rs (renamed from src/librustc_back/target/l4re_base.rs)4
-rw-r--r--src/librustc_target/spec/linux_base.rs (renamed from src/librustc_back/target/linux_base.rs)3
-rw-r--r--src/librustc_target/spec/linux_musl_base.rs (renamed from src/librustc_back/target/linux_musl_base.rs)3
-rw-r--r--src/librustc_target/spec/mips64_unknown_linux_gnuabi64.rs (renamed from src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs)3
-rw-r--r--src/librustc_target/spec/mips64el_unknown_linux_gnuabi64.rs (renamed from src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs)3
-rw-r--r--src/librustc_target/spec/mips_unknown_linux_gnu.rs (renamed from src/librustc_back/target/mips_unknown_linux_gnu.rs)3
-rw-r--r--src/librustc_target/spec/mips_unknown_linux_musl.rs (renamed from src/librustc_back/target/mips_unknown_linux_musl.rs)3
-rw-r--r--src/librustc_target/spec/mips_unknown_linux_uclibc.rs (renamed from src/librustc_back/target/mips_unknown_linux_uclibc.rs)3
-rw-r--r--src/librustc_target/spec/mipsel_unknown_linux_gnu.rs (renamed from src/librustc_back/target/mipsel_unknown_linux_gnu.rs)3
-rw-r--r--src/librustc_target/spec/mipsel_unknown_linux_musl.rs (renamed from src/librustc_back/target/mipsel_unknown_linux_musl.rs)3
-rw-r--r--src/librustc_target/spec/mipsel_unknown_linux_uclibc.rs (renamed from src/librustc_back/target/mipsel_unknown_linux_uclibc.rs)3
-rw-r--r--src/librustc_target/spec/mod.rs (renamed from src/librustc_back/target/mod.rs)143
-rw-r--r--src/librustc_target/spec/msp430_none_elf.rs (renamed from src/librustc_back/target/msp430_none_elf.rs)3
-rw-r--r--src/librustc_target/spec/netbsd_base.rs (renamed from src/librustc_back/target/netbsd_base.rs)3
-rw-r--r--src/librustc_target/spec/openbsd_base.rs (renamed from src/librustc_back/target/openbsd_base.rs)3
-rw-r--r--src/librustc_target/spec/powerpc64_unknown_linux_gnu.rs (renamed from src/librustc_back/target/powerpc64_unknown_linux_gnu.rs)3
-rw-r--r--src/librustc_target/spec/powerpc64le_unknown_linux_gnu.rs (renamed from src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs)3
-rw-r--r--src/librustc_target/spec/powerpc_unknown_linux_gnu.rs (renamed from src/librustc_back/target/powerpc_unknown_linux_gnu.rs)3
-rw-r--r--src/librustc_target/spec/powerpc_unknown_linux_gnuspe.rs (renamed from src/librustc_back/target/powerpc_unknown_linux_gnuspe.rs)3
-rw-r--r--src/librustc_target/spec/powerpc_unknown_netbsd.rs (renamed from src/librustc_back/target/powerpc_unknown_netbsd.rs)3
-rw-r--r--src/librustc_target/spec/redox_base.rs (renamed from src/librustc_back/target/redox_base.rs)3
-rw-r--r--src/librustc_target/spec/s390x_unknown_linux_gnu.rs (renamed from src/librustc_back/target/s390x_unknown_linux_gnu.rs)3
-rw-r--r--src/librustc_target/spec/solaris_base.rs (renamed from src/librustc_back/target/solaris_base.rs)2
-rw-r--r--src/librustc_target/spec/sparc64_unknown_linux_gnu.rs (renamed from src/librustc_back/target/sparc64_unknown_linux_gnu.rs)3
-rw-r--r--src/librustc_target/spec/sparc64_unknown_netbsd.rs (renamed from src/librustc_back/target/sparc64_unknown_netbsd.rs)3
-rw-r--r--src/librustc_target/spec/sparc_unknown_linux_gnu.rs (renamed from src/librustc_back/target/sparc_unknown_linux_gnu.rs)3
-rw-r--r--src/librustc_target/spec/sparcv9_sun_solaris.rs (renamed from src/librustc_back/target/sparcv9_sun_solaris.rs)3
-rw-r--r--src/librustc_target/spec/thumb_base.rs (renamed from src/librustc_back/target/thumb_base.rs)3
-rw-r--r--src/librustc_target/spec/thumbv6m_none_eabi.rs (renamed from src/librustc_back/target/thumbv6m_none_eabi.rs)3
-rw-r--r--src/librustc_target/spec/thumbv7em_none_eabi.rs (renamed from src/librustc_back/target/thumbv7em_none_eabi.rs)3
-rw-r--r--src/librustc_target/spec/thumbv7em_none_eabihf.rs (renamed from src/librustc_back/target/thumbv7em_none_eabihf.rs)3
-rw-r--r--src/librustc_target/spec/thumbv7m_none_eabi.rs (renamed from src/librustc_back/target/thumbv7m_none_eabi.rs)3
-rw-r--r--src/librustc_target/spec/wasm32_experimental_emscripten.rs (renamed from src/librustc_back/target/wasm32_experimental_emscripten.rs)3
-rw-r--r--src/librustc_target/spec/wasm32_unknown_emscripten.rs (renamed from src/librustc_back/target/wasm32_unknown_emscripten.rs)3
-rw-r--r--src/librustc_target/spec/wasm32_unknown_unknown.rs (renamed from src/librustc_back/target/wasm32_unknown_unknown.rs)3
-rw-r--r--src/librustc_target/spec/windows_base.rs (renamed from src/librustc_back/target/windows_base.rs)3
-rw-r--r--src/librustc_target/spec/windows_msvc_base.rs (renamed from src/librustc_back/target/windows_msvc_base.rs)3
-rw-r--r--src/librustc_target/spec/x86_64_apple_darwin.rs (renamed from src/librustc_back/target/x86_64_apple_darwin.rs)3
-rw-r--r--src/librustc_target/spec/x86_64_apple_ios.rs (renamed from src/librustc_back/target/x86_64_apple_ios.rs)3
-rw-r--r--src/librustc_target/spec/x86_64_linux_android.rs (renamed from src/librustc_back/target/x86_64_linux_android.rs)3
-rw-r--r--src/librustc_target/spec/x86_64_pc_windows_gnu.rs (renamed from src/librustc_back/target/x86_64_pc_windows_gnu.rs)3
-rw-r--r--src/librustc_target/spec/x86_64_pc_windows_msvc.rs (renamed from src/librustc_back/target/x86_64_pc_windows_msvc.rs)3
-rw-r--r--src/librustc_target/spec/x86_64_rumprun_netbsd.rs (renamed from src/librustc_back/target/x86_64_rumprun_netbsd.rs)3
-rw-r--r--src/librustc_target/spec/x86_64_sun_solaris.rs (renamed from src/librustc_back/target/x86_64_sun_solaris.rs)3
-rw-r--r--src/librustc_target/spec/x86_64_unknown_bitrig.rs (renamed from src/librustc_back/target/x86_64_unknown_bitrig.rs)3
-rw-r--r--src/librustc_target/spec/x86_64_unknown_cloudabi.rs (renamed from src/librustc_back/target/x86_64_unknown_cloudabi.rs)3
-rw-r--r--src/librustc_target/spec/x86_64_unknown_dragonfly.rs (renamed from src/librustc_back/target/x86_64_unknown_dragonfly.rs)3
-rw-r--r--src/librustc_target/spec/x86_64_unknown_freebsd.rs (renamed from src/librustc_back/target/x86_64_unknown_freebsd.rs)3
-rw-r--r--src/librustc_target/spec/x86_64_unknown_fuchsia.rs (renamed from src/librustc_back/target/x86_64_unknown_fuchsia.rs)3
-rw-r--r--src/librustc_target/spec/x86_64_unknown_haiku.rs (renamed from src/librustc_back/target/x86_64_unknown_haiku.rs)3
-rw-r--r--src/librustc_target/spec/x86_64_unknown_l4re_uclibc.rs (renamed from src/librustc_back/target/x86_64_unknown_l4re_uclibc.rs)3
-rw-r--r--src/librustc_target/spec/x86_64_unknown_linux_gnu.rs (renamed from src/librustc_back/target/x86_64_unknown_linux_gnu.rs)3
-rw-r--r--src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs (renamed from src/librustc_back/target/x86_64_unknown_linux_gnux32.rs)3
-rw-r--r--src/librustc_target/spec/x86_64_unknown_linux_musl.rs (renamed from src/librustc_back/target/x86_64_unknown_linux_musl.rs)3
-rw-r--r--src/librustc_target/spec/x86_64_unknown_netbsd.rs (renamed from src/librustc_back/target/x86_64_unknown_netbsd.rs)3
-rw-r--r--src/librustc_target/spec/x86_64_unknown_openbsd.rs (renamed from src/librustc_back/target/x86_64_unknown_openbsd.rs)3
-rw-r--r--src/librustc_target/spec/x86_64_unknown_redox.rs (renamed from src/librustc_back/target/x86_64_unknown_redox.rs)3
-rw-r--r--src/librustc_trans/Cargo.toml7
-rw-r--r--src/librustc_trans/abi.rs597
-rw-r--r--src/librustc_trans/back/command.rs2
-rw-r--r--src/librustc_trans/back/link.rs4
-rw-r--r--src/librustc_trans/back/linker.rs2
-rw-r--r--src/librustc_trans/base.rs2
-rw-r--r--src/librustc_trans/callee.rs2
-rw-r--r--src/librustc_trans/common.rs2
-rw-r--r--src/librustc_trans/context.rs10
-rw-r--r--src/librustc_trans/debuginfo/metadata.rs2
-rw-r--r--src/librustc_trans/declare.rs6
-rw-r--r--src/librustc_trans/intrinsic.rs4
-rw-r--r--src/librustc_trans/lib.rs22
-rw-r--r--src/librustc_trans/metadata.rs2
-rw-r--r--src/librustc_trans/meth.rs4
-rw-r--r--src/librustc_trans/mir/block.rs14
-rw-r--r--src/librustc_trans/mir/mod.rs6
-rw-r--r--src/librustc_trans/type_of.rs4
-rw-r--r--src/librustc_trans_utils/Cargo.toml2
-rw-r--r--src/librustc_trans_utils/lib.rs2
-rw-r--r--src/librustc_trans_utils/trans_crate.rs2
-rw-r--r--src/librustc_typeck/Cargo.toml1
-rw-r--r--src/librustc_typeck/astconv.rs3
-rw-r--r--src/librustc_typeck/check/callee.rs2
-rw-r--r--src/librustc_typeck/check/closure.rs2
-rw-r--r--src/librustc_typeck/check/intrinsic.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs2
-rw-r--r--src/librustc_typeck/collect.rs3
-rw-r--r--src/librustc_typeck/lib.rs3
-rw-r--r--src/librustc_typeck/outlives/implicit_infer.rs3
-rw-r--r--src/librustdoc/clean/mod.rs2
-rw-r--r--src/librustdoc/core.rs2
-rw-r--r--src/librustdoc/doctree.rs2
-rw-r--r--src/librustdoc/html/format.rs2
-rw-r--r--src/librustdoc/html/render.rs3
-rw-r--r--src/librustdoc/lib.rs4
-rw-r--r--src/librustdoc/visit_ast.rs2
-rw-r--r--src/libsyntax/Cargo.toml2
-rw-r--r--src/libsyntax/ast.rs2
-rw-r--r--src/libsyntax/ext/build.rs2
-rw-r--r--src/libsyntax/feature_gate.rs2
-rw-r--r--src/libsyntax/lib.rs6
-rw-r--r--src/libsyntax/parse/mod.rs2
-rw-r--r--src/libsyntax/parse/parser.rs2
-rw-r--r--src/libsyntax/print/pprust.rs2
-rw-r--r--src/libsyntax/test.rs4
-rw-r--r--src/libsyntax/visit.rs2
-rw-r--r--src/libsyntax_ext/Cargo.toml3
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs2
-rw-r--r--src/libsyntax_ext/lib.rs1
-rw-r--r--src/rustc/Cargo.toml4
251 files changed, 2267 insertions, 2086 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock
index b265ee5765a..e14b9da9713 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -1728,10 +1728,10 @@ dependencies = [
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro 0.0.0",
  "rustc_apfloat 0.0.0",
- "rustc_back 0.0.0",
  "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
+ "rustc_target 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
@@ -1818,8 +1818,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "rustc-main"
 version = "0.0.0"
 dependencies = [
- "rustc_back 0.0.0",
  "rustc_driver 0.0.0",
+ "rustc_target 0.0.0",
 ]
 
 [[package]]
@@ -1833,6 +1833,7 @@ version = "0.0.0"
 dependencies = [
  "rustc 0.0.0",
  "rustc_errors 0.0.0",
+ "rustc_target 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -1858,16 +1859,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "rustc_back"
-version = "0.0.0"
-dependencies = [
- "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serialize 0.0.0",
- "syntax 0.0.0",
-]
-
-[[package]]
 name = "rustc_borrowck"
 version = "0.0.0"
 dependencies = [
@@ -1895,6 +1886,7 @@ name = "rustc_cratesio_shim"
 version = "0.0.0"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1906,6 +1898,7 @@ dependencies = [
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc_cratesio_shim 0.0.0",
  "serialize 0.0.0",
  "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1921,7 +1914,6 @@ dependencies = [
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_allocator 0.0.0",
- "rustc_back 0.0.0",
  "rustc_borrowck 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
@@ -1934,6 +1926,7 @@ dependencies = [
  "rustc_privacy 0.0.0",
  "rustc_resolve 0.0.0",
  "rustc_save_analysis 0.0.0",
+ "rustc_target 0.0.0",
  "rustc_traits 0.0.0",
  "rustc_trans_utils 0.0.0",
  "rustc_typeck 0.0.0",
@@ -1976,6 +1969,7 @@ dependencies = [
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_mir 0.0.0",
+ "rustc_target 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -2011,9 +2005,9 @@ dependencies = [
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro 0.0.0",
  "rustc 0.0.0",
- "rustc_back 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
+ "rustc_target 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
  "syntax_ext 0.0.0",
@@ -2032,10 +2026,10 @@ dependencies = [
  "log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_apfloat 0.0.0",
- "rustc_back 0.0.0",
  "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
+ "rustc_target 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
@@ -2116,12 +2110,23 @@ dependencies = [
  "rustc 0.0.0",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_data_structures 0.0.0",
+ "rustc_target 0.0.0",
  "rustc_typeck 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
 
 [[package]]
+name = "rustc_target"
+version = "0.0.0"
+dependencies = [
+ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc_cratesio_shim 0.0.0",
+ "serialize 0.0.0",
+]
+
+[[package]]
 name = "rustc_traits"
 version = "0.0.0"
 dependencies = [
@@ -2138,7 +2143,6 @@ dependencies = [
 name = "rustc_trans"
 version = "0.0.0"
 dependencies = [
- "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2150,7 +2154,6 @@ dependencies = [
  "rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_allocator 0.0.0",
  "rustc_apfloat 0.0.0",
- "rustc_back 0.0.0",
  "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
@@ -2158,6 +2161,7 @@ dependencies = [
  "rustc_llvm 0.0.0",
  "rustc_mir 0.0.0",
  "rustc_platform_intrinsics 0.0.0",
+ "rustc_target 0.0.0",
  "rustc_trans_utils 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
@@ -2173,10 +2177,10 @@ dependencies = [
  "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
- "rustc_back 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_incremental 0.0.0",
  "rustc_mir 0.0.0",
+ "rustc_target 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -2205,6 +2209,7 @@ dependencies = [
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_platform_intrinsics 0.0.0",
+ "rustc_target 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -2543,9 +2548,9 @@ version = "0.0.0"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc_cratesio_shim 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
+ "rustc_target 0.0.0",
  "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serialize 0.0.0",
  "syntax_pos 0.0.0",
@@ -2559,6 +2564,7 @@ dependencies = [
  "proc_macro 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
+ "rustc_target 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index 2aae0f24d48..357ebb89fb6 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -18,7 +18,7 @@ lazy_static = "1.0.0"
 log = { version = "0.4", features = ["release_max_level_info", "std"] }
 proc_macro = { path = "../libproc_macro" }
 rustc_apfloat = { path = "../librustc_apfloat" }
-rustc_back = { path = "../librustc_back" }
+rustc_target = { path = "../librustc_target" }
 rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index be9f8b8dac5..62f3f9f4486 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -41,7 +41,7 @@
 //! This order consistency is required in a few places in rustc, for
 //! example generator inference, and possibly also HIR borrowck.
 
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute};
 use syntax_pos::Span;
 use hir::*;
diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs
index 1eaacdb1d7f..362c0bf07f7 100644
--- a/src/librustc/hir/map/blocks.rs
+++ b/src/librustc/hir/map/blocks.rs
@@ -25,7 +25,7 @@ use hir as ast;
 use hir::map::{self, Node};
 use hir::{Expr, FnDecl};
 use hir::intravisit::FnKind;
-use syntax::abi;
+use rustc_target::spec::abi;
 use syntax::ast::{Attribute, Name, NodeId};
 use syntax_pos::Span;
 
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 9520ed32af9..a9613a60a57 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -21,7 +21,7 @@ use hir::def_id::{CRATE_DEF_INDEX, DefId, LocalDefId, DefIndexAddressSpace};
 
 use middle::cstore::CrateStore;
 
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax::ast::{self, Name, NodeId, CRATE_NODE_ID};
 use syntax::codemap::Spanned;
 use syntax::ext::base::MacroKind;
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index f471ffb072d..0dc89d64bd5 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -34,7 +34,7 @@ use mir::mono::Linkage;
 
 use syntax_pos::{Span, DUMMY_SP};
 use syntax::codemap::{self, Spanned};
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
 use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
 use syntax::attr::InlineAttr;
diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs
index d3f2458ef87..3943c30127d 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -10,7 +10,7 @@
 
 pub use self::AnnNode::*;
 
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax::ast;
 use syntax::codemap::{CodeMap, Spanned};
 use syntax::parse::{token, ParseSess};
diff --git a/src/librustc/ich/impls_misc.rs b/src/librustc/ich/impls_misc.rs
index 951315fb4a8..db404179175 100644
--- a/src/librustc/ich/impls_misc.rs
+++ b/src/librustc/ich/impls_misc.rs
@@ -20,7 +20,7 @@ impl_stable_hash_for!(enum ::session::search_paths::PathKind {
     All
 });
 
-impl_stable_hash_for!(enum ::rustc_back::PanicStrategy {
+impl_stable_hash_for!(enum ::rustc_target::spec::PanicStrategy {
     Abort,
     Unwind
 });
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index 4ac678aaa05..d7e16ab3620 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -82,7 +82,7 @@ impl_stable_hash_for!(enum ::syntax::ext::base::MacroKind {
 });
 
 
-impl_stable_hash_for!(enum ::syntax::abi::Abi {
+impl_stable_hash_for!(enum ::rustc_target::spec::abi::Abi {
     Cdecl,
     Stdcall,
     Fastcall,
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index bb495049483..f85d0a9bf0c 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -81,7 +81,7 @@ extern crate graphviz;
 #[macro_use] extern crate lazy_static;
 #[cfg(windows)]
 extern crate libc;
-extern crate rustc_back;
+extern crate rustc_target;
 #[macro_use] extern crate rustc_data_structures;
 extern crate serialize;
 extern crate rustc_const_math;
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index d5849ea22b1..f90baa2ccd9 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -657,7 +657,8 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for &'a LateContext<'a, 'tcx> {
+impl<'a, 'tcx> LayoutOf for &'a LateContext<'a, 'tcx> {
+    type Ty = Ty<'tcx>;
     type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>;
 
     fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 60e197e614a..4400ebc294f 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -37,7 +37,7 @@ use syntax::ast;
 use syntax::ext::base::SyntaxExtension;
 use syntax::symbol::Symbol;
 use syntax_pos::Span;
-use rustc_back::target::Target;
+use rustc_target::spec::Target;
 use rustc_data_structures::sync::{MetadataRef, Lrc};
 
 pub use self::NativeLibraryKind::*;
diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs
index e7fc8d633c8..4996a6acff8 100644
--- a/src/librustc/middle/dependency_format.rs
+++ b/src/librustc/middle/dependency_format.rs
@@ -69,7 +69,7 @@ use ty::TyCtxt;
 use middle::cstore::{self, DepKind};
 use middle::cstore::LinkagePreference::{self, RequireStatic, RequireDynamic};
 use util::nodemap::FxHashMap;
-use rustc_back::PanicStrategy;
+use rustc_target::spec::PanicStrategy;
 
 /// A list of dependencies for a certain crate type.
 ///
diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs
index 0a4e5094cde..27f7dbf508d 100644
--- a/src/librustc/middle/intrinsicck.rs
+++ b/src/librustc/middle/intrinsicck.rs
@@ -13,7 +13,7 @@ use hir::def_id::DefId;
 use ty::{self, Ty, TyCtxt};
 use ty::layout::{LayoutError, Pointer, SizeSkeleton};
 
-use syntax::abi::Abi::RustIntrinsic;
+use rustc_target::spec::abi::Abi::RustIntrinsic;
 use syntax_pos::Span;
 use hir::intravisit::{self, Visitor, NestedVisitorMap};
 use hir;
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 48a62c8c14d..0aeb15b49fb 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -26,7 +26,7 @@ use middle::privacy;
 use session::config;
 use util::nodemap::{NodeSet, FxHashSet};
 
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax::ast;
 use syntax::attr;
 use hir;
diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs
index a2bceb19102..42e4d3861ba 100644
--- a/src/librustc/middle/weak_lang_items.rs
+++ b/src/librustc/middle/weak_lang_items.rs
@@ -13,7 +13,7 @@
 use session::config;
 use middle::lang_items;
 
-use rustc_back::PanicStrategy;
+use rustc_target::spec::PanicStrategy;
 use syntax::ast;
 use syntax::symbol::Symbol;
 use syntax_pos::Span;
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 456e83f4700..ab703d423c6 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -22,8 +22,8 @@ use session::{early_error, early_warn, Session};
 use session::search_paths::SearchPaths;
 
 use ich::StableHashingContext;
-use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
-use rustc_back::target::{Target, TargetTriple};
+use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel};
+use rustc_target::spec::{Target, TargetTriple};
 use rustc_data_structures::stable_hasher::ToStableHashKey;
 use lint;
 use middle::cstore;
@@ -770,7 +770,7 @@ macro_rules! options {
         pub const parse_sanitizer: Option<&'static str> =
             Some("one of: `address`, `leak`, `memory` or `thread`");
         pub const parse_linker_flavor: Option<&'static str> =
-            Some(::rustc_back::LinkerFlavor::one_of());
+            Some(::rustc_target::spec::LinkerFlavor::one_of());
         pub const parse_optimization_fuel: Option<&'static str> =
             Some("crate=integer");
         pub const parse_unpretty: Option<&'static str> =
@@ -782,7 +782,7 @@ macro_rules! options {
     #[allow(dead_code)]
     mod $mod_set {
         use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto};
-        use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
+        use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel};
         use std::path::PathBuf;
 
         $(
@@ -2323,8 +2323,7 @@ mod dep_tracking {
     use super::{CrateType, DebugInfoLevel, ErrorOutputType, Lto, OptLevel, OutputTypes,
                 Passes, Sanitizer};
     use syntax::feature_gate::UnstableFeatures;
-    use rustc_back::{PanicStrategy, RelroLevel};
-    use rustc_back::target::TargetTriple;
+    use rustc_target::spec::{PanicStrategy, RelroLevel, TargetTriple};
     use syntax::edition::Edition;
 
     pub trait DepTrackingHash {
@@ -2456,7 +2455,7 @@ mod tests {
     use std::iter::FromIterator;
     use std::path::PathBuf;
     use super::{Externs, OutputType, OutputTypes};
-    use rustc_back::{PanicStrategy, RelroLevel};
+    use rustc_target::spec::{PanicStrategy, RelroLevel};
     use syntax::symbol::Symbol;
     use syntax::edition::{Edition, DEFAULT_EDITION};
     use syntax;
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 3bd2bb3c8be..a0f11443425 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -41,8 +41,8 @@ use syntax::{ast, codemap};
 use syntax::feature_gate::AttributeType;
 use syntax_pos::{MultiSpan, Span};
 
-use rustc_back::{LinkerFlavor, PanicStrategy};
-use rustc_back::target::{Target, TargetTriple};
+use rustc_target::spec::{LinkerFlavor, PanicStrategy};
+use rustc_target::spec::{Target, TargetTriple};
 use rustc_data_structures::flock;
 use jobserver::Client;
 
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index a7669b942e3..33abc0c7e15 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -1091,7 +1091,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                     tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })),
                     false,
                     hir::Unsafety::Normal,
-                    ::syntax::abi::Abi::Rust
+                    ::rustc_target::spec::abi::Abi::Rust
                 )
             } else {
                 tcx.mk_fn_sig(
@@ -1099,7 +1099,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                     tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })),
                     false,
                     hir::Unsafety::Normal,
-                    ::syntax::abi::Abi::Rust
+                    ::rustc_target::spec::abi::Abi::Rust
                 )
             };
             format!("{}", ty::Binder::bind(sig))
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index cfc14b7bfe4..f43f5cf3e3f 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -51,7 +51,7 @@ use std::cmp;
 use std::fmt;
 use std::mem;
 use std::rc::Rc;
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use hir;
 use util::nodemap::{FxHashMap, FxHashSet};
 
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index c35f515a99e..4f49b159ad3 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -70,7 +70,7 @@ use std::ops::Deref;
 use std::iter;
 use std::sync::mpsc;
 use std::sync::Arc;
-use syntax::abi;
+use rustc_target::spec::abi;
 use syntax::ast::{self, NodeId};
 use syntax::attr;
 use syntax::codemap::MultiSpan;
@@ -1204,7 +1204,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                                   f: F) -> R
                                   where F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'tcx>) -> R
     {
-        let data_layout = TargetDataLayout::parse(s);
+        let data_layout = TargetDataLayout::parse(&s.target.target).unwrap_or_else(|err| {
+            s.fatal(&err);
+        });
         let interners = CtxtInterners::new(&arenas.interner);
         let common_types = CommonTypes::new(&interners);
         let dep_graph = hir.dep_graph.clone();
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index eb392418647..cf2004a681e 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -11,7 +11,7 @@
 use hir::def_id::DefId;
 use ty::{self, BoundRegion, Region, Ty, TyCtxt};
 use std::fmt;
-use syntax::abi;
+use rustc_target::spec::abi;
 use syntax::ast;
 use errors::DiagnosticBuilder;
 use syntax_pos::Span;
diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs
index 02a03bc542a..ecd415c4bc4 100644
--- a/src/librustc/ty/instance.rs
+++ b/src/librustc/ty/instance.rs
@@ -12,7 +12,7 @@ use hir::def_id::DefId;
 use ty::{self, Ty, TypeFoldable, Substs, TyCtxt};
 use ty::subst::Kind;
 use traits;
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use util::ppaux;
 
 use std::fmt;
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 77e2e9447f1..942cfdb36b8 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -8,10 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use self::Integer::*;
-pub use self::Primitive::*;
-
-use session::{self, DataTypeKind, Session};
+use session::{self, DataTypeKind};
 use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions};
 
 use syntax::ast::{self, FloatTy, IntTy, UintTy};
@@ -21,432 +18,28 @@ use syntax_pos::DUMMY_SP;
 use std::cmp;
 use std::fmt;
 use std::i128;
-use std::iter;
 use std::mem;
-use std::ops::{Add, Sub, Mul, AddAssign, Deref, RangeInclusive};
+use std::ops::RangeInclusive;
 
 use ich::StableHashingContext;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
                                            StableHasherResult};
 
-/// Parsed [Data layout](http://llvm.org/docs/LangRef.html#data-layout)
-/// for a target, which contains everything needed to compute layouts.
-pub struct TargetDataLayout {
-    pub endian: Endian,
-    pub i1_align: Align,
-    pub i8_align: Align,
-    pub i16_align: Align,
-    pub i32_align: Align,
-    pub i64_align: Align,
-    pub i128_align: Align,
-    pub f32_align: Align,
-    pub f64_align: Align,
-    pub pointer_size: Size,
-    pub pointer_align: Align,
-    pub aggregate_align: Align,
-
-    /// Alignments for vector types.
-    pub vector_align: Vec<(Size, Align)>
-}
-
-impl Default for TargetDataLayout {
-    /// Creates an instance of `TargetDataLayout`.
-    fn default() -> TargetDataLayout {
-        TargetDataLayout {
-            endian: Endian::Big,
-            i1_align: Align::from_bits(8, 8).unwrap(),
-            i8_align: Align::from_bits(8, 8).unwrap(),
-            i16_align: Align::from_bits(16, 16).unwrap(),
-            i32_align: Align::from_bits(32, 32).unwrap(),
-            i64_align: Align::from_bits(32, 64).unwrap(),
-            i128_align: Align::from_bits(32, 64).unwrap(),
-            f32_align: Align::from_bits(32, 32).unwrap(),
-            f64_align: Align::from_bits(64, 64).unwrap(),
-            pointer_size: Size::from_bits(64),
-            pointer_align: Align::from_bits(64, 64).unwrap(),
-            aggregate_align: Align::from_bits(0, 64).unwrap(),
-            vector_align: vec![
-                (Size::from_bits(64), Align::from_bits(64, 64).unwrap()),
-                (Size::from_bits(128), Align::from_bits(128, 128).unwrap())
-            ]
-        }
-    }
-}
-
-impl TargetDataLayout {
-    pub fn parse(sess: &Session) -> TargetDataLayout {
-        // Parse a bit count from a string.
-        let parse_bits = |s: &str, kind: &str, cause: &str| {
-            s.parse::<u64>().unwrap_or_else(|err| {
-                sess.err(&format!("invalid {} `{}` for `{}` in \"data-layout\": {}",
-                                  kind, s, cause, err));
-                0
-            })
-        };
-
-        // Parse a size string.
-        let size = |s: &str, cause: &str| {
-            Size::from_bits(parse_bits(s, "size", cause))
-        };
-
-        // Parse an alignment string.
-        let align = |s: &[&str], cause: &str| {
-            if s.is_empty() {
-                sess.err(&format!("missing alignment for `{}` in \"data-layout\"", cause));
-            }
-            let abi = parse_bits(s[0], "alignment", cause);
-            let pref = s.get(1).map_or(abi, |pref| parse_bits(pref, "alignment", cause));
-            Align::from_bits(abi, pref).unwrap_or_else(|err| {
-                sess.err(&format!("invalid alignment for `{}` in \"data-layout\": {}",
-                                  cause, err));
-                Align::from_bits(8, 8).unwrap()
-            })
-        };
-
-        let mut dl = TargetDataLayout::default();
-        let mut i128_align_src = 64;
-        for spec in sess.target.target.data_layout.split("-") {
-            match &spec.split(":").collect::<Vec<_>>()[..] {
-                &["e"] => dl.endian = Endian::Little,
-                &["E"] => dl.endian = Endian::Big,
-                &["a", ref a..] => dl.aggregate_align = align(a, "a"),
-                &["f32", ref a..] => dl.f32_align = align(a, "f32"),
-                &["f64", ref a..] => dl.f64_align = align(a, "f64"),
-                &[p @ "p", s, ref a..] | &[p @ "p0", s, ref a..] => {
-                    dl.pointer_size = size(s, p);
-                    dl.pointer_align = align(a, p);
-                }
-                &[s, ref a..] if s.starts_with("i") => {
-                    let bits = match s[1..].parse::<u64>() {
-                        Ok(bits) => bits,
-                        Err(_) => {
-                            size(&s[1..], "i"); // For the user error.
-                            continue;
-                        }
-                    };
-                    let a = align(a, s);
-                    match bits {
-                        1 => dl.i1_align = a,
-                        8 => dl.i8_align = a,
-                        16 => dl.i16_align = a,
-                        32 => dl.i32_align = a,
-                        64 => dl.i64_align = a,
-                        _ => {}
-                    }
-                    if bits >= i128_align_src && bits <= 128 {
-                        // Default alignment for i128 is decided by taking the alignment of
-                        // largest-sized i{64...128}.
-                        i128_align_src = bits;
-                        dl.i128_align = a;
-                    }
-                }
-                &[s, ref a..] if s.starts_with("v") => {
-                    let v_size = size(&s[1..], "v");
-                    let a = align(a, s);
-                    if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) {
-                        v.1 = a;
-                        continue;
-                    }
-                    // No existing entry, add a new one.
-                    dl.vector_align.push((v_size, a));
-                }
-                _ => {} // Ignore everything else.
-            }
-        }
-
-        // Perform consistency checks against the Target information.
-        let endian_str = match dl.endian {
-            Endian::Little => "little",
-            Endian::Big => "big"
-        };
-        if endian_str != sess.target.target.target_endian {
-            sess.err(&format!("inconsistent target specification: \"data-layout\" claims \
-                               architecture is {}-endian, while \"target-endian\" is `{}`",
-                              endian_str, sess.target.target.target_endian));
-        }
-
-        if dl.pointer_size.bits().to_string() != sess.target.target.target_pointer_width {
-            sess.err(&format!("inconsistent target specification: \"data-layout\" claims \
-                               pointers are {}-bit, while \"target-pointer-width\" is `{}`",
-                              dl.pointer_size.bits(), sess.target.target.target_pointer_width));
-        }
-
-        dl
-    }
-
-    /// Return exclusive upper bound on object size.
-    ///
-    /// The theoretical maximum object size is defined as the maximum positive `isize` value.
-    /// This ensures that the `offset` semantics remain well-defined by allowing it to correctly
-    /// index every address within an object along with one byte past the end, along with allowing
-    /// `isize` to store the difference between any two pointers into an object.
-    ///
-    /// The upper bound on 64-bit currently needs to be lower because LLVM uses a 64-bit integer
-    /// to represent object size in bits. It would need to be 1 << 61 to account for this, but is
-    /// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable
-    /// address space on 64-bit ARMv8 and x86_64.
-    pub fn obj_size_bound(&self) -> u64 {
-        match self.pointer_size.bits() {
-            16 => 1 << 15,
-            32 => 1 << 31,
-            64 => 1 << 47,
-            bits => bug!("obj_size_bound: unknown pointer bit size {}", bits)
-        }
-    }
-
-    pub fn ptr_sized_integer(&self) -> Integer {
-        match self.pointer_size.bits() {
-            16 => I16,
-            32 => I32,
-            64 => I64,
-            bits => bug!("ptr_sized_integer: unknown pointer bit size {}", bits)
-        }
-    }
-
-    pub fn vector_align(&self, vec_size: Size) -> Align {
-        for &(size, align) in &self.vector_align {
-            if size == vec_size {
-                return align;
-            }
-        }
-        // Default to natural alignment, which is what LLVM does.
-        // That is, use the size, rounded up to a power of 2.
-        let align = vec_size.bytes().next_power_of_two();
-        Align::from_bytes(align, align).unwrap()
-    }
-}
-
-pub trait HasDataLayout: Copy {
-    fn data_layout(&self) -> &TargetDataLayout;
-}
-
-impl<'a> HasDataLayout for &'a TargetDataLayout {
-    fn data_layout(&self) -> &TargetDataLayout {
-        self
-    }
-}
-
-/// Endianness of the target, which must match cfg(target-endian).
-#[derive(Copy, Clone)]
-pub enum Endian {
-    Little,
-    Big
-}
-
-/// Size of a type in bytes.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-pub struct Size {
-    raw: u64
-}
-
-impl Size {
-    pub fn from_bits(bits: u64) -> Size {
-        // Avoid potential overflow from `bits + 7`.
-        Size::from_bytes(bits / 8 + ((bits % 8) + 7) / 8)
-    }
-
-    pub fn from_bytes(bytes: u64) -> Size {
-        if bytes >= (1 << 61) {
-            bug!("Size::from_bytes: {} bytes in bits doesn't fit in u64", bytes)
-        }
-        Size {
-            raw: bytes
-        }
-    }
-
-    pub fn bytes(self) -> u64 {
-        self.raw
-    }
-
-    pub fn bits(self) -> u64 {
-        self.bytes() * 8
-    }
-
-    pub fn abi_align(self, align: Align) -> Size {
-        let mask = align.abi() - 1;
-        Size::from_bytes((self.bytes() + mask) & !mask)
-    }
-
-    pub fn is_abi_aligned(self, align: Align) -> bool {
-        let mask = align.abi() - 1;
-        self.bytes() & mask == 0
-    }
-
-    pub fn checked_add<C: HasDataLayout>(self, offset: Size, cx: C) -> Option<Size> {
-        let dl = cx.data_layout();
-
-        // Each Size is less than dl.obj_size_bound(), so the sum is
-        // also less than 1 << 62 (and therefore can't overflow).
-        let bytes = self.bytes() + offset.bytes();
-
-        if bytes < dl.obj_size_bound() {
-            Some(Size::from_bytes(bytes))
-        } else {
-            None
-        }
-    }
-
-    pub fn checked_mul<C: HasDataLayout>(self, count: u64, cx: C) -> Option<Size> {
-        let dl = cx.data_layout();
-
-        match self.bytes().checked_mul(count) {
-            Some(bytes) if bytes < dl.obj_size_bound() => {
-                Some(Size::from_bytes(bytes))
-            }
-            _ => None
-        }
-    }
-}
-
-// Panicking addition, subtraction and multiplication for convenience.
-// Avoid during layout computation, return `LayoutError` instead.
-
-impl Add for Size {
-    type Output = Size;
-    fn add(self, other: Size) -> Size {
-        // Each Size is less than 1 << 61, so the sum is
-        // less than 1 << 62 (and therefore can't overflow).
-        Size::from_bytes(self.bytes() + other.bytes())
-    }
-}
-
-impl Sub for Size {
-    type Output = Size;
-    fn sub(self, other: Size) -> Size {
-        // Each Size is less than 1 << 61, so an underflow
-        // would result in a value larger than 1 << 61,
-        // which Size::from_bytes will catch for us.
-        Size::from_bytes(self.bytes() - other.bytes())
-    }
-}
-
-impl Mul<u64> for Size {
-    type Output = Size;
-    fn mul(self, count: u64) -> Size {
-        match self.bytes().checked_mul(count) {
-            Some(bytes) => Size::from_bytes(bytes),
-            None => {
-                bug!("Size::mul: {} * {} doesn't fit in u64", self.bytes(), count)
-            }
-        }
-    }
-}
-
-impl AddAssign for Size {
-    fn add_assign(&mut self, other: Size) {
-        *self = *self + other;
-    }
-}
-
-/// Alignment of a type in bytes, both ABI-mandated and preferred.
-/// Each field is a power of two, giving the alignment a maximum
-/// value of 2<sup>(2<sup>8</sup> - 1)</sup>, which is limited by LLVM to a i32, with
-/// a maximum capacity of 2<sup>31</sup> - 1 or 2147483647.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
-pub struct Align {
-    abi_pow2: u8,
-    pref_pow2: u8,
-}
+pub use rustc_target::abi::*;
 
-impl Align {
-    pub fn from_bits(abi: u64, pref: u64) -> Result<Align, String> {
-        Align::from_bytes(Size::from_bits(abi).bytes(),
-                          Size::from_bits(pref).bytes())
-    }
-
-    pub fn from_bytes(abi: u64, pref: u64) -> Result<Align, String> {
-        let log2 = |align: u64| {
-            // Treat an alignment of 0 bytes like 1-byte alignment.
-            if align == 0 {
-                return Ok(0);
-            }
-
-            let mut bytes = align;
-            let mut pow: u8 = 0;
-            while (bytes & 1) == 0 {
-                pow += 1;
-                bytes >>= 1;
-            }
-            if bytes != 1 {
-                Err(format!("`{}` is not a power of 2", align))
-            } else if pow > 30 {
-                Err(format!("`{}` is too large", align))
-            } else {
-                Ok(pow)
-            }
-        };
-
-        Ok(Align {
-            abi_pow2: log2(abi)?,
-            pref_pow2: log2(pref)?,
-        })
-    }
-
-    pub fn abi(self) -> u64 {
-        1 << self.abi_pow2
-    }
-
-    pub fn pref(self) -> u64 {
-        1 << self.pref_pow2
-    }
-
-    pub fn abi_bits(self) -> u64 {
-        self.abi() * 8
-    }
-
-    pub fn pref_bits(self) -> u64 {
-        self.pref() * 8
-    }
-
-    pub fn min(self, other: Align) -> Align {
-        Align {
-            abi_pow2: cmp::min(self.abi_pow2, other.abi_pow2),
-            pref_pow2: cmp::min(self.pref_pow2, other.pref_pow2),
-        }
-    }
-
-    pub fn max(self, other: Align) -> Align {
-        Align {
-            abi_pow2: cmp::max(self.abi_pow2, other.abi_pow2),
-            pref_pow2: cmp::max(self.pref_pow2, other.pref_pow2),
-        }
-    }
-}
-
-/// Integers, also used for enum discriminants.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-pub enum Integer {
-    I8,
-    I16,
-    I32,
-    I64,
-    I128,
+pub trait IntegerExt {
+    fn to_ty<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, signed: bool) -> Ty<'tcx>;
+    fn from_attr<C: HasDataLayout>(cx: C, ity: attr::IntType) -> Integer;
+    fn repr_discr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                  ty: Ty<'tcx>,
+                  repr: &ReprOptions,
+                  min: i128,
+                  max: i128)
+                  -> (Integer, bool);
 }
 
-impl<'a, 'tcx> Integer {
-    pub fn size(&self) -> Size {
-        match *self {
-            I8 => Size::from_bytes(1),
-            I16 => Size::from_bytes(2),
-            I32 => Size::from_bytes(4),
-            I64  => Size::from_bytes(8),
-            I128  => Size::from_bytes(16),
-        }
-    }
-
-    pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
-        let dl = cx.data_layout();
-
-        match *self {
-            I8 => dl.i8_align,
-            I16 => dl.i16_align,
-            I32 => dl.i32_align,
-            I64 => dl.i64_align,
-            I128 => dl.i128_align,
-        }
-    }
-
-    pub fn to_ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, signed: bool) -> Ty<'tcx> {
+impl IntegerExt for Integer {
+    fn to_ty<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, signed: bool) -> Ty<'tcx> {
         match (*self, signed) {
             (I8, false) => tcx.types.u8,
             (I16, false) => tcx.types.u16,
@@ -461,57 +54,8 @@ impl<'a, 'tcx> Integer {
         }
     }
 
-    /// Find the smallest Integer type which can represent the signed value.
-    pub fn fit_signed(x: i128) -> Integer {
-        match x {
-            -0x0000_0000_0000_0080...0x0000_0000_0000_007f => I8,
-            -0x0000_0000_0000_8000...0x0000_0000_0000_7fff => I16,
-            -0x0000_0000_8000_0000...0x0000_0000_7fff_ffff => I32,
-            -0x8000_0000_0000_0000...0x7fff_ffff_ffff_ffff => I64,
-            _ => I128
-        }
-    }
-
-    /// Find the smallest Integer type which can represent the unsigned value.
-    pub fn fit_unsigned(x: u128) -> Integer {
-        match x {
-            0...0x0000_0000_0000_00ff => I8,
-            0...0x0000_0000_0000_ffff => I16,
-            0...0x0000_0000_ffff_ffff => I32,
-            0...0xffff_ffff_ffff_ffff => I64,
-            _ => I128,
-        }
-    }
-
-    /// Find the smallest integer with the given alignment.
-    pub fn for_abi_align<C: HasDataLayout>(cx: C, align: Align) -> Option<Integer> {
-        let dl = cx.data_layout();
-
-        let wanted = align.abi();
-        for &candidate in &[I8, I16, I32, I64, I128] {
-            if wanted == candidate.align(dl).abi() && wanted == candidate.size().bytes() {
-                return Some(candidate);
-            }
-        }
-        None
-    }
-
-    /// Find the largest integer with the given alignment or less.
-    pub fn approximate_abi_align<C: HasDataLayout>(cx: C, align: Align) -> Integer {
-        let dl = cx.data_layout();
-
-        let wanted = align.abi();
-        // FIXME(eddyb) maybe include I128 in the future, when it works everywhere.
-        for &candidate in &[I64, I32, I16] {
-            if wanted >= candidate.align(dl).abi() && wanted >= candidate.size().bytes() {
-                return candidate;
-            }
-        }
-        I8
-    }
-
     /// Get the Integer type from an attr::IntType.
-    pub fn from_attr<C: HasDataLayout>(cx: C, ity: attr::IntType) -> Integer {
+    fn from_attr<C: HasDataLayout>(cx: C, ity: attr::IntType) -> Integer {
         let dl = cx.data_layout();
 
         match ity {
@@ -530,7 +74,7 @@ impl<'a, 'tcx> Integer {
     /// signed discriminant range and #[repr] attribute.
     /// N.B.: u128 values above i128::MAX will be treated as signed, but
     /// that shouldn't affect anything, other than maybe debuginfo.
-    fn repr_discr(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    fn repr_discr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                   ty: Ty<'tcx>,
                   repr: &ReprOptions,
                   min: i128,
@@ -578,46 +122,12 @@ impl<'a, 'tcx> Integer {
     }
 }
 
-/// Fundamental unit of memory access and layout.
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-pub enum Primitive {
-    /// The `bool` is the signedness of the `Integer` type.
-    ///
-    /// One would think we would not care about such details this low down,
-    /// but some ABIs are described in terms of C types and ISAs where the
-    /// integer arithmetic is done on {sign,zero}-extended registers, e.g.
-    /// a negative integer passed by zero-extension will appear positive in
-    /// the callee, and most operations on it will produce the wrong values.
-    Int(Integer, bool),
-    F32,
-    F64,
-    Pointer
+pub trait PrimitiveExt {
+    fn to_ty<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx>;
 }
 
-impl<'a, 'tcx> Primitive {
-    pub fn size<C: HasDataLayout>(self, cx: C) -> Size {
-        let dl = cx.data_layout();
-
-        match self {
-            Int(i, _) => i.size(),
-            F32 => Size::from_bits(32),
-            F64 => Size::from_bits(64),
-            Pointer => dl.pointer_size
-        }
-    }
-
-    pub fn align<C: HasDataLayout>(self, cx: C) -> Align {
-        let dl = cx.data_layout();
-
-        match self {
-            Int(i, _) => i.align(dl),
-            F32 => dl.f32_align,
-            F64 => dl.f64_align,
-            Pointer => dl.pointer_align
-        }
-    }
-
-    pub fn to_ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
+impl PrimitiveExt for Primitive {
+    fn to_ty<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
         match *self {
             Int(i, signed) => i.to_ty(tcx, signed),
             F32 => tcx.types.f32,
@@ -627,29 +137,6 @@ impl<'a, 'tcx> Primitive {
     }
 }
 
-/// Information about one scalar component of a Rust type.
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
-pub struct Scalar {
-    pub value: Primitive,
-
-    /// Inclusive wrap-around range of valid values, that is, if
-    /// min > max, it represents min..=u128::MAX followed by 0..=max.
-    // FIXME(eddyb) always use the shortest range, e.g. by finding
-    // the largest space between two consecutive valid values and
-    // taking everything else as the (shortest) valid range.
-    pub valid_range: RangeInclusive<u128>,
-}
-
-impl Scalar {
-    pub fn is_bool(&self) -> bool {
-        if let Int(I8, _) = self.value {
-            self.valid_range == (0..=1)
-        } else {
-            false
-        }
-    }
-}
-
 /// The first half of a fat pointer.
 ///
 /// - For a trait object, this is the address of the box.
@@ -662,183 +149,6 @@ pub const FAT_PTR_ADDR: usize = 0;
 /// - For a slice, this is the length.
 pub const FAT_PTR_EXTRA: usize = 1;
 
-/// Describes how the fields of a type are located in memory.
-#[derive(PartialEq, Eq, Hash, Debug)]
-pub enum FieldPlacement {
-    /// All fields start at no offset. The `usize` is the field count.
-    Union(usize),
-
-    /// Array/vector-like placement, with all fields of identical types.
-    Array {
-        stride: Size,
-        count: u64
-    },
-
-    /// Struct-like placement, with precomputed offsets.
-    ///
-    /// Fields are guaranteed to not overlap, but note that gaps
-    /// before, between and after all the fields are NOT always
-    /// padding, and as such their contents may not be discarded.
-    /// For example, enum variants leave a gap at the start,
-    /// where the discriminant field in the enum layout goes.
-    Arbitrary {
-        /// Offsets for the first byte of each field,
-        /// ordered to match the source definition order.
-        /// This vector does not go in increasing order.
-        // FIXME(eddyb) use small vector optimization for the common case.
-        offsets: Vec<Size>,
-
-        /// Maps source order field indices to memory order indices,
-        /// depending how fields were permuted.
-        // FIXME(camlorn) also consider small vector  optimization here.
-        memory_index: Vec<u32>
-    }
-}
-
-impl FieldPlacement {
-    pub fn count(&self) -> usize {
-        match *self {
-            FieldPlacement::Union(count) => count,
-            FieldPlacement::Array { count, .. } => {
-                let usize_count = count as usize;
-                assert_eq!(usize_count as u64, count);
-                usize_count
-            }
-            FieldPlacement::Arbitrary { ref offsets, .. } => offsets.len()
-        }
-    }
-
-    pub fn offset(&self, i: usize) -> Size {
-        match *self {
-            FieldPlacement::Union(_) => Size::from_bytes(0),
-            FieldPlacement::Array { stride, count } => {
-                let i = i as u64;
-                assert!(i < count);
-                stride * i
-            }
-            FieldPlacement::Arbitrary { ref offsets, .. } => offsets[i]
-        }
-    }
-
-    pub fn memory_index(&self, i: usize) -> usize {
-        match *self {
-            FieldPlacement::Union(_) |
-            FieldPlacement::Array { .. } => i,
-            FieldPlacement::Arbitrary { ref memory_index, .. } => {
-                let r = memory_index[i];
-                assert_eq!(r as usize as u32, r);
-                r as usize
-            }
-        }
-    }
-
-    /// Get source indices of the fields by increasing offsets.
-    #[inline]
-    pub fn index_by_increasing_offset<'a>(&'a self) -> impl iter::Iterator<Item=usize>+'a {
-        let mut inverse_small = [0u8; 64];
-        let mut inverse_big = vec![];
-        let use_small = self.count() <= inverse_small.len();
-
-        // We have to write this logic twice in order to keep the array small.
-        if let FieldPlacement::Arbitrary { ref memory_index, .. } = *self {
-            if use_small {
-                for i in 0..self.count() {
-                    inverse_small[memory_index[i] as usize] = i as u8;
-                }
-            } else {
-                inverse_big = vec![0; self.count()];
-                for i in 0..self.count() {
-                    inverse_big[memory_index[i] as usize] = i as u32;
-                }
-            }
-        }
-
-        (0..self.count()).map(move |i| {
-            match *self {
-                FieldPlacement::Union(_) |
-                FieldPlacement::Array { .. } => i,
-                FieldPlacement::Arbitrary { .. } => {
-                    if use_small { inverse_small[i] as usize }
-                    else { inverse_big[i] as usize }
-                }
-            }
-        })
-    }
-}
-
-/// Describes how values of the type are passed by target ABIs,
-/// in terms of categories of C types there are ABI rules for.
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
-pub enum Abi {
-    Uninhabited,
-    Scalar(Scalar),
-    ScalarPair(Scalar, Scalar),
-    Vector {
-        element: Scalar,
-        count: u64
-    },
-    Aggregate {
-        /// If true, the size is exact, otherwise it's only a lower bound.
-        sized: bool,
-    }
-}
-
-impl Abi {
-    /// Returns true if the layout corresponds to an unsized type.
-    pub fn is_unsized(&self) -> bool {
-        match *self {
-            Abi::Uninhabited |
-            Abi::Scalar(_) |
-            Abi::ScalarPair(..) |
-            Abi::Vector { .. } => false,
-            Abi::Aggregate { sized } => !sized
-        }
-    }
-
-    /// Returns true if this is a single signed integer scalar
-    pub fn is_signed(&self) -> bool {
-        match *self {
-            Abi::Scalar(ref scal) => match scal.value {
-                Primitive::Int(_, signed) => signed,
-                _ => false,
-            },
-            _ => false,
-        }
-    }
-}
-
-#[derive(PartialEq, Eq, Hash, Debug)]
-pub enum Variants {
-    /// Single enum variants, structs/tuples, unions, and all non-ADTs.
-    Single {
-        index: usize
-    },
-
-    /// General-case enums: for each case there is a struct, and they all have
-    /// all space reserved for the discriminant, and their first field starts
-    /// at a non-0 offset, after where the discriminant would go.
-    Tagged {
-        discr: Scalar,
-        variants: Vec<LayoutDetails>,
-    },
-
-    /// Multiple cases distinguished by a niche (values invalid for a type):
-    /// the variant `dataful_variant` contains a niche at an arbitrary
-    /// offset (field 0 of the enum), which for a variant with discriminant
-    /// `d` is set to `(d - niche_variants.start).wrapping_add(niche_start)`.
-    ///
-    /// For example, `Option<(usize, &T)>`  is represented such that
-    /// `None` has a null pointer for the second tuple field, and
-    /// `Some` is the identity function (with a non-null reference).
-    NicheFilling {
-        dataful_variant: usize,
-        niche_variants: RangeInclusive<usize>,
-        niche: Scalar,
-        niche_start: u128,
-        variants: Vec<LayoutDetails>,
-    }
-}
-
 #[derive(Copy, Clone, Debug)]
 pub enum LayoutError<'tcx> {
     Unknown(Ty<'tcx>),
@@ -858,40 +168,6 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
     }
 }
 
-#[derive(PartialEq, Eq, Hash, Debug)]
-pub struct LayoutDetails {
-    pub variants: Variants,
-    pub fields: FieldPlacement,
-    pub abi: Abi,
-    pub align: Align,
-    pub size: Size
-}
-
-impl LayoutDetails {
-    fn scalar<C: HasDataLayout>(cx: C, scalar: Scalar) -> Self {
-        let size = scalar.value.size(cx);
-        let align = scalar.value.align(cx);
-        LayoutDetails {
-            variants: Variants::Single { index: 0 },
-            fields: FieldPlacement::Union(0),
-            abi: Abi::Scalar(scalar),
-            size,
-            align,
-        }
-    }
-
-    fn uninhabited(field_count: usize) -> Self {
-        let align = Align::from_bytes(1, 1).unwrap();
-        LayoutDetails {
-            variants: Variants::Single { index: 0 },
-            fields: FieldPlacement::Union(field_count),
-            abi: Abi::Uninhabited,
-            align,
-            size: Size::from_bytes(0)
-        }
-    }
-}
-
 fn layout_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
                         -> Result<&'tcx LayoutDetails, LayoutError<'tcx>>
@@ -1525,9 +801,9 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
 
                     if let Some(i) = dataful_variant {
                         let count = (niche_variants.end - niche_variants.start + 1) as u128;
-                        for (field_index, field) in variants[i].iter().enumerate() {
+                        for (field_index, &field) in variants[i].iter().enumerate() {
                             let (offset, niche, niche_start) =
-                                match field.find_niche(self, count)? {
+                                match self.find_niche(field, count)? {
                                     Some(niche) => niche,
                                     None => continue
                                 };
@@ -2024,26 +1300,6 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> {
     }
 }
 
-/// The details of the layout of a type, alongside the type itself.
-/// Provides various type traversal APIs (e.g. recursing into fields).
-///
-/// Note that the details are NOT guaranteed to always be identical
-/// to those obtained from `layout_of(ty)`, as we need to produce
-/// layouts for which Rust types do not exist, such as enum variants
-/// or synthetic fields of enums (i.e. discriminants) and fat pointers.
-#[derive(Copy, Clone, Debug)]
-pub struct TyLayout<'tcx> {
-    pub ty: Ty<'tcx>,
-    details: &'tcx LayoutDetails
-}
-
-impl<'tcx> Deref for TyLayout<'tcx> {
-    type Target = &'tcx LayoutDetails;
-    fn deref(&self) -> &&'tcx LayoutDetails {
-        &self.details
-    }
-}
-
 pub trait HasTyCtxt<'tcx>: HasDataLayout {
     fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>;
 }
@@ -2095,13 +1351,10 @@ impl<T, E> MaybeResult<T> for Result<T, E> {
     }
 }
 
-pub trait LayoutOf<T> {
-    type TyLayout;
+pub type TyLayout<'tcx> = ::rustc_target::abi::TyLayout<'tcx, Ty<'tcx>>;
 
-    fn layout_of(self, ty: T) -> Self::TyLayout;
-}
-
-impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
+impl<'a, 'tcx> LayoutOf for LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
+    type Ty = Ty<'tcx>;
     type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>;
 
     /// Computes the layout of a type. Note that this implicitly
@@ -2127,7 +1380,8 @@ impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
     }
 }
 
-impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for LayoutCx<'tcx, ty::maps::TyCtxtAt<'a, 'tcx, 'tcx>> {
+impl<'a, 'tcx> LayoutOf for LayoutCx<'tcx, ty::maps::TyCtxtAt<'a, 'tcx, 'tcx>> {
+    type Ty = Ty<'tcx>;
     type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>;
 
     /// Computes the layout of a type. Note that this implicitly
@@ -2186,22 +1440,22 @@ impl<'a, 'tcx> ty::maps::TyCtxtAt<'a, 'tcx, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> TyLayout<'tcx> {
-    pub fn for_variant<C>(&self, cx: C, variant_index: usize) -> Self
-        where C: LayoutOf<Ty<'tcx>> + HasTyCtxt<'tcx>,
-              C::TyLayout: MaybeResult<TyLayout<'tcx>>
-    {
-        let details = match self.variants {
-            Variants::Single { index } if index == variant_index => self.details,
+impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
+    where C: LayoutOf<Ty = Ty<'tcx>> + HasTyCtxt<'tcx>,
+          C::TyLayout: MaybeResult<TyLayout<'tcx>>
+{
+    fn for_variant(this: TyLayout<'tcx>, cx: C, variant_index: usize) -> TyLayout<'tcx> {
+        let details = match this.variants {
+            Variants::Single { index } if index == variant_index => this.details,
 
             Variants::Single { index } => {
                 // Deny calling for_variant more than once for non-Single enums.
-                cx.layout_of(self.ty).map_same(|layout| {
+                cx.layout_of(this.ty).map_same(|layout| {
                     assert_eq!(layout.variants, Variants::Single { index });
                     layout
                 });
 
-                let fields = match self.ty.sty {
+                let fields = match this.ty.sty {
                     ty::TyAdt(def, _) => def.variants[variant_index].fields.len(),
                     _ => bug!()
                 };
@@ -2219,17 +1473,14 @@ impl<'a, 'tcx> TyLayout<'tcx> {
         assert_eq!(details.variants, Variants::Single { index: variant_index });
 
         TyLayout {
-            ty: self.ty,
+            ty: this.ty,
             details
         }
     }
 
-    pub fn field<C>(&self, cx: C, i: usize) -> C::TyLayout
-        where C: LayoutOf<Ty<'tcx>> + HasTyCtxt<'tcx>,
-              C::TyLayout: MaybeResult<TyLayout<'tcx>>
-    {
+    fn field(this: TyLayout<'tcx>, cx: C, i: usize) -> C::TyLayout {
         let tcx = cx.tcx();
-        cx.layout_of(match self.ty.sty {
+        cx.layout_of(match this.ty.sty {
             ty::TyBool |
             ty::TyChar |
             ty::TyInt(_) |
@@ -2241,7 +1492,7 @@ impl<'a, 'tcx> TyLayout<'tcx> {
             ty::TyGeneratorWitness(..) |
             ty::TyForeign(..) |
             ty::TyDynamic(..) => {
-                bug!("TyLayout::field_type({:?}): not applicable", self)
+                bug!("TyLayout::field_type({:?}): not applicable", this)
             }
 
             // Potentially-fat pointers.
@@ -2255,13 +1506,13 @@ impl<'a, 'tcx> TyLayout<'tcx> {
                 // as the `Abi` or `FieldPlacement` is checked by users.
                 if i == 0 {
                     let nil = tcx.mk_nil();
-                    let ptr_ty = if self.ty.is_unsafe_ptr() {
+                    let ptr_ty = if this.ty.is_unsafe_ptr() {
                         tcx.mk_mut_ptr(nil)
                     } else {
                         tcx.mk_mut_ref(tcx.types.re_static, nil)
                     };
                     return cx.layout_of(ptr_ty).map_same(|mut ptr_layout| {
-                        ptr_layout.ty = self.ty;
+                        ptr_layout.ty = this.ty;
                         ptr_layout
                     });
                 }
@@ -2274,7 +1525,7 @@ impl<'a, 'tcx> TyLayout<'tcx> {
                         // the correct number of vtables slots.
                         tcx.mk_imm_ref(tcx.types.re_static, tcx.mk_nil())
                     }
-                    _ => bug!("TyLayout::field_type({:?}): not applicable", self)
+                    _ => bug!("TyLayout::field_type({:?}): not applicable", this)
                 }
             }
 
@@ -2296,12 +1547,12 @@ impl<'a, 'tcx> TyLayout<'tcx> {
 
             // SIMD vector types.
             ty::TyAdt(def, ..) if def.repr.simd() => {
-                self.ty.simd_type(tcx)
+                this.ty.simd_type(tcx)
             }
 
             // ADTs.
             ty::TyAdt(def, substs) => {
-                match self.variants {
+                match this.variants {
                     Variants::Single { index } => {
                         def.variants[index].fields[i].ty(tcx, substs)
                     }
@@ -2321,45 +1572,25 @@ impl<'a, 'tcx> TyLayout<'tcx> {
 
             ty::TyProjection(_) | ty::TyAnon(..) | ty::TyParam(_) |
             ty::TyInfer(_) | ty::TyError => {
-                bug!("TyLayout::field_type: unexpected type `{}`", self.ty)
+                bug!("TyLayout::field_type: unexpected type `{}`", this.ty)
             }
         })
     }
+}
 
-    /// Returns true if the layout corresponds to an unsized type.
-    pub fn is_unsized(&self) -> bool {
-        self.abi.is_unsized()
-    }
-
-    /// Returns true if the type is a ZST and not unsized.
-    pub fn is_zst(&self) -> bool {
-        match self.abi {
-            Abi::Uninhabited => true,
-            Abi::Scalar(_) |
-            Abi::ScalarPair(..) |
-            Abi::Vector { .. } => false,
-            Abi::Aggregate { sized } => sized && self.size.bytes() == 0
-        }
-    }
-
-    pub fn size_and_align(&self) -> (Size, Align) {
-        (self.size, self.align)
-    }
-
+impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
     /// Find the offset of a niche leaf field, starting from
     /// the given type and recursing through aggregates, which
     /// has at least `count` consecutive invalid values.
     /// The tuple is `(offset, scalar, niche_value)`.
     // FIXME(eddyb) traverse already optimized enums.
-    fn find_niche<C>(&self, cx: C, count: u128)
+    fn find_niche(self, layout: TyLayout<'tcx>, count: u128)
         -> Result<Option<(Size, Scalar, u128)>, LayoutError<'tcx>>
-        where C: LayoutOf<Ty<'tcx>, TyLayout = Result<Self, LayoutError<'tcx>>> +
-                 HasTyCtxt<'tcx>
     {
         let scalar_component = |scalar: &Scalar, offset| {
             let Scalar { value, valid_range: ref v } = *scalar;
 
-            let bits = value.size(cx).bits();
+            let bits = value.size(self).bits();
             assert!(bits <= 128);
             let max_value = !0u128 >> (128 - bits);
 
@@ -2386,17 +1617,17 @@ impl<'a, 'tcx> TyLayout<'tcx> {
         // Locals variables which live across yields are stored
         // in the generator type as fields. These may be uninitialized
         // so we don't look for niches there.
-        if let ty::TyGenerator(..) = self.ty.sty {
+        if let ty::TyGenerator(..) = layout.ty.sty {
             return Ok(None);
         }
 
-        match self.abi {
+        match layout.abi {
             Abi::Scalar(ref scalar) => {
                 return Ok(scalar_component(scalar, Size::from_bytes(0)));
             }
             Abi::ScalarPair(ref a, ref b) => {
                 return Ok(scalar_component(a, Size::from_bytes(0)).or_else(|| {
-                    scalar_component(b, a.value.size(cx).abi_align(b.value.align(cx)))
+                    scalar_component(b, a.value.size(self).abi_align(b.value.align(self)))
                 }));
             }
             Abi::Vector { ref element, .. } => {
@@ -2406,22 +1637,22 @@ impl<'a, 'tcx> TyLayout<'tcx> {
         }
 
         // Perhaps one of the fields is non-zero, let's recurse and find out.
-        if let FieldPlacement::Union(_) = self.fields {
+        if let FieldPlacement::Union(_) = layout.fields {
             // Only Rust enums have safe-to-inspect fields
             // (a discriminant), other unions are unsafe.
-            if let Variants::Single { .. } = self.variants {
+            if let Variants::Single { .. } = layout.variants {
                 return Ok(None);
             }
         }
-        if let FieldPlacement::Array { .. } = self.fields {
-            if self.fields.count() > 0 {
-                return self.field(cx, 0)?.find_niche(cx, count);
+        if let FieldPlacement::Array { .. } = layout.fields {
+            if layout.fields.count() > 0 {
+                return self.find_niche(layout.field(self, 0)?, count);
             }
         }
-        for i in 0..self.fields.count() {
-            let r = self.field(cx, i)?.find_niche(cx, count)?;
+        for i in 0..layout.fields.count() {
+            let r = self.find_niche(layout.field(self, i)?, count)?;
             if let Some((offset, scalar, niche_value)) = r {
-                let offset = self.fields.offset(i) + offset;
+                let offset = layout.fields.offset(i) + offset;
                 return Ok(Some((offset, scalar, niche_value)));
             }
         }
@@ -2549,14 +1780,22 @@ impl_stable_hash_for!(enum ::ty::layout::Primitive {
     Pointer
 });
 
-impl_stable_hash_for!(struct ::ty::layout::Align {
-    abi_pow2,
-    pref_pow2
-});
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for Align {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hasher: &mut StableHasher<W>) {
+        self.abi().hash_stable(hcx, hasher);
+        self.pref().hash_stable(hcx, hasher);
+    }
+}
 
-impl_stable_hash_for!(struct ::ty::layout::Size {
-    raw
-});
+impl<'gcx> HashStable<StableHashingContext<'gcx>> for Size {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'gcx>,
+                                          hasher: &mut StableHasher<W>) {
+        self.bytes().hash_stable(hcx, hasher);
+    }
+}
 
 impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for LayoutError<'gcx>
 {
diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs
index 92d23d4338f..f5cb3643de8 100644
--- a/src/librustc/ty/maps/mod.rs
+++ b/src/librustc/ty/maps/mod.rs
@@ -45,7 +45,7 @@ use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet};
 use util::common::{profq_msg, ErrorReported, ProfileQueriesMsg};
 
 use rustc_data_structures::indexed_set::IdxSetBuf;
-use rustc_back::PanicStrategy;
+use rustc_target::spec::PanicStrategy;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stable_hasher::StableVec;
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 348cf03dd87..03ed6e7ac90 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -22,7 +22,7 @@ use mir::interpret::{GlobalId, Value, PrimVal};
 use util::common::ErrorReported;
 use std::rc::Rc;
 use std::iter;
-use syntax::abi;
+use rustc_target::spec::abi;
 use hir as ast;
 use rustc_data_structures::accumulate_vec::AccumulateVec;
 
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 199a46678c8..9b20fce6673 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -44,7 +44,7 @@ CloneTypeFoldableAndLiftImpls! {
     ::hir::MatchSource,
     ::hir::Mutability,
     ::hir::Unsafety,
-    ::syntax::abi::Abi,
+    ::rustc_target::spec::abi::Abi,
     ::mir::Local,
     ::mir::Promoted,
     ::traits::Reveal,
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 92e879a584b..0dfae13cc75 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -22,7 +22,7 @@ use util::captures::Captures;
 
 use std::iter;
 use std::cmp::Ordering;
-use syntax::abi;
+use rustc_target::spec::abi;
 use syntax::ast::{self, Name};
 use syntax::symbol::{keywords, InternedString};
 
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index b23e9124ddc..a10ca132472 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -22,7 +22,7 @@ use ty::fold::TypeVisitor;
 use ty::subst::UnpackedKind;
 use ty::maps::TyCtxtAt;
 use ty::TypeVariants::*;
-use ty::layout::Integer;
+use ty::layout::{Integer, IntegerExt};
 use util::common::ErrorReported;
 use middle::lang_items;
 use mir::interpret::{Value, PrimVal};
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index efe83252d0f..905776373bd 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -28,7 +28,7 @@ use std::fmt;
 use std::usize;
 
 use rustc_data_structures::indexed_vec::Idx;
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax::ast::CRATE_NODE_ID;
 use syntax::symbol::{Symbol, InternedString};
 use hir;
diff --git a/src/librustc_allocator/Cargo.toml b/src/librustc_allocator/Cargo.toml
index e3d1d8e32c4..765cb80f357 100644
--- a/src/librustc_allocator/Cargo.toml
+++ b/src/librustc_allocator/Cargo.toml
@@ -11,5 +11,6 @@ test = false
 [dependencies]
 rustc = { path = "../librustc" }
 rustc_errors = { path = "../librustc_errors" }
+rustc_target = { path = "../librustc_target" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_allocator/expand.rs b/src/librustc_allocator/expand.rs
index 9338d000c12..de8814d3d6a 100644
--- a/src/librustc_allocator/expand.rs
+++ b/src/librustc_allocator/expand.rs
@@ -10,7 +10,7 @@
 
 use rustc::middle::allocator::AllocatorKind;
 use rustc_errors;
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax::ast::{Attribute, Crate, LitKind, StrStyle};
 use syntax::ast::{Arg, Constness, Generics, Mac, Mutability, Ty, Unsafety};
 use syntax::ast::{self, Expr, Ident, Item, ItemKind, TyKind, VisibilityKind};
diff --git a/src/librustc_allocator/lib.rs b/src/librustc_allocator/lib.rs
index 969086815de..6595564fb30 100644
--- a/src/librustc_allocator/lib.rs
+++ b/src/librustc_allocator/lib.rs
@@ -12,6 +12,7 @@
 
 extern crate rustc;
 extern crate rustc_errors;
+extern crate rustc_target;
 extern crate syntax;
 extern crate syntax_pos;
 
diff --git a/src/librustc_back/README.md b/src/librustc_back/README.md
deleted file mode 100644
index 3c01692c12b..00000000000
--- a/src/librustc_back/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-`librustc_back` contains some very low-level details that are
-specific to different LLVM targets and so forth.
-
-For more information about how trans works, see the [rustc guide].
-
-[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trans.html
diff --git a/src/librustc_back/lib.rs b/src/librustc_back/lib.rs
deleted file mode 100644
index 027a9c45555..00000000000
--- a/src/librustc_back/lib.rs
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Some stuff used by rustc that doesn't have many dependencies
-//!
-//! Originally extracted from rustc::back, which was nominally the
-//! compiler 'backend', though LLVM is rustc's backend, so rustc_back
-//! is really just odds-and-ends relating to code gen and linking.
-//! This crate mostly exists to make rustc smaller, so we might put
-//! more 'stuff' here in the future.  It does not have a dependency on
-//! rustc_llvm.
-//!
-//! FIXME: Split this into two crates: one that has deps on syntax, and
-//! one that doesn't; the one that doesn't might get decent parallel
-//! build speedups.
-
-#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
-      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
-      html_root_url = "https://doc.rust-lang.org/nightly/")]
-
-#![feature(box_syntax)]
-#![feature(const_fn)]
-#![feature(fs_read_write)]
-
-extern crate syntax;
-extern crate rand;
-extern crate serialize;
-#[macro_use] extern crate log;
-
-extern crate serialize as rustc_serialize; // used by deriving
-
-pub mod target;
-
-use std::str::FromStr;
-
-use serialize::json::{Json, ToJson};
-
-#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash,
-         RustcEncodable, RustcDecodable)]
-pub enum LinkerFlavor {
-    Em,
-    Gcc,
-    Ld,
-    Msvc,
-    Lld(LldFlavor),
-}
-
-#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash,
-         RustcEncodable, RustcDecodable)]
-pub enum LldFlavor {
-    Wasm,
-    Ld64,
-    Ld,
-    Link,
-}
-
-impl ToJson for LinkerFlavor {
-    fn to_json(&self) -> Json {
-        self.desc().to_json()
-    }
-}
-macro_rules! flavor_mappings {
-    ($((($($flavor:tt)*), $string:expr),)*) => (
-        impl LinkerFlavor {
-            pub const fn one_of() -> &'static str {
-                concat!("one of: ", $($string, " ",)+)
-            }
-
-            pub fn from_str(s: &str) -> Option<Self> {
-                Some(match s {
-                    $($string => $($flavor)*,)+
-                    _ => return None,
-                })
-            }
-
-            pub fn desc(&self) -> &str {
-                match *self {
-                    $($($flavor)* => $string,)+
-                }
-            }
-        }
-    )
-}
-
-
-flavor_mappings! {
-    ((LinkerFlavor::Em), "em"),
-    ((LinkerFlavor::Gcc), "gcc"),
-    ((LinkerFlavor::Ld), "ld"),
-    ((LinkerFlavor::Msvc), "msvc"),
-    ((LinkerFlavor::Lld(LldFlavor::Wasm)), "wasm-ld"),
-    ((LinkerFlavor::Lld(LldFlavor::Ld64)), "ld64.lld"),
-    ((LinkerFlavor::Lld(LldFlavor::Ld)), "ld.lld"),
-    ((LinkerFlavor::Lld(LldFlavor::Link)), "lld-link"),
-}
-
-#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
-pub enum PanicStrategy {
-    Unwind,
-    Abort,
-}
-
-impl PanicStrategy {
-    pub fn desc(&self) -> &str {
-        match *self {
-            PanicStrategy::Unwind => "unwind",
-            PanicStrategy::Abort => "abort",
-        }
-    }
-}
-
-impl ToJson for PanicStrategy {
-    fn to_json(&self) -> Json {
-        match *self {
-            PanicStrategy::Abort => "abort".to_json(),
-            PanicStrategy::Unwind => "unwind".to_json(),
-        }
-    }
-}
-
-#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
-pub enum RelroLevel {
-    Full,
-    Partial,
-    Off,
-    None,
-}
-
-impl RelroLevel {
-    pub fn desc(&self) -> &str {
-        match *self {
-            RelroLevel::Full => "full",
-            RelroLevel::Partial => "partial",
-            RelroLevel::Off => "off",
-            RelroLevel::None => "none",
-        }
-    }
-}
-
-impl FromStr for RelroLevel {
-    type Err = ();
-
-    fn from_str(s: &str) -> Result<RelroLevel, ()> {
-        match s {
-            "full" => Ok(RelroLevel::Full),
-            "partial" => Ok(RelroLevel::Partial),
-            "off" => Ok(RelroLevel::Off),
-            "none" => Ok(RelroLevel::None),
-            _ => Err(()),
-        }
-    }
-}
-
-impl ToJson for RelroLevel {
-    fn to_json(&self) -> Json {
-        match *self {
-            RelroLevel::Full => "full".to_json(),
-            RelroLevel::Partial => "partial".to_json(),
-            RelroLevel::Off => "off".to_json(),
-            RelroLevel::None => "None".to_json(),
-        }
-    }
-}
diff --git a/src/librustc_cratesio_shim/Cargo.toml b/src/librustc_cratesio_shim/Cargo.toml
index 143f88e8f4b..342c7d1b678 100644
--- a/src/librustc_cratesio_shim/Cargo.toml
+++ b/src/librustc_cratesio_shim/Cargo.toml
@@ -21,3 +21,4 @@ crate-type = ["dylib"]
 
 [dependencies]
 bitflags = "1.0"
+log = "0.4"
diff --git a/src/librustc_cratesio_shim/src/lib.rs b/src/librustc_cratesio_shim/src/lib.rs
index 769b4f57206..85a5b331d8c 100644
--- a/src/librustc_cratesio_shim/src/lib.rs
+++ b/src/librustc_cratesio_shim/src/lib.rs
@@ -12,3 +12,4 @@
 #![allow(unused_extern_crates)]
 
 extern crate bitflags;
+extern crate log;
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index e1f0a74fc68..9178d0d00fa 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -11,6 +11,7 @@ crate-type = ["dylib"]
 [dependencies]
 ena = "0.9.1"
 log = "0.4"
+rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
 serialize = { path = "../libserialize" }
 cfg-if = "0.1.2"
 stable_deref_trait = "1.0.0"
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index ba1d73dc268..1320fe75bc5 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -45,6 +45,10 @@ extern crate parking_lot;
 extern crate cfg_if;
 extern crate stable_deref_trait;
 
+// See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
+#[allow(unused_extern_crates)]
+extern crate rustc_cratesio_shim;
+
 pub use rustc_serialize::hex::ToHex;
 
 pub mod array_vec;
diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml
index 3bff79ed3a6..5aae1bcad89 100644
--- a/src/librustc_driver/Cargo.toml
+++ b/src/librustc_driver/Cargo.toml
@@ -15,7 +15,7 @@ log = "0.4"
 env_logger = { version = "0.5", default-features = false }
 rustc = { path = "../librustc" }
 rustc_allocator = { path = "../librustc_allocator" }
-rustc_back = { path = "../librustc_back" }
+rustc_target = { path = "../librustc_target" }
 rustc_borrowck = { path = "../librustc_borrowck" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index fb333ec38fb..b203f387e46 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -35,7 +35,7 @@ extern crate env_logger;
 extern crate libc;
 extern crate rustc;
 extern crate rustc_allocator;
-extern crate rustc_back;
+extern crate rustc_target;
 extern crate rustc_borrowck;
 extern crate rustc_data_structures;
 extern crate rustc_errors as errors;
@@ -1021,7 +1021,7 @@ impl RustcDefaultCalls {
         for req in &sess.opts.prints {
             match *req {
                 TargetList => {
-                    let mut targets = rustc_back::target::get_targets().collect::<Vec<String>>();
+                    let mut targets = rustc_target::spec::get_targets().collect::<Vec<String>>();
                     targets.sort();
                     println!("{}", targets.join("\n"));
                 },
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 83501f45ec0..47c49fbe9ef 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -31,7 +31,7 @@ use rustc::session::config::{OutputFilenames, OutputTypes};
 use rustc_data_structures::sync::{self, Lrc};
 use syntax;
 use syntax::ast;
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax::codemap::{CodeMap, FilePathMapping, FileName};
 use errors;
 use errors::emitter::Emitter;
diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml
index 5ff891202db..f097095abe4 100644
--- a/src/librustc_lint/Cargo.toml
+++ b/src/librustc_lint/Cargo.toml
@@ -13,5 +13,6 @@ test = false
 log = "0.4"
 rustc = { path = "../librustc" }
 rustc_mir = { path = "../librustc_mir"}
+rustc_target = { path = "../librustc_target" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs
index 463ec4796e8..651a2e187f6 100644
--- a/src/librustc_lint/bad_style.rs
+++ b/src/librustc_lint/bad_style.rs
@@ -13,7 +13,7 @@ use rustc::ty;
 use lint::{LateContext, LintContext, LintArray};
 use lint::{LintPass, LateLintPass};
 
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax::ast;
 use syntax::attr;
 use syntax_pos::Span;
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 76991e3e52d..91ce6f3854a 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -1169,7 +1169,7 @@ impl LintPass for MutableTransmutes {
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
     fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) {
-        use syntax::abi::Abi::RustIntrinsic;
+        use rustc_target::spec::abi::Abi::RustIntrinsic;
 
         let msg = "mutating transmuted &mut T from &T may cause undefined behavior, \
                    consider instead using an UnsafeCell";
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 889c7d3e34e..65b340d6568 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -37,6 +37,7 @@ extern crate rustc;
 #[macro_use]
 extern crate log;
 extern crate rustc_mir;
+extern crate rustc_target;
 extern crate syntax_pos;
 
 use rustc::lint;
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 445fe0cc401..904a3e4c427 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -13,7 +13,7 @@
 use rustc::hir::map as hir_map;
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
-use rustc::ty::layout::{self, LayoutOf};
+use rustc::ty::layout::{self, IntegerExt, LayoutOf};
 use util::nodemap::FxHashSet;
 use lint::{LateContext, LintContext, LintArray};
 use lint::{LintPass, LateLintPass};
@@ -22,7 +22,7 @@ use std::cmp;
 use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
 
 use syntax::{ast, attr};
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax_pos::Span;
 use syntax::codemap;
 
diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml
index a2dcf7f3f83..338824d5efe 100644
--- a/src/librustc_metadata/Cargo.toml
+++ b/src/librustc_metadata/Cargo.toml
@@ -13,7 +13,7 @@ flate2 = "1.0"
 log = "0.4"
 proc_macro = { path = "../libproc_macro" }
 rustc = { path = "../librustc" }
-rustc_back = { path = "../librustc_back" }
+rustc_target = { path = "../librustc_target" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
 serialize = { path = "../libserialize" }
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index 8a18a4b5290..d0237071a60 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -21,8 +21,7 @@ use rustc::middle::allocator::AllocatorKind;
 use rustc::middle::cstore::DepKind;
 use rustc::session::{Session, CrateDisambiguator};
 use rustc::session::config::{Sanitizer, self};
-use rustc_back::PanicStrategy;
-use rustc_back::target::TargetTriple;
+use rustc_target::spec::{PanicStrategy, TargetTriple};
 use rustc::session::search_paths::PathKind;
 use rustc::middle;
 use rustc::middle::cstore::{validate_crate_name, ExternCrate, ExternCrateSource};
diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs
index 8765d9d8c2b..64bbcf436cb 100644
--- a/src/librustc_metadata/cstore.rs
+++ b/src/librustc_metadata/cstore.rs
@@ -18,7 +18,7 @@ use rustc::hir::map::definitions::DefPathTable;
 use rustc::hir::svh::Svh;
 use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader};
 use rustc::session::{Session, CrateDisambiguator};
-use rustc_back::PanicStrategy;
+use rustc_target::spec::PanicStrategy;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc::util::nodemap::{FxHashMap, NodeMap};
 
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index 9ecb3fd6cdd..a99e0a32e66 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -38,7 +38,7 @@ extern crate proc_macro;
 
 #[macro_use]
 extern crate rustc;
-extern crate rustc_back;
+extern crate rustc_target;
 #[macro_use]
 extern crate rustc_data_structures;
 
diff --git a/src/librustc_metadata/link_args.rs b/src/librustc_metadata/link_args.rs
index 6fafde0d09c..b699885b0eb 100644
--- a/src/librustc_metadata/link_args.rs
+++ b/src/librustc_metadata/link_args.rs
@@ -11,7 +11,7 @@
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::hir;
 use rustc::ty::TyCtxt;
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 
 pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Vec<String> {
     let mut collector = Collector {
diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs
index f553c55ae56..9b1b48efca5 100644
--- a/src/librustc_metadata/locator.rs
+++ b/src/librustc_metadata/locator.rs
@@ -236,7 +236,7 @@ use rustc::util::nodemap::FxHashMap;
 use errors::DiagnosticBuilder;
 use syntax::symbol::Symbol;
 use syntax_pos::Span;
-use rustc_back::target::{Target, TargetTriple};
+use rustc_target::spec::{Target, TargetTriple};
 
 use std::cmp;
 use std::collections::HashSet;
diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs
index 4bb6d8fb87c..70b8c7b11fd 100644
--- a/src/librustc_metadata/native_libs.rs
+++ b/src/librustc_metadata/native_libs.rs
@@ -14,7 +14,7 @@ use rustc::middle::cstore::{self, NativeLibrary};
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc::util::nodemap::FxHashSet;
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax::attr;
 use syntax::codemap::Span;
 use syntax::feature_gate::{self, GateIssue};
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index ddeb797f1be..c9949389ace 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -19,8 +19,7 @@ use rustc::middle::lang_items;
 use rustc::mir;
 use rustc::session::CrateDisambiguator;
 use rustc::ty::{self, Ty, ReprOptions};
-use rustc_back::PanicStrategy;
-use rustc_back::target::TargetTriple;
+use rustc_target::spec::{PanicStrategy, TargetTriple};
 
 use rustc_serialize as serialize;
 use syntax::{ast, attr};
diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml
index 90a0f18aba3..a1b348774b1 100644
--- a/src/librustc_mir/Cargo.toml
+++ b/src/librustc_mir/Cargo.toml
@@ -15,7 +15,7 @@ graphviz = { path = "../libgraphviz" }
 log = "0.4"
 log_settings = "0.1.1"
 rustc = { path = "../librustc" }
-rustc_back = { path = "../librustc_back" }
+rustc_target = { path = "../librustc_target" }
 rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index 28dc329e4fe..c130b4f550f 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -16,7 +16,7 @@ use hair::*;
 use rustc::ty;
 use rustc::mir::*;
 
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 
 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     /// Compile `expr`, storing the result into `destination`, which
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 9b0e4c64171..0d836f5cb97 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -20,12 +20,12 @@ use rustc::mir::visit::{MutVisitor, TyContext};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::Substs;
 use rustc::util::nodemap::NodeMap;
-use rustc_back::PanicStrategy;
+use rustc_target::spec::PanicStrategy;
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 use shim;
 use std::mem;
 use std::u32;
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax::ast;
 use syntax::attr::{self, UnwindAttr};
 use syntax::symbol::keywords;
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index d8d5f5073ab..e6aa2d3abb7 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -22,6 +22,7 @@ use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::middle::region;
 use rustc::infer::InferCtxt;
+use rustc::ty::layout::IntegerExt;
 use rustc::ty::subst::Subst;
 use rustc::ty::{self, Ty, TyCtxt, layout};
 use rustc::ty::subst::Substs;
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index b98ab218de5..42f0e38af1f 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -5,7 +5,7 @@ use rustc::hir::def::Def;
 use rustc::hir::map::definitions::DefPathData;
 use rustc::middle::const_val::{ConstVal, ErrKind};
 use rustc::mir;
-use rustc::ty::layout::{self, Size, Align, HasDataLayout, LayoutOf, TyLayout};
+use rustc::ty::layout::{self, Size, Align, HasDataLayout, IntegerExt, LayoutOf, TyLayout};
 use rustc::ty::subst::{Subst, Substs};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::maps::TyCtxtAt;
@@ -162,7 +162,8 @@ impl<'c, 'b, 'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> layout::HasTyCtxt<'tcx>
     }
 }
 
-impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf<Ty<'tcx>> for &'a EvalContext<'a, 'mir, 'tcx, M> {
+impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf for &'a EvalContext<'a, 'mir, 'tcx, M> {
+    type Ty = Ty<'tcx>;
     type TyLayout = EvalResult<'tcx, TyLayout<'tcx>>;
 
     fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
@@ -171,8 +172,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf<Ty<'tcx>> for &'a EvalCont
     }
 }
 
-impl<'c, 'b, 'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf<Ty<'tcx>>
+impl<'c, 'b, 'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf
     for &'c &'b mut EvalContext<'a, 'mir, 'tcx, M> {
+    type Ty = Ty<'tcx>;
     type TyLayout = EvalResult<'tcx, TyLayout<'tcx>>;
 
     #[inline]
diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs
index 3360e5b72a7..aa80ee7af18 100644
--- a/src/librustc_mir/interpret/terminator/mod.rs
+++ b/src/librustc_mir/interpret/terminator/mod.rs
@@ -2,7 +2,7 @@ use rustc::mir;
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::LayoutOf;
 use syntax::codemap::Span;
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 
 use rustc::mir::interpret::{EvalResult, PrimVal, Value};
 use super::{EvalContext, Place, Machine, ValTy};
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index a47b3cacc51..399892522a3 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -49,7 +49,7 @@ extern crate rustc_errors;
 #[macro_use]
 extern crate syntax;
 extern crate syntax_pos;
-extern crate rustc_back;
+extern crate rustc_target;
 extern crate rustc_const_math;
 extern crate core; // for NonZero
 extern crate log_settings;
diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs
index 181751f1777..9e0c977a3f0 100644
--- a/src/librustc_mir/monomorphize/item.rs
+++ b/src/librustc_mir/monomorphize/item.rs
@@ -339,7 +339,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
                 }
 
                 let abi = sig.abi();
-                if abi != ::syntax::abi::Abi::Rust {
+                if abi != ::rustc_target::spec::abi::Abi::Rust {
                     output.push_str("extern \"");
                     output.push_str(abi.name());
                     output.push_str("\" ");
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 6a0f42c6dbb..af60a83a4a2 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -20,7 +20,7 @@ use rustc::mir::interpret::{Value, PrimVal};
 
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax::ast;
 use syntax_pos::Span;
 
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index a3d96f0c073..47b2f430bc7 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -72,7 +72,8 @@ struct ConstPropagator<'b, 'a, 'tcx:'a+'b> {
     param_env: ParamEnv<'tcx>,
 }
 
-impl<'a, 'b, 'tcx> LayoutOf<ty::Ty<'tcx>> for &'a ConstPropagator<'a, 'b, 'tcx> {
+impl<'a, 'b, 'tcx> LayoutOf for &'a ConstPropagator<'a, 'b, 'tcx> {
+    type Ty = ty::Ty<'tcx>;
     type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>;
 
     fn layout_of(self, ty: ty::Ty<'tcx>) -> Self::TyLayout {
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 2dd805ccf9b..2b491385d66 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -28,7 +28,7 @@ use transform::{MirPass, MirSource};
 use super::simplify::{remove_dead_blocks, CfgSimplifier};
 
 use syntax::{attr};
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 
 const DEFAULT_THRESHOLD: usize = 50;
 const HINT_THRESHOLD: usize = 100;
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 591732fbba9..ff7551ed6f4 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -29,7 +29,7 @@ use rustc::mir::*;
 use rustc::mir::traversal::ReversePostorder;
 use rustc::mir::visit::{PlaceContext, Visitor};
 use rustc::middle::lang_items;
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax::attr;
 use syntax::ast::LitKind;
 use syntax::feature_gate::UnstableFeatures;
diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs
index 45e7a0d3f4c..8f67b9e7c3d 100644
--- a/src/librustc_mir/transform/rustc_peek.rs
+++ b/src/librustc_mir/transform/rustc_peek.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use syntax::abi::{Abi};
+use rustc_target::spec::abi::{Abi};
 use syntax::ast;
 use syntax_pos::Span;
 
diff --git a/src/librustc_save_analysis/Cargo.toml b/src/librustc_save_analysis/Cargo.toml
index 005faa55b58..976614c9542 100644
--- a/src/librustc_save_analysis/Cargo.toml
+++ b/src/librustc_save_analysis/Cargo.toml
@@ -12,6 +12,7 @@ crate-type = ["dylib"]
 log = "0.4"
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_target = { path = "../librustc_target" }
 rustc_typeck = { path = "../librustc_typeck" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 6a747decbd3..401a280412a 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -22,6 +22,7 @@ extern crate rustc;
 extern crate log;
 extern crate rustc_data_structures;
 extern crate rustc_serialize;
+extern crate rustc_target;
 extern crate rustc_typeck;
 #[macro_use]
 extern crate syntax;
diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs
index a9df898efb6..829ed320d75 100644
--- a/src/librustc_save_analysis/sig.rs
+++ b/src/librustc_save_analysis/sig.rs
@@ -237,7 +237,7 @@ impl Sig for ast::Ty {
                 if f.unsafety == ast::Unsafety::Unsafe {
                     text.push_str("unsafe ");
                 }
-                if f.abi != ::syntax::abi::Abi::Rust {
+                if f.abi != ::rustc_target::spec::abi::Abi::Rust {
                     text.push_str("extern");
                     text.push_str(&f.abi.to_string());
                     text.push(' ');
@@ -388,7 +388,7 @@ impl Sig for ast::Item {
                 if unsafety == ast::Unsafety::Unsafe {
                     text.push_str("unsafe ");
                 }
-                if abi != ::syntax::abi::Abi::Rust {
+                if abi != ::rustc_target::spec::abi::Abi::Rust {
                     text.push_str("extern");
                     text.push_str(&abi.to_string());
                     text.push(' ');
@@ -931,7 +931,7 @@ fn make_method_signature(
     if m.unsafety == ast::Unsafety::Unsafe {
         text.push_str("unsafe ");
     }
-    if m.abi != ::syntax::abi::Abi::Rust {
+    if m.abi != ::rustc_target::spec::abi::Abi::Rust {
         text.push_str("extern");
         text.push_str(&m.abi.to_string());
         text.push(' ');
diff --git a/src/librustc_back/Cargo.toml b/src/librustc_target/Cargo.toml
index 4c5b1417a2f..bb686e914a0 100644
--- a/src/librustc_back/Cargo.toml
+++ b/src/librustc_target/Cargo.toml
@@ -1,18 +1,18 @@
 [package]
 authors = ["The Rust Project Developers"]
-name = "rustc_back"
+name = "rustc_target"
 version = "0.0.0"
 
 [lib]
-name = "rustc_back"
+name = "rustc_target"
 path = "lib.rs"
 crate-type = ["dylib"]
 
 [dependencies]
-syntax = { path = "../libsyntax" }
-serialize = { path = "../libserialize" }
+bitflags = "1.0"
 log = "0.4"
-rand = "0.4"
+rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
+serialize = { path = "../libserialize" }
 
 [features]
 jemalloc = []
diff --git a/src/librustc_target/README.md b/src/librustc_target/README.md
new file mode 100644
index 00000000000..f5b1acb1921
--- /dev/null
+++ b/src/librustc_target/README.md
@@ -0,0 +1,6 @@
+`librustc_target` contains some very low-level details that are
+specific to different compilation targets and so forth.
+
+For more information about how rustc works, see the [rustc guide].
+
+[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/
diff --git a/src/librustc_trans/cabi_aarch64.rs b/src/librustc_target/abi/call/aarch64.rs
index 72ae1449de0..90b5b97b51e 100644
--- a/src/librustc_trans/cabi_aarch64.rs
+++ b/src/librustc_target/abi/call/aarch64.rs
@@ -8,11 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use abi::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform};
-use context::CodegenCx;
+use abi::call::{FnType, ArgType, Reg, RegKind, Uniform};
+use abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
 
-fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
-                                     -> Option<Uniform> {
+fn is_homogeneous_aggregate<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>)
+                                     -> Option<Uniform>
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
         let size = arg.layout.size;
 
@@ -38,7 +41,10 @@ fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgTyp
     })
 }
 
-fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
+fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<'a, Ty>)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(32);
         return;
@@ -69,7 +75,10 @@ fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>)
     ret.make_indirect();
 }
 
-fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
+fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     if !arg.layout.is_aggregate() {
         arg.extend_integer_width_to(32);
         return;
@@ -100,7 +109,10 @@ fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
     arg.make_indirect();
 }
 
-pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     if !fty.ret.is_ignore() {
         classify_ret_ty(cx, &mut fty.ret);
     }
diff --git a/src/librustc_trans/cabi_arm.rs b/src/librustc_target/abi/call/arm.rs
index b6cf16cb8d5..249aad2d937 100644
--- a/src/librustc_trans/cabi_arm.rs
+++ b/src/librustc_target/abi/call/arm.rs
@@ -8,12 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use abi::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform};
-use context::CodegenCx;
-use llvm::CallConv;
+use abi::call::{Conv, FnType, ArgType, Reg, RegKind, Uniform};
+use abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
+use spec::HasTargetSpec;
 
-fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
-                                     -> Option<Uniform> {
+fn is_homogeneous_aggregate<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>)
+                                     -> Option<Uniform>
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
         let size = arg.layout.size;
 
@@ -39,7 +42,10 @@ fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgTyp
     })
 }
 
-fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>, vfp: bool) {
+fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<'a, Ty>, vfp: bool)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(32);
         return;
@@ -71,7 +77,10 @@ fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>,
     ret.make_indirect();
 }
 
-fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>, vfp: bool) {
+fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>, vfp: bool)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     if !arg.layout.is_aggregate() {
         arg.extend_integer_width_to(32);
         return;
@@ -92,11 +101,14 @@ fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>,
     });
 }
 
-pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout + HasTargetSpec
+{
     // If this is a target with a hard-float ABI, and the function is not explicitly
     // `extern "aapcs"`, then we must use the VFP registers for homogeneous aggregates.
-    let vfp = cx.sess().target.target.llvm_target.ends_with("hf")
-        && fty.cconv != CallConv::ArmAapcsCallConv
+    let vfp = cx.target_spec().llvm_target.ends_with("hf")
+        && fty.conv != Conv::ArmAapcs
         && !fty.variadic;
 
     if !fty.ret.is_ignore() {
diff --git a/src/librustc_trans/cabi_asmjs.rs b/src/librustc_target/abi/call/asmjs.rs
index b182f833dd6..81d6f7b134b 100644
--- a/src/librustc_trans/cabi_asmjs.rs
+++ b/src/librustc_target/abi/call/asmjs.rs
@@ -8,15 +8,18 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use abi::{FnType, ArgType, LayoutExt, Uniform};
-use context::CodegenCx;
+use abi::call::{FnType, ArgType, Uniform};
+use abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
 
 // Data layout: e-p:32:32-i64:64-v128:32:128-n32-S128
 
 // See the https://github.com/kripken/emscripten-fastcomp-clang repository.
 // The class `EmscriptenABIInfo` in `/lib/CodeGen/TargetInfo.cpp` contains the ABI definitions.
 
-fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
+fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<'a, Ty>)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     if ret.layout.is_aggregate() {
         if let Some(unit) = ret.layout.homogeneous_aggregate(cx) {
             let size = ret.layout.size;
@@ -33,13 +36,16 @@ fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>)
     }
 }
 
-fn classify_arg_ty(arg: &mut ArgType) {
+fn classify_arg_ty<Ty>(arg: &mut ArgType<Ty>) {
     if arg.layout.is_aggregate() {
         arg.make_indirect_byval();
     }
 }
 
-pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     if !fty.ret.is_ignore() {
         classify_ret_ty(cx, &mut fty.ret);
     }
diff --git a/src/librustc_trans/cabi_hexagon.rs b/src/librustc_target/abi/call/hexagon.rs
index 7e7e483fea0..d37d5584591 100644
--- a/src/librustc_trans/cabi_hexagon.rs
+++ b/src/librustc_target/abi/call/hexagon.rs
@@ -10,9 +10,9 @@
 
 #![allow(non_upper_case_globals)]
 
-use abi::{FnType, ArgType, LayoutExt};
+use abi::call::{FnType, ArgType};
 
-fn classify_ret_ty(ret: &mut ArgType) {
+fn classify_ret_ty<Ty>(ret: &mut ArgType<Ty>) {
     if ret.layout.is_aggregate() && ret.layout.size.bits() > 64 {
         ret.make_indirect();
     } else {
@@ -20,7 +20,7 @@ fn classify_ret_ty(ret: &mut ArgType) {
     }
 }
 
-fn classify_arg_ty(arg: &mut ArgType) {
+fn classify_arg_ty<Ty>(arg: &mut ArgType<Ty>) {
     if arg.layout.is_aggregate() && arg.layout.size.bits() > 64 {
         arg.make_indirect();
     } else {
@@ -28,7 +28,7 @@ fn classify_arg_ty(arg: &mut ArgType) {
     }
 }
 
-pub fn compute_abi_info(fty: &mut FnType) {
+pub fn compute_abi_info<Ty>(fty: &mut FnType<Ty>) {
     if !fty.ret.is_ignore() {
         classify_ret_ty(&mut fty.ret);
     }
diff --git a/src/librustc_trans/cabi_mips.rs b/src/librustc_target/abi/call/mips.rs
index cd567f517fe..5001499ea5d 100644
--- a/src/librustc_trans/cabi_mips.rs
+++ b/src/librustc_target/abi/call/mips.rs
@@ -8,24 +8,24 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use abi::{ArgType, FnType, LayoutExt, Reg, Uniform};
-use context::CodegenCx;
+use abi::call::{ArgType, FnType, Reg, Uniform};
+use abi::{HasDataLayout, LayoutOf, Size, TyLayoutMethods};
 
-use rustc::ty::layout::Size;
-
-fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                             ret: &mut ArgType<'tcx>,
-                             offset: &mut Size) {
+fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<Ty>, offset: &mut Size)
+    where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout
+{
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(32);
     } else {
         ret.make_indirect();
-        *offset += cx.tcx.data_layout.pointer_size;
+        *offset += cx.data_layout().pointer_size;
     }
 }
 
-fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
-    let dl = &cx.tcx.data_layout;
+fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<Ty>, offset: &mut Size)
+    where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout
+{
+    let dl = cx.data_layout();
     let size = arg.layout.size;
     let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align);
 
@@ -44,7 +44,9 @@ fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
     *offset = offset.abi_align(align) + size.abi_align(align);
 }
 
-pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<Ty>)
+    where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout
+{
     let mut offset = Size::from_bytes(0);
     if !fty.ret.is_ignore() {
         classify_ret_ty(cx, &mut fty.ret, &mut offset);
diff --git a/src/librustc_trans/cabi_mips64.rs b/src/librustc_target/abi/call/mips64.rs
index 231fe4c6edb..e5cbc6424a4 100644
--- a/src/librustc_trans/cabi_mips64.rs
+++ b/src/librustc_target/abi/call/mips64.rs
@@ -8,14 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use abi::{ArgAttribute, ArgType, CastTarget, FnType, LayoutExt, PassMode, Reg, RegKind, Uniform};
-use context::CodegenCx;
-use rustc::ty::layout::{self, Size};
+use abi::call::{ArgAttribute, ArgType, CastTarget, FnType, PassMode, Reg, RegKind, Uniform};
+use abi::{self, HasDataLayout, LayoutOf, Size, TyLayout, TyLayoutMethods};
 
-fn extend_integer_width_mips(arg: &mut ArgType, bits: u64) {
+fn extend_integer_width_mips<Ty>(arg: &mut ArgType<Ty>, bits: u64) {
     // Always sign extend u32 values on 64-bit mips
-    if let layout::Abi::Scalar(ref scalar) = arg.layout.abi {
-        if let layout::Int(i, signed) = scalar.value {
+    if let abi::Abi::Scalar(ref scalar) = arg.layout.abi {
+        if let abi::Int(i, signed) = scalar.value {
             if !signed && i.size().bits() == 32 {
                 if let PassMode::Direct(ref mut attrs) = arg.mode {
                     attrs.set(ArgAttribute::SExt);
@@ -28,18 +27,24 @@ fn extend_integer_width_mips(arg: &mut ArgType, bits: u64) {
     arg.extend_integer_width_to(bits);
 }
 
-fn float_reg<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &ArgType<'tcx>, i: usize) -> Option<Reg> {
+fn float_reg<'a, Ty, C>(cx: C, ret: &ArgType<'a, Ty>, i: usize) -> Option<Reg>
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     match ret.layout.field(cx, i).abi {
-        layout::Abi::Scalar(ref scalar) => match scalar.value {
-            layout::F32 => Some(Reg::f32()),
-            layout::F64 => Some(Reg::f64()),
+        abi::Abi::Scalar(ref scalar) => match scalar.value {
+            abi::F32 => Some(Reg::f32()),
+            abi::F64 => Some(Reg::f64()),
             _ => None
         },
         _ => None
     }
 }
 
-fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
+fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<'a, Ty>)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     if !ret.layout.is_aggregate() {
         extend_integer_width_mips(ret, 64);
         return;
@@ -52,7 +57,7 @@ fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>)
         // use of float registers to structures (not unions) containing exactly one or two
         // float fields.
 
-        if let layout::FieldPlacement::Arbitrary { .. } = ret.layout.fields {
+        if let abi::FieldPlacement::Arbitrary { .. } = ret.layout.fields {
             if ret.layout.fields.count() == 1 {
                 if let Some(reg) = float_reg(cx, ret, 0) {
                     ret.cast_to(reg);
@@ -78,27 +83,30 @@ fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>)
     }
 }
 
-fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
+fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     if !arg.layout.is_aggregate() {
         extend_integer_width_mips(arg, 64);
         return;
     }
 
-    let dl = &cx.tcx.data_layout;
+    let dl = cx.data_layout();
     let size = arg.layout.size;
     let mut prefix = [None; 8];
     let mut prefix_index = 0;
 
     match arg.layout.fields {
-        layout::FieldPlacement::Array { .. } => {
+        abi::FieldPlacement::Array { .. } => {
             // Arrays are passed indirectly
             arg.make_indirect();
             return;
         }
-        layout::FieldPlacement::Union(_) => {
+        abi::FieldPlacement::Union(_) => {
             // Unions and are always treated as a series of 64-bit integer chunks
         },
-        layout::FieldPlacement::Arbitrary { .. } => {
+        abi::FieldPlacement::Arbitrary { .. } => {
             // Structures are split up into a series of 64-bit integer chunks, but any aligned
             // doubles not part of another aggregate are passed as floats.
             let mut last_offset = Size::from_bytes(0);
@@ -108,8 +116,8 @@ fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
                 let offset = arg.layout.fields.offset(i);
 
                 // We only care about aligned doubles
-                if let layout::Abi::Scalar(ref scalar) = field.abi {
-                    if let layout::F64 = scalar.value {
+                if let abi::Abi::Scalar(ref scalar) = field.abi {
+                    if let abi::F64 = scalar.value {
                         if offset.is_abi_aligned(dl.f64_align) {
                             // Insert enough integers to cover [last_offset, offset)
                             assert!(last_offset.is_abi_aligned(dl.f64_align));
@@ -143,7 +151,10 @@ fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
     });
 }
 
-pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     if !fty.ret.is_ignore() {
         classify_ret_ty(cx, &mut fty.ret);
     }
diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs
new file mode 100644
index 00000000000..2d8996bb5ae
--- /dev/null
+++ b/src/librustc_target/abi/call/mod.rs
@@ -0,0 +1,511 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use abi::{self, Abi, Align, FieldPlacement, Size};
+use abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
+use spec::HasTargetSpec;
+
+mod aarch64;
+mod arm;
+mod asmjs;
+mod hexagon;
+mod mips;
+mod mips64;
+mod msp430;
+mod nvptx;
+mod nvptx64;
+mod powerpc;
+mod powerpc64;
+mod s390x;
+mod sparc;
+mod sparc64;
+mod x86;
+mod x86_64;
+mod x86_win64;
+mod wasm32;
+
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+pub enum PassMode {
+    /// Ignore the argument (useful for empty struct).
+    Ignore,
+    /// Pass the argument directly.
+    Direct(ArgAttributes),
+    /// Pass a pair's elements directly in two arguments.
+    Pair(ArgAttributes, ArgAttributes),
+    /// Pass the argument after casting it, to either
+    /// a single uniform or a pair of registers.
+    Cast(CastTarget),
+    /// Pass the argument indirectly via a hidden pointer.
+    Indirect(ArgAttributes),
+}
+
+// Hack to disable non_upper_case_globals only for the bitflags! and not for the rest
+// of this module
+pub use self::attr_impl::ArgAttribute;
+
+#[allow(non_upper_case_globals)]
+#[allow(unused)]
+mod attr_impl {
+    // The subset of llvm::Attribute needed for arguments, packed into a bitfield.
+    bitflags! {
+        #[derive(Default)]
+        pub struct ArgAttribute: u16 {
+            const ByVal     = 1 << 0;
+            const NoAlias   = 1 << 1;
+            const NoCapture = 1 << 2;
+            const NonNull   = 1 << 3;
+            const ReadOnly  = 1 << 4;
+            const SExt      = 1 << 5;
+            const StructRet = 1 << 6;
+            const ZExt      = 1 << 7;
+            const InReg     = 1 << 8;
+        }
+    }
+}
+
+/// A compact representation of LLVM attributes (at least those relevant for this module)
+/// that can be manipulated without interacting with LLVM's Attribute machinery.
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub struct ArgAttributes {
+    pub regular: ArgAttribute,
+    pub pointee_size: Size,
+    pub pointee_align: Option<Align>
+}
+
+impl ArgAttributes {
+    pub fn new() -> Self {
+        ArgAttributes {
+            regular: ArgAttribute::default(),
+            pointee_size: Size::from_bytes(0),
+            pointee_align: None,
+        }
+    }
+
+    pub fn set(&mut self, attr: ArgAttribute) -> &mut Self {
+        self.regular = self.regular | attr;
+        self
+    }
+
+    pub fn contains(&self, attr: ArgAttribute) -> bool {
+        self.regular.contains(attr)
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum RegKind {
+    Integer,
+    Float,
+    Vector
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub struct Reg {
+    pub kind: RegKind,
+    pub size: Size,
+}
+
+macro_rules! reg_ctor {
+    ($name:ident, $kind:ident, $bits:expr) => {
+        pub fn $name() -> Reg {
+            Reg {
+                kind: RegKind::$kind,
+                size: Size::from_bits($bits)
+            }
+        }
+    }
+}
+
+impl Reg {
+    reg_ctor!(i8, Integer, 8);
+    reg_ctor!(i16, Integer, 16);
+    reg_ctor!(i32, Integer, 32);
+    reg_ctor!(i64, Integer, 64);
+
+    reg_ctor!(f32, Float, 32);
+    reg_ctor!(f64, Float, 64);
+}
+
+impl Reg {
+    pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
+        let dl = cx.data_layout();
+        match self.kind {
+            RegKind::Integer => {
+                match self.size.bits() {
+                    1 => dl.i1_align,
+                    2...8 => dl.i8_align,
+                    9...16 => dl.i16_align,
+                    17...32 => dl.i32_align,
+                    33...64 => dl.i64_align,
+                    65...128 => dl.i128_align,
+                    _ => panic!("unsupported integer: {:?}", self)
+                }
+            }
+            RegKind::Float => {
+                match self.size.bits() {
+                    32 => dl.f32_align,
+                    64 => dl.f64_align,
+                    _ => panic!("unsupported float: {:?}", self)
+                }
+            }
+            RegKind::Vector => dl.vector_align(self.size)
+        }
+    }
+}
+
+/// An argument passed entirely registers with the
+/// same kind (e.g. HFA / HVA on PPC64 and AArch64).
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+pub struct Uniform {
+    pub unit: Reg,
+
+    /// The total size of the argument, which can be:
+    /// * equal to `unit.size` (one scalar/vector)
+    /// * a multiple of `unit.size` (an array of scalar/vectors)
+    /// * if `unit.kind` is `Integer`, the last element
+    ///   can be shorter, i.e. `{ i64, i64, i32 }` for
+    ///   64-bit integers with a total size of 20 bytes
+    pub total: Size,
+}
+
+impl From<Reg> for Uniform {
+    fn from(unit: Reg) -> Uniform {
+        Uniform {
+            unit,
+            total: unit.size
+        }
+    }
+}
+
+impl Uniform {
+    pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
+        self.unit.align(cx)
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+pub struct CastTarget {
+    pub prefix: [Option<RegKind>; 8],
+    pub prefix_chunk: Size,
+    pub rest: Uniform,
+}
+
+impl From<Reg> for CastTarget {
+    fn from(unit: Reg) -> CastTarget {
+        CastTarget::from(Uniform::from(unit))
+    }
+}
+
+impl From<Uniform> for CastTarget {
+    fn from(uniform: Uniform) -> CastTarget {
+        CastTarget {
+            prefix: [None; 8],
+            prefix_chunk: Size::from_bytes(0),
+            rest: uniform
+        }
+    }
+}
+
+impl CastTarget {
+    pub fn pair(a: Reg, b: Reg) -> CastTarget {
+        CastTarget {
+            prefix: [Some(a.kind), None, None, None, None, None, None, None],
+            prefix_chunk: a.size,
+            rest: Uniform::from(b)
+        }
+    }
+
+    pub fn size<C: HasDataLayout>(&self, cx: C) -> Size {
+        (self.prefix_chunk * self.prefix.iter().filter(|x| x.is_some()).count() as u64)
+             .abi_align(self.rest.align(cx)) + self.rest.total
+    }
+
+    pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
+        self.prefix.iter()
+            .filter_map(|x| x.map(|kind| Reg { kind: kind, size: self.prefix_chunk }.align(cx)))
+            .fold(cx.data_layout().aggregate_align.max(self.rest.align(cx)),
+                |acc, align| acc.max(align))
+    }
+}
+
+impl<'a, Ty> TyLayout<'a, Ty> {
+    fn is_aggregate(&self) -> bool {
+        match self.abi {
+            Abi::Uninhabited |
+            Abi::Scalar(_) |
+            Abi::Vector { .. } => false,
+            Abi::ScalarPair(..) |
+            Abi::Aggregate { .. } => true
+        }
+    }
+
+    fn homogeneous_aggregate<C>(&self, cx: C) -> Option<Reg>
+        where Ty: TyLayoutMethods<'a, C> + Copy, C: LayoutOf<Ty = Ty, TyLayout = Self> + Copy
+    {
+        match self.abi {
+            Abi::Uninhabited => None,
+
+            // The primitive for this algorithm.
+            Abi::Scalar(ref scalar) => {
+                let kind = match scalar.value {
+                    abi::Int(..) |
+                    abi::Pointer => RegKind::Integer,
+                    abi::F32 |
+                    abi::F64 => RegKind::Float
+                };
+                Some(Reg {
+                    kind,
+                    size: self.size
+                })
+            }
+
+            Abi::Vector { .. } => {
+                Some(Reg {
+                    kind: RegKind::Vector,
+                    size: self.size
+                })
+            }
+
+            Abi::ScalarPair(..) |
+            Abi::Aggregate { .. } => {
+                let mut total = Size::from_bytes(0);
+                let mut result = None;
+
+                let is_union = match self.fields {
+                    FieldPlacement::Array { count, .. } => {
+                        if count > 0 {
+                            return self.field(cx, 0).homogeneous_aggregate(cx);
+                        } else {
+                            return None;
+                        }
+                    }
+                    FieldPlacement::Union(_) => true,
+                    FieldPlacement::Arbitrary { .. } => false
+                };
+
+                for i in 0..self.fields.count() {
+                    if !is_union && total != self.fields.offset(i) {
+                        return None;
+                    }
+
+                    let field = self.field(cx, i);
+                    match (result, field.homogeneous_aggregate(cx)) {
+                        // The field itself must be a homogeneous aggregate.
+                        (_, None) => return None,
+                        // If this is the first field, record the unit.
+                        (None, Some(unit)) => {
+                            result = Some(unit);
+                        }
+                        // For all following fields, the unit must be the same.
+                        (Some(prev_unit), Some(unit)) => {
+                            if prev_unit != unit {
+                                return None;
+                            }
+                        }
+                    }
+
+                    // Keep track of the offset (without padding).
+                    let size = field.size;
+                    if is_union {
+                        total = total.max(size);
+                    } else {
+                        total += size;
+                    }
+                }
+
+                // There needs to be no padding.
+                if total != self.size {
+                    None
+                } else {
+                    result
+                }
+            }
+        }
+    }
+}
+
+/// Information about how to pass an argument to,
+/// or return a value from, a function, under some ABI.
+#[derive(Debug)]
+pub struct ArgType<'a, Ty> {
+    pub layout: TyLayout<'a, Ty>,
+
+    /// Dummy argument, which is emitted before the real argument.
+    pub pad: Option<Reg>,
+
+    pub mode: PassMode,
+}
+
+impl<'a, Ty> ArgType<'a, Ty> {
+    pub fn new(layout: TyLayout<'a, Ty>) -> Self {
+        ArgType {
+            layout,
+            pad: None,
+            mode: PassMode::Direct(ArgAttributes::new()),
+        }
+    }
+
+    pub fn make_indirect(&mut self) {
+        assert_eq!(self.mode, PassMode::Direct(ArgAttributes::new()));
+
+        // Start with fresh attributes for the pointer.
+        let mut attrs = ArgAttributes::new();
+
+        // For non-immediate arguments the callee gets its own copy of
+        // the value on the stack, so there are no aliases. It's also
+        // program-invisible so can't possibly capture
+        attrs.set(ArgAttribute::NoAlias)
+             .set(ArgAttribute::NoCapture)
+             .set(ArgAttribute::NonNull);
+        attrs.pointee_size = self.layout.size;
+        // FIXME(eddyb) We should be doing this, but at least on
+        // i686-pc-windows-msvc, it results in wrong stack offsets.
+        // attrs.pointee_align = Some(self.layout.align);
+
+        self.mode = PassMode::Indirect(attrs);
+    }
+
+    pub fn make_indirect_byval(&mut self) {
+        self.make_indirect();
+        match self.mode {
+            PassMode::Indirect(ref mut attrs) => {
+                attrs.set(ArgAttribute::ByVal);
+            }
+            _ => unreachable!()
+        }
+    }
+
+    pub fn extend_integer_width_to(&mut self, bits: u64) {
+        // Only integers have signedness
+        if let Abi::Scalar(ref scalar) = self.layout.abi {
+            if let abi::Int(i, signed) = scalar.value {
+                if i.size().bits() < bits {
+                    if let PassMode::Direct(ref mut attrs) = self.mode {
+                        attrs.set(if signed {
+                            ArgAttribute::SExt
+                        } else {
+                            ArgAttribute::ZExt
+                        });
+                    }
+                }
+            }
+        }
+    }
+
+    pub fn cast_to<T: Into<CastTarget>>(&mut self, target: T) {
+        assert_eq!(self.mode, PassMode::Direct(ArgAttributes::new()));
+        self.mode = PassMode::Cast(target.into());
+    }
+
+    pub fn pad_with(&mut self, reg: Reg) {
+        self.pad = Some(reg);
+    }
+
+    pub fn is_indirect(&self) -> bool {
+        match self.mode {
+            PassMode::Indirect(_) => true,
+            _ => false
+        }
+    }
+
+    pub fn is_ignore(&self) -> bool {
+        self.mode == PassMode::Ignore
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub enum Conv {
+    C,
+
+    ArmAapcs,
+
+    Msp430Intr,
+
+    PtxKernel,
+
+    X86Fastcall,
+    X86Intr,
+    X86Stdcall,
+    X86ThisCall,
+    X86VectorCall,
+
+    X86_64SysV,
+    X86_64Win64,
+}
+
+/// Metadata describing how the arguments to a native function
+/// should be passed in order to respect the native ABI.
+///
+/// I will do my best to describe this structure, but these
+/// comments are reverse-engineered and may be inaccurate. -NDM
+#[derive(Debug)]
+pub struct FnType<'a, Ty> {
+    /// The LLVM types of each argument.
+    pub args: Vec<ArgType<'a, Ty>>,
+
+    /// LLVM return type.
+    pub ret: ArgType<'a, Ty>,
+
+    pub variadic: bool,
+
+    pub conv: Conv,
+}
+
+impl<'a, Ty> FnType<'a, Ty> {
+    pub fn adjust_for_cabi<C>(&mut self, cx: C, abi: ::spec::abi::Abi) -> Result<(), String>
+        where Ty: TyLayoutMethods<'a, C> + Copy,
+              C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout + HasTargetSpec
+    {
+        match &cx.target_spec().arch[..] {
+            "x86" => {
+                let flavor = if abi == ::spec::abi::Abi::Fastcall {
+                    x86::Flavor::Fastcall
+                } else {
+                    x86::Flavor::General
+                };
+                x86::compute_abi_info(cx, self, flavor);
+            },
+            "x86_64" => if abi == ::spec::abi::Abi::SysV64 {
+                x86_64::compute_abi_info(cx, self);
+            } else if abi == ::spec::abi::Abi::Win64 || cx.target_spec().options.is_like_windows {
+                x86_win64::compute_abi_info(self);
+            } else {
+                x86_64::compute_abi_info(cx, self);
+            },
+            "aarch64" => aarch64::compute_abi_info(cx, self),
+            "arm" => arm::compute_abi_info(cx, self),
+            "mips" => mips::compute_abi_info(cx, self),
+            "mips64" => mips64::compute_abi_info(cx, self),
+            "powerpc" => powerpc::compute_abi_info(cx, self),
+            "powerpc64" => powerpc64::compute_abi_info(cx, self),
+            "s390x" => s390x::compute_abi_info(cx, self),
+            "asmjs" => asmjs::compute_abi_info(cx, self),
+            "wasm32" => {
+                if cx.target_spec().llvm_target.contains("emscripten") {
+                    asmjs::compute_abi_info(cx, self)
+                } else {
+                    wasm32::compute_abi_info(self)
+                }
+            }
+            "msp430" => msp430::compute_abi_info(self),
+            "sparc" => sparc::compute_abi_info(cx, self),
+            "sparc64" => sparc64::compute_abi_info(cx, self),
+            "nvptx" => nvptx::compute_abi_info(self),
+            "nvptx64" => nvptx64::compute_abi_info(self),
+            "hexagon" => hexagon::compute_abi_info(self),
+            a => return Err(format!("unrecognized arch \"{}\" in target specification", a))
+        }
+
+        if let PassMode::Indirect(ref mut attrs) = self.ret.mode {
+            attrs.set(ArgAttribute::StructRet);
+        }
+
+        Ok(())
+    }
+}
diff --git a/src/librustc_trans/cabi_msp430.rs b/src/librustc_target/abi/call/msp430.rs
index d270886a19c..e57ca03da60 100644
--- a/src/librustc_trans/cabi_msp430.rs
+++ b/src/librustc_target/abi/call/msp430.rs
@@ -11,7 +11,7 @@
 // Reference: MSP430 Embedded Application Binary Interface
 // http://www.ti.com/lit/an/slaa534/slaa534.pdf
 
-use abi::{ArgType, FnType, LayoutExt};
+use abi::call::{ArgType, FnType};
 
 // 3.5 Structures or Unions Passed and Returned by Reference
 //
@@ -19,7 +19,7 @@ use abi::{ArgType, FnType, LayoutExt};
 // returned by reference. To pass a structure or union by reference, the caller
 // places its address in the appropriate location: either in a register or on
 // the stack, according to its position in the argument list. (..)"
-fn classify_ret_ty(ret: &mut ArgType) {
+fn classify_ret_ty<Ty>(ret: &mut ArgType<Ty>) {
     if ret.layout.is_aggregate() && ret.layout.size.bits() > 32 {
         ret.make_indirect();
     } else {
@@ -27,7 +27,7 @@ fn classify_ret_ty(ret: &mut ArgType) {
     }
 }
 
-fn classify_arg_ty(arg: &mut ArgType) {
+fn classify_arg_ty<Ty>(arg: &mut ArgType<Ty>) {
     if arg.layout.is_aggregate() && arg.layout.size.bits() > 32 {
         arg.make_indirect();
     } else {
@@ -35,7 +35,7 @@ fn classify_arg_ty(arg: &mut ArgType) {
     }
 }
 
-pub fn compute_abi_info(fty: &mut FnType) {
+pub fn compute_abi_info<Ty>(fty: &mut FnType<Ty>) {
     if !fty.ret.is_ignore() {
         classify_ret_ty(&mut fty.ret);
     }
diff --git a/src/librustc_trans/cabi_nvptx.rs b/src/librustc_target/abi/call/nvptx.rs
index 69cfc690a9f..f23f7ddf2ab 100644
--- a/src/librustc_trans/cabi_nvptx.rs
+++ b/src/librustc_target/abi/call/nvptx.rs
@@ -11,9 +11,9 @@
 // Reference: PTX Writer's Guide to Interoperability
 // http://docs.nvidia.com/cuda/ptx-writers-guide-to-interoperability
 
-use abi::{ArgType, FnType, LayoutExt};
+use abi::call::{ArgType, FnType};
 
-fn classify_ret_ty(ret: &mut ArgType) {
+fn classify_ret_ty<Ty>(ret: &mut ArgType<Ty>) {
     if ret.layout.is_aggregate() && ret.layout.size.bits() > 32 {
         ret.make_indirect();
     } else {
@@ -21,7 +21,7 @@ fn classify_ret_ty(ret: &mut ArgType) {
     }
 }
 
-fn classify_arg_ty(arg: &mut ArgType) {
+fn classify_arg_ty<Ty>(arg: &mut ArgType<Ty>) {
     if arg.layout.is_aggregate() && arg.layout.size.bits() > 32 {
         arg.make_indirect();
     } else {
@@ -29,7 +29,7 @@ fn classify_arg_ty(arg: &mut ArgType) {
     }
 }
 
-pub fn compute_abi_info(fty: &mut FnType) {
+pub fn compute_abi_info<Ty>(fty: &mut FnType<Ty>) {
     if !fty.ret.is_ignore() {
         classify_ret_ty(&mut fty.ret);
     }
diff --git a/src/librustc_trans/cabi_nvptx64.rs b/src/librustc_target/abi/call/nvptx64.rs
index 4d76c156038..4399a2fec6c 100644
--- a/src/librustc_trans/cabi_nvptx64.rs
+++ b/src/librustc_target/abi/call/nvptx64.rs
@@ -11,9 +11,9 @@
 // Reference: PTX Writer's Guide to Interoperability
 // http://docs.nvidia.com/cuda/ptx-writers-guide-to-interoperability
 
-use abi::{ArgType, FnType, LayoutExt};
+use abi::call::{ArgType, FnType};
 
-fn classify_ret_ty(ret: &mut ArgType) {
+fn classify_ret_ty<Ty>(ret: &mut ArgType<Ty>) {
     if ret.layout.is_aggregate() && ret.layout.size.bits() > 64 {
         ret.make_indirect();
     } else {
@@ -21,7 +21,7 @@ fn classify_ret_ty(ret: &mut ArgType) {
     }
 }
 
-fn classify_arg_ty(arg: &mut ArgType) {
+fn classify_arg_ty<Ty>(arg: &mut ArgType<Ty>) {
     if arg.layout.is_aggregate() && arg.layout.size.bits() > 64 {
         arg.make_indirect();
     } else {
@@ -29,7 +29,7 @@ fn classify_arg_ty(arg: &mut ArgType) {
     }
 }
 
-pub fn compute_abi_info(fty: &mut FnType) {
+pub fn compute_abi_info<Ty>(fty: &mut FnType<Ty>) {
     if !fty.ret.is_ignore() {
         classify_ret_ty(&mut fty.ret);
     }
diff --git a/src/librustc_trans/cabi_powerpc.rs b/src/librustc_target/abi/call/powerpc.rs
index 1ea6e9b2695..8c3c2422d7f 100644
--- a/src/librustc_trans/cabi_powerpc.rs
+++ b/src/librustc_target/abi/call/powerpc.rs
@@ -8,24 +8,24 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use abi::{ArgType, FnType, LayoutExt, Reg, Uniform};
-use context::CodegenCx;
+use abi::call::{ArgType, FnType, Reg, Uniform};
+use abi::{HasDataLayout, LayoutOf, Size, TyLayoutMethods};
 
-use rustc::ty::layout::Size;
-
-fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                             ret: &mut ArgType<'tcx>,
-                             offset: &mut Size) {
+fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<Ty>, offset: &mut Size)
+    where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout
+{
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(32);
     } else {
         ret.make_indirect();
-        *offset += cx.tcx.data_layout.pointer_size;
+        *offset += cx.data_layout().pointer_size;
     }
 }
 
-fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
-    let dl = &cx.tcx.data_layout;
+fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<Ty>, offset: &mut Size)
+    where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout
+{
+    let dl = cx.data_layout();
     let size = arg.layout.size;
     let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align);
 
@@ -44,7 +44,9 @@ fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
     *offset = offset.abi_align(align) + size.abi_align(align);
 }
 
-pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<Ty>)
+    where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout
+{
     let mut offset = Size::from_bytes(0);
     if !fty.ret.is_ignore() {
         classify_ret_ty(cx, &mut fty.ret, &mut offset);
diff --git a/src/librustc_trans/cabi_powerpc64.rs b/src/librustc_target/abi/call/powerpc64.rs
index c614cf3a5a9..0c5ec77a398 100644
--- a/src/librustc_trans/cabi_powerpc64.rs
+++ b/src/librustc_target/abi/call/powerpc64.rs
@@ -12,9 +12,8 @@
 // Alignment of 128 bit types is not currently handled, this will
 // need to be fixed when PowerPC vector support is added.
 
-use abi::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform};
-use context::CodegenCx;
-use rustc::ty::layout;
+use abi::call::{FnType, ArgType, Reg, RegKind, Uniform};
+use abi::{Align, Endian, HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
 
 #[derive(Debug, Clone, Copy, PartialEq)]
 enum ABI {
@@ -23,10 +22,11 @@ enum ABI {
 }
 use self::ABI::*;
 
-fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                      arg: &mut ArgType<'tcx>,
-                                      abi: ABI)
-                                     -> Option<Uniform> {
+fn is_homogeneous_aggregate<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>, abi: ABI)
+                                       -> Option<Uniform>
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
         // ELFv1 only passes one-member aggregates transparently.
         // ELFv2 passes up to eight uniquely addressable members.
@@ -52,7 +52,10 @@ fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     })
 }
 
-fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>, abi: ABI) {
+fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<'a, Ty>, abi: ABI)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(64);
         return;
@@ -92,7 +95,10 @@ fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>,
     ret.make_indirect();
 }
 
-fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>, abi: ABI) {
+fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>, abi: ABI)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     if !arg.layout.is_aggregate() {
         arg.extend_integer_width_to(64);
         return;
@@ -112,7 +118,7 @@ fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>,
             if size.bits() <= 64 {
                 (Reg { kind: RegKind::Integer, size }, size)
             } else {
-                let align = layout::Align::from_bits(64, 64).unwrap();
+                let align = Align::from_bits(64, 64).unwrap();
                 (Reg::i64(), size.abi_align(align))
             }
         },
@@ -128,11 +134,13 @@ fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>,
     });
 }
 
-pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
-    let abi = match cx.sess().target.target.target_endian.as_str() {
-        "big" => ELFv1,
-        "little" => ELFv2,
-        _ => unimplemented!(),
+pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
+    let abi = match cx.data_layout().endian {
+        Endian::Big => ELFv1,
+        Endian::Little => ELFv2,
     };
 
     if !fty.ret.is_ignore() {
diff --git a/src/librustc_trans/cabi_s390x.rs b/src/librustc_target/abi/call/s390x.rs
index 5e817686def..3002a3c46c8 100644
--- a/src/librustc_trans/cabi_s390x.rs
+++ b/src/librustc_target/abi/call/s390x.rs
@@ -11,12 +11,12 @@
 // FIXME: The assumes we're using the non-vector ABI, i.e. compiling
 // for a pre-z13 machine or using -mno-vx.
 
-use abi::{FnType, ArgType, LayoutExt, Reg};
-use context::CodegenCx;
+use abi::call::{FnType, ArgType, Reg};
+use abi::{self, HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
 
-use rustc::ty::layout::{self, TyLayout};
-
-fn classify_ret_ty(ret: &mut ArgType) {
+fn classify_ret_ty<'a, Ty, C>(ret: &mut ArgType<Ty>)
+    where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout
+{
     if !ret.layout.is_aggregate() && ret.layout.size.bits() <= 64 {
         ret.extend_integer_width_to(64);
     } else {
@@ -24,16 +24,18 @@ fn classify_ret_ty(ret: &mut ArgType) {
     }
 }
 
-fn is_single_fp_element<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                  layout: TyLayout<'tcx>) -> bool {
+fn is_single_fp_element<'a, Ty, C>(cx: C, layout: TyLayout<'a, Ty>) -> bool
+    where Ty: TyLayoutMethods<'a, C>,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     match layout.abi {
-        layout::Abi::Scalar(ref scalar) => {
+        abi::Abi::Scalar(ref scalar) => {
             match scalar.value {
-                layout::F32 | layout::F64 => true,
+                abi::F32 | abi::F64 => true,
                 _ => false
             }
         }
-        layout::Abi::Aggregate { .. } => {
+        abi::Abi::Aggregate { .. } => {
             if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
                 is_single_fp_element(cx, layout.field(cx, 0))
             } else {
@@ -44,7 +46,10 @@ fn is_single_fp_element<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     }
 }
 
-fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
+fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     if !arg.layout.is_aggregate() && arg.layout.size.bits() <= 64 {
         arg.extend_integer_width_to(64);
         return;
@@ -67,7 +72,10 @@ fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
     }
 }
 
-pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     if !fty.ret.is_ignore() {
         classify_ret_ty(&mut fty.ret);
     }
diff --git a/src/librustc_trans/cabi_sparc.rs b/src/librustc_target/abi/call/sparc.rs
index cd567f517fe..5001499ea5d 100644
--- a/src/librustc_trans/cabi_sparc.rs
+++ b/src/librustc_target/abi/call/sparc.rs
@@ -8,24 +8,24 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use abi::{ArgType, FnType, LayoutExt, Reg, Uniform};
-use context::CodegenCx;
+use abi::call::{ArgType, FnType, Reg, Uniform};
+use abi::{HasDataLayout, LayoutOf, Size, TyLayoutMethods};
 
-use rustc::ty::layout::Size;
-
-fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                             ret: &mut ArgType<'tcx>,
-                             offset: &mut Size) {
+fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<Ty>, offset: &mut Size)
+    where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout
+{
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(32);
     } else {
         ret.make_indirect();
-        *offset += cx.tcx.data_layout.pointer_size;
+        *offset += cx.data_layout().pointer_size;
     }
 }
 
-fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
-    let dl = &cx.tcx.data_layout;
+fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<Ty>, offset: &mut Size)
+    where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout
+{
+    let dl = cx.data_layout();
     let size = arg.layout.size;
     let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align);
 
@@ -44,7 +44,9 @@ fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
     *offset = offset.abi_align(align) + size.abi_align(align);
 }
 
-pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<Ty>)
+    where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout
+{
     let mut offset = Size::from_bytes(0);
     if !fty.ret.is_ignore() {
         classify_ret_ty(cx, &mut fty.ret, &mut offset);
diff --git a/src/librustc_trans/cabi_sparc64.rs b/src/librustc_target/abi/call/sparc64.rs
index b3fc6a68061..987f56e6f98 100644
--- a/src/librustc_trans/cabi_sparc64.rs
+++ b/src/librustc_target/abi/call/sparc64.rs
@@ -10,11 +10,14 @@
 
 // FIXME: This needs an audit for correctness and completeness.
 
-use abi::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform};
-use context::CodegenCx;
+use abi::call::{FnType, ArgType, Reg, RegKind, Uniform};
+use abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
 
-fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
-                                     -> Option<Uniform> {
+fn is_homogeneous_aggregate<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>)
+                                     -> Option<Uniform>
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
         // Ensure we have at most eight uniquely addressable members.
         if arg.layout.size > unit.size.checked_mul(8, cx).unwrap() {
@@ -38,7 +41,10 @@ fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgTyp
     })
 }
 
-fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
+fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<'a, Ty>)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     if !ret.layout.is_aggregate() {
         ret.extend_integer_width_to(64);
         return;
@@ -72,7 +78,10 @@ fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>)
     ret.make_indirect();
 }
 
-fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
+fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     if !arg.layout.is_aggregate() {
         arg.extend_integer_width_to(64);
         return;
@@ -95,7 +104,10 @@ fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
     });
 }
 
-pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     if !fty.ret.is_ignore() {
         classify_ret_ty(cx, &mut fty.ret);
     }
diff --git a/src/librustc_trans/cabi_wasm32.rs b/src/librustc_target/abi/call/wasm32.rs
index 5530a03d65d..7109eea535d 100644
--- a/src/librustc_trans/cabi_wasm32.rs
+++ b/src/librustc_target/abi/call/wasm32.rs
@@ -8,20 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use abi::{FnType, ArgType};
-use context::CodegenCx;
+use abi::call::{FnType, ArgType};
 
-fn classify_ret_ty<'a, 'tcx>(_cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
+fn classify_ret_ty<Ty>(ret: &mut ArgType<Ty>) {
     ret.extend_integer_width_to(32);
 }
 
-fn classify_arg_ty(arg: &mut ArgType) {
+fn classify_arg_ty<Ty>(arg: &mut ArgType<Ty>) {
     arg.extend_integer_width_to(32);
 }
 
-pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<Ty>(fty: &mut FnType<Ty>) {
     if !fty.ret.is_ignore() {
-        classify_ret_ty(cx, &mut fty.ret);
+        classify_ret_ty(&mut fty.ret);
     }
 
     for arg in &mut fty.args {
diff --git a/src/librustc_trans/cabi_x86.rs b/src/librustc_target/abi/call/x86.rs
index b1455844806..e803b96b21c 100644
--- a/src/librustc_trans/cabi_x86.rs
+++ b/src/librustc_target/abi/call/x86.rs
@@ -8,10 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use abi::{ArgAttribute, FnType, LayoutExt, PassMode, Reg, RegKind};
-use common::CodegenCx;
-
-use rustc::ty::layout::{self, TyLayout};
+use abi::call::{ArgAttribute, FnType, PassMode, Reg, RegKind};
+use abi::{self, HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
+use spec::HasTargetSpec;
 
 #[derive(PartialEq)]
 pub enum Flavor {
@@ -19,16 +18,18 @@ pub enum Flavor {
     Fastcall
 }
 
-fn is_single_fp_element<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                  layout: TyLayout<'tcx>) -> bool {
+fn is_single_fp_element<'a, Ty, C>(cx: C, layout: TyLayout<'a, Ty>) -> bool
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     match layout.abi {
-        layout::Abi::Scalar(ref scalar) => {
+        abi::Abi::Scalar(ref scalar) => {
             match scalar.value {
-                layout::F32 | layout::F64 => true,
+                abi::F32 | abi::F64 => true,
                 _ => false
             }
         }
-        layout::Abi::Aggregate { .. } => {
+        abi::Abi::Aggregate { .. } => {
             if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
                 is_single_fp_element(cx, layout.field(cx, 0))
             } else {
@@ -39,9 +40,10 @@ fn is_single_fp_element<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     }
 }
 
-pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                                  fty: &mut FnType<'tcx>,
-                                  flavor: Flavor) {
+pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>, flavor: Flavor)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout + HasTargetSpec
+{
     if !fty.ret.is_ignore() {
         if fty.ret.layout.is_aggregate() {
             // Returning a structure. Most often, this will use
@@ -51,7 +53,7 @@ pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
             // Some links:
             // http://www.angelcode.com/dev/callconv/callconv.html
             // Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp
-            let t = &cx.sess().target.target;
+            let t = cx.target_spec();
             if t.options.abi_return_struct_as_int {
                 // According to Clang, everyone but MSVC returns single-element
                 // float aggregates directly in a floating-point register.
@@ -106,7 +108,7 @@ pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                 PassMode::Direct(ref mut attrs) => attrs,
                 PassMode::Pair(..) |
                 PassMode::Cast(_) => {
-                    bug!("x86 shouldn't be passing arguments by {:?}", arg.mode)
+                    unreachable!("x86 shouldn't be passing arguments by {:?}", arg.mode)
                 }
             };
 
diff --git a/src/librustc_trans/cabi_x86_64.rs b/src/librustc_target/abi/call/x86_64.rs
index 7eadaa7f493..0ba1ee736e7 100644
--- a/src/librustc_trans/cabi_x86_64.rs
+++ b/src/librustc_target/abi/call/x86_64.rs
@@ -11,10 +11,8 @@
 // The classification code for the x86_64 ABI is taken from the clay language
 // https://github.com/jckarter/clay/blob/master/compiler/src/externals.cpp
 
-use abi::{ArgType, CastTarget, FnType, LayoutExt, Reg, RegKind};
-use context::CodegenCx;
-
-use rustc::ty::layout::{self, TyLayout, Size};
+use abi::call::{ArgType, CastTarget, FnType, Reg, RegKind};
+use abi::{self, Abi, HasDataLayout, LayoutOf, Size, TyLayout, TyLayoutMethods};
 
 /// Classification of "eightbyte" components.
 // NB: the order of the variants is from general to specific,
@@ -33,13 +31,16 @@ struct Memory;
 const LARGEST_VECTOR_SIZE: usize = 512;
 const MAX_EIGHTBYTES: usize = LARGEST_VECTOR_SIZE / 64;
 
-fn classify_arg<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &ArgType<'tcx>)
-                          -> Result<[Option<Class>; MAX_EIGHTBYTES], Memory> {
-    fn classify<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
-                          layout: TyLayout<'tcx>,
-                          cls: &mut [Option<Class>],
-                          off: Size)
-                          -> Result<(), Memory> {
+fn classify_arg<'a, Ty, C>(cx: C, arg: &ArgType<'a, Ty>)
+                          -> Result<[Option<Class>; MAX_EIGHTBYTES], Memory>
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
+    fn classify<'a, Ty, C>(cx: C, layout: TyLayout<'a, Ty>,
+                          cls: &mut [Option<Class>], off: Size) -> Result<(), Memory>
+        where Ty: TyLayoutMethods<'a, C> + Copy,
+            C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+    {
         if !off.is_abi_aligned(layout.align) {
             if !layout.is_zst() {
                 return Err(Memory);
@@ -48,31 +49,31 @@ fn classify_arg<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &ArgType<'tcx>)
         }
 
         let mut c = match layout.abi {
-            layout::Abi::Uninhabited => return Ok(()),
+            Abi::Uninhabited => return Ok(()),
 
-            layout::Abi::Scalar(ref scalar) => {
+            Abi::Scalar(ref scalar) => {
                 match scalar.value {
-                    layout::Int(..) |
-                    layout::Pointer => Class::Int,
-                    layout::F32 |
-                    layout::F64 => Class::Sse
+                    abi::Int(..) |
+                    abi::Pointer => Class::Int,
+                    abi::F32 |
+                    abi::F64 => Class::Sse
                 }
             }
 
-            layout::Abi::Vector { .. } => Class::Sse,
+            Abi::Vector { .. } => Class::Sse,
 
-            layout::Abi::ScalarPair(..) |
-            layout::Abi::Aggregate { .. } => {
+            Abi::ScalarPair(..) |
+            Abi::Aggregate { .. } => {
                 match layout.variants {
-                    layout::Variants::Single { .. } => {
+                    abi::Variants::Single { .. } => {
                         for i in 0..layout.fields.count() {
                             let field_off = off + layout.fields.offset(i);
                             classify(cx, layout.field(cx, i), cls, field_off)?;
                         }
                         return Ok(());
                     }
-                    layout::Variants::Tagged { .. } |
-                    layout::Variants::NicheFilling { .. } => return Err(Memory),
+                    abi::Variants::Tagged { .. } |
+                    abi::Variants::NicheFilling { .. } => return Err(Memory),
                 }
             }
 
@@ -160,7 +161,7 @@ fn reg_component(cls: &[Option<Class>], i: &mut usize, size: Size) -> Option<Reg
                 }
             })
         }
-        Some(c) => bug!("reg_component: unhandled class {:?}", c)
+        Some(c) => unreachable!("reg_component: unhandled class {:?}", c)
     }
 }
 
@@ -178,11 +179,14 @@ fn cast_target(cls: &[Option<Class>], size: Size) -> CastTarget {
     target
 }
 
-pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
+pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>)
+    where Ty: TyLayoutMethods<'a, C> + Copy,
+          C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
+{
     let mut int_regs = 6; // RDI, RSI, RDX, RCX, R8, R9
     let mut sse_regs = 8; // XMM0-7
 
-    let mut x86_64_ty = |arg: &mut ArgType<'tcx>, is_arg: bool| {
+    let mut x86_64_ty = |arg: &mut ArgType<'a, Ty>, is_arg: bool| {
         let mut cls_or_mem = classify_arg(cx, arg);
 
         let mut needed_int = 0;
diff --git a/src/librustc_trans/cabi_x86_win64.rs b/src/librustc_target/abi/call/x86_win64.rs
index eb5ec403490..1ee069e2bbb 100644
--- a/src/librustc_trans/cabi_x86_win64.rs
+++ b/src/librustc_target/abi/call/x86_win64.rs
@@ -8,18 +8,17 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use abi::{ArgType, FnType, Reg};
-
-use rustc::ty::layout;
+use abi::call::{ArgType, FnType, Reg};
+use abi::Abi;
 
 // Win64 ABI: http://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
 
-pub fn compute_abi_info(fty: &mut FnType) {
-    let fixup = |a: &mut ArgType| {
+pub fn compute_abi_info<Ty>(fty: &mut FnType<Ty>) {
+    let fixup = |a: &mut ArgType<Ty>| {
         match a.layout.abi {
-            layout::Abi::Uninhabited => {}
-            layout::Abi::ScalarPair(..) |
-            layout::Abi::Aggregate { .. } => {
+            Abi::Uninhabited => {}
+            Abi::ScalarPair(..) |
+            Abi::Aggregate { .. } => {
                 match a.layout.size.bits() {
                     8 => a.cast_to(Reg::i8()),
                     16 => a.cast_to(Reg::i16()),
@@ -28,11 +27,11 @@ pub fn compute_abi_info(fty: &mut FnType) {
                     _ => a.make_indirect()
                 }
             }
-            layout::Abi::Vector { .. } => {
+            Abi::Vector { .. } => {
                 // FIXME(eddyb) there should be a size cap here
                 // (probably what clang calls "illegal vectors").
             }
-            layout::Abi::Scalar(_) => {
+            Abi::Scalar(_) => {
                 if a.layout.size.bytes() > 8 {
                     a.make_indirect();
                 } else {
diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs
new file mode 100644
index 00000000000..18dd04c0ee8
--- /dev/null
+++ b/src/librustc_target/abi/mod.rs
@@ -0,0 +1,823 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub use self::Integer::*;
+pub use self::Primitive::*;
+
+use spec::Target;
+
+use std::cmp;
+use std::ops::{Add, Deref, Sub, Mul, AddAssign, RangeInclusive};
+
+pub mod call;
+
+/// Parsed [Data layout](http://llvm.org/docs/LangRef.html#data-layout)
+/// for a target, which contains everything needed to compute layouts.
+pub struct TargetDataLayout {
+    pub endian: Endian,
+    pub i1_align: Align,
+    pub i8_align: Align,
+    pub i16_align: Align,
+    pub i32_align: Align,
+    pub i64_align: Align,
+    pub i128_align: Align,
+    pub f32_align: Align,
+    pub f64_align: Align,
+    pub pointer_size: Size,
+    pub pointer_align: Align,
+    pub aggregate_align: Align,
+
+    /// Alignments for vector types.
+    pub vector_align: Vec<(Size, Align)>
+}
+
+impl Default for TargetDataLayout {
+    /// Creates an instance of `TargetDataLayout`.
+    fn default() -> TargetDataLayout {
+        TargetDataLayout {
+            endian: Endian::Big,
+            i1_align: Align::from_bits(8, 8).unwrap(),
+            i8_align: Align::from_bits(8, 8).unwrap(),
+            i16_align: Align::from_bits(16, 16).unwrap(),
+            i32_align: Align::from_bits(32, 32).unwrap(),
+            i64_align: Align::from_bits(32, 64).unwrap(),
+            i128_align: Align::from_bits(32, 64).unwrap(),
+            f32_align: Align::from_bits(32, 32).unwrap(),
+            f64_align: Align::from_bits(64, 64).unwrap(),
+            pointer_size: Size::from_bits(64),
+            pointer_align: Align::from_bits(64, 64).unwrap(),
+            aggregate_align: Align::from_bits(0, 64).unwrap(),
+            vector_align: vec![
+                (Size::from_bits(64), Align::from_bits(64, 64).unwrap()),
+                (Size::from_bits(128), Align::from_bits(128, 128).unwrap())
+            ]
+        }
+    }
+}
+
+impl TargetDataLayout {
+    pub fn parse(target: &Target) -> Result<TargetDataLayout, String> {
+        // Parse a bit count from a string.
+        let parse_bits = |s: &str, kind: &str, cause: &str| {
+            s.parse::<u64>().map_err(|err| {
+                format!("invalid {} `{}` for `{}` in \"data-layout\": {}",
+                        kind, s, cause, err)
+            })
+        };
+
+        // Parse a size string.
+        let size = |s: &str, cause: &str| {
+            parse_bits(s, "size", cause).map(Size::from_bits)
+        };
+
+        // Parse an alignment string.
+        let align = |s: &[&str], cause: &str| {
+            if s.is_empty() {
+                return Err(format!("missing alignment for `{}` in \"data-layout\"", cause));
+            }
+            let abi = parse_bits(s[0], "alignment", cause)?;
+            let pref = s.get(1).map_or(Ok(abi), |pref| parse_bits(pref, "alignment", cause))?;
+            Align::from_bits(abi, pref).map_err(|err| {
+                format!("invalid alignment for `{}` in \"data-layout\": {}",
+                        cause, err)
+            })
+        };
+
+        let mut dl = TargetDataLayout::default();
+        let mut i128_align_src = 64;
+        for spec in target.data_layout.split("-") {
+            match &spec.split(":").collect::<Vec<_>>()[..] {
+                &["e"] => dl.endian = Endian::Little,
+                &["E"] => dl.endian = Endian::Big,
+                &["a", ref a..] => dl.aggregate_align = align(a, "a")?,
+                &["f32", ref a..] => dl.f32_align = align(a, "f32")?,
+                &["f64", ref a..] => dl.f64_align = align(a, "f64")?,
+                &[p @ "p", s, ref a..] | &[p @ "p0", s, ref a..] => {
+                    dl.pointer_size = size(s, p)?;
+                    dl.pointer_align = align(a, p)?;
+                }
+                &[s, ref a..] if s.starts_with("i") => {
+                    let bits = match s[1..].parse::<u64>() {
+                        Ok(bits) => bits,
+                        Err(_) => {
+                            size(&s[1..], "i")?; // For the user error.
+                            continue;
+                        }
+                    };
+                    let a = align(a, s)?;
+                    match bits {
+                        1 => dl.i1_align = a,
+                        8 => dl.i8_align = a,
+                        16 => dl.i16_align = a,
+                        32 => dl.i32_align = a,
+                        64 => dl.i64_align = a,
+                        _ => {}
+                    }
+                    if bits >= i128_align_src && bits <= 128 {
+                        // Default alignment for i128 is decided by taking the alignment of
+                        // largest-sized i{64...128}.
+                        i128_align_src = bits;
+                        dl.i128_align = a;
+                    }
+                }
+                &[s, ref a..] if s.starts_with("v") => {
+                    let v_size = size(&s[1..], "v")?;
+                    let a = align(a, s)?;
+                    if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) {
+                        v.1 = a;
+                        continue;
+                    }
+                    // No existing entry, add a new one.
+                    dl.vector_align.push((v_size, a));
+                }
+                _ => {} // Ignore everything else.
+            }
+        }
+
+        // Perform consistency checks against the Target information.
+        let endian_str = match dl.endian {
+            Endian::Little => "little",
+            Endian::Big => "big"
+        };
+        if endian_str != target.target_endian {
+            return Err(format!("inconsistent target specification: \"data-layout\" claims \
+                                architecture is {}-endian, while \"target-endian\" is `{}`",
+                               endian_str, target.target_endian));
+        }
+
+        if dl.pointer_size.bits().to_string() != target.target_pointer_width {
+            return Err(format!("inconsistent target specification: \"data-layout\" claims \
+                                pointers are {}-bit, while \"target-pointer-width\" is `{}`",
+                               dl.pointer_size.bits(), target.target_pointer_width));
+        }
+
+        Ok(dl)
+    }
+
+    /// Return exclusive upper bound on object size.
+    ///
+    /// The theoretical maximum object size is defined as the maximum positive `isize` value.
+    /// This ensures that the `offset` semantics remain well-defined by allowing it to correctly
+    /// index every address within an object along with one byte past the end, along with allowing
+    /// `isize` to store the difference between any two pointers into an object.
+    ///
+    /// The upper bound on 64-bit currently needs to be lower because LLVM uses a 64-bit integer
+    /// to represent object size in bits. It would need to be 1 << 61 to account for this, but is
+    /// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable
+    /// address space on 64-bit ARMv8 and x86_64.
+    pub fn obj_size_bound(&self) -> u64 {
+        match self.pointer_size.bits() {
+            16 => 1 << 15,
+            32 => 1 << 31,
+            64 => 1 << 47,
+            bits => panic!("obj_size_bound: unknown pointer bit size {}", bits)
+        }
+    }
+
+    pub fn ptr_sized_integer(&self) -> Integer {
+        match self.pointer_size.bits() {
+            16 => I16,
+            32 => I32,
+            64 => I64,
+            bits => panic!("ptr_sized_integer: unknown pointer bit size {}", bits)
+        }
+    }
+
+    pub fn vector_align(&self, vec_size: Size) -> Align {
+        for &(size, align) in &self.vector_align {
+            if size == vec_size {
+                return align;
+            }
+        }
+        // Default to natural alignment, which is what LLVM does.
+        // That is, use the size, rounded up to a power of 2.
+        let align = vec_size.bytes().next_power_of_two();
+        Align::from_bytes(align, align).unwrap()
+    }
+}
+
+pub trait HasDataLayout: Copy {
+    fn data_layout(&self) -> &TargetDataLayout;
+}
+
+impl<'a> HasDataLayout for &'a TargetDataLayout {
+    fn data_layout(&self) -> &TargetDataLayout {
+        self
+    }
+}
+
+/// Endianness of the target, which must match cfg(target-endian).
+#[derive(Copy, Clone)]
+pub enum Endian {
+    Little,
+    Big
+}
+
+/// Size of a type in bytes.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+pub struct Size {
+    raw: u64
+}
+
+impl Size {
+    pub fn from_bits(bits: u64) -> Size {
+        // Avoid potential overflow from `bits + 7`.
+        Size::from_bytes(bits / 8 + ((bits % 8) + 7) / 8)
+    }
+
+    pub fn from_bytes(bytes: u64) -> Size {
+        if bytes >= (1 << 61) {
+            panic!("Size::from_bytes: {} bytes in bits doesn't fit in u64", bytes)
+        }
+        Size {
+            raw: bytes
+        }
+    }
+
+    pub fn bytes(self) -> u64 {
+        self.raw
+    }
+
+    pub fn bits(self) -> u64 {
+        self.bytes() * 8
+    }
+
+    pub fn abi_align(self, align: Align) -> Size {
+        let mask = align.abi() - 1;
+        Size::from_bytes((self.bytes() + mask) & !mask)
+    }
+
+    pub fn is_abi_aligned(self, align: Align) -> bool {
+        let mask = align.abi() - 1;
+        self.bytes() & mask == 0
+    }
+
+    pub fn checked_add<C: HasDataLayout>(self, offset: Size, cx: C) -> Option<Size> {
+        let dl = cx.data_layout();
+
+        // Each Size is less than dl.obj_size_bound(), so the sum is
+        // also less than 1 << 62 (and therefore can't overflow).
+        let bytes = self.bytes() + offset.bytes();
+
+        if bytes < dl.obj_size_bound() {
+            Some(Size::from_bytes(bytes))
+        } else {
+            None
+        }
+    }
+
+    pub fn checked_mul<C: HasDataLayout>(self, count: u64, cx: C) -> Option<Size> {
+        let dl = cx.data_layout();
+
+        match self.bytes().checked_mul(count) {
+            Some(bytes) if bytes < dl.obj_size_bound() => {
+                Some(Size::from_bytes(bytes))
+            }
+            _ => None
+        }
+    }
+}
+
+// Panicking addition, subtraction and multiplication for convenience.
+// Avoid during layout computation, return `LayoutError` instead.
+
+impl Add for Size {
+    type Output = Size;
+    fn add(self, other: Size) -> Size {
+        // Each Size is less than 1 << 61, so the sum is
+        // less than 1 << 62 (and therefore can't overflow).
+        Size::from_bytes(self.bytes() + other.bytes())
+    }
+}
+
+impl Sub for Size {
+    type Output = Size;
+    fn sub(self, other: Size) -> Size {
+        // Each Size is less than 1 << 61, so an underflow
+        // would result in a value larger than 1 << 61,
+        // which Size::from_bytes will catch for us.
+        Size::from_bytes(self.bytes() - other.bytes())
+    }
+}
+
+impl Mul<u64> for Size {
+    type Output = Size;
+    fn mul(self, count: u64) -> Size {
+        match self.bytes().checked_mul(count) {
+            Some(bytes) => Size::from_bytes(bytes),
+            None => {
+                panic!("Size::mul: {} * {} doesn't fit in u64", self.bytes(), count)
+            }
+        }
+    }
+}
+
+impl AddAssign for Size {
+    fn add_assign(&mut self, other: Size) {
+        *self = *self + other;
+    }
+}
+
+/// Alignment of a type in bytes, both ABI-mandated and preferred.
+/// Each field is a power of two, giving the alignment a maximum value of
+/// 2<sup>(2<sup>8</sup> - 1)</sup>, which is limited by LLVM to a i32,
+/// with a maximum capacity of 2<sup>31</sup> - 1 or 2147483647.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
+pub struct Align {
+    abi_pow2: u8,
+    pref_pow2: u8,
+}
+
+impl Align {
+    pub fn from_bits(abi: u64, pref: u64) -> Result<Align, String> {
+        Align::from_bytes(Size::from_bits(abi).bytes(),
+                          Size::from_bits(pref).bytes())
+    }
+
+    pub fn from_bytes(abi: u64, pref: u64) -> Result<Align, String> {
+        let log2 = |align: u64| {
+            // Treat an alignment of 0 bytes like 1-byte alignment.
+            if align == 0 {
+                return Ok(0);
+            }
+
+            let mut bytes = align;
+            let mut pow: u8 = 0;
+            while (bytes & 1) == 0 {
+                pow += 1;
+                bytes >>= 1;
+            }
+            if bytes != 1 {
+                Err(format!("`{}` is not a power of 2", align))
+            } else if pow > 30 {
+                Err(format!("`{}` is too large", align))
+            } else {
+                Ok(pow)
+            }
+        };
+
+        Ok(Align {
+            abi_pow2: log2(abi)?,
+            pref_pow2: log2(pref)?,
+        })
+    }
+
+    pub fn abi(self) -> u64 {
+        1 << self.abi_pow2
+    }
+
+    pub fn pref(self) -> u64 {
+        1 << self.pref_pow2
+    }
+
+    pub fn abi_bits(self) -> u64 {
+        self.abi() * 8
+    }
+
+    pub fn pref_bits(self) -> u64 {
+        self.pref() * 8
+    }
+
+    pub fn min(self, other: Align) -> Align {
+        Align {
+            abi_pow2: cmp::min(self.abi_pow2, other.abi_pow2),
+            pref_pow2: cmp::min(self.pref_pow2, other.pref_pow2),
+        }
+    }
+
+    pub fn max(self, other: Align) -> Align {
+        Align {
+            abi_pow2: cmp::max(self.abi_pow2, other.abi_pow2),
+            pref_pow2: cmp::max(self.pref_pow2, other.pref_pow2),
+        }
+    }
+}
+
+/// Integers, also used for enum discriminants.
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+pub enum Integer {
+    I8,
+    I16,
+    I32,
+    I64,
+    I128,
+}
+
+impl Integer {
+    pub fn size(&self) -> Size {
+        match *self {
+            I8 => Size::from_bytes(1),
+            I16 => Size::from_bytes(2),
+            I32 => Size::from_bytes(4),
+            I64  => Size::from_bytes(8),
+            I128  => Size::from_bytes(16),
+        }
+    }
+
+    pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
+        let dl = cx.data_layout();
+
+        match *self {
+            I8 => dl.i8_align,
+            I16 => dl.i16_align,
+            I32 => dl.i32_align,
+            I64 => dl.i64_align,
+            I128 => dl.i128_align,
+        }
+    }
+
+    /// Find the smallest Integer type which can represent the signed value.
+    pub fn fit_signed(x: i128) -> Integer {
+        match x {
+            -0x0000_0000_0000_0080...0x0000_0000_0000_007f => I8,
+            -0x0000_0000_0000_8000...0x0000_0000_0000_7fff => I16,
+            -0x0000_0000_8000_0000...0x0000_0000_7fff_ffff => I32,
+            -0x8000_0000_0000_0000...0x7fff_ffff_ffff_ffff => I64,
+            _ => I128
+        }
+    }
+
+    /// Find the smallest Integer type which can represent the unsigned value.
+    pub fn fit_unsigned(x: u128) -> Integer {
+        match x {
+            0...0x0000_0000_0000_00ff => I8,
+            0...0x0000_0000_0000_ffff => I16,
+            0...0x0000_0000_ffff_ffff => I32,
+            0...0xffff_ffff_ffff_ffff => I64,
+            _ => I128,
+        }
+    }
+
+    /// Find the smallest integer with the given alignment.
+    pub fn for_abi_align<C: HasDataLayout>(cx: C, align: Align) -> Option<Integer> {
+        let dl = cx.data_layout();
+
+        let wanted = align.abi();
+        for &candidate in &[I8, I16, I32, I64, I128] {
+            if wanted == candidate.align(dl).abi() && wanted == candidate.size().bytes() {
+                return Some(candidate);
+            }
+        }
+        None
+    }
+
+    /// Find the largest integer with the given alignment or less.
+    pub fn approximate_abi_align<C: HasDataLayout>(cx: C, align: Align) -> Integer {
+        let dl = cx.data_layout();
+
+        let wanted = align.abi();
+        // FIXME(eddyb) maybe include I128 in the future, when it works everywhere.
+        for &candidate in &[I64, I32, I16] {
+            if wanted >= candidate.align(dl).abi() && wanted >= candidate.size().bytes() {
+                return candidate;
+            }
+        }
+        I8
+    }
+}
+
+/// Fundamental unit of memory access and layout.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub enum Primitive {
+    /// The `bool` is the signedness of the `Integer` type.
+    ///
+    /// One would think we would not care about such details this low down,
+    /// but some ABIs are described in terms of C types and ISAs where the
+    /// integer arithmetic is done on {sign,zero}-extended registers, e.g.
+    /// a negative integer passed by zero-extension will appear positive in
+    /// the callee, and most operations on it will produce the wrong values.
+    Int(Integer, bool),
+    F32,
+    F64,
+    Pointer
+}
+
+impl<'a, 'tcx> Primitive {
+    pub fn size<C: HasDataLayout>(self, cx: C) -> Size {
+        let dl = cx.data_layout();
+
+        match self {
+            Int(i, _) => i.size(),
+            F32 => Size::from_bits(32),
+            F64 => Size::from_bits(64),
+            Pointer => dl.pointer_size
+        }
+    }
+
+    pub fn align<C: HasDataLayout>(self, cx: C) -> Align {
+        let dl = cx.data_layout();
+
+        match self {
+            Int(i, _) => i.align(dl),
+            F32 => dl.f32_align,
+            F64 => dl.f64_align,
+            Pointer => dl.pointer_align
+        }
+    }
+}
+
+/// Information about one scalar component of a Rust type.
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub struct Scalar {
+    pub value: Primitive,
+
+    /// Inclusive wrap-around range of valid values, that is, if
+    /// min > max, it represents min..=u128::MAX followed by 0..=max.
+    // FIXME(eddyb) always use the shortest range, e.g. by finding
+    // the largest space between two consecutive valid values and
+    // taking everything else as the (shortest) valid range.
+    pub valid_range: RangeInclusive<u128>,
+}
+
+impl Scalar {
+    pub fn is_bool(&self) -> bool {
+        if let Int(I8, _) = self.value {
+            self.valid_range == (0..=1)
+        } else {
+            false
+        }
+    }
+}
+
+/// Describes how the fields of a type are located in memory.
+#[derive(PartialEq, Eq, Hash, Debug)]
+pub enum FieldPlacement {
+    /// All fields start at no offset. The `usize` is the field count.
+    Union(usize),
+
+    /// Array/vector-like placement, with all fields of identical types.
+    Array {
+        stride: Size,
+        count: u64
+    },
+
+    /// Struct-like placement, with precomputed offsets.
+    ///
+    /// Fields are guaranteed to not overlap, but note that gaps
+    /// before, between and after all the fields are NOT always
+    /// padding, and as such their contents may not be discarded.
+    /// For example, enum variants leave a gap at the start,
+    /// where the discriminant field in the enum layout goes.
+    Arbitrary {
+        /// Offsets for the first byte of each field,
+        /// ordered to match the source definition order.
+        /// This vector does not go in increasing order.
+        // FIXME(eddyb) use small vector optimization for the common case.
+        offsets: Vec<Size>,
+
+        /// Maps source order field indices to memory order indices,
+        /// depending how fields were permuted.
+        // FIXME(camlorn) also consider small vector  optimization here.
+        memory_index: Vec<u32>
+    }
+}
+
+impl FieldPlacement {
+    pub fn count(&self) -> usize {
+        match *self {
+            FieldPlacement::Union(count) => count,
+            FieldPlacement::Array { count, .. } => {
+                let usize_count = count as usize;
+                assert_eq!(usize_count as u64, count);
+                usize_count
+            }
+            FieldPlacement::Arbitrary { ref offsets, .. } => offsets.len()
+        }
+    }
+
+    pub fn offset(&self, i: usize) -> Size {
+        match *self {
+            FieldPlacement::Union(_) => Size::from_bytes(0),
+            FieldPlacement::Array { stride, count } => {
+                let i = i as u64;
+                assert!(i < count);
+                stride * i
+            }
+            FieldPlacement::Arbitrary { ref offsets, .. } => offsets[i]
+        }
+    }
+
+    pub fn memory_index(&self, i: usize) -> usize {
+        match *self {
+            FieldPlacement::Union(_) |
+            FieldPlacement::Array { .. } => i,
+            FieldPlacement::Arbitrary { ref memory_index, .. } => {
+                let r = memory_index[i];
+                assert_eq!(r as usize as u32, r);
+                r as usize
+            }
+        }
+    }
+
+    /// Get source indices of the fields by increasing offsets.
+    #[inline]
+    pub fn index_by_increasing_offset<'a>(&'a self) -> impl Iterator<Item=usize>+'a {
+        let mut inverse_small = [0u8; 64];
+        let mut inverse_big = vec![];
+        let use_small = self.count() <= inverse_small.len();
+
+        // We have to write this logic twice in order to keep the array small.
+        if let FieldPlacement::Arbitrary { ref memory_index, .. } = *self {
+            if use_small {
+                for i in 0..self.count() {
+                    inverse_small[memory_index[i] as usize] = i as u8;
+                }
+            } else {
+                inverse_big = vec![0; self.count()];
+                for i in 0..self.count() {
+                    inverse_big[memory_index[i] as usize] = i as u32;
+                }
+            }
+        }
+
+        (0..self.count()).map(move |i| {
+            match *self {
+                FieldPlacement::Union(_) |
+                FieldPlacement::Array { .. } => i,
+                FieldPlacement::Arbitrary { .. } => {
+                    if use_small { inverse_small[i] as usize }
+                    else { inverse_big[i] as usize }
+                }
+            }
+        })
+    }
+}
+
+/// Describes how values of the type are passed by target ABIs,
+/// in terms of categories of C types there are ABI rules for.
+#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+pub enum Abi {
+    Uninhabited,
+    Scalar(Scalar),
+    ScalarPair(Scalar, Scalar),
+    Vector {
+        element: Scalar,
+        count: u64
+    },
+    Aggregate {
+        /// If true, the size is exact, otherwise it's only a lower bound.
+        sized: bool,
+    }
+}
+
+impl Abi {
+    /// Returns true if the layout corresponds to an unsized type.
+    pub fn is_unsized(&self) -> bool {
+        match *self {
+            Abi::Uninhabited |
+            Abi::Scalar(_) |
+            Abi::ScalarPair(..) |
+            Abi::Vector { .. } => false,
+            Abi::Aggregate { sized } => !sized
+        }
+    }
+
+    /// Returns true if this is a single signed integer scalar
+    pub fn is_signed(&self) -> bool {
+        match *self {
+            Abi::Scalar(ref scal) => match scal.value {
+                Primitive::Int(_, signed) => signed,
+                _ => false,
+            },
+            _ => false,
+        }
+    }
+}
+
+#[derive(PartialEq, Eq, Hash, Debug)]
+pub enum Variants {
+    /// Single enum variants, structs/tuples, unions, and all non-ADTs.
+    Single {
+        index: usize
+    },
+
+    /// General-case enums: for each case there is a struct, and they all have
+    /// all space reserved for the discriminant, and their first field starts
+    /// at a non-0 offset, after where the discriminant would go.
+    Tagged {
+        discr: Scalar,
+        variants: Vec<LayoutDetails>,
+    },
+
+    /// Multiple cases distinguished by a niche (values invalid for a type):
+    /// the variant `dataful_variant` contains a niche at an arbitrary
+    /// offset (field 0 of the enum), which for a variant with discriminant
+    /// `d` is set to `(d - niche_variants.start).wrapping_add(niche_start)`.
+    ///
+    /// For example, `Option<(usize, &T)>`  is represented such that
+    /// `None` has a null pointer for the second tuple field, and
+    /// `Some` is the identity function (with a non-null reference).
+    NicheFilling {
+        dataful_variant: usize,
+        niche_variants: RangeInclusive<usize>,
+        niche: Scalar,
+        niche_start: u128,
+        variants: Vec<LayoutDetails>,
+    }
+}
+
+#[derive(PartialEq, Eq, Hash, Debug)]
+pub struct LayoutDetails {
+    pub variants: Variants,
+    pub fields: FieldPlacement,
+    pub abi: Abi,
+    pub align: Align,
+    pub size: Size
+}
+
+impl LayoutDetails {
+    pub fn scalar<C: HasDataLayout>(cx: C, scalar: Scalar) -> Self {
+        let size = scalar.value.size(cx);
+        let align = scalar.value.align(cx);
+        LayoutDetails {
+            variants: Variants::Single { index: 0 },
+            fields: FieldPlacement::Union(0),
+            abi: Abi::Scalar(scalar),
+            size,
+            align,
+        }
+    }
+
+    pub fn uninhabited(field_count: usize) -> Self {
+        let align = Align::from_bytes(1, 1).unwrap();
+        LayoutDetails {
+            variants: Variants::Single { index: 0 },
+            fields: FieldPlacement::Union(field_count),
+            abi: Abi::Uninhabited,
+            align,
+            size: Size::from_bytes(0)
+        }
+    }
+}
+
+/// The details of the layout of a type, alongside the type itself.
+/// Provides various type traversal APIs (e.g. recursing into fields).
+///
+/// Note that the details are NOT guaranteed to always be identical
+/// to those obtained from `layout_of(ty)`, as we need to produce
+/// layouts for which Rust types do not exist, such as enum variants
+/// or synthetic fields of enums (i.e. discriminants) and fat pointers.
+#[derive(Copy, Clone, Debug)]
+pub struct TyLayout<'a, Ty> {
+    pub ty: Ty,
+    pub details: &'a LayoutDetails
+}
+
+impl<'a, Ty> Deref for TyLayout<'a, Ty> {
+    type Target = &'a LayoutDetails;
+    fn deref(&self) -> &&'a LayoutDetails {
+        &self.details
+    }
+}
+
+pub trait LayoutOf {
+    type Ty;
+    type TyLayout;
+
+    fn layout_of(self, ty: Self::Ty) -> Self::TyLayout;
+}
+
+pub trait TyLayoutMethods<'a, C: LayoutOf<Ty = Self>>: Sized {
+    fn for_variant(this: TyLayout<'a, Self>, cx: C, variant_index: usize) -> TyLayout<'a, Self>;
+    fn field(this: TyLayout<'a, Self>, cx: C, i: usize) -> C::TyLayout;
+}
+
+impl<'a, Ty> TyLayout<'a, Ty> {
+    pub fn for_variant<C>(self, cx: C, variant_index: usize) -> Self
+    where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> {
+        Ty::for_variant(self, cx, variant_index)
+    }
+    pub fn field<C>(self, cx: C, i: usize) -> C::TyLayout
+    where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> {
+        Ty::field(self, cx, i)
+    }
+}
+
+impl<'a, Ty> TyLayout<'a, Ty> {
+    /// Returns true if the layout corresponds to an unsized type.
+    pub fn is_unsized(&self) -> bool {
+        self.abi.is_unsized()
+    }
+
+    /// Returns true if the type is a ZST and not unsized.
+    pub fn is_zst(&self) -> bool {
+        match self.abi {
+            Abi::Uninhabited => true,
+            Abi::Scalar(_) |
+            Abi::ScalarPair(..) |
+            Abi::Vector { .. } => false,
+            Abi::Aggregate { sized } => sized && self.size.bytes() == 0
+        }
+    }
+
+    pub fn size_and_align(&self) -> (Size, Align) {
+        (self.size, self.align)
+    }
+}
diff --git a/src/librustc_back/build.rs b/src/librustc_target/build.rs
index 6f6fde1e9e7..6f6fde1e9e7 100644
--- a/src/librustc_back/build.rs
+++ b/src/librustc_target/build.rs
diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs
new file mode 100644
index 00000000000..8f491157439
--- /dev/null
+++ b/src/librustc_target/lib.rs
@@ -0,0 +1,46 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Some stuff used by rustc that doesn't have many dependencies
+//!
+//! Originally extracted from rustc::back, which was nominally the
+//! compiler 'backend', though LLVM is rustc's backend, so rustc_target
+//! is really just odds-and-ends relating to code gen and linking.
+//! This crate mostly exists to make rustc smaller, so we might put
+//! more 'stuff' here in the future.  It does not have a dependency on
+//! rustc_llvm.
+//!
+//! FIXME: Split this into two crates: one that has deps on syntax, and
+//! one that doesn't; the one that doesn't might get decent parallel
+//! build speedups.
+
+#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+      html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
+      html_root_url = "https://doc.rust-lang.org/nightly/")]
+
+#![feature(box_syntax)]
+#![feature(const_fn)]
+#![feature(fs_read_write)]
+#![feature(inclusive_range)]
+#![feature(slice_patterns)]
+
+#[macro_use]
+extern crate bitflags;
+extern crate serialize;
+#[macro_use] extern crate log;
+
+extern crate serialize as rustc_serialize; // used by deriving
+
+// See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
+#[allow(unused_extern_crates)]
+extern crate rustc_cratesio_shim;
+
+pub mod abi;
+pub mod spec;
diff --git a/src/librustc_back/target/aarch64_apple_ios.rs b/src/librustc_target/spec/aarch64_apple_ios.rs
index cff6eb534b1..90f8cd90c66 100644
--- a/src/librustc_back/target/aarch64_apple_ios.rs
+++ b/src/librustc_target/spec/aarch64_apple_ios.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 use super::apple_ios_base::{opts, Arch};
 
 pub fn target() -> TargetResult {
diff --git a/src/librustc_back/target/aarch64_linux_android.rs b/src/librustc_target/spec/aarch64_linux_android.rs
index 2c0d6a55ed8..afd67112f0d 100644
--- a/src/librustc_back/target/aarch64_linux_android.rs
+++ b/src/librustc_target/spec/aarch64_linux_android.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 // See https://developer.android.com/ndk/guides/abis.html#arm64-v8a
 // for target ABI requirements.
diff --git a/src/librustc_back/target/aarch64_unknown_cloudabi.rs b/src/librustc_target/spec/aarch64_unknown_cloudabi.rs
index a5d0e5bf166..ffdb7decd0b 100644
--- a/src/librustc_back/target/aarch64_unknown_cloudabi.rs
+++ b/src/librustc_target/spec/aarch64_unknown_cloudabi.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::cloudabi_base::opts();
diff --git a/src/librustc_back/target/aarch64_unknown_freebsd.rs b/src/librustc_target/spec/aarch64_unknown_freebsd.rs
index 1ce8d600c03..48177b8c79a 100644
--- a/src/librustc_back/target/aarch64_unknown_freebsd.rs
+++ b/src/librustc_target/spec/aarch64_unknown_freebsd.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::freebsd_base::opts();
diff --git a/src/librustc_back/target/aarch64_unknown_fuchsia.rs b/src/librustc_target/spec/aarch64_unknown_fuchsia.rs
index 73cd9c92701..4da6724ef62 100644
--- a/src/librustc_back/target/aarch64_unknown_fuchsia.rs
+++ b/src/librustc_target/spec/aarch64_unknown_fuchsia.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::fuchsia_base::opts();
diff --git a/src/librustc_back/target/aarch64_unknown_linux_gnu.rs b/src/librustc_target/spec/aarch64_unknown_linux_gnu.rs
index 5c9c9a0c555..2351d014692 100644
--- a/src/librustc_back/target/aarch64_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/aarch64_unknown_linux_gnu.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
diff --git a/src/librustc_back/target/aarch64_unknown_linux_musl.rs b/src/librustc_target/spec/aarch64_unknown_linux_musl.rs
index d39ad97bbcb..5ab55a076f4 100644
--- a/src/librustc_back/target/aarch64_unknown_linux_musl.rs
+++ b/src/librustc_target/spec/aarch64_unknown_linux_musl.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_musl_base::opts();
diff --git a/src/libsyntax/abi.rs b/src/librustc_target/spec/abi.rs
index ed2eb209906..ed2eb209906 100644
--- a/src/libsyntax/abi.rs
+++ b/src/librustc_target/spec/abi.rs
diff --git a/src/librustc_back/target/android_base.rs b/src/librustc_target/spec/android_base.rs
index 3660bf7bea9..7e27e8aa9a7 100644
--- a/src/librustc_back/target/android_base.rs
+++ b/src/librustc_target/spec/android_base.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::TargetOptions;
+use spec::{LinkerFlavor, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     let mut base = super::linux_base::opts();
diff --git a/src/librustc_back/target/apple_base.rs b/src/librustc_target/spec/apple_base.rs
index 480de9ff486..4b66891e36f 100644
--- a/src/librustc_back/target/apple_base.rs
+++ b/src/librustc_target/spec/apple_base.rs
@@ -10,7 +10,7 @@
 
 use std::env;
 
-use target::{LinkArgs, TargetOptions};
+use spec::{LinkArgs, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     // ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6
diff --git a/src/librustc_back/target/apple_ios_base.rs b/src/librustc_target/spec/apple_ios_base.rs
index 1895ab1eb7e..acbbab313fe 100644
--- a/src/librustc_back/target/apple_ios_base.rs
+++ b/src/librustc_target/spec/apple_ios_base.rs
@@ -8,10 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
 use std::io;
 use std::process::Command;
-use target::{LinkArgs, TargetOptions};
+use spec::{LinkArgs, LinkerFlavor, TargetOptions};
 
 use self::Arch::*;
 
diff --git a/src/librustc_back/target/arm_base.rs b/src/librustc_target/spec/arm_base.rs
index 416e5a0e13a..635b8ae7388 100644
--- a/src/librustc_back/target/arm_base.rs
+++ b/src/librustc_target/spec/arm_base.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use syntax::abi::Abi;
+use spec::abi::Abi;
 
 // All the calling conventions trigger an assertion(Unsupported calling convention) in llvm on arm
 pub fn abi_blacklist() -> Vec<Abi> {
diff --git a/src/librustc_back/target/arm_linux_androideabi.rs b/src/librustc_target/spec/arm_linux_androideabi.rs
index ba21b1df032..ffd242b2bc2 100644
--- a/src/librustc_back/target/arm_linux_androideabi.rs
+++ b/src/librustc_target/spec/arm_linux_androideabi.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::android_base::opts();
diff --git a/src/librustc_back/target/arm_unknown_linux_gnueabi.rs b/src/librustc_target/spec/arm_unknown_linux_gnueabi.rs
index e630376a67d..c67a25e8bc2 100644
--- a/src/librustc_back/target/arm_unknown_linux_gnueabi.rs
+++ b/src/librustc_target/spec/arm_unknown_linux_gnueabi.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
diff --git a/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs b/src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs
index 178a948b2b9..ed0049a932e 100644
--- a/src/librustc_back/target/arm_unknown_linux_gnueabihf.rs
+++ b/src/librustc_target/spec/arm_unknown_linux_gnueabihf.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
diff --git a/src/librustc_back/target/arm_unknown_linux_musleabi.rs b/src/librustc_target/spec/arm_unknown_linux_musleabi.rs
index 29720ec5efc..c34093fbab9 100644
--- a/src/librustc_back/target/arm_unknown_linux_musleabi.rs
+++ b/src/librustc_target/spec/arm_unknown_linux_musleabi.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_musl_base::opts();
diff --git a/src/librustc_back/target/arm_unknown_linux_musleabihf.rs b/src/librustc_target/spec/arm_unknown_linux_musleabihf.rs
index fc8313877f6..967873b3201 100644
--- a/src/librustc_back/target/arm_unknown_linux_musleabihf.rs
+++ b/src/librustc_target/spec/arm_unknown_linux_musleabihf.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_musl_base::opts();
diff --git a/src/librustc_back/target/armv4t_unknown_linux_gnueabi.rs b/src/librustc_target/spec/armv4t_unknown_linux_gnueabi.rs
index 33399a78493..fb99dffeddd 100644
--- a/src/librustc_back/target/armv4t_unknown_linux_gnueabi.rs
+++ b/src/librustc_target/spec/armv4t_unknown_linux_gnueabi.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let base = super::linux_base::opts();
diff --git a/src/librustc_back/target/armv5te_unknown_linux_gnueabi.rs b/src/librustc_target/spec/armv5te_unknown_linux_gnueabi.rs
index 4efe66980a0..810f0912472 100644
--- a/src/librustc_back/target/armv5te_unknown_linux_gnueabi.rs
+++ b/src/librustc_target/spec/armv5te_unknown_linux_gnueabi.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let base = super::linux_base::opts();
diff --git a/src/librustc_back/target/armv7_apple_ios.rs b/src/librustc_target/spec/armv7_apple_ios.rs
index 67d3d12fb57..da7cbb918bd 100644
--- a/src/librustc_back/target/armv7_apple_ios.rs
+++ b/src/librustc_target/spec/armv7_apple_ios.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 use super::apple_ios_base::{opts, Arch};
 
 pub fn target() -> TargetResult {
diff --git a/src/librustc_back/target/armv7_linux_androideabi.rs b/src/librustc_target/spec/armv7_linux_androideabi.rs
index 9e3eec13ab7..cfdc5cddcfb 100644
--- a/src/librustc_back/target/armv7_linux_androideabi.rs
+++ b/src/librustc_target/spec/armv7_linux_androideabi.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 // See https://developer.android.com/ndk/guides/abis.html#v7a
 // for target ABI requirements.
diff --git a/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs b/src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs
index fa66a35abbf..393c45e434e 100644
--- a/src/librustc_back/target/armv7_unknown_cloudabi_eabihf.rs
+++ b/src/librustc_target/spec/armv7_unknown_cloudabi_eabihf.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::cloudabi_base::opts();
diff --git a/src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs b/src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs
index 569c721473d..14e8fa9dc02 100644
--- a/src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs
+++ b/src/librustc_target/spec/armv7_unknown_linux_gnueabihf.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let base = super::linux_base::opts();
diff --git a/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs b/src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs
index 88f2b596751..6e71cb307b9 100644
--- a/src/librustc_back/target/armv7_unknown_linux_musleabihf.rs
+++ b/src/librustc_target/spec/armv7_unknown_linux_musleabihf.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     let base = super::linux_musl_base::opts();
diff --git a/src/librustc_back/target/armv7s_apple_ios.rs b/src/librustc_target/spec/armv7s_apple_ios.rs
index e4cc89ab211..c0c577c3b8c 100644
--- a/src/librustc_back/target/armv7s_apple_ios.rs
+++ b/src/librustc_target/spec/armv7s_apple_ios.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 use super::apple_ios_base::{opts, Arch};
 
 pub fn target() -> TargetResult {
diff --git a/src/librustc_back/target/asmjs_unknown_emscripten.rs b/src/librustc_target/spec/asmjs_unknown_emscripten.rs
index ab7df4ba1c5..e2cf714f0ea 100644
--- a/src/librustc_back/target/asmjs_unknown_emscripten.rs
+++ b/src/librustc_target/spec/asmjs_unknown_emscripten.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use super::{LinkArgs, Target, TargetOptions};
+use super::{LinkArgs, LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Result<Target, String> {
     let mut args = LinkArgs::new();
diff --git a/src/librustc_back/target/bitrig_base.rs b/src/librustc_target/spec/bitrig_base.rs
index 45ceb2d5a60..e0cbfcdcef0 100644
--- a/src/librustc_back/target/bitrig_base.rs
+++ b/src/librustc_target/spec/bitrig_base.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{TargetOptions, RelroLevel};
+use spec::{TargetOptions, RelroLevel};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
diff --git a/src/librustc_back/target/cloudabi_base.rs b/src/librustc_target/spec/cloudabi_base.rs
index 4cd52ebb26d..2ffa74e737f 100644
--- a/src/librustc_back/target/cloudabi_base.rs
+++ b/src/librustc_target/spec/cloudabi_base.rs
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{LinkArgs, TargetOptions, RelroLevel};
-use std::default::Default;
+use spec::{LinkArgs, LinkerFlavor, TargetOptions, RelroLevel};
 
 pub fn opts() -> TargetOptions {
     let mut args = LinkArgs::new();
diff --git a/src/librustc_back/target/dragonfly_base.rs b/src/librustc_target/spec/dragonfly_base.rs
index 21dca99aa50..32eac8663af 100644
--- a/src/librustc_back/target/dragonfly_base.rs
+++ b/src/librustc_target/spec/dragonfly_base.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{LinkArgs, TargetOptions, RelroLevel};
+use spec::{LinkArgs, LinkerFlavor, TargetOptions, RelroLevel};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
diff --git a/src/librustc_back/target/freebsd_base.rs b/src/librustc_target/spec/freebsd_base.rs
index 291b2276899..04b8a6e7060 100644
--- a/src/librustc_back/target/freebsd_base.rs
+++ b/src/librustc_target/spec/freebsd_base.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{LinkArgs, TargetOptions, RelroLevel};
+use spec::{LinkArgs, LinkerFlavor, TargetOptions, RelroLevel};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
diff --git a/src/librustc_back/target/fuchsia_base.rs b/src/librustc_target/spec/fuchsia_base.rs
index 63ccd21c220..19a66b693f2 100644
--- a/src/librustc_back/target/fuchsia_base.rs
+++ b/src/librustc_target/spec/fuchsia_base.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{LinkArgs, TargetOptions};
+use spec::{LinkArgs, LinkerFlavor, TargetOptions};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
diff --git a/src/librustc_back/target/haiku_base.rs b/src/librustc_target/spec/haiku_base.rs
index a1ccb632cab..bf62b49f914 100644
--- a/src/librustc_back/target/haiku_base.rs
+++ b/src/librustc_target/spec/haiku_base.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::{TargetOptions, RelroLevel};
+use spec::{TargetOptions, RelroLevel};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
diff --git a/src/librustc_back/target/i386_apple_ios.rs b/src/librustc_target/spec/i386_apple_ios.rs
index 82eae1a31a9..9eb0327f625 100644
--- a/src/librustc_back/target/i386_apple_ios.rs
+++ b/src/librustc_target/spec/i386_apple_ios.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 use super::apple_ios_base::{opts, Arch};
 
 pub fn target() -> TargetResult {
diff --git a/src/librustc_back/target/i586_pc_windows_msvc.rs b/src/librustc_target/spec/i586_pc_windows_msvc.rs
index 9b88cde5989..9a20b854e0f 100644
--- a/src/librustc_back/target/i586_pc_windows_msvc.rs
+++ b/src/librustc_target/spec/i586_pc_windows_msvc.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::TargetResult;
+use spec::TargetResult;
 
 pub fn target() -> TargetResult {
     let mut base = super::i686_pc_windows_msvc::target()?;
diff --git a/src/librustc_back/target/i586_unknown_linux_gnu.rs b/src/librustc_target/spec/i586_unknown_linux_gnu.rs
index 40fb4a67acd..35bca76af47 100644
--- a/src/librustc_back/target/i586_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/i586_unknown_linux_gnu.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::TargetResult;
+use spec::TargetResult;
 
 pub fn target() -> TargetResult {
     let mut base = super::i686_unknown_linux_gnu::target()?;
diff --git a/src/librustc_back/target/i586_unknown_linux_musl.rs b/src/librustc_target/spec/i586_unknown_linux_musl.rs
index 416eacf475b..ba23e1d6860 100644
--- a/src/librustc_back/target/i586_unknown_linux_musl.rs
+++ b/src/librustc_target/spec/i586_unknown_linux_musl.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::TargetResult;
+use spec::TargetResult;
 
 pub fn target() -> TargetResult {
     let mut base = super::i686_unknown_linux_musl::target()?;
diff --git a/src/librustc_back/target/i686_apple_darwin.rs b/src/librustc_target/spec/i686_apple_darwin.rs
index 14937f9aa55..06ea1e4649b 100644
--- a/src/librustc_back/target/i686_apple_darwin.rs
+++ b/src/librustc_target/spec/i686_apple_darwin.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::apple_base::opts();
diff --git a/src/librustc_back/target/i686_linux_android.rs b/src/librustc_target/spec/i686_linux_android.rs
index bf27bce79ac..171e0899595 100644
--- a/src/librustc_back/target/i686_linux_android.rs
+++ b/src/librustc_target/spec/i686_linux_android.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 // See https://developer.android.com/ndk/guides/abis.html#x86
 // for target ABI requirements.
diff --git a/src/librustc_back/target/i686_pc_windows_gnu.rs b/src/librustc_target/spec/i686_pc_windows_gnu.rs
index 5f20a620b6e..867d04ec3f2 100644
--- a/src/librustc_back/target/i686_pc_windows_gnu.rs
+++ b/src/librustc_target/spec/i686_pc_windows_gnu.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::windows_base::opts();
diff --git a/src/librustc_back/target/i686_pc_windows_msvc.rs b/src/librustc_target/spec/i686_pc_windows_msvc.rs
index 48cee044573..3570f379c30 100644
--- a/src/librustc_back/target/i686_pc_windows_msvc.rs
+++ b/src/librustc_target/spec/i686_pc_windows_msvc.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::windows_msvc_base::opts();
diff --git a/src/librustc_back/target/i686_unknown_cloudabi.rs b/src/librustc_target/spec/i686_unknown_cloudabi.rs
index 69c3b298cab..335105bb1a8 100644
--- a/src/librustc_back/target/i686_unknown_cloudabi.rs
+++ b/src/librustc_target/spec/i686_unknown_cloudabi.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::cloudabi_base::opts();
diff --git a/src/librustc_back/target/i686_unknown_dragonfly.rs b/src/librustc_target/spec/i686_unknown_dragonfly.rs
index 891127b9d37..cb0c471353b 100644
--- a/src/librustc_back/target/i686_unknown_dragonfly.rs
+++ b/src/librustc_target/spec/i686_unknown_dragonfly.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::dragonfly_base::opts();
diff --git a/src/librustc_back/target/i686_unknown_freebsd.rs b/src/librustc_target/spec/i686_unknown_freebsd.rs
index 076acb8ed31..3838a157d10 100644
--- a/src/librustc_back/target/i686_unknown_freebsd.rs
+++ b/src/librustc_target/spec/i686_unknown_freebsd.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::freebsd_base::opts();
diff --git a/src/librustc_back/target/i686_unknown_haiku.rs b/src/librustc_target/spec/i686_unknown_haiku.rs
index 02a15d6445c..98f0787beba 100644
--- a/src/librustc_back/target/i686_unknown_haiku.rs
+++ b/src/librustc_target/spec/i686_unknown_haiku.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::haiku_base::opts();
diff --git a/src/librustc_back/target/i686_unknown_linux_gnu.rs b/src/librustc_target/spec/i686_unknown_linux_gnu.rs
index b509e019c7e..c3ff347882d 100644
--- a/src/librustc_back/target/i686_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/i686_unknown_linux_gnu.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
diff --git a/src/librustc_back/target/i686_unknown_linux_musl.rs b/src/librustc_target/spec/i686_unknown_linux_musl.rs
index 99c0d4c8179..c02076c071a 100644
--- a/src/librustc_back/target/i686_unknown_linux_musl.rs
+++ b/src/librustc_target/spec/i686_unknown_linux_musl.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_musl_base::opts();
diff --git a/src/librustc_back/target/i686_unknown_netbsd.rs b/src/librustc_target/spec/i686_unknown_netbsd.rs
index dd21c205106..d60ed988599 100644
--- a/src/librustc_back/target/i686_unknown_netbsd.rs
+++ b/src/librustc_target/spec/i686_unknown_netbsd.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::netbsd_base::opts();
diff --git a/src/librustc_back/target/i686_unknown_openbsd.rs b/src/librustc_target/spec/i686_unknown_openbsd.rs
index 8daa5fcb88b..79c059c8f95 100644
--- a/src/librustc_back/target/i686_unknown_openbsd.rs
+++ b/src/librustc_target/spec/i686_unknown_openbsd.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::openbsd_base::opts();
diff --git a/src/librustc_back/target/l4re_base.rs b/src/librustc_target/spec/l4re_base.rs
index 3b13ef01500..4ebc930d48b 100644
--- a/src/librustc_back/target/l4re_base.rs
+++ b/src/librustc_target/spec/l4re_base.rs
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use PanicStrategy;
-use target::{LinkArgs, TargetOptions};
+use spec::{LinkArgs, LinkerFlavor, PanicStrategy, TargetOptions};
 use std::default::Default;
 //use std::process::Command;
 
diff --git a/src/librustc_back/target/linux_base.rs b/src/librustc_target/spec/linux_base.rs
index 52f700ac751..4a9cd9e2f32 100644
--- a/src/librustc_back/target/linux_base.rs
+++ b/src/librustc_target/spec/linux_base.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{LinkArgs, TargetOptions, RelroLevel};
+use spec::{LinkArgs, LinkerFlavor, TargetOptions, RelroLevel};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
diff --git a/src/librustc_back/target/linux_musl_base.rs b/src/librustc_target/spec/linux_musl_base.rs
index 6e5e139715c..293f23eab38 100644
--- a/src/librustc_back/target/linux_musl_base.rs
+++ b/src/librustc_target/spec/linux_musl_base.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::TargetOptions;
+use spec::{LinkerFlavor, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     let mut base = super::linux_base::opts();
diff --git a/src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs b/src/librustc_target/spec/mips64_unknown_linux_gnuabi64.rs
index 5c3cf31b3e4..1f60d918908 100644
--- a/src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs
+++ b/src/librustc_target/spec/mips64_unknown_linux_gnuabi64.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
diff --git a/src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs b/src/librustc_target/spec/mips64el_unknown_linux_gnuabi64.rs
index 96988388e81..e42fde8d403 100644
--- a/src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs
+++ b/src/librustc_target/spec/mips64el_unknown_linux_gnuabi64.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
diff --git a/src/librustc_back/target/mips_unknown_linux_gnu.rs b/src/librustc_target/spec/mips_unknown_linux_gnu.rs
index cffd1daed99..59e15137cf4 100644
--- a/src/librustc_back/target/mips_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/mips_unknown_linux_gnu.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
diff --git a/src/librustc_back/target/mips_unknown_linux_musl.rs b/src/librustc_target/spec/mips_unknown_linux_musl.rs
index 80168d4af4b..8ee399ba56c 100644
--- a/src/librustc_back/target/mips_unknown_linux_musl.rs
+++ b/src/librustc_target/spec/mips_unknown_linux_musl.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_musl_base::opts();
diff --git a/src/librustc_back/target/mips_unknown_linux_uclibc.rs b/src/librustc_target/spec/mips_unknown_linux_uclibc.rs
index c851cab069a..384ab1e4131 100644
--- a/src/librustc_back/target/mips_unknown_linux_uclibc.rs
+++ b/src/librustc_target/spec/mips_unknown_linux_uclibc.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
diff --git a/src/librustc_back/target/mipsel_unknown_linux_gnu.rs b/src/librustc_target/spec/mipsel_unknown_linux_gnu.rs
index 555855b8f81..edd29164cac 100644
--- a/src/librustc_back/target/mipsel_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/mipsel_unknown_linux_gnu.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
diff --git a/src/librustc_back/target/mipsel_unknown_linux_musl.rs b/src/librustc_target/spec/mipsel_unknown_linux_musl.rs
index 6bef2fe2ea7..1d9378ca1b8 100644
--- a/src/librustc_back/target/mipsel_unknown_linux_musl.rs
+++ b/src/librustc_target/spec/mipsel_unknown_linux_musl.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_musl_base::opts();
diff --git a/src/librustc_back/target/mipsel_unknown_linux_uclibc.rs b/src/librustc_target/spec/mipsel_unknown_linux_uclibc.rs
index a5dbdd11183..a1db1791bb7 100644
--- a/src/librustc_back/target/mipsel_unknown_linux_uclibc.rs
+++ b/src/librustc_target/spec/mipsel_unknown_linux_uclibc.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_target/spec/mod.rs
index e46266b576e..1e94f037885 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -49,10 +49,10 @@ use std::collections::BTreeMap;
 use std::default::Default;
 use std::{fmt, io};
 use std::path::{Path, PathBuf};
-use syntax::abi::{Abi, lookup as lookup_abi};
-
-use {LinkerFlavor, PanicStrategy, RelroLevel};
+use std::str::FromStr;
+use spec::abi::{Abi, lookup as lookup_abi};
 
+pub mod abi;
 mod android_base;
 mod apple_base;
 mod apple_ios_base;
@@ -74,6 +74,133 @@ mod l4re_base;
 mod fuchsia_base;
 mod redox_base;
 
+#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash,
+         RustcEncodable, RustcDecodable)]
+pub enum LinkerFlavor {
+    Em,
+    Gcc,
+    Ld,
+    Msvc,
+    Lld(LldFlavor),
+}
+
+#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash,
+         RustcEncodable, RustcDecodable)]
+pub enum LldFlavor {
+    Wasm,
+    Ld64,
+    Ld,
+    Link,
+}
+
+impl ToJson for LinkerFlavor {
+    fn to_json(&self) -> Json {
+        self.desc().to_json()
+    }
+}
+macro_rules! flavor_mappings {
+    ($((($($flavor:tt)*), $string:expr),)*) => (
+        impl LinkerFlavor {
+            pub const fn one_of() -> &'static str {
+                concat!("one of: ", $($string, " ",)+)
+            }
+
+            pub fn from_str(s: &str) -> Option<Self> {
+                Some(match s {
+                    $($string => $($flavor)*,)+
+                    _ => return None,
+                })
+            }
+
+            pub fn desc(&self) -> &str {
+                match *self {
+                    $($($flavor)* => $string,)+
+                }
+            }
+        }
+    )
+}
+
+
+flavor_mappings! {
+    ((LinkerFlavor::Em), "em"),
+    ((LinkerFlavor::Gcc), "gcc"),
+    ((LinkerFlavor::Ld), "ld"),
+    ((LinkerFlavor::Msvc), "msvc"),
+    ((LinkerFlavor::Lld(LldFlavor::Wasm)), "wasm-ld"),
+    ((LinkerFlavor::Lld(LldFlavor::Ld64)), "ld64.lld"),
+    ((LinkerFlavor::Lld(LldFlavor::Ld)), "ld.lld"),
+    ((LinkerFlavor::Lld(LldFlavor::Link)), "lld-link"),
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+pub enum PanicStrategy {
+    Unwind,
+    Abort,
+}
+
+impl PanicStrategy {
+    pub fn desc(&self) -> &str {
+        match *self {
+            PanicStrategy::Unwind => "unwind",
+            PanicStrategy::Abort => "abort",
+        }
+    }
+}
+
+impl ToJson for PanicStrategy {
+    fn to_json(&self) -> Json {
+        match *self {
+            PanicStrategy::Abort => "abort".to_json(),
+            PanicStrategy::Unwind => "unwind".to_json(),
+        }
+    }
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+pub enum RelroLevel {
+    Full,
+    Partial,
+    Off,
+    None,
+}
+
+impl RelroLevel {
+    pub fn desc(&self) -> &str {
+        match *self {
+            RelroLevel::Full => "full",
+            RelroLevel::Partial => "partial",
+            RelroLevel::Off => "off",
+            RelroLevel::None => "none",
+        }
+    }
+}
+
+impl FromStr for RelroLevel {
+    type Err = ();
+
+    fn from_str(s: &str) -> Result<RelroLevel, ()> {
+        match s {
+            "full" => Ok(RelroLevel::Full),
+            "partial" => Ok(RelroLevel::Partial),
+            "off" => Ok(RelroLevel::Off),
+            "none" => Ok(RelroLevel::None),
+            _ => Err(()),
+        }
+    }
+}
+
+impl ToJson for RelroLevel {
+    fn to_json(&self) -> Json {
+        match *self {
+            RelroLevel::Full => "full".to_json(),
+            RelroLevel::Partial => "partial".to_json(),
+            RelroLevel::Off => "off".to_json(),
+            RelroLevel::None => "None".to_json(),
+        }
+    }
+}
+
 pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<String>>;
 pub type TargetResult = Result<Target, String>;
 
@@ -271,6 +398,16 @@ pub struct Target {
     pub options: TargetOptions,
 }
 
+pub trait HasTargetSpec: Copy {
+    fn target_spec(&self) -> &Target;
+}
+
+impl<'a> HasTargetSpec for &'a Target {
+    fn target_spec(&self) -> &Target {
+        self
+    }
+}
+
 /// Optional aspects of a target specification.
 ///
 /// This has an implementation of `Default`, see each field for what the default is. In general,
diff --git a/src/librustc_back/target/msp430_none_elf.rs b/src/librustc_target/spec/msp430_none_elf.rs
index 31df9be0bc3..ce42a908b0e 100644
--- a/src/librustc_back/target/msp430_none_elf.rs
+++ b/src/librustc_target/spec/msp430_none_elf.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use {LinkerFlavor, PanicStrategy};
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
diff --git a/src/librustc_back/target/netbsd_base.rs b/src/librustc_target/spec/netbsd_base.rs
index 1cb31137193..8b6bb5dec91 100644
--- a/src/librustc_back/target/netbsd_base.rs
+++ b/src/librustc_target/spec/netbsd_base.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{LinkArgs, TargetOptions, RelroLevel};
+use spec::{LinkArgs, LinkerFlavor, TargetOptions, RelroLevel};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
diff --git a/src/librustc_back/target/openbsd_base.rs b/src/librustc_target/spec/openbsd_base.rs
index 311e260ee3f..90ab1135c54 100644
--- a/src/librustc_back/target/openbsd_base.rs
+++ b/src/librustc_target/spec/openbsd_base.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{LinkArgs, TargetOptions, RelroLevel};
+use spec::{LinkArgs, LinkerFlavor, TargetOptions, RelroLevel};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
diff --git a/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs b/src/librustc_target/spec/powerpc64_unknown_linux_gnu.rs
index 1f119c7204b..19598711613 100644
--- a/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/powerpc64_unknown_linux_gnu.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult, RelroLevel};
+use spec::{LinkerFlavor, Target, TargetResult, RelroLevel};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
diff --git a/src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs b/src/librustc_target/spec/powerpc64le_unknown_linux_gnu.rs
index 13c59785d48..39840692dff 100644
--- a/src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/powerpc64le_unknown_linux_gnu.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
diff --git a/src/librustc_back/target/powerpc_unknown_linux_gnu.rs b/src/librustc_target/spec/powerpc_unknown_linux_gnu.rs
index 1797126b310..c05b110a75d 100644
--- a/src/librustc_back/target/powerpc_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/powerpc_unknown_linux_gnu.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
diff --git a/src/librustc_back/target/powerpc_unknown_linux_gnuspe.rs b/src/librustc_target/spec/powerpc_unknown_linux_gnuspe.rs
index ffcc321749b..c76c3119c87 100644
--- a/src/librustc_back/target/powerpc_unknown_linux_gnuspe.rs
+++ b/src/librustc_target/spec/powerpc_unknown_linux_gnuspe.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
diff --git a/src/librustc_back/target/powerpc_unknown_netbsd.rs b/src/librustc_target/spec/powerpc_unknown_netbsd.rs
index 2c78dbd2061..c05e40b9c25 100644
--- a/src/librustc_back/target/powerpc_unknown_netbsd.rs
+++ b/src/librustc_target/spec/powerpc_unknown_netbsd.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::netbsd_base::opts();
diff --git a/src/librustc_back/target/redox_base.rs b/src/librustc_target/spec/redox_base.rs
index c7915d4de72..c28746a9363 100644
--- a/src/librustc_back/target/redox_base.rs
+++ b/src/librustc_target/spec/redox_base.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{LinkArgs, TargetOptions};
+use spec::{LinkArgs, LinkerFlavor, TargetOptions};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
diff --git a/src/librustc_back/target/s390x_unknown_linux_gnu.rs b/src/librustc_target/spec/s390x_unknown_linux_gnu.rs
index d96379547fb..c9a9625ebab 100644
--- a/src/librustc_back/target/s390x_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/s390x_unknown_linux_gnu.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
diff --git a/src/librustc_back/target/solaris_base.rs b/src/librustc_target/spec/solaris_base.rs
index 41323c9c26b..c14cc3f5bc3 100644
--- a/src/librustc_back/target/solaris_base.rs
+++ b/src/librustc_target/spec/solaris_base.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use target::TargetOptions;
+use spec::TargetOptions;
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
diff --git a/src/librustc_back/target/sparc64_unknown_linux_gnu.rs b/src/librustc_target/spec/sparc64_unknown_linux_gnu.rs
index aed40e9df43..f68b5fd24bf 100644
--- a/src/librustc_back/target/sparc64_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/sparc64_unknown_linux_gnu.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
diff --git a/src/librustc_back/target/sparc64_unknown_netbsd.rs b/src/librustc_target/spec/sparc64_unknown_netbsd.rs
index 483c8790945..1c1bca9b2b8 100644
--- a/src/librustc_back/target/sparc64_unknown_netbsd.rs
+++ b/src/librustc_target/spec/sparc64_unknown_netbsd.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::netbsd_base::opts();
diff --git a/src/librustc_back/target/sparc_unknown_linux_gnu.rs b/src/librustc_target/spec/sparc_unknown_linux_gnu.rs
index a03e6937b2c..4e352374f90 100644
--- a/src/librustc_back/target/sparc_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/sparc_unknown_linux_gnu.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
diff --git a/src/librustc_back/target/sparcv9_sun_solaris.rs b/src/librustc_target/spec/sparcv9_sun_solaris.rs
index 1d9027275db..7dea1b75a3c 100644
--- a/src/librustc_back/target/sparcv9_sun_solaris.rs
+++ b/src/librustc_target/spec/sparcv9_sun_solaris.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::solaris_base::opts();
diff --git a/src/librustc_back/target/thumb_base.rs b/src/librustc_target/spec/thumb_base.rs
index bb1fbfad261..fdaf1dc6110 100644
--- a/src/librustc_back/target/thumb_base.rs
+++ b/src/librustc_target/spec/thumb_base.rs
@@ -35,9 +35,8 @@
 // differentiate these targets from our other `arm(v7)-*-*-gnueabi(hf)` targets in the context of
 // build scripts / gcc flags.
 
-use PanicStrategy;
 use std::default::Default;
-use target::TargetOptions;
+use spec::{PanicStrategy, TargetOptions};
 
 pub fn opts() -> TargetOptions {
     // See rust-lang/rfcs#1645 for a discussion about these defaults
diff --git a/src/librustc_back/target/thumbv6m_none_eabi.rs b/src/librustc_target/spec/thumbv6m_none_eabi.rs
index d164fbf9d96..9fea07c36f4 100644
--- a/src/librustc_back/target/thumbv6m_none_eabi.rs
+++ b/src/librustc_target/spec/thumbv6m_none_eabi.rs
@@ -10,8 +10,7 @@
 
 // Targets the Cortex-M0, Cortex-M0+ and Cortex-M1 processors (ARMv6-M architecture)
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
diff --git a/src/librustc_back/target/thumbv7em_none_eabi.rs b/src/librustc_target/spec/thumbv7em_none_eabi.rs
index 7e66ddf7b06..ab85c97b1b5 100644
--- a/src/librustc_back/target/thumbv7em_none_eabi.rs
+++ b/src/librustc_target/spec/thumbv7em_none_eabi.rs
@@ -19,8 +19,7 @@
 // To opt-in to hardware accelerated floating point operations, you can use, for example,
 // `-C target-feature=+vfp4` or `-C target-cpu=cortex-m4`.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
diff --git a/src/librustc_back/target/thumbv7em_none_eabihf.rs b/src/librustc_target/spec/thumbv7em_none_eabihf.rs
index 31835de36d6..4e62f29134e 100644
--- a/src/librustc_back/target/thumbv7em_none_eabihf.rs
+++ b/src/librustc_target/spec/thumbv7em_none_eabihf.rs
@@ -18,8 +18,7 @@
 //
 // To opt into double precision hardware support, use the `-C target-feature=-fp-only-sp` flag.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
diff --git a/src/librustc_back/target/thumbv7m_none_eabi.rs b/src/librustc_target/spec/thumbv7m_none_eabi.rs
index 8f16ae4ea12..10dc503388a 100644
--- a/src/librustc_back/target/thumbv7m_none_eabi.rs
+++ b/src/librustc_target/spec/thumbv7m_none_eabi.rs
@@ -10,8 +10,7 @@
 
 // Targets the Cortex-M3 processor (ARMv7-M)
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 
 pub fn target() -> TargetResult {
     Ok(Target {
diff --git a/src/librustc_back/target/wasm32_experimental_emscripten.rs b/src/librustc_target/spec/wasm32_experimental_emscripten.rs
index 13dee3a5768..164df20f84f 100644
--- a/src/librustc_back/target/wasm32_experimental_emscripten.rs
+++ b/src/librustc_target/spec/wasm32_experimental_emscripten.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use super::{LinkArgs, Target, TargetOptions};
+use super::{LinkArgs, LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Result<Target, String> {
     let mut post_link_args = LinkArgs::new();
diff --git a/src/librustc_back/target/wasm32_unknown_emscripten.rs b/src/librustc_target/spec/wasm32_unknown_emscripten.rs
index 2770e67e30a..5077abf1e0e 100644
--- a/src/librustc_back/target/wasm32_unknown_emscripten.rs
+++ b/src/librustc_target/spec/wasm32_unknown_emscripten.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use super::{LinkArgs, Target, TargetOptions};
+use super::{LinkArgs, LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Result<Target, String> {
     let mut post_link_args = LinkArgs::new();
diff --git a/src/librustc_back/target/wasm32_unknown_unknown.rs b/src/librustc_target/spec/wasm32_unknown_unknown.rs
index 1d84e137517..56170bbb869 100644
--- a/src/librustc_back/target/wasm32_unknown_unknown.rs
+++ b/src/librustc_target/spec/wasm32_unknown_unknown.rs
@@ -17,8 +17,7 @@
 // (aka panic=abort by default), but otherwise this is in general a relatively
 // standard target.
 
-use {LinkerFlavor, LldFlavor};
-use super::{Target, TargetOptions, PanicStrategy};
+use super::{LldFlavor, LinkerFlavor, Target, TargetOptions, PanicStrategy};
 
 pub fn target() -> Result<Target, String> {
     let opts = TargetOptions {
diff --git a/src/librustc_back/target/windows_base.rs b/src/librustc_target/spec/windows_base.rs
index 4b4fb27caa8..176df9f1325 100644
--- a/src/librustc_back/target/windows_base.rs
+++ b/src/librustc_target/spec/windows_base.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{LinkArgs, TargetOptions};
+use spec::{LinkArgs, LinkerFlavor, TargetOptions};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
diff --git a/src/librustc_back/target/windows_msvc_base.rs b/src/librustc_target/spec/windows_msvc_base.rs
index fee5a0284c8..1f00e690cd3 100644
--- a/src/librustc_back/target/windows_msvc_base.rs
+++ b/src/librustc_target/spec/windows_msvc_base.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{LinkArgs, TargetOptions};
+use spec::{LinkArgs, LinkerFlavor, TargetOptions};
 use std::default::Default;
 
 pub fn opts() -> TargetOptions {
diff --git a/src/librustc_back/target/x86_64_apple_darwin.rs b/src/librustc_target/spec/x86_64_apple_darwin.rs
index 71ac360eb99..a4efd7e0066 100644
--- a/src/librustc_back/target/x86_64_apple_darwin.rs
+++ b/src/librustc_target/spec/x86_64_apple_darwin.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::apple_base::opts();
diff --git a/src/librustc_back/target/x86_64_apple_ios.rs b/src/librustc_target/spec/x86_64_apple_ios.rs
index eed99e3784c..eeb53d72fe8 100644
--- a/src/librustc_back/target/x86_64_apple_ios.rs
+++ b/src/librustc_target/spec/x86_64_apple_ios.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetOptions, TargetResult};
+use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
 use super::apple_ios_base::{opts, Arch};
 
 pub fn target() -> TargetResult {
diff --git a/src/librustc_back/target/x86_64_linux_android.rs b/src/librustc_target/spec/x86_64_linux_android.rs
index 2aae7394153..06abe916784 100644
--- a/src/librustc_back/target/x86_64_linux_android.rs
+++ b/src/librustc_target/spec/x86_64_linux_android.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::android_base::opts();
diff --git a/src/librustc_back/target/x86_64_pc_windows_gnu.rs b/src/librustc_target/spec/x86_64_pc_windows_gnu.rs
index 70062d13638..8d2f702bc4a 100644
--- a/src/librustc_back/target/x86_64_pc_windows_gnu.rs
+++ b/src/librustc_target/spec/x86_64_pc_windows_gnu.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::windows_base::opts();
diff --git a/src/librustc_back/target/x86_64_pc_windows_msvc.rs b/src/librustc_target/spec/x86_64_pc_windows_msvc.rs
index 813d0f1bad9..ab610ea94ae 100644
--- a/src/librustc_back/target/x86_64_pc_windows_msvc.rs
+++ b/src/librustc_target/spec/x86_64_pc_windows_msvc.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::windows_msvc_base::opts();
diff --git a/src/librustc_back/target/x86_64_rumprun_netbsd.rs b/src/librustc_target/spec/x86_64_rumprun_netbsd.rs
index 3158665a2e2..ed15cfd9036 100644
--- a/src/librustc_back/target/x86_64_rumprun_netbsd.rs
+++ b/src/librustc_target/spec/x86_64_rumprun_netbsd.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::netbsd_base::opts();
diff --git a/src/librustc_back/target/x86_64_sun_solaris.rs b/src/librustc_target/spec/x86_64_sun_solaris.rs
index d5541385390..e84f21c5006 100644
--- a/src/librustc_back/target/x86_64_sun_solaris.rs
+++ b/src/librustc_target/spec/x86_64_sun_solaris.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::solaris_base::opts();
diff --git a/src/librustc_back/target/x86_64_unknown_bitrig.rs b/src/librustc_target/spec/x86_64_unknown_bitrig.rs
index 1ea985d70ea..21ec6dffcbb 100644
--- a/src/librustc_back/target/x86_64_unknown_bitrig.rs
+++ b/src/librustc_target/spec/x86_64_unknown_bitrig.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::bitrig_base::opts();
diff --git a/src/librustc_back/target/x86_64_unknown_cloudabi.rs b/src/librustc_target/spec/x86_64_unknown_cloudabi.rs
index d1a9cb1cd7e..8dc8bd7a7fa 100644
--- a/src/librustc_back/target/x86_64_unknown_cloudabi.rs
+++ b/src/librustc_target/spec/x86_64_unknown_cloudabi.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::cloudabi_base::opts();
diff --git a/src/librustc_back/target/x86_64_unknown_dragonfly.rs b/src/librustc_target/spec/x86_64_unknown_dragonfly.rs
index 56e4685fed5..50b2871c2ee 100644
--- a/src/librustc_back/target/x86_64_unknown_dragonfly.rs
+++ b/src/librustc_target/spec/x86_64_unknown_dragonfly.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::dragonfly_base::opts();
diff --git a/src/librustc_back/target/x86_64_unknown_freebsd.rs b/src/librustc_target/spec/x86_64_unknown_freebsd.rs
index 3d26592530a..f0aa81ed459 100644
--- a/src/librustc_back/target/x86_64_unknown_freebsd.rs
+++ b/src/librustc_target/spec/x86_64_unknown_freebsd.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::freebsd_base::opts();
diff --git a/src/librustc_back/target/x86_64_unknown_fuchsia.rs b/src/librustc_target/spec/x86_64_unknown_fuchsia.rs
index 6e97d53cfad..a510ec8eb34 100644
--- a/src/librustc_back/target/x86_64_unknown_fuchsia.rs
+++ b/src/librustc_target/spec/x86_64_unknown_fuchsia.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::fuchsia_base::opts();
diff --git a/src/librustc_back/target/x86_64_unknown_haiku.rs b/src/librustc_target/spec/x86_64_unknown_haiku.rs
index f42c480e7a1..1e78461861a 100644
--- a/src/librustc_back/target/x86_64_unknown_haiku.rs
+++ b/src/librustc_target/spec/x86_64_unknown_haiku.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::haiku_base::opts();
diff --git a/src/librustc_back/target/x86_64_unknown_l4re_uclibc.rs b/src/librustc_target/spec/x86_64_unknown_l4re_uclibc.rs
index 821a77f52f5..f1179c18294 100644
--- a/src/librustc_back/target/x86_64_unknown_l4re_uclibc.rs
+++ b/src/librustc_target/spec/x86_64_unknown_l4re_uclibc.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::l4re_base::opts();
diff --git a/src/librustc_back/target/x86_64_unknown_linux_gnu.rs b/src/librustc_target/spec/x86_64_unknown_linux_gnu.rs
index cfe80c96732..56559661b03 100644
--- a/src/librustc_back/target/x86_64_unknown_linux_gnu.rs
+++ b/src/librustc_target/spec/x86_64_unknown_linux_gnu.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
diff --git a/src/librustc_back/target/x86_64_unknown_linux_gnux32.rs b/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs
index 70382032836..72b5bd27c7d 100644
--- a/src/librustc_back/target/x86_64_unknown_linux_gnux32.rs
+++ b/src/librustc_target/spec/x86_64_unknown_linux_gnux32.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
diff --git a/src/librustc_back/target/x86_64_unknown_linux_musl.rs b/src/librustc_target/spec/x86_64_unknown_linux_musl.rs
index 7e304748e32..f1924efcf98 100644
--- a/src/librustc_back/target/x86_64_unknown_linux_musl.rs
+++ b/src/librustc_target/spec/x86_64_unknown_linux_musl.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::linux_musl_base::opts();
diff --git a/src/librustc_back/target/x86_64_unknown_netbsd.rs b/src/librustc_target/spec/x86_64_unknown_netbsd.rs
index 7afb446f5dc..6e8ca6b9e19 100644
--- a/src/librustc_back/target/x86_64_unknown_netbsd.rs
+++ b/src/librustc_target/spec/x86_64_unknown_netbsd.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::netbsd_base::opts();
diff --git a/src/librustc_back/target/x86_64_unknown_openbsd.rs b/src/librustc_target/spec/x86_64_unknown_openbsd.rs
index e4bbdbec4c8..c60b7c86680 100644
--- a/src/librustc_back/target/x86_64_unknown_openbsd.rs
+++ b/src/librustc_target/spec/x86_64_unknown_openbsd.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::openbsd_base::opts();
diff --git a/src/librustc_back/target/x86_64_unknown_redox.rs b/src/librustc_target/spec/x86_64_unknown_redox.rs
index 401fa4ca2cb..548dfb06109 100644
--- a/src/librustc_back/target/x86_64_unknown_redox.rs
+++ b/src/librustc_target/spec/x86_64_unknown_redox.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use LinkerFlavor;
-use target::{Target, TargetResult};
+use spec::{LinkerFlavor, Target, TargetResult};
 
 pub fn target() -> TargetResult {
     let mut base = super::redox_base::opts();
diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml
index 176fd86f29d..32432d6cc83 100644
--- a/src/librustc_trans/Cargo.toml
+++ b/src/librustc_trans/Cargo.toml
@@ -10,7 +10,6 @@ crate-type = ["dylib"]
 test = false
 
 [dependencies]
-bitflags = "1.0"
 cc = "1.0.1"
 flate2 = "1.0"
 jobserver = "0.1.5"
@@ -21,7 +20,7 @@ rustc = { path = "../librustc" }
 rustc-demangle = "0.1.4"
 rustc_allocator = { path = "../librustc_allocator" }
 rustc_apfloat = { path = "../librustc_apfloat" }
-rustc_back = { path = "../librustc_back" }
+rustc_target = { path = "../librustc_target" }
 rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
@@ -40,9 +39,9 @@ tempdir = "0.3"
 env_logger = { version = "0.5", default-features = false }
 
 [features]
-# Used to communicate the feature to `rustc_back` in the same manner that the
+# Used to communicate the feature to `rustc_target` in the same manner that the
 # `rustc` driver script communicate this.
-jemalloc = ["rustc_back/jemalloc"]
+jemalloc = ["rustc_target/jemalloc"]
 
 # This is used to convince Cargo to separately cache builds of `rustc_trans`
 # when this option is enabled or not. That way we can build two, cache two
diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs
index 19ae1fa0478..483f36afe27 100644
--- a/src/librustc_trans/abi.rs
+++ b/src/librustc_trans/abi.rs
@@ -13,77 +13,20 @@ use base;
 use builder::Builder;
 use common::{ty_fn_sig, C_usize};
 use context::CodegenCx;
-use cabi_x86;
-use cabi_x86_64;
-use cabi_x86_win64;
-use cabi_arm;
-use cabi_aarch64;
-use cabi_powerpc;
-use cabi_powerpc64;
-use cabi_s390x;
-use cabi_mips;
-use cabi_mips64;
-use cabi_asmjs;
-use cabi_msp430;
-use cabi_sparc;
-use cabi_sparc64;
-use cabi_nvptx;
-use cabi_nvptx64;
-use cabi_hexagon;
-use cabi_wasm32;
 use mir::place::PlaceRef;
 use mir::operand::OperandValue;
 use type_::Type;
 use type_of::{LayoutLlvmExt, PointerKind};
 
+use rustc_target::abi::{LayoutOf, Size, TyLayout};
 use rustc::ty::{self, Ty};
-use rustc::ty::layout::{self, Align, Size, TyLayout};
-use rustc::ty::layout::{HasDataLayout, LayoutOf};
+use rustc::ty::layout;
 
 use libc::c_uint;
-use std::cmp;
 
-pub use syntax::abi::Abi;
+pub use rustc_target::spec::abi::Abi;
 pub use rustc::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
-
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
-pub enum PassMode {
-    /// Ignore the argument (useful for empty struct).
-    Ignore,
-    /// Pass the argument directly.
-    Direct(ArgAttributes),
-    /// Pass a pair's elements directly in two arguments.
-    Pair(ArgAttributes, ArgAttributes),
-    /// Pass the argument after casting it, to either
-    /// a single uniform or a pair of registers.
-    Cast(CastTarget),
-    /// Pass the argument indirectly via a hidden pointer.
-    Indirect(ArgAttributes),
-}
-
-// Hack to disable non_upper_case_globals only for the bitflags! and not for the rest
-// of this module
-pub use self::attr_impl::ArgAttribute;
-
-#[allow(non_upper_case_globals)]
-#[allow(unused)]
-mod attr_impl {
-    // The subset of llvm::Attribute needed for arguments, packed into a bitfield.
-    bitflags! {
-        #[derive(Default)]
-        pub struct ArgAttribute: u16 {
-            const ByVal     = 1 << 0;
-            const NoAlias   = 1 << 1;
-            const NoCapture = 1 << 2;
-            const NonNull   = 1 << 3;
-            const ReadOnly  = 1 << 4;
-            const SExt      = 1 << 5;
-            const StructRet = 1 << 6;
-            const ZExt      = 1 << 7;
-            const InReg     = 1 << 8;
-        }
-    }
-}
+pub use rustc_target::abi::call::*;
 
 macro_rules! for_each_kind {
     ($flags: ident, $f: ident, $($kind: ident),+) => ({
@@ -91,41 +34,24 @@ macro_rules! for_each_kind {
     })
 }
 
-impl ArgAttribute {
+trait ArgAttributeExt {
+    fn for_each_kind<F>(&self, f: F) where F: FnMut(llvm::Attribute);
+}
+
+impl ArgAttributeExt for ArgAttribute {
     fn for_each_kind<F>(&self, mut f: F) where F: FnMut(llvm::Attribute) {
         for_each_kind!(self, f,
                        ByVal, NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt, InReg)
     }
 }
 
-/// A compact representation of LLVM attributes (at least those relevant for this module)
-/// that can be manipulated without interacting with LLVM's Attribute machinery.
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub struct ArgAttributes {
-    regular: ArgAttribute,
-    pointee_size: Size,
-    pointee_align: Option<Align>
+pub trait ArgAttributesExt {
+    fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef);
+    fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef);
 }
 
-impl ArgAttributes {
-    fn new() -> Self {
-        ArgAttributes {
-            regular: ArgAttribute::default(),
-            pointee_size: Size::from_bytes(0),
-            pointee_align: None,
-        }
-    }
-
-    pub fn set(&mut self, attr: ArgAttribute) -> &mut Self {
-        self.regular = self.regular | attr;
-        self
-    }
-
-    pub fn contains(&self, attr: ArgAttribute) -> bool {
-        self.regular.contains(attr)
-    }
-
-    pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
+impl ArgAttributesExt for ArgAttributes {
+    fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) {
         let mut regular = self.regular;
         unsafe {
             let deref = self.pointee_size.bytes();
@@ -150,7 +76,7 @@ impl ArgAttributes {
         }
     }
 
-    pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
+    fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) {
         let mut regular = self.regular;
         unsafe {
             let deref = self.pointee_size.bytes();
@@ -175,67 +101,13 @@ impl ArgAttributes {
         }
     }
 }
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum RegKind {
-    Integer,
-    Float,
-    Vector
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub struct Reg {
-    pub kind: RegKind,
-    pub size: Size,
-}
-
-macro_rules! reg_ctor {
-    ($name:ident, $kind:ident, $bits:expr) => {
-        pub fn $name() -> Reg {
-            Reg {
-                kind: RegKind::$kind,
-                size: Size::from_bits($bits)
-            }
-        }
-    }
-}
-
-impl Reg {
-    reg_ctor!(i8, Integer, 8);
-    reg_ctor!(i16, Integer, 16);
-    reg_ctor!(i32, Integer, 32);
-    reg_ctor!(i64, Integer, 64);
 
-    reg_ctor!(f32, Float, 32);
-    reg_ctor!(f64, Float, 64);
+pub trait LlvmType {
+    fn llvm_type(&self, cx: &CodegenCx) -> Type;
 }
 
-impl Reg {
-    pub fn align(&self, cx: &CodegenCx) -> Align {
-        let dl = cx.data_layout();
-        match self.kind {
-            RegKind::Integer => {
-                match self.size.bits() {
-                    1 => dl.i1_align,
-                    2...8 => dl.i8_align,
-                    9...16 => dl.i16_align,
-                    17...32 => dl.i32_align,
-                    33...64 => dl.i64_align,
-                    65...128 => dl.i128_align,
-                    _ => bug!("unsupported integer: {:?}", self)
-                }
-            }
-            RegKind::Float => {
-                match self.size.bits() {
-                    32 => dl.f32_align,
-                    64 => dl.f64_align,
-                    _ => bug!("unsupported float: {:?}", self)
-                }
-            }
-            RegKind::Vector => dl.vector_align(self.size)
-        }
-    }
-
-    pub fn llvm_type(&self, cx: &CodegenCx) -> Type {
+impl LlvmType for Reg {
+    fn llvm_type(&self, cx: &CodegenCx) -> Type {
         match self.kind {
             RegKind::Integer => Type::ix(cx, self.size.bits()),
             RegKind::Float => {
@@ -252,180 +124,8 @@ impl Reg {
     }
 }
 
-/// An argument passed entirely registers with the
-/// same kind (e.g. HFA / HVA on PPC64 and AArch64).
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
-pub struct Uniform {
-    pub unit: Reg,
-
-    /// The total size of the argument, which can be:
-    /// * equal to `unit.size` (one scalar/vector)
-    /// * a multiple of `unit.size` (an array of scalar/vectors)
-    /// * if `unit.kind` is `Integer`, the last element
-    ///   can be shorter, i.e. `{ i64, i64, i32 }` for
-    ///   64-bit integers with a total size of 20 bytes
-    pub total: Size,
-}
-
-impl From<Reg> for Uniform {
-    fn from(unit: Reg) -> Uniform {
-        Uniform {
-            unit,
-            total: unit.size
-        }
-    }
-}
-
-impl Uniform {
-    pub fn align(&self, cx: &CodegenCx) -> Align {
-        self.unit.align(cx)
-    }
-}
-
-pub trait LayoutExt<'tcx> {
-    fn is_aggregate(&self) -> bool;
-    fn homogeneous_aggregate<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Option<Reg>;
-}
-
-impl<'tcx> LayoutExt<'tcx> for TyLayout<'tcx> {
-    fn is_aggregate(&self) -> bool {
-        match self.abi {
-            layout::Abi::Uninhabited |
-            layout::Abi::Scalar(_) |
-            layout::Abi::Vector { .. } => false,
-            layout::Abi::ScalarPair(..) |
-            layout::Abi::Aggregate { .. } => true
-        }
-    }
-
-    fn homogeneous_aggregate<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Option<Reg> {
-        match self.abi {
-            layout::Abi::Uninhabited => None,
-
-            // The primitive for this algorithm.
-            layout::Abi::Scalar(ref scalar) => {
-                let kind = match scalar.value {
-                    layout::Int(..) |
-                    layout::Pointer => RegKind::Integer,
-                    layout::F32 |
-                    layout::F64 => RegKind::Float
-                };
-                Some(Reg {
-                    kind,
-                    size: self.size
-                })
-            }
-
-            layout::Abi::Vector { .. } => {
-                Some(Reg {
-                    kind: RegKind::Vector,
-                    size: self.size
-                })
-            }
-
-            layout::Abi::ScalarPair(..) |
-            layout::Abi::Aggregate { .. } => {
-                let mut total = Size::from_bytes(0);
-                let mut result = None;
-
-                let is_union = match self.fields {
-                    layout::FieldPlacement::Array { count, .. } => {
-                        if count > 0 {
-                            return self.field(cx, 0).homogeneous_aggregate(cx);
-                        } else {
-                            return None;
-                        }
-                    }
-                    layout::FieldPlacement::Union(_) => true,
-                    layout::FieldPlacement::Arbitrary { .. } => false
-                };
-
-                for i in 0..self.fields.count() {
-                    if !is_union && total != self.fields.offset(i) {
-                        return None;
-                    }
-
-                    let field = self.field(cx, i);
-                    match (result, field.homogeneous_aggregate(cx)) {
-                        // The field itself must be a homogeneous aggregate.
-                        (_, None) => return None,
-                        // If this is the first field, record the unit.
-                        (None, Some(unit)) => {
-                            result = Some(unit);
-                        }
-                        // For all following fields, the unit must be the same.
-                        (Some(prev_unit), Some(unit)) => {
-                            if prev_unit != unit {
-                                return None;
-                            }
-                        }
-                    }
-
-                    // Keep track of the offset (without padding).
-                    let size = field.size;
-                    if is_union {
-                        total = cmp::max(total, size);
-                    } else {
-                        total += size;
-                    }
-                }
-
-                // There needs to be no padding.
-                if total != self.size {
-                    None
-                } else {
-                    result
-                }
-            }
-        }
-    }
-}
-
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
-pub struct CastTarget {
-    pub prefix: [Option<RegKind>; 8],
-    pub prefix_chunk: Size,
-    pub rest: Uniform,
-}
-
-impl From<Reg> for CastTarget {
-    fn from(unit: Reg) -> CastTarget {
-        CastTarget::from(Uniform::from(unit))
-    }
-}
-
-impl From<Uniform> for CastTarget {
-    fn from(uniform: Uniform) -> CastTarget {
-        CastTarget {
-            prefix: [None; 8],
-            prefix_chunk: Size::from_bytes(0),
-            rest: uniform
-        }
-    }
-}
-
-impl CastTarget {
-    pub fn pair(a: Reg, b: Reg) -> CastTarget {
-        CastTarget {
-            prefix: [Some(a.kind), None, None, None, None, None, None, None],
-            prefix_chunk: a.size,
-            rest: Uniform::from(b)
-        }
-    }
-
-    pub fn size(&self, cx: &CodegenCx) -> Size {
-        (self.prefix_chunk * self.prefix.iter().filter(|x| x.is_some()).count() as u64)
-            .abi_align(self.rest.align(cx)) + self.rest.total
-    }
-
-    pub fn align(&self, cx: &CodegenCx) -> Align {
-        self.prefix.iter()
-            .filter_map(|x| x.map(|kind| Reg { kind: kind, size: self.prefix_chunk }.align(cx)))
-            .fold(cx.data_layout().aggregate_align.max(self.rest.align(cx)),
-                |acc, align| acc.max(align))
-    }
-
-    pub fn llvm_type(&self, cx: &CodegenCx) -> Type {
+impl LlvmType for CastTarget {
+    fn llvm_type(&self, cx: &CodegenCx) -> Type {
         let rest_ll_unit = self.rest.unit.llvm_type(cx);
         let rest_count = self.rest.total.bytes() / self.rest.unit.size.bytes();
         let rem_bytes = self.rest.total.bytes() % self.rest.unit.size.bytes();
@@ -460,97 +160,16 @@ impl CastTarget {
     }
 }
 
-/// Information about how to pass an argument to,
-/// or return a value from, a function, under some ABI.
-#[derive(Debug)]
-pub struct ArgType<'tcx> {
-    pub layout: TyLayout<'tcx>,
-
-    /// Dummy argument, which is emitted before the real argument.
-    pub pad: Option<Reg>,
-
-    pub mode: PassMode,
+pub trait ArgTypeExt<'a, 'tcx> {
+    fn memory_ty(&self, cx: &CodegenCx<'a, 'tcx>) -> Type;
+    fn store(&self, bx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>);
+    fn store_fn_arg(&self, bx: &Builder<'a, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx>);
 }
 
-impl<'a, 'tcx> ArgType<'tcx> {
-    fn new(layout: TyLayout<'tcx>) -> ArgType<'tcx> {
-        ArgType {
-            layout,
-            pad: None,
-            mode: PassMode::Direct(ArgAttributes::new()),
-        }
-    }
-
-    pub fn make_indirect(&mut self) {
-        assert_eq!(self.mode, PassMode::Direct(ArgAttributes::new()));
-
-        // Start with fresh attributes for the pointer.
-        let mut attrs = ArgAttributes::new();
-
-        // For non-immediate arguments the callee gets its own copy of
-        // the value on the stack, so there are no aliases. It's also
-        // program-invisible so can't possibly capture
-        attrs.set(ArgAttribute::NoAlias)
-             .set(ArgAttribute::NoCapture)
-             .set(ArgAttribute::NonNull);
-        attrs.pointee_size = self.layout.size;
-        // FIXME(eddyb) We should be doing this, but at least on
-        // i686-pc-windows-msvc, it results in wrong stack offsets.
-        // attrs.pointee_align = Some(self.layout.align);
-
-        self.mode = PassMode::Indirect(attrs);
-    }
-
-    pub fn make_indirect_byval(&mut self) {
-        self.make_indirect();
-        match self.mode {
-            PassMode::Indirect(ref mut attrs) => {
-                attrs.set(ArgAttribute::ByVal);
-            }
-            _ => bug!()
-        }
-    }
-
-    pub fn extend_integer_width_to(&mut self, bits: u64) {
-        // Only integers have signedness
-        if let layout::Abi::Scalar(ref scalar) = self.layout.abi {
-            if let layout::Int(i, signed) = scalar.value {
-                if i.size().bits() < bits {
-                    if let PassMode::Direct(ref mut attrs) = self.mode {
-                        attrs.set(if signed {
-                            ArgAttribute::SExt
-                        } else {
-                            ArgAttribute::ZExt
-                        });
-                    }
-                }
-            }
-        }
-    }
-
-    pub fn cast_to<T: Into<CastTarget>>(&mut self, target: T) {
-        assert_eq!(self.mode, PassMode::Direct(ArgAttributes::new()));
-        self.mode = PassMode::Cast(target.into());
-    }
-
-    pub fn pad_with(&mut self, reg: Reg) {
-        self.pad = Some(reg);
-    }
-
-    pub fn is_indirect(&self) -> bool {
-        match self.mode {
-            PassMode::Indirect(_) => true,
-            _ => false
-        }
-    }
-
-    pub fn is_ignore(&self) -> bool {
-        self.mode == PassMode::Ignore
-    }
-
+impl<'a, 'tcx> ArgTypeExt<'a, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
     /// Get the LLVM type for a place of the original Rust type of
     /// this argument/return, i.e. the result of `type_of::type_of`.
-    pub fn memory_ty(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
+    fn memory_ty(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
         self.layout.llvm_type(cx)
     }
 
@@ -558,7 +177,7 @@ impl<'a, 'tcx> ArgType<'tcx> {
     /// place for the original Rust type of this argument/return.
     /// Can be used for both storing formal arguments into Rust variables
     /// or results of call/invoke instructions into their destinations.
-    pub fn store(&self, bx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>) {
+    fn store(&self, bx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>) {
         if self.is_ignore() {
             return;
         }
@@ -610,7 +229,7 @@ impl<'a, 'tcx> ArgType<'tcx> {
         }
     }
 
-    pub fn store_fn_arg(&self, bx: &Builder<'a, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx>) {
+    fn store_fn_arg(&self, bx: &Builder<'a, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx>) {
         let mut next = || {
             let val = llvm::get_param(bx.llfn(), *idx as c_uint);
             *idx += 1;
@@ -628,26 +247,29 @@ impl<'a, 'tcx> ArgType<'tcx> {
     }
 }
 
-/// Metadata describing how the arguments to a native function
-/// should be passed in order to respect the native ABI.
-///
-/// I will do my best to describe this structure, but these
-/// comments are reverse-engineered and may be inaccurate. -NDM
-#[derive(Debug)]
-pub struct FnType<'tcx> {
-    /// The LLVM types of each argument.
-    pub args: Vec<ArgType<'tcx>>,
-
-    /// LLVM return type.
-    pub ret: ArgType<'tcx>,
-
-    pub variadic: bool,
-
-    pub cconv: llvm::CallConv
+pub trait FnTypeExt<'a, 'tcx> {
+    fn of_instance(cx: &CodegenCx<'a, 'tcx>, instance: &ty::Instance<'tcx>)
+                   -> Self;
+    fn new(cx: &CodegenCx<'a, 'tcx>,
+           sig: ty::FnSig<'tcx>,
+           extra_args: &[Ty<'tcx>]) -> Self;
+    fn new_vtable(cx: &CodegenCx<'a, 'tcx>,
+                  sig: ty::FnSig<'tcx>,
+                  extra_args: &[Ty<'tcx>]) -> Self;
+    fn unadjusted(cx: &CodegenCx<'a, 'tcx>,
+                  sig: ty::FnSig<'tcx>,
+                  extra_args: &[Ty<'tcx>]) -> Self;
+    fn adjust_for_abi(&mut self,
+                      cx: &CodegenCx<'a, 'tcx>,
+                      abi: Abi);
+    fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type;
+    fn llvm_cconv(&self) -> llvm::CallConv;
+    fn apply_attrs_llfn(&self, llfn: ValueRef);
+    fn apply_attrs_callsite(&self, callsite: ValueRef);
 }
 
-impl<'a, 'tcx> FnType<'tcx> {
-    pub fn of_instance(cx: &CodegenCx<'a, 'tcx>, instance: &ty::Instance<'tcx>)
+impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> {
+    fn of_instance(cx: &CodegenCx<'a, 'tcx>, instance: &ty::Instance<'tcx>)
                        -> Self {
         let fn_ty = instance.ty(cx.tcx);
         let sig = ty_fn_sig(cx, fn_ty);
@@ -655,17 +277,17 @@ impl<'a, 'tcx> FnType<'tcx> {
         FnType::new(cx, sig, &[])
     }
 
-    pub fn new(cx: &CodegenCx<'a, 'tcx>,
+    fn new(cx: &CodegenCx<'a, 'tcx>,
                sig: ty::FnSig<'tcx>,
-               extra_args: &[Ty<'tcx>]) -> FnType<'tcx> {
+               extra_args: &[Ty<'tcx>]) -> Self {
         let mut fn_ty = FnType::unadjusted(cx, sig, extra_args);
         fn_ty.adjust_for_abi(cx, sig.abi);
         fn_ty
     }
 
-    pub fn new_vtable(cx: &CodegenCx<'a, 'tcx>,
+    fn new_vtable(cx: &CodegenCx<'a, 'tcx>,
                       sig: ty::FnSig<'tcx>,
-                      extra_args: &[Ty<'tcx>]) -> FnType<'tcx> {
+                      extra_args: &[Ty<'tcx>]) -> Self {
         let mut fn_ty = FnType::unadjusted(cx, sig, extra_args);
         // Don't pass the vtable, it's not an argument of the virtual fn.
         {
@@ -688,34 +310,34 @@ impl<'a, 'tcx> FnType<'tcx> {
         fn_ty
     }
 
-    pub fn unadjusted(cx: &CodegenCx<'a, 'tcx>,
+    fn unadjusted(cx: &CodegenCx<'a, 'tcx>,
                       sig: ty::FnSig<'tcx>,
-                      extra_args: &[Ty<'tcx>]) -> FnType<'tcx> {
+                      extra_args: &[Ty<'tcx>]) -> Self {
         debug!("FnType::unadjusted({:?}, {:?})", sig, extra_args);
 
         use self::Abi::*;
-        let cconv = match cx.sess().target.target.adjust_abi(sig.abi) {
+        let conv = match cx.sess().target.target.adjust_abi(sig.abi) {
             RustIntrinsic | PlatformIntrinsic |
-            Rust | RustCall => llvm::CCallConv,
+            Rust | RustCall => Conv::C,
 
             // It's the ABI's job to select this, not us.
             System => bug!("system abi should be selected elsewhere"),
 
-            Stdcall => llvm::X86StdcallCallConv,
-            Fastcall => llvm::X86FastcallCallConv,
-            Vectorcall => llvm::X86_VectorCall,
-            Thiscall => llvm::X86_ThisCall,
-            C => llvm::CCallConv,
-            Unadjusted => llvm::CCallConv,
-            Win64 => llvm::X86_64_Win64,
-            SysV64 => llvm::X86_64_SysV,
-            Aapcs => llvm::ArmAapcsCallConv,
-            PtxKernel => llvm::PtxKernel,
-            Msp430Interrupt => llvm::Msp430Intr,
-            X86Interrupt => llvm::X86_Intr,
+            Stdcall => Conv::X86Stdcall,
+            Fastcall => Conv::X86Fastcall,
+            Vectorcall => Conv::X86VectorCall,
+            Thiscall => Conv::X86ThisCall,
+            C => Conv::C,
+            Unadjusted => Conv::C,
+            Win64 => Conv::X86_64Win64,
+            SysV64 => Conv::X86_64SysV,
+            Aapcs => Conv::ArmAapcs,
+            PtxKernel => Conv::PtxKernel,
+            Msp430Interrupt => Conv::Msp430Intr,
+            X86Interrupt => Conv::X86Intr,
 
             // These API constants ought to be more specific...
-            Cdecl => llvm::CCallConv,
+            Cdecl => Conv::C,
         };
 
         let mut inputs = sig.inputs();
@@ -752,7 +374,7 @@ impl<'a, 'tcx> FnType<'tcx> {
         // Handle safe Rust thin and fat pointers.
         let adjust_for_rust_scalar = |attrs: &mut ArgAttributes,
                                       scalar: &layout::Scalar,
-                                      layout: TyLayout<'tcx>,
+                                      layout: TyLayout<'tcx, Ty<'tcx>>,
                                       offset: Size,
                                       is_return: bool| {
             // Booleans are always an i1 that needs to be zero-extended.
@@ -858,7 +480,7 @@ impl<'a, 'tcx> FnType<'tcx> {
                 arg_of(ty, false)
             }).collect(),
             variadic: sig.variadic,
-            cconv,
+            conv,
         }
     }
 
@@ -869,7 +491,7 @@ impl<'a, 'tcx> FnType<'tcx> {
 
         if abi == Abi::Rust || abi == Abi::RustCall ||
            abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
-            let fixup = |arg: &mut ArgType<'tcx>| {
+            let fixup = |arg: &mut ArgType<'tcx, Ty<'tcx>>| {
                 if arg.is_ignore() { return; }
 
                 match arg.layout.abi {
@@ -925,52 +547,12 @@ impl<'a, 'tcx> FnType<'tcx> {
             return;
         }
 
-        match &cx.sess().target.target.arch[..] {
-            "x86" => {
-                let flavor = if abi == Abi::Fastcall {
-                    cabi_x86::Flavor::Fastcall
-                } else {
-                    cabi_x86::Flavor::General
-                };
-                cabi_x86::compute_abi_info(cx, self, flavor);
-            },
-            "x86_64" => if abi == Abi::SysV64 {
-                cabi_x86_64::compute_abi_info(cx, self);
-            } else if abi == Abi::Win64 || cx.sess().target.target.options.is_like_windows {
-                cabi_x86_win64::compute_abi_info(self);
-            } else {
-                cabi_x86_64::compute_abi_info(cx, self);
-            },
-            "aarch64" => cabi_aarch64::compute_abi_info(cx, self),
-            "arm" => cabi_arm::compute_abi_info(cx, self),
-            "mips" => cabi_mips::compute_abi_info(cx, self),
-            "mips64" => cabi_mips64::compute_abi_info(cx, self),
-            "powerpc" => cabi_powerpc::compute_abi_info(cx, self),
-            "powerpc64" => cabi_powerpc64::compute_abi_info(cx, self),
-            "s390x" => cabi_s390x::compute_abi_info(cx, self),
-            "asmjs" => cabi_asmjs::compute_abi_info(cx, self),
-            "wasm32" => {
-                if cx.sess().opts.target_triple.triple().contains("emscripten") {
-                    cabi_asmjs::compute_abi_info(cx, self)
-                } else {
-                    cabi_wasm32::compute_abi_info(cx, self)
-                }
-            }
-            "msp430" => cabi_msp430::compute_abi_info(self),
-            "sparc" => cabi_sparc::compute_abi_info(cx, self),
-            "sparc64" => cabi_sparc64::compute_abi_info(cx, self),
-            "nvptx" => cabi_nvptx::compute_abi_info(self),
-            "nvptx64" => cabi_nvptx64::compute_abi_info(self),
-            "hexagon" => cabi_hexagon::compute_abi_info(self),
-            a => cx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a))
-        }
-
-        if let PassMode::Indirect(ref mut attrs) = self.ret.mode {
-            attrs.set(ArgAttribute::StructRet);
+        if let Err(msg) = self.adjust_for_cabi(cx, abi) {
+            cx.sess().fatal(&msg);
         }
     }
 
-    pub fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
+    fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type {
         let mut llargument_tys = Vec::new();
 
         let llreturn_ty = match self.ret.mode {
@@ -1012,7 +594,23 @@ impl<'a, 'tcx> FnType<'tcx> {
         }
     }
 
-    pub fn apply_attrs_llfn(&self, llfn: ValueRef) {
+    fn llvm_cconv(&self) -> llvm::CallConv {
+        match self.conv {
+            Conv::C => llvm::CCallConv,
+            Conv::ArmAapcs => llvm::ArmAapcsCallConv,
+            Conv::Msp430Intr => llvm::Msp430Intr,
+            Conv::PtxKernel => llvm::PtxKernel,
+            Conv::X86Fastcall => llvm::X86FastcallCallConv,
+            Conv::X86Intr => llvm::X86_Intr,
+            Conv::X86Stdcall => llvm::X86StdcallCallConv,
+            Conv::X86ThisCall => llvm::X86_ThisCall,
+            Conv::X86VectorCall => llvm::X86_VectorCall,
+            Conv::X86_64SysV => llvm::X86_64_SysV,
+            Conv::X86_64Win64 => llvm::X86_64_Win64,
+        }
+    }
+
+    fn apply_attrs_llfn(&self, llfn: ValueRef) {
         let mut i = 0;
         let mut apply = |attrs: &ArgAttributes| {
             attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn);
@@ -1042,7 +640,7 @@ impl<'a, 'tcx> FnType<'tcx> {
         }
     }
 
-    pub fn apply_attrs_callsite(&self, callsite: ValueRef) {
+    fn apply_attrs_callsite(&self, callsite: ValueRef) {
         let mut i = 0;
         let mut apply = |attrs: &ArgAttributes| {
             attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite);
@@ -1071,8 +669,9 @@ impl<'a, 'tcx> FnType<'tcx> {
             }
         }
 
-        if self.cconv != llvm::CCallConv {
-            llvm::SetInstructionCallConv(callsite, self.cconv);
+        let cconv = self.llvm_cconv();
+        if cconv != llvm::CCallConv {
+            llvm::SetInstructionCallConv(callsite, cconv);
         }
     }
 }
diff --git a/src/librustc_trans/back/command.rs b/src/librustc_trans/back/command.rs
index a5649e98baa..9ebbdd7c3c9 100644
--- a/src/librustc_trans/back/command.rs
+++ b/src/librustc_trans/back/command.rs
@@ -17,7 +17,7 @@ use std::io;
 use std::mem;
 use std::process::{self, Output};
 
-use rustc_back::LldFlavor;
+use rustc_target::spec::LldFlavor;
 
 #[derive(Clone)]
 pub struct Command {
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index 97683840172..92f9a9e8ba9 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -17,7 +17,6 @@ use super::command::Command;
 use super::rpath::RPathConfig;
 use super::rpath;
 use metadata::METADATA_FILENAME;
-use rustc_back::LinkerFlavor;
 use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType, PrintRequest};
 use rustc::session::config::{RUST_CGU_EXT, Lto};
 use rustc::session::filesearch;
@@ -30,8 +29,7 @@ use rustc::util::common::time;
 use rustc::util::fs::fix_windows_verbatim_for_gcc;
 use rustc::hir::def_id::CrateNum;
 use tempdir::TempDir;
-use rustc_back::{PanicStrategy, RelroLevel};
-use rustc_back::target::TargetTriple;
+use rustc_target::spec::{PanicStrategy, RelroLevel, LinkerFlavor, TargetTriple};
 use rustc_data_structures::fx::FxHashSet;
 use context::get_reloc_model;
 use llvm;
diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs
index e001e809ee5..f9a8473464d 100644
--- a/src/librustc_trans/back/linker.rs
+++ b/src/librustc_trans/back/linker.rs
@@ -23,7 +23,7 @@ use rustc::middle::dependency_format::Linkage;
 use rustc::session::Session;
 use rustc::session::config::{self, CrateType, OptLevel, DebugInfoLevel};
 use rustc::ty::TyCtxt;
-use rustc_back::{LinkerFlavor, LldFlavor};
+use rustc_target::spec::{LinkerFlavor, LldFlavor};
 use serialize::{json, Encoder};
 
 /// For all the linkers we support, and information they might
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index a4e1b7f2925..2323ec3ef11 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -74,7 +74,7 @@ use type_of::LayoutLlvmExt;
 use rustc::util::nodemap::{FxHashMap, FxHashSet, DefIdSet};
 use CrateInfo;
 use rustc_data_structures::sync::Lrc;
-use rustc_back::target::TargetTriple;
+use rustc_target::spec::TargetTriple;
 
 use std::any::Any;
 use std::collections::BTreeMap;
diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs
index 2c503bdab30..5849437758a 100644
--- a/src/librustc_trans/callee.rs
+++ b/src/librustc_trans/callee.rs
@@ -26,7 +26,7 @@ use rustc::hir::def_id::DefId;
 use rustc::ty::{self, TypeFoldable};
 use rustc::ty::layout::LayoutOf;
 use rustc::ty::subst::Substs;
-use rustc_back::PanicStrategy;
+use rustc_target::spec::PanicStrategy;
 
 /// Translates a reference to a fn/method item, monomorphizing and
 /// inlining as it goes.
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index e83e73c8ae7..25ca2152b27 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -32,7 +32,7 @@ use rustc::hir;
 use libc::{c_uint, c_char};
 use std::iter;
 
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax::symbol::InternedString;
 use syntax_pos::{Span, DUMMY_SP};
 
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index 4d781d7280d..76f8be9ee98 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -31,6 +31,7 @@ use rustc::session::Session;
 use rustc::ty::layout::{LayoutError, LayoutOf, Size, TyLayout};
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::util::nodemap::FxHashMap;
+use rustc_target::spec::{HasTargetSpec, Target};
 
 use std::ffi::{CStr, CString};
 use std::cell::{Cell, RefCell};
@@ -453,13 +454,20 @@ impl<'a, 'tcx> ty::layout::HasDataLayout for &'a CodegenCx<'a, 'tcx> {
     }
 }
 
+impl<'a, 'tcx> HasTargetSpec for &'a CodegenCx<'a, 'tcx> {
+    fn target_spec(&self) -> &Target {
+        &self.tcx.sess.target.target
+    }
+}
+
 impl<'a, 'tcx> ty::layout::HasTyCtxt<'tcx> for &'a CodegenCx<'a, 'tcx> {
     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
         self.tcx
     }
 }
 
-impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for &'a CodegenCx<'a, 'tcx> {
+impl<'a, 'tcx> LayoutOf for &'a CodegenCx<'a, 'tcx> {
+    type Ty = Ty<'tcx>;
     type TyLayout = TyLayout<'tcx>;
 
     fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs
index eb550d7a605..5359e0e0405 100644
--- a/src/librustc_trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/debuginfo/metadata.rs
@@ -32,7 +32,7 @@ use rustc::ich::Fingerprint;
 use rustc::ty::Instance;
 use common::CodegenCx;
 use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
-use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout};
+use rustc::ty::layout::{self, Align, LayoutOf, PrimitiveExt, Size, TyLayout};
 use rustc::session::config;
 use rustc::util::nodemap::FxHashMap;
 use rustc::util::common::path2cstr;
diff --git a/src/librustc_trans/declare.rs b/src/librustc_trans/declare.rs
index c2010feb1b6..bbe4e18b18c 100644
--- a/src/librustc_trans/declare.rs
+++ b/src/librustc_trans/declare.rs
@@ -24,8 +24,8 @@ use llvm::{self, ValueRef};
 use llvm::AttributePlace::Function;
 use rustc::ty::{self, Ty};
 use rustc::session::config::Sanitizer;
-use rustc_back::PanicStrategy;
-use abi::{Abi, FnType};
+use rustc_target::spec::PanicStrategy;
+use abi::{Abi, FnType, FnTypeExt};
 use attributes;
 use context::CodegenCx;
 use common;
@@ -131,7 +131,7 @@ pub fn declare_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, name: &str,
     debug!("declare_rust_fn (after region erasure) sig={:?}", sig);
 
     let fty = FnType::new(cx, sig, &[]);
-    let llfn = declare_raw_fn(cx, name, fty.cconv, fty.llvm_type(cx));
+    let llfn = declare_raw_fn(cx, name, fty.llvm_cconv(), fty.llvm_type(cx));
 
     // FIXME(canndrew): This is_never should really be an is_uninhabited
     if sig.output().is_never() {
diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs
index ecdc2d20d21..103b04e6f13 100644
--- a/src/librustc_trans/intrinsic.rs
+++ b/src/librustc_trans/intrinsic.rs
@@ -13,7 +13,7 @@
 use intrinsics::{self, Intrinsic};
 use llvm;
 use llvm::{ValueRef};
-use abi::{Abi, FnType, PassMode};
+use abi::{Abi, FnType, LlvmType, PassMode};
 use mir::place::PlaceRef;
 use mir::operand::{OperandRef, OperandValue};
 use base::*;
@@ -87,7 +87,7 @@ fn get_simple_intrinsic(cx: &CodegenCx, name: &str) -> Option<ValueRef> {
 /// add them to librustc_trans/trans/context.rs
 pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
                                       callee_ty: Ty<'tcx>,
-                                      fn_ty: &FnType<'tcx>,
+                                      fn_ty: &FnType<'tcx, Ty<'tcx>>,
                                       args: &[OperandRef<'tcx>],
                                       llresult: ValueRef,
                                       span: Span) {
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index 49d0f638f20..dab01abd335 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -33,8 +33,6 @@
 use rustc::dep_graph::WorkProduct;
 use syntax_pos::symbol::Symbol;
 
-#[macro_use]
-extern crate bitflags;
 extern crate flate2;
 extern crate libc;
 #[macro_use] extern crate rustc;
@@ -43,7 +41,7 @@ extern crate num_cpus;
 extern crate rustc_mir;
 extern crate rustc_allocator;
 extern crate rustc_apfloat;
-extern crate rustc_back;
+extern crate rustc_target;
 extern crate rustc_const_math;
 #[macro_use] extern crate rustc_data_structures;
 extern crate rustc_demangle;
@@ -104,24 +102,6 @@ mod asm;
 mod attributes;
 mod base;
 mod builder;
-mod cabi_aarch64;
-mod cabi_arm;
-mod cabi_asmjs;
-mod cabi_hexagon;
-mod cabi_mips;
-mod cabi_mips64;
-mod cabi_msp430;
-mod cabi_nvptx;
-mod cabi_nvptx64;
-mod cabi_powerpc;
-mod cabi_powerpc64;
-mod cabi_s390x;
-mod cabi_sparc;
-mod cabi_sparc64;
-mod cabi_x86;
-mod cabi_x86_64;
-mod cabi_x86_win64;
-mod cabi_wasm32;
 mod callee;
 mod common;
 mod consts;
diff --git a/src/librustc_trans/metadata.rs b/src/librustc_trans/metadata.rs
index 9483420f2f0..144baa65c1b 100644
--- a/src/librustc_trans/metadata.rs
+++ b/src/librustc_trans/metadata.rs
@@ -10,7 +10,7 @@
 
 use rustc::util::common;
 use rustc::middle::cstore::MetadataLoader;
-use rustc_back::target::Target;
+use rustc_target::spec::Target;
 use llvm;
 use llvm::{False, ObjectFile, mk_section_iter};
 use llvm::archive_ro::ArchiveRO;
diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs
index 6b542ae2e93..21bbdf31dcb 100644
--- a/src/librustc_trans/meth.rs
+++ b/src/librustc_trans/meth.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use llvm::ValueRef;
-use abi::FnType;
+use abi::{FnType, FnTypeExt};
 use callee;
 use common::*;
 use builder::Builder;
@@ -35,7 +35,7 @@ impl<'a, 'tcx> VirtualIndex {
 
     pub fn get_fn(self, bx: &Builder<'a, 'tcx>,
                   llvtable: ValueRef,
-                  fn_ty: &FnType<'tcx>) -> ValueRef {
+                  fn_ty: &FnType<'tcx, Ty<'tcx>>) -> ValueRef {
         // Load the data pointer from the object.
         debug!("get_fn({:?}, {:?})", Value(llvtable), self);
 
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index 93bc89f0914..36f03605fea 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -10,10 +10,10 @@
 
 use llvm::{self, ValueRef, BasicBlockRef};
 use rustc::middle::lang_items;
-use rustc::ty::{self, TypeFoldable};
+use rustc::ty::{self, Ty, TypeFoldable};
 use rustc::ty::layout::{self, LayoutOf};
 use rustc::mir;
-use abi::{Abi, FnType, ArgType, PassMode};
+use abi::{Abi, ArgType, ArgTypeExt, FnType, FnTypeExt, LlvmType, PassMode};
 use base;
 use callee;
 use builder::Builder;
@@ -110,7 +110,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
         let do_call = |
             this: &mut Self,
             bx: Builder<'a, 'tcx>,
-            fn_ty: FnType<'tcx>,
+            fn_ty: FnType<'tcx, Ty<'tcx>>,
             fn_ptr: ValueRef,
             llargs: &[ValueRef],
             destination: Option<(ReturnDest<'tcx>, mir::BasicBlock)>,
@@ -604,7 +604,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                       bx: &Builder<'a, 'tcx>,
                       op: OperandRef<'tcx>,
                       llargs: &mut Vec<ValueRef>,
-                      arg: &ArgType<'tcx>) {
+                      arg: &ArgType<'tcx, Ty<'tcx>>) {
         // Fill padding with undef value, where applicable.
         if let Some(ty) = arg.pad {
             llargs.push(C_undef(ty.llvm_type(bx.cx)));
@@ -683,7 +683,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                                 bx: &Builder<'a, 'tcx>,
                                 operand: &mir::Operand<'tcx>,
                                 llargs: &mut Vec<ValueRef>,
-                                args: &[ArgType<'tcx>]) {
+                                args: &[ArgType<'tcx, Ty<'tcx>>]) {
         let tuple = self.trans_operand(bx, operand);
 
         // Handle both by-ref and immediate tuples.
@@ -776,7 +776,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     }
 
     fn make_return_dest(&mut self, bx: &Builder<'a, 'tcx>,
-                        dest: &mir::Place<'tcx>, fn_ret: &ArgType<'tcx>,
+                        dest: &mir::Place<'tcx>, fn_ret: &ArgType<'tcx, Ty<'tcx>>,
                         llargs: &mut Vec<ValueRef>, is_intrinsic: bool)
                         -> ReturnDest<'tcx> {
         // If the return is ignored, we can just return a do-nothing ReturnDest
@@ -873,7 +873,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
     fn store_return(&mut self,
                     bx: &Builder<'a, 'tcx>,
                     dest: ReturnDest<'tcx>,
-                    ret_ty: &ArgType<'tcx>,
+                    ret_ty: &ArgType<'tcx, Ty<'tcx>>,
                     llval: ValueRef) {
         use self::ReturnDest::*;
 
diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs
index c55836919a9..a074f25dfc9 100644
--- a/src/librustc_trans/mir/mod.rs
+++ b/src/librustc_trans/mir/mod.rs
@@ -12,7 +12,7 @@ use common::{C_i32, C_null};
 use libc::c_uint;
 use llvm::{self, ValueRef, BasicBlockRef};
 use llvm::debuginfo::DIScope;
-use rustc::ty::{self, TypeFoldable};
+use rustc::ty::{self, Ty, TypeFoldable};
 use rustc::ty::layout::{LayoutOf, TyLayout};
 use rustc::mir::{self, Mir};
 use rustc::ty::subst::Substs;
@@ -22,7 +22,7 @@ use builder::Builder;
 use common::{CodegenCx, Funclet};
 use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebugContext};
 use monomorphize::Instance;
-use abi::{ArgAttribute, FnType, PassMode};
+use abi::{ArgAttribute, ArgTypeExt, FnType, FnTypeExt, PassMode};
 use type_::Type;
 
 use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span};
@@ -53,7 +53,7 @@ pub struct FunctionCx<'a, 'tcx:'a> {
 
     cx: &'a CodegenCx<'a, 'tcx>,
 
-    fn_ty: FnType<'tcx>,
+    fn_ty: FnType<'tcx, Ty<'tcx>>,
 
     /// When unwinding is initiated, we have to store this personality
     /// value somewhere so that we can load it and re-use it in the
diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs
index f37114ee4ac..5e6b2764957 100644
--- a/src/librustc_trans/type_of.rs
+++ b/src/librustc_trans/type_of.rs
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use abi::FnType;
+use abi::{FnType, FnTypeExt};
 use common::*;
 use rustc::hir;
 use rustc::ty::{self, Ty, TypeFoldable};
 use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout};
-use rustc_back::PanicStrategy;
+use rustc_target::spec::PanicStrategy;
 use trans_item::DefPathBasedNames;
 use type_::Type;
 
diff --git a/src/librustc_trans_utils/Cargo.toml b/src/librustc_trans_utils/Cargo.toml
index 7a01b6d261a..323d9d1ceda 100644
--- a/src/librustc_trans_utils/Cargo.toml
+++ b/src/librustc_trans_utils/Cargo.toml
@@ -17,7 +17,7 @@ log = "0.4"
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 rustc = { path = "../librustc" }
-rustc_back = { path = "../librustc_back" }
+rustc_target = { path = "../librustc_target" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_mir = { path = "../librustc_mir" }
 rustc_incremental = { path = "../librustc_incremental" }
diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs
index 0c6bc9e246b..b91f4e4dffb 100644
--- a/src/librustc_trans_utils/lib.rs
+++ b/src/librustc_trans_utils/lib.rs
@@ -30,7 +30,7 @@ extern crate log;
 
 #[macro_use]
 extern crate rustc;
-extern crate rustc_back;
+extern crate rustc_target;
 extern crate rustc_mir;
 extern crate rustc_incremental;
 extern crate syntax;
diff --git a/src/librustc_trans_utils/trans_crate.rs b/src/librustc_trans_utils/trans_crate.rs
index b7895631c60..7b585d1060f 100644
--- a/src/librustc_trans_utils/trans_crate.rs
+++ b/src/librustc_trans_utils/trans_crate.rs
@@ -43,7 +43,7 @@ use rustc::ty::maps::Providers;
 use rustc::middle::cstore::EncodedMetadata;
 use rustc::middle::cstore::MetadataLoader;
 use rustc::dep_graph::DepGraph;
-use rustc_back::target::Target;
+use rustc_target::spec::Target;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_mir::monomorphize::collector;
 use link::{build_link_meta, out_filename};
diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml
index c7868cc1e95..70c13e9b7d6 100644
--- a/src/librustc_typeck/Cargo.toml
+++ b/src/librustc_typeck/Cargo.toml
@@ -18,5 +18,6 @@ rustc = { path = "../librustc" }
 rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" }
+rustc_target = { path = "../librustc_target" }
 syntax_pos = { path = "../libsyntax_pos" }
 rustc_errors = { path = "../librustc_errors" }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index d657db0b125..6cdce127308 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -23,6 +23,7 @@ use rustc::ty::subst::{Kind, UnpackedKind, Subst, Substs};
 use rustc::traits;
 use rustc::ty::{self, RegionKind, Ty, TyCtxt, ToPredicate, TypeFoldable};
 use rustc::ty::wf::object_region_bounds;
+use rustc_target::spec::abi;
 use std::slice;
 use require_c_abi_if_variadic;
 use util::common::ErrorReported;
@@ -30,7 +31,7 @@ use util::nodemap::FxHashSet;
 use errors::FatalError;
 
 use std::iter;
-use syntax::{abi, ast};
+use syntax::ast;
 use syntax::feature_gate::{GateIssue, emit_feature_err};
 use syntax_pos::Span;
 
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 0c95f5eeb43..4df496763e4 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -17,7 +17,7 @@ use hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::{infer, traits};
 use rustc::ty::{self, TyCtxt, TypeFoldable, Ty};
 use rustc::ty::adjustment::{Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
-use syntax::abi;
+use rustc_target::spec::abi;
 use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index ed0613860d0..3b9d561ffc5 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -23,7 +23,7 @@ use rustc::ty::subst::Substs;
 use rustc::ty::TypeFoldable;
 use std::cmp;
 use std::iter;
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax::codemap::Span;
 use rustc::hir;
 
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 64b0e7d0a7d..283fbf8fecc 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -17,7 +17,7 @@ use rustc::ty::{self, TyCtxt, Ty};
 use rustc::util::nodemap::FxHashMap;
 use require_same_types;
 
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax::ast;
 use syntax::symbol::Symbol;
 use syntax_pos::Span;
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 4083d4a21ef..787df7c6479 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -118,7 +118,7 @@ use std::fmt::Display;
 use std::mem::replace;
 use std::iter;
 use std::ops::{self, Deref};
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax::ast;
 use syntax::attr;
 use syntax::codemap::{original_sp, Spanned};
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index fb8c6ba6401..2ebbd64cab9 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -38,8 +38,9 @@ use rustc::ty::util::IntTypeExt;
 use rustc::ty::util::Discr;
 use rustc::util::captures::Captures;
 use rustc::util::nodemap::FxHashMap;
+use rustc_target::spec::abi;
 
-use syntax::{abi, ast};
+use syntax::ast;
 use syntax::ast::MetaItemKind;
 use syntax::attr::{InlineAttr, list_contains_name, mark_used};
 use syntax::codemap::Spanned;
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index d29ee3d9b3a..23fe91ffdeb 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -94,6 +94,7 @@ extern crate rustc_platform_intrinsics as intrinsics;
 extern crate rustc_const_math;
 extern crate rustc_data_structures;
 extern crate rustc_errors as errors;
+extern crate rustc_target;
 
 use rustc::hir;
 use rustc::lint;
@@ -111,7 +112,7 @@ use session::{CompileIncomplete, config};
 use util::common::time;
 
 use syntax::ast;
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax_pos::Span;
 
 use std::iter;
diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs
index 65c78d3593f..26fba71c812 100644
--- a/src/librustc_typeck/outlives/implicit_infer.rs
+++ b/src/librustc_typeck/outlives/implicit_infer.rs
@@ -23,7 +23,8 @@ use rustc::ty::{self, AdtKind, CratePredicatesMap, Region, RegionKind, ReprOptio
                 ToPolyTraitRef, ToPredicate, Ty, TyCtxt};
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::Lrc;
-use syntax::{abi, ast};
+use rustc_target::spec::abi;
+use syntax::ast;
 use syntax_pos::{Span, DUMMY_SP};
 
 /// Infer predicates for the items in the crate.
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index e37b3a7fcc4..fb05cbfe32c 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -20,7 +20,7 @@ pub use self::FunctionRetTy::*;
 pub use self::Visibility::*;
 
 use syntax;
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax::ast::{self, AttrStyle, Ident};
 use syntax::attr;
 use syntax::codemap::{dummy_spanned, Spanned};
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 2bd1e72f0eb..d423203b996 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -23,7 +23,7 @@ use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc_resolve as resolve;
 use rustc_metadata::creader::CrateLoader;
 use rustc_metadata::cstore::CStore;
-use rustc_back::target::TargetTriple;
+use rustc_target::spec::TargetTriple;
 
 use syntax::ast::NodeId;
 use syntax::codemap;
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index 413e5623118..f85a70a6d40 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -13,7 +13,7 @@
 pub use self::StructType::*;
 pub use self::TypeBound::*;
 
-use syntax::abi;
+use rustc_target::spec::abi;
 use syntax::ast;
 use syntax::ast::{Name, NodeId};
 use syntax::attr;
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 0a7e19fc643..a9a4c511374 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -19,7 +19,7 @@ use std::fmt;
 use std::iter::repeat;
 
 use rustc::hir::def_id::DefId;
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use rustc::hir;
 
 use clean::{self, PrimitiveType};
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 0ae946c4182..82449e9b5f9 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -54,7 +54,7 @@ use std::sync::Arc;
 use externalfiles::ExternalHtml;
 
 use serialize::json::{ToJson, Json, as_json};
-use syntax::{abi, ast};
+use syntax::ast;
 use syntax::codemap::FileName;
 use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId};
 use rustc::middle::privacy::AccessLevels;
@@ -62,6 +62,7 @@ use rustc::middle::stability;
 use rustc::hir;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc_data_structures::flock;
+use rustc_target::spec::abi;
 
 use clean::{self, AttributesExt, GetDefId, SelfTy, Mutability};
 use doctree;
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 60b713f2995..614386a583a 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -35,8 +35,8 @@ extern crate rustc_trans_utils;
 extern crate rustc_driver;
 extern crate rustc_resolve;
 extern crate rustc_lint;
-extern crate rustc_back;
 extern crate rustc_metadata;
+extern crate rustc_target;
 extern crate rustc_typeck;
 extern crate serialize;
 #[macro_use] extern crate syntax;
@@ -66,7 +66,7 @@ use externalfiles::ExternalHtml;
 use rustc::session::search_paths::SearchPaths;
 use rustc::session::config::{ErrorOutputType, RustcOptGroup, Externs, CodegenOptions};
 use rustc::session::config::{nightly_options, build_codegen_options};
-use rustc_back::target::TargetTriple;
+use rustc_target::spec::TargetTriple;
 
 #[macro_use]
 pub mod externalfiles;
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index f45a5b030db..967c50e62db 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -13,7 +13,7 @@
 
 use std::mem;
 
-use syntax::abi;
+use rustc_target::spec::abi;
 use syntax::ast;
 use syntax::attr;
 use syntax_pos::Span;
diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml
index 8c24f36615b..d1a5ab0211b 100644
--- a/src/libsyntax/Cargo.toml
+++ b/src/libsyntax/Cargo.toml
@@ -14,6 +14,6 @@ serialize = { path = "../libserialize" }
 log = "0.4"
 scoped-tls = "0.1"
 syntax_pos = { path = "../libsyntax_pos" }
-rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_target = { path = "../librustc_target" }
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 4e3ee241468..cbfcad12f1e 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -19,7 +19,7 @@ pub use util::parser::ExprPrecedence;
 
 use syntax_pos::{Span, DUMMY_SP};
 use codemap::{respan, Spanned};
-use abi::Abi;
+use rustc_target::spec::abi::Abi;
 use ext::hygiene::{Mark, SyntaxContext};
 use print::pprust;
 use ptr::P;
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index a9f48342243..0b64189b2bc 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use abi::Abi;
+use rustc_target::spec::abi::Abi;
 use ast::{self, Ident, Generics, Expr, BlockCheckMode, UnOp, PatKind};
 use attr;
 use syntax_pos::{Pos, Span, DUMMY_SP};
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 39ddb13d347..0331e90164f 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -25,7 +25,7 @@
 use self::AttributeType::*;
 use self::AttributeGate::*;
 
-use abi::Abi;
+use rustc_target::spec::abi::Abi;
 use ast::{self, NodeId, PatKind, RangeEnd};
 use attr;
 use edition::{ALL_EDITIONS, Edition};
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index ad98e2a6b71..870ce1926ad 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -28,10 +28,6 @@
 
 #![recursion_limit="256"]
 
-// See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
-#[allow(unused_extern_crates)]
-extern crate rustc_cratesio_shim;
-
 #[macro_use] extern crate bitflags;
 extern crate core;
 extern crate serialize;
@@ -39,6 +35,7 @@ extern crate serialize;
 pub extern crate rustc_errors as errors;
 extern crate syntax_pos;
 extern crate rustc_data_structures;
+extern crate rustc_target;
 #[macro_use] extern crate scoped_tls;
 
 extern crate serialize as rustc_serialize; // used by deriving
@@ -138,7 +135,6 @@ pub mod syntax {
     pub use ast;
 }
 
-pub mod abi;
 pub mod ast;
 pub mod attr;
 pub mod codemap;
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 0397c3297db..ff09c6aa2f0 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -678,7 +678,7 @@ mod tests {
     use syntax_pos::{self, Span, BytePos, Pos, NO_EXPANSION};
     use codemap::{respan, Spanned};
     use ast::{self, Ident, PatKind};
-    use abi::Abi;
+    use rustc_target::spec::abi::Abi;
     use attr::first_attr_value_str_by_name;
     use parse;
     use parse::parser::Parser;
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 9fa3952ca80..324cadc84e8 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use abi::{self, Abi};
+use rustc_target::spec::abi::{self, Abi};
 use ast::{AngleBracketedParameterData, ParenthesizedParameterData, AttrStyle, BareFnTy};
 use ast::{RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
 use ast::Unsafety;
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index bd06ae8c1a9..88860df10e2 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -10,7 +10,7 @@
 
 pub use self::AnnNode::*;
 
-use abi::{self, Abi};
+use rustc_target::spec::abi::{self, Abi};
 use ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
 use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
 use ast::Attribute;
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index 325927ed832..1734692f9e7 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -563,7 +563,9 @@ fn mk_main(cx: &mut TestCtxt) -> P<ast::Item> {
     let main = ast::ItemKind::Fn(ecx.fn_decl(vec![], ast::FunctionRetTy::Ty(main_ret_ty)),
                            ast::Unsafety::Normal,
                            dummy_spanned(ast::Constness::NotConst),
-                           ::abi::Abi::Rust, ast::Generics::default(), main_body);
+                           ::rustc_target::spec::abi::Abi::Rust,
+                           ast::Generics::default(),
+                           main_body);
     P(ast::Item {
         ident: Ident::from_str("main"),
         attrs: vec![main_attr],
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 8743840e443..40d59d3ff8b 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -23,7 +23,7 @@
 //! instance, a walker looking for item names in a module will miss all of
 //! those that are created by the expansion of a macro.
 
-use abi::Abi;
+use rustc_target::spec::abi::Abi;
 use ast::*;
 use syntax_pos::Span;
 use codemap::Spanned;
diff --git a/src/libsyntax_ext/Cargo.toml b/src/libsyntax_ext/Cargo.toml
index d8eeb5ed255..1676757d9b8 100644
--- a/src/libsyntax_ext/Cargo.toml
+++ b/src/libsyntax_ext/Cargo.toml
@@ -14,4 +14,5 @@ proc_macro = { path = "../libproc_macro" }
 rustc_errors = { path = "../librustc_errors" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
-rustc_data_structures = { path = "../librustc_data_structures" }
\ No newline at end of file
+rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_target = { path = "../librustc_target" }
\ No newline at end of file
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index 1ef0d2b0b49..becd70149fd 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -191,7 +191,7 @@ use std::cell::RefCell;
 use std::collections::HashSet;
 use std::vec;
 
-use syntax::abi::Abi;
+use rustc_target::spec::abi::Abi;
 use syntax::ast::{
     self, BinOpKind, EnumDef, Expr, GenericParam, Generics, Ident, PatKind, VariantData
 };
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index 39ad594e5c5..b6721dd28f3 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -27,6 +27,7 @@ extern crate syntax_pos;
 extern crate proc_macro;
 extern crate rustc_data_structures;
 extern crate rustc_errors as errors;
+extern crate rustc_target;
 
 #[cfg(not(stage0))]
 mod diagnostics;
diff --git a/src/rustc/Cargo.toml b/src/rustc/Cargo.toml
index bbc4c2ee43e..9986e0b512a 100644
--- a/src/rustc/Cargo.toml
+++ b/src/rustc/Cargo.toml
@@ -8,8 +8,8 @@ name = "rustc"
 path = "rustc.rs"
 
 [dependencies]
-rustc_back = { path = "../librustc_back" }
+rustc_target = { path = "../librustc_target" }
 rustc_driver = { path = "../librustc_driver" }
 
 [features]
-jemalloc = ["rustc_back/jemalloc"]
+jemalloc = ["rustc_target/jemalloc"]