1
Fork 0

auto merge of #5962 : pcwalton/rust/shootout, r=pcwalton

r? @brson
This commit is contained in:
bors 2013-04-19 19:24:52 -07:00
commit 8b3c09a103
61 changed files with 3052 additions and 1122 deletions

View file

@ -95,9 +95,10 @@ pub use str::{StrSlice};
pub use container::{Container, Mutable};
pub use vec::{CopyableVector, ImmutableVector};
pub use vec::{ImmutableEqVector, ImmutableCopyableVector};
pub use vec::{OwnedVector, OwnedCopyableVector};
pub use vec::{OwnedVector, OwnedCopyableVector, MutableVector};
pub use iter::{BaseIter, ExtendedIter, EqIter, CopyableIter};
pub use iter::{CopyableOrderedIter, CopyableNonstrictIter, Times};
pub use iter::{ExtendedMutableIter};
pub use num::{Num, NumCast};
pub use ptr::Ptr;

View file

@ -16,7 +16,6 @@
use container::{Container, Mutable, Map, Set};
use cmp::{Eq, Equiv};
use hash::Hash;
use to_bytes::IterBytes;
use iter::BaseIter;
use hash::Hash;
use iter;
@ -72,7 +71,7 @@ fn linear_map_with_capacity_and_keys<K:Eq + Hash,V>(
}
}
priv impl<K:Hash + IterBytes + Eq,V> HashMap<K, V> {
priv impl<K:Hash + Eq,V> HashMap<K, V> {
#[inline(always)]
fn to_bucket(&self, h: uint) -> uint {
// A good hash function with entropy spread over all of the
@ -111,9 +110,8 @@ priv impl<K:Hash + IterBytes + Eq,V> HashMap<K, V> {
}
#[inline(always)]
fn bucket_for_key_equiv<Q:Hash + IterBytes + Equiv<K>>(&self,
k: &Q)
-> SearchResult {
fn bucket_for_key_equiv<Q:Hash + Equiv<K>>(&self, k: &Q)
-> SearchResult {
let hash = k.hash_keyed(self.k0, self.k1) as uint;
self.bucket_for_key_with_hash_equiv(hash, k)
}
@ -303,7 +301,7 @@ priv impl<K:Hash + IterBytes + Eq,V> HashMap<K, V> {
}
}
impl<K:Hash + IterBytes + Eq,V> Container for HashMap<K, V> {
impl<K:Hash + Eq,V> Container for HashMap<K, V> {
/// Return the number of elements in the map
fn len(&const self) -> uint { self.size }
@ -311,7 +309,7 @@ impl<K:Hash + IterBytes + Eq,V> Container for HashMap<K, V> {
fn is_empty(&const self) -> bool { self.len() == 0 }
}
impl<K:Hash + IterBytes + Eq,V> Mutable for HashMap<K, V> {
impl<K:Hash + Eq,V> Mutable for HashMap<K, V> {
/// Clear the map, removing all key-value pairs.
fn clear(&mut self) {
for uint::range(0, self.buckets.len()) |idx| {
@ -321,7 +319,7 @@ impl<K:Hash + IterBytes + Eq,V> Mutable for HashMap<K, V> {
}
}
impl<K:Hash + IterBytes + Eq,V> Map<K, V> for HashMap<K, V> {
impl<K:Hash + Eq,V> Map<K, V> for HashMap<K, V> {
/// Return true if the map contains a value for the specified key
fn contains_key(&self, k: &K) -> bool {
match self.bucket_for_key(k) {
@ -458,7 +456,7 @@ impl<K:Hash + IterBytes + Eq,V> Map<K, V> for HashMap<K, V> {
}
}
pub impl<K: Hash + IterBytes + Eq, V> HashMap<K, V> {
pub impl<K: Hash + Eq, V> HashMap<K, V> {
/// Create an empty HashMap
fn new() -> HashMap<K, V> {
HashMap::with_capacity(INITIAL_CAPACITY)
@ -669,8 +667,7 @@ pub impl<K: Hash + IterBytes + Eq, V> HashMap<K, V> {
/// Return true if the map contains a value for the specified key,
/// using equivalence
fn contains_key_equiv<Q:Hash + IterBytes + Equiv<K>>(&self, key: &Q)
-> bool {
fn contains_key_equiv<Q:Hash + Equiv<K>>(&self, key: &Q) -> bool {
match self.bucket_for_key_equiv(key) {
FoundEntry(_) => {true}
TableFull | FoundHole(_) => {false}
@ -680,8 +677,7 @@ pub impl<K: Hash + IterBytes + Eq, V> HashMap<K, V> {
/// Return the value corresponding to the key in the map, using
/// equivalence
#[cfg(stage0)]
fn find_equiv<Q:Hash + IterBytes + Equiv<K>>(&self, k: &Q)
-> Option<&'self V> {
fn find_equiv<Q:Hash + Equiv<K>>(&self, k: &Q) -> Option<&'self V> {
match self.bucket_for_key_equiv(k) {
FoundEntry(idx) => Some(self.value_for_bucket(idx)),
TableFull | FoundHole(_) => None,
@ -693,9 +689,7 @@ pub impl<K: Hash + IterBytes + Eq, V> HashMap<K, V> {
#[cfg(stage1)]
#[cfg(stage2)]
#[cfg(stage3)]
fn find_equiv<'a, Q:Hash + IterBytes + Equiv<K>>(
&'a self, k: &Q) -> Option<&'a V>
{
fn find_equiv<'a, Q:Hash + Equiv<K>>(&'a self, k: &Q) -> Option<&'a V> {
match self.bucket_for_key_equiv(k) {
FoundEntry(idx) => Some(self.value_for_bucket(idx)),
TableFull | FoundHole(_) => None,
@ -703,7 +697,7 @@ pub impl<K: Hash + IterBytes + Eq, V> HashMap<K, V> {
}
}
impl<K:Hash + IterBytes + Eq,V:Eq> Eq for HashMap<K, V> {
impl<K:Hash + Eq,V:Eq> Eq for HashMap<K, V> {
fn eq(&self, other: &HashMap<K, V>) -> bool {
if self.len() != other.len() { return false; }
@ -724,18 +718,18 @@ pub struct HashSet<T> {
priv map: HashMap<T, ()>
}
impl<T:Hash + IterBytes + Eq> BaseIter<T> for HashSet<T> {
impl<T:Hash + Eq> BaseIter<T> for HashSet<T> {
/// Visit all values in order
fn each(&self, f: &fn(&T) -> bool) { self.map.each_key(f) }
fn size_hint(&self) -> Option<uint> { Some(self.len()) }
}
impl<T:Hash + IterBytes + Eq> Eq for HashSet<T> {
impl<T:Hash + Eq> Eq for HashSet<T> {
fn eq(&self, other: &HashSet<T>) -> bool { self.map == other.map }
fn ne(&self, other: &HashSet<T>) -> bool { self.map != other.map }
}
impl<T:Hash + IterBytes + Eq> Container for HashSet<T> {
impl<T:Hash + Eq> Container for HashSet<T> {
/// Return the number of elements in the set
fn len(&const self) -> uint { self.map.len() }
@ -743,12 +737,12 @@ impl<T:Hash + IterBytes + Eq> Container for HashSet<T> {
fn is_empty(&const self) -> bool { self.map.is_empty() }
}
impl<T:Hash + IterBytes + Eq> Mutable for HashSet<T> {
impl<T:Hash + Eq> Mutable for HashSet<T> {
/// Clear the set, removing all values.
fn clear(&mut self) { self.map.clear() }
}
impl<T:Hash + IterBytes + Eq> Set<T> for HashSet<T> {
impl<T:Hash + Eq> Set<T> for HashSet<T> {
/// Return true if the set contains a value
fn contains(&self, value: &T) -> bool { self.map.contains_key(value) }
@ -816,7 +810,7 @@ impl<T:Hash + IterBytes + Eq> Set<T> for HashSet<T> {
}
}
pub impl <T:Hash + IterBytes + Eq> HashSet<T> {
pub impl <T:Hash + Eq> HashSet<T> {
/// Create an empty HashSet
fn new() -> HashSet<T> {
HashSet::with_capacity(INITIAL_CAPACITY)

View file

@ -45,6 +45,10 @@ pub trait ExtendedIter<A> {
fn flat_map_to_vec<B,IB: BaseIter<B>>(&self, op: &fn(&A) -> IB) -> ~[B];
}
pub trait ExtendedMutableIter<A> {
fn eachi_mut(&mut self, blk: &fn(uint, &mut A) -> bool);
}
pub trait EqIter<A:Eq> {
fn contains(&self, x: &A) -> bool;
fn count(&self, x: &A) -> uint;

View file

@ -1097,9 +1097,12 @@ pub mod funcs {
unsafe fn setbuf(stream: *FILE, buf: *c_char);
// Omitted: printf and scanf variants.
unsafe fn fgetc(stream: *FILE) -> c_int;
#[fast_ffi]
unsafe fn fgets(buf: *mut c_char, n: c_int,
stream: *FILE) -> *c_char;
#[fast_ffi]
unsafe fn fputc(c: c_int, stream: *FILE) -> c_int;
#[fast_ffi]
unsafe fn fputs(s: *c_char, stream: *FILE) -> *c_char;
// Omitted: getc, getchar (might be macros).
@ -1109,8 +1112,10 @@ pub mod funcs {
// Omitted: putc, putchar (might be macros).
unsafe fn puts(s: *c_char) -> c_int;
unsafe fn ungetc(c: c_int, stream: *FILE) -> c_int;
#[fast_ffi]
unsafe fn fread(ptr: *mut c_void, size: size_t,
nobj: size_t, stream: *FILE) -> size_t;
#[fast_ffi]
unsafe fn fwrite(ptr: *c_void, size: size_t,
nobj: size_t, stream: *FILE) -> size_t;
unsafe fn fseek(stream: *FILE, offset: c_long,
@ -1144,9 +1149,13 @@ pub mod funcs {
-> c_long;
unsafe fn strtoul(s: *c_char, endp: **c_char, base: c_int)
-> c_ulong;
#[fast_ffi]
unsafe fn calloc(nobj: size_t, size: size_t) -> *c_void;
#[fast_ffi]
unsafe fn malloc(size: size_t) -> *c_void;
#[fast_ffi]
unsafe fn realloc(p: *c_void, size: size_t) -> *c_void;
#[fast_ffi]
unsafe fn free(p: *c_void);
unsafe fn abort() -> !;
unsafe fn exit(status: c_int) -> !;
@ -1257,6 +1266,7 @@ pub mod funcs {
unsafe fn pclose(stream: *FILE) -> c_int;
#[link_name = "_fdopen"]
#[fast_ffi]
unsafe fn fdopen(fd: c_int, mode: *c_char) -> *FILE;
#[link_name = "_fileno"]
@ -1340,6 +1350,7 @@ pub mod funcs {
textmode: c_int) -> c_int;
#[link_name = "_read"]
#[fast_ffi]
unsafe fn read(fd: c_int, buf: *mut c_void, count: c_uint)
-> c_int;
@ -1350,6 +1361,7 @@ pub mod funcs {
unsafe fn unlink(c: *c_char) -> c_int;
#[link_name = "_write"]
#[fast_ffi]
unsafe fn write(fd: c_int, buf: *c_void, count: c_uint)
-> c_int;
}
@ -1502,6 +1514,7 @@ pub mod funcs {
unsafe fn pathconf(path: *c_char, name: c_int) -> c_long;
unsafe fn pause() -> c_int;
unsafe fn pipe(fds: *mut c_int) -> c_int;
#[fast_ffi]
unsafe fn read(fd: c_int, buf: *mut c_void,
count: size_t) -> ssize_t;
unsafe fn rmdir(path: *c_char) -> c_int;
@ -1514,6 +1527,7 @@ pub mod funcs {
unsafe fn tcgetpgrp(fd: c_int) -> pid_t;
unsafe fn ttyname(fd: c_int) -> *c_char;
unsafe fn unlink(c: *c_char) -> c_int;
#[fast_ffi]
unsafe fn write(fd: c_int, buf: *c_void, count: size_t)
-> ssize_t;
}

View file

@ -503,4 +503,4 @@ mod tests {
fn test_range_step_zero_step() {
for range_step(0,10,0) |_i| {}
}
}
}

View file

@ -474,4 +474,4 @@ mod tests {
fn test_range_step_zero_step_down() {
for range_step(0,-10,0) |_i| {}
}
}
}

View file

@ -33,7 +33,7 @@ pub use container::{Container, Mutable, Map, Set};
pub use hash::Hash;
pub use iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter};
pub use iter::{CopyableIter, CopyableOrderedIter, CopyableNonstrictIter};
pub use iter::Times;
pub use iter::{Times, ExtendedMutableIter};
pub use num::{Num, NumCast};
pub use path::GenericPath;
pub use path::Path;
@ -46,7 +46,7 @@ pub use to_str::ToStr;
pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps};
pub use vec::{CopyableVector, ImmutableVector};
pub use vec::{ImmutableEqVector, ImmutableCopyableVector};
pub use vec::{OwnedVector, OwnedCopyableVector};
pub use vec::{OwnedVector, OwnedCopyableVector, MutableVector};
pub use io::{Reader, ReaderUtil, Writer, WriterUtil};
/* Reexported runtime types */

View file

@ -67,6 +67,15 @@ pub fn from_bytes_with_null<'a>(vv: &'a [u8]) -> &'a str {
return unsafe { raw::from_bytes_with_null(vv) };
}
pub fn from_bytes_slice<'a>(vector: &'a [u8]) -> &'a str {
unsafe {
assert!(is_utf8(vector));
let (ptr, len): (*u8, uint) = ::cast::transmute(vector);
let string: &'a str = ::cast::transmute((ptr, len + 1));
string
}
}
/// Copy a slice into a new unique str
pub fn from_slice(s: &str) -> ~str {
unsafe { raw::slice_bytes_owned(s, 0, len(s)) }
@ -421,6 +430,15 @@ pub fn byte_slice<T>(s: &str, f: &fn(v: &[u8]) -> T) -> T {
}
}
/// Work with the string as a byte slice, not including trailing null, without
/// a callback.
#[inline(always)]
pub fn byte_slice_no_callback<'a>(s: &'a str) -> &'a [u8] {
unsafe {
cast::transmute(s)
}
}
/// Convert a string to a unique vector of characters
pub fn to_chars(s: &str) -> ~[char] {
let mut buf = ~[];

View file

@ -35,6 +35,14 @@ pub mod rustrt {
#[rust_stack]
unsafe fn rust_upcall_free(ptr: *c_char);
#[fast_ffi]
unsafe fn rust_upcall_malloc_noswitch(td: *c_char,
size: uintptr_t)
-> *c_char;
#[fast_ffi]
unsafe fn rust_upcall_free_noswitch(ptr: *c_char);
}
}
@ -81,7 +89,7 @@ pub unsafe fn exchange_free(ptr: *c_char) {
#[lang="malloc"]
#[inline(always)]
pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char {
return rustrt::rust_upcall_malloc(td, size);
return rustrt::rust_upcall_malloc_noswitch(td, size);
}
// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
@ -90,7 +98,7 @@ pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char {
#[lang="free"]
#[inline(always)]
pub unsafe fn local_free(ptr: *c_char) {
rustrt::rust_upcall_free(ptr);
rustrt::rust_upcall_free_noswitch(ptr);
}
#[lang="borrow_as_imm"]

View file

@ -12,8 +12,9 @@
#[warn(non_camel_case_types)];
use container::{Container, Mutable};
use cast::transmute;
use cast;
use container::{Container, Mutable};
use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
use clone::Clone;
use iter::BaseIter;
@ -43,9 +44,11 @@ pub mod rustrt {
pub extern {
// These names are terrible. reserve_shared applies
// to ~[] and reserve_shared_actual applies to @[].
#[fast_ffi]
unsafe fn vec_reserve_shared(++t: *sys::TypeDesc,
++v: **raw::VecRepr,
++n: libc::size_t);
#[fast_ffi]
unsafe fn vec_reserve_shared_actual(++t: *sys::TypeDesc,
++v: **raw::VecRepr,
++n: libc::size_t);
@ -73,6 +76,7 @@ pub fn same_length<T, U>(xs: &const [T], ys: &const [U]) -> bool {
* * v - A vector
* * n - The number of elements to reserve space for
*/
#[inline]
pub fn reserve<T>(v: &mut ~[T], n: uint) {
// Only make the (slow) call into the runtime if we have to
use managed;
@ -1386,13 +1390,19 @@ pub fn each<'r,T>(v: &'r [T], f: &fn(&'r T) -> bool) {
/// to mutate the contents as you iterate.
#[inline(always)]
pub fn each_mut<'r,T>(v: &'r mut [T], f: &fn(elem: &'r mut T) -> bool) {
let mut i = 0;
let n = v.len();
while i < n {
if !f(&mut v[i]) {
return;
do vec::as_mut_buf(v) |p, n| {
let mut n = n;
let mut p = p;
while n > 0 {
unsafe {
let q: &'r mut T = cast::transmute_mut_region(&mut *p);
if !f(q) {
break;
}
p = p.offset(1);
}
n -= 1;
}
i += 1;
}
}
@ -1424,6 +1434,22 @@ pub fn eachi<'r,T>(v: &'r [T], f: &fn(uint, v: &'r T) -> bool) {
}
}
/**
* Iterates over a mutable vector's elements and indices
*
* Return true to continue, false to break.
*/
#[inline(always)]
pub fn eachi_mut<'r,T>(v: &'r mut [T], f: &fn(uint, v: &'r mut T) -> bool) {
let mut i = 0;
for each_mut(v) |p| {
if !f(i, p) {
return;
}
i += 1;
}
}
/**
* Iterates over a vector's elements in reverse
*
@ -1806,6 +1832,7 @@ pub trait ImmutableVector<T> {
fn alli(&self, f: &fn(uint, t: &T) -> bool) -> bool;
fn flat_map<U>(&self, f: &fn(t: &T) -> ~[U]) -> ~[U];
fn filter_mapped<U:Copy>(&self, f: &fn(t: &T) -> Option<U>) -> ~[U];
unsafe fn unsafe_ref(&self, index: uint) -> *T;
}
/// Extension methods for vectors
@ -1916,6 +1943,14 @@ impl<'self,T> ImmutableVector<T> for &'self [T] {
fn filter_mapped<U:Copy>(&self, f: &fn(t: &T) -> Option<U>) -> ~[U] {
filter_mapped(*self, f)
}
/// Returns a pointer to the element at the given index, without doing
/// bounds checking.
#[inline(always)]
unsafe fn unsafe_ref(&self, index: uint) -> *T {
let (ptr, _): (*T, uint) = transmute(*self);
ptr.offset(index)
}
}
#[cfg(stage1)]
@ -1941,6 +1976,7 @@ pub trait ImmutableVector<'self, T> {
fn alli(&self, f: &fn(uint, t: &T) -> bool) -> bool;
fn flat_map<U>(&self, f: &fn(t: &T) -> ~[U]) -> ~[U];
fn filter_mapped<U:Copy>(&self, f: &fn(t: &T) -> Option<U>) -> ~[U];
unsafe fn unsafe_ref(&self, index: uint) -> *T;
}
/// Extension methods for vectors
@ -2062,6 +2098,14 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
fn filter_mapped<U:Copy>(&self, f: &fn(t: &T) -> Option<U>) -> ~[U] {
filter_mapped(*self, f)
}
/// Returns a pointer to the element at the given index, without doing
/// bounds checking.
#[inline(always)]
unsafe fn unsafe_ref(&self, index: uint) -> *T {
let (ptr, _): (*T, uint) = transmute(*self);
ptr.offset(index)
}
}
pub trait ImmutableEqVector<T:Eq> {
@ -2113,6 +2157,7 @@ pub trait ImmutableCopyableVector<T> {
fn filtered(&self, f: &fn(&T) -> bool) -> ~[T];
fn rfind(&self, f: &fn(t: &T) -> bool) -> Option<T>;
fn partitioned(&self, f: &fn(&T) -> bool) -> (~[T], ~[T]);
unsafe fn unsafe_get(&self, elem: uint) -> T;
}
/// Extension methods for vectors
@ -2149,6 +2194,12 @@ impl<'self,T:Copy> ImmutableCopyableVector<T> for &'self [T] {
fn partitioned(&self, f: &fn(&T) -> bool) -> (~[T], ~[T]) {
partitioned(*self, f)
}
/// Returns the element at the given index, without doing bounds checking.
#[inline(always)]
unsafe fn unsafe_get(&self, index: uint) -> T {
*self.unsafe_ref(index)
}
}
pub trait OwnedVector<T> {
@ -2289,6 +2340,25 @@ impl<T:Eq> OwnedEqVector<T> for ~[T] {
}
}
pub trait MutableVector<T> {
unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T;
unsafe fn unsafe_set(&self, index: uint, val: T);
}
impl<'self,T> MutableVector<T> for &'self mut [T] {
#[inline(always)]
unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T {
let pair_ptr: &(*mut T, uint) = transmute(self);
let (ptr, _) = *pair_ptr;
ptr.offset(index)
}
#[inline(always)]
unsafe fn unsafe_set(&self, index: uint, val: T) {
*self.unsafe_mut_ref(index) = val;
}
}
/**
* Constructs a vector from an unsafe pointer to a buffer
*
@ -2652,6 +2722,13 @@ impl<'self,A> iter::ExtendedIter<A> for &'self [A] {
}
}
impl<'self,A> iter::ExtendedMutableIter<A> for &'self mut [A] {
#[inline(always)]
pub fn eachi_mut(&mut self, blk: &fn(uint, v: &mut A) -> bool) {
eachi_mut(*self, blk)
}
}
// FIXME(#4148): This should be redundant
impl<A> iter::ExtendedIter<A> for ~[A] {
pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) {

View file

@ -188,8 +188,10 @@ pub mod write {
return false;
}
pub fn run_passes(sess: Session, llmod: ModuleRef,
output_type: output_type, output: &Path) {
pub fn run_passes(sess: Session,
llmod: ModuleRef,
output_type: output_type,
output: &Path) {
unsafe {
let opts = sess.opts;
if sess.time_llvm_passes() { llvm::LLVMRustEnableTimePasses(); }

View file

@ -172,10 +172,13 @@ pub enum compile_upto {
// For continuing compilation after a parsed crate has been
// modified
pub fn compile_rest(sess: Session, cfg: ast::crate_cfg,
upto: compile_upto, outputs: Option<@OutputFilenames>,
#[fixed_stack_segment]
pub fn compile_rest(sess: Session,
cfg: ast::crate_cfg,
upto: compile_upto,
outputs: Option<@OutputFilenames>,
curr: Option<@ast::crate>)
-> (@ast::crate, Option<ty::ctxt>) {
-> (@ast::crate, Option<ty::ctxt>) {
let time_passes = sess.time_passes();
let mut crate = curr.get();

File diff suppressed because it is too large Load diff

View file

@ -37,7 +37,7 @@ use std::serialize::Decodable;
use syntax::ast_map;
use syntax::attr;
use syntax::diagnostic::span_handler;
use syntax::parse::token::{ident_interner, special_idents};
use syntax::parse::token::{StringRef, ident_interner, special_idents};
use syntax::print::pprust;
use syntax::{ast, ast_util};
use syntax::codemap;
@ -249,12 +249,7 @@ fn doc_transformed_self_ty(doc: ebml::Doc,
pub fn item_type(item_id: ast::def_id, item: ebml::Doc,
tcx: ty::ctxt, cdata: cmd) -> ty::t {
let t = doc_type(item, tcx, cdata);
if family_names_type(item_family(item)) {
ty::mk_with_id(tcx, t, item_id)
} else {
t
}
doc_type(item, tcx, cdata)
}
fn doc_trait_ref(doc: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ty::TraitRef {
@ -327,7 +322,13 @@ fn item_path(intr: @ident_interner, item_doc: ebml::Doc) -> ast_map::path {
fn item_name(intr: @ident_interner, item: ebml::Doc) -> ast::ident {
let name = reader::get_doc(item, tag_paths_data_name);
intr.intern(@str::from_bytes(reader::doc_data(name)))
do reader::with_doc_data(name) |data| {
let string = str::from_bytes_slice(data);
match intr.find_equiv(&StringRef(string)) {
None => intr.intern(@(string.to_owned())),
Some(val) => val,
}
}
}
fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num)

View file

@ -381,9 +381,9 @@ fn parse_ty(st: @mut PState, conv: conv_did) -> ty::t {
}
}
'"' => {
let def = parse_def(st, TypeWithId, conv);
let _ = parse_def(st, TypeWithId, conv);
let inner = parse_ty(st, conv);
ty::mk_with_id(st.tcx, inner, def)
inner
}
'B' => ty::mk_opaque_box(st.tcx),
'a' => {

View file

@ -78,19 +78,6 @@ pub fn enc_ty(w: @io::Writer, cx: @ctxt, t: ty::t) {
Some(a) => { w.write_str(*a.s); return; }
None => {
let pos = w.tell();
match ty::type_def_id(t) {
Some(def_id) => {
// Do not emit node ids that map to unexported names. Those
// are not helpful.
if def_id.crate != local_crate ||
(cx.reachable)(def_id.node) {
w.write_char('"');
w.write_str((cx.ds)(def_id));
w.write_char('|');
}
}
_ => {}
}
enc_sty(w, cx, /*bad*/copy ty::get(t).sty);
let end = w.tell();
let len = end - pos;

View file

@ -143,13 +143,17 @@ pub fn log_fn_time(ccx: @CrateContext, +name: ~str, start: time::Timespec,
ccx.stats.fn_times.push((name, elapsed));
}
pub fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv,
llty: TypeRef) -> ValueRef {
pub fn decl_fn(llmod: ModuleRef,
name: &str,
cc: lib::llvm::CallConv,
llty: TypeRef)
-> ValueRef {
let llfn: ValueRef = str::as_c_str(name, |buf| {
unsafe {
llvm::LLVMGetOrInsertFunction(llmod, buf, llty)
}
});
lib::llvm::SetFunctionCallConv(llfn, cc);
return llfn;
}
@ -406,24 +410,24 @@ pub fn set_optimize_for_size(f: ValueRef) {
unsafe {
llvm::LLVMAddFunctionAttr(f,
lib::llvm::OptimizeForSizeAttribute
as c_ulonglong,
0u as c_ulonglong);
as c_uint,
0);
}
}
pub fn set_no_inline(f: ValueRef) {
unsafe {
llvm::LLVMAddFunctionAttr(f,
lib::llvm::NoInlineAttribute as c_ulonglong,
0u as c_ulonglong);
lib::llvm::NoInlineAttribute as c_uint,
0);
}
}
pub fn set_no_unwind(f: ValueRef) {
unsafe {
llvm::LLVMAddFunctionAttr(f,
lib::llvm::NoUnwindAttribute as c_ulonglong,
0u as c_ulonglong);
lib::llvm::NoUnwindAttribute as c_uint,
0);
}
}
@ -432,15 +436,16 @@ pub fn set_no_unwind(f: ValueRef) {
pub fn set_uwtable(f: ValueRef) {
unsafe {
llvm::LLVMAddFunctionAttr(f,
lib::llvm::UWTableAttribute as c_ulonglong,
0u as c_ulonglong);
lib::llvm::UWTableAttribute as c_uint,
0);
}
}
pub fn set_inline_hint(f: ValueRef) {
unsafe {
llvm::LLVMAddFunctionAttr(f, lib::llvm::InlineHintAttribute
as c_ulonglong, 0u as c_ulonglong);
llvm::LLVMAddFunctionAttr(f,
lib::llvm::InlineHintAttribute as c_uint,
0);
}
}
@ -456,14 +461,15 @@ pub fn set_inline_hint_if_appr(attrs: &[ast::attribute],
pub fn set_always_inline(f: ValueRef) {
unsafe {
llvm::LLVMAddFunctionAttr(f, lib::llvm::AlwaysInlineAttribute
as c_ulonglong, 0u as c_ulonglong);
llvm::LLVMAddFunctionAttr(f,
lib::llvm::AlwaysInlineAttribute as c_uint,
0);
}
}
pub fn set_custom_stack_growth_fn(f: ValueRef) {
pub fn set_fixed_stack_segment(f: ValueRef) {
unsafe {
llvm::LLVMAddFunctionAttr(f, 0u as c_ulonglong, 1u as c_ulonglong);
llvm::LLVMAddFunctionAttr(f, 0, 1 << (39 - 32));
}
}
@ -483,17 +489,25 @@ pub fn note_unique_llvm_symbol(ccx: @CrateContext, sym: @~str) {
}
pub fn get_res_dtor(ccx: @CrateContext, did: ast::def_id,
parent_id: ast::def_id, substs: &[ty::t])
-> ValueRef {
pub fn get_res_dtor(ccx: @CrateContext,
did: ast::def_id,
parent_id: ast::def_id,
substs: &[ty::t])
-> ValueRef {
let _icx = ccx.insn_ctxt("trans_res_dtor");
if !substs.is_empty() {
let did = if did.crate != ast::local_crate {
inline::maybe_instantiate_inline(ccx, did, true)
} else { did };
} else {
did
};
assert!(did.crate == ast::local_crate);
let (val, _) =
monomorphize::monomorphic_fn(ccx, did, substs, None, None, None);
let (val, _) = monomorphize::monomorphic_fn(ccx,
did,
substs,
None,
None,
None);
val
} else if did.crate == ast::local_crate {
@ -501,11 +515,16 @@ pub fn get_res_dtor(ccx: @CrateContext, did: ast::def_id,
} else {
let tcx = ccx.tcx;
let name = csearch::get_symbol(ccx.sess.cstore, did);
let class_ty = ty::subst_tps(tcx, substs, None,
ty::lookup_item_type(tcx, parent_id).ty);
let class_ty = ty::subst_tps(tcx,
substs,
None,
ty::lookup_item_type(tcx, parent_id).ty);
let llty = type_of_dtor(ccx, class_ty);
let name = name.to_managed(); // :-(
get_extern_fn(ccx.externs, ccx.llmod, name, lib::llvm::CCallConv,
get_extern_fn(ccx.externs,
ccx.llmod,
name,
lib::llvm::CCallConv,
llty)
}
}
@ -809,9 +828,12 @@ pub fn trans_external_path(ccx: @CrateContext, did: ast::def_id, t: ty::t)
};
}
pub fn invoke(bcx: block, llfn: ValueRef, +llargs: ~[ValueRef]) -> block {
pub fn invoke(bcx: block, llfn: ValueRef, +llargs: ~[ValueRef])
-> (ValueRef, block) {
let _icx = bcx.insn_ctxt("invoke_");
if bcx.unreachable { return bcx; }
if bcx.unreachable {
return (C_null(T_i8()), bcx);
}
match bcx.node_info {
None => debug!("invoke at ???"),
@ -831,8 +853,12 @@ pub fn invoke(bcx: block, llfn: ValueRef, +llargs: ~[ValueRef]) -> block {
}
}
let normal_bcx = sub_block(bcx, ~"normal return");
Invoke(bcx, llfn, llargs, normal_bcx.llbb, get_landing_pad(bcx));
return normal_bcx;
let llresult = Invoke(bcx,
llfn,
llargs,
normal_bcx.llbb,
get_landing_pad(bcx));
return (llresult, normal_bcx);
} else {
unsafe {
debug!("calling %x at %x",
@ -842,8 +868,8 @@ pub fn invoke(bcx: block, llfn: ValueRef, +llargs: ~[ValueRef]) -> block {
debug!("arg: %x", ::core::cast::transmute(llarg));
}
}
Call(bcx, llfn, llargs);
return bcx;
let llresult = Call(bcx, llfn, llargs);
return (llresult, bcx);
}
}
@ -1574,6 +1600,18 @@ pub fn mk_standard_basic_blocks(llfn: ValueRef) -> BasicBlocks {
}
}
// Creates and returns space for, or returns the argument representing, the
// slot where the return value of the function must go.
pub fn make_return_pointer(fcx: fn_ctxt, output_type: ty::t) -> ValueRef {
unsafe {
if !ty::type_is_immediate(output_type) {
llvm::LLVMGetParam(fcx.llfn, 0)
} else {
let lloutputtype = type_of::type_of(*fcx.ccx, output_type);
alloca(raw_block(fcx, false, fcx.llstaticallocas), lloutputtype)
}
}
}
// NB: must keep 4 fns in sync:
//
@ -1585,10 +1623,11 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
+path: path,
llfndecl: ValueRef,
id: ast::node_id,
output_type: ty::t,
impl_id: Option<ast::def_id>,
param_substs: Option<@param_substs>,
sp: Option<span>) -> fn_ctxt
{
sp: Option<span>)
-> fn_ctxt {
for param_substs.each |p| { p.validate(); }
debug!("new_fn_ctxt_w_id(path=%s, id=%?, impl_id=%?, \
@ -1599,16 +1638,26 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
param_substs.repr(ccx.tcx));
let llbbs = mk_standard_basic_blocks(llfndecl);
return @mut fn_ctxt_ {
let substd_output_type = match param_substs {
None => output_type,
Some(substs) => {
ty::subst_tps(ccx.tcx, substs.tys, substs.self_ty, output_type)
}
};
let is_immediate = ty::type_is_immediate(substd_output_type);
let fcx = @mut fn_ctxt_ {
llfn: llfndecl,
llenv: unsafe { llvm::LLVMGetParam(llfndecl, 1u as c_uint) },
llretptr: unsafe { llvm::LLVMGetParam(llfndecl, 0u as c_uint) },
llretptr: None,
llstaticallocas: llbbs.sa,
llloadenv: None,
llreturn: llbbs.rt,
llself: None,
personality: None,
loop_ret: None,
has_immediate_return_value: is_immediate,
llargs: @mut HashMap::new(),
lllocals: @mut HashMap::new(),
llupvars: @mut HashMap::new(),
@ -1619,14 +1668,18 @@ pub fn new_fn_ctxt_w_id(ccx: @CrateContext,
path: path,
ccx: @ccx
};
fcx.llretptr = Some(make_return_pointer(fcx, substd_output_type));
fcx
}
pub fn new_fn_ctxt(ccx: @CrateContext,
+path: path,
llfndecl: ValueRef,
output_type: ty::t,
sp: Option<span>)
-> fn_ctxt {
return new_fn_ctxt_w_id(ccx, path, llfndecl, -1, None, None, sp);
new_fn_ctxt_w_id(ccx, path, llfndecl, -1, output_type, None, None, sp)
}
// NB: must keep 4 fns in sync:
@ -1645,7 +1698,8 @@ pub fn new_fn_ctxt(ccx: @CrateContext,
// field of the fn_ctxt with
pub fn create_llargs_for_fn_args(cx: fn_ctxt,
ty_self: self_arg,
args: &[ast::arg]) -> ~[ValueRef] {
args: &[ast::arg])
-> ~[ValueRef] {
let _icx = cx.insn_ctxt("create_llargs_for_fn_args");
match ty_self {
@ -1751,8 +1805,19 @@ pub fn copy_args_to_allocas(fcx: fn_ctxt,
pub fn finish_fn(fcx: fn_ctxt, lltop: BasicBlockRef) {
let _icx = fcx.insn_ctxt("finish_fn");
tie_up_header_blocks(fcx, lltop);
build_return_block(fcx);
}
// Builds the return block for a function.
pub fn build_return_block(fcx: fn_ctxt) {
let ret_cx = raw_block(fcx, false, fcx.llreturn);
RetVoid(ret_cx);
// Return the value if this function immediate; otherwise, return void.
if fcx.has_immediate_return_value {
Ret(ret_cx, Load(ret_cx, fcx.llretptr.get()))
} else {
RetVoid(ret_cx)
}
}
pub fn tie_up_header_blocks(fcx: fn_ctxt, lltop: BasicBlockRef) {
@ -1782,6 +1847,8 @@ pub fn trans_closure(ccx: @CrateContext,
param_substs: Option<@param_substs>,
id: ast::node_id,
impl_id: Option<ast::def_id>,
attributes: &[ast::attribute],
output_type: ty::t,
maybe_load_env: &fn(fn_ctxt),
finish: &fn(block)) {
ccx.stats.n_closures += 1;
@ -1792,10 +1859,21 @@ pub fn trans_closure(ccx: @CrateContext,
param_substs.repr(ccx.tcx));
// Set up arguments to the function.
let fcx = new_fn_ctxt_w_id(ccx, path, llfndecl, id, impl_id, param_substs,
Some(body.span));
let raw_llargs = create_llargs_for_fn_args(fcx, ty_self,
decl.inputs);
let fcx = new_fn_ctxt_w_id(ccx,
path,
llfndecl,
id,
output_type,
impl_id,
param_substs,
Some(body.span));
let raw_llargs = create_llargs_for_fn_args(fcx, ty_self, decl.inputs);
// Set the fixed stack segment flag if necessary.
if attr::attrs_contains_name(attributes, "fixed_stack_segment") {
set_no_inline(fcx.llfn);
set_fixed_stack_segment(fcx.llfn);
}
// Set GC for function.
if ccx.sess.opts.gc {
@ -1828,7 +1906,8 @@ pub fn trans_closure(ccx: @CrateContext,
{
bcx = controlflow::trans_block(bcx, body, expr::Ignore);
} else {
bcx = controlflow::trans_block(bcx, body, expr::SaveIn(fcx.llretptr));
let dest = expr::SaveIn(fcx.llretptr.get());
bcx = controlflow::trans_block(bcx, body, dest);
}
finish(bcx);
@ -1848,7 +1927,8 @@ pub fn trans_fn(ccx: @CrateContext,
ty_self: self_arg,
param_substs: Option<@param_substs>,
id: ast::node_id,
impl_id: Option<ast::def_id>) {
impl_id: Option<ast::def_id>,
attrs: &[ast::attribute]) {
let do_time = ccx.sess.trans_stats();
let start = if do_time { time::get_time() }
else { time::Timespec::new(0, 0) };
@ -1858,8 +1938,18 @@ pub fn trans_fn(ccx: @CrateContext,
let _icx = ccx.insn_ctxt("trans_fn");
ccx.stats.n_fns += 1;
let the_path_str = path_str(ccx.sess, path);
trans_closure(ccx, path, decl, body, llfndecl, ty_self,
param_substs, id, impl_id,
let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, id));
trans_closure(ccx,
path,
decl,
body,
llfndecl,
ty_self,
param_substs,
id,
impl_id,
attrs,
output_type,
|fcx| {
if ccx.sess.opts.extra_debuginfo
&& fcx_has_nonzero_span(fcx) {
@ -1894,26 +1984,39 @@ pub fn trans_enum_variant(ccx: @CrateContext,
id: varg.id,
}
};
let fcx = new_fn_ctxt_w_id(ccx, ~[], llfndecl, variant.node.id, None,
param_substs, None);
let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args);
let ty_param_substs = match param_substs {
Some(ref substs) => { copy substs.tys }
None => ~[]
};
let enum_ty = ty::subst_tps(ccx.tcx,
ty_param_substs,
None,
ty::node_id_to_type(ccx.tcx, enum_id));
let fcx = new_fn_ctxt_w_id(ccx,
~[],
llfndecl,
variant.node.id,
enum_ty,
None,
param_substs,
None);
let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args);
let bcx = top_scope_block(fcx, None), lltop = bcx.llbb;
let arg_tys = ty::ty_fn_args(node_id_type(bcx, variant.node.id));
let bcx = copy_args_to_allocas(fcx, bcx, fn_args, raw_llargs, arg_tys);
// XXX is there a better way to reconstruct the ty::t?
let enum_ty = ty::subst_tps(ccx.tcx, ty_param_substs, None,
ty::node_id_to_type(ccx.tcx, enum_id));
let repr = adt::represent_type(ccx, enum_ty);
adt::trans_start_init(bcx, repr, fcx.llretptr, disr);
adt::trans_start_init(bcx, repr, fcx.llretptr.get(), disr);
for vec::eachi(args) |i, va| {
let lldestptr = adt::trans_field_ptr(bcx, repr, fcx.llretptr,
disr, i);
let lldestptr = adt::trans_field_ptr(bcx,
repr,
fcx.llretptr.get(),
disr,
i);
// If this argument to this function is a enum, it'll have come in to
// this function as an opaque blob due to the way that type_of()
@ -1951,21 +2054,6 @@ pub fn trans_tuple_struct(ccx: @CrateContext,
}
};
let fcx = new_fn_ctxt_w_id(ccx,
~[],
llfndecl,
ctor_id,
None,
param_substs,
None);
let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args);
let bcx = top_scope_block(fcx, None);
let lltop = bcx.llbb;
let arg_tys = ty::ty_fn_args(node_id_type(bcx, ctor_id));
let bcx = copy_args_to_allocas(fcx, bcx, fn_args, raw_llargs, arg_tys);
// XXX is there a better way to reconstruct the ty::t?
let ty_param_substs = match param_substs {
Some(ref substs) => { copy substs.tys }
@ -1979,10 +2067,31 @@ pub fn trans_tuple_struct(ccx: @CrateContext,
return type %s",
ty_to_str(ccx.tcx, ctor_ty)))
};
let fcx = new_fn_ctxt_w_id(ccx,
~[],
llfndecl,
ctor_id,
tup_ty,
None,
param_substs,
None);
let raw_llargs = create_llargs_for_fn_args(fcx, no_self, fn_args);
let bcx = top_scope_block(fcx, None);
let lltop = bcx.llbb;
let arg_tys = ty::ty_fn_args(node_id_type(bcx, ctor_id));
let bcx = copy_args_to_allocas(fcx, bcx, fn_args, raw_llargs, arg_tys);
let repr = adt::represent_type(ccx, tup_ty);
for fields.eachi |i, field| {
let lldestptr = adt::trans_field_ptr(bcx, repr, fcx.llretptr, 0, i);
let lldestptr = adt::trans_field_ptr(bcx,
repr,
fcx.llretptr.get(),
0,
i);
let llarg = match *fcx.llargs.get(&field.node.id) {
local_mem(x) => x,
_ => {
@ -2032,8 +2141,16 @@ pub fn trans_struct_dtor(ccx: @CrateContext,
}
/* Translate the dtor body */
let decl = ast_util::dtor_dec();
trans_fn(ccx, path, &decl, body, lldecl,
impl_self(class_ty), psubsts, dtor_id, None);
trans_fn(ccx,
path,
&decl,
body,
lldecl,
impl_self(class_ty),
psubsts,
dtor_id,
None,
[]);
lldecl
}
@ -2074,15 +2191,24 @@ pub fn trans_item(ccx: @CrateContext, item: ast::item) {
if purity == ast::extern_fn {
let llfndecl = get_item_val(ccx, item.id);
foreign::trans_foreign_fn(ccx,
vec::append(
/*bad*/copy *path,
~[path_name(item.ident)]),
decl, body, llfndecl, item.id);
vec::append(/*bad*/copy *path,
~[path_name(item.ident)]),
decl,
body,
llfndecl,
item.id);
} else if !generics.is_type_parameterized() {
let llfndecl = get_item_val(ccx, item.id);
trans_fn(ccx,
vec::append(/*bad*/copy *path, ~[path_name(item.ident)]),
decl, body, llfndecl, no_self, None, item.id, None);
decl,
body,
llfndecl,
no_self,
None,
item.id,
None,
item.attrs);
} else {
for body.node.stmts.each |stmt| {
match stmt.node {
@ -2187,7 +2313,7 @@ pub fn register_fn_fuller(ccx: @CrateContext,
node_type: ty::t,
cc: lib::llvm::CallConv,
llfty: TypeRef)
-> ValueRef {
-> ValueRef {
debug!("register_fn_fuller creating fn for item %d with path %s",
node_id,
ast_map::path_to_str(path, ccx.sess.parse_sess.interner));
@ -2207,7 +2333,9 @@ pub fn register_fn_fuller(ccx: @CrateContext,
(!*ccx.sess.building_library ||
(*ccx.sess.building_library &&
ccx.sess.targ_cfg.os == session::os_android));
if is_entry { create_entry_wrapper(ccx, sp, llfn); }
if is_entry {
create_entry_wrapper(ccx, sp, llfn);
}
llfn
}
@ -2236,23 +2364,26 @@ pub fn create_entry_wrapper(ccx: @CrateContext,
let llfdecl = decl_fn(ccx.llmod, ~"_rust_main",
lib::llvm::CCallConv, llfty);
let fcx = new_fn_ctxt(ccx, ~[], llfdecl, None);
let fcx = new_fn_ctxt(ccx, ~[], llfdecl, nt, None);
let bcx = top_scope_block(fcx, None);
let lltop = bcx.llbb;
// Call main.
let lloutputarg = unsafe { llvm::LLVMGetParam(llfdecl, 0 as c_uint) };
let lloutputarg = C_null(T_ptr(T_i8()));
let llenvarg = unsafe { llvm::LLVMGetParam(llfdecl, 1 as c_uint) };
let mut args = ~[lloutputarg, llenvarg];
Call(bcx, main_llfn, args);
let llresult = Call(bcx, main_llfn, args);
Store(bcx, llresult, fcx.llretptr.get());
build_return(bcx);
finish_fn(fcx, lltop);
return llfdecl;
}
fn create_entry_fn(ccx: @CrateContext, rust_main: ValueRef, use_start_lang_item:bool) {
fn create_entry_fn(ccx: @CrateContext,
rust_main: ValueRef,
use_start_lang_item: bool) {
let llfty = T_fn(~[ccx.int_type, T_ptr(T_ptr(T_i8()))], ccx.int_type);
// FIXME #4404 android JNI hacks
@ -2273,58 +2404,70 @@ pub fn create_entry_wrapper(ccx: @CrateContext,
let bld = ccx.builder.B;
unsafe {
llvm::LLVMPositionBuilderAtEnd(bld, llbb);
}
let retptr = unsafe {
llvm::LLVMBuildAlloca(bld, ccx.int_type, noname())
};
let crate_map = ccx.crate_map;
let opaque_crate_map = unsafe {llvm::LLVMBuildPointerCast(
bld, crate_map, T_ptr(T_i8()), noname())};
let (start_fn, args) = if use_start_lang_item {
let crate_map = ccx.crate_map;
let start_def_id = ccx.tcx.lang_items.start_fn();
let start_fn = if start_def_id.crate == ast::local_crate {
ccx.sess.bug(~"start lang item is never in the local crate")
} else {
let start_fn_type = csearch::get_type(ccx.tcx,
start_def_id).ty;
start_def_id).ty;
trans_external_path(ccx, start_def_id, start_fn_type)
};
let args = unsafe {
let opaque_rust_main = llvm::LLVMBuildPointerCast(
bld, rust_main, T_ptr(T_i8()), noname());
let retptr = llvm::LLVMBuildAlloca(bld, T_i8(), noname());
~[
retptr,
C_null(T_opaque_box_ptr(ccx)),
opaque_rust_main,
llvm::LLVMGetParam(llfn, 0 as c_uint),
llvm::LLVMGetParam(llfn, 1 as c_uint),
opaque_crate_map
]
};
(start_fn, args)
} else {
debug!("using user-defined start fn");
let args = unsafe {
~[ retptr,
C_null(T_opaque_box_ptr(ccx)),
llvm::LLVMGetParam(llfn, 0 as c_uint),
llvm::LLVMGetParam(llfn, 1 as c_uint),
opaque_crate_map
]
let crate_map = ccx.crate_map;
let opaque_crate_map = llvm::LLVMBuildPointerCast(bld,
crate_map,
T_ptr(T_i8()),
noname());
let (start_fn, args) = if use_start_lang_item {
let start_def_id = ccx.tcx.lang_items.start_fn();
let start_fn = if start_def_id.crate == ast::local_crate {
ccx.sess.bug(~"start lang item is never in the local \
crate")
} else {
let start_fn_type = csearch::get_type(ccx.tcx,
start_def_id).ty;
trans_external_path(ccx, start_def_id, start_fn_type)
};
let args = {
let opaque_rust_main = llvm::LLVMBuildPointerCast(
bld, rust_main, T_ptr(T_i8()), noname());
~[
retptr,
C_null(T_opaque_box_ptr(ccx)),
opaque_rust_main,
llvm::LLVMGetParam(llfn, 0),
llvm::LLVMGetParam(llfn, 1),
opaque_crate_map
]
};
(start_fn, args)
} else {
debug!("using user-defined start fn");
let args = {
~[
retptr,
C_null(T_opaque_box_ptr(ccx)),
llvm::LLVMGetParam(llfn, 0 as c_uint),
llvm::LLVMGetParam(llfn, 1 as c_uint),
opaque_crate_map
]
};
(rust_main, args)
};
(rust_main, args)
};
unsafe {
llvm::LLVMBuildCall(bld, start_fn, vec::raw::to_ptr(args),
args.len() as c_uint, noname());
let result = llvm::LLVMBuildLoad(bld, retptr, noname());
let result = llvm::LLVMBuildCall(bld,
start_fn,
&args[0],
args.len() as c_uint,
noname());
llvm::LLVMBuildRet(bld, result);
}
}
@ -2395,7 +2538,6 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef {
match ccx.item_vals.find(&id) {
Some(&v) => v,
None => {
let mut exprt = false;
let val = match *ccx.tcx.items.get(&id) {
ast_map::node_item(i, pth) => {
@ -2487,10 +2629,10 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef {
assert!(!ty::type_has_params(class_ty));
let lldty = unsafe {
T_fn(~[
T_ptr(type_of(ccx, ty::mk_nil(tcx))),
T_ptr(T_i8()),
T_ptr(type_of(ccx, class_ty))
],
llvm::LLVMVoidType())
T_nil())
};
let s = get_dtor_symbol(ccx, /*bad*/copy *pt, dt.node.id, None);

View file

@ -181,9 +181,15 @@ pub fn noname() -> *libc::c_char {
}
}
pub fn Invoke(cx: block, Fn: ValueRef, Args: &[ValueRef],
Then: BasicBlockRef, Catch: BasicBlockRef) {
if cx.unreachable { return; }
pub fn Invoke(cx: block,
Fn: ValueRef,
Args: &[ValueRef],
Then: BasicBlockRef,
Catch: BasicBlockRef)
-> ValueRef {
if cx.unreachable {
return C_null(T_i8());
}
check_not_terminated(cx);
terminate(cx, "Invoke");
debug!("Invoke(%s with arguments (%s))",
@ -193,9 +199,13 @@ pub fn Invoke(cx: block, Fn: ValueRef, Args: &[ValueRef],
~", "));
unsafe {
count_insn(cx, "invoke");
llvm::LLVMBuildInvoke(B(cx), Fn, vec::raw::to_ptr(Args),
Args.len() as c_uint, Then, Catch,
noname());
llvm::LLVMBuildInvoke(B(cx),
Fn,
vec::raw::to_ptr(Args),
Args.len() as c_uint,
Then,
Catch,
noname())
}
}

View file

@ -92,16 +92,19 @@ pub impl FnType {
return llargvals;
}
fn build_shim_ret(&self, bcx: block,
arg_tys: &[TypeRef], ret_def: bool,
llargbundle: ValueRef, llretval: ValueRef) {
fn build_shim_ret(&self,
bcx: block,
arg_tys: &[TypeRef],
ret_def: bool,
llargbundle: ValueRef,
llretval: ValueRef) {
for vec::eachi(self.attrs) |i, a| {
match *a {
option::Some(attr) => {
unsafe {
llvm::LLVMAddInstrAttribute(
llretval, (i + 1u) as c_uint,
attr as c_uint);
llvm::LLVMAddInstrAttribute(llretval,
(i + 1u) as c_uint,
attr as c_uint);
}
}
_ => ()
@ -125,8 +128,11 @@ pub impl FnType {
};
}
fn build_wrap_args(&self, bcx: block, ret_ty: TypeRef,
llwrapfn: ValueRef, llargbundle: ValueRef) {
fn build_wrap_args(&self,
bcx: block,
ret_ty: TypeRef,
llwrapfn: ValueRef,
llargbundle: ValueRef) {
let mut atys = /*bad*/copy self.arg_tys;
let mut attrs = /*bad*/copy self.attrs;
let mut j = 0u;
@ -161,22 +167,27 @@ pub impl FnType {
store_inbounds(bcx, llretptr, llargbundle, [0u, n]);
}
fn build_wrap_ret(&self, bcx: block,
arg_tys: &[TypeRef], llargbundle: ValueRef) {
fn build_wrap_ret(&self,
bcx: block,
arg_tys: &[TypeRef],
llargbundle: ValueRef) {
unsafe {
if llvm::LLVMGetTypeKind(self.ret_ty.ty) == Void {
RetVoid(bcx);
return;
}
}
let n = vec::len(arg_tys);
let llretval = load_inbounds(bcx, llargbundle, ~[0u, n]);
let llretval = load_inbounds(bcx, llargbundle, ~[ 0, arg_tys.len() ]);
let llretval = if self.ret_ty.cast {
let retptr = BitCast(bcx, llretval, T_ptr(self.ret_ty.ty));
Load(bcx, retptr)
} else {
Load(bcx, llretval)
};
Ret(bcx, llretval);
let llretptr = BitCast(bcx,
bcx.fcx.llretptr.get(),
T_ptr(self.ret_ty.ty));
Store(bcx, llretval, llretptr);
}
}

View file

@ -314,11 +314,16 @@ pub fn trans_call(in_cx: block,
args: CallArgs,
id: ast::node_id,
dest: expr::Dest)
-> block {
-> block {
let _icx = in_cx.insn_ctxt("trans_call");
trans_call_inner(
in_cx, call_ex.info(), expr_ty(in_cx, f), node_id_type(in_cx, id),
|cx| trans(cx, f), args, dest, DontAutorefArg)
trans_call_inner(in_cx,
call_ex.info(),
expr_ty(in_cx, f),
node_id_type(in_cx, id),
|cx| trans(cx, f),
args,
dest,
DontAutorefArg)
}
pub fn trans_method_call(in_cx: block,
@ -326,7 +331,7 @@ pub fn trans_method_call(in_cx: block,
rcvr: @ast::expr,
args: CallArgs,
dest: expr::Dest)
-> block {
-> block {
let _icx = in_cx.insn_ctxt("trans_method_call");
debug!("trans_method_call(call_ex=%s, rcvr=%s)",
call_ex.repr(in_cx.tcx()),
@ -439,15 +444,15 @@ pub fn body_contains_ret(body: &ast::blk) -> bool {
}
// See [Note-arg-mode]
pub fn trans_call_inner(
++in_cx: block,
call_info: Option<NodeInfo>,
fn_expr_ty: ty::t,
ret_ty: ty::t,
get_callee: &fn(block) -> Callee,
args: CallArgs,
dest: expr::Dest,
autoref_arg: AutorefArg) -> block {
pub fn trans_call_inner(++in_cx: block,
call_info: Option<NodeInfo>,
fn_expr_ty: ty::t,
ret_ty: ty::t,
get_callee: &fn(block) -> Callee,
args: CallArgs,
dest: expr::Dest,
autoref_arg: AutorefArg)
-> block {
do base::with_scope(in_cx, call_info, ~"call") |cx| {
let ret_in_loop = match args {
ArgExprs(args) => {
@ -500,7 +505,15 @@ pub fn trans_call_inner(
let llretslot = trans_ret_slot(bcx, fn_expr_ty, dest);
let mut llargs = ~[];
llargs.push(llretslot);
if ty::type_is_immediate(ret_ty) {
unsafe {
llargs.push(llvm::LLVMGetUndef(T_ptr(T_i8())));
}
} else {
llargs.push(llretslot);
}
llargs.push(llenv);
bcx = trans_args(bcx, args, fn_expr_ty,
ret_flag, autoref_arg, &mut llargs);
@ -527,17 +540,34 @@ pub fn trans_call_inner(
// If the block is terminated, then one or more of the args
// has type _|_. Since that means it diverges, the code for
// the call itself is unreachable.
bcx = base::invoke(bcx, llfn, llargs);
match dest { // drop the value if it is not being saved.
let (llresult, new_bcx) = base::invoke(bcx, llfn, llargs);
bcx = new_bcx;
match dest {
expr::Ignore => {
// drop the value if it is not being saved.
unsafe {
if llvm::LLVMIsUndef(llretslot) != lib::llvm::True {
bcx = glue::drop_ty(bcx, llretslot, ret_ty);
if ty::type_is_immediate(ret_ty) {
let llscratchptr = alloc_ty(bcx, ret_ty);
Store(bcx, llresult, llscratchptr);
bcx = glue::drop_ty(bcx, llscratchptr, ret_ty);
} else {
bcx = glue::drop_ty(bcx, llretslot, ret_ty);
}
}
}
}
expr::SaveIn(_) => { }
expr::SaveIn(lldest) => {
// If this is an immediate, store into the result location.
// (If this was not an immediate, the result will already be
// directly written into the output slot.)
if ty::type_is_immediate(ret_ty) {
Store(bcx, llresult, lldest);
}
}
}
if ty::type_is_bot(ret_ty) {
Unreachable(bcx);
} else if ret_in_loop {
@ -545,7 +575,7 @@ pub fn trans_call_inner(
bcx = do with_cond(bcx, ret_flag_result) |bcx| {
for (copy bcx.fcx.loop_ret).each |&(flagptr, _)| {
Store(bcx, C_bool(true), flagptr);
Store(bcx, C_bool(false), bcx.fcx.llretptr);
Store(bcx, C_bool(false), bcx.fcx.llretptr.get());
}
base::cleanup_and_leave(bcx, None, Some(bcx.fcx.llreturn));
Unreachable(bcx);
@ -562,11 +592,10 @@ pub enum CallArgs<'self> {
ArgVals(&'self [ValueRef])
}
pub fn trans_ret_slot(+bcx: block,
+fn_ty: ty::t,
+dest: expr::Dest) -> ValueRef
{
pub fn trans_ret_slot(+bcx: block, +fn_ty: ty::t, +dest: expr::Dest)
-> ValueRef {
let retty = ty::ty_fn_ret(fn_ty);
match dest {
expr::SaveIn(dst) => dst,
expr::Ignore => {

View file

@ -299,7 +299,7 @@ pub fn build_closure(bcx0: block,
// the right thing):
let ret_true = match bcx.fcx.loop_ret {
Some((_, retptr)) => retptr,
None => bcx.fcx.llretptr
None => bcx.fcx.llretptr.get()
};
let ret_casted = PointerCast(bcx, ret_true, T_ptr(T_nil()));
let ret_datum = Datum {val: ret_casted, ty: ty::mk_nil(tcx),
@ -367,8 +367,7 @@ pub fn trans_expr_fn(bcx: block,
outer_id: ast::node_id,
user_id: ast::node_id,
is_loop_body: Option<Option<ValueRef>>,
dest: expr::Dest) -> block
{
dest: expr::Dest) -> block {
/*!
*
* Translates the body of a closure expression.
@ -400,7 +399,9 @@ pub fn trans_expr_fn(bcx: block,
let ccx = bcx.ccx();
let fty = node_id_type(bcx, outer_id);
let llfnty = type_of_fn_from_ty(ccx, fty);
let sub_path = vec::append_one(/*bad*/copy bcx.fcx.path,
path_name(special_idents::anon));
// XXX: Bad copy.
@ -409,6 +410,21 @@ pub fn trans_expr_fn(bcx: block,
~"expr_fn");
let llfn = decl_internal_cdecl_fn(ccx.llmod, s, llfnty);
// Always mark inline if this is a loop body. This is important for
// performance on many programs with tight loops.
if is_loop_body.is_some() {
set_always_inline(llfn);
} else {
// Can't hurt.
set_inline_hint(llfn);
}
let real_return_type = if is_loop_body.is_some() {
ty::mk_bool(bcx.tcx())
} else {
ty::ty_fn_ret(fty)
};
let Result {bcx: bcx, val: closure} = match sigil {
ast::BorrowedSigil | ast::ManagedSigil | ast::OwnedSigil => {
let cap_vars = *ccx.maps.capture_map.get(&user_id);
@ -416,14 +432,24 @@ pub fn trans_expr_fn(bcx: block,
None => None};
let ClosureResult {llbox, cdata_ty, bcx}
= build_closure(bcx, cap_vars, sigil, ret_handle);
trans_closure(ccx, sub_path, decl,
body, llfn, no_self,
/*bad*/ copy bcx.fcx.param_substs, user_id, None,
trans_closure(ccx,
sub_path,
decl,
body,
llfn,
no_self,
/*bad*/ copy bcx.fcx.param_substs,
user_id,
None,
[],
real_return_type,
|fcx| load_environment(fcx, cdata_ty, cap_vars,
ret_handle.is_some(), sigil),
|bcx| {
if is_loop_body.is_some() {
Store(bcx, C_bool(true), bcx.fcx.llretptr);
Store(bcx,
C_bool(true),
bcx.fcx.llretptr.get());
}
});
rslt(bcx, llbox)

View file

@ -291,10 +291,15 @@ pub struct fn_ctxt_ {
// section of the executable we're generating.
llfn: ValueRef,
// The two implicit arguments that arrive in the function we're creating.
// For instance, foo(int, int) is really foo(ret*, env*, int, int).
// The implicit environment argument that arrives in the function we're
// creating.
llenv: ValueRef,
llretptr: ValueRef,
// The place to store the return value. If the return type is immediate,
// this is an alloca in the function. Otherwise, it's the hidden first
// parameter to the function. After function construction, this should
// always be Some.
llretptr: Option<ValueRef>,
// These elements: "hoisted basic blocks" containing
// administrative activities that have to happen in only one place in
@ -322,6 +327,11 @@ pub struct fn_ctxt_ {
// for that (flagptr, retptr)
loop_ret: Option<(ValueRef, ValueRef)>,
// True if this function has an immediate return value, false otherwise.
// If this is false, the llretptr will alias the first argument of the
// function.
has_immediate_return_value: bool,
// Maps arguments to allocas created for them in llallocas.
llargs: @mut HashMap<ast::node_id, local_val>,
// Maps the def_ids for local variables to the allocas created for

View file

@ -274,7 +274,7 @@ pub fn trans_break_cont(bcx: block,
Some(bcx) => bcx,
// This is a return from a loop body block
None => {
Store(bcx, C_bool(!to_end), bcx.fcx.llretptr);
Store(bcx, C_bool(!to_end), bcx.fcx.llretptr.get());
cleanup_and_leave(bcx, None, Some(bcx.fcx.llreturn));
Unreachable(bcx);
return bcx;
@ -303,14 +303,14 @@ pub fn trans_ret(bcx: block, e: Option<@ast::expr>) -> block {
// to false, return flag to true, and then store the value in the
// parent's retptr.
Store(bcx, C_bool(true), flagptr);
Store(bcx, C_bool(false), bcx.fcx.llretptr);
Store(bcx, C_bool(false), bcx.fcx.llretptr.get());
match e {
Some(x) => PointerCast(bcx, retptr,
T_ptr(type_of(bcx.ccx(), expr_ty(bcx, x)))),
None => retptr
}
}
None => bcx.fcx.llretptr
None => bcx.fcx.llretptr.get()
};
match e {
Some(x) => {

View file

@ -31,7 +31,7 @@
* value stored in the datum is indicated in the field `ty`.
*
* Generally speaking, you probably do not want to access the `val` field
* unless you know what mode the value is in. Intead you should use one
* unless you know what mode the value is in. Instead you should use one
* of the following accessors:
*
* - `to_value_llval()` converts to by-value

View file

@ -624,10 +624,14 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
let sigil = ty::ty_closure_sigil(expr_ty);
match blk.node {
ast::expr_fn_block(ref decl, ref body) => {
return closure::trans_expr_fn(bcx, sigil,
decl, body,
expr.id, blk.id,
Some(None), dest);
return closure::trans_expr_fn(bcx,
sigil,
decl,
body,
expr.id,
blk.id,
Some(None),
dest);
}
_ => {
bcx.sess().impossible_case(
@ -655,15 +659,30 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
}
ast::expr_binary(_, lhs, rhs) => {
// if not overloaded, would be RvalueDatumExpr
return trans_overloaded_op(bcx, expr, lhs, ~[rhs], dest);
return trans_overloaded_op(bcx,
expr,
lhs,
~[rhs],
expr_ty(bcx, expr),
dest);
}
ast::expr_unary(_, subexpr) => {
// if not overloaded, would be RvalueDatumExpr
return trans_overloaded_op(bcx, expr, subexpr, ~[], dest);
return trans_overloaded_op(bcx,
expr,
subexpr,
~[],
expr_ty(bcx, expr),
dest);
}
ast::expr_index(base, idx) => {
// if not overloaded, would be RvalueDatumExpr
return trans_overloaded_op(bcx, expr, base, ~[idx], dest);
return trans_overloaded_op(bcx,
expr,
base,
~[idx],
expr_ty(bcx, expr),
dest);
}
ast::expr_cast(val, _) => {
match ty::get(node_id_type(bcx, expr.id)).sty {
@ -1554,15 +1573,24 @@ fn trans_overloaded_op(bcx: block,
expr: @ast::expr,
rcvr: @ast::expr,
+args: ~[@ast::expr],
dest: Dest) -> block
{
ret_ty: ty::t,
dest: Dest)
-> block {
let origin = *bcx.ccx().maps.method_map.get(&expr.id);
let fty = node_id_type(bcx, expr.callee_id);
return callee::trans_call_inner(
bcx, expr.info(), fty,
expr_ty(bcx, expr),
|bcx| meth::trans_method_callee(bcx, expr.callee_id, rcvr, origin),
callee::ArgExprs(args), dest, DoAutorefArg);
callee::trans_call_inner(bcx,
expr.info(),
fty,
ret_ty,
|bcx| {
meth::trans_method_callee(bcx,
expr.callee_id,
rcvr,
origin)
},
callee::ArgExprs(args),
dest,
DoAutorefArg)
}
fn int_cast(bcx: block, lldsttype: TypeRef, llsrctype: TypeRef,
@ -1697,7 +1725,11 @@ fn trans_assign_op(bcx: block,
if bcx.ccx().maps.method_map.find(&expr.id).is_some() {
// FIXME(#2528) evaluates the receiver twice!!
let scratch = scratch_datum(bcx, dst_datum.ty, false);
let bcx = trans_overloaded_op(bcx, expr, dst, ~[src],
let bcx = trans_overloaded_op(bcx,
expr,
dst,
~[src],
dst_datum.ty,
SaveIn(scratch.val));
return scratch.move_to_datum(bcx, DROP_EXISTING, dst_datum);
}

File diff suppressed because it is too large Load diff

View file

@ -499,7 +499,8 @@ pub fn trans_struct_drop(bcx: block,
}
let self_arg = PointerCast(bcx, llval, params[1]);
let args = ~[bcx.fcx.llretptr, self_arg];
let args = ~[C_null(T_ptr(T_i8())), self_arg];
Call(bcx, dtor_addr, args);
// Drop the fields
@ -575,9 +576,7 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
build_return(bcx);
}
pub fn decr_refcnt_maybe_free(bcx: block,
box_ptr: ValueRef,
t: ty::t)
pub fn decr_refcnt_maybe_free(bcx: block, box_ptr: ValueRef, t: ty::t)
-> block {
let _icx = bcx.insn_ctxt("decr_refcnt_maybe_free");
let ccx = bcx.ccx();
@ -737,7 +736,7 @@ pub fn make_generic_glue_inner(ccx: @CrateContext,
helper: glue_helper)
-> ValueRef {
let _icx = ccx.insn_ctxt("make_generic_glue_inner");
let fcx = new_fn_ctxt(ccx, ~[], llfn, None);
let fcx = new_fn_ctxt(ccx, ~[], llfn, ty::mk_nil(ccx.tcx), None);
lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
ccx.stats.n_glues_created += 1u;
// All glue functions take values passed *by alias*; this is a
@ -756,8 +755,11 @@ pub fn make_generic_glue_inner(ccx: @CrateContext,
return llfn;
}
pub fn make_generic_glue(ccx: @CrateContext, t: ty::t, llfn: ValueRef,
helper: glue_helper, name: &str)
pub fn make_generic_glue(ccx: @CrateContext,
t: ty::t,
llfn: ValueRef,
helper: glue_helper,
name: &str)
-> ValueRef {
let _icx = ccx.insn_ctxt("make_generic_glue");
if !ccx.sess.trans_stats() {
@ -767,8 +769,10 @@ pub fn make_generic_glue(ccx: @CrateContext, t: ty::t, llfn: ValueRef,
let start = time::get_time();
let llval = make_generic_glue_inner(ccx, t, llfn, helper);
let end = time::get_time();
log_fn_time(ccx, fmt!("glue %s %s", name, ty_to_short_str(ccx.tcx, t)),
start, end);
log_fn_time(ccx,
fmt!("glue %s %s", name, ty_to_short_str(ccx.tcx, t)),
start,
end);
return llval;
}

View file

@ -116,7 +116,8 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::def_id,
self_kind,
None,
mth.id,
Some(impl_did));
Some(impl_did),
[]);
}
local_def(mth.id)
}

View file

@ -137,7 +137,8 @@ pub fn trans_method(ccx: @CrateContext,
self_arg,
param_substs,
method.id,
Some(impl_id));
Some(impl_id),
[]);
}
pub fn trans_self_arg(bcx: block,

View file

@ -195,7 +195,16 @@ pub fn monomorphic_fn(ccx: @CrateContext,
}, _) => {
let d = mk_lldecl();
set_inline_hint_if_appr(/*bad*/copy i.attrs, d);
trans_fn(ccx, pt, decl, body, d, no_self, psubsts, fn_id.node, None);
trans_fn(ccx,
pt,
decl,
body,
d,
no_self,
psubsts,
fn_id.node,
None,
[]);
d
}
ast_map::node_item(*) => {

View file

@ -288,11 +288,15 @@ pub impl Reflector {
let arg = unsafe {
llvm::LLVMGetParam(llfdecl, first_real_arg as c_uint)
};
let fcx = new_fn_ctxt(ccx, ~[], llfdecl, None);
let fcx = new_fn_ctxt(ccx,
~[],
llfdecl,
ty::mk_uint(ccx.tcx),
None);
let bcx = top_scope_block(fcx, None);
let arg = BitCast(bcx, arg, llptrty);
let ret = adt::trans_get_discr(bcx, repr, arg);
Store(bcx, ret, fcx.llretptr);
Store(bcx, ret, fcx.llretptr.get());
cleanup_and_Br(bcx, bcx, fcx.llreturn);
finish_fn(fcx, bcx.llbb);
llfdecl

View file

@ -39,20 +39,34 @@ pub fn type_of_explicit_args(ccx: @CrateContext,
inputs.map(|arg| type_of_explicit_arg(ccx, arg))
}
pub fn type_of_fn(cx: @CrateContext, inputs: &[ty::arg],
output: ty::t) -> TypeRef {
pub fn type_of_fn(cx: @CrateContext, inputs: &[ty::arg], output: ty::t)
-> TypeRef {
unsafe {
let mut atys: ~[TypeRef] = ~[];
// Arg 0: Output pointer.
atys.push(T_ptr(type_of(cx, output)));
// (if the output type is non-immediate)
let output_is_immediate = ty::type_is_immediate(output);
let lloutputtype = type_of(cx, output);
if !output_is_immediate {
atys.push(T_ptr(lloutputtype));
} else {
// XXX: Eliminate this.
atys.push(T_ptr(T_i8()));
}
// Arg 1: Environment
atys.push(T_opaque_box_ptr(cx));
// ... then explicit args.
atys.push_all(type_of_explicit_args(cx, inputs));
return T_fn(atys, llvm::LLVMVoidType());
// Use the output as the actual return value if it's immediate.
if output_is_immediate {
T_fn(atys, lloutputtype)
} else {
T_fn(atys, llvm::LLVMVoidType())
}
}
}
@ -318,11 +332,9 @@ pub fn llvm_type_name(cx: @CrateContext,
}
pub fn type_of_dtor(ccx: @CrateContext, self_ty: ty::t) -> TypeRef {
unsafe {
T_fn(~[T_ptr(type_of(ccx, ty::mk_nil(ccx.tcx))), // output pointer
T_ptr(type_of(ccx, self_ty))], // self arg
llvm::LLVMVoidType())
}
T_fn(~[T_ptr(T_i8()), // output pointer
T_ptr(type_of(ccx, self_ty))], // self arg
T_nil())
}
pub fn type_of_rooted(ccx: @CrateContext, t: ty::t) -> TypeRef {
@ -336,5 +348,5 @@ pub fn type_of_glue_fn(ccx: @CrateContext, t: ty::t) -> TypeRef {
let tydescpp = T_ptr(T_ptr(ccx.tydesc_type));
let llty = T_ptr(type_of(ccx, t));
return T_fn(~[T_ptr(T_nil()), T_ptr(T_nil()), tydescpp, llty],
T_void());
T_nil());
}

View file

@ -133,7 +133,6 @@ impl to_bytes::IterBytes for creader_cache_key {
struct intern_key {
sty: *sty,
o_def_id: Option<ast::def_id>
}
// NB: Do not replace this with #[deriving(Eq)]. The automatically-derived
@ -142,7 +141,7 @@ struct intern_key {
impl cmp::Eq for intern_key {
fn eq(&self, other: &intern_key) -> bool {
unsafe {
*self.sty == *other.sty && self.o_def_id == other.o_def_id
*self.sty == *other.sty
}
}
fn ne(&self, other: &intern_key) -> bool {
@ -153,7 +152,7 @@ impl cmp::Eq for intern_key {
impl to_bytes::IterBytes for intern_key {
fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
unsafe {
to_bytes::iter_bytes_2(&*self.sty, &self.o_def_id, lsb0, f);
(*self.sty).iter_bytes(lsb0, f);
}
}
}
@ -232,7 +231,7 @@ pub type ctxt = @ctxt_;
struct ctxt_ {
diag: @syntax::diagnostic::span_handler,
interner: @mut HashMap<intern_key, t_box>,
interner: @mut HashMap<intern_key, ~t_box_>,
next_id: @mut uint,
vecs_implicitly_copyable: bool,
legacy_modes: bool,
@ -307,7 +306,7 @@ struct ctxt_ {
used_unsafe: @mut HashSet<ast::node_id>,
}
enum tbox_flag {
pub enum tbox_flag {
has_params = 1,
has_self = 2,
needs_infer = 4,
@ -320,13 +319,12 @@ enum tbox_flag {
needs_subst = 1 | 2 | 8
}
type t_box = @t_box_;
pub type t_box = &'static t_box_;
struct t_box_ {
pub struct t_box_ {
sty: sty,
id: uint,
flags: uint,
o_def_id: Option<ast::def_id>
}
// To reduce refcounting cost, we're representing types as unsafe pointers
@ -359,7 +357,6 @@ pub fn type_needs_infer(t: t) -> bool {
pub fn type_has_regions(t: t) -> bool {
tbox_has_flag(get(t), has_regions)
}
pub fn type_def_id(t: t) -> Option<ast::def_id> { get(t).o_def_id }
pub fn type_id(t: t) -> uint { get(t).id }
#[deriving(Eq)]
@ -513,6 +510,53 @@ pub struct substs {
tps: ~[t]
}
mod primitives {
use super::{sty, t_box_};
use syntax::ast;
macro_rules! def_prim_ty(
($name:ident, $sty:expr, $id:expr) => (
pub static $name: t_box_ = t_box_ {
sty: $sty,
id: $id,
flags: 0,
};
)
)
def_prim_ty!(TY_NIL, super::ty_nil, 0)
def_prim_ty!(TY_BOOL, super::ty_bool, 1)
def_prim_ty!(TY_INT, super::ty_int(ast::ty_i), 2)
def_prim_ty!(TY_CHAR, super::ty_int(ast::ty_char), 3)
def_prim_ty!(TY_I8, super::ty_int(ast::ty_i8), 4)
def_prim_ty!(TY_I16, super::ty_int(ast::ty_i16), 5)
def_prim_ty!(TY_I32, super::ty_int(ast::ty_i32), 6)
def_prim_ty!(TY_I64, super::ty_int(ast::ty_i64), 7)
def_prim_ty!(TY_UINT, super::ty_uint(ast::ty_u), 8)
def_prim_ty!(TY_U8, super::ty_uint(ast::ty_u8), 9)
def_prim_ty!(TY_U16, super::ty_uint(ast::ty_u16), 10)
def_prim_ty!(TY_U32, super::ty_uint(ast::ty_u32), 11)
def_prim_ty!(TY_U64, super::ty_uint(ast::ty_u64), 12)
def_prim_ty!(TY_FLOAT, super::ty_float(ast::ty_f), 13)
def_prim_ty!(TY_F32, super::ty_float(ast::ty_f32), 14)
def_prim_ty!(TY_F64, super::ty_float(ast::ty_f64), 15)
pub static TY_BOT: t_box_ = t_box_ {
sty: super::ty_bot,
id: 16,
flags: super::has_ty_bot as uint,
};
pub static TY_ERR: t_box_ = t_box_ {
sty: super::ty_err,
id: 17,
flags: super::has_ty_err as uint,
};
pub static LAST_PRIMITIVE_ID: uint = 18;
}
// NB: If you change this, you'll probably want to change the corresponding
// AST structure in libsyntax/ast.rs as well.
#[deriving(Eq)]
@ -852,7 +896,7 @@ pub fn mk_ctxt(s: session::Session,
@ctxt_ {
diag: s.diagnostic(),
interner: @mut HashMap::new(),
next_id: @mut 0,
next_id: @mut primitives::LAST_PRIMITIVE_ID,
vecs_implicitly_copyable: vecs_implicitly_copyable,
legacy_modes: legacy_modes,
cstore: s.cstore,
@ -894,16 +938,25 @@ pub fn mk_ctxt(s: session::Session,
}
}
// Type constructors
fn mk_t(cx: ctxt, +st: sty) -> t { mk_t_with_id(cx, st, None) }
// Interns a type/name combination, stores the resulting box in cx.interner,
// and returns the box as cast to an unsafe ptr (see comments for t above).
fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option<ast::def_id>) -> t {
let key = intern_key { sty: to_unsafe_ptr(&st), o_def_id: o_def_id };
fn mk_t(cx: ctxt, +st: sty) -> t {
// Check for primitive types.
match st {
ty_nil => return mk_nil(cx),
ty_err => return mk_err(cx),
ty_bool => return mk_bool(cx),
ty_int(i) => return mk_mach_int(cx, i),
ty_uint(u) => return mk_mach_uint(cx, u),
ty_float(f) => return mk_mach_float(cx, f),
_ => {}
};
let key = intern_key { sty: to_unsafe_ptr(&st) };
match cx.interner.find(&key) {
Some(&t) => unsafe { return cast::reinterpret_cast(&t); },
Some(t) => unsafe { return cast::transmute(&t.sty); },
_ => ()
}
@ -973,66 +1026,116 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option<ast::def_id>) -> t {
}
}
let t = @t_box_ {
let t = ~t_box_ {
sty: st,
id: *cx.next_id,
flags: flags,
o_def_id: o_def_id
};
let sty_ptr = to_unsafe_ptr(&t.sty);
let key = intern_key {
sty: to_unsafe_ptr(&t.sty),
o_def_id: o_def_id
sty: sty_ptr,
};
cx.interner.insert(key, t);
*cx.next_id += 1;
unsafe { cast::reinterpret_cast(&t) }
unsafe {
cast::transmute::<*sty, t>(sty_ptr)
}
}
pub fn mk_nil(cx: ctxt) -> t { mk_t(cx, ty_nil) }
#[inline(always)]
pub fn mk_prim_t(cx: ctxt, primitive: &'static t_box_) -> t {
unsafe {
cast::transmute::<&'static t_box_, t>(primitive)
}
}
pub fn mk_err(cx: ctxt) -> t { mk_t(cx, ty_err) }
#[inline(always)]
pub fn mk_nil(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_NIL) }
pub fn mk_bot(cx: ctxt) -> t { mk_t(cx, ty_bot) }
#[inline(always)]
pub fn mk_err(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_ERR) }
pub fn mk_bool(cx: ctxt) -> t { mk_t(cx, ty_bool) }
#[inline(always)]
pub fn mk_bot(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_BOT) }
pub fn mk_int(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i)) }
#[inline(always)]
pub fn mk_bool(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_BOOL) }
pub fn mk_i8(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i8)) }
#[inline(always)]
pub fn mk_int(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_INT) }
pub fn mk_i16(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i16)) }
#[inline(always)]
pub fn mk_i8(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_I8) }
pub fn mk_i32(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i32)) }
#[inline(always)]
pub fn mk_i16(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_I16) }
pub fn mk_i64(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_i64)) }
#[inline(always)]
pub fn mk_i32(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_I32) }
pub fn mk_float(cx: ctxt) -> t { mk_t(cx, ty_float(ast::ty_f)) }
#[inline(always)]
pub fn mk_i64(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_I64) }
pub fn mk_uint(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u)) }
#[inline(always)]
pub fn mk_float(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_FLOAT) }
pub fn mk_u8(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u8)) }
#[inline(always)]
pub fn mk_f32(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_F32) }
pub fn mk_u16(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u16)) }
#[inline(always)]
pub fn mk_f64(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_F64) }
pub fn mk_u32(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u32)) }
#[inline(always)]
pub fn mk_uint(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_UINT) }
pub fn mk_u64(cx: ctxt) -> t { mk_t(cx, ty_uint(ast::ty_u64)) }
#[inline(always)]
pub fn mk_u8(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_U8) }
pub fn mk_f32(cx: ctxt) -> t { mk_t(cx, ty_float(ast::ty_f32)) }
#[inline(always)]
pub fn mk_u16(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_U16) }
pub fn mk_f64(cx: ctxt) -> t { mk_t(cx, ty_float(ast::ty_f64)) }
#[inline(always)]
pub fn mk_u32(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_U32) }
pub fn mk_mach_int(cx: ctxt, tm: ast::int_ty) -> t { mk_t(cx, ty_int(tm)) }
#[inline(always)]
pub fn mk_u64(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_U64) }
pub fn mk_mach_uint(cx: ctxt, tm: ast::uint_ty) -> t { mk_t(cx, ty_uint(tm)) }
pub fn mk_mach_int(cx: ctxt, tm: ast::int_ty) -> t {
match tm {
ast::ty_i => mk_int(cx),
ast::ty_char => mk_char(cx),
ast::ty_i8 => mk_i8(cx),
ast::ty_i16 => mk_i16(cx),
ast::ty_i32 => mk_i32(cx),
ast::ty_i64 => mk_i64(cx),
}
}
pub fn mk_mach_uint(cx: ctxt, tm: ast::uint_ty) -> t {
match tm {
ast::ty_u => mk_uint(cx),
ast::ty_u8 => mk_u8(cx),
ast::ty_u16 => mk_u16(cx),
ast::ty_u32 => mk_u32(cx),
ast::ty_u64 => mk_u64(cx),
}
}
pub fn mk_mach_float(cx: ctxt, tm: ast::float_ty) -> t {
mk_t(cx, ty_float(tm))
match tm {
ast::ty_f => mk_float(cx),
ast::ty_f32 => mk_f32(cx),
ast::ty_f64 => mk_f64(cx),
}
}
pub fn mk_char(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_char)) }
#[inline(always)]
pub fn mk_char(cx: ctxt) -> t { mk_prim_t(cx, &primitives::TY_CHAR) }
pub fn mk_estr(cx: ctxt, t: vstore) -> t {
mk_t(cx, ty_estr(t))
@ -1149,10 +1252,6 @@ pub fn mk_opaque_closure_ptr(cx: ctxt, sigil: ast::Sigil) -> t {
pub fn mk_opaque_box(cx: ctxt) -> t { mk_t(cx, ty_opaque_box) }
pub fn mk_with_id(cx: ctxt, base: t, def_id: ast::def_id) -> t {
mk_t_with_id(cx, /*bad*/copy get(base).sty, Some(def_id))
}
// Converts s to its machine type equivalent
pub fn mach_sty(cfg: @session::config, t: t) -> sty {
match get(t).sty {

View file

@ -1085,16 +1085,7 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item)
let region_parameterization =
RegionParameterization::from_variance_and_generics(rp, generics);
let tpt = {
let ty = {
let t0 = ccx.to_ty(&type_rscope(region_parameterization), t);
// Do not associate a def id with a named, parameterized type
// like "foo<X>". This is because otherwise ty_to_str will
// print the name as merely "foo", as it has no way to
// reconstruct the value of X.
if generics.is_parameterized() { t0 } else {
ty::mk_with_id(tcx, t0, def_id)
}
};
let ty = ccx.to_ty(&type_rscope(region_parameterization), t);
ty_param_bounds_and_ty {
generics: ty_generics(ccx, rp, generics, 0),
ty: ty

View file

@ -59,10 +59,13 @@ pub mod reader {
use ebml::{EsVec, EsVecElt, EsVecLen, TaggedDoc};
use serialize;
use core::cast::transmute;
use core::int;
use core::io;
use core::prelude::*;
use core::ptr::offset;
use core::str;
use core::unstable::intrinsics::bswap32;
use core::vec;
// ebml reading
@ -78,7 +81,8 @@ pub mod reader {
next: uint
}
fn vuint_at(data: &[u8], start: uint) -> Res {
#[inline(never)]
fn vuint_at_slow(data: &[u8], start: uint) -> Res {
let a = data[start];
if a & 0x80u8 != 0u8 {
return Res {val: (a & 0x7fu8) as uint, next: start + 1u};
@ -87,18 +91,63 @@ pub mod reader {
return Res {val: ((a & 0x3fu8) as uint) << 8u |
(data[start + 1u] as uint),
next: start + 2u};
} else if a & 0x20u8 != 0u8 {
}
if a & 0x20u8 != 0u8 {
return Res {val: ((a & 0x1fu8) as uint) << 16u |
(data[start + 1u] as uint) << 8u |
(data[start + 2u] as uint),
next: start + 3u};
} else if a & 0x10u8 != 0u8 {
}
if a & 0x10u8 != 0u8 {
return Res {val: ((a & 0x0fu8) as uint) << 24u |
(data[start + 1u] as uint) << 16u |
(data[start + 2u] as uint) << 8u |
(data[start + 3u] as uint),
next: start + 4u};
} else { error!("vint too big"); fail!(); }
}
fail!(~"vint too big");
}
#[cfg(target_arch = "x86")]
#[cfg(target_arch = "x86_64")]
pub fn vuint_at(data: &[u8], start: uint) -> Res {
if data.len() - start < 4 {
return vuint_at_slow(data, start);
}
unsafe {
let (ptr, _): (*u8, uint) = transmute(data);
let ptr = offset(ptr, start);
let ptr: *i32 = transmute(ptr);
let val = bswap32(*ptr);
let val: u32 = transmute(val);
if (val & 0x80000000) != 0 {
Res {
val: ((val >> 24) & 0x7f) as uint,
next: start + 1
}
} else if (val & 0x40000000) != 0 {
Res {
val: ((val >> 16) & 0x3fff) as uint,
next: start + 2
}
} else if (val & 0x20000000) != 0 {
Res {
val: ((val >> 8) & 0x1fffff) as uint,
next: start + 3
}
} else {
Res {
val: (val & 0x0fffffff) as uint,
next: start + 4
}
}
}
}
#[cfg(target_arch = "arm")]
pub fn vuint_at(data: &[u8], start: uint) -> Res {
vuint_at_slow(data, start)
}
pub fn Doc(data: @~[u8]) -> Doc {

View file

@ -222,7 +222,11 @@ pub fn connect(input_ip: ip::IpAddr, port: uint,
};
match connect_result {
0i32 => {
debug!("tcp_connect successful");
debug!("tcp_connect successful: \
stream %x,
socket data %x",
stream_handle_ptr as uint,
socket_data_ptr as uint);
// reusable data that we'll have for the
// duration..
uv::ll::set_data_for_uv_handle(
@ -556,13 +560,21 @@ pub fn accept(new_conn: TcpNewConnection)
server_handle_ptr as *libc::c_void,
client_stream_handle_ptr as *libc::c_void) {
0i32 => {
debug!(
"successfully accepted client \
connection");
debug!("successfully accepted client \
connection: \
stream %x, \
socket data %x",
client_stream_handle_ptr as uint,
client_socket_data_ptr as uint);
uv::ll::set_data_for_uv_handle(
client_stream_handle_ptr,
client_socket_data_ptr
as *libc::c_void);
let ptr = uv::ll::get_data_for_uv_handle(
client_stream_handle_ptr);
debug!("ptrs: %x %x",
client_socket_data_ptr as uint,
ptr as uint);
result_ch.send(None);
}
_ => {
@ -1268,14 +1280,15 @@ impl ToTcpErr for uv::ll::uv_err_data {
}
extern fn on_tcp_read_cb(stream: *uv::ll::uv_stream_t,
nread: libc::ssize_t,
buf: uv::ll::uv_buf_t) {
nread: libc::ssize_t,
buf: uv::ll::uv_buf_t) {
unsafe {
debug!("entering on_tcp_read_cb stream: %? nread: %?",
stream, nread);
debug!("entering on_tcp_read_cb stream: %x nread: %?",
stream as uint, nread);
let loop_ptr = uv::ll::get_loop_for_uv_handle(stream);
let socket_data_ptr = uv::ll::get_data_for_uv_handle(stream)
as *TcpSocketData;
debug!("socket data is %x", socket_data_ptr as uint);
match nread as int {
// incoming err.. probably eof
-1 => {

View file

@ -1156,8 +1156,7 @@ pub unsafe fn set_data_for_uv_loop(loop_ptr: *libc::c_void,
pub unsafe fn get_data_for_uv_handle<T>(handle: *T) -> *libc::c_void {
return rustrt::rust_uv_get_data_for_uv_handle(handle as *libc::c_void);
}
pub unsafe fn set_data_for_uv_handle<T, U>(handle: *T,
data: *U) {
pub unsafe fn set_data_for_uv_handle<T, U>(handle: *T, data: *U) {
rustrt::rust_uv_set_data_for_uv_handle(handle as *libc::c_void,
data as *libc::c_void);
}

View file

@ -18,9 +18,11 @@ use util::interner;
use core::cast;
use core::char;
use core::cmp::Equiv;
use core::hashmap::HashSet;
use core::str;
use core::task;
use core::to_bytes;
#[auto_encode]
#[auto_decode]
@ -355,16 +357,29 @@ pub mod special_idents {
pub static type_self: ident = ident { repr: 36u, ctxt: 0}; // `Self`
}
pub struct StringRef<'self>(&'self str);
impl<'self> Equiv<@~str> for StringRef<'self> {
#[inline(always)]
fn equiv(&self, other: &@~str) -> bool { str::eq_slice(**self, **other) }
}
impl<'self> to_bytes::IterBytes for StringRef<'self> {
fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
(**self).iter_bytes(lsb0, f);
}
}
pub struct ident_interner {
priv interner: Interner<@~str>,
}
pub impl ident_interner {
fn intern(&self, val: @~str) -> ast::ident {
ast::ident { repr: self.interner.intern(val), ctxt: 0}
ast::ident { repr: self.interner.intern(val), ctxt: 0 }
}
fn gensym(&self, val: @~str) -> ast::ident {
ast::ident { repr: self.interner.gensym(val), ctxt: 0}
ast::ident { repr: self.interner.gensym(val), ctxt: 0 }
}
fn get(&self, idx: ast::ident) -> @~str {
self.interner.get(idx.repr)
@ -372,6 +387,13 @@ pub impl ident_interner {
fn len(&self) -> uint {
self.interner.len()
}
fn find_equiv<Q:Hash + IterBytes + Equiv<@~str>>(&self, val: &Q)
-> Option<ast::ident> {
match self.interner.find_equiv(val) {
Some(v) => Some(ast::ident { repr: v, ctxt: 0 }),
None => None,
}
}
}
pub fn mk_ident_interner() -> @ident_interner {

View file

@ -16,6 +16,7 @@
#[macro_escape];
use core::prelude::*;
use core::cmp::Equiv;
use core::hashmap::HashMap;
pub struct Interner<T> {
@ -67,6 +68,14 @@ pub impl<T:Eq + IterBytes + Hash + Const + Copy> Interner<T> {
fn get(&self, idx: uint) -> T { self.vect[idx] }
fn len(&self) -> uint { let vect = &*self.vect; vect.len() }
fn find_equiv<Q:Hash + IterBytes + Equiv<T>>(&self, val: &Q)
-> Option<uint> {
match self.map.find_equiv(val) {
Some(v) => Some(*v),
None => None,
}
}
}
/* Key for thread-local data for sneaking interner information to the

View file

@ -29,6 +29,8 @@ rust_sched_loop::rust_sched_loop(rust_scheduler *sched, int id, bool killed) :
should_exit(false),
cached_c_stack(NULL),
extra_c_stack(NULL),
cached_big_stack(NULL),
extra_big_stack(NULL),
dead_task(NULL),
killed(killed),
pump_signal(NULL),
@ -263,6 +265,11 @@ rust_sched_loop::run_single_turn() {
destroy_exchange_stack(kernel->region(), cached_c_stack);
cached_c_stack = NULL;
}
assert(!extra_big_stack);
if (cached_big_stack) {
destroy_exchange_stack(kernel->region(), cached_big_stack);
cached_big_stack = NULL;
}
sched->release_task_thread();
return sched_loop_state_exit;
@ -392,6 +399,13 @@ rust_sched_loop::prepare_c_stack(rust_task *task) {
cached_c_stack = create_exchange_stack(kernel->region(),
C_STACK_SIZE);
}
assert(!extra_big_stack);
if (!cached_big_stack) {
cached_big_stack = create_exchange_stack(kernel->region(),
C_STACK_SIZE +
(C_STACK_SIZE * 2));
cached_big_stack->is_big = 1;
}
}
void
@ -400,6 +414,10 @@ rust_sched_loop::unprepare_c_stack() {
destroy_exchange_stack(kernel->region(), extra_c_stack);
extra_c_stack = NULL;
}
if (extra_big_stack) {
destroy_exchange_stack(kernel->region(), extra_big_stack);
extra_big_stack = NULL;
}
}
//

View file

@ -67,6 +67,8 @@ private:
stk_seg *cached_c_stack;
stk_seg *extra_c_stack;
stk_seg *cached_big_stack;
stk_seg *extra_big_stack;
rust_task_list running_tasks;
rust_task_list blocked_tasks;
@ -147,6 +149,10 @@ public:
stk_seg *borrow_c_stack();
void return_c_stack(stk_seg *stack);
// Called by tasks when they need a big stack
stk_seg *borrow_big_stack();
void return_big_stack(stk_seg *stack);
int get_id() { return this->id; }
};
@ -202,6 +208,32 @@ rust_sched_loop::return_c_stack(stk_seg *stack) {
}
}
// NB: Runs on the Rust stack. Might return NULL!
inline stk_seg *
rust_sched_loop::borrow_big_stack() {
assert(cached_big_stack);
stk_seg *your_stack;
if (extra_big_stack) {
your_stack = extra_big_stack;
extra_big_stack = NULL;
} else {
your_stack = cached_big_stack;
cached_big_stack = NULL;
}
return your_stack;
}
// NB: Runs on the Rust stack
inline void
rust_sched_loop::return_big_stack(stk_seg *stack) {
assert(!extra_big_stack);
assert(stack);
if (!cached_big_stack)
cached_big_stack = stack;
else
extra_big_stack = stack;
}
// this is needed to appease the circular dependency gods
#include "rust_task.h"

View file

@ -13,6 +13,8 @@
#include "vg/valgrind.h"
#include "vg/memcheck.h"
#include <cstdio>
#ifdef _LP64
const uintptr_t canary_value = 0xABCDABCDABCDABCD;
#else
@ -61,6 +63,7 @@ create_stack(memory_region *region, size_t sz) {
stk_seg *stk = (stk_seg *)region->malloc(total_sz, "stack");
memset(stk, 0, sizeof(stk_seg));
stk->end = (uintptr_t) &stk->data[sz];
stk->is_big = 0;
add_stack_canary(stk);
register_valgrind_stack(stk);
return stk;
@ -78,6 +81,7 @@ create_exchange_stack(rust_exchange_alloc *exchange, size_t sz) {
stk_seg *stk = (stk_seg *)exchange->malloc(total_sz);
memset(stk, 0, sizeof(stk_seg));
stk->end = (uintptr_t) &stk->data[sz];
stk->is_big = 0;
add_stack_canary(stk);
register_valgrind_stack(stk);
return stk;

View file

@ -22,9 +22,7 @@ struct stk_seg {
stk_seg *next;
uintptr_t end;
unsigned int valgrind_id;
#ifndef _LP64
uint32_t pad;
#endif
uint8_t is_big;
rust_task *task;
uintptr_t canary;

View file

@ -53,7 +53,8 @@ rust_task::rust_task(rust_sched_loop *sched_loop, rust_task_state state,
disallow_yield(0),
c_stack(NULL),
next_c_sp(0),
next_rust_sp(0)
next_rust_sp(0),
big_stack(NULL)
{
LOGPTR(sched_loop, "new task", (uintptr_t)this);
DLOG(sched_loop, task, "sizeof(task) = %d (0x%x)",
@ -457,8 +458,9 @@ rust_task::get_next_stack_size(size_t min, size_t current, size_t requested) {
"min: %" PRIdPTR " current: %" PRIdPTR " requested: %" PRIdPTR,
min, current, requested);
// Allocate at least enough to accomodate the next frame
size_t sz = std::max(min, requested);
// Allocate at least enough to accomodate the next frame, plus a little
// slack to avoid thrashing
size_t sz = std::max(min, requested + (requested / 2));
// And double the stack size each allocation
const size_t max = 1024 * 1024;
@ -555,13 +557,63 @@ rust_task::cleanup_after_turn() {
// Delete any spare stack segments that were left
// behind by calls to prev_stack
assert(stk);
while (stk->next) {
stk_seg *new_next = stk->next->next;
free_stack(stk->next);
if (stk->next->is_big) {
assert (big_stack == stk->next);
sched_loop->return_big_stack(big_stack);
big_stack = NULL;
} else {
free_stack(stk->next);
}
stk->next = new_next;
}
}
// NB: Runs on the Rust stack. Returns true if we successfully allocated the big
// stack and false otherwise.
bool
rust_task::new_big_stack() {
// If we have a cached big stack segment, use it.
if (big_stack) {
// Check to see if we're already on the big stack.
stk_seg *ss = stk;
while (ss != NULL) {
if (ss == big_stack)
return false;
ss = ss->prev;
}
// Unlink the big stack.
if (big_stack->next)
big_stack->next->prev = big_stack->prev;
if (big_stack->prev)
big_stack->prev->next = big_stack->next;
} else {
stk_seg *borrowed_big_stack = sched_loop->borrow_big_stack();
if (!borrowed_big_stack) {
abort();
} else {
big_stack = borrowed_big_stack;
}
}
big_stack->task = this;
big_stack->next = stk->next;
if (big_stack->next)
big_stack->next->prev = big_stack;
big_stack->prev = stk;
if (stk)
stk->next = big_stack;
stk = big_stack;
return true;
}
static bool
sp_in_stk_seg(uintptr_t sp, stk_seg *stk) {
// Not positive these bounds for sp are correct. I think that the first
@ -601,9 +653,16 @@ rust_task::delete_all_stacks() {
assert(stk->next == NULL);
while (stk != NULL) {
stk_seg *prev = stk->prev;
free_stack(stk);
if (stk->is_big)
sched_loop->return_big_stack(stk);
else
free_stack(stk);
stk = prev;
}
big_stack = NULL;
}
/*

View file

@ -133,6 +133,9 @@
#define RZ_BSD_32 (1024*20)
#define RZ_BSD_64 (1024*20)
// The threshold beyond which we switch to the C stack.
#define STACK_THRESHOLD (1024 * 1024)
#ifdef __linux__
#ifdef __i386__
#define RED_ZONE_SIZE RZ_LINUX_32
@ -263,9 +266,13 @@ private:
uintptr_t next_c_sp;
uintptr_t next_rust_sp;
// The big stack.
stk_seg *big_stack;
// Called when the atomic refcount reaches zero
void delete_this();
bool new_big_stack();
void new_stack_fast(size_t requested_sz);
void new_stack(size_t requested_sz);
void free_stack(stk_seg *stk);
@ -568,6 +575,11 @@ rust_task::new_stack_fast(size_t requested_sz) {
// The minimum stack size, in bytes, of a Rust stack, excluding red zone
size_t min_sz = sched_loop->min_stack_size;
if (requested_sz > STACK_THRESHOLD) {
if (new_big_stack())
return;
}
// Try to reuse an existing stack segment
if (stk != NULL && stk->next != NULL) {
size_t next_sz = user_stack_size(stk->next);

View file

@ -191,6 +191,14 @@ rust_upcall_malloc(type_desc *td, uintptr_t size) {
return upcall_malloc(td, size);
}
extern "C" CDECL uintptr_t
rust_upcall_malloc_noswitch(type_desc *td, uintptr_t size) {
rust_task *task = rust_get_current_task();
s_malloc_args args = {task, 0, td, size};
upcall_s_malloc(&args);
return args.retval;
}
/**********************************************************************
* Called whenever an object in the task-local heap is freed.
*/
@ -231,6 +239,13 @@ rust_upcall_free(void* ptr) {
upcall_free(ptr);
}
extern "C" CDECL void
rust_upcall_free_noswitch(void* ptr) {
rust_task *task = rust_get_current_task();
s_free_args args = {task,ptr};
upcall_s_free(&args);
}
/**********************************************************************/
extern "C" _Unwind_Reason_Code

View file

@ -401,8 +401,7 @@ rust_uv_get_data_for_uv_handle(uv_handle_t* handle) {
}
extern "C" void
rust_uv_set_data_for_uv_handle(uv_handle_t* handle,
void* data) {
rust_uv_set_data_for_uv_handle(uv_handle_t* handle, void* data) {
handle->data = data;
}

View file

@ -67,7 +67,9 @@ upcall_del_stack
upcall_reset_stack_limit
rust_upcall_fail
rust_upcall_free
rust_upcall_free_noswitch
rust_upcall_malloc
rust_upcall_malloc_noswitch
rust_uv_loop_new
rust_uv_loop_delete
rust_uv_walk

View file

@ -15,6 +15,8 @@
//
//===----------------------------------------------------------------------===
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Linker.h"
#include "llvm/PassManager.h"
#include "llvm/IR/InlineAsm.h"
@ -152,7 +154,9 @@ public:
unsigned SectionID);
virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID);
unsigned SectionID, bool isReadOnly);
virtual bool applyPermissions(std::string *Str);
virtual void *getPointerToNamedFunction(const std::string &Name,
bool AbortOnFailure = true);
@ -218,12 +222,6 @@ public:
virtual void deallocateExceptionTable(void *ET) {
llvm_unreachable("Unimplemented call");
}
virtual uint8_t* allocateDataSection(uintptr_t, unsigned int, unsigned int, bool) {
llvm_unreachable("Unimplemented call");
}
virtual bool applyPermissions(std::string*) {
llvm_unreachable("Unimplemented call");
}
};
bool RustMCJITMemoryManager::loadCrate(const char* file, std::string* err) {
@ -240,8 +238,9 @@ bool RustMCJITMemoryManager::loadCrate(const char* file, std::string* err) {
}
uint8_t *RustMCJITMemoryManager::allocateDataSection(uintptr_t Size,
unsigned Alignment,
unsigned SectionID) {
unsigned Alignment,
unsigned SectionID,
bool isReadOnly) {
if (!Alignment)
Alignment = 16;
uint8_t *Addr = (uint8_t*)calloc((Size + Alignment - 1)/Alignment, Alignment);
@ -249,9 +248,14 @@ uint8_t *RustMCJITMemoryManager::allocateDataSection(uintptr_t Size,
return Addr;
}
bool RustMCJITMemoryManager::applyPermissions(std::string *Str) {
// Empty.
return true;
}
uint8_t *RustMCJITMemoryManager::allocateCodeSection(uintptr_t Size,
unsigned Alignment,
unsigned SectionID) {
unsigned Alignment,
unsigned SectionID) {
if (!Alignment)
Alignment = 16;
unsigned NeedAllocate = Alignment * ((Size + Alignment - 1)/Alignment + 1);
@ -451,6 +455,7 @@ LLVMRustWriteOutputFile(LLVMPassManagerRef PMR,
TargetOptions Options;
Options.NoFramePointerElim = true;
Options.EnableSegmentedStacks = EnableSegmentedStacks;
Options.FixedStackSegmentSize = 2 * 1024 * 1024; // XXX: This is too big.
PassManager *PM = unwrap<PassManager>(PMR);
@ -484,13 +489,12 @@ LLVMRustWriteOutputFile(LLVMPassManagerRef PMR,
}
extern "C" LLVMModuleRef LLVMRustParseAssemblyFile(const char *Filename) {
SMDiagnostic d;
Module *m = ParseAssemblyFile(Filename, d, getGlobalContext());
if (m) {
return wrap(m);
} else {
LLVMRustError = d.getMessage().data();
LLVMRustError = d.getMessage().str().c_str();
return NULL;
}
}

View file

@ -88,6 +88,7 @@ fn vector<M: Map<uint, uint>>(map: &mut M, n_keys: uint, dist: &[uint]) {
}
}
#[fixed_stack_segment]
fn main() {
let args = os::args();
let n_keys = {

View file

@ -0,0 +1,95 @@
use core::from_str::FromStr;
use core::i32::range;
use core::vec::MutableVector;
fn max(a: i32, b: i32) -> i32 {
if a > b {
a
} else {
b
}
}
#[inline(never)]
fn fannkuch_redux(n: i32) -> i32 {
let mut perm = vec::from_elem(n as uint, 0i32);
let mut perm1 = vec::from_fn(n as uint, |i| i as i32);
let mut count = vec::from_elem(n as uint, 0i32);
let mut max_flips_count = 0i32, perm_count = 0i32, checksum = 0i32;
let mut r = n;
loop {
unsafe {
while r != 1 {
count.unsafe_set((r-1) as uint, r);
r -= 1;
}
// XXX: Need each2_mut.
for vec::eachi_mut(perm) |i, perm_i| {
*perm_i = perm1.unsafe_get(i);
}
let mut flips_count: i32 = 0;
let mut k: i32;
loop {
k = perm.unsafe_get(0);
if k == 0 {
break;
}
let k2 = (k+1) >> 1;
for range(0, k2) |i| {
let (perm_i, perm_k_i) = {
(perm.unsafe_get(i as uint),
perm.unsafe_get((k-i) as uint))
};
perm.unsafe_set(i as uint, perm_k_i);
perm.unsafe_set((k-i) as uint, perm_i);
}
flips_count += 1;
}
max_flips_count = max(max_flips_count, flips_count);
checksum += if perm_count % 2 == 0 {
flips_count
} else {
-flips_count
};
// Use incremental change to generate another permutation.
loop {
if r == n {
println(checksum.to_str());
return max_flips_count;
}
let perm0 = perm1[0];
let mut i: i32 = 0;
while i < r {
let j = i + 1;
let perm1_j = { perm1.unsafe_get(j as uint) };
perm1.unsafe_set(i as uint, perm1_j);
i = j;
}
perm1.unsafe_set(r as uint, perm0);
let count_r = { count.unsafe_get(r as uint) };
count.unsafe_set(r as uint, count_r - 1);
if count.unsafe_get(r as uint) > 0 {
break;
}
r += 1;
}
perm_count += 1;
}
}
}
#[fixed_stack_segment]
fn main() {
let n: i32 = FromStr::from_str(os::args()[1]).get();
println(fmt!("Pfannkuchen(%d) = %d", n as int, fannkuch_redux(n) as int));
}

View file

@ -1,81 +0,0 @@
// Copyright 2012 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.
// Based on Isaac Gouy's fannkuchredux.csharp
extern mod std;
fn fannkuch(n: int) -> int {
fn perm1init(i: uint) -> int { return i as int; }
let mut perm = vec::from_elem(n as uint, 0);
let mut perm1 = vec::from_fn(n as uint, |i| perm1init(i));
let mut count = vec::from_elem(n as uint, 0);
let mut f = 0;
let mut i = 0;
let mut k = 0;
let mut r = 0;
let mut flips = 0;
let mut nperm = 0;
let mut checksum = 0;
r = n;
while r > 0 {
i = 0;
while r != 1 { count[r - 1] = r; r -= 1; }
while i < n { perm[i] = perm1[i]; i += 1; }
// Count flips and update max and checksum
f = 0;
k = perm[0];
while k != 0 {
i = 0;
while 2 * i < k {
let t = perm[i];
perm[i] = perm[k - i];
perm[k - i] = t;
i += 1;
}
k = perm[0];
f += 1;
}
if f > flips { flips = f; }
if nperm & 0x1 == 0 { checksum += f; } else { checksum -= f; }
// Use incremental change to generate another permutation
let mut go = true;
while go {
if r == n {
io::println(fmt!("%d", checksum));
return flips;
}
let p0 = perm1[0];
i = 0;
while i < r { let j = i + 1; perm1[i] = perm1[j]; i = j; }
perm1[r] = p0;
count[r] -= 1;
if count[r] > 0 { go = false; } else { r += 1; }
}
nperm += 1;
}
return flips;
}
fn main() {
let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"10"]
} else if args.len() <= 1u {
~[~"", ~"8"]
} else {
args
};
let n = int::from_str(args[1]).get();
io::println(fmt!("Pfannkuchen(%d) = %d", n, fannkuch(n)));
}

View file

@ -0,0 +1,204 @@
use core::cast::transmute;
use core::from_str::FromStr;
use core::libc::{FILE, STDOUT_FILENO, c_int, fdopen, fputc, fputs, fwrite};
use core::uint::{min, range};
use core::vec::bytes::copy_memory;
static LINE_LEN: uint = 60;
static LOOKUP_SIZE: uint = 4 * 1024;
static LOOKUP_SCALE: f32 = (LOOKUP_SIZE - 1) as f32;
// Random number generator constants
static IM: u32 = 139968;
static IA: u32 = 3877;
static IC: u32 = 29573;
static ALU: &'static str = "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTG\
GGAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGA\
GACCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAA\
AATACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAAT\
CCCAGCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAAC\
CCGGGAGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTG\
CACTCCAGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA";
static NULL_AMINO_ACID: AminoAcid = AminoAcid { c: ' ' as u8, p: 0.0 };
static MESSAGE_1: &'static str = ">ONE Homo sapiens alu\n";
static MESSAGE_2: &'static str = ">TWO IUB ambiguity codes\n";
static MESSAGE_3: &'static str = ">THREE Homo sapiens frequency\n";
static IUB: [AminoAcid, ..15] = [
AminoAcid { c: 'a' as u8, p: 0.27 },
AminoAcid { c: 'c' as u8, p: 0.12 },
AminoAcid { c: 'g' as u8, p: 0.12 },
AminoAcid { c: 't' as u8, p: 0.27 },
AminoAcid { c: 'B' as u8, p: 0.02 },
AminoAcid { c: 'D' as u8, p: 0.02 },
AminoAcid { c: 'H' as u8, p: 0.02 },
AminoAcid { c: 'K' as u8, p: 0.02 },
AminoAcid { c: 'M' as u8, p: 0.02 },
AminoAcid { c: 'N' as u8, p: 0.02 },
AminoAcid { c: 'R' as u8, p: 0.02 },
AminoAcid { c: 'S' as u8, p: 0.02 },
AminoAcid { c: 'V' as u8, p: 0.02 },
AminoAcid { c: 'W' as u8, p: 0.02 },
AminoAcid { c: 'Y' as u8, p: 0.02 },
];
static HOMO_SAPIENS: [AminoAcid, ..4] = [
AminoAcid { c: 'a' as u8, p: 0.3029549426680 },
AminoAcid { c: 'c' as u8, p: 0.1979883004921 },
AminoAcid { c: 'g' as u8, p: 0.1975473066391 },
AminoAcid { c: 't' as u8, p: 0.3015094502008 },
];
// XXX: Use map().
fn sum_and_scale(a: &'static [AminoAcid]) -> ~[AminoAcid] {
let mut result = ~[];
let mut p = 0f32;
for a.each |a_i| {
let mut a_i = *a_i;
p += a_i.p;
a_i.p = p * LOOKUP_SCALE;
result.push(a_i);
}
result[result.len() - 1].p = LOOKUP_SCALE;
result
}
struct AminoAcid {
c: u8,
p: f32,
}
struct RepeatFasta {
alu: &'static str,
stdout: *FILE,
}
impl RepeatFasta {
fn new(stdout: *FILE, alu: &'static str) -> RepeatFasta {
RepeatFasta {
alu: alu,
stdout: stdout,
}
}
fn make(&mut self, n: uint) {
unsafe {
let stdout = self.stdout;
let alu_len = self.alu.len();
let mut buf = vec::from_elem(alu_len + LINE_LEN, 0u8);
let alu: &[u8] = str::byte_slice_no_callback(self.alu);
copy_memory(buf, alu, alu_len);
copy_memory(vec::mut_slice(buf, alu_len, buf.len()),
alu,
LINE_LEN);
let mut pos = 0, bytes, n = n;
while n > 0 {
bytes = min(LINE_LEN, n);
fwrite(transmute(&buf[pos]), bytes as u64, 1, stdout);
fputc('\n' as c_int, stdout);
pos += bytes;
if pos > alu_len {
pos -= alu_len;
}
n -= bytes;
}
}
}
}
struct RandomFasta {
seed: u32,
stdout: *FILE,
lookup: [AminoAcid, ..LOOKUP_SIZE],
}
impl RandomFasta {
fn new(stdout: *FILE, a: &[AminoAcid]) -> RandomFasta {
RandomFasta {
seed: 42,
stdout: stdout,
lookup: RandomFasta::make_lookup(a),
}
}
fn make_lookup(a: &[AminoAcid]) -> [AminoAcid, ..LOOKUP_SIZE] {
let mut lookup = [ NULL_AMINO_ACID, ..LOOKUP_SIZE ];
let mut j = 0;
for vec::eachi_mut(lookup) |i, slot| {
while a[j].p < (i as f32) {
j += 1;
}
*slot = a[j];
}
lookup
}
fn rng(&mut self, max: f32) -> f32 {
self.seed = (self.seed * IA + IC) % IM;
max * (self.seed as f32) / (IM as f32)
}
fn nextc(&mut self) -> u8 {
let r = self.rng(1.0);
for self.lookup.each |a| {
if a.p >= r {
return a.c;
}
}
0
}
fn make(&mut self, n: uint) {
unsafe {
let lines = n / LINE_LEN, chars_left = n % LINE_LEN;
let mut buf = [0, ..LINE_LEN + 1];
for lines.times {
for range(0, LINE_LEN) |i| {
buf[i] = self.nextc();
}
buf[LINE_LEN] = '\n' as u8;
fwrite(transmute(&buf[0]),
LINE_LEN as u64 + 1,
1,
self.stdout);
}
for range(0, chars_left) |i| {
buf[i] = self.nextc();
}
fwrite(transmute(&buf[0]), chars_left as u64, 1, self.stdout);
}
}
}
#[fixed_stack_segment]
fn main() {
let n: uint = FromStr::from_str(os::args()[1]).get();
unsafe {
let mode = "w";
let stdout = fdopen(STDOUT_FILENO as c_int, transmute(&mode[0]));
fputs(transmute(&MESSAGE_1[0]), stdout);
let mut repeat = RepeatFasta::new(stdout, ALU);
repeat.make(n * 2);
fputs(transmute(&MESSAGE_2[0]), stdout);
let iub = sum_and_scale(IUB);
let mut random = RandomFasta::new(stdout, iub);
random.make(n * 3);
fputs(transmute(&MESSAGE_3[0]), stdout);
let homo_sapiens = sum_and_scale(HOMO_SAPIENS);
random.lookup = RandomFasta::make_lookup(homo_sapiens);
random.make(n * 5);
fputc('\n' as c_int, stdout);
}
}

View file

@ -0,0 +1,316 @@
// xfail-test
extern mod std;
use core::cast::transmute;
use core::i32::range;
use core::libc::{STDIN_FILENO, c_int, fdopen, fgets, fileno, fopen, fstat};
use core::libc::{stat, strlen};
use core::ptr::null;
use core::unstable::intrinsics::init;
use core::vec::{reverse, slice};
use std::sort::quick_sort3;
static LINE_LEN: uint = 80;
static TABLE: [u8, ..4] = [ 'A' as u8, 'C' as u8, 'G' as u8, 'T' as u8 ];
static TABLE_SIZE: uint = 2 << 16;
static OCCURRENCES: [&'static str, ..5] = [
"GGT",
"GGTA",
"GGTATT",
"GGTATTTTAATT",
"GGTATTTTAATTTATAGT",
];
// Code implementation
#[deriving(Eq, Ord)]
struct Code(u64);
impl Code {
fn hash(&self) -> u64 {
**self
}
#[inline(always)]
fn push_char(&self, c: u8) -> Code {
Code((**self << 2) + (pack_symbol(c) as u64))
}
fn rotate(&self, c: u8, frame: i32) -> Code {
Code(*self.push_char(c) & ((1u64 << (2 * (frame as u64))) - 1))
}
fn pack(string: &str) -> Code {
let mut code = Code(0u64);
for uint::range(0, string.len()) |i| {
code = code.push_char(string[i]);
}
code
}
// XXX: Inefficient.
fn unpack(&self, frame: i32) -> ~str {
let mut key = **self;
let mut result = ~[];
for (frame as uint).times {
result.push(unpack_symbol((key as u8) & 3));
key >>= 2;
}
reverse(result);
str::from_bytes(result)
}
}
// Hash table implementation
trait TableCallback {
fn f(&self, entry: &mut Entry);
}
struct BumpCallback;
impl TableCallback for BumpCallback {
fn f(&self, entry: &mut Entry) {
entry.count += 1;
}
}
struct PrintCallback(&'static str);
impl TableCallback for PrintCallback {
fn f(&self, entry: &mut Entry) {
println(fmt!("%d\t%s", entry.count as int, **self));
}
}
struct Entry {
code: Code,
count: i32,
next: Option<~Entry>,
}
struct Table {
count: i32,
items: [Option<~Entry>, ..TABLE_SIZE]
}
impl Table {
fn new() -> Table {
Table {
count: 0,
items: [ None, ..TABLE_SIZE ],
}
}
fn search_remainder<C:TableCallback>(item: &mut Entry, key: Code, c: C) {
match item.next {
None => {
let mut entry = ~Entry {
code: key,
count: 0,
next: None,
};
c.f(entry);
item.next = Some(entry);
}
Some(ref mut entry) => {
if entry.code == key {
c.f(*entry);
return;
}
Table::search_remainder(*entry, key, c)
}
}
}
fn lookup<C:TableCallback>(&mut self, key: Code, c: C) {
let index = *key % (TABLE_SIZE as u64);
{
if self.items[index].is_none() {
let mut entry = ~Entry {
code: key,
count: 0,
next: None,
};
c.f(entry);
self.items[index] = Some(entry);
return;
}
}
{
let mut entry = &mut *self.items[index].get_mut_ref();
if entry.code == key {
c.f(*entry);
return;
}
Table::search_remainder(*entry, key, c)
}
}
fn each(&self, f: &fn(entry: &Entry) -> bool) {
for self.items.each |item| {
match *item {
None => {}
Some(ref item) => {
let mut item: &Entry = *item;
loop {
if !f(item) {
return;
}
match item.next {
None => break,
Some(ref next_item) => item = &**next_item,
}
}
}
};
}
}
}
// Main program
fn pack_symbol(c: u8) -> u8 {
match c {
'a' as u8 | 'A' as u8 => 0,
'c' as u8 | 'C' as u8 => 1,
'g' as u8 | 'G' as u8 => 2,
't' as u8 | 'T' as u8 => 3,
_ => fail!(c.to_str())
}
}
fn unpack_symbol(c: u8) -> u8 {
TABLE[c]
}
fn next_char<'a>(mut buf: &'a [u8]) -> &'a [u8] {
loop {
buf = slice(buf, 1, buf.len());
if buf.len() == 0 {
break;
}
if buf[0] != (' ' as u8) && buf[0] != ('\t' as u8) &&
buf[0] != ('\n' as u8) && buf[0] != 0 {
break;
}
}
buf
}
#[inline(never)]
fn read_stdin() -> ~[u8] {
unsafe {
let mode = "r";
//let stdin = fdopen(STDIN_FILENO as c_int, transmute(&mode[0]));
let path = "knucleotide-input.txt";
let stdin = fopen(transmute(&path[0]), transmute(&mode[0]));
let mut st: stat = init();
fstat(fileno(stdin), &mut st);
let mut buf = vec::from_elem(st.st_size as uint, 0);
let header = str::byte_slice_no_callback(">THREE");
let header = vec::slice(header, 0, 6);
{
let mut window: &mut [u8] = buf;
loop {
fgets(transmute(&mut window[0]), LINE_LEN as c_int, stdin);
{
if vec::slice(window, 0, 6) == header {
break;
}
}
}
while fgets(transmute(&mut window[0]),
LINE_LEN as c_int,
stdin) != null() {
window = vec::mut_slice(window,
strlen(transmute(&window[0])) as uint,
window.len());
}
}
buf
}
}
#[inline(never)]
#[fixed_stack_segment]
fn generate_frequencies(frequencies: &mut Table,
mut input: &[u8],
frame: i32) {
let mut code = Code(0);
// Pull first frame.
for (frame as uint).times {
code = code.push_char(input[0]);
input = next_char(input);
}
frequencies.lookup(code, BumpCallback);
while input.len() != 0 && input[0] != ('>' as u8) {
code = code.rotate(input[0], frame);
frequencies.lookup(code, BumpCallback);
input = next_char(input);
}
}
#[inline(never)]
#[fixed_stack_segment]
fn print_frequencies(frequencies: &Table, frame: i32) {
let mut vector = ~[];
for frequencies.each |entry| {
vector.push((entry.code, entry.count));
}
quick_sort3(vector);
let mut total_count = 0;
for vector.each |&(_, count)| {
total_count += count;
}
for vector.each |&(key, count)| {
println(fmt!("%s %.3f",
key.unpack(frame),
(count as float * 100.0) / (total_count as float)));
}
}
fn print_occurrences(frequencies: &mut Table, occurrence: &'static str) {
frequencies.lookup(Code::pack(occurrence), PrintCallback(occurrence))
}
#[fixed_stack_segment]
fn main() {
let input = read_stdin();
let mut frequencies = ~Table::new();
generate_frequencies(frequencies, input, 1);
print_frequencies(frequencies, 1);
*frequencies = Table::new();
generate_frequencies(frequencies, input, 2);
print_frequencies(frequencies, 2);
for range(0, 5) |i| {
let occurrence = OCCURRENCES[i];
*frequencies = Table::new();
generate_frequencies(frequencies,
input,
occurrence.len() as i32);
print_occurrences(frequencies, occurrence);
}
}

View file

@ -1,182 +1,60 @@
// Copyright 2012-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.
use core::cast::transmute;
use core::from_str::FromStr;
use core::i32::range;
use core::libc::{STDOUT_FILENO, c_int, fdopen, fputc};
// based on:
// http://shootout.alioth.debian.org/
// u64q/program.php?test=mandelbrot&lang=python3&id=2
//
// takes 3 optional args:
// square image size, defaults to 80_u
// output path, default is "" (no output), "-" means stdout
// depth (max iterations per pixel), defaults to 50_u
//
// in the shootout, they use 16000 as image size, 50 as depth,
// and write to stdout:
//
// ./shootout_mandelbrot 16000 "-" 50 > /tmp/mandel.pbm
//
// writes pbm image to output path
use core::io::WriterUtil;
use core::hashmap::HashMap;
struct cmplx {
re: f64,
im: f64
}
impl ops::Mul<cmplx,cmplx> for cmplx {
fn mul(&self, x: &cmplx) -> cmplx {
cmplx {
re: self.re*(*x).re - self.im*(*x).im,
im: self.re*(*x).im + self.im*(*x).re
}
}
}
impl ops::Add<cmplx,cmplx> for cmplx {
fn add(&self, x: &cmplx) -> cmplx {
cmplx {
re: self.re + (*x).re,
im: self.im + (*x).im
}
}
}
struct Line {i: uint, b: ~[u8]}
fn cabs(x: cmplx) -> f64
{
x.re*x.re + x.im*x.im
}
fn mb(x: cmplx, depth: uint) -> bool
{
let mut z = x;
let mut i = 0;
while i < depth {
if cabs(z) >= 4_f64 {
return false;
}
z = z*z + x;
i += 1;
}
true
}
fn fillbyte(x: cmplx, incr: f64, depth: uint) -> u8 {
let mut rv = 0_u8;
let mut i = 0_u8;
while i < 8_u8 {
let z = cmplx {re: x.re + (i as f64)*incr, im: x.im};
if mb(z, depth) {
rv += 1_u8 << (7_u8 - i);
}
i += 1_u8;
}
rv
}
fn chanmb(i: uint, size: uint, depth: uint) -> Line
{
let bsize = size/8_u;
let mut crv = vec::with_capacity(bsize);
let incr = 2_f64/(size as f64);
let y = incr*(i as f64) - 1_f64;
let xincr = 8_f64*incr;
for uint::range(0_u, bsize) |j| {
let x = cmplx {re: xincr*(j as f64) - 1.5_f64, im: y};
crv.push(fillbyte(x, incr, depth));
};
Line {i:i, b:crv}
}
struct Devnull();
impl io::Writer for Devnull {
fn write(&self, _b: &const [u8]) {}
fn seek(&self, _i: int, _s: io::SeekStyle) {}
fn tell(&self) -> uint {0_u}
fn flush(&self) -> int {0}
fn get_type(&self) -> io::WriterType { io::File }
}
fn writer(path: ~str, pport: comm::Port<Line>, size: uint)
{
let cout: @io::Writer = match path {
~"" => {
@Devnull as @io::Writer
}
~"-" => {
io::stdout()
}
_ => {
result::get(
&io::file_writer(&Path(path),
~[io::Create, io::Truncate]))
}
};
cout.write_line("P4");
cout.write_line(fmt!("%u %u", size, size));
let mut lines: HashMap<uint, Line> = HashMap::new();
let mut done = 0_u;
let mut i = 0_u;
while i < size {
let aline = pport.recv();
if aline.i == done {
debug!("W %u", done);
cout.write(aline.b);
done += 1_u;
let mut prev = done;
while prev <= i {
match lines.pop(&prev) {
Some(pl) => {
debug!("WS %u", prev);
cout.write(pl.b);
done += 1_u;
prev += 1_u;
}
None => break
};
};
}
else {
debug!("S %u", aline.i);
lines.insert(aline.i, aline);
};
i += 1_u;
}
}
static ITER: uint = 50;
static LIMIT: f64 = 2.0;
#[fixed_stack_segment]
fn main() {
let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"4000", ~"50"]
} else {
args
};
unsafe {
let w: i32 = FromStr::from_str(os::args()[1]).get(), h = w;
let mut byte_acc: i8 = 0;
let mut bit_num: i32 = 0;
let depth = if vec::len(args) < 4_u { 50_u }
else { uint::from_str(args[3]).get() };
println(fmt!("P4\n%d %d", w as int, h as int));
let path = if vec::len(args) < 3_u { ~"" }
else { copy args[2] }; // FIXME: bad for perf
let mode = "w";
let stdout = fdopen(STDOUT_FILENO as c_int, transmute(&mode[0]));
let size = if vec::len(args) < 2_u { 80_u }
else { uint::from_str(args[1]).get() };
for range(0, h) |y| {
let y = y as f64;
for range(0, w) |x| {
let mut (Zr, Zi, Tr, Ti) = (0f64, 0f64, 0f64, 0f64);
let Cr = 2.0 * (x as f64) / (w as f64) - 1.5;
let Ci = 2.0 * (y as f64) / (h as f64) - 1.0;
let (pport, pchan) = comm::stream();
let pchan = comm::SharedChan::new(pchan);
for uint::range(0_u, size) |j| {
let cchan = pchan.clone();
do task::spawn { cchan.send(chanmb(j, size, depth)) };
};
writer(path, pport, size);
for ITER.times {
if Tr + Ti > LIMIT * LIMIT {
break;
}
Zi = 2.0*Zr*Zi + Ci;
Zr = Tr - Ti + Cr;
Tr = Zr * Zr;
Ti = Zi * Zi;
}
byte_acc <<= 1;
if Tr + Ti <= LIMIT * LIMIT {
byte_acc |= 1;
}
bit_num += 1;
if bit_num == 8 {
fputc(byte_acc as c_int, stdout);
byte_acc = 0;
bit_num = 0;
} else if x == w - 1 {
byte_acc <<= 8 - w%8;
fputc(byte_acc as c_int, stdout);
byte_acc = 0;
bit_num = 0;
}
}
}
}
}

View file

@ -1,254 +1,150 @@
// Copyright 2012 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.
use core::from_str::FromStr;
use core::uint::range;
use core::unstable::intrinsics::sqrtf64;
// based on:
// http://shootout.alioth.debian.org/u32/benchmark.php?test=nbody&lang=java
static PI: f64 = 3.141592653589793;
static SOLAR_MASS: f64 = 4.0 * PI * PI;
static YEAR: f64 = 365.24;
static N_BODIES: uint = 5;
extern mod std;
static BODIES: [Planet, ..N_BODIES] = [
// Sun
Planet {
x: [ 0.0, 0.0, 0.0 ],
v: [ 0.0, 0.0, 0.0 ],
mass: SOLAR_MASS,
},
// Jupiter
Planet {
x: [
4.84143144246472090e+00,
-1.16032004402742839e+00,
-1.03622044471123109e-01,
],
v: [
1.66007664274403694e-03 * YEAR,
7.69901118419740425e-03 * YEAR,
-6.90460016972063023e-05 * YEAR,
],
mass: 9.54791938424326609e-04 * SOLAR_MASS,
},
// Saturn
Planet {
x: [
8.34336671824457987e+00,
4.12479856412430479e+00,
-4.03523417114321381e-01,
],
v: [
-2.76742510726862411e-03 * YEAR,
4.99852801234917238e-03 * YEAR,
2.30417297573763929e-05 * YEAR,
],
mass: 2.85885980666130812e-04 * SOLAR_MASS,
},
// Uranus
Planet {
x: [
1.28943695621391310e+01,
-1.51111514016986312e+01,
-2.23307578892655734e-01,
],
v: [
2.96460137564761618e-03 * YEAR,
2.37847173959480950e-03 * YEAR,
-2.96589568540237556e-05 * YEAR,
],
mass: 4.36624404335156298e-05 * SOLAR_MASS,
},
// Neptune
Planet {
x: [
1.53796971148509165e+01,
-2.59193146099879641e+01,
1.79258772950371181e-01,
],
v: [
2.68067772490389322e-03 * YEAR,
1.62824170038242295e-03 * YEAR,
-9.51592254519715870e-05 * YEAR,
],
mass: 5.15138902046611451e-05 * SOLAR_MASS,
},
];
use core::os;
struct Planet {
x: [f64, ..3],
v: [f64, ..3],
mass: f64,
}
// Using sqrt from the standard library is way slower than using libc
// directly even though std just calls libc, I guess it must be
// because the the indirection through another dynamic linker
// stub. Kind of shocking. Might be able to make it faster still with
// an llvm intrinsic.
mod libc {
#[nolink]
pub extern {
pub fn sqrt(n: float) -> float;
fn advance(bodies: &mut [Planet, ..N_BODIES], dt: f64, steps: i32) {
let mut d = [ 0.0, ..3 ];
for (steps as uint).times {
for range(0, N_BODIES) |i| {
for range(i + 1, N_BODIES) |j| {
d[0] = bodies[i].x[0] - bodies[j].x[0];
d[1] = bodies[i].x[1] - bodies[j].x[1];
d[2] = bodies[i].x[2] - bodies[j].x[2];
let d2 = d[0]*d[0] + d[1]*d[1] + d[2]*d[2];
let mag = dt / (d2 * sqrtf64(d2));
let a_mass = bodies[i].mass, b_mass = bodies[j].mass;
bodies[i].v[0] -= d[0] * b_mass * mag;
bodies[i].v[1] -= d[1] * b_mass * mag;
bodies[i].v[2] -= d[2] * b_mass * mag;
bodies[j].v[0] += d[0] * a_mass * mag;
bodies[j].v[1] += d[1] * a_mass * mag;
bodies[j].v[2] += d[2] * a_mass * mag;
}
}
for vec::each_mut(*bodies) |a| {
a.x[0] += dt * a.v[0];
a.x[1] += dt * a.v[1];
a.x[2] += dt * a.v[2];
}
}
}
fn energy(bodies: &[Planet, ..N_BODIES]) -> f64 {
let mut e = 0.0;
let mut d = [ 0.0, ..3 ];
for range(0, N_BODIES) |i| {
for range(0, 3) |k| {
e += bodies[i].mass * bodies[i].v[k] * bodies[i].v[k] / 2.0;
}
for range(i + 1, N_BODIES) |j| {
for range(0, 3) |k| {
d[k] = bodies[i].x[k] - bodies[j].x[k];
}
let dist = sqrtf64(d[0]*d[0] + d[1]*d[1] + d[2]*d[2]);
e -= bodies[i].mass * bodies[j].mass / dist;
}
}
e
}
fn offset_momentum(bodies: &mut [Planet, ..N_BODIES]) {
for range(0, N_BODIES) |i| {
for range(0, 3) |k| {
bodies[0].v[k] -= bodies[i].v[k] * bodies[i].mass / SOLAR_MASS;
}
}
}
fn main() {
let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"4000000"]
} else if args.len() <= 1u {
~[~"", ~"100000"]
} else {
args
};
let n = int::from_str(args[1]).get();
let mut bodies: ~[Body::Props] = NBodySystem::make();
io::println(fmt!("%f", NBodySystem::energy(bodies)));
let mut i = 0;
while i < n {
NBodySystem::advance(bodies, 0.01);
i += 1;
}
io::println(fmt!("%f", NBodySystem::energy(bodies)));
let n: i32 = FromStr::from_str(os::args()[1]).get();
let mut bodies = BODIES;
offset_momentum(&mut bodies);
println(fmt!("%.9f", energy(&bodies) as float));
advance(&mut bodies, 0.01, n);
println(fmt!("%.9f", energy(&bodies) as float));
}
pub mod NBodySystem {
use Body;
pub fn make() -> ~[Body::Props] {
let mut bodies: ~[Body::Props] =
~[Body::sun(),
Body::jupiter(),
Body::saturn(),
Body::uranus(),
Body::neptune()];
let mut px = 0.0;
let mut py = 0.0;
let mut pz = 0.0;
let mut i = 0;
while i < 5 {
px += bodies[i].vx * bodies[i].mass;
py += bodies[i].vy * bodies[i].mass;
pz += bodies[i].vz * bodies[i].mass;
i += 1;
}
// side-effecting
Body::offset_momentum(&mut bodies[0], px, py, pz);
return bodies;
}
pub fn advance(bodies: &mut [Body::Props], dt: float) {
let mut i = 0;
while i < 5 {
let mut j = i + 1;
while j < 5 {
advance_one(&mut bodies[i],
&mut bodies[j], dt);
j += 1;
}
i += 1;
}
i = 0;
while i < 5 {
move_(&mut bodies[i], dt);
i += 1;
}
}
pub fn advance_one(bi: &mut Body::Props,
bj: &mut Body::Props,
dt: float) {
unsafe {
let dx = bi.x - bj.x;
let dy = bi.y - bj.y;
let dz = bi.z - bj.z;
let dSquared = dx * dx + dy * dy + dz * dz;
let distance = ::libc::sqrt(dSquared);
let mag = dt / (dSquared * distance);
bi.vx -= dx * bj.mass * mag;
bi.vy -= dy * bj.mass * mag;
bi.vz -= dz * bj.mass * mag;
bj.vx += dx * bi.mass * mag;
bj.vy += dy * bi.mass * mag;
bj.vz += dz * bi.mass * mag;
}
}
pub fn move_(b: &mut Body::Props, dt: float) {
b.x += dt * b.vx;
b.y += dt * b.vy;
b.z += dt * b.vz;
}
pub fn energy(bodies: &[Body::Props]) -> float {
unsafe {
let mut dx;
let mut dy;
let mut dz;
let mut distance;
let mut e = 0.0;
let mut i = 0;
while i < 5 {
e +=
0.5 * bodies[i].mass *
(bodies[i].vx * bodies[i].vx
+ bodies[i].vy * bodies[i].vy
+ bodies[i].vz * bodies[i].vz);
let mut j = i + 1;
while j < 5 {
dx = bodies[i].x - bodies[j].x;
dy = bodies[i].y - bodies[j].y;
dz = bodies[i].z - bodies[j].z;
distance = ::libc::sqrt(dx * dx
+ dy * dy
+ dz * dz);
e -= bodies[i].mass
* bodies[j].mass / distance;
j += 1;
}
i += 1;
}
return e;
}
}
}
pub mod Body {
use Body;
pub static PI: float = 3.141592653589793;
pub static SOLAR_MASS: float = 39.478417604357432;
// was 4 * PI * PI originally
pub static DAYS_PER_YEAR: float = 365.24;
pub struct Props {
x: float,
y: float,
z: float,
vx: float,
vy: float,
vz: float,
mass: float
}
pub fn jupiter() -> Body::Props {
return Props {
x: 4.84143144246472090e+00,
y: -1.16032004402742839e+00,
z: -1.03622044471123109e-01,
vx: 1.66007664274403694e-03 * DAYS_PER_YEAR,
vy: 7.69901118419740425e-03 * DAYS_PER_YEAR,
vz: -6.90460016972063023e-05 * DAYS_PER_YEAR,
mass: 9.54791938424326609e-04 * SOLAR_MASS
};
}
pub fn saturn() -> Body::Props {
return Props {
x: 8.34336671824457987e+00,
y: 4.12479856412430479e+00,
z: -4.03523417114321381e-01,
vx: -2.76742510726862411e-03 * DAYS_PER_YEAR,
vy: 4.99852801234917238e-03 * DAYS_PER_YEAR,
vz: 2.30417297573763929e-05 * DAYS_PER_YEAR,
mass: 2.85885980666130812e-04 * SOLAR_MASS
};
}
pub fn uranus() -> Body::Props {
return Props {
x: 1.28943695621391310e+01,
y: -1.51111514016986312e+01,
z: -2.23307578892655734e-01,
vx: 2.96460137564761618e-03 * DAYS_PER_YEAR,
vy: 2.37847173959480950e-03 * DAYS_PER_YEAR,
vz: -2.96589568540237556e-05 * DAYS_PER_YEAR,
mass: 4.36624404335156298e-05 * SOLAR_MASS
};
}
pub fn neptune() -> Body::Props {
return Props {
x: 1.53796971148509165e+01,
y: -2.59193146099879641e+01,
z: 1.79258772950371181e-01,
vx: 2.68067772490389322e-03 * DAYS_PER_YEAR,
vy: 1.62824170038242295e-03 * DAYS_PER_YEAR,
vz: -9.51592254519715870e-05 * DAYS_PER_YEAR,
mass: 5.15138902046611451e-05 * SOLAR_MASS
};
}
pub fn sun() -> Body::Props {
return Props {
x: 0.0,
y: 0.0,
z: 0.0,
vx: 0.0,
vy: 0.0,
vz: 0.0,
mass: SOLAR_MASS
};
}
pub fn offset_momentum(props: &mut Body::Props,
px: float,
py: float,
pz: float) {
props.vx = -px / SOLAR_MASS;
props.vy = -py / SOLAR_MASS;
props.vz = -pz / SOLAR_MASS;
}
}

View file

@ -0,0 +1,178 @@
// xfail-test
use core::cast::transmute;
use core::from_str::FromStr;
use core::libc::{STDOUT_FILENO, c_char, c_int, c_uint, c_void, fdopen, fputc};
use core::libc::{fputs};
use core::ptr::null;
struct mpz_t {
_mp_alloc: c_int,
_mp_size: c_int,
_mp_limb_t: *c_void,
}
impl mpz_t {
fn new() -> mpz_t {
mpz_t {
_mp_alloc: 0,
_mp_size: 0,
_mp_limb_t: null(),
}
}
}
#[link_args="-lgmp"]
extern {
#[fast_ffi]
#[link_name="__gmpz_add"]
fn mpz_add(x: *mpz_t, y: *mpz_t, z: *mpz_t);
#[fast_ffi]
#[link_name="__gmpz_cmp"]
fn mpz_cmp(x: *mpz_t, y: *mpz_t) -> c_int;
#[fast_ffi]
#[link_name="__gmpz_fdiv_qr"]
fn mpz_fdiv_qr(a: *mpz_t, b: *mpz_t, c: *mpz_t, d: *mpz_t);
#[fast_ffi]
#[link_name="__gmpz_get_ui"]
fn mpz_get_ui(x: *mpz_t) -> c_uint;
#[fast_ffi]
#[link_name="__gmpz_init"]
fn mpz_init(x: *mpz_t);
#[fast_ffi]
#[link_name="__gmpz_init_set_ui"]
fn mpz_init_set_ui(x: *mpz_t, y: c_uint);
#[fast_ffi]
#[link_name="__gmpz_mul_2exp"]
fn mpz_mul_2exp(x: *mpz_t, y: *mpz_t, z: c_uint);
#[fast_ffi]
#[link_name="__gmpz_mul_ui"]
fn mpz_mul_ui(x: *mpz_t, y: *mpz_t, z: c_uint);
#[fast_ffi]
#[link_name="__gmpz_submul_ui"]
fn mpz_submul_ui(x: *mpz_t, y: *mpz_t, z: c_uint);
}
struct Context {
numer: mpz_t,
accum: mpz_t,
denom: mpz_t,
tmp1: mpz_t,
tmp2: mpz_t,
}
impl Context {
fn new() -> Context {
unsafe {
let mut result = Context {
numer: mpz_t::new(),
accum: mpz_t::new(),
denom: mpz_t::new(),
tmp1: mpz_t::new(),
tmp2: mpz_t::new(),
};
mpz_init(&result.tmp1);
mpz_init(&result.tmp2);
mpz_init_set_ui(&result.numer, 1);
mpz_init_set_ui(&result.accum, 0);
mpz_init_set_ui(&result.denom, 1);
result
}
}
fn extract_digit(&mut self) -> i32 {
unsafe {
if mpz_cmp(&self.numer, &self.accum) > 0 {
return -1;
}
// Compute (numer * 3 + accum) / denom
mpz_mul_2exp(&self.tmp1, &self.numer, 1);
mpz_add(&self.tmp1, &self.tmp1, &self.numer);
mpz_add(&self.tmp1, &self.tmp1, &self.accum);
mpz_fdiv_qr(&self.tmp1, &self.tmp2, &self.tmp1, &self.denom);
// Now, if (numer * 4 + accum) % denom...
mpz_add(&self.tmp2, &self.tmp2, &self.numer);
// ... is normalized, then the two divisions have the same result.
if mpz_cmp(&self.tmp2, &self.denom) >= 0 {
return -1;
}
mpz_get_ui(&self.tmp1) as i32
}
}
fn next_term(&mut self, k: u32) {
unsafe {
let y2 = k*2 + 1;
mpz_mul_2exp(&self.tmp1, &self.numer, 1);
mpz_add(&self.accum, &self.accum, &self.tmp1);
mpz_mul_ui(&self.accum, &self.accum, y2);
mpz_mul_ui(&self.numer, &self.numer, k);
mpz_mul_ui(&self.denom, &self.denom, y2);
}
}
fn eliminate_digit(&mut self, d: u32) {
unsafe {
mpz_submul_ui(&self.accum, &self.denom, d);
mpz_mul_ui(&self.accum, &self.accum, 10);
mpz_mul_ui(&self.numer, &self.numer, 10);
}
}
}
fn pidigits(n: u32) {
unsafe {
let mode = "w";
let stdout = fdopen(STDOUT_FILENO as c_int, transmute(&mode[0]));
let mut d: i32;
let mut i: u32 = 0, k: u32 = 0, m: u32;
let mut context = Context::new();
loop {
loop {
k += 1;
context.next_term(k);
d = context.extract_digit();
if d != -1 {
break;
}
}
fputc((d as c_int) + ('0' as c_int), stdout);
i += 1;
m = i % 10;
if m == 0 {
let res = fmt!("\t:%d\n", i as int);
fputs(transmute(&res[0]), stdout);
}
if i >= n {
break;
}
context.eliminate_digit(d as u32);
}
if m != 0 {
m = 10 - m;
while m != 0 {
m -= 1;
fputc(' ' as c_int, stdout);
}
let res = fmt!("\t:%d\n", i as int);
fputs(transmute(&res[0]), stdout);
}
}
}
#[fixed_stack_segment]
fn main() {
let n: u32 = FromStr::from_str(os::args()[1]).get();
pidigits(n);
}

View file

@ -0,0 +1,155 @@
// xfail-pretty
// xfail-test
use core::cast::transmute;
use core::libc::{STDOUT_FILENO, c_int, fdopen, fgets, fopen, fputc, fwrite};
use core::libc::{size_t};
use core::ptr::null;
use core::vec::{capacity, reserve, reserve_at_least};
use core::vec::raw::set_len;
static LINE_LEN: u32 = 80;
static COMPLEMENTS: [u8, ..256] = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
'T' as u8,
'V' as u8,
'G' as u8,
'H' as u8,
0,
0,
'C' as u8,
'D' as u8,
0,
0,
'M' as u8,
0,
'K' as u8,
'N' as u8,
0,
0,
0,
'Y' as u8,
'S' as u8,
'A' as u8,
'A' as u8,
'B' as u8,
'W' as u8,
0,
'R' as u8,
0,
0,
0,
0,
0,
0,
0,
'T' as u8,
'V' as u8,
'G' as u8,
'H' as u8,
0,
0,
'C' as u8,
'D' as u8,
0,
0,
'M' as u8,
0,
'K' as u8,
'N' as u8,
0,
0,
0,
'Y' as u8,
'S' as u8,
'A' as u8,
'A' as u8,
'B' as u8,
'W' as u8,
0,
'R' as u8,
0,
0,
0,
0,
0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
];
#[fixed_stack_segment]
fn main() {
unsafe {
let mode = "r";
//let stdin = fdopen(STDIN_FILENO as c_int, transmute(&mode[0]));
let path = "reversecomplement-input.txt";
let stdin = fopen(transmute(&path[0]), transmute(&mode[0]));
let mode = "w";
let stdout = fdopen(STDOUT_FILENO as c_int, transmute(&mode[0]));
let mut out: ~[u8] = ~[];
reserve(&mut out, 12777888);
let mut pos = 0;
loop {
let needed = pos + (LINE_LEN as uint) + 1;
if capacity(&out) < needed {
reserve_at_least(&mut out, needed);
}
let mut ptr = out.unsafe_mut_ref(pos);
if fgets(transmute(ptr), LINE_LEN as c_int, stdin) == null() {
break;
}
// Don't change lines that begin with '>' or ';'.
let first = *ptr;
if first == ('>' as u8) {
while *ptr != 0 {
ptr = ptr.offset(1);
}
*ptr = '\n' as u8;
pos = (ptr as uint) - (out.unsafe_ref(0) as uint);
fwrite(transmute(out.unsafe_ref(0)),
1,
pos as size_t,
stdout);
pos = 0;
loop;
}
// Complement other lines.
loop {
let ch = *ptr;
if ch == 0 {
break;
}
*ptr = COMPLEMENTS.unsafe_get(ch as uint);
ptr = ptr.offset(1);
}
*ptr = '\n' as u8;
pos = (ptr as uint) - (out.unsafe_ref(0) as uint);
}
fwrite(transmute(out.unsafe_ref(0)), 1, pos as size_t, stdout);
}
}

View file

@ -1,84 +1,54 @@
// Copyright 2012 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.
use core::from_str::FromStr;
use core::iter::ExtendedMutableIter;
use core::unstable::intrinsics::sqrtf64;
// Based on spectalnorm.gcc by Sebastien Loisel
extern mod std;
fn eval_A(i: uint, j: uint) -> float {
1.0/(((i+j)*(i+j+1u)/2u+i+1u) as float)
#[inline]
fn A(i: i32, j: i32) -> i32 {
(i+j) * (i+j+1) / 2 + i + 1
}
fn eval_A_times_u(u: &const [float], Au: &mut [float]) {
let N = vec::len(u);
let mut i = 0u;
while i < N {
Au[i] = 0.0;
let mut j = 0u;
while j < N {
Au[i] += eval_A(i, j) * u[j];
j += 1u;
fn dot(v: &[f64], u: &[f64]) -> f64 {
let mut sum = 0.0;
for v.eachi |i, &v_i| {
sum += v_i * u[i];
}
sum
}
fn mult_Av(v: &mut [f64], out: &mut [f64]) {
for vec::eachi_mut(out) |i, out_i| {
let mut sum = 0.0;
for vec::eachi_mut(v) |j, &v_j| {
sum += v_j / (A(i as i32, j as i32) as f64);
}
i += 1u;
*out_i = sum;
}
}
fn eval_At_times_u(u: &const [float], Au: &mut [float]) {
let N = vec::len(u);
let mut i = 0u;
while i < N {
Au[i] = 0.0;
let mut j = 0u;
while j < N {
Au[i] += eval_A(j, i) * u[j];
j += 1u;
fn mult_Atv(v: &mut [f64], out: &mut [f64]) {
for vec::eachi_mut(out) |i, out_i| {
let mut sum = 0.0;
for vec::eachi_mut(v) |j, &v_j| {
sum += v_j / (A(j as i32, i as i32) as f64);
}
i += 1u;
*out_i = sum;
}
}
fn eval_AtA_times_u(u: &const [float], AtAu: &mut [float]) {
let mut v = vec::from_elem(vec::len(u), 0.0);
eval_A_times_u(u, v);
eval_At_times_u(v, AtAu);
fn mult_AtAv(v: &mut [f64], out: &mut [f64], tmp: &mut [f64]) {
mult_Av(v, tmp);
mult_Atv(tmp, out);
}
#[fixed_stack_segment]
fn main() {
let args = os::args();
let args = if os::getenv(~"RUST_BENCH").is_some() {
~[~"", ~"2000"]
} else if args.len() <= 1u {
~[~"", ~"1000"]
} else {
args
};
let N = uint::from_str(args[1]).get();
let mut u = vec::from_elem(N, 1.0);
let mut v = vec::from_elem(N, 0.0);
let mut i = 0u;
while i < 10u {
eval_AtA_times_u(u, v);
eval_AtA_times_u(v, u);
i += 1u;
let n: uint = FromStr::from_str(os::args()[1]).get();
let mut u = vec::from_elem(n, 1f64), v = u.clone(), tmp = u.clone();
for 8.times {
mult_AtAv(u, v, tmp);
mult_AtAv(v, u, tmp);
}
let mut vBv = 0.0;
let mut vv = 0.0;
let mut i = 0u;
while i < N {
vBv += u[i] * v[i];
vv += v[i] * v[i];
i += 1u;
}
io::println(fmt!("%0.9f\n", float::sqrt(vBv / vv)));
println(fmt!("%.9f", sqrtf64(dot(u,v) / dot(v,v)) as float));
}

View file

@ -17,11 +17,11 @@ fn foo<T:Copy + Const>(x: T) -> T { x }
struct F { field: int }
pub fn main() {
foo(1);
/*foo(1);
foo(~"hi");
foo(~[1, 2, 3]);
foo(F{field: 42});
foo((1, 2u));
foo(@1);
foo(@1);*/
foo(~1);
}

View file

@ -11,7 +11,7 @@
mod rustrt {
pub extern {
pub fn rust_dbg_call(cb: *u8, data: libc::uintptr_t)
-> libc::uintptr_t;
-> libc::uintptr_t;
}
}