about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml10
-rw-r--r--README.md5
-rw-r--r--appveyor.yml9
-rwxr-xr-xconfigure5
-rw-r--r--mk/cfg/sparc64-unknown-linux-gnu.mk1
-rw-r--r--mk/cfg/sparc64-unknown-netbsd.mk3
-rw-r--r--mk/crates.mk25
-rw-r--r--mk/main.mk2
-rw-r--r--src/Cargo.lock17
-rw-r--r--src/bootstrap/bin/rustc.rs4
-rw-r--r--src/bootstrap/check.rs51
-rw-r--r--src/bootstrap/compile.rs116
-rw-r--r--src/bootstrap/config.rs13
-rw-r--r--src/bootstrap/config.toml.example18
-rw-r--r--src/bootstrap/dist.rs17
-rw-r--r--src/bootstrap/doc.rs30
-rw-r--r--src/bootstrap/lib.rs51
-rw-r--r--src/bootstrap/mk/Makefile.in14
-rw-r--r--src/bootstrap/native.rs9
-rw-r--r--src/bootstrap/step.rs281
-rw-r--r--src/bootstrap/util.rs4
-rw-r--r--src/ci/docker/arm-android/Dockerfile3
-rw-r--r--src/ci/docker/cross/Dockerfile4
-rw-r--r--src/ci/docker/i686-gnu-nopt/Dockerfile3
-rw-r--r--src/ci/docker/i686-gnu/Dockerfile3
-rw-r--r--src/ci/docker/x86_64-freebsd/Dockerfile3
-rw-r--r--src/ci/docker/x86_64-gnu-aux/Dockerfile (renamed from src/ci/docker/x86_64-gnu-cargotest/Dockerfile)5
-rw-r--r--src/ci/docker/x86_64-gnu-debug/Dockerfile3
-rw-r--r--src/ci/docker/x86_64-gnu-distcheck/Dockerfile26
-rw-r--r--src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile28
-rw-r--r--src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile3
-rw-r--r--src/ci/docker/x86_64-gnu-make/Dockerfile3
-rw-r--r--src/ci/docker/x86_64-gnu-nopt/Dockerfile3
-rw-r--r--src/ci/docker/x86_64-gnu/Dockerfile3
-rw-r--r--src/ci/docker/x86_64-musl/Dockerfile4
-rwxr-xr-xsrc/ci/run.sh14
-rw-r--r--src/doc/book/closures.md4
-rw-r--r--src/doc/book/ffi.md25
-rw-r--r--src/doc/book/lifetimes.md2
-rw-r--r--src/doc/book/strings.md4
-rw-r--r--src/doc/book/variable-bindings.md2
-rw-r--r--src/doc/nomicon/atomics.md8
-rw-r--r--src/doc/nomicon/meet-safe-and-unsafe.md2
-rw-r--r--src/doc/nomicon/races.md10
-rw-r--r--src/doc/reference.md9
-rw-r--r--src/etc/debugger_pretty_printers_common.py16
-rw-r--r--src/etc/lldb_rust_formatters.py4
-rw-r--r--src/etc/platform-intrinsics/nvptx/cuda.json13
-rw-r--r--src/etc/platform-intrinsics/nvptx/info.json7
-rw-r--r--src/etc/platform-intrinsics/nvptx/sreg.json90
-rw-r--r--src/liballoc/arc.rs32
-rw-r--r--src/liballoc_jemalloc/Cargo.toml1
-rw-r--r--src/liballoc_jemalloc/build.rs6
-rw-r--r--src/liballoc_jemalloc/lib.rs3
-rw-r--r--src/liballoc_system/Cargo.toml1
-rw-r--r--src/liballoc_system/lib.rs3
-rw-r--r--src/libarena/lib.rs131
-rw-r--r--src/libcollectionstest/str.rs16
-rw-r--r--src/libcompiler_builtins/Cargo.toml1
-rw-r--r--src/libcompiler_builtins/lib.rs785
-rw-r--r--src/libcore/clone.rs4
-rw-r--r--src/libcore/cmp.rs8
-rw-r--r--src/libcore/default.rs4
-rw-r--r--src/libcore/fmt/num.rs21
-rw-r--r--src/libcore/hash/mod.rs19
-rw-r--r--src/libcore/iter/range.rs2
-rw-r--r--src/libcore/iter/sources.rs8
-rw-r--r--src/libcore/lib.rs9
-rw-r--r--src/libcore/nonzero.rs4
-rw-r--r--src/libcore/num/i128.rs17
-rw-r--r--src/libcore/num/i16.rs2
-rw-r--r--src/libcore/num/i32.rs2
-rw-r--r--src/libcore/num/i64.rs2
-rw-r--r--src/libcore/num/i8.rs2
-rw-r--r--src/libcore/num/int_macros.rs2
-rw-r--r--src/libcore/num/isize.rs7
-rw-r--r--src/libcore/num/mod.rs131
-rw-r--r--src/libcore/num/u128.rs16
-rw-r--r--src/libcore/num/u16.rs2
-rw-r--r--src/libcore/num/u32.rs2
-rw-r--r--src/libcore/num/u64.rs2
-rw-r--r--src/libcore/num/u8.rs2
-rw-r--r--src/libcore/num/uint_macros.rs2
-rw-r--r--src/libcore/num/usize.rs7
-rw-r--r--src/libcore/num/wrapping.rs2
-rw-r--r--src/libcore/ops.rs61
-rw-r--r--src/libcore/slice.rs45
-rw-r--r--src/libcore/str/mod.rs26
-rw-r--r--src/libcore/sync/atomic.rs175
m---------src/liblibc0
-rw-r--r--src/libpanic_abort/Cargo.toml1
-rw-r--r--src/libpanic_unwind/Cargo.toml1
-rw-r--r--src/libpanic_unwind/gcc.rs3
-rw-r--r--src/librand/Cargo.toml1
-rw-r--r--src/librustc/Cargo.toml1
-rw-r--r--src/librustc/infer/mod.rs9
-rw-r--r--src/librustc/lib.rs3
-rw-r--r--src/librustc/middle/dead.rs7
-rw-r--r--src/librustc/middle/lang_items.rs2
-rw-r--r--src/librustc/ty/context.rs139
-rw-r--r--src/librustc/ty/layout.rs81
-rw-r--r--src/librustc/ty/mod.rs4
-rw-r--r--src/librustc/ty/util.rs6
-rw-r--r--src/librustc_back/target/asmjs_unknown_emscripten.rs5
-rw-r--r--src/librustc_back/target/emscripten_base.rs17
-rw-r--r--src/librustc_back/target/mod.rs4
-rw-r--r--src/librustc_back/target/sparc64_unknown_linux_gnu.rs30
-rw-r--r--src/librustc_back/target/sparc64_unknown_netbsd.rs30
-rw-r--r--src/librustc_back/target/wasm32_unknown_emscripten.rs5
-rw-r--r--src/librustc_const_eval/Cargo.toml3
-rw-r--r--src/librustc_const_eval/_match.rs145
-rw-r--r--src/librustc_const_eval/check_match.rs43
-rw-r--r--src/librustc_const_eval/eval.rs219
-rw-r--r--src/librustc_const_eval/lib.rs3
-rw-r--r--src/librustc_const_eval/pattern.rs386
-rw-r--r--src/librustc_const_math/Cargo.toml1
-rw-r--r--src/librustc_const_math/err.rs2
-rw-r--r--src/librustc_const_math/int.rs339
-rw-r--r--src/librustc_const_math/is.rs5
-rw-r--r--src/librustc_const_math/lib.rs4
-rw-r--r--src/librustc_const_math/us.rs5
-rw-r--r--src/librustc_data_structures/Cargo.toml1
-rw-r--r--src/librustc_data_structures/lib.rs2
-rw-r--r--src/librustc_data_structures/stable_hasher.rs5
-rw-r--r--src/librustc_driver/driver.rs20
-rw-r--r--src/librustc_driver/lib.rs1
-rw-r--r--src/librustc_driver/pretty.rs18
-rw-r--r--src/librustc_driver/test.rs5
-rw-r--r--src/librustc_i128/Cargo.toml8
-rw-r--r--src/librustc_i128/lib.rs29
-rw-r--r--src/librustc_incremental/Cargo.toml1
-rw-r--r--src/librustc_incremental/lib.rs2
-rw-r--r--src/librustc_lint/Cargo.toml1
-rw-r--r--src/librustc_lint/lib.rs2
-rw-r--r--src/librustc_lint/types.rs59
-rw-r--r--src/librustc_llvm/build.rs2
-rw-r--r--src/librustc_llvm/ffi.rs6
-rw-r--r--src/librustc_llvm/lib.rs13
-rw-r--r--src/librustc_metadata/Cargo.toml1
-rw-r--r--src/librustc_metadata/decoder.rs3
-rw-r--r--src/librustc_metadata/encoder.rs12
-rw-r--r--src/librustc_metadata/lib.rs3
-rw-r--r--src/librustc_metadata/schema.rs4
-rw-r--r--src/librustc_mir/Cargo.toml1
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs11
-rw-r--r--src/librustc_mir/build/misc.rs2
-rw-r--r--src/librustc_mir/lib.rs2
-rw-r--r--src/librustc_platform_intrinsics/lib.rs3
-rw-r--r--src/librustc_platform_intrinsics/nvptx.rs92
-rw-r--r--src/librustc_resolve/lib.rs18
-rw-r--r--src/librustc_resolve/macros.rs6
-rw-r--r--src/librustc_trans/Cargo.toml3
-rw-r--r--src/librustc_trans/abi.rs12
-rw-r--r--src/librustc_trans/cabi_nvptx.rs53
-rw-r--r--src/librustc_trans/cabi_nvptx64.rs53
-rw-r--r--src/librustc_trans/cabi_sparc64.rs185
-rw-r--r--src/librustc_trans/cabi_x86_win64.rs24
-rw-r--r--src/librustc_trans/common.rs42
-rw-r--r--src/librustc_trans/context.rs11
-rw-r--r--src/librustc_trans/debuginfo/metadata.rs5
-rw-r--r--src/librustc_trans/disr.rs3
-rw-r--r--src/librustc_trans/glue.rs5
-rw-r--r--src/librustc_trans/intrinsic.rs10
-rw-r--r--src/librustc_trans/lib.rs4
-rw-r--r--src/librustc_trans/mir/block.rs16
-rw-r--r--src/librustc_trans/mir/constant.rs66
-rw-r--r--src/librustc_trans/mir/mod.rs1
-rw-r--r--src/librustc_trans/mir/operand.rs2
-rw-r--r--src/librustc_trans/mir/rvalue.rs6
-rw-r--r--src/librustc_trans/trans_item.rs2
-rw-r--r--src/librustc_trans/type_.rs11
-rw-r--r--src/librustc_typeck/check/intrinsic.rs4
-rw-r--r--src/librustc_typeck/check/method/probe.rs8
-rw-r--r--src/librustc_typeck/check/mod.rs7
-rw-r--r--src/librustc_typeck/coherence/orphan.rs14
-rw-r--r--src/librustc_typeck/collect.rs2
-rw-r--r--src/librustdoc/clean/inline.rs2
-rw-r--r--src/librustdoc/clean/mod.rs90
-rw-r--r--src/librustdoc/core.rs7
-rw-r--r--src/librustdoc/html/render.rs3
-rw-r--r--src/libserialize/Cargo.toml1
-rw-r--r--src/libserialize/json.rs8
-rw-r--r--src/libserialize/leb128.rs34
-rw-r--r--src/libserialize/lib.rs2
-rw-r--r--src/libserialize/opaque.rs24
-rw-r--r--src/libserialize/serialize.rs33
-rw-r--r--src/libstd/env.rs6
-rw-r--r--src/libstd/lib.rs7
-rw-r--r--src/libstd/os/linux/raw.rs9
-rw-r--r--src/libstd/primitive_docs.rs22
-rw-r--r--src/libstd/sys/unix/fd.rs27
-rw-r--r--src/libstd/sys/windows/handle.rs9
-rw-r--r--src/libstd/sys/windows/thread_local.rs2
-rw-r--r--src/libstd/thread/mod.rs126
-rw-r--r--src/libsyntax/Cargo.toml1
-rw-r--r--src/libsyntax/abi.rs4
-rw-r--r--src/libsyntax/ast.rs42
-rw-r--r--src/libsyntax/attr.rs5
-rw-r--r--src/libsyntax/ext/build.rs14
-rw-r--r--src/libsyntax/ext/quote.rs6
-rw-r--r--src/libsyntax/feature_gate.rs39
-rw-r--r--src/libsyntax/lib.rs3
-rw-r--r--src/libsyntax/parse/mod.rs8
-rw-r--r--src/libsyntax/parse/parser.rs4
-rw-r--r--src/libsyntax/print/pprust.rs1719
-rw-r--r--src/libsyntax_ext/deriving/custom.rs4
-rw-r--r--src/libsyntax_ext/deriving/generic/mod.rs2
-rw-r--r--src/libterm/terminfo/mod.rs2
-rw-r--r--src/libunwind/Cargo.toml1
-rw-r--r--src/libunwind/libunwind.rs3
-rw-r--r--src/rustc/libc_shim/Cargo.toml1
-rw-r--r--src/rustc/std_shim/Cargo.toml1
-rw-r--r--src/rustllvm/ArchiveWrapper.cpp306
-rw-r--r--src/rustllvm/PassWrapper.cpp671
-rw-r--r--src/rustllvm/RustWrapper.cpp1867
-rw-r--r--src/rustllvm/rustllvm.h140
-rw-r--r--src/test/compile-fail/const-tup-index-span.rs2
-rw-r--r--src/test/compile-fail/i128-feature-2.rs29
-rw-r--r--src/test/compile-fail/i128-feature.rs17
-rw-r--r--src/test/compile-fail/unadjusted-unstable.rs (renamed from src/test/compile-fail/oversized-literal.rs)8
-rw-r--r--src/test/debuginfo/issue-12886.rs (renamed from src/test/debuginfo/issue12886.rs)0
-rw-r--r--src/test/debuginfo/issue-13213.rs (renamed from src/test/debuginfo/issue13213.rs)0
-rw-r--r--src/test/debuginfo/issue-14411.rs (renamed from src/test/debuginfo/issue14411.rs)0
-rw-r--r--src/test/debuginfo/issue-22656.rs (renamed from src/test/debuginfo/issue22656.rs)0
-rw-r--r--src/test/debuginfo/issue-7712.rs (renamed from src/test/debuginfo/issue7712.rs)0
-rw-r--r--src/test/debuginfo/union-smoke.rs5
-rw-r--r--src/test/debuginfo/unsized.rs45
-rw-r--r--src/test/parse-fail/int-literal-too-large-span.rs4
-rw-r--r--src/test/parse-fail/issue-5544-a.rs2
-rw-r--r--src/test/parse-fail/issue-5544-b.rs2
-rw-r--r--src/test/parse-fail/lex-bad-numeric-literals.rs4
-rw-r--r--src/test/run-make/test-harness/Makefile2
-rw-r--r--src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-nothing.rs24
-rw-r--r--src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs28
-rw-r--r--src/test/run-pass/i128.rs99
-rw-r--r--src/test/run-pass/issue-18173.rs (renamed from src/test/run-pass/issue18173.rs)0
-rw-r--r--src/test/run-pass/issue-22008.rs (renamed from src/test/run-pass/issue22008.rs)0
-rw-r--r--src/test/run-pass/issue-22346.rs (renamed from src/test/run-pass/issue22346.rs)0
-rw-r--r--src/test/run-pass/issue-24353.rs (renamed from src/test/run-pass/issue24353.rs)0
-rw-r--r--src/test/run-pass/issue-26127.rs (renamed from src/test/run-pass/issue26127.rs)0
-rw-r--r--src/test/run-pass/issue-29927.rs (renamed from src/test/run-pass/issue29927.rs)0
-rw-r--r--src/test/run-pass/issue-34569.rs (renamed from src/test/run-pass/issue34569.rs)0
-rw-r--r--src/test/run-pass/issue-34796.rs (renamed from src/test/run-pass/issue34796.rs)0
-rw-r--r--src/test/run-pass/issue-36260.rs (renamed from src/test/run-pass/issue36260.rs)0
-rw-r--r--src/test/run-pass/test-allow-dead-extern-static-no-warning.rs20
-rw-r--r--src/test/run-pass/u128.rs67
-rw-r--r--src/test/ui/codemap_tests/unicode.stderr2
-rw-r--r--src/tools/cargotest/main.rs51
-rw-r--r--src/tools/compiletest/Cargo.toml2
-rw-r--r--src/tools/compiletest/src/main.rs22
-rw-r--r--src/tools/compiletest/src/runtest.rs38
-rw-r--r--src/tools/tidy/src/pal.rs2
252 files changed, 6926 insertions, 3744 deletions
diff --git a/.travis.yml b/.travis.yml
index 3a9635a8618..26cabf92bda 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -19,12 +19,14 @@ matrix:
     - env: IMAGE=i686-gnu-nopt
     - env: IMAGE=x86_64-freebsd
     - env: IMAGE=x86_64-gnu
-    - env: IMAGE=x86_64-gnu-cargotest
+    - env: IMAGE=x86_64-gnu-full-bootstrap
+    - env: IMAGE=x86_64-gnu-aux
     - env: IMAGE=x86_64-gnu-debug
     - env: IMAGE=x86_64-gnu-nopt
     - env: IMAGE=x86_64-gnu-make
     - env: IMAGE=x86_64-gnu-llvm-3.7 ALLOW_PR=1 RUST_BACKTRACE=1
     - env: IMAGE=x86_64-musl
+    - env: IMAGE=x86_64-gnu-distcheck
 
     # OSX builders
     - env: >
@@ -66,10 +68,10 @@ script:
       if [ "$ALLOW_PR" = "" ] && [ "$TRAVIS_BRANCH" != "auto" ]; then
           echo skipping, not a full build;
       elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
-          git submodule update --init;
+          git submodule update --init &&
           src/ci/run.sh;
       else
-          git submodule update --init;
+          git submodule update --init &&
           src/ci/docker/run.sh $IMAGE;
       fi
 
@@ -78,7 +80,7 @@ before_cache:
   - docker history -q rust-ci |
     grep -v missing |
     xargs docker save |
-    gzip -9 > $HOME/docker/rust-ci.tar.gz
+    gzip > $HOME/docker/rust-ci.tar.gz
 before_install:
   - zcat $HOME/docker/rust-ci.tar.gz | docker load || true
 
diff --git a/README.md b/README.md
index 2133b17de0f..c1218e9c600 100644
--- a/README.md
+++ b/README.md
@@ -82,8 +82,9 @@ build.
    # Install build tools needed for Rust. If you're building a 32-bit compiler,
    # then replace "x86_64" below with "i686". If you've already got git, python,
    # or CMake installed and in PATH you can remove them from this list. Note
-   # that it is important that the `python2` and `cmake` packages **not** used.
-   # The build has historically been known to fail with these packages.
+   # that it is important that you do **not** use the 'python2' and 'cmake'
+   # packages from the 'msys2' subsystem. The build has historically been known
+   # to fail with these packages.
    $ pacman -S git \
                make \
                diffutils \
diff --git a/appveyor.yml b/appveyor.yml
index cb3b50cbaef..a4b5cbc1152 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -21,7 +21,7 @@ environment:
   # MSVC cargotest
   - MSYS_BITS: 64
     NO_VENDOR: 1
-    RUST_CHECK_TARGET: check-cargotest
+    RUST_CHECK_TARGET: check-aux
     RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
 
   # 32/64-bit MinGW builds.
@@ -96,6 +96,13 @@ install:
   - 7z x -y sccache.tar > nul
   - set PATH=%PATH%;%CD%\sccache2
 
+  # Help debug some handle issues on AppVeyor
+  - ps: Invoke-WebRequest -Uri https://download.sysinternals.com/files/Handle.zip -OutFile handle.zip
+  - mkdir handle
+  - ps: Expand-Archive handle.zip -dest handle
+  - set PATH=%PATH%;%CD%\handle
+  - handle.exe -accepteula -help
+
 test_script:
   - git submodule update --init
   - set SRC=.
diff --git a/configure b/configure
index 4f1e8f656ae..ee5922b1f14 100755
--- a/configure
+++ b/configure
@@ -693,6 +693,7 @@ opt_nosave manage-submodules 1 "let the build manage the git submodules"
 opt_nosave clang 0 "prefer clang to gcc for building the runtime"
 opt_nosave jemalloc 1 "build liballoc with jemalloc"
 opt elf-tls 1 "elf thread local storage on platforms where supported"
+opt full-bootstrap 0 "build three compilers instead of two"
 
 valopt_nosave prefix "/usr/local" "set installation prefix"
 valopt_nosave local-rust-root "/usr/local" "set prefix for local rust binary"
@@ -1567,7 +1568,7 @@ do
     then
         LLVM_BUILD_DIR=${CFG_BUILD_DIR}$t/llvm
         LLVM_INST_DIR=$LLVM_BUILD_DIR
-        # For some crazy reason the MSVC output dir is different than Unix
+        # For some weird reason the MSVC output dir is different than Unix
         if [ ${is_msvc} -ne 0 ]; then
             if [ -n "$CFG_DISABLE_OPTIMIZE_LLVM" ]
             then
@@ -1821,7 +1822,7 @@ do
         CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_ASSERTIONS=ON"
     fi
 
-    CMAKE_ARGS="$CMAKE_ARGS -DLLVM_TARGETS_TO_BUILD='X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430'"
+    CMAKE_ARGS="$CMAKE_ARGS -DLLVM_TARGETS_TO_BUILD='X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc'"
     CMAKE_ARGS="$CMAKE_ARGS -G '$CFG_CMAKE_GENERATOR'"
     CMAKE_ARGS="$CMAKE_ARGS $CFG_LLVM_SRC_DIR"
 
diff --git a/mk/cfg/sparc64-unknown-linux-gnu.mk b/mk/cfg/sparc64-unknown-linux-gnu.mk
new file mode 100644
index 00000000000..34aee77ae21
--- /dev/null
+++ b/mk/cfg/sparc64-unknown-linux-gnu.mk
@@ -0,0 +1 @@
+# rustbuild-only target
diff --git a/mk/cfg/sparc64-unknown-netbsd.mk b/mk/cfg/sparc64-unknown-netbsd.mk
new file mode 100644
index 00000000000..a2b01ba0537
--- /dev/null
+++ b/mk/cfg/sparc64-unknown-netbsd.mk
@@ -0,0 +1,3 @@
+# This file is intentially left empty to indicate that, while this target is
+# supported, it's not supported using plain GNU Make builds. Use a --rustbuild
+# instead.
diff --git a/mk/crates.mk b/mk/crates.mk
index 79df941aeb3..9624a51dda0 100644
--- a/mk/crates.mk
+++ b/mk/crates.mk
@@ -54,7 +54,7 @@ TARGET_CRATES := libc std term \
                  compiler_builtins core alloc \
                  std_unicode rustc_bitflags \
 		 alloc_system alloc_jemalloc \
-		 panic_abort panic_unwind unwind
+		 panic_abort panic_unwind unwind rustc_i128
 RUSTC_CRATES := rustc rustc_typeck rustc_mir rustc_borrowck rustc_resolve rustc_driver \
                 rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint \
                 rustc_data_structures rustc_platform_intrinsics rustc_errors \
@@ -92,23 +92,26 @@ DEPS_getopts := std
 DEPS_graphviz := std
 DEPS_log := std
 DEPS_num := std
-DEPS_serialize := std log
+DEPS_serialize := std log rustc_i128
 DEPS_term := std
 DEPS_test := std getopts term native:rust_test_helpers
+DEPS_rustc_i128 = std
 
-DEPS_syntax := std term serialize log arena libc rustc_bitflags std_unicode rustc_errors syntax_pos rustc_data_structures
+DEPS_syntax := std term serialize log arena libc rustc_bitflags std_unicode rustc_errors \
+			syntax_pos rustc_data_structures rustc_i128
 DEPS_syntax_ext := syntax syntax_pos rustc_errors fmt_macros proc_macro
+DEPS_proc_macro := syntax syntax_pos rustc_plugin log
 DEPS_syntax_pos := serialize
 DEPS_proc_macro_tokens := syntax syntax_pos log
 DEPS_proc_macro_plugin := syntax syntax_pos rustc_plugin log proc_macro_tokens
 
-DEPS_rustc_const_math := std syntax log serialize
+DEPS_rustc_const_math := std syntax log serialize rustc_i128
 DEPS_rustc_const_eval := rustc_const_math rustc syntax log serialize \
-			     rustc_back graphviz syntax_pos
+			     rustc_back graphviz syntax_pos rustc_i128
 
 DEPS_rustc := syntax fmt_macros flate arena serialize getopts \
               log graphviz rustc_llvm rustc_back rustc_data_structures\
-	      rustc_const_math syntax_pos rustc_errors
+	      rustc_const_math syntax_pos rustc_errors rustc_i128
 DEPS_rustc_back := std syntax flate log libc
 DEPS_rustc_borrowck := rustc log graphviz syntax syntax_pos rustc_errors rustc_mir
 DEPS_rustc_data_structures := std log serialize libc
@@ -119,19 +122,20 @@ DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_bo
                      rustc_passes rustc_save_analysis rustc_const_eval \
                      rustc_incremental syntax_pos rustc_errors proc_macro rustc_data_structures
 DEPS_rustc_errors := log libc serialize syntax_pos
-DEPS_rustc_lint := rustc log syntax syntax_pos rustc_const_eval
+DEPS_rustc_lint := rustc log syntax syntax_pos rustc_const_eval rustc_i128
 DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
 DEPS_proc_macro := std syntax
 DEPS_rustc_metadata := rustc syntax syntax_pos rustc_errors rustc_const_math \
-			proc_macro syntax_ext
+			proc_macro syntax_ext rustc_i128
 DEPS_rustc_passes := syntax syntax_pos rustc core rustc_const_eval rustc_errors
-DEPS_rustc_mir := rustc syntax syntax_pos rustc_const_math rustc_const_eval rustc_bitflags
+DEPS_rustc_mir := rustc syntax syntax_pos rustc_const_math rustc_const_eval rustc_bitflags \
+					rustc_i128
 DEPS_rustc_resolve := arena rustc log syntax syntax_pos rustc_errors
 DEPS_rustc_platform_intrinsics := std
 DEPS_rustc_plugin := rustc rustc_metadata syntax syntax_pos rustc_errors
 DEPS_rustc_privacy := rustc log syntax syntax_pos
 DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
-                    log syntax serialize rustc_llvm rustc_platform_intrinsics \
+                    log syntax serialize rustc_llvm rustc_platform_intrinsics rustc_i128 \
                     rustc_const_math rustc_const_eval rustc_incremental rustc_errors syntax_pos
 DEPS_rustc_incremental := rustc syntax_pos serialize rustc_data_structures
 DEPS_rustc_save_analysis := rustc log syntax syntax_pos serialize
@@ -159,6 +163,7 @@ ONLY_RLIB_alloc := 1
 ONLY_RLIB_rand := 1
 ONLY_RLIB_collections := 1
 ONLY_RLIB_std_unicode := 1
+ONLY_RLIB_rustc_i128 := 1
 ONLY_RLIB_rustc_bitflags := 1
 ONLY_RLIB_alloc_system := 1
 ONLY_RLIB_alloc_jemalloc := 1
diff --git a/mk/main.mk b/mk/main.mk
index d01ec07b424..2c646450d01 100644
--- a/mk/main.mk
+++ b/mk/main.mk
@@ -285,7 +285,7 @@ endif
 # LLVM macros
 ######################################################################
 
-LLVM_OPTIONAL_COMPONENTS=x86 arm aarch64 mips powerpc pnacl systemz jsbackend msp430
+LLVM_OPTIONAL_COMPONENTS=x86 arm aarch64 mips powerpc pnacl systemz jsbackend msp430 sparc
 LLVM_REQUIRED_COMPONENTS=ipo bitreader bitwriter linker asmparser mcjit \
                 interpreter instrumentation
 
diff --git a/src/Cargo.lock b/src/Cargo.lock
index 9cd77e71b82..3da29933c81 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -89,7 +89,7 @@ version = "0.0.0"
 dependencies = [
  "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "serialize 0.0.0",
+ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -249,6 +249,7 @@ dependencies = [
  "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
+ "rustc_i128 0.0.0",
  "rustc_llvm 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
@@ -308,6 +309,7 @@ dependencies = [
  "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
+ "rustc_i128 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
@@ -318,6 +320,7 @@ name = "rustc_const_math"
 version = "0.0.0"
 dependencies = [
  "log 0.0.0",
+ "rustc_i128 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
 ]
@@ -327,6 +330,7 @@ name = "rustc_data_structures"
 version = "0.0.0"
 dependencies = [
  "log 0.0.0",
+ "rustc_i128 0.0.0",
  "serialize 0.0.0",
 ]
 
@@ -373,6 +377,10 @@ dependencies = [
 ]
 
 [[package]]
+name = "rustc_i128"
+version = "0.0.0"
+
+[[package]]
 name = "rustc_incremental"
 version = "0.0.0"
 dependencies = [
@@ -380,6 +388,7 @@ dependencies = [
  "log 0.0.0",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
+ "rustc_i128 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
@@ -393,6 +402,7 @@ dependencies = [
  "rustc 0.0.0",
  "rustc_back 0.0.0",
  "rustc_const_eval 0.0.0",
+ "rustc_i128 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -418,6 +428,7 @@ dependencies = [
  "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
+ "rustc_i128 0.0.0",
  "rustc_llvm 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
@@ -437,6 +448,7 @@ dependencies = [
  "rustc_const_eval 0.0.0",
  "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
+ "rustc_i128 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
@@ -519,6 +531,7 @@ dependencies = [
  "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
+ "rustc_i128 0.0.0",
  "rustc_incremental 0.0.0",
  "rustc_llvm 0.0.0",
  "rustc_platform_intrinsics 0.0.0",
@@ -574,6 +587,7 @@ name = "serialize"
 version = "0.0.0"
 dependencies = [
  "log 0.0.0",
+ "rustc_i128 0.0.0",
 ]
 
 [[package]]
@@ -619,6 +633,7 @@ dependencies = [
  "rustc_bitflags 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
+ "rustc_i128 0.0.0",
  "serialize 0.0.0",
  "syntax_pos 0.0.0",
 ]
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index 129798836e0..90fd31ecbdd 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -89,7 +89,9 @@ fn main() {
         // When we build Rust dylibs they're all intended for intermediate
         // usage, so make sure we pass the -Cprefer-dynamic flag instead of
         // linking all deps statically into the dylib.
-        cmd.arg("-Cprefer-dynamic");
+        if env::var_os("RUSTC_NO_PREFER_DYNAMIC").is_none() {
+            cmd.arg("-Cprefer-dynamic");
+        }
 
         // Help the libc crate compile by assisting it in finding the MUSL
         // native libraries.
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index e7b0afeb8ce..6db1afa54a6 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -62,9 +62,9 @@ impl fmt::Display for TestKind {
 ///
 /// This tool in `src/tools` will verify the validity of all our links in the
 /// documentation to ensure we don't have a bunch of dead ones.
-pub fn linkcheck(build: &Build, stage: u32, host: &str) {
-    println!("Linkcheck stage{} ({})", stage, host);
-    let compiler = Compiler::new(stage, host);
+pub fn linkcheck(build: &Build, host: &str) {
+    println!("Linkcheck ({})", host);
+    let compiler = Compiler::new(0, host);
 
     let _time = util::timeit();
     build.run(build.tool_cmd(&compiler, "linkchecker")
@@ -93,10 +93,11 @@ pub fn cargotest(build: &Build, stage: u32, host: &str) {
     t!(fs::create_dir_all(&out_dir));
 
     let _time = util::timeit();
-    build.run(build.tool_cmd(compiler, "cargotest")
-                   .env("PATH", newpath)
-                   .arg(&build.cargo)
-                   .arg(&out_dir));
+    let mut cmd = Command::new(build.tool(&Compiler::new(0, host), "cargotest"));
+    build.prepare_tool_cmd(compiler, &mut cmd);
+    build.run(cmd.env("PATH", newpath)
+                 .arg(&build.cargo)
+                 .arg(&out_dir));
 }
 
 /// Runs the `tidy` tool as compiled in `stage` by the `host` compiler.
@@ -104,9 +105,9 @@ pub fn cargotest(build: &Build, stage: u32, host: &str) {
 /// This tool in `src/tools` checks up on various bits and pieces of style and
 /// otherwise just implements a few lint-like checks that are specific to the
 /// compiler itself.
-pub fn tidy(build: &Build, stage: u32, host: &str) {
-    println!("tidy check stage{} ({})", stage, host);
-    let compiler = Compiler::new(stage, host);
+pub fn tidy(build: &Build, host: &str) {
+    println!("tidy check ({})", host);
+    let compiler = Compiler::new(0, host);
     build.run(build.tool_cmd(&compiler, "tidy")
                    .arg(build.src.join("src")));
 }
@@ -127,7 +128,9 @@ pub fn compiletest(build: &Build,
                    suite: &str) {
     println!("Check compiletest suite={} mode={} ({} -> {})",
              suite, mode, compiler.host, target);
-    let mut cmd = build.tool_cmd(compiler, "compiletest");
+    let mut cmd = Command::new(build.tool(&Compiler::new(0, compiler.host),
+                                          "compiletest"));
+    build.prepare_tool_cmd(compiler, &mut cmd);
 
     // compiletest currently has... a lot of arguments, so let's just pass all
     // of them!
@@ -287,7 +290,8 @@ pub fn error_index(build: &Build, compiler: &Compiler) {
     let output = dir.join("error-index.md");
 
     let _time = util::timeit();
-    build.run(build.tool_cmd(compiler, "error_index_generator")
+    build.run(build.tool_cmd(&Compiler::new(0, compiler.host),
+                             "error_index_generator")
                    .arg("markdown")
                    .arg(&output)
                    .env("CFG_BUILD", &build.config.build));
@@ -341,12 +345,22 @@ pub fn krate(build: &Build,
     println!("{} {} stage{} ({} -> {})", test_kind, name, compiler.stage,
              compiler.host, target);
 
+    // If we're not doing a full bootstrap but we're testing a stage2 version of
+    // libstd, then what we're actually testing is the libstd produced in
+    // stage1. Reflect that here by updating the compiler that we're working
+    // with automatically.
+    let compiler = if build.force_use_stage1(compiler, target) {
+        Compiler::new(1, compiler.host)
+    } else {
+        compiler.clone()
+    };
+
     // Build up the base `cargo test` command.
     //
     // Pass in some standard flags then iterate over the graph we've discovered
     // in `cargo metadata` with the maps above and figure out what `-p`
     // arguments need to get passed.
-    let mut cargo = build.cargo(compiler, mode, target, test_kind.subcommand());
+    let mut cargo = build.cargo(&compiler, mode, target, test_kind.subcommand());
     cargo.arg("--manifest-path")
          .arg(build.src.join(path).join("Cargo.toml"))
          .arg("--features").arg(features);
@@ -380,7 +394,7 @@ pub fn krate(build: &Build,
     // Note that to run the compiler we need to run with the *host* libraries,
     // but our wrapper scripts arrange for that to be the case anyway.
     let mut dylib_path = dylib_path();
-    dylib_path.insert(0, build.sysroot_libdir(compiler, target));
+    dylib_path.insert(0, build.sysroot_libdir(&compiler, target));
     cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
 
     if target.contains("android") {
@@ -399,10 +413,10 @@ pub fn krate(build: &Build,
 
     if target.contains("android") {
         build.run(&mut cargo);
-        krate_android(build, compiler, target, mode);
+        krate_android(build, &compiler, target, mode);
     } else if target.contains("emscripten") {
         build.run(&mut cargo);
-        krate_emscripten(build, compiler, target, mode);
+        krate_emscripten(build, &compiler, target, mode);
     } else {
         cargo.args(&build.flags.cmd.test_args());
         build.run(&mut cargo);
@@ -497,6 +511,10 @@ fn find_tests(dir: &Path,
 pub fn android_copy_libs(build: &Build,
                          compiler: &Compiler,
                          target: &str) {
+    if !target.contains("android") {
+        return
+    }
+
     println!("Android copy libs to emulator ({})", target);
     build.run(Command::new("adb").arg("remount"));
     build.run(Command::new("adb").args(&["shell", "rm", "-r", ADB_TEST_DIR]));
@@ -544,6 +562,7 @@ pub fn distcheck(build: &Build) {
        .current_dir(&dir);
     build.run(&mut cmd);
     build.run(Command::new("./configure")
+                     .args(&build.config.configure_args)
                      .current_dir(&dir));
     build.run(Command::new(build_helper::make(&build.config.build))
                      .arg("check")
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index b268686ca6c..31f8754d209 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -33,17 +33,12 @@ use {Build, Compiler, Mode};
 /// This will build the standard library for a particular stage of the build
 /// using the `compiler` targeting the `target` architecture. The artifacts
 /// created will also be linked into the sysroot directory.
-pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
-    println!("Building stage{} std artifacts ({} -> {})", compiler.stage,
-             compiler.host, target);
-
+pub fn std(build: &Build, target: &str, compiler: &Compiler) {
     let libdir = build.sysroot_libdir(compiler, target);
-    let _ = fs::remove_dir_all(&libdir);
     t!(fs::create_dir_all(&libdir));
 
-    // Some platforms have startup objects that may be required to produce the
-    // libstd dynamic library, for example.
-    build_startup_objects(build, target, &libdir);
+    println!("Building stage{} std artifacts ({} -> {})", compiler.stage,
+             compiler.host, target);
 
     let out_dir = build.cargo_out(compiler, Mode::Libstd, target);
     build.clear_if_dirty(&out_dir, &build.compiler_path(compiler));
@@ -65,29 +60,30 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
 
     build.run(&mut cargo);
     update_mtime(&libstd_stamp(build, &compiler, target));
-    std_link(build, target, compiler.stage, compiler.host);
 }
 
 /// Link all libstd rlibs/dylibs into the sysroot location.
 ///
-/// Links those artifacts generated in the given `stage` for `target` produced
-/// by `compiler` into `host`'s sysroot.
+/// Links those artifacts generated by `compiler` to a the `stage` compiler's
+/// sysroot for the specified `host` and `target`.
+///
+/// Note that this assumes that `compiler` has already generated the libstd
+/// libraries for `target`, and this method will find them in the relevant
+/// output directory.
 pub fn std_link(build: &Build,
-                target: &str,
-                stage: u32,
-                host: &str) {
-    let compiler = Compiler::new(stage, &build.config.build);
-    let target_compiler = Compiler::new(compiler.stage, host);
+                compiler: &Compiler,
+                target_compiler: &Compiler,
+                target: &str) {
+    println!("Copying stage{} std from stage{} ({} -> {} / {})",
+             target_compiler.stage,
+             compiler.stage,
+             compiler.host,
+             target_compiler.host,
+             target);
     let libdir = build.sysroot_libdir(&target_compiler, target);
     let out_dir = build.cargo_out(&compiler, Mode::Libstd, target);
 
-    // If we're linking one compiler host's output into another, then we weren't
-    // called from the `std` method above. In that case we clean out what's
-    // already there.
-    if host != compiler.host {
-        let _ = fs::remove_dir_all(&libdir);
-        t!(fs::create_dir_all(&libdir));
-    }
+    t!(fs::create_dir_all(&libdir));
     add_to_sysroot(&out_dir, &libdir);
 
     if target.contains("musl") && !target.contains("mips") {
@@ -110,12 +106,15 @@ fn copy_musl_third_party_objects(build: &Build, target: &str, into: &Path) {
 /// They don't require any library support as they're just plain old object
 /// files, so we just use the nightly snapshot compiler to always build them (as
 /// no other compilers are guaranteed to be available).
-fn build_startup_objects(build: &Build, target: &str, into: &Path) {
+pub fn build_startup_objects(build: &Build, for_compiler: &Compiler, target: &str) {
     if !target.contains("pc-windows-gnu") {
         return
     }
+
     let compiler = Compiler::new(0, &build.config.build);
     let compiler_path = build.compiler_path(&compiler);
+    let into = build.sysroot_libdir(for_compiler, target);
+    t!(fs::create_dir_all(&into));
 
     for file in t!(fs::read_dir(build.src.join("src/rtstartup"))) {
         let file = t!(file);
@@ -123,7 +122,7 @@ fn build_startup_objects(build: &Build, target: &str, into: &Path) {
         build.run(cmd.env("RUSTC_BOOTSTRAP", "1")
                      .arg("--target").arg(target)
                      .arg("--emit=obj")
-                     .arg("--out-dir").arg(into)
+                     .arg("--out-dir").arg(&into)
                      .arg(file.path()));
     }
 
@@ -137,7 +136,7 @@ fn build_startup_objects(build: &Build, target: &str, into: &Path) {
 /// This will build libtest and supporting libraries for a particular stage of
 /// the build using the `compiler` targeting the `target` architecture. The
 /// artifacts created will also be linked into the sysroot directory.
-pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
+pub fn test(build: &Build, target: &str, compiler: &Compiler) {
     println!("Building stage{} test artifacts ({} -> {})", compiler.stage,
              compiler.host, target);
     let out_dir = build.cargo_out(compiler, Mode::Libtest, target);
@@ -147,19 +146,19 @@ pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
          .arg(build.src.join("src/rustc/test_shim/Cargo.toml"));
     build.run(&mut cargo);
     update_mtime(&libtest_stamp(build, compiler, target));
-    test_link(build, target, compiler.stage, compiler.host);
 }
 
-/// Link all libtest rlibs/dylibs into the sysroot location.
-///
-/// Links those artifacts generated in the given `stage` for `target` produced
-/// by `compiler` into `host`'s sysroot.
+/// Same as `std_link`, only for libtest
 pub fn test_link(build: &Build,
-                 target: &str,
-                 stage: u32,
-                 host: &str) {
-    let compiler = Compiler::new(stage, &build.config.build);
-    let target_compiler = Compiler::new(compiler.stage, host);
+                 compiler: &Compiler,
+                 target_compiler: &Compiler,
+                 target: &str) {
+    println!("Copying stage{} test from stage{} ({} -> {} / {})",
+             target_compiler.stage,
+             compiler.stage,
+             compiler.host,
+             target_compiler.host,
+             target);
     let libdir = build.sysroot_libdir(&target_compiler, target);
     let out_dir = build.cargo_out(&compiler, Mode::Libtest, target);
     add_to_sysroot(&out_dir, &libdir);
@@ -170,7 +169,7 @@ pub fn test_link(build: &Build,
 /// This will build the compiler for a particular stage of the build using
 /// the `compiler` targeting the `target` architecture. The artifacts
 /// created will also be linked into the sysroot directory.
-pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
+pub fn rustc(build: &Build, target: &str, compiler: &Compiler) {
     println!("Building stage{} compiler artifacts ({} -> {})",
              compiler.stage, compiler.host, target);
 
@@ -222,20 +221,19 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) {
         cargo.env("CFG_DEFAULT_AR", s);
     }
     build.run(&mut cargo);
-
-    rustc_link(build, target, compiler.stage, compiler.host);
 }
 
-/// Link all librustc rlibs/dylibs into the sysroot location.
-///
-/// Links those artifacts generated in the given `stage` for `target` produced
-/// by `compiler` into `host`'s sysroot.
+/// Same as `std_link`, only for librustc
 pub fn rustc_link(build: &Build,
-                  target: &str,
-                  stage: u32,
-                  host: &str) {
-    let compiler = Compiler::new(stage, &build.config.build);
-    let target_compiler = Compiler::new(compiler.stage, host);
+                  compiler: &Compiler,
+                  target_compiler: &Compiler,
+                  target: &str) {
+    println!("Copying stage{} rustc from stage{} ({} -> {} / {})",
+             target_compiler.stage,
+             compiler.stage,
+             compiler.host,
+             target_compiler.host,
+             target);
     let libdir = build.sysroot_libdir(&target_compiler, target);
     let out_dir = build.cargo_out(&compiler, Mode::Librustc, target);
     add_to_sysroot(&out_dir, &libdir);
@@ -259,6 +257,12 @@ fn compiler_file(compiler: &Path, file: &str) -> PathBuf {
     PathBuf::from(out.trim())
 }
 
+pub fn create_sysroot(build: &Build, compiler: &Compiler) {
+    let sysroot = build.sysroot(compiler);
+    let _ = fs::remove_dir_all(&sysroot);
+    t!(fs::create_dir_all(&sysroot));
+}
+
 /// Prepare a new compiler from the artifacts in `stage`
 ///
 /// This will assemble a compiler in `build/$host/stage$stage`. The compiler
@@ -269,18 +273,17 @@ pub fn assemble_rustc(build: &Build, stage: u32, host: &str) {
     if stage == 0 {
         return
     }
+
+    println!("Copying stage{} compiler ({})", stage, host);
+
     // The compiler that we're assembling
     let target_compiler = Compiler::new(stage, host);
 
     // The compiler that compiled the compiler we're assembling
     let build_compiler = Compiler::new(stage - 1, &build.config.build);
 
-    // Clear out old files
-    let sysroot = build.sysroot(&target_compiler);
-    let _ = fs::remove_dir_all(&sysroot);
-    t!(fs::create_dir_all(&sysroot));
-
     // Link in all dylibs to the libdir
+    let sysroot = build.sysroot(&target_compiler);
     let sysroot_libdir = sysroot.join(libdir(host));
     t!(fs::create_dir_all(&sysroot_libdir));
     let src_libdir = build.sysroot_libdir(&build_compiler, host);
@@ -371,6 +374,11 @@ pub fn tool(build: &Build, stage: u32, host: &str, tool: &str) {
     let mut cargo = build.cargo(&compiler, Mode::Tool, host, "build");
     cargo.arg("--manifest-path")
          .arg(build.src.join(format!("src/tools/{}/Cargo.toml", tool)));
+
+    // We don't want to build tools dynamically as they'll be running across
+    // stages and such and it's just easier if they're not dynamically linked.
+    cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
+
     build.run(&mut cargo);
 }
 
@@ -383,7 +391,7 @@ pub fn tool(build: &Build, stage: u32, host: &str, tool: &str) {
 /// all files in a directory and updating the stamp if any are newer.
 fn update_mtime(path: &Path) {
     let mut max = None;
-    if let Ok(entries) = path.parent().unwrap().read_dir() {
+    if let Ok(entries) = path.parent().unwrap().join("deps").read_dir() {
         for entry in entries.map(|e| t!(e)) {
             if t!(entry.file_type()).is_file() {
                 let meta = t!(entry.metadata());
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 6b86e537b7d..11c5b374ed9 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -46,6 +46,7 @@ pub struct Config {
     pub docs: bool,
     pub vendor: bool,
     pub target_config: HashMap<String, Target>,
+    pub full_bootstrap: bool,
 
     // llvm codegen options
     pub llvm_assertions: bool,
@@ -54,6 +55,7 @@ pub struct Config {
     pub llvm_version_check: bool,
     pub llvm_static_stdcpp: bool,
     pub llvm_link_shared: bool,
+    pub llvm_targets: Option<String>,
 
     // rust codegen options
     pub rust_optimize: bool,
@@ -92,6 +94,7 @@ pub struct Config {
     pub nodejs: Option<PathBuf>,
     pub gdb: Option<PathBuf>,
     pub python: Option<PathBuf>,
+    pub configure_args: Vec<String>,
 }
 
 /// Per-target configuration stored in the global configuration structure.
@@ -134,6 +137,7 @@ struct Build {
     vendor: Option<bool>,
     nodejs: Option<String>,
     python: Option<String>,
+    full_bootstrap: Option<bool>,
 }
 
 /// TOML representation of various global install decisions.
@@ -152,6 +156,7 @@ struct Llvm {
     release_debuginfo: Option<bool>,
     version_check: Option<bool>,
     static_libstdcpp: Option<bool>,
+    targets: Option<String>,
 }
 
 #[derive(RustcDecodable)]
@@ -264,6 +269,7 @@ impl Config {
         set(&mut config.docs, build.docs);
         set(&mut config.submodules, build.submodules);
         set(&mut config.vendor, build.vendor);
+        set(&mut config.full_bootstrap, build.full_bootstrap);
 
         if let Some(ref install) = toml.install {
             config.prefix = install.prefix.clone();
@@ -285,6 +291,7 @@ impl Config {
             set(&mut config.llvm_release_debuginfo, llvm.release_debuginfo);
             set(&mut config.llvm_version_check, llvm.version_check);
             set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp);
+            config.llvm_targets = llvm.targets.clone();
         }
 
         if let Some(ref rust) = toml.rust {
@@ -393,6 +400,7 @@ impl Config {
                 ("NINJA", self.ninja),
                 ("CODEGEN_TESTS", self.codegen_tests),
                 ("VENDOR", self.vendor),
+                ("FULL_BOOTSTRAP", self.full_bootstrap),
             }
 
             match key {
@@ -512,6 +520,11 @@ impl Config {
                 "CFG_ENABLE_SCCACHE" if value == "1" => {
                     self.ccache = Some("sccache".to_string());
                 }
+                "CFG_CONFIGURE_ARGS" if value.len() > 0 => {
+                    self.configure_args = value.split_whitespace()
+                                               .map(|s| s.to_string())
+                                               .collect();
+                }
                 _ => {}
             }
         }
diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example
index 5fc095137c7..69210c4959b 100644
--- a/src/bootstrap/config.toml.example
+++ b/src/bootstrap/config.toml.example
@@ -42,6 +42,17 @@
 # example.
 #ninja = false
 
+# LLVM targets to build support for.
+# Note: this is NOT related to Rust compilation targets. However, as Rust is
+# dependent on LLVM for code generation, turning targets off here WILL lead to
+# the resulting rustc being unable to compile for the disabled architectures.
+# Also worth pointing out is that, in case support for new targets are added to
+# LLVM, enabling them here doesn't mean Rust is automatically gaining said
+# support. You'll need to write a target specification at least, and most
+# likely, teach rustc about the C ABI of the target. Get in touch with the
+# Rust team and file an issue if you need assistance in porting!
+#targets = "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX"
+
 # =============================================================================
 # General build configuration options
 # =============================================================================
@@ -100,6 +111,13 @@
 # Indicate whether the vendored sources are used for Rust dependencies or not
 #vendor = false
 
+# Typically the build system will build the rust compiler twice. The second
+# compiler, however, will simply use its own libraries to link against. If you
+# would rather to perform a full bootstrap, compiling the compiler three times,
+# then you can set this option to true. You shouldn't ever need to set this
+# option to true.
+#full-bootstrap = false
+
 # =============================================================================
 # General install configuration options
 # =============================================================================
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 6e3174ed2f6..9b0c7a04d6b 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -320,10 +320,18 @@ pub fn analysis(build: &Build, compiler: &Compiler, target: &str) {
         return
     }
 
+    // Package save-analysis from stage1 if not doing a full bootstrap, as the
+    // stage2 artifacts is simply copied from stage1 in that case.
+    let compiler = if build.force_use_stage1(compiler, target) {
+        Compiler::new(1, compiler.host)
+    } else {
+        compiler.clone()
+    };
+
     let name = format!("rust-analysis-{}", package_vers(build));
     let image = tmpdir(build).join(format!("{}-{}-image", name, target));
 
-    let src = build.stage_out(compiler, Mode::Libstd).join(target).join("release").join("deps");
+    let src = build.stage_out(&compiler, Mode::Libstd).join(target).join("release").join("deps");
 
     let image_src = src.join("save-analysis");
     let dst = image.join("lib/rustlib").join(target).join("analysis");
@@ -397,6 +405,13 @@ pub fn rust_src(build: &Build, host: &str) {
             }
         }
 
+        // If we're inside the vendor directory then we need to preserve
+        // everything as Cargo's vendoring support tracks all checksums and we
+        // want to be sure we don't accidentally leave out a file.
+        if spath.contains("vendor") {
+            return true
+        }
+
         let excludes = [
             "CVS", "RCS", "SCCS", ".git", ".gitignore", ".gitmodules",
             ".gitattributes", ".cvsignore", ".svn", ".arch-ids", "{arch}",
diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs
index 30c7fefad87..bbbf5cba8a1 100644
--- a/src/bootstrap/doc.rs
+++ b/src/bootstrap/doc.rs
@@ -29,19 +29,19 @@ use util::{up_to_date, cp_r};
 ///
 /// This will not actually generate any documentation if the documentation has
 /// already been generated.
-pub fn rustbook(build: &Build, stage: u32, target: &str, name: &str) {
+pub fn rustbook(build: &Build, target: &str, name: &str) {
     let out = build.doc_out(target);
     t!(fs::create_dir_all(&out));
 
     let out = out.join(name);
-    let compiler = Compiler::new(stage, &build.config.build);
+    let compiler = Compiler::new(0, &build.config.build);
     let src = build.src.join("src/doc").join(name);
     let index = out.join("index.html");
     let rustbook = build.tool(&compiler, "rustbook");
     if up_to_date(&src, &index) && up_to_date(&rustbook, &index) {
         return
     }
-    println!("Rustbook stage{} ({}) - {}", stage, target, name);
+    println!("Rustbook ({}) - {}", target, name);
     let _ = fs::remove_dir_all(&out);
     build.run(build.tool_cmd(&compiler, "rustbook")
                    .arg("build")
@@ -137,6 +137,11 @@ pub fn std(build: &Build, stage: u32, target: &str) {
     let out = build.doc_out(target);
     t!(fs::create_dir_all(&out));
     let compiler = Compiler::new(stage, &build.config.build);
+    let compiler = if build.force_use_stage1(&compiler, target) {
+        Compiler::new(1, compiler.host)
+    } else {
+        compiler
+    };
     let out_dir = build.stage_out(&compiler, Mode::Libstd)
                        .join(target).join("doc");
     let rustdoc = build.rustdoc(&compiler);
@@ -146,7 +151,8 @@ pub fn std(build: &Build, stage: u32, target: &str) {
     let mut cargo = build.cargo(&compiler, Mode::Libstd, target, "doc");
     cargo.arg("--manifest-path")
          .arg(build.src.join("src/rustc/std_shim/Cargo.toml"))
-         .arg("--features").arg(build.std_features());
+         .arg("--features").arg(build.std_features())
+         .arg("-p").arg("std");
     build.run(&mut cargo);
     cp_r(&out_dir, &out)
 }
@@ -160,6 +166,11 @@ pub fn test(build: &Build, stage: u32, target: &str) {
     let out = build.doc_out(target);
     t!(fs::create_dir_all(&out));
     let compiler = Compiler::new(stage, &build.config.build);
+    let compiler = if build.force_use_stage1(&compiler, target) {
+        Compiler::new(1, compiler.host)
+    } else {
+        compiler
+    };
     let out_dir = build.stage_out(&compiler, Mode::Libtest)
                        .join(target).join("doc");
     let rustdoc = build.rustdoc(&compiler);
@@ -182,6 +193,11 @@ pub fn rustc(build: &Build, stage: u32, target: &str) {
     let out = build.doc_out(target);
     t!(fs::create_dir_all(&out));
     let compiler = Compiler::new(stage, &build.config.build);
+    let compiler = if build.force_use_stage1(&compiler, target) {
+        Compiler::new(1, compiler.host)
+    } else {
+        compiler
+    };
     let out_dir = build.stage_out(&compiler, Mode::Librustc)
                        .join(target).join("doc");
     let rustdoc = build.rustdoc(&compiler);
@@ -198,11 +214,11 @@ pub fn rustc(build: &Build, stage: u32, target: &str) {
 
 /// Generates the HTML rendered error-index by running the
 /// `error_index_generator` tool.
-pub fn error_index(build: &Build, stage: u32, target: &str) {
-    println!("Documenting stage{} error index ({})", stage, target);
+pub fn error_index(build: &Build, target: &str) {
+    println!("Documenting error index ({})", target);
     let out = build.doc_out(target);
     t!(fs::create_dir_all(&out));
-    let compiler = Compiler::new(stage, &build.config.build);
+    let compiler = Compiler::new(0, &build.config.build);
     let mut index = build.tool_cmd(&compiler, "error_index_generator");
     index.arg("html");
     index.arg(out.join("error-index.html"));
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 665e0c67b7f..6b2b6ad5c02 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -521,7 +521,7 @@ impl Build {
                  .env(format!("CFLAGS_{}", target), self.cflags(target).join(" "));
         }
 
-        if self.config.channel == "nightly" && compiler.stage == 2 {
+        if self.config.channel == "nightly" && compiler.is_final_stage(self) {
             cargo.env("RUSTC_SAVE_ANALYSIS", "api".to_string());
         }
 
@@ -570,11 +570,18 @@ impl Build {
     /// `host`.
     fn tool_cmd(&self, compiler: &Compiler, tool: &str) -> Command {
         let mut cmd = Command::new(self.tool(&compiler, tool));
+        self.prepare_tool_cmd(compiler, &mut cmd);
+        return cmd
+    }
+
+    /// Prepares the `cmd` provided to be able to run the `compiler` provided.
+    ///
+    /// Notably this munges the dynamic library lookup path to point to the
+    /// right location to run `compiler`.
+    fn prepare_tool_cmd(&self, compiler: &Compiler, cmd: &mut Command) {
         let host = compiler.host;
         let mut paths = vec![
-            self.cargo_out(compiler, Mode::Libstd, host).join("deps"),
-            self.cargo_out(compiler, Mode::Libtest, host).join("deps"),
-            self.cargo_out(compiler, Mode::Librustc, host).join("deps"),
+            self.sysroot_libdir(compiler, compiler.host),
             self.cargo_out(compiler, Mode::Tool, host).join("deps"),
         ];
 
@@ -595,8 +602,7 @@ impl Build {
                 }
             }
         }
-        add_lib_path(paths, &mut cmd);
-        return cmd
+        add_lib_path(paths, cmd);
     }
 
     /// Get the space-separated set of activated features for the standard
@@ -880,6 +886,30 @@ impl Build {
     fn python(&self) -> &Path {
         self.config.python.as_ref().unwrap()
     }
+
+    /// Tests whether the `compiler` compiling for `target` should be forced to
+    /// use a stage1 compiler instead.
+    ///
+    /// Currently, by default, the build system does not perform a "full
+    /// bootstrap" by default where we compile the compiler three times.
+    /// Instead, we compile the compiler two times. The final stage (stage2)
+    /// just copies the libraries from the previous stage, which is what this
+    /// method detects.
+    ///
+    /// Here we return `true` if:
+    ///
+    /// * The build isn't performing a full bootstrap
+    /// * The `compiler` is in the final stage, 2
+    /// * We're not cross-compiling, so the artifacts are already available in
+    ///   stage1
+    ///
+    /// When all of these conditions are met the build will lift artifacts from
+    /// the previous stage forward.
+    fn force_use_stage1(&self, compiler: &Compiler, target: &str) -> bool {
+        !self.config.full_bootstrap &&
+            compiler.stage >= 2 &&
+            self.config.host.iter().any(|h| h == target)
+    }
 }
 
 impl<'a> Compiler<'a> {
@@ -892,4 +922,13 @@ impl<'a> Compiler<'a> {
     fn is_snapshot(&self, build: &Build) -> bool {
         self.stage == 0 && self.host == build.config.build
     }
+
+    /// Returns if this compiler should be treated as a final stage one in the
+    /// current build session.
+    /// This takes into account whether we're performing a full bootstrap or
+    /// not; don't directly compare the stage with `2`!
+    fn is_final_stage(&self, build: &Build) -> bool {
+        let final_stage = if build.config.full_bootstrap { 2 } else { 1 };
+        self.stage >= final_stage
+    }
 }
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index 0d83a79cf32..d6f6a7772c9 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -51,8 +51,16 @@ standalone-docs:
 	$(Q)$(BOOTSTRAP) doc src/doc $(BOOTSTRAP_ARGS)
 check:
 	$(Q)$(BOOTSTRAP) test $(BOOTSTRAP_ARGS)
-check-cargotest:
-	$(Q)$(BOOTSTRAP) test src/tools/cargotest $(BOOTSTRAP_ARGS)
+check-aux:
+	$(Q)$(BOOTSTRAP) test \
+		src/tools/cargotest \
+		src/test/pretty \
+		src/test/run-pass/pretty \
+		src/test/run-fail/pretty \
+		src/test/run-pass-valgrind/pretty \
+		src/test/run-pass-fulldeps/pretty \
+		src/test/run-fail-fulldeps/pretty \
+		$(BOOTSTRAP_ARGS)
 dist:
 	$(Q)$(BOOTSTRAP) dist $(BOOTSTRAP_ARGS)
 distcheck:
@@ -61,7 +69,7 @@ distcheck:
 install:
 	$(Q)$(BOOTSTRAP) dist --install $(BOOTSTRAP_ARGS)
 tidy:
-	$(Q)$(BOOTSTRAP) test src/tools/tidy $(BOOTSTRAP_ARGS) --stage 0
+	$(Q)$(BOOTSTRAP) test src/tools/tidy $(BOOTSTRAP_ARGS)
 
 check-stage2-T-arm-linux-androideabi-H-x86_64-unknown-linux-gnu:
 	$(Q)$(BOOTSTRAP) test --target arm-linux-androideabi
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 09dbd9f8220..4b6fef8edc1 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -75,13 +75,18 @@ pub fn llvm(build: &Build, target: &str) {
         (true, true) => "RelWithDebInfo",
     };
 
+    // NOTE: remember to also update `config.toml.example` when changing the defaults!
+    let llvm_targets = match build.config.llvm_targets {
+        Some(ref s) => s,
+        None => "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX",
+    };
+
     cfg.target(target)
        .host(&build.config.build)
        .out_dir(&dst)
        .profile(profile)
        .define("LLVM_ENABLE_ASSERTIONS", assertions)
-       .define("LLVM_TARGETS_TO_BUILD",
-               "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc")
+       .define("LLVM_TARGETS_TO_BUILD", llvm_targets)
        .define("LLVM_INCLUDE_EXAMPLES", "OFF")
        .define("LLVM_INCLUDE_TESTS", "OFF")
        .define("LLVM_INCLUDE_DOCS", "OFF")
diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs
index 52caa3f0958..6a81f759dc7 100644
--- a/src/bootstrap/step.rs
+++ b/src/bootstrap/step.rs
@@ -44,7 +44,7 @@ pub fn run(build: &Build) {
     rules.run(&steps);
 }
 
-pub fn build_rules(build: &Build) -> Rules {
+pub fn build_rules<'a>(build: &'a Build) -> Rules {
     let mut rules = Rules::new(build);
 
     // This is the first rule that we're going to define for rustbuild, which is
@@ -117,6 +117,7 @@ pub fn build_rules(build: &Build) -> Rules {
 
     // the compiler with no target libraries ready to go
     rules.build("rustc", "src/rustc")
+         .dep(|s| s.name("create-sysroot").target(s.host))
          .dep(move |s| {
              if s.stage == 0 {
                  Step::noop()
@@ -151,91 +152,153 @@ pub fn build_rules(build: &Build) -> Rules {
     // Crate compilations
     //
     // Tools used during the build system but not shipped
+    rules.build("create-sysroot", "path/to/nowhere")
+         .run(move |s| compile::create_sysroot(build, &s.compiler()));
+
+    // These rules are "pseudo rules" that don't actually do any work
+    // themselves, but represent a complete sysroot with the relevant compiler
+    // linked into place.
+    //
+    // That is, depending on "libstd" means that when the rule is completed then
+    // the `stage` sysroot for the compiler `host` will be available with a
+    // standard library built for `target` linked in place. Not all rules need
+    // the compiler itself to be available, just the standard library, so
+    // there's a distinction between the two.
     rules.build("libstd", "src/libstd")
-         .dep(|s| s.name("build-crate-std_shim"));
+         .dep(|s| s.name("rustc").target(s.host))
+         .dep(|s| s.name("libstd-link"));
     rules.build("libtest", "src/libtest")
-         .dep(|s| s.name("build-crate-test_shim"));
+         .dep(|s| s.name("libstd"))
+         .dep(|s| s.name("libtest-link"))
+         .default(true);
     rules.build("librustc", "src/librustc")
-         .dep(|s| s.name("build-crate-rustc-main"));
+         .dep(|s| s.name("libtest"))
+         .dep(|s| s.name("librustc-link"))
+         .host(true)
+         .default(true);
+
+    // Helper method to define the rules to link a crate into its place in the
+    // sysroot.
+    //
+    // The logic here is a little subtle as there's a few cases to consider.
+    // Not all combinations of (stage, host, target) actually require something
+    // to be compiled, but rather libraries could get propagated from a
+    // different location. For example:
+    //
+    // * Any crate with a `host` that's not the build triple will not actually
+    //   compile something. A different `host` means that the build triple will
+    //   actually compile the libraries, and then we'll copy them over from the
+    //   build triple to the `host` directory.
+    //
+    // * Some crates aren't even compiled by the build triple, but may be copied
+    //   from previous stages. For example if we're not doing a full bootstrap
+    //   then we may just depend on the stage1 versions of libraries to be
+    //   available to get linked forward.
+    //
+    // * Finally, there are some cases, however, which do indeed comiple crates
+    //   and link them into place afterwards.
+    //
+    // The rule definition below mirrors these three cases. The `dep` method
+    // calculates the correct dependency which either comes from stage1, a
+    // different compiler, or from actually building the crate itself (the `dep`
+    // rule). The `run` rule then mirrors these three cases and links the cases
+    // forward into the compiler sysroot specified from the correct location.
+    fn crate_rule<'a, 'b>(build: &'a Build,
+                          rules: &'b mut Rules<'a>,
+                          krate: &'a str,
+                          dep: &'a str,
+                          link: fn(&Build, &Compiler, &Compiler, &str))
+                          -> RuleBuilder<'a, 'b> {
+        let mut rule = rules.build(&krate, "path/to/nowhere");
+        rule.dep(move |s| {
+                if build.force_use_stage1(&s.compiler(), s.target) {
+                    s.host(&build.config.build).stage(1)
+                } else if s.host == build.config.build {
+                    s.name(dep)
+                } else {
+                    s.host(&build.config.build)
+                }
+            })
+            .run(move |s| {
+                if build.force_use_stage1(&s.compiler(), s.target) {
+                    link(build,
+                         &s.stage(1).host(&build.config.build).compiler(),
+                         &s.compiler(),
+                         s.target)
+                } else if s.host == build.config.build {
+                    link(build, &s.compiler(), &s.compiler(), s.target)
+                } else {
+                    link(build,
+                         &s.host(&build.config.build).compiler(),
+                         &s.compiler(),
+                         s.target)
+                }
+            });
+            return rule
+    }
+
+    // Similar to the `libstd`, `libtest`, and `librustc` rules above, except
+    // these rules only represent the libraries being available in the sysroot,
+    // not the compiler itself. This is done as not all rules need a compiler in
+    // the sysroot, but may just need the libraries.
+    //
+    // All of these rules use the helper definition above.
+    crate_rule(build,
+               &mut rules,
+               "libstd-link",
+               "build-crate-std_shim",
+               compile::std_link)
+        .dep(|s| s.name("startup-objects"))
+        .dep(|s| s.name("create-sysroot").target(s.host));
+    crate_rule(build,
+               &mut rules,
+               "libtest-link",
+               "build-crate-test_shim",
+               compile::test_link)
+        .dep(|s| s.name("libstd-link"));
+    crate_rule(build,
+               &mut rules,
+               "librustc-link",
+               "build-crate-rustc-main",
+               compile::rustc_link)
+        .dep(|s| s.name("libtest-link"));
+
     for (krate, path, _default) in krates("std_shim") {
         rules.build(&krate.build_step, path)
+             .dep(|s| s.name("startup-objects"))
              .dep(move |s| s.name("rustc").host(&build.config.build).target(s.host))
-             .dep(move |s| {
-                 if s.host == build.config.build {
-                     Step::noop()
-                 } else {
-                    s.host(&build.config.build)
-                 }
-             })
-             .run(move |s| {
-                 if s.host == build.config.build {
-                    compile::std(build, s.target, &s.compiler())
-                 } else {
-                    compile::std_link(build, s.target, s.stage, s.host)
-                 }
-             });
+             .run(move |s| compile::std(build, s.target, &s.compiler()));
     }
-    for (krate, path, default) in krates("test_shim") {
+    for (krate, path, _default) in krates("test_shim") {
         rules.build(&krate.build_step, path)
-             .dep(|s| s.name("libstd"))
-             .dep(move |s| {
-                 if s.host == build.config.build {
-                    Step::noop()
-                 } else {
-                    s.host(&build.config.build)
-                 }
-             })
-             .default(default)
-             .run(move |s| {
-                 if s.host == build.config.build {
-                    compile::test(build, s.target, &s.compiler())
-                 } else {
-                    compile::test_link(build, s.target, s.stage, s.host)
-                 }
-             });
+             .dep(|s| s.name("libstd-link"))
+             .run(move |s| compile::test(build, s.target, &s.compiler()));
     }
-    for (krate, path, default) in krates("rustc-main") {
+    for (krate, path, _default) in krates("rustc-main") {
         rules.build(&krate.build_step, path)
-             .dep(|s| s.name("libtest"))
+             .dep(|s| s.name("libtest-link"))
              .dep(move |s| s.name("llvm").host(&build.config.build).stage(0))
-             .dep(move |s| {
-                 if s.host == build.config.build {
-                    Step::noop()
-                 } else {
-                    s.host(&build.config.build)
-                 }
-             })
-             .host(true)
-             .default(default)
-             .run(move |s| {
-                 if s.host == build.config.build {
-                    compile::rustc(build, s.target, &s.compiler())
-                 } else {
-                    compile::rustc_link(build, s.target, s.stage, s.host)
-                 }
-             });
+             .run(move |s| compile::rustc(build, s.target, &s.compiler()));
     }
 
+    rules.build("startup-objects", "src/rtstartup")
+         .dep(|s| s.name("create-sysroot").target(s.host))
+         .run(move |s| compile::build_startup_objects(build, &s.compiler(), s.target));
+
     // ========================================================================
     // Test targets
     //
     // Various unit tests and tests suites we can run
     {
-        let mut suite = |name, path, dir, mode| {
+        let mut suite = |name, path, mode, dir| {
             rules.test(name, path)
                  .dep(|s| s.name("libtest"))
-                 .dep(|s| s.name("tool-compiletest").target(s.host))
+                 .dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
                  .dep(|s| s.name("test-helpers"))
-                 .dep(move |s| {
-                     if s.target.contains("android") {
-                         s.name("android-copy-libs")
-                     } else {
-                         Step::noop()
-                     }
-                 })
-                 .default(true)
+                 .dep(|s| s.name("android-copy-libs"))
+                 .default(mode != "pretty") // pretty tests don't run everywhere
                  .run(move |s| {
-                     check::compiletest(build, &s.compiler(), s.target, dir, mode)
+                     check::compiletest(build, &s.compiler(), s.target, mode, dir)
                  });
         };
 
@@ -254,35 +317,33 @@ pub fn build_rules(build: &Build) -> Rules {
         suite("check-incremental", "src/test/incremental", "incremental",
               "incremental");
         suite("check-ui", "src/test/ui", "ui", "ui");
-        suite("check-pretty", "src/test/pretty", "pretty", "pretty");
-        suite("check-pretty-rpass", "src/test/run-pass/pretty", "pretty",
-              "run-pass");
-        suite("check-pretty-rfail", "src/test/run-pass/pretty", "pretty",
-              "run-fail");
-        suite("check-pretty-valgrind", "src/test/run-pass-valgrind", "pretty",
-              "run-pass-valgrind");
     }
 
     if build.config.build.contains("msvc") {
         // nothing to do for debuginfo tests
-    } else if build.config.build.contains("apple") {
-        rules.test("check-debuginfo", "src/test/debuginfo")
-             .default(true)
+    } else {
+        rules.test("check-debuginfo-lldb", "src/test/debuginfo-lldb")
              .dep(|s| s.name("libtest"))
-             .dep(|s| s.name("tool-compiletest").target(s.host))
+             .dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
              .dep(|s| s.name("test-helpers"))
              .dep(|s| s.name("debugger-scripts"))
              .run(move |s| check::compiletest(build, &s.compiler(), s.target,
                                          "debuginfo-lldb", "debuginfo"));
-    } else {
-        rules.test("check-debuginfo", "src/test/debuginfo")
-             .default(true)
+        rules.test("check-debuginfo-gdb", "src/test/debuginfo-gdb")
              .dep(|s| s.name("libtest"))
-             .dep(|s| s.name("tool-compiletest").target(s.host))
+             .dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
              .dep(|s| s.name("test-helpers"))
              .dep(|s| s.name("debugger-scripts"))
+             .dep(|s| s.name("android-copy-libs"))
              .run(move |s| check::compiletest(build, &s.compiler(), s.target,
                                          "debuginfo-gdb", "debuginfo"));
+        let mut rule = rules.test("check-debuginfo", "src/test/debuginfo");
+        rule.default(true);
+        if build.config.build.contains("apple") {
+            rule.dep(|s| s.name("check-debuginfo-lldb"));
+        } else {
+            rule.dep(|s| s.name("check-debuginfo-gdb"));
+        }
     }
 
     rules.test("debugger-scripts", "src/etc/lldb_batchmode.py")
@@ -290,14 +351,15 @@ pub fn build_rules(build: &Build) -> Rules {
                                          s.target));
 
     {
-        let mut suite = |name, path, dir, mode| {
+        let mut suite = |name, path, mode, dir| {
             rules.test(name, path)
                  .dep(|s| s.name("librustc"))
-                 .dep(|s| s.name("tool-compiletest").target(s.host))
-                 .default(true)
+                 .dep(|s| s.name("test-helpers"))
+                 .dep(|s| s.name("tool-compiletest").target(s.host).stage(0))
+                 .default(mode != "pretty")
                  .host(true)
                  .run(move |s| {
-                     check::compiletest(build, &s.compiler(), s.target, dir, mode)
+                     check::compiletest(build, &s.compiler(), s.target, mode, dir)
                  });
         };
 
@@ -307,21 +369,30 @@ pub fn build_rules(build: &Build) -> Rules {
               "compile-fail", "compile-fail-fulldeps");
         suite("check-rmake", "src/test/run-make", "run-make", "run-make");
         suite("check-rustdoc", "src/test/rustdoc", "rustdoc", "rustdoc");
-        suite("check-pretty-rpass-full", "src/test/run-pass-fulldeps",
+        suite("check-pretty", "src/test/pretty", "pretty", "pretty");
+        suite("check-pretty-rpass", "src/test/run-pass/pretty", "pretty",
+              "run-pass");
+        suite("check-pretty-rfail", "src/test/run-fail/pretty", "pretty",
+              "run-fail");
+        suite("check-pretty-valgrind", "src/test/run-pass-valgrind/pretty", "pretty",
+              "run-pass-valgrind");
+        suite("check-pretty-rpass-full", "src/test/run-pass-fulldeps/pretty",
               "pretty", "run-pass-fulldeps");
-        suite("check-pretty-rfail-full", "src/test/run-fail-fulldeps",
+        suite("check-pretty-rfail-full", "src/test/run-fail-fulldeps/pretty",
               "pretty", "run-fail-fulldeps");
     }
 
     for (krate, path, _default) in krates("std_shim") {
         rules.test(&krate.test_step, path)
              .dep(|s| s.name("libtest"))
+             .dep(|s| s.name("android-copy-libs"))
              .run(move |s| check::krate(build, &s.compiler(), s.target,
                                         Mode::Libstd, TestKind::Test,
                                         Some(&krate.name)));
     }
     rules.test("check-std-all", "path/to/nowhere")
          .dep(|s| s.name("libtest"))
+         .dep(|s| s.name("android-copy-libs"))
          .default(true)
          .run(move |s| check::krate(build, &s.compiler(), s.target,
                                     Mode::Libstd, TestKind::Test, None));
@@ -330,12 +401,14 @@ pub fn build_rules(build: &Build) -> Rules {
     for (krate, path, _default) in krates("std_shim") {
         rules.bench(&krate.bench_step, path)
              .dep(|s| s.name("libtest"))
+             .dep(|s| s.name("android-copy-libs"))
              .run(move |s| check::krate(build, &s.compiler(), s.target,
                                         Mode::Libstd, TestKind::Bench,
                                         Some(&krate.name)));
     }
     rules.bench("bench-std-all", "path/to/nowhere")
          .dep(|s| s.name("libtest"))
+         .dep(|s| s.name("android-copy-libs"))
          .default(true)
          .run(move |s| check::krate(build, &s.compiler(), s.target,
                                     Mode::Libstd, TestKind::Bench, None));
@@ -343,18 +416,21 @@ pub fn build_rules(build: &Build) -> Rules {
     for (krate, path, _default) in krates("test_shim") {
         rules.test(&krate.test_step, path)
              .dep(|s| s.name("libtest"))
+             .dep(|s| s.name("android-copy-libs"))
              .run(move |s| check::krate(build, &s.compiler(), s.target,
                                         Mode::Libtest, TestKind::Test,
                                         Some(&krate.name)));
     }
     rules.test("check-test-all", "path/to/nowhere")
          .dep(|s| s.name("libtest"))
+         .dep(|s| s.name("android-copy-libs"))
          .default(true)
          .run(move |s| check::krate(build, &s.compiler(), s.target,
                                     Mode::Libtest, TestKind::Test, None));
     for (krate, path, _default) in krates("rustc-main") {
         rules.test(&krate.test_step, path)
              .dep(|s| s.name("librustc"))
+             .dep(|s| s.name("android-copy-libs"))
              .host(true)
              .run(move |s| check::krate(build, &s.compiler(), s.target,
                                         Mode::Librustc, TestKind::Test,
@@ -362,19 +438,20 @@ pub fn build_rules(build: &Build) -> Rules {
     }
     rules.test("check-rustc-all", "path/to/nowhere")
          .dep(|s| s.name("librustc"))
+         .dep(|s| s.name("android-copy-libs"))
          .default(true)
          .host(true)
          .run(move |s| check::krate(build, &s.compiler(), s.target,
                                     Mode::Librustc, TestKind::Test, None));
 
     rules.test("check-linkchecker", "src/tools/linkchecker")
-         .dep(|s| s.name("tool-linkchecker"))
+         .dep(|s| s.name("tool-linkchecker").stage(0))
          .dep(|s| s.name("default:doc"))
          .default(true)
          .host(true)
-         .run(move |s| check::linkcheck(build, s.stage, s.target));
+         .run(move |s| check::linkcheck(build, s.target));
     rules.test("check-cargotest", "src/tools/cargotest")
-         .dep(|s| s.name("tool-cargotest"))
+         .dep(|s| s.name("tool-cargotest").stage(0))
          .dep(|s| s.name("librustc"))
          .host(true)
          .run(move |s| check::cargotest(build, s.stage, s.target));
@@ -382,10 +459,10 @@ pub fn build_rules(build: &Build) -> Rules {
          .dep(|s| s.name("tool-tidy").stage(0))
          .default(true)
          .host(true)
-         .run(move |s| check::tidy(build, 0, s.target));
+         .run(move |s| check::tidy(build, s.target));
     rules.test("check-error-index", "src/tools/error_index_generator")
          .dep(|s| s.name("libstd"))
-         .dep(|s| s.name("tool-error-index").host(s.host))
+         .dep(|s| s.name("tool-error-index").host(s.host).stage(0))
          .default(true)
          .host(true)
          .run(move |s| check::error_index(build, &s.compiler()));
@@ -431,38 +508,38 @@ pub fn build_rules(build: &Build) -> Rules {
     // ========================================================================
     // Documentation targets
     rules.doc("doc-book", "src/doc/book")
-         .dep(move |s| s.name("tool-rustbook").target(&build.config.build))
+         .dep(move |s| s.name("tool-rustbook").target(&build.config.build).stage(0))
          .default(build.config.docs)
-         .run(move |s| doc::rustbook(build, s.stage, s.target, "book"));
+         .run(move |s| doc::rustbook(build, s.target, "book"));
     rules.doc("doc-nomicon", "src/doc/nomicon")
-         .dep(move |s| s.name("tool-rustbook").target(&build.config.build))
+         .dep(move |s| s.name("tool-rustbook").target(&build.config.build).stage(0))
          .default(build.config.docs)
-         .run(move |s| doc::rustbook(build, s.stage, s.target, "nomicon"));
+         .run(move |s| doc::rustbook(build, s.target, "nomicon"));
     rules.doc("doc-standalone", "src/doc")
          .dep(move |s| s.name("rustc").host(&build.config.build).target(&build.config.build))
          .default(build.config.docs)
          .run(move |s| doc::standalone(build, s.stage, s.target));
     rules.doc("doc-error-index", "src/tools/error_index_generator")
-         .dep(move |s| s.name("tool-error-index").target(&build.config.build))
-         .dep(move |s| s.name("librustc"))
+         .dep(move |s| s.name("tool-error-index").target(&build.config.build).stage(0))
+         .dep(move |s| s.name("librustc-link").stage(0))
          .default(build.config.docs)
          .host(true)
-         .run(move |s| doc::error_index(build, s.stage, s.target));
+         .run(move |s| doc::error_index(build, s.target));
     for (krate, path, default) in krates("std_shim") {
         rules.doc(&krate.doc_step, path)
-             .dep(|s| s.name("libstd"))
+             .dep(|s| s.name("libstd-link"))
              .default(default && build.config.docs)
              .run(move |s| doc::std(build, s.stage, s.target));
     }
     for (krate, path, default) in krates("test_shim") {
         rules.doc(&krate.doc_step, path)
-             .dep(|s| s.name("libtest"))
+             .dep(|s| s.name("libtest-link"))
              .default(default && build.config.compiler_docs)
              .run(move |s| doc::test(build, s.stage, s.target));
     }
     for (krate, path, default) in krates("rustc-main") {
         rules.doc(&krate.doc_step, path)
-             .dep(|s| s.name("librustc"))
+             .dep(|s| s.name("librustc-link"))
              .host(true)
              .default(default && build.config.compiler_docs)
              .run(move |s| doc::rustc(build, s.stage, s.target));
@@ -481,9 +558,9 @@ pub fn build_rules(build: &Build) -> Rules {
              // for the `rust-std` package, so if this is a host target we
              // depend on librustc and otherwise we just depend on libtest.
              if build.config.host.iter().any(|t| t == s.target) {
-                 s.name("librustc")
+                 s.name("librustc-link")
              } else {
-                 s.name("libtest")
+                 s.name("libtest-link")
              }
          })
          .default(true)
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index c9e756b6f99..2ab3776ada0 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -76,9 +76,9 @@ pub fn cp_r(src: &Path, dst: &Path) {
 /// Copies the `src` directory recursively to `dst`. Both are assumed to exist
 /// when this function is called. Unwanted files or directories can be skipped
 /// by returning `false` from the filter function.
-pub fn cp_filtered<F: Fn(&Path) -> bool>(src: &Path, dst: &Path, filter: &F) {
+pub fn cp_filtered(src: &Path, dst: &Path, filter: &Fn(&Path) -> bool) {
     // Inner function does the actual work
-    fn recurse<F: Fn(&Path) -> bool>(src: &Path, dst: &Path, relative: &Path, filter: &F) {
+    fn recurse(src: &Path, dst: &Path, relative: &Path, filter: &Fn(&Path) -> bool) {
         for f in t!(fs::read_dir(src)) {
             let f = t!(f);
             let path = f.path();
diff --git a/src/ci/docker/arm-android/Dockerfile b/src/ci/docker/arm-android/Dockerfile
index 8911b4ff0cb..a40e76839ec 100644
--- a/src/ci/docker/arm-android/Dockerfile
+++ b/src/ci/docker/arm-android/Dockerfile
@@ -11,7 +11,6 @@ RUN dpkg --add-architecture i386 && \
   python2.7 \
   git \
   cmake \
-  ccache \
   unzip \
   expect \
   openjdk-9-jre \
@@ -50,5 +49,3 @@ ENV RUST_CONFIGURE_ARGS \
       --i686-linux-android-ndk=/android/ndk-x86-9 \
       --aarch64-linux-android-ndk=/android/ndk-aarch64
 ENV XPY_CHECK test --target arm-linux-androideabi
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
diff --git a/src/ci/docker/cross/Dockerfile b/src/ci/docker/cross/Dockerfile
index 08b436313f6..c5aa323f50c 100644
--- a/src/ci/docker/cross/Dockerfile
+++ b/src/ci/docker/cross/Dockerfile
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   sudo \
   gcc-aarch64-linux-gnu libc6-dev-arm64-cross \
   gcc-arm-linux-gnueabi libc6-dev-armel-cross \
@@ -70,6 +69,3 @@ ENV AR_s390x_unknown_linux_gnu=s390x-linux-gnu-ar \
 
 # FIXME(rust-lang/rust#36150): powerpc unfortunately aborts right now
 ENV NO_LLVM_ASSERTIONS=1
-
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
diff --git a/src/ci/docker/i686-gnu-nopt/Dockerfile b/src/ci/docker/i686-gnu-nopt/Dockerfile
index 1da33c94c7b..1ffb24981c5 100644
--- a/src/ci/docker/i686-gnu-nopt/Dockerfile
+++ b/src/ci/docker/i686-gnu-nopt/Dockerfile
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   sudo \
   gdb \
   xz-utils
@@ -25,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests
 ENV RUST_CHECK_TARGET check
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
diff --git a/src/ci/docker/i686-gnu/Dockerfile b/src/ci/docker/i686-gnu/Dockerfile
index 9e5b0e0435e..e4310232d78 100644
--- a/src/ci/docker/i686-gnu/Dockerfile
+++ b/src/ci/docker/i686-gnu/Dockerfile
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   sudo \
   gdb \
   xz-utils
@@ -25,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu
 ENV RUST_CHECK_TARGET check
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
diff --git a/src/ci/docker/x86_64-freebsd/Dockerfile b/src/ci/docker/x86_64-freebsd/Dockerfile
index 75f3174e2c0..86efa74ba3b 100644
--- a/src/ci/docker/x86_64-freebsd/Dockerfile
+++ b/src/ci/docker/x86_64-freebsd/Dockerfile
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   sudo \
   bzip2 \
   xz-utils \
@@ -33,5 +32,3 @@ ENV \
 
 ENV RUST_CONFIGURE_ARGS --target=x86_64-unknown-freebsd
 ENV RUST_CHECK_TARGET ""
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
diff --git a/src/ci/docker/x86_64-gnu-cargotest/Dockerfile b/src/ci/docker/x86_64-gnu-aux/Dockerfile
index 2c3db87d9fb..0ec0bfd1897 100644
--- a/src/ci/docker/x86_64-gnu-cargotest/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-aux/Dockerfile
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   libssl-dev \
   sudo \
   xz-utils \
@@ -25,7 +24,5 @@ RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-ini
 ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
-ENV RUST_CHECK_TARGET check-cargotest
+ENV RUST_CHECK_TARGET check-aux
 ENV NO_VENDOR 1
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
diff --git a/src/ci/docker/x86_64-gnu-debug/Dockerfile b/src/ci/docker/x86_64-gnu-debug/Dockerfile
index eec88442293..9ec8c6059ec 100644
--- a/src/ci/docker/x86_64-gnu-debug/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-debug/Dockerfile
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   sudo \
   gdb \
   xz-utils
@@ -28,5 +27,3 @@ ENV RUST_CONFIGURE_ARGS \
       --enable-debug \
       --enable-optimize
 ENV RUST_CHECK_TARGET ""
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
diff --git a/src/ci/docker/x86_64-gnu-distcheck/Dockerfile b/src/ci/docker/x86_64-gnu-distcheck/Dockerfile
new file mode 100644
index 00000000000..880c70866b0
--- /dev/null
+++ b/src/ci/docker/x86_64-gnu-distcheck/Dockerfile
@@ -0,0 +1,26 @@
+FROM ubuntu:16.04
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+  g++ \
+  make \
+  file \
+  curl \
+  ca-certificates \
+  python2.7 \
+  git \
+  cmake \
+  sudo \
+  gdb \
+  xz-utils
+
+ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
+RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
+      tar xJf - -C /usr/local/bin --strip-components=1
+
+RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
+    dpkg -i dumb-init_*.deb && \
+    rm dumb-init_*.deb
+ENTRYPOINT ["/usr/bin/dumb-init", "--"]
+
+ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
+ENV XPY_RUN test distcheck
diff --git a/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile b/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile
new file mode 100644
index 00000000000..7c079e45751
--- /dev/null
+++ b/src/ci/docker/x86_64-gnu-full-bootstrap/Dockerfile
@@ -0,0 +1,28 @@
+FROM ubuntu:16.04
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+  g++ \
+  make \
+  file \
+  curl \
+  ca-certificates \
+  python2.7 \
+  git \
+  cmake \
+  sudo \
+  gdb \
+  xz-utils
+
+ENV SCCACHE_DIGEST=7237e38e029342fa27b7ac25412cb9d52554008b12389727320bd533fd7f05b6a96d55485f305caf95e5c8f5f97c3313e10012ccad3e752aba2518f3522ba783
+RUN curl -L https://api.pub.build.mozilla.org/tooltool/sha512/$SCCACHE_DIGEST | \
+      tar xJf - -C /usr/local/bin --strip-components=1
+
+RUN curl -OL https://github.com/Yelp/dumb-init/releases/download/v1.2.0/dumb-init_1.2.0_amd64.deb && \
+    dpkg -i dumb-init_*.deb && \
+    rm dumb-init_*.deb
+ENTRYPOINT ["/usr/bin/dumb-init", "--"]
+
+ENV RUST_CONFIGURE_ARGS \
+      --build=x86_64-unknown-linux-gnu \
+      --enable-full-bootstrap
+ENV RUST_CHECK_TARGET ""
diff --git a/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile
index 4c9198d88eb..aabfc0cd1bd 100644
--- a/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-llvm-3.7/Dockerfile
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   sudo \
   gdb \
   llvm-3.7-tools \
@@ -30,5 +29,3 @@ ENV RUST_CONFIGURE_ARGS \
       --build=x86_64-unknown-linux-gnu \
       --llvm-root=/usr/lib/llvm-3.7
 ENV RUST_CHECK_TARGET check
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
diff --git a/src/ci/docker/x86_64-gnu-make/Dockerfile b/src/ci/docker/x86_64-gnu-make/Dockerfile
index 1c503aea13d..c6071d704f5 100644
--- a/src/ci/docker/x86_64-gnu-make/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-make/Dockerfile
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   sudo \
   gdb \
   xz-utils
@@ -25,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-rustbuild
 ENV RUST_CHECK_TARGET check
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
diff --git a/src/ci/docker/x86_64-gnu-nopt/Dockerfile b/src/ci/docker/x86_64-gnu-nopt/Dockerfile
index 66de6ea13ac..d28dc3de1b4 100644
--- a/src/ci/docker/x86_64-gnu-nopt/Dockerfile
+++ b/src/ci/docker/x86_64-gnu-nopt/Dockerfile
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   sudo \
   gdb \
   xz-utils
@@ -25,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --disable-optimize-tests
 ENV RUST_CHECK_TARGET check
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
diff --git a/src/ci/docker/x86_64-gnu/Dockerfile b/src/ci/docker/x86_64-gnu/Dockerfile
index 3d71b7ffb9a..9d8b75c80c7 100644
--- a/src/ci/docker/x86_64-gnu/Dockerfile
+++ b/src/ci/docker/x86_64-gnu/Dockerfile
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   sudo \
   gdb \
   xz-utils
@@ -25,5 +24,3 @@ ENTRYPOINT ["/usr/bin/dumb-init", "--"]
 
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu
 ENV RUST_CHECK_TARGET check
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
diff --git a/src/ci/docker/x86_64-musl/Dockerfile b/src/ci/docker/x86_64-musl/Dockerfile
index 96b38067cbb..49954157ec0 100644
--- a/src/ci/docker/x86_64-musl/Dockerfile
+++ b/src/ci/docker/x86_64-musl/Dockerfile
@@ -9,7 +9,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   python2.7 \
   git \
   cmake \
-  ccache \
   xz-utils \
   sudo \
   gdb
@@ -33,6 +32,3 @@ ENV RUST_CONFIGURE_ARGS \
 ENV RUST_CHECK_TARGET check-stage2-T-x86_64-unknown-linux-musl-H-x86_64-unknown-linux-gnu
 ENV PATH=$PATH:/musl-x86_64/bin
 ENV XPY_CHECK test --target x86_64-unknown-linux-musl
-
-RUN mkdir /tmp/obj
-RUN chmod 777 /tmp/obj
diff --git a/src/ci/run.sh b/src/ci/run.sh
index 152694346aa..3dc3cf91501 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -43,10 +43,14 @@ else
     ncpus=$(nproc)
 fi
 
-make -j $ncpus tidy
-make -j $ncpus
-if [ ! -z "$XPY_CHECK" ]; then
-  exec python2.7 $SRC/x.py $XPY_CHECK
+if [ ! -z "$XPY_RUN" ]; then
+  exec python2.7 $SRC/x.py $XPY_RUN
 else
-  exec make $RUST_CHECK_TARGET -j $ncpus
+  make -j $ncpus tidy
+  make -j $ncpus
+  if [ ! -z "$XPY_CHECK" ]; then
+    exec python2.7 $SRC/x.py $XPY_CHECK
+  else
+    exec make $RUST_CHECK_TARGET -j $ncpus
+  fi
 fi
diff --git a/src/doc/book/closures.md b/src/doc/book/closures.md
index a3c7333c6be..115fe1f7662 100644
--- a/src/doc/book/closures.md
+++ b/src/doc/book/closures.md
@@ -283,7 +283,7 @@ fn call_with_one<F>(some_closure: F) -> i32
 #    some_closure(1) }
 ```
 
-We take one parameter, and it has the type `F`. We also return a `i32`. This part
+We take one parameter, and it has the type `F`. We also return an `i32`. This part
 isn’t interesting. The next part is:
 
 ```rust
@@ -293,7 +293,7 @@ isn’t interesting. The next part is:
 ```
 
 Because `Fn` is a trait, we can use it as a bound for our generic type. In
-this case, our closure takes a `i32` as an argument and returns an `i32`, and
+this case, our closure takes an `i32` as an argument and returns an `i32`, and
 so the generic bound we use is `Fn(i32) -> i32`.
 
 There’s one other key point here: because we’re bounding a generic with a
diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md
index b53af694428..41457ee67a5 100644
--- a/src/doc/book/ffi.md
+++ b/src/doc/book/ffi.md
@@ -574,6 +574,31 @@ The [`libc` crate on crates.io][libc] includes type aliases and function
 definitions for the C standard library in the `libc` module, and Rust links
 against `libc` and `libm` by default.
 
+# Variadic functions
+
+In C, functions can be 'variadic', meaning they accept a variable number of arguments. This can
+be achieved in Rust by specifying `...` within the argument list of a foreign function declaration:
+
+```no_run
+extern {
+    fn foo(x: i32, ...);
+}
+
+fn main() {
+    unsafe {
+        foo(10, 20, 30, 40, 50);
+    }
+}
+```
+
+Normal Rust functions can *not* be variadic:
+
+```ignore
+// This will not compile
+
+fn foo(x: i32, ...) { }
+```
+
 # The "nullable pointer optimization"
 
 Certain Rust types are defined to never be `null`. This includes references (`&T`,
diff --git a/src/doc/book/lifetimes.md b/src/doc/book/lifetimes.md
index 140e27d1924..546e66fc8ac 100644
--- a/src/doc/book/lifetimes.md
+++ b/src/doc/book/lifetimes.md
@@ -128,7 +128,7 @@ _descriptive_, not _prescriptive_. This means that how long a reference is valid
 is determined by the code, not by the annotations. The annotations, however,
 give information about lifetimes to the compiler that uses them to check the
 validity of references. The compiler can do so without annotations in simple
-cases, but needs the programmers support in complex scenarios.
+cases, but needs the programmer's support in complex scenarios.
 
 [traits]: traits.html
 
diff --git a/src/doc/book/strings.md b/src/doc/book/strings.md
index 6af15d87683..a2146b669e3 100644
--- a/src/doc/book/strings.md
+++ b/src/doc/book/strings.md
@@ -163,8 +163,8 @@ let hachi = &dog[0..2];
 with this error:
 
 ```text
-thread 'main' panicked at 'index 0 and/or 2 in `忠犬ハチ公` do not lie on
-character boundary'
+thread 'main' panicked at 'byte index 2 is not a char boundary; it is inside '忠'
+(bytes 0..3) of `忠犬ハチ公`'
 ```
 
 ## Concatenation
diff --git a/src/doc/book/variable-bindings.md b/src/doc/book/variable-bindings.md
index 37b6c0513fc..e1947310a9a 100644
--- a/src/doc/book/variable-bindings.md
+++ b/src/doc/book/variable-bindings.md
@@ -102,7 +102,7 @@ mutation, then the solution is quite easy: add `mut`.
 There are other good reasons to avoid mutable state when possible, but they’re
 out of the scope of this guide. In general, you can often avoid explicit
 mutation, and so it is preferable in Rust. That said, sometimes, mutation is
-what you need, so it’s not verboten.
+what you need, so it’s not forbidden.
 
 # Initializing bindings
 
diff --git a/src/doc/nomicon/atomics.md b/src/doc/nomicon/atomics.md
index 1efca08abd0..7b4c44ff051 100644
--- a/src/doc/nomicon/atomics.md
+++ b/src/doc/nomicon/atomics.md
@@ -24,10 +24,10 @@ exactly what we said but, you know, fast. Wouldn't that be great?
 
 # Compiler Reordering
 
-Compilers fundamentally want to be able to do all sorts of crazy transformations
-to reduce data dependencies and eliminate dead code. In particular, they may
-radically change the actual order of events, or make events never occur! If we
-write something like
+Compilers fundamentally want to be able to do all sorts of complicated
+transformations to reduce data dependencies and eliminate dead code. In
+particular, they may radically change the actual order of events, or make events
+never occur! If we write something like
 
 ```rust,ignore
 x = 1;
diff --git a/src/doc/nomicon/meet-safe-and-unsafe.md b/src/doc/nomicon/meet-safe-and-unsafe.md
index 978d0518729..15d84fdbf29 100644
--- a/src/doc/nomicon/meet-safe-and-unsafe.md
+++ b/src/doc/nomicon/meet-safe-and-unsafe.md
@@ -22,7 +22,7 @@ Well, Rust *has* a safe programming language. Let's step back a bit.
 Rust can be thought of as being composed of two programming languages: *Safe
 Rust* and *Unsafe Rust*. Safe Rust is For Reals  Totally Safe. Unsafe Rust,
 unsurprisingly, is *not* For Reals Totally Safe.  In fact, Unsafe Rust lets you
-do some really crazy unsafe things.
+do some really, *really* unsafe things.
 
 Safe Rust is the *true* Rust programming language. If all you do is write Safe
 Rust, you will never have to worry about type-safety or memory-safety. You will
diff --git a/src/doc/nomicon/races.md b/src/doc/nomicon/races.md
index f0732cf2656..5145987158a 100644
--- a/src/doc/nomicon/races.md
+++ b/src/doc/nomicon/races.md
@@ -21,11 +21,11 @@ prevent *all* race conditions would be pretty awful to use, if not just
 incorrect.
 
 So it's perfectly "fine" for a Safe Rust program to get deadlocked or do
-something incredibly stupid with incorrect synchronization. Obviously such a
-program isn't very good, but Rust can only hold your hand so far. Still, a
-race condition can't violate memory safety in a Rust program on
-its own. Only in conjunction with some other unsafe code can a race condition
-actually violate memory safety. For instance:
+something nonsensical with incorrect synchronization. Obviously such a program
+isn't very good, but Rust can only hold your hand so far. Still, a race
+condition can't violate memory safety in a Rust program on its own. Only in
+conjunction with some other unsafe code can a race condition actually violate
+memory safety. For instance:
 
 ```rust,no_run
 use std::thread;
diff --git a/src/doc/reference.md b/src/doc/reference.md
index b5a91a170d8..9898c31282c 100644
--- a/src/doc/reference.md
+++ b/src/doc/reference.md
@@ -1657,6 +1657,15 @@ Functions within external blocks may be called by Rust code, just like
 functions defined in Rust. The Rust compiler automatically translates between
 the Rust ABI and the foreign ABI.
 
+Functions within external blocks may be variadic by specifying `...` after one
+or more named arguments in the argument list:
+
+```ignore
+extern {
+    fn foo(x: i32, ...);
+}
+```
+
 A number of [attributes](#ffi-attributes) control the behavior of external blocks.
 
 By default external blocks assume that the library they are calling uses the
diff --git a/src/etc/debugger_pretty_printers_common.py b/src/etc/debugger_pretty_printers_common.py
index eb562877c85..5e3ff5246a9 100644
--- a/src/etc/debugger_pretty_printers_common.py
+++ b/src/etc/debugger_pretty_printers_common.py
@@ -45,6 +45,7 @@ TYPE_KIND_SINGLETON_ENUM    = 13
 TYPE_KIND_CSTYLE_ENUM       = 14
 TYPE_KIND_PTR               = 15
 TYPE_KIND_FIXED_SIZE_VEC    = 16
+TYPE_KIND_REGULAR_UNION     = 17
 
 ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$"
 ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR"
@@ -188,15 +189,18 @@ class Type(object):
         union_member_count = len(union_members)
         if union_member_count == 0:
             return TYPE_KIND_EMPTY
-        elif union_member_count == 1:
-            first_variant_name = union_members[0].name
-            if first_variant_name is None:
+
+        first_variant_name = union_members[0].name
+        if first_variant_name is None:
+            if union_member_count == 1:
                 return TYPE_KIND_SINGLETON_ENUM
             else:
-                assert first_variant_name.startswith(ENCODED_ENUM_PREFIX)
-                return TYPE_KIND_COMPRESSED_ENUM
+                return TYPE_KIND_REGULAR_ENUM
+        elif first_variant_name.startswith(ENCODED_ENUM_PREFIX):
+            assert union_member_count == 1
+            return TYPE_KIND_COMPRESSED_ENUM
         else:
-            return TYPE_KIND_REGULAR_ENUM
+            return TYPE_KIND_REGULAR_UNION
 
 
     def __conforms_to_field_layout(self, expected_fields):
diff --git a/src/etc/lldb_rust_formatters.py b/src/etc/lldb_rust_formatters.py
index 335acae5fb6..4427313f9e5 100644
--- a/src/etc/lldb_rust_formatters.py
+++ b/src/etc/lldb_rust_formatters.py
@@ -90,6 +90,7 @@ def print_val(lldb_val, internal_dict):
     type_kind = val.type.get_type_kind()
 
     if (type_kind == rustpp.TYPE_KIND_REGULAR_STRUCT or
+        type_kind == rustpp.TYPE_KIND_REGULAR_UNION or
         type_kind == rustpp.TYPE_KIND_EMPTY):
         return print_struct_val(val,
                                 internal_dict,
@@ -175,7 +176,8 @@ def print_struct_val(val, internal_dict, omit_first_field, omit_type_name, is_tu
     Prints a struct, tuple, or tuple struct value with Rust syntax.
     Ignores any fields before field_start_index.
     """
-    assert val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_STRUCT
+    assert (val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_STRUCT or
+            val.type.get_dwarf_type_kind() == rustpp.DWARF_TYPE_CODE_UNION)
 
     if omit_type_name:
         type_name = ""
diff --git a/src/etc/platform-intrinsics/nvptx/cuda.json b/src/etc/platform-intrinsics/nvptx/cuda.json
new file mode 100644
index 00000000000..1beaaeb5d87
--- /dev/null
+++ b/src/etc/platform-intrinsics/nvptx/cuda.json
@@ -0,0 +1,13 @@
+{
+    "intrinsic_prefix": "_",
+    "llvm_prefix": "llvm.cuda.",
+    "intrinsics": [
+        {
+            "intrinsic": "syncthreads",
+            "width": ["0"],
+            "llvm": "syncthreads",
+            "ret": "V",
+            "args": []
+        }
+    ]
+}
diff --git a/src/etc/platform-intrinsics/nvptx/info.json b/src/etc/platform-intrinsics/nvptx/info.json
new file mode 100644
index 00000000000..80332c54e04
--- /dev/null
+++ b/src/etc/platform-intrinsics/nvptx/info.json
@@ -0,0 +1,7 @@
+{
+  "platform": "nvptx",
+  "number_info": {
+    "signed": {}
+  },
+  "width_info": {}
+}
diff --git a/src/etc/platform-intrinsics/nvptx/sreg.json b/src/etc/platform-intrinsics/nvptx/sreg.json
new file mode 100644
index 00000000000..33d97f26946
--- /dev/null
+++ b/src/etc/platform-intrinsics/nvptx/sreg.json
@@ -0,0 +1,90 @@
+{
+    "intrinsic_prefix": "_",
+    "llvm_prefix": "llvm.nvvm.read.ptx.sreg.",
+    "intrinsics": [
+        {
+            "intrinsic": "block_dim_x",
+            "width": ["0"],
+            "llvm": "ntid.x",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "block_dim_y",
+            "width": ["0"],
+            "llvm": "ntid.y",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "block_dim_z",
+            "width": ["0"],
+            "llvm": "ntid.z",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "block_idx_x",
+            "width": ["0"],
+            "llvm": "ctaid.x",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "block_idx_y",
+            "width": ["0"],
+            "llvm": "ctaid.y",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "block_idx_z",
+            "width": ["0"],
+            "llvm": "ctaid.z",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "grid_dim_x",
+            "width": ["0"],
+            "llvm": "nctaid.x",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "grid_dim_y",
+            "width": ["0"],
+            "llvm": "nctaid.y",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "grid_dim_z",
+            "width": ["0"],
+            "llvm": "nctaid.z",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "thread_idx_x",
+            "width": ["0"],
+            "llvm": "tid.x",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "thread_idx_y",
+            "width": ["0"],
+            "llvm": "tid.y",
+            "ret": "S32",
+            "args": []
+        },
+        {
+            "intrinsic": "thread_idx_z",
+            "width": ["0"],
+            "llvm": "tid.z",
+            "ret": "S32",
+            "args": []
+        }
+    ]
+}
diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs
index 1cad8f7f407..e1a240a0d2e 100644
--- a/src/liballoc/arc.rs
+++ b/src/liballoc/arc.rs
@@ -55,24 +55,24 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
 /// [`RwLock`][rwlock], or one of the [`Atomic`][atomic] types.
 ///
 /// `Arc` uses atomic operations for reference counting, so `Arc`s can be
-/// sent between threads. In other words, `Arc<T>` implements [`Send`][send]
-/// as long as `T` implements `Send` and [`Sync`][sync]. The disadvantage is
+/// sent between threads. In other words, `Arc<T>` implements [`Send`]
+/// as long as `T` implements [`Send`] and [`Sync`][sync]. The disadvantage is
 /// that atomic operations are more expensive than ordinary memory accesses.
 /// If you are not sharing reference-counted values between threads, consider
-/// using [`rc::Rc`][rc] for lower overhead. `Rc` is a safe default, because
-/// the compiler will catch any attempt to send an `Rc` between threads.
+/// using [`rc::Rc`] for lower overhead. [`Rc`] is a safe default, because
+/// the compiler will catch any attempt to send an [`Rc`] between threads.
 /// However, a library might choose `Arc` in order to give library consumers
 /// more flexibility.
 ///
 /// The [`downgrade`][downgrade] method can be used to create a non-owning
-/// [`Weak`][weak] pointer. A `Weak` pointer can be [`upgrade`][upgrade]d
-/// to an `Arc`, but this will return [`None`][option] if the value has
-/// already been dropped.
+/// [`Weak`][weak] pointer. A [`Weak`][weak] pointer can be [`upgrade`][upgrade]d
+/// to an `Arc`, but this will return [`None`] if the value has already been
+/// dropped.
 ///
 /// A cycle between `Arc` pointers will never be deallocated. For this reason,
-/// `Weak` is used to break cycles. For example, a tree could have strong
-/// `Arc` pointers from parent nodes to children, and `Weak` pointers from
-/// children back to their parents.
+/// [`Weak`][weak] is used to break cycles. For example, a tree could have
+/// strong `Arc` pointers from parent nodes to children, and [`Weak`][weak]
+/// pointers from children back to their parents.
 ///
 /// `Arc<T>` automatically dereferences to `T` (via the [`Deref`][deref] trait),
 /// so you can call `T`'s methods on a value of type `Arc<T>`. To avoid name
@@ -86,22 +86,22 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
 /// Arc::downgrade(&my_arc);
 /// ```
 ///
-/// `Weak<T>` does not auto-dereference to `T`, because the value may have
+/// [`Weak<T>`][weak] does not auto-dereference to `T`, because the value may have
 /// already been destroyed.
 ///
 /// [arc]: struct.Arc.html
 /// [weak]: struct.Weak.html
-/// [rc]: ../../std/rc/struct.Rc.html
+/// [`Rc`]: ../../std/rc/struct.Rc.html
 /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
 /// [mutex]: ../../std/sync/struct.Mutex.html
 /// [rwlock]: ../../std/sync/struct.RwLock.html
 /// [atomic]: ../../std/sync/atomic/index.html
-/// [send]: ../../std/marker/trait.Send.html
+/// [`Send`]: ../../std/marker/trait.Send.html
 /// [sync]: ../../std/marker/trait.Sync.html
 /// [deref]: ../../std/ops/trait.Deref.html
 /// [downgrade]: struct.Arc.html#method.downgrade
 /// [upgrade]: struct.Weak.html#method.upgrade
-/// [option]: ../../std/option/enum.Option.html
+/// [`None`]: ../../std/option/enum.Option.html#variant.None
 /// [assoc]: ../../book/method-syntax.html#associated-functions
 ///
 /// # Examples
@@ -127,7 +127,9 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
 /// }
 /// ```
 ///
-/// Sharing a mutable `AtomicUsize`:
+/// Sharing a mutable [`AtomicUsize`]:
+///
+/// [`AtomicUsize`]: ../../std/sync/atomic/struct.AtomicUsize.html
 ///
 /// ```no_run
 /// use std::sync::Arc;
diff --git a/src/liballoc_jemalloc/Cargo.toml b/src/liballoc_jemalloc/Cargo.toml
index 25b3c8a3a0a..01393be9949 100644
--- a/src/liballoc_jemalloc/Cargo.toml
+++ b/src/liballoc_jemalloc/Cargo.toml
@@ -9,6 +9,7 @@ links = "jemalloc"
 name = "alloc_jemalloc"
 path = "lib.rs"
 test = false
+doc = false
 
 [dependencies]
 core = { path = "../libcore" }
diff --git a/src/liballoc_jemalloc/build.rs b/src/liballoc_jemalloc/build.rs
index 2bbec9e5fc2..1edcb0b1f24 100644
--- a/src/liballoc_jemalloc/build.rs
+++ b/src/liballoc_jemalloc/build.rs
@@ -151,6 +151,12 @@ fn main() {
     cmd.arg(format!("--host={}", build_helper::gnu_target(&target)));
     cmd.arg(format!("--build={}", build_helper::gnu_target(&host)));
 
+    // for some reason, jemalloc configure doesn't detect this value
+    // automatically for this target
+    if target == "sparc64-unknown-linux-gnu" {
+        cmd.arg("--with-lg-quantum=4");
+    }
+
     run(&mut cmd);
     let mut make = Command::new(build_helper::make(&host));
     make.current_dir(&build_dir)
diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs
index 21e45f9c4b2..f2df393ad77 100644
--- a/src/liballoc_jemalloc/lib.rs
+++ b/src/liballoc_jemalloc/lib.rs
@@ -84,7 +84,8 @@ mod imp {
                   target_arch = "aarch64",
                   target_arch = "powerpc64",
                   target_arch = "mips64",
-                  target_arch = "s390x")))]
+                  target_arch = "s390x",
+                  target_arch = "sparc64")))]
     const MIN_ALIGN: usize = 16;
 
     // MALLOCX_ALIGN(a) macro
diff --git a/src/liballoc_system/Cargo.toml b/src/liballoc_system/Cargo.toml
index 88e8e2d7adb..8e3c2c0b9cc 100644
--- a/src/liballoc_system/Cargo.toml
+++ b/src/liballoc_system/Cargo.toml
@@ -7,6 +7,7 @@ version = "0.0.0"
 name = "alloc_system"
 path = "lib.rs"
 test = false
+doc = false
 
 [dependencies]
 core = { path = "../libcore" }
diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs
index 4daa6cbb846..5f0b637656b 100644
--- a/src/liballoc_system/lib.rs
+++ b/src/liballoc_system/lib.rs
@@ -35,7 +35,8 @@ const MIN_ALIGN: usize = 8;
 #[cfg(all(any(target_arch = "x86_64",
               target_arch = "aarch64",
               target_arch = "mips64",
-              target_arch = "s390x")))]
+              target_arch = "s390x",
+              target_arch = "sparc64")))]
 const MIN_ALIGN: usize = 16;
 
 #[no_mangle]
diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs
index 6044bec2c5a..174a93ed23e 100644
--- a/src/libarena/lib.rs
+++ b/src/libarena/lib.rs
@@ -196,9 +196,9 @@ impl<T> TypedArena<T> {
                     self.end.set(last_chunk.end());
                     return;
                 } else {
-                    let prev_capacity = last_chunk.storage.cap();
+                    new_capacity = last_chunk.storage.cap();
                     loop {
-                        new_capacity = prev_capacity.checked_mul(2).unwrap();
+                        new_capacity = new_capacity.checked_mul(2).unwrap();
                         if new_capacity >= currently_used_cap + n {
                             break;
                         }
@@ -280,6 +280,133 @@ impl<T> Drop for TypedArena<T> {
 
 unsafe impl<T: Send> Send for TypedArena<T> {}
 
+pub struct DroplessArena {
+    /// A pointer to the next object to be allocated.
+    ptr: Cell<*mut u8>,
+
+    /// A pointer to the end of the allocated area. When this pointer is
+    /// reached, a new chunk is allocated.
+    end: Cell<*mut u8>,
+
+    /// A vector of arena chunks.
+    chunks: RefCell<Vec<TypedArenaChunk<u8>>>,
+}
+
+impl DroplessArena {
+    pub fn new() -> DroplessArena {
+        DroplessArena {
+            ptr: Cell::new(0 as *mut u8),
+            end: Cell::new(0 as *mut u8),
+            chunks: RefCell::new(vec![]),
+        }
+    }
+
+    pub fn in_arena<T: ?Sized>(&self, ptr: *const T) -> bool {
+        let ptr = ptr as *const u8 as *mut u8;
+        for chunk in &*self.chunks.borrow() {
+            if chunk.start() <= ptr && ptr < chunk.end() {
+                return true;
+            }
+        }
+
+        false
+    }
+
+    fn align_for<T>(&self) {
+        let align = mem::align_of::<T>();
+        let final_address = ((self.ptr.get() as usize) + align - 1) & !(align - 1);
+        self.ptr.set(final_address as *mut u8);
+        assert!(self.ptr <= self.end);
+    }
+
+    #[inline(never)]
+    #[cold]
+    fn grow<T>(&self, n: usize) {
+        let needed_bytes = n * mem::size_of::<T>();
+        unsafe {
+            let mut chunks = self.chunks.borrow_mut();
+            let (chunk, mut new_capacity);
+            if let Some(last_chunk) = chunks.last_mut() {
+                let used_bytes = self.ptr.get() as usize - last_chunk.start() as usize;
+                if last_chunk.storage.reserve_in_place(used_bytes, needed_bytes) {
+                    self.end.set(last_chunk.end());
+                    return;
+                } else {
+                    new_capacity = last_chunk.storage.cap();
+                    loop {
+                        new_capacity = new_capacity.checked_mul(2).unwrap();
+                        if new_capacity >= used_bytes + needed_bytes {
+                            break;
+                        }
+                    }
+                }
+            } else {
+                new_capacity = cmp::max(needed_bytes, PAGE);
+            }
+            chunk = TypedArenaChunk::<u8>::new(new_capacity);
+            self.ptr.set(chunk.start());
+            self.end.set(chunk.end());
+            chunks.push(chunk);
+        }
+    }
+
+    #[inline]
+    pub fn alloc<T>(&self, object: T) -> &mut T {
+        unsafe {
+            assert!(!intrinsics::needs_drop::<T>());
+            assert!(mem::size_of::<T>() != 0);
+
+            self.align_for::<T>();
+            let future_end = intrinsics::arith_offset(self.ptr.get(), mem::size_of::<T>() as isize);
+            if (future_end as *mut u8) >= self.end.get() {
+                self.grow::<T>(1)
+            }
+
+            let ptr = self.ptr.get();
+            // Set the pointer past ourselves
+            self.ptr.set(intrinsics::arith_offset(
+                    self.ptr.get(), mem::size_of::<T>() as isize
+            ) as *mut u8);
+            // Write into uninitialized memory.
+            ptr::write(ptr as *mut T, object);
+            &mut *(ptr as *mut T)
+        }
+    }
+
+    /// Allocates a slice of objects that are copied into the `DroplessArena`, returning a mutable
+    /// reference to it. Will panic if passed a zero-sized type.
+    ///
+    /// Panics:
+    ///  - Zero-sized types
+    ///  - Zero-length slices
+    #[inline]
+    pub fn alloc_slice<T>(&self, slice: &[T]) -> &mut [T]
+        where T: Copy {
+        unsafe {
+            assert!(!intrinsics::needs_drop::<T>());
+        }
+        assert!(mem::size_of::<T>() != 0);
+        assert!(slice.len() != 0);
+        self.align_for::<T>();
+
+        let future_end = unsafe {
+            intrinsics::arith_offset(self.ptr.get(), (slice.len() * mem::size_of::<T>()) as isize)
+        };
+        if (future_end as *mut u8) >= self.end.get() {
+            self.grow::<T>(slice.len());
+        }
+
+        unsafe {
+            let arena_slice = slice::from_raw_parts_mut(self.ptr.get() as *mut T, slice.len());
+            self.ptr.set(intrinsics::arith_offset(
+                    self.ptr.get(), (slice.len() * mem::size_of::<T>()) as isize
+            ) as *mut u8);
+            arena_slice.copy_from_slice(slice);
+            arena_slice
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     extern crate test;
diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs
index 384579ce6b8..5e685847e3c 100644
--- a/src/libcollectionstest/str.rs
+++ b/src/libcollectionstest/str.rs
@@ -383,18 +383,30 @@ tempus vel, gravida nec quam.";
 
 // check the panic includes the prefix of the sliced string
 #[test]
-#[should_panic(expected="Lorem ipsum dolor sit amet")]
+#[should_panic(expected="byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
 fn test_slice_fail_truncated_1() {
     &LOREM_PARAGRAPH[..1024];
 }
 // check the truncation in the panic message
 #[test]
-#[should_panic(expected="luctus, im`[...] do not lie on character boundary")]
+#[should_panic(expected="luctus, im`[...]")]
 fn test_slice_fail_truncated_2() {
     &LOREM_PARAGRAPH[..1024];
 }
 
 #[test]
+#[should_panic(expected="byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of")]
+fn test_slice_fail_boundary_1() {
+    &"abcαβγ"[4..];
+}
+
+#[test]
+#[should_panic(expected="byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of")]
+fn test_slice_fail_boundary_2() {
+    &"abcαβγ"[2..6];
+}
+
+#[test]
 fn test_slice_from() {
     assert_eq!(&"abcd"[0..], "abcd");
     assert_eq!(&"abcd"[2..], "cd");
diff --git a/src/libcompiler_builtins/Cargo.toml b/src/libcompiler_builtins/Cargo.toml
index 79570dc0252..1a549ae823a 100644
--- a/src/libcompiler_builtins/Cargo.toml
+++ b/src/libcompiler_builtins/Cargo.toml
@@ -9,6 +9,7 @@ name = "compiler_builtins"
 path = "lib.rs"
 test = false
 bench = false
+doc = false
 
 [dependencies]
 core = { path = "../libcore" }
diff --git a/src/libcompiler_builtins/lib.rs b/src/libcompiler_builtins/lib.rs
index 4a703b3da68..1bc9b660001 100644
--- a/src/libcompiler_builtins/lib.rs
+++ b/src/libcompiler_builtins/lib.rs
@@ -16,4 +16,787 @@
             issue = "0")]
 #![crate_name = "compiler_builtins"]
 #![crate_type = "rlib"]
-#![feature(staged_api)]
+#![allow(unused_features)]
+#![feature(staged_api, core_intrinsics, repr_simd,
+           i128_type, core_float, abi_unadjusted, associated_consts)]
+#![allow(non_camel_case_types, unused_variables, unused_imports)]
+#![cfg_attr(stage0, allow(dead_code))]
+
+#[cfg(any(target_pointer_width="32", target_pointer_width="16", target_os="windows",
+          target_arch="mips64"))]
+pub mod reimpls {
+
+    #![allow(unused_comparisons)]
+
+    use core::intrinsics::unchecked_div;
+    use core::intrinsics::unchecked_rem;
+    use core::ptr;
+
+    // C API is expected to tolerate some amount of size mismatch in ABI. Hopefully the amount of
+    // handling is sufficient for bootstrapping.
+    #[cfg(stage0)]
+    type u128_ = u64;
+    #[cfg(stage0)]
+    type i128_ = i64;
+    #[cfg(not(stage0))]
+    type u128_ = u128;
+    #[cfg(not(stage0))]
+    type i128_ = i128;
+
+    macro_rules! ashl {
+        ($a:expr, $b:expr, $ty:ty) => {{
+            let (a, b) = ($a, $b);
+            let bits = (::core::mem::size_of::<$ty>() * 8) as $ty;
+            let half_bits = bits >> 1;
+            if b & half_bits != 0 {
+                <$ty>::from_parts(0, a.low().wrapping_shl(
+                                        b.wrapping_sub(half_bits) as u32))
+            } else if b == 0 {
+                a
+            } else {
+                <$ty>::from_parts(a.low().wrapping_shl(b as u32),
+                                  a.high().wrapping_shl(b as u32)
+                                  | a.low()
+                                     .wrapping_shr(half_bits.wrapping_sub(b) as u32))
+            }
+        }}
+    }
+
+    #[export_name="__ashlti3"]
+    pub extern "C" fn shl(a: u128_, b: u128_) -> u128_ {
+        ashl!(a, b, u128_)
+    }
+
+    macro_rules! ashr {
+        ($a: expr, $b: expr, $ty:ty) => {{
+            let (a, b) = ($a, $b);
+            let bits = (::core::mem::size_of::<$ty>() * 8) as $ty;
+            let half_bits = bits >> 1;
+            if b & half_bits != 0 {
+                <$ty>::from_parts(a.high().wrapping_shr(b.wrapping_sub(half_bits) as u32)
+                                  as <$ty as LargeInt>::LowHalf,
+                                  a.high().wrapping_shr(half_bits.wrapping_sub(1) as u32))
+            } else if b == 0 {
+                a
+            } else {
+                let high_unsigned = a.high() as <$ty as LargeInt>::LowHalf;
+                <$ty>::from_parts(high_unsigned.wrapping_shl(half_bits.wrapping_sub(b) as u32)
+                                  | a.low().wrapping_shr(b as u32),
+                                  a.high().wrapping_shr(b as u32))
+            }
+        }}
+    }
+
+    #[export_name="__ashrti3"]
+    pub extern "C" fn shr(a: i128_, b: i128_) -> i128_ {
+        ashr!(a, b, i128_)
+    }
+
+    macro_rules! lshr {
+        ($a: expr, $b: expr, $ty:ty) => {{
+            let (a, b) = ($a, $b);
+            let bits = (::core::mem::size_of::<$ty>() * 8) as $ty;
+            let half_bits = bits >> 1;
+            if b & half_bits != 0 {
+                <$ty>::from_parts(a.high().wrapping_shr(b.wrapping_sub(half_bits) as u32), 0)
+            } else if b == 0 {
+                a
+            } else {
+                <$ty>::from_parts(a.high().wrapping_shl(half_bits.wrapping_sub(b) as u32)
+                                  | a.low().wrapping_shr(b as u32),
+                                  a.high().wrapping_shr(b as u32))
+            }
+        }}
+    }
+
+
+    #[export_name="__lshrti3"]
+    pub extern "C" fn lshr(a: u128_, b: u128_) -> u128_ {
+        lshr!(a, b, u128_)
+    }
+
+    #[cfg(stage0)]
+    pub extern "C" fn u128_div_mod(n: u128_, d: u128_, rem: *mut u128_) -> u128_ {
+        unsafe {
+        if !rem.is_null() {
+            *rem = unchecked_rem(n, d);
+        }
+        unchecked_div(n, d)
+        }
+    }
+
+    #[cfg(not(stage0))]
+    pub extern "C" fn u128_div_mod(n: u128_, d: u128_, rem: *mut u128_) -> u128_ {
+        // Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide
+        unsafe {
+        // special cases, X is unknown, K != 0
+        if n.high() == 0 {
+            if d.high() == 0 {
+                // 0 X
+                // ---
+                // 0 X
+                if !rem.is_null() {
+                    *rem = u128::from(unchecked_rem(n.low(), d.low()));
+                }
+                return u128::from(unchecked_div(n.low(), d.low()));
+            } else {
+                // 0 X
+                // ---
+                // K X
+                if !rem.is_null() {
+                    *rem = n;
+                }
+                return 0;
+            };
+        }
+
+        let mut sr;
+        let mut q;
+        let mut r;
+
+        if d.low() == 0 {
+            if d.high() == 0 {
+                // K X
+                // ---
+                // 0 0
+                if !rem.is_null() {
+                    *rem = u128::from(unchecked_rem(n.high(), d.low()));
+                }
+                return u128::from(unchecked_div(n.high(), d.low()));
+            }
+
+            if n.low() == 0 {
+                // K 0
+                // ---
+                // K 0
+                if !rem.is_null() {
+                    *rem = u128::from_parts(0, unchecked_rem(n.high(), d.high()));
+                }
+                return u128::from(unchecked_div(n.high(), d.high()));
+            }
+
+            // K K
+            // ---
+            // K 0
+
+            if d.high().is_power_of_two() {
+                if !rem.is_null() {
+                    *rem = u128::from_parts(n.low(),
+                                            n.high() & (d.high().wrapping_sub(1)));
+                }
+                return u128::from(n.high().wrapping_shr(d.high().trailing_zeros()));
+            }
+
+            // K K
+            // ---
+            // K 0
+            sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros());
+
+            // D > N
+            if sr > 64 - 2 {
+                if !rem.is_null() {
+                    *rem = n;
+                }
+                return 0;
+            }
+
+            sr = sr.wrapping_add(1);
+
+            // 1 <= sr <= u64::bits() - 1
+            q = n.wrapping_shl(64u32.wrapping_sub(sr));
+            r = n.wrapping_shr(sr);
+        } else {
+            if d.high() == 0 {
+                // K X
+                // ---
+                // 0 K
+                if d.low().is_power_of_two() {
+                    if !rem.is_null() {
+                        *rem = u128::from(n.low() & (d.low().wrapping_sub(1)));
+                    }
+
+                    if d.low() == 1 {
+                        return n;
+                    } else {
+                        let sr = d.low().trailing_zeros();
+                        return n.wrapping_shr(sr);
+                    };
+                }
+
+                sr = (1 + 64u32)
+                    .wrapping_add(d.low().leading_zeros())
+                    .wrapping_sub(n.high().leading_zeros());
+
+                // 2 <= sr <= u64::bits() - 1
+                q = n.wrapping_shl(128u32.wrapping_sub(sr));
+                r = n.wrapping_shr(sr);
+                // FIXME the C compiler-rt implementation has something here
+                // that looks like a speed optimisation.
+                // It would be worth a try to port it to Rust too and
+                // compare the speed.
+            } else {
+                // K X
+                // ---
+                // K K
+                sr = d.high().leading_zeros().wrapping_sub(n.high().leading_zeros());
+
+                // D > N
+                if sr > 64 - 1 {
+                    if !rem.is_null() {
+                        *rem = n;
+                    }
+                    return 0;
+                }
+
+                sr = sr.wrapping_add(1);
+
+                // 1 <= sr <= u32::bits()
+                q = n.wrapping_shl(128u32.wrapping_sub(sr));
+                r = n.wrapping_shr(sr);
+            }
+        }
+
+        // Not a special case
+        // q and r are initialized with
+        // q = n << (u64::bits() - sr)
+        // r = n >> sr
+        // 1 <= sr <= u64::bits() - 1
+        let mut carry = 0;
+
+        // FIXME: replace this with a for loop
+        // (atm not doable as this generates call to
+        // eh_personality when optimisations are turned off,
+        // which in turn gives a linker error in later
+        // compilation steps)
+        while sr > 0 {
+            // r:q = ((r:q) << 1) | carry
+            r = r.wrapping_shl(1) | q.wrapping_shr(128 - 1);
+            q = q.wrapping_shl(1) | carry as u128;
+
+            // carry = 0
+            // if r >= d {
+            //     r -= d;
+            //     carry = 1;
+            // }
+            let s = ((d.wrapping_sub(r).wrapping_sub(1)) as i128).wrapping_shr(128 - 1);
+            carry = (s & 1) as u64;
+            r = r.wrapping_sub(d & s as u128);
+            sr = sr.wrapping_sub(1);
+        }
+
+        if !rem.is_null() {
+            *rem = r;
+        }
+        (q.wrapping_shl(1)) | carry as u128
+        }
+    }
+
+    fn i128_mod(a: i128_, b: i128_) -> i128_ {
+        let b = b.uabs();
+        let sa = a.signum();
+        let a = a.uabs();
+        unsafe {
+            let mut r = ::core::mem::zeroed();
+            u128_div_mod(a, b, &mut r);
+            if sa == -1 { (r as i128_).unchecked_neg() } else { r as i128_ }
+        }
+    }
+
+    fn i128_div(a: i128_, b: i128_) -> i128_ {
+        let sa = a.signum();
+        let sb = b.signum();
+        let a = a.uabs();
+        let b = b.uabs();
+        let sr = sa.wrapping_mul(sb); // sign of quotient
+        (if sr == -1 {
+            (u128_div_mod(a, b, ptr::null_mut()) as i128_).unchecked_neg()
+        } else {
+            u128_div_mod(a, b, ptr::null_mut()) as i128_
+        })
+    }
+
+    #[cfg(stage0)]
+    #[export_name="__udivti3"]
+    pub extern "C" fn u128_div(a: u128_, b: u128_) -> u128_ {
+        (a / b)
+    }
+
+    macro_rules! mulo {
+        ($a:expr, $b:expr, $o: expr, $ty: ty) => {{
+            let (a, b, overflow) = ($a, $b, $o);
+            *overflow = 0;
+            let result = a.wrapping_mul(b);
+            if a == <$ty>::min_value() {
+                if b != 0 && b != 1 {
+                    *overflow = 1;
+                }
+                return result;
+            }
+            if b == <$ty>::min_value() {
+                if a != 0 && a != 1 {
+                    *overflow = 1;
+                }
+                return result;
+            }
+
+            let sa = a.signum();
+            let abs_a = a.iabs();
+            let sb = b.signum();
+            let abs_b = b.iabs();
+            if abs_a < 2 || abs_b < 2 {
+                return result;
+            }
+            if sa == sb {
+                if abs_a > unchecked_div(<$ty>::max_value(), abs_b) {
+                    *overflow = 1;
+                }
+            } else {
+                if abs_a > unchecked_div(<$ty>::min_value(), abs_b.unchecked_neg()) {
+                    *overflow = 1;
+                }
+            }
+            result
+        }}
+    }
+
+    pub trait LargeInt {
+        type LowHalf;
+        type HighHalf;
+
+        fn low(self) -> Self::LowHalf;
+        fn high(self) -> Self::HighHalf;
+        fn from_parts(low: Self::LowHalf, high: Self::HighHalf) -> Self;
+    }
+    impl LargeInt for u64 {
+        type LowHalf = u32;
+        type HighHalf = u32;
+
+        fn low(self) -> u32 {
+            self as u32
+        }
+        fn high(self) -> u32 {
+            (self.wrapping_shr(32)) as u32
+        }
+        fn from_parts(low: u32, high: u32) -> u64 {
+            low as u64 | (high as u64).wrapping_shl(32)
+        }
+    }
+    impl LargeInt for i64 {
+        type LowHalf = u32;
+        type HighHalf = i32;
+
+        fn low(self) -> u32 {
+            self as u32
+        }
+        fn high(self) -> i32 {
+            self.wrapping_shr(32) as i32
+        }
+        fn from_parts(low: u32, high: i32) -> i64 {
+            low as i64 | (high as i64).wrapping_shl(32)
+        }
+    }
+    #[cfg(not(stage0))]
+    impl LargeInt for u128 {
+        type LowHalf = u64;
+        type HighHalf = u64;
+
+        fn low(self) -> u64 {
+            self as u64
+        }
+        fn high(self) -> u64 {
+            unsafe { *(&self as *const u128 as *const u64).offset(1) }
+        }
+        fn from_parts(low: u64, high: u64) -> u128 {
+            #[repr(C, packed)] struct Parts(u64, u64);
+            unsafe { ::core::mem::transmute(Parts(low, high)) }
+        }
+    }
+    #[cfg(not(stage0))]
+    impl LargeInt for i128 {
+        type LowHalf = u64;
+        type HighHalf = i64;
+
+        fn low(self) -> u64 {
+            self as u64
+        }
+        fn high(self) -> i64 {
+            unsafe { *(&self as *const i128 as *const i64).offset(1) }
+        }
+        fn from_parts(low: u64, high: i64) -> i128 {
+            u128::from_parts(low, high as u64) as i128
+        }
+    }
+
+    macro_rules! mul {
+        ($a:expr, $b:expr, $ty: ty, $tyh: ty) => {{
+            let (a, b) = ($a, $b);
+            let half_bits = ((::core::mem::size_of::<$tyh>() * 8) / 2) as u32;
+            let lower_mask = (!0u64).wrapping_shr(half_bits);
+            let mut low = (a.low() & lower_mask).wrapping_mul(b.low() & lower_mask);
+            let mut t = low.wrapping_shr(half_bits);
+            low &= lower_mask;
+            t = t.wrapping_add(a.low().wrapping_shr(half_bits)
+                                      .wrapping_mul(b.low() & lower_mask));
+            low = low.wrapping_add((t & lower_mask).wrapping_shl(half_bits));
+            let mut high = t.wrapping_shr(half_bits) as $tyh;
+            t = low.wrapping_shr(half_bits);
+            low &= lower_mask;
+            t = t.wrapping_add(b.low().wrapping_shr(half_bits)
+                                      .wrapping_mul(a.low() & lower_mask));
+            low = low.wrapping_add((t & lower_mask).wrapping_shl(half_bits));
+            high = high.wrapping_add(t.wrapping_shr(half_bits) as $tyh);
+            high = high.wrapping_add(a.low().wrapping_shr(half_bits)
+                           .wrapping_mul(b.low().wrapping_shr(half_bits)) as $tyh);
+            high = high
+                .wrapping_add(a.high()
+                .wrapping_mul(b.low() as $tyh))
+                .wrapping_add((a.low() as $tyh)
+                .wrapping_mul(b.high()));
+            <$ty>::from_parts(low, high)
+        }}
+    }
+
+    #[cfg(stage0)]
+    #[export_name="__multi3"]
+    pub extern "C" fn u128_mul(a: i128_, b: i128_) -> i128_ {
+        ((a as i64).wrapping_mul(b as i64) as i128_)
+    }
+
+    #[cfg(not(stage0))]
+    #[export_name="__multi3"]
+    pub extern "C" fn u128_mul(a: i128_, b: i128_) -> i128_ {
+        mul!(a, b, i128_, i64)
+    }
+
+    trait AbsExt: Sized {
+        fn uabs(self) -> u128_ {
+            self.iabs() as u128_
+        }
+        fn iabs(self) -> i128_;
+    }
+
+    #[cfg(stage0)]
+    impl AbsExt for i128_ {
+        fn iabs(self) -> i128_ {
+            let s = self >> 63;
+            ((self ^ s).wrapping_sub(s))
+        }
+    }
+
+    #[cfg(not(stage0))]
+    impl AbsExt for i128_ {
+        fn iabs(self) -> i128_ {
+            let s = self >> 127;
+            ((self ^ s).wrapping_sub(s))
+        }
+    }
+
+    trait NegExt: Sized {
+        fn unchecked_neg(self) -> i128_;
+    }
+
+    impl NegExt for i128_ {
+        fn unchecked_neg(self) -> i128_ {
+            (!self).wrapping_add(1)
+        }
+    }
+
+    trait FloatStuff: Sized {
+        type ToBytes;
+
+        const MANTISSA_BITS: u32;
+        const MAX_EXP: i32;
+        const EXP_MASK: Self::ToBytes;
+        const MANTISSA_MASK: Self::ToBytes;
+        const MANTISSA_LEAD_BIT: Self::ToBytes;
+
+        fn to_bytes(self) -> Self::ToBytes;
+        fn get_exponent(self) -> i32;
+    }
+
+    impl FloatStuff for f32 {
+        type ToBytes = u32;
+        const MANTISSA_BITS: u32 = 23;
+        const MAX_EXP: i32 = 127;
+        const EXP_MASK: u32 = 0x7F80_0000;
+        const MANTISSA_MASK: u32 = 0x007F_FFFF;
+        const MANTISSA_LEAD_BIT: u32 = 0x0080_0000;
+
+        fn to_bytes(self) -> u32 { unsafe { ::core::mem::transmute(self) } }
+        fn get_exponent(self) -> i32 {
+            ((self.to_bytes() & Self::EXP_MASK).wrapping_shr(Self::MANTISSA_BITS) as i32)
+            .wrapping_sub(Self::MAX_EXP)
+        }
+    }
+
+    impl FloatStuff for f64 {
+        type ToBytes = u64;
+        const MANTISSA_BITS: u32 = 52;
+        const MAX_EXP: i32 = 1023;
+        const EXP_MASK: u64 = 0x7FF0_0000_0000_0000;
+        const MANTISSA_MASK: u64 = 0x000F_FFFF_FFFF_FFFF;
+        const MANTISSA_LEAD_BIT: u64 = 0x0010_0000_0000_0000;
+
+        fn to_bytes(self) -> u64 { unsafe { ::core::mem::transmute(self) } }
+        fn get_exponent(self) -> i32 {
+            ((self.to_bytes() & Self::EXP_MASK).wrapping_shr(Self::MANTISSA_BITS) as i32)
+            .wrapping_sub(Self::MAX_EXP)
+        }
+    }
+
+    macro_rules! float_as_unsigned {
+        ($from: expr, $fromty: ty, $outty: ty) => { {
+            use core::num::Float;
+            let repr = $from.to_bytes();
+            let sign = $from.signum();
+            let exponent = $from.get_exponent();
+            let mantissa_fraction = repr & <$fromty as FloatStuff>::MANTISSA_MASK;
+            let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT;
+            if sign == -1.0 || exponent < 0 { return 0 as u128_; }
+            if exponent > ::core::mem::size_of::<$outty>() as i32 * 8 {
+                return !(0 as u128_);
+            }
+            (if exponent < (<$fromty as FloatStuff>::MANTISSA_BITS) as i32 {
+                (mantissa as $outty)
+                    .wrapping_shr((<$fromty as FloatStuff>::MANTISSA_BITS as i32)
+                                  .wrapping_sub(exponent) as u32)
+            } else {
+                (mantissa as $outty)
+                    .wrapping_shl(exponent.wrapping_sub(
+                        <$fromty as FloatStuff>::MANTISSA_BITS as i32) as u32)
+            })
+        } }
+    }
+
+    macro_rules! float_as_signed {
+        ($from: expr, $fromty: ty, $outty: ty) => {{
+            use core::num::Float;
+            let repr = $from.to_bytes();
+            let sign = $from.signum();
+            let exponent = $from.get_exponent();
+            let mantissa_fraction = repr & <$fromty as FloatStuff>::MANTISSA_MASK;
+            let mantissa = mantissa_fraction | <$fromty as FloatStuff>::MANTISSA_LEAD_BIT;
+
+            if exponent < 0 { return 0 as i128_; }
+            if exponent > ::core::mem::size_of::<$outty>() as i32 * 8 {
+                let ret = if sign > 0.0 { <$outty>::max_value() } else { <$outty>::min_value() };
+                return ret
+            }
+            let r = if exponent < (<$fromty as FloatStuff>::MANTISSA_BITS) as i32 {
+                (mantissa as $outty)
+                    .wrapping_shr((<$fromty as FloatStuff>::MANTISSA_BITS as i32)
+                                  .wrapping_sub(exponent) as u32)
+            } else {
+                (mantissa as $outty)
+                    .wrapping_shl(exponent.wrapping_sub(
+                        <$fromty as FloatStuff>::MANTISSA_BITS as i32) as u32)
+            };
+            (if sign >= 0.0 { r } else { r.unchecked_neg() })
+        }}
+    }
+
+
+    fn i128_as_f64(a: i128_) -> f64 {
+        match a.signum() {
+            1 => u128_as_f64(a.uabs()),
+            0 => 0.0,
+            _ => -u128_as_f64(a.uabs()),
+        }
+    }
+
+    fn i128_as_f32(a: i128_) -> f32 {
+        match a.signum() {
+            1 => u128_as_f32(a.uabs()),
+            0 => 0.0,
+            _ => -u128_as_f32(a.uabs()),
+        }
+    }
+
+    fn u128_as_f64(mut a: u128_) -> f64 {
+        use ::core::f64::MANTISSA_DIGITS;
+        if a == 0 { return 0.0; }
+        let sd = 128u32.wrapping_sub(a.leading_zeros());
+        let mut e = sd.wrapping_sub(1);
+        const MD1 : u32 = MANTISSA_DIGITS + 1;
+        const MD2 : u32 = MANTISSA_DIGITS + 2;
+
+        // SNAP: replace this with !0u128
+        let negn :u128_ = !0;
+
+        if sd > MANTISSA_DIGITS {
+            a = match sd {
+                MD1 => a.wrapping_shl(1),
+                MD2 => a,
+                _ => a.wrapping_shr(sd.wrapping_sub(MANTISSA_DIGITS + 2)) |
+                     (if (a & (negn.wrapping_shr(128 + MANTISSA_DIGITS + 2)
+                                   .wrapping_sub(sd as u128_))) == 0 { 0 } else { 1 })
+            };
+            a |= if (a & 4) == 0 { 0 } else { 1 };
+            a = a.wrapping_add(1);
+            a = a.wrapping_shr(2);
+            if a & (1 << MANTISSA_DIGITS) != 0 {
+                a = a.wrapping_shr(1);
+                e = e.wrapping_add(1);
+            }
+        } else {
+            a = a.wrapping_shl(MANTISSA_DIGITS.wrapping_sub(sd));
+        }
+        unsafe {
+            ::core::mem::transmute((e as u64).wrapping_add(1023).wrapping_shl(52)
+                                   | (a as u64 & 0x000f_ffff_ffff_ffff))
+        }
+    }
+
+    fn u128_as_f32(mut a: u128_) -> f32 {
+        use ::core::f32::MANTISSA_DIGITS;
+        if a == 0 { return 0.0; }
+        let sd = 128u32.wrapping_sub(a.leading_zeros());
+        let mut e = sd.wrapping_sub(1);
+        const MD1 : u32 = MANTISSA_DIGITS + 1;
+        const MD2 : u32 = MANTISSA_DIGITS + 2;
+
+        // SNAP: replace this with !0u128
+        let negn :u128_ = !0;
+
+        if sd > MANTISSA_DIGITS {
+            a = match sd {
+                MD1 => a.wrapping_shl(1),
+                MD2 => a,
+                _ => a.wrapping_shr(sd.wrapping_sub(MANTISSA_DIGITS + 2)) |
+                     (if (a & (negn.wrapping_shr(128 + MANTISSA_DIGITS + 2)
+                                   .wrapping_sub(sd as u128_))) == 0 { 0 } else { 1 })
+            };
+            a |= if (a & 4) == 0 { 0 } else { 1 };
+            a = a.wrapping_add(1);
+            a = a.wrapping_shr(2);
+            if a & (1 << MANTISSA_DIGITS) != 0 {
+                a = a.wrapping_shr(1);
+                e = e.wrapping_add(1);
+            }
+        } else {
+            a = a.wrapping_shl(MANTISSA_DIGITS.wrapping_sub(sd));
+        }
+        unsafe {
+            ::core::mem::transmute((e as u32).wrapping_add(127).wrapping_shl(23)
+                                   | (a as u32 & 0x007f_ffff))
+        }
+    }
+
+
+    macro_rules! why_are_abi_strings_checked_by_parser { ($cret:ty, $conv:expr, $unadj:tt) => {
+    mod imp {
+        use super::{i128_, u128_, LargeInt, FloatStuff, NegExt, AbsExt};
+        use super::{i128_as_f64, i128_as_f32, u128_as_f64, u128_as_f32,
+                    i128_div, i128_mod, u128_div_mod, unchecked_div, ptr};
+        // For x64
+        // rdx:rcx, r9:r8, stack -> rdx:rax
+        // aka.
+        // define i128 @__muloti4(i128, i128, i32*)
+        #[export_name="__muloti4"]
+        pub unsafe extern $unadj fn i128_mul_oflow(a: i128_, b: i128_, o: *mut i32) -> i128_ {
+            mulo!(a, b, o, i128_)
+        }
+
+        // For x64
+        // rdx:rax -> xmm0
+        // aka.
+        // define double @__muloti4(i128)
+        #[export_name="__floattidf"]
+        pub extern $unadj fn i128_as_f64_(a: i128_) -> f64 {
+            i128_as_f64(a)
+        }
+        #[export_name="__floattisf"]
+        pub extern $unadj fn i128_as_f32_(a: i128_) -> f32 {
+            i128_as_f32(a)
+        }
+        #[export_name="__floatuntidf"]
+        pub extern $unadj fn u128_as_f64_(a: u128_) -> f64 {
+            u128_as_f64(a)
+        }
+        #[export_name="__floatuntisf"]
+        pub extern $unadj fn u128_as_f32_(a: u128_) -> f32 {
+            u128_as_f32(a)
+        }
+
+        // For x64
+        // xmm0 -> rdx:rax
+        // aka.
+        // define i128 @stuff(double)
+        #[export_name="__fixunsdfti"]
+        pub extern $unadj fn f64_as_u128(a: f64) -> u128_ {
+            float_as_unsigned!(a, f64, u128_)
+        }
+
+        #[export_name="__fixunssfti"]
+        pub extern "unadjusted" fn f32_as_u128(a: f32) -> u128_ {
+            float_as_unsigned!(a, f32, u128_)
+        }
+
+        #[export_name="__fixdfti"]
+        pub extern "unadjusted" fn f64_as_i128(a: f64) -> i128_ {
+            float_as_signed!(a, f64, i128_)
+        }
+
+        #[export_name="__fixsfti"]
+        pub extern "unadjusted" fn f32_as_i128(a: f32) -> i128_ {
+            float_as_signed!(a, f32, i128_)
+        }
+
+        #[repr(simd)]
+        pub struct u64x2(u64, u64);
+
+        // For x64
+        // pointers -> xmm0
+        // aka.
+        // define <2 x u64> @stuff(i128*, i128*, i128*)
+        //
+        // That almost matches the C ABI, so we simply use the C ABI
+        #[export_name="__udivmodti4"]
+        pub extern "C" fn u128_div_mod_(n: u128_, d: u128_, rem: *mut u128_) -> $cret {
+            let x = u128_div_mod(n, d, rem);
+            ($conv)(x)
+        }
+
+        #[export_name="__udivti3"]
+        pub extern "C" fn u128_div_(a: u128_, b: u128_) -> $cret {
+            let x = u128_div_mod(a, b, ptr::null_mut());
+            ($conv)(x)
+        }
+
+        #[export_name="__umodti3"]
+        pub extern "C" fn u128_mod_(a: u128_, b: u128_) -> $cret {
+            unsafe {
+                let mut r = ::core::mem::zeroed();
+                u128_div_mod(a, b, &mut r);
+                ($conv)(r)
+            }
+        }
+
+        #[export_name="__divti3"]
+        pub extern "C" fn i128_div_(a: i128_, b: i128_) -> $cret {
+            let x = i128_div(a, b);
+            ($conv)(x as u128_)
+        }
+
+        #[export_name="__modti3"]
+        pub extern "C" fn i128_mod_(a: i128_, b: i128_) -> $cret {
+            let x = i128_mod(a, b);
+            ($conv)(x as u128_)
+        }
+    }
+    } }
+
+    // LLVM expectations for ABI on windows x64 are pure madness.
+    #[cfg(not(stage0))]
+    #[cfg(all(windows, target_pointer_width="64"))]
+    why_are_abi_strings_checked_by_parser!(u64x2,
+                                           |i: u128_| u64x2(i.low(), i.high()),
+                                           "unadjusted");
+
+    #[cfg(not(stage0))]
+    #[cfg(not(all(windows, target_pointer_width="64")))]
+    why_are_abi_strings_checked_by_parser!(u128_, |i|{ i }, "C");
+
+    #[cfg(not(stage0))]
+    pub use self::imp::*;
+}
diff --git a/src/libcore/clone.rs b/src/libcore/clone.rs
index d72b18ae345..cd2e8f10181 100644
--- a/src/libcore/clone.rs
+++ b/src/libcore/clone.rs
@@ -153,12 +153,16 @@ clone_impl! { i8 }
 clone_impl! { i16 }
 clone_impl! { i32 }
 clone_impl! { i64 }
+#[cfg(not(stage0))]
+clone_impl! { i128 }
 
 clone_impl! { usize }
 clone_impl! { u8 }
 clone_impl! { u16 }
 clone_impl! { u32 }
 clone_impl! { u64 }
+#[cfg(not(stage0))]
+clone_impl! { u128 }
 
 clone_impl! { f32 }
 clone_impl! { f64 }
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 0daf658a0f4..a78d27ea3af 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -429,7 +429,7 @@ impl PartialOrd for Ordering {
 /// This trait can be used with `#[derive]`. When `derive`d, it will produce a lexicographic
 /// ordering based on the top-to-bottom declaration order of the struct's members.
 ///
-/// ## How can I implement `Ord`?
+/// ## How can I implement `PartialOrd`?
 ///
 /// PartialOrd only requires implementation of the `partial_cmp` method, with the others generated
 /// from default implementations.
@@ -681,6 +681,8 @@ mod impls {
     partial_eq_impl! {
         bool char usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64
     }
+    #[cfg(not(stage0))]
+    partial_eq_impl! { u128 i128 }
 
     macro_rules! eq_impl {
         ($($t:ty)*) => ($(
@@ -690,6 +692,8 @@ mod impls {
     }
 
     eq_impl! { () bool char usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
+    #[cfg(not(stage0))]
+    eq_impl! { u128 i128 }
 
     macro_rules! partial_ord_impl {
         ($($t:ty)*) => ($(
@@ -779,6 +783,8 @@ mod impls {
     }
 
     ord_impl! { char usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
+    #[cfg(not(stage0))]
+    ord_impl! { u128 i128 }
 
     #[unstable(feature = "never_type_impls", issue = "35121")]
     impl PartialEq for ! {
diff --git a/src/libcore/default.rs b/src/libcore/default.rs
index 85e4b2a0067..ccd4343336f 100644
--- a/src/libcore/default.rs
+++ b/src/libcore/default.rs
@@ -144,12 +144,16 @@ default_impl! { u8, 0 }
 default_impl! { u16, 0 }
 default_impl! { u32, 0 }
 default_impl! { u64, 0 }
+#[cfg(not(stage0))]
+default_impl! { u128, 0 }
 
 default_impl! { isize, 0 }
 default_impl! { i8, 0 }
 default_impl! { i16, 0 }
 default_impl! { i32, 0 }
 default_impl! { i64, 0 }
+#[cfg(not(stage0))]
+default_impl! { i128, 0 }
 
 default_impl! { f32, 0.0f32 }
 default_impl! { f64, 0.0f64 }
diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs
index 0145897d8f6..cd725392b66 100644
--- a/src/libcore/fmt/num.rs
+++ b/src/libcore/fmt/num.rs
@@ -30,6 +30,8 @@ trait Int: Zero + PartialEq + PartialOrd + Div<Output=Self> + Rem<Output=Self> +
     fn to_u16(&self) -> u16;
     fn to_u32(&self) -> u32;
     fn to_u64(&self) -> u64;
+    #[cfg(not(stage0))]
+    fn to_u128(&self) -> u128;
 }
 
 macro_rules! doit {
@@ -39,9 +41,13 @@ macro_rules! doit {
         fn to_u16(&self) -> u16 { *self as u16 }
         fn to_u32(&self) -> u32 { *self as u32 }
         fn to_u64(&self) -> u64 { *self as u64 }
+        #[cfg(not(stage0))]
+        fn to_u128(&self) -> u128 { *self as u128 }
     })*)
 }
 doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
+#[cfg(not(stage0))]
+doit! { i128 u128 }
 
 /// A type that represents a specific radix
 #[doc(hidden)]
@@ -59,11 +65,11 @@ trait GenericRadix {
 
     /// Format an integer using the radix using a formatter.
     fn fmt_int<T: Int>(&self, mut x: T, f: &mut fmt::Formatter) -> fmt::Result {
-        // The radix can be as low as 2, so we need a buffer of at least 64
+        // The radix can be as low as 2, so we need a buffer of at least 128
         // characters for a base 2 number.
         let zero = T::zero();
         let is_nonnegative = x >= zero;
-        let mut buf = [0; 64];
+        let mut buf = [0; 128];
         let mut curr = buf.len();
         let base = T::from_u8(self.base());
         if is_nonnegative {
@@ -182,6 +188,8 @@ integer! { i8, u8 }
 integer! { i16, u16 }
 integer! { i32, u32 }
 integer! { i64, u64 }
+#[cfg(not(stage0))]
+integer! { i128, u128 }
 
 const DEC_DIGITS_LUT: &'static[u8] =
     b"0001020304050607080910111213141516171819\
@@ -203,14 +211,15 @@ macro_rules! impl_Display {
                 // convert the negative num to positive by summing 1 to it's 2 complement
                 (!self.$conv_fn()).wrapping_add(1)
             };
-            let mut buf: [u8; 20] = unsafe { mem::uninitialized() };
+            let mut buf: [u8; 39] = unsafe { mem::uninitialized() };
             let mut curr = buf.len() as isize;
             let buf_ptr = buf.as_mut_ptr();
             let lut_ptr = DEC_DIGITS_LUT.as_ptr();
 
             unsafe {
-                // eagerly decode 4 characters at a time
-                if <$t>::max_value() as u64 >= 10000 {
+                // need at least 16 bits for the 4-characters-at-a-time to work.
+                if ::mem::size_of::<$t>() >= 2 {
+                    // eagerly decode 4 characters at a time
                     while n >= 10000 {
                         let rem = (n % 10000) as isize;
                         n /= 10000;
@@ -256,6 +265,8 @@ macro_rules! impl_Display {
 
 impl_Display!(i8, u8, i16, u16, i32, u32: to_u32);
 impl_Display!(i64, u64: to_u64);
+#[cfg(not(stage0))]
+impl_Display!(i128, u128: to_u128);
 #[cfg(target_pointer_width = "16")]
 impl_Display!(isize, usize: to_u16);
 #[cfg(target_pointer_width = "32")]
diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs
index 18b465d85a1..92657a6d0b1 100644
--- a/src/libcore/hash/mod.rs
+++ b/src/libcore/hash/mod.rs
@@ -186,6 +186,13 @@ pub trait Hasher {
     fn write_u64(&mut self, i: u64) {
         self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) })
     }
+    #[cfg(not(stage0))]
+    /// Writes a single `u128` into this hasher.
+    #[inline]
+    #[unstable(feature = "i128", issue = "35118")]
+    fn write_u128(&mut self, i: u128) {
+        self.write(&unsafe { mem::transmute::<_, [u8; 16]>(i) })
+    }
     /// Writes a single `usize` into this hasher.
     #[inline]
     #[stable(feature = "hasher_write", since = "1.3.0")]
@@ -220,6 +227,13 @@ pub trait Hasher {
     fn write_i64(&mut self, i: i64) {
         self.write_u64(i as u64)
     }
+    #[cfg(not(stage0))]
+    /// Writes a single `i128` into this hasher.
+    #[inline]
+    #[unstable(feature = "i128", issue = "35118")]
+    fn write_i128(&mut self, i: i128) {
+        self.write_u128(i as u128)
+    }
     /// Writes a single `isize` into this hasher.
     #[inline]
     #[stable(feature = "hasher_write", since = "1.3.0")]
@@ -362,6 +376,11 @@ mod impls {
         (i64, write_i64),
         (isize, write_isize),
     }
+    #[cfg(not(stage0))]
+    impl_write! {
+        (u128, write_u128),
+        (i128, write_i128),
+    }
 
     #[stable(feature = "rust1", since = "1.0.0")]
     impl Hash for bool {
diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs
index e6f21d6c17a..9d22037882f 100644
--- a/src/libcore/iter/range.rs
+++ b/src/libcore/iter/range.rs
@@ -242,6 +242,8 @@ step_impl_signed!(i64);
 // assume here that it is less than 64-bits.
 #[cfg(not(target_pointer_width = "64"))]
 step_impl_no_between!(u64 i64);
+#[cfg(not(stage0))]
+step_impl_no_between!(u128 i128);
 
 /// An adapter for stepping range iterators by a custom amount.
 ///
diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs
index da346eaf1db..b988ce73bde 100644
--- a/src/libcore/iter/sources.rs
+++ b/src/libcore/iter/sources.rs
@@ -12,7 +12,7 @@ use fmt;
 use marker;
 use usize;
 
-use super::FusedIterator;
+use super::{FusedIterator, TrustedLen};
 
 /// An iterator that repeats an element endlessly.
 ///
@@ -138,6 +138,9 @@ impl<T> ExactSizeIterator for Empty<T> {
     }
 }
 
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<T> TrustedLen for Empty<T> {}
+
 #[unstable(feature = "fused", issue = "35602")]
 impl<T> FusedIterator for Empty<T> {}
 
@@ -216,6 +219,9 @@ impl<T> ExactSizeIterator for Once<T> {
     }
 }
 
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl<T> TrustedLen for Once<T> {}
+
 #[unstable(feature = "fused", issue = "35602")]
 impl<T> FusedIterator for Once<T> {}
 
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 9834fca5fdc..2cb2f81fcff 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -90,6 +90,7 @@
 #![feature(staged_api)]
 #![feature(unboxed_closures)]
 #![feature(never_type)]
+#![cfg_attr(not(stage0), feature(i128_type))]
 #![feature(prelude_import)]
 
 #[prelude_import]
@@ -120,12 +121,20 @@ mod uint_macros;
 #[path = "num/i32.rs"]   pub mod i32;
 #[path = "num/i64.rs"]   pub mod i64;
 
+// SNAP
+#[cfg(not(stage0))]
+#[path = "num/i128.rs"]   pub mod i128;
+
 #[path = "num/usize.rs"] pub mod usize;
 #[path = "num/u8.rs"]    pub mod u8;
 #[path = "num/u16.rs"]   pub mod u16;
 #[path = "num/u32.rs"]   pub mod u32;
 #[path = "num/u64.rs"]   pub mod u64;
 
+// SNAP
+#[cfg(not(stage0))]
+#[path = "num/u128.rs"]   pub mod u128;
+
 #[path = "num/f32.rs"]   pub mod f32;
 #[path = "num/f64.rs"]   pub mod f64;
 
diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs
index 47afaf77353..539ad00bd30 100644
--- a/src/libcore/nonzero.rs
+++ b/src/libcore/nonzero.rs
@@ -30,6 +30,10 @@ unsafe impl Zeroable for i32 {}
 unsafe impl Zeroable for u32 {}
 unsafe impl Zeroable for i64 {}
 unsafe impl Zeroable for u64 {}
+#[cfg(not(stage0))]
+unsafe impl Zeroable for i128 {}
+#[cfg(not(stage0))]
+unsafe impl Zeroable for u128 {}
 
 /// A wrapper type for raw pointers and integers that will never be
 /// NULL or 0 that might allow certain optimizations.
diff --git a/src/libcore/num/i128.rs b/src/libcore/num/i128.rs
new file mode 100644
index 00000000000..6268271a1dc
--- /dev/null
+++ b/src/libcore/num/i128.rs
@@ -0,0 +1,17 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! The 128-bit signed integer type.
+//!
+//! *[See also the `i128` primitive type](../../std/primitive.i128.html).*
+
+#![unstable(feature = "i128", issue="35118")]
+
+int_module! { i128 }
diff --git a/src/libcore/num/i16.rs b/src/libcore/num/i16.rs
index 1dd820980f4..0f3a5baa2dd 100644
--- a/src/libcore/num/i16.rs
+++ b/src/libcore/num/i16.rs
@@ -14,4 +14,4 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-int_module! { i16, 16 }
+int_module! { i16 }
diff --git a/src/libcore/num/i32.rs b/src/libcore/num/i32.rs
index 8a2168933dc..ea8b3a9145c 100644
--- a/src/libcore/num/i32.rs
+++ b/src/libcore/num/i32.rs
@@ -14,4 +14,4 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-int_module! { i32, 32 }
+int_module! { i32 }
diff --git a/src/libcore/num/i64.rs b/src/libcore/num/i64.rs
index 2ce9eb11936..aa21b1190ae 100644
--- a/src/libcore/num/i64.rs
+++ b/src/libcore/num/i64.rs
@@ -14,4 +14,4 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-int_module! { i64, 64 }
+int_module! { i64 }
diff --git a/src/libcore/num/i8.rs b/src/libcore/num/i8.rs
index 8b5a7f1910e..1bed4861594 100644
--- a/src/libcore/num/i8.rs
+++ b/src/libcore/num/i8.rs
@@ -14,4 +14,4 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-int_module! { i8, 8 }
+int_module! { i8 }
diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs
index e74c30d5e5a..630fac9d92f 100644
--- a/src/libcore/num/int_macros.rs
+++ b/src/libcore/num/int_macros.rs
@@ -10,7 +10,7 @@
 
 #![doc(hidden)]
 
-macro_rules! int_module { ($T:ident, $bits:expr) => (
+macro_rules! int_module { ($T:ident) => (
 
 /// The smallest value that can be represented by this integer type.
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/num/isize.rs b/src/libcore/num/isize.rs
index 86bcef4011d..e0917f79c43 100644
--- a/src/libcore/num/isize.rs
+++ b/src/libcore/num/isize.rs
@@ -14,9 +14,4 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-#[cfg(target_pointer_width = "16")]
-int_module! { isize, 16 }
-#[cfg(target_pointer_width = "32")]
-int_module! { isize, 32 }
-#[cfg(target_pointer_width = "64")]
-int_module! { isize, 64 }
+int_module! { isize }
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index a4529909e83..61c687313dc 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -145,6 +145,8 @@ macro_rules! zero_one_impl {
     )*)
 }
 zero_one_impl! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
+#[cfg(not(stage0))]
+zero_one_impl! { u128 i128 }
 
 macro_rules! zero_one_impl_float {
     ($($t:ty)*) => ($(
@@ -191,7 +193,7 @@ macro_rules! int_impl {
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
         pub const fn min_value() -> Self {
-            (-1 as Self) << ($BITS - 1)
+            !0 ^ ((!0 as $UnsignedT) >> 1) as Self
         }
 
         /// Returns the largest value that can be represented by this integer type.
@@ -1298,6 +1300,16 @@ impl i64 {
         intrinsics::mul_with_overflow }
 }
 
+// SNAP
+#[cfg(not(stage0))]
+#[lang = "i128"]
+impl i128 {
+    int_impl! { i128, u128, 128,
+        intrinsics::add_with_overflow,
+        intrinsics::sub_with_overflow,
+        intrinsics::mul_with_overflow }
+}
+
 #[cfg(target_pointer_width = "16")]
 #[lang = "isize"]
 impl isize {
@@ -2330,6 +2342,20 @@ impl u64 {
         intrinsics::mul_with_overflow }
 }
 
+// SNAP
+#[cfg(not(stage0))]
+#[lang = "u128"]
+impl u128 {
+    uint_impl! { u128, 128,
+        intrinsics::ctpop,
+        intrinsics::ctlz,
+        intrinsics::cttz,
+        intrinsics::bswap,
+        intrinsics::add_with_overflow,
+        intrinsics::sub_with_overflow,
+        intrinsics::mul_with_overflow }
+}
+
 #[cfg(target_pointer_width = "16")]
 #[lang = "usize"]
 impl usize {
@@ -2543,6 +2569,8 @@ macro_rules! from_str_radix_int_impl {
     )*}
 }
 from_str_radix_int_impl! { isize i8 i16 i32 i64 usize u8 u16 u32 u64 }
+#[cfg(not(stage0))]
+from_str_radix_int_impl! { u128 i128 }
 
 /// The error type returned when a checked integral type conversion fails.
 #[unstable(feature = "try_from", issue = "33417")]
@@ -2567,7 +2595,7 @@ impl fmt::Display for TryFromIntError {
     }
 }
 
-macro_rules! same_sign_from_int_impl {
+macro_rules! same_sign_try_from_int_impl {
     ($storage:ty, $target:ty, $($source:ty),*) => {$(
         #[unstable(feature = "try_from", issue = "33417")]
         impl TryFrom<$source> for $target {
@@ -2586,16 +2614,51 @@ macro_rules! same_sign_from_int_impl {
     )*}
 }
 
-same_sign_from_int_impl!(u64, u8, u8, u16, u32, u64, usize);
-same_sign_from_int_impl!(i64, i8, i8, i16, i32, i64, isize);
-same_sign_from_int_impl!(u64, u16, u8, u16, u32, u64, usize);
-same_sign_from_int_impl!(i64, i16, i8, i16, i32, i64, isize);
-same_sign_from_int_impl!(u64, u32, u8, u16, u32, u64, usize);
-same_sign_from_int_impl!(i64, i32, i8, i16, i32, i64, isize);
-same_sign_from_int_impl!(u64, u64, u8, u16, u32, u64, usize);
-same_sign_from_int_impl!(i64, i64, i8, i16, i32, i64, isize);
-same_sign_from_int_impl!(u64, usize, u8, u16, u32, u64, usize);
-same_sign_from_int_impl!(i64, isize, i8, i16, i32, i64, isize);
+#[cfg(stage0)]
+same_sign_try_from_int_impl!(u64, u8, u8, u16, u32, u64, usize);
+#[cfg(stage0)]
+same_sign_try_from_int_impl!(i64, i8, i8, i16, i32, i64, isize);
+#[cfg(stage0)]
+same_sign_try_from_int_impl!(u64, u16, u8, u16, u32, u64, usize);
+#[cfg(stage0)]
+same_sign_try_from_int_impl!(i64, i16, i8, i16, i32, i64, isize);
+#[cfg(stage0)]
+same_sign_try_from_int_impl!(u64, u32, u8, u16, u32, u64, usize);
+#[cfg(stage0)]
+same_sign_try_from_int_impl!(i64, i32, i8, i16, i32, i64, isize);
+#[cfg(stage0)]
+same_sign_try_from_int_impl!(u64, u64, u8, u16, u32, u64, usize);
+#[cfg(stage0)]
+same_sign_try_from_int_impl!(i64, i64, i8, i16, i32, i64, isize);
+#[cfg(stage0)]
+same_sign_try_from_int_impl!(u64, usize, u8, u16, u32, u64, usize);
+#[cfg(stage0)]
+same_sign_try_from_int_impl!(i64, isize, i8, i16, i32, i64, isize);
+
+#[cfg(not(stage0))]
+same_sign_try_from_int_impl!(u128, u8, u8, u16, u32, u64, u128, usize);
+#[cfg(not(stage0))]
+same_sign_try_from_int_impl!(i128, i8, i8, i16, i32, i64, i128, isize);
+#[cfg(not(stage0))]
+same_sign_try_from_int_impl!(u128, u16, u8, u16, u32, u64, u128, usize);
+#[cfg(not(stage0))]
+same_sign_try_from_int_impl!(i128, i16, i8, i16, i32, i64, i128, isize);
+#[cfg(not(stage0))]
+same_sign_try_from_int_impl!(u128, u32, u8, u16, u32, u64, u128, usize);
+#[cfg(not(stage0))]
+same_sign_try_from_int_impl!(i128, i32, i8, i16, i32, i64, i128, isize);
+#[cfg(not(stage0))]
+same_sign_try_from_int_impl!(u128, u64, u8, u16, u32, u64, u128, usize);
+#[cfg(not(stage0))]
+same_sign_try_from_int_impl!(i128, i64, i8, i16, i32, i64, i128, isize);
+#[cfg(not(stage0))]
+same_sign_try_from_int_impl!(u128, u128, u8, u16, u32, u64, u128, usize);
+#[cfg(not(stage0))]
+same_sign_try_from_int_impl!(i128, i128, i8, i16, i32, i64, i128, isize);
+#[cfg(not(stage0))]
+same_sign_try_from_int_impl!(u128, usize, u8, u16, u32, u64, u128, usize);
+#[cfg(not(stage0))]
+same_sign_try_from_int_impl!(i128, isize, i8, i16, i32, i64, i128, isize);
 
 macro_rules! cross_sign_from_int_impl {
     ($unsigned:ty, $($signed:ty),*) => {$(
@@ -2629,12 +2692,30 @@ macro_rules! cross_sign_from_int_impl {
     )*}
 }
 
+#[cfg(stage0)]
 cross_sign_from_int_impl!(u8, i8, i16, i32, i64, isize);
+#[cfg(stage0)]
 cross_sign_from_int_impl!(u16, i8, i16, i32, i64, isize);
+#[cfg(stage0)]
 cross_sign_from_int_impl!(u32, i8, i16, i32, i64, isize);
+#[cfg(stage0)]
 cross_sign_from_int_impl!(u64, i8, i16, i32, i64, isize);
+#[cfg(stage0)]
 cross_sign_from_int_impl!(usize, i8, i16, i32, i64, isize);
 
+#[cfg(not(stage0))]
+cross_sign_from_int_impl!(u8, i8, i16, i32, i64, i128, isize);
+#[cfg(not(stage0))]
+cross_sign_from_int_impl!(u16, i8, i16, i32, i64, i128, isize);
+#[cfg(not(stage0))]
+cross_sign_from_int_impl!(u32, i8, i16, i32, i64, i128, isize);
+#[cfg(not(stage0))]
+cross_sign_from_int_impl!(u64, i8, i16, i32, i64, i128, isize);
+#[cfg(not(stage0))]
+cross_sign_from_int_impl!(u128, i8, i16, i32, i64, i128, isize);
+#[cfg(not(stage0))]
+cross_sign_from_int_impl!(usize, i8, i16, i32, i64, i128, isize);
+
 #[doc(hidden)]
 trait FromStrRadixHelper: PartialOrd + Copy {
     fn min_value() -> Self;
@@ -2662,6 +2743,8 @@ macro_rules! doit {
     })*)
 }
 doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
+#[cfg(not(stage0))]
+doit! { i128 u128 }
 
 fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, ParseIntError> {
     use self::IntErrorKind::*;
@@ -2795,27 +2878,51 @@ macro_rules! impl_from {
 impl_from! { u8, u16 }
 impl_from! { u8, u32 }
 impl_from! { u8, u64 }
+#[cfg(not(stage0))]
+impl_from! { u8, u128 }
 impl_from! { u8, usize }
 impl_from! { u16, u32 }
 impl_from! { u16, u64 }
+#[cfg(not(stage0))]
+impl_from! { u16, u128 }
 impl_from! { u32, u64 }
+#[cfg(not(stage0))]
+impl_from! { u32, u128 }
+#[cfg(not(stage0))]
+impl_from! { u64, u128 }
 
 // Signed -> Signed
 impl_from! { i8, i16 }
 impl_from! { i8, i32 }
 impl_from! { i8, i64 }
+#[cfg(not(stage0))]
+impl_from! { i8, i128 }
 impl_from! { i8, isize }
 impl_from! { i16, i32 }
 impl_from! { i16, i64 }
+#[cfg(not(stage0))]
+impl_from! { i16, i128 }
 impl_from! { i32, i64 }
+#[cfg(not(stage0))]
+impl_from! { i32, i128 }
+#[cfg(not(stage0))]
+impl_from! { i64, i128 }
 
 // Unsigned -> Signed
 impl_from! { u8, i16 }
 impl_from! { u8, i32 }
 impl_from! { u8, i64 }
+#[cfg(not(stage0))]
+impl_from! { u8, i128 }
 impl_from! { u16, i32 }
 impl_from! { u16, i64 }
+#[cfg(not(stage0))]
+impl_from! { u16, i128 }
 impl_from! { u32, i64 }
+#[cfg(not(stage0))]
+impl_from! { u32, i128 }
+#[cfg(not(stage0))]
+impl_from! { u64, i128 }
 
 // Note: integers can only be represented with full precision in a float if
 // they fit in the significand, which is 24 bits in f32 and 53 bits in f64.
diff --git a/src/libcore/num/u128.rs b/src/libcore/num/u128.rs
new file mode 100644
index 00000000000..77291f68725
--- /dev/null
+++ b/src/libcore/num/u128.rs
@@ -0,0 +1,16 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! The 128-bit unsigned integer type.
+//!
+//! *[See also the `u128` primitive type](../../std/primitive.u128.html).*
+
+#![unstable(feature = "i128", issue="35118")]
+uint_module! { u128 }
diff --git a/src/libcore/num/u16.rs b/src/libcore/num/u16.rs
index d34d87caa55..9c318216f1f 100644
--- a/src/libcore/num/u16.rs
+++ b/src/libcore/num/u16.rs
@@ -14,4 +14,4 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-uint_module! { u16, 16 }
+uint_module! { u16 }
diff --git a/src/libcore/num/u32.rs b/src/libcore/num/u32.rs
index f9c9099e47f..84367c20738 100644
--- a/src/libcore/num/u32.rs
+++ b/src/libcore/num/u32.rs
@@ -14,4 +14,4 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-uint_module! { u32, 32 }
+uint_module! { u32 }
diff --git a/src/libcore/num/u64.rs b/src/libcore/num/u64.rs
index 8dfe4335a3d..cc48a28b22f 100644
--- a/src/libcore/num/u64.rs
+++ b/src/libcore/num/u64.rs
@@ -14,4 +14,4 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-uint_module! { u64, 64 }
+uint_module! { u64 }
diff --git a/src/libcore/num/u8.rs b/src/libcore/num/u8.rs
index 0106ee8e401..6c0daa7763a 100644
--- a/src/libcore/num/u8.rs
+++ b/src/libcore/num/u8.rs
@@ -14,4 +14,4 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-uint_module! { u8, 8 }
+uint_module! { u8 }
diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs
index cc9256ab6bf..a3a2dc73e9c 100644
--- a/src/libcore/num/uint_macros.rs
+++ b/src/libcore/num/uint_macros.rs
@@ -10,7 +10,7 @@
 
 #![doc(hidden)]
 
-macro_rules! uint_module { ($T:ident, $bits:expr) => (
+macro_rules! uint_module { ($T:ident) => (
 
 /// The smallest value that can be represented by this integer type.
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/num/usize.rs b/src/libcore/num/usize.rs
index 685c52e271e..0b6f1c73c58 100644
--- a/src/libcore/num/usize.rs
+++ b/src/libcore/num/usize.rs
@@ -14,9 +14,4 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-#[cfg(target_pointer_width = "16")]
-uint_module! { usize, 16 }
-#[cfg(target_pointer_width = "32")]
-uint_module! { usize, 32 }
-#[cfg(target_pointer_width = "64")]
-uint_module! { usize, 64 }
+uint_module! { usize }
diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs
index 50d64838a5c..b3c2c25551e 100644
--- a/src/libcore/num/wrapping.rs
+++ b/src/libcore/num/wrapping.rs
@@ -298,6 +298,8 @@ macro_rules! wrapping_impl {
 }
 
 wrapping_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
+#[cfg(not(stage0))]
+wrapping_impl! { u128 i128 }
 
 mod shift_max {
     #![allow(non_upper_case_globals)]
diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs
index 07ae5b920b2..40d941a8b27 100644
--- a/src/libcore/ops.rs
+++ b/src/libcore/ops.rs
@@ -268,6 +268,8 @@ macro_rules! add_impl {
 }
 
 add_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
+#[cfg(not(stage0))]
+add_impl! { u128 i128 }
 
 /// The `Sub` trait is used to specify the functionality of `-`.
 ///
@@ -341,6 +343,8 @@ macro_rules! sub_impl {
 }
 
 sub_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
+#[cfg(not(stage0))]
+sub_impl! { u128 i128 }
 
 /// The `Mul` trait is used to specify the functionality of `*`.
 ///
@@ -463,6 +467,8 @@ macro_rules! mul_impl {
 }
 
 mul_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
+#[cfg(not(stage0))]
+mul_impl! { u128 i128 }
 
 /// The `Div` trait is used to specify the functionality of `/`.
 ///
@@ -592,6 +598,8 @@ macro_rules! div_impl_integer {
 }
 
 div_impl_integer! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
+#[cfg(not(stage0))]
+div_impl_integer! { u128 i128 }
 
 macro_rules! div_impl_float {
     ($($t:ty)*) => ($(
@@ -671,6 +679,9 @@ macro_rules! rem_impl_integer {
 }
 
 rem_impl_integer! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
+#[cfg(not(stage0))]
+rem_impl_integer! { u128 i128 }
+
 
 macro_rules! rem_impl_float {
     ($($t:ty)*) => ($(
@@ -766,6 +777,8 @@ macro_rules! neg_impl_unsigned {
 
 // neg_impl_unsigned! { usize u8 u16 u32 u64 }
 neg_impl_numeric! { isize i8 i16 i32 i64 f32 f64 }
+#[cfg(not(stage0))]
+neg_impl_numeric! { i128 }
 
 /// The `Not` trait is used to specify the functionality of unary `!`.
 ///
@@ -824,6 +837,8 @@ macro_rules! not_impl {
 }
 
 not_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
+#[cfg(not(stage0))]
+not_impl! { u128 i128 }
 
 /// The `BitAnd` trait is used to specify the functionality of `&`.
 ///
@@ -907,6 +922,8 @@ macro_rules! bitand_impl {
 }
 
 bitand_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
+#[cfg(not(stage0))]
+bitand_impl! { u128 i128 }
 
 /// The `BitOr` trait is used to specify the functionality of `|`.
 ///
@@ -990,6 +1007,8 @@ macro_rules! bitor_impl {
 }
 
 bitor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
+#[cfg(not(stage0))]
+bitor_impl! { u128 i128 }
 
 /// The `BitXor` trait is used to specify the functionality of `^`.
 ///
@@ -1076,6 +1095,8 @@ macro_rules! bitxor_impl {
 }
 
 bitxor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
+#[cfg(not(stage0))]
+bitxor_impl! { u128 i128 }
 
 /// The `Shl` trait is used to specify the functionality of `<<`.
 ///
@@ -1166,17 +1187,23 @@ macro_rules! shl_impl_all {
         shl_impl! { $t, u16 }
         shl_impl! { $t, u32 }
         shl_impl! { $t, u64 }
+        #[cfg(not(stage0))]
+        shl_impl! { $t, u128 }
         shl_impl! { $t, usize }
 
         shl_impl! { $t, i8 }
         shl_impl! { $t, i16 }
         shl_impl! { $t, i32 }
         shl_impl! { $t, i64 }
+        #[cfg(not(stage0))]
+        shl_impl! { $t, i128 }
         shl_impl! { $t, isize }
     )*)
 }
 
 shl_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
+#[cfg(not(stage0))]
+shl_impl_all! { u128 i128 }
 
 /// The `Shr` trait is used to specify the functionality of `>>`.
 ///
@@ -1267,17 +1294,23 @@ macro_rules! shr_impl_all {
         shr_impl! { $t, u16 }
         shr_impl! { $t, u32 }
         shr_impl! { $t, u64 }
+        #[cfg(not(stage0))]
+        shr_impl! { $t, u128 }
         shr_impl! { $t, usize }
 
         shr_impl! { $t, i8 }
         shr_impl! { $t, i16 }
         shr_impl! { $t, i32 }
         shr_impl! { $t, i64 }
+        #[cfg(not(stage0))]
+        shr_impl! { $t, i128 }
         shr_impl! { $t, isize }
     )*)
 }
 
 shr_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
+#[cfg(not(stage0))]
+shr_impl_all! { u128 i128 }
 
 /// The `AddAssign` trait is used to specify the functionality of `+=`.
 ///
@@ -1334,6 +1367,8 @@ macro_rules! add_assign_impl {
 }
 
 add_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
+#[cfg(not(stage0))]
+add_assign_impl! { u128 i128 }
 
 /// The `SubAssign` trait is used to specify the functionality of `-=`.
 ///
@@ -1390,6 +1425,8 @@ macro_rules! sub_assign_impl {
 }
 
 sub_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
+#[cfg(not(stage0))]
+sub_assign_impl! { u128 i128 }
 
 /// The `MulAssign` trait is used to specify the functionality of `*=`.
 ///
@@ -1435,6 +1472,8 @@ macro_rules! mul_assign_impl {
 }
 
 mul_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
+#[cfg(not(stage0))]
+mul_assign_impl! { u128 i128 }
 
 /// The `DivAssign` trait is used to specify the functionality of `/=`.
 ///
@@ -1479,6 +1518,8 @@ macro_rules! div_assign_impl {
 }
 
 div_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
+#[cfg(not(stage0))]
+div_assign_impl! { u128 i128 }
 
 /// The `RemAssign` trait is used to specify the functionality of `%=`.
 ///
@@ -1523,6 +1564,8 @@ macro_rules! rem_assign_impl {
 }
 
 rem_assign_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
+#[cfg(not(stage0))]
+rem_assign_impl! { u128 i128 }
 
 /// The `BitAndAssign` trait is used to specify the functionality of `&=`.
 ///
@@ -1609,6 +1652,8 @@ macro_rules! bitand_assign_impl {
 }
 
 bitand_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
+#[cfg(not(stage0))]
+bitand_assign_impl! { u128 i128 }
 
 /// The `BitOrAssign` trait is used to specify the functionality of `|=`.
 ///
@@ -1653,6 +1698,8 @@ macro_rules! bitor_assign_impl {
 }
 
 bitor_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
+#[cfg(not(stage0))]
+bitor_assign_impl! { u128 i128 }
 
 /// The `BitXorAssign` trait is used to specify the functionality of `^=`.
 ///
@@ -1697,6 +1744,8 @@ macro_rules! bitxor_assign_impl {
 }
 
 bitxor_assign_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
+#[cfg(not(stage0))]
+bitxor_assign_impl! { u128 i128 }
 
 /// The `ShlAssign` trait is used to specify the functionality of `<<=`.
 ///
@@ -1749,17 +1798,23 @@ macro_rules! shl_assign_impl_all {
         shl_assign_impl! { $t, u16 }
         shl_assign_impl! { $t, u32 }
         shl_assign_impl! { $t, u64 }
+        #[cfg(not(stage0))]
+        shl_assign_impl! { $t, u128 }
         shl_assign_impl! { $t, usize }
 
         shl_assign_impl! { $t, i8 }
         shl_assign_impl! { $t, i16 }
         shl_assign_impl! { $t, i32 }
         shl_assign_impl! { $t, i64 }
+        #[cfg(not(stage0))]
+        shl_assign_impl! { $t, i128 }
         shl_assign_impl! { $t, isize }
     )*)
 }
 
 shl_assign_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
+#[cfg(not(stage0))]
+shl_assign_impl_all! { u128 i128 }
 
 /// The `ShrAssign` trait is used to specify the functionality of `>>=`.
 ///
@@ -1812,17 +1867,23 @@ macro_rules! shr_assign_impl_all {
         shr_assign_impl! { $t, u16 }
         shr_assign_impl! { $t, u32 }
         shr_assign_impl! { $t, u64 }
+        #[cfg(not(stage0))]
+        shr_assign_impl! { $t, u128 }
         shr_assign_impl! { $t, usize }
 
         shr_assign_impl! { $t, i8 }
         shr_assign_impl! { $t, i16 }
         shr_assign_impl! { $t, i32 }
         shr_assign_impl! { $t, i64 }
+        #[cfg(not(stage0))]
+        shr_assign_impl! { $t, i128 }
         shr_assign_impl! { $t, isize }
     )*)
 }
 
 shr_assign_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
+#[cfg(not(stage0))]
+shr_assign_impl_all! { u128 i128 }
 
 /// The `Index` trait is used to specify the functionality of indexing operations
 /// like `container[index]` when used in an immutable context.
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index e0a49e2ae45..4d4c5129e60 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -1301,6 +1301,11 @@ trait SplitIter: DoubleEndedIterator {
 
 /// An iterator over subslices separated by elements that match a predicate
 /// function.
+///
+/// This struct is created by the [`split`] method on [slices].
+///
+/// [`split`]: ../../std/primitive.slice.html#method.split
+/// [slices]: ../../std/primitive.slice.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Split<'a, T:'a, P> where P: FnMut(&T) -> bool {
     v: &'a [T],
@@ -1387,6 +1392,11 @@ impl<'a, T, P> FusedIterator for Split<'a, T, P> where P: FnMut(&T) -> bool {}
 
 /// An iterator over the subslices of the vector which are separated
 /// by elements that match `pred`.
+///
+/// This struct is created by the [`split_mut`] method on [slices].
+///
+/// [`split_mut`]: ../../std/primitive.slice.html#method.split_mut
+/// [slices]: ../../std/primitive.slice.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct SplitMut<'a, T:'a, P> where P: FnMut(&T) -> bool {
     v: &'a mut [T],
@@ -1512,6 +1522,11 @@ impl<T, I: SplitIter<Item=T>> Iterator for GenericSplitN<I> {
 
 /// An iterator over subslices separated by elements that match a predicate
 /// function, limited to a given number of splits.
+///
+/// This struct is created by the [`splitn`] method on [slices].
+///
+/// [`splitn`]: ../../std/primitive.slice.html#method.splitn
+/// [slices]: ../../std/primitive.slice.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct SplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool {
     inner: GenericSplitN<Split<'a, T, P>>
@@ -1529,6 +1544,11 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for SplitN<'a, T, P> where P: FnMut(&
 /// An iterator over subslices separated by elements that match a
 /// predicate function, limited to a given number of splits, starting
 /// from the end of the slice.
+///
+/// This struct is created by the [`rsplitn`] method on [slices].
+///
+/// [`rsplitn`]: ../../std/primitive.slice.html#method.rsplitn
+/// [slices]: ../../std/primitive.slice.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RSplitN<'a, T: 'a, P> where P: FnMut(&T) -> bool {
     inner: GenericSplitN<Split<'a, T, P>>
@@ -1545,6 +1565,11 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for RSplitN<'a, T, P> where P: FnMut(
 
 /// An iterator over subslices separated by elements that match a predicate
 /// function, limited to a given number of splits.
+///
+/// This struct is created by the [`splitn_mut`] method on [slices].
+///
+/// [`splitn_mut`]: ../../std/primitive.slice.html#method.splitn_mut
+/// [slices]: ../../std/primitive.slice.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct SplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool {
     inner: GenericSplitN<SplitMut<'a, T, P>>
@@ -1562,6 +1587,11 @@ impl<'a, T: 'a + fmt::Debug, P> fmt::Debug for SplitNMut<'a, T, P> where P: FnMu
 /// An iterator over subslices separated by elements that match a
 /// predicate function, limited to a given number of splits, starting
 /// from the end of the slice.
+///
+/// This struct is created by the [`rsplitn_mut`] method on [slices].
+///
+/// [`rsplitn_mut`]: ../../std/primitive.slice.html#method.rsplitn_mut
+/// [slices]: ../../std/primitive.slice.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RSplitNMut<'a, T: 'a, P> where P: FnMut(&T) -> bool {
     inner: GenericSplitN<SplitMut<'a, T, P>>
@@ -1607,6 +1637,11 @@ forward_iterator! { SplitNMut: T, &'a mut [T] }
 forward_iterator! { RSplitNMut: T, &'a mut [T] }
 
 /// An iterator over overlapping subslices of length `size`.
+///
+/// This struct is created by the [`windows`] method on [slices].
+///
+/// [`windows`]: ../../std/primitive.slice.html#method.windows
+/// [slices]: ../../std/primitive.slice.html
 #[derive(Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Windows<'a, T:'a> {
@@ -1704,6 +1739,11 @@ impl<'a, T> FusedIterator for Windows<'a, T> {}
 ///
 /// When the slice len is not evenly divided by the chunk size, the last slice
 /// of the iteration will be the remainder.
+///
+/// This struct is created by the [`chunks`] method on [slices].
+///
+/// [`chunks`]: ../../std/primitive.slice.html#method.chunks
+/// [slices]: ../../std/primitive.slice.html
 #[derive(Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Chunks<'a, T:'a> {
@@ -1808,6 +1848,11 @@ impl<'a, T> FusedIterator for Chunks<'a, T> {}
 /// An iterator over a slice in (non-overlapping) mutable chunks (`size`
 /// elements at a time). When the slice len is not evenly divided by the chunk
 /// size, the last slice of the iteration will be the remainder.
+///
+/// This struct is created by the [`chunks_mut`] method on [slices].
+///
+/// [`chunks_mut`]: ../../std/primitive.slice.html#method.chunks_mut
+/// [slices]: ../../std/primitive.slice.html
 #[derive(Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct ChunksMut<'a, T:'a> {
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index de418b831cc..db46bd00c8b 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -1746,13 +1746,31 @@ fn truncate_to_char_boundary(s: &str, mut max: usize) -> (bool, &str) {
 #[cold]
 fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
     const MAX_DISPLAY_LENGTH: usize = 256;
-    let (truncated, s) = truncate_to_char_boundary(s, MAX_DISPLAY_LENGTH);
+    let (truncated, s_trunc) = truncate_to_char_boundary(s, MAX_DISPLAY_LENGTH);
     let ellipsis = if truncated { "[...]" } else { "" };
 
+    // 1. out of bounds
+    if begin > s.len() || end > s.len() {
+        let oob_index = if begin > s.len() { begin } else { end };
+        panic!("byte index {} is out of bounds of `{}`{}", oob_index, s_trunc, ellipsis);
+    }
+
+    // 2. begin <= end
     assert!(begin <= end, "begin <= end ({} <= {}) when slicing `{}`{}",
-            begin, end, s, ellipsis);
-    panic!("index {} and/or {} in `{}`{} do not lie on character boundary",
-          begin, end, s, ellipsis);
+            begin, end, s_trunc, ellipsis);
+
+    // 3. character boundary
+    let index = if !s.is_char_boundary(begin) { begin } else { end };
+    // find the character
+    let mut char_start = index;
+    while !s.is_char_boundary(char_start) {
+        char_start -= 1;
+    }
+    // `char_start` must be less than len and a char boundary
+    let ch = s[char_start..].chars().next().unwrap();
+    let char_range = char_start .. char_start + ch.len_utf8();
+    panic!("byte index {} is not a char boundary; it is inside {:?} (bytes {:?}) of `{}`{}",
+           index, ch, char_range, s_trunc, ellipsis);
 }
 
 #[stable(feature = "core", since = "1.6.0")]
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 198db0e7c0a..75205794471 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -237,11 +237,16 @@ impl AtomicBool {
 
     /// Loads a value from the bool.
     ///
-    /// `load` takes an `Ordering` argument which describes the memory ordering of this operation.
+    /// `load` takes an [`Ordering`] argument which describes the memory ordering
+    /// of this operation.
     ///
     /// # Panics
     ///
-    /// Panics if `order` is `Release` or `AcqRel`.
+    /// Panics if `order` is [`Release`] or [`AcqRel`].
+    ///
+    /// [`Ordering`]: enum.Ordering.html
+    /// [`Release`]: enum.Ordering.html#variant.Release
+    /// [`AcqRel`]: enum.Ordering.html#variant.Release
     ///
     /// # Examples
     ///
@@ -260,7 +265,10 @@ impl AtomicBool {
 
     /// Stores a value into the bool.
     ///
-    /// `store` takes an `Ordering` argument which describes the memory ordering of this operation.
+    /// `store` takes an [`Ordering`] argument which describes the memory ordering
+    /// of this operation.
+    ///
+    /// [`Ordering`]: enum.Ordering.html
     ///
     /// # Examples
     ///
@@ -286,7 +294,10 @@ impl AtomicBool {
 
     /// Stores a value into the bool, returning the old value.
     ///
-    /// `swap` takes an `Ordering` argument which describes the memory ordering of this operation.
+    /// `swap` takes an [`Ordering`] argument which describes the memory ordering
+    /// of this operation.
+    ///
+    /// [`Ordering`]: enum.Ordering.html
     ///
     /// # Examples
     ///
@@ -309,8 +320,10 @@ impl AtomicBool {
     /// The return value is always the previous value. If it is equal to `current`, then the value
     /// was updated.
     ///
-    /// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of
-    /// this operation.
+    /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
+    /// ordering of this operation.
+    ///
+    /// [`Ordering`]: enum.Ordering.html
     ///
     /// # Examples
     ///
@@ -339,10 +352,15 @@ impl AtomicBool {
     /// The return value is a result indicating whether the new value was written and containing
     /// the previous value. On success this value is guaranteed to be equal to `current`.
     ///
-    /// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of this
-    /// operation. The first describes the required ordering if the operation succeeds while the
-    /// second describes the required ordering when the operation fails. The failure ordering can't
-    /// be `Release` or `AcqRel` and must be equivalent or weaker than the success ordering.
+    /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
+    /// ordering of this operation. The first describes the required ordering if the
+    /// operation succeeds while the second describes the required ordering when the
+    /// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and must
+    /// be equivalent or weaker than the success ordering.
+    ///
+    /// [`Ordering`]: enum.Ordering.html
+    /// [`Release`]: enum.Ordering.html#variant.Release
+    /// [`AcqRel`]: enum.Ordering.html#variant.Release
     ///
     /// # Examples
     ///
@@ -387,11 +405,15 @@ impl AtomicBool {
     /// return value is a result indicating whether the new value was written and containing the
     /// previous value.
     ///
-    /// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory
+    /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
     /// ordering of this operation. The first describes the required ordering if the operation
     /// succeeds while the second describes the required ordering when the operation fails. The
-    /// failure ordering can't be `Release` or `AcqRel` and must be equivalent or weaker than the
-    /// success ordering.
+    /// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or
+    /// weaker than the success ordering.
+    ///
+    /// [`Ordering`]: enum.Ordering.html
+    /// [`Release`]: enum.Ordering.html#variant.Release
+    /// [`AcqRel`]: enum.Ordering.html#variant.Release
     ///
     /// # Examples
     ///
@@ -619,11 +641,16 @@ impl<T> AtomicPtr<T> {
 
     /// Loads a value from the pointer.
     ///
-    /// `load` takes an `Ordering` argument which describes the memory ordering of this operation.
+    /// `load` takes an [`Ordering`] argument which describes the memory ordering
+    /// of this operation.
     ///
     /// # Panics
     ///
-    /// Panics if `order` is `Release` or `AcqRel`.
+    /// Panics if `order` is [`Release`] or [`AcqRel`].
+    ///
+    /// [`Ordering`]: enum.Ordering.html
+    /// [`Release`]: enum.Ordering.html#variant.Release
+    /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
     ///
     /// # Examples
     ///
@@ -643,7 +670,10 @@ impl<T> AtomicPtr<T> {
 
     /// Stores a value into the pointer.
     ///
-    /// `store` takes an `Ordering` argument which describes the memory ordering of this operation.
+    /// `store` takes an [`Ordering`] argument which describes the memory ordering
+    /// of this operation.
+    ///
+    /// [`Ordering`]: enum.Ordering.html
     ///
     /// # Examples
     ///
@@ -671,7 +701,10 @@ impl<T> AtomicPtr<T> {
 
     /// Stores a value into the pointer, returning the old value.
     ///
-    /// `swap` takes an `Ordering` argument which describes the memory ordering of this operation.
+    /// `swap` takes an [`Ordering`] argument which describes the memory ordering
+    /// of this operation.
+    ///
+    /// [`Ordering`]: enum.Ordering.html
     ///
     /// # Examples
     ///
@@ -696,8 +729,10 @@ impl<T> AtomicPtr<T> {
     /// The return value is always the previous value. If it is equal to `current`, then the value
     /// was updated.
     ///
-    /// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of
-    /// this operation.
+    /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
+    /// ordering of this operation.
+    ///
+    /// [`Ordering`]: enum.Ordering.html
     ///
     /// # Examples
     ///
@@ -726,10 +761,15 @@ impl<T> AtomicPtr<T> {
     /// The return value is a result indicating whether the new value was written and containing
     /// the previous value. On success this value is guaranteed to be equal to `current`.
     ///
-    /// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of this
-    /// operation. The first describes the required ordering if the operation succeeds while the
-    /// second describes the required ordering when the operation fails. The failure ordering can't
-    /// be `Release` or `AcqRel` and must be equivalent or weaker than the success ordering.
+    /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
+    /// ordering of this operation. The first describes the required ordering if
+    /// the operation succeeds while the second describes the required ordering when
+    /// the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`]
+    /// and must be equivalent or weaker than the success ordering.
+    ///
+    /// [`Ordering`]: enum.Ordering.html
+    /// [`Release`]: enum.Ordering.html#variant.Release
+    /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
     ///
     /// # Examples
     ///
@@ -768,16 +808,21 @@ impl<T> AtomicPtr<T> {
 
     /// Stores a value into the pointer if the current value is the same as the `current` value.
     ///
-    /// Unlike `compare_exchange`, this function is allowed to spuriously fail even when the
+    /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even when the
     /// comparison succeeds, which can result in more efficient code on some platforms. The
     /// return value is a result indicating whether the new value was written and containing the
     /// previous value.
     ///
-    /// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory
+    /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
     /// ordering of this operation. The first describes the required ordering if the operation
     /// succeeds while the second describes the required ordering when the operation fails. The
-    /// failure ordering can't be `Release` or `AcqRel` and must be equivalent or weaker than the
-    /// success ordering.
+    /// failure ordering can't be [`Release`] or [`AcqRel`] and must be equivalent or
+    /// weaker than the success ordering.
+    ///
+    /// [`compare_exchange`]: #method.compare_exchange
+    /// [`Ordering`]: enum.Ordering.html
+    /// [`Release`]: enum.Ordering.html#variant.Release
+    /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
     ///
     /// # Examples
     ///
@@ -913,12 +958,16 @@ macro_rules! atomic_int {
 
             /// Loads a value from the atomic integer.
             ///
-            /// `load` takes an `Ordering` argument which describes the memory ordering of this
+            /// `load` takes an [`Ordering`] argument which describes the memory ordering of this
             /// operation.
             ///
             /// # Panics
             ///
-            /// Panics if `order` is `Release` or `AcqRel`.
+            /// Panics if `order` is [`Release`] or [`AcqRel`].
+            ///
+            /// [`Ordering`]: enum.Ordering.html
+            /// [`Release`]: enum.Ordering.html#variant.Release
+            /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
             ///
             /// # Examples
             ///
@@ -937,9 +986,11 @@ macro_rules! atomic_int {
 
             /// Stores a value into the atomic integer.
             ///
-            /// `store` takes an `Ordering` argument which describes the memory ordering of this
+            /// `store` takes an [`Ordering`] argument which describes the memory ordering of this
             /// operation.
             ///
+            /// [`Ordering`]: enum.Ordering.html
+            ///
             /// # Examples
             ///
             /// ```
@@ -962,9 +1013,11 @@ macro_rules! atomic_int {
 
             /// Stores a value into the atomic integer, returning the old value.
             ///
-            /// `swap` takes an `Ordering` argument which describes the memory ordering of this
+            /// `swap` takes an [`Ordering`] argument which describes the memory ordering of this
             /// operation.
             ///
+            /// [`Ordering`]: enum.Ordering.html
+            ///
             /// # Examples
             ///
             /// ```
@@ -986,9 +1039,11 @@ macro_rules! atomic_int {
             /// The return value is always the previous value. If it is equal to `current`, then the
             /// value was updated.
             ///
-            /// `compare_and_swap` also takes an `Ordering` argument which describes the memory
+            /// `compare_and_swap` also takes an [`Ordering`] argument which describes the memory
             /// ordering of this operation.
             ///
+            /// [`Ordering`]: enum.Ordering.html
+            ///
             /// # Examples
             ///
             /// ```
@@ -1024,11 +1079,15 @@ macro_rules! atomic_int {
             /// containing the previous value. On success this value is guaranteed to be equal to
             /// `current`.
             ///
-            /// `compare_exchange` takes two `Ordering` arguments to describe the memory ordering of
-            /// this operation. The first describes the required ordering if the operation succeeds
-            /// while the second describes the required ordering when the operation fails. The
-            /// failure ordering can't be `Release` or `AcqRel` and must be equivalent or weaker
-            /// than the success ordering.
+            /// `compare_exchange` takes two [`Ordering`] arguments to describe the memory
+            /// ordering of this operation. The first describes the required ordering if
+            /// the operation succeeds while the second describes the required ordering when
+            /// the operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
+            /// must be equivalent or weaker than the success ordering.
+            ///
+            /// [`Ordering`]: enum.Ordering.html
+            /// [`Release`]: enum.Ordering.html#variant.Release
+            /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
             ///
             /// # Examples
             ///
@@ -1062,16 +1121,21 @@ macro_rules! atomic_int {
             /// Stores a value into the atomic integer if the current value is the same as the
             /// `current` value.
             ///
-            /// Unlike `compare_exchange`, this function is allowed to spuriously fail even when the
-            /// comparison succeeds, which can result in more efficient code on some platforms. The
-            /// return value is a result indicating whether the new value was written and containing
-            /// the previous value.
+            /// Unlike [`compare_exchange`], this function is allowed to spuriously fail even
+            /// when the comparison succeeds, which can result in more efficient code on some
+            /// platforms. The return value is a result indicating whether the new value was
+            /// written and containing the previous value.
             ///
-            /// `compare_exchange_weak` takes two `Ordering` arguments to describe the memory
+            /// `compare_exchange_weak` takes two [`Ordering`] arguments to describe the memory
             /// ordering of this operation. The first describes the required ordering if the
             /// operation succeeds while the second describes the required ordering when the
-            /// operation fails. The failure ordering can't be `Release` or `AcqRel` and must be
-            /// equivalent or weaker than the success ordering.
+            /// operation fails. The failure ordering can't be [`Release`] or [`AcqRel`] and
+            /// must be equivalent or weaker than the success ordering.
+            ///
+            /// [`compare_exchange`]: #method.compare_exchange
+            /// [`Ordering`]: enum.Ordering.html
+            /// [`Release`]: enum.Ordering.html#variant.Release
+            /// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
             ///
             /// # Examples
             ///
@@ -1431,24 +1495,31 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
 
 /// An atomic fence.
 ///
-/// A fence 'A' which has `Release` ordering semantics, synchronizes with a
-/// fence 'B' with (at least) `Acquire` semantics, if and only if there exists
+/// A fence 'A' which has [`Release`] ordering semantics, synchronizes with a
+/// fence 'B' with (at least) [`Acquire`] semantics, if and only if there exists
 /// atomic operations X and Y, both operating on some atomic object 'M' such
 /// that A is sequenced before X, Y is synchronized before B and Y observes
 /// the change to M. This provides a happens-before dependence between A and B.
 ///
-/// Atomic operations with `Release` or `Acquire` semantics can also synchronize
+/// Atomic operations with [`Release`] or [`Acquire`] semantics can also synchronize
 /// with a fence.
 ///
-/// A fence which has `SeqCst` ordering, in addition to having both `Acquire`
-/// and `Release` semantics, participates in the global program order of the
-/// other `SeqCst` operations and/or fences.
+/// A fence which has [`SeqCst`] ordering, in addition to having both [`Acquire`]
+/// and [`Release`] semantics, participates in the global program order of the
+/// other [`SeqCst`] operations and/or fences.
 ///
-/// Accepts `Acquire`, `Release`, `AcqRel` and `SeqCst` orderings.
+/// Accepts [`Acquire`], [`Release`], [`AcqRel`] and [`SeqCst`] orderings.
 ///
 /// # Panics
 ///
-/// Panics if `order` is `Relaxed`.
+/// Panics if `order` is [`Relaxed`].
+///
+/// [`Ordering`]: enum.Ordering.html
+/// [`Acquire`]: enum.Ordering.html#variant.Acquire
+/// [`SeqCst`]: enum.Ordering.html#variant.SeqCst
+/// [`Release`]: enum.Ordering.html#variant.Release
+/// [`AcqRel`]: enum.Ordering.html#variant.AcqRel
+/// [`Relaxed`]: enum.Ordering.html#variant.Relaxed
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn fence(order: Ordering) {
diff --git a/src/liblibc b/src/liblibc
-Subproject e49e9bb7c3d9c7f2fd893f0ee0db81617b8db21
+Subproject 98589876259e19f13eab81b033ced95bbb6deca
diff --git a/src/libpanic_abort/Cargo.toml b/src/libpanic_abort/Cargo.toml
index d90d2864813..e0eac41f49e 100644
--- a/src/libpanic_abort/Cargo.toml
+++ b/src/libpanic_abort/Cargo.toml
@@ -7,6 +7,7 @@ version = "0.0.0"
 path = "lib.rs"
 test = false
 bench = false
+doc = false
 
 [dependencies]
 core = { path = "../libcore" }
diff --git a/src/libpanic_unwind/Cargo.toml b/src/libpanic_unwind/Cargo.toml
index 90c16fff6f1..a978ea16e9e 100644
--- a/src/libpanic_unwind/Cargo.toml
+++ b/src/libpanic_unwind/Cargo.toml
@@ -7,6 +7,7 @@ version = "0.0.0"
 path = "lib.rs"
 test = false
 bench = false
+doc = false
 
 [dependencies]
 alloc = { path = "../liballoc" }
diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs
index 73264fab69c..e8b3a9a42c2 100644
--- a/src/libpanic_unwind/gcc.rs
+++ b/src/libpanic_unwind/gcc.rs
@@ -133,6 +133,9 @@ const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 / X3, X4
 #[cfg(target_arch = "s390x")]
 const UNWIND_DATA_REG: (i32, i32) = (6, 7); // R6, R7
 
+#[cfg(target_arch = "sparc64")]
+const UNWIND_DATA_REG: (i32, i32) = (24, 25); // I0, I1
+
 // The following code is based on GCC's C and C++ personality routines.  For reference, see:
 // https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
 // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
diff --git a/src/librand/Cargo.toml b/src/librand/Cargo.toml
index 86b061db054..eda5f217565 100644
--- a/src/librand/Cargo.toml
+++ b/src/librand/Cargo.toml
@@ -6,6 +6,7 @@ version = "0.0.0"
 [lib]
 name = "rand"
 path = "lib.rs"
+doc = false
 
 [dependencies]
 core = { path = "../libcore" }
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index 578ef68b003..51494885e73 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -20,6 +20,7 @@ rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_llvm = { path = "../librustc_llvm" }
+rustc_i128 = { path = "../librustc_i128" }
 serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 3e7cc0b1e3e..7b6ed56b779 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -41,6 +41,7 @@ use syntax::ast;
 use errors::DiagnosticBuilder;
 use syntax_pos::{self, Span, DUMMY_SP};
 use util::nodemap::{FxHashMap, FxHashSet, NodeMap};
+use arena::DroplessArena;
 
 use self::combine::CombineFields;
 use self::higher_ranked::HrMatchResult;
@@ -374,7 +375,7 @@ impl fmt::Display for FixupError {
 /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(InferCtxt<'b, 'gcx, 'tcx>).
 pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     global_tcx: TyCtxt<'a, 'gcx, 'gcx>,
-    arenas: ty::CtxtArenas<'tcx>,
+    arena: DroplessArena,
     tables: Option<RefCell<ty::Tables<'tcx>>>,
     param_env: Option<ty::ParameterEnvironment<'gcx>>,
     projection_mode: Reveal,
@@ -388,7 +389,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
                       -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
         InferCtxtBuilder {
             global_tcx: self,
-            arenas: ty::CtxtArenas::new(),
+            arena: DroplessArena::new(),
             tables: tables.map(RefCell::new),
             param_env: param_env,
             projection_mode: projection_mode,
@@ -426,7 +427,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
     {
         let InferCtxtBuilder {
             global_tcx,
-            ref arenas,
+            ref arena,
             ref tables,
             ref mut param_env,
             projection_mode,
@@ -439,7 +440,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
         let param_env = param_env.take().unwrap_or_else(|| {
             global_tcx.empty_parameter_environment()
         });
-        global_tcx.enter_local(arenas, |tcx| f(InferCtxt {
+        global_tcx.enter_local(arena, |tcx| f(InferCtxt {
             tcx: tcx,
             tables: tables,
             projection_cache: RefCell::new(traits::ProjectionCache::new()),
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index efe855f0a39..73ec9d8f8c8 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -62,6 +62,9 @@ extern crate rustc_errors as errors;
 
 extern crate serialize as rustc_serialize; // used by deriving
 
+// SNAP:
+extern crate rustc_i128;
+
 #[cfg(test)]
 extern crate test;
 
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 76adee4e00c..00e21410c70 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -445,6 +445,11 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
             && !has_allow_dead_code_or_lang_attr(&variant.attrs)
     }
 
+    fn should_warn_about_foreign_item(&mut self, fi: &hir::ForeignItem) -> bool {
+        !self.symbol_is_live(fi.id, None)
+            && !has_allow_dead_code_or_lang_attr(&fi.attrs)
+    }
+
     // id := node id of an item's definition.
     // ctor_id := `Some` if the item is a struct_ctor (tuple struct),
     //            `None` otherwise.
@@ -534,7 +539,7 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> {
     }
 
     fn visit_foreign_item(&mut self, fi: &'tcx hir::ForeignItem) {
-        if !self.symbol_is_live(fi.id, None) {
+        if self.should_warn_about_foreign_item(fi) {
             self.warn_dead_code(fi.id, fi.span, fi.name, fi.node.descriptive_variant());
         }
         intravisit::walk_foreign_item(self, fi);
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index 4cae5b370eb..cd7859af8ee 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -260,11 +260,13 @@ language_item_table! {
     I16ImplItem,                     "i16",                     i16_impl;
     I32ImplItem,                     "i32",                     i32_impl;
     I64ImplItem,                     "i64",                     i64_impl;
+    I128ImplItem,                     "i128",                   i128_impl;
     IsizeImplItem,                   "isize",                   isize_impl;
     U8ImplItem,                      "u8",                      u8_impl;
     U16ImplItem,                     "u16",                     u16_impl;
     U32ImplItem,                     "u32",                     u32_impl;
     U64ImplItem,                     "u64",                     u64_impl;
+    U128ImplItem,                    "u128",                    u128_impl;
     UsizeImplItem,                   "usize",                   usize_impl;
     F32ImplItem,                     "f32",                     f32_impl;
     F64ImplItem,                     "f64",                     f64_impl;
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index cb1fc15c5f6..f58d7dcb45f 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -39,7 +39,7 @@ use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
 use util::nodemap::{FxHashMap, FxHashSet};
 use rustc_data_structures::accumulate_vec::AccumulateVec;
 
-use arena::TypedArena;
+use arena::{TypedArena, DroplessArena};
 use std::borrow::Borrow;
 use std::cell::{Cell, RefCell};
 use std::hash::{Hash, Hasher};
@@ -55,16 +55,9 @@ use syntax::symbol::{Symbol, keywords};
 use hir;
 
 /// Internal storage
-pub struct CtxtArenas<'tcx> {
+pub struct GlobalArenas<'tcx> {
     // internings
-    type_: TypedArena<TyS<'tcx>>,
-    type_list: TypedArena<Ty<'tcx>>,
-    substs: TypedArena<Kind<'tcx>>,
-    bare_fn: TypedArena<BareFnTy<'tcx>>,
-    region: TypedArena<Region>,
-    stability: TypedArena<attr::Stability>,
     layout: TypedArena<Layout>,
-    existential_predicates: TypedArena<ExistentialPredicate<'tcx>>,
 
     // references
     generics: TypedArena<ty::Generics<'tcx>>,
@@ -73,29 +66,21 @@ pub struct CtxtArenas<'tcx> {
     mir: TypedArena<RefCell<Mir<'tcx>>>,
 }
 
-impl<'tcx> CtxtArenas<'tcx> {
-    pub fn new() -> CtxtArenas<'tcx> {
-        CtxtArenas {
-            type_: TypedArena::new(),
-            type_list: TypedArena::new(),
-            substs: TypedArena::new(),
-            bare_fn: TypedArena::new(),
-            region: TypedArena::new(),
-            stability: TypedArena::new(),
+impl<'tcx> GlobalArenas<'tcx> {
+    pub fn new() -> GlobalArenas<'tcx> {
+        GlobalArenas {
             layout: TypedArena::new(),
-            existential_predicates: TypedArena::new(),
-
             generics: TypedArena::new(),
             trait_def: TypedArena::new(),
             adt_def: TypedArena::new(),
-            mir: TypedArena::new()
+            mir: TypedArena::new(),
         }
     }
 }
 
 pub struct CtxtInterners<'tcx> {
-    /// The arenas that types etc are allocated from.
-    arenas: &'tcx CtxtArenas<'tcx>,
+    /// The arena that types, regions, etc are allocated from
+    arena: &'tcx DroplessArena,
 
     /// Specifically use a speedy hash algorithm for these hash sets,
     /// they're accessed quite often.
@@ -104,22 +89,18 @@ pub struct CtxtInterners<'tcx> {
     substs: RefCell<FxHashSet<Interned<'tcx, Substs<'tcx>>>>,
     bare_fn: RefCell<FxHashSet<Interned<'tcx, BareFnTy<'tcx>>>>,
     region: RefCell<FxHashSet<Interned<'tcx, Region>>>,
-    stability: RefCell<FxHashSet<&'tcx attr::Stability>>,
-    layout: RefCell<FxHashSet<&'tcx Layout>>,
     existential_predicates: RefCell<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
 }
 
 impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
-    fn new(arenas: &'tcx CtxtArenas<'tcx>) -> CtxtInterners<'tcx> {
+    fn new(arena: &'tcx DroplessArena) -> CtxtInterners<'tcx> {
         CtxtInterners {
-            arenas: arenas,
+            arena: arena,
             type_: RefCell::new(FxHashSet()),
             type_list: RefCell::new(FxHashSet()),
             substs: RefCell::new(FxHashSet()),
             bare_fn: RefCell::new(FxHashSet()),
             region: RefCell::new(FxHashSet()),
-            stability: RefCell::new(FxHashSet()),
-            layout: RefCell::new(FxHashSet()),
             existential_predicates: RefCell::new(FxHashSet()),
         }
     }
@@ -158,7 +139,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
                     let ty_struct: TyS<'gcx> = unsafe {
                         mem::transmute(ty_struct)
                     };
-                    let ty: Ty<'gcx> = interner.arenas.type_.alloc(ty_struct);
+                    let ty: Ty<'gcx> = interner.arena.alloc(ty_struct);
                     global_interner.unwrap().insert(Interned(ty));
                     return ty;
                 }
@@ -174,7 +155,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
             }
 
             // Don't be &mut TyS.
-            let ty: Ty<'tcx> = self.arenas.type_.alloc(ty_struct);
+            let ty: Ty<'tcx> = self.arena.alloc(ty_struct);
             interner.insert(Interned(ty));
             ty
         };
@@ -194,11 +175,13 @@ pub struct CommonTypes<'tcx> {
     pub i16: Ty<'tcx>,
     pub i32: Ty<'tcx>,
     pub i64: Ty<'tcx>,
+    pub i128: Ty<'tcx>,
     pub usize: Ty<'tcx>,
     pub u8: Ty<'tcx>,
     pub u16: Ty<'tcx>,
     pub u32: Ty<'tcx>,
     pub u64: Ty<'tcx>,
+    pub u128: Ty<'tcx>,
     pub f32: Ty<'tcx>,
     pub f64: Ty<'tcx>,
     pub never: Ty<'tcx>,
@@ -359,11 +342,13 @@ impl<'tcx> CommonTypes<'tcx> {
             i16: mk(TyInt(ast::IntTy::I16)),
             i32: mk(TyInt(ast::IntTy::I32)),
             i64: mk(TyInt(ast::IntTy::I64)),
+            i128: mk(TyInt(ast::IntTy::I128)),
             usize: mk(TyUint(ast::UintTy::Us)),
             u8: mk(TyUint(ast::UintTy::U8)),
             u16: mk(TyUint(ast::UintTy::U16)),
             u32: mk(TyUint(ast::UintTy::U32)),
             u64: mk(TyUint(ast::UintTy::U64)),
+            u128: mk(TyUint(ast::UintTy::U128)),
             f32: mk(TyFloat(ast::FloatTy::F32)),
             f64: mk(TyFloat(ast::FloatTy::F64)),
         }
@@ -387,6 +372,7 @@ impl<'a, 'gcx, 'tcx> Deref for TyCtxt<'a, 'gcx, 'tcx> {
 }
 
 pub struct GlobalCtxt<'tcx> {
+    global_arenas: &'tcx GlobalArenas<'tcx>,
     global_interners: CtxtInterners<'tcx>,
 
     pub specializes_cache: RefCell<traits::SpecializesCache>,
@@ -582,6 +568,10 @@ pub struct GlobalCtxt<'tcx> {
     /// Map from function to the `#[derive]` mode that it's defining. Only used
     /// by `proc-macro` crates.
     pub derive_macros: RefCell<NodeMap<Symbol>>,
+
+    stability_interner: RefCell<FxHashSet<&'tcx attr::Stability>>,
+
+    layout_interner: RefCell<FxHashSet<&'tcx Layout>>,
 }
 
 impl<'tcx> GlobalCtxt<'tcx> {
@@ -645,15 +635,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
     pub fn alloc_generics(self, generics: ty::Generics<'gcx>)
                           -> &'gcx ty::Generics<'gcx> {
-        self.global_interners.arenas.generics.alloc(generics)
+        self.global_arenas.generics.alloc(generics)
     }
 
     pub fn alloc_mir(self, mir: Mir<'gcx>) -> &'gcx RefCell<Mir<'gcx>> {
-        self.global_interners.arenas.mir.alloc(RefCell::new(mir))
+        self.global_arenas.mir.alloc(RefCell::new(mir))
     }
 
     pub fn alloc_trait_def(self, def: ty::TraitDef) -> &'gcx ty::TraitDef {
-        self.global_interners.arenas.trait_def.alloc(def)
+        self.global_arenas.trait_def.alloc(def)
     }
 
     pub fn alloc_adt_def(self,
@@ -662,32 +652,28 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                          variants: Vec<ty::VariantDef>)
                          -> &'gcx ty::AdtDef {
         let def = ty::AdtDef::new(self, did, kind, variants);
-        self.global_interners.arenas.adt_def.alloc(def)
+        self.global_arenas.adt_def.alloc(def)
     }
 
     pub fn intern_stability(self, stab: attr::Stability) -> &'gcx attr::Stability {
-        if let Some(st) = self.global_interners.stability.borrow().get(&stab) {
+        if let Some(st) = self.stability_interner.borrow().get(&stab) {
             return st;
         }
 
-        let interned = self.global_interners.arenas.stability.alloc(stab);
-        if let Some(prev) = self.global_interners.stability
-                                .borrow_mut()
-                                .replace(interned) {
+        let interned = self.global_interners.arena.alloc(stab);
+        if let Some(prev) = self.stability_interner.borrow_mut().replace(interned) {
             bug!("Tried to overwrite interned Stability: {:?}", prev)
         }
         interned
     }
 
     pub fn intern_layout(self, layout: Layout) -> &'gcx Layout {
-        if let Some(layout) = self.global_interners.layout.borrow().get(&layout) {
+        if let Some(layout) = self.layout_interner.borrow().get(&layout) {
             return layout;
         }
 
-        let interned = self.global_interners.arenas.layout.alloc(layout);
-        if let Some(prev) = self.global_interners.layout
-                                .borrow_mut()
-                                .replace(interned) {
+        let interned = self.global_arenas.layout.alloc(layout);
+        if let Some(prev) = self.layout_interner.borrow_mut().replace(interned) {
             bug!("Tried to overwrite interned Layout: {:?}", prev)
         }
         interned
@@ -724,24 +710,26 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     /// value (types, substs, etc.) can only be used while `ty::tls` has a valid
     /// reference to the context, to allow formatting values that need it.
     pub fn create_and_enter<F, R>(s: &'tcx Session,
-                                  arenas: &'tcx CtxtArenas<'tcx>,
+                                  arenas: &'tcx GlobalArenas<'tcx>,
+                                  arena: &'tcx DroplessArena,
                                   resolutions: ty::Resolutions,
                                   named_region_map: resolve_lifetime::NamedRegionMap,
                                   map: ast_map::Map<'tcx>,
                                   region_maps: RegionMaps,
                                   lang_items: middle::lang_items::LanguageItems,
                                   stability: stability::Index<'tcx>,
-                                 crate_name: &str,
+                                  crate_name: &str,
                                   f: F) -> R
                                   where F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'tcx>) -> R
     {
         let data_layout = TargetDataLayout::parse(s);
-        let interners = CtxtInterners::new(arenas);
+        let interners = CtxtInterners::new(arena);
         let common_types = CommonTypes::new(&interners);
         let dep_graph = map.dep_graph.clone();
         let fulfilled_predicates = traits::GlobalFulfilledPredicates::new(dep_graph.clone());
         tls::enter_global(GlobalCtxt {
             specializes_cache: RefCell::new(traits::SpecializesCache::new()),
+            global_arenas: arenas,
             global_interners: interners,
             dep_graph: dep_graph.clone(),
             types: common_types,
@@ -790,18 +778,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             crate_name: Symbol::intern(crate_name),
             data_layout: data_layout,
             layout_cache: RefCell::new(FxHashMap()),
+            layout_interner: RefCell::new(FxHashSet()),
             layout_depth: Cell::new(0),
             derive_macros: RefCell::new(NodeMap()),
+            stability_interner: RefCell::new(FxHashSet()),
        }, f)
     }
 }
 
 impl<'gcx: 'tcx, 'tcx> GlobalCtxt<'gcx> {
-    /// Call the closure with a local `TyCtxt` using the given arenas.
-    pub fn enter_local<F, R>(&self, arenas: &'tcx CtxtArenas<'tcx>, f: F) -> R
+    /// Call the closure with a local `TyCtxt` using the given arena.
+    pub fn enter_local<F, R>(&self, arena: &'tcx DroplessArena, f: F) -> R
         where F: for<'a> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R
     {
-        let interners = CtxtInterners::new(arenas);
+        let interners = CtxtInterners::new(arena);
         tls::enter(self, &interners, f)
     }
 }
@@ -831,10 +821,8 @@ pub trait Lift<'tcx> {
 impl<'a, 'tcx> Lift<'tcx> for Ty<'a> {
     type Lifted = Ty<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Ty<'tcx>> {
-        if let Some(&Interned(ty)) = tcx.interners.type_.borrow().get(&self.sty) {
-            if *self as *const _ == ty as *const _ {
-                return Some(ty);
-            }
+        if tcx.interners.arena.in_arena(*self as *const _) {
+            return Some(unsafe { mem::transmute(*self) });
         }
         // Also try in the global tcx if we're not that.
         if !tcx.is_global() {
@@ -851,10 +839,8 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> {
         if self.len() == 0 {
             return Some(Slice::empty());
         }
-        if let Some(&Interned(substs)) = tcx.interners.substs.borrow().get(&self[..]) {
-            if *self as *const _ == substs as *const _ {
-                return Some(substs);
-            }
+        if tcx.interners.arena.in_arena(&self[..] as *const _) {
+            return Some(unsafe { mem::transmute(*self) });
         }
         // Also try in the global tcx if we're not that.
         if !tcx.is_global() {
@@ -868,10 +854,8 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> {
 impl<'a, 'tcx> Lift<'tcx> for &'a Region {
     type Lifted = &'tcx Region;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Region> {
-        if let Some(&Interned(region)) = tcx.interners.region.borrow().get(*self) {
-            if *self as *const _ == region as *const _ {
-                return Some(region);
-            }
+        if tcx.interners.arena.in_arena(*self as *const _) {
+            return Some(unsafe { mem::transmute(*self) });
         }
         // Also try in the global tcx if we're not that.
         if !tcx.is_global() {
@@ -889,10 +873,8 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice<Ty<'a>> {
         if self.len() == 0 {
             return Some(Slice::empty());
         }
-        if let Some(&Interned(list)) = tcx.interners.type_list.borrow().get(&self[..]) {
-            if *self as *const _ == list as *const _ {
-                return Some(list);
-            }
+        if tcx.interners.arena.in_arena(*self as *const _) {
+            return Some(unsafe { mem::transmute(*self) });
         }
         // Also try in the global tcx if we're not that.
         if !tcx.is_global() {
@@ -910,10 +892,8 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice<ExistentialPredicate<'a>> {
         if self.is_empty() {
             return Some(Slice::empty());
         }
-        if let Some(&Interned(eps)) = tcx.interners.existential_predicates.borrow().get(&self[..]) {
-            if *self as *const _ == eps as *const _ {
-                return Some(eps);
-            }
+        if tcx.interners.arena.in_arena(*self as *const _) {
+            return Some(unsafe { mem::transmute(*self) });
         }
         // Also try in the global tcx if we're not that.
         if !tcx.is_global() {
@@ -928,10 +908,8 @@ impl<'a, 'tcx> Lift<'tcx> for &'a BareFnTy<'a> {
     type Lifted = &'tcx BareFnTy<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>)
                              -> Option<&'tcx BareFnTy<'tcx>> {
-        if let Some(&Interned(fty)) = tcx.interners.bare_fn.borrow().get(*self) {
-            if *self as *const _ == fty as *const _ {
-                return Some(fty);
-            }
+        if tcx.interners.arena.in_arena(*self as *const _) {
+            return Some(unsafe { mem::transmute(*self) });
         }
         // Also try in the global tcx if we're not that.
         if !tcx.is_global() {
@@ -1097,8 +1075,8 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
         println!("Substs interner: #{}", self.interners.substs.borrow().len());
         println!("BareFnTy interner: #{}", self.interners.bare_fn.borrow().len());
         println!("Region interner: #{}", self.interners.region.borrow().len());
-        println!("Stability interner: #{}", self.interners.stability.borrow().len());
-        println!("Layout interner: #{}", self.interners.layout.borrow().len());
+        println!("Stability interner: #{}", self.stability_interner.borrow().len());
+        println!("Layout interner: #{}", self.layout_interner.borrow().len());
     }
 }
 
@@ -1201,8 +1179,7 @@ macro_rules! intern_method {
                         let v = unsafe {
                             mem::transmute(v)
                         };
-                        let i = ($alloc_to_ret)(self.global_interners.arenas.$name
-                                                    .$alloc_method(v));
+                        let i = ($alloc_to_ret)(self.global_interners.arena.$alloc_method(v));
                         self.global_interners.$name.borrow_mut().insert(Interned(i));
                         return i;
                     }
@@ -1216,7 +1193,7 @@ macro_rules! intern_method {
                     }
                 }
 
-                let i = ($alloc_to_ret)(self.interners.arenas.$name.$alloc_method(v));
+                let i = ($alloc_to_ret)(self.interners.arena.$alloc_method(v));
                 self.interners.$name.borrow_mut().insert(Interned(i));
                 i
             }
@@ -1304,6 +1281,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             ast::IntTy::I16  => self.types.i16,
             ast::IntTy::I32  => self.types.i32,
             ast::IntTy::I64  => self.types.i64,
+            ast::IntTy::I128  => self.types.i128,
         }
     }
 
@@ -1314,6 +1292,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
             ast::UintTy::U16  => self.types.u16,
             ast::UintTy::U32  => self.types.u32,
             ast::UintTy::U64  => self.types.u64,
+            ast::UintTy::U128  => self.types.u128,
         }
     }
 
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index ebac30c8e50..ff95554dbbf 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -20,6 +20,8 @@ use ty::{self, Ty, TyCtxt, TypeFoldable};
 use syntax::ast::{FloatTy, IntTy, UintTy};
 use syntax::attr;
 use syntax_pos::DUMMY_SP;
+use rustc_i128::u128;
+use rustc_const_math::ConstInt;
 
 use std::cmp;
 use std::fmt;
@@ -35,6 +37,7 @@ pub struct TargetDataLayout {
     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,
@@ -55,6 +58,7 @@ impl Default for TargetDataLayout {
             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),
@@ -99,6 +103,7 @@ impl TargetDataLayout {
         };
 
         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,
@@ -111,19 +116,28 @@ impl TargetDataLayout {
                     dl.pointer_align = align(a, p);
                 }
                 &[s, ref a..] if s.starts_with("i") => {
-                    let ty_align = match s[1..].parse::<u64>() {
-                        Ok(1) => &mut dl.i8_align,
-                        Ok(8) => &mut dl.i8_align,
-                        Ok(16) => &mut dl.i16_align,
-                        Ok(32) => &mut dl.i32_align,
-                        Ok(64) => &mut dl.i64_align,
-                        Ok(_) => continue,
+                    let bits = match s[1..].parse::<u64>() {
+                        Ok(bits) => bits,
                         Err(_) => {
                             size(&s[1..], "i"); // For the user error.
                             continue;
                         }
                     };
-                    *ty_align = align(a, s);
+                    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");
@@ -325,7 +339,8 @@ pub enum Integer {
     I8,
     I16,
     I32,
-    I64
+    I64,
+    I128,
 }
 
 impl Integer {
@@ -336,6 +351,7 @@ impl Integer {
             I16 => Size::from_bytes(2),
             I32 => Size::from_bytes(4),
             I64  => Size::from_bytes(8),
+            I128  => Size::from_bytes(16),
         }
     }
 
@@ -346,6 +362,7 @@ impl Integer {
             I16 => dl.i16_align,
             I32 => dl.i32_align,
             I64 => dl.i64_align,
+            I128 => dl.i128_align,
         }
     }
 
@@ -357,33 +374,37 @@ impl Integer {
             (I16, false) => tcx.types.u16,
             (I32, false) => tcx.types.u32,
             (I64, false) => tcx.types.u64,
+            (I128, false) => tcx.types.u128,
             (I1, true) => tcx.types.i8,
             (I8, true) => tcx.types.i8,
             (I16, true) => tcx.types.i16,
             (I32, true) => tcx.types.i32,
             (I64, true) => tcx.types.i64,
+            (I128, true) => tcx.types.i128,
         }
     }
 
     /// Find the smallest Integer type which can represent the signed value.
     pub fn fit_signed(x: i64) -> Integer {
         match x {
-            -0x0000_0001...0x0000_0000 => I1,
-            -0x0000_0080...0x0000_007f => I8,
-            -0x0000_8000...0x0000_7fff => I16,
-            -0x8000_0000...0x7fff_ffff => I32,
-            _ => I64
+            -0x0000_0000_0000_0001...0x0000_0000_0000_0000 => I1,
+            -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: u64) -> Integer {
         match x {
-            0...0x0000_0001 => I1,
-            0...0x0000_00ff => I8,
-            0...0x0000_ffff => I16,
-            0...0xffff_ffff => I32,
-            _ => I64
+            0...0x0000_0000_0000_0001 => I1,
+            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,
         }
     }
 
@@ -406,6 +427,7 @@ impl Integer {
             attr::SignedInt(IntTy::I16) | attr::UnsignedInt(UintTy::U16) => I16,
             attr::SignedInt(IntTy::I32) | attr::UnsignedInt(UintTy::U32) => I32,
             attr::SignedInt(IntTy::I64) | attr::UnsignedInt(UintTy::U64) => I64,
+            attr::SignedInt(IntTy::I128) | attr::UnsignedInt(UintTy::U128) => I128,
             attr::SignedInt(IntTy::Is) | attr::UnsignedInt(UintTy::Us) => {
                 dl.ptr_sized_integer()
             }
@@ -486,6 +508,7 @@ impl Primitive {
             Int(I16) => Size::from_bits(16),
             Int(I32) | F32 => Size::from_bits(32),
             Int(I64) | F64 => Size::from_bits(64),
+            Int(I128) => Size::from_bits(128),
             Pointer => dl.pointer_size
         }
     }
@@ -497,6 +520,7 @@ impl Primitive {
             Int(I16) => dl.i16_align,
             Int(I32) => dl.i32_align,
             Int(I64) => dl.i64_align,
+            Int(I128) => dl.i128_align,
             F32 => dl.f32_align,
             F64 => dl.f64_align,
             Pointer => dl.pointer_align
@@ -1175,19 +1199,30 @@ impl<'a, 'gcx, 'tcx> Layout {
 
                 if def.is_enum() && def.variants.iter().all(|v| v.fields.is_empty()) {
                     // All bodies empty -> intlike
-                    let (mut min, mut max, mut non_zero) = (i64::MAX, i64::MIN, true);
+                    let (mut min, mut max, mut non_zero) = (i64::max_value(),
+                                                            i64::min_value(),
+                                                            true);
                     for v in &def.variants {
-                        let x = v.disr_val.to_u64_unchecked() as i64;
+                        let x = match v.disr_val.erase_type() {
+                            ConstInt::InferSigned(i) => i as i64,
+                            ConstInt::Infer(i) => i as u64 as i64,
+                            _ => bug!()
+                        };
                         if x == 0 { non_zero = false; }
                         if x < min { min = x; }
                         if x > max { max = x; }
                     }
 
-                    let (discr, signed) = Integer::repr_discr(tcx, ty, &hints[..], min, max);
+                    // FIXME: should handle i128? signed-value based impl is weird and hard to
+                    // grok.
+                    let (discr, signed) = Integer::repr_discr(tcx, ty, &hints[..],
+                                                              min,
+                                                              max);
                     return success(CEnum {
                         discr: discr,
                         signed: signed,
                         non_zero: non_zero,
+                        // FIXME: should be u128?
                         min: min as u64,
                         max: max as u64
                     });
@@ -1232,7 +1267,7 @@ impl<'a, 'gcx, 'tcx> Layout {
                 // non-empty body, explicit discriminants should have
                 // been rejected by a checker before this point.
                 for (i, v) in def.variants.iter().enumerate() {
-                    if i as u64 != v.disr_val.to_u64_unchecked() {
+                    if i as u128 != v.disr_val.to_u128_unchecked() {
                         bug!("non-C-like enum {} with specified discriminants",
                             tcx.item_path_str(def.did));
                     }
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index b03a432de41..3e33d246b6d 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -68,8 +68,8 @@ pub use self::sty::Region::*;
 pub use self::sty::TypeVariants::*;
 
 pub use self::contents::TypeContents;
-pub use self::context::{TyCtxt, tls};
-pub use self::context::{CtxtArenas, Lift, Tables};
+pub use self::context::{TyCtxt, GlobalArenas, tls};
+pub use self::context::{Lift, Tables};
 
 pub use self::trait_def::{TraitDef, TraitFlags};
 
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index b4ac6b9d250..0b45ff94a93 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -51,11 +51,13 @@ impl IntTypeExt for attr::IntType {
             SignedInt(ast::IntTy::I16)     => tcx.types.i16,
             SignedInt(ast::IntTy::I32)     => tcx.types.i32,
             SignedInt(ast::IntTy::I64)     => tcx.types.i64,
+            SignedInt(ast::IntTy::I128)     => tcx.types.i128,
             SignedInt(ast::IntTy::Is)   => tcx.types.isize,
             UnsignedInt(ast::UintTy::U8)    => tcx.types.u8,
             UnsignedInt(ast::UintTy::U16)   => tcx.types.u16,
             UnsignedInt(ast::UintTy::U32)   => tcx.types.u32,
             UnsignedInt(ast::UintTy::U64)   => tcx.types.u64,
+            UnsignedInt(ast::UintTy::U128)   => tcx.types.u128,
             UnsignedInt(ast::UintTy::Us) => tcx.types.usize,
         }
     }
@@ -66,6 +68,7 @@ impl IntTypeExt for attr::IntType {
             SignedInt(ast::IntTy::I16)   => ConstInt::I16(0),
             SignedInt(ast::IntTy::I32)   => ConstInt::I32(0),
             SignedInt(ast::IntTy::I64)   => ConstInt::I64(0),
+            SignedInt(ast::IntTy::I128)   => ConstInt::I128(0),
             SignedInt(ast::IntTy::Is) => match tcx.sess.target.int_type {
                 ast::IntTy::I16 => ConstInt::Isize(ConstIsize::Is16(0)),
                 ast::IntTy::I32 => ConstInt::Isize(ConstIsize::Is32(0)),
@@ -76,6 +79,7 @@ impl IntTypeExt for attr::IntType {
             UnsignedInt(ast::UintTy::U16) => ConstInt::U16(0),
             UnsignedInt(ast::UintTy::U32) => ConstInt::U32(0),
             UnsignedInt(ast::UintTy::U64) => ConstInt::U64(0),
+            UnsignedInt(ast::UintTy::U128) => ConstInt::U128(0),
             UnsignedInt(ast::UintTy::Us) => match tcx.sess.target.uint_type {
                 ast::UintTy::U16 => ConstInt::Usize(ConstUsize::Us16(0)),
                 ast::UintTy::U32 => ConstInt::Usize(ConstUsize::Us32(0)),
@@ -91,11 +95,13 @@ impl IntTypeExt for attr::IntType {
             (SignedInt(ast::IntTy::I16), ConstInt::I16(_)) => {},
             (SignedInt(ast::IntTy::I32), ConstInt::I32(_)) => {},
             (SignedInt(ast::IntTy::I64), ConstInt::I64(_)) => {},
+            (SignedInt(ast::IntTy::I128), ConstInt::I128(_)) => {},
             (SignedInt(ast::IntTy::Is), ConstInt::Isize(_)) => {},
             (UnsignedInt(ast::UintTy::U8), ConstInt::U8(_)) => {},
             (UnsignedInt(ast::UintTy::U16), ConstInt::U16(_)) => {},
             (UnsignedInt(ast::UintTy::U32), ConstInt::U32(_)) => {},
             (UnsignedInt(ast::UintTy::U64), ConstInt::U64(_)) => {},
+            (UnsignedInt(ast::UintTy::U128), ConstInt::U128(_)) => {},
             (UnsignedInt(ast::UintTy::Us), ConstInt::Usize(_)) => {},
             _ => bug!("disr type mismatch: {:?} vs {:?}", self, val),
         }
diff --git a/src/librustc_back/target/asmjs_unknown_emscripten.rs b/src/librustc_back/target/asmjs_unknown_emscripten.rs
index 98a9e343d00..2dbaeaf26e9 100644
--- a/src/librustc_back/target/asmjs_unknown_emscripten.rs
+++ b/src/librustc_back/target/asmjs_unknown_emscripten.rs
@@ -9,11 +9,12 @@
 // except according to those terms.
 
 use super::{Target, TargetOptions};
+use super::emscripten_base::{cmd};
 
 pub fn target() -> Result<Target, String> {
     let opts = TargetOptions {
-        linker: "emcc".to_string(),
-        ar: "emar".to_string(),
+        linker: cmd("emcc"),
+        ar: cmd("emar"),
 
         dynamic_linking: false,
         executables: true,
diff --git a/src/librustc_back/target/emscripten_base.rs b/src/librustc_back/target/emscripten_base.rs
new file mode 100644
index 00000000000..bacada3f5ab
--- /dev/null
+++ b/src/librustc_back/target/emscripten_base.rs
@@ -0,0 +1,17 @@
+// Copyright 2014-2015 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 fn cmd(name: &str) -> String {
+    if cfg!(windows) {
+        format!("{}.bat", name)
+    } else {
+        name.to_string()
+    }
+}
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index 6a409edf0fe..5afa85d1552 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -58,6 +58,7 @@ mod apple_ios_base;
 mod arm_base;
 mod bitrig_base;
 mod dragonfly_base;
+mod emscripten_base;
 mod freebsd_base;
 mod haiku_base;
 mod linux_base;
@@ -157,6 +158,8 @@ supported_targets! {
     ("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
     ("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
 
+    ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu),
+
     ("i686-linux-android", i686_linux_android),
     ("arm-linux-androideabi", arm_linux_androideabi),
     ("armv7-linux-androideabi", armv7_linux_androideabi),
@@ -173,6 +176,7 @@ supported_targets! {
     ("i686-unknown-openbsd", i686_unknown_openbsd),
     ("x86_64-unknown-openbsd", x86_64_unknown_openbsd),
 
+    ("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
     ("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
     ("x86_64-rumprun-netbsd", x86_64_rumprun_netbsd),
 
diff --git a/src/librustc_back/target/sparc64_unknown_linux_gnu.rs b/src/librustc_back/target/sparc64_unknown_linux_gnu.rs
new file mode 100644
index 00000000000..f627cc18f0b
--- /dev/null
+++ b/src/librustc_back/target/sparc64_unknown_linux_gnu.rs
@@ -0,0 +1,30 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use target::{Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::linux_base::opts();
+    base.cpu = "v9".to_string();
+    base.max_atomic_width = Some(64);
+    base.exe_allocation_crate = "alloc_system".to_string();
+
+    Ok(Target {
+        llvm_target: "sparc64-unknown-linux-gnu".to_string(),
+        target_endian: "big".to_string(),
+        target_pointer_width: "64".to_string(),
+        data_layout: "E-m:e-i64:64-n32:64-S128".to_string(),
+        arch: "sparc64".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "gnu".to_string(),
+        target_vendor: "unknown".to_string(),
+        options: base,
+    })
+}
diff --git a/src/librustc_back/target/sparc64_unknown_netbsd.rs b/src/librustc_back/target/sparc64_unknown_netbsd.rs
new file mode 100644
index 00000000000..f30cebbc2d5
--- /dev/null
+++ b/src/librustc_back/target/sparc64_unknown_netbsd.rs
@@ -0,0 +1,30 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use target::{Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::netbsd_base::opts();
+    base.cpu = "v9".to_string();
+    base.pre_link_args.push("-m64".to_string());
+    base.max_atomic_width = Some(64);
+
+    Ok(Target {
+        llvm_target: "sparc64-unknown-netbsd".to_string(),
+        target_endian: "big".to_string(),
+        target_pointer_width: "64".to_string(),
+        data_layout: "E-m:e-i64:64-n32:64-S128".to_string(),
+        arch: "sparc64".to_string(),
+        target_os: "netbsd".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
+        options: base,
+    })
+}
diff --git a/src/librustc_back/target/wasm32_unknown_emscripten.rs b/src/librustc_back/target/wasm32_unknown_emscripten.rs
index fec269074da..a06980767fd 100644
--- a/src/librustc_back/target/wasm32_unknown_emscripten.rs
+++ b/src/librustc_back/target/wasm32_unknown_emscripten.rs
@@ -9,11 +9,12 @@
 // except according to those terms.
 
 use super::{Target, TargetOptions};
+use super::emscripten_base::{cmd};
 
 pub fn target() -> Result<Target, String> {
     let opts = TargetOptions {
-        linker: "emcc".to_string(),
-        ar: "emar".to_string(),
+        linker: cmd("emcc"),
+        ar: cmd("emar"),
 
         dynamic_linking: false,
         executables: true,
diff --git a/src/librustc_const_eval/Cargo.toml b/src/librustc_const_eval/Cargo.toml
index 0e5cbce8639..7148e181bbd 100644
--- a/src/librustc_const_eval/Cargo.toml
+++ b/src/librustc_const_eval/Cargo.toml
@@ -19,4 +19,5 @@ rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
 syntax = { path = "../libsyntax" }
 graphviz = { path = "../libgraphviz" }
-syntax_pos = { path = "../libsyntax_pos" }
\ No newline at end of file
+syntax_pos = { path = "../libsyntax_pos" }
+rustc_i128 = { path = "../librustc_i128" }
diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs
index ebe10349011..6d04975f533 100644
--- a/src/librustc_const_eval/_match.rs
+++ b/src/librustc_const_eval/_match.rs
@@ -23,18 +23,12 @@ use rustc_data_structures::indexed_vec::Idx;
 use pattern::{FieldPattern, Pattern, PatternKind};
 use pattern::{PatternFoldable, PatternFolder};
 
-use rustc::hir::def::Def;
 use rustc::hir::def_id::DefId;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 
-use rustc::hir;
-use rustc::hir::def::CtorKind;
-use rustc::hir::{Pat, PatKind};
+use rustc::mir::Field;
 use rustc::util::common::ErrorReported;
 
-use syntax::ast::{self, DUMMY_NODE_ID};
-use syntax::codemap::Spanned;
-use syntax::ptr::P;
 use syntax_pos::{Span, DUMMY_SP};
 
 use arena::TypedArena;
@@ -74,12 +68,6 @@ impl<'tcx> PatternFolder<'tcx> for LiteralExpander {
     }
 }
 
-pub const DUMMY_WILD_PAT: &'static Pat = &Pat {
-    id: DUMMY_NODE_ID,
-    node: PatKind::Wild,
-    span: DUMMY_SP
-};
-
 impl<'tcx> Pattern<'tcx> {
     fn is_wildcard(&self) -> bool {
         match *self.kind {
@@ -224,25 +212,34 @@ pub enum Constructor {
 }
 
 impl<'tcx> Constructor {
-    fn variant_for_adt(&self, adt: &'tcx ty::AdtDef) -> &'tcx ty::VariantDef {
+    fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> usize {
         match self {
-            &Variant(vid) => adt.variant_with_id(vid),
+            &Variant(vid) => adt.variant_index_with_id(vid),
             &Single => {
                 assert_eq!(adt.variants.len(), 1);
-                &adt.variants[0]
+                0
             }
             _ => bug!("bad constructor {:?} for adt {:?}", self, adt)
         }
     }
 }
 
-#[derive(Clone, PartialEq)]
-pub enum Usefulness {
+#[derive(Clone)]
+pub enum Usefulness<'tcx> {
     Useful,
-    UsefulWithWitness(Vec<Witness>),
+    UsefulWithWitness(Vec<Witness<'tcx>>),
     NotUseful
 }
 
+impl<'tcx> Usefulness<'tcx> {
+    fn is_useful(&self) -> bool {
+        match *self {
+            NotUseful => false,
+            _ => true
+        }
+    }
+}
+
 #[derive(Copy, Clone)]
 pub enum WitnessPreference {
     ConstructWitness,
@@ -255,31 +252,17 @@ struct PatternContext<'tcx> {
     max_slice_length: usize,
 }
 
-
-fn const_val_to_expr(value: &ConstVal) -> P<hir::Expr> {
-    let node = match value {
-        &ConstVal::Bool(b) => ast::LitKind::Bool(b),
-        _ => bug!()
-    };
-    P(hir::Expr {
-        id: DUMMY_NODE_ID,
-        node: hir::ExprLit(P(Spanned { node: node, span: DUMMY_SP })),
-        span: DUMMY_SP,
-        attrs: ast::ThinVec::new(),
-    })
-}
-
 /// A stack of patterns in reverse order of construction
-#[derive(Clone, PartialEq, Eq)]
-pub struct Witness(Vec<P<Pat>>);
+#[derive(Clone)]
+pub struct Witness<'tcx>(Vec<Pattern<'tcx>>);
 
-impl Witness {
-    pub fn single_pattern(&self) -> &Pat {
+impl<'tcx> Witness<'tcx> {
+    pub fn single_pattern(&self) -> &Pattern<'tcx> {
         assert_eq!(self.0.len(), 1);
         &self.0[0]
     }
 
-    fn push_wild_constructor<'a, 'tcx>(
+    fn push_wild_constructor<'a>(
         mut self,
         cx: &MatchCheckCtxt<'a, 'tcx>,
         ctor: &Constructor,
@@ -287,7 +270,7 @@ impl Witness {
         -> Self
     {
         let arity = constructor_arity(cx, ctor, ty);
-        self.0.extend(repeat(DUMMY_WILD_PAT).take(arity).map(|p| P(p.clone())));
+        self.0.extend(repeat(cx.wild_pattern).take(arity).cloned());
         self.apply_constructor(cx, ctor, ty)
     }
 
@@ -305,7 +288,7 @@ impl Witness {
     ///
     /// left_ty: struct X { a: (bool, &'static str), b: usize}
     /// pats: [(false, "foo"), 42]  => X { a: (false, "foo"), b: 42 }
-    fn apply_constructor<'a, 'tcx>(
+    fn apply_constructor<'a>(
         mut self,
         cx: &MatchCheckCtxt<'a,'tcx>,
         ctor: &Constructor,
@@ -318,60 +301,56 @@ impl Witness {
             let mut pats = self.0.drain(len-arity..).rev();
 
             match ty.sty {
-                ty::TyTuple(..) => PatKind::Tuple(pats.collect(), None),
-
-                ty::TyAdt(adt, _) => {
-                    let v = ctor.variant_for_adt(adt);
-                    let qpath = hir::QPath::Resolved(None, P(hir::Path {
-                        span: DUMMY_SP,
-                        def: Def::Err,
-                        segments: vec![hir::PathSegment::from_name(v.name)].into(),
-                    }));
-                    match v.ctor_kind {
-                        CtorKind::Fictive => {
-                            let field_pats: hir::HirVec<_> = v.fields.iter()
-                                .zip(pats)
-                                .filter(|&(_, ref pat)| pat.node != PatKind::Wild)
-                                .map(|(field, pat)| Spanned {
-                                    span: DUMMY_SP,
-                                    node: hir::FieldPat {
-                                        name: field.name,
-                                        pat: pat,
-                                        is_shorthand: false,
-                                    }
-                                }).collect();
-                            let has_more_fields = field_pats.len() < arity;
-                            PatKind::Struct(qpath, field_pats, has_more_fields)
+                ty::TyAdt(..) |
+                ty::TyTuple(..) => {
+                    let pats = pats.enumerate().map(|(i, p)| {
+                        FieldPattern {
+                            field: Field::new(i),
+                            pattern: p
                         }
-                        CtorKind::Fn => {
-                            PatKind::TupleStruct(qpath, pats.collect(), None)
+                    }).collect();
+
+                    if let ty::TyAdt(adt, _) = ty.sty {
+                        if adt.variants.len() > 1 {
+                            PatternKind::Variant {
+                                adt_def: adt,
+                                variant_index: ctor.variant_index_for_adt(adt),
+                                subpatterns: pats
+                            }
+                        } else {
+                            PatternKind::Leaf { subpatterns: pats }
                         }
-                        CtorKind::Const => PatKind::Path(qpath)
+                    } else {
+                        PatternKind::Leaf { subpatterns: pats }
                     }
                 }
 
-                ty::TyRef(_, ty::TypeAndMut { mutbl, .. }) => {
-                    PatKind::Ref(pats.nth(0).unwrap(), mutbl)
+                ty::TyRef(..) => {
+                    PatternKind::Deref { subpattern: pats.nth(0).unwrap() }
                 }
 
                 ty::TySlice(_) | ty::TyArray(..) => {
-                    PatKind::Slice(pats.collect(), None, hir::HirVec::new())
+                    PatternKind::Slice {
+                        prefix: pats.collect(),
+                        slice: None,
+                        suffix: vec![]
+                    }
                 }
 
                 _ => {
                     match *ctor {
-                        ConstantValue(ref v) => PatKind::Lit(const_val_to_expr(v)),
-                        _ => PatKind::Wild,
+                        ConstantValue(ref v) => PatternKind::Constant { value: v.clone() },
+                        _ => PatternKind::Wild,
                     }
                 }
             }
         };
 
-        self.0.push(P(hir::Pat {
-            id: DUMMY_NODE_ID,
-            node: pat,
-            span: DUMMY_SP
-        }));
+        self.0.push(Pattern {
+            ty: ty,
+            span: DUMMY_SP,
+            kind: Box::new(pat),
+        });
 
         self
     }
@@ -528,13 +507,13 @@ pub fn is_useful<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                            matrix: &Matrix<'a, 'tcx>,
                            v: &[&'a Pattern<'tcx>],
                            witness: WitnessPreference)
-                           -> Usefulness {
+                           -> Usefulness<'tcx> {
     let &Matrix(ref rows) = matrix;
     debug!("is_useful({:?}, {:?})", matrix, v);
     if rows.is_empty() {
         return match witness {
             ConstructWitness => UsefulWithWitness(vec![Witness(
-                repeat(DUMMY_WILD_PAT).take(v.len()).map(|p| P(p.clone())).collect()
+                repeat(cx.wild_pattern).take(v.len()).cloned().collect()
             )]),
             LeaveOutWitness => Useful
         };
@@ -559,7 +538,7 @@ pub fn is_useful<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
         debug!("is_useful - expanding constructors: {:?}", constructors);
         constructors.into_iter().map(|c|
             is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness)
-        ).find(|result| result != &NotUseful).unwrap_or(NotUseful)
+        ).find(|result| result.is_useful()).unwrap_or(NotUseful)
     } else {
         debug!("is_useful - expanding wildcard");
         let constructors = missing_constructors(cx, matrix, pcx);
@@ -567,7 +546,7 @@ pub fn is_useful<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
         if constructors.is_empty() {
             all_constructors(cx, pcx).into_iter().map(|c| {
                 is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness)
-            }).find(|result| result != &NotUseful).unwrap_or(NotUseful)
+            }).find(|result| result.is_useful()).unwrap_or(NotUseful)
         } else {
             let matrix = rows.iter().filter_map(|r| {
                 if r[0].is_wildcard() {
@@ -597,7 +576,7 @@ fn is_useful_specialized<'a, 'tcx>(
     v: &[&'a Pattern<'tcx>],
     ctor: Constructor,
     lty: Ty<'tcx>,
-    witness: WitnessPreference) -> Usefulness
+    witness: WitnessPreference) -> Usefulness<'tcx>
 {
     let arity = constructor_arity(cx, &ctor, lty);
     let matrix = Matrix(m.iter().flat_map(|r| {
@@ -672,7 +651,7 @@ fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> usize
         },
         ty::TyRef(..) => 1,
         ty::TyAdt(adt, _) => {
-            ctor.variant_for_adt(adt).fields.len()
+            adt.variants[ctor.variant_index_for_adt(adt)].fields.len()
         }
         _ => 0
     }
diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs
index 01b19e1f539..53e83815b46 100644
--- a/src/librustc_const_eval/check_match.rs
+++ b/src/librustc_const_eval/check_match.rs
@@ -9,11 +9,10 @@
 // except according to those terms.
 
 use _match::{MatchCheckCtxt, Matrix, expand_pattern, is_useful};
-use _match::{DUMMY_WILD_PAT};
 use _match::Usefulness::*;
 use _match::WitnessPreference::*;
 
-use pattern::{Pattern, PatternContext, PatternError};
+use pattern::{Pattern, PatternContext, PatternError, PatternKind};
 
 use eval::report_const_eval_err;
 
@@ -117,13 +116,6 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
     fn report_inlining_errors(&self, patcx: PatternContext, pat_span: Span) {
         for error in patcx.errors {
             match error {
-                PatternError::BadConstInPattern(span, def_id) => {
-                    self.tcx.sess.span_err(
-                        span,
-                        &format!("constants of the type `{}` \
-                                  cannot be used in patterns",
-                                 self.tcx.item_path_str(def_id)));
-                }
                 PatternError::StaticInPattern(span) => {
                     span_err!(self.tcx.sess, span, E0158,
                               "statics cannot be referenced in patterns");
@@ -230,9 +222,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
                 Useful => bug!()
             };
 
-            let pattern_string = hir::print::to_string(&self.tcx.map, |s| {
-                s.print_pat(witness[0].single_pattern())
-            });
+            let pattern_string = witness[0].single_pattern().to_string();
             let mut diag = struct_span_err!(
                 self.tcx.sess, pat.span, E0005,
                 "refutable pattern in {}: `{}` not covered",
@@ -369,23 +359,21 @@ fn check_exhaustive<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
     match is_useful(cx, matrix, &[cx.wild_pattern], ConstructWitness) {
         UsefulWithWitness(pats) => {
             let witnesses = if pats.is_empty() {
-                vec![DUMMY_WILD_PAT]
+                vec![cx.wild_pattern]
             } else {
                 pats.iter().map(|w| w.single_pattern()).collect()
             };
             match source {
                 hir::MatchSource::ForLoopDesugar => {
                     // `witnesses[0]` has the form `Some(<head>)`, peel off the `Some`
-                    let witness = match witnesses[0].node {
-                        PatKind::TupleStruct(_, ref pats, _) => match &pats[..] {
-                            &[ref pat] => &**pat,
+                    let witness = match *witnesses[0].kind {
+                        PatternKind::Variant { ref subpatterns, .. } => match &subpatterns[..] {
+                            &[ref pat] => &pat.pattern,
                             _ => bug!(),
                         },
                         _ => bug!(),
                     };
-                    let pattern_string = hir::print::to_string(&cx.tcx.map, |s| {
-                        s.print_pat(witness)
-                    });
+                    let pattern_string = witness.to_string();
                     struct_span_err!(cx.tcx.sess, sp, E0297,
                         "refutable pattern in `for` loop binding: \
                                 `{}` not covered",
@@ -394,24 +382,23 @@ fn check_exhaustive<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                         .emit();
                 },
                 _ => {
-                    let pattern_strings: Vec<_> = witnesses.iter().map(|w| {
-                        hir::print::to_string(&cx.tcx.map, |s| s.print_pat(w))
-                    }).collect();
                     const LIMIT: usize = 3;
-                    let joined_patterns = match pattern_strings.len() {
+                    let joined_patterns = match witnesses.len() {
                         0 => bug!(),
-                        1 => format!("`{}`", pattern_strings[0]),
+                        1 => format!("`{}`", witnesses[0]),
                         2...LIMIT => {
-                            let (tail, head) = pattern_strings.split_last().unwrap();
-                            format!("`{}`", head.join("`, `") + "` and `" + tail)
+                            let (tail, head) = witnesses.split_last().unwrap();
+                            let head: Vec<_> = head.iter().map(|w| w.to_string()).collect();
+                            format!("`{}` and `{}`", head.join("`, `"), tail)
                         },
                         _ => {
-                            let (head, tail) = pattern_strings.split_at(LIMIT);
+                            let (head, tail) = witnesses.split_at(LIMIT);
+                            let head: Vec<_> = head.iter().map(|w| w.to_string()).collect();
                             format!("`{}` and {} more", head.join("`, `"), tail.len())
                         }
                     };
 
-                    let label_text = match pattern_strings.len(){
+                    let label_text = match witnesses.len() {
                         1 => format!("pattern {} not covered", joined_patterns),
                         _ => format!("patterns {} not covered", joined_patterns)
                     };
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index e8e7a2eb7ed..6b8e0e34c1d 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -18,7 +18,7 @@ use self::EvalHint::*;
 use rustc::hir::map as ast_map;
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::traits;
-use rustc::hir::def::{Def, CtorKind};
+use rustc::hir::def::Def;
 use rustc::hir::def_id::DefId;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::util::IntTypeExt;
@@ -26,16 +26,12 @@ use rustc::ty::subst::Substs;
 use rustc::traits::Reveal;
 use rustc::util::common::ErrorReported;
 use rustc::util::nodemap::DefIdMap;
-use rustc::lint;
 
 use graphviz::IntoCow;
 use syntax::ast;
-use rustc::hir::{Expr, PatKind};
-use rustc::hir;
-use syntax::ptr::P;
-use syntax::codemap;
+use rustc::hir::{self, Expr};
 use syntax::attr::IntType;
-use syntax_pos::{self, Span};
+use syntax_pos::Span;
 
 use std::borrow::Cow;
 use std::cmp::Ordering;
@@ -43,6 +39,8 @@ use std::cmp::Ordering;
 use rustc_const_math::*;
 use rustc_errors::DiagnosticBuilder;
 
+use rustc_i128::{i128, u128};
+
 macro_rules! math {
     ($e:expr, $op:expr) => {
         match $op {
@@ -184,126 +182,6 @@ fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
     }
 }
 
-pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                   expr: &Expr,
-                                   pat_id: ast::NodeId,
-                                   span: Span)
-                                   -> Result<P<hir::Pat>, DefId> {
-    let pat_ty = tcx.tables().expr_ty(expr);
-    debug!("expr={:?} pat_ty={:?} pat_id={}", expr, pat_ty, pat_id);
-    match pat_ty.sty {
-        ty::TyFloat(_) => {
-            tcx.sess.add_lint(
-                lint::builtin::ILLEGAL_FLOATING_POINT_CONSTANT_PATTERN,
-                pat_id,
-                span,
-                format!("floating point constants cannot be used in patterns"));
-        }
-        ty::TyAdt(adt_def, _) if adt_def.is_union() => {
-            // Matching on union fields is unsafe, we can't hide it in constants
-            tcx.sess.span_err(span, "cannot use unions in constant patterns");
-        }
-        ty::TyAdt(adt_def, _) => {
-            if !tcx.has_attr(adt_def.did, "structural_match") {
-                tcx.sess.add_lint(
-                    lint::builtin::ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN,
-                    pat_id,
-                    span,
-                    format!("to use a constant of type `{}` \
-                             in a pattern, \
-                             `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
-                            tcx.item_path_str(adt_def.did),
-                            tcx.item_path_str(adt_def.did)));
-            }
-        }
-        _ => { }
-    }
-    let pat = match expr.node {
-        hir::ExprTup(ref exprs) =>
-            PatKind::Tuple(exprs.iter()
-                                .map(|expr| const_expr_to_pat(tcx, &expr, pat_id, span))
-                                .collect::<Result<_, _>>()?, None),
-
-        hir::ExprCall(ref callee, ref args) => {
-            let qpath = match callee.node {
-                hir::ExprPath(ref qpath) => qpath,
-                _ => bug!()
-            };
-            let def = tcx.tables().qpath_def(qpath, callee.id);
-            let ctor_path = if let hir::QPath::Resolved(_, ref path) = *qpath {
-                match def {
-                    Def::StructCtor(_, CtorKind::Fn) |
-                    Def::VariantCtor(_, CtorKind::Fn) => {
-                        Some(path.clone())
-                    }
-                    _ => None
-                }
-            } else {
-                None
-            };
-            match (def, ctor_path) {
-                (Def::Fn(..), None) | (Def::Method(..), None) => {
-                    PatKind::Lit(P(expr.clone()))
-                }
-                (_, Some(ctor_path)) => {
-                    let pats = args.iter()
-                                   .map(|expr| const_expr_to_pat(tcx, expr, pat_id, span))
-                                   .collect::<Result<_, _>>()?;
-                    PatKind::TupleStruct(hir::QPath::Resolved(None, ctor_path), pats, None)
-                }
-                _ => bug!()
-            }
-        }
-
-        hir::ExprStruct(ref qpath, ref fields, None) => {
-            let field_pats =
-                fields.iter()
-                      .map(|field| Ok(codemap::Spanned {
-                          span: syntax_pos::DUMMY_SP,
-                          node: hir::FieldPat {
-                              name: field.name.node,
-                              pat: const_expr_to_pat(tcx, &field.expr, pat_id, span)?,
-                              is_shorthand: false,
-                          },
-                      }))
-                      .collect::<Result<_, _>>()?;
-            PatKind::Struct(qpath.clone(), field_pats, false)
-        }
-
-        hir::ExprArray(ref exprs) => {
-            let pats = exprs.iter()
-                            .map(|expr| const_expr_to_pat(tcx, &expr, pat_id, span))
-                            .collect::<Result<_, _>>()?;
-            PatKind::Slice(pats, None, hir::HirVec::new())
-        }
-
-        hir::ExprPath(ref qpath) => {
-            let def = tcx.tables().qpath_def(qpath, expr.id);
-            match def {
-                Def::StructCtor(_, CtorKind::Const) |
-                Def::VariantCtor(_, CtorKind::Const) => {
-                    match expr.node {
-                        hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
-                            PatKind::Path(hir::QPath::Resolved(None, path.clone()))
-                        }
-                        _ => bug!()
-                    }
-                }
-                Def::Const(def_id) | Def::AssociatedConst(def_id) => {
-                    let substs = Some(tcx.tables().node_id_item_substs(expr.id)
-                        .unwrap_or_else(|| tcx.intern_substs(&[])));
-                    let (expr, _ty) = lookup_const_by_id(tcx, def_id, substs).unwrap();
-                    return const_expr_to_pat(tcx, expr, pat_id, span);
-                },
-                _ => bug!(),
-            }
-        }
-
-        _ => PatKind::Lit(P(expr.clone()))
-    };
-    Ok(P(hir::Pat { id: expr.id, node: pat, span: span }))
-}
-
 pub fn report_const_eval_err<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     err: &ConstEvalErr,
@@ -588,38 +466,43 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         if let hir::ExprLit(ref lit) = inner.node {
             use syntax::ast::*;
             use syntax::ast::LitIntType::*;
-            const I8_OVERFLOW: u64 = ::std::i8::MAX as u64 + 1;
-            const I16_OVERFLOW: u64 = ::std::i16::MAX as u64 + 1;
-            const I32_OVERFLOW: u64 = ::std::i32::MAX as u64 + 1;
-            const I64_OVERFLOW: u64 = ::std::i64::MAX as u64 + 1;
+            const I8_OVERFLOW: u128 = i8::max_value() as u128 + 1;
+            const I16_OVERFLOW: u128 = i16::max_value() as u128 + 1;
+            const I32_OVERFLOW: u128 = i32::max_value() as u128 + 1;
+            const I64_OVERFLOW: u128 = i64::max_value() as u128 + 1;
+            const I128_OVERFLOW: u128 = i128::max_value() as u128 + 1;
             match (&lit.node, ety.map(|t| &t.sty)) {
                 (&LitKind::Int(I8_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I8))) |
                 (&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => {
-                    return Ok(Integral(I8(::std::i8::MIN)))
+                    return Ok(Integral(I8(i8::min_value())))
                 },
                 (&LitKind::Int(I16_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I16))) |
                 (&LitKind::Int(I16_OVERFLOW, Signed(IntTy::I16)), _) => {
-                    return Ok(Integral(I16(::std::i16::MIN)))
+                    return Ok(Integral(I16(i16::min_value())))
                 },
                 (&LitKind::Int(I32_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I32))) |
                 (&LitKind::Int(I32_OVERFLOW, Signed(IntTy::I32)), _) => {
-                    return Ok(Integral(I32(::std::i32::MIN)))
+                    return Ok(Integral(I32(i32::min_value())))
                 },
                 (&LitKind::Int(I64_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I64))) |
                 (&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => {
-                    return Ok(Integral(I64(::std::i64::MIN)))
+                    return Ok(Integral(I64(i64::min_value())))
+                },
+                (&LitKind::Int(I128_OVERFLOW, Unsuffixed), Some(&ty::TyInt(IntTy::I128))) |
+                (&LitKind::Int(I128_OVERFLOW, Signed(IntTy::I128)), _) => {
+                    return Ok(Integral(I128(i128::min_value())))
                 },
                 (&LitKind::Int(n, Unsuffixed), Some(&ty::TyInt(IntTy::Is))) |
                 (&LitKind::Int(n, Signed(IntTy::Is)), _) => {
                     match tcx.sess.target.int_type {
                         IntTy::I16 => if n == I16_OVERFLOW {
-                            return Ok(Integral(Isize(Is16(::std::i16::MIN))));
+                            return Ok(Integral(Isize(Is16(i16::min_value()))));
                         },
                         IntTy::I32 => if n == I32_OVERFLOW {
-                            return Ok(Integral(Isize(Is32(::std::i32::MIN))));
+                            return Ok(Integral(Isize(Is32(i32::min_value()))));
                         },
                         IntTy::I64 => if n == I64_OVERFLOW {
-                            return Ok(Integral(Isize(Is64(::std::i64::MIN))));
+                            return Ok(Integral(Isize(Is64(i64::min_value()))));
                         },
                         _ => bug!(),
                     }
@@ -973,26 +856,30 @@ fn infer<'a, 'tcx>(i: ConstInt,
         (&ty::TyInt(IntTy::I16), result @ I16(_)) => Ok(result),
         (&ty::TyInt(IntTy::I32), result @ I32(_)) => Ok(result),
         (&ty::TyInt(IntTy::I64), result @ I64(_)) => Ok(result),
+        (&ty::TyInt(IntTy::I128), result @ I128(_)) => Ok(result),
         (&ty::TyInt(IntTy::Is), result @ Isize(_)) => Ok(result),
 
         (&ty::TyUint(UintTy::U8), result @ U8(_)) => Ok(result),
         (&ty::TyUint(UintTy::U16), result @ U16(_)) => Ok(result),
         (&ty::TyUint(UintTy::U32), result @ U32(_)) => Ok(result),
         (&ty::TyUint(UintTy::U64), result @ U64(_)) => Ok(result),
+        (&ty::TyUint(UintTy::U128), result @ U128(_)) => Ok(result),
         (&ty::TyUint(UintTy::Us), result @ Usize(_)) => Ok(result),
 
-        (&ty::TyInt(IntTy::I8), Infer(i)) => Ok(I8(i as i64 as i8)),
-        (&ty::TyInt(IntTy::I16), Infer(i)) => Ok(I16(i as i64 as i16)),
-        (&ty::TyInt(IntTy::I32), Infer(i)) => Ok(I32(i as i64 as i32)),
-        (&ty::TyInt(IntTy::I64), Infer(i)) => Ok(I64(i as i64)),
+        (&ty::TyInt(IntTy::I8), Infer(i)) => Ok(I8(i as i128 as i8)),
+        (&ty::TyInt(IntTy::I16), Infer(i)) => Ok(I16(i as i128 as i16)),
+        (&ty::TyInt(IntTy::I32), Infer(i)) => Ok(I32(i as i128 as i32)),
+        (&ty::TyInt(IntTy::I64), Infer(i)) => Ok(I64(i as i128 as i64)),
+        (&ty::TyInt(IntTy::I128), Infer(i)) => Ok(I128(i as i128)),
         (&ty::TyInt(IntTy::Is), Infer(i)) => {
-            Ok(Isize(ConstIsize::new_truncating(i as i64, tcx.sess.target.int_type)))
+            Ok(Isize(ConstIsize::new_truncating(i as i128, tcx.sess.target.int_type)))
         },
 
         (&ty::TyInt(IntTy::I8), InferSigned(i)) => Ok(I8(i as i8)),
         (&ty::TyInt(IntTy::I16), InferSigned(i)) => Ok(I16(i as i16)),
         (&ty::TyInt(IntTy::I32), InferSigned(i)) => Ok(I32(i as i32)),
-        (&ty::TyInt(IntTy::I64), InferSigned(i)) => Ok(I64(i)),
+        (&ty::TyInt(IntTy::I64), InferSigned(i)) => Ok(I64(i as i64)),
+        (&ty::TyInt(IntTy::I128), InferSigned(i)) => Ok(I128(i)),
         (&ty::TyInt(IntTy::Is), InferSigned(i)) => {
             Ok(Isize(ConstIsize::new_truncating(i, tcx.sess.target.int_type)))
         },
@@ -1000,7 +887,8 @@ fn infer<'a, 'tcx>(i: ConstInt,
         (&ty::TyUint(UintTy::U8), Infer(i)) => Ok(U8(i as u8)),
         (&ty::TyUint(UintTy::U16), Infer(i)) => Ok(U16(i as u16)),
         (&ty::TyUint(UintTy::U32), Infer(i)) => Ok(U32(i as u32)),
-        (&ty::TyUint(UintTy::U64), Infer(i)) => Ok(U64(i)),
+        (&ty::TyUint(UintTy::U64), Infer(i)) => Ok(U64(i as u64)),
+        (&ty::TyUint(UintTy::U128), Infer(i)) => Ok(U128(i)),
         (&ty::TyUint(UintTy::Us), Infer(i)) => {
             Ok(Usize(ConstUsize::new_truncating(i, tcx.sess.target.uint_type)))
         },
@@ -1071,21 +959,23 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(
 }
 
 fn cast_const_int<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, val: ConstInt, ty: ty::Ty) -> CastResult {
-    let v = val.to_u64_unchecked();
+    let v = val.to_u128_unchecked();
     match ty.sty {
         ty::TyBool if v == 0 => Ok(Bool(false)),
         ty::TyBool if v == 1 => Ok(Bool(true)),
-        ty::TyInt(ast::IntTy::I8) => Ok(Integral(I8(v as i64 as i8))),
-        ty::TyInt(ast::IntTy::I16) => Ok(Integral(I16(v as i64 as i16))),
-        ty::TyInt(ast::IntTy::I32) => Ok(Integral(I32(v as i64 as i32))),
-        ty::TyInt(ast::IntTy::I64) => Ok(Integral(I64(v as i64))),
+        ty::TyInt(ast::IntTy::I8) => Ok(Integral(I8(v as i128 as i8))),
+        ty::TyInt(ast::IntTy::I16) => Ok(Integral(I16(v as i128 as i16))),
+        ty::TyInt(ast::IntTy::I32) => Ok(Integral(I32(v as i128 as i32))),
+        ty::TyInt(ast::IntTy::I64) => Ok(Integral(I64(v as i128 as i64))),
+        ty::TyInt(ast::IntTy::I128) => Ok(Integral(I128(v as i128))),
         ty::TyInt(ast::IntTy::Is) => {
-            Ok(Integral(Isize(ConstIsize::new_truncating(v as i64, tcx.sess.target.int_type))))
+            Ok(Integral(Isize(ConstIsize::new_truncating(v as i128, tcx.sess.target.int_type))))
         },
         ty::TyUint(ast::UintTy::U8) => Ok(Integral(U8(v as u8))),
         ty::TyUint(ast::UintTy::U16) => Ok(Integral(U16(v as u16))),
         ty::TyUint(ast::UintTy::U32) => Ok(Integral(U32(v as u32))),
-        ty::TyUint(ast::UintTy::U64) => Ok(Integral(U64(v))),
+        ty::TyUint(ast::UintTy::U64) => Ok(Integral(U64(v as u64))),
+        ty::TyUint(ast::UintTy::U128) => Ok(Integral(U128(v as u128))),
         ty::TyUint(ast::UintTy::Us) => {
             Ok(Integral(Usize(ConstUsize::new_truncating(v, tcx.sess.target.uint_type))))
         },
@@ -1115,13 +1005,13 @@ fn cast_const_float<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     match ty.sty {
         ty::TyInt(_) | ty::TyUint(_) => {
             let i = match val {
-                F32(f) if f >= 0.0 => Infer(f as u64),
+                F32(f) if f >= 0.0 => Infer(f as u128),
                 FInfer { f64: f, .. } |
-                F64(f) if f >= 0.0 => Infer(f as u64),
+                F64(f) if f >= 0.0 => Infer(f as u128),
 
-                F32(f) => InferSigned(f as i64),
+                F32(f) => InferSigned(f as i128),
                 FInfer { f64: f, .. } |
-                F64(f) => InferSigned(f as i64)
+                F64(f) => InferSigned(f as i128)
             };
 
             if let (InferSigned(_), &ty::TyUint(_)) = (i, &ty.sty) {
@@ -1145,9 +1035,9 @@ fn cast_const_float<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, val: ConstVal, ty: ty::Ty) -> CastResult {
     match val {
         Integral(i) => cast_const_int(tcx, i, ty),
-        Bool(b) => cast_const_int(tcx, Infer(b as u64), ty),
+        Bool(b) => cast_const_int(tcx, Infer(b as u128), ty),
         Float(f) => cast_const_float(tcx, f, ty),
-        Char(c) => cast_const_int(tcx, Infer(c as u64), ty),
+        Char(c) => cast_const_int(tcx, Infer(c as u128), ty),
         Function(_) => Err(UnimplementedConstVal("casting fn pointers")),
         ByteStr(b) => match ty.sty {
             ty::TyRawPtr(_) => {
@@ -1185,28 +1075,29 @@ fn lit_to_const<'a, 'tcx>(lit: &ast::LitKind,
         LitKind::ByteStr(ref data) => Ok(ByteStr(data.clone())),
         LitKind::Byte(n) => Ok(Integral(U8(n))),
         LitKind::Int(n, Signed(ity)) => {
-            infer(InferSigned(n as i64), tcx, &ty::TyInt(ity)).map(Integral)
+            infer(InferSigned(n as i128), tcx, &ty::TyInt(ity)).map(Integral)
         },
 
+        // FIXME: this should become u128.
         LitKind::Int(n, Unsuffixed) => {
             match ty_hint.map(|t| &t.sty) {
                 Some(&ty::TyInt(ity)) => {
-                    infer(InferSigned(n as i64), tcx, &ty::TyInt(ity)).map(Integral)
+                    infer(InferSigned(n as i128), tcx, &ty::TyInt(ity)).map(Integral)
                 },
                 Some(&ty::TyUint(uty)) => {
-                    infer(Infer(n), tcx, &ty::TyUint(uty)).map(Integral)
+                    infer(Infer(n as u128), tcx, &ty::TyUint(uty)).map(Integral)
                 },
-                None => Ok(Integral(Infer(n))),
+                None => Ok(Integral(Infer(n as u128))),
                 Some(&ty::TyAdt(adt, _)) => {
                     let hints = tcx.lookup_repr_hints(adt.did);
                     let int_ty = tcx.enum_repr_type(hints.iter().next());
-                    infer(Infer(n), tcx, &int_ty.to_ty(tcx).sty).map(Integral)
+                    infer(Infer(n as u128), tcx, &int_ty.to_ty(tcx).sty).map(Integral)
                 },
                 Some(ty_hint) => bug!("bad ty_hint: {:?}, {:?}", ty_hint, lit),
             }
         },
         LitKind::Int(n, Unsigned(ity)) => {
-            infer(Infer(n), tcx, &ty::TyUint(ity)).map(Integral)
+            infer(Infer(n as u128), tcx, &ty::TyUint(ity)).map(Integral)
         },
 
         LitKind::Float(n, fty) => {
diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs
index 7a6cc493723..67b4efdbd1f 100644
--- a/src/librustc_const_eval/lib.rs
+++ b/src/librustc_const_eval/lib.rs
@@ -28,6 +28,7 @@
 #![feature(slice_patterns)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(const_fn)]
 
 extern crate arena;
 #[macro_use] extern crate syntax;
@@ -41,6 +42,8 @@ extern crate graphviz;
 extern crate syntax_pos;
 extern crate serialize as rustc_serialize; // used by deriving
 
+extern crate rustc_i128;
+
 // NB: This module needs to be declared first so diagnostics are
 // registered before they are used.
 pub mod diagnostics;
diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs
index e93178c89c2..b122d97a702 100644
--- a/src/librustc_const_eval/pattern.rs
+++ b/src/librustc_const_eval/pattern.rs
@@ -10,16 +10,17 @@
 
 use eval;
 
+use rustc::lint;
 use rustc::middle::const_val::ConstVal;
 use rustc::mir::{Field, BorrowKind, Mutability};
 use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
 use rustc::hir::{self, PatKind};
-use rustc::hir::def::Def;
-use rustc::hir::def_id::DefId;
+use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::pat_util::EnumerateAndAdjustIterator;
 
 use rustc_data_structures::indexed_vec::Idx;
 
+use std::fmt;
 use syntax::ast;
 use syntax::ptr::P;
 use syntax_pos::Span;
@@ -27,7 +28,6 @@ use syntax_pos::Span;
 #[derive(Clone, Debug)]
 pub enum PatternError {
     StaticInPattern(Span),
-    BadConstInPattern(Span, DefId),
     ConstEval(eval::ConstEvalErr),
 }
 
@@ -105,6 +105,158 @@ pub enum PatternKind<'tcx> {
     },
 }
 
+fn print_const_val(value: &ConstVal, f: &mut fmt::Formatter) -> fmt::Result {
+    match *value {
+        ConstVal::Float(ref x) => write!(f, "{}", x),
+        ConstVal::Integral(ref i) => write!(f, "{}", i),
+        ConstVal::Str(ref s) => write!(f, "{:?}", &s[..]),
+        ConstVal::ByteStr(ref b) => write!(f, "{:?}", &b[..]),
+        ConstVal::Bool(b) => write!(f, "{:?}", b),
+        ConstVal::Char(c) => write!(f, "{:?}", c),
+        ConstVal::Struct(_) |
+        ConstVal::Tuple(_) |
+        ConstVal::Function(_) |
+        ConstVal::Array(..) |
+        ConstVal::Repeat(..) |
+        ConstVal::Dummy => bug!("{:?} not printable in a pattern", value)
+    }
+}
+
+impl<'tcx> fmt::Display for Pattern<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self.kind {
+            PatternKind::Wild => write!(f, "_"),
+            PatternKind::Binding { mutability, name, mode, ref subpattern, .. } => {
+                let is_mut = match mode {
+                    BindingMode::ByValue => mutability == Mutability::Mut,
+                    BindingMode::ByRef(_, bk) => {
+                        write!(f, "ref ")?;
+                        bk == BorrowKind::Mut
+                    }
+                };
+                if is_mut {
+                    write!(f, "mut ")?;
+                }
+                write!(f, "{}", name)?;
+                if let Some(ref subpattern) = *subpattern {
+                    write!(f, " @ {}", subpattern)?;
+                }
+                Ok(())
+            }
+            PatternKind::Variant { ref subpatterns, .. } |
+            PatternKind::Leaf { ref subpatterns } => {
+                let variant = match *self.kind {
+                    PatternKind::Variant { adt_def, variant_index, .. } => {
+                        Some(&adt_def.variants[variant_index])
+                    }
+                    _ => if let ty::TyAdt(adt, _) = self.ty.sty {
+                        Some(adt.struct_variant())
+                    } else {
+                        None
+                    }
+                };
+
+                let mut first = true;
+                let mut start_or_continue = || if first { first = false; "" } else { ", " };
+
+                if let Some(variant) = variant {
+                    write!(f, "{}", variant.name)?;
+
+                    // Only for TyAdt we can have `S {...}`,
+                    // which we handle separately here.
+                    if variant.ctor_kind == CtorKind::Fictive {
+                        write!(f, " {{ ")?;
+
+                        let mut printed = 0;
+                        for p in subpatterns {
+                            if let PatternKind::Wild = *p.pattern.kind {
+                                continue;
+                            }
+                            let name = variant.fields[p.field.index()].name;
+                            write!(f, "{}{}: {}", start_or_continue(), name, p.pattern)?;
+                            printed += 1;
+                        }
+
+                        if printed < variant.fields.len() {
+                            write!(f, "{}..", start_or_continue())?;
+                        }
+
+                        return write!(f, " }}");
+                    }
+                }
+
+                let num_fields = variant.map_or(subpatterns.len(), |v| v.fields.len());
+                if num_fields != 0 || variant.is_none() {
+                    write!(f, "(")?;
+                    for i in 0..num_fields {
+                        write!(f, "{}", start_or_continue())?;
+
+                        // Common case: the field is where we expect it.
+                        if let Some(p) = subpatterns.get(i) {
+                            if p.field.index() == i {
+                                write!(f, "{}", p.pattern)?;
+                                continue;
+                            }
+                        }
+
+                        // Otherwise, we have to go looking for it.
+                        if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
+                            write!(f, "{}", p.pattern)?;
+                        } else {
+                            write!(f, "_")?;
+                        }
+                    }
+                    write!(f, ")")?;
+                }
+
+                Ok(())
+            }
+            PatternKind::Deref { ref subpattern } => {
+                match self.ty.sty {
+                    ty::TyBox(_) => write!(f, "box ")?,
+                    ty::TyRef(_, mt) => {
+                        write!(f, "&")?;
+                        if mt.mutbl == hir::MutMutable {
+                            write!(f, "mut ")?;
+                        }
+                    }
+                    _ => bug!("{} is a bad Deref pattern type", self.ty)
+                }
+                write!(f, "{}", subpattern)
+            }
+            PatternKind::Constant { ref value } => {
+                print_const_val(value, f)
+            }
+            PatternKind::Range { ref lo, ref hi } => {
+                print_const_val(lo, f)?;
+                write!(f, "...")?;
+                print_const_val(hi, f)
+            }
+            PatternKind::Slice { ref prefix, ref slice, ref suffix } |
+            PatternKind::Array { ref prefix, ref slice, ref suffix } => {
+                let mut first = true;
+                let mut start_or_continue = || if first { first = false; "" } else { ", " };
+                write!(f, "[")?;
+                for p in prefix {
+                    write!(f, "{}{}", start_or_continue(), p)?;
+                }
+                if let Some(ref slice) = *slice {
+                    write!(f, "{}", start_or_continue())?;
+                    match *slice.kind {
+                        PatternKind::Wild => {}
+                        _ => write!(f, "{}", slice)?
+                    }
+                    write!(f, "..")?;
+                }
+                for p in suffix {
+                    write!(f, "{}{}", start_or_continue(), p)?;
+                }
+                write!(f, "]")
+            }
+        }
+    }
+}
+
 pub struct PatternContext<'a, 'gcx: 'tcx, 'tcx: 'a> {
     pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
     pub errors: Vec<PatternError>,
@@ -133,64 +285,20 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
         let kind = match pat.node {
             PatKind::Wild => PatternKind::Wild,
 
-            PatKind::Lit(ref value) => {
-                match eval::eval_const_expr_checked(self.tcx.global_tcx(), value) {
-                    Ok(value) => {
-                        PatternKind::Constant { value: value }
-                    }
-                    Err(e) => {
-                        self.errors.push(PatternError::ConstEval(e));
-                        PatternKind::Wild
-                    }
-                }
-            }
+            PatKind::Lit(ref value) => self.lower_lit(value),
 
             PatKind::Range(ref lo, ref hi) => {
-                let r_lo = eval::eval_const_expr_checked(self.tcx.global_tcx(), lo);
-                if let Err(ref e_lo) = r_lo {
-                    self.errors.push(PatternError::ConstEval(e_lo.clone()));
-                }
-
-                let r_hi = eval::eval_const_expr_checked(self.tcx.global_tcx(), hi);
-                if let Err(ref e_hi) = r_hi {
-                    self.errors.push(PatternError::ConstEval(e_hi.clone()));
-                }
-
-                if let (Ok(lo), Ok(hi)) = (r_lo, r_hi) {
-                    PatternKind::Range { lo: lo, hi: hi }
-                } else {
-                    PatternKind::Wild
+                match (self.lower_lit(lo), self.lower_lit(hi)) {
+                    (PatternKind::Constant { value: lo },
+                     PatternKind::Constant { value: hi }) => {
+                        PatternKind::Range { lo: lo, hi: hi }
+                    }
+                    _ => PatternKind::Wild
                 }
             }
 
             PatKind::Path(ref qpath) => {
-                let def = self.tcx.tables().qpath_def(qpath, pat.id);
-                match def {
-                    Def::Const(def_id) | Def::AssociatedConst(def_id) => {
-                        let tcx = self.tcx.global_tcx();
-                        let substs = tcx.tables().node_id_item_substs(pat.id)
-                            .unwrap_or_else(|| tcx.intern_substs(&[]));
-                        match eval::lookup_const_by_id(tcx, def_id, Some(substs)) {
-                            Some((const_expr, _const_ty)) => {
-                                match eval::const_expr_to_pat(
-                                    tcx, const_expr, pat.id, pat.span)
-                                {
-                                    Ok(pat) => return self.lower_pattern(&pat),
-                                    Err(_) => {
-                                        self.errors.push(PatternError::BadConstInPattern(
-                                            pat.span, def_id));
-                                        PatternKind::Wild
-                                    }
-                                }
-                            }
-                            None => {
-                                self.errors.push(PatternError::StaticInPattern(pat.span));
-                                PatternKind::Wild
-                            }
-                        }
-                    }
-                    _ => self.lower_variant_or_leaf(def, vec![])
-                }
+                return self.lower_path(qpath, pat.id, pat.id, pat.span);
             }
 
             PatKind::Ref(ref subpattern, _) |
@@ -447,6 +555,174 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
             _ => bug!()
         }
     }
+
+    fn lower_path(&mut self,
+                  qpath: &hir::QPath,
+                  id: ast::NodeId,
+                  pat_id: ast::NodeId,
+                  span: Span)
+                  -> Pattern<'tcx> {
+        let def = self.tcx.tables().qpath_def(qpath, id);
+        let kind = match def {
+            Def::Const(def_id) | Def::AssociatedConst(def_id) => {
+                let tcx = self.tcx.global_tcx();
+                let substs = tcx.tables().node_id_item_substs(id)
+                    .unwrap_or_else(|| tcx.intern_substs(&[]));
+                match eval::lookup_const_by_id(tcx, def_id, Some(substs)) {
+                    Some((const_expr, _const_ty)) => {
+                        return self.lower_const_expr(const_expr, pat_id, span);
+                    }
+                    None => {
+                        self.errors.push(PatternError::StaticInPattern(span));
+                        PatternKind::Wild
+                    }
+                }
+            }
+            _ => self.lower_variant_or_leaf(def, vec![])
+        };
+
+        Pattern {
+            span: span,
+            ty: self.tcx.tables().node_id_to_type(id),
+            kind: Box::new(kind),
+        }
+    }
+
+    fn lower_lit(&mut self, expr: &hir::Expr) -> PatternKind<'tcx> {
+        match eval::eval_const_expr_checked(self.tcx.global_tcx(), expr) {
+            Ok(value) => {
+                PatternKind::Constant { value: value }
+            }
+            Err(e) => {
+                self.errors.push(PatternError::ConstEval(e));
+                PatternKind::Wild
+            }
+        }
+    }
+
+    fn lower_const_expr(&mut self,
+                        expr: &hir::Expr,
+                        pat_id: ast::NodeId,
+                        span: Span)
+                        -> Pattern<'tcx> {
+        let pat_ty = self.tcx.tables().expr_ty(expr);
+        debug!("expr={:?} pat_ty={:?} pat_id={}", expr, pat_ty, pat_id);
+        match pat_ty.sty {
+            ty::TyFloat(_) => {
+                self.tcx.sess.add_lint(
+                    lint::builtin::ILLEGAL_FLOATING_POINT_CONSTANT_PATTERN,
+                    pat_id,
+                    span,
+                    format!("floating point constants cannot be used in patterns"));
+            }
+            ty::TyAdt(adt_def, _) if adt_def.is_union() => {
+                // Matching on union fields is unsafe, we can't hide it in constants
+                self.tcx.sess.span_err(span, "cannot use unions in constant patterns");
+            }
+            ty::TyAdt(adt_def, _) => {
+                if !self.tcx.has_attr(adt_def.did, "structural_match") {
+                    self.tcx.sess.add_lint(
+                        lint::builtin::ILLEGAL_STRUCT_OR_ENUM_CONSTANT_PATTERN,
+                        pat_id,
+                        span,
+                        format!("to use a constant of type `{}` \
+                                 in a pattern, \
+                                 `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
+                                self.tcx.item_path_str(adt_def.did),
+                                self.tcx.item_path_str(adt_def.did)));
+                }
+            }
+            _ => { }
+        }
+        let kind = match expr.node {
+            hir::ExprTup(ref exprs) => {
+                PatternKind::Leaf {
+                    subpatterns: exprs.iter().enumerate().map(|(i, expr)| {
+                        FieldPattern {
+                            field: Field::new(i),
+                            pattern: self.lower_const_expr(expr, pat_id, span)
+                        }
+                    }).collect()
+                }
+            }
+
+            hir::ExprCall(ref callee, ref args) => {
+                let qpath = match callee.node {
+                    hir::ExprPath(ref qpath) => qpath,
+                    _ => bug!()
+                };
+                let def = self.tcx.tables().qpath_def(qpath, callee.id);
+                match def {
+                    Def::Fn(..) | Def::Method(..) => self.lower_lit(expr),
+                    _ => {
+                        let subpatterns = args.iter().enumerate().map(|(i, expr)| {
+                            FieldPattern {
+                                field: Field::new(i),
+                                pattern: self.lower_const_expr(expr, pat_id, span)
+                            }
+                        }).collect();
+                        self.lower_variant_or_leaf(def, subpatterns)
+                    }
+                }
+            }
+
+            hir::ExprStruct(ref qpath, ref fields, None) => {
+                let def = self.tcx.tables().qpath_def(qpath, expr.id);
+                let pat_ty = self.tcx.tables().node_id_to_type(expr.id);
+                let adt_def = match pat_ty.sty {
+                    ty::TyAdt(adt_def, _) => adt_def,
+                    _ => {
+                        span_bug!(
+                            expr.span,
+                            "struct expr without ADT type");
+                    }
+                };
+                let variant_def = adt_def.variant_of_def(def);
+
+                let subpatterns =
+                    fields.iter()
+                          .map(|field| {
+                              let index = variant_def.index_of_field_named(field.name.node);
+                              let index = index.unwrap_or_else(|| {
+                                  span_bug!(
+                                      expr.span,
+                                      "no field with name {:?}",
+                                      field.name);
+                              });
+                              FieldPattern {
+                                  field: Field::new(index),
+                                  pattern: self.lower_const_expr(&field.expr, pat_id, span),
+                              }
+                          })
+                          .collect();
+
+                self.lower_variant_or_leaf(def, subpatterns)
+            }
+
+            hir::ExprArray(ref exprs) => {
+                let pats = exprs.iter()
+                                .map(|expr| self.lower_const_expr(expr, pat_id, span))
+                                .collect();
+                PatternKind::Array {
+                    prefix: pats,
+                    slice: None,
+                    suffix: vec![]
+                }
+            }
+
+            hir::ExprPath(ref qpath) => {
+                return self.lower_path(qpath, expr.id, pat_id, span);
+            }
+
+            _ => self.lower_lit(expr)
+        };
+
+        Pattern {
+            span: span,
+            ty: pat_ty,
+            kind: Box::new(kind),
+        }
+    }
 }
 
 pub trait PatternFoldable<'tcx> : Sized {
diff --git a/src/librustc_const_math/Cargo.toml b/src/librustc_const_math/Cargo.toml
index 10aadabe22e..3d7a4865e45 100644
--- a/src/librustc_const_math/Cargo.toml
+++ b/src/librustc_const_math/Cargo.toml
@@ -12,3 +12,4 @@ crate-type = ["dylib"]
 log = { path = "../liblog" }
 serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
+rustc_i128 = { path = "../librustc_i128" }
diff --git a/src/librustc_const_math/err.rs b/src/librustc_const_math/err.rs
index e2e30ef026c..1e9c2badd68 100644
--- a/src/librustc_const_math/err.rs
+++ b/src/librustc_const_math/err.rs
@@ -74,11 +74,13 @@ impl ConstMathErr {
             ULitOutOfRange(ast::UintTy::U16) => "literal out of range for u16",
             ULitOutOfRange(ast::UintTy::U32) => "literal out of range for u32",
             ULitOutOfRange(ast::UintTy::U64) => "literal out of range for u64",
+            ULitOutOfRange(ast::UintTy::U128) => "literal out of range for u128",
             ULitOutOfRange(ast::UintTy::Us) => "literal out of range for usize",
             LitOutOfRange(ast::IntTy::I8) => "literal out of range for i8",
             LitOutOfRange(ast::IntTy::I16) => "literal out of range for i16",
             LitOutOfRange(ast::IntTy::I32) => "literal out of range for i32",
             LitOutOfRange(ast::IntTy::I64) => "literal out of range for i64",
+            LitOutOfRange(ast::IntTy::I128) => "literal out of range for i128",
             LitOutOfRange(ast::IntTy::Is) => "literal out of range for isize",
         }
     }
diff --git a/src/librustc_const_math/int.rs b/src/librustc_const_math/int.rs
index 28a58878472..59eb4b70aa8 100644
--- a/src/librustc_const_math/int.rs
+++ b/src/librustc_const_math/int.rs
@@ -11,6 +11,7 @@
 use std::cmp::Ordering;
 use syntax::attr::IntType;
 use syntax::ast::{IntTy, UintTy};
+use rustc_i128::{i128, u128};
 
 use super::is::*;
 use super::us::*;
@@ -22,45 +23,98 @@ pub enum ConstInt {
     I16(i16),
     I32(i32),
     I64(i64),
+    I128(i128),
     Isize(ConstIsize),
     U8(u8),
     U16(u16),
     U32(u32),
     U64(u64),
+    U128(u128),
     Usize(ConstUsize),
-    Infer(u64),
-    InferSigned(i64),
+    Infer(u128),
+    InferSigned(i128),
 }
 pub use self::ConstInt::*;
 
 
 macro_rules! bounds {
-    ($($t:ident $min:ident $max:ident)*) => {
-        mod as_u64 {
-            $(
-                #[allow(dead_code)]
-                pub const $min: u64 = ::std::$t::MIN as u64;
-                #[allow(dead_code)]
-                pub const $max: u64 = ::std::$t::MAX as u64;
-            )*
-        }
-        mod as_i64 {
-            $(
-                #[allow(dead_code)]
-                pub const $min: i64 = ::std::$t::MIN as i64;
-                #[allow(dead_code)]
-                pub const $max: i64 = ::std::$t::MAX as i64;
-            )*
-        }
+    ($ct: ty, $($t:ident $min:ident $max:ident)*) => {
+        $(
+            pub const $min: $ct = $t::min_value() as $ct;
+            pub const $max: $ct = $t::max_value() as $ct;
+        )*
+    };
+    ($ct: ty: $min_val: expr, $($t:ident $min:ident $max:ident)*) => {
+        $(
+            pub const $min: $ct = $min_val;
+            pub const $max: $ct = $t::max_value() as $ct;
+        )*
+    }
+}
+
+mod ubounds {
+    #![allow(dead_code)]
+    use rustc_i128::{u128, i128};
+    bounds!{u128: 0,
+        i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX i128 I128MIN I128MAX
+        u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX u64 U64MIN U64MAX u128 U128MIN U128MAX
+        // do not add constants for isize/usize, because these are guaranteed to be wrong for
+        // arbitrary host/target combinations
     }
 }
 
-bounds!{
-    i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX isize IMIN IMAX
-    u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX u64 U64MIN U64MAX usize UMIN UMAX
+mod ibounds {
+    #![allow(dead_code)]
+    use rustc_i128::i128;
+    #[cfg(stage0)]
+    pub const U64MIN: i128 = 0;
+    #[cfg(stage0)]
+    pub const U64MAX: i128 = i128::max_value();
+    #[cfg(not(stage0))]
+    bounds!(i128, u64 U64MIN U64MAX);
+
+    pub const U128MIN: i128 = 0;
+    pub const U128MAX: i128 = i128::max_value();
+
+    bounds!{i128,
+        i8 I8MIN I8MAX i16 I16MIN I16MAX i32 I32MIN I32MAX i64 I64MIN I64MAX i128 I128MIN I128MAX
+        u8 U8MIN U8MAX u16 U16MIN U16MAX u32 U32MIN U32MAX
+        // do not add constants for isize/usize, because these are guaranteed to be wrong for
+        // arbitrary host/target combinations
+    }
 }
 
 impl ConstInt {
+    /// Creates a new unsigned ConstInt with matching type while also checking that overflow does
+    /// not happen.
+    pub fn new_unsigned(val: u128, ty: UintTy, usize_ty: UintTy) -> Option<ConstInt> {
+        match ty {
+            UintTy::U8 if val <= ubounds::U8MAX => Some(U8(val as u8)),
+            UintTy::U16 if val <= ubounds::U16MAX => Some(U16(val as u16)),
+            UintTy::U32 if val <= ubounds::U32MAX => Some(U32(val as u32)),
+            UintTy::U64 if val <= ubounds::U64MAX => Some(U64(val as u64)),
+            UintTy::Us if val <= ubounds::U64MAX => ConstUsize::new(val as u64, usize_ty).ok()
+                .map(Usize),
+            UintTy::U128 => Some(U128(val)),
+            _ => None
+        }
+    }
+
+    /// Creates a new unsigned ConstInt with matching type while also checking that overflow does
+    /// not happen.
+    pub fn new_signed(val: i128, ty: IntTy, isize_ty: IntTy) -> Option<ConstInt> {
+        match ty {
+            IntTy::I8 if val <= ibounds::I8MAX => Some(I8(val as i8)),
+            IntTy::I16 if val <= ibounds::I16MAX => Some(I16(val as i16)),
+            IntTy::I32 if val <= ibounds::I32MAX => Some(I32(val as i32)),
+            IntTy::I64 if val <= ibounds::I64MAX => Some(I64(val as i64)),
+            IntTy::Is if val <= ibounds::I64MAX => ConstIsize::new(val as i64, isize_ty).ok()
+                .map(Isize),
+            IntTy::I128 => Some(I128(val)),
+            _ => None
+        }
+    }
+
     /// If either value is `Infer` or `InferSigned`, try to turn the value into the type of
     /// the other value. If both values have no type, don't do anything
     pub fn infer(self, other: Self) -> Result<(Self, Self), ConstMathErr> {
@@ -68,46 +122,54 @@ impl ConstInt {
             (InferSigned(_), InferSigned(_))
             | (Infer(_), Infer(_)) => self, // no inference possible
             // kindof wrong, you could have had values > I64MAX during computation of a
-            (Infer(a @ 0...as_u64::I64MAX), InferSigned(_)) => InferSigned(a as i64),
+            (Infer(a @ 0...ubounds::I64MAX), InferSigned(_)) => InferSigned(a as i128),
             (Infer(_), InferSigned(_)) => return Err(ConstMathErr::NotInRange),
             (_, InferSigned(_))
             | (_, Infer(_)) => return other.infer(self).map(|(b, a)| (a, b)),
 
-            (Infer(a @ 0...as_u64::I8MAX), I8(_)) => I8(a as i64 as i8),
-            (Infer(a @ 0...as_u64::I16MAX), I16(_)) => I16(a as i64 as i16),
-            (Infer(a @ 0...as_u64::I32MAX), I32(_)) => I32(a as i64 as i32),
-            (Infer(a @ 0...as_u64::I64MAX), I64(_)) => I64(a as i64),
-            (Infer(a @ 0...as_u64::I16MAX), Isize(Is16(_))) => Isize(Is16(a as i64 as i16)),
-            (Infer(a @ 0...as_u64::I32MAX), Isize(Is32(_))) => Isize(Is32(a as i64 as i32)),
-            (Infer(a @ 0...as_u64::I64MAX), Isize(Is64(_))) => Isize(Is64(a as i64)),
-            (Infer(a @ 0...as_u64::U8MAX), U8(_)) => U8(a as u8),
-            (Infer(a @ 0...as_u64::U16MAX), U16(_)) => U16(a as u16),
-            (Infer(a @ 0...as_u64::U32MAX), U32(_)) => U32(a as u32),
-            (Infer(a), U64(_)) => U64(a),
-            (Infer(a @ 0...as_u64::U16MAX), Usize(Us16(_))) => Usize(Us16(a as u16)),
-            (Infer(a @ 0...as_u64::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)),
-            (Infer(a), Usize(Us64(_))) => Usize(Us64(a)),
+            (Infer(a @ 0...ubounds::I8MAX), I8(_)) => I8(a as i64 as i8),
+            (Infer(a @ 0...ubounds::I16MAX), I16(_)) => I16(a as i64 as i16),
+            (Infer(a @ 0...ubounds::I32MAX), I32(_)) => I32(a as i64 as i32),
+            (Infer(a @ 0...ubounds::I64MAX), I64(_)) => I64(a as i64),
+            (Infer(a @ 0...ubounds::I128MAX), I128(_)) => I128(a as i128),
+            (Infer(a @ 0...ubounds::I16MAX), Isize(Is16(_))) => Isize(Is16(a as i64 as i16)),
+            (Infer(a @ 0...ubounds::I32MAX), Isize(Is32(_))) => Isize(Is32(a as i64 as i32)),
+            (Infer(a @ 0...ubounds::I64MAX), Isize(Is64(_))) => Isize(Is64(a as i64)),
+            (Infer(a @ 0...ubounds::U8MAX), U8(_)) => U8(a as u8),
+            (Infer(a @ 0...ubounds::U16MAX), U16(_)) => U16(a as u16),
+            (Infer(a @ 0...ubounds::U32MAX), U32(_)) => U32(a as u32),
+            (Infer(a @ 0...ubounds::U64MAX), U64(_)) => U64(a as u64),
+            (Infer(a @ 0...ubounds::U128MAX), U128(_)) => U128(a as u128),
+            (Infer(a @ 0...ubounds::U16MAX), Usize(Us16(_))) => Usize(Us16(a as u16)),
+            (Infer(a @ 0...ubounds::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)),
+            (Infer(a @ 0...ubounds::U64MAX), Usize(Us64(_))) => Usize(Us64(a as u64)),
 
             (Infer(_), _) => return Err(ConstMathErr::NotInRange),
 
-            (InferSigned(a @ as_i64::I8MIN...as_i64::I8MAX), I8(_)) => I8(a as i8),
-            (InferSigned(a @ as_i64::I16MIN...as_i64::I16MAX), I16(_)) => I16(a as i16),
-            (InferSigned(a @ as_i64::I32MIN...as_i64::I32MAX), I32(_)) => I32(a as i32),
-            (InferSigned(a), I64(_)) => I64(a),
-            (InferSigned(a @ as_i64::I16MIN...as_i64::I16MAX), Isize(Is16(_))) => {
+            (InferSigned(a @ ibounds::I8MIN...ibounds::I8MAX), I8(_)) => I8(a as i8),
+            (InferSigned(a @ ibounds::I16MIN...ibounds::I16MAX), I16(_)) => I16(a as i16),
+            (InferSigned(a @ ibounds::I32MIN...ibounds::I32MAX), I32(_)) => I32(a as i32),
+            (InferSigned(a @ ibounds::I64MIN...ibounds::I64MAX), I64(_)) => I64(a as i64),
+            (InferSigned(a @ ibounds::I128MIN...ibounds::I128MAX), I128(_)) => I128(a as i128),
+            (InferSigned(a @ ibounds::I16MIN...ibounds::I16MAX), Isize(Is16(_))) => {
                 Isize(Is16(a as i16))
             },
-            (InferSigned(a @ as_i64::I32MIN...as_i64::I32MAX), Isize(Is32(_))) => {
+            (InferSigned(a @ ibounds::I32MIN...ibounds::I32MAX), Isize(Is32(_))) => {
                 Isize(Is32(a as i32))
             },
-            (InferSigned(a), Isize(Is64(_))) => Isize(Is64(a)),
-            (InferSigned(a @ 0...as_i64::U8MAX), U8(_)) => U8(a as u8),
-            (InferSigned(a @ 0...as_i64::U16MAX), U16(_)) => U16(a as u16),
-            (InferSigned(a @ 0...as_i64::U32MAX), U32(_)) => U32(a as u32),
-            (InferSigned(a @ 0...as_i64::I64MAX), U64(_)) => U64(a as u64),
-            (InferSigned(a @ 0...as_i64::U16MAX), Usize(Us16(_))) => Usize(Us16(a as u16)),
-            (InferSigned(a @ 0...as_i64::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)),
-            (InferSigned(a @ 0...as_i64::I64MAX), Usize(Us64(_))) => Usize(Us64(a as u64)),
+            (InferSigned(a @ ibounds::I64MIN...ibounds::I64MAX), Isize(Is64(_))) => {
+                Isize(Is64(a as i64))
+            },
+            (InferSigned(a @ 0...ibounds::U8MAX), U8(_)) => U8(a as u8),
+            (InferSigned(a @ 0...ibounds::U16MAX), U16(_)) => U16(a as u16),
+            (InferSigned(a @ 0...ibounds::U32MAX), U32(_)) => U32(a as u32),
+            // SNAP: replace with U64MAX
+            (InferSigned(a @ 0...ibounds::I64MAX), U64(_)) => U64(a as u64),
+            (InferSigned(a @ 0...ibounds::I128MAX), U128(_)) => U128(a as u128),
+            (InferSigned(a @ 0...ibounds::U16MAX), Usize(Us16(_))) => Usize(Us16(a as u16)),
+            (InferSigned(a @ 0...ibounds::U32MAX), Usize(Us32(_))) => Usize(Us32(a as u32)),
+            // SNAP: replace with U64MAX
+            (InferSigned(a @ 0...ibounds::I64MAX), Usize(Us64(_))) => Usize(Us64(a as u64)),
             (InferSigned(_), _) => return Err(ConstMathErr::NotInRange),
             _ => self, // already known types
         };
@@ -119,28 +181,31 @@ impl ConstInt {
         match self {
             Infer(i) => Infer(i),
             InferSigned(i) if i < 0 => InferSigned(i),
-            I8(i) if i < 0 => InferSigned(i as i64),
-            I16(i) if i < 0 => InferSigned(i as i64),
-            I32(i) if i < 0 => InferSigned(i as i64),
-            I64(i) if i < 0 => InferSigned(i as i64),
-            Isize(Is16(i)) if i < 0 => InferSigned(i as i64),
-            Isize(Is32(i)) if i < 0 => InferSigned(i as i64),
-            Isize(Is64(i)) if i < 0 => InferSigned(i as i64),
-            InferSigned(i) => Infer(i as u64),
-            I8(i) => Infer(i as u64),
-            I16(i) => Infer(i as u64),
-            I32(i) => Infer(i as u64),
-            I64(i) => Infer(i as u64),
-            Isize(Is16(i)) => Infer(i as u64),
-            Isize(Is32(i)) => Infer(i as u64),
-            Isize(Is64(i)) => Infer(i as u64),
-            U8(i) => Infer(i as u64),
-            U16(i) => Infer(i as u64),
-            U32(i) => Infer(i as u64),
-            U64(i) => Infer(i as u64),
-            Usize(Us16(i)) => Infer(i as u64),
-            Usize(Us32(i)) => Infer(i as u64),
-            Usize(Us64(i)) => Infer(i),
+            I8(i) if i < 0 => InferSigned(i as i128),
+            I16(i) if i < 0 => InferSigned(i as i128),
+            I32(i) if i < 0 => InferSigned(i as i128),
+            I64(i) if i < 0 => InferSigned(i as i128),
+            I128(i) if i < 0 => InferSigned(i as i128),
+            Isize(Is16(i)) if i < 0 => InferSigned(i as i128),
+            Isize(Is32(i)) if i < 0 => InferSigned(i as i128),
+            Isize(Is64(i)) if i < 0 => InferSigned(i as i128),
+            InferSigned(i) => Infer(i as u128),
+            I8(i) => Infer(i as u128),
+            I16(i) => Infer(i as u128),
+            I32(i) => Infer(i as u128),
+            I64(i) => Infer(i as u128),
+            I128(i) => Infer(i as u128),
+            Isize(Is16(i)) => Infer(i as u128),
+            Isize(Is32(i)) => Infer(i as u128),
+            Isize(Is64(i)) => Infer(i as u128),
+            U8(i) => Infer(i as u128),
+            U16(i) => Infer(i as u128),
+            U32(i) => Infer(i as u128),
+            U64(i) => Infer(i as u128),
+            U128(i) => Infer(i as u128),
+            Usize(Us16(i)) => Infer(i as u128),
+            Usize(Us32(i)) => Infer(i as u128),
+            Usize(Us64(i)) => Infer(i as u128),
         }
     }
 
@@ -153,67 +218,66 @@ impl ConstInt {
             I16(_) => "i16",
             I32(_) => "i32",
             I64(_) => "i64",
+            I128(_) => "i128",
             Isize(_) => "isize",
             U8(_) => "u8",
             U16(_) => "u16",
             U32(_) => "u32",
             U64(_) => "u64",
+            U128(_) => "u128",
             Usize(_) => "usize",
         }
     }
 
-    /// Erases the type and returns a u64.
-    /// This is not the same as `-5i8 as u64` but as `-5i8 as i64 as u64`
-    pub fn to_u64_unchecked(self) -> u64 {
+    /// Erases the type and returns a u128.
+    /// This is not the same as `-5i8 as u128` but as `-5i8 as i128 as u128`
+    pub fn to_u128_unchecked(self) -> u128 {
         match self.erase_type() {
             ConstInt::Infer(i) => i,
-            ConstInt::InferSigned(i) => i as u64,
+            ConstInt::InferSigned(i) => i as u128,
             _ => unreachable!(),
         }
     }
 
     /// Converts the value to a `u32` if it's in the range 0...std::u32::MAX
     pub fn to_u32(&self) -> Option<u32> {
-        match *self {
-            I8(v) if v >= 0 => Some(v as u32),
-            I16(v) if v >= 0 => Some(v as u32),
-            I32(v) if v >= 0 => Some(v as u32),
-            InferSigned(v)
-            | Isize(Is64(v))
-            | I64(v) if v >= 0 && v <= ::std::u32::MAX as i64 => Some(v as u32),
-            Isize(Is32(v)) if v >= 0 => Some(v as u32),
-            Isize(Is16(v)) if v >= 0 => Some(v as u32),
-            U8(v) => Some(v as u32),
-            U16(v) => Some(v as u32),
-            U32(v) => Some(v),
-            Infer(v)
-            | Usize(Us64(v))
-            | U64(v) if v <= ::std::u32::MAX as u64 => Some(v as u32),
-            Usize(Us32(v)) => Some(v),
-            Usize(Us16(v)) => Some(v as u32),
-            _ => None,
-        }
+        self.to_u128().and_then(|v| if v <= u32::max_value() as u128 {
+            Some(v as u32)
+        } else {
+            None
+        })
     }
 
-    /// Converts the value to a `u64` if it's >= 0
+    /// Converts the value to a `u64` if it's in the range 0...std::u64::MAX
     pub fn to_u64(&self) -> Option<u64> {
+        self.to_u128().and_then(|v| if v <= u64::max_value() as u128 {
+            Some(v as u64)
+        } else {
+            None
+        })
+    }
+
+    /// Converts the value to a `u128` if it's in the range 0...std::u128::MAX
+    pub fn to_u128(&self) -> Option<u128> {
         match *self {
             Infer(v) => Some(v),
-            InferSigned(v) if v >= 0 => Some(v as u64),
-            I8(v) if v >= 0 => Some(v as u64),
-            I16(v) if v >= 0 => Some(v as u64),
-            I32(v) if v >= 0 => Some(v as u64),
-            I64(v) if v >= 0 => Some(v as u64),
-            Isize(Is16(v)) if v >= 0 => Some(v as u64),
-            Isize(Is32(v)) if v >= 0 => Some(v as u64),
-            Isize(Is64(v)) if v >= 0 => Some(v as u64),
-            U8(v) => Some(v as u64),
-            U16(v) => Some(v as u64),
-            U32(v) => Some(v as u64),
-            U64(v) => Some(v),
-            Usize(Us16(v)) => Some(v as u64),
-            Usize(Us32(v)) => Some(v as u64),
-            Usize(Us64(v)) => Some(v),
+            InferSigned(v) if v >= 0 => Some(v as u128),
+            I8(v) if v >= 0 => Some(v as u128),
+            I16(v) if v >= 0 => Some(v as u128),
+            I32(v) if v >= 0 => Some(v as u128),
+            I64(v) if v >= 0 => Some(v as u128),
+            I128(v) if v >= 0 => Some(v as u128),
+            Isize(Is16(v)) if v >= 0 => Some(v as u128),
+            Isize(Is32(v)) if v >= 0 => Some(v as u128),
+            Isize(Is64(v)) if v >= 0 => Some(v as u128),
+            U8(v) => Some(v as u128),
+            U16(v) => Some(v as u128),
+            U32(v) => Some(v as u128),
+            U64(v) => Some(v as u128),
+            U128(v) => Some(v as u128),
+            Usize(Us16(v)) => Some(v as u128),
+            Usize(Us32(v)) => Some(v as u128),
+            Usize(Us64(v)) => Some(v as u128),
             _ => None,
         }
     }
@@ -224,6 +288,7 @@ impl ConstInt {
             I16(v) => v < 0,
             I32(v) => v < 0,
             I64(v) => v < 0,
+            I128(v) => v < 0,
             Isize(Is16(v)) => v < 0,
             Isize(Is32(v)) => v < 0,
             Isize(Is64(v)) => v < 0,
@@ -239,6 +304,7 @@ impl ConstInt {
             (I16(a), I16(b)) => Ok(a.cmp(&b)),
             (I32(a), I32(b)) => Ok(a.cmp(&b)),
             (I64(a), I64(b)) => Ok(a.cmp(&b)),
+            (I128(a), I128(b)) => Ok(a.cmp(&b)),
             (Isize(Is16(a)), Isize(Is16(b))) => Ok(a.cmp(&b)),
             (Isize(Is32(a)), Isize(Is32(b))) => Ok(a.cmp(&b)),
             (Isize(Is64(a)), Isize(Is64(b))) => Ok(a.cmp(&b)),
@@ -246,6 +312,7 @@ impl ConstInt {
             (U16(a), U16(b)) => Ok(a.cmp(&b)),
             (U32(a), U32(b)) => Ok(a.cmp(&b)),
             (U64(a), U64(b)) => Ok(a.cmp(&b)),
+            (U128(a), U128(b)) => Ok(a.cmp(&b)),
             (Usize(Us16(a)), Usize(Us16(b))) => Ok(a.cmp(&b)),
             (Usize(Us32(a)), Usize(Us32(b))) => Ok(a.cmp(&b)),
             (Usize(Us64(a)), Usize(Us64(b))) => Ok(a.cmp(&b)),
@@ -265,6 +332,7 @@ impl ConstInt {
             ConstInt::I16(i) => ConstInt::I16(add1!(i)),
             ConstInt::I32(i) => ConstInt::I32(add1!(i)),
             ConstInt::I64(i) => ConstInt::I64(add1!(i)),
+            ConstInt::I128(i) => ConstInt::I128(add1!(i)),
             ConstInt::Isize(ConstIsize::Is16(i)) => ConstInt::Isize(ConstIsize::Is16(add1!(i))),
             ConstInt::Isize(ConstIsize::Is32(i)) => ConstInt::Isize(ConstIsize::Is32(add1!(i))),
             ConstInt::Isize(ConstIsize::Is64(i)) => ConstInt::Isize(ConstIsize::Is64(add1!(i))),
@@ -272,6 +340,7 @@ impl ConstInt {
             ConstInt::U16(i) => ConstInt::U16(add1!(i)),
             ConstInt::U32(i) => ConstInt::U32(add1!(i)),
             ConstInt::U64(i) => ConstInt::U64(add1!(i)),
+            ConstInt::U128(i) => ConstInt::U128(add1!(i)),
             ConstInt::Usize(ConstUsize::Us16(i)) => ConstInt::Usize(ConstUsize::Us16(add1!(i))),
             ConstInt::Usize(ConstUsize::Us32(i)) => ConstInt::Usize(ConstUsize::Us32(add1!(i))),
             ConstInt::Usize(ConstUsize::Us64(i)) => ConstInt::Usize(ConstUsize::Us64(add1!(i))),
@@ -285,11 +354,13 @@ impl ConstInt {
             ConstInt::I16(_) => Some(IntType::SignedInt(IntTy::I16)),
             ConstInt::I32(_) => Some(IntType::SignedInt(IntTy::I32)),
             ConstInt::I64(_) => Some(IntType::SignedInt(IntTy::I64)),
+            ConstInt::I128(_) => Some(IntType::SignedInt(IntTy::I128)),
             ConstInt::Isize(_) => Some(IntType::SignedInt(IntTy::Is)),
             ConstInt::U8(_) => Some(IntType::UnsignedInt(UintTy::U8)),
             ConstInt::U16(_) => Some(IntType::UnsignedInt(UintTy::U16)),
             ConstInt::U32(_) => Some(IntType::UnsignedInt(UintTy::U32)),
             ConstInt::U64(_) => Some(IntType::UnsignedInt(UintTy::U64)),
+            ConstInt::U128(_) => Some(IntType::UnsignedInt(UintTy::U128)),
             ConstInt::Usize(_) => Some(IntType::UnsignedInt(UintTy::Us)),
             _ => None,
         }
@@ -317,6 +388,7 @@ impl ::std::fmt::Display for ConstInt {
             I16(i) => write!(fmt, "{}i16", i),
             I32(i) => write!(fmt, "{}i32", i),
             I64(i) => write!(fmt, "{}i64", i),
+            I128(i) => write!(fmt, "{}i128", i),
             Isize(ConstIsize::Is64(i)) => write!(fmt, "{}isize", i),
             Isize(ConstIsize::Is32(i)) => write!(fmt, "{}isize", i),
             Isize(ConstIsize::Is16(i)) => write!(fmt, "{}isize", i),
@@ -324,6 +396,7 @@ impl ::std::fmt::Display for ConstInt {
             U16(i) => write!(fmt, "{}u16", i),
             U32(i) => write!(fmt, "{}u32", i),
             U64(i) => write!(fmt, "{}u64", i),
+            U128(i) => write!(fmt, "{}u128", i),
             Usize(ConstUsize::Us64(i)) => write!(fmt, "{}usize", i),
             Usize(ConstUsize::Us32(i)) => write!(fmt, "{}usize", i),
             Usize(ConstUsize::Us16(i)) => write!(fmt, "{}usize", i),
@@ -351,6 +424,7 @@ macro_rules! impl_binop {
                     (I16(a), I16(b)) => a.$checked_func(b).map(I16),
                     (I32(a), I32(b)) => a.$checked_func(b).map(I32),
                     (I64(a), I64(b)) => a.$checked_func(b).map(I64),
+                    (I128(a), I128(b)) => a.$checked_func(b).map(I128),
                     (Isize(Is16(a)), Isize(Is16(b))) => a.$checked_func(b).map(Is16).map(Isize),
                     (Isize(Is32(a)), Isize(Is32(b))) => a.$checked_func(b).map(Is32).map(Isize),
                     (Isize(Is64(a)), Isize(Is64(b))) => a.$checked_func(b).map(Is64).map(Isize),
@@ -358,6 +432,7 @@ macro_rules! impl_binop {
                     (U16(a), U16(b)) => a.$checked_func(b).map(U16),
                     (U32(a), U32(b)) => a.$checked_func(b).map(U32),
                     (U64(a), U64(b)) => a.$checked_func(b).map(U64),
+                    (U128(a), U128(b)) => a.$checked_func(b).map(U128),
                     (Usize(Us16(a)), Usize(Us16(b))) => a.$checked_func(b).map(Us16).map(Usize),
                     (Usize(Us32(a)), Usize(Us32(b))) => a.$checked_func(b).map(Us32).map(Usize),
                     (Usize(Us64(a)), Usize(Us64(b))) => a.$checked_func(b).map(Us64).map(Usize),
@@ -380,6 +455,7 @@ macro_rules! derive_binop {
                     (I16(a), I16(b)) => Ok(I16(a.$func(b))),
                     (I32(a), I32(b)) => Ok(I32(a.$func(b))),
                     (I64(a), I64(b)) => Ok(I64(a.$func(b))),
+                    (I128(a), I128(b)) => Ok(I128(a.$func(b))),
                     (Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a.$func(b)))),
                     (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a.$func(b)))),
                     (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a.$func(b)))),
@@ -387,6 +463,7 @@ macro_rules! derive_binop {
                     (U16(a), U16(b)) => Ok(U16(a.$func(b))),
                     (U32(a), U32(b)) => Ok(U32(a.$func(b))),
                     (U64(a), U64(b)) => Ok(U64(a.$func(b))),
+                    (U128(a), U128(b)) => Ok(U128(a.$func(b))),
                     (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a.$func(b)))),
                     (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a.$func(b)))),
                     (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a.$func(b)))),
@@ -406,6 +483,11 @@ derive_binop!(BitAnd, bitand);
 derive_binop!(BitOr, bitor);
 derive_binop!(BitXor, bitxor);
 
+#[cfg(not(stage0))]
+const I128_MIN: i128 = ::std::i128::MIN;
+#[cfg(stage0)]
+const I128_MIN: i128 = ::std::i64::MIN;
+
 fn check_division(
     lhs: ConstInt,
     rhs: ConstInt,
@@ -417,6 +499,7 @@ fn check_division(
         (I16(_), I16(0)) => Err(zerr),
         (I32(_), I32(0)) => Err(zerr),
         (I64(_), I64(0)) => Err(zerr),
+        (I128(_), I128(0)) => Err(zerr),
         (Isize(_), Isize(Is16(0))) => Err(zerr),
         (Isize(_), Isize(Is32(0))) => Err(zerr),
         (Isize(_), Isize(Is64(0))) => Err(zerr),
@@ -426,6 +509,7 @@ fn check_division(
         (U16(_), U16(0)) => Err(zerr),
         (U32(_), U32(0)) => Err(zerr),
         (U64(_), U64(0)) => Err(zerr),
+        (U128(_), U128(0)) => Err(zerr),
         (Usize(_), Usize(Us16(0))) => Err(zerr),
         (Usize(_), Usize(Us32(0))) => Err(zerr),
         (Usize(_), Usize(Us64(0))) => Err(zerr),
@@ -435,10 +519,11 @@ fn check_division(
         (I16(::std::i16::MIN), I16(-1)) => Err(Overflow(op)),
         (I32(::std::i32::MIN), I32(-1)) => Err(Overflow(op)),
         (I64(::std::i64::MIN), I64(-1)) => Err(Overflow(op)),
+        (I128(I128_MIN), I128(-1)) => Err(Overflow(op)),
         (Isize(Is16(::std::i16::MIN)), Isize(Is16(-1))) => Err(Overflow(op)),
         (Isize(Is32(::std::i32::MIN)), Isize(Is32(-1))) => Err(Overflow(op)),
         (Isize(Is64(::std::i64::MIN)), Isize(Is64(-1))) => Err(Overflow(op)),
-        (InferSigned(::std::i64::MIN), InferSigned(-1)) => Err(Overflow(op)),
+        (InferSigned(I128_MIN), InferSigned(-1)) => Err(Overflow(op)),
 
         _ => Ok(()),
     }
@@ -454,6 +539,7 @@ impl ::std::ops::Div for ConstInt {
             (I16(a), I16(b)) => Ok(I16(a/b)),
             (I32(a), I32(b)) => Ok(I32(a/b)),
             (I64(a), I64(b)) => Ok(I64(a/b)),
+            (I128(a), I128(b)) => Ok(I128(a/b)),
             (Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a/b))),
             (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a/b))),
             (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a/b))),
@@ -463,6 +549,7 @@ impl ::std::ops::Div for ConstInt {
             (U16(a), U16(b)) => Ok(U16(a/b)),
             (U32(a), U32(b)) => Ok(U32(a/b)),
             (U64(a), U64(b)) => Ok(U64(a/b)),
+            (U128(a), U128(b)) => Ok(U128(a/b)),
             (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a/b))),
             (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a/b))),
             (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a/b))),
@@ -484,6 +571,7 @@ impl ::std::ops::Rem for ConstInt {
             (I16(a), I16(b)) => Ok(I16(a%b)),
             (I32(a), I32(b)) => Ok(I32(a%b)),
             (I64(a), I64(b)) => Ok(I64(a%b)),
+            (I128(a), I128(b)) => Ok(I128(a%b)),
             (Isize(Is16(a)), Isize(Is16(b))) => Ok(Isize(Is16(a%b))),
             (Isize(Is32(a)), Isize(Is32(b))) => Ok(Isize(Is32(a%b))),
             (Isize(Is64(a)), Isize(Is64(b))) => Ok(Isize(Is64(a%b))),
@@ -493,6 +581,7 @@ impl ::std::ops::Rem for ConstInt {
             (U16(a), U16(b)) => Ok(U16(a%b)),
             (U32(a), U32(b)) => Ok(U32(a%b)),
             (U64(a), U64(b)) => Ok(U64(a%b)),
+            (U128(a), U128(b)) => Ok(U128(a%b)),
             (Usize(Us16(a)), Usize(Us16(b))) => Ok(Usize(Us16(a%b))),
             (Usize(Us32(a)), Usize(Us32(b))) => Ok(Usize(Us32(a%b))),
             (Usize(Us64(a)), Usize(Us64(b))) => Ok(Usize(Us64(a%b))),
@@ -512,6 +601,7 @@ impl ::std::ops::Shl<ConstInt> for ConstInt {
             I16(a) => Ok(I16(overflowing!(a.overflowing_shl(b), Op::Shl))),
             I32(a) => Ok(I32(overflowing!(a.overflowing_shl(b), Op::Shl))),
             I64(a) => Ok(I64(overflowing!(a.overflowing_shl(b), Op::Shl))),
+            I128(a) => Ok(I128(overflowing!(a.overflowing_shl(b), Op::Shl))),
             Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_shl(b), Op::Shl)))),
             Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_shl(b), Op::Shl)))),
             Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_shl(b), Op::Shl)))),
@@ -519,6 +609,7 @@ impl ::std::ops::Shl<ConstInt> for ConstInt {
             U16(a) => Ok(U16(overflowing!(a.overflowing_shl(b), Op::Shl))),
             U32(a) => Ok(U32(overflowing!(a.overflowing_shl(b), Op::Shl))),
             U64(a) => Ok(U64(overflowing!(a.overflowing_shl(b), Op::Shl))),
+            U128(a) => Ok(U128(overflowing!(a.overflowing_shl(b), Op::Shl))),
             Usize(Us16(a)) => Ok(Usize(Us16(overflowing!(a.overflowing_shl(b), Op::Shl)))),
             Usize(Us32(a)) => Ok(Usize(Us32(overflowing!(a.overflowing_shl(b), Op::Shl)))),
             Usize(Us64(a)) => Ok(Usize(Us64(overflowing!(a.overflowing_shl(b), Op::Shl)))),
@@ -537,6 +628,7 @@ impl ::std::ops::Shr<ConstInt> for ConstInt {
             I16(a) => Ok(I16(overflowing!(a.overflowing_shr(b), Op::Shr))),
             I32(a) => Ok(I32(overflowing!(a.overflowing_shr(b), Op::Shr))),
             I64(a) => Ok(I64(overflowing!(a.overflowing_shr(b), Op::Shr))),
+            I128(a) => Ok(I128(overflowing!(a.overflowing_shr(b), Op::Shr))),
             Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_shr(b), Op::Shr)))),
             Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_shr(b), Op::Shr)))),
             Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_shr(b), Op::Shr)))),
@@ -544,6 +636,7 @@ impl ::std::ops::Shr<ConstInt> for ConstInt {
             U16(a) => Ok(U16(overflowing!(a.overflowing_shr(b), Op::Shr))),
             U32(a) => Ok(U32(overflowing!(a.overflowing_shr(b), Op::Shr))),
             U64(a) => Ok(U64(overflowing!(a.overflowing_shr(b), Op::Shr))),
+            U128(a) => Ok(U128(overflowing!(a.overflowing_shr(b), Op::Shr))),
             Usize(Us16(a)) => Ok(Usize(Us16(overflowing!(a.overflowing_shr(b), Op::Shr)))),
             Usize(Us32(a)) => Ok(Usize(Us32(overflowing!(a.overflowing_shr(b), Op::Shr)))),
             Usize(Us64(a)) => Ok(Usize(Us64(overflowing!(a.overflowing_shr(b), Op::Shr)))),
@@ -561,22 +654,14 @@ impl ::std::ops::Neg for ConstInt {
             I16(a) => Ok(I16(overflowing!(a.overflowing_neg(), Op::Neg))),
             I32(a) => Ok(I32(overflowing!(a.overflowing_neg(), Op::Neg))),
             I64(a) => Ok(I64(overflowing!(a.overflowing_neg(), Op::Neg))),
+            I128(a) => Ok(I128(overflowing!(a.overflowing_neg(), Op::Neg))),
             Isize(Is16(a)) => Ok(Isize(Is16(overflowing!(a.overflowing_neg(), Op::Neg)))),
             Isize(Is32(a)) => Ok(Isize(Is32(overflowing!(a.overflowing_neg(), Op::Neg)))),
             Isize(Is64(a)) => Ok(Isize(Is64(overflowing!(a.overflowing_neg(), Op::Neg)))),
-            U8(0) => Ok(U8(0)),
-            U16(0) => Ok(U16(0)),
-            U32(0) => Ok(U32(0)),
-            U64(0) => Ok(U64(0)),
-            Usize(Us16(0)) => Ok(Usize(Us16(0))),
-            Usize(Us32(0)) => Ok(Usize(Us32(0))),
-            Usize(Us64(0)) => Ok(Usize(Us64(0))),
-            U8(_) => Err(UnsignedNegation),
-            U16(_) => Err(UnsignedNegation),
-            U32(_) => Err(UnsignedNegation),
-            U64(_) => Err(UnsignedNegation),
-            Usize(_) => Err(UnsignedNegation),
-            Infer(a @ 0...as_u64::I64MAX) => Ok(InferSigned(-(a as i64))),
+            a@U8(0) | a@U16(0) | a@U32(0) | a@U64(0) | a@U128(0) |
+            a@Usize(Us16(0)) | a@Usize(Us32(0)) | a@Usize(Us64(0)) => Ok(a),
+            U8(_) | U16(_) | U32(_) | U64(_) | U128(_) | Usize(_) => Err(UnsignedNegation),
+            Infer(a @ 0...ubounds::I64MAX) => Ok(InferSigned(-(a as i128))),
             Infer(_) => Err(Overflow(Op::Neg)),
             InferSigned(a) => Ok(InferSigned(overflowing!(a.overflowing_neg(), Op::Neg))),
         }
@@ -591,6 +676,7 @@ impl ::std::ops::Not for ConstInt {
             I16(a) => Ok(I16(!a)),
             I32(a) => Ok(I32(!a)),
             I64(a) => Ok(I64(!a)),
+            I128(a) => Ok(I128(!a)),
             Isize(Is16(a)) => Ok(Isize(Is16(!a))),
             Isize(Is32(a)) => Ok(Isize(Is32(!a))),
             Isize(Is64(a)) => Ok(Isize(Is64(!a))),
@@ -598,6 +684,7 @@ impl ::std::ops::Not for ConstInt {
             U16(a) => Ok(U16(!a)),
             U32(a) => Ok(U32(!a)),
             U64(a) => Ok(U64(!a)),
+            U128(a) => Ok(U128(!a)),
             Usize(Us16(a)) => Ok(Usize(Us16(!a))),
             Usize(Us32(a)) => Ok(Usize(Us32(!a))),
             Usize(Us64(a)) => Ok(Usize(Us64(!a))),
diff --git a/src/librustc_const_math/is.rs b/src/librustc_const_math/is.rs
index ef92b628523..19ae0c91fc5 100644
--- a/src/librustc_const_math/is.rs
+++ b/src/librustc_const_math/is.rs
@@ -10,6 +10,7 @@
 
 use syntax::ast;
 use super::err::*;
+use rustc_i128::i128;
 
 /// Depending on the target only one variant is ever used in a compilation.
 /// Anything else is an error. This invariant is checked at several locations
@@ -41,11 +42,11 @@ impl ConstIsize {
             _ => unreachable!(),
         }
     }
-    pub fn new_truncating(i: i64, target_int_ty: ast::IntTy) -> Self {
+    pub fn new_truncating(i: i128, target_int_ty: ast::IntTy) -> Self {
         match target_int_ty {
             ast::IntTy::I16 => Is16(i as i16),
             ast::IntTy::I32 => Is32(i as i32),
-            ast::IntTy::I64 => Is64(i),
+            ast::IntTy::I64 => Is64(i as i64),
             _ => unreachable!(),
         }
     }
diff --git a/src/librustc_const_math/lib.rs b/src/librustc_const_math/lib.rs
index f667ff23b27..597344a2c82 100644
--- a/src/librustc_const_math/lib.rs
+++ b/src/librustc_const_math/lib.rs
@@ -25,10 +25,14 @@
 
 #![feature(rustc_private)]
 #![feature(staged_api)]
+#![feature(const_fn)]
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
 
+// SNAP: remove use of this crate
+extern crate rustc_i128;
+
 extern crate serialize as rustc_serialize; // used by deriving
 
 mod float;
diff --git a/src/librustc_const_math/us.rs b/src/librustc_const_math/us.rs
index bf73ff03c98..9ebf5cab6bb 100644
--- a/src/librustc_const_math/us.rs
+++ b/src/librustc_const_math/us.rs
@@ -10,6 +10,7 @@
 
 use syntax::ast;
 use super::err::*;
+use rustc_i128::u128;
 
 /// Depending on the target only one variant is ever used in a compilation.
 /// Anything else is an error. This invariant is checked at several locations
@@ -41,11 +42,11 @@ impl ConstUsize {
             _ => unreachable!(),
         }
     }
-    pub fn new_truncating(i: u64, target_uint_ty: ast::UintTy) -> Self {
+    pub fn new_truncating(i: u128, target_uint_ty: ast::UintTy) -> Self {
         match target_uint_ty {
             ast::UintTy::U16 => Us16(i as u16),
             ast::UintTy::U32 => Us32(i as u32),
-            ast::UintTy::U64 => Us64(i),
+            ast::UintTy::U64 => Us64(i as u64),
             _ => unreachable!(),
         }
     }
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index e2e16059d98..bb610374810 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -11,3 +11,4 @@ crate-type = ["dylib"]
 [dependencies]
 log = { path = "../liblog" }
 serialize = { path = "../libserialize" }
+rustc_i128 = { path = "../librustc_i128" }
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index 86f244d65dd..d3ec674daed 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -44,6 +44,8 @@ extern crate serialize as rustc_serialize; // used by deriving
 #[cfg(unix)]
 extern crate libc;
 
+extern crate rustc_i128;
+
 pub use rustc_serialize::hex::ToHex;
 
 pub mod array_vec;
diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs
index ed97c3dde5e..87048eff5b7 100644
--- a/src/librustc_data_structures/stable_hasher.rs
+++ b/src/librustc_data_structures/stable_hasher.rs
@@ -13,13 +13,14 @@ use std::marker::PhantomData;
 use std::mem;
 use blake2b::Blake2bHasher;
 use rustc_serialize::leb128;
+use rustc_i128::{u128,i128};
 
 fn write_unsigned_leb128_to_buf(buf: &mut [u8; 16], value: u64) -> usize {
-    leb128::write_unsigned_leb128_to(value, |i, v| buf[i] = v)
+    leb128::write_unsigned_leb128_to(value as u128, |i, v| buf[i] = v)
 }
 
 fn write_signed_leb128_to_buf(buf: &mut [u8; 16], value: i64) -> usize {
-    leb128::write_signed_leb128_to(value, |i, v| buf[i] = v)
+    leb128::write_signed_leb128_to(value as i128, |i, v| buf[i] = v)
 }
 
 /// When hashing something that ends up affecting properties like symbol names. We
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 291f0e0d50d..e9c14b4f99c 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -19,7 +19,7 @@ use rustc::session::search_paths::PathKind;
 use rustc::lint;
 use rustc::middle::{self, dependency_format, stability, reachable};
 use rustc::middle::privacy::AccessLevels;
-use rustc::ty::{self, TyCtxt, Resolutions};
+use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas};
 use rustc::util::common::time;
 use rustc::util::nodemap::{NodeSet, NodeMap};
 use rustc_borrowck as borrowck;
@@ -55,6 +55,7 @@ use syntax::symbol::Symbol;
 use syntax::util::node_count::NodeCounter;
 use syntax;
 use syntax_ext;
+use arena::DroplessArena;
 
 use derive_registrar;
 
@@ -123,7 +124,8 @@ pub fn compile_input(sess: &Session,
 
         write_out_deps(sess, &outputs, &crate_name);
 
-        let arenas = ty::CtxtArenas::new();
+        let arena = DroplessArena::new();
+        let arenas = GlobalArenas::new();
 
         // Construct the HIR map
         let hir_map = time(sess.time_passes(),
@@ -138,6 +140,7 @@ pub fn compile_input(sess: &Session,
                                                                   sess,
                                                                   outdir,
                                                                   output,
+                                                                  &arena,
                                                                   &arenas,
                                                                   &cstore,
                                                                   &hir_map,
@@ -164,6 +167,7 @@ pub fn compile_input(sess: &Session,
                                     hir_map,
                                     analysis,
                                     resolutions,
+                                    &arena,
                                     &arenas,
                                     &crate_name,
                                     |tcx, analysis, incremental_hashes_map, result| {
@@ -331,7 +335,8 @@ pub struct CompileState<'a, 'tcx: 'a> {
     pub output_filenames: Option<&'a OutputFilenames>,
     pub out_dir: Option<&'a Path>,
     pub out_file: Option<&'a Path>,
-    pub arenas: Option<&'tcx ty::CtxtArenas<'tcx>>,
+    pub arena: Option<&'tcx DroplessArena>,
+    pub arenas: Option<&'tcx GlobalArenas<'tcx>>,
     pub expanded_crate: Option<&'a ast::Crate>,
     pub hir_crate: Option<&'a hir::Crate>,
     pub ast_map: Option<&'a hir_map::Map<'tcx>>,
@@ -351,6 +356,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> {
             session: session,
             out_dir: out_dir.as_ref().map(|s| &**s),
             out_file: None,
+            arena: None,
             arenas: None,
             krate: None,
             registry: None,
@@ -405,7 +411,8 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> {
                                 session: &'tcx Session,
                                 out_dir: &'a Option<PathBuf>,
                                 out_file: &'a Option<PathBuf>,
-                                arenas: &'tcx ty::CtxtArenas<'tcx>,
+                                arena: &'tcx DroplessArena,
+                                arenas: &'tcx GlobalArenas<'tcx>,
                                 cstore: &'a CStore,
                                 hir_map: &'a hir_map::Map<'tcx>,
                                 analysis: &'a ty::CrateAnalysis<'static>,
@@ -416,6 +423,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> {
                                 -> Self {
         CompileState {
             crate_name: Some(crate_name),
+            arena: Some(arena),
             arenas: Some(arenas),
             cstore: Some(cstore),
             ast_map: Some(hir_map),
@@ -800,7 +808,8 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
                                                hir_map: hir_map::Map<'tcx>,
                                                mut analysis: ty::CrateAnalysis<'tcx>,
                                                resolutions: Resolutions,
-                                               arenas: &'tcx ty::CtxtArenas<'tcx>,
+                                               arena: &'tcx DroplessArena,
+                                               arenas: &'tcx GlobalArenas<'tcx>,
                                                name: &str,
                                                f: F)
                                                -> Result<R, usize>
@@ -858,6 +867,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 
     TyCtxt::create_and_enter(sess,
                              arenas,
+                             arena,
                              resolutions,
                              named_region_map,
                              hir_map,
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 5ceec9edda3..ca31022b04c 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -462,6 +462,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
                                                      &state.expanded_crate.take().unwrap(),
                                                      state.crate_name.unwrap(),
                                                      ppm,
+                                                     state.arena.unwrap(),
                                                      state.arenas.unwrap(),
                                                      opt_uii.clone(),
                                                      state.out_file);
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 5103a55fd71..cc288619cde 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -17,7 +17,7 @@ use self::NodesMatchingUII::*;
 
 use {abort_on_err, driver};
 
-use rustc::ty::{self, TyCtxt, Resolutions};
+use rustc::ty::{self, TyCtxt, GlobalArenas, Resolutions};
 use rustc::cfg;
 use rustc::cfg::graphviz::LabelledCFG;
 use rustc::dep_graph::DepGraph;
@@ -51,6 +51,8 @@ use rustc::hir::map::blocks;
 use rustc::hir;
 use rustc::hir::print as pprust_hir;
 
+use arena::DroplessArena;
+
 #[derive(Copy, Clone, PartialEq, Debug)]
 pub enum PpSourceMode {
     PpmNormal,
@@ -201,7 +203,8 @@ impl PpSourceMode {
                                                ast_map: &hir_map::Map<'tcx>,
                                                analysis: &ty::CrateAnalysis<'tcx>,
                                                resolutions: &Resolutions,
-                                               arenas: &'tcx ty::CtxtArenas<'tcx>,
+                                               arena: &'tcx DroplessArena,
+                                               arenas: &'tcx GlobalArenas<'tcx>,
                                                id: &str,
                                                payload: B,
                                                f: F)
@@ -229,6 +232,7 @@ impl PpSourceMode {
                                                                  ast_map.clone(),
                                                                  analysis.clone(),
                                                                  resolutions.clone(),
+                                                                 arena,
                                                                  arenas,
                                                                  id,
                                                                  |tcx, _, _, _| {
@@ -846,7 +850,8 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
                                                 krate: &ast::Crate,
                                                 crate_name: &str,
                                                 ppm: PpMode,
-                                                arenas: &'tcx ty::CtxtArenas<'tcx>,
+                                                arena: &'tcx DroplessArena,
+                                                arenas: &'tcx GlobalArenas<'tcx>,
                                                 opt_uii: Option<UserIdentifiedItem>,
                                                 ofile: Option<&Path>) {
     let dep_graph = DepGraph::new(false);
@@ -858,6 +863,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
                             analysis,
                             resolutions,
                             crate_name,
+                            arena,
                             arenas,
                             ppm,
                             opt_uii,
@@ -894,6 +900,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
                                            ast_map,
                                            analysis,
                                            resolutions,
+                                           arena,
                                            arenas,
                                            crate_name,
                                            box out,
@@ -917,6 +924,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
                                            ast_map,
                                            analysis,
                                            resolutions,
+                                           arena,
                                            arenas,
                                            crate_name,
                                            (out, uii),
@@ -959,7 +967,8 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
                                        analysis: &ty::CrateAnalysis<'tcx>,
                                        resolutions: &Resolutions,
                                        crate_name: &str,
-                                       arenas: &'tcx ty::CtxtArenas<'tcx>,
+                                       arena: &'tcx DroplessArena,
+                                       arenas: &'tcx GlobalArenas<'tcx>,
                                        ppm: PpMode,
                                        uii: Option<UserIdentifiedItem>,
                                        ofile: Option<&Path>) {
@@ -977,6 +986,7 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
                                                      ast_map.clone(),
                                                      analysis.clone(),
                                                      resolutions.clone(),
+                                                     arena,
                                                      arenas,
                                                      crate_name,
                                                      |tcx, _, _, _| {
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index cbab39c3908..887e586a311 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -38,6 +38,7 @@ use errors::{Level, DiagnosticBuilder};
 use syntax::feature_gate::UnstableFeatures;
 use syntax::symbol::Symbol;
 use syntax_pos::DUMMY_SP;
+use arena::DroplessArena;
 
 use rustc::hir;
 
@@ -128,7 +129,8 @@ fn test_env<F>(source_string: &str,
     };
     let _ignore = dep_graph.in_ignore();
 
-    let arenas = ty::CtxtArenas::new();
+    let arena = DroplessArena::new();
+    let arenas = ty::GlobalArenas::new();
     let ast_map = hir_map::map_crate(&mut hir_forest, defs);
 
     // run just enough stuff to build a tcx:
@@ -138,6 +140,7 @@ fn test_env<F>(source_string: &str,
     let index = stability::Index::new(&ast_map);
     TyCtxt::create_and_enter(&sess,
                              &arenas,
+                             &arena,
                              resolutions,
                              named_region_map.unwrap(),
                              ast_map,
diff --git a/src/librustc_i128/Cargo.toml b/src/librustc_i128/Cargo.toml
new file mode 100644
index 00000000000..6fd67637db7
--- /dev/null
+++ b/src/librustc_i128/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+authors = ["The Rust Project Developers"]
+name = "rustc_i128"
+version = "0.0.0"
+
+[lib]
+name = "rustc_i128"
+path = "lib.rs"
diff --git a/src/librustc_i128/lib.rs b/src/librustc_i128/lib.rs
new file mode 100644
index 00000000000..80f550c7f50
--- /dev/null
+++ b/src/librustc_i128/lib.rs
@@ -0,0 +1,29 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![allow(non_camel_case_types)]
+#![cfg_attr(not(stage0), feature(i128_type))]
+#![no_std]
+#![crate_type="rlib"]
+#![crate_name="rustc_i128"]
+
+#[cfg(stage0)]
+pub type i128 = i64;
+#[cfg(stage0)]
+pub type u128 = u64;
+
+#[cfg(not(stage0))]
+pub type i128 = int::_i128;
+#[cfg(not(stage0))]
+pub type u128 = int::_u128;
+#[cfg(not(stage0))]
+mod int {
+    pub type _i128 = i128;
+    pub type _u128 = u128;
+}
diff --git a/src/librustc_incremental/Cargo.toml b/src/librustc_incremental/Cargo.toml
index e3ee7527545..8a38f36a5d1 100644
--- a/src/librustc_incremental/Cargo.toml
+++ b/src/librustc_incremental/Cargo.toml
@@ -16,3 +16,4 @@ serialize = { path = "../libserialize" }
 log = { path = "../liblog" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
+rustc_i128 = { path = "../librustc_i128" }
diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs
index ce73b14ef2d..d02e4f9b165 100644
--- a/src/librustc_incremental/lib.rs
+++ b/src/librustc_incremental/lib.rs
@@ -33,6 +33,8 @@ extern crate serialize as rustc_serialize;
 #[macro_use] extern crate syntax;
 extern crate syntax_pos;
 
+extern crate rustc_i128;
+
 const ATTR_DIRTY: &'static str = "rustc_dirty";
 const ATTR_CLEAN: &'static str = "rustc_clean";
 const ATTR_DIRTY_METADATA: &'static str = "rustc_metadata_dirty";
diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml
index 4d5c0d7ba0a..272f8b4f64d 100644
--- a/src/librustc_lint/Cargo.toml
+++ b/src/librustc_lint/Cargo.toml
@@ -14,5 +14,6 @@ log = { path = "../liblog" }
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
 rustc_const_eval = { path = "../librustc_const_eval" }
+rustc_i128 = { path = "../librustc_i128" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index a53d43b2a25..a24edfaaac1 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -47,6 +47,8 @@ extern crate rustc_back;
 extern crate rustc_const_eval;
 extern crate syntax_pos;
 
+extern crate rustc_i128;
+
 pub use rustc::lint;
 pub use rustc::middle;
 pub use rustc::session;
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index a3aa4af493a..95e955bd683 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -33,6 +33,8 @@ use syntax::codemap;
 
 use rustc::hir;
 
+use rustc_i128::{i128, u128};
+
 register_long_diagnostics! {
 E0519: r##"
 It is not allowed to negate an unsigned integer.
@@ -147,7 +149,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
                     if let Some(bits) = opt_ty_bits {
                         let exceeding = if let hir::ExprLit(ref lit) = r.node {
                             if let ast::LitKind::Int(shift, _) = lit.node {
-                                shift >= bits
+                                shift as u64 >= bits
                             } else {
                                 false
                             }
@@ -182,12 +184,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
                                     t
                                 };
                                 let (_, max) = int_ty_range(int_type);
+                                let max = max as u128;
                                 let negative = self.negated_expr_id == e.id;
 
                                 // Detect literal value out of range [min, max] inclusive
                                 // avoiding use of -min to prevent overflow/panic
-                                if (negative && v > max as u64 + 1) ||
-                                   (!negative && v > max as u64) {
+                                if (negative && v > max + 1) ||
+                                   (!negative && v > max) {
                                     cx.span_lint(OVERFLOWING_LITERALS,
                                                  e.span,
                                                  &format!("literal out of range for {:?}", t));
@@ -204,7 +207,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
                             t
                         };
                         let (min, max) = uint_ty_range(uint_type);
-                        let lit_val: u64 = match lit.node {
+                        let lit_val: u128 = match lit.node {
                             // _v is u8, within range by definition
                             ast::LitKind::Byte(_v) => return,
                             ast::LitKind::Int(v, _) => v,
@@ -264,23 +267,25 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
 
         // for isize & usize, be conservative with the warnings, so that the
         // warnings are consistent between 32- and 64-bit platforms
-        fn int_ty_range(int_ty: ast::IntTy) -> (i64, i64) {
+        fn int_ty_range(int_ty: ast::IntTy) -> (i128, i128) {
             match int_ty {
-                ast::IntTy::Is => (i64::MIN, i64::MAX),
-                ast::IntTy::I8 => (i8::MIN as i64, i8::MAX as i64),
-                ast::IntTy::I16 => (i16::MIN as i64, i16::MAX as i64),
-                ast::IntTy::I32 => (i32::MIN as i64, i32::MAX as i64),
-                ast::IntTy::I64 => (i64::MIN, i64::MAX),
+                ast::IntTy::Is => (i64::min_value() as i128, i64::max_value() as i128),
+                ast::IntTy::I8 => (i8::min_value() as i64 as i128, i8::max_value() as i128),
+                ast::IntTy::I16 => (i16::min_value() as i64 as i128, i16::max_value() as i128),
+                ast::IntTy::I32 => (i32::min_value() as i64 as i128, i32::max_value() as i128),
+                ast::IntTy::I64 => (i64::min_value() as i128, i64::max_value() as i128),
+                ast::IntTy::I128 =>(i128::min_value() as i128, i128::max_value()),
             }
         }
 
-        fn uint_ty_range(uint_ty: ast::UintTy) -> (u64, u64) {
+        fn uint_ty_range(uint_ty: ast::UintTy) -> (u128, u128) {
             match uint_ty {
-                ast::UintTy::Us => (u64::MIN, u64::MAX),
-                ast::UintTy::U8 => (u8::MIN as u64, u8::MAX as u64),
-                ast::UintTy::U16 => (u16::MIN as u64, u16::MAX as u64),
-                ast::UintTy::U32 => (u32::MIN as u64, u32::MAX as u64),
-                ast::UintTy::U64 => (u64::MIN, u64::MAX),
+                ast::UintTy::Us => (u64::min_value() as u128, u64::max_value() as u128),
+                ast::UintTy::U8 => (u8::min_value() as u128, u8::max_value() as u128),
+                ast::UintTy::U16 => (u16::min_value() as u128, u16::max_value() as u128),
+                ast::UintTy::U32 => (u32::min_value() as u128, u32::max_value() as u128),
+                ast::UintTy::U64 => (u64::min_value() as u128, u64::max_value() as u128),
+                ast::UintTy::U128 => (u128::min_value(), u128::max_value()),
             }
         }
 
@@ -298,6 +303,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
                 ast::IntTy::I16 => 16 as u64,
                 ast::IntTy::I32 => 32,
                 ast::IntTy::I64 => 64,
+                ast::IntTy::I128 => 128,
             }
         }
 
@@ -308,6 +314,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
                 ast::UintTy::U16 => 16,
                 ast::UintTy::U32 => 32,
                 ast::UintTy::U64 => 64,
+                ast::UintTy::U128 => 128,
             }
         }
 
@@ -327,28 +334,28 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
             match tcx.tables().node_id_to_type(expr.id).sty {
                 ty::TyInt(int_ty) => {
                     let (min, max) = int_ty_range(int_ty);
-                    let lit_val: i64 = match lit.node {
+                    let lit_val: i128 = match lit.node {
                         hir::ExprLit(ref li) => {
                             match li.node {
                                 ast::LitKind::Int(v, ast::LitIntType::Signed(_)) |
-                                ast::LitKind::Int(v, ast::LitIntType::Unsuffixed) => v as i64,
-                                _ => return true,
+                                ast::LitKind::Int(v, ast::LitIntType::Unsuffixed) => v as i128,
+                                _ => return true
                             }
-                        }
-                        _ => bug!(),
+                        },
+                        _ => bug!()
                     };
                     is_valid(norm_binop, lit_val, min, max)
                 }
                 ty::TyUint(uint_ty) => {
-                    let (min, max): (u64, u64) = uint_ty_range(uint_ty);
-                    let lit_val: u64 = match lit.node {
+                    let (min, max) :(u128, u128) = uint_ty_range(uint_ty);
+                    let lit_val: u128 = match lit.node {
                         hir::ExprLit(ref li) => {
                             match li.node {
                                 ast::LitKind::Int(v, _) => v,
-                                _ => return true,
+                                _ => return true
                             }
-                        }
-                        _ => bug!(),
+                        },
+                        _ => bug!()
                     };
                     is_valid(norm_binop, lit_val, min, max)
                 }
diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs
index e681a81cf0c..2ee4cc49435 100644
--- a/src/librustc_llvm/build.rs
+++ b/src/librustc_llvm/build.rs
@@ -96,7 +96,7 @@ fn main() {
 
     let optional_components =
         ["x86", "arm", "aarch64", "mips", "powerpc", "pnacl", "systemz", "jsbackend", "msp430",
-         "sparc"];
+         "sparc", "nvptx"];
 
     // FIXME: surely we don't need all these components, right? Stuff like mcjit
     //        or interpreter the compiler itself never uses.
diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs
index 5fd85023e41..6815da4cc20 100644
--- a/src/librustc_llvm/ffi.rs
+++ b/src/librustc_llvm/ffi.rs
@@ -33,7 +33,7 @@ pub enum LLVMRustResult {
 // Consts for the LLVM CallConv type, pre-cast to usize.
 
 /// LLVM CallingConv::ID. Should we wrap this?
-#[derive(Copy, Clone, PartialEq)]
+#[derive(Copy, Clone, PartialEq, Debug)]
 #[repr(C)]
 pub enum CallConv {
     CCallConv = 0,
@@ -42,6 +42,7 @@ pub enum CallConv {
     X86StdcallCallConv = 64,
     X86FastcallCallConv = 65,
     ArmAapcsCallConv = 67,
+    PtxKernel = 71,
     X86_64_SysV = 78,
     X86_64_Win64 = 79,
     X86_VectorCall = 80,
@@ -577,9 +578,12 @@ extern "C" {
 
     // Operations on scalar constants
     pub fn LLVMConstInt(IntTy: TypeRef, N: c_ulonglong, SignExtend: Bool) -> ValueRef;
+    pub fn LLVMConstIntOfArbitraryPrecision(IntTy: TypeRef, Wn: c_uint, Ws: *const u64) -> ValueRef;
     pub fn LLVMConstReal(RealTy: TypeRef, N: f64) -> ValueRef;
     pub fn LLVMConstIntGetZExtValue(ConstantVal: ValueRef) -> c_ulonglong;
     pub fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong;
+    pub fn LLVMRustConstInt128Get(ConstantVal: ValueRef, SExt: bool,
+                                  high: *mut u64, low: *mut u64) -> bool;
 
 
     // Operations on composite constants
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index c8b1ea50f97..938f346e0bf 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -126,11 +126,11 @@ pub enum RustString_opaque {}
 pub type RustStringRef = *mut RustString_opaque;
 type RustStringRepr = *mut RefCell<Vec<u8>>;
 
-/// Appending to a Rust string -- used by raw_rust_string_ostream.
+/// Appending to a Rust string -- used by RawRustStringOstream.
 #[no_mangle]
-pub unsafe extern "C" fn rust_llvm_string_write_impl(sr: RustStringRef,
-                                                     ptr: *const c_char,
-                                                     size: size_t) {
+pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: RustStringRef,
+                                                 ptr: *const c_char,
+                                                 size: size_t) {
     let slice = slice::from_raw_parts(ptr as *const u8, size as usize);
 
     let sr = sr as RustStringRepr;
@@ -376,6 +376,11 @@ pub fn initialize_available_targets() {
                  LLVMInitializeSparcTargetMC,
                  LLVMInitializeSparcAsmPrinter,
                  LLVMInitializeSparcAsmParser);
+    init_target!(llvm_component = "nvptx",
+                 LLVMInitializeNVPTXTargetInfo,
+                 LLVMInitializeNVPTXTarget,
+                 LLVMInitializeNVPTXTargetMC,
+                 LLVMInitializeNVPTXAsmPrinter);
 }
 
 pub fn last_error() -> Option<String> {
diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml
index 6f7f03ca216..4bd98c087f5 100644
--- a/src/librustc_metadata/Cargo.toml
+++ b/src/librustc_metadata/Cargo.toml
@@ -18,6 +18,7 @@ rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_llvm = { path = "../librustc_llvm" }
+rustc_i128 = { path = "../librustc_i128" }
 serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
 syntax_ext = { path = "../libsyntax_ext" }
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index c27e06c5022..dad956afb5e 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -43,6 +43,7 @@ use syntax::attr;
 use syntax::ast::{self, NodeId};
 use syntax::codemap;
 use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP};
+use rustc_i128::{u128, i128};
 
 pub struct DecodeContext<'a, 'tcx: 'a> {
     opaque: opaque::Decoder<'a>,
@@ -211,12 +212,14 @@ impl<'doc, 'tcx> Decoder for DecodeContext<'doc, 'tcx> {
     decoder_methods! {
         read_nil -> ();
 
+        read_u128 -> u128;
         read_u64 -> u64;
         read_u32 -> u32;
         read_u16 -> u16;
         read_u8 -> u8;
         read_usize -> usize;
 
+        read_i128 -> i128;
         read_i64 -> i64;
         read_i32 -> i32;
         read_i16 -> i16;
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 72dcb4ba9a3..c3bcdf42d4e 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -43,6 +43,8 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use rustc::hir::intravisit::{Visitor, NestedVisitorMap};
 use rustc::hir::intravisit;
 
+use rustc_i128::{u128, i128};
+
 use super::index_builder::{FromId, IndexBuilder, Untracked};
 
 pub struct EncodeContext<'a, 'tcx: 'a> {
@@ -75,12 +77,14 @@ impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
 
     encoder_methods! {
         emit_usize(usize);
+        emit_u128(u128);
         emit_u64(u64);
         emit_u32(u32);
         emit_u16(u16);
         emit_u8(u8);
 
         emit_isize(isize);
+        emit_i128(i128);
         emit_i64(i64);
         emit_i32(i32);
         emit_i16(i16);
@@ -259,7 +263,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
         let data = VariantData {
             ctor_kind: variant.ctor_kind,
-            disr: variant.disr_val.to_u64_unchecked(),
+            disr: variant.disr_val.to_u128_unchecked(),
             struct_ctor: None,
         };
 
@@ -386,7 +390,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
         let data = VariantData {
             ctor_kind: variant.ctor_kind,
-            disr: variant.disr_val.to_u64_unchecked(),
+            disr: variant.disr_val.to_u128_unchecked(),
             struct_ctor: Some(def_id.index),
         };
 
@@ -648,7 +652,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 };
                 EntryKind::Struct(self.lazy(&VariantData {
                     ctor_kind: variant.ctor_kind,
-                    disr: variant.disr_val.to_u64_unchecked(),
+                    disr: variant.disr_val.to_u128_unchecked(),
                     struct_ctor: struct_ctor,
                 }))
             }
@@ -657,7 +661,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
                 EntryKind::Union(self.lazy(&VariantData {
                     ctor_kind: variant.ctor_kind,
-                    disr: variant.disr_val.to_u64_unchecked(),
+                    disr: variant.disr_val.to_u128_unchecked(),
                     struct_ctor: None,
                 }))
             }
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index 56f3cfc12c9..f4ccc01544a 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -45,9 +45,12 @@ extern crate rustc_back;
 extern crate rustc_const_math;
 extern crate rustc_data_structures;
 extern crate rustc_llvm;
+extern crate rustc_i128;
 
 mod diagnostics;
 
+pub use rustc::middle;
+
 mod astencode;
 mod index_builder;
 mod index;
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index 2bd5a9ea59d..74825a5c6e3 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -27,6 +27,8 @@ use syntax_pos::{self, Span};
 
 use std::marker::PhantomData;
 
+use rustc_i128::u128;
+
 pub fn rustc_version() -> String {
     format!("rustc {}",
             option_env!("CFG_VERSION").unwrap_or("unknown version"))
@@ -264,7 +266,7 @@ pub struct FnData {
 #[derive(RustcEncodable, RustcDecodable)]
 pub struct VariantData {
     pub ctor_kind: CtorKind,
-    pub disr: u64,
+    pub disr: u128,
 
     /// If this is a struct's only variant, this
     /// is the index of the "struct ctor" item.
diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml
index 2a1a8153306..7e26aa9a57b 100644
--- a/src/librustc_mir/Cargo.toml
+++ b/src/librustc_mir/Cargo.toml
@@ -17,5 +17,6 @@ rustc_const_eval = { path = "../librustc_const_eval" }
 rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_bitflags = { path = "../librustc_bitflags" }
+rustc_i128 = { path = "../librustc_i128" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index b75e52fd4b1..8199a08c852 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -15,6 +15,7 @@ use std;
 use rustc_const_math::{ConstMathErr, Op};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
+use rustc_i128::i128;
 
 use build::{BlockAnd, BlockAndExtension, Builder};
 use build::expr::category::{Category, RvalueFunc};
@@ -347,6 +348,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     ast::IntTy::I16 => ConstInt::I16(-1),
                     ast::IntTy::I32 => ConstInt::I32(-1),
                     ast::IntTy::I64 => ConstInt::I64(-1),
+                    ast::IntTy::I128 => ConstInt::I128(-1),
                     ast::IntTy::Is => {
                         let int_ty = self.hir.tcx().sess.target.int_type;
                         let val = ConstIsize::new(-1, int_ty).unwrap();
@@ -369,10 +371,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         let literal = match ty.sty {
             ty::TyInt(ity) => {
                 let val = match ity {
-                    ast::IntTy::I8  => ConstInt::I8(std::i8::MIN),
-                    ast::IntTy::I16 => ConstInt::I16(std::i16::MIN),
-                    ast::IntTy::I32 => ConstInt::I32(std::i32::MIN),
-                    ast::IntTy::I64 => ConstInt::I64(std::i64::MIN),
+                    ast::IntTy::I8  => ConstInt::I8(i8::min_value()),
+                    ast::IntTy::I16 => ConstInt::I16(i16::min_value()),
+                    ast::IntTy::I32 => ConstInt::I32(i32::min_value()),
+                    ast::IntTy::I64 => ConstInt::I64(i64::min_value()),
+                    ast::IntTy::I128 => ConstInt::I128(i128::min_value()),
                     ast::IntTy::Is => {
                         let int_ty = self.hir.tcx().sess.target.int_type;
                         let min = match int_ty {
diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs
index a5f51ef35b7..99aa5cb0fa8 100644
--- a/src/librustc_mir/build/misc.rs
+++ b/src/librustc_mir/build/misc.rs
@@ -66,6 +66,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     ast::UintTy::U16 => ConstInt::U16(0),
                     ast::UintTy::U32 => ConstInt::U32(0),
                     ast::UintTy::U64 => ConstInt::U64(0),
+                    ast::UintTy::U128 => ConstInt::U128(0),
                     ast::UintTy::Us => {
                         let uint_ty = self.hir.tcx().sess.target.uint_type;
                         let val = ConstUsize::new(0, uint_ty).unwrap();
@@ -81,6 +82,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     ast::IntTy::I16 => ConstInt::I16(0),
                     ast::IntTy::I32 => ConstInt::I32(0),
                     ast::IntTy::I64 => ConstInt::I64(0),
+                    ast::IntTy::I128 => ConstInt::I128(0),
                     ast::IntTy::Is => {
                         let int_ty = self.hir.tcx().sess.target.int_type;
                         let val = ConstIsize::new(0, int_ty).unwrap();
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 56dadd2d673..a608275cefa 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -41,6 +41,8 @@ extern crate syntax_pos;
 extern crate rustc_const_math;
 extern crate rustc_const_eval;
 
+extern crate rustc_i128;
+
 pub mod diagnostics;
 
 pub mod build;
diff --git a/src/librustc_platform_intrinsics/lib.rs b/src/librustc_platform_intrinsics/lib.rs
index 6fe1f0c2b9c..e814050e960 100644
--- a/src/librustc_platform_intrinsics/lib.rs
+++ b/src/librustc_platform_intrinsics/lib.rs
@@ -95,6 +95,7 @@ static VOID: Type = Type::Void;
 mod x86;
 mod arm;
 mod aarch64;
+mod nvptx;
 
 impl Intrinsic {
     pub fn find(name: &str) -> Option<Intrinsic> {
@@ -104,6 +105,8 @@ impl Intrinsic {
             arm::find(name)
         } else if name.starts_with("aarch64_") {
             aarch64::find(name)
+        } else if name.starts_with("nvptx_") {
+            nvptx::find(name)
         } else {
             None
         }
diff --git a/src/librustc_platform_intrinsics/nvptx.rs b/src/librustc_platform_intrinsics/nvptx.rs
new file mode 100644
index 00000000000..82408723ebe
--- /dev/null
+++ b/src/librustc_platform_intrinsics/nvptx.rs
@@ -0,0 +1,92 @@
+// Copyright 2015 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.
+
+// DO NOT EDIT: autogenerated by etc/platform-intrinsics/generator.py
+// ignore-tidy-linelength
+
+#![allow(unused_imports)]
+
+use {Intrinsic, Type};
+use IntrinsicDef::Named;
+
+// The default inlining settings trigger a pathological behaviour in
+// LLVM, which causes makes compilation very slow. See #28273.
+#[inline(never)]
+pub fn find(name: &str) -> Option<Intrinsic> {
+    if !name.starts_with("nvptx") { return None }
+    Some(match &name["nvptx".len()..] {
+        "_syncthreads" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::VOID,
+            definition: Named("llvm.cuda.syncthreads")
+        },
+        "_block_dim_x" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.ntid.x")
+        },
+        "_block_dim_y" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.ntid.y")
+        },
+        "_block_dim_z" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.ntid.z")
+        },
+        "_block_idx_x" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.ctaid.x")
+        },
+        "_block_idx_y" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.ctaid.y")
+        },
+        "_block_idx_z" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.ctaid.z")
+        },
+        "_grid_dim_x" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.nctaid.x")
+        },
+        "_grid_dim_y" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.nctaid.y")
+        },
+        "_grid_dim_z" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.nctaid.z")
+        },
+        "_thread_idx_x" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.tid.x")
+        },
+        "_thread_idx_y" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.tid.y")
+        },
+        "_thread_idx_z" => Intrinsic {
+            inputs: { static INPUTS: [&'static Type; 0] = []; &INPUTS },
+            output: &::I32,
+            definition: Named("llvm.nvvm.read.ptx.sreg.tid.z")
+        },
+        _ => return None,
+    })
+}
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 865195d3db4..b7908f0c0ed 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -61,6 +61,7 @@ use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, Generics};
 use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind};
 use syntax::ast::{Local, Mutability, Pat, PatKind, Path};
 use syntax::ast::{QSelf, TraitItemKind, TraitRef, Ty, TyKind};
+use syntax::feature_gate::{emit_feature_err, GateIssue};
 
 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
 use errors::DiagnosticBuilder;
@@ -1005,13 +1006,14 @@ impl PrimitiveTypeTable {
         table.intern("i16", TyInt(IntTy::I16));
         table.intern("i32", TyInt(IntTy::I32));
         table.intern("i64", TyInt(IntTy::I64));
+        table.intern("i128", TyInt(IntTy::I128));
         table.intern("str", TyStr);
         table.intern("usize", TyUint(UintTy::Us));
         table.intern("u8", TyUint(UintTy::U8));
         table.intern("u16", TyUint(UintTy::U16));
         table.intern("u32", TyUint(UintTy::U32));
         table.intern("u64", TyUint(UintTy::U64));
-
+        table.intern("u128", TyUint(UintTy::U128));
         table
     }
 
@@ -2308,8 +2310,20 @@ impl<'a> Resolver<'a> {
             PathResult::Module(..) | PathResult::Failed(..)
                     if (ns == TypeNS || path.len() > 1) &&
                        self.primitive_type_table.primitive_types.contains_key(&path[0].name) => {
+                let prim = self.primitive_type_table.primitive_types[&path[0].name];
+                match prim {
+                    TyUint(UintTy::U128) | TyInt(IntTy::I128) => {
+                        if !self.session.features.borrow().i128_type {
+                            emit_feature_err(&self.session.parse_sess,
+                                                "i128_type", span, GateIssue::Language,
+                                                "128-bit type is unstable");
+
+                        }
+                    }
+                    _ => {}
+                }
                 PathResolution {
-                    base_def: Def::PrimTy(self.primitive_type_table.primitive_types[&path[0].name]),
+                    base_def: Def::PrimTy(prim),
                     depth: path.len() - 1,
                 }
             }
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 44cc580ad12..47033f74e0e 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -28,7 +28,7 @@ use syntax::ext::expand::{Expansion, mark_tts};
 use syntax::ext::hygiene::Mark;
 use syntax::ext::tt::macro_rules;
 use syntax::feature_gate::{emit_feature_err, GateIssue};
-use syntax::fold::Folder;
+use syntax::fold::{self, Folder};
 use syntax::ptr::P;
 use syntax::symbol::keywords;
 use syntax::util::lev_distance::find_best_match_for_name;
@@ -117,6 +117,10 @@ impl<'a> base::Resolver for Resolver<'a> {
                 }
                 path
             }
+
+            fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
+                fold::noop_fold_mac(mac, self)
+            }
         }
 
         EliminateCrateVar(self).fold_item(item).expect_one("")
diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml
index 796a80d0809..93e2e472b75 100644
--- a/src/librustc_trans/Cargo.toml
+++ b/src/librustc_trans/Cargo.toml
@@ -23,7 +23,8 @@ rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_incremental = { path = "../librustc_incremental" }
 rustc_llvm = { path = "../librustc_llvm" }
+rustc_i128 = { path = "../librustc_i128" }
 rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" }
 serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
-syntax_pos = { path = "../libsyntax_pos" }
\ No newline at end of file
+syntax_pos = { path = "../libsyntax_pos" }
diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs
index 9c4246e079b..b3eec5d66c4 100644
--- a/src/librustc_trans/abi.rs
+++ b/src/librustc_trans/abi.rs
@@ -25,6 +25,9 @@ use cabi_mips64;
 use cabi_asmjs;
 use cabi_msp430;
 use cabi_sparc;
+use cabi_sparc64;
+use cabi_nvptx;
+use cabi_nvptx64;
 use machine::{llalign_of_min, llsize_of, llsize_of_alloc};
 use type_::Type;
 use type_of;
@@ -311,7 +314,7 @@ impl ArgType {
 ///
 /// I will do my best to describe this structure, but these
 /// comments are reverse-engineered and may be inaccurate. -NDM
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct FnType {
     /// The LLVM types of each argument.
     pub args: Vec<ArgType>,
@@ -350,9 +353,11 @@ impl FnType {
             Fastcall => llvm::X86FastcallCallConv,
             Vectorcall => llvm::X86_VectorCall,
             C => llvm::CCallConv,
+            Unadjusted => llvm::CCallConv,
             Win64 => llvm::X86_64_Win64,
             SysV64 => llvm::X86_64_SysV,
             Aapcs => llvm::ArmAapcsCallConv,
+            PtxKernel => llvm::PtxKernel,
 
             // These API constants ought to be more specific...
             Cdecl => llvm::CCallConv,
@@ -525,6 +530,8 @@ impl FnType {
                                     ccx: &CrateContext<'a, 'tcx>,
                                     abi: Abi,
                                     sig: &ty::FnSig<'tcx>) {
+        if abi == Abi::Unadjusted { return }
+
         if abi == Abi::Rust || abi == Abi::RustCall ||
            abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
             let fixup = |arg: &mut ArgType| {
@@ -608,6 +615,9 @@ impl FnType {
             "wasm32" => cabi_asmjs::compute_abi_info(ccx, self),
             "msp430" => cabi_msp430::compute_abi_info(ccx, self),
             "sparc" => cabi_sparc::compute_abi_info(ccx, self),
+            "sparc64" => cabi_sparc64::compute_abi_info(ccx, self),
+            "nvptx" => cabi_nvptx::compute_abi_info(ccx, self),
+            "nvptx64" => cabi_nvptx64::compute_abi_info(ccx, self),
             a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a))
         }
 
diff --git a/src/librustc_trans/cabi_nvptx.rs b/src/librustc_trans/cabi_nvptx.rs
new file mode 100644
index 00000000000..5ece19f764a
--- /dev/null
+++ b/src/librustc_trans/cabi_nvptx.rs
@@ -0,0 +1,53 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Reference: PTX Writer's Guide to Interoperability
+// http://docs.nvidia.com/cuda/ptx-writers-guide-to-interoperability
+
+#![allow(non_upper_case_globals)]
+
+use llvm::Struct;
+
+use abi::{self, ArgType, FnType};
+use context::CrateContext;
+use type_::Type;
+
+fn ty_size(ty: Type) -> usize {
+    abi::ty_size(ty, 4)
+}
+
+fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
+    if ret.ty.kind() == Struct && ty_size(ret.ty) > 32 {
+        ret.make_indirect(ccx);
+    } else {
+        ret.extend_integer_width_to(32);
+    }
+}
+
+fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
+    if arg.ty.kind() == Struct && ty_size(arg.ty) > 32 {
+        arg.make_indirect(ccx);
+    } else {
+        arg.extend_integer_width_to(32);
+    }
+}
+
+pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
+    if !fty.ret.is_ignore() {
+        classify_ret_ty(ccx, &mut fty.ret);
+    }
+
+    for arg in &mut fty.args {
+        if arg.is_ignore() {
+            continue;
+        }
+        classify_arg_ty(ccx, arg);
+    }
+}
diff --git a/src/librustc_trans/cabi_nvptx64.rs b/src/librustc_trans/cabi_nvptx64.rs
new file mode 100644
index 00000000000..880c6cfd7a8
--- /dev/null
+++ b/src/librustc_trans/cabi_nvptx64.rs
@@ -0,0 +1,53 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Reference: PTX Writer's Guide to Interoperability
+// http://docs.nvidia.com/cuda/ptx-writers-guide-to-interoperability
+
+#![allow(non_upper_case_globals)]
+
+use llvm::Struct;
+
+use abi::{self, ArgType, FnType};
+use context::CrateContext;
+use type_::Type;
+
+fn ty_size(ty: Type) -> usize {
+    abi::ty_size(ty, 8)
+}
+
+fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
+    if ret.ty.kind() == Struct && ty_size(ret.ty) > 64 {
+        ret.make_indirect(ccx);
+    } else {
+        ret.extend_integer_width_to(64);
+    }
+}
+
+fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
+    if arg.ty.kind() == Struct && ty_size(arg.ty) > 64 {
+        arg.make_indirect(ccx);
+    } else {
+        arg.extend_integer_width_to(64);
+    }
+}
+
+pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
+    if !fty.ret.is_ignore() {
+        classify_ret_ty(ccx, &mut fty.ret);
+    }
+
+    for arg in &mut fty.args {
+        if arg.is_ignore() {
+            continue;
+        }
+        classify_arg_ty(ccx, arg);
+    }
+}
diff --git a/src/librustc_trans/cabi_sparc64.rs b/src/librustc_trans/cabi_sparc64.rs
new file mode 100644
index 00000000000..e675cca33d1
--- /dev/null
+++ b/src/librustc_trans/cabi_sparc64.rs
@@ -0,0 +1,185 @@
+// Copyright 2014-2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// FIXME: This needs an audit for correctness and completeness.
+
+use llvm::{Integer, Pointer, Float, Double, Struct, Vector, Array};
+use abi::{self, FnType, ArgType};
+use context::CrateContext;
+use type_::Type;
+
+fn ty_size(ty: Type) -> usize {
+    if ty.kind() == Vector {
+        bug!("ty_size: unhandled type")
+    } else {
+        abi::ty_size(ty, 8)
+    }
+}
+
+fn is_homogenous_aggregate_ty(ty: Type) -> Option<(Type, u64)> {
+    fn check_array(ty: Type) -> Option<(Type, u64)> {
+        let len = ty.array_length() as u64;
+        if len == 0 {
+            return None
+        }
+        let elt = ty.element_type();
+
+        // if our element is an HFA/HVA, so are we; multiply members by our len
+        is_homogenous_aggregate_ty(elt).map(|(base_ty, members)| (base_ty, len * members))
+    }
+
+    fn check_struct(ty: Type) -> Option<(Type, u64)> {
+        let str_tys = ty.field_types();
+        if str_tys.len() == 0 {
+            return None
+        }
+
+        let mut prev_base_ty = None;
+        let mut members = 0;
+        for opt_homog_agg in str_tys.iter().map(|t| is_homogenous_aggregate_ty(*t)) {
+            match (prev_base_ty, opt_homog_agg) {
+                // field isn't itself an HFA, so we aren't either
+                (_, None) => return None,
+
+                // first field - store its type and number of members
+                (None, Some((field_ty, field_members))) => {
+                    prev_base_ty = Some(field_ty);
+                    members = field_members;
+                },
+
+                // 2nd or later field - give up if it's a different type; otherwise incr. members
+                (Some(prev_ty), Some((field_ty, field_members))) => {
+                    if prev_ty != field_ty {
+                        return None;
+                    }
+                    members += field_members;
+                }
+            }
+        }
+
+        // Because of previous checks, we know prev_base_ty is Some(...) because
+        //   1. str_tys has at least one element; and
+        //   2. prev_base_ty was filled in (or we would've returned early)
+        let (base_ty, members) = (prev_base_ty.unwrap(), members);
+
+        // Ensure there is no padding.
+        if ty_size(ty) == ty_size(base_ty) * (members as usize) {
+            Some((base_ty, members))
+        } else {
+            None
+        }
+    }
+
+    let homog_agg = match ty.kind() {
+        Float  => Some((ty, 1)),
+        Double => Some((ty, 1)),
+        Array  => check_array(ty),
+        Struct => check_struct(ty),
+        _ => None
+    };
+
+    // Ensure we have at most eight uniquely addressable members
+    homog_agg.and_then(|(base_ty, members)| {
+        if members > 0 && members <= 8 {
+            Some((base_ty, members))
+        } else {
+            None
+        }
+    })
+}
+
+fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
+    if is_reg_ty(ret.ty) {
+        ret.extend_integer_width_to(64);
+        return;
+    }
+
+    // don't return aggregates in registers
+    ret.make_indirect(ccx);
+
+    if let Some((base_ty, members)) = is_homogenous_aggregate_ty(ret.ty) {
+        ret.cast = Some(Type::array(&base_ty, members));
+        return;
+    }
+    let size = ty_size(ret.ty);
+    if size <= 16 {
+        let llty = if size <= 1 {
+            Type::i8(ccx)
+        } else if size <= 2 {
+            Type::i16(ccx)
+        } else if size <= 4 {
+            Type::i32(ccx)
+        } else if size <= 8 {
+            Type::i64(ccx)
+        } else {
+            Type::array(&Type::i64(ccx), ((size + 7 ) / 8 ) as u64)
+        };
+        ret.cast = Some(llty);
+        return;
+    }
+}
+
+fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
+    if is_reg_ty(arg.ty) {
+        arg.extend_integer_width_to(64);
+        return;
+    }
+
+    if let Some((base_ty, members)) = is_homogenous_aggregate_ty(arg.ty) {
+        arg.cast = Some(Type::array(&base_ty, members));
+        return;
+    }
+
+    arg.cast = Some(struct_ty(ccx, arg.ty));
+}
+
+fn is_reg_ty(ty: Type) -> bool {
+    match ty.kind() {
+        Integer
+        | Pointer
+        | Float
+        | Double => true,
+        _ => false
+    }
+}
+
+fn coerce_to_long(ccx: &CrateContext, size: usize) -> Vec<Type> {
+    let long_ty = Type::i64(ccx);
+    let mut args = Vec::new();
+
+    let mut n = size / 64;
+    while n > 0 {
+        args.push(long_ty);
+        n -= 1;
+    }
+
+    let r = size % 64;
+    if r > 0 {
+        args.push(Type::ix(ccx, r as u64));
+    }
+
+    args
+}
+
+fn struct_ty(ccx: &CrateContext, ty: Type) -> Type {
+    let size = ty_size(ty) * 8;
+    Type::struct_(ccx, &coerce_to_long(ccx, size), false)
+}
+
+pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
+    if !fty.ret.is_ignore() {
+        classify_ret_ty(ccx, &mut fty.ret);
+    }
+
+    for arg in &mut fty.args {
+        if arg.is_ignore() { continue; }
+        classify_arg_ty(ccx, arg);
+    }
+}
diff --git a/src/librustc_trans/cabi_x86_win64.rs b/src/librustc_trans/cabi_x86_win64.rs
index 71ecb6e9ca1..a849f382473 100644
--- a/src/librustc_trans/cabi_x86_win64.rs
+++ b/src/librustc_trans/cabi_x86_win64.rs
@@ -18,16 +18,20 @@ use type_::Type;
 
 pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
     let fixup = |a: &mut ArgType| {
-        if a.ty.kind() == Struct {
-            match llsize_of_alloc(ccx, a.ty) {
-                1 => a.cast = Some(Type::i8(ccx)),
-                2 => a.cast = Some(Type::i16(ccx)),
-                4 => a.cast = Some(Type::i32(ccx)),
-                8 => a.cast = Some(Type::i64(ccx)),
-                _ => a.make_indirect(ccx)
-            }
-        } else {
-            a.extend_integer_width_to(32);
+        match a.ty.kind() {
+            Struct => match llsize_of_alloc(ccx, a.ty) {
+                          1 => a.cast = Some(Type::i8(ccx)),
+                          2 => a.cast = Some(Type::i16(ccx)),
+                          4 => a.cast = Some(Type::i32(ccx)),
+                          8 => a.cast = Some(Type::i64(ccx)),
+                          _ => a.make_indirect(ccx)
+                      },
+            Integer => match llsize_of_alloc(ccx, a.ty) {
+                           1 ... 8 => a.extend_integer_width_to(32),
+                           16 => a.make_indirect(ccx),
+                           _ => bug!(),
+            },
+            _ => (),
         }
     };
 
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index 71e17f1ea74..7e7bd15dc6e 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -44,6 +44,8 @@ use syntax::ast;
 use syntax::symbol::{Symbol, InternedString};
 use syntax_pos::Span;
 
+use rustc_i128::u128;
+
 pub use context::{CrateContext, SharedCrateContext};
 
 pub fn type_is_fat_ptr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
@@ -425,6 +427,17 @@ pub fn C_integral(t: Type, u: u64, sign_extend: bool) -> ValueRef {
     }
 }
 
+pub fn C_big_integral(t: Type, u: u128, sign_extend: bool) -> ValueRef {
+    if ::std::mem::size_of::<u128>() == 16 {
+        unsafe {
+            llvm::LLVMConstIntOfArbitraryPrecision(t.to_ref(), 2, &u as *const u128 as *const u64)
+        }
+    } else {
+        // SNAP: remove after snapshot
+        C_integral(t, u as u64, sign_extend)
+    }
+}
+
 pub fn C_floating_f64(f: f64, t: Type) -> ValueRef {
     unsafe {
         llvm::LLVMConstReal(t.to_ref(), f)
@@ -580,20 +593,29 @@ fn is_const_integral(v: ValueRef) -> bool {
     }
 }
 
-pub fn const_to_opt_int(v: ValueRef) -> Option<i64> {
-    unsafe {
-        if is_const_integral(v) {
-            Some(llvm::LLVMConstIntGetSExtValue(v))
-        } else {
-            None
-        }
-    }
+#[inline]
+#[cfg(stage0)]
+fn hi_lo_to_u128(lo: u64, _: u64) -> u128 {
+    lo as u128
 }
 
-pub fn const_to_opt_uint(v: ValueRef) -> Option<u64> {
+#[inline]
+#[cfg(not(stage0))]
+fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
+    ((hi as u128) << 64) | (lo as u128)
+}
+
+pub fn const_to_opt_u128(v: ValueRef, sign_ext: bool) -> Option<u128> {
     unsafe {
         if is_const_integral(v) {
-            Some(llvm::LLVMConstIntGetZExtValue(v))
+            let (mut lo, mut hi) = (0u64, 0u64);
+            let success = llvm::LLVMRustConstInt128Get(v, sign_ext,
+                                                       &mut hi as *mut u64, &mut lo as *mut u64);
+            if success {
+                Some(hi_lo_to_u128(lo, hi))
+            } else {
+                None
+            }
         } else {
             None
         }
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index d9179d6a6fa..413b6437408 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -1022,6 +1022,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: &str) -> Option<ValueRef> {
     let t_i16 = Type::i16(ccx);
     let t_i32 = Type::i32(ccx);
     let t_i64 = Type::i64(ccx);
+    let t_i128 = Type::i128(ccx);
     let t_f32 = Type::f32(ccx);
     let t_f64 = Type::f64(ccx);
 
@@ -1088,50 +1089,60 @@ fn declare_intrinsic(ccx: &CrateContext, key: &str) -> Option<ValueRef> {
     ifn!("llvm.ctpop.i16", fn(t_i16) -> t_i16);
     ifn!("llvm.ctpop.i32", fn(t_i32) -> t_i32);
     ifn!("llvm.ctpop.i64", fn(t_i64) -> t_i64);
+    ifn!("llvm.ctpop.i128", fn(t_i128) -> t_i128);
 
     ifn!("llvm.ctlz.i8", fn(t_i8 , i1) -> t_i8);
     ifn!("llvm.ctlz.i16", fn(t_i16, i1) -> t_i16);
     ifn!("llvm.ctlz.i32", fn(t_i32, i1) -> t_i32);
     ifn!("llvm.ctlz.i64", fn(t_i64, i1) -> t_i64);
+    ifn!("llvm.ctlz.i128", fn(t_i128, i1) -> t_i128);
 
     ifn!("llvm.cttz.i8", fn(t_i8 , i1) -> t_i8);
     ifn!("llvm.cttz.i16", fn(t_i16, i1) -> t_i16);
     ifn!("llvm.cttz.i32", fn(t_i32, i1) -> t_i32);
     ifn!("llvm.cttz.i64", fn(t_i64, i1) -> t_i64);
+    ifn!("llvm.cttz.i128", fn(t_i128, i1) -> t_i128);
 
     ifn!("llvm.bswap.i16", fn(t_i16) -> t_i16);
     ifn!("llvm.bswap.i32", fn(t_i32) -> t_i32);
     ifn!("llvm.bswap.i64", fn(t_i64) -> t_i64);
+    ifn!("llvm.bswap.i128", fn(t_i128) -> t_i128);
 
     ifn!("llvm.sadd.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
     ifn!("llvm.sadd.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
     ifn!("llvm.sadd.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
     ifn!("llvm.sadd.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
+    ifn!("llvm.sadd.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
 
     ifn!("llvm.uadd.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
     ifn!("llvm.uadd.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
     ifn!("llvm.uadd.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
     ifn!("llvm.uadd.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
+    ifn!("llvm.uadd.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
 
     ifn!("llvm.ssub.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
     ifn!("llvm.ssub.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
     ifn!("llvm.ssub.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
     ifn!("llvm.ssub.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
+    ifn!("llvm.ssub.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
 
     ifn!("llvm.usub.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
     ifn!("llvm.usub.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
     ifn!("llvm.usub.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
     ifn!("llvm.usub.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
+    ifn!("llvm.usub.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
 
     ifn!("llvm.smul.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
     ifn!("llvm.smul.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
     ifn!("llvm.smul.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
     ifn!("llvm.smul.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
+    ifn!("llvm.smul.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
 
     ifn!("llvm.umul.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
     ifn!("llvm.umul.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
     ifn!("llvm.umul.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
     ifn!("llvm.umul.with.overflow.i64", fn(t_i64, t_i64) -> mk_struct!{t_i64, i1});
+    ifn!("llvm.umul.with.overflow.i128", fn(t_i128, t_i128) -> mk_struct!{t_i128, i1});
 
     ifn!("llvm.lifetime.start", fn(t_i64,i8p) -> void);
     ifn!("llvm.lifetime.end", fn(t_i64, i8p) -> void);
diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs
index 511c9d3c13f..f6428465eda 100644
--- a/src/librustc_trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/debuginfo/metadata.rs
@@ -906,7 +906,7 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> {
 
             MemberDescription {
                 name: name,
-                llvm_type: type_of::type_of(cx, fty),
+                llvm_type: type_of::in_memory_type_of(cx, fty),
                 type_metadata: type_metadata(cx, fty, self.span),
                 offset: offset,
                 flags: DIFlags::FlagZero,
@@ -1460,7 +1460,8 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 llvm::LLVMRustDIBuilderCreateEnumerator(
                     DIB(cx),
                     name.as_ptr(),
-                    v.disr_val.to_u64_unchecked())
+                    // FIXME: what if enumeration has i128 discriminant?
+                    v.disr_val.to_u128_unchecked() as u64)
             }
         })
         .collect();
diff --git a/src/librustc_trans/disr.rs b/src/librustc_trans/disr.rs
index fc79fa813aa..c5737c6e5f1 100644
--- a/src/librustc_trans/disr.rs
+++ b/src/librustc_trans/disr.rs
@@ -26,7 +26,8 @@ impl ::std::ops::BitAnd for Disr {
 
 impl From<::rustc::ty::Disr> for Disr {
     fn from(i: ::rustc::ty::Disr) -> Disr {
-        Disr(i.to_u64_unchecked())
+        // FIXME: what if discr has 128 bit discr?
+        Disr(i.to_u128_unchecked() as u64)
     }
 }
 
diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs
index 3989dae553f..62141369cae 100644
--- a/src/librustc_trans/glue.rs
+++ b/src/librustc_trans/glue.rs
@@ -346,11 +346,12 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &BlockAndBuilder<'a, 'tcx>,
 
             // Choose max of two known alignments (combined value must
             // be aligned according to more restrictive of the two).
-            let align = match (const_to_opt_uint(sized_align), const_to_opt_uint(unsized_align)) {
+            let align = match (const_to_opt_u128(sized_align, false),
+                               const_to_opt_u128(unsized_align, false)) {
                 (Some(sized_align), Some(unsized_align)) => {
                     // If both alignments are constant, (the sized_align should always be), then
                     // pick the correct alignment statically.
-                    C_uint(ccx, std::cmp::max(sized_align, unsized_align))
+                    C_uint(ccx, std::cmp::max(sized_align, unsized_align) as u64)
                 }
                 _ => bcx.select(bcx.icmp(llvm::IntUGT, sized_align, unsized_align),
                                 sized_align,
diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs
index b7116ba1f33..c4129b346e4 100644
--- a/src/librustc_trans/intrinsic.rs
+++ b/src/librustc_trans/intrinsic.rs
@@ -32,6 +32,8 @@ use syntax::symbol::Symbol;
 use rustc::session::Session;
 use syntax_pos::Span;
 
+use rustc_i128::u128;
+
 use std::cmp::Ordering;
 use std::iter;
 
@@ -1019,7 +1021,7 @@ fn generic_simd_intrinsic<'a, 'tcx>(
                  in_elem, in_ty,
                  ret_ty, ret_ty.simd_type(tcx));
 
-        let total_len = in_len as u64 * 2;
+        let total_len = in_len as u128 * 2;
 
         let vector = llargs[2];
 
@@ -1027,7 +1029,7 @@ fn generic_simd_intrinsic<'a, 'tcx>(
             .map(|i| {
                 let arg_idx = i;
                 let val = const_get_elt(vector, &[i as libc::c_uint]);
-                match const_to_opt_uint(val) {
+                match const_to_opt_u128(val, true) {
                     None => {
                         emit_error!("shuffle index #{} is not a constant", arg_idx);
                         None
@@ -1167,6 +1169,8 @@ fn generic_simd_intrinsic<'a, 'tcx>(
 
 // Returns the width of an int TypeVariant, and if it's signed or not
 // Returns None if the type is not an integer
+// FIXME: there’s multiple of this functions, investigate using some of the already existing
+// stuffs.
 fn int_type_width_signed<'tcx>(sty: &ty::TypeVariants<'tcx>, ccx: &CrateContext)
         -> Option<(u64, bool)> {
     use rustc::ty::{TyInt, TyUint};
@@ -1184,6 +1188,7 @@ fn int_type_width_signed<'tcx>(sty: &ty::TypeVariants<'tcx>, ccx: &CrateContext)
             ast::IntTy::I16 => 16,
             ast::IntTy::I32 => 32,
             ast::IntTy::I64 => 64,
+            ast::IntTy::I128 => 128,
         }, true)),
         TyUint(t) => Some((match t {
             ast::UintTy::Us => {
@@ -1198,6 +1203,7 @@ fn int_type_width_signed<'tcx>(sty: &ty::TypeVariants<'tcx>, ccx: &CrateContext)
             ast::UintTy::U16 => 16,
             ast::UintTy::U32 => 32,
             ast::UintTy::U64 => 64,
+            ast::UintTy::U128 => 128,
         }, false)),
         _ => None,
     }
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index 3a8eef131a2..3a4171e1d0e 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -57,6 +57,7 @@ extern crate rustc_const_eval;
 #[macro_use]
 #[no_link]
 extern crate rustc_bitflags;
+extern crate rustc_i128;
 
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
@@ -103,10 +104,13 @@ mod cabi_asmjs;
 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;
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index 71ac7c0d252..ecedcd68382 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -269,7 +269,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
 
             mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => {
                 let cond = self.trans_operand(&bcx, cond).immediate();
-                let mut const_cond = common::const_to_opt_uint(cond).map(|c| c == 1);
+                let mut const_cond = common::const_to_opt_u128(cond, false).map(|c| c == 1);
 
                 // This case can currently arise only from functions marked
                 // with #[rustc_inherit_overflow_checks] and inlined from
@@ -322,14 +322,12 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
                         let len = self.trans_operand(&mut bcx, len).immediate();
                         let index = self.trans_operand(&mut bcx, index).immediate();
 
-                        let const_err = common::const_to_opt_uint(len).and_then(|len| {
-                            common::const_to_opt_uint(index).map(|index| {
-                                ErrKind::IndexOutOfBounds {
-                                    len: len,
-                                    index: index
-                                }
-                            })
-                        });
+                        let const_err = common::const_to_opt_u128(len, false)
+                            .and_then(|len| common::const_to_opt_u128(index, false)
+                                .map(|index| ErrKind::IndexOutOfBounds {
+                                    len: len as u64,
+                                    index: index as u64
+                                }));
 
                         let file_line = C_struct(bcx.ccx, &[filename, line], false);
                         let align = llalign_of_min(bcx.ccx, common::val_ty(file_line));
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index 1cedaa0a4e1..700894c255d 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -13,7 +13,7 @@ use rustc::middle::const_val::ConstVal;
 use rustc_const_eval::{ErrKind, ConstEvalErr, report_const_eval_err};
 use rustc_const_math::ConstInt::*;
 use rustc_const_math::ConstFloat::*;
-use rustc_const_math::{ConstInt, ConstIsize, ConstUsize, ConstMathErr};
+use rustc_const_math::{ConstInt, ConstMathErr};
 use rustc::hir::def_id::DefId;
 use rustc::infer::TransNormalize;
 use rustc::mir;
@@ -25,16 +25,15 @@ use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use {abi, adt, base, Disr, machine};
 use callee::Callee;
 use common::{self, BlockAndBuilder, CrateContext, const_get_elt, val_ty};
-use common::{C_array, C_bool, C_bytes, C_floating_f64, C_integral};
+use common::{C_array, C_bool, C_bytes, C_floating_f64, C_integral, C_big_integral};
 use common::{C_null, C_struct, C_str_slice, C_undef, C_uint};
-use common::{const_to_opt_int, const_to_opt_uint};
+use common::{const_to_opt_u128};
 use consts;
 use monomorphize::{self, Instance};
 use type_of;
 use type_::Type;
 use value::Value;
 
-use syntax::ast;
 use syntax_pos::Span;
 
 use std::fmt;
@@ -43,6 +42,8 @@ use std::ptr;
 use super::operand::{OperandRef, OperandValue};
 use super::MirContext;
 
+use rustc_i128::{u128, i128};
+
 /// A sized constant rvalue.
 /// The LLVM type might not be the same for a single Rust type,
 /// e.g. each enum variant would have its own LLVM struct type.
@@ -75,6 +76,7 @@ impl<'tcx> Const<'tcx> {
             ConstVal::Integral(I16(v)) => C_integral(Type::i16(ccx), v as u64, true),
             ConstVal::Integral(I32(v)) => C_integral(Type::i32(ccx), v as u64, true),
             ConstVal::Integral(I64(v)) => C_integral(Type::i64(ccx), v as u64, true),
+            ConstVal::Integral(I128(v)) => C_big_integral(Type::i128(ccx), v as u128, true),
             ConstVal::Integral(Isize(v)) => {
                 let i = v.as_i64(ccx.tcx().sess.target.int_type);
                 C_integral(Type::int(ccx), i as u64, true)
@@ -83,6 +85,7 @@ impl<'tcx> Const<'tcx> {
             ConstVal::Integral(U16(v)) => C_integral(Type::i16(ccx), v as u64, false),
             ConstVal::Integral(U32(v)) => C_integral(Type::i32(ccx), v as u64, false),
             ConstVal::Integral(U64(v)) => C_integral(Type::i64(ccx), v, false),
+            ConstVal::Integral(U128(v)) => C_big_integral(Type::i128(ccx), v, false),
             ConstVal::Integral(Usize(v)) => {
                 let u = v.as_u64(ccx.tcx().sess.target.uint_type);
                 C_integral(Type::int(ccx), u, false)
@@ -428,7 +431,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
                     mir::ProjectionElem::Index(ref index) => {
                         let llindex = self.const_operand(index, span)?.llval;
 
-                        let iv = if let Some(iv) = common::const_to_opt_uint(llindex) {
+                        let iv = if let Some(iv) = common::const_to_opt_u128(llindex, false) {
                             iv
                         } else {
                             span_bug!(span, "index is not an integer-constant expression")
@@ -436,7 +439,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
 
                         // Produce an undef instead of a LLVM assertion on OOB.
                         let len = common::const_to_uint(tr_base.len(self.ccx));
-                        let llelem = if iv < len {
+                        let llelem = if iv < len as u128 {
                             const_get_elt(base.llval, &[iv as u32])
                         } else {
                             C_undef(type_of::type_of(self.ccx, projected_ty))
@@ -794,49 +797,14 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
 
 fn to_const_int(value: ValueRef, t: Ty, tcx: TyCtxt) -> Option<ConstInt> {
     match t.sty {
-        ty::TyInt(int_type) => const_to_opt_int(value).and_then(|input| match int_type {
-            ast::IntTy::I8 => {
-                assert_eq!(input as i8 as i64, input);
-                Some(ConstInt::I8(input as i8))
-            },
-            ast::IntTy::I16 => {
-                assert_eq!(input as i16 as i64, input);
-                Some(ConstInt::I16(input as i16))
-            },
-            ast::IntTy::I32 => {
-                assert_eq!(input as i32 as i64, input);
-                Some(ConstInt::I32(input as i32))
-            },
-            ast::IntTy::I64 => {
-                Some(ConstInt::I64(input))
-            },
-            ast::IntTy::Is => {
-                ConstIsize::new(input, tcx.sess.target.int_type)
-                    .ok().map(ConstInt::Isize)
-            },
-        }),
-        ty::TyUint(uint_type) => const_to_opt_uint(value).and_then(|input| match uint_type {
-            ast::UintTy::U8 => {
-                assert_eq!(input as u8 as u64, input);
-                Some(ConstInt::U8(input as u8))
-            },
-            ast::UintTy::U16 => {
-                assert_eq!(input as u16 as u64, input);
-                Some(ConstInt::U16(input as u16))
-            },
-            ast::UintTy::U32 => {
-                assert_eq!(input as u32 as u64, input);
-                Some(ConstInt::U32(input as u32))
-            },
-            ast::UintTy::U64 => {
-                Some(ConstInt::U64(input))
-            },
-            ast::UintTy::Us => {
-                ConstUsize::new(input, tcx.sess.target.uint_type)
-                    .ok().map(ConstInt::Usize)
-            },
-        }),
-        _ => None,
+        ty::TyInt(int_type) => const_to_opt_u128(value, true)
+            .and_then(|input| ConstInt::new_signed(input as i128, int_type,
+                                                   tcx.sess.target.int_type)),
+        ty::TyUint(uint_type) => const_to_opt_u128(value, false)
+            .and_then(|input| ConstInt::new_unsigned(input, uint_type,
+                                                     tcx.sess.target.uint_type)),
+        _ => None
+
     }
 }
 
diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs
index 7a50e5cbe8c..a1373cb9482 100644
--- a/src/librustc_trans/mir/mod.rs
+++ b/src/librustc_trans/mir/mod.rs
@@ -205,6 +205,7 @@ pub fn trans_mir<'a, 'tcx: 'a>(
     sig: &ty::FnSig<'tcx>,
     abi: Abi,
 ) {
+    debug!("fn_ty: {:?}", fn_ty);
     let debug_context =
         debuginfo::create_function_debug_context(fcx.ccx, instance, sig, abi, fcx.llfn, mir);
     let bcx = fcx.get_entry_block();
diff --git a/src/librustc_trans/mir/operand.rs b/src/librustc_trans/mir/operand.rs
index a15d51d9da6..526155655af 100644
--- a/src/librustc_trans/mir/operand.rs
+++ b/src/librustc_trans/mir/operand.rs
@@ -79,7 +79,7 @@ impl<'a, 'tcx> OperandRef<'tcx> {
     pub fn immediate(self) -> ValueRef {
         match self.val {
             OperandValue::Immediate(s) => s,
-            _ => bug!()
+            _ => bug!("not immediate: {:?}", self)
         }
     }
 
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index b17550087ed..cca48737bb9 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -711,11 +711,13 @@ fn get_overflow_intrinsic(oop: OverflowOp, bcx: &BlockAndBuilder, ty: Ty) -> Val
             TyInt(I16) => "llvm.sadd.with.overflow.i16",
             TyInt(I32) => "llvm.sadd.with.overflow.i32",
             TyInt(I64) => "llvm.sadd.with.overflow.i64",
+            TyInt(I128) => "llvm.sadd.with.overflow.i128",
 
             TyUint(U8) => "llvm.uadd.with.overflow.i8",
             TyUint(U16) => "llvm.uadd.with.overflow.i16",
             TyUint(U32) => "llvm.uadd.with.overflow.i32",
             TyUint(U64) => "llvm.uadd.with.overflow.i64",
+            TyUint(U128) => "llvm.uadd.with.overflow.i128",
 
             _ => unreachable!(),
         },
@@ -724,11 +726,13 @@ fn get_overflow_intrinsic(oop: OverflowOp, bcx: &BlockAndBuilder, ty: Ty) -> Val
             TyInt(I16) => "llvm.ssub.with.overflow.i16",
             TyInt(I32) => "llvm.ssub.with.overflow.i32",
             TyInt(I64) => "llvm.ssub.with.overflow.i64",
+            TyInt(I128) => "llvm.ssub.with.overflow.i128",
 
             TyUint(U8) => "llvm.usub.with.overflow.i8",
             TyUint(U16) => "llvm.usub.with.overflow.i16",
             TyUint(U32) => "llvm.usub.with.overflow.i32",
             TyUint(U64) => "llvm.usub.with.overflow.i64",
+            TyUint(U128) => "llvm.usub.with.overflow.i128",
 
             _ => unreachable!(),
         },
@@ -737,11 +741,13 @@ fn get_overflow_intrinsic(oop: OverflowOp, bcx: &BlockAndBuilder, ty: Ty) -> Val
             TyInt(I16) => "llvm.smul.with.overflow.i16",
             TyInt(I32) => "llvm.smul.with.overflow.i32",
             TyInt(I64) => "llvm.smul.with.overflow.i64",
+            TyInt(I128) => "llvm.smul.with.overflow.i128",
 
             TyUint(U8) => "llvm.umul.with.overflow.i8",
             TyUint(U16) => "llvm.umul.with.overflow.i16",
             TyUint(U32) => "llvm.umul.with.overflow.i32",
             TyUint(U64) => "llvm.umul.with.overflow.i64",
+            TyUint(U128) => "llvm.umul.with.overflow.i128",
 
             _ => unreachable!(),
         },
diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs
index 6e0d8d08e70..f6f91411225 100644
--- a/src/librustc_trans/trans_item.rs
+++ b/src/librustc_trans/trans_item.rs
@@ -397,11 +397,13 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
             ty::TyInt(ast::IntTy::I16)   => output.push_str("i16"),
             ty::TyInt(ast::IntTy::I32)   => output.push_str("i32"),
             ty::TyInt(ast::IntTy::I64)   => output.push_str("i64"),
+            ty::TyInt(ast::IntTy::I128)   => output.push_str("i128"),
             ty::TyUint(ast::UintTy::Us)   => output.push_str("usize"),
             ty::TyUint(ast::UintTy::U8)   => output.push_str("u8"),
             ty::TyUint(ast::UintTy::U16)  => output.push_str("u16"),
             ty::TyUint(ast::UintTy::U32)  => output.push_str("u32"),
             ty::TyUint(ast::UintTy::U64)  => output.push_str("u64"),
+            ty::TyUint(ast::UintTy::U128)  => output.push_str("u128"),
             ty::TyFloat(ast::FloatTy::F32) => output.push_str("f32"),
             ty::TyFloat(ast::FloatTy::F64) => output.push_str("f64"),
             ty::TyAdt(adt_def, substs) => {
diff --git a/src/librustc_trans/type_.rs b/src/librustc_trans/type_.rs
index 2b2776acab8..f68acab9113 100644
--- a/src/librustc_trans/type_.rs
+++ b/src/librustc_trans/type_.rs
@@ -94,6 +94,10 @@ impl Type {
         ty!(llvm::LLVMInt64TypeInContext(ccx.llcx()))
     }
 
+    pub fn i128(ccx: &CrateContext) -> Type {
+        ty!(llvm::LLVMIntTypeInContext(ccx.llcx(), 128))
+    }
+
     // Creates an integer type with the given number of bits, e.g. i24
     pub fn ix(ccx: &CrateContext, num_bits: u64) -> Type {
         ty!(llvm::LLVMIntTypeInContext(ccx.llcx(), num_bits as c_uint))
@@ -134,7 +138,8 @@ impl Type {
             ast::IntTy::I8 => Type::i8(ccx),
             ast::IntTy::I16 => Type::i16(ccx),
             ast::IntTy::I32 => Type::i32(ccx),
-            ast::IntTy::I64 => Type::i64(ccx)
+            ast::IntTy::I64 => Type::i64(ccx),
+            ast::IntTy::I128 => Type::i128(ccx),
         }
     }
 
@@ -144,7 +149,8 @@ impl Type {
             ast::UintTy::U8 => Type::i8(ccx),
             ast::UintTy::U16 => Type::i16(ccx),
             ast::UintTy::U32 => Type::i32(ccx),
-            ast::UintTy::U64 => Type::i64(ccx)
+            ast::UintTy::U64 => Type::i64(ccx),
+            ast::UintTy::U128 => Type::i128(ccx),
         }
     }
 
@@ -307,6 +313,7 @@ impl Type {
             I16 => Type::i16(cx),
             I32 => Type::i32(cx),
             I64 => Type::i64(cx),
+            I128 => Type::i128(cx),
         }
     }
 
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index c733c0856c6..4f41bbe9924 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -432,7 +432,9 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
             (true,  32, &ty::TyInt(ast::IntTy::I32)) |
             (false, 32, &ty::TyUint(ast::UintTy::U32)) |
             (true,  64, &ty::TyInt(ast::IntTy::I64)) |
-            (false, 64, &ty::TyUint(ast::UintTy::U64)) => {},
+            (false, 64, &ty::TyUint(ast::UintTy::U64)) |
+            (true,  128, &ty::TyInt(ast::IntTy::I128)) |
+            (false, 128, &ty::TyUint(ast::UintTy::U128)) => {},
             _ => simple_error(&format!("`{}`", t),
                               &format!("`{}{n}`",
                                        if signed {"i"} else {"u"},
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 1962534c397..5c3da4237be 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -435,6 +435,10 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                 let lang_def_id = self.tcx.lang_items.i64_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
+            ty::TyInt(ast::IntTy::I128) => {
+                let lang_def_id = self.tcx.lang_items.i128_impl();
+                self.assemble_inherent_impl_for_primitive(lang_def_id);
+            }
             ty::TyInt(ast::IntTy::Is) => {
                 let lang_def_id = self.tcx.lang_items.isize_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
@@ -455,6 +459,10 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                 let lang_def_id = self.tcx.lang_items.u64_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
             }
+            ty::TyUint(ast::UintTy::U128) => {
+                let lang_def_id = self.tcx.lang_items.u128_impl();
+                self.assemble_inherent_impl_for_primitive(lang_def_id);
+            }
             ty::TyUint(ast::UintTy::Us) => {
                 let lang_def_id = self.tcx.lang_items.usize_impl();
                 self.assemble_inherent_impl_for_primitive(lang_def_id);
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 7275fbd1203..26dd53fecb2 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1330,6 +1330,13 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     }
 
     let repr_type_ty = ccx.tcx.enum_repr_type(Some(&hint)).to_ty(ccx.tcx);
+    if repr_type_ty == ccx.tcx.types.i128 || repr_type_ty == ccx.tcx.types.u128 {
+        if !ccx.tcx.sess.features.borrow().i128_type {
+            emit_feature_err(&ccx.tcx.sess.parse_sess,
+                             "i128_type", sp, GateIssue::Language, "128-bit type is unstable");
+        }
+    }
+
     for v in vs {
         if let Some(e) = v.node.disr_expr {
             check_const_with_type(ccx, e, repr_type_ty, e.node_id);
diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs
index bc1ead07c0e..2b5a4515cd0 100644
--- a/src/librustc_typeck/coherence/orphan.rs
+++ b/src/librustc_typeck/coherence/orphan.rs
@@ -160,6 +160,13 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> {
                                                   "i64",
                                                   item.span);
                     }
+                    ty::TyInt(ast::IntTy::I128) => {
+                        self.check_primitive_impl(def_id,
+                                                  self.tcx.lang_items.i128_impl(),
+                                                  "i128",
+                                                  "i128",
+                                                  item.span);
+                    }
                     ty::TyInt(ast::IntTy::Is) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.isize_impl(),
@@ -195,6 +202,13 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> {
                                                   "u64",
                                                   item.span);
                     }
+                    ty::TyUint(ast::UintTy::U128) => {
+                        self.check_primitive_impl(def_id,
+                                                  self.tcx.lang_items.u128_impl(),
+                                                  "u128",
+                                                  "u128",
+                                                  item.span);
+                    }
                     ty::TyUint(ast::UintTy::Us) => {
                         self.check_primitive_impl(def_id,
                                                   self.tcx.lang_items.usize_impl(),
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index fd51b38e1b5..7ddf10375bf 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1060,11 +1060,13 @@ fn convert_union_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                     (attr::SignedInt(ast::IntTy::I16), ConstInt::I16(_)) |
                     (attr::SignedInt(ast::IntTy::I32), ConstInt::I32(_)) |
                     (attr::SignedInt(ast::IntTy::I64), ConstInt::I64(_)) |
+                    (attr::SignedInt(ast::IntTy::I128), ConstInt::I128(_)) |
                     (attr::SignedInt(ast::IntTy::Is), ConstInt::Isize(_)) |
                     (attr::UnsignedInt(ast::UintTy::U8), ConstInt::U8(_)) |
                     (attr::UnsignedInt(ast::UintTy::U16), ConstInt::U16(_)) |
                     (attr::UnsignedInt(ast::UintTy::U32), ConstInt::U32(_)) |
                     (attr::UnsignedInt(ast::UintTy::U64), ConstInt::U64(_)) |
+                    (attr::UnsignedInt(ast::UintTy::U128), ConstInt::U128(_)) |
                     (attr::UnsignedInt(ast::UintTy::Us), ConstInt::Usize(_)) => Some(i),
                     (_, i) => {
                         print_err(ConstVal::Integral(i));
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index cba5e1ba6f3..93854193762 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -268,11 +268,13 @@ pub fn build_impls(cx: &DocContext, did: DefId) -> Vec<clean::Item> {
         tcx.lang_items.i16_impl(),
         tcx.lang_items.i32_impl(),
         tcx.lang_items.i64_impl(),
+        tcx.lang_items.i128_impl(),
         tcx.lang_items.usize_impl(),
         tcx.lang_items.u8_impl(),
         tcx.lang_items.u16_impl(),
         tcx.lang_items.u32_impl(),
         tcx.lang_items.u64_impl(),
+        tcx.lang_items.u128_impl(),
         tcx.lang_items.f32_impl(),
         tcx.lang_items.f64_impl(),
         tcx.lang_items.char_impl(),
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 3b828198069..e0a26ca3181 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1513,8 +1513,8 @@ pub enum Type {
 
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
 pub enum PrimitiveType {
-    Isize, I8, I16, I32, I64,
-    Usize, U8, U16, U32, U64,
+    Isize, I8, I16, I32, I64, I128,
+    Usize, U8, U16, U32, U64, U128,
     F32, F64,
     Char,
     Bool,
@@ -1595,11 +1595,13 @@ impl PrimitiveType {
             "i16" => Some(PrimitiveType::I16),
             "i32" => Some(PrimitiveType::I32),
             "i64" => Some(PrimitiveType::I64),
+            "i128" => Some(PrimitiveType::I128),
             "usize" => Some(PrimitiveType::Usize),
             "u8" => Some(PrimitiveType::U8),
             "u16" => Some(PrimitiveType::U16),
             "u32" => Some(PrimitiveType::U32),
             "u64" => Some(PrimitiveType::U64),
+            "u128" => Some(PrimitiveType::U128),
             "bool" => Some(PrimitiveType::Bool),
             "char" => Some(PrimitiveType::Char),
             "str" => Some(PrimitiveType::Str),
@@ -1614,26 +1616,29 @@ impl PrimitiveType {
     }
 
     pub fn as_str(&self) -> &'static str {
+        use self::PrimitiveType::*;
         match *self {
-            PrimitiveType::Isize => "isize",
-            PrimitiveType::I8 => "i8",
-            PrimitiveType::I16 => "i16",
-            PrimitiveType::I32 => "i32",
-            PrimitiveType::I64 => "i64",
-            PrimitiveType::Usize => "usize",
-            PrimitiveType::U8 => "u8",
-            PrimitiveType::U16 => "u16",
-            PrimitiveType::U32 => "u32",
-            PrimitiveType::U64 => "u64",
-            PrimitiveType::F32 => "f32",
-            PrimitiveType::F64 => "f64",
-            PrimitiveType::Str => "str",
-            PrimitiveType::Bool => "bool",
-            PrimitiveType::Char => "char",
-            PrimitiveType::Array => "array",
-            PrimitiveType::Slice => "slice",
-            PrimitiveType::Tuple => "tuple",
-            PrimitiveType::RawPointer => "pointer",
+            Isize => "isize",
+            I8 => "i8",
+            I16 => "i16",
+            I32 => "i32",
+            I64 => "i64",
+            I128 => "i128",
+            Usize => "usize",
+            U8 => "u8",
+            U16 => "u16",
+            U32 => "u32",
+            U64 => "u64",
+            U128 => "u128",
+            F32 => "f32",
+            F64 => "f64",
+            Str => "str",
+            Bool => "bool",
+            Char => "char",
+            Array => "array",
+            Slice => "slice",
+            Tuple => "tuple",
+            RawPointer => "pointer",
         }
     }
 
@@ -1650,6 +1655,7 @@ impl From<ast::IntTy> for PrimitiveType {
             ast::IntTy::I16 => PrimitiveType::I16,
             ast::IntTy::I32 => PrimitiveType::I32,
             ast::IntTy::I64 => PrimitiveType::I64,
+            ast::IntTy::I128 => PrimitiveType::I128,
         }
     }
 }
@@ -1662,6 +1668,7 @@ impl From<ast::UintTy> for PrimitiveType {
             ast::UintTy::U16 => PrimitiveType::U16,
             ast::UintTy::U32 => PrimitiveType::U32,
             ast::UintTy::U64 => PrimitiveType::U64,
+            ast::UintTy::U128 => PrimitiveType::U128,
         }
     }
 }
@@ -2486,6 +2493,7 @@ impl Clean<Vec<Item>> for doctree::Impl {
 fn build_deref_target_impls(cx: &DocContext,
                             items: &[Item],
                             ret: &mut Vec<Item>) {
+    use self::PrimitiveType::*;
     let tcx = cx.tcx;
 
     for item in items {
@@ -2505,25 +2513,27 @@ fn build_deref_target_impls(cx: &DocContext,
             }
         };
         let did = match primitive {
-            PrimitiveType::Isize => tcx.lang_items.isize_impl(),
-            PrimitiveType::I8 => tcx.lang_items.i8_impl(),
-            PrimitiveType::I16 => tcx.lang_items.i16_impl(),
-            PrimitiveType::I32 => tcx.lang_items.i32_impl(),
-            PrimitiveType::I64 => tcx.lang_items.i64_impl(),
-            PrimitiveType::Usize => tcx.lang_items.usize_impl(),
-            PrimitiveType::U8 => tcx.lang_items.u8_impl(),
-            PrimitiveType::U16 => tcx.lang_items.u16_impl(),
-            PrimitiveType::U32 => tcx.lang_items.u32_impl(),
-            PrimitiveType::U64 => tcx.lang_items.u64_impl(),
-            PrimitiveType::F32 => tcx.lang_items.f32_impl(),
-            PrimitiveType::F64 => tcx.lang_items.f64_impl(),
-            PrimitiveType::Char => tcx.lang_items.char_impl(),
-            PrimitiveType::Bool => None,
-            PrimitiveType::Str => tcx.lang_items.str_impl(),
-            PrimitiveType::Slice => tcx.lang_items.slice_impl(),
-            PrimitiveType::Array => tcx.lang_items.slice_impl(),
-            PrimitiveType::Tuple => None,
-            PrimitiveType::RawPointer => tcx.lang_items.const_ptr_impl(),
+            Isize => tcx.lang_items.isize_impl(),
+            I8 => tcx.lang_items.i8_impl(),
+            I16 => tcx.lang_items.i16_impl(),
+            I32 => tcx.lang_items.i32_impl(),
+            I64 => tcx.lang_items.i64_impl(),
+            I128 => tcx.lang_items.i128_impl(),
+            Usize => tcx.lang_items.usize_impl(),
+            U8 => tcx.lang_items.u8_impl(),
+            U16 => tcx.lang_items.u16_impl(),
+            U32 => tcx.lang_items.u32_impl(),
+            U64 => tcx.lang_items.u64_impl(),
+            U128 => tcx.lang_items.u128_impl(),
+            F32 => tcx.lang_items.f32_impl(),
+            F64 => tcx.lang_items.f64_impl(),
+            Char => tcx.lang_items.char_impl(),
+            Bool => None,
+            Str => tcx.lang_items.str_impl(),
+            Slice => tcx.lang_items.slice_impl(),
+            Array => tcx.lang_items.slice_impl(),
+            Tuple => None,
+            RawPointer => tcx.lang_items.const_ptr_impl(),
         };
         if let Some(did) = did {
             if !did.is_local() {
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index df25473ddd9..1f989c557d3 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -15,7 +15,7 @@ use rustc::session::{self, config};
 use rustc::hir::def_id::DefId;
 use rustc::hir::def::{Def, ExportMap};
 use rustc::middle::privacy::AccessLevels;
-use rustc::ty::{self, TyCtxt, Ty};
+use rustc::ty::{self, TyCtxt, GlobalArenas, Ty};
 use rustc::hir::map as hir_map;
 use rustc::lint;
 use rustc::util::nodemap::{FxHashMap, NodeMap};
@@ -37,6 +37,7 @@ use visit_ast::RustdocVisitor;
 use clean;
 use clean::Clean;
 use html::render::RenderInfo;
+use arena::DroplessArena;
 
 pub use rustc::session::config::Input;
 pub use rustc::session::search_paths::SearchPaths;
@@ -160,13 +161,15 @@ pub fn run_core(search_paths: SearchPaths,
         ).expect("phase_2_configure_and_expand aborted in rustdoc!")
     };
 
-    let arenas = ty::CtxtArenas::new();
+    let arena = DroplessArena::new();
+    let arenas = GlobalArenas::new();
     let hir_map = hir_map::map_crate(&mut hir_forest, defs);
 
     abort_on_err(driver::phase_3_run_analysis_passes(&sess,
                                                      hir_map,
                                                      analysis,
                                                      resolutions,
+                                                     &arena,
                                                      &arenas,
                                                      &name,
                                                      |tcx, analysis, _, result| {
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index d66adb5ecfa..ff7133f5d0c 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -2057,10 +2057,9 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         let item_type = m.type_();
         let id = derive_id(format!("{}.{}", item_type, name));
         let ns_id = derive_id(format!("{}.{}", name, item_type.name_space()));
-        write!(w, "<h3 id='{id}' class='method stab {stab}'>\
+        write!(w, "<h3 id='{id}' class='method'>\
                    <span id='{ns_id}' class='invisible'><code>",
                id = id,
-               stab = m.stability_class(),
                ns_id = ns_id)?;
         render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl)?;
         write!(w, "</code>")?;
diff --git a/src/libserialize/Cargo.toml b/src/libserialize/Cargo.toml
index 919cda49c00..3213b4e4208 100644
--- a/src/libserialize/Cargo.toml
+++ b/src/libserialize/Cargo.toml
@@ -10,3 +10,4 @@ crate-type = ["dylib", "rlib"]
 
 [dependencies]
 log = { path = "../liblog" }
+rustc_i128 = { path = "../librustc_i128" }
diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs
index 239d32c8fc8..3e62026f512 100644
--- a/src/libserialize/json.rs
+++ b/src/libserialize/json.rs
@@ -211,6 +211,8 @@ use std::string;
 use std::{char, f64, fmt, str};
 use std;
 
+use rustc_i128::{i128, u128};
+
 use Encodable;
 
 /// Represents a json value
@@ -494,12 +496,14 @@ impl<'a> ::Encoder for Encoder<'a> {
     }
 
     fn emit_usize(&mut self, v: usize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
+    fn emit_u128(&mut self, v: u128) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
     fn emit_u64(&mut self, v: u64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
     fn emit_u32(&mut self, v: u32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
     fn emit_u16(&mut self, v: u16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
     fn emit_u8(&mut self, v: u8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
 
     fn emit_isize(&mut self, v: isize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
+    fn emit_i128(&mut self, v: i128) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
     fn emit_i64(&mut self, v: i64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
     fn emit_i32(&mut self, v: i32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
     fn emit_i16(&mut self, v: i16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
@@ -742,12 +746,14 @@ impl<'a> ::Encoder for PrettyEncoder<'a> {
     }
 
     fn emit_usize(&mut self, v: usize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
+    fn emit_u128(&mut self, v: u128) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
     fn emit_u64(&mut self, v: u64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
     fn emit_u32(&mut self, v: u32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
     fn emit_u16(&mut self, v: u16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
     fn emit_u8(&mut self, v: u8) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
 
     fn emit_isize(&mut self, v: isize) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
+    fn emit_i128(&mut self, v: i128) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
     fn emit_i64(&mut self, v: i64) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
     fn emit_i32(&mut self, v: i32) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
     fn emit_i16(&mut self, v: i16) -> EncodeResult { emit_enquoted_if_mapkey!(self, v) }
@@ -2138,11 +2144,13 @@ impl ::Decoder for Decoder {
     read_primitive! { read_u16, u16 }
     read_primitive! { read_u32, u32 }
     read_primitive! { read_u64, u64 }
+    read_primitive! { read_u128, u128 }
     read_primitive! { read_isize, isize }
     read_primitive! { read_i8, i8 }
     read_primitive! { read_i16, i16 }
     read_primitive! { read_i32, i32 }
     read_primitive! { read_i64, i64 }
+    read_primitive! { read_i128, i128 }
 
     fn read_f32(&mut self) -> DecodeResult<f32> { self.read_f64().map(|x| x as f32) }
 
diff --git a/src/libserialize/leb128.rs b/src/libserialize/leb128.rs
index 5b72c6d46ac..392f332d508 100644
--- a/src/libserialize/leb128.rs
+++ b/src/libserialize/leb128.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use rustc_i128::{i128, u128};
+
 #[inline]
 fn write_to_vec(vec: &mut Vec<u8>, position: usize, byte: u8) {
     if position == vec.len() {
@@ -24,11 +26,10 @@ fn write_to_vec(vec: &mut Vec<u8>, position: usize, byte: u8) {
 /// The callback `write` is called once for each position
 /// that is to be written to with the byte to be encoded
 /// at that position.
-pub fn write_unsigned_leb128_to<W>(mut value: u64, mut write: W) -> usize
+pub fn write_unsigned_leb128_to<W>(mut value: u128, mut write: W) -> usize
     where W: FnMut(usize, u8)
 {
     let mut position = 0;
-
     loop {
         let mut byte = (value & 0x7F) as u8;
         value >>= 7;
@@ -47,19 +48,19 @@ pub fn write_unsigned_leb128_to<W>(mut value: u64, mut write: W) -> usize
     position
 }
 
-pub fn write_unsigned_leb128(out: &mut Vec<u8>, start_position: usize, value: u64) -> usize {
+pub fn write_unsigned_leb128(out: &mut Vec<u8>, start_position: usize, value: u128) -> usize {
     write_unsigned_leb128_to(value, |i, v| write_to_vec(out, start_position+i, v))
 }
 
 #[inline]
-pub fn read_unsigned_leb128(data: &[u8], start_position: usize) -> (u64, usize) {
+pub fn read_unsigned_leb128(data: &[u8], start_position: usize) -> (u128, usize) {
     let mut result = 0;
     let mut shift = 0;
     let mut position = start_position;
     loop {
         let byte = data[position];
         position += 1;
-        result |= ((byte & 0x7F) as u64) << shift;
+        result |= ((byte & 0x7F) as u128) << shift;
         if (byte & 0x80) == 0 {
             break;
         }
@@ -76,7 +77,7 @@ pub fn read_unsigned_leb128(data: &[u8], start_position: usize) -> (u64, usize)
 /// The callback `write` is called once for each position
 /// that is to be written to with the byte to be encoded
 /// at that position.
-pub fn write_signed_leb128_to<W>(mut value: i64, mut write: W) -> usize
+pub fn write_signed_leb128_to<W>(mut value: i128, mut write: W) -> usize
     where W: FnMut(usize, u8)
 {
     let mut position = 0;
@@ -86,6 +87,7 @@ pub fn write_signed_leb128_to<W>(mut value: i64, mut write: W) -> usize
         value >>= 7;
         let more = !((((value == 0) && ((byte & 0x40) == 0)) ||
                       ((value == -1) && ((byte & 0x40) != 0))));
+
         if more {
             byte |= 0x80; // Mark this byte to show that more bytes will follow.
         }
@@ -97,16 +99,15 @@ pub fn write_signed_leb128_to<W>(mut value: i64, mut write: W) -> usize
             break;
         }
     }
-
     position
 }
 
-pub fn write_signed_leb128(out: &mut Vec<u8>, start_position: usize, value: i64) -> usize {
+pub fn write_signed_leb128(out: &mut Vec<u8>, start_position: usize, value: i128) -> usize {
     write_signed_leb128_to(value, |i, v| write_to_vec(out, start_position+i, v))
 }
 
 #[inline]
-pub fn read_signed_leb128(data: &[u8], start_position: usize) -> (i64, usize) {
+pub fn read_signed_leb128(data: &[u8], start_position: usize) -> (i128, usize) {
     let mut result = 0;
     let mut shift = 0;
     let mut position = start_position;
@@ -115,7 +116,7 @@ pub fn read_signed_leb128(data: &[u8], start_position: usize) -> (i64, usize) {
     loop {
         byte = data[position];
         position += 1;
-        result |= ((byte & 0x7F) as i64) << shift;
+        result |= ((byte & 0x7F) as i128) << shift;
         shift += 7;
 
         if (byte & 0x80) == 0 {
@@ -125,7 +126,7 @@ pub fn read_signed_leb128(data: &[u8], start_position: usize) -> (i64, usize) {
 
     if (shift < 64) && ((byte & 0x40) != 0) {
         // sign extend
-        result |= -(1i64 << shift);
+        result |= -(1 << shift);
     }
 
     (result, position - start_position)
@@ -153,22 +154,13 @@ fn test_unsigned_leb128() {
 
 #[test]
 fn test_signed_leb128() {
-    let mut values = Vec::new();
-
-    let mut i = -500;
-    while i < 500 {
-        values.push(i * 123457i64);
-        i += 1;
-    }
-
+    let values: Vec<_> = (-500..500).map(|i| i * 0x12345789ABCDEF).collect();
     let mut stream = Vec::new();
-
     for &x in &values {
         let pos = stream.len();
         let bytes_written = write_signed_leb128(&mut stream, pos, x);
         assert_eq!(stream.len(), pos + bytes_written);
     }
-
     let mut pos = 0;
     for &x in &values {
         let (value, bytes_read) = read_signed_leb128(&mut stream, pos);
diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs
index ad2304e1556..0979860189c 100644
--- a/src/libserialize/lib.rs
+++ b/src/libserialize/lib.rs
@@ -44,6 +44,8 @@ Core encoding and decoding interfaces.
 extern crate std_unicode;
 extern crate collections;
 
+extern crate rustc_i128;
+
 pub use self::serialize::{Decoder, Encoder, Decodable, Encodable};
 
 pub use self::serialize::{SpecializationError, SpecializedEncoder, SpecializedDecoder};
diff --git a/src/libserialize/opaque.rs b/src/libserialize/opaque.rs
index 87b6ed2ed40..8a0648d5851 100644
--- a/src/libserialize/opaque.rs
+++ b/src/libserialize/opaque.rs
@@ -13,6 +13,8 @@ use std::borrow::Cow;
 use std::io::{self, Write};
 use serialize;
 
+use rustc_i128::{i128, u128};
+
 // -----------------------------------------------------------------------------
 // Encoder
 // -----------------------------------------------------------------------------
@@ -33,7 +35,7 @@ impl<'a> Encoder<'a> {
 macro_rules! write_uleb128 {
     ($enc:expr, $value:expr) => {{
         let pos = $enc.cursor.position() as usize;
-        let bytes_written = write_unsigned_leb128($enc.cursor.get_mut(), pos, $value as u64);
+        let bytes_written = write_unsigned_leb128($enc.cursor.get_mut(), pos, $value as u128);
         $enc.cursor.set_position((pos + bytes_written) as u64);
         Ok(())
     }}
@@ -42,7 +44,7 @@ macro_rules! write_uleb128 {
 macro_rules! write_sleb128 {
     ($enc:expr, $value:expr) => {{
         let pos = $enc.cursor.position() as usize;
-        let bytes_written = write_signed_leb128($enc.cursor.get_mut(), pos, $value as i64);
+        let bytes_written = write_signed_leb128($enc.cursor.get_mut(), pos, $value as i128);
         $enc.cursor.set_position((pos + bytes_written) as u64);
         Ok(())
     }}
@@ -59,6 +61,10 @@ impl<'a> serialize::Encoder for Encoder<'a> {
         write_uleb128!(self, v)
     }
 
+    fn emit_u128(&mut self, v: u128) -> EncodeResult {
+        write_uleb128!(self, v)
+    }
+
     fn emit_u64(&mut self, v: u64) -> EncodeResult {
         write_uleb128!(self, v)
     }
@@ -80,6 +86,10 @@ impl<'a> serialize::Encoder for Encoder<'a> {
         write_sleb128!(self, v)
     }
 
+    fn emit_i128(&mut self, v: i128) -> EncodeResult {
+        write_sleb128!(self, v)
+    }
+
     fn emit_i64(&mut self, v: i64) -> EncodeResult {
         write_sleb128!(self, v)
     }
@@ -185,6 +195,11 @@ impl<'a> serialize::Decoder for Decoder<'a> {
     }
 
     #[inline]
+    fn read_u128(&mut self) -> Result<u128, Self::Error> {
+        read_uleb128!(self, u128)
+    }
+
+    #[inline]
     fn read_u64(&mut self) -> Result<u64, Self::Error> {
         read_uleb128!(self, u64)
     }
@@ -212,6 +227,11 @@ impl<'a> serialize::Decoder for Decoder<'a> {
     }
 
     #[inline]
+    fn read_i128(&mut self) -> Result<i128, Self::Error> {
+        read_sleb128!(self, i128)
+    }
+
+    #[inline]
     fn read_i64(&mut self) -> Result<i64, Self::Error> {
         read_sleb128!(self, i64)
     }
diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs
index c4613c661a8..395f2ccbe6d 100644
--- a/src/libserialize/serialize.rs
+++ b/src/libserialize/serialize.rs
@@ -20,6 +20,7 @@ use std::path;
 use std::rc::Rc;
 use std::cell::{Cell, RefCell};
 use std::sync::Arc;
+use rustc_i128::{i128, u128};
 
 pub trait Encoder {
     type Error;
@@ -27,11 +28,13 @@ pub trait Encoder {
     // Primitive types:
     fn emit_nil(&mut self) -> Result<(), Self::Error>;
     fn emit_usize(&mut self, v: usize) -> Result<(), Self::Error>;
+    fn emit_u128(&mut self, v: u128) -> Result<(), Self::Error>;
     fn emit_u64(&mut self, v: u64) -> Result<(), Self::Error>;
     fn emit_u32(&mut self, v: u32) -> Result<(), Self::Error>;
     fn emit_u16(&mut self, v: u16) -> Result<(), Self::Error>;
     fn emit_u8(&mut self, v: u8) -> Result<(), Self::Error>;
     fn emit_isize(&mut self, v: isize) -> Result<(), Self::Error>;
+    fn emit_i128(&mut self, v: i128) -> Result<(), Self::Error>;
     fn emit_i64(&mut self, v: i64) -> Result<(), Self::Error>;
     fn emit_i32(&mut self, v: i32) -> Result<(), Self::Error>;
     fn emit_i16(&mut self, v: i16) -> Result<(), Self::Error>;
@@ -144,11 +147,13 @@ pub trait Decoder {
     // Primitive types:
     fn read_nil(&mut self) -> Result<(), Self::Error>;
     fn read_usize(&mut self) -> Result<usize, Self::Error>;
+    fn read_u128(&mut self) -> Result<u128, Self::Error>;
     fn read_u64(&mut self) -> Result<u64, Self::Error>;
     fn read_u32(&mut self) -> Result<u32, Self::Error>;
     fn read_u16(&mut self) -> Result<u16, Self::Error>;
     fn read_u8(&mut self) -> Result<u8, Self::Error>;
     fn read_isize(&mut self) -> Result<isize, Self::Error>;
+    fn read_i128(&mut self) -> Result<i128, Self::Error>;
     fn read_i64(&mut self) -> Result<i64, Self::Error>;
     fn read_i32(&mut self) -> Result<i32, Self::Error>;
     fn read_i16(&mut self) -> Result<i16, Self::Error>;
@@ -328,6 +333,20 @@ impl Decodable for u64 {
     }
 }
 
+#[cfg(not(stage0))]
+impl Encodable for u128 {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        s.emit_u128(*self)
+    }
+}
+
+#[cfg(not(stage0))]
+impl Decodable for u128 {
+    fn decode<D: Decoder>(d: &mut D) -> Result<u128, D::Error> {
+        d.read_u128()
+    }
+}
+
 impl Encodable for isize {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_isize(*self)
@@ -388,6 +407,20 @@ impl Decodable for i64 {
     }
 }
 
+#[cfg(not(stage0))]
+impl Encodable for i128 {
+    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        s.emit_i128(*self)
+    }
+}
+
+#[cfg(not(stage0))]
+impl Decodable for i128 {
+    fn decode<D: Decoder>(d: &mut D) -> Result<i128, D::Error> {
+        d.read_i128()
+    }
+}
+
 impl Encodable for str {
     fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
         s.emit_str(self)
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index 0521f301321..d843d97420a 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -712,6 +712,7 @@ pub mod consts {
     /// - powerpc
     /// - powerpc64
     /// - s390x
+    /// - sparc64
     #[stable(feature = "env", since = "1.0.0")]
     pub const ARCH: &'static str = super::arch::ARCH;
 
@@ -843,6 +844,11 @@ mod arch {
     pub const ARCH: &'static str = "s390x";
 }
 
+#[cfg(target_arch = "sparc64")]
+mod arch {
+    pub const ARCH: &'static str = "sparc64";
+}
+
 #[cfg(target_arch = "le32")]
 mod arch {
     pub const ARCH: &'static str = "le32";
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index fc5c6968544..f1e3996e825 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -301,6 +301,7 @@
 #![feature(unwind_attributes)]
 #![feature(vec_push_all)]
 #![feature(zero_one)]
+#![feature(i128)]
 #![cfg_attr(test, feature(update_panic_count))]
 
 // Explicitly import the prelude. The compiler uses this same unstable attribute
@@ -395,6 +396,9 @@ pub use core::i16;
 pub use core::i32;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::i64;
+#[unstable(feature = "i128", issue = "35118")]
+#[cfg(not(stage0))]
+pub use core::i128;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::usize;
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -423,6 +427,9 @@ pub use core_collections::string;
 pub use core_collections::vec;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use std_unicode::char;
+#[unstable(feature = "i128", issue = "35118")]
+#[cfg(not(stage0))]
+pub use core::u128;
 
 pub mod f32;
 pub mod f64;
diff --git a/src/libstd/os/linux/raw.rs b/src/libstd/os/linux/raw.rs
index 7c9274d0601..bb1830a147e 100644
--- a/src/libstd/os/linux/raw.rs
+++ b/src/libstd/os/linux/raw.rs
@@ -157,12 +157,9 @@ mod arch {
     }
 }
 
-#[cfg(target_arch = "mips64")]
-mod arch {
-    pub use libc::{off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t};
-}
-
-#[cfg(target_arch = "s390x")]
+#[cfg(any(target_arch = "mips64",
+          target_arch = "s390x",
+          target_arch = "sparc64"))]
 mod arch {
     pub use libc::{off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t};
 }
diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs
index 54dde6681e1..5981b482a97 100644
--- a/src/libstd/primitive_docs.rs
+++ b/src/libstd/primitive_docs.rs
@@ -597,6 +597,17 @@ mod prim_i32 { }
 ///
 mod prim_i64 { }
 
+#[doc(primitive = "i128")]
+//
+/// The 128-bit signed integer type.
+///
+/// *[See also the `std::i128` module](i128/index.html).*
+///
+/// However, please note that examples are shared between primitive integer
+/// types. So it's normal if you see usage of types like `i8` in there.
+///
+mod prim_i128 { }
+
 #[doc(primitive = "u8")]
 //
 /// The 8-bit unsigned integer type.
@@ -641,6 +652,17 @@ mod prim_u32 { }
 ///
 mod prim_u64 { }
 
+#[doc(primitive = "u128")]
+//
+/// The 128-bit unsigned integer type.
+///
+/// *[See also the `std::u128` module](u128/index.html).*
+///
+/// However, please note that examples are shared between primitive integer
+/// types. So it's normal if you see usage of types like `u8` in there.
+///
+mod prim_u128 { }
+
 #[doc(primitive = "isize")]
 //
 /// The pointer-sized signed integer type.
diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs
index 2384d959881..dcab30aad83 100644
--- a/src/libstd/sys/unix/fd.rs
+++ b/src/libstd/sys/unix/fd.rs
@@ -10,8 +10,9 @@
 
 #![unstable(reason = "not public", issue = "0", feature = "fd")]
 
+use cmp;
 use io::{self, Read};
-use libc::{self, c_int, c_void};
+use libc::{self, c_int, c_void, ssize_t};
 use mem;
 use sync::atomic::{AtomicBool, Ordering};
 use sys::cvt;
@@ -23,6 +24,22 @@ pub struct FileDesc {
     fd: c_int,
 }
 
+fn max_len() -> usize {
+    // The maximum read limit on most posix-like systems is `SSIZE_MAX`,
+    // with the man page quoting that if the count of bytes to read is
+    // greater than `SSIZE_MAX` the result is "unspecified".
+    //
+    // On OSX, however, apparently the 64-bit libc is either buggy or
+    // intentionally showing odd behavior by rejecting any read with a size
+    // larger than or equal to INT_MAX. To handle both of these the read
+    // size is capped on both platforms.
+    if cfg!(target_os = "macos") {
+        <c_int>::max_value() as usize - 1
+    } else {
+        <ssize_t>::max_value() as usize
+    }
+}
+
 impl FileDesc {
     pub fn new(fd: c_int) -> FileDesc {
         FileDesc { fd: fd }
@@ -41,7 +58,7 @@ impl FileDesc {
         let ret = cvt(unsafe {
             libc::read(self.fd,
                        buf.as_mut_ptr() as *mut c_void,
-                       buf.len())
+                       cmp::min(buf.len(), max_len()))
         })?;
         Ok(ret as usize)
     }
@@ -69,7 +86,7 @@ impl FileDesc {
         unsafe {
             cvt_pread64(self.fd,
                         buf.as_mut_ptr() as *mut c_void,
-                        buf.len(),
+                        cmp::min(buf.len(), max_len()),
                         offset as i64)
                 .map(|n| n as usize)
         }
@@ -79,7 +96,7 @@ impl FileDesc {
         let ret = cvt(unsafe {
             libc::write(self.fd,
                         buf.as_ptr() as *const c_void,
-                        buf.len())
+                        cmp::min(buf.len(), max_len()))
         })?;
         Ok(ret as usize)
     }
@@ -102,7 +119,7 @@ impl FileDesc {
         unsafe {
             cvt_pwrite64(self.fd,
                          buf.as_ptr() as *const c_void,
-                         buf.len(),
+                         cmp::min(buf.len(), max_len()),
                          offset as i64)
                 .map(|n| n as usize)
         }
diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs
index 10b86ba44bc..fdb9483fe1c 100644
--- a/src/libstd/sys/windows/handle.rs
+++ b/src/libstd/sys/windows/handle.rs
@@ -19,7 +19,6 @@ use ptr;
 use sys::c;
 use sys::cvt;
 use sys_common::io::read_to_end_uninitialized;
-use u32;
 
 /// An owned container for `HANDLE` object, closing them on Drop.
 ///
@@ -83,9 +82,7 @@ impl RawHandle {
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
         let mut read = 0;
-        // ReadFile takes a DWORD (u32) for the length so it only supports
-        // reading u32::MAX bytes at a time.
-        let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD;
+        let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
         let res = cvt(unsafe {
             c::ReadFile(self.0, buf.as_mut_ptr() as c::LPVOID,
                         len, &mut read, ptr::null_mut())
@@ -181,9 +178,7 @@ impl RawHandle {
 
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         let mut amt = 0;
-        // WriteFile takes a DWORD (u32) for the length so it only supports
-        // writing u32::MAX bytes at a time.
-        let len = cmp::min(buf.len(), u32::MAX as usize) as c::DWORD;
+        let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;
         cvt(unsafe {
             c::WriteFile(self.0, buf.as_ptr() as c::LPVOID,
                          len, &mut amt, ptr::null_mut())
diff --git a/src/libstd/sys/windows/thread_local.rs b/src/libstd/sys/windows/thread_local.rs
index 5d3084094fb..597f05622a5 100644
--- a/src/libstd/sys/windows/thread_local.rs
+++ b/src/libstd/sys/windows/thread_local.rs
@@ -207,7 +207,7 @@ unsafe fn unregister_dtor(key: Key) -> bool {
 // loop to basically match Unix semantics. If we don't reach a fixed point
 // after a short while then we just inevitably leak something most likely.
 //
-// # The article mentions crazy stuff about "/INCLUDE"?
+// # The article mentions weird stuff about "/INCLUDE"?
 //
 // It sure does! Specifically we're talking about this quote:
 //
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index 6d8b3cc93d9..a2039db0e40 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -216,6 +216,20 @@ pub use self::local::{LocalKey, LocalKeyState};
 
 /// Thread configuration. Provides detailed control over the properties
 /// and behavior of new threads.
+///
+/// # Examples
+///
+/// ```
+/// use std::thread;
+///
+/// let builder = thread::Builder::new();
+///
+/// let handler = builder.spawn(|| {
+///     // thread code
+/// }).unwrap();
+///
+/// handler.join().unwrap();
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Debug)]
 pub struct Builder {
@@ -228,6 +242,22 @@ pub struct Builder {
 impl Builder {
     /// Generates the base configuration for spawning a thread, from which
     /// configuration methods can be chained.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::thread;
+    ///
+    /// let builder = thread::Builder::new()
+    ///                               .name("foo".into())
+    ///                               .stack_size(10);
+    ///
+    /// let handler = builder.spawn(|| {
+    ///     // thread code
+    /// }).unwrap();
+    ///
+    /// handler.join().unwrap();
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> Builder {
         Builder {
@@ -241,7 +271,7 @@ impl Builder {
     ///
     /// # Examples
     ///
-    /// ```rust
+    /// ```
     /// use std::thread;
     ///
     /// let builder = thread::Builder::new()
@@ -260,6 +290,14 @@ impl Builder {
     }
 
     /// Sets the size of the stack for the new thread.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::thread;
+    ///
+    /// let builder = thread::Builder::new().stack_size(10);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn stack_size(mut self, size: usize) -> Builder {
         self.stack_size = Some(size);
@@ -275,9 +313,26 @@ impl Builder {
     ///
     /// # Errors
     ///
-    /// Unlike the `spawn` free function, this method yields an
-    /// `io::Result` to capture any failure to create the thread at
+    /// Unlike the [`spawn`] free function, this method yields an
+    /// [`io::Result`] to capture any failure to create the thread at
     /// the OS level.
+    ///
+    /// [`spawn`]: ../../std/thread/fn.spawn.html
+    /// [`io::Result`]: ../../std/io/type.Result.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::thread;
+    ///
+    /// let builder = thread::Builder::new();
+    ///
+    /// let handler = builder.spawn(|| {
+    ///     // thread code
+    /// }).unwrap();
+    ///
+    /// handler.join().unwrap();
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>> where
         F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
@@ -593,6 +648,23 @@ pub fn park_timeout(dur: Duration) {
 /// A `ThreadId` is an opaque object that has a unique value for each thread
 /// that creates one. `ThreadId`s do not correspond to a thread's system-
 /// designated identifier.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(thread_id)]
+///
+/// use std::thread;
+///
+/// let handler = thread::Builder::new()
+///     .spawn(|| {
+///         let thread = thread::current();
+///         let thread_id = thread.id();
+///     })
+///     .unwrap();
+///
+/// handler.join().unwrap();
+/// ```
 #[unstable(feature = "thread_id", issue = "21507")]
 #[derive(Eq, PartialEq, Copy, Clone)]
 pub struct ThreadId(u64);
@@ -645,6 +717,22 @@ struct Inner {
 #[derive(Clone)]
 #[stable(feature = "rust1", since = "1.0.0")]
 /// A handle to a thread.
+///
+/// # Examples
+///
+/// ```
+/// use std::thread;
+///
+/// let handler = thread::Builder::new()
+///     .name("foo".into())
+///     .spawn(|| {
+///         let thread = thread::current();
+///         println!("thread name: {}", thread.name().unwrap());
+///     })
+///     .unwrap();
+///
+/// handler.join().unwrap();
+/// ```
 pub struct Thread {
     inner: Arc<Inner>,
 }
@@ -668,6 +756,21 @@ impl Thread {
     /// Atomically makes the handle's token available if it is not already.
     ///
     /// See the module doc for more detail.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::thread;
+    ///
+    /// let handler = thread::Builder::new()
+    ///     .spawn(|| {
+    ///         let thread = thread::current();
+    ///         thread.unpark();
+    ///     })
+    ///     .unwrap();
+    ///
+    /// handler.join().unwrap();
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn unpark(&self) {
         let mut guard = self.inner.lock.lock().unwrap();
@@ -678,6 +781,23 @@ impl Thread {
     }
 
     /// Gets the thread's unique identifier.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(thread_id)]
+    ///
+    /// use std::thread;
+    ///
+    /// let handler = thread::Builder::new()
+    ///     .spawn(|| {
+    ///         let thread = thread::current();
+    ///         println!("thread id: {:?}", thread.id());
+    ///     })
+    ///     .unwrap();
+    ///
+    /// handler.join().unwrap();
+    /// ```
     #[unstable(feature = "thread_id", issue = "21507")]
     pub fn id(&self) -> ThreadId {
         self.inner.id
diff --git a/src/libsyntax/Cargo.toml b/src/libsyntax/Cargo.toml
index 0b38f5450b6..a200da6c293 100644
--- a/src/libsyntax/Cargo.toml
+++ b/src/libsyntax/Cargo.toml
@@ -15,3 +15,4 @@ rustc_bitflags = { path = "../librustc_bitflags" }
 syntax_pos = { path = "../libsyntax_pos" }
 rustc_errors = { path = "../librustc_errors" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_i128 = { path = "../librustc_i128" }
diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs
index a39cac8db99..75554f20eff 100644
--- a/src/libsyntax/abi.rs
+++ b/src/libsyntax/abi.rs
@@ -41,6 +41,7 @@ pub enum Abi {
     Aapcs,
     Win64,
     SysV64,
+    PtxKernel,
 
     // Multiplatform / generic ABIs
     Rust,
@@ -49,6 +50,7 @@ pub enum Abi {
     RustIntrinsic,
     RustCall,
     PlatformIntrinsic,
+    Unadjusted
 }
 
 #[allow(non_camel_case_types)]
@@ -82,6 +84,7 @@ const AbiDatas: &'static [AbiData] = &[
     AbiData {abi: Abi::Aapcs, name: "aapcs", generic: false },
     AbiData {abi: Abi::Win64, name: "win64", generic: false },
     AbiData {abi: Abi::SysV64, name: "sysv64", generic: false },
+    AbiData {abi: Abi::PtxKernel, name: "ptx-kernel", generic: false },
 
     // Cross-platform ABIs
     AbiData {abi: Abi::Rust, name: "Rust", generic: true },
@@ -90,6 +93,7 @@ const AbiDatas: &'static [AbiData] = &[
     AbiData {abi: Abi::RustIntrinsic, name: "rust-intrinsic", generic: true },
     AbiData {abi: Abi::RustCall, name: "rust-call", generic: true },
     AbiData {abi: Abi::PlatformIntrinsic, name: "platform-intrinsic", generic: true },
+    AbiData {abi: Abi::Unadjusted, name: "unadjusted", generic: true },
 ];
 
 /// Returns the ABI with the given name (if any).
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index f72985fd91a..da4b787160f 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -33,6 +33,8 @@ use std::u32;
 
 use serialize::{self, Encodable, Decodable, Encoder, Decoder};
 
+use rustc_i128::{u128, i128};
+
 /// An identifier contains a Name (index into the interner
 /// table) and a SyntaxContext to track renaming and
 /// macro expansion per Flatt et al., "Macros That Work Together"
@@ -1062,7 +1064,7 @@ pub enum LitKind {
     /// A character literal (`'a'`)
     Char(char),
     /// An integer literal (`1`)
-    Int(u64, LitIntType),
+    Int(u128, LitIntType),
     /// A float literal (`1f64` or `1E10f64`)
     Float(Symbol, FloatTy),
     /// A float literal without a suffix (`1.0 or 1.0E10`)
@@ -1171,6 +1173,7 @@ pub enum IntTy {
     I16,
     I32,
     I64,
+    I128,
 }
 
 impl fmt::Debug for IntTy {
@@ -1192,24 +1195,16 @@ impl IntTy {
             IntTy::I8 => "i8",
             IntTy::I16 => "i16",
             IntTy::I32 => "i32",
-            IntTy::I64 => "i64"
+            IntTy::I64 => "i64",
+            IntTy::I128 => "i128",
         }
     }
 
-    pub fn val_to_string(&self, val: i64) -> String {
-        // cast to a u64 so we can correctly print INT64_MIN. All integral types
-        // are parsed as u64, so we wouldn't want to print an extra negative
+    pub fn val_to_string(&self, val: i128) -> String {
+        // cast to a u128 so we can correctly print INT128_MIN. All integral types
+        // are parsed as u128, so we wouldn't want to print an extra negative
         // sign.
-        format!("{}{}", val as u64, self.ty_to_string())
-    }
-
-    pub fn ty_max(&self) -> u64 {
-        match *self {
-            IntTy::I8 => 0x80,
-            IntTy::I16 => 0x8000,
-            IntTy::Is | IntTy::I32 => 0x80000000, // FIXME: actually ni about Is
-            IntTy::I64 => 0x8000000000000000
-        }
+        format!("{}{}", val as u128, self.ty_to_string())
     }
 
     pub fn bit_width(&self) -> Option<usize> {
@@ -1219,6 +1214,7 @@ impl IntTy {
             IntTy::I16 => 16,
             IntTy::I32 => 32,
             IntTy::I64 => 64,
+            IntTy::I128 => 128,
         })
     }
 }
@@ -1230,6 +1226,7 @@ pub enum UintTy {
     U16,
     U32,
     U64,
+    U128,
 }
 
 impl UintTy {
@@ -1239,23 +1236,15 @@ impl UintTy {
             UintTy::U8 => "u8",
             UintTy::U16 => "u16",
             UintTy::U32 => "u32",
-            UintTy::U64 => "u64"
+            UintTy::U64 => "u64",
+            UintTy::U128 => "u128",
         }
     }
 
-    pub fn val_to_string(&self, val: u64) -> String {
+    pub fn val_to_string(&self, val: u128) -> String {
         format!("{}{}", val, self.ty_to_string())
     }
 
-    pub fn ty_max(&self) -> u64 {
-        match *self {
-            UintTy::U8 => 0xff,
-            UintTy::U16 => 0xffff,
-            UintTy::Us | UintTy::U32 => 0xffffffff, // FIXME: actually ni about Us
-            UintTy::U64 => 0xffffffffffffffff
-        }
-    }
-
     pub fn bit_width(&self) -> Option<usize> {
         Some(match *self {
             UintTy::Us => return None,
@@ -1263,6 +1252,7 @@ impl UintTy {
             UintTy::U16 => 16,
             UintTy::U32 => 32,
             UintTy::U64 => 64,
+            UintTy::U128 => 128,
         })
     }
 }
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index c31bcfbd869..ab8a49b41f2 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -899,6 +899,8 @@ fn int_type_of_word(s: &str) -> Option<IntType> {
         "u32" => Some(UnsignedInt(ast::UintTy::U32)),
         "i64" => Some(SignedInt(ast::IntTy::I64)),
         "u64" => Some(UnsignedInt(ast::UintTy::U64)),
+        "i128" => Some(SignedInt(ast::IntTy::I128)),
+        "u128" => Some(UnsignedInt(ast::UintTy::U128)),
         "isize" => Some(SignedInt(ast::IntTy::Is)),
         "usize" => Some(UnsignedInt(ast::UintTy::Us)),
         _ => None
@@ -945,7 +947,8 @@ impl IntType {
             SignedInt(ast::IntTy::I8) | UnsignedInt(ast::UintTy::U8) |
             SignedInt(ast::IntTy::I16) | UnsignedInt(ast::UintTy::U16) |
             SignedInt(ast::IntTy::I32) | UnsignedInt(ast::UintTy::U32) |
-            SignedInt(ast::IntTy::I64) | UnsignedInt(ast::UintTy::U64) => true,
+            SignedInt(ast::IntTy::I64) | UnsignedInt(ast::UintTy::U64) |
+            SignedInt(ast::IntTy::I128) | UnsignedInt(ast::UintTy::U128) => true,
             SignedInt(ast::IntTy::Is) | UnsignedInt(ast::UintTy::Us) => false
         }
     }
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 7584fa3916d..28f0c297303 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -16,6 +16,7 @@ use codemap::{dummy_spanned, respan, Spanned};
 use ext::base::ExtCtxt;
 use ptr::P;
 use symbol::{Symbol, keywords};
+use rustc_i128::u128;
 
 // Transitional reexports so qquote can find the paths it is looking for
 mod syntax {
@@ -712,23 +713,26 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
         self.expr(sp, ast::ExprKind::Lit(P(respan(sp, lit))))
     }
     fn expr_usize(&self, span: Span, i: usize) -> P<ast::Expr> {
-        self.expr_lit(span, ast::LitKind::Int(i as u64, ast::LitIntType::Unsigned(ast::UintTy::Us)))
+        self.expr_lit(span, ast::LitKind::Int(i as u128,
+                                              ast::LitIntType::Unsigned(ast::UintTy::Us)))
     }
     fn expr_isize(&self, sp: Span, i: isize) -> P<ast::Expr> {
         if i < 0 {
-            let i = (-i) as u64;
+            let i = (-i) as u128;
             let lit_ty = ast::LitIntType::Signed(ast::IntTy::Is);
             let lit = self.expr_lit(sp, ast::LitKind::Int(i, lit_ty));
             self.expr_unary(sp, ast::UnOp::Neg, lit)
         } else {
-            self.expr_lit(sp, ast::LitKind::Int(i as u64, ast::LitIntType::Signed(ast::IntTy::Is)))
+            self.expr_lit(sp, ast::LitKind::Int(i as u128,
+                                                ast::LitIntType::Signed(ast::IntTy::Is)))
         }
     }
     fn expr_u32(&self, sp: Span, u: u32) -> P<ast::Expr> {
-        self.expr_lit(sp, ast::LitKind::Int(u as u64, ast::LitIntType::Unsigned(ast::UintTy::U32)))
+        self.expr_lit(sp, ast::LitKind::Int(u as u128,
+                                            ast::LitIntType::Unsigned(ast::UintTy::U32)))
     }
     fn expr_u8(&self, sp: Span, u: u8) -> P<ast::Expr> {
-        self.expr_lit(sp, ast::LitKind::Int(u as u64, ast::LitIntType::Unsigned(ast::UintTy::U8)))
+        self.expr_lit(sp, ast::LitKind::Int(u as u128, ast::LitIntType::Unsigned(ast::UintTy::U8)))
     }
     fn expr_bool(&self, sp: Span, value: bool) -> P<ast::Expr> {
         self.expr_lit(sp, ast::LitKind::Bool(value))
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index aa777a19a9b..d2eb2636e6b 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -19,6 +19,7 @@ use parse::token;
 use ptr::P;
 use tokenstream::{self, TokenTree};
 
+
 /// Quasiquoting works via token trees.
 ///
 /// This is registered as a set of expression syntax extension called quote!
@@ -40,6 +41,7 @@ pub mod rt {
     pub use parse::new_parser_from_tts;
     pub use syntax_pos::{BytePos, Span, DUMMY_SP};
     pub use codemap::{dummy_spanned};
+    use rustc_i128::{u128};
 
     pub trait ToTokens {
         fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree>;
@@ -288,7 +290,7 @@ pub mod rt {
                     } else {
                         *self
                     };
-                    let lit = ast::LitKind::Int(val as u64, ast::LitIntType::Signed($tag));
+                    let lit = ast::LitKind::Int(val as u128, ast::LitIntType::Signed($tag));
                     let lit = P(ast::Expr {
                         id: ast::DUMMY_NODE_ID,
                         node: ast::ExprKind::Lit(P(dummy_spanned(lit))),
@@ -310,7 +312,7 @@ pub mod rt {
         (unsigned, $t:ty, $tag:expr) => (
             impl ToTokens for $t {
                 fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
-                    let lit = ast::LitKind::Int(*self as u64, ast::LitIntType::Unsigned($tag));
+                    let lit = ast::LitKind::Int(*self as u128, ast::LitIntType::Unsigned($tag));
                     dummy_spanned(lit).to_tokens(cx)
                 }
             }
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index e04cc11f15e..e7df454cf6a 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -318,6 +318,15 @@ declare_features! (
 
     // Allow safe suggestions for potential type conversions.
     (active, safe_suggestion, "1.0.0", Some(37384)),
+
+    // `extern "ptx-*" fn()`
+    (active, abi_ptx, "1.15.0", None),
+
+    // The `i128` type
+    (active, i128_type, "1.16.0", Some(35118)),
+
+    // The `unadjusted` ABI. Perma unstable.
+    (active, abi_unadjusted, "1.16.0", None),
 );
 
 declare_features! (
@@ -986,7 +995,23 @@ impl<'a> PostExpansionVisitor<'a> {
                 gate_feature_post!(&self, abi_sysv64, span,
                                    "sysv64 ABI is experimental and subject to change");
             },
-            _ => {}
+            Abi::PtxKernel => {
+                gate_feature_post!(&self, abi_ptx, span,
+                                   "PTX ABIs are experimental and subject to change");
+            },
+            Abi::Unadjusted => {
+                gate_feature_post!(&self, abi_unadjusted, span,
+                                   "unadjusted ABI is an implementation detail and perma-unstable");
+            },
+            // Stable
+            Abi::Cdecl |
+            Abi::Stdcall |
+            Abi::Fastcall |
+            Abi::Aapcs |
+            Abi::Win64 |
+            Abi::Rust |
+            Abi::C |
+            Abi::System => {}
         }
     }
 }
@@ -1200,6 +1225,18 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                 gate_feature_post!(&self, loop_break_value, e.span,
                                    "`break` with a value is experimental");
             }
+            ast::ExprKind::Lit(ref lit) => {
+                if let ast::LitKind::Int(_, ref ty) = lit.node {
+                    match *ty {
+                        ast::LitIntType::Signed(ast::IntTy::I128) |
+                        ast::LitIntType::Unsigned(ast::UintTy::U128) => {
+                            gate_feature_post!(&self, i128_type, e.span,
+                                               "128-bit integers are not stable");
+                        }
+                        _ => {}
+                    }
+                }
+            }
             _ => {}
         }
         visit::walk_expr(self, e);
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index b3b0ee6093d..5d6808284f6 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -46,8 +46,9 @@ pub extern crate rustc_errors as errors;
 extern crate syntax_pos;
 extern crate rustc_data_structures;
 
-extern crate serialize as rustc_serialize; // used by deriving
+extern crate rustc_i128;
 
+extern crate serialize as rustc_serialize; // used by deriving
 
 // A variant of 'try!' that panics on an Err. This is used as a crutch on the
 // way towards a non-panic!-prone parser. It should be used for fatal parsing
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 24178e1f675..32b61a88ac1 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -28,6 +28,8 @@ use std::path::{Path, PathBuf};
 use std::rc::Rc;
 use std::str;
 
+use rustc_i128::u128;
+
 pub type PResult<'a, T> = Result<T, DiagnosticBuilder<'a>>;
 
 #[macro_use]
@@ -557,18 +559,20 @@ pub fn integer_lit(s: &str, suffix: Option<Symbol>, sd: &Handler, sp: Span) -> a
             "i16" => ast::LitIntType::Signed(ast::IntTy::I16),
             "i32" => ast::LitIntType::Signed(ast::IntTy::I32),
             "i64" => ast::LitIntType::Signed(ast::IntTy::I64),
+            "i128" => ast::LitIntType::Signed(ast::IntTy::I128),
             "usize" => ast::LitIntType::Unsigned(ast::UintTy::Us),
             "u8"  => ast::LitIntType::Unsigned(ast::UintTy::U8),
             "u16" => ast::LitIntType::Unsigned(ast::UintTy::U16),
             "u32" => ast::LitIntType::Unsigned(ast::UintTy::U32),
             "u64" => ast::LitIntType::Unsigned(ast::UintTy::U64),
+            "u128" => ast::LitIntType::Unsigned(ast::UintTy::U128),
             suf => {
                 // i<digits> and u<digits> look like widths, so lets
                 // give an error message along those lines
                 if looks_like_width_suffix(&['i', 'u'], suf) {
                     sd.struct_span_err(sp, &format!("invalid width `{}` for integer literal",
                                              &suf[1..]))
-                      .help("valid widths are 8, 16, 32 and 64")
+                      .help("valid widths are 8, 16, 32, 64 and 128")
                       .emit();
                 } else {
                     sd.struct_span_err(sp, &format!("invalid suffix `{}` for numeric literal", suf))
@@ -585,7 +589,7 @@ pub fn integer_lit(s: &str, suffix: Option<Symbol>, sd: &Handler, sp: Span) -> a
     debug!("integer_lit: the type is {:?}, base {:?}, the new string is {:?}, the original \
            string was {:?}, the original suffix was {:?}", ty, base, s, orig, suffix);
 
-    match u64::from_str_radix(s, base) {
+    match u128::from_str_radix(s, base) {
         Ok(r) => ast::LitKind::Int(r, ty),
         Err(_) => {
             // small bases are lexed as if they were base 10, e.g, the string
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index a0ed50b33a4..2bb38433a26 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -64,6 +64,8 @@ use std::path::{Path, PathBuf};
 use std::rc::Rc;
 use std::slice;
 
+use rustc_i128::u128;
+
 bitflags! {
     flags Restrictions: u8 {
         const RESTRICTION_STMT_EXPR         = 1 << 0,
@@ -2044,7 +2046,7 @@ impl<'a> Parser<'a> {
     pub fn mk_lit_u32(&mut self, i: u32, attrs: ThinVec<Attribute>) -> P<Expr> {
         let span = &self.span;
         let lv_lit = P(codemap::Spanned {
-            node: LitKind::Int(i as u64, ast::LitIntType::Unsigned(UintTy::U32)),
+            node: LitKind::Int(i as u128, ast::LitIntType::Unsigned(UintTy::U32)),
             span: *span
         });
 
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 7558f0256da..ff77732f535 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -30,6 +30,8 @@ use std_inject;
 use symbol::{Symbol, keywords};
 use tokenstream::{self, TokenTree};
 
+use rustc_i128::i128;
+
 use std::ascii;
 use std::io::{self, Write, Read};
 use std::iter;
@@ -123,16 +125,16 @@ pub fn print_crate<'a>(cm: &'a CodeMap,
         let prelude_import_meta = attr::mk_list_word_item(Symbol::intern("prelude_import"));
         let list = attr::mk_list_item(Symbol::intern("feature"), vec![prelude_import_meta]);
         let fake_attr = attr::mk_attr_inner(attr::mk_attr_id(), list);
-        try!(s.print_attribute(&fake_attr));
+        s.print_attribute(&fake_attr)?;
 
         // #![no_std]
         let no_std_meta = attr::mk_word_item(Symbol::intern("no_std"));
         let fake_attr = attr::mk_attr_inner(attr::mk_attr_id(), no_std_meta);
-        try!(s.print_attribute(&fake_attr));
+        s.print_attribute(&fake_attr)?;
     }
 
-    try!(s.print_mod(&krate.module, &krate.attrs));
-    try!(s.print_remaining_comments());
+    s.print_mod(&krate.module, &krate.attrs)?;
+    s.print_remaining_comments()?;
     eof(&mut s.s)
 }
 
@@ -385,10 +387,10 @@ pub fn fun_to_string(decl: &ast::FnDecl,
                      generics: &ast::Generics)
                      -> String {
     to_string(|s| {
-        try!(s.head(""));
-        try!(s.print_fn(decl, unsafety, constness, Abi::Rust, Some(name),
-                   generics, &ast::Visibility::Inherited));
-        try!(s.end()); // Close the head box
+        s.head("")?;
+        s.print_fn(decl, unsafety, constness, Abi::Rust, Some(name),
+                   generics, &ast::Visibility::Inherited)?;
+        s.end()?; // Close the head box
         s.end() // Close the outer box
     })
 }
@@ -396,9 +398,9 @@ pub fn fun_to_string(decl: &ast::FnDecl,
 pub fn block_to_string(blk: &ast::Block) -> String {
     to_string(|s| {
         // containing cbox, will be closed by print-block at }
-        try!(s.cbox(INDENT_UNIT));
+        s.cbox(INDENT_UNIT)?;
         // head-ibox, will be closed by print-block after {
-        try!(s.ibox(0));
+        s.ibox(0)?;
         s.print_block(blk)
     })
 }
@@ -459,7 +461,7 @@ pub trait PrintState<'a> {
     fn literals(&self) -> &Option<Vec<comments::Literal>>;
 
     fn word_space(&mut self, w: &str) -> io::Result<()> {
-        try!(word(self.writer(), w));
+        word(self.writer(), w)?;
         space(self.writer())
     }
 
@@ -488,7 +490,7 @@ pub trait PrintState<'a> {
 
     fn hardbreak_if_not_bol(&mut self) -> io::Result<()> {
         if !self.is_bol() {
-            try!(hardbreak(self.writer()))
+            hardbreak(self.writer())?
         }
         Ok(())
     }
@@ -512,11 +514,11 @@ pub trait PrintState<'a> {
     fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], mut op: F) -> io::Result<()>
         where F: FnMut(&mut Self, &T) -> io::Result<()>,
     {
-        try!(self.rbox(0, b));
+        self.rbox(0, b)?;
         let mut first = true;
         for elt in elts {
-            if first { first = false; } else { try!(self.word_space(",")); }
-            try!(op(self, elt));
+            if first { first = false; } else { self.word_space(",")?; }
+            op(self, elt)?;
         }
         self.end()
     }
@@ -546,7 +548,7 @@ pub trait PrintState<'a> {
     fn maybe_print_comment(&mut self, pos: BytePos) -> io::Result<()> {
         while let Some(ref cmnt) = self.next_comment() {
             if cmnt.pos < pos {
-                try!(self.print_comment(cmnt));
+                self.print_comment(cmnt)?;
                 self.cur_cmnt_and_lit().cur_cmnt += 1;
             } else {
                 break
@@ -560,36 +562,36 @@ pub trait PrintState<'a> {
         match cmnt.style {
             comments::Mixed => {
                 assert_eq!(cmnt.lines.len(), 1);
-                try!(zerobreak(self.writer()));
-                try!(word(self.writer(), &cmnt.lines[0]));
+                zerobreak(self.writer())?;
+                word(self.writer(), &cmnt.lines[0])?;
                 zerobreak(self.writer())
             }
             comments::Isolated => {
-                try!(self.hardbreak_if_not_bol());
+                self.hardbreak_if_not_bol()?;
                 for line in &cmnt.lines {
                     // Don't print empty lines because they will end up as trailing
                     // whitespace
                     if !line.is_empty() {
-                        try!(word(self.writer(), &line[..]));
+                        word(self.writer(), &line[..])?;
                     }
-                    try!(hardbreak(self.writer()));
+                    hardbreak(self.writer())?;
                 }
                 Ok(())
             }
             comments::Trailing => {
                 if !self.is_bol() {
-                    try!(word(self.writer(), " "));
+                    word(self.writer(), " ")?;
                 }
                 if cmnt.lines.len() == 1 {
-                    try!(word(self.writer(), &cmnt.lines[0]));
+                    word(self.writer(), &cmnt.lines[0])?;
                     hardbreak(self.writer())
                 } else {
-                    try!(self.ibox(0));
+                    self.ibox(0)?;
                     for line in &cmnt.lines {
                         if !line.is_empty() {
-                            try!(word(self.writer(), &line[..]));
+                            word(self.writer(), &line[..])?;
                         }
-                        try!(hardbreak(self.writer()));
+                        hardbreak(self.writer())?;
                     }
                     self.end()
                 }
@@ -601,7 +603,7 @@ pub trait PrintState<'a> {
                     _ => false
                 };
                 if is_semi || self.is_begin() || self.is_end() {
-                    try!(hardbreak(self.writer()));
+                    hardbreak(self.writer())?;
                 }
                 hardbreak(self.writer())
             }
@@ -623,7 +625,7 @@ pub trait PrintState<'a> {
     }
 
     fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> {
-        try!(self.maybe_print_comment(lit.span.lo));
+        self.maybe_print_comment(lit.span.lo)?;
         match self.next_lit(lit.span.lo) {
             Some(ref ltrl) => {
                 return word(self.writer(), &(*ltrl).lit);
@@ -647,8 +649,7 @@ pub trait PrintState<'a> {
             ast::LitKind::Int(i, t) => {
                 match t {
                     ast::LitIntType::Signed(st) => {
-                        word(self.writer(),
-                             &st.val_to_string(i as i64))
+                        word(self.writer(), &st.val_to_string(i as i128))
                     }
                     ast::LitIntType::Unsigned(ut) => {
                         word(self.writer(), &ut.val_to_string(i))
@@ -729,15 +730,15 @@ pub trait PrintState<'a> {
         let mut count = 0;
         for attr in attrs {
             if attr.style == kind {
-                try!(self.print_attribute_inline(attr, is_inline));
+                self.print_attribute_inline(attr, is_inline)?;
                 if is_inline {
-                    try!(self.nbsp());
+                    self.nbsp()?;
                 }
                 count += 1;
             }
         }
         if count > 0 && trailing_hardbreak && !is_inline {
-            try!(self.hardbreak_if_not_bol());
+            self.hardbreak_if_not_bol()?;
         }
         Ok(())
     }
@@ -749,18 +750,18 @@ pub trait PrintState<'a> {
     fn print_attribute_inline(&mut self, attr: &ast::Attribute,
                               is_inline: bool) -> io::Result<()> {
         if !is_inline {
-            try!(self.hardbreak_if_not_bol());
+            self.hardbreak_if_not_bol()?;
         }
-        try!(self.maybe_print_comment(attr.span.lo));
+        self.maybe_print_comment(attr.span.lo)?;
         if attr.is_sugared_doc {
-            try!(word(self.writer(), &attr.value_str().unwrap().as_str()));
+            word(self.writer(), &attr.value_str().unwrap().as_str())?;
             hardbreak(self.writer())
         } else {
             match attr.style {
-                ast::AttrStyle::Inner => try!(word(self.writer(), "#![")),
-                ast::AttrStyle::Outer => try!(word(self.writer(), "#[")),
+                ast::AttrStyle::Inner => word(self.writer(), "#![")?,
+                ast::AttrStyle::Outer => word(self.writer(), "#[")?,
             }
-            try!(self.print_meta_item(&attr.meta()));
+            self.print_meta_item(&attr.meta())?;
             word(self.writer(), "]")
         }
     }
@@ -777,30 +778,30 @@ pub trait PrintState<'a> {
     }
 
     fn print_meta_item(&mut self, item: &ast::MetaItem) -> io::Result<()> {
-        try!(self.ibox(INDENT_UNIT));
+        self.ibox(INDENT_UNIT)?;
         match item.node {
             ast::MetaItemKind::Word => {
-                try!(word(self.writer(), &item.name.as_str()));
+                word(self.writer(), &item.name.as_str())?;
             }
             ast::MetaItemKind::NameValue(ref value) => {
-                try!(self.word_space(&item.name.as_str()));
-                try!(self.word_space("="));
-                try!(self.print_literal(value));
+                self.word_space(&item.name.as_str())?;
+                self.word_space("=")?;
+                self.print_literal(value)?;
             }
             ast::MetaItemKind::List(ref items) => {
-                try!(word(self.writer(), &item.name.as_str()));
-                try!(self.popen());
-                try!(self.commasep(Consistent,
+                word(self.writer(), &item.name.as_str())?;
+                self.popen()?;
+                self.commasep(Consistent,
                               &items[..],
-                              |s, i| s.print_meta_list_item(&i)));
-                try!(self.pclose());
+                              |s, i| s.print_meta_list_item(&i))?;
+                self.pclose()?;
             }
         }
         self.end()
     }
 
     fn space_if_not_bol(&mut self) -> io::Result<()> {
-        if !self.is_bol() { try!(space(self.writer())); }
+        if !self.is_bol() { space(self.writer())?; }
         Ok(())
     }
 
@@ -836,24 +837,24 @@ impl<'a> State<'a> {
     }
 
     pub fn word_nbsp(&mut self, w: &str) -> io::Result<()> {
-        try!(word(&mut self.s, w));
+        word(&mut self.s, w)?;
         self.nbsp()
     }
 
     pub fn head(&mut self, w: &str) -> io::Result<()> {
         // outer-box is consistent
-        try!(self.cbox(INDENT_UNIT));
+        self.cbox(INDENT_UNIT)?;
         // head-box is inconsistent
-        try!(self.ibox(w.len() + 1));
+        self.ibox(w.len() + 1)?;
         // keyword that starts the head
         if !w.is_empty() {
-            try!(self.word_nbsp(w));
+            self.word_nbsp(w)?;
         }
         Ok(())
     }
 
     pub fn bopen(&mut self) -> io::Result<()> {
-        try!(word(&mut self.s, "{"));
+        word(&mut self.s, "{")?;
         self.end() // close the head-box
     }
 
@@ -863,11 +864,11 @@ impl<'a> State<'a> {
     }
     pub fn bclose_maybe_open(&mut self, span: syntax_pos::Span,
                              indented: usize, close_box: bool) -> io::Result<()> {
-        try!(self.maybe_print_comment(span.hi));
-        try!(self.break_offset_if_not_bol(1, -(indented as isize)));
-        try!(word(&mut self.s, "}"));
+        self.maybe_print_comment(span.hi)?;
+        self.break_offset_if_not_bol(1, -(indented as isize))?;
+        word(&mut self.s, "}")?;
         if close_box {
-            try!(self.end()); // close the outer-box
+            self.end()?; // close the outer-box
         }
         Ok(())
     }
@@ -900,10 +901,10 @@ impl<'a> State<'a> {
     // Synthesizes a comment that was not textually present in the original source
     // file.
     pub fn synth_comment(&mut self, text: String) -> io::Result<()> {
-        try!(word(&mut self.s, "/*"));
-        try!(space(&mut self.s));
-        try!(word(&mut self.s, &text[..]));
-        try!(space(&mut self.s));
+        word(&mut self.s, "/*")?;
+        space(&mut self.s)?;
+        word(&mut self.s, &text[..])?;
+        space(&mut self.s)?;
         word(&mut self.s, "*/")
     }
 
@@ -917,18 +918,18 @@ impl<'a> State<'a> {
         F: FnMut(&mut State, &T) -> io::Result<()>,
         G: FnMut(&T) -> syntax_pos::Span,
     {
-        try!(self.rbox(0, b));
+        self.rbox(0, b)?;
         let len = elts.len();
         let mut i = 0;
         for elt in elts {
-            try!(self.maybe_print_comment(get_span(elt).hi));
-            try!(op(self, elt));
+            self.maybe_print_comment(get_span(elt).hi)?;
+            op(self, elt)?;
             i += 1;
             if i < len {
-                try!(word(&mut self.s, ","));
-                try!(self.maybe_print_trailing_comment(get_span(elt),
-                                                  Some(get_span(&elts[i]).hi)));
-                try!(self.space_if_not_bol());
+                word(&mut self.s, ",")?;
+                self.maybe_print_trailing_comment(get_span(elt),
+                                                  Some(get_span(&elts[i]).hi))?;
+                self.space_if_not_bol()?;
             }
         }
         self.end()
@@ -941,18 +942,18 @@ impl<'a> State<'a> {
 
     pub fn print_mod(&mut self, _mod: &ast::Mod,
                      attrs: &[ast::Attribute]) -> io::Result<()> {
-        try!(self.print_inner_attributes(attrs));
+        self.print_inner_attributes(attrs)?;
         for item in &_mod.items {
-            try!(self.print_item(&item));
+            self.print_item(&item)?;
         }
         Ok(())
     }
 
     pub fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod,
                              attrs: &[ast::Attribute]) -> io::Result<()> {
-        try!(self.print_inner_attributes(attrs));
+        self.print_inner_attributes(attrs)?;
         for item in &nmod.items {
-            try!(self.print_foreign_item(item));
+            self.print_foreign_item(item)?;
         }
         Ok(())
     }
@@ -960,50 +961,50 @@ impl<'a> State<'a> {
     pub fn print_opt_lifetime(&mut self,
                               lifetime: &Option<ast::Lifetime>) -> io::Result<()> {
         if let Some(l) = *lifetime {
-            try!(self.print_lifetime(&l));
-            try!(self.nbsp());
+            self.print_lifetime(&l)?;
+            self.nbsp()?;
         }
         Ok(())
     }
 
     pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> {
-        try!(self.maybe_print_comment(ty.span.lo));
-        try!(self.ibox(0));
+        self.maybe_print_comment(ty.span.lo)?;
+        self.ibox(0)?;
         match ty.node {
             ast::TyKind::Slice(ref ty) => {
-                try!(word(&mut self.s, "["));
-                try!(self.print_type(&ty));
-                try!(word(&mut self.s, "]"));
+                word(&mut self.s, "[")?;
+                self.print_type(&ty)?;
+                word(&mut self.s, "]")?;
             }
             ast::TyKind::Ptr(ref mt) => {
-                try!(word(&mut self.s, "*"));
+                word(&mut self.s, "*")?;
                 match mt.mutbl {
-                    ast::Mutability::Mutable => try!(self.word_nbsp("mut")),
-                    ast::Mutability::Immutable => try!(self.word_nbsp("const")),
+                    ast::Mutability::Mutable => self.word_nbsp("mut")?,
+                    ast::Mutability::Immutable => self.word_nbsp("const")?,
                 }
-                try!(self.print_type(&mt.ty));
+                self.print_type(&mt.ty)?;
             }
             ast::TyKind::Rptr(ref lifetime, ref mt) => {
-                try!(word(&mut self.s, "&"));
-                try!(self.print_opt_lifetime(lifetime));
-                try!(self.print_mt(mt));
+                word(&mut self.s, "&")?;
+                self.print_opt_lifetime(lifetime)?;
+                self.print_mt(mt)?;
             }
             ast::TyKind::Never => {
-                try!(word(&mut self.s, "!"));
+                word(&mut self.s, "!")?;
             },
             ast::TyKind::Tup(ref elts) => {
-                try!(self.popen());
-                try!(self.commasep(Inconsistent, &elts[..],
-                              |s, ty| s.print_type(&ty)));
+                self.popen()?;
+                self.commasep(Inconsistent, &elts[..],
+                              |s, ty| s.print_type(&ty))?;
                 if elts.len() == 1 {
-                    try!(word(&mut self.s, ","));
+                    word(&mut self.s, ",")?;
                 }
-                try!(self.pclose());
+                self.pclose()?;
             }
             ast::TyKind::Paren(ref typ) => {
-                try!(self.popen());
-                try!(self.print_type(&typ));
-                try!(self.pclose());
+                self.popen()?;
+                self.print_type(&typ)?;
+                self.pclose()?;
             }
             ast::TyKind::BareFn(ref f) => {
                 let generics = ast::Generics {
@@ -1015,48 +1016,48 @@ impl<'a> State<'a> {
                     },
                     span: syntax_pos::DUMMY_SP,
                 };
-                try!(self.print_ty_fn(f.abi,
+                self.print_ty_fn(f.abi,
                                  f.unsafety,
                                  &f.decl,
                                  None,
-                                 &generics));
+                                 &generics)?;
             }
             ast::TyKind::Path(None, ref path) => {
-                try!(self.print_path(path, false, 0, false));
+                self.print_path(path, false, 0, false)?;
             }
             ast::TyKind::Path(Some(ref qself), ref path) => {
-                try!(self.print_qpath(path, qself, false))
+                self.print_qpath(path, qself, false)?
             }
             ast::TyKind::ObjectSum(ref ty, ref bounds) => {
-                try!(self.print_type(&ty));
-                try!(self.print_bounds("+", &bounds[..]));
+                self.print_type(&ty)?;
+                self.print_bounds("+", &bounds[..])?;
             }
             ast::TyKind::PolyTraitRef(ref bounds) => {
-                try!(self.print_bounds("", &bounds[..]));
+                self.print_bounds("", &bounds[..])?;
             }
             ast::TyKind::ImplTrait(ref bounds) => {
-                try!(self.print_bounds("impl ", &bounds[..]));
+                self.print_bounds("impl ", &bounds[..])?;
             }
             ast::TyKind::Array(ref ty, ref v) => {
-                try!(word(&mut self.s, "["));
-                try!(self.print_type(&ty));
-                try!(word(&mut self.s, "; "));
-                try!(self.print_expr(&v));
-                try!(word(&mut self.s, "]"));
+                word(&mut self.s, "[")?;
+                self.print_type(&ty)?;
+                word(&mut self.s, "; ")?;
+                self.print_expr(&v)?;
+                word(&mut self.s, "]")?;
             }
             ast::TyKind::Typeof(ref e) => {
-                try!(word(&mut self.s, "typeof("));
-                try!(self.print_expr(&e));
-                try!(word(&mut self.s, ")"));
+                word(&mut self.s, "typeof(")?;
+                self.print_expr(&e)?;
+                word(&mut self.s, ")")?;
             }
             ast::TyKind::Infer => {
-                try!(word(&mut self.s, "_"));
+                word(&mut self.s, "_")?;
             }
             ast::TyKind::ImplicitSelf => {
-                try!(word(&mut self.s, "Self"));
+                word(&mut self.s, "Self")?;
             }
             ast::TyKind::Mac(ref m) => {
-                try!(self.print_mac(m, token::Paren));
+                self.print_mac(m, token::Paren)?;
             }
         }
         self.end()
@@ -1064,30 +1065,30 @@ impl<'a> State<'a> {
 
     pub fn print_foreign_item(&mut self,
                               item: &ast::ForeignItem) -> io::Result<()> {
-        try!(self.hardbreak_if_not_bol());
-        try!(self.maybe_print_comment(item.span.lo));
-        try!(self.print_outer_attributes(&item.attrs));
+        self.hardbreak_if_not_bol()?;
+        self.maybe_print_comment(item.span.lo)?;
+        self.print_outer_attributes(&item.attrs)?;
         match item.node {
             ast::ForeignItemKind::Fn(ref decl, ref generics) => {
-                try!(self.head(""));
-                try!(self.print_fn(decl, ast::Unsafety::Normal,
+                self.head("")?;
+                self.print_fn(decl, ast::Unsafety::Normal,
                               ast::Constness::NotConst,
                               Abi::Rust, Some(item.ident),
-                              generics, &item.vis));
-                try!(self.end()); // end head-ibox
-                try!(word(&mut self.s, ";"));
+                              generics, &item.vis)?;
+                self.end()?; // end head-ibox
+                word(&mut self.s, ";")?;
                 self.end() // end the outer fn box
             }
             ast::ForeignItemKind::Static(ref t, m) => {
-                try!(self.head(&visibility_qualified(&item.vis, "static")));
+                self.head(&visibility_qualified(&item.vis, "static"))?;
                 if m {
-                    try!(self.word_space("mut"));
+                    self.word_space("mut")?;
                 }
-                try!(self.print_ident(item.ident));
-                try!(self.word_space(":"));
-                try!(self.print_type(&t));
-                try!(word(&mut self.s, ";"));
-                try!(self.end()); // end the head-ibox
+                self.print_ident(item.ident)?;
+                self.word_space(":")?;
+                self.print_type(&t)?;
+                word(&mut self.s, ";")?;
+                self.end()?; // end the head-ibox
                 self.end() // end the outer cbox
             }
         }
@@ -1100,15 +1101,15 @@ impl<'a> State<'a> {
                               vis: &ast::Visibility)
                               -> io::Result<()>
     {
-        try!(word(&mut self.s, &visibility_qualified(vis, "")));
-        try!(self.word_space("const"));
-        try!(self.print_ident(ident));
-        try!(self.word_space(":"));
-        try!(self.print_type(ty));
+        word(&mut self.s, &visibility_qualified(vis, ""))?;
+        self.word_space("const")?;
+        self.print_ident(ident)?;
+        self.word_space(":")?;
+        self.print_type(ty)?;
         if let Some(expr) = default {
-            try!(space(&mut self.s));
-            try!(self.word_space("="));
-            try!(self.print_expr(expr));
+            space(&mut self.s)?;
+            self.word_space("=")?;
+            self.print_expr(expr)?;
         }
         word(&mut self.s, ";")
     }
@@ -1118,83 +1119,83 @@ impl<'a> State<'a> {
                              bounds: Option<&ast::TyParamBounds>,
                              ty: Option<&ast::Ty>)
                              -> io::Result<()> {
-        try!(self.word_space("type"));
-        try!(self.print_ident(ident));
+        self.word_space("type")?;
+        self.print_ident(ident)?;
         if let Some(bounds) = bounds {
-            try!(self.print_bounds(":", bounds));
+            self.print_bounds(":", bounds)?;
         }
         if let Some(ty) = ty {
-            try!(space(&mut self.s));
-            try!(self.word_space("="));
-            try!(self.print_type(ty));
+            space(&mut self.s)?;
+            self.word_space("=")?;
+            self.print_type(ty)?;
         }
         word(&mut self.s, ";")
     }
 
     /// Pretty-print an item
     pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
-        try!(self.hardbreak_if_not_bol());
-        try!(self.maybe_print_comment(item.span.lo));
-        try!(self.print_outer_attributes(&item.attrs));
-        try!(self.ann.pre(self, NodeItem(item)));
+        self.hardbreak_if_not_bol()?;
+        self.maybe_print_comment(item.span.lo)?;
+        self.print_outer_attributes(&item.attrs)?;
+        self.ann.pre(self, NodeItem(item))?;
         match item.node {
             ast::ItemKind::ExternCrate(ref optional_path) => {
-                try!(self.head(&visibility_qualified(&item.vis, "extern crate")));
+                self.head(&visibility_qualified(&item.vis, "extern crate"))?;
                 if let Some(p) = *optional_path {
                     let val = p.as_str();
                     if val.contains("-") {
-                        try!(self.print_string(&val, ast::StrStyle::Cooked));
+                        self.print_string(&val, ast::StrStyle::Cooked)?;
                     } else {
-                        try!(self.print_name(p));
+                        self.print_name(p)?;
                     }
-                    try!(space(&mut self.s));
-                    try!(word(&mut self.s, "as"));
-                    try!(space(&mut self.s));
+                    space(&mut self.s)?;
+                    word(&mut self.s, "as")?;
+                    space(&mut self.s)?;
                 }
-                try!(self.print_ident(item.ident));
-                try!(word(&mut self.s, ";"));
-                try!(self.end()); // end inner head-block
-                try!(self.end()); // end outer head-block
+                self.print_ident(item.ident)?;
+                word(&mut self.s, ";")?;
+                self.end()?; // end inner head-block
+                self.end()?; // end outer head-block
             }
             ast::ItemKind::Use(ref vp) => {
-                try!(self.head(&visibility_qualified(&item.vis, "use")));
-                try!(self.print_view_path(&vp));
-                try!(word(&mut self.s, ";"));
-                try!(self.end()); // end inner head-block
-                try!(self.end()); // end outer head-block
+                self.head(&visibility_qualified(&item.vis, "use"))?;
+                self.print_view_path(&vp)?;
+                word(&mut self.s, ";")?;
+                self.end()?; // end inner head-block
+                self.end()?; // end outer head-block
             }
             ast::ItemKind::Static(ref ty, m, ref expr) => {
-                try!(self.head(&visibility_qualified(&item.vis, "static")));
+                self.head(&visibility_qualified(&item.vis, "static"))?;
                 if m == ast::Mutability::Mutable {
-                    try!(self.word_space("mut"));
+                    self.word_space("mut")?;
                 }
-                try!(self.print_ident(item.ident));
-                try!(self.word_space(":"));
-                try!(self.print_type(&ty));
-                try!(space(&mut self.s));
-                try!(self.end()); // end the head-ibox
+                self.print_ident(item.ident)?;
+                self.word_space(":")?;
+                self.print_type(&ty)?;
+                space(&mut self.s)?;
+                self.end()?; // end the head-ibox
 
-                try!(self.word_space("="));
-                try!(self.print_expr(&expr));
-                try!(word(&mut self.s, ";"));
-                try!(self.end()); // end the outer cbox
+                self.word_space("=")?;
+                self.print_expr(&expr)?;
+                word(&mut self.s, ";")?;
+                self.end()?; // end the outer cbox
             }
             ast::ItemKind::Const(ref ty, ref expr) => {
-                try!(self.head(&visibility_qualified(&item.vis, "const")));
-                try!(self.print_ident(item.ident));
-                try!(self.word_space(":"));
-                try!(self.print_type(&ty));
-                try!(space(&mut self.s));
-                try!(self.end()); // end the head-ibox
-
-                try!(self.word_space("="));
-                try!(self.print_expr(&expr));
-                try!(word(&mut self.s, ";"));
-                try!(self.end()); // end the outer cbox
+                self.head(&visibility_qualified(&item.vis, "const"))?;
+                self.print_ident(item.ident)?;
+                self.word_space(":")?;
+                self.print_type(&ty)?;
+                space(&mut self.s)?;
+                self.end()?; // end the head-ibox
+
+                self.word_space("=")?;
+                self.print_expr(&expr)?;
+                word(&mut self.s, ";")?;
+                self.end()?; // end the outer cbox
             }
             ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref typarams, ref body) => {
-                try!(self.head(""));
-                try!(self.print_fn(
+                self.head("")?;
+                self.print_fn(
                     decl,
                     unsafety,
                     constness.node,
@@ -1202,68 +1203,68 @@ impl<'a> State<'a> {
                     Some(item.ident),
                     typarams,
                     &item.vis
-                ));
-                try!(word(&mut self.s, " "));
-                try!(self.print_block_with_attrs(&body, &item.attrs));
+                )?;
+                word(&mut self.s, " ")?;
+                self.print_block_with_attrs(&body, &item.attrs)?;
             }
             ast::ItemKind::Mod(ref _mod) => {
-                try!(self.head(&visibility_qualified(&item.vis, "mod")));
-                try!(self.print_ident(item.ident));
-                try!(self.nbsp());
-                try!(self.bopen());
-                try!(self.print_mod(_mod, &item.attrs));
-                try!(self.bclose(item.span));
+                self.head(&visibility_qualified(&item.vis, "mod"))?;
+                self.print_ident(item.ident)?;
+                self.nbsp()?;
+                self.bopen()?;
+                self.print_mod(_mod, &item.attrs)?;
+                self.bclose(item.span)?;
             }
             ast::ItemKind::ForeignMod(ref nmod) => {
-                try!(self.head("extern"));
-                try!(self.word_nbsp(&nmod.abi.to_string()));
-                try!(self.bopen());
-                try!(self.print_foreign_mod(nmod, &item.attrs));
-                try!(self.bclose(item.span));
+                self.head("extern")?;
+                self.word_nbsp(&nmod.abi.to_string())?;
+                self.bopen()?;
+                self.print_foreign_mod(nmod, &item.attrs)?;
+                self.bclose(item.span)?;
             }
             ast::ItemKind::Ty(ref ty, ref params) => {
-                try!(self.ibox(INDENT_UNIT));
-                try!(self.ibox(0));
-                try!(self.word_nbsp(&visibility_qualified(&item.vis, "type")));
-                try!(self.print_ident(item.ident));
-                try!(self.print_generics(params));
-                try!(self.end()); // end the inner ibox
-
-                try!(self.print_where_clause(&params.where_clause));
-                try!(space(&mut self.s));
-                try!(self.word_space("="));
-                try!(self.print_type(&ty));
-                try!(word(&mut self.s, ";"));
-                try!(self.end()); // end the outer ibox
+                self.ibox(INDENT_UNIT)?;
+                self.ibox(0)?;
+                self.word_nbsp(&visibility_qualified(&item.vis, "type"))?;
+                self.print_ident(item.ident)?;
+                self.print_generics(params)?;
+                self.end()?; // end the inner ibox
+
+                self.print_where_clause(&params.where_clause)?;
+                space(&mut self.s)?;
+                self.word_space("=")?;
+                self.print_type(&ty)?;
+                word(&mut self.s, ";")?;
+                self.end()?; // end the outer ibox
             }
             ast::ItemKind::Enum(ref enum_definition, ref params) => {
-                try!(self.print_enum_def(
+                self.print_enum_def(
                     enum_definition,
                     params,
                     item.ident,
                     item.span,
                     &item.vis
-                ));
+                )?;
             }
             ast::ItemKind::Struct(ref struct_def, ref generics) => {
-                try!(self.head(&visibility_qualified(&item.vis, "struct")));
-                try!(self.print_struct(&struct_def, generics, item.ident, item.span, true));
+                self.head(&visibility_qualified(&item.vis, "struct"))?;
+                self.print_struct(&struct_def, generics, item.ident, item.span, true)?;
             }
             ast::ItemKind::Union(ref struct_def, ref generics) => {
-                try!(self.head(&visibility_qualified(&item.vis, "union")));
-                try!(self.print_struct(&struct_def, generics, item.ident, item.span, true));
+                self.head(&visibility_qualified(&item.vis, "union"))?;
+                self.print_struct(&struct_def, generics, item.ident, item.span, true)?;
             }
             ast::ItemKind::DefaultImpl(unsafety, ref trait_ref) => {
-                try!(self.head(""));
-                try!(self.print_visibility(&item.vis));
-                try!(self.print_unsafety(unsafety));
-                try!(self.word_nbsp("impl"));
-                try!(self.print_trait_ref(trait_ref));
-                try!(space(&mut self.s));
-                try!(self.word_space("for"));
-                try!(self.word_space(".."));
-                try!(self.bopen());
-                try!(self.bclose(item.span));
+                self.head("")?;
+                self.print_visibility(&item.vis)?;
+                self.print_unsafety(unsafety)?;
+                self.word_nbsp("impl")?;
+                self.print_trait_ref(trait_ref)?;
+                space(&mut self.s)?;
+                self.word_space("for")?;
+                self.word_space("..")?;
+                self.bopen()?;
+                self.bclose(item.span)?;
             }
             ast::ItemKind::Impl(unsafety,
                           polarity,
@@ -1271,77 +1272,77 @@ impl<'a> State<'a> {
                           ref opt_trait,
                           ref ty,
                           ref impl_items) => {
-                try!(self.head(""));
-                try!(self.print_visibility(&item.vis));
-                try!(self.print_unsafety(unsafety));
-                try!(self.word_nbsp("impl"));
+                self.head("")?;
+                self.print_visibility(&item.vis)?;
+                self.print_unsafety(unsafety)?;
+                self.word_nbsp("impl")?;
 
                 if generics.is_parameterized() {
-                    try!(self.print_generics(generics));
-                    try!(space(&mut self.s));
+                    self.print_generics(generics)?;
+                    space(&mut self.s)?;
                 }
 
                 match polarity {
                     ast::ImplPolarity::Negative => {
-                        try!(word(&mut self.s, "!"));
+                        word(&mut self.s, "!")?;
                     },
                     _ => {}
                 }
 
                 if let Some(ref t) = *opt_trait {
-                    try!(self.print_trait_ref(t));
-                    try!(space(&mut self.s));
-                    try!(self.word_space("for"));
+                    self.print_trait_ref(t)?;
+                    space(&mut self.s)?;
+                    self.word_space("for")?;
                 }
 
-                try!(self.print_type(&ty));
-                try!(self.print_where_clause(&generics.where_clause));
+                self.print_type(&ty)?;
+                self.print_where_clause(&generics.where_clause)?;
 
-                try!(space(&mut self.s));
-                try!(self.bopen());
-                try!(self.print_inner_attributes(&item.attrs));
+                space(&mut self.s)?;
+                self.bopen()?;
+                self.print_inner_attributes(&item.attrs)?;
                 for impl_item in impl_items {
-                    try!(self.print_impl_item(impl_item));
+                    self.print_impl_item(impl_item)?;
                 }
-                try!(self.bclose(item.span));
+                self.bclose(item.span)?;
             }
             ast::ItemKind::Trait(unsafety, ref generics, ref bounds, ref trait_items) => {
-                try!(self.head(""));
-                try!(self.print_visibility(&item.vis));
-                try!(self.print_unsafety(unsafety));
-                try!(self.word_nbsp("trait"));
-                try!(self.print_ident(item.ident));
-                try!(self.print_generics(generics));
+                self.head("")?;
+                self.print_visibility(&item.vis)?;
+                self.print_unsafety(unsafety)?;
+                self.word_nbsp("trait")?;
+                self.print_ident(item.ident)?;
+                self.print_generics(generics)?;
                 let mut real_bounds = Vec::with_capacity(bounds.len());
                 for b in bounds.iter() {
                     if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
-                        try!(space(&mut self.s));
-                        try!(self.word_space("for ?"));
-                        try!(self.print_trait_ref(&ptr.trait_ref));
+                        space(&mut self.s)?;
+                        self.word_space("for ?")?;
+                        self.print_trait_ref(&ptr.trait_ref)?;
                     } else {
                         real_bounds.push(b.clone());
                     }
                 }
-                try!(self.print_bounds(":", &real_bounds[..]));
-                try!(self.print_where_clause(&generics.where_clause));
-                try!(word(&mut self.s, " "));
-                try!(self.bopen());
+                self.print_bounds(":", &real_bounds[..])?;
+                self.print_where_clause(&generics.where_clause)?;
+                word(&mut self.s, " ")?;
+                self.bopen()?;
                 for trait_item in trait_items {
-                    try!(self.print_trait_item(trait_item));
+                    self.print_trait_item(trait_item)?;
                 }
-                try!(self.bclose(item.span));
+                self.bclose(item.span)?;
             }
             ast::ItemKind::Mac(codemap::Spanned { ref node, .. }) => {
-                try!(self.print_visibility(&item.vis));
-                try!(self.print_path(&node.path, false, 0, false));
-                try!(word(&mut self.s, "! "));
-                try!(self.print_ident(item.ident));
-                try!(self.cbox(INDENT_UNIT));
-                try!(self.popen());
-                try!(self.print_tts(&node.tts[..]));
-                try!(self.pclose());
-                try!(word(&mut self.s, ";"));
-                try!(self.end());
+                self.print_visibility(&item.vis)?;
+                self.print_path(&node.path, false, 0, false)?;
+                word(&mut self.s, "! ")?;
+                self.print_ident(item.ident)?;
+                self.cbox(INDENT_UNIT)?;
+                self.popen()?;
+                self.print_tts(&node.tts[..])?;
+                self.pclose()?;
+                word(&mut self.s, ";")?;
+                self.end()?;
             }
         }
         self.ann.post(self, NodeItem(item))
@@ -1353,23 +1354,23 @@ impl<'a> State<'a> {
 
     fn print_formal_lifetime_list(&mut self, lifetimes: &[ast::LifetimeDef]) -> io::Result<()> {
         if !lifetimes.is_empty() {
-            try!(word(&mut self.s, "for<"));
+            word(&mut self.s, "for<")?;
             let mut comma = false;
             for lifetime_def in lifetimes {
                 if comma {
-                    try!(self.word_space(","))
+                    self.word_space(",")?
                 }
-                try!(self.print_outer_attributes_inline(&lifetime_def.attrs));
-                try!(self.print_lifetime_bounds(&lifetime_def.lifetime, &lifetime_def.bounds));
+                self.print_outer_attributes_inline(&lifetime_def.attrs)?;
+                self.print_lifetime_bounds(&lifetime_def.lifetime, &lifetime_def.bounds)?;
                 comma = true;
             }
-            try!(word(&mut self.s, ">"));
+            word(&mut self.s, ">")?;
         }
         Ok(())
     }
 
     fn print_poly_trait_ref(&mut self, t: &ast::PolyTraitRef) -> io::Result<()> {
-        try!(self.print_formal_lifetime_list(&t.bound_lifetimes));
+        self.print_formal_lifetime_list(&t.bound_lifetimes)?;
         self.print_trait_ref(&t.trait_ref)
     }
 
@@ -1377,27 +1378,27 @@ impl<'a> State<'a> {
                           generics: &ast::Generics, ident: ast::Ident,
                           span: syntax_pos::Span,
                           visibility: &ast::Visibility) -> io::Result<()> {
-        try!(self.head(&visibility_qualified(visibility, "enum")));
-        try!(self.print_ident(ident));
-        try!(self.print_generics(generics));
-        try!(self.print_where_clause(&generics.where_clause));
-        try!(space(&mut self.s));
+        self.head(&visibility_qualified(visibility, "enum"))?;
+        self.print_ident(ident)?;
+        self.print_generics(generics)?;
+        self.print_where_clause(&generics.where_clause)?;
+        space(&mut self.s)?;
         self.print_variants(&enum_definition.variants, span)
     }
 
     pub fn print_variants(&mut self,
                           variants: &[ast::Variant],
                           span: syntax_pos::Span) -> io::Result<()> {
-        try!(self.bopen());
+        self.bopen()?;
         for v in variants {
-            try!(self.space_if_not_bol());
-            try!(self.maybe_print_comment(v.span.lo));
-            try!(self.print_outer_attributes(&v.node.attrs));
-            try!(self.ibox(INDENT_UNIT));
-            try!(self.print_variant(v));
-            try!(word(&mut self.s, ","));
-            try!(self.end());
-            try!(self.maybe_print_trailing_comment(v.span, None));
+            self.space_if_not_bol()?;
+            self.maybe_print_comment(v.span.lo)?;
+            self.print_outer_attributes(&v.node.attrs)?;
+            self.ibox(INDENT_UNIT)?;
+            self.print_variant(v)?;
+            word(&mut self.s, ",")?;
+            self.end()?;
+            self.maybe_print_trailing_comment(v.span, None)?;
         }
         self.bclose(span)
     }
@@ -1420,43 +1421,43 @@ impl<'a> State<'a> {
                         ident: ast::Ident,
                         span: syntax_pos::Span,
                         print_finalizer: bool) -> io::Result<()> {
-        try!(self.print_ident(ident));
-        try!(self.print_generics(generics));
+        self.print_ident(ident)?;
+        self.print_generics(generics)?;
         if !struct_def.is_struct() {
             if struct_def.is_tuple() {
-                try!(self.popen());
-                try!(self.commasep(
+                self.popen()?;
+                self.commasep(
                     Inconsistent, struct_def.fields(),
                     |s, field| {
-                        try!(s.maybe_print_comment(field.span.lo));
-                        try!(s.print_outer_attributes(&field.attrs));
-                        try!(s.print_visibility(&field.vis));
+                        s.maybe_print_comment(field.span.lo)?;
+                        s.print_outer_attributes(&field.attrs)?;
+                        s.print_visibility(&field.vis)?;
                         s.print_type(&field.ty)
                     }
-                ));
-                try!(self.pclose());
+                )?;
+                self.pclose()?;
             }
-            try!(self.print_where_clause(&generics.where_clause));
+            self.print_where_clause(&generics.where_clause)?;
             if print_finalizer {
-                try!(word(&mut self.s, ";"));
+                word(&mut self.s, ";")?;
             }
-            try!(self.end());
+            self.end()?;
             self.end() // close the outer-box
         } else {
-            try!(self.print_where_clause(&generics.where_clause));
-            try!(self.nbsp());
-            try!(self.bopen());
-            try!(self.hardbreak_if_not_bol());
+            self.print_where_clause(&generics.where_clause)?;
+            self.nbsp()?;
+            self.bopen()?;
+            self.hardbreak_if_not_bol()?;
 
             for field in struct_def.fields() {
-                try!(self.hardbreak_if_not_bol());
-                try!(self.maybe_print_comment(field.span.lo));
-                try!(self.print_outer_attributes(&field.attrs));
-                try!(self.print_visibility(&field.vis));
-                try!(self.print_ident(field.ident.unwrap()));
-                try!(self.word_nbsp(":"));
-                try!(self.print_type(&field.ty));
-                try!(word(&mut self.s, ","));
+                self.hardbreak_if_not_bol()?;
+                self.maybe_print_comment(field.span.lo)?;
+                self.print_outer_attributes(&field.attrs)?;
+                self.print_visibility(&field.vis)?;
+                self.print_ident(field.ident.unwrap())?;
+                self.word_nbsp(":")?;
+                self.print_type(&field.ty)?;
+                word(&mut self.s, ",")?;
             }
 
             self.bclose(span)
@@ -1473,7 +1474,7 @@ impl<'a> State<'a> {
     pub fn print_tt(&mut self, tt: &tokenstream::TokenTree) -> io::Result<()> {
         match *tt {
             TokenTree::Token(_, ref tk) => {
-                try!(word(&mut self.s, &token_to_string(tk)));
+                word(&mut self.s, &token_to_string(tk))?;
                 match *tk {
                     parse::token::DocComment(..) => {
                         hardbreak(&mut self.s)
@@ -1482,20 +1483,20 @@ impl<'a> State<'a> {
                 }
             }
             TokenTree::Delimited(_, ref delimed) => {
-                try!(word(&mut self.s, &token_to_string(&delimed.open_token())));
-                try!(space(&mut self.s));
-                try!(self.print_tts(&delimed.tts));
-                try!(space(&mut self.s));
+                word(&mut self.s, &token_to_string(&delimed.open_token()))?;
+                space(&mut self.s)?;
+                self.print_tts(&delimed.tts)?;
+                space(&mut self.s)?;
                 word(&mut self.s, &token_to_string(&delimed.close_token()))
             },
             TokenTree::Sequence(_, ref seq) => {
-                try!(word(&mut self.s, "$("));
+                word(&mut self.s, "$(")?;
                 for tt_elt in &seq.tts {
-                    try!(self.print_tt(tt_elt));
+                    self.print_tt(tt_elt)?;
                 }
-                try!(word(&mut self.s, ")"));
+                word(&mut self.s, ")")?;
                 if let Some(ref tk) = seq.separator {
-                    try!(word(&mut self.s, &token_to_string(tk)));
+                    word(&mut self.s, &token_to_string(tk))?;
                 }
                 match seq.op {
                     tokenstream::KleeneOp::ZeroOrMore => word(&mut self.s, "*"),
@@ -1506,24 +1507,24 @@ impl<'a> State<'a> {
     }
 
     pub fn print_tts(&mut self, tts: &[tokenstream::TokenTree]) -> io::Result<()> {
-        try!(self.ibox(0));
+        self.ibox(0)?;
         for (i, tt) in tts.iter().enumerate() {
             if i != 0 {
-                try!(space(&mut self.s));
+                space(&mut self.s)?;
             }
-            try!(self.print_tt(tt));
+            self.print_tt(tt)?;
         }
         self.end()
     }
 
     pub fn print_variant(&mut self, v: &ast::Variant) -> io::Result<()> {
-        try!(self.head(""));
+        self.head("")?;
         let generics = ast::Generics::default();
-        try!(self.print_struct(&v.node.data, &generics, v.node.name, v.span, false));
+        self.print_struct(&v.node.data, &generics, v.node.name, v.span, false)?;
         match v.node.disr_expr {
             Some(ref d) => {
-                try!(space(&mut self.s));
-                try!(self.word_space("="));
+                space(&mut self.s)?;
+                self.word_space("=")?;
                 self.print_expr(&d)
             }
             _ => Ok(())
@@ -1546,31 +1547,31 @@ impl<'a> State<'a> {
 
     pub fn print_trait_item(&mut self, ti: &ast::TraitItem)
                             -> io::Result<()> {
-        try!(self.ann.pre(self, NodeSubItem(ti.id)));
-        try!(self.hardbreak_if_not_bol());
-        try!(self.maybe_print_comment(ti.span.lo));
-        try!(self.print_outer_attributes(&ti.attrs));
+        self.ann.pre(self, NodeSubItem(ti.id))?;
+        self.hardbreak_if_not_bol()?;
+        self.maybe_print_comment(ti.span.lo)?;
+        self.print_outer_attributes(&ti.attrs)?;
         match ti.node {
             ast::TraitItemKind::Const(ref ty, ref default) => {
-                try!(self.print_associated_const(ti.ident, &ty,
+                self.print_associated_const(ti.ident, &ty,
                                             default.as_ref().map(|expr| &**expr),
-                                            &ast::Visibility::Inherited));
+                                            &ast::Visibility::Inherited)?;
             }
             ast::TraitItemKind::Method(ref sig, ref body) => {
                 if body.is_some() {
-                    try!(self.head(""));
+                    self.head("")?;
                 }
-                try!(self.print_method_sig(ti.ident, sig, &ast::Visibility::Inherited));
+                self.print_method_sig(ti.ident, sig, &ast::Visibility::Inherited)?;
                 if let Some(ref body) = *body {
-                    try!(self.nbsp());
-                    try!(self.print_block_with_attrs(body, &ti.attrs));
+                    self.nbsp()?;
+                    self.print_block_with_attrs(body, &ti.attrs)?;
                 } else {
-                    try!(word(&mut self.s, ";"));
+                    word(&mut self.s, ";")?;
                 }
             }
             ast::TraitItemKind::Type(ref bounds, ref default) => {
-                try!(self.print_associated_type(ti.ident, Some(bounds),
-                                           default.as_ref().map(|ty| &**ty)));
+                self.print_associated_type(ti.ident, Some(bounds),
+                                           default.as_ref().map(|ty| &**ty))?;
             }
             ast::TraitItemKind::Macro(codemap::Spanned { ref node, .. }) => {
                 // code copied from ItemKind::Mac:
@@ -1588,85 +1589,85 @@ impl<'a> State<'a> {
     }
 
     pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> io::Result<()> {
-        try!(self.ann.pre(self, NodeSubItem(ii.id)));
-        try!(self.hardbreak_if_not_bol());
-        try!(self.maybe_print_comment(ii.span.lo));
-        try!(self.print_outer_attributes(&ii.attrs));
+        self.ann.pre(self, NodeSubItem(ii.id))?;
+        self.hardbreak_if_not_bol()?;
+        self.maybe_print_comment(ii.span.lo)?;
+        self.print_outer_attributes(&ii.attrs)?;
         if let ast::Defaultness::Default = ii.defaultness {
-            try!(self.word_nbsp("default"));
+            self.word_nbsp("default")?;
         }
         match ii.node {
             ast::ImplItemKind::Const(ref ty, ref expr) => {
-                try!(self.print_associated_const(ii.ident, &ty, Some(&expr), &ii.vis));
+                self.print_associated_const(ii.ident, &ty, Some(&expr), &ii.vis)?;
             }
             ast::ImplItemKind::Method(ref sig, ref body) => {
-                try!(self.head(""));
-                try!(self.print_method_sig(ii.ident, sig, &ii.vis));
-                try!(self.nbsp());
-                try!(self.print_block_with_attrs(body, &ii.attrs));
+                self.head("")?;
+                self.print_method_sig(ii.ident, sig, &ii.vis)?;
+                self.nbsp()?;
+                self.print_block_with_attrs(body, &ii.attrs)?;
             }
             ast::ImplItemKind::Type(ref ty) => {
-                try!(self.print_associated_type(ii.ident, None, Some(ty)));
+                self.print_associated_type(ii.ident, None, Some(ty))?;
             }
             ast::ImplItemKind::Macro(codemap::Spanned { ref node, .. }) => {
                 // code copied from ItemKind::Mac:
-                try!(self.print_path(&node.path, false, 0, false));
-                try!(word(&mut self.s, "! "));
-                try!(self.cbox(INDENT_UNIT));
-                try!(self.popen());
-                try!(self.print_tts(&node.tts[..]));
-                try!(self.pclose());
-                try!(word(&mut self.s, ";"));
-                try!(self.end())
+                self.print_path(&node.path, false, 0, false)?;
+                word(&mut self.s, "! ")?;
+                self.cbox(INDENT_UNIT)?;
+                self.popen()?;
+                self.print_tts(&node.tts[..])?;
+                self.pclose()?;
+                word(&mut self.s, ";")?;
+                self.end()?
             }
         }
         self.ann.post(self, NodeSubItem(ii.id))
     }
 
     pub fn print_stmt(&mut self, st: &ast::Stmt) -> io::Result<()> {
-        try!(self.maybe_print_comment(st.span.lo));
+        self.maybe_print_comment(st.span.lo)?;
         match st.node {
             ast::StmtKind::Local(ref loc) => {
-                try!(self.print_outer_attributes(&loc.attrs));
-                try!(self.space_if_not_bol());
-                try!(self.ibox(INDENT_UNIT));
-                try!(self.word_nbsp("let"));
-
-                try!(self.ibox(INDENT_UNIT));
-                try!(self.print_local_decl(&loc));
-                try!(self.end());
+                self.print_outer_attributes(&loc.attrs)?;
+                self.space_if_not_bol()?;
+                self.ibox(INDENT_UNIT)?;
+                self.word_nbsp("let")?;
+
+                self.ibox(INDENT_UNIT)?;
+                self.print_local_decl(&loc)?;
+                self.end()?;
                 if let Some(ref init) = loc.init {
-                    try!(self.nbsp());
-                    try!(self.word_space("="));
-                    try!(self.print_expr(&init));
+                    self.nbsp()?;
+                    self.word_space("=")?;
+                    self.print_expr(&init)?;
                 }
-                try!(word(&mut self.s, ";"));
+                word(&mut self.s, ";")?;
                 self.end()?;
             }
             ast::StmtKind::Item(ref item) => self.print_item(&item)?,
             ast::StmtKind::Expr(ref expr) => {
-                try!(self.space_if_not_bol());
-                try!(self.print_expr_outer_attr_style(&expr, false));
+                self.space_if_not_bol()?;
+                self.print_expr_outer_attr_style(&expr, false)?;
                 if parse::classify::expr_requires_semi_to_be_stmt(expr) {
-                    try!(word(&mut self.s, ";"));
+                    word(&mut self.s, ";")?;
                 }
             }
             ast::StmtKind::Semi(ref expr) => {
-                try!(self.space_if_not_bol());
-                try!(self.print_expr_outer_attr_style(&expr, false));
-                try!(word(&mut self.s, ";"));
+                self.space_if_not_bol()?;
+                self.print_expr_outer_attr_style(&expr, false)?;
+                word(&mut self.s, ";")?;
             }
             ast::StmtKind::Mac(ref mac) => {
                 let (ref mac, style, ref attrs) = **mac;
-                try!(self.space_if_not_bol());
-                try!(self.print_outer_attributes(&attrs));
+                self.space_if_not_bol()?;
+                self.print_outer_attributes(&attrs)?;
                 let delim = match style {
                     ast::MacStmtStyle::Braces => token::Brace,
                     _ => token::Paren
                 };
-                try!(self.print_mac(&mac, delim));
+                self.print_mac(&mac, delim)?;
                 if style == ast::MacStmtStyle::Semicolon {
-                    try!(word(&mut self.s, ";"));
+                    word(&mut self.s, ";")?;
                 }
             }
         }
@@ -1704,28 +1705,28 @@ impl<'a> State<'a> {
                                       attrs: &[ast::Attribute],
                                       close_box: bool) -> io::Result<()> {
         match blk.rules {
-            BlockCheckMode::Unsafe(..) => try!(self.word_space("unsafe")),
+            BlockCheckMode::Unsafe(..) => self.word_space("unsafe")?,
             BlockCheckMode::Default => ()
         }
-        try!(self.maybe_print_comment(blk.span.lo));
-        try!(self.ann.pre(self, NodeBlock(blk)));
-        try!(self.bopen());
+        self.maybe_print_comment(blk.span.lo)?;
+        self.ann.pre(self, NodeBlock(blk))?;
+        self.bopen()?;
 
-        try!(self.print_inner_attributes(attrs));
+        self.print_inner_attributes(attrs)?;
 
         for (i, st) in blk.stmts.iter().enumerate() {
             match st.node {
                 ast::StmtKind::Expr(ref expr) if i == blk.stmts.len() - 1 => {
-                    try!(self.maybe_print_comment(st.span.lo));
-                    try!(self.space_if_not_bol());
-                    try!(self.print_expr_outer_attr_style(&expr, false));
-                    try!(self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi)));
+                    self.maybe_print_comment(st.span.lo)?;
+                    self.space_if_not_bol()?;
+                    self.print_expr_outer_attr_style(&expr, false)?;
+                    self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi))?;
                 }
-                _ => try!(self.print_stmt(st)),
+                _ => self.print_stmt(st)?,
             }
         }
 
-        try!(self.bclose_maybe_open(blk.span, indented, close_box));
+        self.bclose_maybe_open(blk.span, indented, close_box)?;
         self.ann.post(self, NodeBlock(blk))
     }
 
@@ -1735,32 +1736,32 @@ impl<'a> State<'a> {
                 match _else.node {
                     // "another else-if"
                     ast::ExprKind::If(ref i, ref then, ref e) => {
-                        try!(self.cbox(INDENT_UNIT - 1));
-                        try!(self.ibox(0));
-                        try!(word(&mut self.s, " else if "));
-                        try!(self.print_expr(&i));
-                        try!(space(&mut self.s));
-                        try!(self.print_block(&then));
+                        self.cbox(INDENT_UNIT - 1)?;
+                        self.ibox(0)?;
+                        word(&mut self.s, " else if ")?;
+                        self.print_expr(&i)?;
+                        space(&mut self.s)?;
+                        self.print_block(&then)?;
                         self.print_else(e.as_ref().map(|e| &**e))
                     }
                     // "another else-if-let"
                     ast::ExprKind::IfLet(ref pat, ref expr, ref then, ref e) => {
-                        try!(self.cbox(INDENT_UNIT - 1));
-                        try!(self.ibox(0));
-                        try!(word(&mut self.s, " else if let "));
-                        try!(self.print_pat(&pat));
-                        try!(space(&mut self.s));
-                        try!(self.word_space("="));
-                        try!(self.print_expr(&expr));
-                        try!(space(&mut self.s));
-                        try!(self.print_block(&then));
+                        self.cbox(INDENT_UNIT - 1)?;
+                        self.ibox(0)?;
+                        word(&mut self.s, " else if let ")?;
+                        self.print_pat(&pat)?;
+                        space(&mut self.s)?;
+                        self.word_space("=")?;
+                        self.print_expr(&expr)?;
+                        space(&mut self.s)?;
+                        self.print_block(&then)?;
                         self.print_else(e.as_ref().map(|e| &**e))
                     }
                     // "final else"
                     ast::ExprKind::Block(ref b) => {
-                        try!(self.cbox(INDENT_UNIT - 1));
-                        try!(self.ibox(0));
-                        try!(word(&mut self.s, " else "));
+                        self.cbox(INDENT_UNIT - 1)?;
+                        self.ibox(0)?;
+                        word(&mut self.s, " else ")?;
                         self.print_block(&b)
                     }
                     // BLEAH, constraints would be great here
@@ -1775,39 +1776,39 @@ impl<'a> State<'a> {
 
     pub fn print_if(&mut self, test: &ast::Expr, blk: &ast::Block,
                     elseopt: Option<&ast::Expr>) -> io::Result<()> {
-        try!(self.head("if"));
-        try!(self.print_expr(test));
-        try!(space(&mut self.s));
-        try!(self.print_block(blk));
+        self.head("if")?;
+        self.print_expr(test)?;
+        space(&mut self.s)?;
+        self.print_block(blk)?;
         self.print_else(elseopt)
     }
 
     pub fn print_if_let(&mut self, pat: &ast::Pat, expr: &ast::Expr, blk: &ast::Block,
                         elseopt: Option<&ast::Expr>) -> io::Result<()> {
-        try!(self.head("if let"));
-        try!(self.print_pat(pat));
-        try!(space(&mut self.s));
-        try!(self.word_space("="));
-        try!(self.print_expr(expr));
-        try!(space(&mut self.s));
-        try!(self.print_block(blk));
+        self.head("if let")?;
+        self.print_pat(pat)?;
+        space(&mut self.s)?;
+        self.word_space("=")?;
+        self.print_expr(expr)?;
+        space(&mut self.s)?;
+        self.print_block(blk)?;
         self.print_else(elseopt)
     }
 
     pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken)
                      -> io::Result<()> {
-        try!(self.print_path(&m.node.path, false, 0, false));
-        try!(word(&mut self.s, "!"));
+        self.print_path(&m.node.path, false, 0, false)?;
+        word(&mut self.s, "!")?;
         match delim {
-            token::Paren => try!(self.popen()),
-            token::Bracket => try!(word(&mut self.s, "[")),
+            token::Paren => self.popen()?,
+            token::Bracket => word(&mut self.s, "[")?,
             token::Brace => {
-                try!(self.head(""));
-                try!(self.bopen());
+                self.head("")?;
+                self.bopen()?;
             }
             token::NoDelim => {}
         }
-        try!(self.print_tts(&m.node.tts));
+        self.print_tts(&m.node.tts)?;
         match delim {
             token::Paren => self.pclose(),
             token::Bracket => word(&mut self.s, "]"),
@@ -1818,8 +1819,8 @@ impl<'a> State<'a> {
 
 
     fn print_call_post(&mut self, args: &[P<ast::Expr>]) -> io::Result<()> {
-        try!(self.popen());
-        try!(self.commasep_exprs(Inconsistent, args));
+        self.popen()?;
+        self.commasep_exprs(Inconsistent, args)?;
         self.pclose()
     }
 
@@ -1841,11 +1842,11 @@ impl<'a> State<'a> {
     pub fn print_expr_maybe_paren(&mut self, expr: &ast::Expr) -> io::Result<()> {
         let needs_par = needs_parentheses(expr);
         if needs_par {
-            try!(self.popen());
+            self.popen()?;
         }
-        try!(self.print_expr(expr));
+        self.print_expr(expr)?;
         if needs_par {
-            try!(self.pclose());
+            self.pclose()?;
         }
         Ok(())
     }
@@ -1853,19 +1854,19 @@ impl<'a> State<'a> {
     fn print_expr_in_place(&mut self,
                            place: &ast::Expr,
                            expr: &ast::Expr) -> io::Result<()> {
-        try!(self.print_expr_maybe_paren(place));
-        try!(space(&mut self.s));
-        try!(self.word_space("<-"));
+        self.print_expr_maybe_paren(place)?;
+        space(&mut self.s)?;
+        self.word_space("<-")?;
         self.print_expr_maybe_paren(expr)
     }
 
     fn print_expr_vec(&mut self, exprs: &[P<ast::Expr>],
                       attrs: &[Attribute]) -> io::Result<()> {
-        try!(self.ibox(INDENT_UNIT));
-        try!(word(&mut self.s, "["));
-        try!(self.print_inner_attributes_inline(attrs));
-        try!(self.commasep_exprs(Inconsistent, &exprs[..]));
-        try!(word(&mut self.s, "]"));
+        self.ibox(INDENT_UNIT)?;
+        word(&mut self.s, "[")?;
+        self.print_inner_attributes_inline(attrs)?;
+        self.commasep_exprs(Inconsistent, &exprs[..])?;
+        word(&mut self.s, "]")?;
         self.end()
     }
 
@@ -1873,13 +1874,13 @@ impl<'a> State<'a> {
                          element: &ast::Expr,
                          count: &ast::Expr,
                          attrs: &[Attribute]) -> io::Result<()> {
-        try!(self.ibox(INDENT_UNIT));
-        try!(word(&mut self.s, "["));
-        try!(self.print_inner_attributes_inline(attrs));
-        try!(self.print_expr(element));
-        try!(self.word_space(";"));
-        try!(self.print_expr(count));
-        try!(word(&mut self.s, "]"));
+        self.ibox(INDENT_UNIT)?;
+        word(&mut self.s, "[")?;
+        self.print_inner_attributes_inline(attrs)?;
+        self.print_expr(element)?;
+        self.word_space(";")?;
+        self.print_expr(count)?;
+        word(&mut self.s, "]")?;
         self.end()
     }
 
@@ -1888,48 +1889,48 @@ impl<'a> State<'a> {
                          fields: &[ast::Field],
                          wth: &Option<P<ast::Expr>>,
                          attrs: &[Attribute]) -> io::Result<()> {
-        try!(self.print_path(path, true, 0, false));
-        try!(word(&mut self.s, "{"));
-        try!(self.print_inner_attributes_inline(attrs));
-        try!(self.commasep_cmnt(
+        self.print_path(path, true, 0, false)?;
+        word(&mut self.s, "{")?;
+        self.print_inner_attributes_inline(attrs)?;
+        self.commasep_cmnt(
             Consistent,
             &fields[..],
             |s, field| {
-                try!(s.ibox(INDENT_UNIT));
+                s.ibox(INDENT_UNIT)?;
                 if !field.is_shorthand {
-                    try!(s.print_ident(field.ident.node));
-                    try!(s.word_space(":"));
+                    s.print_ident(field.ident.node)?;
+                    s.word_space(":")?;
                 }
-                try!(s.print_expr(&field.expr));
+                s.print_expr(&field.expr)?;
                 s.end()
             },
-            |f| f.span));
+            |f| f.span)?;
         match *wth {
             Some(ref expr) => {
-                try!(self.ibox(INDENT_UNIT));
+                self.ibox(INDENT_UNIT)?;
                 if !fields.is_empty() {
-                    try!(word(&mut self.s, ","));
-                    try!(space(&mut self.s));
+                    word(&mut self.s, ",")?;
+                    space(&mut self.s)?;
                 }
-                try!(word(&mut self.s, ".."));
-                try!(self.print_expr(&expr));
-                try!(self.end());
+                word(&mut self.s, "..")?;
+                self.print_expr(&expr)?;
+                self.end()?;
             }
             _ => if !fields.is_empty() {
-                try!(word(&mut self.s, ","))
+                word(&mut self.s, ",")?
             }
         }
-        try!(word(&mut self.s, "}"));
+        word(&mut self.s, "}")?;
         Ok(())
     }
 
     fn print_expr_tup(&mut self, exprs: &[P<ast::Expr>],
                       attrs: &[Attribute]) -> io::Result<()> {
-        try!(self.popen());
-        try!(self.print_inner_attributes_inline(attrs));
-        try!(self.commasep_exprs(Inconsistent, &exprs[..]));
+        self.popen()?;
+        self.print_inner_attributes_inline(attrs)?;
+        self.commasep_exprs(Inconsistent, &exprs[..])?;
         if exprs.len() == 1 {
-            try!(word(&mut self.s, ","));
+            word(&mut self.s, ",")?;
         }
         self.pclose()
     }
@@ -1937,7 +1938,7 @@ impl<'a> State<'a> {
     fn print_expr_call(&mut self,
                        func: &ast::Expr,
                        args: &[P<ast::Expr>]) -> io::Result<()> {
-        try!(self.print_expr_maybe_paren(func));
+        self.print_expr_maybe_paren(func)?;
         self.print_call_post(args)
     }
 
@@ -1946,14 +1947,14 @@ impl<'a> State<'a> {
                               tys: &[P<ast::Ty>],
                               args: &[P<ast::Expr>]) -> io::Result<()> {
         let base_args = &args[1..];
-        try!(self.print_expr(&args[0]));
-        try!(word(&mut self.s, "."));
-        try!(self.print_ident(ident.node));
+        self.print_expr(&args[0])?;
+        word(&mut self.s, ".")?;
+        self.print_ident(ident.node)?;
         if !tys.is_empty() {
-            try!(word(&mut self.s, "::<"));
-            try!(self.commasep(Inconsistent, tys,
-                          |s, ty| s.print_type(&ty)));
-            try!(word(&mut self.s, ">"));
+            word(&mut self.s, "::<")?;
+            self.commasep(Inconsistent, tys,
+                          |s, ty| s.print_type(&ty))?;
+            word(&mut self.s, ">")?;
         }
         self.print_call_post(base_args)
     }
@@ -1963,12 +1964,12 @@ impl<'a> State<'a> {
                          lhs: &ast::Expr,
                          rhs: &ast::Expr) -> io::Result<()> {
         if self.check_expr_bin_needs_paren(lhs, op) {
-            try!(self.print_expr_maybe_paren(lhs));
+            self.print_expr_maybe_paren(lhs)?;
         } else {
-            try!(self.print_expr(lhs));
+            self.print_expr(lhs)?;
         }
-        try!(space(&mut self.s));
-        try!(self.word_space(op.node.to_string()));
+        space(&mut self.s)?;
+        self.word_space(op.node.to_string())?;
         if self.check_expr_bin_needs_paren(rhs, op) {
             self.print_expr_maybe_paren(rhs)
         } else {
@@ -1979,15 +1980,15 @@ impl<'a> State<'a> {
     fn print_expr_unary(&mut self,
                         op: ast::UnOp,
                         expr: &ast::Expr) -> io::Result<()> {
-        try!(word(&mut self.s, ast::UnOp::to_string(op)));
+        word(&mut self.s, ast::UnOp::to_string(op))?;
         self.print_expr_maybe_paren(expr)
     }
 
     fn print_expr_addr_of(&mut self,
                           mutability: ast::Mutability,
                           expr: &ast::Expr) -> io::Result<()> {
-        try!(word(&mut self.s, "&"));
-        try!(self.print_mutability(mutability));
+        word(&mut self.s, "&")?;
+        self.print_mutability(mutability)?;
         self.print_expr_maybe_paren(expr)
     }
 
@@ -1998,271 +1999,271 @@ impl<'a> State<'a> {
     fn print_expr_outer_attr_style(&mut self,
                                   expr: &ast::Expr,
                                   is_inline: bool) -> io::Result<()> {
-        try!(self.maybe_print_comment(expr.span.lo));
+        self.maybe_print_comment(expr.span.lo)?;
 
         let attrs = &expr.attrs;
         if is_inline {
-            try!(self.print_outer_attributes_inline(attrs));
+            self.print_outer_attributes_inline(attrs)?;
         } else {
-            try!(self.print_outer_attributes(attrs));
+            self.print_outer_attributes(attrs)?;
         }
 
-        try!(self.ibox(INDENT_UNIT));
-        try!(self.ann.pre(self, NodeExpr(expr)));
+        self.ibox(INDENT_UNIT)?;
+        self.ann.pre(self, NodeExpr(expr))?;
         match expr.node {
             ast::ExprKind::Box(ref expr) => {
-                try!(self.word_space("box"));
-                try!(self.print_expr(expr));
+                self.word_space("box")?;
+                self.print_expr(expr)?;
             }
             ast::ExprKind::InPlace(ref place, ref expr) => {
-                try!(self.print_expr_in_place(place, expr));
+                self.print_expr_in_place(place, expr)?;
             }
             ast::ExprKind::Vec(ref exprs) => {
-                try!(self.print_expr_vec(&exprs[..], attrs));
+                self.print_expr_vec(&exprs[..], attrs)?;
             }
             ast::ExprKind::Repeat(ref element, ref count) => {
-                try!(self.print_expr_repeat(&element, &count, attrs));
+                self.print_expr_repeat(&element, &count, attrs)?;
             }
             ast::ExprKind::Struct(ref path, ref fields, ref wth) => {
-                try!(self.print_expr_struct(path, &fields[..], wth, attrs));
+                self.print_expr_struct(path, &fields[..], wth, attrs)?;
             }
             ast::ExprKind::Tup(ref exprs) => {
-                try!(self.print_expr_tup(&exprs[..], attrs));
+                self.print_expr_tup(&exprs[..], attrs)?;
             }
             ast::ExprKind::Call(ref func, ref args) => {
-                try!(self.print_expr_call(&func, &args[..]));
+                self.print_expr_call(&func, &args[..])?;
             }
             ast::ExprKind::MethodCall(ident, ref tys, ref args) => {
-                try!(self.print_expr_method_call(ident, &tys[..], &args[..]));
+                self.print_expr_method_call(ident, &tys[..], &args[..])?;
             }
             ast::ExprKind::Binary(op, ref lhs, ref rhs) => {
-                try!(self.print_expr_binary(op, &lhs, &rhs));
+                self.print_expr_binary(op, &lhs, &rhs)?;
             }
             ast::ExprKind::Unary(op, ref expr) => {
-                try!(self.print_expr_unary(op, &expr));
+                self.print_expr_unary(op, &expr)?;
             }
             ast::ExprKind::AddrOf(m, ref expr) => {
-                try!(self.print_expr_addr_of(m, &expr));
+                self.print_expr_addr_of(m, &expr)?;
             }
             ast::ExprKind::Lit(ref lit) => {
-                try!(self.print_literal(&lit));
+                self.print_literal(&lit)?;
             }
             ast::ExprKind::Cast(ref expr, ref ty) => {
                 if let ast::ExprKind::Cast(..) = expr.node {
-                    try!(self.print_expr(&expr));
+                    self.print_expr(&expr)?;
                 } else {
-                    try!(self.print_expr_maybe_paren(&expr));
+                    self.print_expr_maybe_paren(&expr)?;
                 }
-                try!(space(&mut self.s));
-                try!(self.word_space("as"));
-                try!(self.print_type(&ty));
+                space(&mut self.s)?;
+                self.word_space("as")?;
+                self.print_type(&ty)?;
             }
             ast::ExprKind::Type(ref expr, ref ty) => {
-                try!(self.print_expr(&expr));
-                try!(self.word_space(":"));
-                try!(self.print_type(&ty));
+                self.print_expr(&expr)?;
+                self.word_space(":")?;
+                self.print_type(&ty)?;
             }
             ast::ExprKind::If(ref test, ref blk, ref elseopt) => {
-                try!(self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e)));
+                self.print_if(&test, &blk, elseopt.as_ref().map(|e| &**e))?;
             }
             ast::ExprKind::IfLet(ref pat, ref expr, ref blk, ref elseopt) => {
-                try!(self.print_if_let(&pat, &expr, &blk, elseopt.as_ref().map(|e| &**e)));
+                self.print_if_let(&pat, &expr, &blk, elseopt.as_ref().map(|e| &**e))?;
             }
             ast::ExprKind::While(ref test, ref blk, opt_ident) => {
                 if let Some(ident) = opt_ident {
-                    try!(self.print_ident(ident.node));
-                    try!(self.word_space(":"));
+                    self.print_ident(ident.node)?;
+                    self.word_space(":")?;
                 }
-                try!(self.head("while"));
-                try!(self.print_expr(&test));
-                try!(space(&mut self.s));
-                try!(self.print_block_with_attrs(&blk, attrs));
+                self.head("while")?;
+                self.print_expr(&test)?;
+                space(&mut self.s)?;
+                self.print_block_with_attrs(&blk, attrs)?;
             }
             ast::ExprKind::WhileLet(ref pat, ref expr, ref blk, opt_ident) => {
                 if let Some(ident) = opt_ident {
-                    try!(self.print_ident(ident.node));
-                    try!(self.word_space(":"));
+                    self.print_ident(ident.node)?;
+                    self.word_space(":")?;
                 }
-                try!(self.head("while let"));
-                try!(self.print_pat(&pat));
-                try!(space(&mut self.s));
-                try!(self.word_space("="));
-                try!(self.print_expr(&expr));
-                try!(space(&mut self.s));
-                try!(self.print_block_with_attrs(&blk, attrs));
+                self.head("while let")?;
+                self.print_pat(&pat)?;
+                space(&mut self.s)?;
+                self.word_space("=")?;
+                self.print_expr(&expr)?;
+                space(&mut self.s)?;
+                self.print_block_with_attrs(&blk, attrs)?;
             }
             ast::ExprKind::ForLoop(ref pat, ref iter, ref blk, opt_ident) => {
                 if let Some(ident) = opt_ident {
-                    try!(self.print_ident(ident.node));
-                    try!(self.word_space(":"));
+                    self.print_ident(ident.node)?;
+                    self.word_space(":")?;
                 }
-                try!(self.head("for"));
-                try!(self.print_pat(&pat));
-                try!(space(&mut self.s));
-                try!(self.word_space("in"));
-                try!(self.print_expr(&iter));
-                try!(space(&mut self.s));
-                try!(self.print_block_with_attrs(&blk, attrs));
+                self.head("for")?;
+                self.print_pat(&pat)?;
+                space(&mut self.s)?;
+                self.word_space("in")?;
+                self.print_expr(&iter)?;
+                space(&mut self.s)?;
+                self.print_block_with_attrs(&blk, attrs)?;
             }
             ast::ExprKind::Loop(ref blk, opt_ident) => {
                 if let Some(ident) = opt_ident {
-                    try!(self.print_ident(ident.node));
-                    try!(self.word_space(":"));
+                    self.print_ident(ident.node)?;
+                    self.word_space(":")?;
                 }
-                try!(self.head("loop"));
-                try!(space(&mut self.s));
-                try!(self.print_block_with_attrs(&blk, attrs));
+                self.head("loop")?;
+                space(&mut self.s)?;
+                self.print_block_with_attrs(&blk, attrs)?;
             }
             ast::ExprKind::Match(ref expr, ref arms) => {
-                try!(self.cbox(INDENT_UNIT));
-                try!(self.ibox(4));
-                try!(self.word_nbsp("match"));
-                try!(self.print_expr(&expr));
-                try!(space(&mut self.s));
-                try!(self.bopen());
-                try!(self.print_inner_attributes_no_trailing_hardbreak(attrs));
+                self.cbox(INDENT_UNIT)?;
+                self.ibox(4)?;
+                self.word_nbsp("match")?;
+                self.print_expr(&expr)?;
+                space(&mut self.s)?;
+                self.bopen()?;
+                self.print_inner_attributes_no_trailing_hardbreak(attrs)?;
                 for arm in arms {
-                    try!(self.print_arm(arm));
+                    self.print_arm(arm)?;
                 }
-                try!(self.bclose_(expr.span, INDENT_UNIT));
+                self.bclose_(expr.span, INDENT_UNIT)?;
             }
             ast::ExprKind::Closure(capture_clause, ref decl, ref body, _) => {
-                try!(self.print_capture_clause(capture_clause));
+                self.print_capture_clause(capture_clause)?;
 
-                try!(self.print_fn_block_args(&decl));
-                try!(space(&mut self.s));
-                try!(self.print_expr(body));
-                try!(self.end()); // need to close a box
+                self.print_fn_block_args(&decl)?;
+                space(&mut self.s)?;
+                self.print_expr(body)?;
+                self.end()?; // need to close a box
 
                 // a box will be closed by print_expr, but we didn't want an overall
                 // wrapper so we closed the corresponding opening. so create an
                 // empty box to satisfy the close.
-                try!(self.ibox(0));
+                self.ibox(0)?;
             }
             ast::ExprKind::Block(ref blk) => {
                 // containing cbox, will be closed by print-block at }
-                try!(self.cbox(INDENT_UNIT));
+                self.cbox(INDENT_UNIT)?;
                 // head-box, will be closed by print-block after {
-                try!(self.ibox(0));
-                try!(self.print_block_with_attrs(&blk, attrs));
+                self.ibox(0)?;
+                self.print_block_with_attrs(&blk, attrs)?;
             }
             ast::ExprKind::Assign(ref lhs, ref rhs) => {
-                try!(self.print_expr(&lhs));
-                try!(space(&mut self.s));
-                try!(self.word_space("="));
-                try!(self.print_expr(&rhs));
+                self.print_expr(&lhs)?;
+                space(&mut self.s)?;
+                self.word_space("=")?;
+                self.print_expr(&rhs)?;
             }
             ast::ExprKind::AssignOp(op, ref lhs, ref rhs) => {
-                try!(self.print_expr(&lhs));
-                try!(space(&mut self.s));
-                try!(word(&mut self.s, op.node.to_string()));
-                try!(self.word_space("="));
-                try!(self.print_expr(&rhs));
+                self.print_expr(&lhs)?;
+                space(&mut self.s)?;
+                word(&mut self.s, op.node.to_string())?;
+                self.word_space("=")?;
+                self.print_expr(&rhs)?;
             }
             ast::ExprKind::Field(ref expr, id) => {
-                try!(self.print_expr(&expr));
-                try!(word(&mut self.s, "."));
-                try!(self.print_ident(id.node));
+                self.print_expr(&expr)?;
+                word(&mut self.s, ".")?;
+                self.print_ident(id.node)?;
             }
             ast::ExprKind::TupField(ref expr, id) => {
-                try!(self.print_expr(&expr));
-                try!(word(&mut self.s, "."));
-                try!(self.print_usize(id.node));
+                self.print_expr(&expr)?;
+                word(&mut self.s, ".")?;
+                self.print_usize(id.node)?;
             }
             ast::ExprKind::Index(ref expr, ref index) => {
-                try!(self.print_expr(&expr));
-                try!(word(&mut self.s, "["));
-                try!(self.print_expr(&index));
-                try!(word(&mut self.s, "]"));
+                self.print_expr(&expr)?;
+                word(&mut self.s, "[")?;
+                self.print_expr(&index)?;
+                word(&mut self.s, "]")?;
             }
             ast::ExprKind::Range(ref start, ref end, limits) => {
                 if let &Some(ref e) = start {
-                    try!(self.print_expr(&e));
+                    self.print_expr(&e)?;
                 }
                 if limits == ast::RangeLimits::HalfOpen {
-                    try!(word(&mut self.s, ".."));
+                    word(&mut self.s, "..")?;
                 } else {
-                    try!(word(&mut self.s, "..."));
+                    word(&mut self.s, "...")?;
                 }
                 if let &Some(ref e) = end {
-                    try!(self.print_expr(&e));
+                    self.print_expr(&e)?;
                 }
             }
             ast::ExprKind::Path(None, ref path) => {
-                try!(self.print_path(path, true, 0, false))
+                self.print_path(path, true, 0, false)?
             }
             ast::ExprKind::Path(Some(ref qself), ref path) => {
-                try!(self.print_qpath(path, qself, true))
+                self.print_qpath(path, qself, true)?
             }
             ast::ExprKind::Break(opt_ident, ref opt_expr) => {
-                try!(word(&mut self.s, "break"));
-                try!(space(&mut self.s));
+                word(&mut self.s, "break")?;
+                space(&mut self.s)?;
                 if let Some(ident) = opt_ident {
-                    try!(self.print_ident(ident.node));
-                    try!(space(&mut self.s));
+                    self.print_ident(ident.node)?;
+                    space(&mut self.s)?;
                 }
                 if let Some(ref expr) = *opt_expr {
-                    try!(self.print_expr(expr));
-                    try!(space(&mut self.s));
+                    self.print_expr(expr)?;
+                    space(&mut self.s)?;
                 }
             }
             ast::ExprKind::Continue(opt_ident) => {
-                try!(word(&mut self.s, "continue"));
-                try!(space(&mut self.s));
+                word(&mut self.s, "continue")?;
+                space(&mut self.s)?;
                 if let Some(ident) = opt_ident {
-                    try!(self.print_ident(ident.node));
-                    try!(space(&mut self.s))
+                    self.print_ident(ident.node)?;
+                    space(&mut self.s)?
                 }
             }
             ast::ExprKind::Ret(ref result) => {
-                try!(word(&mut self.s, "return"));
+                word(&mut self.s, "return")?;
                 match *result {
                     Some(ref expr) => {
-                        try!(word(&mut self.s, " "));
-                        try!(self.print_expr(&expr));
+                        word(&mut self.s, " ")?;
+                        self.print_expr(&expr)?;
                     }
                     _ => ()
                 }
             }
             ast::ExprKind::InlineAsm(ref a) => {
-                try!(word(&mut self.s, "asm!"));
-                try!(self.popen());
-                try!(self.print_string(&a.asm.as_str(), a.asm_str_style));
-                try!(self.word_space(":"));
+                word(&mut self.s, "asm!")?;
+                self.popen()?;
+                self.print_string(&a.asm.as_str(), a.asm_str_style)?;
+                self.word_space(":")?;
 
-                try!(self.commasep(Inconsistent, &a.outputs, |s, out| {
+                self.commasep(Inconsistent, &a.outputs, |s, out| {
                     let constraint = out.constraint.as_str();
                     let mut ch = constraint.chars();
                     match ch.next() {
                         Some('=') if out.is_rw => {
-                            try!(s.print_string(&format!("+{}", ch.as_str()),
-                                           ast::StrStyle::Cooked))
+                            s.print_string(&format!("+{}", ch.as_str()),
+                                           ast::StrStyle::Cooked)?
                         }
-                        _ => try!(s.print_string(&constraint, ast::StrStyle::Cooked))
+                        _ => s.print_string(&constraint, ast::StrStyle::Cooked)?
                     }
-                    try!(s.popen());
-                    try!(s.print_expr(&out.expr));
-                    try!(s.pclose());
+                    s.popen()?;
+                    s.print_expr(&out.expr)?;
+                    s.pclose()?;
                     Ok(())
-                }));
-                try!(space(&mut self.s));
-                try!(self.word_space(":"));
-
-                try!(self.commasep(Inconsistent, &a.inputs, |s, &(co, ref o)| {
-                    try!(s.print_string(&co.as_str(), ast::StrStyle::Cooked));
-                    try!(s.popen());
-                    try!(s.print_expr(&o));
-                    try!(s.pclose());
+                })?;
+                space(&mut self.s)?;
+                self.word_space(":")?;
+
+                self.commasep(Inconsistent, &a.inputs, |s, &(co, ref o)| {
+                    s.print_string(&co.as_str(), ast::StrStyle::Cooked)?;
+                    s.popen()?;
+                    s.print_expr(&o)?;
+                    s.pclose()?;
                     Ok(())
-                }));
-                try!(space(&mut self.s));
-                try!(self.word_space(":"));
+                })?;
+                space(&mut self.s)?;
+                self.word_space(":")?;
 
-                try!(self.commasep(Inconsistent, &a.clobbers,
+                self.commasep(Inconsistent, &a.clobbers,
                                    |s, co| {
-                    try!(s.print_string(&co.as_str(), ast::StrStyle::Cooked));
+                    s.print_string(&co.as_str(), ast::StrStyle::Cooked)?;
                     Ok(())
-                }));
+                })?;
 
                 let mut options = vec![];
                 if a.volatile {
@@ -2276,44 +2277,44 @@ impl<'a> State<'a> {
                 }
 
                 if !options.is_empty() {
-                    try!(space(&mut self.s));
-                    try!(self.word_space(":"));
-                    try!(self.commasep(Inconsistent, &options,
+                    space(&mut self.s)?;
+                    self.word_space(":")?;
+                    self.commasep(Inconsistent, &options,
                                   |s, &co| {
-                                      try!(s.print_string(co, ast::StrStyle::Cooked));
+                                      s.print_string(co, ast::StrStyle::Cooked)?;
                                       Ok(())
-                                  }));
+                                  })?;
                 }
 
-                try!(self.pclose());
+                self.pclose()?;
             }
-            ast::ExprKind::Mac(ref m) => try!(self.print_mac(m, token::Paren)),
+            ast::ExprKind::Mac(ref m) => self.print_mac(m, token::Paren)?,
             ast::ExprKind::Paren(ref e) => {
-                try!(self.popen());
-                try!(self.print_inner_attributes_inline(attrs));
-                try!(self.print_expr(&e));
-                try!(self.pclose());
+                self.popen()?;
+                self.print_inner_attributes_inline(attrs)?;
+                self.print_expr(&e)?;
+                self.pclose()?;
             },
             ast::ExprKind::Try(ref e) => {
-                try!(self.print_expr(e));
-                try!(word(&mut self.s, "?"))
+                self.print_expr(e)?;
+                word(&mut self.s, "?")?
             }
         }
-        try!(self.ann.post(self, NodeExpr(expr)));
+        self.ann.post(self, NodeExpr(expr))?;
         self.end()
     }
 
     pub fn print_local_decl(&mut self, loc: &ast::Local) -> io::Result<()> {
-        try!(self.print_pat(&loc.pat));
+        self.print_pat(&loc.pat)?;
         if let Some(ref ty) = loc.ty {
-            try!(self.word_space(":"));
-            try!(self.print_type(&ty));
+            self.word_space(":")?;
+            self.print_type(&ty)?;
         }
         Ok(())
     }
 
     pub fn print_ident(&mut self, ident: ast::Ident) -> io::Result<()> {
-        try!(word(&mut self.s, &ident.name.as_str()));
+        word(&mut self.s, &ident.name.as_str())?;
         self.ann.post(self, NodeIdent(&ident))
     }
 
@@ -2322,15 +2323,15 @@ impl<'a> State<'a> {
     }
 
     pub fn print_name(&mut self, name: ast::Name) -> io::Result<()> {
-        try!(word(&mut self.s, &name.as_str()));
+        word(&mut self.s, &name.as_str())?;
         self.ann.post(self, NodeName(&name))
     }
 
     pub fn print_for_decl(&mut self, loc: &ast::Local,
                           coll: &ast::Expr) -> io::Result<()> {
-        try!(self.print_local_decl(loc));
-        try!(space(&mut self.s));
-        try!(self.word_space("in"));
+        self.print_local_decl(loc)?;
+        space(&mut self.s)?;
+        self.word_space("in")?;
         self.print_expr(coll)
     }
 
@@ -2341,7 +2342,7 @@ impl<'a> State<'a> {
                   defaults_to_global: bool)
                   -> io::Result<()>
     {
-        try!(self.maybe_print_comment(path.span.lo));
+        self.maybe_print_comment(path.span.lo)?;
 
         let mut segments = path.segments[..path.segments.len()-depth].iter();
         if defaults_to_global && path.is_global() {
@@ -2349,13 +2350,13 @@ impl<'a> State<'a> {
         }
         for (i, segment) in segments.enumerate() {
             if i > 0 {
-                try!(word(&mut self.s, "::"))
+                word(&mut self.s, "::")?
             }
             if segment.identifier.name != keywords::CrateRoot.name() &&
                segment.identifier.name != "$crate" {
-                try!(self.print_ident(segment.identifier));
+                self.print_ident(segment.identifier)?;
                 if let Some(ref parameters) = segment.parameters {
-                    try!(self.print_path_parameters(parameters, colons_before_params));
+                    self.print_path_parameters(parameters, colons_before_params)?;
                 }
             }
         }
@@ -2369,18 +2370,18 @@ impl<'a> State<'a> {
                    colons_before_params: bool)
                    -> io::Result<()>
     {
-        try!(word(&mut self.s, "<"));
-        try!(self.print_type(&qself.ty));
+        word(&mut self.s, "<")?;
+        self.print_type(&qself.ty)?;
         if qself.position > 0 {
-            try!(space(&mut self.s));
-            try!(self.word_space("as"));
+            space(&mut self.s)?;
+            self.word_space("as")?;
             let depth = path.segments.len() - qself.position;
-            try!(self.print_path(&path, false, depth, false));
+            self.print_path(&path, false, depth, false)?;
         }
-        try!(word(&mut self.s, ">"));
-        try!(word(&mut self.s, "::"));
+        word(&mut self.s, ">")?;
+        word(&mut self.s, "::")?;
         let item_segment = path.segments.last().unwrap();
-        try!(self.print_ident(item_segment.identifier));
+        self.print_ident(item_segment.identifier)?;
         match item_segment.parameters {
             Some(ref parameters) => self.print_path_parameters(parameters, colons_before_params),
             None => Ok(()),
@@ -2393,59 +2394,59 @@ impl<'a> State<'a> {
                              -> io::Result<()>
     {
         if colons_before_params {
-            try!(word(&mut self.s, "::"))
+            word(&mut self.s, "::")?
         }
 
         match *parameters {
             ast::PathParameters::AngleBracketed(ref data) => {
-                try!(word(&mut self.s, "<"));
+                word(&mut self.s, "<")?;
 
                 let mut comma = false;
                 for lifetime in &data.lifetimes {
                     if comma {
-                        try!(self.word_space(","))
+                        self.word_space(",")?
                     }
-                    try!(self.print_lifetime(lifetime));
+                    self.print_lifetime(lifetime)?;
                     comma = true;
                 }
 
                 if !data.types.is_empty() {
                     if comma {
-                        try!(self.word_space(","))
+                        self.word_space(",")?
                     }
-                    try!(self.commasep(
+                    self.commasep(
                         Inconsistent,
                         &data.types,
-                        |s, ty| s.print_type(&ty)));
+                        |s, ty| s.print_type(&ty))?;
                         comma = true;
                 }
 
                 for binding in data.bindings.iter() {
                     if comma {
-                        try!(self.word_space(","))
+                        self.word_space(",")?
                     }
-                    try!(self.print_ident(binding.ident));
-                    try!(space(&mut self.s));
-                    try!(self.word_space("="));
-                    try!(self.print_type(&binding.ty));
+                    self.print_ident(binding.ident)?;
+                    space(&mut self.s)?;
+                    self.word_space("=")?;
+                    self.print_type(&binding.ty)?;
                     comma = true;
                 }
 
-                try!(word(&mut self.s, ">"))
+                word(&mut self.s, ">")?
             }
 
             ast::PathParameters::Parenthesized(ref data) => {
-                try!(word(&mut self.s, "("));
-                try!(self.commasep(
+                word(&mut self.s, "(")?;
+                self.commasep(
                     Inconsistent,
                     &data.inputs,
-                    |s, ty| s.print_type(&ty)));
-                try!(word(&mut self.s, ")"));
+                    |s, ty| s.print_type(&ty))?;
+                word(&mut self.s, ")")?;
 
                 if let Some(ref ty) = data.output {
-                    try!(self.space_if_not_bol());
-                    try!(self.word_space("->"));
-                    try!(self.print_type(&ty));
+                    self.space_if_not_bol()?;
+                    self.word_space("->")?;
+                    self.print_type(&ty)?;
                 }
             }
         }
@@ -2454,133 +2455,133 @@ impl<'a> State<'a> {
     }
 
     pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
-        try!(self.maybe_print_comment(pat.span.lo));
-        try!(self.ann.pre(self, NodePat(pat)));
+        self.maybe_print_comment(pat.span.lo)?;
+        self.ann.pre(self, NodePat(pat))?;
         /* Pat isn't normalized, but the beauty of it
          is that it doesn't matter */
         match pat.node {
-            PatKind::Wild => try!(word(&mut self.s, "_")),
+            PatKind::Wild => word(&mut self.s, "_")?,
             PatKind::Ident(binding_mode, ref path1, ref sub) => {
                 match binding_mode {
                     ast::BindingMode::ByRef(mutbl) => {
-                        try!(self.word_nbsp("ref"));
-                        try!(self.print_mutability(mutbl));
+                        self.word_nbsp("ref")?;
+                        self.print_mutability(mutbl)?;
                     }
                     ast::BindingMode::ByValue(ast::Mutability::Immutable) => {}
                     ast::BindingMode::ByValue(ast::Mutability::Mutable) => {
-                        try!(self.word_nbsp("mut"));
+                        self.word_nbsp("mut")?;
                     }
                 }
-                try!(self.print_ident(path1.node));
+                self.print_ident(path1.node)?;
                 if let Some(ref p) = *sub {
-                    try!(word(&mut self.s, "@"));
-                    try!(self.print_pat(&p));
+                    word(&mut self.s, "@")?;
+                    self.print_pat(&p)?;
                 }
             }
             PatKind::TupleStruct(ref path, ref elts, ddpos) => {
-                try!(self.print_path(path, true, 0, false));
-                try!(self.popen());
+                self.print_path(path, true, 0, false)?;
+                self.popen()?;
                 if let Some(ddpos) = ddpos {
-                    try!(self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p)));
+                    self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))?;
                     if ddpos != 0 {
-                        try!(self.word_space(","));
+                        self.word_space(",")?;
                     }
-                    try!(word(&mut self.s, ".."));
+                    word(&mut self.s, "..")?;
                     if ddpos != elts.len() {
-                        try!(word(&mut self.s, ","));
-                        try!(self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p)));
+                        word(&mut self.s, ",")?;
+                        self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?;
                     }
                 } else {
-                    try!(self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p)));
+                    self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?;
                 }
-                try!(self.pclose());
+                self.pclose()?;
             }
             PatKind::Path(None, ref path) => {
-                try!(self.print_path(path, true, 0, false));
+                self.print_path(path, true, 0, false)?;
             }
             PatKind::Path(Some(ref qself), ref path) => {
-                try!(self.print_qpath(path, qself, false));
+                self.print_qpath(path, qself, false)?;
             }
             PatKind::Struct(ref path, ref fields, etc) => {
-                try!(self.print_path(path, true, 0, false));
-                try!(self.nbsp());
-                try!(self.word_space("{"));
-                try!(self.commasep_cmnt(
+                self.print_path(path, true, 0, false)?;
+                self.nbsp()?;
+                self.word_space("{")?;
+                self.commasep_cmnt(
                     Consistent, &fields[..],
                     |s, f| {
-                        try!(s.cbox(INDENT_UNIT));
+                        s.cbox(INDENT_UNIT)?;
                         if !f.node.is_shorthand {
-                            try!(s.print_ident(f.node.ident));
-                            try!(s.word_nbsp(":"));
+                            s.print_ident(f.node.ident)?;
+                            s.word_nbsp(":")?;
                         }
-                        try!(s.print_pat(&f.node.pat));
+                        s.print_pat(&f.node.pat)?;
                         s.end()
                     },
-                    |f| f.node.pat.span));
+                    |f| f.node.pat.span)?;
                 if etc {
-                    if !fields.is_empty() { try!(self.word_space(",")); }
-                    try!(word(&mut self.s, ".."));
+                    if !fields.is_empty() { self.word_space(",")?; }
+                    word(&mut self.s, "..")?;
                 }
-                try!(space(&mut self.s));
-                try!(word(&mut self.s, "}"));
+                space(&mut self.s)?;
+                word(&mut self.s, "}")?;
             }
             PatKind::Tuple(ref elts, ddpos) => {
-                try!(self.popen());
+                self.popen()?;
                 if let Some(ddpos) = ddpos {
-                    try!(self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p)));
+                    self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))?;
                     if ddpos != 0 {
-                        try!(self.word_space(","));
+                        self.word_space(",")?;
                     }
-                    try!(word(&mut self.s, ".."));
+                    word(&mut self.s, "..")?;
                     if ddpos != elts.len() {
-                        try!(word(&mut self.s, ","));
-                        try!(self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p)));
+                        word(&mut self.s, ",")?;
+                        self.commasep(Inconsistent, &elts[ddpos..], |s, p| s.print_pat(&p))?;
                     }
                 } else {
-                    try!(self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p)));
+                    self.commasep(Inconsistent, &elts[..], |s, p| s.print_pat(&p))?;
                     if elts.len() == 1 {
-                        try!(word(&mut self.s, ","));
+                        word(&mut self.s, ",")?;
                     }
                 }
-                try!(self.pclose());
+                self.pclose()?;
             }
             PatKind::Box(ref inner) => {
-                try!(word(&mut self.s, "box "));
-                try!(self.print_pat(&inner));
+                word(&mut self.s, "box ")?;
+                self.print_pat(&inner)?;
             }
             PatKind::Ref(ref inner, mutbl) => {
-                try!(word(&mut self.s, "&"));
+                word(&mut self.s, "&")?;
                 if mutbl == ast::Mutability::Mutable {
-                    try!(word(&mut self.s, "mut "));
+                    word(&mut self.s, "mut ")?;
                 }
-                try!(self.print_pat(&inner));
+                self.print_pat(&inner)?;
             }
-            PatKind::Lit(ref e) => try!(self.print_expr(&**e)),
+            PatKind::Lit(ref e) => self.print_expr(&**e)?,
             PatKind::Range(ref begin, ref end) => {
-                try!(self.print_expr(&begin));
-                try!(space(&mut self.s));
-                try!(word(&mut self.s, "..."));
-                try!(self.print_expr(&end));
+                self.print_expr(&begin)?;
+                space(&mut self.s)?;
+                word(&mut self.s, "...")?;
+                self.print_expr(&end)?;
             }
             PatKind::Slice(ref before, ref slice, ref after) => {
-                try!(word(&mut self.s, "["));
-                try!(self.commasep(Inconsistent,
+                word(&mut self.s, "[")?;
+                self.commasep(Inconsistent,
                                    &before[..],
-                                   |s, p| s.print_pat(&p)));
+                                   |s, p| s.print_pat(&p))?;
                 if let Some(ref p) = *slice {
-                    if !before.is_empty() { try!(self.word_space(",")); }
+                    if !before.is_empty() { self.word_space(",")?; }
                     if p.node != PatKind::Wild {
-                        try!(self.print_pat(&p));
+                        self.print_pat(&p)?;
                     }
-                    try!(word(&mut self.s, ".."));
-                    if !after.is_empty() { try!(self.word_space(",")); }
+                    word(&mut self.s, "..")?;
+                    if !after.is_empty() { self.word_space(",")?; }
                 }
-                try!(self.commasep(Inconsistent,
+                self.commasep(Inconsistent,
                                    &after[..],
-                                   |s, p| s.print_pat(&p)));
-                try!(word(&mut self.s, "]"));
+                                   |s, p| s.print_pat(&p))?;
+                word(&mut self.s, "]")?;
             }
-            PatKind::Mac(ref m) => try!(self.print_mac(m, token::Paren)),
+            PatKind::Mac(ref m) => self.print_mac(m, token::Paren)?,
         }
         self.ann.post(self, NodePat(pat))
     }
@@ -2589,44 +2590,44 @@ impl<'a> State<'a> {
         // I have no idea why this check is necessary, but here it
         // is :(
         if arm.attrs.is_empty() {
-            try!(space(&mut self.s));
+            space(&mut self.s)?;
         }
-        try!(self.cbox(INDENT_UNIT));
-        try!(self.ibox(0));
-        try!(self.maybe_print_comment(arm.pats[0].span.lo));
-        try!(self.print_outer_attributes(&arm.attrs));
+        self.cbox(INDENT_UNIT)?;
+        self.ibox(0)?;
+        self.maybe_print_comment(arm.pats[0].span.lo)?;
+        self.print_outer_attributes(&arm.attrs)?;
         let mut first = true;
         for p in &arm.pats {
             if first {
                 first = false;
             } else {
-                try!(space(&mut self.s));
-                try!(self.word_space("|"));
+                space(&mut self.s)?;
+                self.word_space("|")?;
             }
-            try!(self.print_pat(&p));
+            self.print_pat(&p)?;
         }
-        try!(space(&mut self.s));
+        space(&mut self.s)?;
         if let Some(ref e) = arm.guard {
-            try!(self.word_space("if"));
-            try!(self.print_expr(&e));
-            try!(space(&mut self.s));
+            self.word_space("if")?;
+            self.print_expr(&e)?;
+            space(&mut self.s)?;
         }
-        try!(self.word_space("=>"));
+        self.word_space("=>")?;
 
         match arm.body.node {
             ast::ExprKind::Block(ref blk) => {
                 // the block will close the pattern's ibox
-                try!(self.print_block_unclosed_indent(&blk, INDENT_UNIT));
+                self.print_block_unclosed_indent(&blk, INDENT_UNIT)?;
 
                 // If it is a user-provided unsafe block, print a comma after it
                 if let BlockCheckMode::Unsafe(ast::UserProvided) = blk.rules {
-                    try!(word(&mut self.s, ","));
+                    word(&mut self.s, ",")?;
                 }
             }
             _ => {
-                try!(self.end()); // close the ibox for the pattern
-                try!(self.print_expr(&arm.body));
-                try!(word(&mut self.s, ","));
+                self.end()?; // close the ibox for the pattern
+                self.print_expr(&arm.body)?;
+                word(&mut self.s, ",")?;
             }
         }
         self.end() // close enclosing cbox
@@ -2635,19 +2636,19 @@ impl<'a> State<'a> {
     fn print_explicit_self(&mut self, explicit_self: &ast::ExplicitSelf) -> io::Result<()> {
         match explicit_self.node {
             SelfKind::Value(m) => {
-                try!(self.print_mutability(m));
+                self.print_mutability(m)?;
                 word(&mut self.s, "self")
             }
             SelfKind::Region(ref lt, m) => {
-                try!(word(&mut self.s, "&"));
-                try!(self.print_opt_lifetime(lt));
-                try!(self.print_mutability(m));
+                word(&mut self.s, "&")?;
+                self.print_opt_lifetime(lt)?;
+                self.print_mutability(m)?;
                 word(&mut self.s, "self")
             }
             SelfKind::Explicit(ref typ, m) => {
-                try!(self.print_mutability(m));
-                try!(word(&mut self.s, "self"));
-                try!(self.word_space(":"));
+                self.print_mutability(m)?;
+                word(&mut self.s, "self")?;
+                self.word_space(":")?;
                 self.print_type(&typ)
             }
         }
@@ -2661,25 +2662,25 @@ impl<'a> State<'a> {
                     name: Option<ast::Ident>,
                     generics: &ast::Generics,
                     vis: &ast::Visibility) -> io::Result<()> {
-        try!(self.print_fn_header_info(unsafety, constness, abi, vis));
+        self.print_fn_header_info(unsafety, constness, abi, vis)?;
 
         if let Some(name) = name {
-            try!(self.nbsp());
-            try!(self.print_ident(name));
+            self.nbsp()?;
+            self.print_ident(name)?;
         }
-        try!(self.print_generics(generics));
-        try!(self.print_fn_args_and_ret(decl));
+        self.print_generics(generics)?;
+        self.print_fn_args_and_ret(decl)?;
         self.print_where_clause(&generics.where_clause)
     }
 
     pub fn print_fn_args_and_ret(&mut self, decl: &ast::FnDecl)
         -> io::Result<()> {
-        try!(self.popen());
-        try!(self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, false)));
+        self.popen()?;
+        self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, false))?;
         if decl.variadic {
-            try!(word(&mut self.s, ", ..."));
+            word(&mut self.s, ", ...")?;
         }
-        try!(self.pclose());
+        self.pclose()?;
 
         self.print_fn_output(decl)
     }
@@ -2688,19 +2689,19 @@ impl<'a> State<'a> {
             &mut self,
             decl: &ast::FnDecl)
             -> io::Result<()> {
-        try!(word(&mut self.s, "|"));
-        try!(self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, true)));
-        try!(word(&mut self.s, "|"));
+        word(&mut self.s, "|")?;
+        self.commasep(Inconsistent, &decl.inputs, |s, arg| s.print_arg(arg, true))?;
+        word(&mut self.s, "|")?;
 
         if let ast::FunctionRetTy::Default(..) = decl.output {
             return Ok(());
         }
 
-        try!(self.space_if_not_bol());
-        try!(self.word_space("->"));
+        self.space_if_not_bol()?;
+        self.word_space("->")?;
         match decl.output {
             ast::FunctionRetTy::Ty(ref ty) => {
-                try!(self.print_type(&ty));
+                self.print_type(&ty)?;
                 self.maybe_print_comment(ty.span.lo)
             }
             ast::FunctionRetTy::Default(..) => unreachable!(),
@@ -2720,28 +2721,28 @@ impl<'a> State<'a> {
                         bounds: &[ast::TyParamBound])
                         -> io::Result<()> {
         if !bounds.is_empty() {
-            try!(word(&mut self.s, prefix));
+            word(&mut self.s, prefix)?;
             let mut first = true;
             for bound in bounds {
-                try!(self.nbsp());
+                self.nbsp()?;
                 if first {
                     first = false;
                 } else {
-                    try!(self.word_space("+"));
+                    self.word_space("+")?;
                 }
 
-                try!(match *bound {
+                (match *bound {
                     TraitTyParamBound(ref tref, TraitBoundModifier::None) => {
                         self.print_poly_trait_ref(tref)
                     }
                     TraitTyParamBound(ref tref, TraitBoundModifier::Maybe) => {
-                        try!(word(&mut self.s, "?"));
+                        word(&mut self.s, "?")?;
                         self.print_poly_trait_ref(tref)
                     }
                     RegionTyParamBound(ref lt) => {
                         self.print_lifetime(lt)
                     }
-                })
+                })?
             }
             Ok(())
         } else {
@@ -2761,14 +2762,14 @@ impl<'a> State<'a> {
                                  bounds: &[ast::Lifetime])
                                  -> io::Result<()>
     {
-        try!(self.print_lifetime(lifetime));
+        self.print_lifetime(lifetime)?;
         if !bounds.is_empty() {
-            try!(word(&mut self.s, ": "));
+            word(&mut self.s, ": ")?;
             for (i, bound) in bounds.iter().enumerate() {
                 if i != 0 {
-                    try!(word(&mut self.s, " + "));
+                    word(&mut self.s, " + ")?;
                 }
-                try!(self.print_lifetime(bound));
+                self.print_lifetime(bound)?;
             }
         }
         Ok(())
@@ -2783,37 +2784,37 @@ impl<'a> State<'a> {
             return Ok(());
         }
 
-        try!(word(&mut self.s, "<"));
+        word(&mut self.s, "<")?;
 
         let mut ints = Vec::new();
         for i in 0..total {
             ints.push(i);
         }
 
-        try!(self.commasep(Inconsistent, &ints[..], |s, &idx| {
+        self.commasep(Inconsistent, &ints[..], |s, &idx| {
             if idx < generics.lifetimes.len() {
                 let lifetime_def = &generics.lifetimes[idx];
-                try!(s.print_outer_attributes_inline(&lifetime_def.attrs));
+                s.print_outer_attributes_inline(&lifetime_def.attrs)?;
                 s.print_lifetime_bounds(&lifetime_def.lifetime, &lifetime_def.bounds)
             } else {
                 let idx = idx - generics.lifetimes.len();
                 let param = &generics.ty_params[idx];
                 s.print_ty_param(param)
             }
-        }));
+        })?;
 
-        try!(word(&mut self.s, ">"));
+        word(&mut self.s, ">")?;
         Ok(())
     }
 
     pub fn print_ty_param(&mut self, param: &ast::TyParam) -> io::Result<()> {
-        try!(self.print_outer_attributes_inline(&param.attrs));
-        try!(self.print_ident(param.ident));
-        try!(self.print_bounds(":", &param.bounds));
+        self.print_outer_attributes_inline(&param.attrs)?;
+        self.print_ident(param.ident)?;
+        self.print_bounds(":", &param.bounds)?;
         match param.default {
             Some(ref default) => {
-                try!(space(&mut self.s));
-                try!(self.word_space("="));
+                space(&mut self.s)?;
+                self.word_space("=")?;
                 self.print_type(&default)
             }
             _ => Ok(())
@@ -2826,12 +2827,12 @@ impl<'a> State<'a> {
             return Ok(())
         }
 
-        try!(space(&mut self.s));
-        try!(self.word_space("where"));
+        space(&mut self.s)?;
+        self.word_space("where")?;
 
         for (i, predicate) in where_clause.predicates.iter().enumerate() {
             if i != 0 {
-                try!(self.word_space(","));
+                self.word_space(",")?;
             }
 
             match *predicate {
@@ -2839,20 +2840,20 @@ impl<'a> State<'a> {
                                                                              ref bounded_ty,
                                                                              ref bounds,
                                                                              ..}) => {
-                    try!(self.print_formal_lifetime_list(bound_lifetimes));
-                    try!(self.print_type(&bounded_ty));
-                    try!(self.print_bounds(":", bounds));
+                    self.print_formal_lifetime_list(bound_lifetimes)?;
+                    self.print_type(&bounded_ty)?;
+                    self.print_bounds(":", bounds)?;
                 }
                 ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
                                                                                ref bounds,
                                                                                ..}) => {
-                    try!(self.print_lifetime_bounds(lifetime, bounds));
+                    self.print_lifetime_bounds(lifetime, bounds)?;
                 }
                 ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => {
-                    try!(self.print_path(path, false, 0, false));
-                    try!(space(&mut self.s));
-                    try!(self.word_space("="));
-                    try!(self.print_type(&ty));
+                    self.print_path(path, false, 0, false)?;
+                    space(&mut self.s)?;
+                    self.word_space("=")?;
+                    self.print_type(&ty)?;
                 }
             }
         }
@@ -2863,39 +2864,39 @@ impl<'a> State<'a> {
     pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> io::Result<()> {
         match vp.node {
             ast::ViewPathSimple(ident, ref path) => {
-                try!(self.print_path(path, false, 0, true));
+                self.print_path(path, false, 0, true)?;
 
                 if path.segments.last().unwrap().identifier.name !=
                         ident.name {
-                    try!(space(&mut self.s));
-                    try!(self.word_space("as"));
-                    try!(self.print_ident(ident));
+                    space(&mut self.s)?;
+                    self.word_space("as")?;
+                    self.print_ident(ident)?;
                 }
 
                 Ok(())
             }
 
             ast::ViewPathGlob(ref path) => {
-                try!(self.print_path(path, false, 0, true));
+                self.print_path(path, false, 0, true)?;
                 word(&mut self.s, "::*")
             }
 
             ast::ViewPathList(ref path, ref idents) => {
                 if path.segments.is_empty() {
-                    try!(word(&mut self.s, "{"));
+                    word(&mut self.s, "{")?;
                 } else {
-                    try!(self.print_path(path, false, 0, true));
-                    try!(word(&mut self.s, "::{"));
+                    self.print_path(path, false, 0, true)?;
+                    word(&mut self.s, "::{")?;
                 }
-                try!(self.commasep(Inconsistent, &idents[..], |s, w| {
-                    try!(s.print_ident(w.node.name));
+                self.commasep(Inconsistent, &idents[..], |s, w| {
+                    s.print_ident(w.node.name)?;
                     if let Some(ident) = w.node.rename {
-                        try!(space(&mut s.s));
-                        try!(s.word_space("as"));
-                        try!(s.print_ident(ident));
+                        space(&mut s.s)?;
+                        s.word_space("as")?;
+                        s.print_ident(ident)?;
                     }
                     Ok(())
-                }));
+                })?;
                 word(&mut self.s, "}")
             }
         }
@@ -2910,17 +2911,17 @@ impl<'a> State<'a> {
     }
 
     pub fn print_mt(&mut self, mt: &ast::MutTy) -> io::Result<()> {
-        try!(self.print_mutability(mt.mutbl));
+        self.print_mutability(mt.mutbl)?;
         self.print_type(&mt.ty)
     }
 
     pub fn print_arg(&mut self, input: &ast::Arg, is_closure: bool) -> io::Result<()> {
-        try!(self.ibox(INDENT_UNIT));
+        self.ibox(INDENT_UNIT)?;
         match input.ty.node {
-            ast::TyKind::Infer if is_closure => try!(self.print_pat(&input.pat)),
+            ast::TyKind::Infer if is_closure => self.print_pat(&input.pat)?,
             _ => {
                 if let Some(eself) = input.to_self() {
-                    try!(self.print_explicit_self(&eself));
+                    self.print_explicit_self(&eself)?;
                 } else {
                     let invalid = if let PatKind::Ident(_, ident, _) = input.pat.node {
                         ident.node.name == keywords::Invalid.name()
@@ -2928,11 +2929,11 @@ impl<'a> State<'a> {
                         false
                     };
                     if !invalid {
-                        try!(self.print_pat(&input.pat));
-                        try!(word(&mut self.s, ":"));
-                        try!(space(&mut self.s));
+                        self.print_pat(&input.pat)?;
+                        word(&mut self.s, ":")?;
+                        space(&mut self.s)?;
                     }
-                    try!(self.print_type(&input.ty));
+                    self.print_type(&input.ty)?;
                 }
             }
         }
@@ -2944,15 +2945,15 @@ impl<'a> State<'a> {
             return Ok(());
         }
 
-        try!(self.space_if_not_bol());
-        try!(self.ibox(INDENT_UNIT));
-        try!(self.word_space("->"));
+        self.space_if_not_bol()?;
+        self.ibox(INDENT_UNIT)?;
+        self.word_space("->")?;
         match decl.output {
             ast::FunctionRetTy::Default(..) => unreachable!(),
             ast::FunctionRetTy::Ty(ref ty) =>
-                try!(self.print_type(&ty))
+                self.print_type(&ty)?
         }
-        try!(self.end());
+        self.end()?;
 
         match decl.output {
             ast::FunctionRetTy::Ty(ref output) => self.maybe_print_comment(output.span.lo),
@@ -2967,10 +2968,10 @@ impl<'a> State<'a> {
                        name: Option<ast::Ident>,
                        generics: &ast::Generics)
                        -> io::Result<()> {
-        try!(self.ibox(INDENT_UNIT));
+        self.ibox(INDENT_UNIT)?;
         if !generics.lifetimes.is_empty() || !generics.ty_params.is_empty() {
-            try!(word(&mut self.s, "for"));
-            try!(self.print_generics(generics));
+            word(&mut self.s, "for")?;
+            self.print_generics(generics)?;
         }
         let generics = ast::Generics {
             lifetimes: Vec::new(),
@@ -2981,13 +2982,13 @@ impl<'a> State<'a> {
             },
             span: syntax_pos::DUMMY_SP,
         };
-        try!(self.print_fn(decl,
+        self.print_fn(decl,
                       unsafety,
                       ast::Constness::NotConst,
                       abi,
                       name,
                       &generics,
-                      &ast::Visibility::Inherited));
+                      &ast::Visibility::Inherited)?;
         self.end()
     }
 
@@ -3015,12 +3016,12 @@ impl<'a> State<'a> {
         // If there aren't any remaining comments, then we need to manually
         // make sure there is a line break at the end.
         if self.next_comment().is_none() {
-            try!(hardbreak(&mut self.s));
+            hardbreak(&mut self.s)?;
         }
         loop {
             match self.next_comment() {
                 Some(ref cmnt) => {
-                    try!(self.print_comment(cmnt));
+                    self.print_comment(cmnt)?;
                     self.cur_cmnt_and_lit.cur_cmnt += 1;
                 }
                 _ => break
@@ -3035,7 +3036,7 @@ impl<'a> State<'a> {
         match opt_abi {
             Some(Abi::Rust) => Ok(()),
             Some(abi) => {
-                try!(self.word_nbsp("extern"));
+                self.word_nbsp("extern")?;
                 self.word_nbsp(&abi.to_string())
             }
             None => Ok(())
@@ -3046,7 +3047,7 @@ impl<'a> State<'a> {
                                 opt_abi: Option<Abi>) -> io::Result<()> {
         match opt_abi {
             Some(abi) => {
-                try!(self.word_nbsp("extern"));
+                self.word_nbsp("extern")?;
                 self.word_nbsp(&abi.to_string())
             }
             None => Ok(())
@@ -3058,18 +3059,18 @@ impl<'a> State<'a> {
                                 constness: ast::Constness,
                                 abi: Abi,
                                 vis: &ast::Visibility) -> io::Result<()> {
-        try!(word(&mut self.s, &visibility_qualified(vis, "")));
+        word(&mut self.s, &visibility_qualified(vis, ""))?;
 
         match constness {
             ast::Constness::NotConst => {}
-            ast::Constness::Const => try!(self.word_nbsp("const"))
+            ast::Constness::Const => self.word_nbsp("const")?
         }
 
-        try!(self.print_unsafety(unsafety));
+        self.print_unsafety(unsafety)?;
 
         if abi != Abi::Rust {
-            try!(self.word_nbsp("extern"));
-            try!(self.word_nbsp(&abi.to_string()));
+            self.word_nbsp("extern")?;
+            self.word_nbsp(&abi.to_string())?;
         }
 
         word(&mut self.s, "fn")
diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs
index 6f02a348f91..64ec460a524 100644
--- a/src/libsyntax_ext/deriving/custom.rs
+++ b/src/libsyntax_ext/deriving/custom.rs
@@ -12,7 +12,7 @@ use std::panic;
 
 use errors::FatalError;
 use proc_macro::{TokenStream, __internal};
-use syntax::ast::{self, ItemKind, Attribute};
+use syntax::ast::{self, ItemKind, Attribute, Mac};
 use syntax::attr::{mark_used, mark_known};
 use syntax::codemap::Span;
 use syntax::ext::base::*;
@@ -28,6 +28,8 @@ impl<'a> Visitor<'a> for MarkAttrs<'a> {
             mark_known(attr);
         }
     }
+
+    fn visit_mac(&mut self, _mac: &Mac) {}
 }
 
 pub struct CustomDerive {
diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs
index 7f187d8d1c1..0d2f4eaaffd 100644
--- a/src/libsyntax_ext/deriving/generic/mod.rs
+++ b/src/libsyntax_ext/deriving/generic/mod.rs
@@ -782,12 +782,14 @@ fn find_repr_type_name(diagnostic: &Handler, type_attrs: &[ast::Attribute]) -> &
                 attr::ReprInt(attr::SignedInt(ast::IntTy::I16)) => "i16",
                 attr::ReprInt(attr::SignedInt(ast::IntTy::I32)) => "i32",
                 attr::ReprInt(attr::SignedInt(ast::IntTy::I64)) => "i64",
+                attr::ReprInt(attr::SignedInt(ast::IntTy::I128)) => "i128",
 
                 attr::ReprInt(attr::UnsignedInt(ast::UintTy::Us)) => "usize",
                 attr::ReprInt(attr::UnsignedInt(ast::UintTy::U8)) => "u8",
                 attr::ReprInt(attr::UnsignedInt(ast::UintTy::U16)) => "u16",
                 attr::ReprInt(attr::UnsignedInt(ast::UintTy::U32)) => "u32",
                 attr::ReprInt(attr::UnsignedInt(ast::UintTy::U64)) => "u64",
+                attr::ReprInt(attr::UnsignedInt(ast::UintTy::U128)) => "u128",
             }
         }
     }
diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs
index 395d966b9f2..68cfc7033ef 100644
--- a/src/libterm/terminfo/mod.rs
+++ b/src/libterm/terminfo/mod.rs
@@ -190,7 +190,7 @@ impl<T: Write + Send> Terminal for TerminfoTerminal<T> {
     fn reset(&mut self) -> io::Result<bool> {
         // are there any terminals that have color/attrs and not sgr0?
         // Try falling back to sgr, then op
-        let cmd = match ["sg0", "sgr", "op"]
+        let cmd = match ["sgr0", "sgr", "op"]
                             .iter()
                             .filter_map(|cap| self.ti.strings.get(*cap))
                             .next() {
diff --git a/src/libunwind/Cargo.toml b/src/libunwind/Cargo.toml
index 36f361b7238..fbd9789d2f5 100644
--- a/src/libunwind/Cargo.toml
+++ b/src/libunwind/Cargo.toml
@@ -9,6 +9,7 @@ name = "unwind"
 path = "lib.rs"
 test = false
 bench = false
+doc = false
 
 [dependencies]
 core = { path = "../libcore" }
diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs
index bbac6c07c57..269c2d65b63 100644
--- a/src/libunwind/libunwind.rs
+++ b/src/libunwind/libunwind.rs
@@ -65,6 +65,9 @@ pub const unwinder_private_data_size: usize = 2;
 #[cfg(target_arch = "s390x")]
 pub const unwinder_private_data_size: usize = 2;
 
+#[cfg(target_arch = "sparc64")]
+pub const unwinder_private_data_size: usize = 2;
+
 #[cfg(target_os = "emscripten")]
 pub const unwinder_private_data_size: usize = 20;
 
diff --git a/src/rustc/libc_shim/Cargo.toml b/src/rustc/libc_shim/Cargo.toml
index e501766fbed..39df3528be3 100644
--- a/src/rustc/libc_shim/Cargo.toml
+++ b/src/rustc/libc_shim/Cargo.toml
@@ -17,6 +17,7 @@ name = "libc"
 path = "../../liblibc/src/lib.rs"
 test = false
 bench = false
+doc = false
 
 [dependencies]
 core = { path = "../../libcore" }
diff --git a/src/rustc/std_shim/Cargo.toml b/src/rustc/std_shim/Cargo.toml
index 18680dc4fd9..1fa91772435 100644
--- a/src/rustc/std_shim/Cargo.toml
+++ b/src/rustc/std_shim/Cargo.toml
@@ -27,6 +27,7 @@ authors = ["The Rust Project Developers"]
 [lib]
 name = "std_shim"
 path = "lib.rs"
+doc = false
 
 [dependencies]
 std = { path = "../../libstd" }
diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp
index c7f426fbfa3..f04251136f4 100644
--- a/src/rustllvm/ArchiveWrapper.cpp
+++ b/src/rustllvm/ArchiveWrapper.cpp
@@ -17,53 +17,55 @@ using namespace llvm;
 using namespace llvm::object;
 
 struct RustArchiveMember {
-  const char *filename;
-  const char *name;
-  Archive::Child child;
+  const char *Filename;
+  const char *Name;
+  Archive::Child Child;
 
-  RustArchiveMember(): filename(NULL), name(NULL),
+  RustArchiveMember()
+      : Filename(nullptr), Name(nullptr),
 #if LLVM_VERSION_GE(3, 8)
-    child(NULL, NULL, NULL)
+        Child(nullptr, nullptr, nullptr)
 #else
-    child(NULL, NULL)
+        Child(nullptr, nullptr)
 #endif
-  {}
+  {
+  }
   ~RustArchiveMember() {}
 };
 
-
 struct RustArchiveIterator {
-    Archive::child_iterator cur;
-    Archive::child_iterator end;
+  bool First;
+  Archive::child_iterator Cur;
+  Archive::child_iterator End;
 #if LLVM_VERSION_GE(3, 9)
-    Error err;
+  Error Err;
 
-    RustArchiveIterator() : err(Error::success()) { }
+  RustArchiveIterator() : First(true), Err(Error::success()) {}
+#else
+  RustArchiveIterator() : First(true) {}
 #endif
 };
 
 enum class LLVMRustArchiveKind {
-    Other,
-    GNU,
-    MIPS64,
-    BSD,
-    COFF,
+  Other,
+  GNU,
+  MIPS64,
+  BSD,
+  COFF,
 };
 
-static Archive::Kind
-from_rust(LLVMRustArchiveKind kind)
-{
-    switch (kind) {
-    case LLVMRustArchiveKind::GNU:
-        return Archive::K_GNU;
-    case LLVMRustArchiveKind::MIPS64:
-        return Archive::K_MIPS64;
-    case LLVMRustArchiveKind::BSD:
-        return Archive::K_BSD;
-    case LLVMRustArchiveKind::COFF:
-        return Archive::K_COFF;
-    default:
-      llvm_unreachable("Bad ArchiveKind.");
+static Archive::Kind fromRust(LLVMRustArchiveKind Kind) {
+  switch (Kind) {
+  case LLVMRustArchiveKind::GNU:
+    return Archive::K_GNU;
+  case LLVMRustArchiveKind::MIPS64:
+    return Archive::K_MIPS64;
+  case LLVMRustArchiveKind::BSD:
+    return Archive::K_BSD;
+  case LLVMRustArchiveKind::COFF:
+    return Archive::K_COFF;
+  default:
+    llvm_unreachable("Bad ArchiveKind.");
   }
 }
 
@@ -73,189 +75,199 @@ typedef Archive::Child *LLVMRustArchiveChildRef;
 typedef Archive::Child const *LLVMRustArchiveChildConstRef;
 typedef RustArchiveIterator *LLVMRustArchiveIteratorRef;
 
-extern "C" LLVMRustArchiveRef
-LLVMRustOpenArchive(char *path) {
-    ErrorOr<std::unique_ptr<MemoryBuffer>> buf_or = MemoryBuffer::getFile(path,
-                                                                          -1,
-                                                                          false);
-    if (!buf_or) {
-        LLVMRustSetLastError(buf_or.getError().message().c_str());
-        return nullptr;
-    }
+extern "C" LLVMRustArchiveRef LLVMRustOpenArchive(char *Path) {
+  ErrorOr<std::unique_ptr<MemoryBuffer>> BufOr =
+      MemoryBuffer::getFile(Path, -1, false);
+  if (!BufOr) {
+    LLVMRustSetLastError(BufOr.getError().message().c_str());
+    return nullptr;
+  }
 
 #if LLVM_VERSION_LE(3, 8)
-    ErrorOr<std::unique_ptr<Archive>> archive_or =
+  ErrorOr<std::unique_ptr<Archive>> ArchiveOr =
 #else
-    Expected<std::unique_ptr<Archive>> archive_or =
+  Expected<std::unique_ptr<Archive>> ArchiveOr =
 #endif
-        Archive::create(buf_or.get()->getMemBufferRef());
+      Archive::create(BufOr.get()->getMemBufferRef());
 
-    if (!archive_or) {
+  if (!ArchiveOr) {
 #if LLVM_VERSION_LE(3, 8)
-        LLVMRustSetLastError(archive_or.getError().message().c_str());
+    LLVMRustSetLastError(ArchiveOr.getError().message().c_str());
 #else
-        LLVMRustSetLastError(toString(archive_or.takeError()).c_str());
+    LLVMRustSetLastError(toString(ArchiveOr.takeError()).c_str());
 #endif
-        return nullptr;
-    }
+    return nullptr;
+  }
 
-    OwningBinary<Archive> *ret = new OwningBinary<Archive>(
-            std::move(archive_or.get()), std::move(buf_or.get()));
+  OwningBinary<Archive> *Ret = new OwningBinary<Archive>(
+      std::move(ArchiveOr.get()), std::move(BufOr.get()));
 
-    return ret;
+  return Ret;
 }
 
-extern "C" void
-LLVMRustDestroyArchive(LLVMRustArchiveRef ar) {
-    delete ar;
+extern "C" void LLVMRustDestroyArchive(LLVMRustArchiveRef RustArchive) {
+  delete RustArchive;
 }
 
 extern "C" LLVMRustArchiveIteratorRef
-LLVMRustArchiveIteratorNew(LLVMRustArchiveRef ra) {
-    Archive *ar = ra->getBinary();
-    RustArchiveIterator *rai = new RustArchiveIterator();
+LLVMRustArchiveIteratorNew(LLVMRustArchiveRef RustArchive) {
+  Archive *Archive = RustArchive->getBinary();
+  RustArchiveIterator *RAI = new RustArchiveIterator();
 #if LLVM_VERSION_LE(3, 8)
-    rai->cur = ar->child_begin();
+  RAI->Cur = Archive->child_begin();
 #else
-    rai->cur = ar->child_begin(rai->err);
-    if (rai->err) {
-        LLVMRustSetLastError(toString(std::move(rai->err)).c_str());
-        return NULL;
-    }
+  RAI->Cur = Archive->child_begin(RAI->Err);
+  if (RAI->Err) {
+    LLVMRustSetLastError(toString(std::move(RAI->Err)).c_str());
+    delete RAI;
+    return nullptr;
+  }
 #endif
-    rai->end = ar->child_end();
-    return rai;
+  RAI->End = Archive->child_end();
+  return RAI;
 }
 
 extern "C" LLVMRustArchiveChildConstRef
-LLVMRustArchiveIteratorNext(LLVMRustArchiveIteratorRef rai) {
+LLVMRustArchiveIteratorNext(LLVMRustArchiveIteratorRef RAI) {
+  if (RAI->Cur == RAI->End)
+    return nullptr;
+
+  // Advancing the iterator validates the next child, and this can
+  // uncover an error. LLVM requires that we check all Errors,
+  // so we only advance the iterator if we actually need to fetch
+  // the next child.
+  // This means we must not advance the iterator in the *first* call,
+  // but instead advance it *before* fetching the child in all later calls.
+  if (!RAI->First) {
+    ++RAI->Cur;
 #if LLVM_VERSION_GE(3, 9)
-    if (rai->err) {
-        LLVMRustSetLastError(toString(std::move(rai->err)).c_str());
-        return NULL;
+    if (RAI->Err) {
+      LLVMRustSetLastError(toString(std::move(RAI->Err)).c_str());
+      return nullptr;
     }
 #endif
-    if (rai->cur == rai->end)
-        return NULL;
+  } else {
+    RAI->First = false;
+  }
+
+  if (RAI->Cur == RAI->End)
+    return nullptr;
+
 #if LLVM_VERSION_EQ(3, 8)
-    const ErrorOr<Archive::Child>* cur = rai->cur.operator->();
-    if (!*cur) {
-        LLVMRustSetLastError(cur->getError().message().c_str());
-        return NULL;
-    }
-    const Archive::Child &child = cur->get();
+  const ErrorOr<Archive::Child> *Cur = RAI->Cur.operator->();
+  if (!*Cur) {
+    LLVMRustSetLastError(Cur->getError().message().c_str());
+    return nullptr;
+  }
+  const Archive::Child &Child = Cur->get();
 #else
-    const Archive::Child &child = *rai->cur.operator->();
+  const Archive::Child &Child = *RAI->Cur.operator->();
 #endif
-    Archive::Child *ret = new Archive::Child(child);
+  Archive::Child *Ret = new Archive::Child(Child);
 
-    ++rai->cur;
-    return ret;
+  return Ret;
 }
 
-extern "C" void
-LLVMRustArchiveChildFree(LLVMRustArchiveChildRef child) {
-    delete child;
+extern "C" void LLVMRustArchiveChildFree(LLVMRustArchiveChildRef Child) {
+  delete Child;
 }
 
-extern "C" void
-LLVMRustArchiveIteratorFree(LLVMRustArchiveIteratorRef rai) {
-    delete rai;
+extern "C" void LLVMRustArchiveIteratorFree(LLVMRustArchiveIteratorRef RAI) {
+  delete RAI;
 }
 
-extern "C" const char*
-LLVMRustArchiveChildName(LLVMRustArchiveChildConstRef child, size_t *size) {
+extern "C" const char *
+LLVMRustArchiveChildName(LLVMRustArchiveChildConstRef Child, size_t *Size) {
 #if LLVM_VERSION_GE(4, 0)
-    Expected<StringRef> name_or_err = child->getName();
-    if (!name_or_err) {
-        // rustc_llvm currently doesn't use this error string, but it might be useful
-        // in the future, and in the mean time this tells LLVM that the error was
-        // not ignored and that it shouldn't abort the process.
-        LLVMRustSetLastError(toString(name_or_err.takeError()).c_str());
-        return NULL;
-    }
+  Expected<StringRef> NameOrErr = Child->getName();
+  if (!NameOrErr) {
+    // rustc_llvm currently doesn't use this error string, but it might be
+    // useful in the future, and in the mean time this tells LLVM that the
+    // error was not ignored and that it shouldn't abort the process.
+    LLVMRustSetLastError(toString(NameOrErr.takeError()).c_str());
+    return nullptr;
+  }
 #else
-    ErrorOr<StringRef> name_or_err = child->getName();
-    if (name_or_err.getError())
-        return NULL;
+  ErrorOr<StringRef> NameOrErr = Child->getName();
+  if (NameOrErr.getError())
+    return nullptr;
 #endif
-    StringRef name = name_or_err.get();
-    *size = name.size();
-    return name.data();
+  StringRef Name = NameOrErr.get();
+  *Size = Name.size();
+  return Name.data();
 }
 
-extern "C" const char*
-LLVMRustArchiveChildData(LLVMRustArchiveChildRef child, size_t *size) {
-    StringRef buf;
+extern "C" const char *LLVMRustArchiveChildData(LLVMRustArchiveChildRef Child,
+                                                size_t *Size) {
+  StringRef Buf;
 #if LLVM_VERSION_GE(4, 0)
-    Expected<StringRef> buf_or_err = child->getBuffer();
-    if (!buf_or_err) {
-      LLVMRustSetLastError(toString(buf_or_err.takeError()).c_str());
-      return NULL;
-    }
+  Expected<StringRef> BufOrErr = Child->getBuffer();
+  if (!BufOrErr) {
+    LLVMRustSetLastError(toString(BufOrErr.takeError()).c_str());
+    return nullptr;
+  }
 #else
-    ErrorOr<StringRef> buf_or_err = child->getBuffer();
-    if (buf_or_err.getError()) {
-      LLVMRustSetLastError(buf_or_err.getError().message().c_str());
-      return NULL;
-    }
+  ErrorOr<StringRef> BufOrErr = Child->getBuffer();
+  if (BufOrErr.getError()) {
+    LLVMRustSetLastError(BufOrErr.getError().message().c_str());
+    return nullptr;
+  }
 #endif
-    buf = buf_or_err.get();
-    *size = buf.size();
-    return buf.data();
+  Buf = BufOrErr.get();
+  *Size = Buf.size();
+  return Buf.data();
 }
 
 extern "C" LLVMRustArchiveMemberRef
 LLVMRustArchiveMemberNew(char *Filename, char *Name,
-			 LLVMRustArchiveChildRef child) {
-    RustArchiveMember *Member = new RustArchiveMember;
-    Member->filename = Filename;
-    Member->name = Name;
-    if (child)
-        Member->child = *child;
-    return Member;
+                         LLVMRustArchiveChildRef Child) {
+  RustArchiveMember *Member = new RustArchiveMember;
+  Member->Filename = Filename;
+  Member->Name = Name;
+  if (Child)
+    Member->Child = *Child;
+  return Member;
 }
 
-extern "C" void
-LLVMRustArchiveMemberFree(LLVMRustArchiveMemberRef Member) {
-    delete Member;
+extern "C" void LLVMRustArchiveMemberFree(LLVMRustArchiveMemberRef Member) {
+  delete Member;
 }
 
 extern "C" LLVMRustResult
-LLVMRustWriteArchive(char *Dst,
-                     size_t NumMembers,
+LLVMRustWriteArchive(char *Dst, size_t NumMembers,
                      const LLVMRustArchiveMemberRef *NewMembers,
-                     bool WriteSymbtab,
-                     LLVMRustArchiveKind rust_kind) {
+                     bool WriteSymbtab, LLVMRustArchiveKind RustKind) {
 
 #if LLVM_VERSION_LE(3, 8)
   std::vector<NewArchiveIterator> Members;
 #else
   std::vector<NewArchiveMember> Members;
 #endif
-  auto Kind = from_rust(rust_kind);
+  auto Kind = fromRust(RustKind);
 
-  for (size_t i = 0; i < NumMembers; i++) {
-    auto Member = NewMembers[i];
-    assert(Member->name);
-    if (Member->filename) {
+  for (size_t I = 0; I < NumMembers; I++) {
+    auto Member = NewMembers[I];
+    assert(Member->Name);
+    if (Member->Filename) {
 #if LLVM_VERSION_GE(3, 9)
-      Expected<NewArchiveMember> MOrErr = NewArchiveMember::getFile(Member->filename, true);
+      Expected<NewArchiveMember> MOrErr =
+          NewArchiveMember::getFile(Member->Filename, true);
       if (!MOrErr) {
         LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
         return LLVMRustResult::Failure;
       }
       Members.push_back(std::move(*MOrErr));
 #elif LLVM_VERSION_EQ(3, 8)
-      Members.push_back(NewArchiveIterator(Member->filename));
+      Members.push_back(NewArchiveIterator(Member->Filename));
 #else
-      Members.push_back(NewArchiveIterator(Member->filename, Member->name));
+      Members.push_back(NewArchiveIterator(Member->Filename, Member->Name));
 #endif
     } else {
 #if LLVM_VERSION_LE(3, 8)
-      Members.push_back(NewArchiveIterator(Member->child, Member->name));
+      Members.push_back(NewArchiveIterator(Member->Child, Member->Name));
 #else
-      Expected<NewArchiveMember> MOrErr = NewArchiveMember::getOldMember(Member->child, true);
+      Expected<NewArchiveMember> MOrErr =
+          NewArchiveMember::getOldMember(Member->Child, true);
       if (!MOrErr) {
         LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
         return LLVMRustResult::Failure;
@@ -265,12 +277,12 @@ LLVMRustWriteArchive(char *Dst,
     }
   }
 #if LLVM_VERSION_GE(3, 8)
-  auto pair = writeArchive(Dst, Members, WriteSymbtab, Kind, true, false);
+  auto Pair = writeArchive(Dst, Members, WriteSymbtab, Kind, true, false);
 #else
-  auto pair = writeArchive(Dst, Members, WriteSymbtab, Kind, true);
+  auto Pair = writeArchive(Dst, Members, WriteSymbtab, Kind, true);
 #endif
-  if (!pair.second)
+  if (!Pair.second)
     return LLVMRustResult::Success;
-  LLVMRustSetLastError(pair.second.message().c_str());
+  LLVMRustSetLastError(Pair.second.message().c_str());
   return LLVMRustResult::Failure;
 }
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index c45d1c2d088..c410a6b1349 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -12,12 +12,12 @@
 
 #include "rustllvm.h"
 
-#include "llvm/Support/CBindingWrapping.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Host.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/IR/AutoUpgrade.h"
+#include "llvm/Support/CBindingWrapping.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Host.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetSubtargetInfo.h"
 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
@@ -38,10 +38,10 @@ typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef;
 
 DEFINE_STDCXX_CONVERSION_FUNCTIONS(Pass, LLVMPassRef)
 DEFINE_STDCXX_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
-DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBuilder, LLVMPassManagerBuilderRef)
+DEFINE_STDCXX_CONVERSION_FUNCTIONS(PassManagerBuilder,
+                                   LLVMPassManagerBuilderRef)
 
-extern "C" void
-LLVMInitializePasses() {
+extern "C" void LLVMInitializePasses() {
   PassRegistry &Registry = *PassRegistry::getPassRegistry();
   initializeCore(Registry);
   initializeCodeGen(Registry);
@@ -64,44 +64,39 @@ enum class LLVMRustPassKind {
   Module,
 };
 
-static LLVMRustPassKind
-to_rust(PassKind kind)
-{
-  switch (kind) {
+static LLVMRustPassKind toRust(PassKind Kind) {
+  switch (Kind) {
   case PT_Function:
-      return LLVMRustPassKind::Function;
+    return LLVMRustPassKind::Function;
   case PT_Module:
-      return LLVMRustPassKind::Module;
+    return LLVMRustPassKind::Module;
   default:
-      return LLVMRustPassKind::Other;
+    return LLVMRustPassKind::Other;
   }
 }
 
-extern "C" LLVMPassRef
-LLVMRustFindAndCreatePass(const char *PassName) {
-    StringRef SR(PassName);
-    PassRegistry *PR = PassRegistry::getPassRegistry();
+extern "C" LLVMPassRef LLVMRustFindAndCreatePass(const char *PassName) {
+  StringRef SR(PassName);
+  PassRegistry *PR = PassRegistry::getPassRegistry();
 
-    const PassInfo *PI = PR->getPassInfo(SR);
-    if (PI) {
-      return wrap(PI->createPass());
-    }
-    return NULL;
+  const PassInfo *PI = PR->getPassInfo(SR);
+  if (PI) {
+    return wrap(PI->createPass());
+  }
+  return nullptr;
 }
 
-extern "C" LLVMRustPassKind
-LLVMRustPassKind(LLVMPassRef rust_pass) {
-    assert(rust_pass);
-    Pass *pass = unwrap(rust_pass);
-    return to_rust(pass->getPassKind());
+extern "C" LLVMRustPassKind LLVMRustPassKind(LLVMPassRef RustPass) {
+  assert(RustPass);
+  Pass *Pass = unwrap(RustPass);
+  return toRust(Pass->getPassKind());
 }
 
-extern "C" void
-LLVMRustAddPass(LLVMPassManagerRef PM, LLVMPassRef rust_pass) {
-    assert(rust_pass);
-    Pass *pass = unwrap(rust_pass);
-    PassManagerBase *pm = unwrap(PM);
-    pm->add(pass);
+extern "C" void LLVMRustAddPass(LLVMPassManagerRef PMR, LLVMPassRef RustPass) {
+  assert(RustPass);
+  Pass *Pass = unwrap(RustPass);
+  PassManagerBase *PMB = unwrap(PMR);
+  PMB->add(Pass);
 }
 
 #ifdef LLVM_COMPONENT_X86
@@ -146,100 +141,101 @@ LLVMRustAddPass(LLVMPassManagerRef PM, LLVMPassRef rust_pass) {
 #define SUBTARGET_MSP430
 #endif
 
-#define GEN_SUBTARGETS    \
-        SUBTARGET_X86     \
-        SUBTARGET_ARM     \
-        SUBTARGET_AARCH64 \
-        SUBTARGET_MIPS    \
-        SUBTARGET_PPC     \
-        SUBTARGET_SYSTEMZ \
-        SUBTARGET_MSP430
-
-#define SUBTARGET(x) namespace llvm {                \
-    extern const SubtargetFeatureKV x##FeatureKV[];  \
-    extern const SubtargetFeatureKV x##SubTypeKV[];  \
+#ifdef LLVM_COMPONENT_SPARC
+#define SUBTARGET_SPARC SUBTARGET(Sparc)
+#else
+#define SUBTARGET_SPARC
+#endif
+
+#define GEN_SUBTARGETS                                                         \
+  SUBTARGET_X86                                                                \
+  SUBTARGET_ARM                                                                \
+  SUBTARGET_AARCH64                                                            \
+  SUBTARGET_MIPS                                                               \
+  SUBTARGET_PPC                                                                \
+  SUBTARGET_SYSTEMZ                                                            \
+  SUBTARGET_MSP430                                                             \
+  SUBTARGET_SPARC
+
+#define SUBTARGET(x)                                                           \
+  namespace llvm {                                                             \
+  extern const SubtargetFeatureKV x##FeatureKV[];                              \
+  extern const SubtargetFeatureKV x##SubTypeKV[];                              \
   }
 
 GEN_SUBTARGETS
 #undef SUBTARGET
 
-extern "C" bool
-LLVMRustHasFeature(LLVMTargetMachineRef TM,
-		   const char *feature) {
-    TargetMachine *Target = unwrap(TM);
-    const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
-    const FeatureBitset &Bits = MCInfo->getFeatureBits();
-    const llvm::SubtargetFeatureKV *FeatureEntry;
-
-#define SUBTARGET(x)                                        \
-    if (MCInfo->isCPUStringValid(x##SubTypeKV[0].Key)) {    \
-        FeatureEntry = x##FeatureKV;                       \
-    } else
-
-    GEN_SUBTARGETS {
-        return false;
-    }
+extern "C" bool LLVMRustHasFeature(LLVMTargetMachineRef TM,
+                                   const char *Feature) {
+  TargetMachine *Target = unwrap(TM);
+  const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
+  const FeatureBitset &Bits = MCInfo->getFeatureBits();
+  const llvm::SubtargetFeatureKV *FeatureEntry;
+
+#define SUBTARGET(x)                                                           \
+  if (MCInfo->isCPUStringValid(x##SubTypeKV[0].Key)) {                         \
+    FeatureEntry = x##FeatureKV;                                               \
+  } else
+
+  GEN_SUBTARGETS { return false; }
 #undef SUBTARGET
 
-    while (strcmp(feature, FeatureEntry->Key) != 0)
-        FeatureEntry++;
+  while (strcmp(Feature, FeatureEntry->Key) != 0)
+    FeatureEntry++;
 
-    return (Bits & FeatureEntry->Value) == FeatureEntry->Value;
+  return (Bits & FeatureEntry->Value) == FeatureEntry->Value;
 }
 
 enum class LLVMRustCodeModel {
-    Other,
-    Default,
-    JITDefault,
-    Small,
-    Kernel,
-    Medium,
-    Large,
+  Other,
+  Default,
+  JITDefault,
+  Small,
+  Kernel,
+  Medium,
+  Large,
 };
 
-static CodeModel::Model
-from_rust(LLVMRustCodeModel model)
-{
-    switch (model) {
-    case LLVMRustCodeModel::Default:
-        return CodeModel::Default;
-    case LLVMRustCodeModel::JITDefault:
-        return CodeModel::JITDefault;
-    case LLVMRustCodeModel::Small:
-        return CodeModel::Small;
-    case LLVMRustCodeModel::Kernel:
-        return CodeModel::Kernel;
-    case LLVMRustCodeModel::Medium:
-        return CodeModel::Medium;
-    case LLVMRustCodeModel::Large:
-        return CodeModel::Large;
-    default:
-        llvm_unreachable("Bad CodeModel.");
+static CodeModel::Model fromRust(LLVMRustCodeModel Model) {
+  switch (Model) {
+  case LLVMRustCodeModel::Default:
+    return CodeModel::Default;
+  case LLVMRustCodeModel::JITDefault:
+    return CodeModel::JITDefault;
+  case LLVMRustCodeModel::Small:
+    return CodeModel::Small;
+  case LLVMRustCodeModel::Kernel:
+    return CodeModel::Kernel;
+  case LLVMRustCodeModel::Medium:
+    return CodeModel::Medium;
+  case LLVMRustCodeModel::Large:
+    return CodeModel::Large;
+  default:
+    llvm_unreachable("Bad CodeModel.");
   }
 }
 
 enum class LLVMRustCodeGenOptLevel {
-    Other,
-    None,
-    Less,
-    Default,
-    Aggressive,
+  Other,
+  None,
+  Less,
+  Default,
+  Aggressive,
 };
 
-static CodeGenOpt::Level
-from_rust(LLVMRustCodeGenOptLevel level)
-{
-    switch (level) {
-    case LLVMRustCodeGenOptLevel::None:
-        return CodeGenOpt::None;
-    case LLVMRustCodeGenOptLevel::Less:
-        return CodeGenOpt::Less;
-    case LLVMRustCodeGenOptLevel::Default:
-        return CodeGenOpt::Default;
-    case LLVMRustCodeGenOptLevel::Aggressive:
-        return CodeGenOpt::Aggressive;
-    default:
-        llvm_unreachable("Bad CodeGenOptLevel.");
+static CodeGenOpt::Level fromRust(LLVMRustCodeGenOptLevel Level) {
+  switch (Level) {
+  case LLVMRustCodeGenOptLevel::None:
+    return CodeGenOpt::None;
+  case LLVMRustCodeGenOptLevel::Less:
+    return CodeGenOpt::Less;
+  case LLVMRustCodeGenOptLevel::Default:
+    return CodeGenOpt::Default;
+  case LLVMRustCodeGenOptLevel::Aggressive:
+    return CodeGenOpt::Aggressive;
+  default:
+    llvm_unreachable("Bad CodeGenOptLevel.");
   }
 }
 
@@ -253,241 +249,216 @@ static size_t getLongestEntryLength(ArrayRef<SubtargetFeatureKV> Table) {
   return MaxLen;
 }
 
-extern "C" void
-LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) {
-    const TargetMachine *Target = unwrap(TM);
-    const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
-    const ArrayRef<SubtargetFeatureKV> CPUTable = MCInfo->getCPUTable();
-    unsigned MaxCPULen = getLongestEntryLength(CPUTable);
-
-    printf("Available CPUs for this target:\n");
-    for (auto &CPU : CPUTable)
-        printf("    %-*s - %s.\n", MaxCPULen, CPU.Key, CPU.Desc);
-    printf("\n");
+extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM) {
+  const TargetMachine *Target = unwrap(TM);
+  const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
+  const ArrayRef<SubtargetFeatureKV> CPUTable = MCInfo->getCPUTable();
+  unsigned MaxCPULen = getLongestEntryLength(CPUTable);
+
+  printf("Available CPUs for this target:\n");
+  for (auto &CPU : CPUTable)
+    printf("    %-*s - %s.\n", MaxCPULen, CPU.Key, CPU.Desc);
+  printf("\n");
 }
 
-extern "C" void
-LLVMRustPrintTargetFeatures(LLVMTargetMachineRef TM) {
-    const TargetMachine *Target = unwrap(TM);
-    const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
-    const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
-    unsigned MaxFeatLen = getLongestEntryLength(FeatTable);
-
-    printf("Available features for this target:\n");
-    for (auto &Feature : FeatTable)
-        printf("    %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
-    printf("\n");
-
-    printf("Use +feature to enable a feature, or -feature to disable it.\n"
-            "For example, rustc -C -target-cpu=mycpu -C target-feature=+feature1,-feature2\n\n");
+extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef TM) {
+  const TargetMachine *Target = unwrap(TM);
+  const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
+  const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
+  unsigned MaxFeatLen = getLongestEntryLength(FeatTable);
+
+  printf("Available features for this target:\n");
+  for (auto &Feature : FeatTable)
+    printf("    %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
+  printf("\n");
+
+  printf("Use +feature to enable a feature, or -feature to disable it.\n"
+         "For example, rustc -C -target-cpu=mycpu -C "
+         "target-feature=+feature1,-feature2\n\n");
 }
 
 #else
 
-extern "C" void
-LLVMRustPrintTargetCPUs(LLVMTargetMachineRef) {
-    printf("Target CPU help is not supported by this LLVM version.\n\n");
+extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef) {
+  printf("Target CPU help is not supported by this LLVM version.\n\n");
 }
 
-extern "C" void
-LLVMRustPrintTargetFeatures(LLVMTargetMachineRef) {
-    printf("Target features help is not supported by this LLVM version.\n\n");
+extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef) {
+  printf("Target features help is not supported by this LLVM version.\n\n");
 }
 #endif
 
-extern "C" LLVMTargetMachineRef
-LLVMRustCreateTargetMachine(const char *triple,
-                            const char *cpu,
-                            const char *feature,
-                            LLVMRustCodeModel rust_CM,
-                            LLVMRelocMode Reloc,
-                            LLVMRustCodeGenOptLevel rust_OptLevel,
-                            bool UseSoftFloat,
-                            bool PositionIndependentExecutable,
-                            bool FunctionSections,
-                            bool DataSections) {
+extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
+    const char *TripleStr, const char *CPU, const char *Feature,
+    LLVMRustCodeModel RustCM, LLVMRelocMode Reloc,
+    LLVMRustCodeGenOptLevel RustOptLevel, bool UseSoftFloat,
+    bool PositionIndependentExecutable, bool FunctionSections,
+    bool DataSections) {
 
 #if LLVM_VERSION_LE(3, 8)
-    Reloc::Model RM;
+  Reloc::Model RM;
 #else
-    Optional<Reloc::Model> RM;
+  Optional<Reloc::Model> RM;
 #endif
-    auto CM = from_rust(rust_CM);
-    auto OptLevel = from_rust(rust_OptLevel);
-
-    switch (Reloc){
-        case LLVMRelocStatic:
-            RM = Reloc::Static;
-            break;
-        case LLVMRelocPIC:
-            RM = Reloc::PIC_;
-            break;
-        case LLVMRelocDynamicNoPic:
-            RM = Reloc::DynamicNoPIC;
-            break;
-        default:
+  auto CM = fromRust(RustCM);
+  auto OptLevel = fromRust(RustOptLevel);
+
+  switch (Reloc) {
+  case LLVMRelocStatic:
+    RM = Reloc::Static;
+    break;
+  case LLVMRelocPIC:
+    RM = Reloc::PIC_;
+    break;
+  case LLVMRelocDynamicNoPic:
+    RM = Reloc::DynamicNoPIC;
+    break;
+  default:
 #if LLVM_VERSION_LE(3, 8)
-            RM = Reloc::Default;
+    RM = Reloc::Default;
 #endif
-            break;
-    }
+    break;
+  }
 
-    std::string Error;
-    Triple Trip(Triple::normalize(triple));
-    const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Trip.getTriple(),
-                                                                 Error);
-    if (TheTarget == NULL) {
-        LLVMRustSetLastError(Error.c_str());
-        return NULL;
-    }
+  std::string Error;
+  Triple Trip(Triple::normalize(TripleStr));
+  const llvm::Target *TheTarget =
+      TargetRegistry::lookupTarget(Trip.getTriple(), Error);
+  if (TheTarget == nullptr) {
+    LLVMRustSetLastError(Error.c_str());
+    return nullptr;
+  }
 
-    StringRef real_cpu = cpu;
-    if (real_cpu == "native") {
-        real_cpu = sys::getHostCPUName();
-    }
+  StringRef RealCPU = CPU;
+  if (RealCPU == "native") {
+    RealCPU = sys::getHostCPUName();
+  }
 
-    TargetOptions Options;
+  TargetOptions Options;
 #if LLVM_VERSION_LE(3, 8)
-    Options.PositionIndependentExecutable = PositionIndependentExecutable;
+  Options.PositionIndependentExecutable = PositionIndependentExecutable;
 #endif
 
-    Options.FloatABIType = FloatABI::Default;
-    if (UseSoftFloat) {
-        Options.FloatABIType = FloatABI::Soft;
-    }
-    Options.DataSections = DataSections;
-    Options.FunctionSections = FunctionSections;
-
-    TargetMachine *TM = TheTarget->createTargetMachine(Trip.getTriple(),
-                                                       real_cpu,
-                                                       feature,
-                                                       Options,
-                                                       RM,
-                                                       CM,
-                                                       OptLevel);
-    return wrap(TM);
+  Options.FloatABIType = FloatABI::Default;
+  if (UseSoftFloat) {
+    Options.FloatABIType = FloatABI::Soft;
+  }
+  Options.DataSections = DataSections;
+  Options.FunctionSections = FunctionSections;
+
+  TargetMachine *TM = TheTarget->createTargetMachine(
+      Trip.getTriple(), RealCPU, Feature, Options, RM, CM, OptLevel);
+  return wrap(TM);
 }
 
-extern "C" void
-LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
-    delete unwrap(TM);
+extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
+  delete unwrap(TM);
 }
 
 // Unfortunately, LLVM doesn't expose a C API to add the corresponding analysis
 // passes for a target to a pass manager. We export that functionality through
 // this function.
-extern "C" void
-LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM,
-                          LLVMPassManagerRef PMR,
-                          LLVMModuleRef M) {
-    PassManagerBase *PM = unwrap(PMR);
-    PM->add(createTargetTransformInfoWrapperPass(
-          unwrap(TM)->getTargetIRAnalysis()));
+extern "C" void LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM,
+                                          LLVMPassManagerRef PMR,
+                                          LLVMModuleRef M) {
+  PassManagerBase *PM = unwrap(PMR);
+  PM->add(
+      createTargetTransformInfoWrapperPass(unwrap(TM)->getTargetIRAnalysis()));
 }
 
-extern "C" void
-LLVMRustConfigurePassManagerBuilder(LLVMPassManagerBuilderRef PMB,
-				    LLVMRustCodeGenOptLevel OptLevel,
-                                    bool MergeFunctions,
-                                    bool SLPVectorize,
-                                    bool LoopVectorize) {
-    // Ignore mergefunc for now as enabling it causes crashes.
-    //unwrap(PMB)->MergeFunctions = MergeFunctions;
-    unwrap(PMB)->SLPVectorize = SLPVectorize;
-    unwrap(PMB)->OptLevel = from_rust(OptLevel);
-    unwrap(PMB)->LoopVectorize = LoopVectorize;
+extern "C" void LLVMRustConfigurePassManagerBuilder(
+    LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel,
+    bool MergeFunctions, bool SLPVectorize, bool LoopVectorize) {
+  // Ignore mergefunc for now as enabling it causes crashes.
+  // unwrap(PMBR)->MergeFunctions = MergeFunctions;
+  unwrap(PMBR)->SLPVectorize = SLPVectorize;
+  unwrap(PMBR)->OptLevel = fromRust(OptLevel);
+  unwrap(PMBR)->LoopVectorize = LoopVectorize;
 }
 
 // Unfortunately, the LLVM C API doesn't provide a way to set the `LibraryInfo`
 // field of a PassManagerBuilder, we expose our own method of doing so.
-extern "C" void
-LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMB,
-                              LLVMModuleRef M,
-                              bool DisableSimplifyLibCalls) {
-    Triple TargetTriple(unwrap(M)->getTargetTriple());
-    TargetLibraryInfoImpl *TLI = new TargetLibraryInfoImpl(TargetTriple);
-    if (DisableSimplifyLibCalls)
-      TLI->disableAllFunctions();
-    unwrap(PMB)->LibraryInfo = TLI;
+extern "C" void LLVMRustAddBuilderLibraryInfo(LLVMPassManagerBuilderRef PMBR,
+                                              LLVMModuleRef M,
+                                              bool DisableSimplifyLibCalls) {
+  Triple TargetTriple(unwrap(M)->getTargetTriple());
+  TargetLibraryInfoImpl *TLI = new TargetLibraryInfoImpl(TargetTriple);
+  if (DisableSimplifyLibCalls)
+    TLI->disableAllFunctions();
+  unwrap(PMBR)->LibraryInfo = TLI;
 }
 
 // Unfortunately, the LLVM C API doesn't provide a way to create the
 // TargetLibraryInfo pass, so we use this method to do so.
-extern "C" void
-LLVMRustAddLibraryInfo(LLVMPassManagerRef PMB,
-                       LLVMModuleRef M,
-                       bool DisableSimplifyLibCalls) {
-    Triple TargetTriple(unwrap(M)->getTargetTriple());
-    TargetLibraryInfoImpl TLII(TargetTriple);
-    if (DisableSimplifyLibCalls)
-      TLII.disableAllFunctions();
-    unwrap(PMB)->add(new TargetLibraryInfoWrapperPass(TLII));
+extern "C" void LLVMRustAddLibraryInfo(LLVMPassManagerRef PMR, LLVMModuleRef M,
+                                       bool DisableSimplifyLibCalls) {
+  Triple TargetTriple(unwrap(M)->getTargetTriple());
+  TargetLibraryInfoImpl TLII(TargetTriple);
+  if (DisableSimplifyLibCalls)
+    TLII.disableAllFunctions();
+  unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII));
 }
 
 // Unfortunately, the LLVM C API doesn't provide an easy way of iterating over
 // all the functions in a module, so we do that manually here. You'll find
 // similar code in clang's BackendUtil.cpp file.
-extern "C" void
-LLVMRustRunFunctionPassManager(LLVMPassManagerRef PM, LLVMModuleRef M) {
-    llvm::legacy::FunctionPassManager *P = unwrap<llvm::legacy::FunctionPassManager>(PM);
-    P->doInitialization();
-
-    // Upgrade all calls to old intrinsics first.
-    for (Module::iterator I = unwrap(M)->begin(),
-         E = unwrap(M)->end(); I != E;)
-        UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
-
-    for (Module::iterator I = unwrap(M)->begin(),
-         E = unwrap(M)->end(); I != E; ++I)
-        if (!I->isDeclaration())
-            P->run(*I);
-
-    P->doFinalization();
+extern "C" void LLVMRustRunFunctionPassManager(LLVMPassManagerRef PMR,
+                                               LLVMModuleRef M) {
+  llvm::legacy::FunctionPassManager *P =
+      unwrap<llvm::legacy::FunctionPassManager>(PMR);
+  P->doInitialization();
+
+  // Upgrade all calls to old intrinsics first.
+  for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;)
+    UpgradeCallsToIntrinsic(&*I++); // must be post-increment, as we remove
+
+  for (Module::iterator I = unwrap(M)->begin(), E = unwrap(M)->end(); I != E;
+       ++I)
+    if (!I->isDeclaration())
+      P->run(*I);
+
+  P->doFinalization();
 }
 
-extern "C" void
-LLVMRustSetLLVMOptions(int Argc, char **Argv) {
-    // Initializing the command-line options more than once is not allowed. So,
-    // check if they've already been initialized.  (This could happen if we're
-    // being called from rustpkg, for example). If the arguments change, then
-    // that's just kinda unfortunate.
-    static bool initialized = false;
-    if (initialized) return;
-    initialized = true;
-    cl::ParseCommandLineOptions(Argc, Argv);
+extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) {
+  // Initializing the command-line options more than once is not allowed. So,
+  // check if they've already been initialized.  (This could happen if we're
+  // being called from rustpkg, for example). If the arguments change, then
+  // that's just kinda unfortunate.
+  static bool Initialized = false;
+  if (Initialized)
+    return;
+  Initialized = true;
+  cl::ParseCommandLineOptions(Argc, Argv);
 }
 
 enum class LLVMRustFileType {
-    Other,
-    AssemblyFile,
-    ObjectFile,
+  Other,
+  AssemblyFile,
+  ObjectFile,
 };
 
-static TargetMachine::CodeGenFileType
-from_rust(LLVMRustFileType type)
-{
-    switch (type) {
-    case LLVMRustFileType::AssemblyFile:
-        return TargetMachine::CGFT_AssemblyFile;
-    case LLVMRustFileType::ObjectFile:
-        return TargetMachine::CGFT_ObjectFile;
-    default:
-        llvm_unreachable("Bad FileType.");
+static TargetMachine::CodeGenFileType fromRust(LLVMRustFileType Type) {
+  switch (Type) {
+  case LLVMRustFileType::AssemblyFile:
+    return TargetMachine::CGFT_AssemblyFile;
+  case LLVMRustFileType::ObjectFile:
+    return TargetMachine::CGFT_ObjectFile;
+  default:
+    llvm_unreachable("Bad FileType.");
   }
 }
 
 extern "C" LLVMRustResult
-LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
-                        LLVMPassManagerRef PMR,
-                        LLVMModuleRef M,
-                        const char *path,
-                        LLVMRustFileType rust_FileType) {
+LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR,
+                        LLVMModuleRef M, const char *Path,
+                        LLVMRustFileType RustFileType) {
   llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
-  auto FileType = from_rust(rust_FileType);
+  auto FileType = fromRust(RustFileType);
 
   std::string ErrorInfo;
   std::error_code EC;
-  raw_fd_ostream OS(path, EC, sys::fs::F_None);
+  raw_fd_ostream OS(Path, EC, sys::fs::F_None);
   if (EC)
     ErrorInfo = EC.message();
   if (ErrorInfo != "") {
@@ -505,15 +476,13 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
   return LLVMRustResult::Success;
 }
 
-extern "C" void
-LLVMRustPrintModule(LLVMPassManagerRef PMR,
-                    LLVMModuleRef M,
-                    const char* path) {
+extern "C" void LLVMRustPrintModule(LLVMPassManagerRef PMR, LLVMModuleRef M,
+                                    const char *Path) {
   llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
   std::string ErrorInfo;
 
   std::error_code EC;
-  raw_fd_ostream OS(path, EC, sys::fs::F_None);
+  raw_fd_ostream OS(Path, EC, sys::fs::F_None);
   if (EC)
     ErrorInfo = EC.message();
 
@@ -524,102 +493,96 @@ LLVMRustPrintModule(LLVMPassManagerRef PMR,
   PM->run(*unwrap(M));
 }
 
-extern "C" void
-LLVMRustPrintPasses() {
-    LLVMInitializePasses();
-    struct MyListener : PassRegistrationListener {
-        void passEnumerate(const PassInfo *info) {
+extern "C" void LLVMRustPrintPasses() {
+  LLVMInitializePasses();
+  struct MyListener : PassRegistrationListener {
+    void passEnumerate(const PassInfo *Info) {
 #if LLVM_VERSION_GE(4, 0)
-            StringRef PassArg = info->getPassArgument();
-            StringRef PassName = info->getPassName();
-            if (!PassArg.empty()) {
-                // These unsigned->signed casts could theoretically overflow, but
-                // realistically never will (and even if, the result is implementation
-                // defined rather plain UB).
-                printf("%15.*s - %.*s\n", (int)PassArg.size(), PassArg.data(),
-                       (int)PassName.size(), PassName.data());
-            }
+      StringRef PassArg = Info->getPassArgument();
+      StringRef PassName = Info->getPassName();
+      if (!PassArg.empty()) {
+        // These unsigned->signed casts could theoretically overflow, but
+        // realistically never will (and even if, the result is implementation
+        // defined rather plain UB).
+        printf("%15.*s - %.*s\n", (int)PassArg.size(), PassArg.data(),
+               (int)PassName.size(), PassName.data());
+      }
 #else
-            if (info->getPassArgument() && *info->getPassArgument()) {
-                printf("%15s - %s\n", info->getPassArgument(),
-                       info->getPassName());
-            }
+      if (Info->getPassArgument() && *Info->getPassArgument()) {
+        printf("%15s - %s\n", Info->getPassArgument(), Info->getPassName());
+      }
 #endif
-        }
-    } listener;
+    }
+  } Listener;
 
-    PassRegistry *PR = PassRegistry::getPassRegistry();
-    PR->enumerateWith(&listener);
+  PassRegistry *PR = PassRegistry::getPassRegistry();
+  PR->enumerateWith(&Listener);
 }
 
-extern "C" void
-LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMB, bool AddLifetimes) {
+extern "C" void LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMBR,
+                                            bool AddLifetimes) {
 #if LLVM_VERSION_GE(4, 0)
-    unwrap(PMB)->Inliner = llvm::createAlwaysInlinerLegacyPass(AddLifetimes);
+  unwrap(PMBR)->Inliner = llvm::createAlwaysInlinerLegacyPass(AddLifetimes);
 #else
-    unwrap(PMB)->Inliner = createAlwaysInlinerPass(AddLifetimes);
+  unwrap(PMBR)->Inliner = createAlwaysInlinerPass(AddLifetimes);
 #endif
 }
 
-extern "C" void
-LLVMRustRunRestrictionPass(LLVMModuleRef M, char **symbols, size_t len) {
-    llvm::legacy::PassManager passes;
+extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols,
+                                           size_t Len) {
+  llvm::legacy::PassManager passes;
 
 #if LLVM_VERSION_LE(3, 8)
-    ArrayRef<const char*> ref(symbols, len);
-    passes.add(llvm::createInternalizePass(ref));
+  ArrayRef<const char *> Ref(Symbols, Len);
+  passes.add(llvm::createInternalizePass(Ref));
 #else
-    auto PreserveFunctions = [=](const GlobalValue &GV) {
-        for (size_t i=0; i<len; i++) {
-            if (GV.getName() == symbols[i]) {
-                return true;
-            }
-        }
-        return false;
-    };
+  auto PreserveFunctions = [=](const GlobalValue &GV) {
+    for (size_t I = 0; I < Len; I++) {
+      if (GV.getName() == Symbols[I]) {
+        return true;
+      }
+    }
+    return false;
+  };
 
-    passes.add(llvm::createInternalizePass(PreserveFunctions));
+  passes.add(llvm::createInternalizePass(PreserveFunctions));
 #endif
 
-    passes.run(*unwrap(M));
+  passes.run(*unwrap(M));
 }
 
-extern "C" void
-LLVMRustMarkAllFunctionsNounwind(LLVMModuleRef M) {
-    for (Module::iterator GV = unwrap(M)->begin(),
-         E = unwrap(M)->end(); GV != E; ++GV) {
-        GV->setDoesNotThrow();
-        Function *F = dyn_cast<Function>(GV);
-        if (F == NULL)
-            continue;
-
-        for (Function::iterator B = F->begin(), BE = F->end(); B != BE; ++B) {
-            for (BasicBlock::iterator I = B->begin(), IE = B->end();
-                 I != IE; ++I) {
-                if (isa<InvokeInst>(I)) {
-                    InvokeInst *CI = cast<InvokeInst>(I);
-                    CI->setDoesNotThrow();
-                }
-            }
+extern "C" void LLVMRustMarkAllFunctionsNounwind(LLVMModuleRef M) {
+  for (Module::iterator GV = unwrap(M)->begin(), E = unwrap(M)->end(); GV != E;
+       ++GV) {
+    GV->setDoesNotThrow();
+    Function *F = dyn_cast<Function>(GV);
+    if (F == nullptr)
+      continue;
+
+    for (Function::iterator B = F->begin(), BE = F->end(); B != BE; ++B) {
+      for (BasicBlock::iterator I = B->begin(), IE = B->end(); I != IE; ++I) {
+        if (isa<InvokeInst>(I)) {
+          InvokeInst *CI = cast<InvokeInst>(I);
+          CI->setDoesNotThrow();
         }
+      }
     }
+  }
 }
 
 extern "C" void
 LLVMRustSetDataLayoutFromTargetMachine(LLVMModuleRef Module,
                                        LLVMTargetMachineRef TMR) {
-    TargetMachine *Target = unwrap(TMR);
-    unwrap(Module)->setDataLayout(Target->createDataLayout());
+  TargetMachine *Target = unwrap(TMR);
+  unwrap(Module)->setDataLayout(Target->createDataLayout());
 }
 
-extern "C" LLVMTargetDataRef
-LLVMRustGetModuleDataLayout(LLVMModuleRef M) {
-    return wrap(&unwrap(M)->getDataLayout());
+extern "C" LLVMTargetDataRef LLVMRustGetModuleDataLayout(LLVMModuleRef M) {
+  return wrap(&unwrap(M)->getDataLayout());
 }
 
-extern "C" void
-LLVMRustSetModulePIELevel(LLVMModuleRef M) {
+extern "C" void LLVMRustSetModulePIELevel(LLVMModuleRef M) {
 #if LLVM_VERSION_GE(3, 9)
-    unwrap(M)->setPIELevel(PIELevel::Level::Large);
+  unwrap(M)->setPIELevel(PIELevel::Level::Large);
 #endif
 }
diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 5d5845213e2..ea31e8dab67 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -9,11 +9,11 @@
 // except according to those terms.
 
 #include "rustllvm.h"
-#include "llvm/Object/Archive.h"
-#include "llvm/Object/ObjectFile.h"
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/DiagnosticPrinter.h"
 #include "llvm/IR/Instructions.h"
+#include "llvm/Object/Archive.h"
+#include "llvm/Object/ObjectFile.h"
 
 #include "llvm/IR/CallSite.h"
 
@@ -30,78 +30,75 @@ using namespace llvm::object;
 
 // LLVMAtomicOrdering is already an enum - don't create another
 // one.
-static AtomicOrdering from_rust(LLVMAtomicOrdering Ordering) {
+static AtomicOrdering fromRust(LLVMAtomicOrdering Ordering) {
   switch (Ordering) {
-    case LLVMAtomicOrderingNotAtomic:
-        return AtomicOrdering::NotAtomic;
-    case LLVMAtomicOrderingUnordered:
-        return AtomicOrdering::Unordered;
-    case LLVMAtomicOrderingMonotonic:
-        return AtomicOrdering::Monotonic;
-    case LLVMAtomicOrderingAcquire:
-        return AtomicOrdering::Acquire;
-    case LLVMAtomicOrderingRelease:
-        return AtomicOrdering::Release;
-    case LLVMAtomicOrderingAcquireRelease:
-        return AtomicOrdering::AcquireRelease;
-    case LLVMAtomicOrderingSequentiallyConsistent:
-        return AtomicOrdering::SequentiallyConsistent;
+  case LLVMAtomicOrderingNotAtomic:
+    return AtomicOrdering::NotAtomic;
+  case LLVMAtomicOrderingUnordered:
+    return AtomicOrdering::Unordered;
+  case LLVMAtomicOrderingMonotonic:
+    return AtomicOrdering::Monotonic;
+  case LLVMAtomicOrderingAcquire:
+    return AtomicOrdering::Acquire;
+  case LLVMAtomicOrderingRelease:
+    return AtomicOrdering::Release;
+  case LLVMAtomicOrderingAcquireRelease:
+    return AtomicOrdering::AcquireRelease;
+  case LLVMAtomicOrderingSequentiallyConsistent:
+    return AtomicOrdering::SequentiallyConsistent;
   }
 
   llvm_unreachable("Invalid LLVMAtomicOrdering value!");
 }
 
-
 static char *LastError;
 
 extern "C" LLVMMemoryBufferRef
 LLVMRustCreateMemoryBufferWithContentsOfFile(const char *Path) {
-  ErrorOr<std::unique_ptr<MemoryBuffer>> buf_or = MemoryBuffer::getFile(Path,
-                                                                        -1,
-                                                                        false);
-  if (!buf_or) {
-      LLVMRustSetLastError(buf_or.getError().message().c_str());
-      return nullptr;
+  ErrorOr<std::unique_ptr<MemoryBuffer>> BufOr =
+      MemoryBuffer::getFile(Path, -1, false);
+  if (!BufOr) {
+    LLVMRustSetLastError(BufOr.getError().message().c_str());
+    return nullptr;
   }
-  return wrap(buf_or.get().release());
+  return wrap(BufOr.get().release());
 }
 
 extern "C" char *LLVMRustGetLastError(void) {
-  char *ret = LastError;
-  LastError = NULL;
-  return ret;
+  char *Ret = LastError;
+  LastError = nullptr;
+  return Ret;
 }
 
-void LLVMRustSetLastError(const char *err) {
-  free((void*) LastError);
-  LastError = strdup(err);
+void LLVMRustSetLastError(const char *Err) {
+  free((void *)LastError);
+  LastError = strdup(Err);
 }
 
-extern "C" void
-LLVMRustSetNormalizedTarget(LLVMModuleRef M, const char *triple) {
-    unwrap(M)->setTargetTriple(Triple::normalize(triple));
+extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M,
+                                            const char *Triple) {
+  unwrap(M)->setTargetTriple(Triple::normalize(Triple));
 }
 
 extern "C" void LLVMRustPrintPassTimings() {
-  raw_fd_ostream OS (2, false); // stderr.
+  raw_fd_ostream OS(2, false); // stderr.
   TimerGroup::printAll(OS);
 }
 
 extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M,
-					      const char* Name) {
-    return wrap(unwrap(M)->getNamedValue(Name));
+                                              const char *Name) {
+  return wrap(unwrap(M)->getNamedValue(Name));
 }
 
 extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
-						    const char* Name,
-						    LLVMTypeRef FunctionTy) {
-  return wrap(unwrap(M)->getOrInsertFunction(Name,
-                                             unwrap<FunctionType>(FunctionTy)));
+                                                    const char *Name,
+                                                    LLVMTypeRef FunctionTy) {
+  return wrap(
+      unwrap(M)->getOrInsertFunction(Name, unwrap<FunctionType>(FunctionTy)));
 }
 
-extern "C" LLVMValueRef LLVMRustGetOrInsertGlobal(LLVMModuleRef M,
-						  const char* Name,
-						  LLVMTypeRef Ty) {
+extern "C" LLVMValueRef
+LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, LLVMTypeRef Ty) {
   return wrap(unwrap(M)->getOrInsertGlobal(Name, unwrap(Ty)));
 }
 
@@ -109,192 +106,172 @@ extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) {
   return wrap(Type::getMetadataTy(*unwrap(C)));
 }
 
-static Attribute::AttrKind
-from_rust(LLVMRustAttribute kind) {
-  switch (kind) {
-    case AlwaysInline:
-      return Attribute::AlwaysInline;
-    case ByVal:
-      return Attribute::ByVal;
-    case Cold:
-      return Attribute::Cold;
-    case InlineHint:
-      return Attribute::InlineHint;
-    case MinSize:
-      return Attribute::MinSize;
-    case Naked:
-      return Attribute::Naked;
-    case NoAlias:
-      return Attribute::NoAlias;
-    case NoCapture:
-      return Attribute::NoCapture;
-    case NoInline:
-      return Attribute::NoInline;
-    case NonNull:
-      return Attribute::NonNull;
-    case NoRedZone:
-      return Attribute::NoRedZone;
-    case NoReturn:
-      return Attribute::NoReturn;
-    case NoUnwind:
-      return Attribute::NoUnwind;
-    case OptimizeForSize:
-      return Attribute::OptimizeForSize;
-    case ReadOnly:
-      return Attribute::ReadOnly;
-    case SExt:
-      return Attribute::SExt;
-    case StructRet:
-      return Attribute::StructRet;
-    case UWTable:
-      return Attribute::UWTable;
-    case ZExt:
-      return Attribute::ZExt;
-    case InReg:
-      return Attribute::InReg;
-    default:
-      llvm_unreachable("bad AttributeKind");
+static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
+  switch (Kind) {
+  case AlwaysInline:
+    return Attribute::AlwaysInline;
+  case ByVal:
+    return Attribute::ByVal;
+  case Cold:
+    return Attribute::Cold;
+  case InlineHint:
+    return Attribute::InlineHint;
+  case MinSize:
+    return Attribute::MinSize;
+  case Naked:
+    return Attribute::Naked;
+  case NoAlias:
+    return Attribute::NoAlias;
+  case NoCapture:
+    return Attribute::NoCapture;
+  case NoInline:
+    return Attribute::NoInline;
+  case NonNull:
+    return Attribute::NonNull;
+  case NoRedZone:
+    return Attribute::NoRedZone;
+  case NoReturn:
+    return Attribute::NoReturn;
+  case NoUnwind:
+    return Attribute::NoUnwind;
+  case OptimizeForSize:
+    return Attribute::OptimizeForSize;
+  case ReadOnly:
+    return Attribute::ReadOnly;
+  case SExt:
+    return Attribute::SExt;
+  case StructRet:
+    return Attribute::StructRet;
+  case UWTable:
+    return Attribute::UWTable;
+  case ZExt:
+    return Attribute::ZExt;
+  case InReg:
+    return Attribute::InReg;
+  default:
+    llvm_unreachable("bad AttributeKind");
   }
 }
 
-extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, LLVMRustAttribute attr) {
+extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned Index,
+                                             LLVMRustAttribute RustAttr) {
   CallSite Call = CallSite(unwrap<Instruction>(Instr));
-  Attribute Attr = Attribute::get(Call->getContext(), from_rust(attr));
+  Attribute Attr = Attribute::get(Call->getContext(), fromRust(RustAttr));
   AttrBuilder B(Attr);
-  Call.setAttributes(
-    Call.getAttributes().addAttributes(Call->getContext(), index,
-                                       AttributeSet::get(Call->getContext(),
-                                                         index, B)));
+  Call.setAttributes(Call.getAttributes().addAttributes(
+      Call->getContext(), Index,
+      AttributeSet::get(Call->getContext(), Index, B)));
 }
 
 extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr,
-                                                      unsigned index,
-                                                      uint64_t bytes)
-{
+                                                       unsigned Index,
+                                                       uint64_t Bytes) {
   CallSite Call = CallSite(unwrap<Instruction>(Instr));
   AttrBuilder B;
-  B.addDereferenceableAttr(bytes);
-  Call.setAttributes(
-    Call.getAttributes().addAttributes(Call->getContext(), index,
-                                       AttributeSet::get(Call->getContext(),
-                                                         index, B)));
+  B.addDereferenceableAttr(Bytes);
+  Call.setAttributes(Call.getAttributes().addAttributes(
+      Call->getContext(), Index,
+      AttributeSet::get(Call->getContext(), Index, B)));
 }
 
-extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn,
-					     unsigned index,
-					     LLVMRustAttribute attr)
-{
+extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
+                                             LLVMRustAttribute RustAttr) {
   Function *A = unwrap<Function>(Fn);
-  Attribute Attr = Attribute::get(A->getContext(), from_rust(attr));
+  Attribute Attr = Attribute::get(A->getContext(), fromRust(RustAttr));
   AttrBuilder B(Attr);
-  A->addAttributes(index, AttributeSet::get(A->getContext(), index, B));
+  A->addAttributes(Index, AttributeSet::get(A->getContext(), Index, B));
 }
 
-extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn,
-					       unsigned index,
-					       uint64_t bytes)
-{
+extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn, unsigned Index,
+                                               uint64_t Bytes) {
   Function *A = unwrap<Function>(Fn);
   AttrBuilder B;
-  B.addDereferenceableAttr(bytes);
-  A->addAttributes(index, AttributeSet::get(A->getContext(), index, B));
+  B.addDereferenceableAttr(Bytes);
+  A->addAttributes(Index, AttributeSet::get(A->getContext(), Index, B));
 }
 
 extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
-						   unsigned index,
-						   const char *Name,
-						   const char *Value) {
+                                                   unsigned Index,
+                                                   const char *Name,
+                                                   const char *Value) {
   Function *F = unwrap<Function>(Fn);
   AttrBuilder B;
   B.addAttribute(Name, Value);
-  F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
+  F->addAttributes(Index, AttributeSet::get(F->getContext(), Index, B));
 }
 
 extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn,
-						 unsigned index,
-						 LLVMRustAttribute attr)
-{
+                                                 unsigned Index,
+                                                 LLVMRustAttribute RustAttr) {
   Function *F = unwrap<Function>(Fn);
   const AttributeSet PAL = F->getAttributes();
-  Attribute Attr = Attribute::get(F->getContext(), from_rust(attr));
+  Attribute Attr = Attribute::get(F->getContext(), fromRust(RustAttr));
   AttrBuilder B(Attr);
-  const AttributeSet PALnew =
-    PAL.removeAttributes(F->getContext(), index,
-                         AttributeSet::get(F->getContext(), index, B));
-  F->setAttributes(PALnew);
+  const AttributeSet PALNew = PAL.removeAttributes(
+      F->getContext(), Index, AttributeSet::get(F->getContext(), Index, B));
+  F->setAttributes(PALNew);
 }
 
 // enable fpmath flag UnsafeAlgebra
 extern "C" void LLVMRustSetHasUnsafeAlgebra(LLVMValueRef V) {
-    if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
-        I->setHasUnsafeAlgebra(true);
-    }
+  if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
+    I->setHasUnsafeAlgebra(true);
+  }
 }
 
-extern "C" LLVMValueRef LLVMRustBuildAtomicLoad(LLVMBuilderRef B,
-						LLVMValueRef source,
-						const char* Name,
-						LLVMAtomicOrdering order,
-						unsigned alignment) {
-    LoadInst* li = new LoadInst(unwrap(source),0);
-    li->setAtomic(from_rust(order));
-    li->setAlignment(alignment);
-    return wrap(unwrap(B)->Insert(li, Name));
+extern "C" LLVMValueRef
+LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMValueRef Source, const char *Name,
+                        LLVMAtomicOrdering Order, unsigned Alignment) {
+  LoadInst *LI = new LoadInst(unwrap(Source), 0);
+  LI->setAtomic(fromRust(Order));
+  LI->setAlignment(Alignment);
+  return wrap(unwrap(B)->Insert(LI, Name));
 }
 
 extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B,
-						 LLVMValueRef val,
-						 LLVMValueRef target,
-						 LLVMAtomicOrdering order,
-						 unsigned alignment) {
-    StoreInst* si = new StoreInst(unwrap(val),unwrap(target));
-    si->setAtomic(from_rust(order));
-    si->setAlignment(alignment);
-    return wrap(unwrap(B)->Insert(si));
-}
-
-extern "C" LLVMValueRef LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B,
-                                               LLVMValueRef target,
-                                               LLVMValueRef old,
-                                               LLVMValueRef source,
-                                               LLVMAtomicOrdering order,
-                                               LLVMAtomicOrdering failure_order,
-                                               LLVMBool weak) {
-    AtomicCmpXchgInst* acxi = unwrap(B)->CreateAtomicCmpXchg(
-        unwrap(target),
-        unwrap(old),
-        unwrap(source),
-        from_rust(order),
-	from_rust(failure_order));
-    acxi->setWeak(weak);
-    return wrap(acxi);
+                                                 LLVMValueRef V,
+                                                 LLVMValueRef Target,
+                                                 LLVMAtomicOrdering Order,
+                                                 unsigned Alignment) {
+  StoreInst *SI = new StoreInst(unwrap(V), unwrap(Target));
+  SI->setAtomic(fromRust(Order));
+  SI->setAlignment(Alignment);
+  return wrap(unwrap(B)->Insert(SI));
+}
+
+extern "C" LLVMValueRef
+LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target,
+                           LLVMValueRef Old, LLVMValueRef Source,
+                           LLVMAtomicOrdering Order,
+                           LLVMAtomicOrdering FailureOrder, LLVMBool Weak) {
+  AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
+      unwrap(Target), unwrap(Old), unwrap(Source), fromRust(Order),
+      fromRust(FailureOrder));
+  ACXI->setWeak(Weak);
+  return wrap(ACXI);
 }
 
 enum class LLVMRustSynchronizationScope {
-    Other,
-    SingleThread,
-    CrossThread,
+  Other,
+  SingleThread,
+  CrossThread,
 };
 
-static SynchronizationScope
-from_rust(LLVMRustSynchronizationScope scope)
-{
-    switch (scope) {
-    case LLVMRustSynchronizationScope::SingleThread:
-        return SingleThread;
-    case LLVMRustSynchronizationScope::CrossThread:
-        return CrossThread;
-    default:
-        llvm_unreachable("bad SynchronizationScope.");
-    }
+static SynchronizationScope fromRust(LLVMRustSynchronizationScope Scope) {
+  switch (Scope) {
+  case LLVMRustSynchronizationScope::SingleThread:
+    return SingleThread;
+  case LLVMRustSynchronizationScope::CrossThread:
+    return CrossThread;
+  default:
+    llvm_unreachable("bad SynchronizationScope.");
+  }
 }
 
-extern "C" LLVMValueRef LLVMRustBuildAtomicFence(
-    LLVMBuilderRef B,
-    LLVMAtomicOrdering order,
-    LLVMRustSynchronizationScope scope)
-{
-    return wrap(unwrap(B)->CreateFence(from_rust(order), from_rust(scope)));
+extern "C" LLVMValueRef
+LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order,
+                         LLVMRustSynchronizationScope Scope) {
+  return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope)));
 }
 
 extern "C" void LLVMRustSetDebug(int Enabled) {
@@ -304,36 +281,32 @@ extern "C" void LLVMRustSetDebug(int Enabled) {
 }
 
 enum class LLVMRustAsmDialect {
-    Other,
-    Att,
-    Intel,
+  Other,
+  Att,
+  Intel,
 };
 
-static InlineAsm::AsmDialect
-from_rust(LLVMRustAsmDialect dialect)
-{
-    switch (dialect) {
-    case LLVMRustAsmDialect::Att:
-        return InlineAsm::AD_ATT;
-    case LLVMRustAsmDialect::Intel:
-        return InlineAsm::AD_Intel;
-    default:
-        llvm_unreachable("bad AsmDialect.");
-    }
+static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) {
+  switch (Dialect) {
+  case LLVMRustAsmDialect::Att:
+    return InlineAsm::AD_ATT;
+  case LLVMRustAsmDialect::Intel:
+    return InlineAsm::AD_Intel;
+  default:
+    llvm_unreachable("bad AsmDialect.");
+  }
 }
 
-extern "C" LLVMValueRef LLVMRustInlineAsm(LLVMTypeRef Ty,
-					  char *AsmString,
-					  char *Constraints,
-					  LLVMBool HasSideEffects,
-					  LLVMBool IsAlignStack,
-					  LLVMRustAsmDialect Dialect) {
-    return wrap(InlineAsm::get(unwrap<FunctionType>(Ty), AsmString,
-                               Constraints, HasSideEffects,
-                               IsAlignStack, from_rust(Dialect)));
+extern "C" LLVMValueRef LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString,
+                                          char *Constraints,
+                                          LLVMBool HasSideEffects,
+                                          LLVMBool IsAlignStack,
+                                          LLVMRustAsmDialect Dialect) {
+  return wrap(InlineAsm::get(unwrap<FunctionType>(Ty), AsmString, Constraints,
+                             HasSideEffects, IsAlignStack, fromRust(Dialect)));
 }
 
-typedef DIBuilder* LLVMRustDIBuilderRef;
+typedef DIBuilder *LLVMRustDIBuilderRef;
 
 typedef struct LLVMOpaqueMetadata *LLVMRustMetadataRef;
 
@@ -341,631 +314,498 @@ namespace llvm {
 DEFINE_ISA_CONVERSION_FUNCTIONS(Metadata, LLVMRustMetadataRef)
 
 inline Metadata **unwrap(LLVMRustMetadataRef *Vals) {
-  return reinterpret_cast<Metadata**>(Vals);
+  return reinterpret_cast<Metadata **>(Vals);
 }
 }
 
-template<typename DIT>
-DIT* unwrapDIptr(LLVMRustMetadataRef ref) {
-    return (DIT*) (ref ? unwrap<MDNode>(ref) : NULL);
+template <typename DIT> DIT *unwrapDIPtr(LLVMRustMetadataRef Ref) {
+  return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
 }
 
 #define DIDescriptor DIScope
 #define DIArray DINodeArray
-#define unwrapDI unwrapDIptr
+#define unwrapDI unwrapDIPtr
 
 // These values **must** match debuginfo::DIFlags! They also *happen*
 // to match LLVM, but that isn't required as we do giant sets of
 // matching below. The value shouldn't be directly passed to LLVM.
 enum class LLVMRustDIFlags : uint32_t {
-    FlagZero                = 0,
-    FlagPrivate             = 1,
-    FlagProtected           = 2,
-    FlagPublic              = 3,
-    FlagFwdDecl             = (1 << 2),
-    FlagAppleBlock          = (1 << 3),
-    FlagBlockByrefStruct    = (1 << 4),
-    FlagVirtual             = (1 << 5),
-    FlagArtificial          = (1 << 6),
-    FlagExplicit            = (1 << 7),
-    FlagPrototyped          = (1 << 8),
-    FlagObjcClassComplete   = (1 << 9),
-    FlagObjectPointer       = (1 << 10),
-    FlagVector              = (1 << 11),
-    FlagStaticMember        = (1 << 12),
-    FlagLValueReference     = (1 << 13),
-    FlagRValueReference     = (1 << 14),
-    // Do not add values that are not supported by the minimum LLVM
-    // version we support!
+  FlagZero = 0,
+  FlagPrivate = 1,
+  FlagProtected = 2,
+  FlagPublic = 3,
+  FlagFwdDecl = (1 << 2),
+  FlagAppleBlock = (1 << 3),
+  FlagBlockByrefStruct = (1 << 4),
+  FlagVirtual = (1 << 5),
+  FlagArtificial = (1 << 6),
+  FlagExplicit = (1 << 7),
+  FlagPrototyped = (1 << 8),
+  FlagObjcClassComplete = (1 << 9),
+  FlagObjectPointer = (1 << 10),
+  FlagVector = (1 << 11),
+  FlagStaticMember = (1 << 12),
+  FlagLValueReference = (1 << 13),
+  FlagRValueReference = (1 << 14),
+  // Do not add values that are not supported by the minimum LLVM
+  // version we support!
 };
 
-inline LLVMRustDIFlags operator& (LLVMRustDIFlags a, LLVMRustDIFlags b) {
-    return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(a) & static_cast<uint32_t>(b));
+inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) {
+  return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) &
+                                      static_cast<uint32_t>(B));
 }
 
-inline LLVMRustDIFlags operator| (LLVMRustDIFlags a, LLVMRustDIFlags b) {
-    return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
+inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) {
+  return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) |
+                                      static_cast<uint32_t>(B));
 }
 
-inline LLVMRustDIFlags& operator|= (LLVMRustDIFlags& a, LLVMRustDIFlags b) {
-    return a = a | b;
+inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) {
+  return A = A | B;
 }
 
-inline bool is_set(LLVMRustDIFlags f) {
-    return f != LLVMRustDIFlags::FlagZero;
-}
+inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; }
 
-inline LLVMRustDIFlags visibility(LLVMRustDIFlags f) {
-    return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(f) & 0x3);
+inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) {
+  return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3);
 }
 
 #if LLVM_VERSION_GE(4, 0)
-static DINode::DIFlags from_rust(LLVMRustDIFlags flags) {
-    DINode::DIFlags result = DINode::DIFlags::FlagZero;
+static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
+  DINode::DIFlags Result = DINode::DIFlags::FlagZero;
 #else
-static unsigned from_rust(LLVMRustDIFlags flags) {
-    unsigned result = 0;
+static unsigned fromRust(LLVMRustDIFlags Flags) {
+  unsigned Result = 0;
 #endif
 
-    switch (visibility(flags)) {
-    case LLVMRustDIFlags::FlagPrivate:
-        result |= DINode::DIFlags::FlagPrivate;
-        break;
-    case LLVMRustDIFlags::FlagProtected:
-        result |= DINode::DIFlags::FlagProtected;
-        break;
-    case LLVMRustDIFlags::FlagPublic:
-        result |= DINode::DIFlags::FlagPublic;
-        break;
-    default:
-        // The rest are handled below
-        break;
-    }
+  switch (visibility(Flags)) {
+  case LLVMRustDIFlags::FlagPrivate:
+    Result |= DINode::DIFlags::FlagPrivate;
+    break;
+  case LLVMRustDIFlags::FlagProtected:
+    Result |= DINode::DIFlags::FlagProtected;
+    break;
+  case LLVMRustDIFlags::FlagPublic:
+    Result |= DINode::DIFlags::FlagPublic;
+    break;
+  default:
+    // The rest are handled below
+    break;
+  }
 
-    if (is_set(flags & LLVMRustDIFlags::FlagFwdDecl))             { result |= DINode::DIFlags::FlagFwdDecl; }
-    if (is_set(flags & LLVMRustDIFlags::FlagAppleBlock))          { result |= DINode::DIFlags::FlagAppleBlock; }
-    if (is_set(flags & LLVMRustDIFlags::FlagBlockByrefStruct))    { result |= DINode::DIFlags::FlagBlockByrefStruct; }
-    if (is_set(flags & LLVMRustDIFlags::FlagVirtual))             { result |= DINode::DIFlags::FlagVirtual; }
-    if (is_set(flags & LLVMRustDIFlags::FlagArtificial))          { result |= DINode::DIFlags::FlagArtificial; }
-    if (is_set(flags & LLVMRustDIFlags::FlagExplicit))            { result |= DINode::DIFlags::FlagExplicit; }
-    if (is_set(flags & LLVMRustDIFlags::FlagPrototyped))          { result |= DINode::DIFlags::FlagPrototyped; }
-    if (is_set(flags & LLVMRustDIFlags::FlagObjcClassComplete))   { result |= DINode::DIFlags::FlagObjcClassComplete; }
-    if (is_set(flags & LLVMRustDIFlags::FlagObjectPointer))       { result |= DINode::DIFlags::FlagObjectPointer; }
-    if (is_set(flags & LLVMRustDIFlags::FlagVector))              { result |= DINode::DIFlags::FlagVector; }
-    if (is_set(flags & LLVMRustDIFlags::FlagStaticMember))        { result |= DINode::DIFlags::FlagStaticMember; }
-    if (is_set(flags & LLVMRustDIFlags::FlagLValueReference))     { result |= DINode::DIFlags::FlagLValueReference; }
-    if (is_set(flags & LLVMRustDIFlags::FlagRValueReference))     { result |= DINode::DIFlags::FlagRValueReference; }
+  if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) {
+    Result |= DINode::DIFlags::FlagFwdDecl;
+  }
+  if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
+    Result |= DINode::DIFlags::FlagAppleBlock;
+  }
+  if (isSet(Flags & LLVMRustDIFlags::FlagBlockByrefStruct)) {
+    Result |= DINode::DIFlags::FlagBlockByrefStruct;
+  }
+  if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
+    Result |= DINode::DIFlags::FlagVirtual;
+  }
+  if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) {
+    Result |= DINode::DIFlags::FlagArtificial;
+  }
+  if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) {
+    Result |= DINode::DIFlags::FlagExplicit;
+  }
+  if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) {
+    Result |= DINode::DIFlags::FlagPrototyped;
+  }
+  if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) {
+    Result |= DINode::DIFlags::FlagObjcClassComplete;
+  }
+  if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) {
+    Result |= DINode::DIFlags::FlagObjectPointer;
+  }
+  if (isSet(Flags & LLVMRustDIFlags::FlagVector)) {
+    Result |= DINode::DIFlags::FlagVector;
+  }
+  if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) {
+    Result |= DINode::DIFlags::FlagStaticMember;
+  }
+  if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) {
+    Result |= DINode::DIFlags::FlagLValueReference;
+  }
+  if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
+    Result |= DINode::DIFlags::FlagRValueReference;
+  }
 
-    return result;
+  return Result;
 }
 
 extern "C" uint32_t LLVMRustDebugMetadataVersion() {
-    return DEBUG_METADATA_VERSION;
+  return DEBUG_METADATA_VERSION;
 }
 
-extern "C" uint32_t LLVMRustVersionMinor() {
-  return LLVM_VERSION_MINOR;
-}
+extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
 
-extern "C" uint32_t LLVMRustVersionMajor() {
-  return LLVM_VERSION_MAJOR;
-}
+extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
 
-extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M,
-                                      const char *name,
-                                      uint32_t value) {
-    unwrap(M)->addModuleFlag(Module::Warning, name, value);
+extern "C" void LLVMRustAddModuleFlag(LLVMModuleRef M, const char *Name,
+                                      uint32_t Value) {
+  unwrap(M)->addModuleFlag(Module::Warning, Name, Value);
 }
 
 extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
-    return new DIBuilder(*unwrap(M));
+  return new DIBuilder(*unwrap(M));
 }
 
 extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
-    delete Builder;
+  delete Builder;
 }
 
 extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
-    Builder->finalize();
+  Builder->finalize();
 }
 
 extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateCompileUnit(
-    LLVMRustDIBuilderRef Builder,
-    unsigned Lang,
-    const char* File,
-    const char* Dir,
-    const char* Producer,
-    bool isOptimized,
-    const char* Flags,
-    unsigned RuntimeVer,
-    const char* SplitName) {
-    return wrap(Builder->createCompileUnit(Lang,
-                                           File,
-                                           Dir,
-                                           Producer,
-                                           isOptimized,
-                                           Flags,
-                                           RuntimeVer,
-                                           SplitName));
-}
-
-extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateFile(
-    LLVMRustDIBuilderRef Builder,
-    const char* Filename,
-    const char* Directory) {
-    return wrap(Builder->createFile(Filename, Directory));
-}
-
-extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateSubroutineType(
-    LLVMRustDIBuilderRef Builder,
-    LLVMRustMetadataRef File,
-    LLVMRustMetadataRef ParameterTypes) {
-    return wrap(Builder->createSubroutineType(
+    LLVMRustDIBuilderRef Builder, unsigned Lang, const char *File,
+    const char *Dir, const char *Producer, bool isOptimized, const char *Flags,
+    unsigned RuntimeVer, const char *SplitName) {
+  return wrap(Builder->createCompileUnit(Lang, File, Dir, Producer, isOptimized,
+                                         Flags, RuntimeVer, SplitName));
+}
+
+extern "C" LLVMRustMetadataRef
+LLVMRustDIBuilderCreateFile(LLVMRustDIBuilderRef Builder, const char *Filename,
+                            const char *Directory) {
+  return wrap(Builder->createFile(Filename, Directory));
+}
+
+extern "C" LLVMRustMetadataRef
+LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
+                                      LLVMRustMetadataRef File,
+                                      LLVMRustMetadataRef ParameterTypes) {
+  return wrap(Builder->createSubroutineType(
 #if LLVM_VERSION_EQ(3, 7)
-        unwrapDI<DIFile>(File),
+      unwrapDI<DIFile>(File),
 #endif
-        DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
+      DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
 }
 
 extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateFunction(
-    LLVMRustDIBuilderRef Builder,
-    LLVMRustMetadataRef Scope,
-    const char* Name,
-    const char* LinkageName,
-    LLVMRustMetadataRef File,
-    unsigned LineNo,
-    LLVMRustMetadataRef Ty,
-    bool isLocalToUnit,
-    bool isDefinition,
-    unsigned ScopeLine,
-    LLVMRustDIFlags Flags,
-    bool isOptimized,
-    LLVMValueRef Fn,
-    LLVMRustMetadataRef TParam,
-    LLVMRustMetadataRef Decl) {
+    LLVMRustDIBuilderRef Builder, LLVMRustMetadataRef Scope, const char *Name,
+    const char *LinkageName, LLVMRustMetadataRef File, unsigned LineNo,
+    LLVMRustMetadataRef Ty, bool IsLocalToUnit, bool IsDefinition,
+    unsigned ScopeLine, LLVMRustDIFlags Flags, bool IsOptimized,
+    LLVMValueRef Fn, LLVMRustMetadataRef TParam, LLVMRustMetadataRef Decl) {
 #if LLVM_VERSION_GE(3, 8)
-    DITemplateParameterArray TParams =
-        DITemplateParameterArray(unwrap<MDTuple>(TParam));
-    DISubprogram *Sub = Builder->createFunction(
-        unwrapDI<DIScope>(Scope), Name, LinkageName,
-        unwrapDI<DIFile>(File), LineNo,
-        unwrapDI<DISubroutineType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
-        from_rust(Flags), isOptimized,
-        TParams,
-        unwrapDIptr<DISubprogram>(Decl));
-    unwrap<Function>(Fn)->setSubprogram(Sub);
-    return wrap(Sub);
+  DITemplateParameterArray TParams =
+      DITemplateParameterArray(unwrap<MDTuple>(TParam));
+  DISubprogram *Sub = Builder->createFunction(
+      unwrapDI<DIScope>(Scope), Name, LinkageName, unwrapDI<DIFile>(File),
+      LineNo, unwrapDI<DISubroutineType>(Ty), IsLocalToUnit, IsDefinition,
+      ScopeLine, fromRust(Flags), IsOptimized, TParams,
+      unwrapDIPtr<DISubprogram>(Decl));
+  unwrap<Function>(Fn)->setSubprogram(Sub);
+  return wrap(Sub);
 #else
-    return wrap(Builder->createFunction(
-        unwrapDI<DIScope>(Scope), Name, LinkageName,
-        unwrapDI<DIFile>(File), LineNo,
-        unwrapDI<DISubroutineType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
-        from_rust(Flags), isOptimized,
-        unwrap<Function>(Fn),
-        unwrapDIptr<MDNode>(TParam),
-        unwrapDIptr<MDNode>(Decl)));
+  return wrap(Builder->createFunction(
+      unwrapDI<DIScope>(Scope), Name, LinkageName, unwrapDI<DIFile>(File),
+      LineNo, unwrapDI<DISubroutineType>(Ty), IsLocalToUnit, IsDefinition,
+      ScopeLine, fromRust(Flags), IsOptimized, unwrap<Function>(Fn),
+      unwrapDIPtr<MDNode>(TParam), unwrapDIPtr<MDNode>(Decl)));
 #endif
 }
 
-extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateBasicType(
-    LLVMRustDIBuilderRef Builder,
-    const char* Name,
-    uint64_t SizeInBits,
-    uint64_t AlignInBits,
-    unsigned Encoding) {
-    return wrap(Builder->createBasicType(
-        Name,
-        SizeInBits,
+extern "C" LLVMRustMetadataRef
+LLVMRustDIBuilderCreateBasicType(LLVMRustDIBuilderRef Builder, const char *Name,
+                                 uint64_t SizeInBits, uint64_t AlignInBits,
+                                 unsigned Encoding) {
+  return wrap(Builder->createBasicType(Name, SizeInBits,
 #if LLVM_VERSION_LE(3, 9)
-        AlignInBits,
+                                       AlignInBits,
 #endif
-        Encoding
-    ));
+                                       Encoding));
 }
 
 extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreatePointerType(
-    LLVMRustDIBuilderRef Builder,
-    LLVMRustMetadataRef PointeeTy,
-    uint64_t SizeInBits,
-    uint64_t AlignInBits,
-    const char* Name) {
-    return wrap(Builder->createPointerType(
-        unwrapDI<DIType>(PointeeTy), SizeInBits, AlignInBits, Name));
+    LLVMRustDIBuilderRef Builder, LLVMRustMetadataRef PointeeTy,
+    uint64_t SizeInBits, uint64_t AlignInBits, const char *Name) {
+  return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
+                                         SizeInBits, AlignInBits, Name));
 }
 
 extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateStructType(
-    LLVMRustDIBuilderRef Builder,
-    LLVMRustMetadataRef Scope,
-    const char* Name,
-    LLVMRustMetadataRef File,
-    unsigned LineNumber,
-    uint64_t SizeInBits,
-    uint64_t AlignInBits,
-    LLVMRustDIFlags Flags,
-    LLVMRustMetadataRef DerivedFrom,
-    LLVMRustMetadataRef Elements,
-    unsigned RunTimeLang,
-    LLVMRustMetadataRef VTableHolder,
+    LLVMRustDIBuilderRef Builder, LLVMRustMetadataRef Scope, const char *Name,
+    LLVMRustMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
+    uint64_t AlignInBits, LLVMRustDIFlags Flags,
+    LLVMRustMetadataRef DerivedFrom, LLVMRustMetadataRef Elements,
+    unsigned RunTimeLang, LLVMRustMetadataRef VTableHolder,
     const char *UniqueId) {
-    return wrap(Builder->createStructType(
-        unwrapDI<DIDescriptor>(Scope),
-        Name,
-        unwrapDI<DIFile>(File),
-        LineNumber,
-        SizeInBits,
-        AlignInBits,
-        from_rust(Flags),
-        unwrapDI<DIType>(DerivedFrom),
-        DINodeArray(unwrapDI<MDTuple>(Elements)),
-        RunTimeLang,
-        unwrapDI<DIType>(VTableHolder),
-        UniqueId
-        ));
+  return wrap(Builder->createStructType(
+      unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNumber,
+      SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
+      DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
+      unwrapDI<DIType>(VTableHolder), UniqueId));
 }
 
 extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateMemberType(
-    LLVMRustDIBuilderRef Builder,
-    LLVMRustMetadataRef Scope,
-    const char* Name,
-    LLVMRustMetadataRef File,
-    unsigned LineNo,
-    uint64_t SizeInBits,
-    uint64_t AlignInBits,
-    uint64_t OffsetInBits,
-    LLVMRustDIFlags Flags,
+    LLVMRustDIBuilderRef Builder, LLVMRustMetadataRef Scope, const char *Name,
+    LLVMRustMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
+    uint64_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
     LLVMRustMetadataRef Ty) {
-    return wrap(Builder->createMemberType(
-        unwrapDI<DIDescriptor>(Scope), Name,
-        unwrapDI<DIFile>(File), LineNo,
-        SizeInBits, AlignInBits, OffsetInBits, from_rust(Flags),
-        unwrapDI<DIType>(Ty)));
+  return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope), Name,
+                                        unwrapDI<DIFile>(File), LineNo,
+                                        SizeInBits, AlignInBits, OffsetInBits,
+                                        fromRust(Flags), unwrapDI<DIType>(Ty)));
 }
 
 extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
-    LLVMRustDIBuilderRef Builder,
-    LLVMRustMetadataRef Scope,
-    LLVMRustMetadataRef File,
-    unsigned Line,
-    unsigned Col) {
-    return wrap(Builder->createLexicalBlock(
-        unwrapDI<DIDescriptor>(Scope),
-        unwrapDI<DIFile>(File), Line, Col
-        ));
+    LLVMRustDIBuilderRef Builder, LLVMRustMetadataRef Scope,
+    LLVMRustMetadataRef File, unsigned Line, unsigned Col) {
+  return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
+                                          unwrapDI<DIFile>(File), Line, Col));
 }
 
-extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateLexicalBlockFile(
-    LLVMRustDIBuilderRef Builder,
-    LLVMRustMetadataRef Scope,
-    LLVMRustMetadataRef File) {
-    return wrap(Builder->createLexicalBlockFile(
-        unwrapDI<DIDescriptor>(Scope),
-        unwrapDI<DIFile>(File)));
+extern "C" LLVMRustMetadataRef
+LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
+                                        LLVMRustMetadataRef Scope,
+                                        LLVMRustMetadataRef File) {
+  return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
+                                              unwrapDI<DIFile>(File)));
 }
 
 extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateStaticVariable(
-    LLVMRustDIBuilderRef Builder,
-    LLVMRustMetadataRef Context,
-    const char* Name,
-    const char* LinkageName,
-    LLVMRustMetadataRef File,
-    unsigned LineNo,
-    LLVMRustMetadataRef Ty,
-    bool isLocalToUnit,
-    LLVMValueRef Val,
-    LLVMRustMetadataRef Decl = NULL,
-    uint64_t AlignInBits = 0) {
-    Constant *InitVal = cast<Constant>(unwrap(Val));
+    LLVMRustDIBuilderRef Builder, LLVMRustMetadataRef Context, const char *Name,
+    const char *LinkageName, LLVMRustMetadataRef File, unsigned LineNo,
+    LLVMRustMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
+    LLVMRustMetadataRef Decl = nullptr, uint64_t AlignInBits = 0) {
+  Constant *InitVal = cast<Constant>(unwrap(V));
 
 #if LLVM_VERSION_GE(4, 0)
-    llvm::DIExpression *InitExpr = nullptr;
-    if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
-      InitExpr = Builder->createConstantValueExpression(
-          IntVal->getValue().getSExtValue());
-    } else if (llvm::ConstantFP *FPVal = llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
-        InitExpr = Builder->createConstantValueExpression(
-                FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
-    }
+  llvm::DIExpression *InitExpr = nullptr;
+  if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
+    InitExpr = Builder->createConstantValueExpression(
+        IntVal->getValue().getSExtValue());
+  } else if (llvm::ConstantFP *FPVal =
+                 llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
+    InitExpr = Builder->createConstantValueExpression(
+        FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
+  }
 #endif
 
-    return wrap(Builder->createGlobalVariable(unwrapDI<DIDescriptor>(Context),
-        Name,
-        LinkageName,
-        unwrapDI<DIFile>(File),
-        LineNo,
-        unwrapDI<DIType>(Ty),
-        isLocalToUnit,
+  return wrap(Builder->createGlobalVariable(
+      unwrapDI<DIDescriptor>(Context), Name, LinkageName,
+      unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
 #if LLVM_VERSION_GE(4, 0)
-        InitExpr,
+      InitExpr,
 #else
-        InitVal,
+      InitVal,
 #endif
-        unwrapDIptr<MDNode>(Decl)
+      unwrapDIPtr<MDNode>(Decl)
 #if LLVM_VERSION_GE(4, 0)
-        , AlignInBits
+      ,
+      AlignInBits
 #endif
-    ));
+      ));
 }
 
 extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateVariable(
-    LLVMRustDIBuilderRef Builder,
-    unsigned Tag,
-    LLVMRustMetadataRef Scope,
-    const char* Name,
-    LLVMRustMetadataRef File,
-    unsigned LineNo,
-    LLVMRustMetadataRef Ty,
-    bool AlwaysPreserve,
-    LLVMRustDIFlags Flags,
-    unsigned ArgNo,
-    uint64_t AlignInBits)
-{
+    LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMRustMetadataRef Scope,
+    const char *Name, LLVMRustMetadataRef File, unsigned LineNo,
+    LLVMRustMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
+    unsigned ArgNo, uint64_t AlignInBits) {
 #if LLVM_VERSION_GE(3, 8)
-    if (Tag == 0x100) { // DW_TAG_auto_variable
-        return wrap(Builder->createAutoVariable(
-            unwrapDI<DIDescriptor>(Scope),
-            Name,
-            unwrapDI<DIFile>(File),
-            LineNo,
-            unwrapDI<DIType>(Ty),
-            AlwaysPreserve,
-            from_rust(Flags)
-#if LLVM_VERSION_GE(4,0)
-            , AlignInBits
+  if (Tag == 0x100) { // DW_TAG_auto_variable
+    return wrap(Builder->createAutoVariable(
+        unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNo,
+        unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)
+#if LLVM_VERSION_GE(4, 0)
+        ,
+	AlignInBits
 #endif
         ));
-    } else {
-        return wrap(Builder->createParameterVariable(
-            unwrapDI<DIDescriptor>(Scope), Name, ArgNo,
-            unwrapDI<DIFile>(File),
-            LineNo,
-            unwrapDI<DIType>(Ty), AlwaysPreserve, from_rust(Flags)));
-    }
+  } else {
+    return wrap(Builder->createParameterVariable(
+        unwrapDI<DIDescriptor>(Scope), Name, ArgNo, unwrapDI<DIFile>(File),
+        LineNo, unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
+  }
 #else
-    return wrap(Builder->createLocalVariable(Tag,
-        unwrapDI<DIDescriptor>(Scope), Name,
-        unwrapDI<DIFile>(File),
-        LineNo,
-        unwrapDI<DIType>(Ty), AlwaysPreserve, from_rust(Flags), ArgNo));
+  return wrap(Builder->createLocalVariable(
+      Tag, unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNo,
+      unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), ArgNo));
 #endif
 }
 
-extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateArrayType(
-    LLVMRustDIBuilderRef Builder,
-    uint64_t Size,
-    uint64_t AlignInBits,
-    LLVMRustMetadataRef Ty,
-    LLVMRustMetadataRef Subscripts) {
-    return wrap(Builder->createArrayType(Size, AlignInBits,
-        unwrapDI<DIType>(Ty),
-        DINodeArray(unwrapDI<MDTuple>(Subscripts))
-    ));
+extern "C" LLVMRustMetadataRef
+LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
+                                 uint64_t AlignInBits, LLVMRustMetadataRef Ty,
+                                 LLVMRustMetadataRef Subscripts) {
+  return wrap(
+      Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
+                               DINodeArray(unwrapDI<MDTuple>(Subscripts))));
 }
 
-extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateVectorType(
-    LLVMRustDIBuilderRef Builder,
-    uint64_t Size,
-    uint64_t AlignInBits,
-    LLVMRustMetadataRef Ty,
-    LLVMRustMetadataRef Subscripts) {
-    return wrap(Builder->createVectorType(Size, AlignInBits,
-        unwrapDI<DIType>(Ty),
-        DINodeArray(unwrapDI<MDTuple>(Subscripts))
-    ));
+extern "C" LLVMRustMetadataRef
+LLVMRustDIBuilderCreateVectorType(LLVMRustDIBuilderRef Builder, uint64_t Size,
+                                  uint64_t AlignInBits, LLVMRustMetadataRef Ty,
+                                  LLVMRustMetadataRef Subscripts) {
+  return wrap(
+      Builder->createVectorType(Size, AlignInBits, unwrapDI<DIType>(Ty),
+                                DINodeArray(unwrapDI<MDTuple>(Subscripts))));
 }
 
-extern "C" LLVMRustMetadataRef LLVMRustDIBuilderGetOrCreateSubrange(
-    LLVMRustDIBuilderRef Builder,
-    int64_t Lo,
-    int64_t Count) {
-    return wrap(Builder->getOrCreateSubrange(Lo, Count));
+extern "C" LLVMRustMetadataRef
+LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
+                                     int64_t Count) {
+  return wrap(Builder->getOrCreateSubrange(Lo, Count));
 }
 
-extern "C" LLVMRustMetadataRef LLVMRustDIBuilderGetOrCreateArray(
-    LLVMRustDIBuilderRef Builder,
-    LLVMRustMetadataRef* Ptr,
-    unsigned Count) {
-    Metadata **DataValue = unwrap(Ptr);
-    return wrap(Builder->getOrCreateArray(
-        ArrayRef<Metadata*>(DataValue, Count)).get());
+extern "C" LLVMRustMetadataRef
+LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
+                                  LLVMRustMetadataRef *Ptr, unsigned Count) {
+  Metadata **DataValue = unwrap(Ptr);
+  return wrap(
+      Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
 }
 
 extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
-    LLVMRustDIBuilderRef Builder,
-    LLVMValueRef Val,
-    LLVMRustMetadataRef VarInfo,
-    int64_t* AddrOps,
-    unsigned AddrOpsCount,
-    LLVMValueRef DL,
+    LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMRustMetadataRef VarInfo,
+    int64_t *AddrOps, unsigned AddrOpsCount, LLVMValueRef DL,
     LLVMBasicBlockRef InsertAtEnd) {
-    return wrap(Builder->insertDeclare(
-        unwrap(Val),
-        unwrap<DILocalVariable>(VarInfo),
-        Builder->createExpression(
-          llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
-        DebugLoc(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())),
-        unwrap(InsertAtEnd)));
-}
-
-extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateEnumerator(
-    LLVMRustDIBuilderRef Builder,
-    const char* Name,
-    uint64_t Val)
-{
-    return wrap(Builder->createEnumerator(Name, Val));
+  return wrap(Builder->insertDeclare(
+      unwrap(V), unwrap<DILocalVariable>(VarInfo),
+      Builder->createExpression(llvm::ArrayRef<int64_t>(AddrOps, AddrOpsCount)),
+      DebugLoc(cast<MDNode>(unwrap<MetadataAsValue>(DL)->getMetadata())),
+      unwrap(InsertAtEnd)));
+}
+
+extern "C" LLVMRustMetadataRef
+LLVMRustDIBuilderCreateEnumerator(LLVMRustDIBuilderRef Builder,
+                                  const char *Name, uint64_t Val) {
+  return wrap(Builder->createEnumerator(Name, Val));
 }
 
 extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateEnumerationType(
-    LLVMRustDIBuilderRef Builder,
-    LLVMRustMetadataRef Scope,
-    const char* Name,
-    LLVMRustMetadataRef File,
-    unsigned LineNumber,
-    uint64_t SizeInBits,
-    uint64_t AlignInBits,
-    LLVMRustMetadataRef Elements,
-    LLVMRustMetadataRef ClassType)
-{
-    return wrap(Builder->createEnumerationType(
-        unwrapDI<DIDescriptor>(Scope),
-        Name,
-        unwrapDI<DIFile>(File),
-        LineNumber,
-        SizeInBits,
-        AlignInBits,
-        DINodeArray(unwrapDI<MDTuple>(Elements)),
-        unwrapDI<DIType>(ClassType)));
+    LLVMRustDIBuilderRef Builder, LLVMRustMetadataRef Scope, const char *Name,
+    LLVMRustMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
+    uint64_t AlignInBits, LLVMRustMetadataRef Elements,
+    LLVMRustMetadataRef ClassTy) {
+  return wrap(Builder->createEnumerationType(
+      unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNumber,
+      SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
+      unwrapDI<DIType>(ClassTy)));
 }
 
 extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateUnionType(
-    LLVMRustDIBuilderRef Builder,
-    LLVMRustMetadataRef Scope,
-    const char* Name,
-    LLVMRustMetadataRef File,
-    unsigned LineNumber,
-    uint64_t SizeInBits,
-    uint64_t AlignInBits,
-    LLVMRustDIFlags Flags,
-    LLVMRustMetadataRef Elements,
-    unsigned RunTimeLang,
-    const char* UniqueId)
-{
-    return wrap(Builder->createUnionType(
-        unwrapDI<DIDescriptor>(Scope),
-        Name,
-        unwrapDI<DIFile>(File),
-        LineNumber,
-        SizeInBits,
-        AlignInBits,
-        from_rust(Flags),
-        DINodeArray(unwrapDI<MDTuple>(Elements)),
-        RunTimeLang,
-        UniqueId
-        ));
+    LLVMRustDIBuilderRef Builder, LLVMRustMetadataRef Scope, const char *Name,
+    LLVMRustMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
+    uint64_t AlignInBits, LLVMRustDIFlags Flags, LLVMRustMetadataRef Elements,
+    unsigned RunTimeLang, const char *UniqueId) {
+  return wrap(Builder->createUnionType(
+      unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNumber,
+      SizeInBits, AlignInBits, fromRust(Flags),
+      DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang, UniqueId));
 }
 
 extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
-    LLVMRustDIBuilderRef Builder,
-    LLVMRustMetadataRef Scope,
-    const char* Name,
-    LLVMRustMetadataRef Ty,
-    LLVMRustMetadataRef File,
-    unsigned LineNo,
-    unsigned ColumnNo)
-{
-    return wrap(Builder->createTemplateTypeParameter(
-      unwrapDI<DIDescriptor>(Scope),
-      Name,
-      unwrapDI<DIType>(Ty)
-      ));
-}
-
-extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateNameSpace(
-    LLVMRustDIBuilderRef Builder,
-    LLVMRustMetadataRef Scope,
-    const char* Name,
-    LLVMRustMetadataRef File,
-    unsigned LineNo)
-{
-    return wrap(Builder->createNameSpace(
-        unwrapDI<DIDescriptor>(Scope),
-        Name,
-        unwrapDI<DIFile>(File),
-        LineNo
+    LLVMRustDIBuilderRef Builder, LLVMRustMetadataRef Scope, const char *Name,
+    LLVMRustMetadataRef Ty, LLVMRustMetadataRef File, unsigned LineNo,
+    unsigned ColumnNo) {
+  return wrap(Builder->createTemplateTypeParameter(
+      unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIType>(Ty)));
+}
+
+extern "C" LLVMRustMetadataRef
+LLVMRustDIBuilderCreateNameSpace(LLVMRustDIBuilderRef Builder,
+                                 LLVMRustMetadataRef Scope, const char *Name,
+                                 LLVMRustMetadataRef File, unsigned LineNo) {
+  return wrap(Builder->createNameSpace(
+      unwrapDI<DIDescriptor>(Scope), Name, unwrapDI<DIFile>(File), LineNo
 #if LLVM_VERSION_GE(4, 0)
-        , false // ExportSymbols (only relevant for C++ anonymous namespaces)
+      ,
+      false // ExportSymbols (only relevant for C++ anonymous namespaces)
 #endif
-    ));
+      ));
 }
 
-extern "C" void LLVMRustDICompositeTypeSetTypeArray(
-    LLVMRustDIBuilderRef Builder,
-    LLVMRustMetadataRef CompositeType,
-    LLVMRustMetadataRef TypeArray)
-{
-    DICompositeType *tmp = unwrapDI<DICompositeType>(CompositeType);
-    Builder->replaceArrays(tmp, DINodeArray(unwrap<MDTuple>(TypeArray)));
+extern "C" void
+LLVMRustDICompositeTypeSetTypeArray(LLVMRustDIBuilderRef Builder,
+                                    LLVMRustMetadataRef CompositeTy,
+                                    LLVMRustMetadataRef TyArray) {
+  DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
+  Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(TyArray)));
 }
 
-extern "C" LLVMValueRef LLVMRustDIBuilderCreateDebugLocation(
-  LLVMContextRef Context,
-  unsigned Line,
-  unsigned Column,
-  LLVMRustMetadataRef Scope,
-  LLVMRustMetadataRef InlinedAt)
-{
-    LLVMContext& context = *unwrap(Context);
+extern "C" LLVMValueRef
+LLVMRustDIBuilderCreateDebugLocation(LLVMContextRef ContextRef, unsigned Line,
+                                     unsigned Column, LLVMRustMetadataRef Scope,
+                                     LLVMRustMetadataRef InlinedAt) {
+  LLVMContext &Context = *unwrap(ContextRef);
 
-    DebugLoc debug_loc = DebugLoc::get(Line,
-                                       Column,
-                                       unwrapDIptr<MDNode>(Scope),
-                                       unwrapDIptr<MDNode>(InlinedAt));
+  DebugLoc debug_loc = DebugLoc::get(Line, Column, unwrapDIPtr<MDNode>(Scope),
+                                     unwrapDIPtr<MDNode>(InlinedAt));
 
-    return wrap(MetadataAsValue::get(context, debug_loc.getAsMDNode()));
+  return wrap(MetadataAsValue::get(Context, debug_loc.getAsMDNode()));
 }
 
-extern "C" int64_t LLVMRustDIBuilderCreateOpDeref()
-{
-    return dwarf::DW_OP_deref;
+extern "C" int64_t LLVMRustDIBuilderCreateOpDeref() {
+  return dwarf::DW_OP_deref;
 }
 
-extern "C" int64_t LLVMRustDIBuilderCreateOpPlus()
-{
-    return dwarf::DW_OP_plus;
-}
+extern "C" int64_t LLVMRustDIBuilderCreateOpPlus() { return dwarf::DW_OP_plus; }
 
-extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Type, RustStringRef str) {
-    raw_rust_string_ostream os(str);
-    unwrap<llvm::Type>(Type)->print(os);
+extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
+  RawRustStringOstream OS(Str);
+  unwrap<llvm::Type>(Ty)->print(OS);
 }
 
-extern "C" void LLVMRustWriteValueToString(LLVMValueRef Value, RustStringRef str) {
-    raw_rust_string_ostream os(str);
-    os << "(";
-    unwrap<llvm::Value>(Value)->getType()->print(os);
-    os << ":";
-    unwrap<llvm::Value>(Value)->print(os);
-    os << ")";
+extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
+                                           RustStringRef Str) {
+  RawRustStringOstream OS(Str);
+  OS << "(";
+  unwrap<llvm::Value>(V)->getType()->print(OS);
+  OS << ":";
+  unwrap<llvm::Value>(V)->print(OS);
+  OS << ")";
 }
 
-extern "C" bool
-LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
-    Module *Dst = unwrap(dst);
+extern "C" bool LLVMRustLinkInExternalBitcode(LLVMModuleRef DstRef, char *BC,
+                                              size_t Len) {
+  Module *Dst = unwrap(DstRef);
 
-    std::unique_ptr<MemoryBuffer> buf = MemoryBuffer::getMemBufferCopy(StringRef(bc, len));
+  std::unique_ptr<MemoryBuffer> Buf =
+      MemoryBuffer::getMemBufferCopy(StringRef(BC, Len));
 
 #if LLVM_VERSION_GE(4, 0)
-    Expected<std::unique_ptr<Module>> SrcOrError =
-        llvm::getLazyBitcodeModule(buf->getMemBufferRef(), Dst->getContext());
-    if (!SrcOrError) {
-        LLVMRustSetLastError(toString(SrcOrError.takeError()).c_str());
-        return false;
-    }
+  Expected<std::unique_ptr<Module>> SrcOrError =
+      llvm::getLazyBitcodeModule(Buf->getMemBufferRef(), Dst->getContext());
+  if (!SrcOrError) {
+    LLVMRustSetLastError(toString(SrcOrError.takeError()).c_str());
+    return false;
+  }
 
-    auto Src = std::move(*SrcOrError);
+  auto Src = std::move(*SrcOrError);
 #else
-    ErrorOr<std::unique_ptr<Module>> Src =
-        llvm::getLazyBitcodeModule(std::move(buf), Dst->getContext());
-    if (!Src) {
-        LLVMRustSetLastError(Src.getError().message().c_str());
-        return false;
-    }
+  ErrorOr<std::unique_ptr<Module>> Src =
+      llvm::getLazyBitcodeModule(std::move(Buf), Dst->getContext());
+  if (!Src) {
+    LLVMRustSetLastError(Src.getError().message().c_str());
+    return false;
+  }
 #endif
 
-    std::string Err;
+  std::string Err;
 
-    raw_string_ostream Stream(Err);
-    DiagnosticPrinterRawOStream DP(Stream);
+  raw_string_ostream Stream(Err);
+  DiagnosticPrinterRawOStream DP(Stream);
 #if LLVM_VERSION_GE(4, 0)
-    if (Linker::linkModules(*Dst, std::move(Src))) {
+  if (Linker::linkModules(*Dst, std::move(Src))) {
 #elif LLVM_VERSION_GE(3, 8)
-    if (Linker::linkModules(*Dst, std::move(Src.get()))) {
+  if (Linker::linkModules(*Dst, std::move(Src.get()))) {
 #else
-    if (Linker::LinkModules(Dst, Src->get(), [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
+  if (Linker::LinkModules(Dst, Src->get(),
+                          [&](const DiagnosticInfo &DI) { DI.print(DP); })) {
 #endif
-        LLVMRustSetLastError(Err.c_str());
-        return false;
-    }
-    return true;
+    LLVMRustSetLastError(Err.c_str());
+    return false;
+  }
+  return true;
 }
 
 // Note that the two following functions look quite similar to the
@@ -980,127 +820,119 @@ LLVMRustLinkInExternalBitcode(LLVMModuleRef dst, char *bc, size_t len) {
 // that's returned.
 
 inline section_iterator *unwrap(LLVMSectionIteratorRef SI) {
-    return reinterpret_cast<section_iterator*>(SI);
+  return reinterpret_cast<section_iterator *>(SI);
 }
 
-extern "C" size_t
-LLVMRustGetSectionName(LLVMSectionIteratorRef SI, const char **ptr) {
-    StringRef ret;
-    if (std::error_code ec = (*unwrap(SI))->getName(ret))
-      report_fatal_error(ec.message());
-    *ptr = ret.data();
-    return ret.size();
+extern "C" size_t LLVMRustGetSectionName(LLVMSectionIteratorRef SI,
+                                         const char **Ptr) {
+  StringRef Ret;
+  if (std::error_code EC = (*unwrap(SI))->getName(Ret))
+    report_fatal_error(EC.message());
+  *Ptr = Ret.data();
+  return Ret.size();
 }
 
 // LLVMArrayType function does not support 64-bit ElementCount
-extern "C" LLVMTypeRef
-LLVMRustArrayType(LLVMTypeRef ElementType, uint64_t ElementCount) {
-    return wrap(ArrayType::get(unwrap(ElementType), ElementCount));
+extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
+                                         uint64_t ElementCount) {
+  return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
 }
 
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DebugLoc, LLVMDebugLocRef)
 
-extern "C" void
-LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef str) {
-    raw_rust_string_ostream os(str);
-    unwrap(T)->print(os);
+extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
+  RawRustStringOstream OS(Str);
+  unwrap(T)->print(OS);
 }
 
-extern "C" void
-LLVMRustUnpackOptimizationDiagnostic(
-    LLVMDiagnosticInfoRef di,
-    RustStringRef pass_name_out,
-    LLVMValueRef *function_out,
-    LLVMDebugLocRef *debugloc_out,
-    RustStringRef message_out)
-{
-    // Undefined to call this not on an optimization diagnostic!
-    llvm::DiagnosticInfoOptimizationBase *opt
-        = static_cast<llvm::DiagnosticInfoOptimizationBase*>(unwrap(di));
+extern "C" void LLVMRustUnpackOptimizationDiagnostic(
+    LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
+    LLVMValueRef *FunctionOut, LLVMDebugLocRef *DebugLocOut,
+    RustStringRef MessageOut) {
+  // Undefined to call this not on an optimization diagnostic!
+  llvm::DiagnosticInfoOptimizationBase *Opt =
+      static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
 
-    raw_rust_string_ostream pass_name_os(pass_name_out);
-    pass_name_os << opt->getPassName();
-    *function_out = wrap(&opt->getFunction());
-    *debugloc_out = wrap(&opt->getDebugLoc());
-    raw_rust_string_ostream message_os(message_out);
-    message_os << opt->getMsg();
+  RawRustStringOstream PassNameOS(PassNameOut);
+  PassNameOS << Opt->getPassName();
+  *FunctionOut = wrap(&Opt->getFunction());
+  *DebugLocOut = wrap(&Opt->getDebugLoc());
+  RawRustStringOstream MessageOS(MessageOut);
+  MessageOS << Opt->getMsg();
 }
 
 extern "C" void
-LLVMRustUnpackInlineAsmDiagnostic(
-    LLVMDiagnosticInfoRef di,
-    unsigned *cookie_out,
-    LLVMTwineRef *message_out,
-    LLVMValueRef *instruction_out)
-{
-    // Undefined to call this not on an inline assembly diagnostic!
-    llvm::DiagnosticInfoInlineAsm *ia
-        = static_cast<llvm::DiagnosticInfoInlineAsm*>(unwrap(di));
+LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI, unsigned *CookieOut,
+                                  LLVMTwineRef *MessageOut,
+                                  LLVMValueRef *InstructionOut) {
+  // Undefined to call this not on an inline assembly diagnostic!
+  llvm::DiagnosticInfoInlineAsm *IA =
+      static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
 
-    *cookie_out = ia->getLocCookie();
-    *message_out = wrap(&ia->getMsgStr());
-    *instruction_out = wrap(ia->getInstruction());
+  *CookieOut = IA->getLocCookie();
+  *MessageOut = wrap(&IA->getMsgStr());
+  *InstructionOut = wrap(IA->getInstruction());
 }
 
-extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef di, RustStringRef str) {
-    raw_rust_string_ostream os(str);
-    DiagnosticPrinterRawOStream dp(os);
-    unwrap(di)->print(dp);
+extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
+                                                    RustStringRef Str) {
+  RawRustStringOstream OS(Str);
+  DiagnosticPrinterRawOStream DP(OS);
+  unwrap(DI)->print(DP);
 }
 
 enum class LLVMRustDiagnosticKind {
-    Other,
-    InlineAsm,
-    StackSize,
-    DebugMetadataVersion,
-    SampleProfile,
-    OptimizationRemark,
-    OptimizationRemarkMissed,
-    OptimizationRemarkAnalysis,
-    OptimizationRemarkAnalysisFPCommute,
-    OptimizationRemarkAnalysisAliasing,
-    OptimizationRemarkOther,
-    OptimizationFailure,
+  Other,
+  InlineAsm,
+  StackSize,
+  DebugMetadataVersion,
+  SampleProfile,
+  OptimizationRemark,
+  OptimizationRemarkMissed,
+  OptimizationRemarkAnalysis,
+  OptimizationRemarkAnalysisFPCommute,
+  OptimizationRemarkAnalysisAliasing,
+  OptimizationRemarkOther,
+  OptimizationFailure,
 };
 
-static LLVMRustDiagnosticKind
-to_rust(DiagnosticKind kind)
-{
-    switch (kind) {
-    case DK_InlineAsm:
-        return LLVMRustDiagnosticKind::InlineAsm;
-    case DK_StackSize:
-        return LLVMRustDiagnosticKind::StackSize;
-    case DK_DebugMetadataVersion:
-        return LLVMRustDiagnosticKind::DebugMetadataVersion;
-    case DK_SampleProfile:
-        return LLVMRustDiagnosticKind::SampleProfile;
-    case DK_OptimizationRemark:
-        return LLVMRustDiagnosticKind::OptimizationRemark;
-    case DK_OptimizationRemarkMissed:
-        return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
-    case DK_OptimizationRemarkAnalysis:
-        return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
+static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
+  switch (Kind) {
+  case DK_InlineAsm:
+    return LLVMRustDiagnosticKind::InlineAsm;
+  case DK_StackSize:
+    return LLVMRustDiagnosticKind::StackSize;
+  case DK_DebugMetadataVersion:
+    return LLVMRustDiagnosticKind::DebugMetadataVersion;
+  case DK_SampleProfile:
+    return LLVMRustDiagnosticKind::SampleProfile;
+  case DK_OptimizationRemark:
+    return LLVMRustDiagnosticKind::OptimizationRemark;
+  case DK_OptimizationRemarkMissed:
+    return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
+  case DK_OptimizationRemarkAnalysis:
+    return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
 #if LLVM_VERSION_GE(3, 8)
-    case DK_OptimizationRemarkAnalysisFPCommute:
-        return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
-    case DK_OptimizationRemarkAnalysisAliasing:
-        return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
+  case DK_OptimizationRemarkAnalysisFPCommute:
+    return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
+  case DK_OptimizationRemarkAnalysisAliasing:
+    return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
 #endif
-    default:
+  default:
 #if LLVM_VERSION_GE(3, 9)
-        return (kind >= DK_FirstRemark && kind <= DK_LastRemark) ?
-            LLVMRustDiagnosticKind::OptimizationRemarkOther :
-            LLVMRustDiagnosticKind::Other;
+    return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
+               ? LLVMRustDiagnosticKind::OptimizationRemarkOther
+               : LLVMRustDiagnosticKind::Other;
 #else
-        return LLVMRustDiagnosticKind::Other;
+    return LLVMRustDiagnosticKind::Other;
 #endif
   }
 }
 
-extern "C" LLVMRustDiagnosticKind LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef di) {
-    return to_rust((DiagnosticKind) unwrap(di)->getKind());
+extern "C" LLVMRustDiagnosticKind
+LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
+  return toRust((DiagnosticKind)unwrap(DI)->getKind());
 }
 // This is kept distinct from LLVMGetTypeKind, because when
 // a new type kind is added, the Rust-side enum must be
@@ -1147,359 +979,334 @@ extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
   llvm_unreachable("Unhandled TypeID.");
 }
 
-extern "C" void LLVMRustWriteDebugLocToString(
-    LLVMContextRef C,
-    LLVMDebugLocRef dl,
-    RustStringRef str)
-{
-    raw_rust_string_ostream os(str);
-    unwrap(dl)->print(os);
+extern "C" void LLVMRustWriteDebugLocToString(LLVMContextRef C,
+                                              LLVMDebugLocRef DL,
+                                              RustStringRef Str) {
+  RawRustStringOstream OS(Str);
+  unwrap(DL)->print(OS);
 }
 
 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
 
 extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
-    LLVMContextRef C,
-    LLVMContext::InlineAsmDiagHandlerTy H,
-    void *CX)
-{
-    unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
+    LLVMContextRef C, LLVMContext::InlineAsmDiagHandlerTy H, void *CX) {
+  unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
 }
 
-extern "C" void LLVMRustWriteSMDiagnosticToString(LLVMSMDiagnosticRef d,
-						  RustStringRef str) {
-    raw_rust_string_ostream os(str);
-    unwrap(d)->print("", os);
+extern "C" void LLVMRustWriteSMDiagnosticToString(LLVMSMDiagnosticRef D,
+                                                  RustStringRef Str) {
+  RawRustStringOstream OS(Str);
+  unwrap(D)->print("", OS);
 }
 
 extern "C" LLVMValueRef
-LLVMRustBuildLandingPad(LLVMBuilderRef Builder,
-                        LLVMTypeRef Ty,
-                        LLVMValueRef PersFn,
-                        unsigned NumClauses,
-                        const char* Name,
-                        LLVMValueRef F) {
-    return LLVMBuildLandingPad(Builder, Ty, PersFn, NumClauses, Name);
+LLVMRustBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty,
+                        LLVMValueRef PersFn, unsigned NumClauses,
+                        const char *Name, LLVMValueRef F) {
+  return LLVMBuildLandingPad(B, Ty, PersFn, NumClauses, Name);
 }
 
-extern "C" LLVMValueRef
-LLVMRustBuildCleanupPad(LLVMBuilderRef Builder,
-                        LLVMValueRef ParentPad,
-                        unsigned ArgCnt,
-                        LLVMValueRef *LLArgs,
-                        const char *Name) {
+extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
+                                                LLVMValueRef ParentPad,
+                                                unsigned ArgCount,
+                                                LLVMValueRef *LLArgs,
+                                                const char *Name) {
 #if LLVM_VERSION_GE(3, 8)
-    Value **Args = unwrap(LLArgs);
-    if (ParentPad == NULL) {
-        Type *Ty = Type::getTokenTy(unwrap(Builder)->getContext());
-        ParentPad = wrap(Constant::getNullValue(Ty));
-    }
-    return wrap(unwrap(Builder)->CreateCleanupPad(unwrap(ParentPad),
-                                                  ArrayRef<Value*>(Args, ArgCnt),
-                                                  Name));
+  Value **Args = unwrap(LLArgs);
+  if (ParentPad == nullptr) {
+    Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
+    ParentPad = wrap(Constant::getNullValue(Ty));
+  }
+  return wrap(unwrap(B)->CreateCleanupPad(
+      unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
 #else
-    return NULL;
+  return nullptr;
 #endif
 }
 
-extern "C" LLVMValueRef
-LLVMRustBuildCleanupRet(LLVMBuilderRef Builder,
-                        LLVMValueRef CleanupPad,
-                        LLVMBasicBlockRef UnwindBB) {
+extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
+                                                LLVMValueRef CleanupPad,
+                                                LLVMBasicBlockRef UnwindBB) {
 #if LLVM_VERSION_GE(3, 8)
-    CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
-    return wrap(unwrap(Builder)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
+  CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
+  return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
 #else
-    return NULL;
+  return nullptr;
 #endif
 }
 
 extern "C" LLVMValueRef
-LLVMRustBuildCatchPad(LLVMBuilderRef Builder,
-                      LLVMValueRef ParentPad,
-                      unsigned ArgCnt,
-                      LLVMValueRef *LLArgs,
-                      const char *Name) {
+LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
+                      unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
 #if LLVM_VERSION_GE(3, 8)
-    Value **Args = unwrap(LLArgs);
-    return wrap(unwrap(Builder)->CreateCatchPad(unwrap(ParentPad),
-                                                ArrayRef<Value*>(Args, ArgCnt),
-                                                Name));
+  Value **Args = unwrap(LLArgs);
+  return wrap(unwrap(B)->CreateCatchPad(
+      unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
 #else
-    return NULL;
+  return nullptr;
 #endif
 }
 
-extern "C" LLVMValueRef
-LLVMRustBuildCatchRet(LLVMBuilderRef Builder,
-                      LLVMValueRef Pad,
-                      LLVMBasicBlockRef BB) {
+extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
+                                              LLVMValueRef Pad,
+                                              LLVMBasicBlockRef BB) {
 #if LLVM_VERSION_GE(3, 8)
-    return wrap(unwrap(Builder)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
-                                                unwrap(BB)));
+  return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
+                                              unwrap(BB)));
 #else
-    return NULL;
+  return nullptr;
 #endif
 }
 
-extern "C" LLVMValueRef
-LLVMRustBuildCatchSwitch(LLVMBuilderRef Builder,
-                         LLVMValueRef ParentPad,
-                         LLVMBasicBlockRef BB,
-                         unsigned NumHandlers,
-                         const char *Name) {
+extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
+                                                 LLVMValueRef ParentPad,
+                                                 LLVMBasicBlockRef BB,
+                                                 unsigned NumHandlers,
+                                                 const char *Name) {
 #if LLVM_VERSION_GE(3, 8)
-    if (ParentPad == NULL) {
-        Type *Ty = Type::getTokenTy(unwrap(Builder)->getContext());
-        ParentPad = wrap(Constant::getNullValue(Ty));
-    }
-    return wrap(unwrap(Builder)->CreateCatchSwitch(unwrap(ParentPad),
-                                                   unwrap(BB),
-                                                   NumHandlers,
-                                                   Name));
+  if (ParentPad == nullptr) {
+    Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
+    ParentPad = wrap(Constant::getNullValue(Ty));
+  }
+  return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
+                                                 NumHandlers, Name));
 #else
-    return NULL;
+  return nullptr;
 #endif
 }
 
-extern "C" void
-LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
-                   LLVMBasicBlockRef Handler) {
+extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
+                                   LLVMBasicBlockRef Handler) {
 #if LLVM_VERSION_GE(3, 8)
-    Value *CatchSwitch = unwrap(CatchSwitchRef);
-    cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
+  Value *CatchSwitch = unwrap(CatchSwitchRef);
+  cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
 #endif
 }
 
-extern "C" void
-LLVMRustSetPersonalityFn(LLVMBuilderRef B,
-                         LLVMValueRef Personality) {
+extern "C" void LLVMRustSetPersonalityFn(LLVMBuilderRef B,
+                                         LLVMValueRef Personality) {
 #if LLVM_VERSION_GE(3, 8)
-    unwrap(B)->GetInsertBlock()
-             ->getParent()
-             ->setPersonalityFn(cast<Function>(unwrap(Personality)));
+  unwrap(B)->GetInsertBlock()->getParent()->setPersonalityFn(
+      cast<Function>(unwrap(Personality)));
 #endif
 }
 
 #if LLVM_VERSION_GE(3, 8)
-extern "C" OperandBundleDef*
-LLVMRustBuildOperandBundleDef(const char *Name,
-                              LLVMValueRef *Inputs,
-                              unsigned NumInputs) {
+extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
+                                                           LLVMValueRef *Inputs,
+                                                           unsigned NumInputs) {
   return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
 }
 
-extern "C" void
-LLVMRustFreeOperandBundleDef(OperandBundleDef* Bundle) {
+extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
   delete Bundle;
 }
 
-extern "C" LLVMValueRef
-LLVMRustBuildCall(LLVMBuilderRef B,
-                    LLVMValueRef Fn,
-                    LLVMValueRef *Args,
-                    unsigned NumArgs,
-                    OperandBundleDef *Bundle,
-                    const char *Name) {
-    unsigned len = Bundle ? 1 : 0;
-    ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, len);
-    return wrap(unwrap(B)->CreateCall(unwrap(Fn),
-                                      makeArrayRef(unwrap(Args), NumArgs),
-                                      Bundles,
-                                      Name));
+extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMValueRef Fn,
+                                          LLVMValueRef *Args, unsigned NumArgs,
+                                          OperandBundleDef *Bundle,
+                                          const char *Name) {
+  unsigned Len = Bundle ? 1 : 0;
+  ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
+  return wrap(unwrap(B)->CreateCall(
+      unwrap(Fn), makeArrayRef(unwrap(Args), NumArgs), Bundles, Name));
 }
 
 extern "C" LLVMValueRef
-LLVMRustBuildInvoke(LLVMBuilderRef B,
-                    LLVMValueRef Fn,
-                    LLVMValueRef *Args,
-                    unsigned NumArgs,
-                    LLVMBasicBlockRef Then,
-                    LLVMBasicBlockRef Catch,
-                    OperandBundleDef *Bundle,
+LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
+                    unsigned NumArgs, LLVMBasicBlockRef Then,
+                    LLVMBasicBlockRef Catch, OperandBundleDef *Bundle,
                     const char *Name) {
-    unsigned len = Bundle ? 1 : 0;
-    ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, len);
-    return wrap(unwrap(B)->CreateInvoke(unwrap(Fn), unwrap(Then), unwrap(Catch),
-                                        makeArrayRef(unwrap(Args), NumArgs),
-                                        Bundles,
-                                        Name));
+  unsigned Len = Bundle ? 1 : 0;
+  ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
+  return wrap(unwrap(B)->CreateInvoke(unwrap(Fn), unwrap(Then), unwrap(Catch),
+                                      makeArrayRef(unwrap(Args), NumArgs),
+                                      Bundles, Name));
 }
 #else
-extern "C" void*
-LLVMRustBuildOperandBundleDef(const char *Name,
-                              LLVMValueRef *Inputs,
-                              unsigned NumInputs) {
-  return NULL;
+extern "C" void *LLVMRustBuildOperandBundleDef(const char *Name,
+                                               LLVMValueRef *Inputs,
+                                               unsigned NumInputs) {
+  return nullptr;
 }
 
-extern "C" void
-LLVMRustFreeOperandBundleDef(void* Bundle) {
-}
+extern "C" void LLVMRustFreeOperandBundleDef(void *Bundle) {}
 
-extern "C" LLVMValueRef
-LLVMRustBuildCall(LLVMBuilderRef B,
-                    LLVMValueRef Fn,
-                    LLVMValueRef *Args,
-                    unsigned NumArgs,
-                    void *Bundle,
-                    const char *Name) {
-    return LLVMBuildCall(B, Fn, Args, NumArgs, Name);
+extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMValueRef Fn,
+                                          LLVMValueRef *Args, unsigned NumArgs,
+                                          void *Bundle, const char *Name) {
+  return LLVMBuildCall(B, Fn, Args, NumArgs, Name);
 }
 
 extern "C" LLVMValueRef
-LLVMRustBuildInvoke(LLVMBuilderRef B,
-                    LLVMValueRef Fn,
-                    LLVMValueRef *Args,
-                    unsigned NumArgs,
-                    LLVMBasicBlockRef Then,
-                    LLVMBasicBlockRef Catch,
-                    void *Bundle,
-                    const char *Name) {
-    return LLVMBuildInvoke(B, Fn, Args, NumArgs, Then, Catch, Name);
+LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
+                    unsigned NumArgs, LLVMBasicBlockRef Then,
+                    LLVMBasicBlockRef Catch, void *Bundle, const char *Name) {
+  return LLVMBuildInvoke(B, Fn, Args, NumArgs, Then, Catch, Name);
 }
 #endif
 
-extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B, LLVMBasicBlockRef BB) {
-    auto point = unwrap(BB)->getFirstInsertionPt();
-    unwrap(B)->SetInsertPoint(unwrap(BB), point);
+extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
+                                               LLVMBasicBlockRef BB) {
+  auto Point = unwrap(BB)->getFirstInsertionPt();
+  unwrap(B)->SetInsertPoint(unwrap(BB), Point);
 }
 
-extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V, const char *Name) {
-    Triple TargetTriple(unwrap(M)->getTargetTriple());
-    GlobalObject *GV = unwrap<GlobalObject>(V);
-    if (!TargetTriple.isOSBinFormatMachO()) {
-        GV->setComdat(unwrap(M)->getOrInsertComdat(Name));
-    }
+extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
+                                  const char *Name) {
+  Triple TargetTriple(unwrap(M)->getTargetTriple());
+  GlobalObject *GV = unwrap<GlobalObject>(V);
+  if (!TargetTriple.isOSBinFormatMachO()) {
+    GV->setComdat(unwrap(M)->getOrInsertComdat(Name));
+  }
 }
 
 extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
-    GlobalObject *GV = unwrap<GlobalObject>(V);
-    GV->setComdat(nullptr);
+  GlobalObject *GV = unwrap<GlobalObject>(V);
+  GV->setComdat(nullptr);
 }
 
 enum class LLVMRustLinkage {
-    ExternalLinkage = 0,
-    AvailableExternallyLinkage = 1,
-    LinkOnceAnyLinkage = 2,
-    LinkOnceODRLinkage = 3,
-    WeakAnyLinkage = 4,
-    WeakODRLinkage = 5,
-    AppendingLinkage = 6,
-    InternalLinkage = 7,
-    PrivateLinkage = 8,
-    ExternalWeakLinkage = 9,
-    CommonLinkage = 10,
+  ExternalLinkage = 0,
+  AvailableExternallyLinkage = 1,
+  LinkOnceAnyLinkage = 2,
+  LinkOnceODRLinkage = 3,
+  WeakAnyLinkage = 4,
+  WeakODRLinkage = 5,
+  AppendingLinkage = 6,
+  InternalLinkage = 7,
+  PrivateLinkage = 8,
+  ExternalWeakLinkage = 9,
+  CommonLinkage = 10,
 };
 
-static LLVMRustLinkage to_rust(LLVMLinkage linkage) {
-    switch (linkage) {
-        case LLVMExternalLinkage:
-            return LLVMRustLinkage::ExternalLinkage;
-        case LLVMAvailableExternallyLinkage:
-            return LLVMRustLinkage::AvailableExternallyLinkage;
-        case LLVMLinkOnceAnyLinkage:
-            return LLVMRustLinkage::LinkOnceAnyLinkage;
-        case LLVMLinkOnceODRLinkage:
-            return LLVMRustLinkage::LinkOnceODRLinkage;
-        case LLVMWeakAnyLinkage:
-            return LLVMRustLinkage::WeakAnyLinkage;
-        case LLVMWeakODRLinkage:
-            return LLVMRustLinkage::WeakODRLinkage;
-        case LLVMAppendingLinkage:
-            return LLVMRustLinkage::AppendingLinkage;
-        case LLVMInternalLinkage:
-            return LLVMRustLinkage::InternalLinkage;
-        case LLVMPrivateLinkage:
-            return LLVMRustLinkage::PrivateLinkage;
-        case LLVMExternalWeakLinkage:
-            return LLVMRustLinkage::ExternalWeakLinkage;
-        case LLVMCommonLinkage:
-            return LLVMRustLinkage::CommonLinkage;
-        default:
-            llvm_unreachable("Invalid LLVMRustLinkage value!");
-    }
+static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
+  switch (Linkage) {
+  case LLVMExternalLinkage:
+    return LLVMRustLinkage::ExternalLinkage;
+  case LLVMAvailableExternallyLinkage:
+    return LLVMRustLinkage::AvailableExternallyLinkage;
+  case LLVMLinkOnceAnyLinkage:
+    return LLVMRustLinkage::LinkOnceAnyLinkage;
+  case LLVMLinkOnceODRLinkage:
+    return LLVMRustLinkage::LinkOnceODRLinkage;
+  case LLVMWeakAnyLinkage:
+    return LLVMRustLinkage::WeakAnyLinkage;
+  case LLVMWeakODRLinkage:
+    return LLVMRustLinkage::WeakODRLinkage;
+  case LLVMAppendingLinkage:
+    return LLVMRustLinkage::AppendingLinkage;
+  case LLVMInternalLinkage:
+    return LLVMRustLinkage::InternalLinkage;
+  case LLVMPrivateLinkage:
+    return LLVMRustLinkage::PrivateLinkage;
+  case LLVMExternalWeakLinkage:
+    return LLVMRustLinkage::ExternalWeakLinkage;
+  case LLVMCommonLinkage:
+    return LLVMRustLinkage::CommonLinkage;
+  default:
+    llvm_unreachable("Invalid LLVMRustLinkage value!");
+  }
 }
 
-static LLVMLinkage from_rust(LLVMRustLinkage linkage) {
-    switch (linkage) {
-        case LLVMRustLinkage::ExternalLinkage:
-            return LLVMExternalLinkage;
-        case LLVMRustLinkage::AvailableExternallyLinkage:
-            return LLVMAvailableExternallyLinkage;
-        case LLVMRustLinkage::LinkOnceAnyLinkage:
-            return LLVMLinkOnceAnyLinkage;
-        case LLVMRustLinkage::LinkOnceODRLinkage:
-            return LLVMLinkOnceODRLinkage;
-        case LLVMRustLinkage::WeakAnyLinkage:
-            return LLVMWeakAnyLinkage;
-        case LLVMRustLinkage::WeakODRLinkage:
-            return LLVMWeakODRLinkage;
-        case LLVMRustLinkage::AppendingLinkage:
-            return LLVMAppendingLinkage;
-        case LLVMRustLinkage::InternalLinkage:
-            return LLVMInternalLinkage;
-        case LLVMRustLinkage::PrivateLinkage:
-            return LLVMPrivateLinkage;
-        case LLVMRustLinkage::ExternalWeakLinkage:
-            return LLVMExternalWeakLinkage;
-        case LLVMRustLinkage::CommonLinkage:
-            return LLVMCommonLinkage;
-        default:
-            llvm_unreachable("Invalid LLVMRustLinkage value!");
-    }
+static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
+  switch (Linkage) {
+  case LLVMRustLinkage::ExternalLinkage:
+    return LLVMExternalLinkage;
+  case LLVMRustLinkage::AvailableExternallyLinkage:
+    return LLVMAvailableExternallyLinkage;
+  case LLVMRustLinkage::LinkOnceAnyLinkage:
+    return LLVMLinkOnceAnyLinkage;
+  case LLVMRustLinkage::LinkOnceODRLinkage:
+    return LLVMLinkOnceODRLinkage;
+  case LLVMRustLinkage::WeakAnyLinkage:
+    return LLVMWeakAnyLinkage;
+  case LLVMRustLinkage::WeakODRLinkage:
+    return LLVMWeakODRLinkage;
+  case LLVMRustLinkage::AppendingLinkage:
+    return LLVMAppendingLinkage;
+  case LLVMRustLinkage::InternalLinkage:
+    return LLVMInternalLinkage;
+  case LLVMRustLinkage::PrivateLinkage:
+    return LLVMPrivateLinkage;
+  case LLVMRustLinkage::ExternalWeakLinkage:
+    return LLVMExternalWeakLinkage;
+  case LLVMRustLinkage::CommonLinkage:
+    return LLVMCommonLinkage;
+  default:
+    llvm_unreachable("Invalid LLVMRustLinkage value!");
+  }
 }
 
 extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
-    return to_rust(LLVMGetLinkage(V));
+  return toRust(LLVMGetLinkage(V));
 }
 
-extern "C" void LLVMRustSetLinkage(LLVMValueRef V, LLVMRustLinkage RustLinkage) {
-    LLVMSetLinkage(V, from_rust(RustLinkage));
+extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
+                                   LLVMRustLinkage RustLinkage) {
+  LLVMSetLinkage(V, fromRust(RustLinkage));
+}
+
+// Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
+// the common sizes (1, 8, 16, 32, 64, 128 bits)
+extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
+{
+    auto C = unwrap<llvm::ConstantInt>(CV);
+    if (C->getBitWidth() > 128) { return false; }
+    APInt AP;
+    if (sext) {
+        AP = C->getValue().sextOrSelf(128);
+    } else {
+        AP = C->getValue().zextOrSelf(128);
+    }
+    *low = AP.getLoBits(64).getZExtValue();
+    *high = AP.getHiBits(64).getZExtValue();
+    return true;
 }
 
 extern "C" LLVMContextRef LLVMRustGetValueContext(LLVMValueRef V) {
-    return wrap(&unwrap(V)->getContext());
+  return wrap(&unwrap(V)->getContext());
 }
 
 enum class LLVMRustVisibility {
-    Default = 0,
-    Hidden = 1,
-    Protected = 2,
+  Default = 0,
+  Hidden = 1,
+  Protected = 2,
 };
 
-static LLVMRustVisibility to_rust(LLVMVisibility vis) {
-    switch (vis) {
-        case LLVMDefaultVisibility:
-            return LLVMRustVisibility::Default;
-        case LLVMHiddenVisibility:
-            return LLVMRustVisibility::Hidden;
-        case LLVMProtectedVisibility:
-            return LLVMRustVisibility::Protected;
-
-        default:
-            llvm_unreachable("Invalid LLVMRustVisibility value!");
-    }
+static LLVMRustVisibility toRust(LLVMVisibility Vis) {
+  switch (Vis) {
+  case LLVMDefaultVisibility:
+    return LLVMRustVisibility::Default;
+  case LLVMHiddenVisibility:
+    return LLVMRustVisibility::Hidden;
+  case LLVMProtectedVisibility:
+    return LLVMRustVisibility::Protected;
+
+  default:
+    llvm_unreachable("Invalid LLVMRustVisibility value!");
+  }
 }
 
-static LLVMVisibility from_rust(LLVMRustVisibility vis) {
-    switch (vis) {
-        case LLVMRustVisibility::Default:
-            return LLVMDefaultVisibility;
-        case LLVMRustVisibility::Hidden:
-            return LLVMHiddenVisibility;
-        case LLVMRustVisibility::Protected:
-            return LLVMProtectedVisibility;
+static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
+  switch (Vis) {
+  case LLVMRustVisibility::Default:
+    return LLVMDefaultVisibility;
+  case LLVMRustVisibility::Hidden:
+    return LLVMHiddenVisibility;
+  case LLVMRustVisibility::Protected:
+    return LLVMProtectedVisibility;
 
-        default:
-            llvm_unreachable("Invalid LLVMRustVisibility value!");
-    }
+  default:
+    llvm_unreachable("Invalid LLVMRustVisibility value!");
+  }
 }
 
 extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
-    return to_rust(LLVMGetVisibility(V));
+  return toRust(LLVMGetVisibility(V));
 }
 
-extern "C" void LLVMRustSetVisibility(LLVMValueRef V, LLVMRustVisibility RustVisibility) {
-    LLVMSetVisibility(V, from_rust(RustVisibility));
+extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
+                                      LLVMRustVisibility RustVisibility) {
+  LLVMSetVisibility(V, fromRust(RustVisibility));
 }
diff --git a/src/rustllvm/rustllvm.h b/src/rustllvm/rustllvm.h
index 8f7e0e3d918..a30fa3133e2 100644
--- a/src/rustllvm/rustllvm.h
+++ b/src/rustllvm/rustllvm.h
@@ -8,50 +8,52 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#include "llvm-c/BitReader.h"
+#include "llvm-c/Core.h"
+#include "llvm-c/ExecutionEngine.h"
+#include "llvm-c/Object.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Analysis/Lint.h"
+#include "llvm/Analysis/Passes.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/Interpreter.h"
+#include "llvm/ExecutionEngine/MCJIT.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/InlineAsm.h"
-#include "llvm/IR/LLVMContext.h"
-#include "llvm/IR/Module.h"
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/LLVMContext.h"
-#include "llvm/Analysis/Passes.h"
-#include "llvm/Analysis/Lint.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/ADT/DenseSet.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
 #include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/Timer.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/TargetSelect.h"
-#include "llvm/Support/TargetRegistry.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/Host.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/Host.h"
 #include "llvm/Support/Memory.h"
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/ExecutionEngine/MCJIT.h"
-#include "llvm/ExecutionEngine/Interpreter.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Target/TargetOptions.h"
-#include "llvm/Transforms/Scalar.h"
 #include "llvm/Transforms/IPO.h"
 #include "llvm/Transforms/Instrumentation.h"
+#include "llvm/Transforms/Scalar.h"
 #include "llvm/Transforms/Vectorize.h"
-#include "llvm-c/Core.h"
-#include "llvm-c/BitReader.h"
-#include "llvm-c/ExecutionEngine.h"
-#include "llvm-c/Object.h"
 
-#define LLVM_VERSION_GE(major, minor) \
-  (LLVM_VERSION_MAJOR > (major) || LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR >= (minor))
+#define LLVM_VERSION_GE(major, minor)                                          \
+  (LLVM_VERSION_MAJOR > (major) ||                                             \
+   LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR >= (minor))
 
-#define LLVM_VERSION_EQ(major, minor) \
+#define LLVM_VERSION_EQ(major, minor)                                          \
   (LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR == (minor))
 
-#define LLVM_VERSION_LE(major, minor) \
-  (LLVM_VERSION_MAJOR < (major) || LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR <= (minor))
+#define LLVM_VERSION_LE(major, minor)                                          \
+  (LLVM_VERSION_MAJOR < (major) ||                                             \
+   LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR <= (minor))
 
 #if LLVM_VERSION_GE(3, 7)
 #include "llvm/IR/LegacyPassManager.h"
@@ -66,39 +68,36 @@
 #include "llvm/Bitcode/ReaderWriter.h"
 #endif
 
-#include "llvm/IR/IRPrintingPasses.h"
-#include "llvm/IR/DebugInfo.h"
 #include "llvm/IR/DIBuilder.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/IRPrintingPasses.h"
 #include "llvm/Linker/Linker.h"
 
-void LLVMRustSetLastError(const char*);
+void LLVMRustSetLastError(const char *);
 
-enum class LLVMRustResult {
-    Success,
-    Failure
-};
+enum class LLVMRustResult { Success, Failure };
 
 enum LLVMRustAttribute {
-    AlwaysInline    = 0,
-    ByVal           = 1,
-    Cold            = 2,
-    InlineHint      = 3,
-    MinSize         = 4,
-    Naked           = 5,
-    NoAlias         = 6,
-    NoCapture       = 7,
-    NoInline        = 8,
-    NonNull         = 9,
-    NoRedZone       = 10,
-    NoReturn        = 11,
-    NoUnwind        = 12,
-    OptimizeForSize = 13,
-    ReadOnly        = 14,
-    SExt            = 15,
-    StructRet       = 16,
-    UWTable         = 17,
-    ZExt            = 18,
-    InReg           = 19,
+  AlwaysInline = 0,
+  ByVal = 1,
+  Cold = 2,
+  InlineHint = 3,
+  MinSize = 4,
+  Naked = 5,
+  NoAlias = 6,
+  NoCapture = 7,
+  NoInline = 8,
+  NonNull = 9,
+  NoRedZone = 10,
+  NoReturn = 11,
+  NoUnwind = 12,
+  OptimizeForSize = 13,
+  ReadOnly = 14,
+  SExt = 15,
+  StructRet = 16,
+  UWTable = 17,
+  ZExt = 18,
+  InReg = 19,
 };
 
 typedef struct OpaqueRustString *RustStringRef;
@@ -107,28 +106,25 @@ typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef;
 typedef struct LLVMOpaqueSMDiagnostic *LLVMSMDiagnosticRef;
 typedef struct LLVMOpaqueRustJITMemoryManager *LLVMRustJITMemoryManagerRef;
 
-extern "C" void
-rust_llvm_string_write_impl(RustStringRef str, const char *ptr, size_t size);
+extern "C" void LLVMRustStringWriteImpl(RustStringRef Str, const char *Ptr,
+                                        size_t Size);
 
-class raw_rust_string_ostream : public llvm::raw_ostream  {
-    RustStringRef str;
-    uint64_t pos;
+class RawRustStringOstream : public llvm::raw_ostream {
+  RustStringRef Str;
+  uint64_t Pos;
 
-    void write_impl(const char *ptr, size_t size) override {
-        rust_llvm_string_write_impl(str, ptr, size);
-        pos += size;
-    }
+  void write_impl(const char *Ptr, size_t Size) override {
+    LLVMRustStringWriteImpl(Str, Ptr, Size);
+    Pos += Size;
+  }
 
-    uint64_t current_pos() const override {
-        return pos;
-    }
+  uint64_t current_pos() const override { return Pos; }
 
 public:
-    explicit raw_rust_string_ostream(RustStringRef str)
-        : str(str), pos(0) { }
+  explicit RawRustStringOstream(RustStringRef Str) : Str(Str), Pos(0) {}
 
-    ~raw_rust_string_ostream() {
-        // LLVM requires this.
-        flush();
-    }
+  ~RawRustStringOstream() {
+    // LLVM requires this.
+    flush();
+  }
 };
diff --git a/src/test/compile-fail/const-tup-index-span.rs b/src/test/compile-fail/const-tup-index-span.rs
index 8f7ec9de58a..f3fb92e2b22 100644
--- a/src/test/compile-fail/const-tup-index-span.rs
+++ b/src/test/compile-fail/const-tup-index-span.rs
@@ -10,7 +10,7 @@
 
 // Test spans of errors
 
-const TUP: (usize,) = 5 << 64;
+const TUP: (usize,) = 5usize << 64;
 //~^ ERROR E0080
 //~| attempt to shift left with overflow
 const ARR: [i32; TUP.0] = [];
diff --git a/src/test/compile-fail/i128-feature-2.rs b/src/test/compile-fail/i128-feature-2.rs
new file mode 100644
index 00000000000..4a76d399218
--- /dev/null
+++ b/src/test/compile-fail/i128-feature-2.rs
@@ -0,0 +1,29 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+fn test1() -> i128 { //~ ERROR 128-bit type is unstable
+    0
+}
+
+fn test1_2() -> u128 { //~ ERROR 128-bit type is unstable
+    0
+}
+
+fn test3() {
+    let x: i128 = 0; //~ ERROR 128-bit type is unstable
+}
+
+fn test3_2() {
+    let x: u128 = 0; //~ ERROR 128-bit type is unstable
+}
+
+#[repr(u128)]
+enum A { //~ ERROR 128-bit type is unstable
+    A(u64)
+}
diff --git a/src/test/compile-fail/i128-feature.rs b/src/test/compile-fail/i128-feature.rs
new file mode 100644
index 00000000000..87dda469f93
--- /dev/null
+++ b/src/test/compile-fail/i128-feature.rs
@@ -0,0 +1,17 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+fn test2() {
+    0i128; //~ ERROR 128-bit integers are not stable
+}
+
+fn test2_2() {
+    0u128; //~ ERROR 128-bit integers are not stable
+}
+
diff --git a/src/test/compile-fail/oversized-literal.rs b/src/test/compile-fail/unadjusted-unstable.rs
index 5416bcacf3d..501f4451ed8 100644
--- a/src/test/compile-fail/oversized-literal.rs
+++ b/src/test/compile-fail/unadjusted-unstable.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,6 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+extern "unadjusted" fn foo() {
+//~^ ERROR: unadjusted ABI is an implementation detail and perma-unstable
+}
+
 fn main() {
-    println!("{}", 18446744073709551616u64);  //~ error: int literal is too large
+    foo();
 }
diff --git a/src/test/debuginfo/issue12886.rs b/src/test/debuginfo/issue-12886.rs
index c30ee92dc53..c30ee92dc53 100644
--- a/src/test/debuginfo/issue12886.rs
+++ b/src/test/debuginfo/issue-12886.rs
diff --git a/src/test/debuginfo/issue13213.rs b/src/test/debuginfo/issue-13213.rs
index 67975d02b19..67975d02b19 100644
--- a/src/test/debuginfo/issue13213.rs
+++ b/src/test/debuginfo/issue-13213.rs
diff --git a/src/test/debuginfo/issue14411.rs b/src/test/debuginfo/issue-14411.rs
index d334e33f887..d334e33f887 100644
--- a/src/test/debuginfo/issue14411.rs
+++ b/src/test/debuginfo/issue-14411.rs
diff --git a/src/test/debuginfo/issue22656.rs b/src/test/debuginfo/issue-22656.rs
index a971e06ed5e..a971e06ed5e 100644
--- a/src/test/debuginfo/issue22656.rs
+++ b/src/test/debuginfo/issue-22656.rs
diff --git a/src/test/debuginfo/issue7712.rs b/src/test/debuginfo/issue-7712.rs
index 124cdfb436c..124cdfb436c 100644
--- a/src/test/debuginfo/issue7712.rs
+++ b/src/test/debuginfo/issue-7712.rs
diff --git a/src/test/debuginfo/union-smoke.rs b/src/test/debuginfo/union-smoke.rs
index ada9e0b30cc..5d3fbd62023 100644
--- a/src/test/debuginfo/union-smoke.rs
+++ b/src/test/debuginfo/union-smoke.rs
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 // min-lldb-version: 310
-// ignore-macos FIXME(#37479)
 
 // compile-flags:-g
 
@@ -27,9 +26,9 @@
 
 // lldb-command:run
 // lldb-command:print u
-// lldb-check:[...]$0 = { a = ('\x02', '\x02') b = 514 }
+// lldb-check:[...]$0 = U { a: ('\x02', '\x02'), b: 514 }
 // lldb-command:print union_smoke::SU
-// lldb-check:[...]$1 = 257
+// lldb-check:[...]$1 = U { a: ('\x01', '\x01'), b: 257 }
 
 #![allow(unused)]
 #![feature(omit_gdb_pretty_printer_section)]
diff --git a/src/test/debuginfo/unsized.rs b/src/test/debuginfo/unsized.rs
new file mode 100644
index 00000000000..b0ce335a8d9
--- /dev/null
+++ b/src/test/debuginfo/unsized.rs
@@ -0,0 +1,45 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags:-g
+
+// === GDB TESTS ===================================================================================
+
+// gdb-command:run
+
+// gdb-command:print *a
+// gdbg-check:$1 = {value = [...] "abc"}
+// gdbr-check:$1 = unsized::Foo<[u8]> {value: [...]}
+
+// gdb-command:print *b
+// gdbg-check:$2 = {value = {value = [...] "abc"}}
+// gdbr-check:$2 = unsized::Foo<unsized::Foo<[u8]>> {value: unsized::Foo<[u8]> {value: [...]}}
+
+
+#![feature(omit_gdb_pretty_printer_section)]
+#![omit_gdb_pretty_printer_section]
+
+struct Foo<T: ?Sized> {
+    value: T
+}
+
+fn main() {
+    let foo: Foo<Foo<[u8; 4]>> = Foo {
+        value: Foo {
+            value: *b"abc\0"
+        }
+    };
+    let a: &Foo<[u8]> = &foo.value;
+    let b: &Foo<Foo<[u8]>> = &foo;
+
+    zzz(); // #break
+}
+
+fn zzz() { () }
diff --git a/src/test/parse-fail/int-literal-too-large-span.rs b/src/test/parse-fail/int-literal-too-large-span.rs
index c4b25d43579..1af8df7d2f6 100644
--- a/src/test/parse-fail/int-literal-too-large-span.rs
+++ b/src/test/parse-fail/int-literal-too-large-span.rs
@@ -13,7 +13,7 @@
 // issue #17123
 
 fn main() {
-    100000000000000000000000000000000 //~ ERROR int literal is too large
-
+    9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+    //~^ ERROR int literal is too large
         ; // the span shouldn't point to this.
 }
diff --git a/src/test/parse-fail/issue-5544-a.rs b/src/test/parse-fail/issue-5544-a.rs
index f406b2cc803..cf1500e34d8 100644
--- a/src/test/parse-fail/issue-5544-a.rs
+++ b/src/test/parse-fail/issue-5544-a.rs
@@ -11,6 +11,6 @@
 // compile-flags: -Z parse-only
 
 fn main() {
-    let __isize = 18446744073709551616; // 2^64
+    let __isize = 340282366920938463463374607431768211456; // 2^128
     //~^ ERROR int literal is too large
 }
diff --git a/src/test/parse-fail/issue-5544-b.rs b/src/test/parse-fail/issue-5544-b.rs
index 898b0920645..8c0b6741cb8 100644
--- a/src/test/parse-fail/issue-5544-b.rs
+++ b/src/test/parse-fail/issue-5544-b.rs
@@ -11,6 +11,6 @@
 // compile-flags: -Z parse-only
 
 fn main() {
-    let __isize = 0xff_ffff_ffff_ffff_ffff;
+    let __isize = 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff_ff;
     //~^ ERROR int literal is too large
 }
diff --git a/src/test/parse-fail/lex-bad-numeric-literals.rs b/src/test/parse-fail/lex-bad-numeric-literals.rs
index bb97b037a00..d495a8edd09 100644
--- a/src/test/parse-fail/lex-bad-numeric-literals.rs
+++ b/src/test/parse-fail/lex-bad-numeric-literals.rs
@@ -23,8 +23,8 @@ fn main() {
     0o; //~ ERROR: no valid digits
     1e+; //~ ERROR: expected at least one digit in exponent
     0x539.0; //~ ERROR: hexadecimal float literal is not supported
-    99999999999999999999999999999999; //~ ERROR: int literal is too large
-    99999999999999999999999999999999; //~ ERROR: int literal is too large
+    9900000000000000000000000000999999999999999999999999999999; //~ ERROR: int literal is too large
+    9900000000000000000000000000999999999999999999999999999999; //~ ERROR: int literal is too large
     0x; //~ ERROR: no valid digits
     0xu32; //~ ERROR: no valid digits
     0ou32; //~ ERROR: no valid digits
diff --git a/src/test/run-make/test-harness/Makefile b/src/test/run-make/test-harness/Makefile
index fc9b65c47a9..aad8b1b3fbb 100644
--- a/src/test/run-make/test-harness/Makefile
+++ b/src/test/run-make/test-harness/Makefile
@@ -1,7 +1,7 @@
 -include ../tools.mk
 
 all:
-	# check that #[ignore(cfg(...))] does the right thing.
+	# check that #[cfg_attr(..., ignore)] does the right thing.
 	$(RUSTC) --test test-ignore-cfg.rs --cfg ignorecfg
 	$(call RUN,test-ignore-cfg) | grep 'shouldnotignore ... ok'
 	$(call RUN,test-ignore-cfg) | grep 'shouldignore ... ignored'
diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-nothing.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-nothing.rs
new file mode 100644
index 00000000000..a9257cb4c8b
--- /dev/null
+++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-nothing.rs
@@ -0,0 +1,24 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro)]
+#![feature(proc_macro_lib)]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Nothing)]
+pub fn nothing(input: TokenStream) -> TokenStream {
+    "".parse().unwrap()
+}
diff --git a/src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs b/src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs
new file mode 100644
index 00000000000..818308b05a4
--- /dev/null
+++ b/src/test/run-pass-fulldeps/proc-macro/struct-field-macro.rs
@@ -0,0 +1,28 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:derive-nothing.rs
+// ignore-stage1
+
+#![feature(proc_macro)]
+
+#[macro_use]
+extern crate derive_nothing;
+
+macro_rules! int {
+    () => { i32 }
+}
+
+#[derive(Nothing)]
+struct S {
+    x: int!(),
+}
+
+fn main() {}
diff --git a/src/test/run-pass/i128.rs b/src/test/run-pass/i128.rs
new file mode 100644
index 00000000000..b7aeb21229c
--- /dev/null
+++ b/src/test/run-pass/i128.rs
@@ -0,0 +1,99 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-stage0
+// ignore-stage1
+#![feature(i128_type, test)]
+
+extern crate test;
+use test::black_box as b;
+
+fn main() {
+    let x: i128 = -1;
+    assert_eq!(0, !x);
+    let y: i128 = -2;
+    assert_eq!(!1, y);
+    let z: i128 = 0xABCD_EF;
+    assert_eq!(z * z, 0x734C_C2F2_A521);
+    assert_eq!(z * z * z * z, 0x33EE_0E2A_54E2_59DA_A0E7_8E41);
+    assert_eq!(-z * -z, 0x734C_C2F2_A521);
+    assert_eq!(-z * -z * -z * -z, 0x33EE_0E2A_54E2_59DA_A0E7_8E41);
+    assert_eq!(-z + -z + -z + -z, -0x2AF3_7BC);
+    let k: i128 = -0x1234_5678_9ABC_DEFF_EDCB_A987_6543_210;
+    assert_eq!(k + k, -0x2468_ACF1_3579_BDFF_DB97_530E_CA86_420);
+    assert_eq!(0, k - k);
+    assert_eq!(-0x1234_5678_9ABC_DEFF_EDCB_A987_5A86_421, k + z);
+    assert_eq!(-0x1000_0000_0000_0000_0000_0000_0000_000,
+               k + 0x234_5678_9ABC_DEFF_EDCB_A987_6543_210);
+    assert_eq!(-0x6EF5_DE4C_D3BC_2AAA_3BB4_CC5D_D6EE_8, k / 42);
+    assert_eq!(-k, k / -1);
+    assert_eq!(-0x91A2_B3C4_D5E6_F8, k >> 65);
+    assert_eq!(-0xFDB9_7530_ECA8_6420_0000_0000_0000_0000, k << 65);
+    assert!(k < z);
+    assert!(y > k);
+    assert!(y < x);
+    assert_eq!(x as i64, -1);
+    assert_eq!(z as i64, 0xABCD_EF);
+    assert_eq!(k as i64, -0xFEDC_BA98_7654_3210);
+    assert_eq!(k as u128, 0xFEDC_BA98_7654_3210_0123_4567_89AB_CDF0);
+    assert_eq!(-k as u128, 0x1234_5678_9ABC_DEFF_EDCB_A987_6543_210);
+    assert_eq!((-z as f64) as i128, -z);
+    assert_eq!((-z as f32) as i128, -z);
+    assert_eq!((-z as f64 * 16.0) as i128, -z * 16);
+    assert_eq!((-z as f32 * 16.0) as i128, -z * 16);
+    // Same stuff as above, but blackboxed, to force use of intrinsics
+    let x: i128 = b(-1);
+    assert_eq!(0, !x);
+    let y: i128 = b(-2);
+    assert_eq!(!1, y);
+    let z: i128 = b(0xABCD_EF);
+    assert_eq!(z * z, 0x734C_C2F2_A521);
+    assert_eq!(z * z * z * z, 0x33EE_0E2A_54E2_59DA_A0E7_8E41);
+    assert_eq!(-z * -z, 0x734C_C2F2_A521);
+    assert_eq!(-z * -z * -z * -z, 0x33EE_0E2A_54E2_59DA_A0E7_8E41);
+    assert_eq!(-z + -z + -z + -z, -0x2AF3_7BC);
+    let k: i128 = b(-0x1234_5678_9ABC_DEFF_EDCB_A987_6543_210);
+    assert_eq!(k + k, -0x2468_ACF1_3579_BDFF_DB97_530E_CA86_420);
+    assert_eq!(0, k - k);
+    assert_eq!(-0x1234_5678_9ABC_DEFF_EDCB_A987_5A86_421, k + z);
+    assert_eq!(-0x1000_0000_0000_0000_0000_0000_0000_000,
+               k + 0x234_5678_9ABC_DEFF_EDCB_A987_6543_210);
+    assert_eq!(-0x6EF5_DE4C_D3BC_2AAA_3BB4_CC5D_D6EE_8, k / 42);
+    assert_eq!(-k, k / -1);
+    assert_eq!(-0x91A2_B3C4_D5E6_F8, k >> 65);
+    assert_eq!(-0xFDB9_7530_ECA8_6420_0000_0000_0000_0000, k << 65);
+    assert!(k < z);
+    assert!(y > k);
+    assert!(y < x);
+    assert_eq!(x as i64, -1);
+    assert_eq!(z as i64, 0xABCD_EF);
+    assert_eq!(k as i64, -0xFEDC_BA98_7654_3210);
+    assert_eq!(k as u128, 0xFEDC_BA98_7654_3210_0123_4567_89AB_CDF0);
+    assert_eq!(-k as u128, 0x1234_5678_9ABC_DEFF_EDCB_A987_6543_210);
+    assert_eq!((-z as f64) as i128, -z);
+    assert_eq!((-z as f32) as i128, -z);
+    assert_eq!((-z as f64 * 16.0) as i128, -z * 16);
+    assert_eq!((-z as f32 * 16.0) as i128, -z * 16);
+    // formatting
+    let j: i128 = -(1 << 67);
+    assert_eq!("-147573952589676412928", format!("{}", j));
+    assert_eq!("fffffffffffffff80000000000000000", format!("{:x}", j));
+    assert_eq!("3777777777777777777760000000000000000000000", format!("{:o}", j));
+    assert_eq!("1111111111111111111111111111111111111111111111111111111111111\
+                0000000000000000000000000000000000000000000000000000000000000000000",
+               format!("{:b}", j));
+    assert_eq!("-147573952589676412928", format!("{:?}", j));
+    // common traits
+    assert_eq!(x, b(x.clone()));
+    // overflow checks
+    assert_eq!((-z).checked_mul(-z), Some(0x734C_C2F2_A521));
+    assert_eq!((z).checked_mul(z), Some(0x734C_C2F2_A521));
+    assert_eq!((k).checked_mul(k), None);
+}
diff --git a/src/test/run-pass/issue18173.rs b/src/test/run-pass/issue-18173.rs
index f4266fada32..f4266fada32 100644
--- a/src/test/run-pass/issue18173.rs
+++ b/src/test/run-pass/issue-18173.rs
diff --git a/src/test/run-pass/issue22008.rs b/src/test/run-pass/issue-22008.rs
index 3e145122e5a..3e145122e5a 100644
--- a/src/test/run-pass/issue22008.rs
+++ b/src/test/run-pass/issue-22008.rs
diff --git a/src/test/run-pass/issue22346.rs b/src/test/run-pass/issue-22346.rs
index 8538950a895..8538950a895 100644
--- a/src/test/run-pass/issue22346.rs
+++ b/src/test/run-pass/issue-22346.rs
diff --git a/src/test/run-pass/issue24353.rs b/src/test/run-pass/issue-24353.rs
index 7a41a013927..7a41a013927 100644
--- a/src/test/run-pass/issue24353.rs
+++ b/src/test/run-pass/issue-24353.rs
diff --git a/src/test/run-pass/issue26127.rs b/src/test/run-pass/issue-26127.rs
index 75cbcc83d61..75cbcc83d61 100644
--- a/src/test/run-pass/issue26127.rs
+++ b/src/test/run-pass/issue-26127.rs
diff --git a/src/test/run-pass/issue29927.rs b/src/test/run-pass/issue-29927.rs
index 6d9adbcd579..6d9adbcd579 100644
--- a/src/test/run-pass/issue29927.rs
+++ b/src/test/run-pass/issue-29927.rs
diff --git a/src/test/run-pass/issue34569.rs b/src/test/run-pass/issue-34569.rs
index 41d02e96cc2..41d02e96cc2 100644
--- a/src/test/run-pass/issue34569.rs
+++ b/src/test/run-pass/issue-34569.rs
diff --git a/src/test/run-pass/issue34796.rs b/src/test/run-pass/issue-34796.rs
index 0fb6ccc0dc8..0fb6ccc0dc8 100644
--- a/src/test/run-pass/issue34796.rs
+++ b/src/test/run-pass/issue-34796.rs
diff --git a/src/test/run-pass/issue36260.rs b/src/test/run-pass/issue-36260.rs
index 08dbbb5c9fe..08dbbb5c9fe 100644
--- a/src/test/run-pass/issue36260.rs
+++ b/src/test/run-pass/issue-36260.rs
diff --git a/src/test/run-pass/test-allow-dead-extern-static-no-warning.rs b/src/test/run-pass/test-allow-dead-extern-static-no-warning.rs
new file mode 100644
index 00000000000..8df32b54b85
--- /dev/null
+++ b/src/test/run-pass/test-allow-dead-extern-static-no-warning.rs
@@ -0,0 +1,20 @@
+// 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.
+
+// compile-flags: --test
+
+#![deny(dead_code)]
+
+extern "C" {
+    #[allow(dead_code)]
+    static Qt: u64;
+}
+
+fn main() {}
diff --git a/src/test/run-pass/u128.rs b/src/test/run-pass/u128.rs
new file mode 100644
index 00000000000..d138e09318b
--- /dev/null
+++ b/src/test/run-pass/u128.rs
@@ -0,0 +1,67 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-stage0
+// ignore-stage1
+#![feature(i128_type)]
+
+fn main() {
+    let x: u128 = 0xFFFF_FFFF_FFFF_FFFF__FFFF_FFFF_FFFF_FFFF;
+    assert_eq!(0, !x);
+    assert_eq!(0, !x);
+    let y: u128 = 0xFFFF_FFFF_FFFF_FFFF__FFFF_FFFF_FFFF_FFFE;
+    assert_eq!(!1, y);
+    assert_eq!(x, y | 1);
+    assert_eq!(0xFAFF_0000_FF8F_0000__FFFF_0000_FFFF_FFFE,
+               y &
+               0xFAFF_0000_FF8F_0000__FFFF_0000_FFFF_FFFF);
+    let z: u128 = 0xABCD_EF;
+    assert_eq!(z * z, 0x734C_C2F2_A521);
+    assert_eq!(z * z * z * z, 0x33EE_0E2A_54E2_59DA_A0E7_8E41);
+    assert_eq!(z + z + z + z, 0x2AF3_7BC);
+    let k: u128 = 0x1234_5678_9ABC_DEFF_EDCB_A987_6543_210;
+    assert_eq!(k + k, 0x2468_ACF1_3579_BDFF_DB97_530E_CA86_420);
+    assert_eq!(0, k - k);
+    assert_eq!(0x1234_5678_9ABC_DEFF_EDCB_A987_5A86_421, k - z);
+    assert_eq!(0x1000_0000_0000_0000_0000_0000_0000_000,
+               k - 0x234_5678_9ABC_DEFF_EDCB_A987_6543_210);
+    assert_eq!(0x6EF5_DE4C_D3BC_2AAA_3BB4_CC5D_D6EE_8, k / 42);
+    assert_eq!(0, k % 42);
+    assert_eq!(15, z % 42);
+    assert_eq!(0x169D_A8020_CEC18, k % 0x3ACB_FE49_FF24_AC);
+    assert_eq!(0x91A2_B3C4_D5E6_F7, k >> 65);
+    assert_eq!(0xFDB9_7530_ECA8_6420_0000_0000_0000_0000, k << 65);
+    assert!(k > z);
+    assert!(y > k);
+    assert!(y < x);
+    assert_eq!(x as u64, !0);
+    assert_eq!(z as u64, 0xABCD_EF);
+    assert_eq!(k as u64, 0xFEDC_BA98_7654_3210);
+    assert_eq!(k as i128, 0x1234_5678_9ABC_DEFF_EDCB_A987_6543_210);
+    assert_eq!((z as f64) as u128, z);
+    assert_eq!((z as f32) as u128, z);
+    assert_eq!((z as f64 * 16.0) as u128, z * 16);
+    assert_eq!((z as f32 * 16.0) as u128, z * 16);
+    let l :u128 = 432 << 100;
+    assert_eq!((l as f32) as u128, l);
+    assert_eq!((l as f64) as u128, l);
+    // formatting
+    let j: u128 = 1 << 67;
+    assert_eq!("147573952589676412928", format!("{}", j));
+    assert_eq!("80000000000000000", format!("{:x}", j));
+    assert_eq!("20000000000000000000000", format!("{:o}", j));
+    assert_eq!("10000000000000000000000000000000000000000000000000000000000000000000",
+               format!("{:b}", j));
+    assert_eq!("340282366920938463463374607431768211455",
+        format!("{}", u128::max_value()));
+    assert_eq!("147573952589676412928", format!("{:?}", j));
+    // common traits
+    x.clone();
+}
diff --git a/src/test/ui/codemap_tests/unicode.stderr b/src/test/ui/codemap_tests/unicode.stderr
index a748e13ecf1..f71ef126b64 100644
--- a/src/test/ui/codemap_tests/unicode.stderr
+++ b/src/test/ui/codemap_tests/unicode.stderr
@@ -1,4 +1,4 @@
-error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, aapcs, win64, sysv64, Rust, C, system, rust-intrinsic, rust-call, platform-intrinsic], found `路濫狼á́́`
+error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, aapcs, win64, sysv64, ptx-kernel, Rust, C, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted], found `路濫狼á́́`
   --> $DIR/unicode.rs:11:8
    |
 11 | extern "路濫狼á́́" fn foo() {}
diff --git a/src/tools/cargotest/main.rs b/src/tools/cargotest/main.rs
index 26a2e96f571..8a891d624f4 100644
--- a/src/tools/cargotest/main.rs
+++ b/src/tools/cargotest/main.rs
@@ -21,19 +21,44 @@ struct Test {
     lock: Option<&'static str>,
 }
 
-const TEST_REPOS: &'static [Test] = &[Test {
-                                          name: "cargo",
-                                          repo: "https://github.com/rust-lang/cargo",
-                                          sha: "b7be4f2ef2cf743492edc6dfb55d087ed88f2d76",
-                                          lock: None,
-                                      },
-                                      Test {
-                                          name: "iron",
-                                          repo: "https://github.com/iron/iron",
-                                          sha: "16c858ec2901e2992fe5e529780f59fa8ed12903",
-                                          lock: Some(include_str!("lockfiles/iron-Cargo.lock")),
-                                      }];
-
+const TEST_REPOS: &'static [Test] = &[
+    Test {
+        name: "cargo",
+        repo: "https://github.com/rust-lang/cargo",
+        sha: "b7be4f2ef2cf743492edc6dfb55d087ed88f2d76",
+        lock: None,
+    },
+    Test {
+        name: "iron",
+        repo: "https://github.com/iron/iron",
+        sha: "16c858ec2901e2992fe5e529780f59fa8ed12903",
+        lock: Some(include_str!("lockfiles/iron-Cargo.lock")),
+    },
+    Test {
+        name: "ripgrep",
+        repo: "https://github.com/BurntSushi/ripgrep",
+        sha: "b65bb37b14655e1a89c7cd19c8b011ef3e312791",
+        lock: None,
+    },
+    Test {
+        name: "tokei",
+        repo: "https://github.com/Aaronepower/tokei",
+        sha: "5e11c4852fe4aa086b0e4fe5885822fbe57ba928",
+        lock: None,
+    },
+    Test {
+        name: "treeify",
+        repo: "https://github.com/dzamlo/treeify",
+        sha: "999001b223152441198f117a68fb81f57bc086dd",
+        lock: None,
+    },
+    Test {
+        name: "xsv",
+        repo: "https://github.com/BurntSushi/xsv",
+        sha: "a9a7163f2a2953cea426fee1216bec914fe2f56a",
+        lock: None,
+    },
+];
 
 fn main() {
     // One of the projects being tested here is Cargo, and when being tested
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index 227b695635d..2982f29f931 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -7,4 +7,4 @@ build = "build.rs"
 [dependencies]
 log = "0.3"
 env_logger = { version = "0.3.5", default-features = false }
-serialize = { path = "../../libserialize" }
+rustc-serialize = "0.3"
diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs
index e4d9836c562..f6c8393ac21 100644
--- a/src/tools/compiletest/src/main.rs
+++ b/src/tools/compiletest/src/main.rs
@@ -21,6 +21,10 @@
 extern crate libc;
 extern crate test;
 extern crate getopts;
+
+#[cfg(cargobuild)]
+extern crate rustc_serialize;
+#[cfg(not(cargobuild))]
 extern crate serialize as rustc_serialize;
 
 #[macro_use]
@@ -261,7 +265,23 @@ pub fn run_tests(config: &Config) {
         // android debug-info test uses remote debugger
         // so, we test 1 thread at once.
         // also trying to isolate problems with adb_run_wrapper.sh ilooping
-        env::set_var("RUST_TEST_THREADS","1");
+        match config.mode {
+            // These tests don't actually run code or don't run for android, so
+            // we don't need to limit ourselves there
+            Mode::Ui |
+            Mode::CompileFail |
+            Mode::ParseFail |
+            Mode::RunMake |
+            Mode::Codegen |
+            Mode::CodegenUnits |
+            Mode::Pretty |
+            Mode::Rustdoc => {}
+
+            _ => {
+                env::set_var("RUST_TEST_THREADS", "1");
+            }
+
+        }
     }
 
     match config.mode {
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index d729deb8605..05f9beca3d1 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1619,10 +1619,48 @@ actual:\n\
     }
 
     fn fatal_proc_rec(&self, err: &str, proc_res: &ProcRes) -> ! {
+        self.try_print_open_handles();
         self.error(err);
         proc_res.fatal(None);
     }
 
+    // This function is a poor man's attempt to debug rust-lang/rust#38620, if
+    // that's closed then this should be deleted
+    //
+    // This is a very "opportunistic" debugging attempt, so we ignore all
+    // errors here.
+    fn try_print_open_handles(&self) {
+        if !cfg!(windows) {
+            return
+        }
+        if self.config.mode != Incremental {
+            return
+        }
+
+        let filename = match self.testpaths.file.file_stem() {
+            Some(path) => path,
+            None => return,
+        };
+
+        let mut cmd = Command::new("handle.exe");
+        cmd.arg("-a").arg("-u");
+        cmd.arg(filename);
+        cmd.arg("-nobanner");
+        let output = match cmd.output() {
+            Ok(output) => output,
+            Err(_) => return,
+        };
+        println!("---------------------------------------------------");
+        println!("ran extra command to debug rust-lang/rust#38620: ");
+        println!("{:?}", cmd);
+        println!("result: {}", output.status);
+        println!("--- stdout ----------------------------------------");
+        println!("{}", String::from_utf8_lossy(&output.stdout));
+        println!("--- stderr ----------------------------------------");
+        println!("{}", String::from_utf8_lossy(&output.stderr));
+        println!("---------------------------------------------------");
+    }
+
     fn _arm_exec_compiled_test(&self, env: Vec<(String, String)>) -> ProcRes {
         let args = self.make_run_args();
         let cmdline = self.make_cmdline("", &args.prog, &args.args);
diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs
index a5e4e5a4c26..3808c05c6b9 100644
--- a/src/tools/tidy/src/pal.rs
+++ b/src/tools/tidy/src/pal.rs
@@ -26,6 +26,7 @@
 //! exceptions:
 //!
 //! - core may not have platform-specific code
+//! - libcompiler_builtins may have platform-specific code
 //! - liballoc_system may have platform-specific code
 //! - liballoc_jemalloc may have platform-specific code
 //! - libpanic_abort may have platform-specific code
@@ -53,6 +54,7 @@ const EXCEPTION_PATHS: &'static [&'static str] = &[
     // std crates
     "src/liballoc_jemalloc",
     "src/liballoc_system",
+    "src/libcompiler_builtins",
     "src/liblibc",
     "src/libpanic_abort",
     "src/libpanic_unwind",