about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-01-31 10:01:48 -0800
committerbors <bors@rust-lang.org>2014-01-31 10:01:48 -0800
commit237885cc53fa9dc6e1fe140b767ef3b2f4093c62 (patch)
tree9458a2a47e5621f6320900ed966051b3a97bf247
parentbec01ad17c6a519c38063d99b8863bf1f801f226 (diff)
parente532e8d55d4f8a327b7163606c537fe3e358b03a (diff)
downloadrust-237885cc53fa9dc6e1fe140b767ef3b2f4093c62.tar.gz
rust-237885cc53fa9dc6e1fe140b767ef3b2f4093c62.zip
auto merge of #11917 : thestinger/rust/intrinsic, r=alexcrichton
-rw-r--r--src/librustc/middle/trans/intrinsic.rs112
-rw-r--r--src/librustc/middle/trans/monomorphize.rs161
2 files changed, 137 insertions, 136 deletions
diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs
index 25c4ff04ce5..b662d08062f 100644
--- a/src/librustc/middle/trans/intrinsic.rs
+++ b/src/librustc/middle/trans/intrinsic.rs
@@ -29,27 +29,68 @@ use util::ppaux::ty_to_str;
 use middle::trans::machine::llsize_of;
 use middle::trans::type_::Type;
 
+pub fn get_simple_intrinsic(ccx: @CrateContext, item: &ast::ForeignItem) -> Option<ValueRef> {
+    let nm = ccx.sess.str_of(item.ident);
+    let name = nm.as_slice();
+
+    match name {
+        "sqrtf32" => Some(ccx.intrinsics.get_copy(&("llvm.sqrt.f32"))),
+        "sqrtf64" => Some(ccx.intrinsics.get_copy(&("llvm.sqrt.f64"))),
+        "powif32" => Some(ccx.intrinsics.get_copy(&("llvm.powi.f32"))),
+        "powif64" => Some(ccx.intrinsics.get_copy(&("llvm.powi.f64"))),
+        "sinf32" => Some(ccx.intrinsics.get_copy(&("llvm.sin.f32"))),
+        "sinf64" => Some(ccx.intrinsics.get_copy(&("llvm.sin.f64"))),
+        "cosf32" => Some(ccx.intrinsics.get_copy(&("llvm.cos.f32"))),
+        "cosf64" => Some(ccx.intrinsics.get_copy(&("llvm.cos.f64"))),
+        "powf32" => Some(ccx.intrinsics.get_copy(&("llvm.pow.f32"))),
+        "powf64" => Some(ccx.intrinsics.get_copy(&("llvm.pow.f64"))),
+        "expf32" => Some(ccx.intrinsics.get_copy(&("llvm.exp.f32"))),
+        "expf64" => Some(ccx.intrinsics.get_copy(&("llvm.exp.f64"))),
+        "exp2f32" => Some(ccx.intrinsics.get_copy(&("llvm.exp2.f32"))),
+        "exp2f64" => Some(ccx.intrinsics.get_copy(&("llvm.exp2.f64"))),
+        "logf32" => Some(ccx.intrinsics.get_copy(&("llvm.log.f32"))),
+        "logf64" => Some(ccx.intrinsics.get_copy(&("llvm.log.f64"))),
+        "log10f32" => Some(ccx.intrinsics.get_copy(&("llvm.log10.f32"))),
+        "log10f64" => Some(ccx.intrinsics.get_copy(&("llvm.log10.f64"))),
+        "log2f32" => Some(ccx.intrinsics.get_copy(&("llvm.log2.f32"))),
+        "log2f64" => Some(ccx.intrinsics.get_copy(&("llvm.log2.f64"))),
+        "fmaf32" => Some(ccx.intrinsics.get_copy(&("llvm.fma.f32"))),
+        "fmaf64" => Some(ccx.intrinsics.get_copy(&("llvm.fma.f64"))),
+        "fabsf32" => Some(ccx.intrinsics.get_copy(&("llvm.fabs.f32"))),
+        "fabsf64" => Some(ccx.intrinsics.get_copy(&("llvm.fabs.f64"))),
+        "copysignf32" => Some(ccx.intrinsics.get_copy(&("llvm.copysign.f32"))),
+        "copysignf64" => Some(ccx.intrinsics.get_copy(&("llvm.copysign.f64"))),
+        "floorf32" => Some(ccx.intrinsics.get_copy(&("llvm.floor.f32"))),
+        "floorf64" => Some(ccx.intrinsics.get_copy(&("llvm.floor.f64"))),
+        "ceilf32" => Some(ccx.intrinsics.get_copy(&("llvm.ceil.f32"))),
+        "ceilf64" => Some(ccx.intrinsics.get_copy(&("llvm.ceil.f64"))),
+        "truncf32" => Some(ccx.intrinsics.get_copy(&("llvm.trunc.f32"))),
+        "truncf64" => Some(ccx.intrinsics.get_copy(&("llvm.trunc.f64"))),
+        "rintf32" => Some(ccx.intrinsics.get_copy(&("llvm.rint.f32"))),
+        "rintf64" => Some(ccx.intrinsics.get_copy(&("llvm.rint.f64"))),
+        "nearbyintf32" => Some(ccx.intrinsics.get_copy(&("llvm.nearbyint.f32"))),
+        "nearbyintf64" => Some(ccx.intrinsics.get_copy(&("llvm.nearbyint.f64"))),
+        "roundf32" => Some(ccx.intrinsics.get_copy(&("llvm.round.f32"))),
+        "roundf64" => Some(ccx.intrinsics.get_copy(&("llvm.round.f64"))),
+        "ctpop8" => Some(ccx.intrinsics.get_copy(&("llvm.ctpop.i8"))),
+        "ctpop16" => Some(ccx.intrinsics.get_copy(&("llvm.ctpop.i16"))),
+        "ctpop32" => Some(ccx.intrinsics.get_copy(&("llvm.ctpop.i32"))),
+        "ctpop64" => Some(ccx.intrinsics.get_copy(&("llvm.ctpop.i64"))),
+        "bswap16" => Some(ccx.intrinsics.get_copy(&("llvm.bswap.i16"))),
+        "bswap32" => Some(ccx.intrinsics.get_copy(&("llvm.bswap.i32"))),
+        "bswap64" => Some(ccx.intrinsics.get_copy(&("llvm.bswap.i64"))),
+        _ => None
+    }
+}
+
 pub fn trans_intrinsic(ccx: @CrateContext,
                        decl: ValueRef,
                        item: &ast::ForeignItem,
                        path: ast_map::Path,
                        substs: @param_substs,
-                       _attributes: &[ast::Attribute],
                        ref_id: Option<ast::NodeId>) {
     debug!("trans_intrinsic(item.ident={})", ccx.sess.str_of(item.ident));
 
-    fn simple_llvm_intrinsic(bcx: &Block, name: &'static str, num_args: uint) {
-        assert!(num_args <= 4);
-        let mut args = [0 as ValueRef, ..4];
-        let first_real_arg = bcx.fcx.arg_pos(0u);
-        for i in range(0u, num_args) {
-            args[i] = get_param(bcx.fcx.llfn, first_real_arg + i);
-        }
-        let llfn = bcx.ccx().intrinsics.get_copy(&name);
-        let llcall = Call(bcx, llfn, args.slice(0, num_args), []);
-        Ret(bcx, llcall);
-    }
-
     fn with_overflow_instrinsic(bcx: &Block, name: &'static str, t: ty::t) {
         let first_real_arg = bcx.fcx.arg_pos(0u);
         let a = get_param(bcx.fcx.llfn, first_real_arg);
@@ -431,48 +472,6 @@ pub fn trans_intrinsic(ccx: @CrateContext,
         "copy_nonoverlapping_memory" => copy_intrinsic(bcx, false, substs.tys[0]),
         "copy_memory" => copy_intrinsic(bcx, true, substs.tys[0]),
         "set_memory" => memset_intrinsic(bcx, substs.tys[0]),
-        "sqrtf32" => simple_llvm_intrinsic(bcx, "llvm.sqrt.f32", 1),
-        "sqrtf64" => simple_llvm_intrinsic(bcx, "llvm.sqrt.f64", 1),
-        "powif32" => simple_llvm_intrinsic(bcx, "llvm.powi.f32", 2),
-        "powif64" => simple_llvm_intrinsic(bcx, "llvm.powi.f64", 2),
-        "sinf32" => simple_llvm_intrinsic(bcx, "llvm.sin.f32", 1),
-        "sinf64" => simple_llvm_intrinsic(bcx, "llvm.sin.f64", 1),
-        "cosf32" => simple_llvm_intrinsic(bcx, "llvm.cos.f32", 1),
-        "cosf64" => simple_llvm_intrinsic(bcx, "llvm.cos.f64", 1),
-        "powf32" => simple_llvm_intrinsic(bcx, "llvm.pow.f32", 2),
-        "powf64" => simple_llvm_intrinsic(bcx, "llvm.pow.f64", 2),
-        "expf32" => simple_llvm_intrinsic(bcx, "llvm.exp.f32", 1),
-        "expf64" => simple_llvm_intrinsic(bcx, "llvm.exp.f64", 1),
-        "exp2f32" => simple_llvm_intrinsic(bcx, "llvm.exp2.f32", 1),
-        "exp2f64" => simple_llvm_intrinsic(bcx, "llvm.exp2.f64", 1),
-        "logf32" => simple_llvm_intrinsic(bcx, "llvm.log.f32", 1),
-        "logf64" => simple_llvm_intrinsic(bcx, "llvm.log.f64", 1),
-        "log10f32" => simple_llvm_intrinsic(bcx, "llvm.log10.f32", 1),
-        "log10f64" => simple_llvm_intrinsic(bcx, "llvm.log10.f64", 1),
-        "log2f32" => simple_llvm_intrinsic(bcx, "llvm.log2.f32", 1),
-        "log2f64" => simple_llvm_intrinsic(bcx, "llvm.log2.f64", 1),
-        "fmaf32" => simple_llvm_intrinsic(bcx, "llvm.fma.f32", 3),
-        "fmaf64" => simple_llvm_intrinsic(bcx, "llvm.fma.f64", 3),
-        "fabsf32" => simple_llvm_intrinsic(bcx, "llvm.fabs.f32", 1),
-        "fabsf64" => simple_llvm_intrinsic(bcx, "llvm.fabs.f64", 1),
-        "copysignf32" => simple_llvm_intrinsic(bcx, "llvm.copysign.f32", 2),
-        "copysignf64" => simple_llvm_intrinsic(bcx, "llvm.copysign.f64", 2),
-        "floorf32" => simple_llvm_intrinsic(bcx, "llvm.floor.f32", 1),
-        "floorf64" => simple_llvm_intrinsic(bcx, "llvm.floor.f64", 1),
-        "ceilf32" => simple_llvm_intrinsic(bcx, "llvm.ceil.f32", 1),
-        "ceilf64" => simple_llvm_intrinsic(bcx, "llvm.ceil.f64", 1),
-        "truncf32" => simple_llvm_intrinsic(bcx, "llvm.trunc.f32", 1),
-        "truncf64" => simple_llvm_intrinsic(bcx, "llvm.trunc.f64", 1),
-        "rintf32" => simple_llvm_intrinsic(bcx, "llvm.rint.f32", 1),
-        "rintf64" => simple_llvm_intrinsic(bcx, "llvm.rint.f64", 1),
-        "nearbyintf32" => simple_llvm_intrinsic(bcx, "llvm.nearbyint.f32", 1),
-        "nearbyintf64" => simple_llvm_intrinsic(bcx, "llvm.nearbyint.f64", 1),
-        "roundf32" => simple_llvm_intrinsic(bcx, "llvm.round.f32", 1),
-        "roundf64" => simple_llvm_intrinsic(bcx, "llvm.round.f64", 1),
-        "ctpop8" => simple_llvm_intrinsic(bcx, "llvm.ctpop.i8", 1),
-        "ctpop16" => simple_llvm_intrinsic(bcx, "llvm.ctpop.i16", 1),
-        "ctpop32" => simple_llvm_intrinsic(bcx, "llvm.ctpop.i32", 1),
-        "ctpop64" => simple_llvm_intrinsic(bcx, "llvm.ctpop.i64", 1),
         "ctlz8" => count_zeros_intrinsic(bcx, "llvm.ctlz.i8"),
         "ctlz16" => count_zeros_intrinsic(bcx, "llvm.ctlz.i16"),
         "ctlz32" => count_zeros_intrinsic(bcx, "llvm.ctlz.i32"),
@@ -481,9 +480,6 @@ pub fn trans_intrinsic(ccx: @CrateContext,
         "cttz16" => count_zeros_intrinsic(bcx, "llvm.cttz.i16"),
         "cttz32" => count_zeros_intrinsic(bcx, "llvm.cttz.i32"),
         "cttz64" => count_zeros_intrinsic(bcx, "llvm.cttz.i64"),
-        "bswap16" => simple_llvm_intrinsic(bcx, "llvm.bswap.i16", 1),
-        "bswap32" => simple_llvm_intrinsic(bcx, "llvm.bswap.i32", 1),
-        "bswap64" => simple_llvm_intrinsic(bcx, "llvm.bswap.i64", 1),
 
         "volatile_load" => volatile_load_intrinsic(bcx),
         "volatile_store" => volatile_store_intrinsic(bcx),
diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs
index 678d23c0e19..25c536f2a6d 100644
--- a/src/librustc/middle/trans/monomorphize.rs
+++ b/src/librustc/middle/trans/monomorphize.rs
@@ -223,90 +223,95 @@ pub fn monomorphic_fn(ccx: @CrateContext,
     };
 
     let lldecl = match map_node {
-      ast_map::NodeItem(i, _) => {
-          match *i {
-            ast::Item {
-                node: ast::ItemFn(decl, _, _, _, body),
-                ..
-            } => {
-                let d = mk_lldecl();
-                set_llvm_fn_attrs(i.attrs, d);
-                trans_fn(ccx, pt, decl, body, d, Some(psubsts), fn_id.node, []);
-                d
-            }
-            _ => {
-              ccx.tcx.sess.bug("Can't monomorphize this kind of item")
-            }
-          }
-      }
-      ast_map::NodeForeignItem(i, _, _, _) => {
-          let d = mk_lldecl();
-          intrinsic::trans_intrinsic(ccx, d, i, pt, psubsts, i.attrs,
-                                     ref_id);
-          d
-      }
-      ast_map::NodeVariant(v, enum_item, _) => {
-        let tvs = ty::enum_variants(ccx.tcx, local_def(enum_item.id));
-        let this_tv = *tvs.iter().find(|tv| { tv.id.node == fn_id.node}).unwrap();
-        let d = mk_lldecl();
-        set_inline_hint(d);
-        match v.node.kind {
-            ast::TupleVariantKind(ref args) => {
-                trans_enum_variant(ccx,
-                                   enum_item.id,
-                                   v,
-                                   (*args).clone(),
-                                   this_tv.disr_val,
-                                   Some(psubsts),
-                                   d);
-            }
-            ast::StructVariantKind(_) =>
-                ccx.tcx.sess.bug("can't monomorphize struct variants"),
-        }
-        d
-      }
-      ast_map::NodeMethod(mth, _, _) => {
-        let d = mk_lldecl();
-        set_llvm_fn_attrs(mth.attrs, d);
-        trans_fn(ccx, pt, mth.decl, mth.body, d, Some(psubsts), mth.id, []);
-        d
-      }
-      ast_map::NodeTraitMethod(method, _, pt) => {
-          match *method {
-              ast::Provided(mth) => {
+        ast_map::NodeItem(i, _) => {
+            match *i {
+              ast::Item {
+                  node: ast::ItemFn(decl, _, _, _, body),
+                  ..
+              } => {
                   let d = mk_lldecl();
-                  set_llvm_fn_attrs(mth.attrs, d);
-                  trans_fn(ccx, (*pt).clone(), mth.decl, mth.body,
-                           d, Some(psubsts), mth.id, []);
+                  set_llvm_fn_attrs(i.attrs, d);
+                  trans_fn(ccx, pt, decl, body, d, Some(psubsts), fn_id.node, []);
                   d
               }
               _ => {
-                ccx.tcx.sess.bug(format!("Can't monomorphize a {:?}",
-                                         map_node))
+                ccx.tcx.sess.bug("Can't monomorphize this kind of item")
               }
-          }
-      }
-      ast_map::NodeStructCtor(struct_def, _, _) => {
-        let d = mk_lldecl();
-        set_inline_hint(d);
-        base::trans_tuple_struct(ccx,
-                                 struct_def.fields,
-                                 struct_def.ctor_id.expect("ast-mapped tuple struct \
-                                                            didn't have a ctor id"),
-                                 Some(psubsts),
-                                 d);
-        d
-      }
+            }
+        }
+        ast_map::NodeForeignItem(i, _, _, _) => {
+            let simple = intrinsic::get_simple_intrinsic(ccx, i);
+            match simple {
+                Some(decl) => decl,
+                None => {
+                    let d = mk_lldecl();
+                    intrinsic::trans_intrinsic(ccx, d, i, pt, psubsts, ref_id);
+                    d
+                }
+            }
+        }
+        ast_map::NodeVariant(v, enum_item, _) => {
+            let tvs = ty::enum_variants(ccx.tcx, local_def(enum_item.id));
+            let this_tv = *tvs.iter().find(|tv| { tv.id.node == fn_id.node}).unwrap();
+            let d = mk_lldecl();
+            set_inline_hint(d);
+            match v.node.kind {
+                ast::TupleVariantKind(ref args) => {
+                    trans_enum_variant(ccx,
+                                       enum_item.id,
+                                       v,
+                                       (*args).clone(),
+                                       this_tv.disr_val,
+                                       Some(psubsts),
+                                       d);
+                }
+                ast::StructVariantKind(_) =>
+                    ccx.tcx.sess.bug("can't monomorphize struct variants"),
+            }
+            d
+        }
+        ast_map::NodeMethod(mth, _, _) => {
+            let d = mk_lldecl();
+            set_llvm_fn_attrs(mth.attrs, d);
+            trans_fn(ccx, pt, mth.decl, mth.body, d, Some(psubsts), mth.id, []);
+            d
+        }
+        ast_map::NodeTraitMethod(method, _, pt) => {
+            match *method {
+                ast::Provided(mth) => {
+                    let d = mk_lldecl();
+                    set_llvm_fn_attrs(mth.attrs, d);
+                    trans_fn(ccx, (*pt).clone(), mth.decl, mth.body,
+                             d, Some(psubsts), mth.id, []);
+                    d
+                }
+                _ => {
+                    ccx.tcx.sess.bug(format!("Can't monomorphize a {:?}",
+                                             map_node))
+                }
+            }
+        }
+        ast_map::NodeStructCtor(struct_def, _, _) => {
+            let d = mk_lldecl();
+            set_inline_hint(d);
+            base::trans_tuple_struct(ccx,
+                                     struct_def.fields,
+                                     struct_def.ctor_id.expect("ast-mapped tuple struct \
+                                                                didn't have a ctor id"),
+                                     Some(psubsts),
+                                     d);
+            d
+        }
 
-      // Ugh -- but this ensures any new variants won't be forgotten
-      ast_map::NodeExpr(..) |
-      ast_map::NodeStmt(..) |
-      ast_map::NodeArg(..) |
-      ast_map::NodeBlock(..) |
-      ast_map::NodeCalleeScope(..) |
-      ast_map::NodeLocal(..) => {
-        ccx.tcx.sess.bug(format!("Can't monomorphize a {:?}", map_node))
-      }
+        // Ugh -- but this ensures any new variants won't be forgotten
+        ast_map::NodeExpr(..) |
+        ast_map::NodeStmt(..) |
+        ast_map::NodeArg(..) |
+        ast_map::NodeBlock(..) |
+        ast_map::NodeCalleeScope(..) |
+        ast_map::NodeLocal(..) => {
+            ccx.tcx.sess.bug(format!("Can't monomorphize a {:?}", map_node))
+        }
     };
 
     {