Skip to content

Commit 2fcc70e

Browse files
committed
Add a "system" ABI
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
1 parent 9d8dc00 commit 2fcc70e

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;
@@ -864,13 +865,13 @@ pub fn mangle_internal_name_by_path(ccx: &mut CrateContext, path: path) -> ~str
864865
}
865866

866867

867-
pub fn output_dll_filename(os: session::Os, lm: LinkMeta) -> ~str {
868+
pub fn output_dll_filename(os: abi::Os, lm: LinkMeta) -> ~str {
868869
let (dll_prefix, dll_suffix) = match os {
869-
session::OsWin32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX),
870-
session::OsMacos => (macos::DLL_PREFIX, macos::DLL_SUFFIX),
871-
session::OsLinux => (linux::DLL_PREFIX, linux::DLL_SUFFIX),
872-
session::OsAndroid => (android::DLL_PREFIX, android::DLL_SUFFIX),
873-
session::OsFreebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
870+
abi::OsWin32 => (win32::DLL_PREFIX, win32::DLL_SUFFIX),
871+
abi::OsMacos => (macos::DLL_PREFIX, macos::DLL_SUFFIX),
872+
abi::OsLinux => (linux::DLL_PREFIX, linux::DLL_SUFFIX),
873+
abi::OsAndroid => (android::DLL_PREFIX, android::DLL_SUFFIX),
874+
abi::OsFreebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
874875
};
875876
format!("{}{}-{}-{}{}", dll_prefix, lm.name, lm.extras_hash, lm.vers, dll_suffix)
876877
}
@@ -885,7 +886,7 @@ pub fn get_cc_prog(sess: Session) -> ~str {
885886
match sess.opts.linker {
886887
Some(ref linker) => linker.to_str(),
887888
None => match sess.targ_cfg.os {
888-
session::OsAndroid =>
889+
abi::OsAndroid =>
889890
match &sess.opts.android_cross_path {
890891
&Some(ref path) => {
891892
format!("{}/bin/arm-linux-androideabi-gcc", *path)
@@ -895,7 +896,7 @@ pub fn get_cc_prog(sess: Session) -> ~str {
895896
(--android-cross-path)")
896897
}
897898
},
898-
session::OsWin32 => ~"g++",
899+
abi::OsWin32 => ~"g++",
899900
_ => ~"cc"
900901
}
901902
}
@@ -943,7 +944,7 @@ pub fn link_binary(sess: Session,
943944
}
944945

945946
// Clean up on Darwin
946-
if sess.targ_cfg.os == session::OsMacos {
947+
if sess.targ_cfg.os == abi::OsMacos {
947948
// FIXME (#9639): This needs to handle non-utf8 paths
948949
run::process_status("dsymutil", [output.as_str().unwrap().to_owned()]);
949950
}
@@ -972,7 +973,7 @@ pub fn link_args(sess: Session,
972973
// Converts a library file-stem into a cc -l argument
973974
fn unlib(config: @session::config, stem: ~str) -> ~str {
974975
if stem.starts_with("lib") &&
975-
config.os != session::OsWin32 {
976+
config.os != abi::OsWin32 {
976977
stem.slice(3, stem.len()).to_owned()
977978
} else {
978979
stem
@@ -1016,7 +1017,7 @@ pub fn link_args(sess: Session,
10161017
obj_filename.as_str().unwrap().to_owned()]);
10171018

10181019
let lib_cmd = match sess.targ_cfg.os {
1019-
session::OsMacos => ~"-dynamiclib",
1020+
abi::OsMacos => ~"-dynamiclib",
10201021
_ => ~"-shared"
10211022
};
10221023

@@ -1067,7 +1068,7 @@ pub fn link_args(sess: Session,
10671068

10681069
// On mac we need to tell the linker to let this library
10691070
// be rpathed
1070-
if sess.targ_cfg.os == session::OsMacos {
1071+
if sess.targ_cfg.os == abi::OsMacos {
10711072
// FIXME (#9639): This needs to handle non-utf8 paths
10721073
args.push("-Wl,-install_name,@rpath/"
10731074
+ output.filename_str().unwrap());
@@ -1076,20 +1077,20 @@ pub fn link_args(sess: Session,
10761077

10771078
// On linux librt and libdl are an indirect dependencies via rustrt,
10781079
// and binutils 2.22+ won't add them automatically
1079-
if sess.targ_cfg.os == session::OsLinux {
1080+
if sess.targ_cfg.os == abi::OsLinux {
10801081
args.push_all([~"-lrt", ~"-ldl"]);
10811082

10821083
// LLVM implements the `frem` instruction as a call to `fmod`,
10831084
// which lives in libm. Similar to above, on some linuxes we
10841085
// have to be explicit about linking to it. See #2510
10851086
args.push(~"-lm");
10861087
}
1087-
else if sess.targ_cfg.os == session::OsAndroid {
1088+
else if sess.targ_cfg.os == abi::OsAndroid {
10881089
args.push_all([~"-ldl", ~"-llog", ~"-lsupc++", ~"-lgnustl_shared"]);
10891090
args.push(~"-lm");
10901091
}
10911092

1092-
if sess.targ_cfg.os == session::OsFreebsd {
1093+
if sess.targ_cfg.os == abi::OsFreebsd {
10931094
args.push_all([~"-pthread", ~"-lrt",
10941095
~"-L/usr/local/lib", ~"-lexecinfo",
10951096
~"-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)