Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sparc64-unknown-netbsd target #38656

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion configure
Original file line number Diff line number Diff line change
Expand Up @@ -1822,7 +1822,7 @@ do
CMAKE_ARGS="$CMAKE_ARGS -DLLVM_ENABLE_ASSERTIONS=ON"
fi

CMAKE_ARGS="$CMAKE_ARGS -DLLVM_TARGETS_TO_BUILD='X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430'"
CMAKE_ARGS="$CMAKE_ARGS -DLLVM_TARGETS_TO_BUILD='X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc'"
CMAKE_ARGS="$CMAKE_ARGS -G '$CFG_CMAKE_GENERATOR'"
CMAKE_ARGS="$CMAKE_ARGS $CFG_LLVM_SRC_DIR"

Expand Down
3 changes: 3 additions & 0 deletions mk/cfg/sparc64-unknown-netbsd.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# This file is intentially left empty to indicate that, while this target is
# supported, it's not supported using plain GNU Make builds. Use a --rustbuild
# instead.
2 changes: 1 addition & 1 deletion mk/main.mk
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ endif
# LLVM macros
######################################################################

LLVM_OPTIONAL_COMPONENTS=x86 arm aarch64 mips powerpc pnacl systemz jsbackend msp430
LLVM_OPTIONAL_COMPONENTS=x86 arm aarch64 mips powerpc pnacl systemz jsbackend msp430 sparc
LLVM_REQUIRED_COMPONENTS=ipo bitreader bitwriter linker asmparser mcjit \
interpreter instrumentation

Expand Down
3 changes: 2 additions & 1 deletion src/liballoc_jemalloc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ mod imp {
target_arch = "aarch64",
target_arch = "powerpc64",
target_arch = "mips64",
target_arch = "s390x")))]
target_arch = "s390x",
target_arch = "sparc64")))]
const MIN_ALIGN: usize = 16;

// MALLOCX_ALIGN(a) macro
Expand Down
3 changes: 2 additions & 1 deletion src/liballoc_system/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ const MIN_ALIGN: usize = 8;
#[cfg(all(any(target_arch = "x86_64",
target_arch = "aarch64",
target_arch = "mips64",
target_arch = "s390x")))]
target_arch = "s390x",
target_arch = "sparc64")))]
const MIN_ALIGN: usize = 16;

#[no_mangle]
Expand Down
3 changes: 3 additions & 0 deletions src/libpanic_unwind/gcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 / X3, X4
#[cfg(target_arch = "s390x")]
const UNWIND_DATA_REG: (i32, i32) = (6, 7); // R6, R7

#[cfg(target_arch = "sparc64")]
const UNWIND_DATA_REG: (i32, i32) = (24, 25); // I0, I1

// The following code is based on GCC's C and C++ personality routines. For reference, see:
// https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
// https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
Expand Down
1 change: 1 addition & 0 deletions src/librustc_back/target/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ supported_targets! {
("i686-unknown-openbsd", i686_unknown_openbsd),
("x86_64-unknown-openbsd", x86_64_unknown_openbsd),

("sparc64-unknown-netbsd", sparc64_unknown_netbsd),
("x86_64-unknown-netbsd", x86_64_unknown_netbsd),
("x86_64-rumprun-netbsd", x86_64_rumprun_netbsd),

Expand Down
30 changes: 30 additions & 0 deletions src/librustc_back/target/sparc64_unknown_netbsd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// 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, TargetResult};

pub fn target() -> TargetResult {
let mut base = super::netbsd_base::opts();
base.cpu = "v9".to_string();
base.pre_link_args.push("-m64".to_string());
base.max_atomic_width = Some(64);

Ok(Target {
llvm_target: "sparc64-unknown-netbsd".to_string(),
target_endian: "big".to_string(),
target_pointer_width: "64".to_string(),
data_layout: "E-m:e-i64:64-n32:64-S128".to_string(),
arch: "sparc64".to_string(),
target_os: "netbsd".to_string(),
target_env: "".to_string(),
target_vendor: "unknown".to_string(),
options: base,
})
}
2 changes: 2 additions & 0 deletions src/librustc_trans/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use cabi_mips64;
use cabi_asmjs;
use cabi_msp430;
use cabi_sparc;
use cabi_sparc64;
use cabi_nvptx;
use cabi_nvptx64;
use machine::{llalign_of_min, llsize_of, llsize_of_alloc};
Expand Down Expand Up @@ -611,6 +612,7 @@ impl FnType {
"wasm32" => cabi_asmjs::compute_abi_info(ccx, self),
"msp430" => cabi_msp430::compute_abi_info(ccx, self),
"sparc" => cabi_sparc::compute_abi_info(ccx, self),
"sparc64" => cabi_sparc64::compute_abi_info(ccx, self),
"nvptx" => cabi_nvptx::compute_abi_info(ccx, self),
"nvptx64" => cabi_nvptx64::compute_abi_info(ccx, self),
a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a))
Expand Down
185 changes: 185 additions & 0 deletions src/librustc_trans/cabi_sparc64.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
// 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: This needs an audit for correctness and completeness.

