From 6a5bdb78f15b8e53fa848e31c90298edf6c48d6c Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 26 Aug 2016 17:06:13 -0500 Subject: [PATCH 1/6] 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 #![feature(start)] #![feature(lang_items)] #![feature(no_core)] #![no_core] #[link(name = "c")] extern { fn puts(_: *const u8); } #[start] fn start(_: isize, _: *const *const u8) -> isize { unsafe { let msg = b"Hello, world!\0"; puts(msg as *const _ as *const u8); } 0 } #[lang = "copy"] trait Copy {} #[lang = "sized"] trait Sized {} ``` --- mk/cfg/mips64-unknown-linux-gnuabi64.mk | 1 + mk/cfg/mips64el-unknown-linux-gnuabi64.mk | 1 + .../target/mips64_unknown_linux_gnuabi64.rs | 31 ++++ .../target/mips64el_unknown_linux_gnuabi64.rs | 31 ++++ src/librustc_back/target/mod.rs | 2 + src/librustc_trans/abi.rs | 2 + src/librustc_trans/cabi_mips64.rs | 168 ++++++++++++++++++ src/librustc_trans/cabi_powerpc.rs | 12 +- src/librustc_trans/lib.rs | 1 + 9 files changed, 239 insertions(+), 10 deletions(-) create mode 100644 mk/cfg/mips64-unknown-linux-gnuabi64.mk create mode 100644 mk/cfg/mips64el-unknown-linux-gnuabi64.mk create mode 100644 src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs create mode 100644 src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs create mode 100644 src/librustc_trans/cabi_mips64.rs diff --git a/mk/cfg/mips64-unknown-linux-gnuabi64.mk b/mk/cfg/mips64-unknown-linux-gnuabi64.mk new file mode 100644 index 0000000000000..34aee77ae2107 --- /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 0000000000000..34aee77ae2107 --- /dev/null +++ b/mk/cfg/mips64el-unknown-linux-gnuabi64.mk @@ -0,0 +1 @@ +# rustbuild-only target 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 0000000000000..7e45b32065360 --- /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 or the MIT license +// , 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:e-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 0000000000000..338a5da1e1d1d --- /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 or the MIT license +// , 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:e-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 86cd86d282cf5..3c5ec84a8fa68 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 3a7fde6a36bad..5e264c80c4c1c 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; @@ -498,6 +499,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 0000000000000..d3d3f83eac431 --- /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 or the MIT license +// , 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 { + if ((align - 1 ) & offset) > 0 { + Some(Type::i32(ccx)) + } else { + None + } +} + +fn coerce_to_int(ccx: &CrateContext, size: usize) -> Vec { + let int_ty = Type::i32(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 efbdce67a8b2a..e05c31b1d88cd 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 1286df7b97e67..6ede55d5ff49a 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; From 1b9e9ab1dc523c4778a2510e4f9e2d470fe7a4a3 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Fri, 26 Aug 2016 20:25:59 -0500 Subject: [PATCH 2/6] update libc --- src/liblibc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liblibc b/src/liblibc index 5066b7dcab7e7..71b5d57ada32c 160000 --- a/src/liblibc +++ b/src/liblibc @@ -1 +1 @@ -Subproject commit 5066b7dcab7e700844b0e2ba71b8af9dc627a59b +Subproject commit 71b5d57ada32cc5076791becc3b9019da29dffd4 From 43615a03f31d3c60c4af13a1fe17bd4cf3edad06 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sat, 27 Aug 2016 01:39:29 -0500 Subject: [PATCH 3/6] fix cross compilation of std --- src/liballoc_jemalloc/lib.rs | 3 ++- src/liballoc_system/lib.rs | 3 ++- src/libpanic_unwind/gcc.rs | 2 +- src/libstd/env.rs | 6 ++++++ src/libstd/os/linux/raw.rs | 5 +++++ src/libunwind/libunwind.rs | 3 +++ 6 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/liballoc_jemalloc/lib.rs b/src/liballoc_jemalloc/lib.rs index 347e97e6ffc0a..aae0528e42cc9 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 9eade937bfb4c..2c0c6d068caae 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/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index bd0c2f5126d13..c2e8eccbd22a4 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/libstd/env.rs b/src/libstd/env.rs index 753411991abea..0380965ed2058 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -661,6 +661,7 @@ pub mod consts { /// - arm /// - aarch64 /// - mips + /// - mips64 /// - powerpc /// - powerpc64 #[stable(feature = "env", since = "1.0.0")] @@ -928,6 +929,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 1be76961fea9e..0f62877500b2c 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 680ad3ecd64a6..8292a68417810 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; From bc288a598c018273343f29f6ad609062ce4ac2c7 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sun, 28 Aug 2016 17:41:26 -0500 Subject: [PATCH 4/6] cabi: change some more 32s to 64s --- src/librustc_trans/cabi_mips64.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_trans/cabi_mips64.rs b/src/librustc_trans/cabi_mips64.rs index d3d3f83eac431..e92ef1eaec8ec 100644 --- a/src/librustc_trans/cabi_mips64.rs +++ b/src/librustc_trans/cabi_mips64.rs @@ -124,14 +124,14 @@ fn is_reg_ty(ty: Type) -> bool { fn padding_ty(ccx: &CrateContext, align: usize, offset: usize) -> Option { if ((align - 1 ) & offset) > 0 { - Some(Type::i32(ccx)) + Some(Type::i64(ccx)) } else { None } } fn coerce_to_int(ccx: &CrateContext, size: usize) -> Vec { - let int_ty = Type::i32(ccx); + let int_ty = Type::i64(ccx); let mut args = Vec::new(); let mut n = size / 64; From 2222d437a75dec627a21c0b68b32bee080fa1f5a Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Sun, 28 Aug 2016 21:34:04 -0500 Subject: [PATCH 5/6] fix data-layouts --- src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs | 2 +- src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs b/src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs index 7e45b32065360..837856344280f 100644 --- a/src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs +++ b/src/librustc_back/target/mips64_unknown_linux_gnuabi64.rs @@ -15,7 +15,7 @@ pub fn target() -> TargetResult { llvm_target: "mips64-unknown-linux-gnuabi64".to_string(), target_endian: "big".to_string(), target_pointer_width: "64".to_string(), - data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".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(), diff --git a/src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs b/src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs index 338a5da1e1d1d..e1340e8e127b2 100644 --- a/src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs +++ b/src/librustc_back/target/mips64el_unknown_linux_gnuabi64.rs @@ -15,7 +15,7 @@ pub fn target() -> TargetResult { llvm_target: "mips64el-unknown-linux-gnuabi64".to_string(), target_endian: "little".to_string(), target_pointer_width: "64".to_string(), - data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".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(), From bbf2c3c31f3dd7703f4a13724bada979a921a65f Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Mon, 29 Aug 2016 12:25:06 -0500 Subject: [PATCH 6/6] update libc submodule --- src/liblibc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liblibc b/src/liblibc index 71b5d57ada32c..49d64cae0699e 160000 --- a/src/liblibc +++ b/src/liblibc @@ -1 +1 @@ -Subproject commit 71b5d57ada32cc5076791becc3b9019da29dffd4 +Subproject commit 49d64cae0699ed9d9ed84810d737a26b0b519da8