about summary refs log tree commit diff
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2016-01-15 17:28:28 +0530
committerManish Goregaokar <manishsmail@gmail.com>2016-01-15 17:28:28 +0530
commit7208d2500394ce51010641919f3f79a5ce88dba0 (patch)
treecd4ce2d9f411c08239b14bf906139ab83dc23305
parentad83ea6a6554dfc837a8e42c1af8af093d98c63d (diff)
parent12aec073a8cd293bede167a7ef062044eb07299e (diff)
downloadrust-7208d2500394ce51010641919f3f79a5ce88dba0.tar.gz
rust-7208d2500394ce51010641919f3f79a5ce88dba0.zip
Rollup merge of #30776 - antonblanchard:powerpc64_merge, r=alexcrichton
This adds support for big endian and little endian PowerPC64.
make check runs clean apart from one big endian backtrace issue.
-rwxr-xr-xconfigure13
-rw-r--r--mk/cfg/powerpc64-unknown-linux-gnu.mk24
-rw-r--r--mk/cfg/powerpc64le-unknown-linux-gnu.mk24
-rw-r--r--src/compiletest/util.rs2
-rw-r--r--src/doc/reference.md2
-rw-r--r--src/liballoc_jemalloc/lib.rs4
-rw-r--r--src/liballoc_system/lib.rs4
-rw-r--r--src/librustc_back/target/mod.rs4
-rw-r--r--src/librustc_back/target/powerpc64_unknown_linux_gnu.rs27
-rw-r--r--src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs27
-rw-r--r--src/librustc_trans/trans/cabi.rs2
-rw-r--r--src/librustc_trans/trans/cabi_powerpc64.rs259
-rw-r--r--src/librustc_trans/trans/mod.rs1
-rw-r--r--src/libstd/env.rs12
-rw-r--r--src/libstd/os/linux/raw.rs3
-rw-r--r--src/libstd/os/raw.rs10
-rw-r--r--src/libstd/rand/os.rs21
-rw-r--r--src/libstd/sys/common/libunwind.rs3
-rw-r--r--src/test/auxiliary/extern_calling_convention.rs2
-rw-r--r--src/test/run-pass/bitwise.rs4
-rw-r--r--src/test/run-pass/conditional-compile-arch.rs6
-rw-r--r--src/test/run-pass/intrinsic-alignment.rs2
-rw-r--r--src/test/run-pass/issue-2895.rs4
-rw-r--r--src/test/run-pass/rec-align-u32.rs8
-rw-r--r--src/test/run-pass/rec-align-u64.rs2
-rw-r--r--src/test/run-pass/struct-return.rs4
26 files changed, 440 insertions, 34 deletions
diff --git a/configure b/configure
index c42fc047667..0255b04caa3 100755
--- a/configure
+++ b/configure
@@ -499,13 +499,18 @@ case $CFG_CPUTYPE in
         CFG_CPUTYPE=aarch64
         ;;
 
-    # At some point, when ppc64[le] support happens, this will need to do
-    # something clever. For now it's safe to assume that we're only ever
-    # interested in building 32 bit.
-    powerpc | ppc | ppc64)
+    powerpc | ppc)
         CFG_CPUTYPE=powerpc
         ;;
 
+    powerpc64 | ppc64)
+        CFG_CPUTYPE=powerpc64
+        ;;
+
+    powerpc64le | ppc64le)
+        CFG_CPUTYPE=powerpc64le
+        ;;
+
     x86_64 | x86-64 | x64 | amd64)
         CFG_CPUTYPE=x86_64
         ;;
diff --git a/mk/cfg/powerpc64-unknown-linux-gnu.mk b/mk/cfg/powerpc64-unknown-linux-gnu.mk
new file mode 100644
index 00000000000..a9e8585ad6d
--- /dev/null
+++ b/mk/cfg/powerpc64-unknown-linux-gnu.mk
@@ -0,0 +1,24 @@
+# powerpc64-unknown-linux-gnu configuration
+CROSS_PREFIX_powerpc64-unknown-linux-gnu=powerpc64-linux-gnu-
+CC_powerpc64-unknown-linux-gnu=$(CC)
+CXX_powerpc64-unknown-linux-gnu=$(CXX)
+CPP_powerpc64-unknown-linux-gnu=$(CPP)
+AR_powerpc64-unknown-linux-gnu=$(AR)
+CFG_LIB_NAME_powerpc64-unknown-linux-gnu=lib$(1).so
+CFG_STATIC_LIB_NAME_powerpc64-unknown-linux-gnu=lib$(1).a
+CFG_LIB_GLOB_powerpc64-unknown-linux-gnu=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_powerpc64-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
+CFG_CFLAGS_powerpc64-unknown-linux-gnu := -m64 $(CFLAGS)
+CFG_GCCISH_CFLAGS_powerpc64-unknown-linux-gnu := -Wall -Werror -g -fPIC -m64 $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_powerpc64-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
+CFG_GCCISH_LINK_FLAGS_powerpc64-unknown-linux-gnu := -shared -fPIC -ldl -pthread  -lrt -g -m64
+CFG_GCCISH_DEF_FLAG_powerpc64-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
+CFG_LLC_FLAGS_powerpc64-unknown-linux-gnu :=
+CFG_INSTALL_NAME_powerpc64-unknown-linux-gnu =
+CFG_EXE_SUFFIX_powerpc64-unknown-linux-gnu =
+CFG_WINDOWSY_powerpc64-unknown-linux-gnu :=
+CFG_UNIXY_powerpc64-unknown-linux-gnu := 1
+CFG_LDPATH_powerpc64-unknown-linux-gnu :=
+CFG_RUN_powerpc64-unknown-linux-gnu=$(2)
+CFG_RUN_TARG_powerpc64-unknown-linux-gnu=$(call CFG_RUN_powerpc64-unknown-linux-gnu,,$(2))
+CFG_GNU_TRIPLE_powerpc64-unknown-linux-gnu := powerpc64-unknown-linux-gnu
diff --git a/mk/cfg/powerpc64le-unknown-linux-gnu.mk b/mk/cfg/powerpc64le-unknown-linux-gnu.mk
new file mode 100644
index 00000000000..a2049331ab2
--- /dev/null
+++ b/mk/cfg/powerpc64le-unknown-linux-gnu.mk
@@ -0,0 +1,24 @@
+# powerpc64le-unknown-linux-gnu configuration
+CROSS_PREFIX_powerpc64le-unknown-linux-gnu=powerpc64le-linux-gnu-
+CC_powerpc64le-unknown-linux-gnu=$(CC)
+CXX_powerpc64le-unknown-linux-gnu=$(CXX)
+CPP_powerpc64le-unknown-linux-gnu=$(CPP)
+AR_powerpc64le-unknown-linux-gnu=$(AR)
+CFG_LIB_NAME_powerpc64le-unknown-linux-gnu=lib$(1).so
+CFG_STATIC_LIB_NAME_powerpc64le-unknown-linux-gnu=lib$(1).a
+CFG_LIB_GLOB_powerpc64le-unknown-linux-gnu=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_powerpc64le-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
+CFG_CFLAGS_powerpc64le-unknown-linux-gnu := -m64 $(CFLAGS)
+CFG_GCCISH_CFLAGS_powerpc64le-unknown-linux-gnu := -Wall -Werror -g -fPIC -m64 $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_powerpc64le-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
+CFG_GCCISH_LINK_FLAGS_powerpc64le-unknown-linux-gnu := -shared -fPIC -ldl -pthread  -lrt -g -m64
+CFG_GCCISH_DEF_FLAG_powerpc64le-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
+CFG_LLC_FLAGS_powerpc64le-unknown-linux-gnu :=
+CFG_INSTALL_NAME_powerpc64le-unknown-linux-gnu =
+CFG_EXE_SUFFIX_powerpc64le-unknown-linux-gnu =
+CFG_WINDOWSY_powerpc64le-unknown-linux-gnu :=
+CFG_UNIXY_powerpc64le-unknown-linux-gnu := 1
+CFG_LDPATH_powerpc64le-unknown-linux-gnu :=
+CFG_RUN_powerpc64le-unknown-linux-gnu=$(2)
+CFG_RUN_TARG_powerpc64le-unknown-linux-gnu=$(call CFG_RUN_powerpc64le-unknown-linux-gnu,,$(2))
+CFG_GNU_TRIPLE_powerpc64le-unknown-linux-gnu := powerpc64le-unknown-linux-gnu
diff --git a/src/compiletest/util.rs b/src/compiletest/util.rs
index fbafee102e4..103ca463f7a 100644
--- a/src/compiletest/util.rs
+++ b/src/compiletest/util.rs
@@ -38,6 +38,8 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[
     ("mips", "mips"),
     ("msp430", "msp430"),
     ("powerpc", "powerpc"),
+    ("powerpc64", "powerpc64"),
+    ("powerpc64le", "powerpc64le"),
     ("s390x", "systemz"),
     ("sparc", "sparc"),
     ("x86_64", "x86_64"),
diff --git a/src/doc/reference.md b/src/doc/reference.md
index 87104b4526f..b786b59ec98 100644
--- a/src/doc/reference.md
+++ b/src/doc/reference.md
@@ -2044,7 +2044,7 @@ The following configurations must be defined by the implementation:
   production.  For example, it controls the behavior of the standard library's
   `debug_assert!` macro.
 * `target_arch = "..."` - Target CPU architecture, such as `"x86"`, `"x86_64"`
-  `"mips"`, `"powerpc"`, `"arm"`, or `"aarch64"`.
+  `"mips"`, `"powerpc"`, `"powerpc64"`, `"powerpc64le"`, `"arm"`, or `"aarch64"`.
 * `target_endian = "..."` - Endianness of the target CPU, either `"little"` or
   `"big"`.
 * `target_env = ".."` - An option provided by the compiler by default
diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs
index eaaa9391d31..91d229b819d 100644
--- a/src/liballoc_jemalloc/lib.rs
+++ b/src/liballoc_jemalloc/lib.rs
@@ -55,7 +55,9 @@ extern "C" {
 const MIN_ALIGN: usize = 8;
 #[cfg(all(any(target_arch = "x86",
               target_arch = "x86_64",
-              target_arch = "aarch64")))]
+              target_arch = "aarch64",
+              target_arch = "powerpc64",
+              target_arch = "powerpc64le")))]
 const MIN_ALIGN: usize = 16;
 
 // MALLOCX_ALIGN(a) macro
diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs
index a4e98e413bb..ffb6999d6e3 100644
--- a/src/liballoc_system/lib.rs
+++ b/src/liballoc_system/lib.rs
@@ -29,7 +29,9 @@ extern crate libc;
               target_arch = "arm",
               target_arch = "mips",
               target_arch = "mipsel",
-              target_arch = "powerpc")))]
+              target_arch = "powerpc",
+              target_arch = "powerpc64",
+              target_arch = "powerpc64le")))]
 const MIN_ALIGN: usize = 8;
 #[cfg(all(any(target_arch = "x86_64",
               target_arch = "aarch64")))]
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index 666903b4eed..51149101e0c 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -80,7 +80,7 @@ pub struct Target {
     /// Vendor name to use for conditional compilation.
     pub target_vendor: String,
     /// Architecture to use for ABI considerations. Valid options: "x86", "x86_64", "arm",
-    /// "aarch64", "mips", and "powerpc". "mips" includes "mipsel".
+    /// "aarch64", "mips", "powerpc", "powerpc64" and "powerpc64le". "mips" includes "mipsel".
     pub arch: String,
     /// Optional settings with defaults.
     pub options: TargetOptions,
@@ -413,6 +413,8 @@ impl Target {
             mips_unknown_linux_gnu,
             mipsel_unknown_linux_gnu,
             powerpc_unknown_linux_gnu,
+            powerpc64_unknown_linux_gnu,
+            powerpc64le_unknown_linux_gnu,
             arm_unknown_linux_gnueabi,
             arm_unknown_linux_gnueabihf,
             aarch64_unknown_linux_gnu,
diff --git a/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs b/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs
new file mode 100644
index 00000000000..83970e73b93
--- /dev/null
+++ b/src/librustc_back/target/powerpc64_unknown_linux_gnu.rs
@@ -0,0 +1,27 @@
+// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use target::Target;
+
+pub fn target() -> Target {
+    let mut base = super::linux_base::opts();
+    base.pre_link_args.push("-m64".to_string());
+
+    Target {
+        llvm_target: "powerpc64-unknown-linux-gnu".to_string(),
+        target_endian: "big".to_string(),
+        target_pointer_width: "64".to_string(),
+        arch: "powerpc64".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/powerpc64le_unknown_linux_gnu.rs b/src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs
new file mode 100644
index 00000000000..0f5252fdc23
--- /dev/null
+++ b/src/librustc_back/target/powerpc64le_unknown_linux_gnu.rs
@@ -0,0 +1,27 @@
+// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use target::Target;
+
+pub fn target() -> Target {
+    let mut base = super::linux_base::opts();
+    base.pre_link_args.push("-m64".to_string());
+
+    Target {
+        llvm_target: "powerpc64le-unknown-linux-gnu".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        arch: "powerpc64le".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "gnu".to_string(),
+        target_vendor: "unknown".to_string(),
+        options: base,
+    }
+}
diff --git a/src/librustc_trans/trans/cabi.rs b/src/librustc_trans/trans/cabi.rs
index 0ff5264c00f..4bfbb8b69f0 100644
--- a/src/librustc_trans/trans/cabi.rs
+++ b/src/librustc_trans/trans/cabi.rs
@@ -19,6 +19,7 @@ use trans::cabi_x86_win64;
 use trans::cabi_arm;
 use trans::cabi_aarch64;
 use trans::cabi_powerpc;
+use trans::cabi_powerpc64;
 use trans::cabi_mips;
 use trans::type_::Type;
 
@@ -127,6 +128,7 @@ pub fn compute_abi_info(ccx: &CrateContext,
         },
         "mips" => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def),
         "powerpc" => cabi_powerpc::compute_abi_info(ccx, atys, rty, ret_def),
+        "powerpc64" | "powerpc64le" => cabi_powerpc64::compute_abi_info(ccx, atys, rty, ret_def),
         a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a)
                               ),
     }
diff --git a/src/librustc_trans/trans/cabi_powerpc64.rs b/src/librustc_trans/trans/cabi_powerpc64.rs
new file mode 100644
index 00000000000..cba73004279
--- /dev/null
+++ b/src/librustc_trans/trans/cabi_powerpc64.rs
@@ -0,0 +1,259 @@
+// 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: The PowerPC64 ABI needs to zero or sign extend function
+// call parameters, but compute_abi_info() is passed LLVM types
+// which have no sign information.
+//
+// Alignment of 128 bit types is not currently handled, this will
+// need to be fixed when PowerPC vector support is added.
+
+use llvm::{Integer, Pointer, Float, Double, Struct, Array, Attribute};
+use trans::cabi::{FnType, ArgType};
+use trans::context::CrateContext;
+use trans::type_::Type;
+
+use std::cmp;
+
+fn align_up_to(off: usize, a: usize) -> usize {
+    return (off + a - 1) / a * a;
+}
+
+fn align(off: usize, ty: Type) -> usize {
+    let a = ty_align(ty);
+    return align_up_to(off, a);
+}
+
+fn ty_align(ty: Type) -> usize {
+    match ty.kind() {
+        Integer => ((ty.int_width() as usize) + 7) / 8,
+        Pointer => 8,
+        Float => 4,
+        Double => 8,
+        Struct => {
+            if ty.is_packed() {
+                1
+            } else {
+                let str_tys = ty.field_types();
+                str_tys.iter().fold(1, |a, t| cmp::max(a, ty_align(*t)))
+            }
+        }
+        Array => {
+            let elt = ty.element_type();
+            ty_align(elt)
+        }
+        _ => panic!("ty_align: unhandled type")
+    }
+}
+
+fn ty_size(ty: Type) -> usize {
+    match ty.kind() {
+        Integer => ((ty.int_width() as usize) + 7) / 8,
+        Pointer => 8,
+        Float => 4,
+        Double => 8,
+        Struct => {
+            if ty.is_packed() {
+                let str_tys = ty.field_types();
+                str_tys.iter().fold(0, |s, t| s + ty_size(*t))
+            } else {
+                let str_tys = ty.field_types();
+                let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
+                align(size, ty)
+            }
+        }
+        Array => {
+            let len = ty.array_length();
+            let elt = ty.element_type();
+            let eltsz = ty_size(elt);
+            len * eltsz
+        }
+        _ => panic!("ty_size: unhandled type")
+    }
+}
+
+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, ty: Type) -> ArgType {
+    if is_reg_ty(ty) {
+        let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExt) } else { None };
+        return ArgType::direct(ty, None, None, attr);
+    }
+
+    // The PowerPC64 big endian ABI doesn't return aggregates in registers
+    if ccx.sess().target.target.arch == "powerpc64" {
+        return ArgType::indirect(ty, Some(Attribute::StructRet))
+    }
+
+    if let Some((base_ty, members)) = is_homogenous_aggregate_ty(ty) {
+        let llty = Type::array(&base_ty, members);
+        return ArgType::direct(ty, Some(llty), None, None);
+    }
+    let size = ty_size(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)
+        };
+        return ArgType::direct(ty, Some(llty), None, None);
+    }
+
+    ArgType::indirect(ty, Some(Attribute::StructRet))
+}
+
+fn classify_arg_ty(ccx: &CrateContext, ty: Type) -> ArgType {
+    if is_reg_ty(ty) {
+        let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExt) } else { None };
+        return ArgType::direct(ty, None, None, attr);
+    }
+    if let Some((base_ty, members)) = is_homogenous_aggregate_ty(ty) {
+        let llty = Type::array(&base_ty, members);
+        return ArgType::direct(ty, Some(llty), None, None);
+    }
+
+    ArgType::direct(
+        ty,
+        Some(struct_ty(ccx, ty)),
+        None,
+        None
+    )
+}
+
+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,
+                        atys: &[Type],
+                        rty: Type,
+                        ret_def: bool) -> FnType {
+    let ret_ty = if ret_def {
+        classify_ret_ty(ccx, rty)
+    } else {
+        ArgType::direct(Type::void(ccx), None, None, None)
+    };
+
+    let mut arg_tys = Vec::new();
+    for &aty in atys {
+        let ty = classify_arg_ty(ccx, aty);
+        arg_tys.push(ty);
+    };
+
+    return FnType {
+        arg_tys: arg_tys,
+        ret_ty: ret_ty,
+    };
+}
diff --git a/src/librustc_trans/trans/mod.rs b/src/librustc_trans/trans/mod.rs
index 1fbc0d5c015..f474e288efe 100644
--- a/src/librustc_trans/trans/mod.rs
+++ b/src/librustc_trans/trans/mod.rs
@@ -31,6 +31,7 @@ mod cabi_aarch64;
 mod cabi_arm;
 mod cabi_mips;
 mod cabi_powerpc;
