From 01cc5b3e195bb01088fdd59638f0d8c6d0a78142 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Tue, 13 Mar 2018 16:46:55 +0100 Subject: [PATCH 01/17] add intrinsics for portable packed simd vector reductions --- src/librustc_llvm/ffi.rs | 40 ++++ src/librustc_trans/builder.rs | 75 ++++++ src/librustc_trans/intrinsic.rs | 219 +++++++++++++++++- src/librustc_typeck/check/intrinsic.rs | 5 + src/rustllvm/RustWrapper.cpp | 46 ++++ .../simd-intrinsic-generic-reduction.rs | 143 ++++++++++++ 6 files changed, 525 insertions(+), 3 deletions(-) create mode 100644 src/test/run-pass/simd-intrinsic-generic-reduction.rs diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index 0ec5700f5f32a..00547017349d4 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -1201,6 +1201,46 @@ extern "C" { Name: *const c_char) -> ValueRef; + pub fn LLVMRustBuildVectorReduceFAdd(B: BuilderRef, + Acc: ValueRef, + Src: ValueRef) + -> ValueRef; + pub fn LLVMRustBuildVectorReduceFMul(B: BuilderRef, + Acc: ValueRef, + Src: ValueRef) + -> ValueRef; + pub fn LLVMRustBuildVectorReduceAdd(B: BuilderRef, + Src: ValueRef) + -> ValueRef; + pub fn LLVMRustBuildVectorReduceMul(B: BuilderRef, + Src: ValueRef) + -> ValueRef; + pub fn LLVMRustBuildVectorReduceAnd(B: BuilderRef, + Src: ValueRef) + -> ValueRef; + pub fn LLVMRustBuildVectorReduceOr(B: BuilderRef, + Src: ValueRef) + -> ValueRef; + pub fn LLVMRustBuildVectorReduceXor(B: BuilderRef, + Src: ValueRef) + -> ValueRef; + pub fn LLVMRustBuildVectorReduceMin(B: BuilderRef, + Src: ValueRef, + IsSigned: bool) + -> ValueRef; + pub fn LLVMRustBuildVectorReduceMax(B: BuilderRef, + Src: ValueRef, + IsSigned: bool) + -> ValueRef; + pub fn LLVMRustBuildVectorReduceFMin(B: BuilderRef, + Src: ValueRef, + IsNaN: bool) + -> ValueRef; + pub fn LLVMRustBuildVectorReduceFMax(B: BuilderRef, + Src: ValueRef, + IsNaN: bool) + -> ValueRef; + pub fn LLVMBuildIsNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef; pub fn LLVMBuildIsNotNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef; pub fn LLVMBuildPtrDiff(B: BuilderRef, diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs index d4e05a18e3a50..2c38197d68ecf 100644 --- a/src/librustc_trans/builder.rs +++ b/src/librustc_trans/builder.rs @@ -955,6 +955,81 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } + pub fn vector_reduce_fadd_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.fadd_fast"); + unsafe { + let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src); + llvm::LLVMRustSetHasUnsafeAlgebra(instr); + instr + } + } + pub fn vector_reduce_fmul_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.fmul_fast"); + unsafe { + let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src); + llvm::LLVMRustSetHasUnsafeAlgebra(instr); + instr + } + } + pub fn vector_reduce_add(&self, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.add"); + unsafe { + llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src) + } + } + pub fn vector_reduce_mul(&self, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.mul"); + unsafe { + llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src) + } + } + pub fn vector_reduce_and(&self, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.and"); + unsafe { + llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src) + } + } + pub fn vector_reduce_or(&self, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.or"); + unsafe { + llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src) + } + } + pub fn vector_reduce_xor(&self, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.xor"); + unsafe { + llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src) + } + } + pub fn vector_reduce_fmin_fast(&self, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.fmin_fast"); + unsafe { + let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, false); + llvm::LLVMRustSetHasUnsafeAlgebra(instr); + instr + } + } + pub fn vector_reduce_fmax_fast(&self, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.fmax_fast"); + unsafe { + let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, false); + llvm::LLVMRustSetHasUnsafeAlgebra(instr); + instr + } + } + pub fn vector_reduce_min(&self, src: ValueRef, is_signed: bool) -> ValueRef { + self.count_insn("vector.reduce.min"); + unsafe { + llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed) + } + } + pub fn vector_reduce_max(&self, src: ValueRef, is_signed: bool) -> ValueRef { + self.count_insn("vector.reduce.max"); + unsafe { + llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed) + } + } + pub fn extract_value(&self, agg_val: ValueRef, idx: u64) -> ValueRef { self.count_insn("extractvalue"); assert_eq!(idx as c_uint as u64, idx); diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 3f87ce7e04792..011273f02e116 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -1018,14 +1018,22 @@ fn generic_simd_intrinsic<'a, 'tcx>( name, $($fmt)*)); } } - macro_rules! require { - ($cond: expr, $($fmt: tt)*) => { - if !$cond { + macro_rules! return_error { + ($($fmt: tt)*) => { + { emit_error!($($fmt)*); return Err(()); } } } + + macro_rules! require { + ($cond: expr, $($fmt: tt)*) => { + if !$cond { + return_error!($($fmt)*); + } + }; + } macro_rules! require_simd { ($ty: expr, $position: expr) => { require!($ty.is_simd(), "expected SIMD {} type, found non-SIMD `{}`", $position, $ty) @@ -1142,6 +1150,211 @@ fn generic_simd_intrinsic<'a, 'tcx>( return Ok(bx.extract_element(args[0].immediate(), args[1].immediate())) } + if name == "simd_reduce_add" { + require!(ret_ty == in_elem, + "expected return type `{}` (element of input `{}`), found `{}`", + in_elem, in_ty, ret_ty); + return match in_elem.sty { + ty::TyInt(_i) => { + Ok(bx.vector_reduce_add(args[0].immediate())) + }, + ty::TyUint(_u) => { + Ok(bx.vector_reduce_add(args[0].immediate())) + }, + ty::TyFloat(f) => { + // undef as accumulator makes the reduction unordered: + let acc = match f.bit_width() { + 32 => C_undef(Type::f32(bx.cx)), + 64 => C_undef(Type::f64(bx.cx)), + v => { + return_error!( + "unsupported {} from `{}` with element `{}` of size `{}` to `{}`", + "simd_reduce_add", in_ty, in_elem, v, ret_ty) + } + }; + Ok(bx.vector_reduce_fadd_fast(acc, args[0].immediate())) + } + _ => { + return_error!("unsupported {} from `{}` with element `{}` to `{}`", + "simd_reduce_add", in_ty, in_elem, ret_ty) + }, + } + } + + if name == "simd_reduce_mul" { + require!(ret_ty == in_elem, + "expected return type `{}` (element of input `{}`), found `{}`", + in_elem, in_ty, ret_ty); + return match in_elem.sty { + ty::TyInt(_i) => { + Ok(bx.vector_reduce_mul(args[0].immediate())) + }, + ty::TyUint(_u) => { + Ok(bx.vector_reduce_mul(args[0].immediate())) + }, + ty::TyFloat(f) => { + // undef as accumulator makes the reduction unordered: + let acc = match f.bit_width() { + 32 => C_undef(Type::f32(bx.cx)), + 64 => C_undef(Type::f64(bx.cx)), + v => { + return_error!( + "unsupported {} from `{}` with element `{}` of size `{}` to `{}`", + "simd_reduce_mul", in_ty, in_elem, v, ret_ty) + } + }; + Ok(bx.vector_reduce_fmul_fast(acc, args[0].immediate())) + } + _ => { + return_error!("unsupported {} from `{}` with element `{}` to `{}`", + "simd_reduce_mul", in_ty, in_elem, ret_ty) + }, + } + } + + if name == "simd_reduce_min" { + require!(ret_ty == in_elem, + "expected return type `{}` (element of input `{}`), found `{}`", + in_elem, in_ty, ret_ty); + return match in_elem.sty { + ty::TyInt(_i) => { + Ok(bx.vector_reduce_min(args[0].immediate(), true)) + }, + ty::TyUint(_u) => { + Ok(bx.vector_reduce_min(args[0].immediate(), false)) + }, + ty::TyFloat(_f) => { + Ok(bx.vector_reduce_fmin_fast(args[0].immediate())) + } + _ => { + return_error!("unsupported {} from `{}` with element `{}` to `{}`", + "simd_reduce_min", in_ty, in_elem, ret_ty) + }, + } + } + + if name == "simd_reduce_max" { + require!(ret_ty == in_elem, + "expected return type `{}` (element of input `{}`), found `{}`", + in_elem, in_ty, ret_ty); + return match in_elem.sty { + ty::TyInt(_i) => { + Ok(bx.vector_reduce_max(args[0].immediate(), true)) + }, + ty::TyUint(_u) => { + Ok(bx.vector_reduce_max(args[0].immediate(), false)) + }, + ty::TyFloat(_f) => { + Ok(bx.vector_reduce_fmax_fast(args[0].immediate())) + } + _ => { + return_error!("unsupported {} from `{}` with element `{}` to `{}`", + "simd_reduce_max", in_ty, in_elem, ret_ty) + }, + } + } + + if name == "simd_reduce_and" { + require!(ret_ty == in_elem, + "expected return type `{}` (element of input `{}`), found `{}`", + in_elem, in_ty, ret_ty); + return match in_elem.sty { + ty::TyInt(_i) => { + Ok(bx.vector_reduce_and(args[0].immediate())) + }, + ty::TyUint(_u) => { + Ok(bx.vector_reduce_and(args[0].immediate())) + }, + _ => { + return_error!("unsupported {} from `{}` with element `{}` to `{}`", + "simd_reduce_and", in_ty, in_elem, ret_ty) + }, + } + } + + if name == "simd_reduce_or" { + require!(ret_ty == in_elem, + "expected return type `{}` (element of input `{}`), found `{}`", + in_elem, in_ty, ret_ty); + return match in_elem.sty { + ty::TyInt(_i) => { + Ok(bx.vector_reduce_or(args[0].immediate())) + }, + ty::TyUint(_u) => { + Ok(bx.vector_reduce_or(args[0].immediate())) + }, + _ => { + return_error!("unsupported {} from `{}` with element `{}` to `{}`", + "simd_reduce_or", in_ty, in_elem, ret_ty) + }, + } + } + + if name == "simd_reduce_xor" { + require!(ret_ty == in_elem, + "expected return type `{}` (element of input `{}`), found `{}`", + in_elem, in_ty, ret_ty); + return match in_elem.sty { + ty::TyInt(_i) => { + Ok(bx.vector_reduce_xor(args[0].immediate())) + }, + ty::TyUint(_u) => { + Ok(bx.vector_reduce_xor(args[0].immediate())) + }, + _ => { + return_error!("unsupported {} from `{}` with element `{}` to `{}`", + "simd_reduce_xor", in_ty, in_elem, ret_ty) + }, + } + } + + if name == "simd_reduce_all" { + //require!(ret_ty == in_elem, + // "expected return type `{}` (element of input `{}`), found `{}`", + // in_elem, in_ty, ret_ty); + let i1 = Type::i1(bx.cx); + let i1xn = Type::vector(&i1, in_len as u64); + let v = bx.trunc(args[0].immediate(), i1xn); + + let red = match in_elem.sty { + ty::TyInt(_i) => { + bx.vector_reduce_and(v) + }, + ty::TyUint(_u) => { + bx.vector_reduce_and(v) + }, + _ => { + return_error!("unsupported {} from `{}` with element `{}` to `{}`", + "simd_reduce_and", in_ty, in_elem, ret_ty) + }, + }; + return Ok(bx.zext(red, Type::bool(bx.cx))); + } + + if name == "simd_reduce_any" { + //require!(ret_ty == in_elem, + // "expected return type `{}` (element of input `{}`), found `{}`", + // in_elem, in_ty, ret_ty); + let i1 = Type::i1(bx.cx); + let i1xn = Type::vector(&i1, in_len as u64); + let v = bx.trunc(args[0].immediate(), i1xn); + + let red = match in_elem.sty { + ty::TyInt(_i) => { + bx.vector_reduce_or(v) + }, + ty::TyUint(_u) => { + bx.vector_reduce_or(v) + }, + _ => { + return_error!("unsupported {} from `{}` with element `{}` to `{}`", + "simd_reduce_and", in_ty, in_elem, ret_ty) + }, + }; + return Ok(bx.zext(red, Type::bool(bx.cx))); + } + + if name == "simd_cast" { require_simd!(ret_ty, "return"); let out_len = ret_ty.simd_size(tcx); diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 2e00040d99a73..f2d01c57f298e 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -361,6 +361,11 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "simd_insert" => (2, vec![param(0), tcx.types.u32, param(1)], param(0)), "simd_extract" => (2, vec![param(0), tcx.types.u32], param(1)), "simd_cast" => (2, vec![param(0)], param(1)), + "simd_reduce_all" | "simd_reduce_any" => (1, vec![param(0)], tcx.types.bool), + "simd_reduce_add" | "simd_reduce_mul" | + "simd_reduce_and" | "simd_reduce_or" | "simd_reduce_xor" | + "simd_reduce_min" | "simd_reduce_max" + => (2, vec![param(0)], param(1)), name if name.starts_with("simd_shuffle") => { match name["simd_shuffle".len()..].parse() { Ok(n) => { diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 27d5496f57628..e749549201e69 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -1395,3 +1395,49 @@ LLVMRustModuleCost(LLVMModuleRef M) { auto f = unwrap(M)->functions(); return std::distance(std::begin(f), std::end(f)); } + +// Vector reductions: +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) { + return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src))); +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) { + return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src))); +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) { + return wrap(unwrap(B)->CreateAddReduce(unwrap(Src))); +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) { + return wrap(unwrap(B)->CreateMulReduce(unwrap(Src))); +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) { + return wrap(unwrap(B)->CreateAndReduce(unwrap(Src))); +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) { + return wrap(unwrap(B)->CreateOrReduce(unwrap(Src))); +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) { + return wrap(unwrap(B)->CreateXorReduce(unwrap(Src))); +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) { + return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned)); +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) { + return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned)); +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) { + return wrap(unwrap(B)->CreateFPMinReduce(unwrap(Src), NoNaN)); +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) { + return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Src), NoNaN)); +} diff --git a/src/test/run-pass/simd-intrinsic-generic-reduction.rs b/src/test/run-pass/simd-intrinsic-generic-reduction.rs new file mode 100644 index 0000000000000..15b291ae179c5 --- /dev/null +++ b/src/test/run-pass/simd-intrinsic-generic-reduction.rs @@ -0,0 +1,143 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that the simd_reduce_{op} intrinsics produce the correct results. + +#![feature(repr_simd, platform_intrinsics)] +#[allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone)] +struct i32x4(pub i32, pub i32, pub i32, pub i32); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct u32x4(pub u32, pub u32, pub u32, pub u32); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct b8x4(pub i8, pub i8, pub i8, pub i8); + +#[repr(simd)] +#[derive(Copy, Clone)] +struct b8x16( + pub i8, pub i8, pub i8, pub i8, + pub i8, pub i8, pub i8, pub i8, + pub i8, pub i8, pub i8, pub i8, + pub i8, pub i8, pub i8, pub i8 +); + +extern "platform-intrinsic" { + fn simd_reduce_add(x: T) -> U; + fn simd_reduce_mul(x: T) -> U; + fn simd_reduce_min(x: T) -> U; + fn simd_reduce_max(x: T) -> U; + fn simd_reduce_and(x: T) -> U; + fn simd_reduce_or(x: T) -> U; + fn simd_reduce_xor(x: T) -> U; + fn simd_reduce_all(x: T) -> bool; + fn simd_reduce_any(x: T) -> bool; +} + +fn main() { + unsafe { + let x = i32x4(1, -2, 3, 4); + let r: i32 = simd_reduce_add(x); + assert!(r == 6_i32); + let r: i32 = simd_reduce_mul(x); + assert!(r == -24_i32); + let r: i32 = simd_reduce_min(x); + assert!(r == -21_i32); + let r: i32 = simd_reduce_max(x); + assert!(r == 4_i32); + + let x = i32x4(-1, -1, -1, -1); + let r: i32 = simd_reduce_and(x); + assert!(r == -1_i32); + let r: i32 = simd_reduce_or(x); + assert!(r == -1_i32); + let r: i32 = simd_reduce_xor(x); + assert!(r == 0_i32); + + let x = i32x4(-1, -1, 0, -1); + let r: i32 = simd_reduce_and(x); + assert!(r == 0_i32); + let r: i32 = simd_reduce_or(x); + assert!(r == -1_i32); + let r: i32 = simd_reduce_xor(x); + assert!(r == -1_i32); + } + + unsafe { + let x = u32x4(1, 2, 3, 4); + let r: u32 = simd_reduce_add(x); + assert!(r == 10_u32); + let r: u32 = simd_reduce_mul(x); + assert!(r == 24_u32); + let r: u32 = simd_reduce_min(x); + assert!(r == 1_u32); + let r: u32 = simd_reduce_max(x); + assert!(r == 4_u32); + + let t = u32::max_value(); + let x = u32x4(t, t, t, t); + let r: u32 = simd_reduce_and(x); + assert!(r == t); + let r: u32 = simd_reduce_or(x); + assert!(r == t); + let r: u32 = simd_reduce_xor(x); + assert!(r == 0_u32); + + let x = u32x4(t, t, 0, t); + let r: u32 = simd_reduce_and(x); + assert!(r == 0_u32); + let r: u32 = simd_reduce_or(x); + assert!(r == t); + let r: u32 = simd_reduce_xor(x); + assert!(r == t); + } + + unsafe { + let x = f32x4(1., -2., 3., 4.); + let r: f32 = simd_reduce_add(x); + assert!(r == 6_f32); + let r: f32 = simd_reduce_mul(x); + assert!(r == -24_f32); + let r: f32 = simd_reduce_min(x); + assert!(r == -2_f32); + let r: f32 = simd_reduce_max(x); + assert!(r == 4_f32); + } + + unsafe { + let x = b8x4(!0, !0, !0, !0); + let r: bool = simd_reduce_all(x); + //let r: bool = foobar(x); + assert!(r); + let r: bool = simd_reduce_any(x); + assert!(r); + + let x = b8x4(!0, !0, 0, !0); + let r: bool = simd_reduce_all(x); + assert!(!r); + let r: bool = simd_reduce_any(x); + assert!(r); + + let x = b8x4(0, 0, 0, 0); + let r: bool = simd_reduce_all(x); + assert!(!r); + let r: bool = simd_reduce_any(x); + assert!(!r); + } +} From 07ce659dd03523b526cb4804b9ef882f31e9ecf3 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 14 Mar 2018 17:22:40 +0100 Subject: [PATCH 02/17] expose ordered/unordered/nanless intirnsics --- src/librustc_trans/builder.rs | 18 ++ src/librustc_trans/intrinsic.rs | 300 +++++++----------- src/librustc_typeck/check/intrinsic.rs | 7 +- src/rustllvm/RustWrapper.cpp | 2 + .../simd-intrinsic-generic-reduction.rs | 104 +++--- 5 files changed, 202 insertions(+), 229 deletions(-) diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs index 2c38197d68ecf..371f53013b903 100644 --- a/src/librustc_trans/builder.rs +++ b/src/librustc_trans/builder.rs @@ -958,6 +958,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub fn vector_reduce_fadd_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef { self.count_insn("vector.reduce.fadd_fast"); unsafe { + // FIXME: add a non-fast math version once + // https://bugs.llvm.org/show_bug.cgi?id=36732 + // is fixed. let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src); llvm::LLVMRustSetHasUnsafeAlgebra(instr); instr @@ -966,6 +969,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub fn vector_reduce_fmul_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef { self.count_insn("vector.reduce.fmul_fast"); unsafe { + // FIXME: add a non-fast math version once + // https://bugs.llvm.org/show_bug.cgi?id=36732 + // is fixed. let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src); llvm::LLVMRustSetHasUnsafeAlgebra(instr); instr @@ -1001,6 +1007,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src) } } + pub fn vector_reduce_fmin(&self, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.fmin"); + unsafe { + llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, true) + } + } + pub fn vector_reduce_fmax(&self, src: ValueRef) -> ValueRef { + self.count_insn("vector.reduce.fmax"); + unsafe { + llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, true) + } + } pub fn vector_reduce_fmin_fast(&self, src: ValueRef) -> ValueRef { self.count_insn("vector.reduce.fmin_fast"); unsafe { diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 011273f02e116..8b62a1be80c3d 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -1150,210 +1150,134 @@ fn generic_simd_intrinsic<'a, 'tcx>( return Ok(bx.extract_element(args[0].immediate(), args[1].immediate())) } - if name == "simd_reduce_add" { - require!(ret_ty == in_elem, - "expected return type `{}` (element of input `{}`), found `{}`", - in_elem, in_ty, ret_ty); - return match in_elem.sty { - ty::TyInt(_i) => { - Ok(bx.vector_reduce_add(args[0].immediate())) - }, - ty::TyUint(_u) => { - Ok(bx.vector_reduce_add(args[0].immediate())) - }, - ty::TyFloat(f) => { - // undef as accumulator makes the reduction unordered: - let acc = match f.bit_width() { - 32 => C_undef(Type::f32(bx.cx)), - 64 => C_undef(Type::f64(bx.cx)), - v => { - return_error!( - "unsupported {} from `{}` with element `{}` of size `{}` to `{}`", - "simd_reduce_add", in_ty, in_elem, v, ret_ty) + macro_rules! arith_red { + ($name:tt : $integer_reduce:ident, $float_reduce:ident, $ordered:expr) => { + if name == $name { + require!(ret_ty == in_elem, + "expected return type `{}` (element of input `{}`), found `{}`", + in_elem, in_ty, ret_ty); + return match in_elem.sty { + ty::TyInt(_) | ty::TyUint(_) => { + let r = bx.$integer_reduce(args[0].immediate()); + if $ordered { + // if overflow occurs, the result is the + // mathematical result modulo 2^n: + if name.contains("mul") { + Ok(bx.mul(args[1].immediate(), r)) + } else { + Ok(bx.add(args[1].immediate(), r)) + } + } else { + Ok(bx.$integer_reduce(args[0].immediate())) + } + }, + ty::TyFloat(f) => { + // ordered arithmetic reductions take an accumulator + let acc = if $ordered { + args[1].immediate() + } else { + // unordered arithmetic reductions do not: + match f.bit_width() { + 32 => C_undef(Type::f32(bx.cx)), + 64 => C_undef(Type::f64(bx.cx)), + v => { + return_error!( + "unsupported {} from `{}` with element `{}` of size `{}` to `{}`", + $name, in_ty, in_elem, v, ret_ty + ) + } + } + + }; + Ok(bx.$float_reduce(acc, args[0].immediate())) } - }; - Ok(bx.vector_reduce_fadd_fast(acc, args[0].immediate())) + _ => { + return_error!( + "unsupported {} from `{}` with element `{}` to `{}`", + $name, in_ty, in_elem, ret_ty + ) + }, + } } - _ => { - return_error!("unsupported {} from `{}` with element `{}` to `{}`", - "simd_reduce_add", in_ty, in_elem, ret_ty) - }, } } - if name == "simd_reduce_mul" { - require!(ret_ty == in_elem, - "expected return type `{}` (element of input `{}`), found `{}`", - in_elem, in_ty, ret_ty); - return match in_elem.sty { - ty::TyInt(_i) => { - Ok(bx.vector_reduce_mul(args[0].immediate())) - }, - ty::TyUint(_u) => { - Ok(bx.vector_reduce_mul(args[0].immediate())) - }, - ty::TyFloat(f) => { - // undef as accumulator makes the reduction unordered: - let acc = match f.bit_width() { - 32 => C_undef(Type::f32(bx.cx)), - 64 => C_undef(Type::f64(bx.cx)), - v => { - return_error!( - "unsupported {} from `{}` with element `{}` of size `{}` to `{}`", - "simd_reduce_mul", in_ty, in_elem, v, ret_ty) + arith_red!("simd_reduce_add_ordered": vector_reduce_add, vector_reduce_fadd_fast, true); + arith_red!("simd_reduce_mul_ordered": vector_reduce_mul, vector_reduce_fmul_fast, true); + arith_red!("simd_reduce_add_unordered": vector_reduce_add, vector_reduce_fadd_fast, false); + arith_red!("simd_reduce_mul_unordered": vector_reduce_mul, vector_reduce_fmul_fast, false); + + macro_rules! minmax_red { + ($name:tt: $int_red:ident, $float_red:ident) => { + if name == $name { + require!(ret_ty == in_elem, + "expected return type `{}` (element of input `{}`), found `{}`", + in_elem, in_ty, ret_ty); + return match in_elem.sty { + ty::TyInt(_i) => { + Ok(bx.$int_red(args[0].immediate(), true)) + }, + ty::TyUint(_u) => { + Ok(bx.$int_red(args[0].immediate(), false)) + }, + ty::TyFloat(_f) => { + Ok(bx.$float_red(args[0].immediate())) } - }; - Ok(bx.vector_reduce_fmul_fast(acc, args[0].immediate())) + _ => { + return_error!("unsupported {} from `{}` with element `{}` to `{}`", + $name, in_ty, in_elem, ret_ty) + }, + } } - _ => { - return_error!("unsupported {} from `{}` with element `{}` to `{}`", - "simd_reduce_mul", in_ty, in_elem, ret_ty) - }, - } - } - if name == "simd_reduce_min" { - require!(ret_ty == in_elem, - "expected return type `{}` (element of input `{}`), found `{}`", - in_elem, in_ty, ret_ty); - return match in_elem.sty { - ty::TyInt(_i) => { - Ok(bx.vector_reduce_min(args[0].immediate(), true)) - }, - ty::TyUint(_u) => { - Ok(bx.vector_reduce_min(args[0].immediate(), false)) - }, - ty::TyFloat(_f) => { - Ok(bx.vector_reduce_fmin_fast(args[0].immediate())) - } - _ => { - return_error!("unsupported {} from `{}` with element `{}` to `{}`", - "simd_reduce_min", in_ty, in_elem, ret_ty) - }, } } - if name == "simd_reduce_max" { - require!(ret_ty == in_elem, - "expected return type `{}` (element of input `{}`), found `{}`", - in_elem, in_ty, ret_ty); - return match in_elem.sty { - ty::TyInt(_i) => { - Ok(bx.vector_reduce_max(args[0].immediate(), true)) - }, - ty::TyUint(_u) => { - Ok(bx.vector_reduce_max(args[0].immediate(), false)) - }, - ty::TyFloat(_f) => { - Ok(bx.vector_reduce_fmax_fast(args[0].immediate())) - } - _ => { - return_error!("unsupported {} from `{}` with element `{}` to `{}`", - "simd_reduce_max", in_ty, in_elem, ret_ty) - }, - } - } + minmax_red!("simd_reduce_min": vector_reduce_min, vector_reduce_fmin); + minmax_red!("simd_reduce_max": vector_reduce_max, vector_reduce_fmax); - if name == "simd_reduce_and" { - require!(ret_ty == in_elem, - "expected return type `{}` (element of input `{}`), found `{}`", - in_elem, in_ty, ret_ty); - return match in_elem.sty { - ty::TyInt(_i) => { - Ok(bx.vector_reduce_and(args[0].immediate())) - }, - ty::TyUint(_u) => { - Ok(bx.vector_reduce_and(args[0].immediate())) - }, - _ => { - return_error!("unsupported {} from `{}` with element `{}` to `{}`", - "simd_reduce_and", in_ty, in_elem, ret_ty) - }, - } - } + minmax_red!("simd_reduce_min_nanless": vector_reduce_min, vector_reduce_fmin_fast); + minmax_red!("simd_reduce_max_nanless": vector_reduce_max, vector_reduce_fmax_fast); - if name == "simd_reduce_or" { - require!(ret_ty == in_elem, - "expected return type `{}` (element of input `{}`), found `{}`", - in_elem, in_ty, ret_ty); - return match in_elem.sty { - ty::TyInt(_i) => { - Ok(bx.vector_reduce_or(args[0].immediate())) - }, - ty::TyUint(_u) => { - Ok(bx.vector_reduce_or(args[0].immediate())) - }, - _ => { - return_error!("unsupported {} from `{}` with element `{}` to `{}`", - "simd_reduce_or", in_ty, in_elem, ret_ty) - }, - } - } - - if name == "simd_reduce_xor" { - require!(ret_ty == in_elem, - "expected return type `{}` (element of input `{}`), found `{}`", - in_elem, in_ty, ret_ty); - return match in_elem.sty { - ty::TyInt(_i) => { - Ok(bx.vector_reduce_xor(args[0].immediate())) - }, - ty::TyUint(_u) => { - Ok(bx.vector_reduce_xor(args[0].immediate())) - }, - _ => { - return_error!("unsupported {} from `{}` with element `{}` to `{}`", - "simd_reduce_xor", in_ty, in_elem, ret_ty) - }, + macro_rules! bitwise_red { + ($name:tt : $red:ident, $boolean:expr) => { + if name == $name { + let input = if !$boolean { + require!(ret_ty == in_elem, + "expected return type `{}` (element of input `{}`), found `{}`", + in_elem, in_ty, ret_ty); + args[0].immediate() + } else { + // boolean reductions operate on vectors of i1s: + let i1 = Type::i1(bx.cx); + let i1xn = Type::vector(&i1, in_len as u64); + bx.trunc(args[0].immediate(), i1xn) + }; + return match in_elem.sty { + ty::TyInt(_) | ty::TyUint(_) => { + let r = bx.$red(input); + Ok( + if !$boolean { + r + } else { + bx.zext(r, Type::bool(bx.cx)) + } + ) + }, + _ => { + return_error!("unsupported {} from `{}` with element `{}` to `{}`", + $name, in_ty, in_elem, ret_ty) + }, + } + } } } - if name == "simd_reduce_all" { - //require!(ret_ty == in_elem, - // "expected return type `{}` (element of input `{}`), found `{}`", - // in_elem, in_ty, ret_ty); - let i1 = Type::i1(bx.cx); - let i1xn = Type::vector(&i1, in_len as u64); - let v = bx.trunc(args[0].immediate(), i1xn); - - let red = match in_elem.sty { - ty::TyInt(_i) => { - bx.vector_reduce_and(v) - }, - ty::TyUint(_u) => { - bx.vector_reduce_and(v) - }, - _ => { - return_error!("unsupported {} from `{}` with element `{}` to `{}`", - "simd_reduce_and", in_ty, in_elem, ret_ty) - }, - }; - return Ok(bx.zext(red, Type::bool(bx.cx))); - } - - if name == "simd_reduce_any" { - //require!(ret_ty == in_elem, - // "expected return type `{}` (element of input `{}`), found `{}`", - // in_elem, in_ty, ret_ty); - let i1 = Type::i1(bx.cx); - let i1xn = Type::vector(&i1, in_len as u64); - let v = bx.trunc(args[0].immediate(), i1xn); - - let red = match in_elem.sty { - ty::TyInt(_i) => { - bx.vector_reduce_or(v) - }, - ty::TyUint(_u) => { - bx.vector_reduce_or(v) - }, - _ => { - return_error!("unsupported {} from `{}` with element `{}` to `{}`", - "simd_reduce_and", in_ty, in_elem, ret_ty) - }, - }; - return Ok(bx.zext(red, Type::bool(bx.cx))); - } - + bitwise_red!("simd_reduce_and": vector_reduce_and, false); + bitwise_red!("simd_reduce_or": vector_reduce_or, false); + bitwise_red!("simd_reduce_xor": vector_reduce_xor, false); + bitwise_red!("simd_reduce_all": vector_reduce_and, true); + bitwise_red!("simd_reduce_any": vector_reduce_or, true); if name == "simd_cast" { require_simd!(ret_ty, "return"); diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index f2d01c57f298e..b87b8aa0bdb65 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -362,9 +362,12 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, "simd_extract" => (2, vec![param(0), tcx.types.u32], param(1)), "simd_cast" => (2, vec![param(0)], param(1)), "simd_reduce_all" | "simd_reduce_any" => (1, vec![param(0)], tcx.types.bool), - "simd_reduce_add" | "simd_reduce_mul" | + "simd_reduce_add_ordered" | "simd_reduce_mul_ordered" + => (2, vec![param(0), param(1)], param(1)), + "simd_reduce_add_unordered" | "simd_reduce_mul_unordered" | "simd_reduce_and" | "simd_reduce_or" | "simd_reduce_xor" | - "simd_reduce_min" | "simd_reduce_max" + "simd_reduce_min" | "simd_reduce_max" | + "simd_reduce_min_nanless" | "simd_reduce_max_nanless" => (2, vec![param(0)], param(1)), name if name.starts_with("simd_shuffle") => { match name["simd_shuffle".len()..].parse() { diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index e749549201e69..9d5f9042f1878 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -1397,6 +1397,7 @@ LLVMRustModuleCost(LLVMModuleRef M) { } // Vector reductions: +#if LLVM_VERSION_GE(6, 0) extern "C" LLVMValueRef LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) { return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src))); @@ -1441,3 +1442,4 @@ extern "C" LLVMValueRef LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) { return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Src), NoNaN)); } +#endif diff --git a/src/test/run-pass/simd-intrinsic-generic-reduction.rs b/src/test/run-pass/simd-intrinsic-generic-reduction.rs index 15b291ae179c5..6755c92961b12 100644 --- a/src/test/run-pass/simd-intrinsic-generic-reduction.rs +++ b/src/test/run-pass/simd-intrinsic-generic-reduction.rs @@ -39,10 +39,14 @@ struct b8x16( ); extern "platform-intrinsic" { - fn simd_reduce_add(x: T) -> U; - fn simd_reduce_mul(x: T) -> U; + fn simd_reduce_add_unordered(x: T) -> U; + fn simd_reduce_mul_unordered(x: T) -> U; + fn simd_reduce_add_ordered(x: T, acc: U) -> U; + fn simd_reduce_mul_ordered(x: T, acc: U) -> U; fn simd_reduce_min(x: T) -> U; fn simd_reduce_max(x: T) -> U; + fn simd_reduce_min_nanless(x: T) -> U; + fn simd_reduce_max_nanless(x: T) -> U; fn simd_reduce_and(x: T) -> U; fn simd_reduce_or(x: T) -> U; fn simd_reduce_xor(x: T) -> U; @@ -53,91 +57,113 @@ extern "platform-intrinsic" { fn main() { unsafe { let x = i32x4(1, -2, 3, 4); - let r: i32 = simd_reduce_add(x); - assert!(r == 6_i32); - let r: i32 = simd_reduce_mul(x); - assert!(r == -24_i32); + let r: i32 = simd_reduce_add_unordered(x); + assert_eq!(r, 6_i32); + let r: i32 = simd_reduce_mul_unordered(x); + assert_eq!(r, -24_i32); + let r: i32 = simd_reduce_add_ordered(x, -1); + assert_eq!(r, 5_i32); + let r: i32 = simd_reduce_mul_ordered(x, -1); + assert_eq!(r, 24_i32); + let r: i32 = simd_reduce_min(x); - assert!(r == -21_i32); + assert_eq!(r, -2_i32); let r: i32 = simd_reduce_max(x); - assert!(r == 4_i32); + assert_eq!(r, 4_i32); let x = i32x4(-1, -1, -1, -1); let r: i32 = simd_reduce_and(x); - assert!(r == -1_i32); + assert_eq!(r, -1_i32); let r: i32 = simd_reduce_or(x); - assert!(r == -1_i32); + assert_eq!(r, -1_i32); let r: i32 = simd_reduce_xor(x); - assert!(r == 0_i32); + assert_eq!(r, 0_i32); let x = i32x4(-1, -1, 0, -1); let r: i32 = simd_reduce_and(x); - assert!(r == 0_i32); + assert_eq!(r, 0_i32); let r: i32 = simd_reduce_or(x); - assert!(r == -1_i32); + assert_eq!(r, -1_i32); let r: i32 = simd_reduce_xor(x); - assert!(r == -1_i32); + assert_eq!(r, -1_i32); } unsafe { let x = u32x4(1, 2, 3, 4); - let r: u32 = simd_reduce_add(x); - assert!(r == 10_u32); - let r: u32 = simd_reduce_mul(x); - assert!(r == 24_u32); + let r: u32 = simd_reduce_add_unordered(x); + assert_eq!(r, 10_u32); + let r: u32 = simd_reduce_mul_unordered(x); + assert_eq!(r, 24_u32); + let r: u32 = simd_reduce_add_ordered(x, 1); + assert_eq!(r, 11_u32); + let r: u32 = simd_reduce_mul_ordered(x, 2); + assert_eq!(r, 48_u32); + let r: u32 = simd_reduce_min(x); - assert!(r == 1_u32); + assert_eq!(r, 1_u32); let r: u32 = simd_reduce_max(x); - assert!(r == 4_u32); + assert_eq!(r, 4_u32); let t = u32::max_value(); let x = u32x4(t, t, t, t); let r: u32 = simd_reduce_and(x); - assert!(r == t); + assert_eq!(r, t); let r: u32 = simd_reduce_or(x); - assert!(r == t); + assert_eq!(r, t); let r: u32 = simd_reduce_xor(x); - assert!(r == 0_u32); + assert_eq!(r, 0_u32); let x = u32x4(t, t, 0, t); let r: u32 = simd_reduce_and(x); - assert!(r == 0_u32); + assert_eq!(r, 0_u32); let r: u32 = simd_reduce_or(x); - assert!(r == t); + assert_eq!(r, t); let r: u32 = simd_reduce_xor(x); - assert!(r == t); + assert_eq!(r, t); } unsafe { let x = f32x4(1., -2., 3., 4.); - let r: f32 = simd_reduce_add(x); - assert!(r == 6_f32); - let r: f32 = simd_reduce_mul(x); - assert!(r == -24_f32); + let r: f32 = simd_reduce_add_unordered(x); + assert_eq!(r, 6_f32); + let r: f32 = simd_reduce_mul_unordered(x); + assert_eq!(r, -24_f32); + // FIXME: only works correctly for accumulator, 0: + // https://bugs.llvm.org/show_bug.cgi?id=36734 + let r: f32 = simd_reduce_add_ordered(x, 0.); + assert_eq!(r, 6_f32); + // FIXME: only works correctly for accumulator, 1: + // https://bugs.llvm.org/show_bug.cgi?id=36734 + let r: f32 = simd_reduce_mul_ordered(x, 1.); + assert_eq!(r, -24_f32); + let r: f32 = simd_reduce_min(x); - assert!(r == -2_f32); + assert_eq!(r, -2_f32); let r: f32 = simd_reduce_max(x); - assert!(r == 4_f32); + assert_eq!(r, 4_f32); + let r: f32 = simd_reduce_min_nanless(x); + assert_eq!(r, -2_f32); + let r: f32 = simd_reduce_max_nanless(x); + assert_eq!(r, 4_f32); } unsafe { let x = b8x4(!0, !0, !0, !0); let r: bool = simd_reduce_all(x); - //let r: bool = foobar(x); - assert!(r); + assert_eq!(r, true); let r: bool = simd_reduce_any(x); - assert!(r); + assert_eq!(r, true); let x = b8x4(!0, !0, 0, !0); let r: bool = simd_reduce_all(x); - assert!(!r); + assert_eq!(r, false); let r: bool = simd_reduce_any(x); - assert!(r); + assert_eq!(r, true); let x = b8x4(0, 0, 0, 0); let r: bool = simd_reduce_all(x); - assert!(!r); + assert_eq!(r, false); let r: bool = simd_reduce_any(x); - assert!(!r); + assert_eq!(r, false); } } From 51832c36b73107fcee63728dee5a5f3798ea4059 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 14 Mar 2018 20:14:47 +0100 Subject: [PATCH 03/17] fix style --- src/librustc_trans/intrinsic.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 8b62a1be80c3d..72c619a3b0ca0 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -1181,8 +1181,8 @@ fn generic_simd_intrinsic<'a, 'tcx>( 32 => C_undef(Type::f32(bx.cx)), 64 => C_undef(Type::f64(bx.cx)), v => { - return_error!( - "unsupported {} from `{}` with element `{}` of size `{}` to `{}`", + return_error!(r#" +unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, $name, in_ty, in_elem, v, ret_ty ) } From c990fa0d880586d85e191b0691a415f9180f4e61 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Wed, 14 Mar 2018 22:12:38 +0100 Subject: [PATCH 04/17] add dummy symbols for LLVM<6 --- src/rustllvm/RustWrapper.cpp | 47 ++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 9d5f9042f1878..c647218c1acac 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -1442,4 +1442,51 @@ extern "C" LLVMValueRef LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) { return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Src), NoNaN)); } + +#else + +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef, LLVMValueRef, LLVMValueRef Src) { + return Src; +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceFMul(LLVMBuilderRef, LLVMValueRef, LLVMValueRef Src) { + return Src; +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceAdd(LLVMBuilderRef, LLVMValueRef Src) { + return Src; +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceMul(LLVMBuilderRef, LLVMValueRef Src) { + return Src; +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceAnd(LLVMBuilderRef, LLVMValueRef Src) { + return Src; +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceOr(LLVMBuilderRef, LLVMValueRef Src) { + return Src; +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceXor(LLVMBuilderRef, LLVMValueRef Src) { + return Src; +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceMin(LLVMBuilderRef, LLVMValueRef Src, bool) { + return Src; +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceMax(LLVMBuilderRef, LLVMValueRef Src, bool) { + return Src; +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceFMin(LLVMBuilderRef, LLVMValueRef Src, bool) { + return Src; +} +extern "C" LLVMValueRef +LLVMRustBuildVectorReduceFMax(LLVMBuilderRef, LLVMValueRef Src, bool) { + return Src; +} #endif From f9bf8270556ea7f89df32c40bd536a26457f8818 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 12 Mar 2018 16:31:34 -0400 Subject: [PATCH 05/17] resolve `'_` in `dyn Trait` just like ordinary elision cc #48468 --- src/librustc/middle/resolve_lifetime.rs | 25 ++++++++++++--- .../dyn-trait-underscore.rs | 32 +++++++++++++++++++ .../dyn-trait-underscore.stderr | 27 ++++++++++++++++ 3 files changed, 80 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/underscore-lifetime/dyn-trait-underscore.rs create mode 100644 src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index f8fb2e5a1c821..0aa750aba0660 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -19,6 +19,7 @@ use hir::map::Map; use hir::def::Def; use hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use hir::ItemLocalId; +use hir::LifetimeName; use ty::{self, TyCtxt}; use std::cell::Cell; @@ -569,10 +570,26 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { for bound in bounds { self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None); } - if lifetime.is_elided() { - self.resolve_object_lifetime_default(lifetime) - } else { - self.visit_lifetime(lifetime); + match lifetime.name { + LifetimeName::Implicit => { + // If the user does not write *anything*, we + // use the object lifetime defaulting + // rules. So e.g. `Box` becomes + // `Box`. + self.resolve_object_lifetime_default(lifetime) + } + LifetimeName::Underscore => { + // If the user writes `'_`, we use the *ordinary* elision + // rules. So the `'_` in e.g. `Box` will be + // resolved the same as the `'_` in `&'_ Foo`. + // + // cc #48468 + self.resolve_elided_lifetimes(slice::from_ref(lifetime), false) + } + LifetimeName::Static | LifetimeName::Name(_) => { + // If the user wrote an explicit name, use that. + self.visit_lifetime(lifetime); + } } } hir::TyRptr(ref lifetime_ref, ref mt) => { diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs new file mode 100644 index 0000000000000..c24762201004b --- /dev/null +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs @@ -0,0 +1,32 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that the `'_` in `dyn Trait + '_` acts like ordinary elision, +// and not like an object lifetime default. +// +// cc #48468 + +#![feature(dyn_trait)] +#![feature(underscore_lifetimes)] + +fn a(items: &[T]) -> Box> { + // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` + Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime +} + +fn b(items: &[T]) -> Box + '_> { + Box::new(items.iter()) // OK, equivalent to c +} + +fn c<'a, T>(items: &'a [T]) -> Box + 'a> { + Box::new(items.iter()) // OK, equivalent to b +} + +fn main() { } diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr new file mode 100644 index 0000000000000..cb3035f42a04a --- /dev/null +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -0,0 +1,27 @@ +error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements + --> $DIR/dyn-trait-underscore.rs:21:20 + | +LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime + | ^^^^ + | +note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 19:1... + --> $DIR/dyn-trait-underscore.rs:19:1 + | +LL | / fn a(items: &[T]) -> Box> { +LL | | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` +LL | | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime +LL | | } + | |_^ +note: ...so that reference does not outlive borrowed content + --> $DIR/dyn-trait-underscore.rs:21:14 + | +LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime + | ^^^^^ + = note: but, the lifetime must be valid for the static lifetime... + = note: ...so that the expression is assignable: + expected std::boxed::Box + 'static> + found std::boxed::Box> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0495`. From 3125a307596db12d8b014da330373446dda5d7ca Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Thu, 15 Mar 2018 10:08:22 +0100 Subject: [PATCH 06/17] error on vector reduction usage if LLVM version is < 5.0 --- src/rustllvm/RustWrapper.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index c647218c1acac..cd3ae1e743bf8 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -21,6 +21,8 @@ #if LLVM_VERSION_GE(5, 0) #include "llvm/ADT/Optional.h" +#else +#include #endif //===----------------------------------------------------------------------=== @@ -1397,7 +1399,7 @@ LLVMRustModuleCost(LLVMModuleRef M) { } // Vector reductions: -#if LLVM_VERSION_GE(6, 0) +#if LLVM_VERSION_GE(5, 0) extern "C" LLVMValueRef LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) { return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src))); @@ -1445,48 +1447,65 @@ LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) { #else +void error_and_exit(const char* msg) { + raw_fd_ostream OS(2, false); + OS << ::std::string(msg); + std::exit(EXIT_FAILURE); +} + extern "C" LLVMValueRef LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef, LLVMValueRef, LLVMValueRef Src) { + error_and_exit("LLVMRustBuildVectorReduceFAdd requires LLVM >= 5.0"); return Src; } extern "C" LLVMValueRef LLVMRustBuildVectorReduceFMul(LLVMBuilderRef, LLVMValueRef, LLVMValueRef Src) { + error_and_exit("LLVMRustBuildVectorReduceFMul requires LLVM >= 5.0"); return Src; } extern "C" LLVMValueRef LLVMRustBuildVectorReduceAdd(LLVMBuilderRef, LLVMValueRef Src) { + error_and_exit("LLVMRustBuildVectorReduceAdd requires LLVM >= 5.0"); return Src; } extern "C" LLVMValueRef LLVMRustBuildVectorReduceMul(LLVMBuilderRef, LLVMValueRef Src) { + error_and_exit("LLVMRustBuildVectorReduceMul requires LLVM >= 5.0"); return Src; } extern "C" LLVMValueRef LLVMRustBuildVectorReduceAnd(LLVMBuilderRef, LLVMValueRef Src) { + error_and_exit("LLVMRustBuildVectorReduceAnd requires LLVM >= 5.0"); return Src; } extern "C" LLVMValueRef LLVMRustBuildVectorReduceOr(LLVMBuilderRef, LLVMValueRef Src) { + error_and_exit("LLVMRustBuildVectorReduceOr requires LLVM >= 5.0"); return Src; } extern "C" LLVMValueRef LLVMRustBuildVectorReduceXor(LLVMBuilderRef, LLVMValueRef Src) { + error_and_exit("LLVMRustBuildVectorReduceXor requires LLVM >= 5.0"); return Src; } extern "C" LLVMValueRef LLVMRustBuildVectorReduceMin(LLVMBuilderRef, LLVMValueRef Src, bool) { + error_and_exit("LLVMRustBuildVectorReduceMin requires LLVM >= 5.0"); return Src; } extern "C" LLVMValueRef LLVMRustBuildVectorReduceMax(LLVMBuilderRef, LLVMValueRef Src, bool) { + error_and_exit("LLVMRustBuildVectorReduceMax requires LLVM >= 5.0"); return Src; } extern "C" LLVMValueRef LLVMRustBuildVectorReduceFMin(LLVMBuilderRef, LLVMValueRef Src, bool) { + error_and_exit("LLVMRustBuildVectorReduceFMin requires LLVM >= 5.0"); return Src; } extern "C" LLVMValueRef LLVMRustBuildVectorReduceFMax(LLVMBuilderRef, LLVMValueRef Src, bool) { + error_and_exit("LLVMRustBuildVectorReduceFMax requires LLVM >= 5.0"); return Src; } #endif From 8478fa2007a2d2a9de21d88ebed13f16b6330393 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Thu, 15 Mar 2018 10:10:16 +0100 Subject: [PATCH 07/17] add min-llvm version to reduction tests --- src/test/run-pass/simd-intrinsic-generic-reduction.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/run-pass/simd-intrinsic-generic-reduction.rs b/src/test/run-pass/simd-intrinsic-generic-reduction.rs index 6755c92961b12..7355aba6c1141 100644 --- a/src/test/run-pass/simd-intrinsic-generic-reduction.rs +++ b/src/test/run-pass/simd-intrinsic-generic-reduction.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// min-llvm-version 5.0 + // Test that the simd_reduce_{op} intrinsics produce the correct results. #![feature(repr_simd, platform_intrinsics)] From 4fe6acf9721b520ddf3c5ee1bc7d300d13545649 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Thu, 15 Mar 2018 16:36:02 +0100 Subject: [PATCH 08/17] add compile fail tests --- src/librustc_llvm/ffi.rs | 2 + src/librustc_trans/common.rs | 20 +++++ src/librustc_trans/intrinsic.rs | 28 ++++++- .../simd-intrinsic-generic-reduction.rs | 76 +++++++++++++++++++ 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 src/test/compile-fail/simd-intrinsic-generic-reduction.rs diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index 00547017349d4..c0cdd21277062 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -621,6 +621,7 @@ extern "C" { pub fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong; pub fn LLVMRustConstInt128Get(ConstantVal: ValueRef, SExt: bool, high: *mut u64, low: *mut u64) -> bool; + pub fn LLVMConstRealGetDouble (ConstantVal: ValueRef, losesInfo: *mut Bool) -> f64; // Operations on composite constants @@ -1607,6 +1608,7 @@ extern "C" { pub fn LLVMRustWriteValueToString(value_ref: ValueRef, s: RustStringRef); pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef; + pub fn LLVMIsAConstantFP(value_ref: ValueRef) -> ValueRef; pub fn LLVMRustPassKind(Pass: PassRef) -> PassKind; pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef; diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 7c4e2340d5bdc..a2c2fad68f6bd 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -270,6 +270,19 @@ pub fn const_get_elt(v: ValueRef, idx: u64) -> ValueRef { } } +pub fn const_get_real(v: ValueRef) -> Option<(f64, bool)> { + unsafe { + if is_const_real(v) { + let mut loses_info: llvm::Bool = ::std::mem::uninitialized(); + let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info as *mut llvm::Bool); + let loses_info = if loses_info == 1 { true } else { false }; + Some((r, loses_info)) + } else { + None + } + } +} + pub fn const_to_uint(v: ValueRef) -> u64 { unsafe { llvm::LLVMConstIntGetZExtValue(v) @@ -282,6 +295,13 @@ pub fn is_const_integral(v: ValueRef) -> bool { } } +pub fn is_const_real(v: ValueRef) -> bool { + unsafe { + !llvm::LLVMIsAConstantFP(v).is_null() + } +} + + #[inline] fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 { ((hi as u128) << 64) | (lo as u128) diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 72c619a3b0ca0..f1ecad2067b20 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -1174,7 +1174,25 @@ fn generic_simd_intrinsic<'a, 'tcx>( ty::TyFloat(f) => { // ordered arithmetic reductions take an accumulator let acc = if $ordered { - args[1].immediate() + let acc = args[1].immediate(); + // FIXME: https://bugs.llvm.org/show_bug.cgi?id=36734 + // * if the accumulator of the fadd isn't 0, incorrect + // code is generated + // * if the accumulator of the fmul isn't 1, incorrect + // code is generated + match const_get_real(acc) { + None => return_error!("accumulator of {} is not a constant", $name), + Some((v, loses_info)) => { + if $name.contains("mul") && v != 1.0_f64 { + return_error!("accumulator of {} is not 1.0", $name); + } else if $name.contains("add") && v != 0.0_f64 { + return_error!("accumulator of {} is not 0.0", $name); + } else if loses_info { + return_error!("accumulator of {} loses information", $name); + } + } + } + acc } else { // unordered arithmetic reductions do not: match f.bit_width() { @@ -1248,6 +1266,14 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, in_elem, in_ty, ret_ty); args[0].immediate() } else { + match in_elem.sty { + ty::TyInt(_) | ty::TyUint(_) => {}, + _ => { + return_error!("unsupported {} from `{}` with element `{}` to `{}`", + $name, in_ty, in_elem, ret_ty) + } + } + // boolean reductions operate on vectors of i1s: let i1 = Type::i1(bx.cx); let i1xn = Type::vector(&i1, in_len as u64); diff --git a/src/test/compile-fail/simd-intrinsic-generic-reduction.rs b/src/test/compile-fail/simd-intrinsic-generic-reduction.rs new file mode 100644 index 0000000000000..b4c069eb10f5c --- /dev/null +++ b/src/test/compile-fail/simd-intrinsic-generic-reduction.rs @@ -0,0 +1,76 @@ +// Copyright 2015 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct f32x4(pub f32, pub f32, pub f32, pub f32); + +#[repr(simd)] +#[derive(Copy, Clone)] +pub struct u32x4(pub u32, pub u32, pub u32, pub u32); + + +extern "platform-intrinsic" { + fn simd_reduce_add_ordered(x: T, y: U) -> U; + fn simd_reduce_mul_ordered(x: T, y: U) -> U; + fn simd_reduce_and(x: T) -> U; + fn simd_reduce_or(x: T) -> U; + fn simd_reduce_xor(x: T) -> U; + fn simd_reduce_all(x: T) -> bool; + fn simd_reduce_any(x: T) -> bool; +} + +fn main() { + let x = u32x4(0, 0, 0, 0); + let z = f32x4(0.0, 0.0, 0.0, 0.0); + + unsafe { + simd_reduce_add_ordered(z, 0_f32); + simd_reduce_mul_ordered(z, 1_f32); + + simd_reduce_add_ordered(z, 2_f32); + //~^ ERROR accumulator of simd_reduce_add_ordered is not 0.0 + simd_reduce_mul_ordered(z, 3_f32); + //~^ ERROR accumulator of simd_reduce_mul_ordered is not 1.0 + + let _: f32 = simd_reduce_and(x); + //~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32` + let _: f32 = simd_reduce_or(x); + //~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32` + let _: f32 = simd_reduce_xor(x); + //~^ ERROR expected return type `u32` (element of input `u32x4`), found `f32` + + let _: f32 = simd_reduce_and(z); + //~^ ERROR unsupported simd_reduce_and from `f32x4` with element `f32` to `f32` + let _: f32 = simd_reduce_or(z); + //~^ ERROR unsupported simd_reduce_or from `f32x4` with element `f32` to `f32` + let _: f32 = simd_reduce_xor(z); + //~^ ERROR unsupported simd_reduce_xor from `f32x4` with element `f32` to `f32` + + let _: bool = simd_reduce_all(z); + //~^ ERROR unsupported simd_reduce_all from `f32x4` with element `f32` to `bool` + let _: bool = simd_reduce_any(z); + //~^ ERROR unsupported simd_reduce_any from `f32x4` with element `f32` to `bool` + + foo(0_f32); + } +} + +#[inline(never)] +unsafe fn foo(x: f32) { + let z = f32x4(0.0, 0.0, 0.0, 0.0); + simd_reduce_add_ordered(z, x); + //~^ ERROR accumulator of simd_reduce_add_ordered is not a constant + simd_reduce_mul_ordered(z, x); + //~^ ERROR accumulator of simd_reduce_mul_ordered is not a constant +} From 19b81f61142fe69edb48d08e9bbfa96d389e8ffd Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Thu, 15 Mar 2018 16:51:58 +0100 Subject: [PATCH 09/17] error via bug! instead of stderr+terminate --- src/librustc_trans/builder.rs | 66 ++++++++++++++++++++++++++++++----- src/rustllvm/RustWrapper.cpp | 61 ++++++++++++-------------------- 2 files changed, 79 insertions(+), 48 deletions(-) diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs index 371f53013b903..3f5a9a54ff1ea 100644 --- a/src/librustc_trans/builder.rs +++ b/src/librustc_trans/builder.rs @@ -962,6 +962,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // https://bugs.llvm.org/show_bug.cgi?id=36732 // is fixed. let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceFAdd is not available in LLVM version < 5.0"); + } llvm::LLVMRustSetHasUnsafeAlgebra(instr); instr } @@ -973,6 +976,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // https://bugs.llvm.org/show_bug.cgi?id=36732 // is fixed. let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceFMul is not available in LLVM version < 5.0"); + } llvm::LLVMRustSetHasUnsafeAlgebra(instr); instr } @@ -980,49 +986,80 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub fn vector_reduce_add(&self, src: ValueRef) -> ValueRef { self.count_insn("vector.reduce.add"); unsafe { - llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src) + let instr = llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceAdd is not available in LLVM version < 5.0"); + } + instr } } pub fn vector_reduce_mul(&self, src: ValueRef) -> ValueRef { self.count_insn("vector.reduce.mul"); unsafe { - llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src) + let instr = llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceMul is not available in LLVM version < 5.0"); + } + instr } } pub fn vector_reduce_and(&self, src: ValueRef) -> ValueRef { self.count_insn("vector.reduce.and"); unsafe { - llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src) + let instr = llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceAnd is not available in LLVM version < 5.0"); + } + instr } } pub fn vector_reduce_or(&self, src: ValueRef) -> ValueRef { self.count_insn("vector.reduce.or"); unsafe { - llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src) + let instr = llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceOr is not available in LLVM version < 5.0"); + } + instr } } pub fn vector_reduce_xor(&self, src: ValueRef) -> ValueRef { self.count_insn("vector.reduce.xor"); unsafe { - llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src) + let instr = llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceXor is not available in LLVM version < 5.0"); + } + instr } } pub fn vector_reduce_fmin(&self, src: ValueRef) -> ValueRef { self.count_insn("vector.reduce.fmin"); unsafe { - llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, true) + let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, true); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0"); + } + instr } } pub fn vector_reduce_fmax(&self, src: ValueRef) -> ValueRef { self.count_insn("vector.reduce.fmax"); unsafe { - llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, true) + let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, true); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0"); + } + instr } } pub fn vector_reduce_fmin_fast(&self, src: ValueRef) -> ValueRef { self.count_insn("vector.reduce.fmin_fast"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, false); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0"); + } llvm::LLVMRustSetHasUnsafeAlgebra(instr); instr } @@ -1031,6 +1068,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.count_insn("vector.reduce.fmax_fast"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, false); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0"); + } llvm::LLVMRustSetHasUnsafeAlgebra(instr); instr } @@ -1038,13 +1078,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub fn vector_reduce_min(&self, src: ValueRef, is_signed: bool) -> ValueRef { self.count_insn("vector.reduce.min"); unsafe { - llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed) + let instr = llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceMin is not available in LLVM version < 5.0"); + } + instr } } pub fn vector_reduce_max(&self, src: ValueRef, is_signed: bool) -> ValueRef { self.count_insn("vector.reduce.max"); unsafe { - llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed) + let instr = llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed); + if instr.is_null() { + bug!("LLVMRustBuildVectorReduceMax is not available in LLVM version < 5.0"); + } + instr } } diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index cd3ae1e743bf8..a5644d6f9e2e1 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -1447,65 +1447,48 @@ LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) { #else -void error_and_exit(const char* msg) { - raw_fd_ostream OS(2, false); - OS << ::std::string(msg); - std::exit(EXIT_FAILURE); -} - extern "C" LLVMValueRef -LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef, LLVMValueRef, LLVMValueRef Src) { - error_and_exit("LLVMRustBuildVectorReduceFAdd requires LLVM >= 5.0"); - return Src; +LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) { + return nullptr; } extern "C" LLVMValueRef -LLVMRustBuildVectorReduceFMul(LLVMBuilderRef, LLVMValueRef, LLVMValueRef Src) { - error_and_exit("LLVMRustBuildVectorReduceFMul requires LLVM >= 5.0"); - return Src; +LLVMRustBuildVectorReduceFMul(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) { + return nullptr; } extern "C" LLVMValueRef -LLVMRustBuildVectorReduceAdd(LLVMBuilderRef, LLVMValueRef Src) { - error_and_exit("LLVMRustBuildVectorReduceAdd requires LLVM >= 5.0"); - return Src; +LLVMRustBuildVectorReduceAdd(LLVMBuilderRef, LLVMValueRef) { + return nullptr; } extern "C" LLVMValueRef -LLVMRustBuildVectorReduceMul(LLVMBuilderRef, LLVMValueRef Src) { - error_and_exit("LLVMRustBuildVectorReduceMul requires LLVM >= 5.0"); - return Src; +LLVMRustBuildVectorReduceMul(LLVMBuilderRef, LLVMValueRef) { + return nullptr; } extern "C" LLVMValueRef -LLVMRustBuildVectorReduceAnd(LLVMBuilderRef, LLVMValueRef Src) { - error_and_exit("LLVMRustBuildVectorReduceAnd requires LLVM >= 5.0"); - return Src; +LLVMRustBuildVectorReduceAnd(LLVMBuilderRef, LLVMValueRef) { + return nullptr; } extern "C" LLVMValueRef -LLVMRustBuildVectorReduceOr(LLVMBuilderRef, LLVMValueRef Src) { - error_and_exit("LLVMRustBuildVectorReduceOr requires LLVM >= 5.0"); - return Src; +LLVMRustBuildVectorReduceOr(LLVMBuilderRef, LLVMValueRef) { + return nullptr; } extern "C" LLVMValueRef -LLVMRustBuildVectorReduceXor(LLVMBuilderRef, LLVMValueRef Src) { - error_and_exit("LLVMRustBuildVectorReduceXor requires LLVM >= 5.0"); - return Src; +LLVMRustBuildVectorReduceXor(LLVMBuilderRef, LLVMValueRef) { + return nullptr; } extern "C" LLVMValueRef -LLVMRustBuildVectorReduceMin(LLVMBuilderRef, LLVMValueRef Src, bool) { - error_and_exit("LLVMRustBuildVectorReduceMin requires LLVM >= 5.0"); - return Src; +LLVMRustBuildVectorReduceMin(LLVMBuilderRef, LLVMValueRef, bool) { + return nullptr; } extern "C" LLVMValueRef -LLVMRustBuildVectorReduceMax(LLVMBuilderRef, LLVMValueRef Src, bool) { - error_and_exit("LLVMRustBuildVectorReduceMax requires LLVM >= 5.0"); - return Src; +LLVMRustBuildVectorReduceMax(LLVMBuilderRef, LLVMValueRef, bool) { + return nullptr; } extern "C" LLVMValueRef -LLVMRustBuildVectorReduceFMin(LLVMBuilderRef, LLVMValueRef Src, bool) { - error_and_exit("LLVMRustBuildVectorReduceFMin requires LLVM >= 5.0"); - return Src; +LLVMRustBuildVectorReduceFMin(LLVMBuilderRef, LLVMValueRef, bool) { + return nullptr; } extern "C" LLVMValueRef -LLVMRustBuildVectorReduceFMax(LLVMBuilderRef, LLVMValueRef Src, bool) { - error_and_exit("LLVMRustBuildVectorReduceFMax requires LLVM >= 5.0"); - return Src; +LLVMRustBuildVectorReduceFMax(LLVMBuilderRef, LLVMValueRef, bool) { + return nullptr; } #endif From f173a4c064e2bce979d85cc610264186913dc164 Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Thu, 15 Mar 2018 18:42:53 +0100 Subject: [PATCH 10/17] add missing min-llvm-version --- src/test/compile-fail/simd-intrinsic-generic-reduction.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/test/compile-fail/simd-intrinsic-generic-reduction.rs b/src/test/compile-fail/simd-intrinsic-generic-reduction.rs index b4c069eb10f5c..4cb9d6aba75cf 100644 --- a/src/test/compile-fail/simd-intrinsic-generic-reduction.rs +++ b/src/test/compile-fail/simd-intrinsic-generic-reduction.rs @@ -8,6 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// min-llvm-version 5.0 + +// Test that the simd_reduce_{op} intrinsics produce ok-ish error +// messages when misused. + #![feature(repr_simd, platform_intrinsics)] #![allow(non_camel_case_types)] From 72cb109bec8e73b1568c2f287ed08348453bf534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 15 Mar 2018 20:13:33 +0100 Subject: [PATCH 11/17] Faster submodule updating --- config.toml.example | 4 +++ src/bootstrap/bootstrap.py | 62 ++++++++++++++++++++++++++++++-------- 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/config.toml.example b/config.toml.example index b47f9163c0dac..aec5e5a0e2c80 100644 --- a/config.toml.example +++ b/config.toml.example @@ -118,6 +118,10 @@ # Indicate whether submodules are managed and updated automatically. #submodules = true +# Update submodules only when the checked out commit in the submodules differs +# from what is committed in the main rustc repo. +#fast-submodules = true + # The path to (or name of) the GDB executable to use. This is only used for # executing the debuginfo test suite. #gdb = "gdb" diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index d8f7cd7ed9227..6ea374b2f265a 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -614,20 +614,55 @@ def build_triple(self): return config return default_build_triple() + def check_submodule(self, module, slow_submodules): + if not slow_submodules: + checked_out = subprocess.Popen(["git", "rev-parse", "HEAD"], + cwd=os.path.join(self.rust_root, module), + stdout=subprocess.PIPE) + return checked_out + else: + return None + + def update_submodule(self, module, checked_out, recorded_submodules): + module_path = os.path.join(self.rust_root, module) + + if checked_out != None: + default_encoding = sys.getdefaultencoding() + checked_out = checked_out.communicate()[0].decode(default_encoding).strip() + if recorded_submodules[module] == checked_out: + return + + print("Updating submodule", module) + + run(["git", "submodule", "-q", "sync", module], + cwd=self.rust_root, verbose=self.verbose) + run(["git", "submodule", "update", + "--init", "--recursive", module], + cwd=self.rust_root, verbose=self.verbose) + run(["git", "reset", "-q", "--hard"], + cwd=module_path, verbose=self.verbose) + run(["git", "clean", "-qdfx"], + cwd=module_path, verbose=self.verbose) + def update_submodules(self): """Update submodules""" if (not os.path.exists(os.path.join(self.rust_root, ".git"))) or \ self.get_toml('submodules') == "false": return - print('Updating submodules') + slow_submodules = self.get_toml('fast-submodule') == "false" + start_time = time() + if slow_submodules: + print('Unconditionally updating all submodules') + else: + print('Updating only changed submodules') default_encoding = sys.getdefaultencoding() - run(["git", "submodule", "-q", "sync"], cwd=self.rust_root, verbose=self.verbose) submodules = [s.split(' ', 1)[1] for s in subprocess.check_output( ["git", "config", "--file", os.path.join(self.rust_root, ".gitmodules"), "--get-regexp", "path"] ).decode(default_encoding).splitlines()] filtered_submodules = [] + submodules_names = [] for module in submodules: if module.endswith("llvm"): if self.get_toml('llvm-config'): @@ -645,16 +680,19 @@ def update_submodules(self): config = self.get_toml('lld') if config is None or config == 'false': continue - filtered_submodules.append(module) - run(["git", "submodule", "update", - "--init", "--recursive"] + filtered_submodules, - cwd=self.rust_root, verbose=self.verbose) - run(["git", "submodule", "-q", "foreach", "git", - "reset", "-q", "--hard"], - cwd=self.rust_root, verbose=self.verbose) - run(["git", "submodule", "-q", "foreach", "git", - "clean", "-qdfx"], - cwd=self.rust_root, verbose=self.verbose) + check = self.check_submodule(module, slow_submodules) + filtered_submodules.append((module, check)) + submodules_names.append(module) + recorded = subprocess.Popen(["git", "ls-tree", "HEAD"] + submodules_names, + cwd=self.rust_root, stdout=subprocess.PIPE) + recorded = recorded.communicate()[0].decode(default_encoding).strip().splitlines() + recorded_submodules = {} + for data in recorded: + data = data.split() + recorded_submodules[data[3]] = data[2] + for module in filtered_submodules: + self.update_submodule(module[0], module[1], recorded_submodules) + print("Submodules updated in %.2f seconds" % (time() - start_time)) def set_dev_environment(self): """Set download URL for development environment""" From ec49234f44adbaf858efa646df67a41055fc905d Mon Sep 17 00:00:00 2001 From: comex Date: Sun, 11 Mar 2018 16:44:05 -0700 Subject: [PATCH 12/17] Support extra-verbose builds: - The bootstrap crate currently passes -v to Cargo if itself invoked with -vv. But Cargo supports -vv (to show build script output), so make bootstrap pass that if itself invoked with -vvv. (More specifically, pass N '-v's to Cargo if invoked with N+1 of them.) - bootstrap.py currently tries to pass on up to two '-v's to cargo when building bootstrap, but incorrectly ('-v' is marked as 'store_true', so argparse stores either False or True, ignoring multiple '-v's). Fix this, allow passing any number of '-v's, and make it consistent with bootstrap's invocation of Cargo (i.e. subtract one from the number of '-v's). - Also improve bootstrap.py's config.toml 'parsing' to support arbitrary verbosity levels, + allow command line to override it. --- src/bootstrap/bootstrap.py | 13 +++++-------- src/bootstrap/builder.rs | 2 +- src/bootstrap/flags.rs | 2 +- src/bootstrap/lib.rs | 4 ---- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index d8f7cd7ed9227..11f174a52a631 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -597,10 +597,8 @@ def build_bootstrap(self): self.cargo())) args = [self.cargo(), "build", "--manifest-path", os.path.join(self.rust_root, "src/bootstrap/Cargo.toml")] - if self.verbose: + for _ in range(1, self.verbose): args.append("--verbose") - if self.verbose > 1: - args.append("--verbose") if self.use_locked_deps: args.append("--locked") if self.use_vendored_sources: @@ -675,7 +673,7 @@ def bootstrap(help_triggered): parser.add_argument('--config') parser.add_argument('--build') parser.add_argument('--clean', action='store_true') - parser.add_argument('-v', '--verbose', action='store_true') + parser.add_argument('-v', '--verbose', action='count', default=0) args = [a for a in sys.argv if a != '-h' and a != '--help'] args, _ = parser.parse_known_args(args) @@ -691,10 +689,9 @@ def bootstrap(help_triggered): except (OSError, IOError): pass - if '\nverbose = 2' in build.config_toml: - build.verbose = 2 - elif '\nverbose = 1' in build.config_toml: - build.verbose = 1 + match = re.search(r'\nverbose = (\d+)', build.config_toml) + if match is not None: + build.verbose = max(build.verbose, int(match.group(1))) build.use_vendored_sources = '\nvendor = true' in build.config_toml diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 1b74e7c41e7a7..4185384cf499d 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -763,7 +763,7 @@ impl<'a> Builder<'a> { cargo.env("WINAPI_NO_BUNDLED_LIBRARIES", "1"); } - if self.is_very_verbose() { + for _ in 1..self.verbosity { cargo.arg("-v"); } diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index af50ad1e96b9f..c5af0f8e2e153 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -29,7 +29,7 @@ use cache::{Interned, INTERNER}; /// Deserialized version of all flags for this compile. pub struct Flags { - pub verbose: usize, // verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose + pub verbose: usize, // number of -v args; each extra -v after the first is passed to Cargo pub on_fail: Option, pub stage: Option, pub keep_stage: Option, diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 938237dd82d52..8b3fbf56d594b 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -605,10 +605,6 @@ impl Build { self.verbosity > 0 } - pub fn is_very_verbose(&self) -> bool { - self.verbosity > 1 - } - /// Prints a message if this build is configured in verbose mode. fn verbose(&self, msg: &str) { if self.is_verbose() { From 4be3e96b80a5dc5bddeaccd2a7c3af1abf8bf452 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Fri, 16 Mar 2018 16:53:40 +0900 Subject: [PATCH 13/17] Checks for unknown attributes before aborting ...due to unresolved macros. --- src/librustc_driver/driver.rs | 10 ++++++---- src/test/ui/issue-49074.rs | 24 ++++++++++++++++++++++++ src/test/ui/issue-49074.stderr | 19 +++++++++++++++++++ 3 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/issue-49074.rs create mode 100644 src/test/ui/issue-49074.stderr diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index e52575f02b2ff..b5e31bdf6686a 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -877,10 +877,6 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, Ok(()) })?; - if resolver.found_unresolved_macro { - sess.parse_sess.span_diagnostic.abort_if_errors(); - } - // Needs to go *after* expansion to be able to check the results of macro expansion. time(sess, "complete gated feature checking", || { sess.track_errors(|| { @@ -892,6 +888,12 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, }) })?; + // Unresolved macros might be due to mistyped `#[macro_use]`, + // so abort after checking for unknown attributes. (#49074) + if resolver.found_unresolved_macro { + sess.parse_sess.span_diagnostic.abort_if_errors(); + } + // Lower ast -> hir. // First, we need to collect the dep_graph. let dep_graph = match future_dep_graph { diff --git a/src/test/ui/issue-49074.rs b/src/test/ui/issue-49074.rs new file mode 100644 index 0000000000000..2e7e118441090 --- /dev/null +++ b/src/test/ui/issue-49074.rs @@ -0,0 +1,24 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that unknown attribute error is shown even if there are unresolved macros. + +#[marco_use] // typo +//~^ ERROR The attribute `marco_use` is currently unknown to the compiler +mod foo { + macro_rules! bar { + () => (); + } +} + +fn main() { + bar!(); + //~^ ERROR cannot find macro `bar!` +} diff --git a/src/test/ui/issue-49074.stderr b/src/test/ui/issue-49074.stderr new file mode 100644 index 0000000000000..c9984ea2e9a8a --- /dev/null +++ b/src/test/ui/issue-49074.stderr @@ -0,0 +1,19 @@ +error: cannot find macro `bar!` in this scope + --> $DIR/issue-49074.rs:22:4 + | +LL | bar!(); + | ^^^ + | + = help: have you added the `#[macro_use]` on the module/import? + +error[E0658]: The attribute `marco_use` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/issue-49074.rs:13:1 + | +LL | #[marco_use] // typo + | ^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. From 06148cb4b0f83ecec70148de8b589644b618e66f Mon Sep 17 00:00:00 2001 From: gnzlbg Date: Fri, 16 Mar 2018 09:39:41 +0100 Subject: [PATCH 14/17] ignore emscripten --- src/test/compile-fail/simd-intrinsic-generic-reduction.rs | 1 + src/test/run-pass/simd-intrinsic-generic-reduction.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/test/compile-fail/simd-intrinsic-generic-reduction.rs b/src/test/compile-fail/simd-intrinsic-generic-reduction.rs index 4cb9d6aba75cf..57e4bb76a6ce8 100644 --- a/src/test/compile-fail/simd-intrinsic-generic-reduction.rs +++ b/src/test/compile-fail/simd-intrinsic-generic-reduction.rs @@ -9,6 +9,7 @@ // except according to those terms. // min-llvm-version 5.0 +// ignore-emscripten // Test that the simd_reduce_{op} intrinsics produce ok-ish error // messages when misused. diff --git a/src/test/run-pass/simd-intrinsic-generic-reduction.rs b/src/test/run-pass/simd-intrinsic-generic-reduction.rs index 7355aba6c1141..9a1214d3b35e5 100644 --- a/src/test/run-pass/simd-intrinsic-generic-reduction.rs +++ b/src/test/run-pass/simd-intrinsic-generic-reduction.rs @@ -9,6 +9,7 @@ // except according to those terms. // min-llvm-version 5.0 +// ignore-emscripten // Test that the simd_reduce_{op} intrinsics produce the correct results. From f0ad533fe316c4eb26ab6ebda879e60956633c0e Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 16 Mar 2018 11:44:55 +0100 Subject: [PATCH 15/17] Remove deprecated unstable alloc::heap::EMPTY constant --- src/liballoc/heap.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index 372d606e45722..c13ad39e5e1d5 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -228,14 +228,6 @@ unsafe impl Alloc for Heap { } } -/// An arbitrary non-null address to represent zero-size allocations. -/// -/// This preserves the non-null invariant for types like `Box`. The address -/// may overlap with non-zero-size memory allocations. -#[rustc_deprecated(since = "1.19.0", reason = "Use Unique/NonNull::empty() instead")] -#[unstable(feature = "heap_api", issue = "27700")] -pub const EMPTY: *mut () = 1 as *mut (); - /// The allocator for unique pointers. // This function must not unwind. If it does, MIR trans will fail. #[cfg(not(test))] From 4133b160363143b975cf9927cff87d183f1f5405 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 16 Mar 2018 11:48:32 +0100 Subject: [PATCH 16/17] Only generate miri backtraces if explicitly requested --- src/librustc/mir/interpret/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 51660b180cd98..9e69990f22c0d 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -20,7 +20,7 @@ pub struct EvalError<'tcx> { impl<'tcx> From> for EvalError<'tcx> { fn from(kind: EvalErrorKind<'tcx>) -> Self { - let backtrace = match env::var("RUST_BACKTRACE") { + let backtrace = match env::var("MIRI_BACKTRACE") { Ok(ref val) if !val.is_empty() => Some(Backtrace::new_unresolved()), _ => None }; From 3304c76874b42233d9a552576c637acbb40bc8f4 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 15 Mar 2018 11:35:07 -0700 Subject: [PATCH 17/17] rustbuild: Add more MinGW libraries to ship Closes #49044 --- src/bootstrap/dist.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index c3d8c9f8c010d..5e2df80af373e 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -203,11 +203,14 @@ fn make_win_dist( "libbcrypt.a", "libcomctl32.a", "libcomdlg32.a", + "libcredui.a", "libcrypt32.a", + "libdbghelp.a", "libgdi32.a", "libimagehlp.a", "libiphlpapi.a", "libkernel32.a", + "libmsimg32.a", "libmsvcrt.a", "libodbc32.a", "libole32.a", @@ -215,6 +218,7 @@ fn make_win_dist( "libopengl32.a", "libpsapi.a", "librpcrt4.a", + "libsecur32.a", "libsetupapi.a", "libshell32.a", "libuser32.a", @@ -225,8 +229,6 @@ fn make_win_dist( "libwinspool.a", "libws2_32.a", "libwsock32.a", - "libdbghelp.a", - "libmsimg32.a", ]; //Find mingw artifacts we want to bundle