about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-09-02 03:01:48 -0700
committerGitHub <noreply@github.com>2016-09-02 03:01:48 -0700
commit689c6c48ecd3d89d120c6aecf8b69222920e4520 (patch)
tree8bd8088e0fd7273a62b3123ebb9ea5ef1a72405d
parent022cb6d11d7d3529fc09283d058e66017dadeb8c (diff)
parentbbf2c3c31f3dd7703f4a13724bada979a921a65f (diff)
downloadrust-689c6c48ecd3d89d120c6aecf8b69222920e4520.tar.gz
rust-689c6c48ecd3d89d120c6aecf8b69222920e4520.zip
Auto merge of #36024 - japaric:mips64, r=alexcrichton
add mips64-gnu and mips64el-gnu targets

With this commit one can build no_core (and probably no_std as well)
Rust programs for these targets. It's not yet possible to cross compile
std for these targets because rust-lang/libc doesn't know about the
mips64 architecture.

These targets have been tested by cross compiling the "smallest hello"
program (see code below) and then running it under QEMU.

``` rust

extern {
    fn puts(_: *const u8);
}

fn start(_: isize, _: *const *const u8) -> isize {
    unsafe {
        let msg = b"Hello, world!\0";
        puts(msg as *const _ as *const u8);
    }
    0
}

trait Copy {}

trait Sized {}
```

cc #36015
r? @alexcrichton
cc @brson

The cabi stuff is likely wrong. I just copied cabi_mips source and changed some `4`s to `8`s and `32`s to `64`s. It was enough to get libc's `puts` to work but I'd like someone familiar with this module to check it.
-rw-r--r--mk/cfg/mips64-unknown-linux-gnuabi64.mk1
-rw-r--r--mk/cfg/mips64el-unknown-linux-gnuabi64.mk1
-rw-r--r--src/liballoc_jemalloc/lib.rs3
-rw-r--r--src/liballoc_system/lib.rs3
m---------src/liblibc0
-rw-r--r--src/libpanic_unwind/gcc.rs2
-rw-r--r--src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs31
-rw-r--r--src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs31
-rw-r--r--src/librustc_back/target/mod.rs2
-rw-r--r--src/librustc_trans/abi.rs2
-rw-r--r--src/librustc_trans/cabi_mips64.rs168
-rw-r--r--src/librustc_trans/cabi_powerpc.rs12
-rw-r--r--src/librustc_trans/lib.rs1
-rw-r--r--src/libstd/env.rs6
-rw-r--r--src/libstd/os/linux/raw.rs5
-rw-r--r--src/libunwind/libunwind.rs3
16 files changed, 258 insertions, 13 deletions
diff --git a/mk/cfg/mips64-unknown-linux-gnuabi64.mk b/mk/cfg/mips64-unknown-linux-gnuabi64.mk
new file mode 100644
index 00000000000..34aee77ae21
--- /dev/null
+++ b/mk/cfg/mips64-unknown-linux-gnuabi64.mk
@@ -0,0 +1 @@
+# rustbuild-only target
diff --git a/mk/cfg/mips64el-unknown-linux-gnuabi64.mk b/mk/cfg/mips64el-unknown-linux-gnuabi64.mk
new file mode 100644
index 00000000000..34aee77ae21
--- /dev/null
+++ b/mk/cfg/mips64el-unknown-linux-gnuabi64.mk
@@ -0,0 +1 @@
+# rustbuild-only target
diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs
index 347e97e6ffc..aae0528e42c 100644
--- a/src/liballoc_jemalloc/lib.rs
+++ b/src/liballoc_jemalloc/lib.rs
@@ -77,7 +77,8 @@ const MIN_ALIGN: usize = 8;
 #[cfg(all(any(target_arch = "x86",
               target_arch = "x86_64",
               target_arch = "aarch64",
-              target_arch = "powerpc64")))]
+              target_arch = "powerpc64",
+              target_arch = "mips64")))]
 const MIN_ALIGN: usize = 16;
 
 // MALLOCX_ALIGN(a) macro
diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs
index 9eade937bfb..2c0c6d068ca 100644
--- a/src/liballoc_system/lib.rs
+++ b/src/liballoc_system/lib.rs
@@ -32,7 +32,8 @@
               target_arch = "asmjs")))]
 const MIN_ALIGN: usize = 8;
 #[cfg(all(any(target_arch = "x86_64",
-              target_arch = "aarch64")))]
+              target_arch = "aarch64",
+              target_arch = "mips64")))]
 const MIN_ALIGN: usize = 16;
 
 #[no_mangle]
diff --git a/src/liblibc b/src/liblibc
-Subproject 5066b7dcab7e700844b0e2ba71b8af9dc627a59
+Subproject 49d64cae0699ed9d9ed84810d737a26b0b519da
diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs
index bd0c2f5126d..c2e8eccbd22 100644
--- a/src/libpanic_unwind/gcc.rs
+++ b/src/libpanic_unwind/gcc.rs
@@ -124,7 +124,7 @@ const UNWIND_DATA_REG: (i32, i32) = (0, 1); // RAX, RDX
 #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
 const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 / X0, X1
 
