about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-01-15 05:12:30 +0000
committerbors <bors@rust-lang.org>2015-01-15 05:12:30 +0000
commit0c96037ec1676b420002a06ea337865f95abbf2c (patch)
treecec4f5e86bd892800d343105da4332ad94b3f61a /src
parent451e134c180e88b06e3b747ed750e4901ca93721 (diff)
parent78278d0c76f3c868a4a4bcc47336c384968c6b3a (diff)
downloadrust-0c96037ec1676b420002a06ea337865f95abbf2c.tar.gz
rust-0c96037ec1676b420002a06ea337865f95abbf2c.zip
auto merge of #20980 : richo/rust/final-power, r=alexcrichton
Originally, this was going to be discussed and revisted, however I've been working on this for months, and a rebase on top of master was about 1 flight's worth of work so I just went ahead and did it.

This gets you as far as being able to target powerpc with, eg:

    LD_LIBRARY_PATH=./x86_64-unknown-linux-gnu/stage2/lib/ x86_64-unknown-linux-gnu/stage2/bin/rustc -C linker=powerpc-linux-gnu-gcc --target powerpc-unknown-linux-gnu hello.rs

Would really love to get this out before 1.0. r? @alexcrichton 
Diffstat (limited to 'src')
-rw-r--r--src/doc/reference.md2
-rw-r--r--src/liballoc/heap.rs3
-rw-r--r--src/libcoretest/mem.rs16
-rw-r--r--src/liblibc/lib.rs25
-rw-r--r--src/librustc_back/target/mod.rs4
-rw-r--r--src/librustc_back/target/powerpc_unknown_linux_gnu.rs26
-rw-r--r--src/librustc_llvm/lib.rs11
-rw-r--r--src/librustc_trans/back/write.rs6
-rw-r--r--src/librustc_trans/trans/asm.rs5
-rw-r--r--src/librustc_trans/trans/cabi.rs2
-rw-r--r--src/librustc_trans/trans/cabi_powerpc.rs183
-rw-r--r--src/librustc_trans/trans/mod.rs1
-rw-r--r--src/libstd/os.rs5
-rw-r--r--src/libstd/rand/os.rs14
-rw-r--r--src/libstd/rt/libunwind.rs3
-rw-r--r--src/libstd/sys/common/stack.rs12
-rw-r--r--src/libstd/sys/unix/c.rs12
-rw-r--r--src/libstd/sys/unix/stack_overflow.rs1
-rw-r--r--src/libstd/sys/unix/sync.rs9
-rw-r--r--src/rt/arch/powerpc/morestack.S18
-rw-r--r--src/rt/arch/powerpc/record_sp.S4
-rw-r--r--src/rustllvm/llvm-auto-clean-trigger2
22 files changed, 327 insertions, 37 deletions
diff --git a/src/doc/reference.md b/src/doc/reference.md
index 623097b2fc9..1c9f0799b3b 100644
--- a/src/doc/reference.md
+++ b/src/doc/reference.md
@@ -2170,7 +2170,7 @@ arbitrarily complex configurations through nesting.
 The following configurations must be defined by the implementation:
 
 * `target_arch = "..."`. Target CPU architecture, such as `"x86"`, `"x86_64"`
-  `"mips"`, `"arm"`, or `"aarch64"`.
+  `"mips"`, `"powerpc"`, `"arm"`, or `"aarch64"`.
 * `target_endian = "..."`. Endianness of the target CPU, either `"little"` or
   `"big"`.
 * `target_family = "..."`. Operating system family of the target, e. g.
diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs
index 02933c763ef..b7bc1b47646 100644
--- a/src/liballoc/heap.rs
+++ b/src/liballoc/heap.rs
@@ -119,7 +119,8 @@ unsafe fn exchange_free(ptr: *mut u8, old_size: uint, align: uint) {
           not(feature = "external_crate"),
           any(target_arch = "arm",
               target_arch = "mips",
-              target_arch = "mipsel")))]
+              target_arch = "mipsel",
+              target_arch = "powerpc")))]
 const MIN_ALIGN: uint = 8;
 #[cfg(all(not(feature = "external_funcs"),
           not(feature = "external_crate"),
