Skip to content

Commit 36e1d9f

Browse files
authored
Rollup merge of rust-lang#55562 - smaeul:powerpc-linux-musl, r=alexcrichton
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).
2 parents 13c9439 + 4f9c860 commit 36e1d9f

File tree

5 files changed

+88
-23
lines changed

5 files changed

+88
-23
lines changed

src/librustc_target/abi/call/powerpc64.rs

+22-22
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@
1414

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

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

@@ -75,7 +76,9 @@ fn classify_ret_ty<'a, Ty, C>(cx: &C, ret: &mut ArgType<'a, Ty>, abi: ABI)
7576
let size = ret.layout.size;
7677
let bits = size.bits();
7778
if bits <= 128 {
78-
let unit = if bits <= 8 {
79+
let unit = if cx.data_layout().endian == Endian::Big {
80+
Reg { kind: RegKind::Integer, size }
81+
} else if bits <= 8 {
7982
Reg::i8()
8083
} else if bits <= 16 {
8184
Reg::i16()
@@ -110,22 +113,15 @@ fn classify_arg_ty<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>, abi: ABI)
110113
}
111114

112115
let size = arg.layout.size;
113-
let (unit, total) = match abi {
114-
ELFv1 => {
115-
// In ELFv1, aggregates smaller than a doubleword should appear in
116-
// the least-significant bits of the parameter doubleword. The rest
117-
// should be padded at their tail to fill out multiple doublewords.
118-
if size.bits() <= 64 {
119-
(Reg { kind: RegKind::Integer, size }, size)
120-
} else {
121-
let align = Align::from_bits(64, 64).unwrap();
122-
(Reg::i64(), size.abi_align(align))
123-
}
124-
},
125-
ELFv2 => {
126-
// In ELFv2, we can just cast directly.
127-
(Reg::i64(), size)
128-
},
116+
let (unit, total) = if size.bits() <= 64 {
117+
// Aggregates smaller than a doubleword should appear in
118+
// the least-significant bits of the parameter doubleword.
119+
(Reg { kind: RegKind::Integer, size }, size)
120+
} else {
121+
// Aggregates larger than a doubleword should be padded
122+
// at the tail to fill out a whole number of doublewords.
123+
let align = Align::from_bits(64, 64).unwrap();
124+
(Reg::i64(), size.abi_align(align))
129125
};
130126

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

137133
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fty: &mut FnType<'a, Ty>)
138134
where Ty: TyLayoutMethods<'a, C> + Copy,
139-
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
135+
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout + HasTargetSpec
140136
{
141-
let abi = match cx.data_layout().endian {
142-
Endian::Big => ELFv1,
143-
Endian::Little => ELFv2,
137+
let abi = if cx.target_spec().target_env == "musl" {
138+
ELFv2
139+
} else {
140+
match cx.data_layout().endian {
141+
Endian::Big => ELFv1,
142+
Endian::Little => ELFv2
143+
}
144144
};
145145

146146
if !fty.ret.is_ignore() {

src/librustc_target/abi/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ impl HasDataLayout for TargetDataLayout {
229229
}
230230

231231
/// Endianness of the target, which must match cfg(target-endian).
232-
#[derive(Copy, Clone)]
232+
#[derive(Copy, Clone, PartialEq)]
233233
pub enum Endian {
234234
Little,
235235
Big

src/librustc_target/spec/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,9 @@ supported_targets! {
297297
("mipsel-unknown-linux-gnu", mipsel_unknown_linux_gnu),
298298
("powerpc-unknown-linux-gnu", powerpc_unknown_linux_gnu),
299299
("powerpc-unknown-linux-gnuspe", powerpc_unknown_linux_gnuspe),
300+
("powerpc-unknown-linux-musl", powerpc_unknown_linux_musl),
300301
("powerpc64-unknown-linux-gnu", powerpc64_unknown_linux_gnu),
302+
("powerpc64-unknown-linux-musl", powerpc64_unknown_linux_musl),
301303
("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu),
302304
("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl),
303305
("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use spec::{LinkerFlavor, Target, TargetResult};
12+
13+
pub fn target() -> TargetResult {
14+
let mut base = super::linux_musl_base::opts();
15+
base.cpu = "ppc64".to_string();
16+
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
17+
base.max_atomic_width = Some(64);
18+
19+
Ok(Target {
20+
llvm_target: "powerpc64-unknown-linux-musl".to_string(),
21+
target_endian: "big".to_string(),
22+
target_pointer_width: "64".to_string(),
23+
target_c_int_width: "32".to_string(),
24+
data_layout: "E-m:e-i64:64-n32:64".to_string(),
25+
arch: "powerpc64".to_string(),
26+
target_os: "linux".to_string(),
27+
target_env: "musl".to_string(),
28+
target_vendor: "unknown".to_string(),
29+
linker_flavor: LinkerFlavor::Gcc,
30+
options: base,
31+
})
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use spec::{LinkerFlavor, Target, TargetResult};
12+
13+
pub fn target() -> TargetResult {
14+
let mut base = super::linux_musl_base::opts();
15+
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
16+
base.max_atomic_width = Some(32);
17+
18+
Ok(Target {
19+
llvm_target: "powerpc-unknown-linux-musl".to_string(),
20+
target_endian: "big".to_string(),
21+
target_pointer_width: "32".to_string(),
22+
target_c_int_width: "32".to_string(),
23+
data_layout: "E-m:e-p:32:32-i64:64-n32".to_string(),
24+
arch: "powerpc".to_string(),
25+
target_os: "linux".to_string(),
26+
target_env: "musl".to_string(),
27+
target_vendor: "unknown".to_string(),
28+
linker_flavor: LinkerFlavor::Gcc,
29+
options: base,
30+
})
31+
}

0 commit comments

Comments
 (0)