]>
Commit | Line | Data |
---|---|---|
32a655c1 SL |
1 | // Copyright 2014-2016 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 | // FIXME: This needs an audit for correctness and completeness. | |
12 | ||
83c7162d XL |
13 | use abi::call::{FnType, ArgType, Reg, RegKind, Uniform}; |
14 | use abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; | |
32a655c1 | 15 | |
a1dfa0c6 | 16 | fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>) |
83c7162d XL |
17 | -> Option<Uniform> |
18 | where Ty: TyLayoutMethods<'a, C> + Copy, | |
19 | C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout | |
20 | { | |
2c00a5a8 | 21 | arg.layout.homogeneous_aggregate(cx).and_then(|unit| { |
cc61c64b | 22 | // Ensure we have at most eight uniquely addressable members. |
2c00a5a8 | 23 | if arg.layout.size > unit.size.checked_mul(8, cx).unwrap() { |
cc61c64b | 24 | return None; |
32a655c1 SL |
25 | } |
26 | ||
cc61c64b XL |
27 | let valid_unit = match unit.kind { |
28 | RegKind::Integer => false, | |
29 | RegKind::Float => true, | |
ff7c6d11 | 30 | RegKind::Vector => arg.layout.size.bits() == 128 |
cc61c64b | 31 | }; |
32a655c1 | 32 | |
cc61c64b XL |
33 | if valid_unit { |
34 | Some(Uniform { | |
35 | unit, | |
ff7c6d11 | 36 | total: arg.layout.size |
cc61c64b | 37 | }) |
32a655c1 SL |
38 | } else { |
39 | None | |
40 | } | |
41 | }) | |
42 | } | |
43 | ||
a1dfa0c6 | 44 | fn classify_ret_ty<'a, Ty, C>(cx: &C, ret: &mut ArgType<'a, Ty>) |
83c7162d XL |
45 | where Ty: TyLayoutMethods<'a, C> + Copy, |
46 | C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout | |
47 | { | |
cc61c64b | 48 | if !ret.layout.is_aggregate() { |
32a655c1 SL |
49 | ret.extend_integer_width_to(64); |
50 | return; | |
51 | } | |
52 | ||
2c00a5a8 | 53 | if let Some(uniform) = is_homogeneous_aggregate(cx, ret) { |
ff7c6d11 | 54 | ret.cast_to(uniform); |
32a655c1 SL |
55 | return; |
56 | } | |
ff7c6d11 | 57 | let size = ret.layout.size; |
cc61c64b | 58 | let bits = size.bits(); |
2c00a5a8 | 59 | if bits <= 256 { |
8faf50e0 | 60 | let unit = Reg::i64(); |
ff7c6d11 | 61 | ret.cast_to(Uniform { |
cc61c64b XL |
62 | unit, |
63 | total: size | |
64 | }); | |
32a655c1 SL |
65 | return; |
66 | } | |
cc61c64b XL |
67 | |
68 | // don't return aggregates in registers | |
ff7c6d11 | 69 | ret.make_indirect(); |
32a655c1 SL |
70 | } |
71 | ||
a1dfa0c6 | 72 | fn classify_arg_ty<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>) |
83c7162d XL |
73 | where Ty: TyLayoutMethods<'a, C> + Copy, |
74 | C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout | |
75 | { | |
cc61c64b | 76 | if !arg.layout.is_aggregate() { |
32a655c1 SL |
77 | arg.extend_integer_width_to(64); |
78 | return; | |
79 | } | |
80 | ||
2c00a5a8 | 81 | if let Some(uniform) = is_homogeneous_aggregate(cx, arg) { |
ff7c6d11 | 82 | arg.cast_to(uniform); |
32a655c1 SL |
83 | return; |
84 | } | |
85 | ||
ff7c6d11 | 86 | let total = arg.layout.size; |
2c00a5a8 XL |
87 | if total.bits() > 128 { |
88 | arg.make_indirect(); | |
89 | return; | |
90 | } | |
91 | ||
ff7c6d11 | 92 | arg.cast_to(Uniform { |
cc61c64b XL |
93 | unit: Reg::i64(), |
94 | total | |
95 | }); | |
32a655c1 SL |
96 | } |
97 | ||
a1dfa0c6 | 98 | pub fn compute_abi_info<'a, Ty, C>(cx: &C, fty: &mut FnType<'a, Ty>) |
83c7162d XL |
99 | where Ty: TyLayoutMethods<'a, C> + Copy, |
100 | C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout | |
101 | { | |
32a655c1 | 102 | if !fty.ret.is_ignore() { |
2c00a5a8 | 103 | classify_ret_ty(cx, &mut fty.ret); |
32a655c1 SL |
104 | } |
105 | ||
106 | for arg in &mut fty.args { | |
107 | if arg.is_ignore() { continue; } | |
2c00a5a8 | 108 | classify_arg_ty(cx, arg); |
32a655c1 SL |
109 | } |
110 | } |