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.
This commit is contained in:
commit
689c6c48ec
|
@ -0,0 +1 @@
|
|||
# rustbuild-only target
|
|
@ -0,0 +1 @@
|
|||
# rustbuild-only target
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 5066b7dcab7e700844b0e2ba71b8af9dc627a59b
|
||||
Subproject commit 49d64cae0699ed9d9ed84810d737a26b0b519da8
|
|
@ -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"))]
|
||||
|
|
|
@ -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()
|
||||
},
|
||||
})
|
||||
}
|
|
@ -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()
|
||||
},
|
||||
})
|
||||
}
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue