auto merge of #8705 : brson/rust/lesscxx, r=graydon
This commit is contained in:
commit
f9979247d1
5
mk/rt.mk
5
mk/rt.mk
@ -63,7 +63,6 @@ endif
|
||||
endif
|
||||
|
||||
RUNTIME_CXXS_$(1)_$(2) := \
|
||||
rt/sync/timer.cpp \
|
||||
rt/sync/lock_and_signal.cpp \
|
||||
rt/sync/rust_thread.cpp \
|
||||
rt/rust_builtin.cpp \
|
||||
@ -72,13 +71,9 @@ RUNTIME_CXXS_$(1)_$(2) := \
|
||||
rt/rust_upcall.cpp \
|
||||
rt/rust_uv.cpp \
|
||||
rt/rust_crate_map.cpp \
|
||||
rt/rust_gc_metadata.cpp \
|
||||
rt/rust_util.cpp \
|
||||
rt/rust_log.cpp \
|
||||
rt/rust_exchange_alloc.cpp \
|
||||
rt/isaac/randport.cpp \
|
||||
rt/miniz.cpp \
|
||||
rt/rust_abi.cpp \
|
||||
rt/memory_region.cpp \
|
||||
rt/boxed_region.cpp \
|
||||
rt/arch/$$(HOST_$(1))/context.cpp \
|
||||
|
@ -121,6 +121,9 @@ pub struct Tm {
|
||||
}
|
||||
|
||||
pub fn empty_tm() -> Tm {
|
||||
// 64 is the max size of the timezone buffer allocated on windows
|
||||
// in rust_localtime. In glibc the max timezone size is supposedly 3.
|
||||
let zone = str::with_capacity(64);
|
||||
Tm {
|
||||
tm_sec: 0_i32,
|
||||
tm_min: 0_i32,
|
||||
@ -132,7 +135,7 @@ pub fn empty_tm() -> Tm {
|
||||
tm_yday: 0_i32,
|
||||
tm_isdst: 0_i32,
|
||||
tm_gmtoff: 0_i32,
|
||||
tm_zone: ~"",
|
||||
tm_zone: zone,
|
||||
tm_nsec: 0_i32,
|
||||
}
|
||||
}
|
||||
|
@ -40,12 +40,10 @@ impl LocalHeap {
|
||||
#[fixed_stack_segment] #[inline(never)]
|
||||
pub fn new() -> LocalHeap {
|
||||
unsafe {
|
||||
// Don't need synchronization for the single-threaded local heap
|
||||
let synchronized = false as uintptr_t;
|
||||
// XXX: These usually come from the environment
|
||||
let detailed_leaks = false as uintptr_t;
|
||||
let poison_on_free = false as uintptr_t;
|
||||
let region = rust_new_memory_region(synchronized, detailed_leaks, poison_on_free);
|
||||
let region = rust_new_memory_region(detailed_leaks, poison_on_free);
|
||||
assert!(region.is_not_null());
|
||||
let boxed = rust_new_boxed_region(region, poison_on_free);
|
||||
assert!(boxed.is_not_null());
|
||||
@ -109,8 +107,7 @@ pub fn live_allocs() -> *raw::Box<()> {
|
||||
|
||||
extern {
|
||||
#[fast_ffi]
|
||||
fn rust_new_memory_region(synchronized: uintptr_t,
|
||||
detailed_leaks: uintptr_t,
|
||||
fn rust_new_memory_region(detailed_leaks: uintptr_t,
|
||||
poison_on_free: uintptr_t) -> *MemoryRegion;
|
||||
#[fast_ffi]
|
||||
fn rust_delete_memory_region(region: *MemoryRegion);
|
||||
|
@ -224,10 +224,7 @@ pub fn init(argc: int, argv: **u8, crate_map: *u8) {
|
||||
args::init(argc, argv);
|
||||
env::init();
|
||||
logging::init(crate_map);
|
||||
rust_update_gc_metadata(crate_map);
|
||||
}
|
||||
|
||||
externfn!(fn rust_update_gc_metadata(crate_map: *u8));
|
||||
}
|
||||
|
||||
/// One-time runtime cleanup.
|
||||
|
@ -14,6 +14,7 @@ use libc;
|
||||
use option::{Some, None};
|
||||
use os;
|
||||
use str::StrSlice;
|
||||
use unstable::atomics::{AtomicInt, INIT_ATOMIC_INT, SeqCst};
|
||||
|
||||
#[cfg(target_os="macos")]
|
||||
use unstable::running_on_valgrind;
|
||||
@ -129,24 +130,12 @@ memory and partly incapable of presentation to others.",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_exit_status(code: int) {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
unsafe {
|
||||
return rust_set_exit_status_newrt(code as libc::uintptr_t);
|
||||
}
|
||||
static mut EXIT_STATUS: AtomicInt = INIT_ATOMIC_INT;
|
||||
|
||||
extern {
|
||||
fn rust_set_exit_status_newrt(code: libc::uintptr_t);
|
||||
}
|
||||
pub fn set_exit_status(code: int) {
|
||||
unsafe { EXIT_STATUS.store(code, SeqCst) }
|
||||
}
|
||||
|
||||
pub fn get_exit_status() -> int {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
unsafe {
|
||||
return rust_get_exit_status_newrt() as int;
|
||||
}
|
||||
|
||||
extern {
|
||||
fn rust_get_exit_status_newrt() -> libc::uintptr_t;
|
||||
}
|
||||
unsafe { EXIT_STATUS.load(SeqCst) }
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
// except according to those terms.
|
||||
|
||||
|
||||
#include "sync/sync.h"
|
||||
#include "memory_region.h"
|
||||
|
||||
#if RUSTRT_TRACK_ALLOCATIONS >= 3
|
||||
@ -42,30 +41,25 @@ inline void memory_region::maybe_print_backtrace(const alloc_header *header) con
|
||||
# endif
|
||||
}
|
||||
|
||||
memory_region::memory_region(bool synchronized,
|
||||
bool detailed_leaks,
|
||||
memory_region::memory_region(bool detailed_leaks,
|
||||
bool poison_on_free) :
|
||||
_parent(NULL), _live_allocations(0),
|
||||
_detailed_leaks(detailed_leaks),
|
||||
_poison_on_free(poison_on_free),
|
||||
_synchronized(synchronized) {
|
||||
_poison_on_free(poison_on_free) {
|
||||
}
|
||||
|
||||
memory_region::memory_region(memory_region *parent) :
|
||||
_parent(parent), _live_allocations(0),
|
||||
_detailed_leaks(parent->_detailed_leaks),
|
||||
_poison_on_free(parent->_poison_on_free),
|
||||
_synchronized(parent->_synchronized) {
|
||||
_poison_on_free(parent->_poison_on_free) {
|
||||
}
|
||||
|
||||
void memory_region::add_alloc() {
|
||||
//_live_allocations++;
|
||||
sync::increment(_live_allocations);
|
||||
_live_allocations++;
|
||||
}
|
||||
|
||||
void memory_region::dec_alloc() {
|
||||
//_live_allocations--;
|
||||
sync::decrement(_live_allocations);
|
||||
_live_allocations--;
|
||||
}
|
||||
|
||||
void memory_region::free(void *mem) {
|
||||
@ -112,7 +106,6 @@ memory_region::realloc(void *mem, size_t orig_size) {
|
||||
# endif
|
||||
|
||||
# if RUSTRT_TRACK_ALLOCATIONS >= 2
|
||||
if (_synchronized) { _lock.lock(); }
|
||||
if (_allocation_list[newMem->index] != alloc) {
|
||||
printf("at index %d, found %p, expected %p\n",
|
||||
alloc->index, _allocation_list[alloc->index], alloc);
|
||||
@ -125,7 +118,6 @@ memory_region::realloc(void *mem, size_t orig_size) {
|
||||
// printf("realloc: stored %p at index %d, replacing %p\n",
|
||||
// newMem, index, mem);
|
||||
}
|
||||
if (_synchronized) { _lock.unlock(); }
|
||||
# endif
|
||||
|
||||
return get_data(newMem);
|
||||
@ -160,9 +152,7 @@ memory_region::malloc(size_t size, const char *tag) {
|
||||
}
|
||||
|
||||
memory_region::~memory_region() {
|
||||
if (_synchronized) { _lock.lock(); }
|
||||
if (_live_allocations == 0 && !_detailed_leaks) {
|
||||
if (_synchronized) { _lock.unlock(); }
|
||||
return;
|
||||
}
|
||||
char msg[128];
|
||||
@ -193,7 +183,6 @@ memory_region::~memory_region() {
|
||||
fprintf(stderr, "%s\n", msg);
|
||||
assert(false);
|
||||
}
|
||||
if (_synchronized) { _lock.unlock(); }
|
||||
}
|
||||
|
||||
void
|
||||
@ -204,7 +193,6 @@ memory_region::release_alloc(void *mem) {
|
||||
# endif
|
||||
|
||||
# if RUSTRT_TRACK_ALLOCATIONS >= 2
|
||||
if (_synchronized) { _lock.lock(); }
|
||||
if (((size_t) alloc->index) >= _allocation_list.size()) {
|
||||
printf("free: ptr 0x%" PRIxPTR " (%s) index %d is beyond allocation_list of size %zu\n",
|
||||
(uintptr_t) get_data(alloc), alloc->tag, alloc->index, _allocation_list.size());
|
||||
@ -222,7 +210,6 @@ memory_region::release_alloc(void *mem) {
|
||||
_allocation_list[alloc->index] = NULL;
|
||||
alloc->index = -1;
|
||||
}
|
||||
if (_synchronized) { _lock.unlock(); }
|
||||
# endif
|
||||
|
||||
dec_alloc();
|
||||
@ -236,9 +223,7 @@ memory_region::claim_alloc(void *mem) {
|
||||
# endif
|
||||
|
||||
# if RUSTRT_TRACK_ALLOCATIONS >= 2
|
||||
if (_synchronized) { _lock.lock(); }
|
||||
alloc->index = _allocation_list.append(alloc);
|
||||
if (_synchronized) { _lock.unlock(); }
|
||||
# endif
|
||||
|
||||
# if RUSTRT_TRACK_ALLOCATIONS >= 3
|
||||
|
@ -59,7 +59,6 @@ private:
|
||||
array_list<alloc_header *> _allocation_list;
|
||||
const bool _detailed_leaks;
|
||||
const bool _poison_on_free;
|
||||
const bool _synchronized;
|
||||
lock_and_signal _lock;
|
||||
|
||||
void add_alloc();
|
||||
@ -77,8 +76,7 @@ private:
|
||||
memory_region& operator=(const memory_region& rhs);
|
||||
|
||||
public:
|
||||
memory_region(bool synchronized,
|
||||
bool detailed_leaks, bool poison_on_free);
|
||||
memory_region(bool detailed_leaks, bool poison_on_free);
|
||||
memory_region(memory_region *parent);
|
||||
void *malloc(size_t size, const char *tag);
|
||||
void *realloc(void *mem, size_t size);
|
||||
|
@ -1,88 +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.
|
||||
|
||||
// ABI-specific routines.
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
#include <stdint.h>
|
||||
#include "rust_abi.h"
|
||||
|
||||
#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__)
|
||||
#define HAVE_DLFCN_H
|
||||
#include <dlfcn.h>
|
||||
#elif defined(_WIN32)
|
||||
// Otherwise it's windows.h -- included in rust_abi.h
|
||||
#endif
|
||||
|
||||
#define END_OF_STACK_RA (void (*)())0xdeadbeef
|
||||
|
||||
weak_symbol<uint32_t> abi_version("rust_abi_version");
|
||||
|
||||
uint32_t get_abi_version() {
|
||||
return (*abi_version == NULL) ? 0 : **abi_version;
|
||||
}
|
||||
|
||||
namespace stack_walk {
|
||||
|
||||
#ifdef HAVE_DLFCN_H
|
||||
std::string
|
||||
frame::symbol() const {
|
||||
std::stringstream ss;
|
||||
|
||||
Dl_info info;
|
||||
if (!dladdr((void *)ra, &info))
|
||||
ss << "??";
|
||||
else
|
||||
ss << info.dli_sname;
|
||||
|
||||
ss << " @ " << std::hex << (uintptr_t)ra;
|
||||
return ss.str();
|
||||
}
|
||||
#else
|
||||
std::string
|
||||
frame::symbol() const {
|
||||
std::stringstream ss;
|
||||
ss << std::hex << (uintptr_t)ra;
|
||||
return ss.str();
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<frame>
|
||||
backtrace() {
|
||||
std::vector<frame> frames;
|
||||
|
||||
// Ideally we would use the current value of EIP here, but there's no
|
||||
// portable way to get that and there are never any GC roots in our C++
|
||||
// frames anyhow.
|
||||
frame f(__builtin_frame_address(0), (void (*)())NULL);
|
||||
|
||||
while (f.ra != END_OF_STACK_RA) {
|
||||
frames.push_back(f);
|
||||
f.next();
|
||||
}
|
||||
return frames;
|
||||
}
|
||||
|
||||
std::string
|
||||
symbolicate(const std::vector<frame> &frames) {
|
||||
std::stringstream ss;
|
||||
std::vector<frame>::const_iterator begin(frames.begin()),
|
||||
end(frames.end());
|
||||
while (begin != end) {
|
||||
ss << begin->symbol() << std::endl;
|
||||
++begin;
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
} // end namespace stack_walk
|
@ -1,78 +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.
|
||||
|
||||
// ABI-specific routines.
|
||||
|
||||
#ifndef RUST_ABI_H
|
||||
#define RUST_ABI_H
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __WIN32__
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
class weak_symbol {
|
||||
private:
|
||||
bool init;
|
||||
T *data;
|
||||
const char *name;
|
||||
|
||||
void fill() {
|
||||
if (init)
|
||||
return;
|
||||
|
||||
#ifdef __WIN32__
|
||||
data = (T *)GetProcAddress(GetModuleHandle(NULL), name);
|
||||
#else
|
||||
data = (T *)dlsym(RTLD_DEFAULT, name);
|
||||
#endif
|
||||
|
||||
init = true;
|
||||
}
|
||||
|
||||
public:
|
||||
weak_symbol(const char *in_name)
|
||||
: init(false), data(NULL), name(in_name) {}
|
||||
|
||||
T *&operator*() { fill(); return data; }
|
||||
};
|
||||
|
||||
namespace stack_walk {
|
||||
|
||||
struct frame {
|
||||
uint8_t *bp; // The frame pointer.
|
||||
void (*ra)(); // The return address.
|
||||
|
||||
frame(void *in_bp, void (*in_ra)()) : bp((uint8_t *)in_bp), ra(in_ra) {}
|
||||
|
||||
inline void next() {
|
||||
ra = *(void (**)())(bp + sizeof(void *));
|
||||
bp = *(uint8_t **)bp;
|
||||
}
|
||||
|
||||
std::string symbol() const;
|
||||
};
|
||||
|
||||
std::vector<frame> backtrace();
|
||||
std::string symbolicate(const std::vector<frame> &frames);
|
||||
|
||||
} // end namespace stack_walk
|
||||
|
||||
|
||||
uint32_t get_abi_version();
|
||||
|
||||
#endif
|
@ -11,12 +11,10 @@
|
||||
/* Foreign builtins. */
|
||||
|
||||
#include "rust_util.h"
|
||||
#include "sync/timer.h"
|
||||
#include "sync/rust_thread.h"
|
||||
#include "sync/lock_and_signal.h"
|
||||
#include "memory_region.h"
|
||||
#include "boxed_region.h"
|
||||
#include "rust_abi.h"
|
||||
#include "rust_rng.h"
|
||||
#include "vg/valgrind.h"
|
||||
#include "sp.h"
|
||||
@ -25,6 +23,7 @@
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <crt_externs.h>
|
||||
#include <mach/mach_time.h>
|
||||
#endif
|
||||
|
||||
#if !defined(__WIN32__)
|
||||
@ -99,53 +98,6 @@ rand_free(rust_rng *rng) {
|
||||
free(rng);
|
||||
}
|
||||
|
||||
|
||||
/* Debug helpers strictly to verify ABI conformance.
|
||||
*
|
||||
* FIXME (#2665): move these into a testcase when the testsuite
|
||||
* understands how to have explicit C files included.
|
||||
*/
|
||||
|
||||
struct quad {
|
||||
uint64_t a;
|
||||
uint64_t b;
|
||||
uint64_t c;
|
||||
uint64_t d;
|
||||
};
|
||||
|
||||
struct floats {
|
||||
double a;
|
||||
uint8_t b;
|
||||
double c;
|
||||
};
|
||||
|
||||
extern "C" quad
|
||||
debug_abi_1(quad q) {
|
||||
quad qq = { q.c + 1,
|
||||
q.d - 1,
|
||||
q.a + 1,
|
||||
q.b - 1 };
|
||||
return qq;
|
||||
}
|
||||
|
||||
extern "C" floats
|
||||
debug_abi_2(floats f) {
|
||||
floats ff = { f.c + 1.0,
|
||||
0xff,
|
||||
f.a - 1.0 };
|
||||
return ff;
|
||||
}
|
||||
|
||||
extern "C" int
|
||||
debug_static_mut;
|
||||
|
||||
int debug_static_mut = 3;
|
||||
|
||||
extern "C" void
|
||||
debug_static_mut_check_four() {
|
||||
assert(debug_static_mut == 4);
|
||||
}
|
||||
|
||||
extern "C" CDECL char*
|
||||
#if defined(__WIN32__)
|
||||
rust_list_dir_val(WIN32_FIND_DATA* entry_ptr) {
|
||||
@ -242,10 +194,33 @@ get_time(int64_t *sec, int32_t *nsec) {
|
||||
}
|
||||
#endif
|
||||
|
||||
const uint64_t ns_per_s = 1000000000LL;
|
||||
|
||||
extern "C" CDECL void
|
||||
precise_time_ns(uint64_t *ns) {
|
||||
timer t;
|
||||
*ns = t.time_ns();
|
||||
|
||||
#ifdef __APPLE__
|
||||
uint64_t time = mach_absolute_time();
|
||||
mach_timebase_info_data_t info = {0, 0};
|
||||
if (info.denom == 0) {
|
||||
mach_timebase_info(&info);
|
||||
}
|
||||
uint64_t time_nano = time * (info.numer / info.denom);
|
||||
*ns = time_nano;
|
||||
#elif __WIN32__
|
||||
uint64_t ticks_per_s;
|
||||
QueryPerformanceFrequency((LARGE_INTEGER *)&ticks_per_s);
|
||||
if (ticks_per_s == 0LL) {
|
||||
ticks_per_s = 1LL;
|
||||
}
|
||||
uint64_t ticks;
|
||||
QueryPerformanceCounter((LARGE_INTEGER *)&ticks);
|
||||
*ns = ((ticks * ns_per_s) / ticks_per_s);
|
||||
#else
|
||||
timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
*ns = (ts.tv_sec * ns_per_s + ts.tv_nsec);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct rust_tm {
|
||||
@ -292,7 +267,7 @@ void tm_to_rust_tm(tm* in_tm, rust_tm* out_tm, int32_t gmtoff,
|
||||
|
||||
if (zone != NULL) {
|
||||
size_t size = strlen(zone);
|
||||
reserve_vec_exact(&out_tm->tm_zone, size);
|
||||
assert(out_tm->tm_zone->alloc >= size);
|
||||
memcpy(out_tm->tm_zone->data, zone, size);
|
||||
out_tm->tm_zone->fill = size;
|
||||
}
|
||||
@ -505,11 +480,9 @@ rust_initialize_rt_tls_key() {
|
||||
}
|
||||
|
||||
extern "C" CDECL memory_region*
|
||||
rust_new_memory_region(uintptr_t synchronized,
|
||||
uintptr_t detailed_leaks,
|
||||
rust_new_memory_region(uintptr_t detailed_leaks,
|
||||
uintptr_t poison_on_free) {
|
||||
return new memory_region((bool)synchronized,
|
||||
(bool)detailed_leaks,
|
||||
return new memory_region((bool)detailed_leaks,
|
||||
(bool)poison_on_free);
|
||||
}
|
||||
|
||||
@ -632,21 +605,6 @@ rust_get_global_args_ptr() {
|
||||
return &global_args_ptr;
|
||||
}
|
||||
|
||||
static lock_and_signal exit_status_lock;
|
||||
static uintptr_t exit_status = 0;
|
||||
|
||||
extern "C" CDECL void
|
||||
rust_set_exit_status_newrt(uintptr_t code) {
|
||||
scoped_lock with(exit_status_lock);
|
||||
exit_status = code;
|
||||
}
|
||||
|
||||
extern "C" CDECL uintptr_t
|
||||
rust_get_exit_status_newrt() {
|
||||
scoped_lock with(exit_status_lock);
|
||||
return exit_status;
|
||||
}
|
||||
|
||||
static lock_and_signal change_dir_lock;
|
||||
|
||||
extern "C" CDECL void
|
||||
|
@ -1,35 +0,0 @@
|
||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#include "rust_exchange_alloc.h"
|
||||
#include "sync/sync.h"
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void *
|
||||
rust_exchange_alloc::malloc(size_t size) {
|
||||
void *value = ::malloc(size);
|
||||
assert(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
void *
|
||||
rust_exchange_alloc::realloc(void *ptr, size_t size) {
|
||||
void *new_ptr = ::realloc(ptr, size);
|
||||
assert(new_ptr);
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
void
|
||||
rust_exchange_alloc::free(void *ptr) {
|
||||
::free(ptr);
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#ifndef RUST_EXCHANGE_ALLOC_H
|
||||
#define RUST_EXCHANGE_ALLOC_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
class rust_exchange_alloc {
|
||||
public:
|
||||
void *malloc(size_t size);
|
||||
void *realloc(void *mem, size_t size);
|
||||
void free(void *mem);
|
||||
};
|
||||
|
||||
#endif
|
@ -1,95 +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.
|
||||
|
||||
#include "rust_gc_metadata.h"
|
||||
#include "rust_crate_map.h"
|
||||
#include "rust_globals.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
struct safe_point {
|
||||
uintptr_t safe_point_loc;
|
||||
uintptr_t safe_point_meta;
|
||||
uintptr_t function_meta;
|
||||
};
|
||||
|
||||
struct update_gc_entry_args {
|
||||
std::vector<safe_point> *safe_points;
|
||||
};
|
||||
|
||||
static void
|
||||
update_gc_entry(const mod_entry *entry, void *cookie) {
|
||||
update_gc_entry_args *args = (update_gc_entry_args *)cookie;
|
||||
if (!strcmp(entry->name, "_gc_module_metadata")) {
|
||||
uintptr_t *next = (uintptr_t *)entry->state;
|
||||
uint32_t num_safe_points = *(uint32_t *)next;
|
||||
next++;
|
||||
|
||||
for (uint32_t i = 0; i < num_safe_points; i++) {
|
||||
safe_point sp = { next[0], next[1], next[2] };
|
||||
next += 3;
|
||||
|
||||
args->safe_points->push_back(sp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
cmp_safe_point(safe_point a, safe_point b) {
|
||||
return a.safe_point_loc < b.safe_point_loc;
|
||||
}
|
||||
|
||||
uintptr_t *global_safe_points = 0;
|
||||
|
||||
void
|
||||
update_gc_metadata(const void* map) {
|
||||
std::vector<safe_point> safe_points;
|
||||
update_gc_entry_args args = { &safe_points };
|
||||
|
||||
// Extract list of safe points from each module.
|
||||
iter_crate_map((const cratemap *)map, update_gc_entry, (void *)&args);
|
||||
std::sort(safe_points.begin(), safe_points.end(), cmp_safe_point);
|
||||
|
||||
// Serialize safe point list into format expected by runtime.
|
||||
global_safe_points =
|
||||
(uintptr_t *)malloc((safe_points.size()*3 + 1)*sizeof(uintptr_t));
|
||||
if (!global_safe_points) return;
|
||||
|
||||
uintptr_t *next = global_safe_points;
|
||||
*next = safe_points.size();
|
||||
next++;
|
||||
for (uint32_t i = 0; i < safe_points.size(); i++) {
|
||||
next[0] = safe_points[i].safe_point_loc;
|
||||
next[1] = safe_points[i].safe_point_meta;
|
||||
next[2] = safe_points[i].function_meta;
|
||||
next += 3;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" CDECL void *
|
||||
rust_gc_metadata() {
|
||||
return (void *)global_safe_points;
|
||||
}
|
||||
|
||||
extern "C" CDECL void
|
||||
rust_update_gc_metadata(const void* map) {
|
||||
update_gc_metadata(map);
|
||||
}
|
||||
|
||||
//
|
||||
// Local Variables:
|
||||
// mode: C++
|
||||
// fill-column: 78;
|
||||
// indent-tabs-mode: nil
|
||||
// c-basic-offset: 4
|
||||
// buffer-file-coding-system: utf-8-unix
|
||||
// End:
|
||||
//
|
@ -1,26 +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.
|
||||
|
||||
#ifndef RUST_GC_METADATA_H
|
||||
#define RUST_GC_METADATA_H
|
||||
|
||||
void update_gc_metadata(const void* map);
|
||||
|
||||
//
|
||||
// Local Variables:
|
||||
// mode: C++
|
||||
// fill-column: 78;
|
||||
// indent-tabs-mode: nil
|
||||
// c-basic-offset: 4
|
||||
// buffer-file-coding-system: utf-8-unix
|
||||
// End:
|
||||
//
|
||||
|
||||
#endif /* RUST_GC_METADATA_H */
|
@ -11,10 +11,8 @@
|
||||
// Helper functions used only in tests
|
||||
|
||||
#include "rust_util.h"
|
||||
#include "sync/timer.h"
|
||||
#include "sync/rust_thread.h"
|
||||
#include "sync/lock_and_signal.h"
|
||||
#include "rust_abi.h"
|
||||
|
||||
// These functions are used in the unit tests for C ABI calls.
|
||||
|
||||
@ -179,3 +177,49 @@ extern "C" CDECL intptr_t
|
||||
rust_get_test_int() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Debug helpers strictly to verify ABI conformance.
|
||||
*
|
||||
* FIXME (#2665): move these into a testcase when the testsuite
|
||||
* understands how to have explicit C files included.
|
||||
*/
|
||||
|
||||
struct quad {
|
||||
uint64_t a;
|
||||
uint64_t b;
|
||||
uint64_t c;
|
||||
uint64_t d;
|
||||
};
|
||||
|
||||
struct floats {
|
||||
double a;
|
||||
uint8_t b;
|
||||
double c;
|
||||
};
|
||||
|
||||
extern "C" quad
|
||||
rust_dbg_abi_1(quad q) {
|
||||
quad qq = { q.c + 1,
|
||||
q.d - 1,
|
||||
q.a + 1,
|
||||
q.b - 1 };
|
||||
return qq;
|
||||
}
|
||||
|
||||
extern "C" floats
|
||||
rust_dbg_abi_2(floats f) {
|
||||
floats ff = { f.c + 1.0,
|
||||
0xff,
|
||||
f.a - 1.0 };
|
||||
return ff;
|
||||
}
|
||||
|
||||
extern "C" int
|
||||
rust_dbg_static_mut;
|
||||
|
||||
int rust_dbg_static_mut = 3;
|
||||
|
||||
extern "C" void
|
||||
rust_dbg_static_mut_check_four() {
|
||||
assert(rust_dbg_static_mut == 4);
|
||||
}
|
||||
|
@ -1,35 +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.
|
||||
|
||||
#include "rust_type.h"
|
||||
|
||||
|
||||
// A hardcoded type descriptor for strings, since the runtime needs to
|
||||
// be able to create them.
|
||||
|
||||
struct type_desc str_body_tydesc = {
|
||||
1, // size
|
||||
1, // align
|
||||
NULL, // take_glue
|
||||
NULL, // drop_glue
|
||||
NULL, // free_glue
|
||||
NULL, // visit_glue
|
||||
0, // borrow_offset
|
||||
};
|
||||
|
||||
//
|
||||
// Local Variables:
|
||||
// mode: C++
|
||||
// fill-column: 78;
|
||||
// indent-tabs-mode: nil
|
||||
// c-basic-offset: 4
|
||||
// buffer-file-coding-system: utf-8-unix
|
||||
// End:
|
||||
//
|
@ -12,11 +12,8 @@
|
||||
#define RUST_UTIL_H
|
||||
|
||||
#include <limits.h>
|
||||
#include "rust_exchange_alloc.h"
|
||||
#include "rust_type.h"
|
||||
|
||||
extern struct type_desc str_body_tydesc;
|
||||
|
||||
// Inline fn used regularly elsewhere.
|
||||
|
||||
// Rounds |size| to the nearest |alignment|. Invariant: |alignment| is a power
|
||||
@ -57,16 +54,6 @@ vec_data(rust_vec *v) {
|
||||
return reinterpret_cast<T*>(v->data);
|
||||
}
|
||||
|
||||
inline void reserve_vec_exact(rust_vec** vpp,
|
||||
size_t size) {
|
||||
if (size > (*vpp)->alloc) {
|
||||
rust_exchange_alloc exchange_alloc;
|
||||
*vpp = (rust_vec*)exchange_alloc
|
||||
.realloc(*vpp, size + sizeof(rust_vec));
|
||||
(*vpp)->alloc = size;
|
||||
}
|
||||
}
|
||||
|
||||
typedef rust_vec rust_str;
|
||||
|
||||
inline size_t get_box_size(size_t body_size, size_t body_align) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
debug_abi_1
|
||||
debug_abi_2
|
||||
debug_static_mut
|
||||
debug_static_mut_check_four
|
||||
rust_dbg_abi_1
|
||||
rust_dbg_abi_2
|
||||
rust_dbg_static_mut
|
||||
rust_dbg_static_mut_check_four
|
||||
get_time
|
||||
rust_tzset
|
||||
rust_gmtime
|
||||
@ -130,8 +130,6 @@ rust_lock_little_lock
|
||||
rust_unlock_little_lock
|
||||
tdefl_compress_mem_to_heap
|
||||
tinfl_decompress_mem_to_heap
|
||||
rust_gc_metadata
|
||||
rust_update_gc_metadata
|
||||
rust_uv_ip4_port
|
||||
rust_uv_ip6_port
|
||||
rust_uv_tcp_getpeername
|
||||
@ -191,8 +189,6 @@ rust_get_num_cpus
|
||||
rust_get_global_args_ptr
|
||||
rust_take_global_args_lock
|
||||
rust_drop_global_args_lock
|
||||
rust_set_exit_status_newrt
|
||||
rust_get_exit_status_newrt
|
||||
rust_take_change_dir_lock
|
||||
rust_drop_change_dir_lock
|
||||
rust_get_test_int
|
||||
|
@ -1,53 +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.
|
||||
|
||||
#ifndef SYNC_H
|
||||
#define SYNC_H
|
||||
|
||||
class sync {
|
||||
public:
|
||||
template <class T>
|
||||
static bool compare_and_swap(T *address,
|
||||
T oldValue, T newValue) {
|
||||
return __sync_bool_compare_and_swap(address, oldValue, newValue);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static T increment(T *address) {
|
||||
return __sync_add_and_fetch(address, 1);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static T decrement(T *address) {
|
||||
return __sync_sub_and_fetch(address, 1);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static T increment(T &address) {
|
||||
return __sync_add_and_fetch(&address, 1);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static T decrement(T &address) {
|
||||
return __sync_sub_and_fetch(&address, 1);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static T read(T *address) {
|
||||
return __sync_add_and_fetch(address, 0);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static T read(T &address) {
|
||||
return __sync_add_and_fetch(&address, 0);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* SYNC_H */
|
@ -1,85 +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.
|
||||
|
||||
#include "../rust_globals.h"
|
||||
#include "timer.h"
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include <mach/mach_time.h>
|
||||
#endif
|
||||
|
||||
uint64_t ns_per_s = 1000000000LL;
|
||||
|
||||
timer::timer() {
|
||||
#if __WIN32__
|
||||
_ticks_per_s = 0LL;
|
||||
// FIXME (#2675): assert this works or have a workaround.
|
||||
QueryPerformanceFrequency((LARGE_INTEGER *)&_ticks_per_s);
|
||||
if (_ticks_per_s == 0LL) {
|
||||
_ticks_per_s = 1LL;
|
||||
}
|
||||
#endif
|
||||
reset_us(0);
|
||||
}
|
||||
|
||||
void
|
||||
timer::reset_us(uint64_t timeout_us) {
|
||||
_start_us = time_us();
|
||||
_timeout_us = timeout_us;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
timer::elapsed_us() {
|
||||
return time_us() - _start_us;
|
||||
}
|
||||
|
||||
double
|
||||
timer::elapsed_ms() {
|
||||
return (double) elapsed_us() / 1000.0;
|
||||
}
|
||||
|
||||
int64_t
|
||||
timer::remaining_us() {
|
||||
return _timeout_us - elapsed_us();
|
||||
}
|
||||
|
||||
bool
|
||||
timer::has_timed_out() {
|
||||
return remaining_us() <= 0;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
timer::time_ns() {
|
||||
#ifdef __APPLE__
|
||||
uint64_t time = mach_absolute_time();
|
||||
mach_timebase_info_data_t info = {0, 0};
|
||||
if (info.denom == 0) {
|
||||
mach_timebase_info(&info);
|
||||
}
|
||||
uint64_t time_nano = time * (info.numer / info.denom);
|
||||
return time_nano;
|
||||
#elif __WIN32__
|
||||
uint64_t ticks;
|
||||
QueryPerformanceCounter((LARGE_INTEGER *)&ticks);
|
||||
return ((ticks * ns_per_s) / _ticks_per_s);
|
||||
#else
|
||||
timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return (ts.tv_sec * ns_per_s + ts.tv_nsec);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint64_t
|
||||
timer::time_us() {
|
||||
return time_ns() / 1000;
|
||||
}
|
||||
|
||||
timer::~timer() {
|
||||
}
|
@ -1,37 +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.
|
||||
|
||||
/*
|
||||
* Utility class to measure time in a platform independent way.
|
||||
*/
|
||||
|
||||
#ifndef TIMER_H
|
||||
#define TIMER_H
|
||||
|
||||
class timer {
|
||||
private:
|
||||
uint64_t _start_us;
|
||||
uint64_t _timeout_us;
|
||||
uint64_t time_us();
|
||||
#if __WIN32__
|
||||
uint64_t _ticks_per_s;
|
||||
#endif
|
||||
public:
|
||||
timer();
|
||||
void reset_us(uint64_t timeout);
|
||||
uint64_t elapsed_us();
|
||||
double elapsed_ms();
|
||||
int64_t remaining_us();
|
||||
bool has_timed_out();
|
||||
uint64_t time_ns();
|
||||
virtual ~timer();
|
||||
};
|
||||
|
||||
#endif /* TIMER_H */
|
@ -1,115 +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.
|
||||
|
||||
#ifndef INDEXED_LIST_H
|
||||
#define INDEXED_LIST_H
|
||||
|
||||
#include <assert.h>
|
||||
#include "array_list.h"
|
||||
|
||||
class indexed_list_object {
|
||||
public:
|
||||
virtual ~indexed_list_object() {}
|
||||
int32_t list_index;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class indexed_list_element : public indexed_list_object {
|
||||
public:
|
||||
T value;
|
||||
indexed_list_element(T value) : value(value) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* An array list of objects that are aware of their position in the list.
|
||||
* Normally, objects in this list should derive from the base class
|
||||
* "indexed_list_object" however because of nasty Rust compiler dependencies
|
||||
* on the layout of runtime objects we cannot always derive from this
|
||||
* base class, so instead we just enforce the informal protocol that any
|
||||
* object inserted in this list must define a "int32_t list_index" member.
|
||||
*/
|
||||
template<typename T> class indexed_list {
|
||||
array_list<T*> list;
|
||||
public:
|
||||
int32_t append(T *value);
|
||||
bool pop(T **value);
|
||||
/**
|
||||
* Same as pop(), except that it returns NULL if the list is empty.
|
||||
*/
|
||||
T* pop_value();
|
||||
size_t length() const {
|
||||
return list.size();
|
||||
}
|
||||
bool is_empty() const {
|
||||
return list.is_empty();
|
||||
}
|
||||
int32_t remove(T* value);
|
||||
T * operator[](int32_t index);
|
||||
const T * operator[](int32_t index) const;
|
||||
~indexed_list() {}
|
||||
};
|
||||
|
||||
template<typename T> int32_t
|
||||
indexed_list<T>::append(T *value) {
|
||||
value->list_index = list.push(value);
|
||||
return value->list_index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Swap delete the last object in the list with the specified object.
|
||||
*/
|
||||
template<typename T> int32_t
|
||||
indexed_list<T>::remove(T *value) {
|
||||
assert (value->list_index >= 0);
|
||||
assert (value->list_index < (int32_t)list.size());
|
||||
int32_t removeIndex = value->list_index;
|
||||
T *last = 0;
|
||||
list.pop(&last);
|
||||
if (last->list_index == removeIndex) {
|
||||
last->list_index = -1;
|
||||
return removeIndex;
|
||||
} else {
|
||||
value->list_index = -1;
|
||||
list[removeIndex] = last;
|
||||
last->list_index = removeIndex;
|
||||
return removeIndex;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> bool
|
||||
indexed_list<T>::pop(T **value) {
|
||||
return list.pop(value);
|
||||
}
|
||||
|
||||
template<typename T> T*
|
||||
indexed_list<T>::pop_value() {
|
||||
T *value = NULL;
|
||||
if (list.pop(&value)) {
|
||||
return value;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <typename T> T *
|
||||
indexed_list<T>::operator[](int32_t index) {
|
||||
T *value = list[index];
|
||||
assert(value->list_index == index);
|
||||
return value;
|
||||
}
|
||||
|
||||
template <typename T> const T *
|
||||
indexed_list<T>::operator[](int32_t index) const {
|
||||
T *value = list[index];
|
||||
assert(value->list_index == index);
|
||||
return value;
|
||||
}
|
||||
|
||||
#endif /* INDEXED_LIST_H */
|
@ -16,8 +16,8 @@ use std::libc;
|
||||
|
||||
#[nolink]
|
||||
extern {
|
||||
static mut debug_static_mut: libc::c_int;
|
||||
pub fn debug_static_mut_check_four();
|
||||
static mut rust_dbg_static_mut: libc::c_int;
|
||||
pub fn rust_dbg_static_mut_check_four();
|
||||
#[cfg(stage37)] //~ ERROR expected item after attributes
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,8 @@ use std::libc;
|
||||
|
||||
#[nolink]
|
||||
extern {
|
||||
static mut debug_static_mut: libc::c_int;
|
||||
pub fn debug_static_mut_check_four();
|
||||
static mut rust_dbg_static_mut: libc::c_int;
|
||||
pub fn rust_dbg_static_mut_check_four();
|
||||
}
|
||||
|
||||
unsafe fn static_bound(_: &'static libc::c_int) {}
|
||||
@ -28,18 +28,18 @@ fn static_bound_set(a: &'static mut libc::c_int) {
|
||||
|
||||
#[fixed_stack_segment] #[inline(never)]
|
||||
unsafe fn run() {
|
||||
assert!(debug_static_mut == 3);
|
||||
debug_static_mut = 4;
|
||||
assert!(debug_static_mut == 4);
|
||||
debug_static_mut_check_four();
|
||||
debug_static_mut += 1;
|
||||
assert!(debug_static_mut == 5);
|
||||
debug_static_mut *= 3;
|
||||
assert!(debug_static_mut == 15);
|
||||
debug_static_mut = -3;
|
||||
assert!(debug_static_mut == -3);
|
||||
static_bound(&debug_static_mut);
|
||||
static_bound_set(&mut debug_static_mut);
|
||||
assert!(rust_dbg_static_mut == 3);
|
||||
rust_dbg_static_mut = 4;
|
||||
assert!(rust_dbg_static_mut == 4);
|
||||
rust_dbg_static_mut_check_four();
|
||||
rust_dbg_static_mut += 1;
|
||||
assert!(rust_dbg_static_mut == 5);
|
||||
rust_dbg_static_mut *= 3;
|
||||
assert!(rust_dbg_static_mut == 15);
|
||||
rust_dbg_static_mut = -3;
|
||||
assert!(rust_dbg_static_mut == -3);
|
||||
static_bound(&rust_dbg_static_mut);
|
||||
static_bound_set(&mut rust_dbg_static_mut);
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
|
@ -16,8 +16,8 @@ mod rustrt {
|
||||
|
||||
#[nolink]
|
||||
extern {
|
||||
pub fn debug_abi_1(q: Quad) -> Quad;
|
||||
pub fn debug_abi_2(f: Floats) -> Floats;
|
||||
pub fn rust_dbg_abi_1(q: Quad) -> Quad;
|
||||
pub fn rust_dbg_abi_2(f: Floats) -> Floats;
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ fn test1() {
|
||||
b: 0xbbbb_bbbb_bbbb_bbbb_u64,
|
||||
c: 0xcccc_cccc_cccc_cccc_u64,
|
||||
d: 0xdddd_dddd_dddd_dddd_u64 };
|
||||
let qq = rustrt::debug_abi_1(q);
|
||||
let qq = rustrt::rust_dbg_abi_1(q);
|
||||
error!("a: %x", qq.a as uint);
|
||||
error!("b: %x", qq.b as uint);
|
||||
error!("c: %x", qq.c as uint);
|
||||
@ -48,7 +48,7 @@ fn test2() {
|
||||
let f = Floats { a: 1.234567890e-15_f64,
|
||||
b: 0b_1010_1010_u8,
|
||||
c: 1.0987654321e-15_f64 };
|
||||
let ff = rustrt::debug_abi_2(f);
|
||||
let ff = rustrt::rust_dbg_abi_2(f);
|
||||
error!("a: %f", ff.a as float);
|
||||
error!("b: %u", ff.b as uint);
|
||||
error!("c: %f", ff.c as float);
|
||||
|
Loading…
x
Reference in New Issue
Block a user