diff --git a/src/libcoretest/mem.rs b/src/libcoretest/mem.rs
index 96b50e8bccb..3dc209e6fcb 100644
--- a/src/libcoretest/mem.rs
+++ b/src/libcoretest/mem.rs
@@ -19,18 +19,14 @@ fn size_of_basic() {
 }
 
 #[test]
-#[cfg(any(target_arch = "x86",
-          target_arch = "arm",
-          target_arch = "mips",
-          target_arch = "mipsel"))]
+#[cfg(target_pointer_width = "32")]
 fn size_of_32() {
     assert_eq!(size_of::<uint>(), 4u);
     assert_eq!(size_of::<*const uint>(), 4u);
 }
 
 #[test]
-#[cfg(any(target_arch = "x86_64",
-          target_arch = "aarch64"))]
+#[cfg(target_pointer_width = "64")]
 fn size_of_64() {
     assert_eq!(size_of::<uint>(), 8u);
     assert_eq!(size_of::<*const uint>(), 8u);
@@ -52,18 +48,14 @@ fn align_of_basic() {
 }
 
 #[test]
-#[cfg(any(target_arch = "x86",
-          target_arch = "arm",
-          target_arch = "mips",
-          target_arch = "mipsel"))]
+#[cfg(target_pointer_width = "32")]
 fn align_of_32() {
     assert_eq!(align_of::<uint>(), 4u);
     assert_eq!(align_of::<*const uint>(), 4u);
 }
 
 #[test]
-#[cfg(any(target_arch = "x86_64",
-          target_arch = "aarch64"))]
+#[cfg(target_pointer_width = "64")]
 fn align_of_64() {
     assert_eq!(align_of::<uint>(), 8u);
     assert_eq!(align_of::<*const uint>(), 8u);
diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs
index c866deafee4..deab0cabfbe 100644
--- a/src/liblibc/lib.rs
+++ b/src/liblibc/lib.rs
@@ -497,7 +497,8 @@ pub mod types {
         #[cfg(any(target_arch = "x86",
                   target_arch = "arm",
                   target_arch = "mips",
-                  target_arch = "mipsel"))]
+                  target_arch = "mipsel",
+                  target_arch = "powerpc"))]
         pub mod arch {
             pub mod c95 {
                 pub type c_char = i8;
@@ -528,7 +529,8 @@ pub mod types {
             }
             #[cfg(any(target_arch = "x86",
                       target_arch = "mips",
-                      target_arch = "mipsel"))]
+                      target_arch = "mipsel",
+                      target_arch = "powerpc"))]
             pub mod posix88 {
                 pub type off_t = i32;
                 pub type dev_t = u64;
@@ -642,7 +644,9 @@ pub mod types {
                     pub __size: [u32; 9]
                 }
             }
-            #[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
+            #[cfg(any(target_arch = "mips",
+                      target_arch = "mipsel",
+                      target_arch = "powerpc"))]
             pub mod posix01 {
                 use types::os::arch::c95::{c_long, c_ulong, time_t};
                 use types::os::arch::posix88::{gid_t, ino_t};
@@ -2697,7 +2701,9 @@ pub mod consts {
             pub const EHWPOISON: c_int = 133;
         }
 
-        #[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
+        #[cfg(any(target_arch = "mips",
+                  target_arch = "mipsel",
+                  target_arch = "powerpc"))]
         pub mod posix88 {
             use types::os::arch::c95::c_int;
             use types::common::c95::c_void;
@@ -2982,7 +2988,8 @@ pub mod consts {
             #[cfg(all(target_os = "linux",
                       any(target_arch = "mips",
                           target_arch = "mipsel",
-                          target_arch = "aarch64")))]
+                          target_arch = "aarch64",
+                          target_arch = "powerpc")))]
             pub const PTHREAD_STACK_MIN: size_t = 131072;
 
             pub const CLOCK_REALTIME: c_int = 0;
@@ -3040,7 +3047,9 @@ pub mod consts {
             pub const SHUT_WR: c_int = 1;
             pub const SHUT_RDWR: c_int = 2;
         }
