$(foreach cvar,CC CXX CPP CFLAGS CXXFLAGS CPPFLAGS,\
$(eval $(call SET_FROM_CFG,$(cvar))))
-ifeq ($(CFG_USING_CLANG),1)
- # The -Qunused-arguments sidesteps spurious warnings from clang
- CFLAGS += -Qunused-arguments
- CXXFLAGS += -Qunused-arguments
- CPPFLAGS += -Qunused-arguments
-endif
-
CFG_RLIB_GLOB=lib$(1)-*.rlib
# x86_64-unknown-linux-gnu configuration
CFG_RUN_x86_64-unknown-freebsd=$(2)
CFG_RUN_TARG_x86_64-unknown-freebsd=$(call CFG_RUN_x86_64-unknown-freebsd,,$(2))
+
+# The -Qunused-arguments sidesteps spurious warnings from clang
+define FILTER_FLAGS
+ ifeq ($$(CFG_USING_CLANG),1)
+ ifneq ($(findstring clang,$$(shell $(CC_$(1)) -v)),)
+ CFG_GCCISH_CFLAGS_$(1) += -Qunused-arguments
+ CFG_GCCISH_CXXFLAGS_$(1) += -Qunused-arguments
+ endif
+ endif
+endef
+
+$(foreach target,$(CFG_TARGET),\
+ $(eval $(call FILTER_FLAGS,$(target))))
+
+
ifeq ($(CFG_CCACHE_CPP2),1)
CCACHE_CPP2=1
export CCACHE_CPP
//! ```
//! extern crate collections;
//!
-//! use collections::HashMap;
//! use std::cell::RefCell;
//!
//! struct Graph {
-//! edges: HashMap<uint, uint>,
+//! edges: Vec<(uint, uint)>,
//! span_tree_cache: RefCell<Option<Vec<(uint, uint)>>>
//! }
//!
# Example
```
-use std::unstable::finally::Finally;
+use std::finally::Finally;
(|| {
// ...
* # Example
*
* ```
- * use std::unstable::finally::try_finally;
+ * use std::finally::try_finally;
*
* struct State<'a> { buffer: &'a mut [u8], len: uint }
* # let mut buf = [];
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//! The Rust Core Library
+//! # The Rust Core Library
//!
//! The Rust Core Library is the dependency-free foundation of [The
//! Rust Standard Library](../std/index.html). It is the portable glue
html_root_url = "http://doc.rust-lang.org/")]
#![no_std]
-#![feature(globs, macro_rules, managed_boxes, phase)]
+#![feature(globs, macro_rules, managed_boxes, phase, simd)]
#![deny(missing_doc)]
#[cfg(test)] extern crate realcore = "core";
pub mod option;
pub mod raw;
pub mod result;
+pub mod simd;
pub mod slice;
pub mod str;
pub mod tuple;
// FIXME: talk about offset, copy_memory, copy_nonoverlapping_memory
-//! Conveniences for working with unsafe pointers, the `*T`, and `*mut T` types.
+//! Operations on unsafe pointers, `*T`, and `*mut T`.
//!
-//! Working with unsafe pointers in Rust is fairly uncommon,
-//! and often limited to some narrow use cases: holding
-//! an unsafe pointer when safe pointers are unsuitable;
-//! checking for null; and converting back to safe pointers.
-//! As a result, there is not yet an abundance of library code
-//! for working with unsafe pointers, and in particular,
-//! since pointer math is fairly uncommon in Rust, it is not
-//! all that convenient.
+//! Working with unsafe pointers in Rust is uncommon,
+//! typically limited to a few patterns.
//!
//! Use the [`null` function](fn.null.html) to create null pointers,
//! the [`is_null`](trait.RawPtr.html#tymethod.is_null)
//! and [`is_not_null`](trait.RawPtr.html#method.is_not_null)
//! methods of the [`RawPtr` trait](trait.RawPtr.html) to check for null.
//! The `RawPtr` trait is imported by the prelude, so `is_null` etc.
-//! work everywhere.
+//! work everywhere. The `RawPtr` also defines the `offset` method,
+//! for pointer math.
//!
//! # Common ways to create unsafe pointers
//!
array_each_with_len(arr, len, cb);
}
-/// Extension methods for raw pointers.
+/// Methods on raw pointers
pub trait RawPtr<T> {
/// Returns the null pointer.
fn null() -> Self;
--- /dev/null
+// Copyright 2013 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! SIMD vectors.
+//!
+//! These types can be used for accessing basic SIMD operations. Each of them
+//! implements the standard arithmetic operator traits (Add, Sub, Mul, Div,
+//! Rem, Shl, Shr) through compiler magic, rather than explicitly. Currently
+//! comparison operators are not implemented. To use SSE3+, you must enable
+//! the features, like `-C target-feature=sse3,sse4.1,sse4.2`, or a more
+//! specific `target-cpu`. No other SIMD intrinsics or high-level wrappers are
+//! provided beyond this module.
+//!
+//! ```rust
+//! #[allow(experimental)];
+//!
+//! fn main() {
+//! use std::simd::f32x4;
+//! let a = f32x4(40.0, 41.0, 42.0, 43.0);
+//! let b = f32x4(1.0, 1.1, 3.4, 9.8);
+//! println!("{}", a + b);
+//! }
+//! ```
+//!
+//! ## Stability Note
+//!
+//! These are all experimental. The inferface may change entirely, without
+//! warning.
+
+#![allow(non_camel_case_types)]
+#![allow(missing_doc)]
+
+#[experimental]
+#[simd]
+#[deriving(Show)]
+pub struct i8x16(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);
+
+#[experimental]
+#[simd]
+#[deriving(Show)]
+pub struct i16x8(pub i16, pub i16, pub i16, pub i16,
+ pub i16, pub i16, pub i16, pub i16);
+
+#[experimental]
+#[simd]
+#[deriving(Show)]
+pub struct i32x4(pub i32, pub i32, pub i32, pub i32);
+
+#[experimental]
+#[simd]
+#[deriving(Show)]
+pub struct i64x2(pub i64, pub i64);
+
+#[experimental]
+#[simd]
+#[deriving(Show)]
+pub struct u8x16(pub u8, pub u8, pub u8, pub u8,
+ pub u8, pub u8, pub u8, pub u8,
+ pub u8, pub u8, pub u8, pub u8,
+ pub u8, pub u8, pub u8, pub u8);
+
+#[experimental]
+#[simd]
+#[deriving(Show)]
+pub struct u16x8(pub u16, pub u16, pub u16, pub u16,
+ pub u16, pub u16, pub u16, pub u16);
+
+#[experimental]
+#[simd]
+#[deriving(Show)]
+pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
+
+#[experimental]
+#[simd]
+#[deriving(Show)]
+pub struct u64x2(pub u64, pub u64);
+
+#[experimental]
+#[simd]
+#[deriving(Show)]
+pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
+
+#[experimental]
+#[simd]
+#[deriving(Show)]
+pub struct f64x2(pub f64, pub f64);
use std::c_str::ToCStr;
use std::cell::RefCell;
use collections::HashMap;
-use libc::{c_uint, c_ushort, c_void, free};
+use libc::{c_uint, c_ushort, c_void, free, uint64_t};
use std::str::raw::from_c_str;
use middle::trans::type_::Type;
NonLazyBindAttribute = 1 << 31,
}
+#[repr(u64)]
+pub enum OtherAttribute {
+ // The following are not really exposed in
+ // the LLVM c api so instead to add these
+ // we call a wrapper function in RustWrapper
+ // that uses the C++ api.
+ SanitizeAddressAttribute = 1 << 32,
+ MinSizeAttribute = 1 << 33,
+ NoDuplicateAttribute = 1 << 34,
+ StackProtectStrongAttribute = 1 << 35,
+ SanitizeThreadAttribute = 1 << 36,
+ SanitizeMemoryAttribute = 1 << 37,
+ NoBuiltinAttribute = 1 << 38,
+ ReturnedAttribute = 1 << 39,
+ ColdAttribute = 1 << 40,
+ BuiltinAttribute = 1 << 41,
+ OptimizeNoneAttribute = 1 << 42,
+ InAllocaAttribute = 1 << 43,
+ NonNullAttribute = 1 << 44,
+}
+
+#[repr(C)]
+pub enum AttributeSet {
+ ReturnIndex = 0,
+ FunctionIndex = !0
+}
+
// enum for the LLVM IntPredicate type
pub enum IntPredicate {
IntEQ = 32,
use super::{CodeGenModel, RelocMode, CodeGenOptLevel};
use super::debuginfo::*;
use libc::{c_char, c_int, c_longlong, c_ushort, c_uint, c_ulonglong,
- size_t};
+ size_t, uint64_t};
// Link to our native llvm bindings (things that we need to use the C++ api
// for) and because llvm is written in C++ we need to link against libstdc++
pub fn LLVMSetFunctionCallConv(Fn: ValueRef, CC: c_uint);
pub fn LLVMGetGC(Fn: ValueRef) -> *c_char;
pub fn LLVMSetGC(Fn: ValueRef, Name: *c_char);
- pub fn LLVMAddFunctionAttr(Fn: ValueRef, PA: c_uint);
- pub fn LLVMAddFunctionAttrString(Fn: ValueRef, Name: *c_char);
- pub fn LLVMRemoveFunctionAttrString(Fn: ValueRef, Name: *c_char);
+ pub fn LLVMAddFunctionAttribute(Fn: ValueRef, index: c_uint, PA: uint64_t);
+ pub fn LLVMAddFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *c_char);
+ pub fn LLVMRemoveFunctionAttrString(Fn: ValueRef, index: c_uint, Name: *c_char);
pub fn LLVMGetFunctionAttr(Fn: ValueRef) -> c_ulonglong;
- pub fn LLVMAddReturnAttribute(Fn: ValueRef, PA: c_uint);
- pub fn LLVMRemoveReturnAttribute(Fn: ValueRef, PA: c_uint);
-
- pub fn LLVMAddColdAttribute(Fn: ValueRef);
-
- pub fn LLVMRemoveFunctionAttr(Fn: ValueRef,
- PA: c_ulonglong,
- HighPA: c_ulonglong);
-
/* Operations on parameters */
pub fn LLVMCountParams(Fn: ValueRef) -> c_uint;
pub fn LLVMGetParams(Fn: ValueRef, Params: *ValueRef);
pub fn LLVMSetInstrParamAlignment(Instr: ValueRef,
index: c_uint,
align: c_uint);
+ pub fn LLVMAddCallSiteAttribute(Instr: ValueRef,
+ index: c_uint,
+ Val: uint64_t);
/* Operations on call instructions (only) */
pub fn LLVMIsTailCall(CallInst: ValueRef) -> Bool;
pub fn SetFunctionAttribute(fn_: ValueRef, attr: Attribute) {
unsafe {
- llvm::LLVMAddFunctionAttr(fn_, attr as c_uint)
+ llvm::LLVMAddFunctionAttribute(fn_, FunctionIndex as c_uint, attr as uint64_t)
}
}
/* Memory-managed object interface to type handles. */
use util::nodemap::NodeMap;
use arena::TypedArena;
-use libc::c_uint;
+use libc::{c_uint, uint64_t};
use std::c_str::ToCStr;
use std::cell::{Cell, RefCell};
use std::rc::Rc;
// only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv,
ty: Type, output: ty::t) -> ValueRef {
+
let llfn: ValueRef = name.with_c_str(|buf| {
unsafe {
llvm::LLVMGetOrInsertFunction(llmod, buf, ty.to_ref())
// functions returning bottom may unwind, but can never return normally
ty::ty_bot => {
unsafe {
- llvm::LLVMAddFunctionAttr(llfn, lib::llvm::NoReturnAttribute as c_uint)
- }
- }
- // `~` pointer return values never alias because ownership is transferred
- ty::ty_uniq(..) // | ty::ty_trait(_, _, ty::UniqTraitStore, _, _)
- => {
- unsafe {
- llvm::LLVMAddReturnAttribute(llfn, lib::llvm::NoAliasAttribute as c_uint);
+ llvm::LLVMAddFunctionAttribute(llfn,
+ lib::llvm::FunctionIndex as c_uint,
+ lib::llvm::NoReturnAttribute as uint64_t)
}
}
_ => {}
}
// only use this for foreign function ABIs and glue, use `get_extern_rust_fn` for Rust functions
-pub fn get_extern_fn(externs: &mut ExternMap,
- llmod: ModuleRef,
+pub fn get_extern_fn(ccx: &CrateContext,
+ externs: &mut ExternMap,
name: &str,
cc: lib::llvm::CallConv,
ty: Type,
Some(n) => return *n,
None => {}
}
- let f = decl_fn(llmod, name, cc, ty, output);
+ let f = decl_fn(ccx.llmod, name, cc, ty, output);
externs.insert(name.to_strbuf(), f);
f
}
-fn get_extern_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t,
- name: &str, did: ast::DefId) -> ValueRef {
+fn get_extern_rust_fn(ccx: &CrateContext, fn_ty: ty::t, name: &str, did: ast::DefId) -> ValueRef {
match ccx.externs.borrow().find_equiv(&name) {
Some(n) => return *n,
None => ()
}
- let f = decl_rust_fn(ccx, false, inputs, output, name);
+ let f = decl_rust_fn(ccx, fn_ty, name);
+
csearch::get_item_attrs(&ccx.sess().cstore, did, |meta_items| {
set_llvm_fn_attrs(meta_items.iter().map(|&x| attr::mk_attr_outer(x))
.collect::<Vec<_>>().as_slice(), f)
f
}
-pub fn decl_rust_fn(ccx: &CrateContext, has_env: bool,
- inputs: &[ty::t], output: ty::t,
- name: &str) -> ValueRef {
- use middle::ty::{BrAnon, ReLateBound};
-
- let llfty = type_of_rust_fn(ccx, has_env, inputs, output);
- let llfn = decl_cdecl_fn(ccx.llmod, name, llfty, output);
-
- let uses_outptr = type_of::return_uses_outptr(ccx, output);
- let offset = if uses_outptr { 1 } else { 0 };
- let offset = if has_env { offset + 1 } else { offset };
-
- for (i, &arg_ty) in inputs.iter().enumerate() {
- let llarg = unsafe { llvm::LLVMGetParam(llfn, (offset + i) as c_uint) };
- match ty::get(arg_ty).sty {
- // `~` pointer parameters never alias because ownership is transferred
- ty::ty_uniq(..) => {
- unsafe {
- llvm::LLVMAddAttribute(llarg, lib::llvm::NoAliasAttribute as c_uint);
- }
- }
- // `&mut` pointer parameters never alias other parameters, or mutable global data
- ty::ty_rptr(_, mt) if mt.mutbl == ast::MutMutable => {
- unsafe {
- llvm::LLVMAddAttribute(llarg, lib::llvm::NoAliasAttribute as c_uint);
- }
- }
- // When a reference in an argument has no named lifetime, it's impossible for that
- // reference to escape this function (returned or stored beyond the call by a closure).
- ty::ty_rptr(ReLateBound(_, BrAnon(_)), _) => {
- debug!("marking argument of {} as nocapture because of anonymous lifetime", name);
- unsafe {
- llvm::LLVMAddAttribute(llarg, lib::llvm::NoCaptureAttribute as c_uint);
- }
- }
- _ => {
- // For non-immediate arguments the callee gets its own copy of
- // the value on the stack, so there are no aliases
- if !type_is_immediate(ccx, arg_ty) {
- unsafe {
- llvm::LLVMAddAttribute(llarg, lib::llvm::NoAliasAttribute as c_uint);
- llvm::LLVMAddAttribute(llarg, lib::llvm::NoCaptureAttribute as c_uint);
- }
- }
- }
- }
- }
+pub fn decl_rust_fn(ccx: &CrateContext, fn_ty: ty::t, name: &str) -> ValueRef {
+ let (inputs, output, has_env) = match ty::get(fn_ty).sty {
+ ty::ty_bare_fn(ref f) => (f.sig.inputs.clone(), f.sig.output, false),
+ ty::ty_closure(ref f) => (f.sig.inputs.clone(), f.sig.output, true),
+ _ => fail!("expected closure or fn")
+ };
- // The out pointer will never alias with any other pointers, as the object only exists at a
- // language level after the call. It can also be tagged with SRet to indicate that it is
- // guaranteed to point to a usable block of memory for the type.
- if uses_outptr {
+ let llfty = type_of_rust_fn(ccx, has_env, inputs.as_slice(), output);
+ let llfn = decl_fn(ccx.llmod, name, lib::llvm::CCallConv, llfty, output);
+ let attrs = get_fn_llvm_attributes(ccx, fn_ty);
+ for &(idx, attr) in attrs.iter() {
unsafe {
- let outptr = llvm::LLVMGetParam(llfn, 0);
- llvm::LLVMAddAttribute(outptr, lib::llvm::StructRetAttribute as c_uint);
- llvm::LLVMAddAttribute(outptr, lib::llvm::NoAliasAttribute as c_uint);
+ llvm::LLVMAddFunctionAttribute(llfn, idx as c_uint, attr);
}
}
llfn
}
-pub fn decl_internal_rust_fn(ccx: &CrateContext, has_env: bool,
- inputs: &[ty::t], output: ty::t,
- name: &str) -> ValueRef {
- let llfn = decl_rust_fn(ccx, has_env, inputs, output, name);
+pub fn decl_internal_rust_fn(ccx: &CrateContext, fn_ty: ty::t, name: &str) -> ValueRef {
+ let llfn = decl_rust_fn(ccx, fn_ty, name);
lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
llfn
}
}
if contains_name(attrs, "cold") {
- unsafe { llvm::LLVMAddColdAttribute(llfn) }
+ unsafe {
+ llvm::LLVMAddFunctionAttribute(llfn,
+ lib::llvm::FunctionIndex as c_uint,
+ lib::llvm::ColdAttribute as uint64_t)
+ }
}
}
pub fn set_split_stack(f: ValueRef) {
"split-stack".with_c_str(|buf| {
- unsafe { llvm::LLVMAddFunctionAttrString(f, buf); }
+ unsafe { llvm::LLVMAddFunctionAttrString(f, lib::llvm::FunctionIndex as c_uint, buf); }
})
}
pub fn unset_split_stack(f: ValueRef) {
"split-stack".with_c_str(|buf| {
- unsafe { llvm::LLVMRemoveFunctionAttrString(f, buf); }
+ unsafe { llvm::LLVMRemoveFunctionAttrString(f, lib::llvm::FunctionIndex as c_uint, buf); }
})
}
pub fn get_res_dtor(ccx: &CrateContext,
did: ast::DefId,
+ t: ty::t,
parent_id: ast::DefId,
substs: &ty::substs)
-> ValueRef {
let class_ty = ty::subst(tcx, substs,
ty::lookup_item_type(tcx, parent_id).ty);
let llty = type_of_dtor(ccx, class_ty);
-
- get_extern_fn(&mut *ccx.externs.borrow_mut(),
- ccx.llmod,
+ let dtor_ty = ty::mk_ctor_fn(ccx.tcx(), ast::DUMMY_NODE_ID,
+ [glue::get_drop_glue_type(ccx, t)], ty::mk_nil());
+ get_extern_fn(ccx,
+ &mut *ccx.externs.borrow_mut(),
name.as_slice(),
lib::llvm::CCallConv,
llty,
- ty::mk_nil())
+ dtor_ty)
}
}
match fn_ty.abi.for_target(ccx.sess().targ_cfg.os,
ccx.sess().targ_cfg.arch) {
Some(Rust) | Some(RustIntrinsic) => {
- get_extern_rust_fn(ccx,
- fn_ty.sig.inputs.as_slice(),
- fn_ty.sig.output,
- name.as_slice(),
- did)
+ get_extern_rust_fn(ccx, t, name.as_slice(), did)
}
Some(..) | None => {
foreign::register_foreign_item_fn(ccx, fn_ty.abi, t,
}
}
}
- ty::ty_closure(ref f) => {
- get_extern_rust_fn(ccx,
- f.sig.inputs.as_slice(),
- f.sig.output,
- name.as_slice(),
- did)
+ ty::ty_closure(_) => {
+ get_extern_rust_fn(ccx, t, name.as_slice(), did)
}
_ => {
let llty = type_of(ccx, t);
bcx: &'a Block<'a>,
llfn: ValueRef,
llargs: Vec<ValueRef> ,
- attributes: &[(uint, lib::llvm::Attribute)],
+ fn_ty: ty::t,
call_info: Option<NodeInfo>)
-> (ValueRef, &'a Block<'a>) {
let _icx = push_ctxt("invoke_");
return (C_null(Type::i8(bcx.ccx())), bcx);
}
+ let attributes = get_fn_llvm_attributes(bcx.ccx(), fn_ty);
+
match bcx.opt_node_id {
None => {
debug!("invoke at ???");
llargs.as_slice(),
normal_bcx.llbb,
landing_pad,
- attributes);
+ attributes.as_slice());
return (llresult, normal_bcx);
} else {
debug!("calling {} at {}", llfn, bcx.llbb);
None => debuginfo::clear_source_location(bcx.fcx)
};
- let llresult = Call(bcx, llfn, llargs.as_slice(), attributes);
+ let llresult = Call(bcx, llfn, llargs.as_slice(), attributes.as_slice());
return (llresult, bcx);
}
}
node_id: ast::NodeId,
node_type: ty::t)
-> ValueRef {
- let f = match ty::get(node_type).sty {
+ match ty::get(node_type).sty {
ty::ty_bare_fn(ref f) => {
assert!(f.abi == Rust || f.abi == RustIntrinsic);
- f
}
_ => fail!("expected bare rust fn or an intrinsic")
};
- let llfn = decl_rust_fn(ccx,
- false,
- f.sig.inputs.as_slice(),
- f.sig.output,
- sym.as_slice());
+ let llfn = decl_rust_fn(ccx, node_type, sym.as_slice());
finish_register_fn(ccx, sp, sym, node_id, llfn);
llfn
}
+pub fn get_fn_llvm_attributes(ccx: &CrateContext, fn_ty: ty::t) -> Vec<(uint, u64)> {
+ use middle::ty::{BrAnon, ReLateBound};
+
+ let (fn_sig, has_env) = match ty::get(fn_ty).sty {
+ ty::ty_closure(ref f) => (f.sig.clone(), true),
+ ty::ty_bare_fn(ref f) => (f.sig.clone(), false),
+ _ => fail!("expected closure or function.")
+ };
+
+ // Since index 0 is the return value of the llvm func, we start
+ // at either 1 or 2 depending on whether there's an env slot or not
+ let mut first_arg_offset = if has_env { 2 } else { 1 };
+ let mut attrs = Vec::new();
+ let ret_ty = fn_sig.output;
+
+ // A function pointer is called without the declaration
+ // available, so we have to apply any attributes with ABI
+ // implications directly to the call instruction. Right now,
+ // the only attribute we need to worry about is `sret`.
+ if type_of::return_uses_outptr(ccx, ret_ty) {
+ attrs.push((1, lib::llvm::StructRetAttribute as u64));
+
+ // The outptr can be noalias and nocapture because it's entirely
+ // invisible to the program. We can also mark it as nonnull
+ attrs.push((1, lib::llvm::NoAliasAttribute as u64));
+ attrs.push((1, lib::llvm::NoCaptureAttribute as u64));
+ attrs.push((1, lib::llvm::NonNullAttribute as u64));
+
+ // Add one more since there's an outptr
+ first_arg_offset += 1;
+ } else {
+ // The `noalias` attribute on the return value is useful to a
+ // function ptr caller.
+ match ty::get(ret_ty).sty {
+ // `~` pointer return values never alias because ownership
+ // is transferred
+ ty::ty_uniq(_) => {
+ attrs.push((lib::llvm::ReturnIndex as uint, lib::llvm::NoAliasAttribute as u64));
+ }
+ _ => {}
+ }
+
+ // We can also mark the return value as `nonnull` in certain cases
+ match ty::get(ret_ty).sty {
+ // These are not really pointers but pairs, (pointer, len)
+ ty::ty_rptr(_, ty::mt { ty: it, .. }) |
+ ty::ty_rptr(_, ty::mt { ty: it, .. }) if match ty::get(it).sty {
+ ty::ty_str | ty::ty_vec(..) => true, _ => false
+ } => {}
+ ty::ty_uniq(_) | ty::ty_rptr(_, _) => {
+ attrs.push((lib::llvm::ReturnIndex as uint, lib::llvm::NonNullAttribute as u64));
+ }
+ _ => {}
+ }
+ }
+
+ for (idx, &t) in fn_sig.inputs.iter().enumerate().map(|(i, v)| (i + first_arg_offset, v)) {
+ match ty::get(t).sty {
+ // `~` pointer parameters never alias because ownership is transferred
+ ty::ty_uniq(_) => {
+ attrs.push((idx, lib::llvm::NoAliasAttribute as u64));
+ attrs.push((idx, lib::llvm::NonNullAttribute as u64));
+ }
+ // These are not really pointers but pairs, (pointer, len)
+ ty::ty_rptr(_, ty::mt { ty: it, .. }) |
+ ty::ty_rptr(_, ty::mt { ty: it, .. }) if match ty::get(it).sty {
+ ty::ty_str | ty::ty_vec(..) => true, _ => false
+ } => {}
+ // `&mut` pointer parameters never alias other parameters, or mutable global data
+ ty::ty_rptr(b, mt) if mt.mutbl == ast::MutMutable => {
+ attrs.push((idx, lib::llvm::NoAliasAttribute as u64));
+ attrs.push((idx, lib::llvm::NonNullAttribute as u64));
+ match b {
+ ReLateBound(_, BrAnon(_)) => {
+ attrs.push((idx, lib::llvm::NoCaptureAttribute as u64));
+ }
+ _ => {}
+ }
+ }
+ // When a reference in an argument has no named lifetime, it's impossible for that
+ // reference to escape this function (returned or stored beyond the call by a closure).
+ ty::ty_rptr(ReLateBound(_, BrAnon(_)), _) => {
+ attrs.push((idx, lib::llvm::NoCaptureAttribute as u64));
+ attrs.push((idx, lib::llvm::NonNullAttribute as u64));
+ }
+ // & pointer parameters are never null
+ ty::ty_rptr(_, _) => {
+ attrs.push((idx, lib::llvm::NonNullAttribute as u64));
+ }
+ _ => {
+ // For non-immediate arguments the callee gets its own copy of
+ // the value on the stack, so there are no aliases. It's also
+ // program-invisible so can't possibly capture
+ if !type_is_immediate(ccx, t) {
+ attrs.push((idx, lib::llvm::NoAliasAttribute as u64));
+ attrs.push((idx, lib::llvm::NoCaptureAttribute as u64));
+ }
+ }
+ }
+ }
+
+ attrs
+}
+
// only use this for foreign function ABIs and glue, use `register_fn` for Rust functions
pub fn register_fn_llvmty(ccx: &CrateContext,
sp: Span,
sym: StrBuf,
node_id: ast::NodeId,
cc: lib::llvm::CallConv,
- fn_ty: Type,
- output: ty::t) -> ValueRef {
+ llfty: Type) -> ValueRef {
debug!("register_fn_llvmty id={} sym={}", node_id, sym);
- let llfn = decl_fn(ccx.llmod, sym.as_slice(), cc, fn_ty, output);
+ let llfn = decl_fn(ccx.llmod, sym.as_slice(), cc, llfty, ty::mk_nil());
finish_register_fn(ccx, sp, sym, node_id, llfn);
llfn
}
args: &[ValueRef],
then: BasicBlockRef,
catch: BasicBlockRef,
- attributes: &[(uint, lib::llvm::Attribute)])
+ attributes: &[(uint, u64)])
-> ValueRef {
if cx.unreachable.get() {
return C_null(Type::i8(cx.ccx()));
}
pub fn Call(cx: &Block, fn_: ValueRef, args: &[ValueRef],
- attributes: &[(uint, lib::llvm::Attribute)]) -> ValueRef {
+ attributes: &[(uint, u64)]) -> ValueRef {
if cx.unreachable.get() { return _UndefReturn(cx, fn_); }
B(cx).call(fn_, args, attributes)
}
pub fn CallWithConv(cx: &Block, fn_: ValueRef, args: &[ValueRef], conv: CallConv,
- attributes: &[(uint, lib::llvm::Attribute)]) -> ValueRef {
+ attributes: &[(uint, u64)]) -> ValueRef {
if cx.unreachable.get() { return _UndefReturn(cx, fn_); }
B(cx).call_with_conv(fn_, args, conv, attributes)
}
args: &[ValueRef],
then: BasicBlockRef,
catch: BasicBlockRef,
- attributes: &[(uint, lib::llvm::Attribute)])
+ attributes: &[(uint, u64)])
-> ValueRef {
self.count_insn("invoke");
unsafe {
catch,
noname());
for &(idx, attr) in attributes.iter() {
- llvm::LLVMAddInstrAttribute(v, idx as c_uint, attr as c_uint);
+ llvm::LLVMAddCallSiteAttribute(v, idx as c_uint, attr);
}
v
}
}
pub fn call(&self, llfn: ValueRef, args: &[ValueRef],
- attributes: &[(uint, lib::llvm::Attribute)]) -> ValueRef {
+ attributes: &[(uint, u64)]) -> ValueRef {
self.count_insn("call");
debug!("Call {} with args ({})",
let v = llvm::LLVMBuildCall(self.llbuilder, llfn, args.as_ptr(),
args.len() as c_uint, noname());
for &(idx, attr) in attributes.iter() {
- llvm::LLVMAddInstrAttribute(v, idx as c_uint, attr as c_uint);
+ llvm::LLVMAddCallSiteAttribute(v, idx as c_uint, attr);
}
v
}
}
pub fn call_with_conv(&self, llfn: ValueRef, args: &[ValueRef],
- conv: CallConv, attributes: &[(uint, lib::llvm::Attribute)]) -> ValueRef {
+ conv: CallConv, attributes: &[(uint, u64)]) -> ValueRef {
self.count_insn("callwithconv");
let v = self.call(llfn, args, attributes);
lib::llvm::SetInstructionCallConv(v, conv);
use back::abi;
use driver::session;
-use lib::llvm::{ValueRef, NoAliasAttribute, StructRetAttribute, NoCaptureAttribute};
+use lib::llvm::ValueRef;
use lib::llvm::llvm;
use metadata::csearch;
use middle::trans::base;
llargs.push(opt_llretslot.unwrap());
}
- // start at 1, because index 0 is the return value of the llvm func
- let mut first_arg_offset = 1;
-
// Push the environment (or a trait object's self).
match (llenv, llself) {
(Some(llenv), None) => {
- first_arg_offset += 1;
llargs.push(llenv)
},
(None, Some(llself)) => llargs.push(llself),
fcx.pop_custom_cleanup_scope(arg_cleanup_scope);
- // A function pointer is called without the declaration
- // available, so we have to apply any attributes with ABI
- // implications directly to the call instruction. Right now,
- // the only attribute we need to worry about is `sret`.
- let mut attrs = Vec::new();
- if type_of::return_uses_outptr(ccx, ret_ty) {
- attrs.push((1, StructRetAttribute));
- // The outptr can be noalias and nocapture because it's entirely
- // invisible to the program.
- attrs.push((1, NoAliasAttribute));
- attrs.push((1, NoCaptureAttribute));
- first_arg_offset += 1;
- }
-
- // The `noalias` attribute on the return value is useful to a
- // function ptr caller.
- match ty::get(ret_ty).sty {
- // `~` pointer return values never alias because ownership
- // is transferred
- ty::ty_uniq(ty) => match ty::get(ty).sty {
- ty::ty_str => {}
- _ => attrs.push((0, NoAliasAttribute)),
- },
- _ => {}
- }
-
- debug!("trans_callee_inner: first_arg_offset={}", first_arg_offset);
-
- for (idx, &t) in ty::ty_fn_args(callee_ty).iter().enumerate()
- .map(|(i, v)| (i+first_arg_offset, v)) {
- use middle::ty::{BrAnon, ReLateBound};
- if !type_is_immediate(ccx, t) {
- // if it's not immediate, we have a program-invisible pointer,
- // which it can't possibly capture
- attrs.push((idx, NoCaptureAttribute));
- debug!("trans_callee_inner: argument {} nocapture because it's non-immediate", idx);
- continue;
- }
-
- let t_ = ty::get(t);
- match t_.sty {
- ty::ty_rptr(ReLateBound(_, BrAnon(_)), _) => {
- debug!("trans_callee_inner: argument {} nocapture because \
- of anonymous lifetime", idx);
- attrs.push((idx, NoCaptureAttribute));
- },
- _ => { }
- }
- }
-
// Invoke the actual rust fn and update bcx/llresult.
let (llret, b) = base::invoke(bcx,
llfn,
llargs,
- attrs.as_slice(),
+ callee_ty,
call_info);
bcx = b;
llresult = llret;
};
let ccx = bcx.ccx();
- let fty = node_id_type(bcx, id);
- let f = match ty::get(fty).sty {
- ty::ty_closure(ref f) => f,
- _ => fail!("expected closure")
- };
-
let tcx = bcx.tcx();
+ let fty = node_id_type(bcx, id);
let s = tcx.map.with_path(id, |path| {
mangle_internal_name_by_path_and_seq(path, "closure")
});
- let llfn = decl_internal_rust_fn(ccx,
- true,
- f.sig.inputs.as_slice(),
- f.sig.output,
- s.as_slice());
+ let llfn = decl_internal_rust_fn(ccx, fty, s.as_slice());
// set an inline hint for all closures
set_inline_hint(llfn);
mangle_internal_name_by_path_and_seq(path, "as_closure")
});
let llfn = if is_local {
- decl_internal_rust_fn(ccx,
- true,
- f.sig.inputs.as_slice(),
- f.sig.output,
- name.as_slice())
+ decl_internal_rust_fn(ccx, closure_ty, name.as_slice())
} else {
- decl_rust_fn(ccx,
- true,
- f.sig.inputs.as_slice(),
- f.sig.output,
- name.as_slice())
+ decl_rust_fn(ccx, closure_ty, name.as_slice())
};
ccx.closure_bare_wrapper_cache.borrow_mut().insert(fn_ptr, llfn);
// Create the LLVM value for the C extern fn
let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
- let llfn = base::get_extern_fn(&mut *ccx.externs.borrow_mut(),
- ccx.llmod,
+ let llfn = base::get_extern_fn(ccx,
+ &mut *ccx.externs.borrow_mut(),
name,
cc,
llfn_ty,
- tys.fn_sig.output);
+ fty);
add_argument_attributes(&tys, llfn);
llfn
// A function pointer is called without the declaration available, so we have to apply
// any attributes with ABI implications directly to the call instruction. Right now, the
// only attribute we need to worry about is `sret`.
- let sret_attr = if fn_type.ret_ty.is_indirect() {
- Some((1, StructRetAttribute))
- } else {
- None
+ let mut attrs = Vec::new();
+ if fn_type.ret_ty.is_indirect() {
+ attrs.push((1, lib::llvm::StructRetAttribute as u64));
+
+ // The outptr can be noalias and nocapture because it's entirely
+ // invisible to the program. We can also mark it as nonnull
+ attrs.push((1, lib::llvm::NoAliasAttribute as u64));
+ attrs.push((1, lib::llvm::NoCaptureAttribute as u64));
+ attrs.push((1, lib::llvm::NonNullAttribute as u64));
};
- let attrs = sret_attr.as_slice();
let llforeign_retval = CallWithConv(bcx,
llfn,
llargs_foreign.as_slice(),
cc,
- attrs);
+ attrs.as_slice());
// If the function we just called does not use an outpointer,
// store the result into the rust outpointer. Cast the outpointer
let tys = foreign_types_for_id(ccx, node_id);
let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
let t = ty::node_id_to_type(ccx.tcx(), node_id);
- let (cconv, output) = match ty::get(t).sty {
+ let cconv = match ty::get(t).sty {
ty::ty_bare_fn(ref fn_ty) => {
let c = llvm_calling_convention(ccx, fn_ty.abi);
- (c.unwrap_or(lib::llvm::CCallConv), fn_ty.sig.output)
+ c.unwrap_or(lib::llvm::CCallConv)
}
_ => fail!("expected bare fn in register_rust_fn_with_foreign_abi")
};
- let llfn = base::register_fn_llvmty(ccx, sp, sym, node_id, cconv, llfn_ty, output);
+ let llfn = base::register_fn_llvmty(ccx, sp, sym, node_id, cconv, llfn_ty);
add_argument_attributes(&tys, llfn);
debug!("register_rust_fn_with_foreign_abi(node_id={:?}, llfn_ty={}, llfn={})",
node_id, ccx.tn.type_to_str(llfn_ty), ccx.tn.val_to_str(llfn));
let llrustfn = build_rust_fn(ccx, decl, body, attrs, id);
// Build up the foreign wrapper (`foo` above).
- return build_wrap_fn(ccx, llrustfn, llwrapfn, &tys);
+ return build_wrap_fn(ccx, llrustfn, llwrapfn, &tys, id);
}
fn build_rust_fn(ccx: &CrateContext,
// Compute the type that the function would have if it were just a
// normal Rust function. This will be the type of the wrappee fn.
- let f = match ty::get(t).sty {
+ match ty::get(t).sty {
ty::ty_bare_fn(ref f) => {
assert!(f.abi != Rust && f.abi != RustIntrinsic);
- f
}
_ => {
ccx.sess().bug(format!("build_rust_fn: extern fn {} has ty {}, \
ccx.tcx.map.path_to_str(id),
id, t.repr(tcx));
- let llfn = base::decl_internal_rust_fn(ccx,
- false,
- f.sig.inputs.as_slice(),
- f.sig.output,
- ps.as_slice());
+ let llfn = base::decl_internal_rust_fn(ccx, t, ps.as_slice());
base::set_llvm_fn_attrs(attrs, llfn);
base::trans_fn(ccx, decl, body, llfn, None, id, []);
llfn
unsafe fn build_wrap_fn(ccx: &CrateContext,
llrustfn: ValueRef,
llwrapfn: ValueRef,
- tys: &ForeignTypes) {
+ tys: &ForeignTypes,
+ id: ast::NodeId) {
let _icx = push_ctxt(
"foreign::trans_rust_fn_with_foreign_abi::build_wrap_fn");
let tcx = ccx.tcx();
- debug!("build_wrap_fn(llrustfn={}, llwrapfn={})",
+ let t = ty::node_id_to_type(tcx, id);
+
+ debug!("build_wrap_fn(llrustfn={}, llwrapfn={}, t={})",
ccx.tn.val_to_str(llrustfn),
- ccx.tn.val_to_str(llwrapfn));
+ ccx.tn.val_to_str(llwrapfn),
+ t.repr(ccx.tcx()));
// Avoid all the Rust generation stuff and just generate raw
// LLVM here.
}
// Perform the call itself
- debug!("calling llrustfn = {}", ccx.tn.val_to_str(llrustfn));
+ debug!("calling llrustfn = {}, t = {}", ccx.tn.val_to_str(llrustfn), t.repr(ccx.tcx()));
let llrust_ret_val = llvm::LLVMBuildCall(builder, llrustfn, llrust_args.as_ptr(),
llrust_args.len() as c_uint, noname());
+ let attributes = base::get_fn_llvm_attributes(ccx, t);
+ for &(idx, attr) in attributes.iter() {
+ llvm::LLVMAddCallSiteAttribute(llrust_ret_val, idx as c_uint, attr);
+ }
+
// Get the return value where the foreign fn expects it.
let llforeign_ret_ty = match tys.fn_ty.ret_ty.cast {
Some(ty) => ty,
}
}
-fn get_drop_glue_type(ccx: &CrateContext, t: ty::t) -> ty::t {
+pub fn get_drop_glue_type(ccx: &CrateContext, t: ty::t) -> ty::t {
let tcx = ccx.tcx();
if !ty::type_needs_drop(tcx, t) {
return ty::mk_i8();
let repr = adt::represent_type(bcx.ccx(), t);
// Find and call the actual destructor
- let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did,
+ let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did, t,
class_did, substs);
// The second argument is the "self" argument for drop
fld.mt.ty);
}
- let (_, bcx) = invoke(bcx, dtor_addr, args, [], None);
+ let dtor_ty = ty::mk_ctor_fn(bcx.tcx(), ast::DUMMY_NODE_ID,
+ [get_drop_glue_type(bcx.ccx(), t)], ty::mk_nil());
+ let (_, bcx) = invoke(bcx, dtor_addr, args, dtor_ty, None);
bcx.fcx.pop_and_trans_custom_cleanup_scope(bcx, field_scope)
}
t,
format!("glue_{}", name).as_slice());
debug!("{} is for type {}", fn_nm, ppaux::ty_to_str(ccx.tcx(), t));
- let llfn = decl_cdecl_fn(ccx.llmod,
- fn_nm.as_slice(),
- llfnty,
- ty::mk_nil());
+ let llfn = decl_cdecl_fn(ccx.llmod, fn_nm.as_slice(), llfnty, ty::mk_nil());
note_unique_llvm_symbol(ccx, fn_nm);
return llfn;
}
}
};
- let f = match ty::get(mono_ty).sty {
- ty::ty_bare_fn(ref f) => {
- assert!(f.abi == abi::Rust || f.abi == abi::RustIntrinsic);
- f
- }
- _ => fail!("expected bare rust fn or an intrinsic")
- };
-
ccx.stats.n_monos.set(ccx.stats.n_monos.get() + 1);
let depth;
// This shouldn't need to option dance.
let mut hash_id = Some(hash_id);
let mk_lldecl = || {
- let lldecl = decl_internal_rust_fn(ccx,
- false,
- f.sig.inputs.as_slice(),
- f.sig.output,
- s.as_slice());
+ let lldecl = decl_internal_rust_fn(ccx, mono_ty, s.as_slice());
ccx.monomorphized.borrow_mut().insert(hash_id.take_unwrap(), lldecl);
lldecl
};
let sym = mangle_internal_name_by_path_and_seq(
ast_map::Values([].iter()).chain(None), "get_disr");
+ let fn_ty = ty::mk_ctor_fn(&ccx.tcx, ast::DUMMY_NODE_ID,
+ [opaqueptrty], ty::mk_u64());
let llfdecl = decl_internal_rust_fn(ccx,
- false,
- [opaqueptrty],
- ty::mk_u64(),
+ fn_ty,
sym.as_slice());
let arena = TypedArena::new();
let fcx = new_fn_ctxt(ccx, llfdecl, -1, false,
}
pub fn bound_region_ptr_to_str(cx: &ctxt, br: BoundRegion) -> StrBuf {
- bound_region_to_str(cx, "&", true, br)
+ bound_region_to_str(cx, "", false, br)
}
pub fn bound_region_to_str(cx: &ctxt,
y: 2,
};
b.iter(|| {
- assert_eq!(hash(&compound), 15783192367317361799);
+ assert_eq!(hash(&compound), 12506681940457338191);
})
}
}
use io::net::unix::*;
use io::timer::*;
use io::process::*;
- use unstable::running_on_valgrind;
+ use rt::running_on_valgrind;
use str;
fn f() $b
//! modules deal with unsafe pointers and memory manipulation.
//! [`kinds`](../core/kinds/index.html) defines the special built-in traits,
//! and [`raw`](../core/raw/index.html) the runtime representation of Rust types.
-//! These are some of the lowest-level building blocks of Rust
-//! abstractions.
+//! These are some of the lowest-level building blocks in Rust.
//!
//! ## Math on primitive types and math traits
//!
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/")]
#![feature(macro_rules, globs, asm, managed_boxes, thread_local, link_args,
- simd, linkage, default_type_params, phase, concat_idents, quad_precision_float)]
+ linkage, default_type_params, phase, concat_idents, quad_precision_float)]
// Don't link to std. We are std.
#![no_std]
#[cfg(not(test))] pub use core::cmp;
pub use core::container;
pub use core::default;
+pub use core::finally;
pub use core::intrinsics;
pub use core::iter;
#[cfg(not(test))] pub use core::kinds;
#[cfg(not(test))] pub use core::ops;
pub use core::ptr;
pub use core::raw;
+pub use core::simd;
pub use core::tuple;
#[cfg(not(test))] pub use core::ty;
pub use core::result;
mod tests {
use prelude::*;
use super::*;
- use unstable::finally::Finally;
+ use finally::Finally;
#[test]
fn smoke_test() {
pub use alloc::{heap, libc_heap};
+// Used by I/O tests
+#[experimental]
+pub use self::util::running_on_valgrind;
+
// FIXME: these probably shouldn't be public...
#[doc(hidden)]
pub mod shouldnt_be_public {
use str::SendStr;
use sync::atomics::{AtomicUint, SeqCst};
use task::{TaskResult, TaskOpts};
-use unstable::finally::Finally;
+use finally::Finally;
/// The Task struct represents all state associated with a rust
/// task. There are at this point two primary "subtypes" of task,
use io;
use iter::Iterator;
use libc;
+use libc::uintptr_t;
use option::{Some, None, Option};
use os;
use result::Ok;
use str::{Str, StrSlice};
-use unstable::running_on_valgrind;
use slice::ImmutableVector;
// Indicates whether we should perform expensive sanity checks, including rtassert!
unsafe { intrinsics::abort() }
}
}
+
+/// Dynamically inquire about whether we're running under V.
+/// You should usually not use this unless your test definitely
+/// can't run correctly un-altered. Valgrind is there to help
+/// you notice weirdness in normal, un-doctored code paths!
+pub fn running_on_valgrind() -> bool {
+ unsafe { rust_running_on_valgrind() != 0 }
+}
+
+extern {
+ fn rust_running_on_valgrind() -> uintptr_t;
+}
use ptr::RawPtr;
use ptr;
use rt::heap::{allocate, deallocate};
-use unstable::finally::try_finally;
+use finally::try_finally;
use vec::Vec;
pub use core::slice::{ref_slice, mut_ref_slice, Splits, Windows};
#![doc(hidden)]
-use libc::uintptr_t;
-
-pub use core::finally;
-
pub mod dynamic_lib;
-pub mod simd;
pub mod sync;
pub mod mutex;
-/// Dynamically inquire about whether we're running under V.
-/// You should usually not use this unless your test definitely
-/// can't run correctly un-altered. Valgrind is there to help
-/// you notice weirdness in normal, un-doctored code paths!
-pub fn running_on_valgrind() -> bool {
- unsafe { rust_running_on_valgrind() != 0 }
-}
-
-extern {
- fn rust_running_on_valgrind() -> uintptr_t;
-}
+++ /dev/null
-// Copyright 2013 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! SIMD vectors
-
-#![allow(non_camel_case_types)]
-
-#[experimental]
-#[simd]
-pub struct i8x16(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);
-
-#[experimental]
-#[simd]
-pub struct i16x8(pub i16, pub i16, pub i16, pub i16,
- pub i16, pub i16, pub i16, pub i16);
-
-#[experimental]
-#[simd]
-pub struct i32x4(pub i32, pub i32, pub i32, pub i32);
-
-#[experimental]
-#[simd]
-pub struct i64x2(pub i64, pub i64);
-
-#[experimental]
-#[simd]
-pub struct u8x16(pub u8, pub u8, pub u8, pub u8,
- pub u8, pub u8, pub u8, pub u8,
- pub u8, pub u8, pub u8, pub u8,
- pub u8, pub u8, pub u8, pub u8);
-
-#[experimental]
-#[simd]
-pub struct u16x8(pub u16, pub u16, pub u16, pub u16,
- pub u16, pub u16, pub u16, pub u16);
-
-#[experimental]
-#[simd]
-pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
-
-#[experimental]
-#[simd]
-pub struct u64x2(pub u64, pub u64);
-
-#[experimental]
-#[simd]
-pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
-
-#[experimental]
-#[simd]
-pub struct f64x2(pub f64, pub f64);
use std::kinds::marker;
use std::mem;
use std::sync::atomics;
-use std::unstable::finally::Finally;
+use std::finally::Finally;
use mutex;
-Subproject commit 4b4d0533b4f76cc3fbba31bd9e7ac02e0c738b1d
+Subproject commit 0a894645cf120539876e9eb4eb0d7b572dfa9d14
#include "rustllvm.h"
#include "llvm/Support/CBindingWrapping.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/ObjectFile.h"
+#if LLVM_VERSION_MINOR >= 5
+#include "llvm/IR/CallSite.h"
+#else
+#include "llvm/Support/CallSite.h"
+#endif
+
//===----------------------------------------------------------------------===
//
// This file defines alternate interfaces to core functions that are more
return wrap(Type::getMetadataTy(*unwrap(C)));
}
-extern "C" void LLVMAddFunctionAttrString(LLVMValueRef fn, const char *Name) {
- unwrap<Function>(fn)->addFnAttr(Name);
+extern "C" void LLVMAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, uint64_t Val) {
+ CallSite Call = CallSite(unwrap<Instruction>(Instr));
+ AttrBuilder B;
+ B.addRawValue(Val);
+ Call.setAttributes(
+ Call.getAttributes().addAttributes(Call->getContext(), index,
+ AttributeSet::get(Call->getContext(),
+ index, B)));
+}
+
+extern "C" void LLVMAddFunctionAttribute(LLVMValueRef Fn, unsigned index, uint64_t Val) {
+ Function *A = unwrap<Function>(Fn);
+ AttrBuilder B;
+ B.addRawValue(Val);
+ A->addAttributes(index, AttributeSet::get(A->getContext(), index, B));
+}
+
+extern "C" void LLVMAddFunctionAttrString(LLVMValueRef Fn, unsigned index, const char *Name) {
+ Function *F = unwrap<Function>(Fn);
+ AttrBuilder B;
+ B.addAttribute(Name);
+ F->addAttributes(index, AttributeSet::get(F->getContext(), index, B));
}
-extern "C" void LLVMRemoveFunctionAttrString(LLVMValueRef fn, const char *Name) {
+extern "C" void LLVMRemoveFunctionAttrString(LLVMValueRef fn, unsigned index, const char *Name) {
Function *f = unwrap<Function>(fn);
LLVMContext &C = f->getContext();
AttrBuilder B;
B.addAttribute(Name);
- AttributeSet to_remove = AttributeSet::get(C, AttributeSet::FunctionIndex, B);
+ AttributeSet to_remove = AttributeSet::get(C, index, B);
AttributeSet attrs = f->getAttributes();
f->setAttributes(attrs.removeAttributes(f->getContext(),
- AttributeSet::FunctionIndex,
+ index,
to_remove));
}
-extern "C" void LLVMAddReturnAttribute(LLVMValueRef Fn, LLVMAttribute PA) {
- Function *A = unwrap<Function>(Fn);
- AttrBuilder B(PA);
- A->addAttributes(AttributeSet::ReturnIndex,
- AttributeSet::get(A->getContext(), AttributeSet::ReturnIndex, B));
-}
-
-extern "C" void LLVMRemoveReturnAttribute(LLVMValueRef Fn, LLVMAttribute PA) {
- Function *A = unwrap<Function>(Fn);
- AttrBuilder B(PA);
- A->removeAttributes(AttributeSet::ReturnIndex,
- AttributeSet::get(A->getContext(), AttributeSet::ReturnIndex, B));
-}
-
-#if LLVM_VERSION_MINOR >= 5
-extern "C" void LLVMAddColdAttribute(LLVMValueRef Fn) {
- Function *A = unwrap<Function>(Fn);
- A->addAttribute(AttributeSet::FunctionIndex, Attribute::Cold);
-}
-#else
-extern "C" void LLVMAddColdAttribute(LLVMValueRef Fn) {}
-#endif
-
extern "C" LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B,
LLVMValueRef source,
const char* Name,
# If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
# The actual contents of this file do not matter, but to trigger a change on the
# build bots then the contents should be changed so git updates the mtime.
-2014-04-14
+2014-05-20
use std::io;
use std::os;
-use std::unstable::simd::f64x2;
+use std::simd::f64x2;
use sync::Future;
use sync::Arc;
--- /dev/null
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn test<'x>(x: &'x int) { //~ NOTE the lifetime 'x as defined
+ drop::< <'z>|&'z int| -> &'z int>(|z| {
+ //~^ ERROR mismatched types
+ //~^^ ERROR cannot infer an appropriate lifetime
+ x
+ });
+}
+
+fn main() {}
#![allow(experimental)]
-use std::unstable::simd::f32x4;
+use std::simd::f32x4;
fn main() {
let _ = f32x4(0.0, 0.0, 0.0, 0.0) == f32x4(0.0, 0.0, 0.0, 0.0);
- //~^ ERROR binary comparison operation `==` not supported for floating point SIMD vector `std::unstable::simd::f32x4`
+ //~^ ERROR binary comparison operation `==` not supported for floating point SIMD vector `core::simd::f32x4`
let _ = f32x4(0.0, 0.0, 0.0, 0.0) != f32x4(0.0, 0.0, 0.0, 0.0);
- //~^ ERROR binary comparison operation `!=` not supported for floating point SIMD vector `std::unstable::simd::f32x4`
+ //~^ ERROR binary comparison operation `!=` not supported for floating point SIMD vector `core::simd::f32x4`
let _ = f32x4(0.0, 0.0, 0.0, 0.0) < f32x4(0.0, 0.0, 0.0, 0.0);
- //~^ ERROR binary comparison operation `<` not supported for floating point SIMD vector `std::unstable::simd::f32x4`
+ //~^ ERROR binary comparison operation `<` not supported for floating point SIMD vector `core::simd::f32x4`
let _ = f32x4(0.0, 0.0, 0.0, 0.0) <= f32x4(0.0, 0.0, 0.0, 0.0);
- //~^ ERROR binary comparison operation `<=` not supported for floating point SIMD vector `std::unstable::simd::f32x4`
+ //~^ ERROR binary comparison operation `<=` not supported for floating point SIMD vector `core::simd::f32x4`
let _ = f32x4(0.0, 0.0, 0.0, 0.0) >= f32x4(0.0, 0.0, 0.0, 0.0);
- //~^ ERROR binary comparison operation `>=` not supported for floating point SIMD vector `std::unstable::simd::f32x4`
+ //~^ ERROR binary comparison operation `>=` not supported for floating point SIMD vector `core::simd::f32x4`
let _ = f32x4(0.0, 0.0, 0.0, 0.0) > f32x4(0.0, 0.0, 0.0, 0.0);
- //~^ ERROR binary comparison operation `>` not supported for floating point SIMD vector `std::unstable::simd::f32x4`
+ //~^ ERROR binary comparison operation `>` not supported for floating point SIMD vector `core::simd::f32x4`
}
#![deny(experimental)]
-use std::unstable::simd;
+use std::simd;
fn main() {
let _ = simd::i64x2(0, 0); //~ ERROR: experimental
#![allow(experimental)]
#![allow(unused_variable)]
-use std::unstable::simd::{i8x16, i16x8,i32x4,i64x2,u8x16,u16x8,u32x4,u64x2,f32x4,f64x2};
+use std::simd::{i8x16, i16x8,i32x4,i64x2,u8x16,u16x8,u32x4,u64x2,f32x4,f64x2};
fn main() {
use std::os;
use std::io::process::Command;
-use std::unstable::finally::Finally;
+use std::finally::Finally;
use std::str;
#[start]
#![allow(experimental)]
-use std::unstable::simd::{i32x4, f32x4, u32x4};
+use std::simd::{i32x4, f32x4, u32x4};
fn eq_u32x4(u32x4(x0, x1, x2, x3): u32x4, u32x4(y0, y1, y2, y3): u32x4) -> bool {
(x0 == y0) && (x1 == y1) && (x2 == y2) && (x3 == y3)
#![feature(simd)]
pub fn main() {
- let _o = None::<std::unstable::simd::i32x4>;
+ let _o = None::<std::simd::i32x4>;
}