Skip to content

Commit 3851f90

Browse files
committed
auto merge of #10367 : alexcrichton/rust/system-abi, r=nikomatsakis
This adds an other ABI option which allows a custom selection over the target architecture and OS. The only current candidate for this change is that kernel32 on win32 uses stdcall, but on win64 it uses the cdecl calling convention. Otherwise everywhere else this is defined as using the Cdecl calling convention. cc #10049 Closes #8774
2 parents 8379890 + 2fcc70e commit 3851f90

File tree

14 files changed

+151
-109
lines changed

14 files changed

+151
-109
lines changed

doc/tutorial-ffi.md

+20-3
Original file line numberDiff line numberDiff line change
@@ -418,15 +418,32 @@ calling foreign functions. Some foreign functions, most notably the Windows API,
418418
conventions. Rust provides a way to tell the compiler which convention to use:
419419

420420
~~~~
421-
#[cfg(target_os = "win32")]
421+
#[cfg(target_os = "win32", target_arch = "x86")]
422422
#[link_name = "kernel32"]
423423
extern "stdcall" {
424424
fn SetEnvironmentVariableA(n: *u8, v: *u8) -> int;
425425
}
426426
~~~~
427427

428-
This applies to the entire `extern` block, and must be either `"cdecl"` or
429-
`"stdcall"`. The compiler may eventually support other calling conventions.
428+
This applies to the entire `extern` block. The list of supported ABI constraints
429+
are:
430+
431+
* `stdcall`
432+
* `aapcs`
433+
* `cdecl`
434+
* `fastcall`
435+
* `Rust`
436+
* `rust-intrinsic`
437+
* `system`
438+
* `C`
439+
440+
Most of the abis in this list are self-explanatory, but the `system` abi may
441+
seem a little odd. This constraint selects whatever the appropriate ABI is for
442+
interoperating with the target's libraries. For example, on win32 with a x86
443+
architecture, this means that the abi used would be `stdcall`. On x86_64,
444+
however, windows uses the `C` calling convention, so `C` would be used. This
445+
means that in our previous example, we could have used `extern "system" { ... }`
446+
to define a block for all windows systems, not just x86 ones.
430447

431448
# Interoperability with foreign code
432449

src/librustc/back/arm.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -10,49 +10,49 @@
1010

1111
use back::target_strs;
1212
use driver::session::sess_os_to_meta_os;
13-
use driver::session;
1413
use metadata::loader::meta_section_name;
14+
use syntax::abi;
1515