-        #[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
+        #[cfg(any(target_arch = "mips",
+                  target_arch = "mipsel",
+                  target_arch = "powerpc"))]
         pub mod bsd44 {
             use types::os::arch::c95::c_int;
 
@@ -3115,7 +3124,9 @@ pub mod consts {
             pub const MAP_NONBLOCK : c_int = 0x010000;
             pub const MAP_STACK : c_int = 0x020000;
         }
-        #[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
+        #[cfg(any(target_arch = "mips",
+                  target_arch = "mipsel",
+                  target_arch = "powerpc"))]
         pub mod extra {
             use types::os::arch::c95::c_int;
 
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index 57e2744ae9b..f8eabb4375f 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -72,6 +72,7 @@ mod i686_unknown_dragonfly;
 mod i686_unknown_linux_gnu;
 mod mips_unknown_linux_gnu;
 mod mipsel_unknown_linux_gnu;
+mod powerpc_unknown_linux_gnu;
 mod x86_64_apple_darwin;
 mod x86_64_apple_ios;
 mod x86_64_pc_windows_gnu;
@@ -95,7 +96,7 @@ pub struct Target {
     /// OS name to use for conditional compilation.
     pub target_os: String,
     /// Architecture to use for ABI considerations. Valid options: "x86", "x86_64", "arm",
-    /// "aarch64", and "mips". "mips" includes "mipsel".
+    /// "aarch64", "mips", and "powerpc". "mips" includes "mipsel".
     pub arch: String,
     /// Optional settings with defaults.
     pub options: TargetOptions,
@@ -339,6 +340,7 @@ impl Target {
             i686_unknown_linux_gnu,
             mips_unknown_linux_gnu,
             mipsel_unknown_linux_gnu,
+            powerpc_unknown_linux_gnu,
             arm_linux_androideabi,
             arm_unknown_linux_gnueabi,
             arm_unknown_linux_gnueabihf,
diff --git a/src/librustc_back/target/powerpc_unknown_linux_gnu.rs b/src/librustc_back/target/powerpc_unknown_linux_gnu.rs
new file mode 100644
index 00000000000..5e0b7bcf3ef
--- /dev/null
+++ b/src/librustc_back/target/powerpc_unknown_linux_gnu.rs
@@ -0,0 +1,26 @@
+// Copyright 2012 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("-m32".to_string());
+
+    Target {
+        data_layout: "E-S8-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string(),
+        llvm_target: "powerpc-unknown-linux-gnu".to_string(),
+        target_endian: "big".to_string(),
+        target_pointer_width: "32".to_string(),
+        arch: "powerpc".to_string(),
+        target_os: "linux".to_string(),
+        options: base,
+    }
+}
diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs
index a4f9b1f98d4..3edb1ec48a0 100644
--- a/src/librustc_llvm/lib.rs
+++ b/src/librustc_llvm/lib.rs
@@ -1974,6 +1974,11 @@ extern {
     pub fn LLVMInitializeMipsTargetMC();
     pub fn LLVMInitializeMipsAsmPrinter();
     pub fn LLVMInitializeMipsAsmParser();
+    pub fn LLVMInitializePowerPCTargetInfo();
+    pub fn LLVMInitializePowerPCTarget();
+    pub fn LLVMInitializePowerPCTargetMC();
+    pub fn LLVMInitializePowerPCAsmPrinter();
+    pub fn LLVMInitializePowerPCAsmParser();
 
     pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: *const c_char) -> bool;
     pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
@@ -2249,6 +2254,12 @@ pub unsafe fn static_link_hack_this_sucks() {
     LLVMInitializeMipsAsmPrinter();
     LLVMInitializeMipsAsmParser();
 
+    LLVMInitializePowerPCTargetInfo();
+    LLVMInitializePowerPCTarget();
+    LLVMInitializePowerPCTargetMC();
+    LLVMInitializePowerPCAsmPrinter();
+    LLVMInitializePowerPCAsmParser();
+
     LLVMRustSetLLVMOptions(0 as c_int,
                                        0 as *const _);
 
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index c818dda7581..aa51b0c5ee2 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -1039,6 +1039,12 @@ unsafe fn configure_llvm(sess: &Session) {
         llvm::LLVMInitializeMipsAsmPrinter();
         llvm::LLVMInitializeMipsAsmParser();
 
+        llvm::LLVMInitializePowerPCTargetInfo();
+        llvm::LLVMInitializePowerPCTarget();
+        llvm::LLVMInitializePowerPCTargetMC();
+        llvm::LLVMInitializePowerPCAsmPrinter();
+        llvm::LLVMInitializePowerPCAsmParser();
+
         llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
                                      llvm_args.as_ptr());
     });
diff --git a/src/librustc_trans/trans/asm.rs b/src/librustc_trans/trans/asm.rs
index 9b6fa32405f..05abd3ff557 100644
--- a/src/librustc_trans/trans/asm.rs
+++ b/src/librustc_trans/trans/asm.rs
@@ -161,10 +161,7 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
 // Default per-arch clobbers
 // Basically what clang does
 
-#[cfg(any(target_arch = "arm",
-          target_arch = "aarch64",
-          target_arch = "mips",
-          target_arch = "mipsel"))]
+#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
 fn get_clobbers() -> String {
     "".to_string()
 }