use llvm::{Integer, Pointer, Float, Double, Struct, Vector, Array};
use abi::{self, FnType, ArgType};
use context::CrateContext;
use type_::Type;

fn ty_size(ty: Type) -> usize {
if ty.kind() == Vector {
bug!("ty_size: unhandled type")
} else {
abi::ty_size(ty, 8)
}
}

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, ret: &mut ArgType) {
if is_reg_ty(ret.ty) {
ret.extend_integer_width_to(64);
return;
}

// don't return aggregates in registers
ret.make_indirect(ccx);

if let Some((base_ty, members)) = is_homogenous_aggregate_ty(ret.ty) {
ret.cast = Some(Type::array(&base_ty, members));
return;
}
let size = ty_size(ret.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)
};
ret.cast = Some(llty);
return;
}
}

fn classify_arg_ty(ccx: &CrateContext, arg: &mut ArgType) {
if is_reg_ty(arg.ty) {
arg.extend_integer_width_to(64);
return;
}

if let Some((base_ty, members)) = is_homogenous_aggregate_ty(arg.ty) {
arg.cast = Some(Type::array(&base_ty, members));
return;
}

arg.cast = Some(struct_ty(ccx, arg.ty));
}

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, fty: &mut FnType) {
if !fty.ret.is_ignore() {
classify_ret_ty(ccx, &mut fty.ret);
}

for arg in &mut fty.args {
if arg.is_ignore() { continue; }
classify_arg_ty(ccx, arg);
}
}
1 change: 1 addition & 0 deletions src/librustc_trans/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ mod cabi_powerpc;
mod cabi_powerpc64;
mod cabi_s390x;
mod cabi_sparc;
mod cabi_sparc64;
mod cabi_x86;
mod cabi_x86_64;
mod cabi_x86_win64;
Expand Down
6 changes: 6 additions & 0 deletions src/libstd/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,7 @@ pub mod consts {
/// - powerpc
/// - powerpc64
/// - s390x
/// - sparc64
#[stable(feature = "env", since = "1.0.0")]
pub const ARCH: &'static str = super::arch::ARCH;

Expand Down Expand Up @@ -843,6 +844,11 @@ mod arch {
pub const ARCH: &'static str = "s390x";
}

#[cfg(target_arch = "sparc64")]
mod arch {
pub const ARCH: &'static str = "sparc64";
}

#[cfg(target_arch = "le32")]
mod arch {
pub const ARCH: &'static str = "le32";
Expand Down
3 changes: 3 additions & 0 deletions src/libunwind/libunwind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ pub const unwinder_private_data_size: usize = 2;
#[cfg(target_arch = "s390x")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(target_arch = "sparc64")]
pub const unwinder_private_data_size: usize = 2;

#[cfg(target_os = "emscripten")]
pub const unwinder_private_data_size: usize = 20;

Expand Down
9 changes: 8 additions & 1 deletion src/rustllvm/PassWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,14 +141,21 @@ extern "C" void LLVMRustAddPass(LLVMPassManagerRef PM, LLVMPassRef rust_pass) {
#define SUBTARGET_MSP430
#endif

#ifdef LLVM_COMPONENT_SPARC
#define SUBTARGET_SPARC SUBTARGET(Sparc)
#else
#define SUBTARGET_SPARC
#endif

#define GEN_SUBTARGETS \
SUBTARGET_X86 \
SUBTARGET_ARM \
SUBTARGET_AARCH64 \
SUBTARGET_MIPS \
SUBTARGET_PPC \
SUBTARGET_SYSTEMZ \
SUBTARGET_MSP430
SUBTARGET_MSP430 \
SUBTARGET_SPARC

#define SUBTARGET(x) \
namespace llvm { \
Expand Down