Skip to content

Commit

Permalink
Rollup merge of rust-lang#55562 - smaeul:powerpc-linux-musl, r=alexcr…
Browse files Browse the repository at this point in the history
…ichton

Add powerpc- and powerpc64-unknown-linux-musl targets

Add targets for musl on 32-bit and 64-bit powerpc. This requires some ABI fixes, as musl [uses the ELFv2 ABI on regardless of endianness](http://git.musl-libc.org/cgit/musl/tree/configure?id=8084d6ab57cdb0b8f328d3cdbad3b9d09eaaee04#n638). At the moment, powerpc64 support requires [an LLVM patch](https://reviews.llvm.org/D52013) to select the correct ABI; or I can add [a patch to Rust's LLVM backend](smaeul@e8eaa2a) to always choose the right ABI.

Both architectures are able to run an extended bootstrap, and with some test fixes (e.g. rust-lang#55561), there are no architecture-dependent test failures on powerpc64 (most failures in `src/test` are existing musl-host-related issues).
  • Loading branch information
pietroalbini authored Nov 18, 2018
2 parents 13c9439 + 4f9c860 commit 36e1d9f
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 23 deletions.
44 changes: 22 additions & 22 deletions src/librustc_target/abi/call/powerpc64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@

use abi::call::{FnType, ArgType, Reg, RegKind, Uniform};
use abi::{Align, Endian, HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
use spec::HasTargetSpec;

#[derive(Debug, Clone, Copy, PartialEq)]
enum ABI {
ELFv1, // original ABI used for powerpc64 (big-endian)
ELFv2, // newer ABI used for powerpc64le
ELFv2, // newer ABI used for powerpc64le and musl (both endians)
}
use self::ABI::*;

Expand Down Expand Up @@ -75,7 +76,9 @@ fn classify_ret_ty<'a, Ty, C>(cx: &C, ret: &mut ArgType<'a, Ty>, abi: ABI)
let size = ret.layout.size;
let bits = size.bits();
if bits <= 128 {
let unit = if bits <= 8 {
let unit = if cx.data_layout().endian == Endian::Big {
Reg { kind: RegKind::Integer, size }
} else if bits <= 8 {
Reg::i8()
} else if bits <= 16 {
Reg::i16()
Expand Down Expand Up @@ -110,22 +113,15 @@ fn classify_arg_ty<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>, abi: ABI)
}

let size = arg.layout.size;
let (unit, total) = match abi {
ELFv1 => {
// In ELFv1, aggregates smaller than a doubleword should appear in
// the least-significant bits of the parameter doubleword. The rest
// should be padded at their tail to fill out multiple doublewords.
if size.bits() <= 64 {
(Reg { kind: RegKind::Integer, size }, size)
} else {
let align = Align::from_bits(64, 64).unwrap();
(Reg::i64(), size.abi_align(align))
}
},
ELFv2 => {
// In ELFv2, we can just cast directly.
(Reg::i64(), size)
},
let (unit, total) = if size.bits() <= 64 {
// Aggregates smaller than a doubleword should appear in
// the least-significant bits of the parameter doubleword.
(Reg { kind: RegKind::Integer, size }, size)
} else {
// Aggregates larger than a doubleword should be padded
// at the tail to fill out a whole number of doublewords.
let align = Align::from_bits(64, 64).unwrap();
(Reg::i64(), size.abi_align(align))
};

arg.cast_to(Uniform {
Expand All @@ -136,11 +132,15 @@ fn classify_arg_ty<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>, abi: ABI)

pub fn compute_abi_info<'a, Ty, C>(cx: &C, fty: &mut FnType<'a, Ty>)
where Ty: TyLayoutMethods<'a, C> + Copy,
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout + HasTargetSpec
{
let abi = match cx.data_layout().endian {
Endian::Big => ELFv1,
Endian::Little => ELFv2,
let abi = if cx.target_spec().target_env == "musl" {
ELFv2
} else {
match cx.data_layout().endian {
Endian::Big => ELFv1,
Endian::Little => ELFv2
}
};

if !fty.ret.is_ignore() {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_target/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ impl HasDataLayout for TargetDataLayout {
}

/// Endianness of the target, which must match cfg(target-endian).
#[derive(Copy, Clone)]
#[derive(Copy, Clone, PartialEq)]
pub enum Endian {
Little,
Big
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_target/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,9 @@ supported_targets! {
("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu),
("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu),
("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe),
("powerpc-unknown-linux-musl", powerpc_unknown_linux_musl),
("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
("powerpc64-unknown-linux-musl", powerpc64_unknown_linux_musl),
("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl),
("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
Expand Down
32 changes: 32 additions & 0 deletions src/librustc_target/spec/powerpc64_unknown_linux_musl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2018 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 spec::{LinkerFlavor, Target, TargetResult};

pub fn target() -> TargetResult {
let mut base = super::linux_musl_base::opts();
base.cpu = "ppc64".to_string();
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
base.max_atomic_width = Some(64);

Ok(Target {
llvm_target: "powerpc64-unknown-linux-musl".to_string(),
target_endian: "big".to_string(),
target_pointer_width: "64".to_string(),
target_c_int_width: "32".to_string(),
data_layout: "E-m:e-i64:64-n32:64".to_string(),
arch: "powerpc64".to_string(),
target_os: "linux".to_string(),
target_env: "musl".to_string(),
target_vendor: "unknown".to_string(),
linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}
31 changes: 31 additions & 0 deletions src/librustc_target/spec/powerpc_unknown_linux_musl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright 2018 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 spec::{LinkerFlavor, Target, TargetResult};

pub fn target() -> TargetResult {
let mut base = super::linux_musl_base::opts();
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
base.max_atomic_width = Some(32);

Ok(Target {
llvm_target: "powerpc-unknown-linux-musl".to_string(),
target_endian: "big".to_string(),
target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(),
data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
arch: "powerpc".to_string(),
target_os: "linux".to_string(),
target_env: "musl".to_string(),
target_vendor: "unknown".to_string(),
linker_flavor: LinkerFlavor::Gcc,
options: base,
})
}

0 comments on commit 36e1d9f

Please sign in to comment.