diff --git a/src/librustc_trans/trans/cabi.rs b/src/librustc_trans/trans/cabi.rs
index f7ffbb95feb..7abcdd07cc5 100644
--- a/src/librustc_trans/trans/cabi.rs
+++ b/src/librustc_trans/trans/cabi.rs
@@ -18,6 +18,7 @@ use trans::cabi_x86_64;
 use trans::cabi_x86_win64;
 use trans::cabi_arm;
 use trans::cabi_aarch64;
+use trans::cabi_powerpc;
 use trans::cabi_mips;
 use trans::type_::Type;
 
@@ -125,6 +126,7 @@ pub fn compute_abi_info(ccx: &CrateContext,
             cabi_arm::compute_abi_info(ccx, atys, rty, ret_def, flavor)
         },
         "mips" => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def),
+        "powerpc" => cabi_powerpc::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_powerpc.rs b/src/librustc_trans/trans/cabi_powerpc.rs
new file mode 100644
index 00000000000..9fc67e19662
--- /dev/null
+++ b/src/librustc_trans/trans/cabi_powerpc.rs
@@ -0,0 +1,183 @@
+// 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.
+
+use libc::c_uint;
+use llvm;
+use llvm::{Integer, Pointer, Float, Double, Struct, Array};
+use llvm::{StructRetAttribute, ZExtAttribute};
+use trans::cabi::{FnType, ArgType};
+use trans::context::CrateContext;
+use trans::type_::Type;
+
+use std::cmp;
+
+fn align_up_to(off: uint, a: uint) -> uint {
+    return (off + a - 1u) / a * a;
+}
+
+fn align(off: uint, ty: Type) -> uint {
+    let a = ty_align(ty);
+    return align_up_to(off, a);
+}
+
+fn ty_align(ty: Type) -> uint {
+    match ty.kind() {
+        Integer => {
+            unsafe {
+                ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
+            }
+        }
+        Pointer => 4,
+        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_size: unhandled type")
+    }
+}
+
+fn ty_size(ty: Type) -> uint {
+    match ty.kind() {
+        Integer => {
+            unsafe {
+                ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
+            }
+        }
+        Pointer => 4,
+        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 classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
+    if is_reg_ty(ty) {
+        let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
+        ArgType::direct(ty, None, None, attr)
+    } else {
+        ArgType::indirect(ty, Some(StructRetAttribute))
+    }
+}
+
+fn classify_arg_ty(ccx: &CrateContext, ty: Type, offset: &mut uint) -> ArgType {
+    let orig_offset = *offset;
+    let size = ty_size(ty) * 8;
+    let mut align = ty_align(ty);
+
+    align = cmp::min(cmp::max(align, 4), 8);
+    *offset = align_up_to(*offset, align);
+    *offset += align_up_to(size, align * 8) / 8;
+
+    if is_reg_ty(ty) {
+        let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
+        ArgType::direct(ty, None, None, attr)
+    } else {
+        ArgType::direct(
+            ty,
+            Some(struct_ty(ccx, ty)),
+            padding_ty(ccx, align, orig_offset),
+            None
+        )
+    }
+}
+
+fn is_reg_ty(ty: Type) -> bool {
+    return match ty.kind() {
+        Integer
+        | Pointer
+        | Float
+        | Double => true,
+        _ => false
+    };
+}
+
+fn padding_ty(ccx: &CrateContext, align: uint, offset: uint) -> Option<Type> {
+    if ((align - 1 ) & offset) > 0 {
+        Some(Type::i32(ccx))
+    } else {
+        None
+    }
+}
+
+fn coerce_to_int(ccx: &CrateContext, size: uint) -> Vec<Type> {
+    let int_ty = Type::i32(ccx);
+    let mut args = Vec::new();
+
+    let mut n = size / 32;
+    while n > 0 {
+        args.push(int_ty);
+        n -= 1;
+    }
+
+    let r = size % 32;
+    if r > 0 {
+        unsafe {
+            args.push(Type::from_ref(llvm::LLVMIntTypeInContext(ccx.llcx(), r as c_uint)));
+        }
+    }
+
+    args
+}
+
+fn struct_ty(ccx: &CrateContext, ty: Type) -> Type {
+    let size = ty_size(ty) * 8;
+    Type::struct_(ccx, coerce_to_int(ccx, size).as_slice(), 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 sret = ret_ty.is_indirect();
+    let mut arg_tys = Vec::new();
+    let mut offset = if sret { 4 } else { 0 };
+
+    for aty in atys.iter() {
+        let ty = classify_arg_ty(ccx, *aty, &mut offset);
+        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 42134789546..91c6c9a13a3 100644
--- a/src/librustc_trans/trans/mod.rs
+++ b/src/librustc_trans/trans/mod.rs
@@ -45,6 +45,7 @@ mod cabi_x86_win64;
 mod cabi_arm;
 mod cabi_aarch64;
 mod cabi_mips;
+mod cabi_powerpc;
 mod foreign;
 mod intrinsic;
 mod debuginfo;
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
index 588f729d800..fc0c838a3f1 100644
--- a/src/libstd/os.rs
+++ b/src/libstd/os.rs
@@ -1422,6 +1422,11 @@ mod arch_consts {
     pub const ARCH: &'static str = "mipsel";
 }
 
+#[cfg(target_arch = "powerpc")]
+mod arch_consts {
+    pub const ARCH: &'static str = "powerpc";
+}
+
 #[cfg(test)]
 mod tests {
     use prelude::v1::*;
diff --git a/src/libstd/rand/os.rs b/src/libstd/rand/os.rs
index 18d40ecd3eb..68ba7e1dd29 100644
--- a/src/libstd/rand/os.rs
+++ b/src/libstd/rand/os.rs
@@ -32,7 +32,8 @@ mod imp {
               any(target_arch = "x86_64",
                   target_arch = "x86",
                   target_arch = "arm",
-                  target_arch = "aarch64")))]
+                  target_arch = "aarch64",
+                  target_arch = "powerpc")))]
     fn getrandom(buf: &mut [u8]) -> libc::c_long {
         extern "C" {
             fn syscall(number: libc::c_long, ...) -> libc::c_long;
@@ -44,6 +45,8 @@ mod imp {
         const NR_GETRANDOM: libc::c_long = 355;
         #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
         const NR_GETRANDOM: libc::c_long = 384;
+        #[cfg(target_arch = "powerpc")]
+        const NR_GETRANDOM: libc::c_long = 384;
 
         unsafe {
             syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0u)
@@ -54,7 +57,8 @@ mod imp {
                   any(target_arch = "x86_64",
                       target_arch = "x86",
                       target_arch = "arm",
-                      target_arch = "aarch64"))))]
+                      target_arch = "aarch64",
+                      target_arch = "powerpc"))))]
     fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }
 
     fn getrandom_fill_bytes(v: &mut [u8]) {
@@ -91,7 +95,8 @@ mod imp {
               any(target_arch = "x86_64",
                   target_arch = "x86",
                   target_arch = "arm",
-                  target_arch = "aarch64")))]
+                  target_arch = "aarch64",
+                  target_arch = "powerpc")))]
     fn is_getrandom_available() -> bool {
         use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
 
@@ -119,7 +124,8 @@ mod imp {
                   any(target_arch = "x86_64",
                       target_arch = "x86",
                       target_arch = "arm",
-                      target_arch = "aarch64"))))]
+                      target_arch = "aarch64",
+                      target_arch = "powerpc"))))]
     fn is_getrandom_available() -> bool { false }
 
     /// A random number generator that retrieves randomness straight from
