1 // 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.
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.
11 use lib::llvm::{llvm, ValueRef, Attribute, Void};
12 use middle::trans::base::*;
13 use middle::trans::build::*;
14 use middle::trans::common::*;
16 use middle::trans::type_::Type;
18 use std::libc::c_uint;
22 fn compute_info(&self, atys: &[Type], rty: Type, ret_def: bool) -> FnType;
34 attrs: ~[option::Option<Attribute>],
39 pub fn decl_fn(&self, decl: &fn(fnty: Type) -> ValueRef) -> ValueRef {
40 let atys = self.arg_tys.iter().transform(|t| t.ty).collect::<~[Type]>();
41 let rty = self.ret_ty.ty;
42 let fnty = Type::func(atys, &rty);
43 let llfn = decl(fnty);
45 for self.attrs.iter().enumerate().advance |(i, a)| {
47 option::Some(attr) => {
49 let llarg = get_param(llfn, i);
50 llvm::LLVMAddAttribute(llarg, attr as c_uint);
59 pub fn build_shim_args(&self, bcx: block, arg_tys: &[Type], llargbundle: ValueRef)
61 let mut atys: &[LLVMType] = self.arg_tys;
62 let mut attrs: &[option::Option<Attribute>] = self.attrs;
64 let mut llargvals = ~[];
66 let n = arg_tys.len();
69 let llretptr = GEPi(bcx, llargbundle, [0u, n]);
70 let llretloc = Load(bcx, llretptr);
71 llargvals = ~[llretloc];
77 let llargval = if atys[i].cast {
78 let arg_ptr = GEPi(bcx, llargbundle, [0u, i]);
79 let arg_ptr = BitCast(bcx, arg_ptr, atys[i].ty.ptr_to());
81 } else if attrs[i].is_some() {
82 GEPi(bcx, llargbundle, [0u, i])
84 load_inbounds(bcx, llargbundle, [0u, i])
86 llargvals.push(llargval);
93 pub fn build_shim_ret(&self, bcx: block, arg_tys: &[Type], ret_def: bool,
94 llargbundle: ValueRef, llretval: ValueRef) {
95 for self.attrs.iter().enumerate().advance |(i, a)| {
97 option::Some(attr) => {
99 llvm::LLVMAddInstrAttribute(llretval, (i + 1u) as c_uint, attr as c_uint);
105 if self.sret || !ret_def {
108 let n = arg_tys.len();
109 // 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 {
114 let tmp_ptr = BitCast(bcx, llretloc, self.ret_ty.ty.ptr_to());
116 Store(bcx, llretval, tmp_ptr);
119 Store(bcx, llretval, llretloc);
123 pub fn build_wrap_args(&self, bcx: block, ret_ty: Type,
124 llwrapfn: ValueRef, llargbundle: ValueRef) {
125 let mut atys: &[LLVMType] = self.arg_tys;
126 let mut attrs: &[option::Option<Attribute>] = self.attrs;
128 let llretptr = if self.sret {
130 attrs = attrs.tail();
132 get_param(llwrapfn, 0u)
133 } else if self.ret_ty.cast {
134 let retptr = alloca(bcx, self.ret_ty.ty, "");
135 BitCast(bcx, retptr, ret_ty.ptr_to())
137 alloca(bcx, ret_ty, "")
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]);
149 let argptr = BitCast(bcx, argptr, atys[i].ty.ptr_to());
150 Store(bcx, argval, argptr);
152 store_inbounds(bcx, argval, llargbundle, [0u, i]);
156 store_inbounds(bcx, llretptr, llargbundle, [0u, n]);
159 pub fn build_wrap_ret(&self, bcx: block, arg_tys: &[Type], llargbundle: ValueRef) {
160 if self.ret_ty.ty.kind() == Void {
164 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 {
167 let retptr = BitCast(bcx, llretval, self.ret_ty.ty.ptr_to());
172 let llretptr = BitCast(bcx, bcx.fcx.llretptr.get(), self.ret_ty.ty.ptr_to());
173 Store(bcx, llretval, llretptr);