Skip to content

Commit 4fe6acf

Browse files
committed
add compile fail tests
1 parent 8478fa2 commit 4fe6acf

File tree

4 files changed

+125
-1
lines changed

4 files changed

+125
-1
lines changed

src/librustc_llvm/ffi.rs

+2
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,7 @@ extern "C" {
621621
pub fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong;
622622
pub fn LLVMRustConstInt128Get(ConstantVal: ValueRef, SExt: bool,
623623
high: *mut u64, low: *mut u64) -> bool;
624+
pub fn LLVMConstRealGetDouble (ConstantVal: ValueRef, losesInfo: *mut Bool) -> f64;
624625

625626

626627
// Operations on composite constants
@@ -1607,6 +1608,7 @@ extern "C" {
16071608
pub fn LLVMRustWriteValueToString(value_ref: ValueRef, s: RustStringRef);
16081609

16091610
pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef;
1611+
pub fn LLVMIsAConstantFP(value_ref: ValueRef) -> ValueRef;
16101612

16111613
pub fn LLVMRustPassKind(Pass: PassRef) -> PassKind;
16121614
pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef;

src/librustc_trans/common.rs

+20
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,19 @@ pub fn const_get_elt(v: ValueRef, idx: u64) -> ValueRef {
270270
}
271271
}
272272

273+
pub fn const_get_real(v: ValueRef) -> Option<(f64, bool)> {
274+
unsafe {
275+
if is_const_real(v) {
276+
let mut loses_info: llvm::Bool = ::std::mem::uninitialized();
277+
let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info as *mut llvm::Bool);
278+
let loses_info = if loses_info == 1 { true } else { false };
279+
Some((r, loses_info))
280+
} else {
281+
None
282+
}
283+
}
284+
}
285+
273286
pub fn const_to_uint(v: ValueRef) -> u64 {
274287
unsafe {
275288
llvm::LLVMConstIntGetZExtValue(v)
@@ -282,6 +295,13 @@ pub fn is_const_integral(v: ValueRef) -> bool {
282295
}
283296
}
284297

298+
pub fn is_const_real(v: ValueRef) -> bool {
299+
unsafe {
300+
!llvm::LLVMIsAConstantFP(v).is_null()
301+
}
302+
}
303+
304+
285305
#[inline]
286306
fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 {
287307
((hi as u128) << 64) | (lo as u128)

src/librustc_trans/intrinsic.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -1174,7 +1174,25 @@ fn generic_simd_intrinsic<'a, 'tcx>(
11741174
ty::TyFloat(f) => {
11751175
// ordered arithmetic reductions take an accumulator
11761176
let acc = if $ordered {
1177-
args[1].immediate()
1177+
let acc = args[1].immediate();
1178+
// FIXME: https://bugs.llvm.org/show_bug.cgi?id=36734
1179+
// * if the accumulator of the fadd isn't 0, incorrect
1180+
// code is generated
1181+
// * if the accumulator of the fmul isn't 1, incorrect
1182+
// code is generated
1183+
match const_get_real(acc) {
1184+
None => return_error!("accumulator of {} is not a constant", $name),
1185+
Some((v, loses_info)) => {
1186+
if $name.contains("mul") && v != 1.0_f64 {
1187+
return_error!("accumulator of {} is not 1.0", $name);
1188+
} else if $name.contains("add") && v != 0.0_f64 {
1189+
return_error!("accumulator of {} is not 0.0", $name);
1190+
} else if loses_info {
1191+
return_error!("accumulator of {} loses information", $name);
1192+
}
1193+
}
1194+
}
1195+
acc
11781196
} else {
11791197
// unordered arithmetic reductions do not:
11801198
match f.bit_width() {
@@ -1248,6 +1266,14 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
12481266
in_elem, in_ty, ret_ty);
12491267
args[0].immediate()
12501268
} else {
1269+
match in_elem.sty {
1270+
ty::TyInt(_) | ty::TyUint(_) => {},
1271+
_ => {
1272+
return_error!("unsupported {} from `{}` with element `{}` to `{}`",
1273+
$name, in_ty, in_elem, ret_ty)
1274+
}
1275+
}
1276+
12511277
// boolean reductions operate on vectors of i1s:
12521278
let i1 = Type::i1(bx.cx);
12531279
let i1xn = Type::vector(&i1, in_len as u64);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Copyright 2015 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+
#![feature(repr_simd, platform_intrinsics)]
12+
#![allow(non_camel_case_types)]
13+
14+
#[repr(simd)]
15+
#[derive(Copy, Clone)]
16+
pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
17+
18+
#[repr(simd)]
19+
#[derive(Copy, Clone)]
20+
pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
21+
22+
23+
extern "platform-intrinsic" {
24+
fn simd_reduce_add_ordered<T, U>(x: T, y: U) -> U;
25+
fn simd_reduce_mul_ordered<T, U>(x: T, y: U) -> U;
26+
fn simd_reduce_and<T, U>(x: T) -> U;
27+
fn simd_reduce_or<T, U>(x: T) -> U;
28+
fn simd_reduce_xor<T, U>(x: T) -> U;
29+
fn simd_reduce_all<T>(x: T) -> bool;
30+
fn simd_reduce_any<T>(x: T) -> bool;
31+
}
32+
33+
fn main() {
34+
let x = u32x4(0, 0, 0, 0);
35+
let z = f32x4(0.0, 0.0, 0.0, 0.0);
36+
37+
unsafe {
38+
simd_reduce_add_ordered(z, 0_f32);
39+
simd_reduce_mul_ordered(z, 1_f32);
40+
41+
simd_reduce_add_ordered(z, 2_f32);
42+
//~^ ERROR accumulator of simd_reduce_add_ordered is not 0.0
43+
simd_reduce_mul_ordered(z, 3_f32);
44+
//~^ ERROR accumulator of simd_reduce_mul_ordered is not 1.0
45+
46+
let _: f32 = simd_reduce_and(x);
47+
//~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32`
48+
let _: f32 = simd_reduce_or(x);
49+
//~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32`
50+
let _: f32 = simd_reduce_xor(x);
51+
//~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32`
52+
53+
let _: f32 = simd_reduce_and(z);
54+
//~^ ERROR unsupported simd_reduce_and from `f32x4` with element `f32` to `f32`
55+
let _: f32 = simd_reduce_or(z);
56+
//~^ ERROR unsupported simd_reduce_or from `f32x4` with element `f32` to `f32`
57+
let _: f32 = simd_reduce_xor(z);
58+
//~^ ERROR unsupported simd_reduce_xor from `f32x4` with element `f32` to `f32`
59+
60+
let _: bool = simd_reduce_all(z);
61+
//~^ ERROR unsupported simd_reduce_all from `f32x4` with element `f32` to `bool`
62+
let _: bool = simd_reduce_any(z);
63+
//~^ ERROR unsupported simd_reduce_any from `f32x4` with element `f32` to `bool`
64+
65+
foo(0_f32);
66+
}
67+
}
68+
69+
#[inline(never)]
70+
unsafe fn foo(x: f32) {
71+
let z = f32x4(0.0, 0.0, 0.0, 0.0);
72+
simd_reduce_add_ordered(z, x);
73+
//~^ ERROR accumulator of simd_reduce_add_ordered is not a constant
74+
simd_reduce_mul_ordered(z, x);
75+
//~^ ERROR accumulator of simd_reduce_mul_ordered is not a constant
76+
}

0 commit comments

Comments
 (0)