diff --git a/src/libstd/rt/libunwind.rs b/src/libstd/rt/libunwind.rs
index 7cc39d7d972..dd9923307d6 100644
--- a/src/libstd/rt/libunwind.rs
+++ b/src/libstd/rt/libunwind.rs
@@ -81,6 +81,9 @@ pub const unwinder_private_data_size: uint = 2;
 #[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
 pub const unwinder_private_data_size: uint = 2;
 
+#[cfg(target_arch = "powerpc")]
+pub const unwinder_private_data_size: uint = 2;
+
 #[repr(C)]
 pub struct _Unwind_Exception {
     pub exception_class: _Unwind_Exception_Class,
diff --git a/src/libstd/sys/common/stack.rs b/src/libstd/sys/common/stack.rs
index ce5ab67ae61..88bb9395cf1 100644
--- a/src/libstd/sys/common/stack.rs
+++ b/src/libstd/sys/common/stack.rs
@@ -231,6 +231,12 @@ pub unsafe fn record_sp_limit(limit: uint) {
     unsafe fn target_record_sp_limit(_: uint) {
     }
 
+    // powerpc - FIXME(POWERPC): missing...
+    #[cfg(target_arch = "powerpc")]
+    unsafe fn target_record_sp_limit(_: uint) {
+    }
+
+
     // iOS segmented stack is disabled for now, see related notes
     #[cfg(all(target_arch = "arm", target_os = "ios"))] #[inline(always)]
     unsafe fn target_record_sp_limit(_: uint) {
@@ -326,6 +332,12 @@ pub unsafe fn get_sp_limit() -> uint {
         1024
     }
 
+    // powepc - FIXME(POWERPC): missing...
+    #[cfg(target_arch = "powerpc")]
+    unsafe fn target_get_sp_limit() -> uint {
+        1024
+    }
+
     // iOS doesn't support segmented stacks yet. This function might
     // be called by runtime though so it is unsafe to mark it as
     // unreachable, let's return a fixed constant.
diff --git a/src/libstd/sys/unix/c.rs b/src/libstd/sys/unix/c.rs
index 1d523ed6edd..fed700cc9d5 100644
--- a/src/libstd/sys/unix/c.rs
+++ b/src/libstd/sys/unix/c.rs
@@ -33,7 +33,9 @@ pub const FIONBIO: libc::c_ulong = 0x8004667e;
           target_os = "android"))]
 pub const FIONBIO: libc::c_ulong = 0x5421;
 #[cfg(all(target_os = "linux",
