1
Fork 0

Add AbiSet and integrate it into the AST.

I believe this patch incorporates all expected syntax changes from extern
function reform (#3678). You can now write things like:

    extern "<abi>" fn foo(s: S) -> T { ... }
    extern "<abi>" mod { ... }
    extern "<abi>" fn(S) -> T

The ABI for foreign functions is taken from this syntax (rather than from an
annotation).  We support the full ABI specification I described on the mailing
list.  The correct ABI is chosen based on the target architecture.

Calls by pointer to C functions are not yet supported, and the Rust type of
crust fns is still *u8.
This commit is contained in:
Niko Matsakis 2013-03-13 22:25:28 -04:00 committed by Brian Anderson
parent f864934f54
commit 6965fe4bce
72 changed files with 879 additions and 352 deletions

View file

@ -10,6 +10,8 @@
use core::prelude::*;
use abi::AbiSet;
use abi;
use ast::{RegionTyParamBound, TraitTyParamBound, required, provided};
use ast;
use ast_util;
@ -186,7 +188,8 @@ pub fn fun_to_str(decl: &ast::fn_decl, purity: ast::purity, name: ast::ident,
generics: &ast::Generics, intr: @ident_interner) -> ~str {
do io::with_str_writer |wr| {
let s = rust_printer(wr, intr);
print_fn(s, decl, purity, name, generics, opt_self_ty, ast::inherited);
print_fn(s, decl, Some(purity), AbiSet::Rust(),
name, generics, opt_self_ty, ast::inherited);
end(s); // Close the head box
end(s); // Close the outer box
eof(s.s);
@ -405,7 +408,7 @@ pub fn print_type(s: @ps, &&ty: @ast::Ty) {
ast::ty_bare_fn(f) => {
let generics = ast::Generics {lifetimes: copy f.lifetimes,
ty_params: opt_vec::Empty};
print_ty_fn(s, Some(f.abi), None, None,
print_ty_fn(s, Some(f.abis), None, None,
f.purity, ast::Many, &f.decl, None,
Some(&generics), None);
}
@ -446,7 +449,7 @@ pub fn print_foreign_item(s: @ps, item: @ast::foreign_item) {
print_outer_attributes(s, item.attrs);
match item.node {
ast::foreign_item_fn(ref decl, purity, ref generics) => {
print_fn(s, decl, purity, item.ident, generics, None,
print_fn(s, decl, Some(purity), AbiSet::Rust(), item.ident, generics, None,
ast::inherited);
end(s); // end head-ibox
word(s.s, ~";");
@ -485,11 +488,12 @@ pub fn print_item(s: @ps, &&item: @ast::item) {
end(s); // end the outer cbox
}
ast::item_fn(ref decl, purity, ref typarams, ref body) => {
ast::item_fn(ref decl, purity, abi, ref typarams, ref body) => {
print_fn(
s,
decl,
purity,
Some(purity),
abi,
item.ident,
typarams,
None,
@ -508,8 +512,7 @@ pub fn print_item(s: @ps, &&item: @ast::item) {
}
ast::item_foreign_mod(ref nmod) => {
head(s, visibility_qualified(item.vis, ~"extern"));
print_string(s, *s.intr.get(nmod.abi));
nbsp(s);
word_nbsp(s, nmod.abis.to_str());
match nmod.sort {
ast::named => {
word_nbsp(s, ~"mod");
@ -817,7 +820,7 @@ pub fn print_method(s: @ps, meth: @ast::method) {
hardbreak_if_not_bol(s);
maybe_print_comment(s, meth.span.lo);
print_outer_attributes(s, meth.attrs);
print_fn(s, &meth.decl, meth.purity,
print_fn(s, &meth.decl, Some(meth.purity), AbiSet::Rust(),
meth.ident, &meth.generics, Some(meth.self_ty.node),
meth.vis);
word(s.s, ~" ");
@ -1650,13 +1653,14 @@ pub fn print_self_ty(s: @ps, self_ty: ast::self_ty_) -> bool {
pub fn print_fn(s: @ps,
decl: &ast::fn_decl,
purity: ast::purity,
purity: Option<ast::purity>,
abis: AbiSet,
name: ast::ident,
generics: &ast::Generics,
opt_self_ty: Option<ast::self_ty_>,
vis: ast::visibility) {
head(s, ~"");
print_fn_header_info(s, purity, ast::Many, None, vis);
print_fn_header_info(s, opt_self_ty, purity, abis, ast::Many, None, vis);
nbsp(s);
print_ident(s, name);
print_generics(s, generics);
@ -1905,7 +1909,7 @@ pub fn print_arg(s: @ps, input: ast::arg) {
}
pub fn print_ty_fn(s: @ps,
opt_abi: Option<ast::Abi>,
opt_abis: Option<AbiSet>,
opt_sigil: Option<ast::Sigil>,
opt_region: Option<@ast::Lifetime>,
purity: ast::purity,
@ -1918,7 +1922,7 @@ pub fn print_ty_fn(s: @ps,
// Duplicates the logic in `print_fn_header_info()`. This is because that
// function prints the sigil in the wrong place. That should be fixed.
print_opt_abi(s, opt_abi);
print_extern_opt_abis(s, opt_abis);
print_opt_sigil(s, opt_sigil);
print_opt_lifetime(s, opt_region);
print_purity(s, purity);
@ -2146,9 +2150,22 @@ pub fn next_comment(s: @ps) -> Option<comments::cmnt> {
}
}
pub fn print_opt_abi(s: @ps, opt_abi: Option<ast::Abi>) {
match opt_abi {
Some(ast::RustAbi) => { word_nbsp(s, ~"extern"); }
pub fn print_opt_purity(s: @ps, opt_purity: Option<ast::purity>) {
match opt_purity {
Some(ast::impure_fn) => { }
Some(purity) => {
word_nbsp(s, purity_to_str(purity));
}
None => {}
}
}
pub fn print_extern_opt_abis(s: @ps, opt_abis: Option<AbiSet>) {
match opt_abis {
Some(abis) => {
word_nbsp(s, ~"extern");
word_nbsp(s, abis.to_str());
}
None => {}
};
}
@ -2163,12 +2180,25 @@ pub fn print_opt_sigil(s: @ps, opt_sigil: Option<ast::Sigil>) {
}
pub fn print_fn_header_info(s: @ps,
purity: ast::purity,
opt_sty: Option<ast::self_ty_>,
opt_purity: Option<ast::purity>,
abis: AbiSet,
onceness: ast::Onceness,
opt_sigil: Option<ast::Sigil>,
vis: ast::visibility) {
word(s.s, visibility_qualified(vis, ~""));
print_purity(s, purity);
if abis != AbiSet::Rust() {
word_nbsp(s, ~"extern");
word_nbsp(s, abis.to_str());
if opt_purity != Some(ast::extern_fn) {
print_opt_purity(s, opt_purity);
}
} else {
print_opt_purity(s, opt_purity);
}
print_onceness(s, onceness);
word(s.s, ~"fn");
print_opt_sigil(s, opt_sigil);