use std::os;
use std::hashmap::HashSet;
+pub enum FileMatch { FileMatches, FileDoesntMatch }
+
// A module for searching for libraries
// FIXME (#2658): I'm not happy how this module turned out. Should
// probably just be folded into cstore.
/// Functions with type `pick` take a parent directory as well as
/// a file found in that directory.
-pub type pick<'self, T> = &'self fn(path: &Path) -> Option<T>;
+pub type pick<'self> = &'self fn(path: &Path) -> FileMatch;
pub fn pick_file(file: Path, path: &Path) -> Option<Path> {
if path.file_path() == file {
pub trait FileSearch {
fn sysroot(&self) -> @Path;
- fn for_each_lib_search_path(&self, f: &fn(&Path) -> bool) -> bool;
+ fn for_each_lib_search_path(&self, f: &fn(&Path) -> FileMatch);
fn get_target_lib_path(&self) -> Path;
fn get_target_lib_file_path(&self, file: &Path) -> Path;
}
}
impl FileSearch for FileSearchImpl {
fn sysroot(&self) -> @Path { self.sysroot }
- fn for_each_lib_search_path(&self, f: &fn(&Path) -> bool) -> bool {
+ fn for_each_lib_search_path(&self, f: &fn(&Path) -> FileMatch) {
let mut visited_dirs = HashSet::new();
+ let mut found = false;
debug!("filesearch: searching additional lib search paths [%?]",
self.addl_lib_search_paths.len());
for path in self.addl_lib_search_paths.iter() {
- f(path);
+ match f(path) {
+ FileMatches => found = true,
+ FileDoesntMatch => ()
+ }
visited_dirs.insert(path.to_str());
}
let tlib_path = make_target_lib_path(self.sysroot,
self.target_triple);
if !visited_dirs.contains(&tlib_path.to_str()) {
- if !f(&tlib_path) {
- return false;
+ match f(&tlib_path) {
+ FileMatches => found = true,
+ FileDoesntMatch => ()
}
}
visited_dirs.insert(tlib_path.to_str());
// Try RUST_PATH
- let rustpath = rust_path();
- for path in rustpath.iter() {
+ if !found {
+ let rustpath = rust_path();
+ for path in rustpath.iter() {
+ debug!("is %s in visited_dirs? %?",
+ path.push("lib").to_str(),
+ visited_dirs.contains(&path.push("lib").to_str()));
+
if !visited_dirs.contains(&path.push("lib").to_str()) {
- f(&path.push("lib"));
visited_dirs.insert(path.push("lib").to_str());
+ // Don't keep searching the RUST_PATH if one match turns up --
+ // if we did, we'd get a "multiple matching crates" error
+ match f(&path.push("lib")) {
+ FileMatches => {
+ break;
+ }
+ FileDoesntMatch => ()
+ }
}
+ }
}
- true
}
fn get_target_lib_path(&self) -> Path {
make_target_lib_path(self.sysroot, self.target_triple)
} as @FileSearch
}
-pub fn search<T>(filesearch: @FileSearch, pick: pick<T>) -> Option<T> {
- let mut rslt = None;
+pub fn search(filesearch: @FileSearch, pick: pick) {
do filesearch.for_each_lib_search_path() |lib_search_path| {
debug!("searching %s", lib_search_path.to_str());
let r = os::list_dir_path(lib_search_path);
+ let mut rslt = FileDoesntMatch;
for path in r.iter() {
debug!("testing %s", path.to_str());
let maybe_picked = pick(path);
match maybe_picked {
- Some(_) => {
+ FileMatches => {
debug!("picked %s", path.to_str());
- rslt = maybe_picked;
- break;
+ rslt = FileMatches;
}
- None => {
+ FileDoesntMatch => {
debug!("rejected %s", path.to_str());
}
}
}
- rslt.is_none()
+ rslt
};
- return rslt;
}
pub fn relative_target_lib_path(target_triple: &str) -> Path {
use lib::llvm::{False, llvm, mk_object_file, mk_section_iter};
use metadata::decoder;
use metadata::encoder;
-use metadata::filesearch::FileSearch;
+use metadata::filesearch::{FileSearch, FileMatch, FileMatches, FileDoesntMatch};
use metadata::filesearch;
use syntax::codemap::span;
use syntax::diagnostic::span_handler;
// want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
let prefix = fmt!("%s%s-", prefix, crate_name);
let mut matches = ~[];
- filesearch::search(filesearch, |path| -> Option<()> {
+ filesearch::search(filesearch, |path| -> FileMatch {
let path_str = path.filename();
match path_str {
- None => None,
+ None => FileDoesntMatch,
Some(path_str) =>
if path_str.starts_with(prefix) && path_str.ends_with(suffix) {
debug!("%s is a candidate", path.to_str());
if !crate_matches(cvec, cx.metas, cx.hash) {
debug!("skipping %s, metadata doesn't match",
path.to_str());
- None
+ FileDoesntMatch
} else {
debug!("found %s with matching metadata", path.to_str());
matches.push((path.to_str(), cvec));
- None
+ FileMatches
},
_ => {
debug!("could not load metadata for %s", path.to_str());
- None
+ FileDoesntMatch
}
}
}
else {
- None
+ FileDoesntMatch
}
}
});
decl_cdecl_fn(ccx.llmod, "amain", llfty)
} else {
let main_name = match ccx.sess.targ_cfg.os {
- session::os_win32 => ~"WinMain@16",
+ session::os_win32 => {
+ match ccx.sess.targ_cfg.arch {
+ X86 => ~"WinMain@16",
+ _ => ~"WinMain",
+ }
+ },
_ => ~"main",
};
decl_cdecl_fn(ccx.llmod, main_name, llfty)
/// True if there's a directory in <workspace> with
/// pkgid's short name
pub fn workspace_contains_package_id(pkgid: &PkgId, workspace: &Path) -> bool {
+ debug!("Checking in src dir of %s for %s",
+ workspace.to_str(), pkgid.to_str());
+
let src_dir = workspace.push("src");
let mut found = false;
}
true
};
+
+ debug!(if found { fmt!("Found %s in %s", pkgid.to_str(), workspace.to_str()) }
+ else { fmt!("Didn't find %s in %s", pkgid.to_str(), workspace.to_str()) });
found
}
// argument
let pkgid = PkgId::new(args[0]);
let workspaces = pkg_parent_workspaces(&pkgid);
+ debug!("package ID = %s, found it in %? workspaces",
+ pkgid.to_str(), workspaces.len());
if workspaces.is_empty() {
let rp = rust_path();
assert!(!rp.is_empty());
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use path_util::installed_library_in_workspace;
+use path_util::{installed_library_in_workspace, rust_path};
+use version::Version;
/// If a library with path `p` matching pkg_id's name exists under sroot_opt,
/// return Some(p). Return None if there's no such path or if sroot_opt is None.
installed_library_in_workspace(short_name, sroot)
}
}
+
+/// If some workspace `p` in the RUST_PATH contains a package matching short_name,
+/// return Some(p) (returns the first one of there are multiple matches.) Return
+/// None if there's no such path.
+/// FIXME #8711: This ignores the desired version.
+pub fn find_installed_library_in_rust_path(short_name: &str, _version: &Version) -> Option<Path> {
+ let rp = rust_path();
+ for p in rp.iter() {
+ match installed_library_in_workspace(short_name, p) {
+ Some(path) => return Some(path),
+ None => ()
+ }
+ }
+ None
+}
push("testsuite").push("pass").push("src").push("fancy-lib").push("pkg.rs");
debug!("package_script_with_default_build: %s", source.to_str());
if !os::copy_file(&source,
- & dir.push("src").push("fancy-lib-0.1").push("pkg.rs")) {
+ &dir.push("src").push("fancy-lib-0.1").push("pkg.rs")) {
fail!("Couldn't copy file");
}
command_line_test([~"install", ~"fancy-lib"], &dir);
assert!(bar_date < foo_date);
}
+// n.b. The following two tests are ignored; they worked "accidentally" before,
+// when the behavior was "always rebuild libraries" (now it's "never rebuild
+// libraries if they already exist"). They can be un-ignored once #7075 is done.
#[test]
+#[ignore(reason = "Workcache not yet implemented -- see #7075")]
fn do_rebuild_dep_dates_change() {
let p_id = PkgId::new("foo");
let dep_id = PkgId::new("bar");
let workspace = create_local_package_with_dep(&p_id, &dep_id);
command_line_test([~"build", ~"foo"], &workspace);
- let bar_date = datestamp(&lib_output_file_name(&workspace, "build", "bar"));
+ let bar_lib_name = lib_output_file_name(&workspace, "build", "bar");
+ let bar_date = datestamp(&bar_lib_name);
+ debug!("Datestamp on %s is %?", bar_lib_name.to_str(), bar_date);
touch_source_file(&workspace, &dep_id);
command_line_test([~"build", ~"foo"], &workspace);
- let new_bar_date = datestamp(&lib_output_file_name(&workspace, "build", "bar"));
+ let new_bar_date = datestamp(&bar_lib_name);
+ debug!("Datestamp on %s is %?", bar_lib_name.to_str(), new_bar_date);
assert!(new_bar_date > bar_date);
}
#[test]
+#[ignore(reason = "Workcache not yet implemented -- see #7075")]
fn do_rebuild_dep_only_contents_change() {
let p_id = PkgId::new("foo");
let dep_id = PkgId::new("bar");
os::EXE_SUFFIX))));
}
+#[test]
+fn multiple_workspaces() {
+// Make a package foo; build/install in directory A
+// Copy the exact same package into directory B and install it
+// Set the RUST_PATH to A:B
+// Make a third package that uses foo, make sure we can build/install it
+ let a_loc = mk_temp_workspace(&Path("foo"), &NoVersion).pop().pop();
+ let b_loc = mk_temp_workspace(&Path("foo"), &NoVersion).pop().pop();
+ debug!("Trying to install foo in %s", a_loc.to_str());
+ command_line_test([~"install", ~"foo"], &a_loc);
+ debug!("Trying to install foo in %s", b_loc.to_str());
+ command_line_test([~"install", ~"foo"], &b_loc);
+ let env = Some(~[(~"RUST_PATH", fmt!("%s:%s", a_loc.to_str(), b_loc.to_str()))]);
+ let c_loc = create_local_package_with_dep(&PkgId::new("bar"), &PkgId::new("foo"));
+ command_line_test_with_env([~"install", ~"bar"], &c_loc, env);
+}
+
/// Returns true if p exists and is executable
fn is_executable(p: &Path) -> bool {
use std::libc::consts::os::posix88::{S_IXUSR};
use rustc::driver::session::{lib_crate, bin_crate};
use context::{Ctx, in_target};
use package_id::PkgId;
-use search::find_library_in_search_path;
+use search::{find_library_in_search_path, find_installed_library_in_rust_path};
use path_util::{target_library_in_workspace, U_RWX};
pub use target::{OutputType, Main, Lib, Bench, Test};
+use version::NoVersion;
// It would be nice to have the list of commands in just one place -- for example,
// you could update the match in rustpkg.rc but forget to update this list. I think
debug!("It exists: %s", installed_path.to_str());
}
None => {
- // Try to install it
- let pkg_id = PkgId::new(lib_name);
- my_ctxt.install(&my_workspace, &pkg_id);
- // Also, add an additional search path
- debug!("let installed_path...")
- let installed_path = target_library_in_workspace(&pkg_id,
+ // FIXME #8711: need to parse version out of path_opt
+ match find_installed_library_in_rust_path(lib_name, &NoVersion) {
+ Some(installed_path) => {
+ debug!("Found library %s, not rebuilding it",
+ installed_path.to_str());
+ // Once workcache is implemented, we'll actually check
+ // whether or not the library at installed_path is fresh
+ save(installed_path.pop());
+ }
+ None => {
+ debug!("Trying to install library %s, rebuilding it",
+ lib_name.to_str());
+ // Try to install it
+ let pkg_id = PkgId::new(lib_name);
+ my_ctxt.install(&my_workspace, &pkg_id);
+ // Also, add an additional search path
+ debug!("let installed_path...")
+ let installed_path = target_library_in_workspace(&pkg_id,
&my_workspace).pop();
- debug!("Great, I installed %s, and it's in %s",
- lib_name, installed_path.to_str());
- save(installed_path);
+ debug!("Great, I installed %s, and it's in %s",
+ lib_name, installed_path.to_str());
+ save(installed_path);
+ }
}
}
+ }
}
// Ignore `use`s
_ => ()
pub fn split_version<'a>(s: &'a str) -> Option<(&'a str, Version)> {
// Check for extra '#' characters separately
if s.split_iter('#').len() > 2 {
- None
- }
- else {
- split_version_general(s, '#')
+ return None;
}
+ split_version_general(s, '#')
}
pub fn split_version_general<'a>(s: &'a str, sep: char) -> Option<(&'a str, Version)> {
use int;
use iterator::Iterator;
use libc::consts::os::posix88::*;
-use libc::{c_int, c_long, c_void, size_t, ssize_t};
+use libc::{c_int, c_void, size_t};
use libc;
use num;
use ops::Drop;
unsafe {
assert!(libc::fseek(*self,
- offset as c_long,
+ offset as libc::c_long,
convert_whence(whence)) == 0 as c_int);
}
}
unsafe {
assert!(libc::fseek(*self,
- offset as c_long,
+ offset as libc::c_long,
convert_whence(whence)) == 0 as c_int);
}
}
fn write(&self, v: &[u8]) {
#[fixed_stack_segment]; #[inline(never)];
+ #[cfg(windows)]
+ type IoSize = libc::c_uint;
+ #[cfg(windows)]
+ type IoRet = c_int;
+
+ #[cfg(unix)]
+ type IoSize = size_t;
+ #[cfg(unix)]
+ type IoRet = libc::ssize_t;
+
unsafe {
let mut count = 0u;
do v.as_imm_buf |vbuf, len| {
while count < len {
let vb = ptr::offset(vbuf, count as int) as *c_void;
- let nout = libc::write(*self, vb, len as size_t);
- if nout < 0 as ssize_t {
+ let nout = libc::write(*self, vb, len as IoSize);
+ if nout < 0 as IoRet {
error!("error writing buffer");
error!("%s", os::last_os_error());
fail!();
pub type LPMEMORY_BASIC_INFORMATION = *mut MEMORY_BASIC_INFORMATION;
}
}
+
+ #[cfg(target_arch = "x86_64")]
+ pub mod arch {
+ pub mod c95 {
+ pub type c_char = i8;
+ pub type c_schar = i8;
+ pub type c_uchar = u8;
+ pub type c_short = i16;
+ pub type c_ushort = u16;
+ pub type c_int = i32;
+ pub type c_uint = u32;
+ pub type c_long = i32;
+ pub type c_ulong = u32;
+ pub type c_float = f32;
+ pub type c_double = f64;
+ pub type size_t = u64;
+ pub type ptrdiff_t = i64;
+ pub type clock_t = i32;
+ pub type time_t = i64;
+ pub type wchar_t = u16;
+ }
+ pub mod c99 {
+ pub type c_longlong = i64;
+ pub type c_ulonglong = u64;
+ pub type intptr_t = int;
+ pub type uintptr_t = uint;
+ }
+ pub mod posix88 {
+ pub type off_t = i32; // XXX unless _FILE_OFFSET_BITS == 64
+ pub type dev_t = u32;
+ pub type ino_t = i16;
+ pub type pid_t = i64;
+ pub type useconds_t = u32;
+ pub type mode_t = u16;
+ pub type ssize_t = i64;
+ }
+ pub mod posix01 {
+ }
+ pub mod posix08 {
+ }
+ pub mod bsd44 {
+ }
+ pub mod extra {
+ use ptr;
+ use libc::types::common::c95::c_void;
+ use libc::types::os::arch::c95::{c_char, c_int, c_uint, size_t};
+ use libc::types::os::arch::c95::{c_ulong};
+ use libc::types::os::arch::c95::{wchar_t};
+ use libc::types::os::arch::c99::{c_ulonglong};
+
+ pub type BOOL = c_int;
+ pub type BYTE = u8;
+ pub type CCHAR = c_char;
+ pub type CHAR = c_char;
+
+ pub type DWORD = c_ulong;
+ pub type DWORDLONG = c_ulonglong;
+
+ pub type HANDLE = LPVOID;
+ pub type HMODULE = c_uint;
+
+ pub type LONG_PTR = i64; // changed
+
+ pub type LPCWSTR = *WCHAR;
+ pub type LPCSTR = *CHAR;
+ pub type LPCTSTR = *CHAR;
+ pub type LPTCH = *CHAR;
+
+ pub type LPWSTR = *mut WCHAR;
+ pub type LPSTR = *mut CHAR;
+ pub type LPTSTR = *mut CHAR;
+
+ // Not really, but opaque to us.
+ pub type LPSECURITY_ATTRIBUTES = LPVOID;
+
+ pub type LPVOID = *mut c_void;
+ pub type LPCVOID = *c_void;
+ pub type LPBYTE = *mut BYTE;
+ pub type LPWORD = *mut WORD;
+ pub type LPDWORD = *mut DWORD;
+ pub type LPHANDLE = *mut HANDLE;
+
+ pub type LRESULT = LONG_PTR;
+ pub type PBOOL = *mut BOOL;
+ pub type WCHAR = wchar_t;
+ pub type WORD = u16;
+ pub type SIZE_T = size_t;
+
+ pub type time64_t = i64;
+ pub type int64 = i64;
+
+ pub struct STARTUPINFO {
+ cb: DWORD,
+ lpReserved: LPTSTR,
+ lpDesktop: LPTSTR,
+ lpTitle: LPTSTR,
+ dwX: DWORD,
+ dwY: DWORD,
+ dwXSize: DWORD,
+ dwYSize: DWORD,
+ dwXCountChars: DWORD,
+ dwYCountCharts: DWORD,
+ dwFillAttribute: DWORD,
+ dwFlags: DWORD,
+ wShowWindow: WORD,
+ cbReserved2: WORD,
+ lpReserved2: LPBYTE,
+ hStdInput: HANDLE,
+ hStdOutput: HANDLE,
+ hStdError: HANDLE
+ }
+ pub type LPSTARTUPINFO = *mut STARTUPINFO;
+
+ pub struct PROCESS_INFORMATION {
+ hProcess: HANDLE,
+ hThread: HANDLE,
+ dwProcessId: DWORD,
+ dwThreadId: DWORD
+ }
+ pub type LPPROCESS_INFORMATION = *mut PROCESS_INFORMATION;
+
+ pub struct SYSTEM_INFO {
+ wProcessorArchitecture: WORD,
+ wReserved: WORD,
+ dwPageSize: DWORD,
+ lpMinimumApplicationAddress: LPVOID,
+ lpMaximumApplicationAddress: LPVOID,
+ dwActiveProcessorMask: DWORD,
+ dwNumberOfProcessors: DWORD,
+ dwProcessorType: DWORD,
+ dwAllocationGranularity: DWORD,
+ wProcessorLevel: WORD,
+ wProcessorRevision: WORD
+ }
+ pub type LPSYSTEM_INFO = *mut SYSTEM_INFO;
+
+ impl SYSTEM_INFO {
+ pub fn new() -> SYSTEM_INFO {
+ SYSTEM_INFO {
+ wProcessorArchitecture: 0,
+ wReserved: 0,
+ dwPageSize: 0,
+ lpMinimumApplicationAddress: ptr::mut_null(),
+ lpMaximumApplicationAddress: ptr::mut_null(),
+ dwActiveProcessorMask: 0,
+ dwNumberOfProcessors: 0,
+ dwProcessorType: 0,
+ dwAllocationGranularity: 0,
+ wProcessorLevel: 0,
+ wProcessorRevision: 0
+ }
+ }
+ }
+
+ pub struct MEMORY_BASIC_INFORMATION {
+ BaseAddress: LPVOID,
+ AllocationBase: LPVOID,
+ AllocationProtect: DWORD,
+ RegionSize: SIZE_T,
+ State: DWORD,
+ Protect: DWORD,
+ Type: DWORD
+ }
+ pub type LPMEMORY_BASIC_INFORMATION = *mut MEMORY_BASIC_INFORMATION;
+ }
+ }
}
#[cfg(target_os = "macos")]
LPSYSTEM_INFO};
use libc::types::os::arch::extra::{HANDLE, LPHANDLE};
+ #[cfg(target_arch = "x86")]
#[abi = "stdcall"]
extern "stdcall" {
pub fn GetEnvironmentVariableW(n: LPCWSTR,
-> LPVOID;
pub fn UnmapViewOfFile(lpBaseAddress: LPCVOID) -> BOOL;
}
+
+ #[cfg(target_arch = "x86_64")]
+ extern {
+ pub fn GetEnvironmentVariableW(n: LPCWSTR,
+ v: LPWSTR,
+ nsize: DWORD)
+ -> DWORD;
+ pub fn SetEnvironmentVariableW(n: LPCWSTR, v: LPCWSTR)
+ -> BOOL;
+ pub fn GetEnvironmentStringsA() -> LPTCH;
+ pub fn FreeEnvironmentStringsA(env_ptr: LPTCH) -> BOOL;
+ pub fn GetModuleFileNameW(hModule: HMODULE,
+ lpFilename: LPWSTR,
+ nSize: DWORD)
+ -> DWORD;
+ pub fn CreateDirectoryW(lpPathName: LPCWSTR,
+ lpSecurityAttributes:
+ LPSECURITY_ATTRIBUTES)
+ -> BOOL;
+ pub fn CopyFileW(lpExistingFileName: LPCWSTR,
+ lpNewFileName: LPCWSTR,
+ bFailIfExists: BOOL)
+ -> BOOL;
+ pub fn DeleteFileW(lpPathName: LPCWSTR) -> BOOL;
+ pub fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL;
+ pub fn SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL;
+ pub fn GetLastError() -> DWORD;
+ pub fn FindFirstFileW(fileName: *u16, findFileData: HANDLE)
+ -> HANDLE;
+ pub fn FindNextFileW(findFile: HANDLE, findFileData: HANDLE)
+ -> BOOL;
+ pub fn FindClose(findFile: HANDLE) -> BOOL;
+ pub fn DuplicateHandle(hSourceProcessHandle: HANDLE,
+ hSourceHandle: HANDLE,
+ hTargetProcessHandle: HANDLE,
+ lpTargetHandle: LPHANDLE,
+ dwDesiredAccess: DWORD,
+ bInheritHandle: BOOL,
+ dwOptions: DWORD)
+ -> BOOL;
+ pub fn CloseHandle(hObject: HANDLE) -> BOOL;
+ pub fn OpenProcess(dwDesiredAccess: DWORD,
+ bInheritHandle: BOOL,
+ dwProcessId: DWORD)
+ -> HANDLE;
+ pub fn GetCurrentProcess() -> HANDLE;
+ pub fn CreateProcessA(lpApplicationName: LPCTSTR,
+ lpCommandLine: LPTSTR,
+ lpProcessAttributes:
+ LPSECURITY_ATTRIBUTES,
+ lpThreadAttributes:
+ LPSECURITY_ATTRIBUTES,
+ bInheritHandles: BOOL,
+ dwCreationFlags: DWORD,
+ lpEnvironment: LPVOID,
+ lpCurrentDirectory: LPCTSTR,
+ lpStartupInfo: LPSTARTUPINFO,
+ lpProcessInformation:
+ LPPROCESS_INFORMATION)
+ -> BOOL;
+ pub fn WaitForSingleObject(hHandle: HANDLE,
+ dwMilliseconds: DWORD)
+ -> DWORD;
+ pub fn TerminateProcess(hProcess: HANDLE, uExitCode: c_uint)
+ -> BOOL;
+ pub fn GetExitCodeProcess(hProcess: HANDLE,
+ lpExitCode: LPDWORD)
+ -> BOOL;
+ pub fn GetSystemInfo(lpSystemInfo: LPSYSTEM_INFO);
+ pub fn VirtualAlloc(lpAddress: LPVOID,
+ dwSize: SIZE_T,
+ flAllocationType: DWORD,
+ flProtect: DWORD)
+ -> LPVOID;
+ pub fn VirtualFree(lpAddress: LPVOID,
+ dwSize: SIZE_T,
+ dwFreeType: DWORD)
+ -> BOOL;
+ pub fn VirtualLock(lpAddress: LPVOID, dwSize: SIZE_T) -> BOOL;
+ pub fn VirtualUnlock(lpAddress: LPVOID, dwSize: SIZE_T)
+ -> BOOL;
+ pub fn VirtualProtect(lpAddress: LPVOID,
+ dwSize: SIZE_T,
+ flNewProtect: DWORD,
+ lpflOldProtect: LPDWORD)
+ -> BOOL;
+ pub fn VirtualQuery(lpAddress: LPCVOID,
+ lpBuffer: LPMEMORY_BASIC_INFORMATION,
+ dwLength: SIZE_T)
+ -> SIZE_T;
+ pub fn CreateFileMappingW(hFile: HANDLE,
+ lpAttributes: LPSECURITY_ATTRIBUTES,
+ flProtect: DWORD,
+ dwMaximumSizeHigh: DWORD,
+ dwMaximumSizeLow: DWORD,
+ lpName: LPCTSTR)
+ -> HANDLE;
+ pub fn MapViewOfFile(hFileMappingObject: HANDLE,
+ dwDesiredAccess: DWORD,
+ dwFileOffsetHigh: DWORD,
+ dwFileOffsetLow: DWORD,
+ dwNumberOfBytesToMap: SIZE_T)
+ -> LPVOID;
+ pub fn UnmapViewOfFile(lpBaseAddress: LPCVOID) -> BOOL;
+ }
}
pub mod msvcrt {
#[fixed_stack_segment]; #[inline(never)];
use libc::types::os::arch::extra::DWORD;
+ #[cfg(target_arch = "x86")]
#[link_name = "kernel32"]
#[abi = "stdcall"]
extern "stdcall" {
fn GetLastError() -> DWORD;
}
+ #[cfg(target_arch = "x86_64")]
+ #[link_name = "kernel32"]
+ extern {
+ fn GetLastError() -> DWORD;
+ }
+
unsafe {
GetLastError() as uint
}
use libc::types::os::arch::extra::LPSTR;
use libc::types::os::arch::extra::LPVOID;
+ #[cfg(target_arch = "x86")]
#[link_name = "kernel32"]
#[abi = "stdcall"]
extern "stdcall" {
-> DWORD;
}
+ #[cfg(target_arch = "x86_64")]
+ #[link_name = "kernel32"]
+ extern {
+ fn FormatMessageA(flags: DWORD,
+ lpSrc: LPVOID,
+ msgId: DWORD,
+ langId: DWORD,
+ buf: LPSTR,
+ nsize: DWORD,
+ args: *c_void)
+ -> DWORD;
+ }
+
static FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000;
static FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200;
type LPCWSTR = *u16;
-#[cfg(windows)]
+#[cfg(windows, target_arch = "x86")]
#[link_name="kernel32"]
#[abi="stdcall"]
extern "stdcall" {
fn LocalFree(ptr: *c_void);
}
-#[cfg(windows)]
+#[cfg(windows, target_arch = "x86_64")]
+#[link_name="kernel32"]
+extern {
+ fn GetCommandLineW() -> LPCWSTR;
+ fn LocalFree(ptr: *c_void);
+}
+
+#[cfg(windows, target_arch = "x86")]
#[link_name="shell32"]
#[abi="stdcall"]
extern "stdcall" {
fn CommandLineToArgvW(lpCmdLine: LPCWSTR, pNumArgs: *mut c_int) -> **u16;
}
+#[cfg(windows, target_arch = "x86_64")]
+#[link_name="shell32"]
+extern {
+ fn CommandLineToArgvW(lpCmdLine: LPCWSTR, pNumArgs: *mut c_int) -> **u16;
+}
+
struct OverriddenArgs {
val: ~[~str]
}
let fp: *c_void = task_start_wrapper as *c_void;
let argp: *c_void = unsafe { transmute::<&~fn(), *c_void>(&*start) };
+ let stack_base: *uint = stack.start();
let sp: *uint = stack.end();
let sp: *mut uint = unsafe { transmute_mut_unsafe(sp) };
// Save and then immediately load the current context,
swap_registers(transmute_mut_region(&mut *regs), transmute_region(&*regs));
};
- initialize_call_frame(&mut *regs, fp, argp, sp);
+ initialize_call_frame(&mut *regs, fp, argp, sp, stack_base);
return Context {
start: Some(start),
}
#[cfg(target_arch = "x86")]
-fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
+fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void,
+ sp: *mut uint, _stack_base: *uint) {
let sp = align_down(sp);
let sp = mut_offset(sp, -4);
regs.ebp = 0;
}
-#[cfg(target_arch = "x86_64")]
+#[cfg(windows, target_arch = "x86_64")]
+type Registers = [uint, ..34];
+#[cfg(not(windows), target_arch = "x86_64")]
type Registers = [uint, ..22];
-#[cfg(target_arch = "x86_64")]
+#[cfg(windows, target_arch = "x86_64")]
+fn new_regs() -> ~Registers { ~([0, .. 34]) }
+#[cfg(not(windows), target_arch = "x86_64")]
fn new_regs() -> ~Registers { ~([0, .. 22]) }
#[cfg(target_arch = "x86_64")]
-fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
+fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void,
+ sp: *mut uint, stack_base: *uint) {
// Redefinitions from regs.h
static RUSTRT_ARG0: uint = 3;
static RUSTRT_IP: uint = 8;
static RUSTRT_RBP: uint = 2;
+ #[cfg(windows)]
+ fn initialize_tib(regs: &mut Registers, sp: *mut uint, stack_base: *uint) {
+ // Redefinitions from regs.h
+ static RUSTRT_ST1: uint = 11; // stack bottom
+ static RUSTRT_ST2: uint = 12; // stack top
+ regs[RUSTRT_ST1] = sp as uint;
+ regs[RUSTRT_ST2] = stack_base as uint;
+ }
+ #[cfg(not(windows))]
+ fn initialize_tib(_: &mut Registers, _: *mut uint, _: *uint) {
+ }
+
+ // Win64 manages stack range at TIB: %gs:0x08 (top) and %gs:0x10 (bottom)
+ initialize_tib(regs, sp, stack_base);
+
let sp = align_down(sp);
let sp = mut_offset(sp, -1);
fn new_regs() -> ~Registers { ~([0, .. 32]) }
#[cfg(target_arch = "arm")]
-fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
+fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void,
+ sp: *mut uint, _stack_base: *uint) {
let sp = align_down(sp);
// sp of arm eabi is 8-byte aligned
let sp = mut_offset(sp, -2);
fn new_regs() -> ~Registers { ~([0, .. 32]) }
#[cfg(target_arch = "mips")]
-fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
+fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void,
+ sp: *mut uint, _stack_base: *uint) {
let sp = align_down(sp);
// sp of mips o32 is 8-byte aligned
let sp = mut_offset(sp, -2);
TlsGetValue(key)
}
-#[cfg(windows)]
+#[cfg(windows, target_arch = "x86")]
#[abi = "stdcall"]
extern "stdcall" {
fn TlsAlloc() -> DWORD;
fn TlsGetValue(dwTlsIndex: DWORD) -> LPVOID;
}
+#[cfg(windows, target_arch = "x86_64")]
+extern {
+ fn TlsAlloc() -> DWORD;
+ fn TlsSetValue(dwTlsIndex: DWORD, lpTlsvalue: LPVOID) -> BOOL;
+ fn TlsGetValue(dwTlsIndex: DWORD) -> LPVOID;
+}
+
#[test]
fn tls_smoke_test() {
use cast::transmute;
FreeLibrary(handle); ()
}
+ #[cfg(target_arch = "x86")]
#[link_name = "kernel32"]
extern "stdcall" {
fn SetLastError(error: u32);
fn GetProcAddress(handle: *libc::c_void, name: *libc::c_char) -> *libc::c_void;
fn FreeLibrary(handle: *libc::c_void);
}
+
+ #[cfg(target_arch = "x86_64")]
+ #[link_name = "kernel32"]
+ extern {
+ fn SetLastError(error: u32);
+ fn LoadLibraryW(name: *u16) -> *libc::c_void;
+ fn GetModuleHandleExW(dwFlags: libc::DWORD, name: *u16,
+ handle: **libc::c_void) -> *libc::c_void;
+ fn GetProcAddress(handle: *libc::c_void, name: *libc::c_char) -> *libc::c_void;
+ fn FreeLibrary(handle: *libc::c_void);
+ }
}
use sys;
use sys::size_of;
use uint;
+use unstable::finally::Finally;
use unstable::intrinsics;
use unstable::intrinsics::{get_tydesc, contains_managed};
use unstable::raw::{Box, Repr, Slice, Vec};
let mut v = with_capacity(n_elts);
let p = raw::to_mut_ptr(v);
let mut i: uint = 0u;
- while i < n_elts {
- intrinsics::move_val_init(&mut(*ptr::mut_offset(p, i as int)), op(i));
- i += 1u;
+ do (|| {
+ while i < n_elts {
+ intrinsics::move_val_init(&mut(*ptr::mut_offset(p, i as int)), op(i));
+ i += 1u;
+ }
+ }).finally {
+ raw::set_len(&mut v, i);
}
- raw::set_len(&mut v, n_elts);
v
}
}
anyhow.
*/
-#if defined(__APPLE__) || defined(_WIN32)
+#if defined(__APPLE__)
#define SWAP_REGISTERS _swap_registers
#else
#define SWAP_REGISTERS swap_registers
mov %r14, (RUSTRT_R14*8)(ARG0)
mov %r15, (RUSTRT_R15*8)(ARG0)
+#if defined(__MINGW32__) || defined(_WINDOWS)
+ mov %rdi, (RUSTRT_RDI*8)(ARG0)
+ mov %rsi, (RUSTRT_RSI*8)(ARG0)
+
+ // Save stack range
+ mov %gs:0x08, %r8
+ mov %r8, (RUSTRT_ST1*8)(ARG0)
+ mov %gs:0x10, %r9
+ mov %r9, (RUSTRT_ST2*8)(ARG0)
+#endif
+
// Save 0th argument register:
mov ARG0, (RUSTRT_ARG0*8)(ARG0)
// Save non-volatile XMM registers:
+#if defined(__MINGW32__) || defined(_WINDOWS)
+ movapd %xmm6, (RUSTRT_XMM6*8)(ARG0)
+ movapd %xmm7, (RUSTRT_XMM7*8)(ARG0)
+ movapd %xmm8, (RUSTRT_XMM8*8)(ARG0)
+ movapd %xmm9, (RUSTRT_XMM9*8)(ARG0)
+ movapd %xmm10, (RUSTRT_XMM10*8)(ARG0)
+ movapd %xmm11, (RUSTRT_XMM11*8)(ARG0)
+ movapd %xmm12, (RUSTRT_XMM12*8)(ARG0)
+ movapd %xmm13, (RUSTRT_XMM13*8)(ARG0)
+ movapd %xmm14, (RUSTRT_XMM14*8)(ARG0)
+ movapd %xmm15, (RUSTRT_XMM15*8)(ARG0)
+#else
movapd %xmm0, (RUSTRT_XMM0*8)(ARG0)
movapd %xmm1, (RUSTRT_XMM1*8)(ARG0)
movapd %xmm2, (RUSTRT_XMM2*8)(ARG0)
movapd %xmm3, (RUSTRT_XMM3*8)(ARG0)
movapd %xmm4, (RUSTRT_XMM4*8)(ARG0)
movapd %xmm5, (RUSTRT_XMM5*8)(ARG0)
+#endif
// Restore non-volatile integer registers:
// (including RSP)
mov (RUSTRT_R14*8)(ARG1), %r14
mov (RUSTRT_R15*8)(ARG1), %r15
+#if defined(__MINGW32__) || defined(_WINDOWS)
+ mov (RUSTRT_RDI*8)(ARG1), %rdi
+ mov (RUSTRT_RSI*8)(ARG1), %rsi
+
+ // Restore stack range
+ mov (RUSTRT_ST1*8)(ARG1), %r8
+ mov %r8, %gs:0x08
+ mov (RUSTRT_ST2*8)(ARG1), %r9
+ mov %r9, %gs:0x10
+#endif
+
// Restore 0th argument register:
mov (RUSTRT_ARG0*8)(ARG1), ARG0
// Restore non-volatile XMM registers:
+#if defined(__MINGW32__) || defined(_WINDOWS)
+ movapd (RUSTRT_XMM6*8)(ARG1), %xmm6
+ movapd (RUSTRT_XMM7*8)(ARG1), %xmm7
+ movapd (RUSTRT_XMM8*8)(ARG1), %xmm8
+ movapd (RUSTRT_XMM9*8)(ARG1), %xmm9
+ movapd (RUSTRT_XMM10*8)(ARG1), %xmm10
+ movapd (RUSTRT_XMM11*8)(ARG1), %xmm11
+ movapd (RUSTRT_XMM12*8)(ARG1), %xmm12
+ movapd (RUSTRT_XMM13*8)(ARG1), %xmm13
+ movapd (RUSTRT_XMM14*8)(ARG1), %xmm14
+ movapd (RUSTRT_XMM15*8)(ARG1), %xmm15
+#else
movapd (RUSTRT_XMM0*8)(ARG1), %xmm0
movapd (RUSTRT_XMM1*8)(ARG1), %xmm1
movapd (RUSTRT_XMM2*8)(ARG1), %xmm2
movapd (RUSTRT_XMM3*8)(ARG1), %xmm3
movapd (RUSTRT_XMM4*8)(ARG1), %xmm4
movapd (RUSTRT_XMM5*8)(ARG1), %xmm5
+#endif
// Jump to the instruction pointer
// found in regs:
.text
-#if defined(__APPLE__) || defined(_WIN32)
+#if defined(__APPLE__)
.globl ___morestack
.private_extern MORESTACK
___morestack:
+#elif defined(_WIN32)
+.globl __morestack
+__morestack:
#else
.globl __morestack
.hidden __morestack
.text
-#if defined(__APPLE__) || defined(_WIN32)
+#if defined(__APPLE__)
#define UPCALL_NEW_STACK _upcall_new_stack
#define UPCALL_DEL_STACK _upcall_del_stack
#define MORESTACK ___morestack
#define RUSTRT_R14 6
#define RUSTRT_R15 7
#define RUSTRT_IP 8
-// Not used, just padding
-#define RUSTRT_XXX 9
-#define RUSTRT_XMM0 10
-#define RUSTRT_XMM1 12
-#define RUSTRT_XMM2 14
-#define RUSTRT_XMM3 16
-#define RUSTRT_XMM4 18
-#define RUSTRT_XMM5 20
-#define RUSTRT_MAX 22
+#if defined(__MINGW32__) || defined(_WINDOWS)
+ #define RUSTRT_RDI 9
+ #define RUSTRT_RSI 10
+ #define RUSTRT_ST1 11
+ #define RUSTRT_ST2 12
+ #define RUSTRT_XMM6 14
+ #define RUSTRT_XMM7 16
+ #define RUSTRT_XMM8 18
+ #define RUSTRT_XMM9 20
+ #define RUSTRT_XMM10 22
+ #define RUSTRT_XMM11 24
+ #define RUSTRT_XMM12 26
+ #define RUSTRT_XMM13 28
+ #define RUSTRT_XMM14 30
+ #define RUSTRT_XMM15 32
+ #define RUSTRT_MAX 34
+#else
+ // Not used, just padding
+ #define RUSTRT_XXX 9
+ #define RUSTRT_XMM0 10
+ #define RUSTRT_XMM1 12
+ #define RUSTRT_XMM2 14
+ #define RUSTRT_XMM3 16
+ #define RUSTRT_XMM4 18
+ #define RUSTRT_XMM5 20
+ #define RUSTRT_MAX 22
+#endif
// ARG0 is the register in which the first argument goes.
// Naturally this depends on your operating system.
asm volatile (
"movq %%fs:24, %0"
: "=r"(limit));
+#elif defined(_WIN64)
+ asm volatile (
+ "movq %%gs:0x28, %0"
+ : "=r"(limit));
#endif
return limit;
asm volatile (
"movq %0, %%fs:24"
:: "r"(limit));
+#elif defined(_WIN64)
+ asm volatile (
+ "movq %0, %%gs:0x28"
+ :: "r"(limit));
#endif
}
/**********************************************************************/
+#ifdef __SEH__
+# define PERSONALITY_FUNC __gxx_personality_seh0
+#else
+# ifdef __USING_SJLJ_EXCEPTIONS__
+# define PERSONALITY_FUNC __gxx_personality_sjlj
+# else
+# define PERSONALITY_FUNC __gxx_personality_v0
+# endif
+#endif
+
extern "C" _Unwind_Reason_Code
-__gxx_personality_v0(int version,
+PERSONALITY_FUNC(int version,
_Unwind_Action actions,
uint64_t exception_class,
_Unwind_Exception *ue_header,
extern "C" void
upcall_s_rust_personality(s_rust_personality_args *args) {
- args->retval = __gxx_personality_v0(args->version,
- args->actions,
- args->exception_class,
- args->ue_header,
- args->context);
+ args->retval = PERSONALITY_FUNC(args->version,
+ args->actions,
+ args->exception_class,
+ args->ue_header,
+ args->context);
}
/**
#undef PLAT_x86_darwin
#undef PLAT_amd64_darwin
#undef PLAT_x86_win32
+#undef PLAT_amd64_win64
#undef PLAT_x86_linux
#undef PLAT_amd64_linux
#undef PLAT_ppc32_linux
# define PLAT_amd64_darwin 1
#elif defined(__MINGW32__) || defined(__CYGWIN32__) \
|| (defined(_WIN32) && defined(_M_IX86))
-# define PLAT_x86_win32 1
+# if defined(__x86_64__)
+# define PLAT_amd64_win64 1
+# elif defined(__i386__)
+# define PLAT_x86_win32 1
+# endif
#elif defined(__linux__) && defined(__i386__)
# define PLAT_x86_linux 1
#elif defined(__linux__) && defined(__x86_64__)
/* ------------------------ amd64-{linux,darwin} --------------- */
-#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin)
+#if defined(PLAT_amd64_linux) || defined(PLAT_amd64_darwin) \
+ || defined(PLAT_amd64_win64)
typedef
struct {
#if defined(NVALGRIND)
return 0;
#else /* NVALGRIND */
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) || defined(PLAT_amd64_win64)
uintptr_t _qzz_res;
#else
unsigned long _qzz_res;
#endif
va_list vargs;
va_start(vargs, format);
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) || defined(PLAT_amd64_win64)
_qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
VG_USERREQ__PRINTF_VALIST_BY_REF,
(uintptr_t)format,
#if defined(NVALGRIND)
return 0;
#else /* NVALGRIND */
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) || defined(PLAT_amd64_win64)
uintptr_t _qzz_res;
#else
unsigned long _qzz_res;
#endif
va_list vargs;
va_start(vargs, format);
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) || defined(PLAT_amd64_win64)
_qzz_res = VALGRIND_DO_CLIENT_REQUEST_EXPR(0,
VG_USERREQ__PRINTF_BACKTRACE_VALIST_BY_REF,
(uintptr_t)format,