-          any(target_arch = "mips", target_arch = "mipsel")))]
+          any(target_arch = "mips",
+              target_arch = "mipsel",
+              target_arch = "powerpc")))]
 pub const FIONBIO: libc::c_ulong = 0x667e;
 
 #[cfg(any(target_os = "macos",
@@ -49,7 +51,9 @@ pub const FIOCLEX: libc::c_ulong = 0x20006601;
           target_os = "android"))]
 pub const FIOCLEX: libc::c_ulong = 0x5451;
 #[cfg(all(target_os = "linux",
-          any(target_arch = "mips", target_arch = "mipsel")))]
+          any(target_arch = "mips",
+              target_arch = "mipsel",
+              target_arch = "powerpc")))]
 pub const FIOCLEX: libc::c_ulong = 0x6601;
 
 #[cfg(any(target_os = "macos",
@@ -182,7 +186,9 @@ mod signal {
 }
 
 #[cfg(all(target_os = "linux",
-          any(target_arch = "mips", target_arch = "mipsel")))]
+          any(target_arch = "mips",
+              target_arch = "mipsel",
+              target_arch = "powerpc")))]
 mod signal {
     use libc;
 
diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs
index 48a51813ba4..45680f52e73 100644
--- a/src/libstd/sys/unix/stack_overflow.rs
+++ b/src/libstd/sys/unix/stack_overflow.rs
@@ -150,6 +150,7 @@ mod imp {
               all(target_os = "linux", target_arch = "aarch64"),
               all(target_os = "linux", target_arch = "mips"), // may not match
               all(target_os = "linux", target_arch = "mipsel"), // may not match
+              all(target_os = "linux", target_arch = "powerpc"), // may not match
               target_os = "android"))] // may not match
     mod signal {
         use libc;
diff --git a/src/libstd/sys/unix/sync.rs b/src/libstd/sys/unix/sync.rs
index fbbdee1009d..c1e3fc88794 100644
--- a/src/libstd/sys/unix/sync.rs
+++ b/src/libstd/sys/unix/sync.rs
@@ -126,7 +126,8 @@ mod os {
     #[cfg(any(target_arch = "x86",
               target_arch = "arm",
               target_arch = "mips",
-              target_arch = "mipsel"))]
+              target_arch = "mipsel",
+              target_arch = "powerpc"))]
     const __SIZEOF_PTHREAD_MUTEX_T: uint = 24 - 8;
     #[cfg(target_arch = "aarch64")]
     const __SIZEOF_PTHREAD_MUTEX_T: uint = 48 - 8;
