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

Rollup of 5 pull requests #94443

Closed
wants to merge 12 commits into from
Closed
276 changes: 176 additions & 100 deletions compiler/rustc_target/src/abi/call/sparc64.rs
Original file line number Diff line number Diff line change
@@ -1,136 +1,212 @@
// FIXME: This needs an audit for correctness and completeness.

use crate::abi::call::{
ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, Reg, RegKind, Uniform,
ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, Reg, Uniform,
};
use crate::abi::{self, HasDataLayout, Size, TyAbiInterface};
use crate::abi::{self, HasDataLayout, Scalar, Size, TyAbiInterface, TyAndLayout};

#[derive(Clone, Debug)]
pub struct Sdata {
pub prefix: [Option<Reg>; 8],
pub prefix_index: usize,
pub last_offset: Size,
pub has_float: bool,
pub arg_attribute: ArgAttribute,
}

fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
fn arg_scalar<C>(cx: &C, scalar: &Scalar, offset: Size, mut data: Sdata) -> Sdata
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
{
arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
// Ensure we have at most eight uniquely addressable members.
if arg.layout.size > unit.size.checked_mul(8, cx).unwrap() {
return None;
let dl = cx.data_layout();

if scalar.value != abi::F32 && scalar.value != abi::F64 {
return data;
}

data.has_float = true;

if !data.last_offset.is_aligned(dl.f64_align.abi) && data.last_offset < offset {
if data.prefix_index == data.prefix.len() {
return data;
}
data.prefix[data.prefix_index] = Some(Reg::i32());
data.prefix_index += 1;
data.last_offset = data.last_offset + Reg::i32().size;
}

let valid_unit = match unit.kind {
RegKind::Integer => false,
RegKind::Float => false,
RegKind::Vector => arg.layout.size.bits() == 128,
};
for _ in 0..((offset - data.last_offset).bits() / 64)
.min((data.prefix.len() - data.prefix_index) as u64)
{
data.prefix[data.prefix_index] = Some(Reg::i64());
data.prefix_index += 1;
data.last_offset = data.last_offset + Reg::i64().size;
}

valid_unit.then_some(Uniform { unit, total: arg.layout.size })
})
if data.last_offset < offset {
if data.prefix_index == data.prefix.len() {
return data;
}
data.prefix[data.prefix_index] = Some(Reg::i32());
data.prefix_index += 1;
data.last_offset = data.last_offset + Reg::i32().size;
}

if data.prefix_index == data.prefix.len() {
return data;
}

if scalar.value == abi::F32 {
data.arg_attribute = ArgAttribute::InReg;
data.prefix[data.prefix_index] = Some(Reg::f32());
data.last_offset = offset + Reg::f32().size;
} else {
data.prefix[data.prefix_index] = Some(Reg::f64());
data.last_offset = offset + Reg::f64().size;
}
data.prefix_index += 1;
return data;
}

fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, in_registers_max: Size)
fn arg_scalar_pair<C>(
cx: &C,
scalar1: &Scalar,
scalar2: &Scalar,
mut offset: Size,
mut data: Sdata,
) -> Sdata
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
{
if !arg.layout.is_aggregate() {
arg.extend_integer_width_to(64);
return;
data = arg_scalar(cx, &scalar1, offset, data);
if scalar1.value == abi::F32 {
offset += Reg::f32().size;
} else if scalar2.value == abi::F64 {
offset += Reg::f64().size;
} else if let abi::Int(i, _signed) = scalar1.value {
offset += i.size();
} else if scalar1.value == abi::Pointer {
offset = offset + Reg::i64().size;
}

// This doesn't intentionally handle structures with floats which needs
// special care below.
if let Some(uniform) = is_homogeneous_aggregate(cx, arg) {
arg.cast_to(uniform);
return;
if (offset.raw % 4) != 0 && (scalar2.value == abi::F32 || scalar2.value == abi::F64) {
offset.raw += 4 - (offset.raw % 4);
}
data = arg_scalar(cx, &scalar2, offset, data);
return data;
}

fn parse_structure<'a, Ty, C>(
cx: &C,
layout: TyAndLayout<'a, Ty>,
mut data: Sdata,
mut offset: Size,
) -> Sdata
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
{
if let abi::FieldsShape::Union(_) = layout.fields {
return data;
}

if let abi::FieldsShape::Arbitrary { .. } = arg.layout.fields {
let dl = cx.data_layout();
let size = arg.layout.size;
let mut prefix = [None; 8];
let mut prefix_index = 0;
let mut last_offset = Size::ZERO;
let mut has_float = false;
let mut arg_attribute = ArgAttribute::default();

for i in 0..arg.layout.fields.count() {
let field = arg.layout.field(cx, i);
let offset = arg.layout.fields.offset(i);

if let abi::Abi::Scalar(scalar) = &field.abi {
if scalar.value == abi::F32 || scalar.value == abi::F64 {
has_float = true;

if !last_offset.is_aligned(dl.f64_align.abi) && last_offset < offset {
if prefix_index == prefix.len() {
break;
}
prefix[prefix_index] = Some(Reg::i32());
prefix_index += 1;
last_offset = last_offset + Reg::i32().size;
}

for _ in 0..((offset - last_offset).bits() / 64)
.min((prefix.len() - prefix_index) as u64)
{
prefix[prefix_index] = Some(Reg::i64());
prefix_index += 1;
last_offset = last_offset + Reg::i64().size;
}

if last_offset < offset {
if prefix_index == prefix.len() {
break;
}
prefix[prefix_index] = Some(Reg::i32());
prefix_index += 1;
last_offset = last_offset + Reg::i32().size;
}

if prefix_index == prefix.len() {
break;
}

if scalar.value == abi::F32 {
arg_attribute = ArgAttribute::InReg;
prefix[prefix_index] = Some(Reg::f32());
last_offset = offset + Reg::f32().size;
} else {
prefix[prefix_index] = Some(Reg::f64());
last_offset = offset + Reg::f64().size;
}
prefix_index += 1;
match layout.abi {
abi::Abi::Scalar(scalar) => {
data = arg_scalar(cx, &scalar, offset, data);
}
abi::Abi::Aggregate { .. } => {
for i in 0..layout.fields.count().clone() {
if offset < layout.fields.offset(i) {
offset = layout.fields.offset(i);
}
data = parse_structure(cx, layout.field(cx, i).clone(), data.clone(), offset);
}
}

if has_float && arg.layout.size <= in_registers_max {
let mut rest_size = size - last_offset;

if (rest_size.raw % 8) != 0 && prefix_index < prefix.len() {
prefix[prefix_index] = Some(Reg::i32());
rest_size = rest_size - Reg::i32().size;
_ => {
if let abi::Abi::ScalarPair(scalar1, scalar2) = &layout.abi {
data = arg_scalar_pair(cx, scalar1, scalar2, offset, data);
}

arg.cast_to(CastTarget {
prefix,
rest: Uniform { unit: Reg::i64(), total: rest_size },
attrs: ArgAttributes {
regular: arg_attribute,
arg_ext: ArgExtension::None,
pointee_size: Size::ZERO,
pointee_align: None,
},
});
return;
}
}

return data;
}

fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, in_registers_max: Size)
where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
{
if !arg.layout.is_aggregate() {
arg.extend_integer_width_to(64);
return;
}

let total = arg.layout.size;
if total > in_registers_max {
arg.make_indirect();
return;
}

match arg.layout.fields {
abi::FieldsShape::Primitive => unreachable!(),
abi::FieldsShape::Array { .. } => {
// Arrays are passed indirectly
arg.make_indirect();
return;
}
abi::FieldsShape::Union(_) => {
// Unions and are always treated as a series of 64-bit integer chunks
}
abi::FieldsShape::Arbitrary { .. } => {
// Stuctures with floating point numbers need special care.

let mut data = parse_structure(
cx,
arg.layout.clone(),
Sdata {
prefix: [None; 8],
prefix_index: 0,
last_offset: Size::ZERO,
has_float: false,
arg_attribute: ArgAttribute::default(),
},
Size { raw: 0 },
);

if data.has_float {
// Structure { float, int, int } doesn't like to be handled like
// { float, long int }. Other way around it doesn't mind.
if data.last_offset < arg.layout.size
&& (data.last_offset.raw % 8) != 0
&& data.prefix_index < data.prefix.len()
{
data.prefix[data.prefix_index] = Some(Reg::i32());
data.prefix_index += 1;
data.last_offset += Reg::i32().size;
}

let mut rest_size = arg.layout.size - data.last_offset;
if (rest_size.raw % 8) != 0 && data.prefix_index < data.prefix.len() {
data.prefix[data.prefix_index] = Some(Reg::i32());
rest_size = rest_size - Reg::i32().size;
}

arg.cast_to(CastTarget {
prefix: data.prefix,
rest: Uniform { unit: Reg::i64(), total: rest_size },
attrs: ArgAttributes {
regular: data.arg_attribute,
arg_ext: ArgExtension::None,
pointee_size: Size::ZERO,
pointee_align: None,
},
});
return;
}
}
}

arg.cast_to(Uniform { unit: Reg::i64(), total });
}

Expand Down
8 changes: 7 additions & 1 deletion src/ci/init_repo.sh
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ for i in ${!modules[@]}; do
url=${urls[$i]}
url=${url/\.git/}
fetch_github_commit_archive $module "$url/archive/$commit.tar.gz" &
bg_pids[${i}]=$!
continue
else
use_git="$use_git $module"
Expand All @@ -70,4 +71,9 @@ done
retry sh -c "git submodule deinit -f $use_git && \
git submodule sync && \
git submodule update -j 16 --init --recursive $use_git"
wait
STATUS=0
for pid in ${bg_pids[*]}
do
wait $pid || STATUS=1
done
exit ${STATUS}
2 changes: 1 addition & 1 deletion src/doc/not_found.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ function on_submit(event) {
if (form['from'].value === 'duckduckgo') {
document.location.href = form.action + '?q=' + encodeURIComponent(q + ' site:doc.rust-lang.org');
} else if (form['from'].value === 'library') {
document.location.href = 'std/index.html?search=' + encodeURIComponent(q);
document.location.href = '/std/index.html?search=' + encodeURIComponent(q);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/doc/rustdoc/src/what-to-include.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ rustdoc --theme awesome.css src/lib.rs

Here is an example of a new theme, [Ayu].

[Ayu]: https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/static/themes/ayu.css
[Ayu]: https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/static/css/themes/ayu.css
[API Guidelines]: https://rust-lang.github.io/api-guidelines/documentation.html#rustdoc-does-not-show-unhelpful-implementation-details-c-hidden
[Documentation tests]: documentation-tests.md
[on this blog]: https://blog.guillaume-gomez.fr/articles/2016-09-16+Generating+doc+with+rustdoc+and+a+custom+theme
Expand Down
20 changes: 20 additions & 0 deletions src/test/codegen/sparc-struct-abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,23 @@ pub struct FloatLongFloat {
pub extern "C" fn structfloatlongfloat() -> FloatLongFloat {
FloatLongFloat { f: 0.1, i: 123, g: 3.14 }
}

#[repr(C)]
pub struct FloatFloat {
f: f32,
g: f32,
}

#[repr(C)]
pub struct NestedStructs {
a: FloatFloat,
b: FloatFloat,
}

// CHECK: define inreg { float, float, float, float } @structnestestructs()
// CHECK-NEXT: start:
// CHECK-NEXT: ret { float, float, float, float } { float 0x3FB99999A0000000, float 0x3FF19999A0000000, float 0x40019999A0000000, float 0x400A666660000000 }
#[no_mangle]
pub extern "C" fn structnestestructs() -> NestedStructs {
NestedStructs { a: FloatFloat { f: 0.1, g: 1.1 }, b: FloatFloat { f: 2.2, g: 3.3 } }
}
9 changes: 9 additions & 0 deletions src/test/ui/const-generics/generic_const_exprs/issue-90847.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// check-pass

#![allow(incomplete_features)]
#![feature(generic_const_exprs)]
#![feature(adt_const_params)]

struct Foo<const A: [(); 0 + 0]> where [(); 0 + 0]: Sized;

fn main() {}