]> git.lizzy.rs Git - rust.git/commitdiff
Add more standard c lib llvm intrinsics.
authorLuqman Aden <laden@csclub.uwaterloo.ca>
Thu, 29 Nov 2012 11:48:07 +0000 (06:48 -0500)
committerLuqman Aden <laden@csclub.uwaterloo.ca>
Thu, 29 Nov 2012 11:48:07 +0000 (06:48 -0500)
src/librustc/middle/trans/base.rs
src/librustc/middle/trans/foreign.rs
src/librustc/middle/trans/type_use.rs
src/librustc/middle/typeck/check.rs
src/test/run-pass/intrinsics-math.rs [new file with mode: 0644]

index f4530a28633869c32cc4d6b91a7dab1dc846703e..d44c239c4706f9cf00ed5e474bef6c60d7e45e05 100644 (file)
@@ -2369,6 +2369,67 @@ fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~str, ValueRef> {
     let frameaddress = decl_cdecl_fn(llmod, ~"llvm.frameaddress",
                                      T_fn(T_frameaddress_args,
                                           T_ptr(T_i8())));
+    let sqrtf32 = decl_cdecl_fn(llmod, ~"llvm.sqrt.f32",
+                                T_fn(~[T_f32()], T_f32()));
+    let sqrtf64 = decl_cdecl_fn(llmod, ~"llvm.sqrt.f64",
+                                T_fn(~[T_f64()], T_f64()));
+    let powif32 = decl_cdecl_fn(llmod, ~"llvm.powi.f32",
+                                T_fn(~[T_f32(), T_i32()], T_f32()));
+    let powif64 = decl_cdecl_fn(llmod, ~"llvm.powi.f64",
+                                T_fn(~[T_f64(), T_i32()], T_f64()));
+    let sinf32 = decl_cdecl_fn(llmod, ~"llvm.sin.f32",
+                                T_fn(~[T_f32()], T_f32()));
+    let sinf64 = decl_cdecl_fn(llmod, ~"llvm.sin.f64",
+                                T_fn(~[T_f64()], T_f64()));
+    let cosf32 = decl_cdecl_fn(llmod, ~"llvm.cos.f32",
+                                T_fn(~[T_f32()], T_f32()));
+    let cosf64 = decl_cdecl_fn(llmod, ~"llvm.cos.f64",
+                                T_fn(~[T_f64()], T_f64()));
+    let powf32 = decl_cdecl_fn(llmod, ~"llvm.pow.f32",
+                                T_fn(~[T_f32(), T_f32()], T_f32()));
+    let powf64 = decl_cdecl_fn(llmod, ~"llvm.pow.f64",
+                                T_fn(~[T_f64(), T_f64()], T_f64()));
+    let expf32 = decl_cdecl_fn(llmod, ~"llvm.exp.f32",
+                                T_fn(~[T_f32()], T_f32()));
+    let expf64 = decl_cdecl_fn(llmod, ~"llvm.exp.f64",
+                                T_fn(~[T_f64()], T_f64()));
+    let exp2f32 = decl_cdecl_fn(llmod, ~"llvm.exp2.f32",
+                                T_fn(~[T_f32()], T_f32()));
+    let exp2f64 = decl_cdecl_fn(llmod, ~"llvm.exp2.f64",
+                                T_fn(~[T_f64()], T_f64()));
+    let logf32 = decl_cdecl_fn(llmod, ~"llvm.log.f32",
+                                T_fn(~[T_f32()], T_f32()));
+    let logf64 = decl_cdecl_fn(llmod, ~"llvm.log.f64",
+                                T_fn(~[T_f64()], T_f64()));
+    let log10f32 = decl_cdecl_fn(llmod, ~"llvm.log10.f32",
+                                T_fn(~[T_f32()], T_f32()));
+    let log10f64 = decl_cdecl_fn(llmod, ~"llvm.log10.f64",
+                                T_fn(~[T_f64()], T_f64()));
+    let log2f32 = decl_cdecl_fn(llmod, ~"llvm.log2.f32",
+                                T_fn(~[T_f32()], T_f32()));
+    let log2f64 = decl_cdecl_fn(llmod, ~"llvm.log2.f64",
+                                T_fn(~[T_f64()], T_f64()));
+    let fmaf32 = decl_cdecl_fn(llmod, ~"llvm.fma.f32",
+                                T_fn(~[T_f32(), T_f32(), T_f32()], T_f32()));
+    let fmaf64 = decl_cdecl_fn(llmod, ~"llvm.fma.f64",
+                                T_fn(~[T_f64(), T_f64(), T_f64()], T_f64()));
+    let fabsf32 = decl_cdecl_fn(llmod, ~"llvm.fabs.f32",
+                                T_fn(~[T_f32()], T_f32()));
+    let fabsf64 = decl_cdecl_fn(llmod, ~"llvm.fabs.f64",
+                                T_fn(~[T_f64()], T_f64()));
+    let floorf32 = decl_cdecl_fn(llmod, ~"llvm.floor.f32",
+                                T_fn(~[T_f32()], T_f32()));
+    let floorf64 = decl_cdecl_fn(llmod, ~"llvm.floor.f64",
+                                T_fn(~[T_f64()], T_f64()));
+    let ceilf32 = decl_cdecl_fn(llmod, ~"llvm.ceil.f32",
+                                T_fn(~[T_f32()], T_f32()));
+    let ceilf64 = decl_cdecl_fn(llmod, ~"llvm.ceil.f64",
+                                T_fn(~[T_f64()], T_f64()));
+    let truncf32 = decl_cdecl_fn(llmod, ~"llvm.trunc.f32",
+                                T_fn(~[T_f32()], T_f32()));
+    let truncf64 = decl_cdecl_fn(llmod, ~"llvm.trunc.f64",
+                                T_fn(~[T_f64()], T_f64()));
+
     let intrinsics = HashMap();
     intrinsics.insert(~"llvm.gcroot", gcroot);
     intrinsics.insert(~"llvm.gcread", gcread);
@@ -2378,6 +2439,37 @@ fn declare_intrinsics(llmod: ModuleRef) -> HashMap<~str, ValueRef> {
     intrinsics.insert(~"llvm.memset.p0i8.i64", memset64);
     intrinsics.insert(~"llvm.trap", trap);
     intrinsics.insert(~"llvm.frameaddress", frameaddress);
+    intrinsics.insert(~"llvm.sqrt.f32", sqrtf32);
+    intrinsics.insert(~"llvm.sqrt.f64", sqrtf64);
+    intrinsics.insert(~"llvm.powi.f32", powif32);
+    intrinsics.insert(~"llvm.powi.f64", powif64);
+    intrinsics.insert(~"llvm.sin.f32", sinf32);
+    intrinsics.insert(~"llvm.sin.f64", sinf64);
+    intrinsics.insert(~"llvm.cos.f32", cosf32);
+    intrinsics.insert(~"llvm.cos.f64", cosf64);
+    intrinsics.insert(~"llvm.pow.f32", powf32);
+    intrinsics.insert(~"llvm.pow.f64", powf64);
+    intrinsics.insert(~"llvm.exp.f32", expf32);
+    intrinsics.insert(~"llvm.exp.f64", expf64);
+    intrinsics.insert(~"llvm.exp2.f32", exp2f32);
+    intrinsics.insert(~"llvm.exp2.f64", exp2f64);
+    intrinsics.insert(~"llvm.log.f32", logf32);
+    intrinsics.insert(~"llvm.log.f64", logf64);
+    intrinsics.insert(~"llvm.log10.f32", log10f32);
+    intrinsics.insert(~"llvm.log10.f64", log10f64);
+    intrinsics.insert(~"llvm.log2.f32", log2f32);
+    intrinsics.insert(~"llvm.log2.f64", log2f64);
+    intrinsics.insert(~"llvm.fma.f32", fmaf32);
+    intrinsics.insert(~"llvm.fma.f64", fmaf64);
+    intrinsics.insert(~"llvm.fabs.f32", fabsf32);
+    intrinsics.insert(~"llvm.fabs.f64", fabsf64);
+    intrinsics.insert(~"llvm.floor.f32", floorf32);
+    intrinsics.insert(~"llvm.floor.f64", floorf64);
+    intrinsics.insert(~"llvm.ceil.f32", ceilf32);
+    intrinsics.insert(~"llvm.ceil.f64", ceilf64);
+    intrinsics.insert(~"llvm.trunc.f32", truncf32);
+    intrinsics.insert(~"llvm.trunc.f64", truncf64);
+
     return intrinsics;
 }
 
index 4fe7c307d5977d3b48093ade2a985704e3c42491..8563a79e3d20c95e10f42c6f0fac937aa02cc045 100644 (file)
@@ -973,7 +973,7 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item,
               let llcast = PointerCast(bcx, llcast, T_ptr(T_i8()));
               call_memcpy(bcx, llretptr, llcast, llsize_of(ccx, lltp_ty));
           }
-      }
+        }
         ~"addr_of" => {
             Store(bcx, get_param(decl, first_real_arg), fcx.llretptr);
         }
@@ -1024,6 +1024,164 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item,
                                              T_ptr(T_nil()));
             Store(bcx, morestack_addr, fcx.llretptr);
         }
+        ~"sqrtf32" => {
+            let x = get_param(decl, first_real_arg);
+            let sqrtf = ccx.intrinsics.get(~"llvm.sqrt.f32");
+            Store(bcx, Call(bcx, sqrtf, ~[x]), fcx.llretptr);
+        }
+        ~"sqrtf64" => {
+            let x = get_param(decl, first_real_arg);
+            let sqrtf = ccx.intrinsics.get(~"llvm.sqrt.f64");
+            Store(bcx, Call(bcx, sqrtf, ~[x]), fcx.llretptr);
+        }
+        ~"powif32" => {
+            let a = get_param(decl, first_real_arg);
+            let x = get_param(decl, first_real_arg + 1u);
+            let powif = ccx.intrinsics.get(~"llvm.powi.f32");
+            Store(bcx, Call(bcx, powif, ~[a, x]), fcx.llretptr);
+        }
+        ~"powif64" => {
+            let a = get_param(decl, first_real_arg);
+            let x = get_param(decl, first_real_arg + 1u);
+            let powif = ccx.intrinsics.get(~"llvm.powi.f64");
+            Store(bcx, Call(bcx, powif, ~[a, x]), fcx.llretptr);
+        }
+        ~"sinf32" => {
+            let x = get_param(decl, first_real_arg);
+            let sinf = ccx.intrinsics.get(~"llvm.sin.f32");
+            Store(bcx, Call(bcx, sinf, ~[x]), fcx.llretptr);
+        }
+        ~"sinf64" => {
+            let x = get_param(decl, first_real_arg);
+            let sinf = ccx.intrinsics.get(~"llvm.sin.f64");
+            Store(bcx, Call(bcx, sinf, ~[x]), fcx.llretptr);
+        }
+        ~"cosf32" => {
+            let x = get_param(decl, first_real_arg);
+            let cosf = ccx.intrinsics.get(~"llvm.cos.f32");
+            Store(bcx, Call(bcx, cosf, ~[x]), fcx.llretptr);
+        }
+        ~"cosf64" => {
+            let x = get_param(decl, first_real_arg);
+            let cosf = ccx.intrinsics.get(~"llvm.cos.f64");
+            Store(bcx, Call(bcx, cosf, ~[x]), fcx.llretptr);
+        }
+        ~"powf32" => {
+            let a = get_param(decl, first_real_arg);
+            let x = get_param(decl, first_real_arg + 1u);
+            let powf = ccx.intrinsics.get(~"llvm.pow.f32");
+            Store(bcx, Call(bcx, powf, ~[a, x]), fcx.llretptr);
+        }
+        ~"powf64" => {
+            let a = get_param(decl, first_real_arg);
+            let x = get_param(decl, first_real_arg + 1u);
+            let powf = ccx.intrinsics.get(~"llvm.pow.f64");
+            Store(bcx, Call(bcx, powf, ~[a, x]), fcx.llretptr);
+        }
+        ~"expf32" => {
+            let x = get_param(decl, first_real_arg);
+            let expf = ccx.intrinsics.get(~"llvm.exp.f32");
+            Store(bcx, Call(bcx, expf, ~[x]), fcx.llretptr);
+        }
+        ~"expf64" => {
+            let x = get_param(decl, first_real_arg);
+            let expf = ccx.intrinsics.get(~"llvm.exp.f64");
+            Store(bcx, Call(bcx, expf, ~[x]), fcx.llretptr);
+        }
+        ~"exp2f32" => {
+            let x = get_param(decl, first_real_arg);
+            let exp2f = ccx.intrinsics.get(~"llvm.exp2.f32");
+            Store(bcx, Call(bcx, exp2f, ~[x]), fcx.llretptr);
+        }
+        ~"exp2f64" => {
+            let x = get_param(decl, first_real_arg);
+            let exp2f = ccx.intrinsics.get(~"llvm.exp2.f64");
+            Store(bcx, Call(bcx, exp2f, ~[x]), fcx.llretptr);
+        }
+        ~"logf32" => {
+            let x = get_param(decl, first_real_arg);
+            let logf = ccx.intrinsics.get(~"llvm.log.f32");
+            Store(bcx, Call(bcx, logf, ~[x]), fcx.llretptr);
+        }
+        ~"logf64" => {
+            let x = get_param(decl, first_real_arg);
+            let logf = ccx.intrinsics.get(~"llvm.log.f64");
+            Store(bcx, Call(bcx, logf, ~[x]), fcx.llretptr);
+        }
+        ~"log10f32" => {
+            let x = get_param(decl, first_real_arg);
+            let log10f = ccx.intrinsics.get(~"llvm.log10.f32");
+            Store(bcx, Call(bcx, log10f, ~[x]), fcx.llretptr);
+        }
+        ~"log10f64" => {
+            let x = get_param(decl, first_real_arg);
+            let log10f = ccx.intrinsics.get(~"llvm.log10.f64");
+            Store(bcx, Call(bcx, log10f, ~[x]), fcx.llretptr);
+        }
+        ~"log2f32" => {
+            let x = get_param(decl, first_real_arg);
+            let log2f = ccx.intrinsics.get(~"llvm.log2.f32");
+            Store(bcx, Call(bcx, log2f, ~[x]), fcx.llretptr);
+        }
+        ~"log2f64" => {
+            let x = get_param(decl, first_real_arg);
+            let log2f = ccx.intrinsics.get(~"llvm.log2.f64");
+            Store(bcx, Call(bcx, log2f, ~[x]), fcx.llretptr);
+        }
+        ~"fmaf32" => {
+            let a = get_param(decl, first_real_arg);
+            let b = get_param(decl, first_real_arg + 1u);
+            let c = get_param(decl, first_real_arg + 2u);
+            let fmaf = ccx.intrinsics.get(~"llvm.fma.f32");
+            Store(bcx, Call(bcx, fmaf, ~[a, b, c]), fcx.llretptr);
+        }
+        ~"fmaf64" => {
+            let a = get_param(decl, first_real_arg);
+            let b = get_param(decl, first_real_arg + 1u);
+            let c = get_param(decl, first_real_arg + 2u);
+            let fmaf = ccx.intrinsics.get(~"llvm.fma.f64");
+            Store(bcx, Call(bcx, fmaf, ~[a, b, c]), fcx.llretptr);
+        }
+        ~"fabsf32" => {
+            let x = get_param(decl, first_real_arg);
+            let fabsf = ccx.intrinsics.get(~"llvm.fabs.f32");
+            Store(bcx, Call(bcx, fabsf, ~[x]), fcx.llretptr);
+        }
+        ~"fabsf64" => {
+            let x = get_param(decl, first_real_arg);
+            let fabsf = ccx.intrinsics.get(~"llvm.fabs.f64");
+            Store(bcx, Call(bcx, fabsf, ~[x]), fcx.llretptr);
+        }
+        ~"floorf32" => {
+            let x = get_param(decl, first_real_arg);
+            let floorf = ccx.intrinsics.get(~"llvm.floor.f32");
+            Store(bcx, Call(bcx, floorf, ~[x]), fcx.llretptr);
+        }
+        ~"floorf64" => {
+            let x = get_param(decl, first_real_arg);
+            let floorf = ccx.intrinsics.get(~"llvm.floor.f64");
+            Store(bcx, Call(bcx, floorf, ~[x]), fcx.llretptr);
+        }
+        ~"ceilf32" => {
+            let x = get_param(decl, first_real_arg);
+            let ceilf = ccx.intrinsics.get(~"llvm.ceil.f32");
+            Store(bcx, Call(bcx, ceilf, ~[x]), fcx.llretptr);
+        }
+        ~"ceilf64" => {
+            let x = get_param(decl, first_real_arg);
+            let ceilf = ccx.intrinsics.get(~"llvm.ceil.f64");
+            Store(bcx, Call(bcx, ceilf, ~[x]), fcx.llretptr);
+        }
+        ~"truncf32" => {
+            let x = get_param(decl, first_real_arg);
+            let truncf = ccx.intrinsics.get(~"llvm.trunc.f32");
+            Store(bcx, Call(bcx, truncf, ~[x]), fcx.llretptr);
+        }
+        ~"truncf64" => {
+            let x = get_param(decl, first_real_arg);
+            let truncf = ccx.intrinsics.get(~"llvm.trunc.f64");
+            Store(bcx, Call(bcx, truncf, ~[x]), fcx.llretptr);
+        }
         _ => {
             // Could we make this an enum rather than a string? does it get
             // checked earlier?
index 53889369361fde6091d4955a407dc0aeeb64f1de..0eabd36996726462215c9d35e71bd51f1156eed6 100644 (file)
@@ -108,6 +108,15 @@ fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
                 ~"visit_tydesc"  | ~"forget" | ~"addr_of" |
                 ~"frame_address" | ~"morestack_addr" => 0,
 
+                ~"sqrtf32" | ~"sqrtf64" | ~"powif32" | ~"powif64" |
+                ~"sinf32"  | ~"sinf64"  | ~"cosf32"  | ~"cosf64"  |
+                ~"powf32"  | ~"powf64"  | ~"expf32"  | ~"expf64"  |
+                ~"exp2f32" | ~"exp2f64" | ~"logf32"  | ~"logf64"  |
+                ~"log10f32"| ~"log10f64"| ~"log2f32" | ~"log2f64" |
+                ~"fmaf32"  | ~"fmaf64"  | ~"fabsf32" | ~"fabsf64" |
+                ~"floorf32"| ~"floorf64"| ~"ceilf32" | ~"ceilf64" |
+                ~"truncf32"| ~"truncf64" => 0,
+
                 // would be cool to make these an enum instead of strings!
                 _ => fail ~"unknown intrinsic in type_use"
             };
