From befbd3a680e79672108845e1b2d9d5278f92659c Mon Sep 17 00:00:00 2001 From: James Miller Date: Sun, 16 Jun 2013 11:58:51 +1200 Subject: [PATCH] Add the rest of the atomic operations. This makes the handling of atomic operations more generic, which does impose a specific naming convention for the intrinsics, but that seems ok with me, rather than having an individual case for each name. It also adds the intrinsics to the the intrinsics file. --- src/librustc/middle/trans/foreign.rs | 176 +++------ src/librustc/middle/trans/type_use.rs | 61 ++- src/librustc/middle/typeck/check/mod.rs | 500 ++++++++++++------------ src/libstd/unstable/intrinsics.rs | 112 ++++++ 4 files changed, 464 insertions(+), 385 deletions(-) diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 9516a8b83ab..34898e20f1e 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -11,7 +11,6 @@ use core::prelude::*; use back::{link, abi}; -use lib::llvm::{SequentiallyConsistent, Acquire, Release, Xchg}; use lib::llvm::{TypeRef, ValueRef}; use lib; use middle::trans::base::*; @@ -578,118 +577,73 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, let mut bcx = top_scope_block(fcx, None); let lltop = bcx.llbb; let first_real_arg = fcx.arg_pos(0u); - match ccx.sess.str_of(item.ident).as_slice() { - "atomic_cxchg" => { - let old = AtomicCmpXchg(bcx, - get_param(decl, first_real_arg), + + let nm = ccx.sess.str_of(item.ident); + let name = nm.as_slice(); + + // This requires that atomic intrinsics follow a specific naming pattern: + // "atomic_[_], and no ordering means SeqCst + if name.starts_with("atomic_") { + let split : ~[&str] = name.split_iter('_').collect(); + assert!(split.len() >= 2, "Atomic intrinsic not correct format"); + let order = if split.len() == 2 { + lib::llvm::SequentiallyConsistent + } else { + match split[2] { + "relaxed" => lib::llvm::Monotonic, + "acq" => lib::llvm::Acquire, + "rel" => lib::llvm::Release, + "acqrel" => lib::llvm::AcquireRelease, + _ => ccx.sess.fatal("Unknown ordering in atomic intrinsic") + } + }; + + match split[1] { + "cxchg" => { + let old = AtomicCmpXchg(bcx, get_param(decl, first_real_arg), + get_param(decl, first_real_arg + 1u), + get_param(decl, first_real_arg + 2u), + order); + Store(bcx, old, fcx.llretptr.get()); + } + "load" => { + let old = AtomicLoad(bcx, get_param(decl, first_real_arg), + order); + Store(bcx, old, fcx.llretptr.get()); + } + "store" => { + AtomicStore(bcx, get_param(decl, first_real_arg + 1u), + get_param(decl, first_real_arg), + order); + } + op => { + // These are all AtomicRMW ops + let atom_op = match op { + "xchg" => lib::llvm::Xchg, + "xadd" => lib::llvm::Add, + "xsub" => lib::llvm::Sub, + "and" => lib::llvm::And, + "nand" => lib::llvm::Nand, + "or" => lib::llvm::Or, + "xor" => lib::llvm::Xor, + "max" => lib::llvm::Max, + "min" => lib::llvm::Min, + "umax" => lib::llvm::UMax, + "umin" => lib::llvm::UMin, + _ => ccx.sess.fatal("Unknown atomic operation") + }; + + let old = AtomicRMW(bcx, atom_op, get_param(decl, first_real_arg), get_param(decl, first_real_arg + 1u), - get_param(decl, first_real_arg + 2u), - SequentiallyConsistent); - Store(bcx, old, fcx.llretptr.get()); - } - "atomic_cxchg_acq" => { - let old = AtomicCmpXchg(bcx, - get_param(decl, first_real_arg), - get_param(decl, first_real_arg + 1u), - get_param(decl, first_real_arg + 2u), - Acquire); - Store(bcx, old, fcx.llretptr.get()); - } - "atomic_cxchg_rel" => { - let old = AtomicCmpXchg(bcx, - get_param(decl, first_real_arg), - get_param(decl, first_real_arg + 1u), - get_param(decl, first_real_arg + 2u), - Release); - Store(bcx, old, fcx.llretptr.get()); - } - "atomic_load" => { - let old = AtomicLoad(bcx, - get_param(decl, first_real_arg), - SequentiallyConsistent); - Store(bcx, old, fcx.llretptr.get()); - } - "atomic_load_acq" => { - let old = AtomicLoad(bcx, - get_param(decl, first_real_arg), - Acquire); - Store(bcx, old, fcx.llretptr.get()); - } - "atomic_store" => { - AtomicStore(bcx, - get_param(decl, first_real_arg + 1u), - get_param(decl, first_real_arg), - SequentiallyConsistent); - } - "atomic_store_rel" => { - AtomicStore(bcx, - get_param(decl, first_real_arg + 1u), - get_param(decl, first_real_arg), - Release); - } - "atomic_xchg" => { - let old = AtomicRMW(bcx, Xchg, - get_param(decl, first_real_arg), - get_param(decl, first_real_arg + 1u), - SequentiallyConsistent); - Store(bcx, old, fcx.llretptr.get()); - } - "atomic_xchg_acq" => { - let old = AtomicRMW(bcx, Xchg, - get_param(decl, first_real_arg), - get_param(decl, first_real_arg + 1u), - Acquire); - Store(bcx, old, fcx.llretptr.get()); - } - "atomic_xchg_rel" => { - let old = AtomicRMW(bcx, Xchg, - get_param(decl, first_real_arg), - get_param(decl, first_real_arg + 1u), - Release); - Store(bcx, old, fcx.llretptr.get()); - } - "atomic_xadd" => { - let old = AtomicRMW(bcx, lib::llvm::Add, - get_param(decl, first_real_arg), - get_param(decl, first_real_arg + 1u), - SequentiallyConsistent); - Store(bcx, old, fcx.llretptr.get()); - } - "atomic_xadd_acq" => { - let old = AtomicRMW(bcx, lib::llvm::Add, - get_param(decl, first_real_arg), - get_param(decl, first_real_arg + 1u), - Acquire); - Store(bcx, old, fcx.llretptr.get()); - } - "atomic_xadd_rel" => { - let old = AtomicRMW(bcx, lib::llvm::Add, - get_param(decl, first_real_arg), - get_param(decl, first_real_arg + 1u), - Release); - Store(bcx, old, fcx.llretptr.get()); - } - "atomic_xsub" => { - let old = AtomicRMW(bcx, lib::llvm::Sub, - get_param(decl, first_real_arg), - get_param(decl, first_real_arg + 1u), - SequentiallyConsistent); - Store(bcx, old, fcx.llretptr.get()); - } - "atomic_xsub_acq" => { - let old = AtomicRMW(bcx, lib::llvm::Sub, - get_param(decl, first_real_arg), - get_param(decl, first_real_arg + 1u), - Acquire); - Store(bcx, old, fcx.llretptr.get()); - } - "atomic_xsub_rel" => { - let old = AtomicRMW(bcx, lib::llvm::Sub, - get_param(decl, first_real_arg), - get_param(decl, first_real_arg + 1u), - Release); - Store(bcx, old, fcx.llretptr.get()); + order); + Store(bcx, old, fcx.llretptr.get()); + } } + + return; + } + + match name { "size_of" => { let tp_ty = substs.tys[0]; let lltp_ty = type_of::type_of(ccx, tp_ty); diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs index 8c4ff441564..4f532885c92 100644 --- a/src/librustc/middle/trans/type_use.rs +++ b/src/librustc/middle/trans/type_use.rs @@ -117,46 +117,43 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint) _, _) => { if abi.is_intrinsic() { - let flags = match cx.ccx.sess.str_of(i.ident).as_slice() { - "size_of" | "pref_align_of" | "min_align_of" | - "uninit" | "init" | "transmute" | "move_val" | - "move_val_init" => use_repr, + let nm = cx.ccx.sess.str_of(i.ident); + let name = nm.as_slice(); + let flags = if name.starts_with("atomic_") { + 0 + } else { + match name { + "size_of" | "pref_align_of" | "min_align_of" | + "uninit" | "init" | "transmute" | "move_val" | + "move_val_init" => use_repr, - "get_tydesc" | "needs_drop" => use_tydesc, + "get_tydesc" | "needs_drop" => use_tydesc, - "atomic_cxchg" | "atomic_cxchg_acq"| - "atomic_cxchg_rel"| "atomic_load" | - "atomic_load_acq" | "atomic_store" | - "atomic_store_rel"| "atomic_xchg" | - "atomic_xadd" | "atomic_xsub" | - "atomic_xchg_acq" | "atomic_xadd_acq" | - "atomic_xsub_acq" | "atomic_xchg_rel" | - "atomic_xadd_rel" | "atomic_xsub_rel" => 0, + "visit_tydesc" | "forget" | "frame_address" | + "morestack_addr" => 0, - "visit_tydesc" | "forget" | "frame_address" | - "morestack_addr" => 0, + "memcpy32" | "memcpy64" | "memmove32" | "memmove64" | + "memset32" | "memset64" => use_repr, - "memcpy32" | "memcpy64" | "memmove32" | "memmove64" | - "memset32" | "memset64" => use_repr, + "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, - "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, + "ctpop8" | "ctpop16" | "ctpop32" | "ctpop64" => 0, - "ctpop8" | "ctpop16" | "ctpop32" | "ctpop64" => 0, + "ctlz8" | "ctlz16" | "ctlz32" | "ctlz64" => 0, + "cttz8" | "cttz16" | "cttz32" | "cttz64" => 0, - "ctlz8" | "ctlz16" | "ctlz32" | "ctlz64" => 0, - "cttz8" | "cttz16" | "cttz32" | "cttz64" => 0, + "bswap16" | "bswap32" | "bswap64" => 0, - "bswap16" | "bswap32" | "bswap64" => 0, - - // would be cool to make these an enum instead of strings! - _ => fail!("unknown intrinsic in type_use") + // would be cool to make these an enum instead of strings! + _ => fail!("unknown intrinsic in type_use") + } }; for uint::range(0u, n_tps) |n| { cx.uses[n] |= flags;} } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 13ded501679..1ac30027116 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -3434,252 +3434,268 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { } let tcx = ccx.tcx; - let str = ccx.tcx.sess.str_of(it.ident); - let (n_tps, inputs, output) = match str.as_slice() { - "size_of" | - "pref_align_of" | "min_align_of" => (1u, ~[], ty::mk_uint()), - "init" => (1u, ~[], param(ccx, 0u)), - "uninit" => (1u, ~[], param(ccx, 0u)), - "forget" => (1u, ~[ param(ccx, 0) ], ty::mk_nil()), - "transmute" => (2, ~[ param(ccx, 0) ], param(ccx, 1)), - "move_val" | "move_val_init" => { - (1u, - ~[ - ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), param(ccx, 0)), - param(ccx, 0u) - ], - ty::mk_nil()) - } - "needs_drop" => (1u, ~[], ty::mk_bool()), + let nm = ccx.tcx.sess.str_of(it.ident); + let name = nm.as_slice(); + let (n_tps, inputs, output) = if name.starts_with("atomic_") { + let split : ~[&str] = name.split_iter('_').collect(); + assert!(split.len() >= 2, "Atomic intrinsic not correct format"); - "atomic_cxchg" | "atomic_cxchg_acq"| "atomic_cxchg_rel" => { - (0, - ~[ - ty::mk_mut_rptr(tcx, - ty::re_bound(ty::br_anon(0)), - ty::mk_int()), - ty::mk_int(), - ty::mk_int() - ], - ty::mk_int()) - } - "atomic_load" | "atomic_load_acq" => { - (0, - ~[ - ty::mk_imm_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()) - ], - ty::mk_int()) - } - "atomic_store" | "atomic_store_rel" => { - (0, - ~[ - ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()), - ty::mk_int() - ], - ty::mk_nil()) - } - "atomic_xchg" | "atomic_xadd" | "atomic_xsub" | - "atomic_xchg_acq" | "atomic_xadd_acq" | "atomic_xsub_acq" | - "atomic_xchg_rel" | "atomic_xadd_rel" | "atomic_xsub_rel" => { - (0, - ~[ - ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()), - ty::mk_int() - ], - ty::mk_int()) + //We only care about the operation here + match split[1] { + "cxchg" => (0, ~[ty::mk_mut_rptr(tcx, + ty::re_bound(ty::br_anon(0)), + ty::mk_int()), + ty::mk_int(), + ty::mk_int() + ], ty::mk_int()), + "load" => (0, + ~[ + ty::mk_imm_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()) + ], + ty::mk_int()), + "store" => (0, + ~[ + ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()), + ty::mk_int() + ], + ty::mk_nil()), + + "xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" | + "min" | "umax" | "umin" => { + (0, ~[ty::mk_mut_rptr(tcx, + ty::re_bound(ty::br_anon(0)), + ty::mk_int()), ty::mk_int() ], ty::mk_int()) + } + + op => { + tcx.sess.span_err(it.span, + fmt!("unrecognized atomic operation function: `%s`", + op)); + return; + } } - "get_tydesc" => { - // FIXME (#3730): return *intrinsic::tydesc, not *() - (1u, ~[], ty::mk_nil_ptr(ccx.tcx)) - } - "visit_tydesc" => { - let tydesc_name = special_idents::tydesc; - assert!(tcx.intrinsic_defs.contains_key(&tydesc_name)); - let (_, tydesc_ty) = tcx.intrinsic_defs.get_copy(&tydesc_name); - let (_, visitor_object_ty) = ty::visitor_object_ty(tcx); - let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt { - ty: tydesc_ty, - mutbl: ast::m_imm - }); - (0, ~[ td_ptr, visitor_object_ty ], ty::mk_nil()) - } - "frame_address" => { - let fty = ty::mk_closure(ccx.tcx, ty::ClosureTy { - purity: ast::impure_fn, - sigil: ast::BorrowedSigil, - onceness: ast::Once, - region: ty::re_bound(ty::br_anon(0)), - bounds: ty::EmptyBuiltinBounds(), - sig: ty::FnSig { - bound_lifetime_names: opt_vec::Empty, - inputs: ~[ty::mk_imm_ptr(ccx.tcx, ty::mk_mach_uint(ast::ty_u8))], - output: ty::mk_nil() - } - }); - (0u, ~[fty], ty::mk_nil()) - } - "morestack_addr" => { - (0u, ~[], ty::mk_nil_ptr(ccx.tcx)) - } - "memcpy32" => { - (1, - ~[ - ty::mk_ptr(tcx, ty::mt { - ty: param(ccx, 0), - mutbl: ast::m_mutbl - }), - ty::mk_ptr(tcx, ty::mt { - ty: param(ccx, 0), + } else { + match name { + "size_of" | + "pref_align_of" | "min_align_of" => (1u, ~[], ty::mk_uint()), + "init" => (1u, ~[], param(ccx, 0u)), + "uninit" => (1u, ~[], param(ccx, 0u)), + "forget" => (1u, ~[ param(ccx, 0) ], ty::mk_nil()), + "transmute" => (2, ~[ param(ccx, 0) ], param(ccx, 1)), + "move_val" | "move_val_init" => { + (1u, + ~[ + ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), param(ccx, 0)), + param(ccx, 0u) + ], + ty::mk_nil()) + } + "needs_drop" => (1u, ~[], ty::mk_bool()), + + "atomic_xchg" | "atomic_xadd" | "atomic_xsub" | + "atomic_xchg_acq" | "atomic_xadd_acq" | "atomic_xsub_acq" | + "atomic_xchg_rel" | "atomic_xadd_rel" | "atomic_xsub_rel" => { + (0, + ~[ + ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()), + ty::mk_int() + ], + ty::mk_int()) + } + + "get_tydesc" => { + // FIXME (#3730): return *intrinsic::tydesc, not *() + (1u, ~[], ty::mk_nil_ptr(ccx.tcx)) + } + "visit_tydesc" => { + let tydesc_name = special_idents::tydesc; + assert!(tcx.intrinsic_defs.contains_key(&tydesc_name)); + let (_, tydesc_ty) = tcx.intrinsic_defs.get_copy(&tydesc_name); + let (_, visitor_object_ty) = ty::visitor_object_ty(tcx); + let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt { + ty: tydesc_ty, mutbl: ast::m_imm - }), - ty::mk_u32() - ], - ty::mk_nil()) - } - "memcpy64" => { - (1, - ~[ - ty::mk_ptr(tcx, ty::mt { - ty: param(ccx, 0), - mutbl: ast::m_mutbl - }), - ty::mk_ptr(tcx, ty::mt { - ty: param(ccx, 0), - mutbl: ast::m_imm - }), - ty::mk_u64() - ], - ty::mk_nil()) - } - "memmove32" => { - (1, - ~[ - ty::mk_ptr(tcx, ty::mt { - ty: param(ccx, 0), - mutbl: ast::m_mutbl - }), - ty::mk_ptr(tcx, ty::mt { - ty: param(ccx, 0), - mutbl: ast::m_imm - }), - ty::mk_u32() - ], - ty::mk_nil()) - } - "memmove64" => { - (1, - ~[ - ty::mk_ptr(tcx, ty::mt { - ty: param(ccx, 0), - mutbl: ast::m_mutbl - }), - ty::mk_ptr(tcx, ty::mt { - ty: param(ccx, 0), - mutbl: ast::m_imm - }), - ty::mk_u64() - ], - ty::mk_nil()) - } - "memset32" => { - (1, - ~[ - ty::mk_ptr(tcx, ty::mt { - ty: param(ccx, 0), - mutbl: ast::m_mutbl - }), - ty::mk_u8(), - ty::mk_u32() - ], - ty::mk_nil()) - } - "memset64" => { - (1, - ~[ - ty::mk_ptr(tcx, ty::mt { - ty: param(ccx, 0), - mutbl: ast::m_mutbl - }), - ty::mk_u8(), - ty::mk_u64() - ], - ty::mk_nil()) - } - "sqrtf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "sqrtf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "powif32" => { - (0, - ~[ ty::mk_f32(), ty::mk_i32() ], - ty::mk_f32()) - } - "powif64" => { - (0, - ~[ ty::mk_f64(), ty::mk_i32() ], - ty::mk_f64()) - } - "sinf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "sinf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "cosf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "cosf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "powf32" => { - (0, - ~[ ty::mk_f32(), ty::mk_f32() ], - ty::mk_f32()) - } - "powf64" => { - (0, - ~[ ty::mk_f64(), ty::mk_f64() ], - ty::mk_f64()) - } - "expf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "expf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "exp2f32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "exp2f64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "logf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "logf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "log10f32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "log10f64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "log2f32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "log2f64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "fmaf32" => { - (0, - ~[ ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ], - ty::mk_f32()) - } - "fmaf64" => { - (0, - ~[ ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ], - ty::mk_f64()) - } - "fabsf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "fabsf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "floorf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "floorf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "ceilf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "ceilf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "truncf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), - "truncf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), - "ctpop8" => (0, ~[ ty::mk_i8() ], ty::mk_i8()), - "ctpop16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()), - "ctpop32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()), - "ctpop64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()), - "ctlz8" => (0, ~[ ty::mk_i8() ], ty::mk_i8()), - "ctlz16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()), - "ctlz32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()), - "ctlz64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()), - "cttz8" => (0, ~[ ty::mk_i8() ], ty::mk_i8()), - "cttz16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()), - "cttz32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()), - "cttz64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()), - "bswap16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()), - "bswap32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()), - "bswap64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()), - ref other => { - tcx.sess.span_err(it.span, - fmt!("unrecognized intrinsic function: `%s`", - *other)); - return; + }); + (0, ~[ td_ptr, visitor_object_ty ], ty::mk_nil()) + } + "frame_address" => { + let fty = ty::mk_closure(ccx.tcx, ty::ClosureTy { + purity: ast::impure_fn, + sigil: ast::BorrowedSigil, + onceness: ast::Once, + region: ty::re_bound(ty::br_anon(0)), + bounds: ty::EmptyBuiltinBounds(), + sig: ty::FnSig { + bound_lifetime_names: opt_vec::Empty, + inputs: ~[ty::mk_imm_ptr(ccx.tcx, ty::mk_mach_uint(ast::ty_u8))], + output: ty::mk_nil() + } + }); + (0u, ~[fty], ty::mk_nil()) + } + "morestack_addr" => { + (0u, ~[], ty::mk_nil_ptr(ccx.tcx)) + } + "memcpy32" => { + (1, + ~[ + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::m_mutbl + }), + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::m_imm + }), + ty::mk_u32() + ], + ty::mk_nil()) + } + "memcpy64" => { + (1, + ~[ + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::m_mutbl + }), + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::m_imm + }), + ty::mk_u64() + ], + ty::mk_nil()) + } + "memmove32" => { + (1, + ~[ + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::m_mutbl + }), + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::m_imm + }), + ty::mk_u32() + ], + ty::mk_nil()) + } + "memmove64" => { + (1, + ~[ + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::m_mutbl + }), + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::m_imm + }), + ty::mk_u64() + ], + ty::mk_nil()) + } + "memset32" => { + (1, + ~[ + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::m_mutbl + }), + ty::mk_u8(), + ty::mk_u32() + ], + ty::mk_nil()) + } + "memset64" => { + (1, + ~[ + ty::mk_ptr(tcx, ty::mt { + ty: param(ccx, 0), + mutbl: ast::m_mutbl + }), + ty::mk_u8(), + ty::mk_u64() + ], + ty::mk_nil()) + } + "sqrtf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), + "sqrtf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), + "powif32" => { + (0, + ~[ ty::mk_f32(), ty::mk_i32() ], + ty::mk_f32()) + } + "powif64" => { + (0, + ~[ ty::mk_f64(), ty::mk_i32() ], + ty::mk_f64()) + } + "sinf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), + "sinf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), + "cosf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), + "cosf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), + "powf32" => { + (0, + ~[ ty::mk_f32(), ty::mk_f32() ], + ty::mk_f32()) + } + "powf64" => { + (0, + ~[ ty::mk_f64(), ty::mk_f64() ], + ty::mk_f64()) + } + "expf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), + "expf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), + "exp2f32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), + "exp2f64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), + "logf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), + "logf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), + "log10f32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), + "log10f64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), + "log2f32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), + "log2f64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), + "fmaf32" => { + (0, + ~[ ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ], + ty::mk_f32()) + } + "fmaf64" => { + (0, + ~[ ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ], + ty::mk_f64()) + } + "fabsf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), + "fabsf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), + "floorf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), + "floorf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), + "ceilf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), + "ceilf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), + "truncf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()), + "truncf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()), + "ctpop8" => (0, ~[ ty::mk_i8() ], ty::mk_i8()), + "ctpop16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()), + "ctpop32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()), + "ctpop64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()), + "ctlz8" => (0, ~[ ty::mk_i8() ], ty::mk_i8()), + "ctlz16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()), + "ctlz32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()), + "ctlz64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()), + "cttz8" => (0, ~[ ty::mk_i8() ], ty::mk_i8()), + "cttz16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()), + "cttz32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()), + "cttz64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()), + "bswap16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()), + "bswap32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()), + "bswap64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()), + ref other => { + tcx.sess.span_err(it.span, + fmt!("unrecognized intrinsic function: `%s`", + *other)); + return; + } } }; let fty = ty::mk_bare_fn(tcx, ty::BareFnTy { diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs index 13425007785..e1daf6c81b2 100644 --- a/src/libstd/unstable/intrinsics.rs +++ b/src/libstd/unstable/intrinsics.rs @@ -42,22 +42,38 @@ pub extern "rust-intrinsic" { /// Atomic compare and exchange, release ordering. pub fn atomic_cxchg_rel(dst: &mut int, old: int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_cxchg_acqrel(dst: &mut int, old: int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_cxchg_relaxed(dst: &mut int, old: int, src: int) -> int; + + /// Atomic load, sequentially consistent. pub fn atomic_load(src: &int) -> int; /// Atomic load, acquire ordering. pub fn atomic_load_acq(src: &int) -> int; + #[cfg(not(stage0))] + pub fn atomic_load_relaxed(src: &int) -> int; + /// Atomic store, sequentially consistent. pub fn atomic_store(dst: &mut int, val: int); /// Atomic store, release ordering. pub fn atomic_store_rel(dst: &mut int, val: int); + #[cfg(not(stage0))] + pub fn atomic_store_relaxed(dst: &mut int, val: int); + /// Atomic exchange, sequentially consistent. pub fn atomic_xchg(dst: &mut int, src: int) -> int; /// Atomic exchange, acquire ordering. pub fn atomic_xchg_acq(dst: &mut int, src: int) -> int; /// Atomic exchange, release ordering. pub fn atomic_xchg_rel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_xchg_acqrel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_xchg_relaxed(dst: &mut int, src: int) -> int; /// Atomic addition, sequentially consistent. pub fn atomic_xadd(dst: &mut int, src: int) -> int; @@ -65,6 +81,10 @@ pub extern "rust-intrinsic" { pub fn atomic_xadd_acq(dst: &mut int, src: int) -> int; /// Atomic addition, release ordering. pub fn atomic_xadd_rel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_xadd_acqrel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_xadd_relaxed(dst: &mut int, src: int) -> int; /// Atomic subtraction, sequentially consistent. pub fn atomic_xsub(dst: &mut int, src: int) -> int; @@ -72,6 +92,98 @@ pub extern "rust-intrinsic" { pub fn atomic_xsub_acq(dst: &mut int, src: int) -> int; /// Atomic subtraction, release ordering. pub fn atomic_xsub_rel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_xsub_acqrel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_xsub_relaxed(dst: &mut int, src: int) -> int; + + #[cfg(not(stage0))] + pub fn atomic_and(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_and_acq(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_and_rel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_and_acqrel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_and_relaxed(dst: &mut int, src: int) -> int; + + #[cfg(not(stage0))] + pub fn atomic_nand(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_nand_acq(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_nand_rel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_nand_acqrel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_nand_relaxed(dst: &mut int, src: int) -> int; + + #[cfg(not(stage0))] + pub fn atomic_or(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_or_acq(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_or_rel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_or_acqrel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_or_relaxed(dst: &mut int, src: int) -> int; + + #[cfg(not(stage0))] + pub fn atomic_xor(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_xor_acq(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_xor_rel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_xor_acqrel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_xor_relaxed(dst: &mut int, src: int) -> int; + + #[cfg(not(stage0))] + pub fn atomic_max(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_max_acq(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_max_rel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_max_acqrel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_max_relaxed(dst: &mut int, src: int) -> int; + + #[cfg(not(stage0))] + pub fn atomic_min(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_min_acq(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_min_rel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_min_acqrel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_min_relaxed(dst: &mut int, src: int) -> int; + + #[cfg(not(stage0))] + pub fn atomic_umin(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_umin_acq(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_umin_rel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_umin_acqrel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_umin_relaxed(dst: &mut int, src: int) -> int; + + #[cfg(not(stage0))] + pub fn atomic_umin(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_umin_acq(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_umin_rel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_umin_acqrel(dst: &mut int, src: int) -> int; + #[cfg(not(stage0))] + pub fn atomic_umin_relaxed(dst: &mut int, src: int) -> int; /// The size of a type in bytes. ///