]> git.lizzy.rs Git - rust.git/commitdiff
trans: Revamp and empower cabi::FnType.
authorEduard Burtescu <edy.burt@gmail.com>
Tue, 23 Feb 2016 19:55:19 +0000 (21:55 +0200)
committerEduard Burtescu <edy.burt@gmail.com>
Thu, 17 Mar 2016 16:19:50 +0000 (18:19 +0200)
12 files changed:
src/librustc_trans/trans/cabi.rs
src/librustc_trans/trans/cabi_aarch64.rs
src/librustc_trans/trans/cabi_arm.rs
src/librustc_trans/trans/cabi_asmjs.rs
src/librustc_trans/trans/cabi_mips.rs
src/librustc_trans/trans/cabi_powerpc.rs
src/librustc_trans/trans/cabi_powerpc64.rs
src/librustc_trans/trans/cabi_x86.rs
src/librustc_trans/trans/cabi_x86_64.rs
src/librustc_trans/trans/cabi_x86_win64.rs
src/librustc_trans/trans/foreign.rs
src/librustc_trans/trans/type_of.rs

index b2275171687fa6069546257f358605a992a8c9f3..5325c667eb683b3f0e0603a1c8ec2455e0eb4b37 100644 (file)
@@ -10,8 +10,9 @@
 
 pub use self::ArgKind::*;
 
-use llvm::Attribute;
-use std::option;
+use llvm::{self, AttrHelper, ValueRef};
+use trans::attributes;
+use trans::common::return_type_is_void;
 use trans::context::CrateContext;
 use trans::cabi_x86;
 use trans::cabi_x86_64;
 use trans::cabi_mips;
 use trans::cabi_asmjs;
 use trans::type_::Type;
