conventions. Rust provides a way to tell the compiler which convention to use:
~~~~
-#[cfg(target_os = "win32")]
+#[cfg(target_os = "win32", target_arch = "x86")]
#[link_name = "kernel32"]
extern "stdcall" {
fn SetEnvironmentVariableA(n: *u8, v: *u8) -> int;
}
~~~~
-This applies to the entire `extern` block, and must be either `"cdecl"` or
-`"stdcall"`. The compiler may eventually support other calling conventions.
+This applies to the entire `extern` block. The list of supported ABI constraints
+are:
+
+* `stdcall`
+* `aapcs`
+* `cdecl`
+* `fastcall`
+* `Rust`
+* `rust-intrinsic`
+* `system`
+* `C`
+
+Most of the abis in this list are self-explanatory, but the `system` abi may
+seem a little odd. This constraint selects whatever the appropriate ABI is for
+interoperating with the target's libraries. For example, on win32 with a x86
+architecture, this means that the abi used would be `stdcall`. On x86_64,
+however, windows uses the `C` calling convention, so `C` would be used. This
+means that in our previous example, we could have used `extern "system" { ... }`
+to define a block for all windows systems, not just x86 ones.
# Interoperability with foreign code
use back::target_strs;
use driver::session::sess_os_to_meta_os;
-use driver::session;
use metadata::loader::meta_section_name;
+use syntax::abi;
-pub fn get_target_strs(target_triple: ~str, target_os: session::Os) -> target_strs::t {
+pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs::t {
return target_strs::t {
module_asm: ~"",
meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(),
data_layout: match target_os {
- session::OsMacos => {
+ abi::OsMacos => {
~"e-p:32:32:32" +
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
"-f32:32:32-f64:64:64" +
"-a0:0:64-n32"
}
- session::OsWin32 => {
+ abi::OsWin32 => {
~"e-p:32:32:32" +
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
"-f32:32:32-f64:64:64" +
"-a0:0:64-n32"
}
- session::OsLinux => {
+ abi::OsLinux => {
~"e-p:32:32:32" +
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
"-f32:32:32-f64:64:64" +
"-a0:0:64-n32"
}
- session::OsAndroid => {
+ abi::OsAndroid => {
~"e-p:32:32:32" +
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
"-f32:32:32-f64:64:64" +
"-a0:0:64-n32"
}
- session::OsFreebsd => {
+ abi::OsFreebsd => {
~"e-p:32:32:32" +
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
"-f32:32:32-f64:64:64" +
use std::str;
use std::vec;
use std::rt::io::fs;
+use syntax::abi;
use syntax::ast;
use syntax::ast_map::{path, path_mod, path_name, path_pretty_name};
use syntax::attr;
}
-pub fn output_dll_filename(os: session::Os, lm: LinkMeta) -> ~str {
+pub fn output_dll_filename(os: abi::Os, lm: LinkMeta) -> ~str {
let (dll_prefix, dll_suffix) = match os {
- session::OsWin32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX),
- session::OsMacos => (macos::DLL_PREFIX, macos::DLL_SUFFIX),
- session::OsLinux => (linux::DLL_PREFIX, linux::DLL_SUFFIX),
- session::OsAndroid => (android::DLL_PREFIX, android::DLL_SUFFIX),
- session::OsFreebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
+ abi::OsWin32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX),
+ abi::OsMacos => (macos::DLL_PREFIX, macos::DLL_SUFFIX),
+ abi::OsLinux => (linux::DLL_PREFIX, linux::DLL_SUFFIX),
+ abi::OsAndroid => (android::DLL_PREFIX, android::DLL_SUFFIX),
+ abi::OsFreebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
};
format!("{}{}-{}-{}{}", dll_prefix, lm.name, lm.extras_hash, lm.vers, dll_suffix)
}
match sess.opts.linker {
Some(ref linker) => linker.to_str(),
None => match sess.targ_cfg.os {
- session::OsAndroid =>
+ abi::OsAndroid =>
match &sess.opts.android_cross_path {
&Some(ref path) => {
format!("{}/bin/arm-linux-androideabi-gcc", *path)
(--android-cross-path)")
}
},
- session::OsWin32 => ~"g++",
+ abi::OsWin32 => ~"g++",
_ => ~"cc"
}
}
}
// Clean up on Darwin
- if sess.targ_cfg.os == session::OsMacos {
+ if sess.targ_cfg.os == abi::OsMacos {
// FIXME (#9639): This needs to handle non-utf8 paths
run::process_status("dsymutil", [output.as_str().unwrap().to_owned()]);
}
// Converts a library file-stem into a cc -l argument
fn unlib(config: @session::config, stem: ~str) -> ~str {
if stem.starts_with("lib") &&
- config.os != session::OsWin32 {
+ config.os != abi::OsWin32 {
stem.slice(3, stem.len()).to_owned()
} else {
stem
obj_filename.as_str().unwrap().to_owned()]);
let lib_cmd = match sess.targ_cfg.os {
- session::OsMacos => ~"-dynamiclib",
+ abi::OsMacos => ~"-dynamiclib",
_ => ~"-shared"
};
// On mac we need to tell the linker to let this library
// be rpathed
- if sess.targ_cfg.os == session::OsMacos {
+ if sess.targ_cfg.os == abi::OsMacos {
// FIXME (#9639): This needs to handle non-utf8 paths
args.push("-Wl,-install_name,@rpath/"
+ output.filename_str().unwrap());
// On linux librt and libdl are an indirect dependencies via rustrt,
// and binutils 2.22+ won't add them automatically
- if sess.targ_cfg.os == session::OsLinux {
+ if sess.targ_cfg.os == abi::OsLinux {
args.push_all([~"-lrt", ~"-ldl"]);
// LLVM implements the `frem` instruction as a call to `fmod`,
// have to be explicit about linking to it. See #2510
args.push(~"-lm");
}
- else if sess.targ_cfg.os == session::OsAndroid {
+ else if sess.targ_cfg.os == abi::OsAndroid {
args.push_all([~"-ldl", ~"-llog", ~"-lsupc++", ~"-lgnustl_shared"]);
args.push(~"-lm");
}
- if sess.targ_cfg.os == session::OsFreebsd {
+ if sess.targ_cfg.os == abi::OsFreebsd {
args.push_all([~"-pthread", ~"-lrt",
~"-L/usr/local/lib", ~"-lexecinfo",
~"-L/usr/local/lib/gcc46",
// except according to those terms.
use back::target_strs;
-use driver::session;
use driver::session::sess_os_to_meta_os;
use metadata::loader::meta_section_name;
+use syntax::abi;
-pub fn get_target_strs(target_triple: ~str, target_os: session::Os) -> target_strs::t {
+pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs::t {
return target_strs::t {
module_asm: ~"",
meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(),
data_layout: match target_os {
- session::OsMacos => {
+ abi::OsMacos => {
~"e-p:32:32:32" +
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
"-f32:32:32-f64:64:64" +
"-a0:0:64-n32"
}
- session::OsWin32 => {
+ abi::OsWin32 => {
~"e-p:32:32:32" +
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
"-f32:32:32-f64:64:64" +
"-a0:0:64-n32"
}
- session::OsLinux => {
+ abi::OsLinux => {
~"e-p:32:32:32" +
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
"-f32:32:32-f64:64:64" +
"-a0:0:64-n32"
}
- session::OsAndroid => {
+ abi::OsAndroid => {
~"e-p:32:32:32" +
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
"-f32:32:32-f64:64:64" +
"-a0:0:64-n32"
}
- session::OsFreebsd => {
+ abi::OsFreebsd => {
~"e-p:32:32:32" +
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
"-f32:32:32-f64:64:64" +
use std::hashmap::HashSet;
use std::{os, vec};
+use syntax::abi;
-fn not_win32(os: session::Os) -> bool {
- os != session::OsWin32
+fn not_win32(os: abi::Os) -> bool {
+ os != abi::OsWin32
}
pub fn get_rpath_flags(sess: session::Session, out_filename: &Path)
let os = sess.targ_cfg.os;
// No rpath on windows
- if os == session::OsWin32 {
+ if os == abi::OsWin32 {
return ~[];
}
rpaths.iter().map(|rpath| format!("-Wl,-rpath,{}",*rpath)).collect()
}
-fn get_rpaths(os: session::Os,
+fn get_rpaths(os: abi::Os,
sysroot: &Path,
output: &Path,
libs: &[Path],
return rpaths;
}
-fn get_rpaths_relative_to_output(os: session::Os,
+fn get_rpaths_relative_to_output(os: abi::Os,
output: &Path,
libs: &[Path]) -> ~[~str] {
libs.iter().map(|a| get_rpath_relative_to_output(os, output, a)).collect()
}
-pub fn get_rpath_relative_to_output(os: session::Os,
+pub fn get_rpath_relative_to_output(os: abi::Os,
output: &Path,
lib: &Path)
-> ~str {
// Mac doesn't appear to support $ORIGIN
let prefix = match os {
- session::OsAndroid | session::OsLinux | session::OsFreebsd
+ abi::OsAndroid | abi::OsLinux | abi::OsFreebsd
=> "$ORIGIN",
- session::OsMacos => "@loader_path",
- session::OsWin32 => unreachable!()
+ abi::OsMacos => "@loader_path",
+ abi::OsWin32 => unreachable!()
};
let mut lib = os::make_absolute(lib);
mod test {
use std::os;
- // FIXME(#2119): the outer attribute should be #[cfg(unix, test)], then
- // these redundant #[cfg(test)] blocks can be removed
- #[cfg(test)]
- #[cfg(test)]
use back::rpath::{get_absolute_rpath, get_install_prefix_rpath};
use back::rpath::{minimize_rpaths, rpaths_to_flags, get_rpath_relative_to_output};
use driver::session;
+ use syntax::abi;
#[test]
fn test_rpaths_to_flags() {
#[cfg(target_os = "linux")]
#[cfg(target_os = "android")]
fn test_rpath_relative() {
- let o = session::OsLinux;
+ let o = abi::OsLinux;
let res = get_rpath_relative_to_output(o,
&Path::new("bin/rustc"), &Path::new("lib/libstd.so"));
assert_eq!(res.as_slice(), "$ORIGIN/../lib");
#[test]
#[cfg(target_os = "freebsd")]
fn test_rpath_relative() {
- let o = session::OsFreebsd;
+ let o = abi::OsFreebsd;
let res = get_rpath_relative_to_output(o,
&Path::new("bin/rustc"), &Path::new("lib/libstd.so"));
assert_eq!(res.as_slice(), "$ORIGIN/../lib");
#[test]
#[cfg(target_os = "macos")]
fn test_rpath_relative() {
- let o = session::OsMacos;
+ let o = abi::OsMacos;
let res = get_rpath_relative_to_output(o,
&Path::new("bin/rustc"),
&Path::new("lib/libstd.so"));
use back::target_strs;
use driver::session::sess_os_to_meta_os;
-use driver::session;
use metadata::loader::meta_section_name;
+use syntax::abi;
-pub fn get_target_strs(target_triple: ~str, target_os: session::Os) -> target_strs::t {
+pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs::t {
return target_strs::t {
module_asm: ~"",
meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(),
data_layout: match target_os {
- session::OsMacos => {
+ abi::OsMacos => {
~"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16" +
"-i32:32:32-i64:32:64" +
"-f32:32:32-f64:32:64-v64:64:64" +
"-v128:128:128-a0:0:64-f80:128:128" + "-n8:16:32"
}
- session::OsWin32 => {
+ abi::OsWin32 => {
~"e-p:32:32-f64:64:64-i64:64:64-f80:32:32-n8:16:32"
}
- session::OsLinux => {
+ abi::OsLinux => {
~"e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32"
}
- session::OsAndroid => {
+ abi::OsAndroid => {
~"e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32"
}
- session::OsFreebsd => {
+ abi::OsFreebsd => {
~"e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32"
}
},
use back::target_strs;
use driver::session::sess_os_to_meta_os;
-use driver::session;
use metadata::loader::meta_section_name;
+use syntax::abi;
-pub fn get_target_strs(target_triple: ~str, target_os: session::Os) -> target_strs::t {
+pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs::t {
return target_strs::t {
module_asm: ~"",
meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(),
data_layout: match target_os {
- session::OsMacos => {
+ abi::OsMacos => {
~"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-"+
"f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-"+
"s0:64:64-f80:128:128-n8:16:32:64"
}
- session::OsWin32 => {
+ abi::OsWin32 => {
// FIXME: Test this. Copied from linux (#2398)
~"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-"+
"f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-"+
"s0:64:64-f80:128:128-n8:16:32:64-S128"
}
- session::OsLinux => {
+ abi::OsLinux => {
~"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-"+
"f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-"+
"s0:64:64-f80:128:128-n8:16:32:64-S128"
}
- session::OsAndroid => {
+ abi::OsAndroid => {
~"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-"+
"f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-"+
"s0:64:64-f80:128:128-n8:16:32:64-S128"
}
- session::OsFreebsd => {
+ abi::OsFreebsd => {
~"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-"+
"f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-"+
"s0:64:64-f80:128:128-n8:16:32:64-S128"
pub fn default_configuration(sess: Session) ->
ast::CrateConfig {
let tos = match sess.targ_cfg.os {
- session::OsWin32 => @"win32",
- session::OsMacos => @"macos",
- session::OsLinux => @"linux",
- session::OsAndroid => @"android",
- session::OsFreebsd => @"freebsd"
+ abi::OsWin32 => @"win32",
+ abi::OsMacos => @"macos",
+ abi::OsLinux => @"linux",
+ abi::OsAndroid => @"android",
+ abi::OsFreebsd => @"freebsd"
};
// ARM is bi-endian, however using NDK seems to default
// segmented stacks are enabled. However, unwind info directives in assembly
// output are OK, so we generate assembly first and then run it through
// an external assembler.
- if sess.targ_cfg.os == session::OsWin32 &&
+ if sess.targ_cfg.os == abi::OsWin32 &&
(sess.opts.output_type == link::output_type_object ||
sess.opts.output_type == link::output_type_exe) {
let output_type = link::output_type_assembly;
is_expanded);
}
-pub fn get_os(triple: &str) -> Option<session::Os> {
+pub fn get_os(triple: &str) -> Option<abi::Os> {
for &(name, os) in os_names.iter() {
if triple.contains(name) { return Some(os) }
}
None
}
-static os_names : &'static [(&'static str, session::Os)] = &'static [
- ("mingw32", session::OsWin32),
- ("win32", session::OsWin32),
- ("darwin", session::OsMacos),
- ("android", session::OsAndroid),
- ("linux", session::OsLinux),
- ("freebsd", session::OsFreebsd)];
+static os_names : &'static [(&'static str, abi::Os)] = &'static [
+ ("mingw32", abi::OsWin32),
+ ("win32", abi::OsWin32),
+ ("darwin", abi::OsMacos),
+ ("android", abi::OsAndroid),
+ ("linux", abi::OsLinux),
+ ("freebsd", abi::OsFreebsd)];
pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
for &(arch, abi) in architecture_abis.iter() {
use std::int;
use std::hashmap::{HashMap,HashSet};
-#[deriving(Eq)]
-pub enum Os { OsWin32, OsMacos, OsLinux, OsAndroid, OsFreebsd, }
-
#[deriving(Clone)]
pub enum crate_type {
bin_crate,
}
pub struct config {
- os: Os,
+ os: abi::Os,
arch: abi::Architecture,
target_strs: target_strs::t,
int_type: int_ty,
}
}
-pub fn sess_os_to_meta_os(os: Os) -> metadata::loader::Os {
+pub fn sess_os_to_meta_os(os: abi::Os) -> metadata::loader::Os {
use metadata::loader;
match os {
- OsWin32 => loader::OsWin32,
- OsLinux => loader::OsLinux,
- OsAndroid => loader::OsAndroid,
- OsMacos => loader::OsMacos,
- OsFreebsd => loader::OsFreebsd
+ abi::OsWin32 => loader::OsWin32,
+ abi::OsLinux => loader::OsLinux,
+ abi::OsAndroid => loader::OsAndroid,
+ abi::OsMacos => loader::OsMacos,
+ abi::OsFreebsd => loader::OsFreebsd
}
}
use driver::session;
use driver::session::Session;
+use syntax::abi;
use syntax::ast::{Crate, NodeId, item, item_fn};
use syntax::ast_map;
use syntax::attr;
// FIXME #4404 android JNI hacks
if *session.building_library &&
- session.targ_cfg.os != session::OsAndroid {
+ session.targ_cfg.os != abi::OsAndroid {
// No need to find a main function
return;
}
} else {
// If we *are* building a library, then we're on android where we still might
// optionally want to translate main $4404
- assert_eq!(this.session.targ_cfg.os, session::OsAndroid);
+ assert_eq!(this.session.targ_cfg.os, abi::OsAndroid);
}
}
}
use syntax::parse::token::{special_idents};
use syntax::print::pprust::stmt_to_str;
use syntax::{ast, ast_util, codemap, ast_map};
-use syntax::abi::{X86, X86_64, Arm, Mips, Rust, RustIntrinsic};
+use syntax::abi::{X86, X86_64, Arm, Mips, Rust, RustIntrinsic, OsWin32, OsAndroid};
use syntax::visit;
use syntax::visit::Visitor;
let name = csearch::get_symbol(ccx.sess.cstore, did);
match ty::get(t).sty {
ty::ty_bare_fn(ref fn_ty) => {
- match fn_ty.abis.for_arch(ccx.sess.targ_cfg.arch) {
+ match fn_ty.abis.for_target(ccx.sess.targ_cfg.os,
+ ccx.sess.targ_cfg.arch) {
Some(Rust) | Some(RustIntrinsic) => {
get_extern_rust_fn(ccx, fn_ty.sig.inputs, fn_ty.sig.output, name, did)
}
// FIXME #4404 android JNI hacks
let is_entry = is_entry_fn(&ccx.sess, node_id) && (!*ccx.sess.building_library ||
(*ccx.sess.building_library &&
- ccx.sess.targ_cfg.os == session::OsAndroid));
+ ccx.sess.targ_cfg.os == OsAndroid));
if is_entry {
create_entry_wrapper(ccx, sp, llfn);
}
};
// On windows we'd like to export the toplevel cratemap
// such that we can find it from libstd.
- if targ_cfg.os == session::OsWin32 && "toplevel" == mapname {
+ if targ_cfg.os == OsWin32 && "toplevel" == mapname {
lib::llvm::SetLinkage(map, lib::llvm::DLLExportLinkage);
} else {
lib::llvm::SetLinkage(map, lib::llvm::ExternalLinkage);
// __rust_crate_map_toplevel symbol (extra underscore) which it will
// subsequently fail to find. So to mitigate that we just introduce
// an alias from the symbol it expects to the one that actually exists.
- if ccx.sess.targ_cfg.os == session::OsWin32 &&
+ if ccx.sess.targ_cfg.os == OsWin32 &&
!*ccx.sess.building_library {
let maptype = val_ty(ccx.crate_map).to_ref();
// except according to those terms.
-use driver::session::{OsWin32, OsMacos};
+use syntax::abi::{OsWin32, OsMacos};
use lib::llvm::*;
use super::cabi::*;
use super::common::*;
use syntax::{ast};
use syntax::{attr, ast_map};
use syntax::parse::token::special_idents;
-use syntax::abi::{RustIntrinsic, Rust, Stdcall, Fastcall,
+use syntax::abi::{RustIntrinsic, Rust, Stdcall, Fastcall, System,
Cdecl, Aapcs, C, AbiSet};
use util::ppaux::{Repr, UserString};
use middle::trans::type_::Type;
pub fn llvm_calling_convention(ccx: &mut CrateContext,
abis: AbiSet) -> Option<CallConv> {
+ let os = ccx.sess.targ_cfg.os;
let arch = ccx.sess.targ_cfg.arch;
- abis.for_arch(arch).map(|abi| {
+ abis.for_target(os, arch).map(|abi| {
match abi {
RustIntrinsic => {
// Intrinsics are emitted by monomorphic fn
format!("Foreign functions with Rust ABI"));
}
+ // It's the ABI's job to select this, not us.
+ System => ccx.sess.bug("System abi should be selected elsewhere"),
+
Stdcall => lib::llvm::X86StdcallCallConv,
Fastcall => lib::llvm::X86FastcallCallConv,
C => lib::llvm::CCallConv,
use std::to_bytes;
+#[deriving(Eq)]
+pub enum Os { OsWin32, OsMacos, OsLinux, OsAndroid, OsFreebsd, }
+
#[deriving(Eq)]
pub enum Abi {
// NB: This ordering MUST match the AbiDatas array below.
// Multiplatform ABIs second
Rust,
C,
+ System,
RustIntrinsic,
}
// adjusting the indices below.
AbiData {abi: Rust, name: "Rust", abi_arch: RustArch},
AbiData {abi: C, name: "C", abi_arch: AllArch},
+ AbiData {abi: System, name: "system", abi_arch: AllArch},
AbiData {abi: RustIntrinsic, name: "rust-intrinsic", abi_arch: RustArch},
];
pub fn name(&self) -> &'static str {
self.data().name
}
+
+ pub fn for_target(&self, os: Os, arch: Architecture) -> Abi {
+ match (*self, os, arch) {
+ (System, OsWin32, X86) => Stdcall,
+ (System, _, _) => C,
+ (me, _, _) => me,
+ }
+ }
}
impl Architecture {
self.bits == 0
}
- pub fn for_arch(&self, arch: Architecture) -> Option<Abi> {
+ pub fn for_target(&self, os: Os, arch: Architecture) -> Option<Abi> {
// NB---Single platform ABIs come first
let mut res = None;
}
};
- res
+ res.map(|r| r.for_target(os, arch))
}
pub fn check_valid(&self) -> Option<(Abi, Abi)> {
cannot_combine(RustIntrinsic, Cdecl);
}
+#[test]
+fn can_combine_system_and_cdecl() {
+ can_combine(System, Cdecl);
+}
+
#[test]
fn can_combine_c_and_stdcall() {
can_combine(C, Stdcall);
#[test]
fn indices_are_correct() {
for (i, abi_data) in AbiDatas.iter().enumerate() {
- assert!(i == abi_data.abi.index());
+ assert_eq!(i, abi_data.abi.index());
}
let bits = 1 << (X86 as u32);
let bits = bits | 1 << (X86_64 as u32);
- assert!(IntelBits == bits);
+ assert_eq!(IntelBits, bits);
let bits = 1 << (Arm as u32);
- assert!(ArmBits == bits);
+ assert_eq!(ArmBits, bits);
}
#[cfg(test)]
-fn check_arch(abis: &[Abi], arch: Architecture, expect: Option<Abi>) {
+fn get_arch(abis: &[Abi], os: Os, arch: Architecture) -> Option<Abi> {
let mut set = AbiSet::empty();
for &abi in abis.iter() {
set.add(abi);
}
- let r = set.for_arch(arch);
- assert!(r == expect);
+ set.for_target(os, arch)
}
#[test]
fn pick_multiplatform() {
- check_arch([C, Cdecl], X86, Some(Cdecl));
- check_arch([C, Cdecl], X86_64, Some(Cdecl));
- check_arch([C, Cdecl], Arm, Some(C));
+ assert_eq!(get_arch([C, Cdecl], OsLinux, X86), Some(Cdecl));
+ assert_eq!(get_arch([C, Cdecl], OsLinux, X86_64), Some(Cdecl));
+ assert_eq!(get_arch([C, Cdecl], OsLinux, Arm), Some(C));
}
#[test]
fn pick_uniplatform() {
- check_arch([Stdcall], X86, Some(Stdcall));
- check_arch([Stdcall], Arm, None);
+ assert_eq!(get_arch([Stdcall], OsLinux, X86), Some(Stdcall));
+ assert_eq!(get_arch([Stdcall], OsLinux, Arm), None);
+ assert_eq!(get_arch([System], OsLinux, X86), Some(C));
+ assert_eq!(get_arch([System], OsWin32, X86), Some(Stdcall));
+ assert_eq!(get_arch([System], OsWin32, X86_64), Some(C));
+ assert_eq!(get_arch([System], OsWin32, Arm), Some(C));
+ assert_eq!(get_arch([Stdcall], OsWin32, X86), Some(Stdcall));
+ assert_eq!(get_arch([Stdcall], OsWin32, X86_64), Some(Stdcall));
}