blob: 4526af2da0f49a4b39d98c4d16f24cc7d3b061b2 [file] [log] [blame]
Tim Chevalier41adf9d2013-01-25 22:56:561// Copyright 2012 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
James Miller81cf72c2013-06-16 10:52:4411use lib::llvm::{llvm, ValueRef, Attribute, Void};
Tim Chevalier41adf9d2013-01-25 22:56:5612use middle::trans::base::*;
13use middle::trans::build::*;
14use middle::trans::common::*;
15
James Miller81cf72c2013-06-16 10:52:4416use middle::trans::type_::Type;
17
Alex Crichton2df07dd2013-02-25 19:11:2118use core::libc::c_uint;
19use core::option;
20use core::vec;
21
Patrick Waltonba11e962013-01-30 19:46:1922pub trait ABIInfo {
James Miller81cf72c2013-06-16 10:52:4423 fn compute_info(&self, atys: &[Type], rty: Type, ret_def: bool) -> FnType;
Tim Chevalier41adf9d2013-01-25 22:56:5624}
25
Patrick Waltonba11e962013-01-30 19:46:1926pub struct LLVMType {
Tim Chevalier41adf9d2013-01-25 22:56:5627 cast: bool,
James Millerfd83b922013-06-15 14:29:5228 ty: Type
Tim Chevalier41adf9d2013-01-25 22:56:5629}
30
Patrick Waltonba11e962013-01-30 19:46:1931pub struct FnType {
Tim Chevalier41adf9d2013-01-25 22:56:5632 arg_tys: ~[LLVMType],
33 ret_ty: LLVMType,
Alex Crichton2df07dd2013-02-25 19:11:2134 attrs: ~[option::Option<Attribute>],
Tim Chevalier41adf9d2013-01-25 22:56:5635 sret: bool
36}
37
Patrick Walton5fb25462013-05-31 22:17:2238impl FnType {
James Millerfd83b922013-06-15 14:29:5239 pub fn decl_fn(&self, decl: &fn(fnty: Type) -> ValueRef) -> ValueRef {
Tim Chevalier41adf9d2013-01-25 22:56:5640 let atys = vec::map(self.arg_tys, |t| t.ty);
41 let rty = self.ret_ty.ty;
James Miller81cf72c2013-06-16 10:52:4442 let fnty = Type::func(atys, &rty);
Tim Chevalier41adf9d2013-01-25 22:56:5643 let llfn = decl(fnty);
44
Daniel Micaycbad1da2013-06-17 20:37:1145 for self.attrs.iter().enumerate().advance |(i, a)| {
Tim Chevalier41adf9d2013-01-25 22:56:5646 match *a {
47 option::Some(attr) => {
48 unsafe {
49 let llarg = get_param(llfn, i);
50 llvm::LLVMAddAttribute(llarg, attr as c_uint);
51 }
52 }
53 _ => ()
54 }
55 }
56 return llfn;
57 }
58
James Miller81cf72c2013-06-16 10:52:4459 pub fn build_shim_args(&self, bcx: block, arg_tys: &[Type], llargbundle: ValueRef)
Patrick Walton5fb25462013-05-31 22:17:2260 -> ~[ValueRef] {
Björn Steinbrink1720d9f2013-05-29 18:10:1661 let mut atys: &[LLVMType] = self.arg_tys;
62 let mut attrs: &[option::Option<Attribute>] = self.attrs;
Tim Chevalier41adf9d2013-01-25 22:56:5663
64 let mut llargvals = ~[];
65 let mut i = 0u;
Youngmin Yooa2a85962013-05-14 09:52:1266 let n = arg_tys.len();
Tim Chevalier41adf9d2013-01-25 22:56:5667
68 if self.sret {
69 let llretptr = GEPi(bcx, llargbundle, [0u, n]);
70 let llretloc = Load(bcx, llretptr);
71 llargvals = ~[llretloc];
Björn Steinbrink1720d9f2013-05-29 18:10:1672 atys = atys.tail();
73 attrs = attrs.tail();
Tim Chevalier41adf9d2013-01-25 22:56:5674 }
75
76 while i < n {
77 let llargval = if atys[i].cast {
78 let arg_ptr = GEPi(bcx, llargbundle, [0u, i]);
James Miller81cf72c2013-06-16 10:52:4479 let arg_ptr = BitCast(bcx, arg_ptr, atys[i].ty.ptr_to());
Tim Chevalier41adf9d2013-01-25 22:56:5680 Load(bcx, arg_ptr)
81 } else if attrs[i].is_some() {
82 GEPi(bcx, llargbundle, [0u, i])
83 } else {
84 load_inbounds(bcx, llargbundle, [0u, i])
85 };
86 llargvals.push(llargval);
87 i += 1u;
88 }
89
90 return llargvals;
91 }
92
James Miller81cf72c2013-06-16 10:52:4493 pub fn build_shim_ret(&self, bcx: block, arg_tys: &[Type], ret_def: bool,
94 llargbundle: ValueRef, llretval: ValueRef) {
Daniel Micaycbad1da2013-06-17 20:37:1195 for self.attrs.iter().enumerate().advance |(i, a)| {
Tim Chevalier41adf9d2013-01-25 22:56:5696 match *a {
Alex Crichton2df07dd2013-02-25 19:11:2197 option::Some(attr) => {
Tim Chevalier41adf9d2013-01-25 22:56:5698 unsafe {
James Miller81cf72c2013-06-16 10:52:4499 llvm::LLVMAddInstrAttribute(llretval, (i + 1u) as c_uint, attr as c_uint);
Tim Chevalier41adf9d2013-01-25 22:56:56100 }
101 }
102 _ => ()
103 }
104 }
105 if self.sret || !ret_def {
106 return;
107 }
Youngmin Yooa2a85962013-05-14 09:52:12108 let n = arg_tys.len();
Tim Chevalier41adf9d2013-01-25 22:56:56109 // R** llretptr = &args->r;
110 let llretptr = GEPi(bcx, llargbundle, [0u, n]);
111 // R* llretloc = *llretptr; /* (args->r) */
112 let llretloc = Load(bcx, llretptr);
113 if self.ret_ty.cast {
James Miller81cf72c2013-06-16 10:52:44114 let tmp_ptr = BitCast(bcx, llretloc, self.ret_ty.ty.ptr_to());
Tim Chevalier41adf9d2013-01-25 22:56:56115 // *args->r = r;
116 Store(bcx, llretval, tmp_ptr);
117 } else {
118 // *args->r = r;
119 Store(bcx, llretval, llretloc);
120 };
121 }
122
James Miller81cf72c2013-06-16 10:52:44123 pub fn build_wrap_args(&self, bcx: block, ret_ty: Type,
124 llwrapfn: ValueRef, llargbundle: ValueRef) {
Björn Steinbrink1720d9f2013-05-29 18:10:16125 let mut atys: &[LLVMType] = self.arg_tys;
126 let mut attrs: &[option::Option<Attribute>] = self.attrs;
Tim Chevalier41adf9d2013-01-25 22:56:56127 let mut j = 0u;
128 let llretptr = if self.sret {
Björn Steinbrink1720d9f2013-05-29 18:10:16129 atys = atys.tail();
130 attrs = attrs.tail();
Tim Chevalier41adf9d2013-01-25 22:56:56131 j = 1u;
132 get_param(llwrapfn, 0u)
133 } else if self.ret_ty.cast {
134 let retptr = alloca(bcx, self.ret_ty.ty);
James Millerfd83b922013-06-15 14:29:52135 BitCast(bcx, retptr, ret_ty.ptr_to())
Tim Chevalier41adf9d2013-01-25 22:56:56136 } else {
137 alloca(bcx, ret_ty)
138 };
139
140 let mut i = 0u;
Youngmin Yooa2a85962013-05-14 09:52:12141 let n = atys.len();
Tim Chevalier41adf9d2013-01-25 22:56:56142 while i < n {
143 let mut argval = get_param(llwrapfn, i + j);
144 if attrs[i].is_some() {
145 argval = Load(bcx, argval);
146 store_inbounds(bcx, argval, llargbundle, [0u, i]);
147 } else if atys[i].cast {
148 let argptr = GEPi(bcx, llargbundle, [0u, i]);
James Miller81cf72c2013-06-16 10:52:44149 let argptr = BitCast(bcx, argptr, atys[i].ty.ptr_to());
Tim Chevalier41adf9d2013-01-25 22:56:56150 Store(bcx, argval, argptr);
151 } else {
152 store_inbounds(bcx, argval, llargbundle, [0u, i]);
153 }
154 i += 1u;
155 }
156 store_inbounds(bcx, llretptr, llargbundle, [0u, n]);
157 }
158
James Miller81cf72c2013-06-16 10:52:44159 pub fn build_wrap_ret(&self, bcx: block, arg_tys: &[Type], llargbundle: ValueRef) {
160 if self.ret_ty.ty.kind() == Void {
161 return;
Tim Chevalier41adf9d2013-01-25 22:56:56162 }
Patrick Waltonc995a622013-04-18 22:53:29163
Björn Steinbrink4fb2c092013-06-20 14:42:44164 if bcx.fcx.llretptr.is_some() {
165 let llretval = load_inbounds(bcx, llargbundle, [ 0, arg_tys.len() ]);
166 let llretval = if self.ret_ty.cast {
James Millerfd83b922013-06-15 14:29:52167 let retptr = BitCast(bcx, llretval, self.ret_ty.ty.ptr_to());
Björn Steinbrink4fb2c092013-06-20 14:42:44168 Load(bcx, retptr)
169 } else {
170 Load(bcx, llretval)
171 };
James Miller81cf72c2013-06-16 10:52:44172 let llretptr = BitCast(bcx, bcx.fcx.llretptr.get(), self.ret_ty.ty.ptr_to());
Björn Steinbrink4fb2c092013-06-20 14:42:44173 Store(bcx, llretval, llretptr);
174 }
Tim Chevalier41adf9d2013-01-25 22:56:56175 }
176}