Skip to content

Commit

Permalink
Add AbiSet and integrate it into the AST.
Browse files Browse the repository at this point in the history
I believe this patch incorporates all expected syntax changes from extern
function reform (rust-lang#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.
  • Loading branch information
nikomatsakis committed Mar 25, 2013
1 parent 6d4499c commit 063acf7
Show file tree
Hide file tree
Showing 73 changed files with 854 additions and 339 deletions.
2 changes: 1 addition & 1 deletion src/libcore/cast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
pub mod rusti {
#[abi = "rust-intrinsic"]
#[link_name = "rusti"]
pub extern {
pub extern "rust-intrinsic" {
fn forget<T>(+x: T);
fn reinterpret_cast<T, U>(&&e: T) -> U;
}
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/libc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1617,7 +1617,7 @@ pub mod funcs {
use libc::types::os::arch::extra::{HANDLE};

#[abi = "stdcall"]
pub extern {
pub extern "stdcall" {
unsafe fn GetEnvironmentVariableW(n: LPCWSTR,
v: LPWSTR,
nsize: DWORD)
Expand Down
4 changes: 2 additions & 2 deletions src/libcore/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -944,7 +944,7 @@ pub fn errno() -> uint {

#[link_name = "kernel32"]
#[abi = "stdcall"]
extern {
extern "stdcall" {
unsafe fn GetLastError() -> DWORD;
}

Expand Down Expand Up @@ -1006,7 +1006,7 @@ pub fn last_os_error() -> ~str {

#[link_name = "kernel32"]
#[abi = "stdcall"]
extern {
extern "stdcall" {
unsafe fn FormatMessageA(flags: DWORD, lpSrc: LPVOID,
msgId: DWORD, langId: DWORD,
buf: LPSTR, nsize: DWORD,
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub mod libc_ {

pub mod rusti {
#[abi = "rust-intrinsic"]
pub extern {
pub extern "rust-intrinsic" {
fn addr_of<T>(&&val: T) -> *T;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/rt/thread_local_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ pub unsafe fn get(key: Key) -> *mut c_void {

#[cfg(windows)]
#[abi = "stdcall"]
extern {
extern "stdcall" {
fn TlsAlloc() -> DWORD;
fn TlsSetValue(dwTlsIndex: DWORD, lpTlsvalue: LPVOID) -> BOOL;
fn TlsGetValue(dwTlsIndex: DWORD) -> LPVOID;
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/stackwalk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pub mod rustrt {

pub mod rusti {
#[abi = "rust-intrinsic"]
pub extern {
pub extern "rust-intrinsic" {
pub fn frame_address(f: &once fn(++x: *u8));
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/sys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub struct Closure {

pub mod rusti {
#[abi = "rust-intrinsic"]
pub extern {
pub extern "rust-intrinsic" {
fn get_tydesc<T>() -> *();
fn size_of<T>() -> uint;
fn pref_align_of<T>() -> uint;
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/unstable/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The intrinsics are defined in librustc/middle/trans/foreign.rs.
*/

#[abi = "rust-intrinsic"]
pub extern {
pub extern "rust-intrinsic" {
pub fn atomic_cxchg(dst: &mut int, old: int, src: int) -> int;
pub fn atomic_cxchg_acq(dst: &mut int, old: int, src: int) -> int;
pub fn atomic_cxchg_rel(dst: &mut int, old: int, src: int) -> int;
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ pub mod jit {
pub mod rusti {
#[nolink]
#[abi = "rust-intrinsic"]
pub extern {
pub extern "rust-intrinsic" {
pub fn morestack_addr() -> *();
}
}
Expand Down
37 changes: 19 additions & 18 deletions src/librustc/driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use std::getopts::groups::{optopt, optmulti, optflag, optflagopt, getopts};
use std::getopts::{opt_present};
use std::getopts;
use syntax::ast;
use syntax::abi;
use syntax::attr;
use syntax::codemap;
use syntax::diagnostic;
Expand Down Expand Up @@ -86,10 +87,10 @@ pub fn default_configuration(sess: Session, +argv0: ~str, input: input) ->
// ARM is bi-endian, however using NDK seems to default
// to little-endian unless a flag is provided.
let (end,arch,wordsz) = match sess.targ_cfg.arch {
session::arch_x86 => (~"little",~"x86",~"32"),
session::arch_x86_64 => (~"little",~"x86_64",~"64"),
session::arch_arm => (~"little",~"arm",~"32"),
session::arch_mips => (~"little",~"arm",~"32")
abi::X86 => (~"little",~"x86",~"32"),
abi::X86_64 => (~"little",~"x86_64",~"64"),
abi::Arm => (~"little",~"arm",~"32"),
abi::Mips => (~"little",~"arm",~"32")
};

return ~[ // Target bindings.
Expand Down Expand Up @@ -309,7 +310,7 @@ pub fn compile_rest(sess: Session, cfg: ast::crate_cfg,
};

// NOTE: Android hack
if sess.targ_cfg.arch == session::arch_arm &&
if sess.targ_cfg.arch == abi::Arm &&
(sess.opts.output_type == link::output_type_object ||
sess.opts.output_type == link::output_type_exe) {
let output_type = link::output_type_assembly;
Expand Down Expand Up @@ -454,20 +455,20 @@ pub fn get_os(triple: &str) -> Option<session::os> {
} else { None }
}

pub fn get_arch(triple: &str) -> Option<session::arch> {
pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
if str::contains(triple, ~"i386") ||
str::contains(triple, ~"i486") ||
str::contains(triple, ~"i586") ||
str::contains(triple, ~"i686") ||
str::contains(triple, ~"i786") {
Some(session::arch_x86)
Some(abi::X86)
} else if str::contains(triple, ~"x86_64") {
Some(session::arch_x86_64)
Some(abi::X86_64)
} else if str::contains(triple, ~"arm") ||
str::contains(triple, ~"xscale") {
Some(session::arch_arm)
Some(abi::Arm)
} else if str::contains(triple, ~"mips") {
Some(session::arch_mips)
Some(abi::Mips)
} else { None }
}

Expand All @@ -484,16 +485,16 @@ pub fn build_target_config(sopts: @session::options,
~"unknown architecture: " + sopts.target_triple)
};
let (int_type, uint_type, float_type) = match arch {
session::arch_x86 => (ast::ty_i32, ast::ty_u32, ast::ty_f64),
session::arch_x86_64 => (ast::ty_i64, ast::ty_u64, ast::ty_f64),
session::arch_arm => (ast::ty_i32, ast::ty_u32, ast::ty_f64),
session::arch_mips => (ast::ty_i32, ast::ty_u32, ast::ty_f64)
abi::X86 => (ast::ty_i32, ast::ty_u32, ast::ty_f64),
abi::X86_64 => (ast::ty_i64, ast::ty_u64, ast::ty_f64),
abi::Arm => (ast::ty_i32, ast::ty_u32, ast::ty_f64),
abi::Mips => (ast::ty_i32, ast::ty_u32, ast::ty_f64)
};
let target_strs = match arch {
session::arch_x86 => x86::get_target_strs(os),
session::arch_x86_64 => x86_64::get_target_strs(os),
session::arch_arm => arm::get_target_strs(os),
session::arch_mips => mips::get_target_strs(os)
abi::X86 => x86::get_target_strs(os),
abi::X86_64 => x86_64::get_target_strs(os),
abi::Arm => arm::get_target_strs(os),
abi::Mips => mips::get_target_strs(os)
};
let target_cfg = @session::config {
os: os,
Expand Down
6 changes: 2 additions & 4 deletions src/librustc/driver/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,17 @@ use syntax::codemap::span;
use syntax::diagnostic;
use syntax::parse::ParseSess;
use syntax::{ast, codemap};
use syntax::abi;
use syntax;

#[deriving(Eq)]
pub enum os { os_win32, os_macos, os_linux, os_android, os_freebsd, }

#[deriving(Eq)]
pub enum arch { arch_x86, arch_x86_64, arch_arm, arch_mips, }

pub enum crate_type { bin_crate, lib_crate, unknown_crate, }

pub struct config {
os: os,
arch: arch,
arch: abi::Architecture,
target_strs: target_strs::t,
int_type: int_ty,
uint_type: uint_ty,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/front/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ fn fold_foreign_mod(
nm.view_items.filter_mapped(|a| filter_view_item(cx, *a));
ast::foreign_mod {
sort: nm.sort,
abi: nm.abi,
abis: nm.abis,
view_items: vec::map(filtered_view_items, |x| fld.fold_view_item(*x)),
items: filtered_items
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/front/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ pub mod intrinsic {
use super::{TyDesc, TyVisitor};

#[abi = "rust-intrinsic"]
pub extern {
pub extern "rust-intrinsic" {
pub fn get_tydesc<T>() -> *();
pub fn visit_tydesc(++td: *TyDesc, &&tv: @TyVisitor);
}
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/front/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ fn fold_item(cx: @mut TestCtxt, &&i: @ast::item, fld: @fold::ast_fold)

if is_test_fn(i) || is_bench_fn(i) {
match i.node {
ast::item_fn(_, purity, _, _) if purity == ast::unsafe_fn => {
ast::item_fn(_, purity, _, _, _) if purity == ast::unsafe_fn => {
let sess = cx.sess;
sess.span_fatal(
i.span,
Expand Down Expand Up @@ -178,7 +178,7 @@ fn is_test_fn(i: @ast::item) -> bool {

fn has_test_signature(i: @ast::item) -> bool {
match &i.node {
&ast::item_fn(ref decl, _, ref generics, _) => {
&ast::item_fn(ref decl, _, _, ref generics, _) => {
let no_output = match decl.output.node {
ast::ty_nil => true,
_ => false
Expand All @@ -200,7 +200,7 @@ fn is_bench_fn(i: @ast::item) -> bool {

fn has_test_signature(i: @ast::item) -> bool {
match i.node {
ast::item_fn(ref decl, _, ref generics, _) => {
ast::item_fn(ref decl, _, _, ref generics, _) => {
let input_cnt = vec::len(decl.inputs);
let no_output = match decl.output.node {
ast::ty_nil => true,
Expand Down
8 changes: 2 additions & 6 deletions src/librustc/metadata/creader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,8 @@ fn visit_view_item(e: @mut Env, i: @ast::view_item) {
fn visit_item(e: @mut Env, i: @ast::item) {
match i.node {
ast::item_foreign_mod(ref fm) => {
match attr::foreign_abi(i.attrs) {
either::Right(abi) => {
if abi != ast::foreign_abi_cdecl &&
abi != ast::foreign_abi_stdcall { return; }
}
either::Left(ref msg) => e.diag.span_fatal(i.span, (*msg))
if fm.abis.is_rust() || fm.abis.is_intrinsic() {
return;
}

let cstore = e.cstore;
Expand Down
7 changes: 4 additions & 3 deletions src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use std::oldmap::HashMap;
use std::serialize::Encodable;
use std::{ebml, oldmap};
use std;
use syntax::abi::AbiSet;
use syntax::ast::*;
use syntax::ast;
use syntax::ast_map;
Expand Down Expand Up @@ -657,7 +658,7 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
(ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
ebml_w.end_tag();
}
item_fn(_, purity, ref generics, _) => {
item_fn(_, purity, _, ref generics, _) => {
add_to_index();
ebml_w.start_tag(tag_items_data_item);
encode_def_id(ebml_w, local_def(item.id));
Expand Down Expand Up @@ -983,7 +984,7 @@ fn encode_info_for_foreign_item(ecx: @EncodeContext,
nitem: @foreign_item,
index: @mut ~[entry<int>],
+path: ast_map::path,
abi: foreign_abi) {
abi: AbiSet) {
if !reachable(ecx, nitem.id) { return; }
index.push(entry { val: nitem.id, pos: ebml_w.writer.tell() });

Expand All @@ -994,7 +995,7 @@ fn encode_info_for_foreign_item(ecx: @EncodeContext,
encode_family(ebml_w, purity_fn_family(purity));
encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
if abi == foreign_abi_rust_intrinsic {
if abi.is_intrinsic() {
(ecx.encode_inlined_item)(ecx, ebml_w, path, ii_foreign(nitem));
} else {
encode_symbol(ecx, ebml_w, nitem.id);
Expand Down
39 changes: 29 additions & 10 deletions src/librustc/metadata/tydecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ use middle::ty;
use core::str;
use core::uint;
use core::vec;
use syntax::abi::AbiSet;
use syntax::abi;
use syntax::ast;
use syntax::ast::*;
use syntax::codemap::{respan, dummy_sp};
Expand Down Expand Up @@ -74,17 +76,28 @@ fn next_byte(st: @mut PState) -> u8 {
return b;
}

fn scan<R>(st: &mut PState, is_last: &fn(char) -> bool,
op: &fn(&[u8]) -> R) -> R
{
let start_pos = st.pos;
debug!("scan: '%c' (start)", st.data[st.pos] as char);
while !is_last(st.data[st.pos] as char) {
st.pos += 1;
debug!("scan: '%c'", st.data[st.pos] as char);
}
let end_pos = st.pos;
st.pos += 1;
return op(st.data.slice(start_pos, end_pos));
}

pub fn parse_ident(st: @mut PState, last: char) -> ast::ident {
fn is_last(b: char, c: char) -> bool { return c == b; }
return parse_ident_(st, |a| is_last(last, a) );
}

fn parse_ident_(st: @mut PState, is_last: @fn(char) -> bool) ->
ast::ident {
let mut rslt = ~"";
while !is_last(peek(st)) {
rslt += str::from_byte(next_byte(st));
}
let rslt = scan(st, is_last, str::from_bytes);
return st.tcx.sess.ident_of(rslt);
}

Expand Down Expand Up @@ -415,11 +428,17 @@ fn parse_purity(c: char) -> purity {
}
}

fn parse_abi(c: char) -> Abi {
match c {
'r' => ast::RustAbi,
_ => fail!(fmt!("parse_abi: bad ABI '%c'", c))
fn parse_abi_set(st: @mut PState) -> AbiSet {
fail_unless!(next(st) == '[');
let mut abis = AbiSet::empty();
while peek(st) != ']' {
// FIXME(#5422) str API should not force this copy
let abi_str = scan(st, |c| c == ',', str::from_bytes);
let abi = abi::lookup(abi_str).expect(abi_str);
abis.add(abi);
}
fail_unless!(next(st) == ']');
return abis;
}

fn parse_onceness(c: char) -> ast::Onceness {
Expand Down Expand Up @@ -460,11 +479,11 @@ fn parse_closure_ty(st: @mut PState, conv: conv_did) -> ty::ClosureTy {

fn parse_bare_fn_ty(st: @mut PState, conv: conv_did) -> ty::BareFnTy {
let purity = parse_purity(next(st));
let abi = parse_abi(next(st));
let abi = parse_abi_set(st);
let sig = parse_sig(st, conv);
ty::BareFnTy {
purity: purity,
abi: abi,
abis: abi,
sig: sig
}
}
Expand Down
Loading

0 comments on commit 063acf7

Please sign in to comment.