+mod cabi_powerpc64;
 mod cabi_x86;
 mod cabi_x86_64;
 mod cabi_x86_win64;
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index 760733872ea..6726f522247 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -615,6 +615,8 @@ pub mod consts {
     /// - mips
     /// - mipsel
     /// - powerpc
+    /// - powerpc64
+    /// - powerpc64le
     #[stable(feature = "env", since = "1.0.0")]
     pub const ARCH: &'static str = super::arch::ARCH;
 
@@ -867,6 +869,16 @@ mod arch {
     pub const ARCH: &'static str = "powerpc";
 }
 
+#[cfg(target_arch = "powerpc64")]
+mod arch {
+    pub const ARCH: &'static str = "powerpc64";
+}
+
+#[cfg(target_arch = "powerpc64le")]
+mod arch {
+    pub const ARCH: &'static str = "powerpc64le";
+}
+
 #[cfg(target_arch = "le32")]
 mod arch {
     pub const ARCH: &'static str = "le32";
diff --git a/src/libstd/os/linux/raw.rs b/src/libstd/os/linux/raw.rs
index f44199f311b..953d0917141 100644
--- a/src/libstd/os/linux/raw.rs
+++ b/src/libstd/os/linux/raw.rs
@@ -205,7 +205,8 @@ mod arch {
     }
 }
 
-#[cfg(target_arch = "x86_64")]
+#[cfg(any(target_arch = "x86_64", target_arch = "powerpc64",
+          target_arch = "powerpc64le"))]
 mod arch {
     use super::{dev_t, mode_t};
     use os::raw::{c_long, c_int};
diff --git a/src/libstd/os/raw.rs b/src/libstd/os/raw.rs
index 3bc063f4269..62080fee48e 100644
--- a/src/libstd/os/raw.rs
+++ b/src/libstd/os/raw.rs
@@ -14,11 +14,17 @@
 
 #[cfg(any(target_os = "android",
           all(target_os = "linux", any(target_arch = "aarch64",
-                                       target_arch = "arm"))))]
+                                       target_arch = "arm",
+                                       target_arch = "powerpc",
+                                       target_arch = "powerpc64",
+                                       target_arch = "powerpc64le"))))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8;
 #[cfg(not(any(target_os = "android",
               all(target_os = "linux", any(target_arch = "aarch64",
-                                           target_arch = "arm")))))]
+                                           target_arch = "arm",
+                                           target_arch = "powerpc",
+                                           target_arch = "powerpc64",
+                                           target_arch = "powerpc64le")))))]
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8;
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_schar = i8;
 #[stable(feature = "raw_os", since = "1.1.0")] pub type c_uchar = u8;
diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs
index 23a368a30a5..619f100f1a1 100644
--- a/src/libstd/rand/os.rs
+++ b/src/libstd/rand/os.rs
@@ -30,14 +30,19 @@ mod imp {
                   target_arch = "x86",
                   target_arch = "arm",
                   target_arch = "aarch64",
-                  target_arch = "powerpc")))]
+                  target_arch = "powerpc",
+                  target_arch = "powerpc64",
+                  target_arch = "powerpc64le")))]
     fn getrandom(buf: &mut [u8]) -> libc::c_long {
         #[cfg(target_arch = "x86_64")]
         const NR_GETRANDOM: libc::c_long = 318;
         #[cfg(target_arch = "x86")]
         const NR_GETRANDOM: libc::c_long = 355;
-        #[cfg(any(target_arch = "arm", target_arch = "powerpc"))]
+        #[cfg(target_arch = "arm")]
         const NR_GETRANDOM: libc::c_long = 384;
+        #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64",
+                  target_arch = "powerpc64le"))]
+        const NR_GETRANDOM: libc::c_long = 359;
         #[cfg(target_arch = "aarch64")]
         const NR_GETRANDOM: libc::c_long = 278;
 
@@ -51,7 +56,9 @@ mod imp {
                       target_arch = "x86",
                       target_arch = "arm",
                       target_arch = "aarch64",
-                      target_arch = "powerpc"))))]
+                      target_arch = "powerpc",
+                      target_arch = "powerpc64",
+                      target_arch = "powerpc64le"))))]
     fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }
 
     fn getrandom_fill_bytes(v: &mut [u8]) {
@@ -88,7 +95,9 @@ mod imp {
                   target_arch = "x86",
                   target_arch = "arm",
                   target_arch = "aarch64",
-                  target_arch = "powerpc")))]
+                  target_arch = "powerpc",
+                  target_arch = "powerpc64",
+                  target_arch = "powerpc64le")))]
     fn is_getrandom_available() -> bool {
         use sync::atomic::{AtomicBool, Ordering};
         use sync::Once;
@@ -116,7 +125,9 @@ mod imp {
                       target_arch = "x86",
                       target_arch = "arm",
                       target_arch = "aarch64",
-                      target_arch = "powerpc"))))]
+                      target_arch = "powerpc",
+                      target_arch = "powerpc64",
+                      target_arch = "powerpc64le"))))]
     fn is_getrandom_available() -> bool { false }
 
     /// A random number generator that retrieves randomness straight from