-#[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
+#[cfg(any(target_arch = "mips", target_arch = "mipsel", target_arch = "mips64"))]
 const UNWIND_DATA_REG: (i32, i32) = (4, 5); // A0, A1
 
 #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
diff --git a/src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs b/src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs
new file mode 100644
index 00000000000..83785634428
--- /dev/null
+++ b/src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs
@@ -0,0 +1,31 @@
+// 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, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    Ok(Target {
+        llvm_target: "mips64-unknown-linux-gnuabi64".to_string(),
+        target_endian: "big".to_string(),
+        target_pointer_width: "64".to_string(),
+        data_layout: "E-m:m-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
+        arch: "mips64".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "gnu".to_string(),
+        target_vendor: "unknown".to_string(),
+        options: TargetOptions {
+            // NOTE(mips64r2) matches C toolchain
+            cpu: "mips64r2".to_string(),
+            features: "+mips64r2".to_string(),
+            max_atomic_width: 64,
+            ..super::linux_base::opts()
+        },
+    })
+}
diff --git a/src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs b/src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs
new file mode 100644
index 00000000000..e1340e8e127
--- /dev/null
+++ b/src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs
@@ -0,0 +1,31 @@
+// 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, TargetOptions, TargetResult};
+
+pub fn target() -> TargetResult {
+    Ok(Target {
+        llvm_target: "mips64el-unknown-linux-gnuabi64".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        data_layout: "e-m:m-i8:8:32-i16:16:32-i64:64-n32:64-S128".to_string(),
+        arch: "mips64".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "gnu".to_string(),
+        target_vendor: "unknown".to_string(),
+        options: TargetOptions {
+            // NOTE(mips64r2) matches C toolchain
+            cpu: "mips64r2".to_string(),
+            features: "+mips64r2".to_string(),
+            max_atomic_width: 64,
+            ..super::linux_base::opts()
+        },
+    })
+}
diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs
index 86325cfe544..d48370b23b6 100644
--- a/src/librustc_back/target/mod.rs
+++ b/src/librustc_back/target/mod.rs
@@ -128,6 +128,8 @@ supported_targets! {
     ("i686-unknown-linux-gnu", i686_unknown_linux_gnu),
     ("i586-unknown-linux-gnu", i586_unknown_linux_gnu),
     ("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
+    ("mips64-unknown-linux-gnuabi64", mips64_unknown_linux_gnuabi64),
+    ("mips64el-unknown-linux-gnuabi64", mips64el_unknown_linux_gnuabi64),
     ("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu),
     ("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu),
     ("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs
index 7f209dde27d..c2b040c32f6 100644
--- a/src/librustc_trans/abi.rs
+++ b/src/librustc_trans/abi.rs
@@ -21,6 +21,7 @@ use cabi_aarch64;
 use cabi_powerpc;
 use cabi_powerpc64;
 use cabi_mips;
+use cabi_mips64;
 use cabi_asmjs;
 use machine::{llalign_of_min, llsize_of, llsize_of_real, llsize_of_store};
 use type_::Type;
@@ -501,6 +502,7 @@ impl FnType {
                 cabi_arm::compute_abi_info(ccx, self, flavor);
             },
             "mips" => cabi_mips::compute_abi_info(ccx, self),
+            "mips64" => cabi_mips64::compute_abi_info(ccx, self),
             "powerpc" => cabi_powerpc::compute_abi_info(ccx, self),
             "powerpc64" => cabi_powerpc64::compute_abi_info(ccx, self),
             "asmjs" => cabi_asmjs::compute_abi_info(ccx, self),
diff --git a/src/librustc_trans/cabi_mips64.rs b/src/librustc_trans/cabi_mips64.rs
new file mode 100644
index 00000000000..e92ef1eaec8
--- /dev/null
+++ b/src/librustc_trans/cabi_mips64.rs
@@ -0,0 +1,168 @@
+// 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_upper_case_globals)]
+
+use libc::c_uint;
+use std::cmp;
+use llvm;
+use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
+use abi::{ArgType, FnType};
+use context::CrateContext;
+use type_::Type;
+
+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)
+        }
+        Vector => {
+            let len = ty.vector_length();
+            let elt = ty.element_type();
+            ty_align(elt) * len
+        }
+        _ => bug!("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
+        }
+        Vector => {
+            let len = ty.vector_length();
+            let elt = ty.element_type();
+            let eltsz = ty_size(elt);
+            len * eltsz
+        }
+        _ => bug!("ty_size: unhandled type")
+    }
+}
+
+fn classify_ret_ty(ccx: &CrateContext, ret: &mut ArgType) {
+    if is_reg_ty(ret.ty) {
+        ret.extend_integer_width_to(64);
+    } else {
+        ret.make_indirect(ccx);
+    }
+}
+
+fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType, offset: &mut usize) {
+    let orig_offset = *offset;
+    let size = ty_size(arg.ty) * 8;
+    let mut align = ty_align(arg.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(arg.ty) {
+        arg.cast = Some(struct_ty(ccx, arg.ty));
+        arg.pad = padding_ty(ccx, align, orig_offset);
+    } else {
+        arg.extend_integer_width_to(64);
+    }
+}
+
+fn is_reg_ty(ty: Type) -> bool {
+    return match ty.kind() {
+        Integer
+        | Pointer
+        | Float
+        | Double
+        | Vector => true,
+        _ => false
+    };
+}
+
+fn padding_ty(ccx: &CrateContext, align: usize, offset: usize) -> Option<Type> {
+    if ((align - 1 ) & offset) > 0 {
+        Some(Type::i64(ccx))
+    } else {
+        None
+    }
+}
+
+fn coerce_to_int(ccx: &CrateContext, size: usize) -> Vec<Type> {
+    let int_ty = Type::i64(ccx);
+    let mut args = Vec::new();
+
+    let mut n = size / 64;
+    while n > 0 {
+        args.push(int_ty);
+        n -= 1;
+    }
+
+    let r = size % 64;
+    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), false)
+}
+
+pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
+    if !fty.ret.is_ignore() {
+        classify_ret_ty(ccx, &mut fty.ret);
+    }
+
+    let mut offset = if fty.ret.is_indirect() { 8 } else { 0 };
+    for arg in &mut fty.args {
+        if arg.is_ignore() { continue; }
+        classify_arg_ty(ccx, arg, &mut offset);
+    }
+}
diff --git a/src/librustc_trans/cabi_powerpc.rs b/src/librustc_trans/cabi_powerpc.rs
index efbdce67a8b..e05c31b1d88 100644
--- a/src/librustc_trans/cabi_powerpc.rs
+++ b/src/librustc_trans/cabi_powerpc.rs
@@ -28,11 +28,7 @@ fn align(off: usize, ty: Type) -> usize {
 
 fn ty_align(ty: Type) -> usize {
     match ty.kind() {
-        Integer => {
-            unsafe {
-                ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as usize) + 7) / 8
-            }
-        }
+        Integer => ((ty.int_width() as usize) + 7) / 8,
         Pointer => 4,
         Float => 4,
         Double => 8,
@@ -54,11 +50,7 @@ fn ty_align(ty: Type) -> usize {
 
 fn ty_size(ty: Type) -> usize {
     match ty.kind() {
-        Integer => {
-            unsafe {
-                ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as usize) + 7) / 8
-            }
-        }
+        Integer => ((ty.int_width() as usize) + 7) / 8,
         Pointer => 4,
         Float => 4,
         Double => 8,
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index 1286df7b97e..6ede55d5ff4 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -98,6 +98,7 @@ mod cabi_aarch64;
 mod cabi_arm;
 mod cabi_asmjs;
 mod cabi_mips;
+mod cabi_mips64;
 mod cabi_powerpc;
 mod cabi_powerpc64;
 mod cabi_x86;
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index 7a94c396218..9fcc3a80b98 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -659,6 +659,7 @@ pub mod consts {
     /// - arm
     /// - aarch64
     /// - mips
+    /// - mips64
     /// - powerpc
     /// - powerpc64
     #[stable(feature = "env", since = "1.0.0")]
@@ -926,6 +927,11 @@ mod arch {
     pub const ARCH: &'static str = "mips";
 }
 
+#[cfg(target_arch = "mips64")]
+mod arch {
+    pub const ARCH: &'static str = "mips64";
+}
+
 #[cfg(target_arch = "powerpc")]
 mod arch {
     pub const ARCH: &'static str = "powerpc";
diff --git a/src/libstd/os/linux/raw.rs b/src/libstd/os/linux/raw.rs
index 1be76961fea..0f62877500b 100644
--- a/src/libstd/os/linux/raw.rs
+++ b/src/libstd/os/linux/raw.rs
@@ -155,6 +155,11 @@ 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 = "aarch64")]
 mod arch {
     use os::raw::{c_long, c_int};
diff --git a/src/libunwind/libunwind.rs b/src/libunwind/libunwind.rs
index 680ad3ecd64..8292a684178 100644
--- a/src/libunwind/libunwind.rs
+++ b/src/libunwind/libunwind.rs
@@ -56,6 +56,9 @@ pub const unwinder_private_data_size: usize = 2;
 #[cfg(target_arch = "mips")]
 pub const unwinder_private_data_size: usize = 2;
 
+#[cfg(target_arch = "mips64")]
+pub const unwinder_private_data_size: usize = 2;
+
 #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
 pub const unwinder_private_data_size: usize = 2;