16-
pub fn get_target_strs(target_triple: ~str, target_os: session::Os) -> target_strs::t {
16+
pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs::t {
1717
return target_strs::t {
1818
module_asm: ~"",
1919

2020
meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(),
2121

2222
data_layout: match target_os {
23-
session::OsMacos => {
23+
abi::OsMacos => {
2424
~"e-p:32:32:32" +
2525
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
2626
"-f32:32:32-f64:64:64" +
2727
"-v64:64:64-v128:64:128" +
2828
"-a0:0:64-n32"
2929
}
3030

31-
session::OsWin32 => {
31+
abi::OsWin32 => {
3232
~"e-p:32:32:32" +
3333
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
3434
"-f32:32:32-f64:64:64" +
3535
"-v64:64:64-v128:64:128" +
3636
"-a0:0:64-n32"
3737
}
3838

39-
session::OsLinux => {
39+
abi::OsLinux => {
4040
~"e-p:32:32:32" +
4141
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
4242
"-f32:32:32-f64:64:64" +
4343
"-v64:64:64-v128:64:128" +
4444
"-a0:0:64-n32"
4545
}
4646

47-
session::OsAndroid => {
47+
abi::OsAndroid => {
4848
~"e-p:32:32:32" +
4949
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
5050
"-f32:32:32-f64:64:64" +
5151
"-v64:64:64-v128:64:128" +
5252
"-a0:0:64-n32"
5353
}
5454

55-
session::OsFreebsd => {
55+
abi::OsFreebsd => {
5656
~"e-p:32:32:32" +
5757
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
5858
"-f32:32:32-f64:64:64" +

src/librustc/back/link.rs

+16-15
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use std::run;
3232
use std::str;
3333
use std::vec;
3434
use std::rt::io::fs;
35+
use syntax::abi;
3536
use syntax::ast;
3637
use syntax::ast_map::{path, path_mod, path_name, path_pretty_name};
3738
use syntax::attr;
@@ -877,13 +878,13 @@ pub fn mangle_internal_name_by_path(ccx: &mut CrateContext, path: path) -> ~str
877878
}
878879

879880

880-
pub fn output_dll_filename(os: session::Os, lm: LinkMeta) -> ~str {
881+
pub fn output_dll_filename(os: abi::Os, lm: LinkMeta) -> ~str {
881882
let (dll_prefix, dll_suffix) = match os {
882-
session::OsWin32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX),
883-
session::OsMacos => (macos::DLL_PREFIX, macos::DLL_SUFFIX),
884-
session::OsLinux => (linux::DLL_PREFIX, linux::DLL_SUFFIX),
885-
session::OsAndroid => (android::DLL_PREFIX, android::DLL_SUFFIX),
886-
session::OsFreebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
883+
abi::OsWin32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX),
884+
abi::OsMacos => (macos::DLL_PREFIX, macos::DLL_SUFFIX),
885+
abi::OsLinux => (linux::DLL_PREFIX, linux::DLL_SUFFIX),
886+
abi::OsAndroid => (android::DLL_PREFIX, android::DLL_SUFFIX),
887+
abi::OsFreebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
887888
};
888889
format!("{}{}-{}-{}{}", dll_prefix, lm.name, lm.extras_hash, lm.vers, dll_suffix)
889890
}
@@ -898,7 +899,7 @@ pub fn get_cc_prog(sess: Session) -> ~str {
898899
match sess.opts.linker {
899900
Some(ref linker) => linker.to_str(),
900901
None => match sess.targ_cfg.os {
901-
session::OsAndroid =>
902+
abi::OsAndroid =>
902903
match &sess.opts.android_cross_path {
903904
&Some(ref path) => {
904905
format!("{}/bin/arm-linux-androideabi-gcc", *path)
@@ -908,7 +909,7 @@ pub fn get_cc_prog(sess: Session) -> ~str {
908909
(--android-cross-path)")
909910
}
910911
},
911-
session::OsWin32 => ~"g++",
912+
abi::OsWin32 => ~"g++",
912913
_ => ~"cc"
913914
}
914915
}
@@ -956,7 +957,7 @@ pub fn link_binary(sess: Session,
956957
}
957958

958959
// Clean up on Darwin
959-
if sess.targ_cfg.os == session::OsMacos {
960+
if sess.targ_cfg.os == abi::OsMacos {
960961
// FIXME (#9639): This needs to handle non-utf8 paths
961962
run::process_status("dsymutil", [output.as_str().unwrap().to_owned()]);
962963
}
@@ -985,7 +986,7 @@ pub fn link_args(sess: Session,
985986
// Converts a library file-stem into a cc -l argument
986987
fn unlib(config: @session::config, stem: ~str) -> ~str {
987988
if stem.starts_with("lib") &&
988-
config.os != session::OsWin32 {
989+
config.os != abi::OsWin32 {
989990
stem.slice(3, stem.len()).to_owned()
990991
} else {
991992
stem
@@ -1029,7 +1030,7 @@ pub fn link_args(sess: Session,
10291030
obj_filename.as_str().unwrap().to_owned()]);
10301031

10311032
let lib_cmd = match sess.targ_cfg.os {
1032-
session::OsMacos => ~"-dynamiclib",
1033+
abi::OsMacos => ~"-dynamiclib",
10331034
_ => ~"-shared"
10341035
};
10351036

@@ -1080,7 +1081,7 @@ pub fn link_args(sess: Session,
10801081

10811082
// On mac we need to tell the linker to let this library
10821083
// be rpathed
1083-
if sess.targ_cfg.os == session::OsMacos {
1084+
if sess.targ_cfg.os == abi::OsMacos {
10841085
// FIXME (#9639): This needs to handle non-utf8 paths
10851086
args.push("-Wl,-install_name,@rpath/"
10861087
+ output.filename_str().unwrap());
@@ -1089,20 +1090,20 @@ pub fn link_args(sess: Session,
10891090

10901091
// On linux librt and libdl are an indirect dependencies via rustrt,
10911092
// and binutils 2.22+ won't add them automatically
1092-
if sess.targ_cfg.os == session::OsLinux {
1093+
if sess.targ_cfg.os == abi::OsLinux {
10931094
args.push_all([~"-lrt", ~"-ldl"]);
10941095

10951096
// LLVM implements the `frem` instruction as a call to `fmod`,
10961097
// which lives in libm. Similar to above, on some linuxes we
10971098
// have to be explicit about linking to it. See #2510
10981099
args.push(~"-lm");
10991100
}
1100-
else if sess.targ_cfg.os == session::OsAndroid {
1101+
else if sess.targ_cfg.os == abi::OsAndroid {
11011102
args.push_all([~"-ldl", ~"-llog", ~"-lsupc++", ~"-lgnustl_shared"]);
11021103
args.push(~"-lm");
11031104
}
11041105

1105-
if sess.targ_cfg.os == session::OsFreebsd {
1106+
if sess.targ_cfg.os == abi::OsFreebsd {
11061107
args.push_all([~"-pthread", ~"-lrt",
11071108
~"-L/usr/local/lib", ~"-lexecinfo",
11081109
~"-L/usr/local/lib/gcc46",

src/librustc/back/mips.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -9,50 +9,50 @@
99
// except according to those terms.
1010

1111
use back::target_strs;
12-
use driver::session;
1312
use driver::session::sess_os_to_meta_os;
1413
use metadata::loader::meta_section_name;
14+
use syntax::abi;
1515

16-
pub fn get_target_strs(target_triple: ~str, target_os: session::Os) -> target_strs::t {
16+
pub fn get_target_strs(target_triple: ~str, target_os: abi::Os) -> target_strs::t {
1717
return target_strs::t {
1818
module_asm: ~"",
1919

2020
meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(),
2121

2222
data_layout: match target_os {
23-
session::OsMacos => {
23+
abi::OsMacos => {
2424
~"e-p:32:32:32" +
2525
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
2626
"-f32:32:32-f64:64:64" +
2727
"-v64:64:64-v128:64:128" +
2828
"-a0:0:64-n32"
2929
}
3030

31-
session::OsWin32 => {
31+
abi::OsWin32 => {
3232
~"e-p:32:32:32" +
3333
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
3434
"-f32:32:32-f64:64:64" +
3535
"-v64:64:64-v128:64:128" +
3636
"-a0:0:64-n32"
3737
}
3838

39-
session::OsLinux => {
39+
abi::OsLinux => {
4040
~"e-p:32:32:32" +
4141
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
4242
"-f32:32:32-f64:64:64" +
4343
"-v64:64:64-v128:64:128" +
4444
"-a0:0:64-n32"
4545
}
4646

47-
session::OsAndroid => {
47+
abi::OsAndroid => {
4848
~"e-p:32:32:32" +
4949
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
5050
"-f32:32:32-f64:64:64" +
5151
"-v64:64:64-v128:64:128" +
5252
"-a0:0:64-n32"
5353
}
5454

55-
session::OsFreebsd => {
55+
abi::OsFreebsd => {
5656
~"e-p:32:32:32" +
5757
"-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64" +
5858
"-f32:32:32-f64:64:64" +

src/librustc/back/rpath.rs

+14-16
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,18 @@ use metadata::filesearch;
1515

1616
use std::hashmap::HashSet;
1717
use std::{os, vec};
18+
use syntax::abi;
1819

19-
fn not_win32(os: session::Os) -> bool {
20-
os != session::OsWin32
20+
fn not_win32(os: abi::Os) -> bool {
21+
os != abi::OsWin32
2122
}
2223

2324
pub fn get_rpath_flags(sess: session::Session, out_filename: &Path)
2425
-> ~[~str] {
2526
let os = sess.targ_cfg.os;
2627

2728
// No rpath on windows
28-
if os == session::OsWin32 {
29+
if os == abi::OsWin32 {
2930
return ~[];
3031
}
3132

@@ -55,7 +56,7 @@ pub fn rpaths_to_flags(rpaths: &[~str]) -> ~[~str] {
5556
rpaths.iter().map(|rpath| format!("-Wl,-rpath,{}",*rpath)).collect()
5657
}
5758

58-
fn get_rpaths(os: session::Os,
59+
fn get_rpaths(os: abi::Os,
5960
sysroot: &Path,
6061
output: &Path,
6162
libs: &[Path],
@@ -100,13 +101,13 @@ fn get_rpaths(os: session::Os,
100101
return rpaths;
101102
}
102103

103-
fn get_rpaths_relative_to_output(os: session::Os,
104+
fn get_rpaths_relative_to_output(os: abi::Os,
104105
output: &Path,
105106
libs: &[Path]) -> ~[~str] {
106107
libs.iter().map(|a| get_rpath_relative_to_output(os, output, a)).collect()
107108
}
108109

109-
pub fn get_rpath_relative_to_output(os: session::Os,
110+
pub fn get_rpath_relative_to_output(os: abi::Os,
110111
output: &Path,
111112
lib: &Path)
112113
-> ~str {
@@ -116,10 +117,10 @@ pub fn get_rpath_relative_to_output(os: session::Os,
116117

117118
// Mac doesn't appear to support $ORIGIN
118119
let prefix = match os {
119-
session::OsAndroid | session::OsLinux | session::OsFreebsd
120+
abi::OsAndroid | abi::OsLinux | abi::OsFreebsd
120121
=> "$ORIGIN",
121-
session::OsMacos => "@loader_path",
122-
session::OsWin32 => unreachable!()
122+
abi::OsMacos => "@loader_path",
123+
abi::OsWin32 => unreachable!()
123124
};
124125

125126
let mut lib = os::make_absolute(lib);
@@ -169,13 +170,10 @@ pub fn minimize_rpaths(rpaths: &[~str]) -> ~[~str] {
169170
mod test {
170171
use std::os;
171172

172-
// FIXME(#2119): the outer attribute should be #[cfg(unix, test)], then
173-
// these redundant #[cfg(test)] blocks can be removed
174-
#[cfg(test)]
175-
#[cfg(test)]
176173
use back::rpath::{get_absolute_rpath, get_install_prefix_rpath};
177174
use back::rpath::{minimize_rpaths, rpaths_to_flags, get_rpath_relative_to_output};
178175
use driver::session;
176+
use syntax::abi;
179177

180178
#[test]
181179
fn test_rpaths_to_flags() {
@@ -219,7 +217,7 @@ mod test {
219217
#[cfg(target_os = "linux")]
220218
#[cfg(target_os = "android")]
221219
fn test_rpath_relative() {
222-
let o = session::OsLinux;
220+
let o = abi::OsLinux;
223221
let res = get_rpath_relative_to_output(o,
224222
&Path::new("bin/rustc"), &Path::new("lib/libstd.so"));
225223
assert_eq!(res.as_slice(), "$ORIGIN/../lib");
@@ -228,7 +226,7 @@ mod test {
228226
#[test]
229227
#[cfg(target_os = "freebsd")]
230228
fn test_rpath_relative() {
231-
let o = session::OsFreebsd;
229+
let o = abi::OsFreebsd;
232230
let res = get_rpath_relative_to_output(o,
233231
&Path::new("bin/rustc"), &Path::new("lib/libstd.so"));
234232
assert_eq!(res.as_slice(), "$ORIGIN/../lib");
@@ -237,7 +235,7 @@ mod test {
237235
#[test]
238236
#[cfg(target_os = "macos")]
239237
fn test_rpath_relative() {
240-
let o = session::OsMacos;
238+
let o = abi::OsMacos;
241239
let res = get_rpath_relative_to_output(o,
242240
&Path::new("bin/rustc"),
243241
&Path::new("lib/libstd.so"));

0 commit comments

Comments
 (0)