diff --git a/src/libstd/sys/common/libunwind.rs b/src/libstd/sys/common/libunwind.rs
index feb05c7b560..77d1eed9623 100644
--- a/src/libstd/sys/common/libunwind.rs
+++ b/src/libstd/sys/common/libunwind.rs
@@ -83,7 +83,8 @@ pub const unwinder_private_data_size: usize = 2;
 #[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
 pub const unwinder_private_data_size: usize = 2;
 
-#[cfg(target_arch = "powerpc")]
+#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64",
+          target_arch = "powerpc64le"))]
 pub const unwinder_private_data_size: usize = 2;
 
 #[repr(C)]
diff --git a/src/test/auxiliary/extern_calling_convention.rs b/src/test/auxiliary/extern_calling_convention.rs
index 22cbc415eb4..55a4226c663 100644
--- a/src/test/auxiliary/extern_calling_convention.rs
+++ b/src/test/auxiliary/extern_calling_convention.rs
@@ -24,7 +24,7 @@ pub extern "win64" fn foo(a: isize, b: isize, c: isize, d: isize) {
 }
 
 #[inline(never)]
-#[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "aarch64"))]
+#[cfg(not(target_arch = "x86_64"))]
 pub extern fn foo(a: isize, b: isize, c: isize, d: isize) {
     assert_eq!(a, 1);
     assert_eq!(b, 2);
diff --git a/src/test/run-pass/bitwise.rs b/src/test/run-pass/bitwise.rs
index ac24ed8d916..bb4b9cfecf7 100644
--- a/src/test/run-pass/bitwise.rs
+++ b/src/test/run-pass/bitwise.rs
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[cfg(any(target_arch = "x86", target_arch = "arm"))]
+#[cfg(any(target_pointer_width = "32"))]
 fn target() {
     assert_eq!(-1000isize as usize >> 3_usize, 536870787_usize);
 }
 
-#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
+#[cfg(any(target_pointer_width = "64"))]
 fn target() {
     assert_eq!(-1000isize as usize >> 3_usize, 2305843009213693827_usize);
 }
diff --git a/src/test/run-pass/conditional-compile-arch.rs b/src/test/run-pass/conditional-compile-arch.rs
index e51270fdc8d..4e4c98e50bc 100644
--- a/src/test/run-pass/conditional-compile-arch.rs
+++ b/src/test/run-pass/conditional-compile-arch.rs
@@ -21,3 +21,9 @@ pub fn main() { }
 
 #[cfg(target_arch = "aarch64")]
 pub fn main() { }
+
+#[cfg(target_arch = "powerpc64")]
+pub fn main() { }
+
+#[cfg(target_arch = "powerpc64le")]
+pub fn main() { }
diff --git a/src/test/run-pass/intrinsic-alignment.rs b/src/test/run-pass/intrinsic-alignment.rs
index ef69946d7aa..a4720d48213 100644
--- a/src/test/run-pass/intrinsic-alignment.rs
+++ b/src/test/run-pass/intrinsic-alignment.rs
@@ -35,7 +35,7 @@ mod m {
     }
 
     #[main]
-    #[cfg(any(target_arch = "x86_64", target_arch = "arm", target_arch = "aarch64"))]
+    #[cfg(not(target_arch = "x86"))]
     pub fn main() {
         unsafe {
             assert_eq!(::rusti::pref_align_of::<u64>(), 8);
diff --git a/src/test/run-pass/issue-2895.rs b/src/test/run-pass/issue-2895.rs
index 93d9300edf6..5587f68bd18 100644
--- a/src/test/run-pass/issue-2895.rs
+++ b/src/test/run-pass/issue-2895.rs
@@ -23,13 +23,13 @@ impl Drop for Kitty {
     fn drop(&mut self) {}
 }
 
-#[cfg(any(target_arch = "x86_64", target_arch="aarch64"))]
+#[cfg(target_pointer_width = "64")]
 pub fn main() {
     assert_eq!(mem::size_of::<Cat>(), 8 as usize);
     assert_eq!(mem::size_of::<Kitty>(), 16 as usize);
 }
 
-#[cfg(any(target_arch = "x86", target_arch = "arm"))]
+#[cfg(target_pointer_width = "32")]
 pub fn main() {
     assert_eq!(mem::size_of::<Cat>(), 4 as usize);
     assert_eq!(mem::size_of::<Kitty>(), 8 as usize);
diff --git a/src/test/run-pass/rec-align-u32.rs b/src/test/run-pass/rec-align-u32.rs
index e5d76c3e67a..4a115c737da 100644
--- a/src/test/run-pass/rec-align-u32.rs
+++ b/src/test/run-pass/rec-align-u32.rs
@@ -35,14 +35,6 @@ struct Outer {
     t: Inner
 }
 
-
-#[cfg(any(target_arch = "x86", target_arch = "arm", target_arch = "aarch64"))]
-mod m {
-    pub fn align() -> usize { 4 }
-    pub fn size() -> usize { 8 }
-}
-
-#[cfg(target_arch = "x86_64")]
 mod m {
     pub fn align() -> usize { 4 }
     pub fn size() -> usize { 8 }
diff --git a/src/test/run-pass/rec-align-u64.rs b/src/test/run-pass/rec-align-u64.rs
index fc032aa3ff0..25cd77845ea 100644
--- a/src/test/run-pass/rec-align-u64.rs
+++ b/src/test/run-pass/rec-align-u64.rs
@@ -49,7 +49,7 @@ mod m {
         pub fn size() -> usize { 12 }
     }
 
-    #[cfg(any(target_arch = "x86_64", target_arch = "arm", target_arch = "aarch64"))]
+    #[cfg(not(target_arch = "x86"))]
     pub mod m {
         pub fn align() -> usize { 8 }
         pub fn size() -> usize { 16 }
diff --git a/src/test/run-pass/struct-return.rs b/src/test/run-pass/struct-return.rs
index 109287a83b1..6f23263790c 100644
--- a/src/test/run-pass/struct-return.rs
+++ b/src/test/run-pass/struct-return.rs
@@ -43,7 +43,7 @@ fn test1() {
     }
 }
 
-#[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
+#[cfg(target_pointer_width = "64")]
 fn test2() {
     unsafe {
         let f = Floats { a: 1.234567890e-15_f64,
@@ -59,7 +59,7 @@ fn test2() {
     }
 }
 
-#[cfg(any(target_arch = "x86", target_arch = "arm"))]
+#[cfg(target_pointer_width = "32")]
 fn test2() {
 }