@@ -136,7 +137,8 @@ mod os {
               target_arch = "arm",
               target_arch = "aarch64",
               target_arch = "mips",
-              target_arch = "mipsel"))]
+              target_arch = "mipsel",
+              target_arch = "powerpc"))]
     const __SIZEOF_PTHREAD_COND_T: uint = 48 - 8;
 
     #[cfg(any(target_arch = "x86_64",
@@ -146,7 +148,8 @@ mod os {
     #[cfg(any(target_arch = "x86",
               target_arch = "arm",
               target_arch = "mips",
-              target_arch = "mipsel"))]
+              target_arch = "mipsel",
+              target_arch = "powerpc"))]
     const __SIZEOF_PTHREAD_RWLOCK_T: uint = 32 - 8;
 
     #[repr(C)]
diff --git a/src/rt/arch/powerpc/morestack.S b/src/rt/arch/powerpc/morestack.S
new file mode 100644
index 00000000000..2502ac1eb48
--- /dev/null
+++ b/src/rt/arch/powerpc/morestack.S
@@ -0,0 +1,18 @@
+// Mark stack as non-executable
+#if defined(__linux__) && defined(__ELF__)
+.section       .note.GNU-stack, "", %progbits
+#endif
+
+/* See i386/morestack.S for the lengthy, general explanation. */
+
+.global rust_stack_exhausted
+
+.hidden __morestack
+
+// FIXME(POWERPC): this might not be perfectly right but works for now
+__morestack:
+       .cfi_startproc
+       bl rust_stack_exhausted
+       // the above function ensures that it never returns
+       .cfi_endproc
+.end  __morestack
diff --git a/src/rt/arch/powerpc/record_sp.S b/src/rt/arch/powerpc/record_sp.S
new file mode 100644
index 00000000000..e93a69a711b
--- /dev/null
+++ b/src/rt/arch/powerpc/record_sp.S
@@ -0,0 +1,4 @@
+// Mark stack as non-executable
+#if defined(__linux__) && defined(__ELF__)
+.section       .note.GNU-stack, "", %progbits
+#endif
diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger
index 2ac855681f2..4a16b9c257c 100644
--- a/src/rustllvm/llvm-auto-clean-trigger
+++ b/src/rustllvm/llvm-auto-clean-trigger
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2015-01-05
+2015-01-13