From 063acf7e1632bf874bad09ead2ae9c5042f43c75 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 13 Mar 2013 22:25:28 -0400 Subject: [PATCH 1/3] 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 "" fn foo(s: S) -> T { ... } extern "" mod { ... } extern "" 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. --- src/libcore/cast.rs | 2 +- src/libcore/libc.rs | 2 +- src/libcore/os.rs | 4 +- src/libcore/ptr.rs | 2 +- src/libcore/rt/thread_local_storage.rs | 2 +- src/libcore/stackwalk.rs | 2 +- src/libcore/sys.rs | 2 +- src/libcore/unstable/intrinsics.rs | 2 +- src/librustc/back/link.rs | 2 +- src/librustc/driver/driver.rs | 37 +- src/librustc/driver/session.rs | 6 +- src/librustc/front/config.rs | 2 +- src/librustc/front/intrinsic.rs | 2 +- src/librustc/front/test.rs | 6 +- src/librustc/metadata/creader.rs | 8 +- src/librustc/metadata/encoder.rs | 7 +- src/librustc/metadata/tydecode.rs | 39 +- src/librustc/metadata/tyencode.rs | 12 +- src/librustc/middle/lint.rs | 4 +- src/librustc/middle/resolve.rs | 4 +- src/librustc/middle/trans/base.rs | 27 +- src/librustc/middle/trans/callee.rs | 7 +- src/librustc/middle/trans/common.rs | 17 +- src/librustc/middle/trans/debuginfo.rs | 2 +- src/librustc/middle/trans/foreign.rs | 123 ++++-- src/librustc/middle/trans/monomorphize.rs | 8 +- src/librustc/middle/trans/reachable.rs | 2 +- src/librustc/middle/trans/type_use.rs | 4 +- src/librustc/middle/ty.rs | 11 +- src/librustc/middle/typeck/astconv.rs | 7 +- src/librustc/middle/typeck/check/mod.rs | 21 +- src/librustc/middle/typeck/collect.rs | 15 +- src/librustc/middle/typeck/infer/coercion.rs | 13 +- src/librustc/middle/typeck/infer/combine.rs | 9 +- src/librustc/middle/typeck/infer/glb.rs | 3 +- src/librustc/middle/typeck/infer/lub.rs | 3 +- src/librustc/middle/typeck/infer/sub.rs | 3 +- src/librustc/middle/typeck/mod.rs | 2 +- src/librustc/util/ppaux.rs | 12 +- src/librustdoc/prune_private_pass.rs | 2 +- src/librustdoc/tystr_pass.rs | 2 +- src/librusti/rusti.rc | 2 +- src/librustpkg/rustpkg.rc | 2 +- src/libstd/arena.rs | 2 +- src/libstd/priority_queue.rs | 2 +- src/libsyntax/abi.rs | 427 +++++++++++++++++++ src/libsyntax/ast.rs | 39 +- src/libsyntax/ast_map.rs | 11 +- src/libsyntax/ast_util.rs | 2 +- src/libsyntax/attr.rs | 21 - src/libsyntax/ext/pipes/ast_builder.rs | 2 + src/libsyntax/fold.rs | 7 +- src/libsyntax/parse/parser.rs | 112 +++-- src/libsyntax/print/pprust.rs | 48 ++- src/libsyntax/syntax.rc | 1 + src/libsyntax/visit.rs | 30 +- src/test/auxiliary/cci_intrinsic.rs | 6 +- src/test/compile-fail/block-coerce-no-2.rs | 2 +- src/test/compile-fail/main-wrong-type-2.rs | 2 +- src/test/compile-fail/main-wrong-type.rs | 2 +- src/test/compile-fail/missing-do.rs | 2 +- src/test/pretty/fn-types.rs | 2 +- src/test/run-pass/intrinsic-alignment.rs | 2 +- src/test/run-pass/intrinsic-atomics.rs | 6 +- src/test/run-pass/intrinsic-frame-address.rs | 2 +- src/test/run-pass/intrinsic-move-val.rs | 2 +- src/test/run-pass/intrinsics-integer.rs | 4 +- src/test/run-pass/intrinsics-math.rs | 4 +- src/test/run-pass/issue-2718.rs | 1 - src/test/run-pass/morestack-address.rs | 2 +- src/test/run-pass/rec-align-u32.rs | 2 +- src/test/run-pass/rec-align-u64.rs | 2 +- src/test/run-pass/x86stdcall2.rs | 2 +- 73 files changed, 854 insertions(+), 339 deletions(-) create mode 100644 src/libsyntax/abi.rs diff --git a/src/libcore/cast.rs b/src/libcore/cast.rs index f752f52ce5392..39ac7be91d609 100644 --- a/src/libcore/cast.rs +++ b/src/libcore/cast.rs @@ -11,7 +11,7 @@ pub mod rusti { #[abi = "rust-intrinsic"] #[link_name = "rusti"] - pub extern { + pub extern "rust-intrinsic" { fn forget(+x: T); fn reinterpret_cast(&&e: T) -> U; } diff --git a/src/libcore/libc.rs b/src/libcore/libc.rs index 47eece81ce1c9..9531c7e795652 100644 --- a/src/libcore/libc.rs +++ b/src/libcore/libc.rs @@ -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) diff --git a/src/libcore/os.rs b/src/libcore/os.rs index 3c2dbf7ea15bc..b362f6248c75d 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -944,7 +944,7 @@ pub fn errno() -> uint { #[link_name = "kernel32"] #[abi = "stdcall"] - extern { + extern "stdcall" { unsafe fn GetLastError() -> DWORD; } @@ -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, diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index fa96467cb0f67..dd898e066ea32 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -44,7 +44,7 @@ pub mod libc_ { pub mod rusti { #[abi = "rust-intrinsic"] - pub extern { + pub extern "rust-intrinsic" { fn addr_of(&&val: T) -> *T; } } diff --git a/src/libcore/rt/thread_local_storage.rs b/src/libcore/rt/thread_local_storage.rs index 5af8c79fd635c..a6cc8bf03759a 100644 --- a/src/libcore/rt/thread_local_storage.rs +++ b/src/libcore/rt/thread_local_storage.rs @@ -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; diff --git a/src/libcore/stackwalk.rs b/src/libcore/stackwalk.rs index 955e486649b99..2e97f29091e5b 100644 --- a/src/libcore/stackwalk.rs +++ b/src/libcore/stackwalk.rs @@ -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)); } } diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs index 706cb10dba9f7..3c5185613ced1 100644 --- a/src/libcore/sys.rs +++ b/src/libcore/sys.rs @@ -39,7 +39,7 @@ pub struct Closure { pub mod rusti { #[abi = "rust-intrinsic"] - pub extern { + pub extern "rust-intrinsic" { fn get_tydesc() -> *(); fn size_of() -> uint; fn pref_align_of() -> uint; diff --git a/src/libcore/unstable/intrinsics.rs b/src/libcore/unstable/intrinsics.rs index a27ac2ccb6b3a..ba96c6e5d3036 100644 --- a/src/libcore/unstable/intrinsics.rs +++ b/src/libcore/unstable/intrinsics.rs @@ -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; diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 5f9a3e606f201..7d464e408477f 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -97,7 +97,7 @@ pub mod jit { pub mod rusti { #[nolink] #[abi = "rust-intrinsic"] - pub extern { + pub extern "rust-intrinsic" { pub fn morestack_addr() -> *(); } } diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index a4fdd7f1b5249..df0957545121d 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -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; @@ -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. @@ -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; @@ -454,20 +455,20 @@ pub fn get_os(triple: &str) -> Option { } else { None } } -pub fn get_arch(triple: &str) -> Option { +pub fn get_arch(triple: &str) -> Option { 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 } } @@ -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, diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 28ebc3f424ef0..9f7296aa305b6 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -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, diff --git a/src/librustc/front/config.rs b/src/librustc/front/config.rs index 39a1fda2c9296..908b8f9c6dc32 100644 --- a/src/librustc/front/config.rs +++ b/src/librustc/front/config.rs @@ -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 } diff --git a/src/librustc/front/intrinsic.rs b/src/librustc/front/intrinsic.rs index 6cfcac3e85a28..7d5177a6dfb5d 100644 --- a/src/librustc/front/intrinsic.rs +++ b/src/librustc/front/intrinsic.rs @@ -126,7 +126,7 @@ pub mod intrinsic { use super::{TyDesc, TyVisitor}; #[abi = "rust-intrinsic"] - pub extern { + pub extern "rust-intrinsic" { pub fn get_tydesc() -> *(); pub fn visit_tydesc(++td: *TyDesc, &&tv: @TyVisitor); } diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index 401005310107d..dbedeeaa5cc80 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -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, @@ -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 @@ -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, diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 21b035f2242f6..858c662f25754 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -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; diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index ccc29fbbccb26..39ab7bff5f116 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -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; @@ -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)); @@ -983,7 +984,7 @@ fn encode_info_for_foreign_item(ecx: @EncodeContext, nitem: @foreign_item, index: @mut ~[entry], +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() }); @@ -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); diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index f12cc140d8ab9..aadf8d2b60db0 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -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}; @@ -74,6 +76,20 @@ fn next_byte(st: @mut PState) -> u8 { return b; } +fn scan(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) ); @@ -81,10 +97,7 @@ pub fn parse_ident(st: @mut PState, last: char) -> ast::ident { 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); } @@ -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 { @@ -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 } } diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 880d01d1cdb50..fe5eec7f874cd 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -21,6 +21,7 @@ use core::io; use core::uint; use core::vec; use std::oldmap::HashMap; +use syntax::abi::AbiSet; use syntax::ast::*; use syntax::diagnostic::span_handler; use syntax::print::pprust::*; @@ -368,10 +369,13 @@ fn enc_purity(w: @io::Writer, p: purity) { } } -fn enc_abi(w: @io::Writer, a: Abi) { - match a { - RustAbi => w.write_char('r'), +fn enc_abi_set(w: @io::Writer, abis: AbiSet) { + w.write_char('['); + for abis.each |abi| { + w.write_str(abi.name()); + w.write_char(','); } + w.write_char(']') } fn enc_onceness(w: @io::Writer, o: Onceness) { @@ -383,7 +387,7 @@ fn enc_onceness(w: @io::Writer, o: Onceness) { fn enc_bare_fn_ty(w: @io::Writer, cx: @ctxt, ft: &ty::BareFnTy) { enc_purity(w, ft.purity); - enc_abi(w, ft.abi); + enc_abi_set(w, ft.abis); enc_fn_sig(w, cx, &ft.sig); } diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 2b16ccdd1d220..e52433fa09143 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -759,9 +759,7 @@ fn check_item_ctypes(cx: ty::ctxt, it: @ast::item) { } match it.node { - ast::item_foreign_mod(ref nmod) - if attr::foreign_abi(it.attrs) != - either::Right(ast::foreign_abi_rust_intrinsic) => { + ast::item_foreign_mod(ref nmod) if !nmod.abis.is_intrinsic() => { for nmod.items.each |ni| { match ni.node { ast::foreign_item_fn(ref decl, _, _) => { diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 9517494e492b8..f5e5f2eb13167 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -1135,7 +1135,7 @@ pub impl Resolver { name_bindings.define_value (privacy, def_const(local_def(item.id)), sp); } - item_fn(_, purity, _, _) => { + item_fn(_, purity, _, _, _) => { let (name_bindings, new_parent) = self.add_child(ident, parent, ForbidDuplicateValues, sp); @@ -3617,7 +3617,7 @@ pub impl Resolver { } } - item_fn(ref fn_decl, _, ref generics, ref block) => { + item_fn(ref fn_decl, _, _, ref generics, ref block) => { // If this is the main function, we must record it in the // session. // FIXME #4404 android JNI hacks diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 62fff5837666e..b6e285cfcb8d7 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -83,6 +83,7 @@ use syntax::parse::token::special_idents; use syntax::print::pprust::{expr_to_str, stmt_to_str, path_to_str}; use syntax::visit; use syntax::{ast, ast_util, codemap, ast_map}; +use syntax::abi::{X86, X86_64, Arm, Mips}; pub struct icx_popper { ccx: @CrateContext, @@ -1448,10 +1449,12 @@ pub fn call_memcpy(cx: block, dst: ValueRef, src: ValueRef, let _icx = cx.insn_ctxt("call_memcpy"); let ccx = cx.ccx(); let key = match ccx.sess.targ_cfg.arch { - session::arch_x86 - | session::arch_arm - | session::arch_mips => ~"llvm.memcpy.p0i8.p0i8.i32", - session::arch_x86_64 => ~"llvm.memcpy.p0i8.p0i8.i64" + X86 | Arm | Mips => { + ~"llvm.memcpy.p0i8.p0i8.i32" + } + X86_64 => { + ~"llvm.memcpy.p0i8.p0i8.i64" + } }; let memcpy = ccx.intrinsics.get(&key); let src_ptr = PointerCast(cx, src, T_ptr(T_i8())); @@ -1492,12 +1495,10 @@ pub fn memzero(cx: block, llptr: ValueRef, llty: TypeRef) { let intrinsic_key; match ccx.sess.targ_cfg.arch { - session::arch_x86 - | session::arch_arm - | session::arch_mips => { + X86 | Arm | Mips => { intrinsic_key = ~"llvm.memset.p0i8.i32"; } - session::arch_x86_64 => { + X86_64 => { intrinsic_key = ~"llvm.memset.p0i8.i64"; } } @@ -2054,7 +2055,7 @@ pub fn trans_item(ccx: @CrateContext, item: ast::item) { _ => fail!(~"trans_item"), }; match item.node { - ast::item_fn(ref decl, purity, ref generics, ref body) => { + ast::item_fn(ref decl, purity, _abis, ref generics, ref body) => { if purity == ast::extern_fn { let llfndecl = get_item_val(ccx, item.id); foreign::trans_foreign_fn(ccx, @@ -2096,11 +2097,7 @@ pub fn trans_item(ccx: @CrateContext, item: ast::item) { } ast::item_const(_, expr) => consts::trans_const(ccx, expr, item.id), ast::item_foreign_mod(ref foreign_mod) => { - let abi = match attr::foreign_abi(item.attrs) { - Right(abi_) => abi_, - Left(msg) => ccx.sess.span_fatal(item.span, msg) - }; - foreign::trans_foreign_mod(ccx, foreign_mod, abi); + foreign::trans_foreign_mod(ccx, path, foreign_mod); } ast::item_struct(struct_def, ref generics) => { if !generics.is_type_parameterized() { @@ -2397,7 +2394,7 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef { g } } - ast::item_fn(_, purity, _, _) => { + ast::item_fn(_, purity, _, _, _) => { let llfn = if purity != ast::extern_fn { register_fn(ccx, i.span, my_path, i.id, i.attrs) } else { diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 607d4cff8d6a4..0c119511ace89 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -264,11 +264,8 @@ pub fn trans_fn_ref_with_vtables( || fmt!("local item should be in ast map")); match map_node { - ast_map::node_foreign_item(_, - ast::foreign_abi_rust_intrinsic, - _, - _) => { - must_monomorphise = true; + ast_map::node_foreign_item(_, abis, _, _) => { + must_monomorphise = abis.is_intrinsic() } _ => { must_monomorphise = false; diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 0b7d6f5c39bfe..b6168c984127e 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -58,6 +58,7 @@ use syntax::ast_map::{path, path_elt}; use syntax::codemap::span; use syntax::parse::token::ident_interner; use syntax::{ast, ast_map}; +use syntax::abi::{X86, X86_64, Arm, Mips}; pub type namegen = @fn(+s: ~str) -> ident; pub fn new_namegen(intr: @ident_interner) -> namegen { @@ -762,10 +763,10 @@ pub fn T_bool() -> TypeRef { return T_i8(); } pub fn T_int(targ_cfg: @session::config) -> TypeRef { return match targ_cfg.arch { - session::arch_x86 => T_i32(), - session::arch_x86_64 => T_i64(), - session::arch_arm => T_i32(), - session::arch_mips => T_i32() + X86 => T_i32(), + X86_64 => T_i64(), + Arm => T_i32(), + Mips => T_i32() }; } @@ -800,10 +801,10 @@ pub fn T_float_ty(cx: @CrateContext, t: ast::float_ty) -> TypeRef { pub fn T_float(targ_cfg: @session::config) -> TypeRef { return match targ_cfg.arch { - session::arch_x86 => T_f64(), - session::arch_x86_64 => T_f64(), - session::arch_arm => T_f64(), - session::arch_mips => T_f64() + X86 => T_f64(), + X86_64 => T_f64(), + Arm => T_f64(), + Mips => T_f64() }; } diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 505c08fc8b8c1..c19325d362643 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -854,7 +854,7 @@ pub fn create_function(fcx: fn_ctxt) -> @Metadata { let (ident, ret_ty, id) = match cx.tcx.items.get(&fcx.id) { ast_map::node_item(item, _) => { match item.node { - ast::item_fn(ref decl, _, _, _) => { + ast::item_fn(ref decl, _, _, _, _) => { (item.ident, decl.output, item.id) } _ => fcx.ccx.sess.span_bug(item.span, ~"create_function: item \ diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index dadd51b324847..46fb4ef804a23 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -12,9 +12,6 @@ use core::prelude::*; use back::{link, abi}; use driver::session; -use driver::session::arch_x86_64; -use driver::session::arch_arm; -use driver::session::arch_mips; use lib::llvm::{SequentiallyConsistent, Acquire, Release, Xchg}; use lib::llvm::{llvm, TypeRef, ValueRef, Integer, Pointer, Float, Double}; use lib; @@ -41,13 +38,16 @@ use syntax::codemap::span; use syntax::{ast, ast_util}; use syntax::{attr, ast_map}; use syntax::parse::token::special_idents; +use syntax::abi::{Architecture, X86, X86_64, Arm, Mips}; +use syntax::abi::{RustIntrinsic, Rust, Stdcall, Fastcall, + Cdecl, Aapcs, C}; -fn abi_info(arch: session::arch) -> @cabi::ABIInfo { +fn abi_info(arch: Architecture) -> @cabi::ABIInfo { return match arch { - arch_x86_64 => x86_64_abi_info(), - arch_arm => cabi_arm::abi_info(), - arch_mips => mips_abi_info(), - _ => cabi::llvm_abi_info() + X86_64 => x86_64_abi_info(), + Arm => cabi_arm::abi_info(), + Mips => mips_abi_info(), + X86 => cabi::llvm_abi_info() } } @@ -238,36 +238,65 @@ fn build_wrap_fn_(ccx: @CrateContext, // unnecessary). We used to do this, in fact, and will perhaps do so // in the future. pub fn trans_foreign_mod(ccx: @CrateContext, - foreign_mod: &ast::foreign_mod, - abi: ast::foreign_abi) + path: &ast_map::path, + foreign_mod: &ast::foreign_mod) { let _icx = ccx.insn_ctxt("foreign::trans_foreign_mod"); - let mut cc = match abi { - ast::foreign_abi_rust_intrinsic | - ast::foreign_abi_cdecl => lib::llvm::CCallConv, - ast::foreign_abi_stdcall => lib::llvm::X86StdcallCallConv + let arch = ccx.sess.targ_cfg.arch; + let abi = match foreign_mod.abis.for_arch(arch) { + None => { + ccx.sess.fatal( + fmt!("No suitable ABI for target architecture \ + in module %s", + ast_map::path_to_str(*path, + ccx.sess.intr()))); + } + + Some(abi) => abi, }; - for vec::each(foreign_mod.items) |foreign_item| { + for vec::each(foreign_mod.items) |&foreign_item| { match foreign_item.node { ast::foreign_item_fn(*) => { let id = foreign_item.id; - if abi != ast::foreign_abi_rust_intrinsic { - let llwrapfn = get_item_val(ccx, id); - let tys = shim_types(ccx, id); - if attr::attrs_contains_name( - foreign_item.attrs, "rust_stack") - { - build_direct_fn(ccx, llwrapfn, *foreign_item, - &tys, cc); - } else { - let llshimfn = build_shim_fn(ccx, *foreign_item, - &tys, cc); - build_wrap_fn(ccx, &tys, llshimfn, llwrapfn); + match abi { + RustIntrinsic => { + // Intrinsics are emitted by monomorphic fn + } + + Rust => { + // FIXME(#3678) Implement linking to foreign fns with Rust ABI + ccx.sess.unimpl( + fmt!("Foreign functions with Rust ABI")); + } + + Stdcall => { + build_foreign_fn(ccx, id, foreign_item, + lib::llvm::X86StdcallCallConv); + } + + Fastcall => { + build_foreign_fn(ccx, id, foreign_item, + lib::llvm::X86FastcallCallConv); + } + + Cdecl => { + // FIXME(#3678) should really be more specific + build_foreign_fn(ccx, id, foreign_item, + lib::llvm::CCallConv); + } + + Aapcs => { + // FIXME(#3678) should really be more specific + build_foreign_fn(ccx, id, foreign_item, + lib::llvm::CCallConv); + } + + C => { + build_foreign_fn(ccx, id, foreign_item, + lib::llvm::CCallConv); } - } else { - // Intrinsics are emitted by monomorphic fn } } ast::foreign_item_const(*) => { @@ -278,6 +307,25 @@ pub fn trans_foreign_mod(ccx: @CrateContext, } } + fn build_foreign_fn(ccx: @CrateContext, + id: ast::node_id, + foreign_item: @ast::foreign_item, + cc: lib::llvm::CallConv) + { + let llwrapfn = get_item_val(ccx, id); + let tys = shim_types(ccx, id); + if attr::attrs_contains_name( + foreign_item.attrs, "rust_stack") + { + build_direct_fn(ccx, llwrapfn, foreign_item, + &tys, cc); + } else { + let llshimfn = build_shim_fn(ccx, foreign_item, + &tys, cc); + build_wrap_fn(ccx, &tys, llshimfn, llwrapfn); + } + } + fn build_shim_fn(ccx: @CrateContext, foreign_item: @ast::foreign_item, tys: &ShimTypes, @@ -1078,20 +1126,3 @@ pub fn register_foreign_fn(ccx: @CrateContext, t, lib::llvm::CCallConv, fnty) } } - -fn abi_of_foreign_fn(ccx: @CrateContext, i: @ast::foreign_item) - -> ast::foreign_abi { - match attr::first_attr_value_str_by_name(i.attrs, ~"abi") { - None => match ccx.tcx.items.get(&i.id) { - ast_map::node_foreign_item(_, abi, _, _) => abi, - // ?? - _ => fail!(~"abi_of_foreign_fn: not foreign") - }, - Some(_) => match attr::foreign_abi(i.attrs) { - either::Right(abi) => abi, - either::Left(ref msg) => { - ccx.sess.span_fatal(i.span, (/*bad*/copy *msg)) - } - } - } -} diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index feddbabdcad3f..49bdad540565f 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -39,6 +39,7 @@ use syntax::ast_map; use syntax::ast_map::{path, path_mod, path_name}; use syntax::ast_util::local_def; use syntax::parse::token::special_idents; +use syntax::abi::AbiSet; pub fn monomorphic_fn(ccx: @CrateContext, fn_id: ast::def_id, @@ -94,7 +95,7 @@ pub fn monomorphic_fn(ccx: @CrateContext, ast_map::node_item(i, pt) => (pt, i.ident, i.span), ast_map::node_variant(ref v, enm, pt) => (pt, (*v).node.name, enm.span), ast_map::node_method(m, _, pt) => (pt, m.ident, m.span), - ast_map::node_foreign_item(i, ast::foreign_abi_rust_intrinsic, _, pt) + ast_map::node_foreign_item(i, abis, _, pt) if abis.is_intrinsic() => (pt, i.ident, i.span), ast_map::node_foreign_item(*) => { // Foreign externs don't have to be monomorphized. @@ -169,8 +170,7 @@ pub fn monomorphic_fn(ccx: @CrateContext, let lldecl = match map_node { ast_map::node_item(i@@ast::item { - // XXX: Bad copy. - node: ast::item_fn(ref decl, _, _, ref body), + node: ast::item_fn(ref decl, _, _, _, ref body), _ }, _) => { let d = mk_lldecl(); @@ -279,7 +279,7 @@ pub fn normalize_for_monomorphization(tcx: ty::ctxt, tcx, ty::BareFnTy { purity: ast::impure_fn, - abi: ast::RustAbi, + abis: AbiSet::Rust(), sig: FnSig {inputs: ~[], output: ty::mk_nil(tcx)}})) } diff --git a/src/librustc/middle/trans/reachable.rs b/src/librustc/middle/trans/reachable.rs index 015fc61a3c880..cb1ba4dd44a56 100644 --- a/src/librustc/middle/trans/reachable.rs +++ b/src/librustc/middle/trans/reachable.rs @@ -107,7 +107,7 @@ fn traverse_public_item(cx: ctx, item: @item) { } } } - item_fn(_, _, ref generics, ref blk) => { + item_fn(_, _, _, ref generics, ref blk) => { if generics.ty_params.len() > 0u || attr::find_inline_attr(item.attrs) != attr::ia_none { traverse_inline_body(cx, blk); diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs index 45cf790ccee20..a918afc3e93b6 100644 --- a/src/librustc/middle/trans/type_use.rs +++ b/src/librustc/middle/trans/type_use.rs @@ -102,7 +102,7 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint) fn_id_loc)) }; match map_node { - ast_map::node_item(@ast::item { node: item_fn(_, _, _, ref body), + ast_map::node_item(@ast::item { node: item_fn(_, _, _, _, ref body), _ }, _) | ast_map::node_method(@ast::method {body: ref body, _}, _, _) => { handle_body(cx, body); @@ -121,7 +121,7 @@ pub fn type_uses_for(ccx: @CrateContext, fn_id: def_id, n_tps: uint) abi, _, _) => { - if abi == foreign_abi_rust_intrinsic { + if abi.is_intrinsic() { let flags = match *cx.ccx.sess.str_of(i.ident) { ~"size_of" | ~"pref_align_of" | ~"min_align_of" | ~"init" | ~"reinterpret_cast" | diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index de626675fa3f1..ad1147a4f49bf 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -48,6 +48,7 @@ use syntax::codemap::span; use syntax::codemap; use syntax::print::pprust; use syntax::{ast, ast_map}; +use syntax::abi::AbiSet; use syntax; // Data types @@ -362,7 +363,7 @@ pub fn type_id(t: t) -> uint { get(t).id } #[deriving(Eq)] pub struct BareFnTy { purity: ast::purity, - abi: Abi, + abis: AbiSet, sig: FnSig } @@ -389,7 +390,7 @@ pub struct FnSig { impl to_bytes::IterBytes for BareFnTy { fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { - to_bytes::iter_bytes_3(&self.purity, &self.abi, &self.sig, lsb0, f) + to_bytes::iter_bytes_3(&self.purity, &self.abis, &self.sig, lsb0, f) } } @@ -555,7 +556,7 @@ pub enum type_err { terr_mismatch, terr_purity_mismatch(expected_found), terr_onceness_mismatch(expected_found), - terr_abi_mismatch(expected_found), + terr_abi_mismatch(expected_found), terr_mutability, terr_sigil_mismatch(expected_found), terr_box_mutability, @@ -1065,7 +1066,7 @@ pub fn mk_ctor_fn(cx: ctxt, input_tys: &[ty::t], output: ty::t) -> t { mk_bare_fn(cx, BareFnTy { purity: ast::pure_fn, - abi: ast::RustAbi, + abis: AbiSet::Rust(), sig: FnSig {inputs: input_args, output: output}}) } @@ -1247,7 +1248,7 @@ fn fold_sty(sty: &sty, fldop: &fn(t) -> t) -> sty { } ty_bare_fn(ref f) => { let sig = fold_sig(&f.sig, fldop); - ty_bare_fn(BareFnTy {sig: sig, abi: f.abi, purity: f.purity}) + ty_bare_fn(BareFnTy {sig: sig, abis: f.abis, purity: f.purity}) } ty_closure(ref f) => { let sig = fold_sig(&f.sig, fldop); diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index c288151308fe4..e42f3a819cafc 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -64,6 +64,7 @@ use middle::typeck::{CrateCtxt, write_substs_to_tcx, write_ty_to_tcx}; use core::result; use core::vec; +use syntax::abi::AbiSet; use syntax::{ast, ast_util}; use syntax::codemap::span; use syntax::print::pprust::{lifetime_to_str, path_to_str}; @@ -350,7 +351,7 @@ pub fn ast_ty_to_ty( } ast::ty_bare_fn(ref bf) => { ty::mk_bare_fn(tcx, ty_of_bare_fn(self, rscope, bf.purity, - bf.abi, &bf.decl)) + bf.abis, &bf.decl)) } ast::ty_closure(ref f) => { let fn_decl = ty_of_closure(self, rscope, f.sigil, @@ -509,7 +510,7 @@ pub fn ty_of_bare_fn( self: &AC, rscope: &RS, purity: ast::purity, - abi: ast::Abi, + abi: AbiSet, decl: &ast::fn_decl) -> ty::BareFnTy { debug!("ty_of_fn_decl"); @@ -526,7 +527,7 @@ pub fn ty_of_bare_fn( ty::BareFnTy { purity: purity, - abi: abi, + abis: abi, sig: ty::FnSig {inputs: input_tys, output: output_ty} } } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 12c88ae7198db..95289dab0d0fe 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -120,6 +120,7 @@ use core::vec; use std::list::Nil; use std::oldmap::HashMap; use std::oldmap; +use syntax::abi::AbiSet; use syntax::ast::{provided, required, ty_i}; use syntax::ast; use syntax::ast_map; @@ -561,7 +562,7 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) { enum_definition.variants, it.id); } - ast::item_fn(ref decl, _, _, ref body) => { + ast::item_fn(ref decl, _, _, _, ref body) => { check_bare_fn(ccx, decl, body, it.id, None); } ast::item_impl(_, _, ty, ref ms) => { @@ -595,8 +596,7 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) { check_bounds_are_used(ccx, t.span, &generics.ty_params, tpt_ty); } ast::item_foreign_mod(ref m) => { - if syntax::attr::foreign_abi(it.attrs) == - either::Right(ast::foreign_abi_rust_intrinsic) { + if m.abis.is_intrinsic() { for m.items.each |item| { check_intrinsic_type(ccx, *item); } @@ -1165,6 +1165,19 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, let formal_tys; + // FIXME(#3678) For now, do not permit calls to C abi functions. + match structure_of(fcx, sp, in_fty) { + ty::ty_bare_fn(ty::BareFnTy {abis, _}) => { + if !abis.is_rust() { + tcx.sess.span_err( + sp, + fmt!("Calls to C ABI functions are not (yet) \ + supported; be patient, dear user")); + } + } + _ => {} + } + // This is subtle: we expect `fty` to be a function type, which // normally introduce a level of binding. In this case, we want to // process the types bound by the function but not by any nested @@ -3715,7 +3728,7 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { }; let fty = ty::mk_bare_fn(tcx, ty::BareFnTy { purity: ast::unsafe_fn, - abi: ast::RustAbi, + abis: AbiSet::Rust(), sig: FnSig {inputs: inputs, output: output} }); diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index a8e91f0097a03..87a902900f70d 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -47,6 +47,7 @@ use util::common::{indenter, pluralize}; use util::ppaux; use core::vec; +use syntax::abi::AbiSet; use syntax::ast::{RegionTyParamBound, TraitTyParamBound}; use syntax::ast; use syntax::ast_map; @@ -698,7 +699,7 @@ pub fn convert_struct(ccx: &CrateCtxt, tcx, astconv::ty_of_bare_fn( ccx, &type_rscope(rp), - ast::impure_fn, ast::RustAbi, + ast::impure_fn, AbiSet::Rust(), &ast_util::dtor_dec())); write_ty_to_tcx(tcx, dtor.node.id, t_dtor); tcx.tcache.insert(local_def(dtor.node.id), @@ -763,7 +764,7 @@ pub fn ty_of_method(ccx: &CrateCtxt, ident: m.ident, tps: ty_param_bounds(ccx, &m.generics), fty: astconv::ty_of_bare_fn(ccx, &rscope, m.purity, - ast::RustAbi, &m.decl), + AbiSet::Rust(), &m.decl), self_ty: m.self_ty.node, vis: m.vis, def_id: local_def(m.id) @@ -783,7 +784,7 @@ pub fn ty_of_ty_method(self: &CrateCtxt, ident: m.ident, tps: ty_param_bounds(self, &m.generics), fty: astconv::ty_of_bare_fn(self, &rscope, m.purity, - ast::RustAbi, &m.decl), + AbiSet::Rust(), &m.decl), // assume public, because this is only invoked on trait methods self_ty: m.self_ty.node, vis: ast::public, @@ -836,10 +837,10 @@ pub fn ty_of_item(ccx: &CrateCtxt, it: @ast::item) tcx.tcache.insert(local_def(it.id), tpt); return tpt; } - ast::item_fn(ref decl, purity, ref generics, _) => { + ast::item_fn(ref decl, purity, abi, ref generics, _) => { let bounds = ty_param_bounds(ccx, generics); - let tofd = astconv::ty_of_bare_fn(ccx, &empty_rscope, purity, - ast::RustAbi, decl); + let tofd = astconv::ty_of_bare_fn( + ccx, &empty_rscope, purity, abi, decl); let tpt = ty_param_bounds_and_ty { bounds: bounds, region_param: None, @@ -1011,7 +1012,7 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt, let t_fn = ty::mk_bare_fn( ccx.tcx, ty::BareFnTy { - abi: ast::RustAbi, + abis: AbiSet::Rust(), purity: ast::unsafe_fn, sig: ty::FnSig {inputs: input_tys, output: output_ty} }); diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs index 91c987acc6aa7..95ff552eb51b7 100644 --- a/src/librustc/middle/typeck/infer/coercion.rs +++ b/src/librustc/middle/typeck/infer/coercion.rs @@ -78,6 +78,7 @@ use middle::typeck::infer::to_str::InferStr; use middle::typeck::infer::resolve::try_resolve_tvar_shallow; use util::common::{indent, indenter}; +use syntax::abi::AbiSet; use syntax::ast::{m_const, m_imm, m_mutbl}; use syntax::ast; @@ -334,9 +335,19 @@ pub impl Coerce { b: ty::t, sty_b: &ty::sty) -> CoerceResult { + /*! + * + * Attempts to coerce from a bare Rust function (`extern + * "rust" fn`) into a closure. + */ + debug!("coerce_from_bare_fn(a=%s, b=%s)", a.inf_str(self.infcx), b.inf_str(self.infcx)); + if !fn_ty_a.abis.is_rust() { + return self.subtype(a, b); + } + let fn_ty_b = match *sty_b { ty::ty_closure(ref f) => {copy *f} _ => { @@ -344,8 +355,6 @@ pub impl Coerce { } }; - // for now, bare fn and closures have the same - // representation let adj = @ty::AutoAddEnv(fn_ty_b.region, fn_ty_b.sigil); let a_closure = ty::mk_closure( self.infcx.tcx, diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index 8b128dbc5c595..63fde41be99db 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -71,6 +71,7 @@ use core::vec; use syntax::ast::{Onceness, purity, ret_style}; use syntax::ast; use syntax::codemap::span; +use syntax::abi::AbiSet; pub trait Combine { fn infcx(&self) -> @mut InferCtxt; @@ -100,7 +101,7 @@ pub trait Combine { fn args(&self, a: ty::arg, b: ty::arg) -> cres; fn sigils(&self, p1: ast::Sigil, p2: ast::Sigil) -> cres; fn purities(&self, a: purity, b: purity) -> cres; - fn abis(&self, a: ast::Abi, b: ast::Abi) -> cres; + fn abis(&self, a: AbiSet, b: AbiSet) -> cres; fn oncenesses(&self, a: Onceness, b: Onceness) -> cres; fn contraregions(&self, a: ty::Region, b: ty::Region) -> cres; @@ -395,7 +396,7 @@ pub fn super_closure_tys( } pub fn super_abis( - self: &C, a: ast::Abi, b: ast::Abi) -> cres + self: &C, a: AbiSet, b: AbiSet) -> cres { if a == b { Ok(a) @@ -408,10 +409,10 @@ pub fn super_bare_fn_tys( self: &C, a_f: &ty::BareFnTy, b_f: &ty::BareFnTy) -> cres { let purity = if_ok!(self.purities(a_f.purity, b_f.purity)); - let abi = if_ok!(self.abis(a_f.abi, b_f.abi)); + let abi = if_ok!(self.abis(a_f.abis, b_f.abis)); let sig = if_ok!(self.fn_sigs(&a_f.sig, &b_f.sig)); Ok(ty::BareFnTy {purity: purity, - abi: abi, + abis: abi, sig: sig}) } diff --git a/src/librustc/middle/typeck/infer/glb.rs b/src/librustc/middle/typeck/infer/glb.rs index 55bfa9888c0df..d521d005aba4a 100644 --- a/src/librustc/middle/typeck/infer/glb.rs +++ b/src/librustc/middle/typeck/infer/glb.rs @@ -23,6 +23,7 @@ use syntax::ast; use syntax::ast::{Many, Once, extern_fn, impure_fn, m_const, m_imm, m_mutbl}; use syntax::ast::{noreturn, pure_fn, ret_style, return_val, unsafe_fn}; use syntax::ast::{Onceness, purity}; +use syntax::abi::AbiSet; use syntax::codemap::span; use util::common::{indent, indenter}; use util::ppaux::mt_to_str; @@ -284,7 +285,7 @@ impl Combine for Glb { super_sigils(self, p1, p2) } - fn abis(&self, p1: ast::Abi, p2: ast::Abi) -> cres { + fn abis(&self, p1: AbiSet, p2: AbiSet) -> cres { super_abis(self, p1, p2) } diff --git a/src/librustc/middle/typeck/infer/lub.rs b/src/librustc/middle/typeck/infer/lub.rs index 59cc15dfc024d..1b7aea0e37e78 100644 --- a/src/librustc/middle/typeck/infer/lub.rs +++ b/src/librustc/middle/typeck/infer/lub.rs @@ -23,6 +23,7 @@ use util::common::indent; use util::ppaux::mt_to_str; use std::list; +use syntax::abi::AbiSet; use syntax::ast; use syntax::ast::{Many, Once, extern_fn, m_const, impure_fn, noreturn}; use syntax::ast::{pure_fn, ret_style, return_val, unsafe_fn}; @@ -210,7 +211,7 @@ impl Combine for Lub { super_sigils(self, p1, p2) } - fn abis(&self, p1: ast::Abi, p2: ast::Abi) -> cres { + fn abis(&self, p1: AbiSet, p2: AbiSet) -> cres { super_abis(self, p1, p2) } diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs index 561fabd9d7027..53dfb221c9284 100644 --- a/src/librustc/middle/typeck/infer/sub.rs +++ b/src/librustc/middle/typeck/infer/sub.rs @@ -24,6 +24,7 @@ use util::ppaux::bound_region_to_str; use std::list::Nil; use std::list; +use syntax::abi::AbiSet; use syntax::ast; use syntax::ast::{Onceness, m_const, purity, ret_style}; use syntax::codemap::span; @@ -216,7 +217,7 @@ impl Combine for Sub { super_sigils(self, p1, p2) } - fn abis(&self, p1: ast::Abi, p2: ast::Abi) -> cres { + fn abis(&self, p1: AbiSet, p2: AbiSet) -> cres { super_abis(self, p1, p2) } diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index 7724b43b50f85..96cb3f4d74864 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -283,7 +283,7 @@ fn check_main_fn_ty(ccx: @mut CrateCtxt, match tcx.items.find(&main_id) { Some(ast_map::node_item(it,_)) => { match it.node { - ast::item_fn(_, _, ref ps, _) + ast::item_fn(_, _, _, ref ps, _) if ps.is_parameterized() => { tcx.sess.span_err( main_span, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index eb63d675d80af..821a6ea90585d 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -30,6 +30,7 @@ use syntax::print::pprust; use syntax::print::pprust::{path_to_str, mode_to_str}; use syntax::{ast, ast_util}; use syntax::ast_map; +use syntax::abi::AbiSet; use core::str; use core::vec; @@ -302,15 +303,14 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { } fn bare_fn_to_str(cx: ctxt, purity: ast::purity, - abi: ast::Abi, + abis: AbiSet, ident: Option, sig: &ty::FnSig) -> ~str { let mut s = ~"extern "; - match abi { - ast::RustAbi => {} - } + s.push_str(abis.to_str()); + s.push_char(' '); match purity { ast::impure_fn => {} @@ -386,7 +386,7 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { fn method_to_str(cx: ctxt, m: method) -> ~str { bare_fn_to_str(cx, m.fty.purity, - m.fty.abi, + m.fty.abis, Some(m.ident), &m.fty.sig) + ~";" } @@ -429,7 +429,7 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str { closure_to_str(cx, f) } ty_bare_fn(ref f) => { - bare_fn_to_str(cx, f.purity, f.abi, None, &f.sig) + bare_fn_to_str(cx, f.purity, f.abis, None, &f.sig) } ty_infer(infer_ty) => infer_ty.to_str(), ty_err => ~"[type error]", diff --git a/src/librustdoc/prune_private_pass.rs b/src/librustdoc/prune_private_pass.rs index 67dbc659f9e71..ac575ee6d66ea 100644 --- a/src/librustdoc/prune_private_pass.rs +++ b/src/librustdoc/prune_private_pass.rs @@ -62,7 +62,7 @@ fn is_visible(srv: astsrv::Srv, doc: doc::ItemDoc) -> bool { match item.node { ast::item_impl(_, Some(_), _, _) => { // This is a trait implementation, make it visible - // NOTE: This is not quite right since this could be an impl + // NB: This is not quite right since this could be an impl // of a private trait. We can't know that without running // resolve though. true diff --git a/src/librustdoc/tystr_pass.rs b/src/librustdoc/tystr_pass.rs index 1472f6777b48f..41ec70733e4a9 100644 --- a/src/librustdoc/tystr_pass.rs +++ b/src/librustdoc/tystr_pass.rs @@ -69,7 +69,7 @@ fn get_fn_sig(srv: astsrv::Srv, fn_id: doc::AstId) -> Option<~str> { match ctxt.ast_map.get(&fn_id) { ast_map::node_item(@ast::item { ident: ident, - node: ast::item_fn(ref decl, _, ref tys, _), _ + node: ast::item_fn(ref decl, _, _, ref tys, _), _ }, _) | ast_map::node_foreign_item(@ast::foreign_item { ident: ident, diff --git a/src/librusti/rusti.rc b/src/librusti/rusti.rc index 6a54dc7de1020..5e092fe3018cb 100644 --- a/src/librusti/rusti.rc +++ b/src/librusti/rusti.rc @@ -160,7 +160,7 @@ fn run(repl: Repl, input: ~str) -> Repl { for crate.node.module.items.each |item| { match item.node { - ast::item_fn(_, _, _, blk) => { + ast::item_fn(_, _, _, _, blk) => { if item.ident == sess.ident_of(~"main") { opt = blk.node.expr; } diff --git a/src/librustpkg/rustpkg.rc b/src/librustpkg/rustpkg.rc index 90d6fcbb8a533..529cf28fb6ac0 100644 --- a/src/librustpkg/rustpkg.rc +++ b/src/librustpkg/rustpkg.rc @@ -187,7 +187,7 @@ impl PackageScript { // the build API. for crate.node.module.items.each |i| { match i.node { - ast::item_fn(_, _, _, _) => { + ast::item_fn(*) => { custom = true; break; diff --git a/src/libstd/arena.rs b/src/libstd/arena.rs index a26132d92ca01..e9b8ad5966b88 100644 --- a/src/libstd/arena.rs +++ b/src/libstd/arena.rs @@ -48,7 +48,7 @@ use core::vec; pub mod rusti { #[abi = "rust-intrinsic"] - pub extern { + pub extern "rust-intrinsic" { fn move_val_init(dst: &mut T, +src: T); fn needs_drop() -> bool; } diff --git a/src/libstd/priority_queue.rs b/src/libstd/priority_queue.rs index ff00d26882d32..909685be94980 100644 --- a/src/libstd/priority_queue.rs +++ b/src/libstd/priority_queue.rs @@ -18,7 +18,7 @@ use core::ptr::addr_of; use core::vec; #[abi = "rust-intrinsic"] -extern "C" mod rusti { +extern "rust-intrinsic" mod rusti { fn move_val_init(dst: &mut T, +src: T); fn init() -> T; } diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs new file mode 100644 index 0000000000000..195e7fa27b357 --- /dev/null +++ b/src/libsyntax/abi.rs @@ -0,0 +1,427 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::prelude::*; +use core::to_bytes; +use core::to_str::ToStr; + +#[deriving_eq] +pub enum Abi { + // NB: This ordering MUST match the AbiDatas array below. + // (This is ensured by the test indices_are_correct().) + + // Single platform ABIs come first (`for_arch()` relies on this) + Cdecl, + Stdcall, + Fastcall, + Aapcs, + + // Multiplatform ABIs second + Rust, + C, + RustIntrinsic, +} + +#[deriving_eq] +pub enum Architecture { + // NB. You cannot change the ordering of these + // constants without adjusting IntelBits below. + // (This is ensured by the test indices_are_correct().) + X86, + X86_64, + Arm, + Mips +} + +// FIXME(#5423) After a snapshot, we can change these constants: +// const IntelBits: u32 = (1 << (X86 as uint)) | (1 << X86_64 as uint)); +// const ArmBits: u32 = (1 << (Arm as uint)); +const IntelBits: u32 = 1 | 2; +const ArmBits: u32 = 4; + +struct AbiData { + abi: Abi, + + // Name of this ABI as we like it called. + name: &'static str, + + // Is it specific to a platform? If so, which one? Also, what is + // the name that LLVM gives it (in case we disagree) + abi_arch: AbiArchitecture +} + +enum AbiArchitecture { + RustArch, // Not a real ABI (e.g., intrinsic) + AllArch, // An ABI that specifies cross-platform defaults (e.g., "C") + Archs(u32) // Multiple architectures (bitset) +} + +#[auto_encode] +#[auto_decode] +#[deriving_eq] +pub struct AbiSet { + priv bits: u32 // each bit represents one of the abis below +} + +const AbiDatas: &'static [AbiData] = &[ + // Platform-specific ABIs + AbiData {abi: Cdecl, name: "cdecl", abi_arch: Archs(IntelBits)}, + AbiData {abi: Stdcall, name: "stdcall", abi_arch: Archs(IntelBits)}, + AbiData {abi: Fastcall, name:"fastcall", abi_arch: Archs(IntelBits)}, + AbiData {abi: Aapcs, name: "aapcs", abi_arch: Archs(ArmBits)}, + + // Cross-platform ABIs + // + // NB: Do not adjust this ordering without + // adjusting the indices below. + AbiData {abi: Rust, name: "Rust", abi_arch: RustArch}, + AbiData {abi: C, name: "C", abi_arch: AllArch}, + AbiData {abi: RustIntrinsic, name: "rust-intrinsic", abi_arch: RustArch}, +]; + +fn each_abi(op: &fn(abi: Abi) -> bool) { + /*! + * + * Iterates through each of the defined ABIs. + */ + + for AbiDatas.each |abi_data| { + if !op(abi_data.abi) { + return; + } + } +} + +pub fn lookup(name: &str) -> Option { + /*! + * + * Returns the ABI with the given name (if any). + */ + + for each_abi |abi| { + if name == abi.data().name { + return Some(abi); + } + } + return None; +} + +pub fn all_names() -> ~[&'static str] { + AbiDatas.map(|d| d.name) +} + +pub impl Abi { + #[inline] + pure fn index(&self) -> uint { + *self as uint + } + + #[inline] + pure fn data(&self) -> &'static AbiData { + &AbiDatas[self.index()] + } + + pure fn name(&self) -> &'static str { + self.data().name + } +} + +impl Architecture { + fn bit(&self) -> u32 { + 1 << (*self as u32) + } +} + +pub impl AbiSet { + static fn from(abi: Abi) -> AbiSet { + AbiSet { bits: (1 << abi.index()) } + } + + #[inline] + static fn Rust() -> AbiSet { + AbiSet::from(Rust) + } + + #[inline] + static fn C() -> AbiSet { + AbiSet::from(C) + } + + #[inline] + static fn Intrinsic() -> AbiSet { + AbiSet::from(RustIntrinsic) + } + + static fn default() -> AbiSet { + AbiSet::C() + } + + static fn empty() -> AbiSet { + AbiSet { bits: 0 } + } + + #[inline] + fn is_rust(&self) -> bool { + self.bits == 1 << Rust.index() + } + + #[inline] + fn is_c(&self) -> bool { + self.bits == 1 << C.index() + } + + #[inline] + fn is_intrinsic(&self) -> bool { + self.bits == 1 << RustIntrinsic.index() + } + + fn contains(&self, abi: Abi) -> bool { + (self.bits & (1 << abi.index())) != 0 + } + + fn subset_of(&self, other_abi_set: AbiSet) -> bool { + (self.bits & other_abi_set.bits) == self.bits + } + + fn add(&mut self, abi: Abi) { + self.bits |= (1 << abi.index()); + } + + fn each(&self, op: &fn(abi: Abi) -> bool) { + for each_abi |abi| { + if self.contains(abi) { + if !op(abi) { + return; + } + } + } + } + + fn is_empty(&self) -> bool { + self.bits == 0 + } + + fn for_arch(&self, arch: Architecture) -> Option { + // NB---Single platform ABIs come first + for self.each |abi| { + let data = abi.data(); + match data.abi_arch { + Archs(a) if (a & arch.bit()) != 0 => { return Some(abi); } + Archs(_) => { } + RustArch | AllArch => { return Some(abi); } + } + } + + None + } + + fn check_valid(&self) -> Option<(Abi, Abi)> { + let mut abis = ~[]; + for self.each |abi| { abis.push(abi); } + + for abis.eachi |i, abi| { + let data = abi.data(); + for abis.slice(0, i).each |other_abi| { + let other_data = other_abi.data(); + debug!("abis=(%?,%?) datas=(%?,%?)", + abi, data.abi_arch, + other_abi, other_data.abi_arch); + match (&data.abi_arch, &other_data.abi_arch) { + (&AllArch, &AllArch) => { + // Two cross-architecture ABIs + return Some((*abi, *other_abi)); + } + (_, &RustArch) | + (&RustArch, _) => { + // Cannot combine Rust or Rust-Intrinsic with + // anything else. + return Some((*abi, *other_abi)); + } + (&Archs(is), &Archs(js)) if (is & js) != 0 => { + // Two ABIs for same architecture + return Some((*abi, *other_abi)); + } + _ => {} + } + } + } + + return None; + } +} + +impl to_bytes::IterBytes for Abi { + pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + self.index().iter_bytes(lsb0, f) + } +} + +impl to_bytes::IterBytes for AbiSet { + pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { + self.bits.iter_bytes(lsb0, f) + } +} + +impl ToStr for Abi { + pure fn to_str(&self) -> ~str { + self.data().name.to_str() + } +} + +impl ToStr for AbiSet { + pure fn to_str(&self) -> ~str { + unsafe { // so we can push to strs. + let mut strs = ~[]; + for self.each |abi| { + strs.push(abi.data().name); + } + fmt!("\"%s\"", str::connect_slices(strs, " ")) + } + } +} + +#[test] +fn lookup_Rust() { + let abi = lookup("Rust"); + fail_unless!(abi.is_some() && abi.get().data().name == "Rust"); +} + +#[test] +fn lookup_cdecl() { + let abi = lookup("cdecl"); + fail_unless!(abi.is_some() && abi.get().data().name == "cdecl"); +} + +#[test] +fn lookup_baz() { + let abi = lookup("baz"); + fail_unless!(abi.is_none()); +} + +#[cfg(test)] +fn cannot_combine(n: Abi, m: Abi) { + let mut set = AbiSet::empty(); + set.add(n); + set.add(m); + match set.check_valid() { + Some((a, b)) => { + fail_unless!((n == a && m == b) || + (m == a && n == b)); + } + None => { + fail!(~"Invalid match not detected"); + } + } +} + +#[cfg(test)] +fn can_combine(n: Abi, m: Abi) { + let mut set = AbiSet::empty(); + set.add(n); + set.add(m); + match set.check_valid() { + Some((_, _)) => { + fail!(~"Valid match declared invalid"); + } + None => {} + } +} + +#[test] +fn cannot_combine_cdecl_and_stdcall() { + cannot_combine(Cdecl, Stdcall); +} + +#[test] +fn cannot_combine_c_and_rust() { + cannot_combine(C, Rust); +} + +#[test] +fn cannot_combine_rust_and_cdecl() { + cannot_combine(Rust, Cdecl); +} + +#[test] +fn cannot_combine_rust_intrinsic_and_cdecl() { + cannot_combine(RustIntrinsic, Cdecl); +} + +#[test] +fn can_combine_c_and_stdcall() { + can_combine(C, Stdcall); +} + +#[test] +fn can_combine_aapcs_and_stdcall() { + can_combine(Aapcs, Stdcall); +} + +#[test] +fn abi_to_str_stdcall_aaps() { + let mut set = AbiSet::empty(); + set.add(Aapcs); + set.add(Stdcall); + fail_unless!(set.to_str() == ~"\"stdcall aapcs\""); +} + +#[test] +fn abi_to_str_c_aaps() { + let mut set = AbiSet::empty(); + set.add(Aapcs); + set.add(C); + debug!("set = %s", set.to_str()); + fail_unless!(set.to_str() == ~"\"aapcs C\""); +} + +#[test] +fn abi_to_str_rust() { + let mut set = AbiSet::empty(); + set.add(Rust); + debug!("set = %s", set.to_str()); + fail_unless!(set.to_str() == ~"\"Rust\""); +} + +#[test] +fn indices_are_correct() { + for AbiDatas.eachi |i, abi_data| { + fail_unless!(i == abi_data.abi.index()); + } + + let bits = 1 << (X86 as u32); + let bits = bits | 1 << (X86_64 as u32); + fail_unless!(IntelBits == bits); + + let bits = 1 << (Arm as u32); + fail_unless!(ArmBits == bits); +} + +#[cfg(test)] +fn check_arch(abis: &[Abi], arch: Architecture, expect: Option) { + let mut set = AbiSet::empty(); + for abis.each |&abi| { + set.add(abi); + } + let r = set.for_arch(arch); + fail_unless!(r == expect); +} + +#[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)); +} + +#[test] +fn pick_uniplatform() { + check_arch([Stdcall], X86, Some(Stdcall)); + check_arch([Stdcall], Arm, None); +} diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index bef88e58a1795..048d2c74fe528 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -11,6 +11,8 @@ // The Rust abstract syntax tree. use codemap::{span, FileName, spanned}; +use abi::AbiSet; +use opt_vec::OptVec; use core::cast; use core::option::{None, Option, Some}; @@ -19,7 +21,6 @@ use core::to_bytes; use core::to_str::ToStr; use std::serialize::{Encodable, Decodable, Encoder, Decoder}; -use opt_vec::OptVec; /* can't import macros yet, so this is copied from token.rs. See its comment * there. */ @@ -325,27 +326,6 @@ impl to_bytes::IterBytes for mutability { } } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] -pub enum Abi { - RustAbi -} - -impl to_bytes::IterBytes for Abi { - fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) { - (*self as uint).iter_bytes(lsb0, f) - } -} - -impl ToStr for Abi { - fn to_str(&self) -> ~str { - match *self { - RustAbi => ~"\"rust\"" - } - } -} - #[auto_encode] #[auto_decode] #[deriving(Eq)] @@ -902,7 +882,7 @@ pub struct TyClosure { #[deriving(Eq)] pub struct TyBareFn { purity: purity, - abi: Abi, + abis: AbiSet, decl: fn_decl } @@ -1045,15 +1025,6 @@ pub struct _mod { items: ~[@item], } -#[auto_encode] -#[auto_decode] -#[deriving(Eq)] -pub enum foreign_abi { - foreign_abi_rust_intrinsic, - foreign_abi_cdecl, - foreign_abi_stdcall, -} - // Foreign mods can be named or anonymous #[auto_encode] #[auto_decode] @@ -1065,7 +1036,7 @@ pub enum foreign_mod_sort { named, anonymous } #[deriving(Eq)] pub struct foreign_mod { sort: foreign_mod_sort, - abi: ident, + abis: AbiSet, view_items: ~[@view_item], items: ~[@foreign_item], } @@ -1257,7 +1228,7 @@ pub struct item { #[deriving(Eq)] pub enum item_ { item_const(@Ty, @expr), - item_fn(fn_decl, purity, Generics, blk), + item_fn(fn_decl, purity, AbiSet, Generics, blk), item_mod(_mod), item_foreign_mod(foreign_mod), item_ty(@Ty, Generics), diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index 8989bb88cd7f4..97b8bda67c6a0 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -10,6 +10,7 @@ use core::prelude::*; +use abi::AbiSet; use ast::*; use ast; use ast_util::{inlined_item_utils, path_to_ident, stmt_id}; @@ -87,7 +88,7 @@ pub fn path_elt_to_str(pe: path_elt, itr: @ident_interner) -> ~str { pub enum ast_node { node_item(@item, @path), - node_foreign_item(@foreign_item, foreign_abi, visibility, @path), + node_foreign_item(@foreign_item, AbiSet, visibility, @path), node_trait_method(@trait_method, def_id /* trait did */, @path /* path to the trait */), node_method(@method, def_id /* impl did */, @path /* path to the impl */), @@ -171,7 +172,7 @@ pub fn map_decoded_item(diag: @span_handler, ii_item(*) | ii_dtor(*) => { /* fallthrough */ } ii_foreign(i) => { cx.map.insert(i.id, node_foreign_item(i, - foreign_abi_rust_intrinsic, + AbiSet::Intrinsic(), i.vis, // Wrong but OK @path)); } @@ -274,10 +275,6 @@ pub fn map_item(i: @item, &&cx: @mut Ctx, v: visit::vt<@mut Ctx>) { } } item_foreign_mod(ref nm) => { - let abi = match attr::foreign_abi(i.attrs) { - Left(ref msg) => cx.diag.span_fatal(i.span, (*msg)), - Right(abi) => abi - }; for nm.items.each |nitem| { // Compute the visibility for this native item. let visibility = match nitem.vis { @@ -289,7 +286,7 @@ pub fn map_item(i: @item, &&cx: @mut Ctx, v: visit::vt<@mut Ctx>) { cx.map.insert(nitem.id, node_foreign_item( *nitem, - abi, + nm.abis, visibility, // FIXME (#2543) if nm.sort == ast::named { diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 764393e0feb6e..5db0f4fab97b3 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -465,7 +465,7 @@ pub fn id_visitor(vfn: @fn(node_id)) -> visit::vt<()> { vfn(self_id); vfn(parent_id.node); } - visit::fk_item_fn(_, generics, _) => { + visit::fk_item_fn(_, generics, _, _) => { visit_generics(generics); } visit::fk_method(_, generics, m) => { diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index b22d71afaed2d..40675217600fb 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -304,27 +304,6 @@ pub fn find_linkage_metas(attrs: &[ast::attribute]) -> ~[@ast::meta_item] { } } -pub fn foreign_abi(attrs: &[ast::attribute]) - -> Either<~str, ast::foreign_abi> { - return match attr::first_attr_value_str_by_name(attrs, ~"abi") { - None => { - Right(ast::foreign_abi_cdecl) - } - Some(@~"rust-intrinsic") => { - Right(ast::foreign_abi_rust_intrinsic) - } - Some(@~"cdecl") => { - Right(ast::foreign_abi_cdecl) - } - Some(@~"stdcall") => { - Right(ast::foreign_abi_stdcall) - } - Some(t) => { - Left(~"unsupported abi: " + *t) - } - }; -} - pub enum inline_attr { ia_none, ia_hint, diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs index 76b70225c6c84..2b8ac56b42518 100644 --- a/src/libsyntax/ext/pipes/ast_builder.rs +++ b/src/libsyntax/ext/pipes/ast_builder.rs @@ -15,6 +15,7 @@ use core::prelude::*; +use abi::AbiSet; use ast::{ident, node_id}; use ast; use ast_util; @@ -272,6 +273,7 @@ impl ext_ctxt_ast_builder for @ext_ctxt { dummy_sp(), ast::item_fn(self.fn_decl(inputs, output), ast::impure_fn, + AbiSet::Rust(), generics, body)) } diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 159b23f4f9997..85861ee0432d3 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -237,10 +237,11 @@ fn noop_fold_struct_field(sf: @struct_field, fld: @ast_fold) pub fn noop_fold_item_underscore(i: &item_, fld: @ast_fold) -> item_ { match *i { item_const(t, e) => item_const(fld.fold_ty(t), fld.fold_expr(e)), - item_fn(ref decl, purity, ref generics, ref body) => { + item_fn(ref decl, purity, abi, ref generics, ref body) => { item_fn( fold_fn_decl(decl, fld), purity, + abi, fold_generics(generics, fld), fld.fold_block(body) ) @@ -616,7 +617,7 @@ pub fn noop_fold_ty(t: &ty_, fld: @ast_fold) -> ty_ { ty_bare_fn(ref f) => { ty_bare_fn(@TyBareFn { purity: f.purity, - abi: f.abi, + abis: f.abis, decl: fold_fn_decl(&f.decl, fld) }) } @@ -643,7 +644,7 @@ pub fn noop_fold_mod(m: &_mod, fld: @ast_fold) -> _mod { fn noop_fold_foreign_mod(nm: &foreign_mod, fld: @ast_fold) -> foreign_mod { ast::foreign_mod { sort: nm.sort, - abi: nm.abi, + abis: nm.abis, view_items: vec::map(nm.view_items, |x| fld.fold_view_item(*x)), items: vec::map(nm.items, |x| fld.fold_foreign_item(*x)), } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index af64bf07b7c3e..34a67adb05b72 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -10,7 +10,9 @@ use core::prelude::*; -use ast::{Sigil, BorrowedSigil, ManagedSigil, OwnedSigil, RustAbi}; +use abi; +use abi::AbiSet; +use ast::{Sigil, BorrowedSigil, ManagedSigil, OwnedSigil}; use ast::{CallSugar, NoSugar, DoSugar, ForSugar}; use ast::{TyBareFn, TyClosure}; use ast::{RegionTyParamBound, TraitTyParamBound}; @@ -360,10 +362,12 @@ pub impl Parser { */ + let opt_abis = self.parse_opt_abis(); + let abis = opt_abis.get_or_default(AbiSet::Rust()); let purity = self.parse_purity(); self.expect_keyword(&~"fn"); return ty_bare_fn(@TyBareFn { - abi: RustAbi, + abis: abis, purity: purity, decl: self.parse_ty_fn_decl() }); @@ -3033,11 +3037,13 @@ pub impl Parser { span: mk_sp(lo, hi) } } - fn parse_item_fn(&self, purity: purity) -> item_info { + fn parse_item_fn(&self, purity: purity, abis: AbiSet) -> item_info { let (ident, generics) = self.parse_fn_header(); let decl = self.parse_fn_decl(|p| p.parse_arg()); let (inner_attrs, body) = self.parse_inner_attrs_and_block(true); - (ident, item_fn(decl, purity, generics, body), Some(inner_attrs)) + (ident, + item_fn(decl, purity, abis, generics, body), + Some(inner_attrs)) } fn parse_method(&self) -> @method { @@ -3608,7 +3614,7 @@ pub impl Parser { } fn parse_foreign_mod_items(&self, sort: ast::foreign_mod_sort, - +abi: ast::ident, + +abis: AbiSet, +first_item_attrs: ~[attribute]) -> foreign_mod { // Shouldn't be any view items since we've already parsed an item attr @@ -3631,30 +3637,20 @@ pub impl Parser { } ast::foreign_mod { sort: sort, - abi: abi, + abis: abis, view_items: view_items, items: items } } - fn parse_item_foreign_mod(&self, lo: BytePos, + fn parse_item_foreign_mod(&self, + lo: BytePos, + opt_abis: Option, visibility: visibility, attrs: ~[attribute], items_allowed: bool) - -> item_or_view_item { - - // Parse the ABI. - let abi_opt; - match *self.token { - token::LIT_STR(copy found_abi) => { - self.bump(); - abi_opt = Some(found_abi); - } - _ => { - abi_opt = None; - } - } - + -> item_or_view_item + { let mut must_be_named_mod = false; if self.is_keyword(&~"mod") { must_be_named_mod = true; @@ -3689,14 +3685,10 @@ pub impl Parser { // extern mod { ... } if items_allowed && self.eat(&token::LBRACE) { - let abi; - match abi_opt { - Some(found_abi) => abi = found_abi, - None => abi = special_idents::c_abi, - } + let abis = opt_abis.get_or_default(AbiSet::C()); let (inner, next) = self.parse_inner_attrs_and_next(); - let m = self.parse_foreign_mod_items(sort, abi, next); + let m = self.parse_foreign_mod_items(sort, abis, next); self.expect(&token::RBRACE); return iovi_item(self.mk_item(lo, self.last_span.hi, ident, @@ -3705,12 +3697,8 @@ pub impl Parser { Some(inner)))); } - match abi_opt { - None => {} // OK. - Some(_) => { - self.span_err(*self.span, ~"an ABI may not be specified \ - here"); - } + if opt_abis.is_some() { + self.span_err(*self.span, ~"an ABI may not be specified here"); } // extern mod foo; @@ -3935,6 +3923,48 @@ pub impl Parser { } } + fn parse_opt_abis(&self) -> Option { + match *self.token { + token::LIT_STR(s) => { + self.bump(); + let the_string = self.id_to_str(s); + let words = str::words(*the_string); + let mut abis = AbiSet::empty(); + for words.each |word| { + match abi::lookup(*word) { + Some(abi) => { + if abis.contains(abi) { + self.span_err( + *self.span, + fmt!("ABI `%s` appears twice", + *word)); + } else { + abis.add(abi); + } + } + + None => { + self.span_err( + *self.span, + fmt!("illegal ABI: \ + expected one of [%s], \ + found `%s`", + str::connect_slices( + abi::all_names(), + ", "), + *word)); + } + } + } + Some(abis) + } + + _ => { + None + } + } + } + // parse one of the items or view items allowed by the // flags; on failure, return iovi_none. fn parse_item_or_view_item( @@ -3983,7 +4013,8 @@ pub impl Parser { self.is_keyword(&~"fn") && !self.fn_expr_lookahead(self.look_ahead(1u)) { self.bump(); - let (ident, item_, extra_attrs) = self.parse_item_fn(impure_fn); + let (ident, item_, extra_attrs) = + self.parse_item_fn(impure_fn, AbiSet::Rust()); return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, visibility, maybe_append(attrs, extra_attrs))); @@ -3992,7 +4023,8 @@ pub impl Parser { // PURE FUNCTION ITEM self.obsolete(*self.last_span, ObsoletePurity); self.expect_keyword(&~"fn"); - let (ident, item_, extra_attrs) = self.parse_item_fn(impure_fn); + let (ident, item_, extra_attrs) = + self.parse_item_fn(impure_fn, AbiSet::Rust()); return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, visibility, maybe_append(attrs, extra_attrs))); @@ -4009,16 +4041,20 @@ pub impl Parser { // UNSAFE FUNCTION ITEM (where items are allowed) self.bump(); self.expect_keyword(&~"fn"); - let (ident, item_, extra_attrs) = self.parse_item_fn(unsafe_fn); + let (ident, item_, extra_attrs) = + self.parse_item_fn(unsafe_fn, AbiSet::Rust()); return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, visibility, maybe_append(attrs, extra_attrs))); } if self.eat_keyword(&~"extern") { + let opt_abis = self.parse_opt_abis(); + if items_allowed && self.eat_keyword(&~"fn") { // EXTERN FUNCTION ITEM + let abis = opt_abis.get_or_default(AbiSet::C()); let (ident, item_, extra_attrs) = - self.parse_item_fn(extern_fn); + self.parse_item_fn(extern_fn, abis); return iovi_item(self.mk_item(lo, self.last_span.hi, ident, item_, visibility, maybe_append(attrs, @@ -4026,7 +4062,7 @@ pub impl Parser { } if !foreign_items_allowed { // EXTERN MODULE ITEM - return self.parse_item_foreign_mod(lo, visibility, attrs, + return self.parse_item_foreign_mod(lo, opt_abis, visibility, attrs, items_allowed); } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index a8ff189fade64..7710030023162 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -10,6 +10,8 @@ use core::prelude::*; +use abi::AbiSet; +use abi; use ast::{RegionTyParamBound, TraitTyParamBound, required, provided}; use ast; use ast_util; @@ -185,7 +187,8 @@ pub fn fun_to_str(decl: &ast::fn_decl, 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, None, name, generics, opt_self_ty, ast::inherited); + print_fn(s, decl, None, AbiSet::Rust(), + name, generics, opt_self_ty, ast::inherited); end(s); // Close the head box end(s); // Close the outer box eof(s.s); @@ -402,7 +405,7 @@ pub fn print_type(s: @ps, &&ty: @ast::Ty) { pclose(s); } ast::ty_bare_fn(f) => { - 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, None, None); } @@ -441,7 +444,8 @@ 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, Some(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, ~";"); @@ -480,11 +484,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, Some(purity), + abi, item.ident, typarams, None, @@ -503,8 +508,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"); @@ -815,7 +819,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, Some(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, ~" "); @@ -1664,12 +1668,13 @@ pub fn print_self_ty(s: @ps, self_ty: ast::self_ty_) -> bool { pub fn print_fn(s: @ps, decl: &ast::fn_decl, purity: Option, + abis: AbiSet, name: ast::ident, generics: &ast::Generics, opt_self_ty: Option, vis: ast::visibility) { head(s, ~""); - print_fn_header_info(s, opt_self_ty, 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); @@ -1918,7 +1923,7 @@ pub fn print_arg(s: @ps, input: ast::arg) { } pub fn print_ty_fn(s: @ps, - opt_abi: Option, + opt_abis: Option, opt_sigil: Option, opt_region: Option<@ast::Lifetime>, purity: ast::purity, @@ -1930,7 +1935,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); @@ -2168,9 +2173,12 @@ pub fn print_opt_purity(s: @ps, opt_purity: Option) { } } -pub fn print_opt_abi(s: @ps, opt_abi: Option) { - match opt_abi { - Some(ast::RustAbi) => { word_nbsp(s, ~"extern"); } +pub fn print_extern_opt_abis(s: @ps, opt_abis: Option) { + match opt_abis { + Some(abis) => { + word_nbsp(s, ~"extern"); + word_nbsp(s, abis.to_str()); + } None => {} }; } @@ -2187,11 +2195,23 @@ pub fn print_opt_sigil(s: @ps, opt_sigil: Option) { pub fn print_fn_header_info(s: @ps, opt_sty: Option, opt_purity: Option, + abis: AbiSet, onceness: ast::Onceness, opt_sigil: Option, vis: ast::visibility) { word(s.s, visibility_qualified(vis, ~"")); - print_opt_purity(s, opt_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); diff --git a/src/libsyntax/syntax.rc b/src/libsyntax/syntax.rc index 19ed68093267a..c7ad7ce08fa82 100644 --- a/src/libsyntax/syntax.rc +++ b/src/libsyntax/syntax.rc @@ -39,6 +39,7 @@ pub mod opt_vec; pub mod attr; pub mod diagnostic; pub mod codemap; +pub mod abi; pub mod ast; pub mod ast_util; pub mod ast_map; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index a159c98d21b27..155fdd264a73b 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -10,6 +10,7 @@ use core::prelude::*; +use abi::AbiSet; use ast::*; use ast; use ast_util; @@ -29,10 +30,18 @@ use opt_vec::OptVec; pub enum vt { mk_vt(visitor), } pub enum fn_kind<'self> { - fk_item_fn(ident, &'self Generics, purity), // fn foo() - fk_method(ident, &'self Generics, &'self method), // fn foo(&self) - fk_anon(ast::Sigil), // fn@(x, y) { ... } - fk_fn_block, // |x, y| ... + // fn foo() or extern "Abi" fn foo() + fk_item_fn(ident, &'self Generics, purity, AbiSet), + + // fn foo(&self) + fk_method(ident, &'self Generics, &'self method), + + // fn@(x, y) { ... } + fk_anon(ast::Sigil), + + // |x, y| ... + fk_fn_block, + fk_dtor( // class destructor &'self Generics, &'self [attribute], @@ -43,8 +52,8 @@ pub enum fn_kind<'self> { pub fn name_of_fn(fk: &fn_kind) -> ident { match *fk { - fk_item_fn(name, _, _) | fk_method(name, _, _) => { - /* FIXME (#2543) */ copy name + fk_item_fn(name, _, _, _) | fk_method(name, _, _) => { + name } fk_anon(*) | fk_fn_block(*) => parse::token::special_idents::anon, fk_dtor(*) => parse::token::special_idents::dtor @@ -53,7 +62,7 @@ pub fn name_of_fn(fk: &fn_kind) -> ident { pub fn generics_of_fn(fk: &fn_kind) -> Generics { match *fk { - fk_item_fn(_, generics, _) | + fk_item_fn(_, generics, _, _) | fk_method(_, generics, _) | fk_dtor(generics, _, _, _) => { copy *generics @@ -144,12 +153,13 @@ pub fn visit_item(i: @item, e: E, v: vt) { (v.visit_ty)(t, e, v); (v.visit_expr)(ex, e, v); } - item_fn(ref decl, purity, ref generics, ref body) => { + item_fn(ref decl, purity, abi, ref generics, ref body) => { (v.visit_fn)( &fk_item_fn( - /* FIXME (#2543) */ copy i.ident, + i.ident, generics, - purity + purity, + abi ), decl, body, diff --git a/src/test/auxiliary/cci_intrinsic.rs b/src/test/auxiliary/cci_intrinsic.rs index d8c97218d6fed..e98fc4aac0a93 100644 --- a/src/test/auxiliary/cci_intrinsic.rs +++ b/src/test/auxiliary/cci_intrinsic.rs @@ -10,7 +10,7 @@ pub mod rusti { #[abi = "rust-intrinsic"] - pub extern { + pub extern "rust-intrinsic" { fn atomic_cxchg(dst: &mut int, old: int, src: int) -> int; fn atomic_cxchg_acq(dst: &mut int, old: int, src: int) -> int; fn atomic_cxchg_rel(dst: &mut int, old: int, src: int) -> int; @@ -18,11 +18,11 @@ pub mod rusti { fn atomic_xchg(dst: &mut int, src: int) -> int; fn atomic_xchg_acq(dst: &mut int, src: int) -> int; fn atomic_xchg_rel(dst: &mut int, src: int) -> int; - + fn atomic_xadd(dst: &mut int, src: int) -> int; fn atomic_xadd_acq(dst: &mut int, src: int) -> int; fn atomic_xadd_rel(dst: &mut int, src: int) -> int; - + fn atomic_xsub(dst: &mut int, src: int) -> int; fn atomic_xsub_acq(dst: &mut int, src: int) -> int; fn atomic_xsub_rel(dst: &mut int, src: int) -> int; diff --git a/src/test/compile-fail/block-coerce-no-2.rs b/src/test/compile-fail/block-coerce-no-2.rs index 95ff995258fad..85ef09cc2a631 100644 --- a/src/test/compile-fail/block-coerce-no-2.rs +++ b/src/test/compile-fail/block-coerce-no-2.rs @@ -19,5 +19,5 @@ fn main() { } f(g); - //~^ ERROR mismatched types: expected `extern fn(extern fn(extern fn()))` + //~^ ERROR mismatched types: expected `extern "Rust" fn(extern "Rust" fn(extern "Rust" fn()))` } diff --git a/src/test/compile-fail/main-wrong-type-2.rs b/src/test/compile-fail/main-wrong-type-2.rs index bb6633ecdc1fd..136cc2b8680bc 100644 --- a/src/test/compile-fail/main-wrong-type-2.rs +++ b/src/test/compile-fail/main-wrong-type-2.rs @@ -9,5 +9,5 @@ // except according to those terms. fn main() -> char { -//~^ ERROR Wrong type in main function: found `extern fn() -> char` +//~^ ERROR Wrong type in main function: found `extern "Rust" fn() -> char` } diff --git a/src/test/compile-fail/main-wrong-type.rs b/src/test/compile-fail/main-wrong-type.rs index cdd3b19f0ae37..f3ecac3f406bd 100644 --- a/src/test/compile-fail/main-wrong-type.rs +++ b/src/test/compile-fail/main-wrong-type.rs @@ -14,5 +14,5 @@ struct S { } fn main(foo: S) { -//~^ ERROR Wrong type in main function: found `extern fn(S)` +//~^ ERROR Wrong type in main function: found `extern "Rust" fn(S)` } diff --git a/src/test/compile-fail/missing-do.rs b/src/test/compile-fail/missing-do.rs index 974f30feb0651..b5789d737716b 100644 --- a/src/test/compile-fail/missing-do.rs +++ b/src/test/compile-fail/missing-do.rs @@ -14,6 +14,6 @@ fn foo(f: &fn()) { f() } fn main() { ~"" || 42; //~ ERROR binary operation || cannot be applied to type `~str` - foo || {}; //~ ERROR binary operation || cannot be applied to type `extern fn(&fn())` + foo || {}; //~ ERROR binary operation || cannot be applied to type `extern "Rust" fn(&fn())` //~^ NOTE did you forget the `do` keyword for the call? } diff --git a/src/test/pretty/fn-types.rs b/src/test/pretty/fn-types.rs index 7470151e46cf9..b1f7828a2f425 100644 --- a/src/test/pretty/fn-types.rs +++ b/src/test/pretty/fn-types.rs @@ -10,7 +10,7 @@ // pp-exact -fn from_foreign_fn(x: extern fn()) { } +fn from_foreign_fn(x: extern "Rust" fn()) { } fn from_stack_closure(x: &fn()) { } fn from_box_closure(x: @fn()) { } fn from_unique_closure(x: ~fn()) { } diff --git a/src/test/run-pass/intrinsic-alignment.rs b/src/test/run-pass/intrinsic-alignment.rs index 5d25dafdd0618..6b0496a93b0ab 100644 --- a/src/test/run-pass/intrinsic-alignment.rs +++ b/src/test/run-pass/intrinsic-alignment.rs @@ -12,7 +12,7 @@ mod rusti { #[abi = "rust-intrinsic"] - pub extern { + pub extern "rust-intrinsic" { pub fn pref_align_of() -> uint; pub fn min_align_of() -> uint; } diff --git a/src/test/run-pass/intrinsic-atomics.rs b/src/test/run-pass/intrinsic-atomics.rs index 4e571f90602b5..8105f180ea782 100644 --- a/src/test/run-pass/intrinsic-atomics.rs +++ b/src/test/run-pass/intrinsic-atomics.rs @@ -10,7 +10,7 @@ mod rusti { #[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; @@ -18,11 +18,11 @@ mod rusti { pub fn atomic_xchg(dst: &mut int, src: int) -> int; pub fn atomic_xchg_acq(dst: &mut int, src: int) -> int; pub fn atomic_xchg_rel(dst: &mut int, src: int) -> int; - + pub fn atomic_xadd(dst: &mut int, src: int) -> int; pub fn atomic_xadd_acq(dst: &mut int, src: int) -> int; pub fn atomic_xadd_rel(dst: &mut int, src: int) -> int; - + pub fn atomic_xsub(dst: &mut int, src: int) -> int; pub fn atomic_xsub_acq(dst: &mut int, src: int) -> int; pub fn atomic_xsub_rel(dst: &mut int, src: int) -> int; diff --git a/src/test/run-pass/intrinsic-frame-address.rs b/src/test/run-pass/intrinsic-frame-address.rs index 6c25291c48db1..e49aee8d3f543 100644 --- a/src/test/run-pass/intrinsic-frame-address.rs +++ b/src/test/run-pass/intrinsic-frame-address.rs @@ -13,7 +13,7 @@ mod rusti { #[abi = "rust-intrinsic"] - pub extern { + pub extern "rust-intrinsic" { pub fn frame_address(f: &once fn(*u8)); } } diff --git a/src/test/run-pass/intrinsic-move-val.rs b/src/test/run-pass/intrinsic-move-val.rs index 7544c89197bab..7237e286fd1a5 100644 --- a/src/test/run-pass/intrinsic-move-val.rs +++ b/src/test/run-pass/intrinsic-move-val.rs @@ -10,7 +10,7 @@ mod rusti { #[abi = "rust-intrinsic"] - pub extern { + pub extern "rust-intrinsic" { pub fn move_val_init(dst: &mut T, +src: T); pub fn move_val(dst: &mut T, +src: T); } diff --git a/src/test/run-pass/intrinsics-integer.rs b/src/test/run-pass/intrinsics-integer.rs index 8731b812f4a54..c33a874862c58 100644 --- a/src/test/run-pass/intrinsics-integer.rs +++ b/src/test/run-pass/intrinsics-integer.rs @@ -13,8 +13,8 @@ extern mod std; mod rusti { - #[abi = "rust-intrinsic"] - pub extern { + #[abi = "rust-intrinsic"] + pub extern "rust-intrinsic" { fn ctpop8(x: i8) -> i8; fn ctpop16(x: i16) -> i16; fn ctpop32(x: i32) -> i32; diff --git a/src/test/run-pass/intrinsics-math.rs b/src/test/run-pass/intrinsics-math.rs index b0db48057b19d..9c2805ecde866 100644 --- a/src/test/run-pass/intrinsics-math.rs +++ b/src/test/run-pass/intrinsics-math.rs @@ -15,8 +15,8 @@ extern mod std; use std::cmp::FuzzyEq; mod rusti { - #[abi = "rust-intrinsic"] - pub extern { + #[abi = "rust-intrinsic"] + pub extern "rust-intrinsic" { fn sqrtf32(x: f32) -> f32; fn sqrtf64(x: f64) -> f64; fn powif32(a: f32, x: i32) -> f32; diff --git a/src/test/run-pass/issue-2718.rs b/src/test/run-pass/issue-2718.rs index cc4f10ca347b4..1fd29babb8e84 100644 --- a/src/test/run-pass/issue-2718.rs +++ b/src/test/run-pass/issue-2718.rs @@ -45,7 +45,6 @@ pub mod pipes { } } - #[abi = "rust-intrinsic"] mod rusti { pub fn atomic_xchg(_dst: &mut int, _src: int) -> int { fail!(); } pub fn atomic_xchg_acq(_dst: &mut int, _src: int) -> int { fail!(); } diff --git a/src/test/run-pass/morestack-address.rs b/src/test/run-pass/morestack-address.rs index 9497ca83eccc0..cdb7f3bbaeb33 100644 --- a/src/test/run-pass/morestack-address.rs +++ b/src/test/run-pass/morestack-address.rs @@ -11,7 +11,7 @@ mod rusti { #[nolink] #[abi = "rust-intrinsic"] - pub extern { + pub extern "rust-intrinsic" { pub fn morestack_addr() -> *(); } } diff --git a/src/test/run-pass/rec-align-u32.rs b/src/test/run-pass/rec-align-u32.rs index e5a13fe9c540a..04bc70ce7ecd5 100644 --- a/src/test/run-pass/rec-align-u32.rs +++ b/src/test/run-pass/rec-align-u32.rs @@ -12,7 +12,7 @@ mod rusti { #[abi = "rust-intrinsic"] - pub extern { + pub extern "rust-intrinsic" { pub fn pref_align_of() -> uint; pub fn min_align_of() -> uint; } diff --git a/src/test/run-pass/rec-align-u64.rs b/src/test/run-pass/rec-align-u64.rs index e02a1edf8a62d..764efeae732be 100644 --- a/src/test/run-pass/rec-align-u64.rs +++ b/src/test/run-pass/rec-align-u64.rs @@ -12,7 +12,7 @@ mod rusti { #[abi = "rust-intrinsic"] - pub extern { + pub extern "rust-intrinsic" { pub fn pref_align_of() -> uint; pub fn min_align_of() -> uint; } diff --git a/src/test/run-pass/x86stdcall2.rs b/src/test/run-pass/x86stdcall2.rs index 672505f631518..4ab6c772c3689 100644 --- a/src/test/run-pass/x86stdcall2.rs +++ b/src/test/run-pass/x86stdcall2.rs @@ -19,7 +19,7 @@ mod kernel32 { #[cfg(target_os = "win32")] #[abi = "stdcall"] - pub extern { + pub extern "stdcall" { pub fn GetProcessHeap() -> HANDLE; pub fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID; From 9daf4410d93a537771ae6e96650d381524cd80be Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 25 Mar 2013 13:14:04 -0700 Subject: [PATCH 2/3] add debug printout --- src/librustc/metadata/loader.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 9c61205667750..8b4ddd3c983c0 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -218,6 +218,7 @@ fn get_metadata_section(os: os, let minsz = uint::min(vlen, csz); let mut version_ok = false; do vec::raw::buf_as_slice(cvbuf, minsz) |buf0| { + debug!("buf0=%?", buf0); version_ok = (buf0 == encoder::metadata_encoding_version); } From fc9bd5d47cf8983d6cd22f4d08ad20dec7ed88e9 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 25 Mar 2013 13:14:10 -0700 Subject: [PATCH 3/3] work around strange bug in const u8 slices --- src/librustc/metadata/encoder.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 39ab7bff5f116..cedf81999eb51 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1314,12 +1314,12 @@ fn encode_hash(ebml_w: writer::Encoder, hash: &str) { } // NB: Increment this as you change the metadata encoding version. -pub static metadata_encoding_version : &'static [u8] = - &[0x72, //'r' as u8, - 0x75, //'u' as u8, - 0x73, //'s' as u8, - 0x74, //'t' as u8, - 0, 0, 0, 1 ]; +pub static metadata_encoding_version : [u8 * 8] = + [0x72, //'r' as u8, + 0x75, //'u' as u8, + 0x73, //'s' as u8, + 0x74, //'t' as u8, + 0, 0, 0, 1 ]; pub fn encode_metadata(parms: EncodeParams, crate: &crate) -> ~[u8] { let wr = @io::BytesWriter();