]> git.proxmox.com Git - rustc.git/blob - src/librustc_trans/trans/cabi_x86.rs
Imported Upstream version 1.8.0+dfsg1
[rustc.git] / src / librustc_trans / trans / cabi_x86.rs
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 => {
55 ret_ty = ArgType::indirect(rty, Some(Attribute::StructRet));
56 }
57 }
58 } else {
59 let attr = if rty == Type::i1(ccx) { Some(Attribute::ZExt) } else { None };
60 ret_ty = ArgType::direct(rty, None, None, attr);
61 }
62
63 for &t in atys {
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 {
70 ArgType::indirect(t, Some(Attribute::ByVal))
71 }
72 }
73 _ => {
74 let attr = if t == Type::i1(ccx) { Some(Attribute::ZExt) } else { None };
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 }