+use trans::type_of;
+
+use middle::ty::{self, Ty};
+
+use syntax::abi::Abi;
 
 #[derive(Clone, Copy, PartialEq, Debug)]
 pub enum ArgKind {
@@ -45,17 +51,17 @@ pub struct ArgType {
     /// Original LLVM type
     pub ty: Type,
     /// Coerced LLVM Type
-    pub cast: option::Option<Type>,
+    pub cast: Option<Type>,
     /// Dummy argument, which is emitted before the real argument
-    pub pad: option::Option<Type>,
+    pub pad: Option<Type>,
     /// LLVM attribute of argument
-    pub attr: option::Option<Attribute>
+    pub attr: Option<llvm::Attribute>
 }
 
 impl ArgType {
-    pub fn direct(ty: Type, cast: option::Option<Type>,
-                            pad: option::Option<Type>,
-                            attr: option::Option<Attribute>) -> ArgType {
+    pub fn direct(ty: Type, cast: Option<Type>,
+                            pad: Option<Type>,
+                            attr: Option<llvm::Attribute>) -> ArgType {
         ArgType {
             kind: Direct,
             ty: ty,
@@ -65,12 +71,12 @@ pub fn direct(ty: Type, cast: option::Option<Type>,
         }
     }
 
-    pub fn indirect(ty: Type, attr: option::Option<Attribute>) -> ArgType {
+    pub fn indirect(ty: Type, attr: Option<llvm::Attribute>) -> ArgType {
         ArgType {
             kind: Indirect,
             ty: ty,
-            cast: option::Option::None,
-            pad: option::Option::None,
+            cast: Option::None,
+            pad: Option::None,
             attr: attr
         }
     }
@@ -94,6 +100,14 @@ pub fn is_ignore(&self) -> bool {
     }
 }
 
+fn c_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type {
+    if ty.is_bool() {
+        Type::i1(cx)
+    } else {
+        type_of::type_of(cx, ty)
+    }
+}
+
 /// Metadata describing how the arguments to a native function
 /// should be passed in order to respect the native ABI.
 ///
@@ -101,37 +115,160 @@ pub fn is_ignore(&self) -> bool {
 /// comments are reverse-engineered and may be inaccurate. -NDM
 pub struct FnType {
     /// The LLVM types of each argument.
-    pub arg_tys: Vec<ArgType> ,
+    pub args: Vec<ArgType>,
 
     /// LLVM return type.
-    pub ret_ty: ArgType,
+    pub ret: ArgType,
+
+    pub variadic: bool,
+
+    pub cconv: llvm::CallConv
 }
 
-pub fn compute_abi_info(ccx: &CrateContext,
-                        atys: &[Type],
-                        rty: Type,
-                        ret_def: bool) -> FnType {
-    match &ccx.sess().target.target.arch[..] {
-        "x86" => cabi_x86::compute_abi_info(ccx, atys, rty, ret_def),
-        "x86_64" => if ccx.sess().target.target.options.is_like_windows {
-            cabi_x86_win64::compute_abi_info(ccx, atys, rty, ret_def)
+impl FnType {
+    pub fn new<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                         abi: Abi,
+                         sig: &ty::FnSig<'tcx>,
+                         extra_args: &[Ty<'tcx>]) -> FnType {
+        use syntax::abi::Abi::*;
+        let cconv = match ccx.sess().target.target.adjust_abi(abi) {
+            RustIntrinsic => {
+                // Intrinsics are emitted at the call site
+                ccx.sess().bug("asked to register intrinsic fn");
+            }
+            PlatformIntrinsic => {
+                // Intrinsics are emitted at the call site
+                ccx.sess().bug("asked to register platform intrinsic fn");
+            }
+
+            Rust => {
+                // FIXME(#3678) Implement linking to foreign fns with Rust ABI
+                ccx.sess().unimpl("foreign functions with Rust ABI");
+            }
+
+            RustCall => {
+                // FIXME(#3678) Implement linking to foreign fns with Rust ABI
+                ccx.sess().unimpl("foreign functions with RustCall ABI");
+            }
+
+            // It's the ABI's job to select this, not us.
+            System => ccx.sess().bug("system abi should be selected elsewhere"),
+
+            Stdcall => llvm::X86StdcallCallConv,
+            Fastcall => llvm::X86FastcallCallConv,
+            Vectorcall => llvm::X86_VectorCall,
+            C => llvm::CCallConv,
+            Win64 => llvm::X86_64_Win64,
+
+            // These API constants ought to be more specific...
+            Cdecl => llvm::CCallConv,
+            Aapcs => llvm::CCallConv,
+        };
+
+        let rty = match sig.output {
+            ty::FnConverging(ret_ty) if !return_type_is_void(ccx, ret_ty) => {
+                c_type_of(ccx, ret_ty)
+            }
+            _ => Type::void(ccx)
+        };
+
+        let mut fty = FnType {
+            args: sig.inputs.iter().chain(extra_args.iter()).map(|&ty| {
+                ArgType::direct(c_type_of(ccx, ty), None, None, None)
+            }).collect(),
+            ret: ArgType::direct(rty, None, None, None),
+            variadic: sig.variadic,
+            cconv: cconv
+        };
+
+        match &ccx.sess().target.target.arch[..] {
+            "x86" => cabi_x86::compute_abi_info(ccx, &mut fty),
+            "x86_64" => if ccx.sess().target.target.options.is_like_windows {
+                cabi_x86_win64::compute_abi_info(ccx, &mut fty);
+            } else {
+                cabi_x86_64::compute_abi_info(ccx, &mut fty);
+            },
+            "aarch64" => cabi_aarch64::compute_abi_info(ccx, &mut fty),
+            "arm" => {
+                let flavor = if ccx.sess().target.target.target_os == "ios" {
+                    cabi_arm::Flavor::Ios
+                } else {
+                    cabi_arm::Flavor::General
+                };
+                cabi_arm::compute_abi_info(ccx, &mut fty, flavor);
+            },
+            "mips" => cabi_mips::compute_abi_info(ccx, &mut fty),
+            "powerpc" => cabi_powerpc::compute_abi_info(ccx, &mut fty),
+            "powerpc64" => cabi_powerpc64::compute_abi_info(ccx, &mut fty),
+            "asmjs" => cabi_asmjs::compute_abi_info(ccx, &mut fty),
+            a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a))
+        }
+
+        fty
+    }
+
+    pub fn to_llvm(&self, ccx: &CrateContext) -> Type {
+        let mut llargument_tys = Vec::new();
+
+        let llreturn_ty = if self.ret.is_indirect() {
+            llargument_tys.push(self.ret.ty.ptr_to());
+            Type::void(ccx)
         } else {
-            cabi_x86_64::compute_abi_info(ccx, atys, rty, ret_def)
-        },
-        "aarch64" => cabi_aarch64::compute_abi_info(ccx, atys, rty, ret_def),
-        "arm" => {
-            let flavor = if ccx.sess().target.target.target_os == "ios" {
-                cabi_arm::Flavor::Ios
+            self.ret.cast.unwrap_or(self.ret.ty)
+        };
+
+        for arg in &self.args {
+            if arg.is_ignore() {
+                continue;
+            }
+            // add padding
+            if let Some(ty) = arg.pad {
+                llargument_tys.push(ty);
+            }
+
+            let llarg_ty = if arg.is_indirect() {
+                arg.ty.ptr_to()
             } else {
-                cabi_arm::Flavor::General
+                arg.cast.unwrap_or(arg.ty)
             };
-            cabi_arm::compute_abi_info(ccx, atys, rty, ret_def, flavor)
-        },
-        "mips" => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def),
-        "powerpc" => cabi_powerpc::compute_abi_info(ccx, atys, rty, ret_def),
-        "powerpc64" => cabi_powerpc64::compute_abi_info(ccx, atys, rty, ret_def),
-        "asmjs" => cabi_asmjs::compute_abi_info(ccx, atys, rty, ret_def),
-        a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a)
-                              ),
+
+            llargument_tys.push(llarg_ty);
+        }
+
+        if self.variadic {
+            Type::variadic_func(&llargument_tys, &llreturn_ty)
+        } else {
+            Type::func(&llargument_tys, &llreturn_ty)
+        }
+    }
+
+    pub fn add_attributes(&self, llfn: ValueRef) {
+        let mut i = if self.ret.is_indirect() {
+            1
+        } else {
+            0
+        };
+
+        if let Some(attr) = self.ret.attr {
+            attr.apply_llfn(i, llfn);
+        }
+
+        i += 1;
+
+        for arg in &self.args {
+            if arg.is_ignore() {
+                continue;
+            }
+            // skip padding
+            if arg.pad.is_some() { i += 1; }
+
+            if let Some(attr) = arg.attr {
+                attr.apply_llfn(i, llfn);
+            }
+
+            i += 1;
+        }
+
+        attributes::unwind(llfn, false);
     }
 }
index f2434ceee2b857ee5e5fd09c3bf6037c4a55ccd3..745cc3ba6d6f55c9ca93d5913382695a4decc7f4 100644 (file)
@@ -228,24 +228,12 @@ fn is_reg_ty(ty: Type) -> bool {
     }
 }
 
-pub fn compute_abi_info(ccx: &CrateContext,
-                        atys: &[Type],
-                        rty: Type,
-                        ret_def: bool) -> FnType {
-    let mut arg_tys = Vec::new();
-    for &aty in atys {
-        let ty = classify_arg_ty(ccx, aty);
-        arg_tys.push(ty);
+pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
+    if fty.ret.ty != Type::void(ccx) {
+        fty.ret = classify_ret_ty(ccx, fty.ret.ty);
     }
 
-    let ret_ty = if ret_def {
-        classify_ret_ty(ccx, rty)
-    } else {
-        ArgType::direct(Type::void(ccx), None, None, None)
-    };
-
-    return FnType {
-        arg_tys: arg_tys,
-        ret_ty: ret_ty,
-    };
+    for arg in &mut fty.args {
+        *arg = classify_arg_ty(ccx, arg.ty);
+    }
 }
index c5116e738048d1f3341a034cbcd1d7f7f61679d8..c65fb588e7218d2572b3e040c747bfaac3051a06 100644 (file)
@@ -174,30 +174,17 @@ fn is_reg_ty(ty: Type) -> bool {
     }
 }
 
-pub fn compute_abi_info(ccx: &CrateContext,
-                        atys: &[Type],
-                        rty: Type,
-                        ret_def: bool,
-                        flavor: Flavor) -> FnType {
+pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType, flavor: Flavor) {
     let align_fn = match flavor {
         Flavor::General => general_ty_align as TyAlignFn,
         Flavor::Ios => ios_ty_align as TyAlignFn,
     };
 
-    let mut arg_tys = Vec::new();
-    for &aty in atys {
-        let ty = classify_arg_ty(ccx, aty, align_fn);
-        arg_tys.push(ty);
+    if fty.ret.ty != Type::void(ccx) {
+        fty.ret = classify_ret_ty(ccx, fty.ret.ty, align_fn);
     }
 
-    let ret_ty = if ret_def {
-        classify_ret_ty(ccx, rty, align_fn)
-    } else {
-        ArgType::direct(Type::void(ccx), None, None, None)
-    };
-
-    return FnType {
-        arg_tys: arg_tys,
-        ret_ty: ret_ty,
-    };
+    for arg in &mut fty.args {
+        *arg = classify_arg_ty(ccx, arg.ty, align_fn);
+    }
 }
index 3a4a6b9960e9cea6bd62cb3260b08423def164b6..dd62194a892a70888d7fdb5b5cc88aa4f33f8e83 100644 (file)
@@ -49,24 +49,12 @@ fn classify_arg_ty(ccx: &CrateContext, ty: Type) -> ArgType {
     }
 }
 
-pub fn compute_abi_info(ccx: &CrateContext,
-                        atys: &[Type],
-                        rty: Type,
-                        ret_def: bool) -> FnType {
-    let mut arg_tys = Vec::new();
-    for &aty in atys {
-        let ty = classify_arg_ty(ccx, aty);
-        arg_tys.push(ty);
+pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
+    if fty.ret.ty != Type::void(ccx) {
+        fty.ret = classify_ret_ty(ccx, fty.ret.ty);
     }
 
-    let ret_ty = if ret_def {
-        classify_ret_ty(ccx, rty)
-    } else {
-        ArgType::direct(Type::void(ccx), None, None, None)
-    };
-
-    return FnType {
-        arg_tys: arg_tys,
-        ret_ty: ret_ty,
-    };
+    for arg in &mut fty.args {
+        *arg = classify_arg_ty(ccx, arg.ty);
+    }
 }
index bcffb238f5950c6d1251402a9b63f941dc635152..74fdc0828f203fa93a185bd4993ae692284bdccb 100644 (file)
@@ -161,27 +161,13 @@ fn struct_ty(ccx: &CrateContext, ty: Type) -> Type {
     Type::struct_(ccx, &coerce_to_int(ccx, size), false)
 }
 
-pub fn compute_abi_info(ccx: &CrateContext,
-                        atys: &[Type],
-                        rty: Type,
-                        ret_def: bool) -> FnType {
-    let ret_ty = if ret_def {
-        classify_ret_ty(ccx, rty)
-    } else {
-        ArgType::direct(Type::void(ccx), None, None, None)
-    };
-
-    let sret = ret_ty.is_indirect();
-    let mut arg_tys = Vec::new();
-    let mut offset = if sret { 4 } else { 0 };
-
-    for aty in atys {
-        let ty = classify_arg_ty(ccx, *aty, &mut offset);
-        arg_tys.push(ty);
-    };
+pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
+    if fty.ret.ty != Type::void(ccx) {
+        fty.ret = classify_ret_ty(ccx, fty.ret.ty);
+    }
 
-    return FnType {
-        arg_tys: arg_tys,
-        ret_ty: ret_ty,
-    };
+    let mut offset = if fty.ret.is_indirect() { 4 } else { 0 };
+    for arg in &mut fty.args {
+        *arg = classify_arg_ty(ccx, arg.ty, &mut offset);
+    }
 }
index 1bcc8fd6bbb90e5133e416bf7712022e1b56d8c6..57d49926fae5d2fc8f8edfd1b88c33a5c853e666 100644 (file)
@@ -156,27 +156,13 @@ fn struct_ty(ccx: &CrateContext, ty: Type) -> Type {
     Type::struct_(ccx, &coerce_to_int(ccx, size), false)
 }
 
-pub fn compute_abi_info(ccx: &CrateContext,
-                        atys: &[Type],
-                        rty: Type,
-                        ret_def: bool) -> FnType {
-    let ret_ty = if ret_def {
-        classify_ret_ty(ccx, rty)
-    } else {
-        ArgType::direct(Type::void(ccx), None, None, None)
-    };
-
-    let sret = ret_ty.is_indirect();
-    let mut arg_tys = Vec::new();
-    let mut offset = if sret { 4 } else { 0 };
-
-    for aty in atys {
-        let ty = classify_arg_ty(ccx, *aty, &mut offset);
-        arg_tys.push(ty);
-    };
+pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
+    if fty.ret.ty != Type::void(ccx) {
+        fty.ret = classify_ret_ty(ccx, fty.ret.ty);
+    }
 
-    return FnType {
-        arg_tys: arg_tys,
-        ret_ty: ret_ty,
-    };
+    let mut offset = if fty.ret.is_indirect() { 4 } else { 0 };
+    for arg in &mut fty.args {
+        *arg = classify_arg_ty(ccx, arg.ty, &mut offset);
+    }
 }
index f76bb4f9eebc6596c2d5402130759e8ad283b096..dd50b1164517d206c614f8c0871f716ddb03d970 100644 (file)
@@ -236,24 +236,12 @@ fn struct_ty(ccx: &CrateContext, ty: Type) -> Type {
     Type::struct_(ccx, &coerce_to_long(ccx, size), false)
 }
 
-pub fn compute_abi_info(ccx: &CrateContext,
-                        atys: &[Type],
-                        rty: Type,
-                        ret_def: bool) -> FnType {
-    let ret_ty = if ret_def {
-        classify_ret_ty(ccx, rty)
-    } else {
-        ArgType::direct(Type::void(ccx), None, None, None)
-    };
-
-    let mut arg_tys = Vec::new();
-    for &aty in atys {
-        let ty = classify_arg_ty(ccx, aty);
-        arg_tys.push(ty);
-    };
+pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
+    if fty.ret.ty != Type::void(ccx) {
+        fty.ret = classify_ret_ty(ccx, fty.ret.ty);
+    }
 
-    return FnType {
-        arg_tys: arg_tys,
-        ret_ty: ret_ty,
-    };
+    for arg in &mut fty.args {
+        *arg = classify_arg_ty(ccx, arg.ty);
+    }
 }
index 50a3095dea16970d43c4b350255728c10e2897b4..81fb9d71210d861cbaaa4d1dd07705ff8572db86 100644 (file)
@@ -8,24 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use self::Strategy::*;
 use llvm::*;
 use trans::cabi::{ArgType, FnType};
 use trans::type_::Type;
 use super::common::*;
 use super::machine::*;
 
-enum Strategy { RetValue(Type), RetPointer }
-pub fn compute_abi_info(ccx: &CrateContext,
-                        atys: &[Type],
-                        rty: Type,
-                        ret_def: bool) -> FnType {
-    let mut arg_tys = Vec::new();
-
-    let ret_ty;
-    if !ret_def {
-        ret_ty = ArgType::direct(Type::void(ccx), None, None, None);
-    } else if rty.kind() == Struct {
+pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
+    if fty.ret.ty.kind() == Struct {
         // Returning a structure. Most often, this will use
         // a hidden first argument. On some platforms, though,
         // small structs are returned as integers.
@@ -33,53 +23,33 @@ pub fn compute_abi_info(ccx: &CrateContext,
         // Some links:
         // http://www.angelcode.com/dev/callconv/callconv.html
         // Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp
+        let indirect = ArgType::indirect(fty.ret.ty, Some(Attribute::StructRet));
 
         let t = &ccx.sess().target.target;
-        let strategy = if t.options.is_like_osx || t.options.is_like_windows {
-            match llsize_of_alloc(ccx, rty) {
-                1 => RetValue(Type::i8(ccx)),
-                2 => RetValue(Type::i16(ccx)),
-                4 => RetValue(Type::i32(ccx)),
-                8 => RetValue(Type::i64(ccx)),
-                _ => RetPointer
+        if t.options.is_like_osx || t.options.is_like_windows {
+            match llsize_of_alloc(ccx, fty.ret.ty) {
+                1 => fty.ret.cast = Some(Type::i8(ccx)),
+                2 => fty.ret.cast = Some(Type::i16(ccx)),
+                4 => fty.ret.cast = Some(Type::i32(ccx)),
+                8 => fty.ret.cast = Some(Type::i64(ccx)),
+                _ => fty.ret = indirect
             }
         } else {
-            RetPointer
-        };
-
-        match strategy {
-            RetValue(t) => {
-                ret_ty = ArgType::direct(rty, Some(t), None, None);
-            }
-            RetPointer => {
-                ret_ty = ArgType::indirect(rty, Some(Attribute::StructRet));
-            }
+            fty.ret = indirect;
         }
-    } else {
-        let attr = if rty == Type::i1(ccx) { Some(Attribute::ZExt) } else { None };
-        ret_ty = ArgType::direct(rty, None, None, attr);
+    } else if fty.ret.ty == Type::i1(ccx) {
+        fty.ret.attr = Some(Attribute::ZExt);
     }
 
-    for &t in atys {
-        let ty = match t.kind() {
-            Struct => {
-                let size = llsize_of_alloc(ccx, t);
-                if size == 0 {
-                    ArgType::ignore(t)
-                } else {
-                    ArgType::indirect(t, Some(Attribute::ByVal))
-                }
-            }
-            _ => {
-                let attr = if t == Type::i1(ccx) { Some(Attribute::ZExt) } else { None };
-                ArgType::direct(t, None, None, attr)
-            }
-        };
-        arg_tys.push(ty);
+    for arg in &mut fty.args {
+        if arg.ty.kind() == Struct {
+            *arg = if llsize_of_alloc(ccx, arg.ty) == 0 {
+                ArgType::ignore(arg.ty)
+            } else {
+                ArgType::indirect(arg.ty, Some(Attribute::ByVal))
+            };
+        } else if arg.ty == Type::i1(ccx) {
+            arg.attr = Some(Attribute::ZExt);
+        }
     }
-
-    return FnType {
-        arg_tys: arg_tys,
-        ret_ty: ret_ty,
-    };
 }
index 00d8fdad32de1814e9e7612b4d7651fe51b9e112..5946aa4a8c3668bfbae737eccd5a1d8f5d2785a3 100644 (file)
@@ -383,10 +383,7 @@ fn llvec_len(cls: &[RegClass]) -> usize {
     }
 }
 
-pub fn compute_abi_info(ccx: &CrateContext,
-                        atys: &[Type],
-                        rty: Type,
-                        ret_def: bool) -> FnType {
+pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
     fn x86_64_ty<F>(ccx: &CrateContext,
                     ty: Type,
                     is_mem_cls: F,
@@ -413,8 +410,8 @@ fn x86_64_ty<F>(ccx: &CrateContext,
     let mut int_regs = 6; // RDI, RSI, RDX, RCX, R8, R9
     let mut sse_regs = 8; // XMM0-7
 
-    let ret_ty = if ret_def {
-        x86_64_ty(ccx, rty, |cls| {
+    if fty.ret.ty != Type::void(ccx) {
+        fty.ret = x86_64_ty(ccx, fty.ret.ty, |cls| {
             if cls.is_ret_bysret() {
                 // `sret` parameter thus one less register available
                 int_regs -= 1;
@@ -422,14 +419,11 @@ fn x86_64_ty<F>(ccx: &CrateContext,
             } else {
                 false
             }
-        }, Attribute::StructRet)
-    } else {
-        ArgType::direct(Type::void(ccx), None, None, None)
-    };
+        }, Attribute::StructRet);
+    }
 
-    let mut arg_tys = Vec::new();
-    for t in atys {
-        let ty = x86_64_ty(ccx, *t, |cls| {
+    for arg in &mut fty.args {
+        *arg = x86_64_ty(ccx, arg.ty, |cls| {
             let needed_int = cls.iter().filter(|&&c| c == Int).count() as isize;
             let needed_sse = cls.iter().filter(|c| c.is_sse()).count() as isize;
             let in_mem = cls.is_pass_byval() ||
@@ -445,20 +439,14 @@ fn x86_64_ty<F>(ccx: &CrateContext,
             }
             in_mem
         }, Attribute::ByVal);
-        arg_tys.push(ty);
 
         // An integer, pointer, double or float parameter
         // thus the above closure passed to `x86_64_ty` won't
         // get called.
-        if t.kind() == Integer || t.kind() == Pointer {
-            int_regs -= 1;
-        } else if t.kind() == Double || t.kind() == Float {
-            sse_regs -= 1;
+        match arg.ty.kind() {
+            Integer | Pointer => int_regs -= 1,
+            Double | Float => sse_regs -= 1,
+            _ => {}
         }
     }
-
-    return FnType {
-        arg_tys: arg_tys,
-        ret_ty: ret_ty,
-    };
 }
index 120c8dc0384cef59da2c947aa50b500cc866f46a..21c746a1e88967729b904e084223727317dc70f7 100644 (file)
 
 // Win64 ABI: http://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
 
-pub fn compute_abi_info(ccx: &CrateContext,
-                          atys: &[Type],
-                          rty: Type,
-                          ret_def: bool) -> FnType {
-    let mut arg_tys = Vec::new();
-
-    let ret_ty;
-    if !ret_def {
-        ret_ty = ArgType::direct(Type::void(ccx), None, None, None);
-    } else if rty.kind() == Struct {
-        ret_ty = match llsize_of_alloc(ccx, rty) {
-            1 => ArgType::direct(rty, Some(Type::i8(ccx)), None, None),
-            2 => ArgType::direct(rty, Some(Type::i16(ccx)), None, None),
-            4 => ArgType::direct(rty, Some(Type::i32(ccx)), None, None),
-            8 => ArgType::direct(rty, Some(Type::i64(ccx)), None, None),
-            _ => ArgType::indirect(rty, Some(Attribute::StructRet))
-        };
-    } else {
-        let attr = if rty == Type::i1(ccx) { Some(Attribute::ZExt) } else { None };
-        ret_ty = ArgType::direct(rty, None, None, attr);
-    }
-
-    for &t in atys {
-        let ty = match t.kind() {
-            Struct => {
-                match llsize_of_alloc(ccx, t) {
-                    1 => ArgType::direct(t, Some(Type::i8(ccx)), None, None),
-                    2 => ArgType::direct(t, Some(Type::i16(ccx)), None, None),
-                    4 => ArgType::direct(t, Some(Type::i32(ccx)), None, None),
-                    8 => ArgType::direct(t, Some(Type::i64(ccx)), None, None),
-                    _ => ArgType::indirect(t, None)
-                }
-            }
-            _ => {
-                let attr = if t == Type::i1(ccx) { Some(Attribute::ZExt) } else { None };
-                ArgType::direct(t, None, None, attr)
+pub fn compute_abi_info(ccx: &CrateContext, fty: &mut FnType) {
+    let fixup = |a: &mut ArgType, indirect_attr| {
+        if a.ty.kind() == Struct {
+            match llsize_of_alloc(ccx, a.ty) {
+                1 => a.cast = Some(Type::i8(ccx)),
+                2 => a.cast = Some(Type::i16(ccx)),
+                4 => a.cast = Some(Type::i32(ccx)),
+                8 => a.cast = Some(Type::i64(ccx)),
+                _ => *a = ArgType::indirect(a.ty, indirect_attr)
             }
-        };
-        arg_tys.push(ty);
-    }
-
-    return FnType {
-        arg_tys: arg_tys,
-        ret_ty: ret_ty,
+        } else if a.ty == Type::i1(ccx) {
+            a.attr = Some(Attribute::ZExt);
+        }
     };
+
+    fixup(&mut fty.ret, Some(Attribute::StructRet));
+    for arg in &mut fty.args {
+        fixup(arg, None);
+    }
 }
index 592cb50930a5cd83824ba6dbd81a9c5f5f8d4dc3..99df9c181856c7103111e7f03f352c4f685460a1 100644 (file)
@@ -17,7 +17,7 @@
 use trans::base::{llvm_linkage_by_name, push_ctxt};
 use trans::base;
 use trans::build::*;
-use trans::cabi;
+use trans::cabi::FnType;
 use trans::common::*;
 use trans::debuginfo::DebugLoc;
 use trans::declare;
 use rustc_front::print::pprust;
 use rustc_front::hir;
 
-///////////////////////////////////////////////////////////////////////////
-// Type definitions
-
-struct ForeignTypes<'tcx> {
-    /// Rust signature of the function
-    fn_sig: ty::FnSig<'tcx>,
-
-    /// Adapter object for handling native ABI rules (trust me, you
-    /// don't want to know)
-    fn_ty: cabi::FnType,
-
-    /// LLVM types that will appear on the foreign function
-    llsig: LlvmSignature,
-}
-
-struct LlvmSignature {
-    // LLVM versions of the types of this function's arguments.
-    llarg_tys: Vec<Type> ,
-
-    // LLVM version of the type that this function returns.  Note that
-    // this *may not be* the declared return type of the foreign
-    // function, because the foreign function may opt to return via an
-    // out pointer.
-    llret_ty: Type,
-
-    /// True if there is a return value (not bottom, not unit)
-    ret_def: bool,
-}
-
-
 ///////////////////////////////////////////////////////////////////////////
 // Calls to external functions
 
-pub fn llvm_calling_convention(ccx: &CrateContext,
-                               abi: Abi) -> CallConv {
-    use syntax::abi::Abi::*;
-    match ccx.sess().target.target.adjust_abi(abi) {
-        RustIntrinsic => {
-            // Intrinsics are emitted at the call site
-            ccx.sess().bug("asked to register intrinsic fn");
-        }
-        PlatformIntrinsic => {
-            // Intrinsics are emitted at the call site
-            ccx.sess().bug("asked to register platform intrinsic fn");
-        }
-
-        Rust => {
-            // FIXME(#3678) Implement linking to foreign fns with Rust ABI
-            ccx.sess().unimpl("foreign functions with Rust ABI");
-        }
-
-        RustCall => {
-            // FIXME(#3678) Implement linking to foreign fns with Rust ABI
-            ccx.sess().unimpl("foreign functions with RustCall ABI");
-        }
-
-        // It's the ABI's job to select this, not us.
-        System => ccx.sess().bug("system abi should be selected elsewhere"),
-
-        Stdcall => llvm::X86StdcallCallConv,
-        Fastcall => llvm::X86FastcallCallConv,
-        Vectorcall => llvm::X86_VectorCall,
-        C => llvm::CCallConv,
-        Win64 => llvm::X86_64_Win64,
-
-        // These API constants ought to be more specific...
-        Cdecl => llvm::CCallConv,
-        Aapcs => llvm::CCallConv,
-    }
-}
-
 pub fn register_static(ccx: &CrateContext,
                        foreign_item: &hir::ForeignItem) -> ValueRef {
     let ty = ccx.tcx().node_id_to_type(foreign_item.id);
     let llty = type_of::type_of(ccx, ty);
 
-    let ident = link_name(foreign_item);
+    let ident = link_name(foreign_item.name, &foreign_item.attrs);
     let c = match attr::first_attr_value_str_by_name(&foreign_item.attrs,
                                                      "linkage") {
         // If this is a static with a linkage specified, then we need to handle
@@ -265,13 +197,9 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     };
     let fn_sig = ccx.tcx().erase_late_bound_regions(fn_sig);
     let fn_sig = infer::normalize_associated_type(ccx.tcx(), &fn_sig);
-    let llsig = foreign_signature(ccx, &fn_sig, &passed_arg_tys[..]);
-    let fn_type = cabi::compute_abi_info(ccx,
-                                         &llsig.llarg_tys,
-                                         llsig.llret_ty,
-                                         llsig.ret_def);
 
-    let arg_tys: &[cabi::ArgType] = &fn_type.arg_tys;
+    let extra_args = &passed_arg_tys[fn_sig.inputs.len()..];
+    let fn_type = FnType::new(ccx, fn_abi, &fn_sig, extra_args);
 
     let mut llargs_foreign = Vec::new();
 
@@ -279,8 +207,8 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     // pointer that Rust gave us. Sometimes we have to bitcast
     // because foreign fns return slightly different (but equivalent)
     // views on the same type (e.g., i64 in place of {i32,i32}).
-    if fn_type.ret_ty.is_indirect() {
-        match fn_type.ret_ty.cast {
+    if fn_type.ret.is_indirect() {
+        match fn_type.ret.cast {
             Some(ty) => {
                 let llcastedretptr =
                     BitCast(bcx, llretptr, ty.ptr_to());
@@ -293,7 +221,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }
 
     let mut offset = 0;
-    for (i, arg_ty) in arg_tys.iter().enumerate() {
+    for (i, arg_ty) in fn_type.args.iter().enumerate() {
         let mut llarg_rust = llargs_rust[i + offset];
 
         if arg_ty.is_ignore() {
@@ -359,15 +287,13 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         llargs_foreign.push(llarg_foreign);
     }
 
-    let cc = llvm_calling_convention(ccx, fn_abi);
-
     // A function pointer is called without the declaration available, so we have to apply
     // any attributes with ABI implications directly to the call instruction.
     let mut attrs = llvm::AttrBuilder::new();
 
     // Add attributes that are always applicable, independent of the concrete foreign ABI
-    if fn_type.ret_ty.is_indirect() {
-        let llret_sz = machine::llsize_of_real(ccx, fn_type.ret_ty.ty);
+    if fn_type.ret.is_indirect() {
+        let llret_sz = machine::llsize_of_real(ccx, fn_type.ret.ty);
 
         // The outptr can be noalias and nocapture because it's entirely
         // invisible to the program. We also know it's nonnull as well
@@ -378,14 +304,14 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     };
 
     // Add attributes that depend on the concrete foreign ABI
-    let mut arg_idx = if fn_type.ret_ty.is_indirect() { 1 } else { 0 };
-    match fn_type.ret_ty.attr {
+    let mut arg_idx = if fn_type.ret.is_indirect() { 1 } else { 0 };
+    match fn_type.ret.attr {
         Some(attr) => { attrs.arg(arg_idx, attr); },
         _ => ()
     }
 
     arg_idx += 1;
-    for arg_ty in &fn_type.arg_tys {
+    for arg_ty in &fn_type.args {
         if arg_ty.is_ignore() {
             continue;
         }
@@ -402,7 +328,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let llforeign_retval = CallWithConv(bcx,
                                         llfn,
                                         &llargs_foreign[..],
-                                        cc,
+                                        fn_type.cconv,
                                         Some(attrs),
                                         call_debug_loc);
 
@@ -411,11 +337,11 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     // type to match because some ABIs will use a different type than
     // the Rust type. e.g., a {u32,u32} struct could be returned as
     // u64.
-    if llsig.ret_def && !fn_type.ret_ty.is_indirect() {
-        let llrust_ret_ty = llsig.llret_ty;
-        let llforeign_ret_ty = match fn_type.ret_ty.cast {
+    if fn_type.ret.ty != Type::void(ccx) && !fn_type.ret.is_indirect() {
+        let llrust_ret_ty = fn_type.ret.ty;
+        let llforeign_ret_ty = match fn_type.ret.cast {
             Some(ty) => ty,
-            None => fn_type.ret_ty.ty
+            None => fn_type.ret.ty
         };
 
         debug!("llretptr={:?}", Value(llretptr));
@@ -543,14 +469,20 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     let fnty = ccx.tcx().node_id_to_type(id);
     let mty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &fnty);
-    let tys = foreign_types_for_fn_ty(ccx, mty);
+    let (fn_abi, fn_sig) = match mty.sty {
+        ty::TyFnDef(_, _, ref fn_ty) => (fn_ty.abi, &fn_ty.sig),
+        _ => ccx.sess().bug("trans_rust_fn_with_foreign_abi called on non-function type")
+    };
+    let fn_sig = ccx.tcx().erase_late_bound_regions(fn_sig);
+    let fn_sig = infer::normalize_associated_type(ccx.tcx(), &fn_sig);
+    let fn_ty = FnType::new(ccx, fn_abi, &fn_sig, &[]);
 
     unsafe { // unsafe because we call LLVM operations
         // Build up the Rust function (`foo0` above).
         let llrustfn = build_rust_fn(ccx, decl, body, param_substs, attrs, id, hash);
 
         // Build up the foreign wrapper (`foo` above).
-        return build_wrap_fn(ccx, llrustfn, llwrapfn, &tys, mty);
+        return build_wrap_fn(ccx, llrustfn, llwrapfn, &fn_sig, &fn_ty, mty);
     }
 
     fn build_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
@@ -568,7 +500,7 @@ fn build_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         let t = monomorphize::apply_param_substs(tcx, param_substs, &t);
 
         let path =
-            tcx.map.def_path_from_id(id)
+            tcx.map.def_path(tcx.map.local_def_id(id))
                    .into_iter()
                    .map(|e| e.data.as_interned_str())
                    .chain(once(special_idents::clownshoe_abi.name.as_str()));
@@ -576,23 +508,27 @@ fn build_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
         // Compute the type that the function would have if it were just a
         // normal Rust function. This will be the type of the wrappee fn.
-        match t.sty {
-            ty::TyFnDef(_, _, ref f) | ty::TyFnPtr(ref f)=> {
+        let rust_fn_ty = match t.sty {
+            ty::TyFnDef(_, _, ref f) => {
                 assert!(f.abi != Abi::Rust);
                 assert!(f.abi != Abi::RustIntrinsic);
                 assert!(f.abi != Abi::PlatformIntrinsic);
+                tcx.mk_fn_ptr(ty::BareFnTy {
+                    unsafety: f.unsafety,
+                    abi: Abi::Rust,
+                    sig: f.sig.clone()
+                })
             }
             _ => {
-                ccx.sess().bug(&format!("build_rust_fn: extern fn {} has ty {:?}, \
-                                        expected a bare fn ty",
-                                       ccx.tcx().map.path_to_string(id),
-                                       t));
+                unreachable!("build_rust_fn: extern fn {} has ty {:?}, \
+                              expected a fn item type",
+                              tcx.map.path_to_string(id), t);
             }
         };
 
-        debug!("build_rust_fn: path={} id={} t={:?}",
+        debug!("build_rust_fn: path={} id={} ty={:?}",
                ccx.tcx().map.path_to_string(id),
-               id, t);
+               id, rust_fn_ty);
 
         let llfn = declare::define_internal_rust_fn(ccx, &ps, t);
         attributes::from_fn_attrs(ccx, attrs, llfn);
@@ -603,7 +539,8 @@ fn build_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     unsafe fn build_wrap_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                       llrustfn: ValueRef,
                                       llwrapfn: ValueRef,
-                                      tys: &ForeignTypes<'tcx>,
+                                      fn_sig: &ty::FnSig<'tcx>,
+                                      fn_ty: &FnType,
                                       t: Ty<'tcx>) {
         let _icx = push_ctxt(
             "foreign::trans_rust_fn_with_foreign_abi::build_wrap_fn");
@@ -650,7 +587,7 @@ unsafe fn build_wrap_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
         // If there is an out pointer on the foreign function
         let foreign_outptr = {
-            if tys.fn_ty.ret_ty.is_indirect() {
+            if fn_ty.ret.is_indirect() {
                 Some(get_param(llwrapfn, next_foreign_arg(false)))
             } else {
                 None
@@ -660,7 +597,7 @@ unsafe fn build_wrap_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         let rustfn_ty = Type::from_ref(llvm::LLVMTypeOf(llrustfn)).element_type();
         let mut rust_param_tys = rustfn_ty.func_params().into_iter();
         // Push Rust return pointer, using null if it will be unused.
-        let rust_uses_outptr = match tys.fn_sig.output {
+        let rust_uses_outptr = match fn_sig.output {
             ty::FnConverging(ret_ty) => type_of::return_uses_outptr(ccx, ret_ty),
             ty::FnDiverging => false
         };
@@ -696,7 +633,7 @@ unsafe fn build_wrap_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                             return_ty={:?}",
                            Value(slot),
                            llrust_ret_ty,
-                           tys.fn_sig.output);
+                           fn_sig.output);
                     llrust_args.push(slot);
                     return_alloca = Some(slot);
                 }
@@ -711,8 +648,8 @@ unsafe fn build_wrap_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         // Build up the arguments to the call to the rust function.
         // Careful to adapt for cases where the native convention uses
         // a pointer and Rust does not or vice versa.
-        for i in 0..tys.fn_sig.inputs.len() {
-            let rust_ty = tys.fn_sig.inputs[i];
+        for i in 0..fn_sig.inputs.len() {
+            let rust_ty = fn_sig.inputs[i];
             let rust_indirect = type_of::arg_is_indirect(ccx, rust_ty);
             let llty = rust_param_tys.next().expect("Not enough parameter types!");
             let llrust_ty = if rust_indirect {
@@ -720,7 +657,7 @@ unsafe fn build_wrap_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             } else {
                 llty
             };
-            let llforeign_arg_ty = tys.fn_ty.arg_tys[i];
+            let llforeign_arg_ty = fn_ty.args[i];
             let foreign_indirect = llforeign_arg_ty.is_indirect();
 
             if llforeign_arg_ty.is_ignore() {
@@ -802,12 +739,12 @@ unsafe fn build_wrap_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                           None, Some(attributes));
 
         // Get the return value where the foreign fn expects it.
-        let llforeign_ret_ty = match tys.fn_ty.ret_ty.cast {
+        let llforeign_ret_ty = match fn_ty.ret.cast {
             Some(ty) => ty,
-            None => tys.fn_ty.ret_ty.ty
+            None => fn_ty.ret.ty
         };
         match foreign_outptr {
-            None if !tys.llsig.ret_def => {
+            None if fn_ty.ret.ty == Type::void(ccx) => {
                 // Function returns `()` or `bot`, which in Rust is the LLVM
                 // type "{}" but in foreign ABIs is "Void".
                 builder.ret_void();
@@ -874,140 +811,6 @@ pub fn link_name(name: ast::Name, attrs: &[ast::Attribute]) -> InternedString {
         }
     }
 }
-
-/// The ForeignSignature is the LLVM types of the arguments/return type of a function. Note that
-/// these LLVM types are not quite the same as the LLVM types would be for a native Rust function
-/// because foreign functions just plain ignore modes. They also don't pass aggregate values by
-/// pointer like we do.
-fn foreign_signature<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                               fn_sig: &ty::FnSig<'tcx>,
-                               arg_tys: &[Ty<'tcx>])
-                               -> LlvmSignature {
-    let llarg_tys = arg_tys.iter().map(|&arg| foreign_arg_type_of(ccx, arg)).collect();
-    let (llret_ty, ret_def) = match fn_sig.output {
-        ty::FnConverging(ret_ty) =>
-            (type_of::foreign_arg_type_of(ccx, ret_ty), !return_type_is_void(ccx, ret_ty)),
-        ty::FnDiverging =>
-            (Type::nil(ccx), false)
-    };
-    LlvmSignature {
-        llarg_tys: llarg_tys,
-        llret_ty: llret_ty,
-        ret_def: ret_def
-    }
-}
-
-fn foreign_types_for_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                                     ty: Ty<'tcx>) -> ForeignTypes<'tcx> {
-    let fn_sig = match ty.sty {
-        ty::TyFnDef(_, _, ref fn_ty) | ty::TyFnPtr(ref fn_ty) => &fn_ty.sig,
-        _ => ccx.sess().bug("foreign_types_for_fn_ty called on non-function type")
-    };
-    let fn_sig = ccx.tcx().erase_late_bound_regions(fn_sig);
-    let fn_sig = infer::normalize_associated_type(ccx.tcx(), &fn_sig);
-    let llsig = foreign_signature(ccx, &fn_sig, &fn_sig.inputs);
-    let fn_ty = cabi::compute_abi_info(ccx,
-                                       &llsig.llarg_tys,
-                                       llsig.llret_ty,
-                                       llsig.ret_def);
-    debug!("foreign_types_for_fn_ty(\
-           ty={:?}, \
-           llsig={:?} -> {:?}, \
-           fn_ty={:?} -> {:?}, \
-           ret_def={}",
-           ty,
-           llsig.llarg_tys,
-           llsig.llret_ty,
-           fn_ty.arg_tys,
-           fn_ty.ret_ty,
-           llsig.ret_def);
-
-    ForeignTypes {
-        fn_sig: fn_sig,
-        llsig: llsig,
-        fn_ty: fn_ty
-    }
-}
-
-fn lltype_for_fn_from_foreign_types(ccx: &CrateContext, tys: &ForeignTypes) -> Type {
-    let mut llargument_tys = Vec::new();
-
-    let ret_ty = tys.fn_ty.ret_ty;
-    let llreturn_ty = if ret_ty.is_indirect() {
-        llargument_tys.push(ret_ty.ty.ptr_to());
-        Type::void(ccx)
-    } else {
-        match ret_ty.cast {
-            Some(ty) => ty,
-            None => ret_ty.ty
-        }
-    };
-
-    for &arg_ty in &tys.fn_ty.arg_tys {
-        if arg_ty.is_ignore() {
-            continue;
-        }
-        // add padding
-        match arg_ty.pad {
-            Some(ty) => llargument_tys.push(ty),
-            None => ()
         }
-
-        let llarg_ty = if arg_ty.is_indirect() {
-            arg_ty.ty.ptr_to()
-        } else {
-            match arg_ty.cast {
-                Some(ty) => ty,
-                None => arg_ty.ty
-            }
-        };
-
-        llargument_tys.push(llarg_ty);
-    }
-
-    if tys.fn_sig.variadic {
-        Type::variadic_func(&llargument_tys, &llreturn_ty)
-    } else {
-        Type::func(&llargument_tys[..], &llreturn_ty)
-    }
-}
-
-pub fn lltype_for_foreign_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
-                                       ty: Ty<'tcx>) -> Type {
-    lltype_for_fn_from_foreign_types(ccx, &foreign_types_for_fn_ty(ccx, ty))
-}
-
-fn add_argument_attributes(tys: &ForeignTypes,
-                           llfn: ValueRef) {
-    let mut i = if tys.fn_ty.ret_ty.is_indirect() {
-        1
-    } else {
-        0
-    };
-
-    match tys.fn_ty.ret_ty.attr {
-        Some(attr) => unsafe {
-            llvm::LLVMAddFunctionAttribute(llfn, i as c_uint, attr.bits() as u64);
-        },
-        None => {}
-    }
-
-    i += 1;
-
-    for &arg_ty in &tys.fn_ty.arg_tys {
-        if arg_ty.is_ignore() {
-            continue;
-        }
-        // skip padding
-        if arg_ty.pad.is_some() { i += 1; }
-
-        match arg_ty.attr {
-            Some(attr) => unsafe {
-                llvm::LLVMAddFunctionAttribute(llfn, i as c_uint, attr.bits() as u64);
-            },
-            None => ()
-        }
-
-        i += 1;
     }
 }
index e16f25cfec540c7467bf59ee48543657ddae7e82..ee2d84a7be7e0be68b4ec63ce6acf239e8b9f5d7 100644 (file)
@@ -14,8 +14,8 @@
 use middle::infer;
 use middle::subst;
 use trans::adt;
+use trans::cabi::FnType;
 use trans::common::*;
-use trans::foreign;
 use trans::machine;
 use middle::ty::{self, Ty, TypeFoldable};
 
@@ -239,14 +239,6 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
     llsizingty
 }
 
-pub fn foreign_arg_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
-    if t.is_bool() {
-        Type::i1(cx)
-    } else {
-        type_of(cx, t)
-    }
-}
-
 pub fn arg_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
     if t.is_bool() {
         Type::i1(cx)
@@ -390,12 +382,12 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
 
       ty::TyFnDef(..) => Type::nil(cx),
       ty::TyFnPtr(f) => {
+        let sig = cx.tcx().erase_late_bound_regions(&f.sig);
+        let sig = infer::normalize_associated_type(cx.tcx(), &sig);
         if f.abi == Abi::Rust || f.abi == Abi::RustCall {
-            let sig = cx.tcx().erase_late_bound_regions(&f.sig);
-            let sig = infer::normalize_associated_type(cx.tcx(), &sig);
             type_of_rust_fn(cx, None, &sig, f.abi).ptr_to()
         } else {
-            foreign::lltype_for_foreign_fn(cx, t).ptr_to()
+            FnType::new(cx, f.abi, &sig, &[]).to_llvm(cx).ptr_to()
         }
       }
       ty::TyTuple(ref tys) if tys.is_empty() => Type::nil(cx),