Skip to content

Commit 092f19a

Browse files
authored
Rollup merge of rust-lang#41206 - eddyb:avoid-illegal-vectors, r=nagisa
Fix pairs of doubles using an illegal <8 x i8> vector. Accidentally introduced in rust-lang#40658 and discovered in some Objective-C bindings (returning `NSPoint`). Turns out LLVM will widen element types of illegal vectors instead of increasing element count, i.e. it will zero-extend `<8 x i8>` to `<8 x i16>`, interleaving the bytes, instead of using the first 8 of `<16 x i8>`.
2 parents afb300d + 0303a33 commit 092f19a

File tree

4 files changed

+40
-9
lines changed

4 files changed

+40
-9
lines changed

src/librustc_trans/abi.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ impl<'tcx> LayoutExt<'tcx> for TyLayout<'tcx> {
283283

284284
Layout::Vector { .. } => {
285285
Some(Reg {
286-
kind: RegKind::Integer,
286+
kind: RegKind::Vector,
287287
size: self.size(ccx)
288288
})
289289
}

src/librustc_trans/cabi_x86_64.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -173,14 +173,15 @@ fn reg_component(cls: &[Class], i: &mut usize, size: u64) -> Option<Reg> {
173173
Class::Sse => {
174174
let vec_len = 1 + cls[*i+1..].iter().take_while(|&&c| c == Class::SseUp).count();
175175
*i += vec_len;
176-
Some(match size {
177-
4 => Reg::f32(),
178-
8 => Reg::f64(),
179-
_ => {
180-
Reg {
181-
kind: RegKind::Vector,
182-
size: Size::from_bytes(vec_len as u64 * 8)
183-
}
176+
Some(if vec_len == 1 {
177+
match size {
178+
4 => Reg::f32(),
179+
_ => Reg::f64()
180+
}
181+
} else {
182+
Reg {
183+
kind: RegKind::Vector,
184+
size: Size::from_bytes(vec_len as u64 * 8)
184185
}
185186
})
186187
}

src/test/run-make/extern-fn-struct-passing-abi/test.c

+19
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ struct Huge {
3838
int32_t e;
3939
};
4040

41+
struct FloatPoint {
42+
double x;
43+
double y;
44+
};
45+
4146
// System V x86_64 ABI:
4247
// a, b, c, d, e should be in registers
4348
// s should be byval pointer
@@ -258,3 +263,17 @@ struct Huge huge_struct(struct Huge s) {
258263

259264
return s;
260265
}
266+
267+
// System V x86_64 ABI:
268+
// p should be in registers
269+
// return should be in registers
270+
//
271+
// Win64 ABI:
272+
// p should be a byval pointer
273+
// return should be in a hidden sret pointer
274+
struct FloatPoint float_point(struct FloatPoint p) {
275+
assert(p.x == 5.);
276+
assert(p.y == -3.);
277+
278+
return p;
279+
}

src/test/run-make/extern-fn-struct-passing-abi/test.rs

+11
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ struct Huge {
4646
e: i32
4747
}
4848

49+
#[derive(Clone, Copy, Debug, PartialEq)]
50+
#[repr(C)]
51+
struct FloatPoint {
52+
x: f64,
53+
y: f64
54+
}
55+
4956
#[link(name = "test", kind = "static")]
5057
extern {
5158
fn byval_rect(a: i32, b: i32, c: i32, d: i32, e: i32, s: Rect);
@@ -72,13 +79,16 @@ extern {
7279
fn sret_split_struct(a: i32, b: i32, s: Rect) -> BiggerRect;
7380

7481
fn huge_struct(s: Huge) -> Huge;
82+
83+
fn float_point(p: FloatPoint) -> FloatPoint;
7584
}
7685

7786
fn main() {
7887
let s = Rect { a: 553, b: 554, c: 555, d: 556 };
7988
let t = BiggerRect { s: s, a: 27834, b: 7657 };
8089
let u = FloatRect { a: 3489, b: 3490, c: 8. };
8190
let v = Huge { a: 5647, b: 5648, c: 5649, d: 5650, e: 5651 };
91+
let p = FloatPoint { x: 5., y: -3. };
8292

8393
unsafe {
8494
byval_rect(1, 2, 3, 4, 5, s);
@@ -94,5 +104,6 @@ fn main() {
94104
assert_eq!(split_ret_byval_struct(1, 2, s), s);
95105
assert_eq!(sret_byval_struct(1, 2, 3, 4, s), t);
96106
assert_eq!(sret_split_struct(1, 2, s), t);
107+
assert_eq!(float_point(p), p);
97108
}
98109
}

0 commit comments

Comments
 (0)