index b24550f2bc647bc62c95278870a8fa2626003f82..079e624c20f3f0abd507e899bfda7f4a9b0b57e1 100644 (file)
@@ -2872,6 +2872,136 @@ fn arg(m: ast::rmode, ty: ty::t) -> ty::arg {
       ~"morestack_addr" => {
         (0u, ~[], ty::mk_nil_ptr(tcx))
       }
+
+     ~"sqrtf32" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))],
+         ty::mk_f32(tcx))
+     }
+     ~"sqrtf64" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))],
+         ty::mk_f64(tcx))
+     }
+     ~"powif32" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx)),
+               arg(ast::by_copy, ty::mk_i32(tcx))],
+         ty::mk_f32(tcx))
+     }
+     ~"powif64" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx)),
+               arg(ast::by_copy, ty::mk_i32(tcx))],
+         ty::mk_f64(tcx))
+     }
+     ~"sinf32" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))],
+         ty::mk_f32(tcx))
+     }
+     ~"sinf64" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))],
+         ty::mk_f64(tcx))
+     }
+     ~"cosf32" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))],
+         ty::mk_f32(tcx))
+     }
+     ~"cosf64" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))],
+         ty::mk_f64(tcx))
+     }
+     ~"powf32" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx)),
+               arg(ast::by_copy, ty::mk_f32(tcx))],
+         ty::mk_f32(tcx))
+     }
+     ~"powf64" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx)),
+               arg(ast::by_copy, ty::mk_f64(tcx))],
+         ty::mk_f64(tcx))
+     }
+     ~"expf32" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))],
+         ty::mk_f32(tcx))
+     }
+     ~"expf64" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))],
+         ty::mk_f64(tcx))
+     }
+     ~"exp2f32" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))],
+         ty::mk_f32(tcx))
+     }
+     ~"exp2f64" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))],
+         ty::mk_f64(tcx))
+     }
+     ~"logf32" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))],
+         ty::mk_f32(tcx))
+     }
+     ~"logf64" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))],
+         ty::mk_f64(tcx))
+     }
+     ~"log10f32" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))],
+         ty::mk_f32(tcx))
+     }      
+     ~"log10f64" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))],
+         ty::mk_f64(tcx))
+     }
+     ~"log2f32" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))],
+         ty::mk_f32(tcx))
+     }
+     ~"log2f64" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))],
+         ty::mk_f64(tcx))
+     }
+     ~"fmaf32" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx)),
+               arg(ast::by_copy, ty::mk_f32(tcx)),
+               arg(ast::by_copy, ty::mk_f32(tcx))],
+         ty::mk_f32(tcx))
+     }
+     ~"fmaf64" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx)),
+               arg(ast::by_copy, ty::mk_f64(tcx)),
+               arg(ast::by_copy, ty::mk_f64(tcx))],
+         ty::mk_f64(tcx))
+     }
+     ~"fabsf32" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))],
+         ty::mk_f32(tcx))
+     }
+     ~"fabsf64" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))],
+         ty::mk_f64(tcx))
+     }
+     ~"floorf32" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))],
+         ty::mk_f32(tcx))
+     }
+     ~"floorf64" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))],
+         ty::mk_f64(tcx))
+     }
+     ~"ceilf32" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))],
+         ty::mk_f32(tcx))
+     }
+     ~"ceilf64" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))],
+         ty::mk_f64(tcx))
+     }
+     ~"truncf32" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f32(tcx))],
+         ty::mk_f32(tcx))
+     }
+     ~"truncf64" => {
+        (0u, ~[arg(ast::by_copy, ty::mk_f64(tcx))],
+         ty::mk_f64(tcx))
+     }
+
       other => {
         tcx.sess.span_err(it.span, ~"unrecognized intrinsic function: `" +
                           other + ~"`");
diff --git a/src/test/run-pass/intrinsics-math.rs b/src/test/run-pass/intrinsics-math.rs
new file mode 100644 (file)
index 0000000..3512ccf
--- /dev/null
@@ -0,0 +1,88 @@
+#[abi = "rust-intrinsic"]  
+extern mod rusti {
+    fn sqrtf32(x: f32) -> f32;
+    fn sqrtf64(x: f64) -> f64;
+    fn powif32(a: f32, x: i32) -> f32;
+    fn powif64(a: f64, x: i32) -> f64;
+    fn sinf32(x: f32) -> f32;
+    fn sinf64(x: f64) -> f64;
+    fn cosf32(x: f32) -> f32;
+    fn cosf64(x: f64) -> f64;
+    fn powf32(a: f32, x: f32) -> f32;
+    fn powf64(a: f64, x: f64) -> f64;
+    fn expf32(x: f32) -> f32;
+    fn expf64(x: f64) -> f64;
+    fn exp2f32(x: f32) -> f32;
+    fn exp2f64(x: f64) -> f64;
+    fn logf32(x: f32) -> f32;
+    fn logf64(x: f64) -> f64;
+    fn log10f32(x: f32) -> f32;
+    fn log10f64(x: f64) -> f64;
+    fn log2f32(x: f32) -> f32;
+    fn log2f64(x: f64) -> f64;
+    fn fmaf32(a: f32, b: f32, c: f32) -> f32;
+    fn fmaf64(a: f64, b: f64, c: f64) -> f64;
+    fn fabsf32(x: f32) -> f32;
+    fn fabsf64(x: f64) -> f64;
+    fn floorf32(x: f32) -> f32;
+    fn floorf64(x: f64) -> f64;
+    fn ceilf32(x: f32) -> f32;
+    fn ceilf64(x: f64) -> f64;
+    fn truncf32(x: f32) -> f32;
+    fn truncf64(x: f64) -> f64;
+}
+
+fn main() {
+
+    use rusti::*;
+
+    assert(sqrtf32(64f32) == 8f32);
+    assert(sqrtf64(64f64) == 8f64);
+
+    assert(powif32(25f32, -2i32) == 0.0016f32);
+    assert(powif64(23.2f64, 2i32) == 538.24f64);
+
+    assert(sinf32(0f32) == 0f32);
+    assert(sinf64(f64::consts::pi / 2f64) == 1f64);
+
+    assert(cosf32(0f32) == 1f32);
+    assert(cosf64(f64::consts::pi * 2f64) == 1f64);
+
+    assert(powf32(25f32, -2f32) == 0.0016f32);
+    assert(powf64(400f64, 0.5f64) == 20f64);
+
+    assert(expf32(1f32) == f32::consts::e);
+    assert(expf64(1f64) == f64::consts::e);
+
+    assert(exp2f32(10f32) == 1024f32);
+    assert(exp2f64(50f64) == 1125899906842624f64);
+
+    assert(logf32(f32::consts::e) == 1f32);
+    assert(logf64(1f64) == 0f64);
+
+    assert(log10f32(10f32) == 1f32);
+    assert(log10f64(f64::consts::e) == f64::consts::log10_e);
+
+    assert(log2f32(8f32) == 3f32);
+    assert(log2f64(f64::consts::e) == f64::consts::log2_e);
+  
+    assert(fmaf32(1.0f32, 2.0f32, 5.0f32) == 7.0f32);
+    assert(fmaf64(0.0f64, -2.0f64, f64::consts::e) == f64::consts::e);
+
+    assert(fabsf32(-1.0f32) == 1.0f32);
+    assert(fabsf64(34.2f64) == 34.2f64);
+
+    assert(floorf32(3.8f32) == 3.0f32);
+    assert(floorf64(-1.1f64) == -2.0f64);
+
+    // Causes linker error
+    // undefined reference to llvm.ceil.f32/64
+    //assert(ceilf32(-2.3f32) == -2.0f32);
+    //assert(ceilf64(3.8f64) == 4.0f64);
+  
+    // Causes linker error
+    // undefined reference to llvm.trunc.f32/64
+    //assert(truncf32(0.1f32) == 0.0f32);
+    //assert(truncf64(-0.1f64) == 0.0f64);
+
+}