// Copyright 2012 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. pub use self::ArgKind::*; use llvm::Attribute; use std::option; use middle::trans::context::CrateContext; use middle::trans::cabi_x86; use middle::trans::cabi_x86_64; use middle::trans::cabi_x86_win64; use middle::trans::cabi_arm; use middle::trans::cabi_mips; use middle::trans::type_::Type; #[deriving(Clone, PartialEq)] pub enum ArgKind { /// Pass the argument directly using the normal converted /// LLVM type or by coercing to another specified type Direct, /// Pass the argument indirectly via a hidden pointer Indirect, /// Ignore the argument (useful for empty struct) Ignore, } /// Information about how a specific C type /// should be passed to or returned from a function /// /// This is borrowed from clang's ABIInfo.h #[deriving(Clone)] pub struct ArgType { pub kind: ArgKind, /// Original LLVM type pub ty: Type, /// Coerced LLVM Type pub cast: option::Option, /// Dummy argument, which is emitted before the real argument pub pad: option::Option, /// LLVM attribute of argument pub attr: option::Option } impl ArgType { pub fn direct(ty: Type, cast: option::Option, pad: option::Option, attr: option::Option) -> ArgType { ArgType { kind: Direct, ty: ty, cast: cast, pad: pad, attr: attr } } pub fn indirect(ty: Type, attr: option::Option) -> ArgType { ArgType { kind: Indirect, ty: ty, cast: option::None, pad: option::None, attr: attr } } pub fn ignore(ty: Type) -> ArgType { ArgType { kind: Ignore, ty: ty, cast: None, pad: None, attr: None, } } pub fn is_indirect(&self) -> bool { return self.kind == Indirect; } pub fn is_ignore(&self) -> bool { return self.kind == Ignore; } } /// Metadata describing how the arguments to a native function /// should be passed in order to respect the native ABI. /// /// I will do my best to describe this structure, but these /// comments are reverse-engineered and may be inaccurate. -NDM pub struct FnType { /// The LLVM types of each argument. pub arg_tys: Vec , /// LLVM return type. pub ret_ty: ArgType, } pub fn compute_abi_info(ccx: &CrateContext, atys: &[Type], rty: Type, ret_def: bool) -> FnType { match ccx.sess().target.target.arch.as_slice() { "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) } else { cabi_x86_64::compute_abi_info(ccx, atys, rty, ret_def) }, "arm" => cabi_arm::compute_abi_info(ccx, atys, rty, ret_def), "mips" => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def), a => ccx.sess().fatal((format!("unrecognized arch \"{}\" in target specification", a)) .as_slice()), } }