about summary refs log tree commit diff
path: root/src/librustc_codegen_llvm
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-07-02 23:18:15 +0000
committerbors <bors@rust-lang.org>2020-07-02 23:18:15 +0000
commit5f4abc16e1b2cb035eee6a5079ce45ce924c1f33 (patch)
tree327e15fe3a91f01c5b4cf23b2a31366b384e97bd /src/librustc_codegen_llvm
parent3503f565e1fb7296983757d2716346f48a4a262b (diff)
parent7bd2f97cb61d4578ac55d54bfdfc7c4ade752374 (diff)
Auto merge of #73977 - Manishearth:rollup-2x4s7c6, r=Manishearth
Rollup of 8 pull requests

Successful merges:

 - #73454 (Move contributing.md to rustc-dev-guide and point at getting started)
 - #73724 (Use WASM's saturating casts if they are available)
 - #73726 (resolve: disallow labelled breaks/continues through closures/async blocks)
 - #73753 (Use 'tcx for references to AccessLevels wherever possible.)
 - #73781 (Update psm version)
 - #73952 (Add option for local docker testing.)
 - #73957 (disable BTree min_max test in Miri for now)
 - #73975 (Document rustc_ast::ast::Pat)

Failed merges:

r? @ghost
Diffstat (limited to 'src/librustc_codegen_llvm')
-rw-r--r--src/librustc_codegen_llvm/builder.rs51
-rw-r--r--src/librustc_codegen_llvm/context.rs9
-rw-r--r--src/librustc_codegen_llvm/llvm_util.rs7
3 files changed, 65 insertions, 2 deletions
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index ba285b5ef38..89b70dce52c 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -18,6 +18,7 @@ use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::layout::TyAndLayout;
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::sym;
 use rustc_target::abi::{self, Align, Size};
 use rustc_target::spec::{HasTargetSpec, Target};
 use std::borrow::Cow;
@@ -652,6 +653,56 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         unsafe { llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, UNNAMED) }
     }
 
+    fn fptoui_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> {
+        // WebAssembly has saturating floating point to integer casts if the
+        // `nontrapping-fptoint` target feature is activated. We'll use those if
+        // they are available.
+        if self.sess().target.target.arch == "wasm32"
+            && self.sess().target_features.contains(&sym::nontrapping_fptoint)
+        {
+            let src_ty = self.cx.val_ty(val);
+            let float_width = self.cx.float_width(src_ty);
+            let int_width = self.cx.int_width(dest_ty);
+            let name = match (int_width, float_width) {
+                (32, 32) => Some("llvm.wasm.trunc.saturate.unsigned.i32.f32"),
+                (32, 64) => Some("llvm.wasm.trunc.saturate.unsigned.i32.f64"),
+                (64, 32) => Some("llvm.wasm.trunc.saturate.unsigned.i64.f32"),
+                (64, 64) => Some("llvm.wasm.trunc.saturate.unsigned.i64.f64"),
+                _ => None,
+            };
+            if let Some(name) = name {
+                let intrinsic = self.get_intrinsic(name);
+                return Some(self.call(intrinsic, &[val], None));
+            }
+        }
+        None
+    }
+
+    fn fptosi_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> {
+        // WebAssembly has saturating floating point to integer casts if the
+        // `nontrapping-fptoint` target feature is activated. We'll use those if
+        // they are available.
+        if self.sess().target.target.arch == "wasm32"
+            && self.sess().target_features.contains(&sym::nontrapping_fptoint)
+        {
+            let src_ty = self.cx.val_ty(val);
+            let float_width = self.cx.float_width(src_ty);
+            let int_width = self.cx.int_width(dest_ty);
+            let name = match (int_width, float_width) {
+                (32, 32) => Some("llvm.wasm.trunc.saturate.signed.i32.f32"),
+                (32, 64) => Some("llvm.wasm.trunc.saturate.signed.i32.f64"),
+                (64, 32) => Some("llvm.wasm.trunc.saturate.signed.i64.f32"),
+                (64, 64) => Some("llvm.wasm.trunc.saturate.signed.i64.f64"),
+                _ => None,
+            };
+            if let Some(name) = name {
+                let intrinsic = self.get_intrinsic(name);
+                return Some(self.call(intrinsic, &[val], None));
+            }
+        }
+        None
+    }
+
     fn fptoui(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         unsafe { llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, UNNAMED) }
     }
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index e9a001bab75..d484e15eb2f 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -497,6 +497,15 @@ impl CodegenCx<'b, 'tcx> {
             t_v8f64: t_f64, 8;
         }
 
+        ifn!("llvm.wasm.trunc.saturate.unsigned.i32.f32", fn(t_f32) -> t_i32);
+        ifn!("llvm.wasm.trunc.saturate.unsigned.i32.f64", fn(t_f64) -> t_i32);
+        ifn!("llvm.wasm.trunc.saturate.unsigned.i64.f32", fn(t_f32) -> t_i64);
+        ifn!("llvm.wasm.trunc.saturate.unsigned.i64.f64", fn(t_f64) -> t_i64);
+        ifn!("llvm.wasm.trunc.saturate.signed.i32.f32", fn(t_f32) -> t_i32);
+        ifn!("llvm.wasm.trunc.saturate.signed.i32.f64", fn(t_f64) -> t_i32);
+        ifn!("llvm.wasm.trunc.saturate.signed.i64.f32", fn(t_f32) -> t_i64);
+        ifn!("llvm.wasm.trunc.saturate.signed.i64.f64", fn(t_f64) -> t_i64);
+
         ifn!("llvm.trap", fn() -> void);
         ifn!("llvm.debugtrap", fn() -> void);
         ifn!("llvm.frameaddress", fn(t_i32) -> i8p);
diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs
index 80278bb9f53..2e2ce154410 100644
--- a/src/librustc_codegen_llvm/llvm_util.rs
+++ b/src/librustc_codegen_llvm/llvm_util.rs
@@ -250,8 +250,11 @@ const RISCV_WHITELIST: &[(&str, Option<Symbol>)] = &[
     ("e", Some(sym::riscv_target_feature)),
 ];
 
-const WASM_WHITELIST: &[(&str, Option<Symbol>)] =
-    &[("simd128", Some(sym::wasm_target_feature)), ("atomics", Some(sym::wasm_target_feature))];
+const WASM_WHITELIST: &[(&str, Option<Symbol>)] = &[
+    ("simd128", Some(sym::wasm_target_feature)),
+    ("atomics", Some(sym::wasm_target_feature)),
+    ("nontrapping-fptoint", Some(sym::wasm_target_feature)),
+];
 
 /// When rustdoc is running, provide a list of all known features so that all their respective
 /// primitives may be documented.