1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11
12 use syntax::abi::{OsWin32, OsMacos};
13 use lib::llvm::*;
14 use super::cabi::*;
15 use super::common::*;
16 use super::machine::*;
17 use middle::trans::type_::Type;
18
19 pub fn compute_abi_info(ccx: &CrateContext,
20 atys: &[Type],
21 rty: Type,
22 ret_def: bool) -> FnType {
23 let mut arg_tys = Vec::new();
24
25 let ret_ty;
26 if !ret_def {
27 ret_ty = ArgType::direct(Type::void(ccx), None, None, None);
28 } else if rty.kind() == Struct {
29 // Returning a structure. Most often, this will use
30 // a hidden first argument. On some platforms, though,
31 // small structs are returned as integers.
32 //
33 // Some links:
34 // http://www.angelcode.com/dev/callconv/callconv.html
35 // Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp
36
37 enum Strategy { RetValue(Type), RetPointer }
38 let strategy = match ccx.sess().targ_cfg.os {
39 OsWin32 | OsMacos => {
40 match llsize_of_alloc(ccx, rty) {
41 1 => RetValue(Type::i8(ccx)),
42 2 => RetValue(Type::i16(ccx)),
43 4 => RetValue(Type::i32(ccx)),
44 8 => RetValue(Type::i64(ccx)),
45 _ => RetPointer
46 }
47 }
48 _ => {
49 RetPointer
50 }
51 };
52
53 match strategy {
54 RetValue(t) => {
55 ret_ty = ArgType::direct(rty, Some(t), None, None);
56 }
57 RetPointer => {
58 ret_ty = ArgType::indirect(rty, Some(StructRetAttribute));
59 }
60 }
61 } else {
62 ret_ty = ArgType::direct(rty, None, None, None);
63 }
64
65 for &t in atys.iter() {
66 let ty = match t.kind() {
67 Struct => {
68 let size = llsize_of_alloc(ccx, t);
69 if size == 0 {
70 ArgType::ignore(t)
71 } else {
72 ArgType::indirect(t, Some(ByValAttribute))
73 }
74 }
75 _ => ArgType::direct(t, None, None, None),
76 };
77 arg_tys.push(ty);
78 }
79
80 return FnType {
81 arg_tys: arg_tys,
82 ret_ty: ret_ty,
83 };
84 }