]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
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 | use self::Strategy::*; | |
12 | use llvm::*; | |
13 | use trans::cabi::{ArgType, FnType}; | |
14 | use trans::type_::Type; | |
15 | use super::common::*; | |
16 | use super::machine::*; | |
17 | ||
18 | enum Strategy { RetValue(Type), RetPointer } | |
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 | let t = &ccx.sess().target.target; | |
38 | let strategy = if t.options.is_like_osx || t.options.is_like_windows { | |
39 | match llsize_of_alloc(ccx, rty) { | |
40 | 1 => RetValue(Type::i8(ccx)), | |
41 | 2 => RetValue(Type::i16(ccx)), | |
42 | 4 => RetValue(Type::i32(ccx)), | |
43 | 8 => RetValue(Type::i64(ccx)), | |
44 | _ => RetPointer | |
45 | } | |
46 | } else { | |
47 | RetPointer | |
48 | }; | |
49 | ||
50 | match strategy { | |
51 | RetValue(t) => { | |
52 | ret_ty = ArgType::direct(rty, Some(t), None, None); | |
53 | } | |
54 | RetPointer => { | |
d9579d0f | 55 | ret_ty = ArgType::indirect(rty, Some(Attribute::StructRet)); |
1a4d82fc JJ |
56 | } |
57 | } | |
58 | } else { | |
d9579d0f | 59 | let attr = if rty == Type::i1(ccx) { Some(Attribute::ZExt) } else { None }; |
1a4d82fc JJ |
60 | ret_ty = ArgType::direct(rty, None, None, attr); |
61 | } | |
62 | ||
85aaf69f | 63 | for &t in atys { |
1a4d82fc JJ |
64 | let ty = match t.kind() { |
65 | Struct => { | |
66 | let size = llsize_of_alloc(ccx, t); | |
67 | if size == 0 { | |
68 | ArgType::ignore(t) | |
69 | } else { | |
d9579d0f | 70 | ArgType::indirect(t, Some(Attribute::ByVal)) |
1a4d82fc JJ |
71 | } |
72 | } | |
73 | _ => { | |
d9579d0f | 74 | let attr = if t == Type::i1(ccx) { Some(Attribute::ZExt) } else { None }; |
1a4d82fc JJ |
75 | ArgType::direct(t, None, None, attr) |
76 | } | |
77 | }; | |
78 | arg_tys.push(ty); | |
79 | } | |
80 | ||
81 | return FnType { | |
82 | arg_tys: arg_tys, | |
83 | ret_ty: ret_ty, | |
84 | }; | |
85 | } |