Skip to content

Commit b72d4d7

Browse files
committed
add ABIInfo trait and separate x86-64 ABI implementation from foreign trans
ABIInfo provides a method to translate the type of foreign function. The foreign trans uses the method to get ABI-specific type and uses the result to generate LLVM instructions for wrapper and shim functions.
1 parent 721c174 commit b72d4d7

File tree

4 files changed

+660
-605
lines changed

4 files changed

+660
-605
lines changed

src/librustc/middle/trans/cabi.rs

+214
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
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.
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 lib::llvm::{llvm, TypeRef, ValueRef, Attribute};
12+
use middle::trans::base::*;
13+
use middle::trans::build::*;
14+
use middle::trans::common::*;
15+
16+
export ABIInfo, LLVMType, FnType;
17+
export llvm_abi_info;
18+
19+
trait ABIInfo {
20+
fn compute_info(&self,
21+
atys: &[TypeRef],
22+
rty: TypeRef,
23+
ret_def: bool) -> FnType;
24+
}
25+
26+
struct LLVMType {
27+
cast: bool,
28+
ty: TypeRef
29+
}
30+
31+
struct FnType {
32+
arg_tys: ~[LLVMType],
33+
ret_ty: LLVMType,
34+
attrs: ~[Option<Attribute>],
35+
sret: bool
36+
}
37+
38+
impl FnType {
39+
fn decl_fn(&self, decl: fn(fnty: TypeRef) -> ValueRef) -> ValueRef {
40+
let atys = vec::map(self.arg_tys, |t| t.ty);
41+
let rty = self.ret_ty.ty;
42+
let fnty = T_fn(atys, rty);
43+
let llfn = decl(fnty);
44+
45+
for vec::eachi(self.attrs) |i, a| {
46+
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+
59+
fn build_shim_args(&self, bcx: block,
60+
arg_tys: &[TypeRef],
61+
llargbundle: ValueRef) -> ~[ValueRef] {
62+
let mut atys = /*bad*/copy self.arg_tys;
63+
let mut attrs = /*bad*/copy self.attrs;
64+
65+
let mut llargvals = ~[];
66+
let mut i = 0u;
67+
let n = vec::len(arg_tys);
68+
69+
if self.sret {
70+
let llretptr = GEPi(bcx, llargbundle, [0u, n]);
71+
let llretloc = Load(bcx, llretptr);
72+
llargvals = ~[llretloc];
73+
atys = vec::tail(atys);
74+
attrs = vec::tail(attrs);
75+
}
76+
77+
while i < n {
78+
let llargval = if atys[i].cast {
79+
let arg_ptr = GEPi(bcx, llargbundle, [0u, i]);
80+
let arg_ptr = BitCast(bcx, arg_ptr, T_ptr(atys[i].ty));
81+
Load(bcx, arg_ptr)
82+
} else if attrs[i].is_some() {
83+
GEPi(bcx, llargbundle, [0u, i])
84+
} else {
85+
load_inbounds(bcx, llargbundle, [0u, i])
86+
};
87+
llargvals.push(llargval);
88+
i += 1u;
89+
}
90+
91+
return llargvals;
92+
}
93+
94+
fn build_shim_ret(&self, bcx: block,
95+
arg_tys: &[TypeRef], ret_def: bool,
96+
llargbundle: ValueRef, llretval: ValueRef) {
97+
for vec::eachi(self.attrs) |i, a| {
98+
match *a {
99+
Some(attr) => {
100+
unsafe {
101+
llvm::LLVMAddInstrAttribute(
102+
llretval, (i + 1u) as c_uint,
103+
attr as c_uint);
104+
}
105+
}
106+
_ => ()
107+
}
108+
}
109+
if self.sret || !ret_def {
110+
return;
111+
}
112+
let n = vec::len(arg_tys);
113+
// R** llretptr = &args->r;
114+
let llretptr = GEPi(bcx, llargbundle, [0u, n]);
115+
// R* llretloc = *llretptr; /* (args->r) */
116+
let llretloc = Load(bcx, llretptr);
117+
if self.ret_ty.cast {
118+
let tmp_ptr = BitCast(bcx, llretloc, T_ptr(self.ret_ty.ty));
119+
// *args->r = r;
120+
Store(bcx, llretval, tmp_ptr);
121+
} else {
122+
// *args->r = r;
123+
Store(bcx, llretval, llretloc);
124+
};
125+
}
126+
127+
fn build_wrap_args(&self, bcx: block, ret_ty: TypeRef,
128+
llwrapfn: ValueRef, llargbundle: ValueRef) {
129+
let mut atys = /*bad*/copy self.arg_tys;
130+
let mut attrs = /*bad*/copy self.attrs;
131+
let mut j = 0u;
132+
let llretptr = if self.sret {
133+
atys = vec::tail(atys);
134+
attrs = vec::tail(attrs);
135+
j = 1u;
136+
get_param(llwrapfn, 0u)
137+
} else if self.ret_ty.cast {
138+
let retptr = alloca(bcx, self.ret_ty.ty);
139+
BitCast(bcx, retptr, T_ptr(ret_ty))
140+
} else {
141+
alloca(bcx, ret_ty)
142+
};
143+
144+
let mut i = 0u;
145+
let n = vec::len(atys);
146+
while i < n {
147+
let mut argval = get_param(llwrapfn, i + j);
148+
if attrs[i].is_some() {
149+
argval = Load(bcx, argval);
150+
store_inbounds(bcx, argval, llargbundle, [0u, i]);
151+
} else if atys[i].cast {
152+
let argptr = GEPi(bcx, llargbundle, [0u, i]);
153+
let argptr = BitCast(bcx, argptr, T_ptr(atys[i].ty));
154+
Store(bcx, argval, argptr);
155+
} else {
156+
store_inbounds(bcx, argval, llargbundle, [0u, i]);
157+
}
158+
i += 1u;
159+
}
160+
store_inbounds(bcx, llretptr, llargbundle, [0u, n]);
161+
}
162+
163+
fn build_wrap_ret(&self, bcx: block,
164+
arg_tys: &[TypeRef], ret_def: bool,
165+
llargbundle: ValueRef) {
166+
if self.sret || !ret_def {
167+
RetVoid(bcx);
168+
return;
169+
}
170+
let n = vec::len(arg_tys);
171+
let llretval = load_inbounds(bcx, llargbundle, ~[0u, n]);
172+
let llretval = if self.ret_ty.cast {
173+
let retptr = BitCast(bcx, llretval, T_ptr(self.ret_ty.ty));
174+
Load(bcx, retptr)
175+
} else {
176+
Load(bcx, llretval)
177+
};
178+
Ret(bcx, llretval);
179+
}
180+
}
181+
182+
enum LLVM_ABIInfo { LLVM_ABIInfo }
183+
184+
impl LLVM_ABIInfo: ABIInfo {
185+
fn compute_info(&self,
186+
atys: &[TypeRef],
187+
rty: TypeRef,
188+
_ret_def: bool) -> FnType {
189+
let arg_tys = do atys.map |a| {
190+
LLVMType { cast: false, ty: *a }
191+
};
192+
let ret_ty = LLVMType {
193+
cast: false,
194+
ty: rty
195+
};
196+
let attrs = do atys.map |_| {
197+
option::None
198+
};
199+
let sret = false;
200+
201+
return FnType {
202+
arg_tys: arg_tys,
203+
ret_ty: ret_ty,
204+
attrs: attrs,
205+
sret: sret
206+
};
207+
}
208+
}
209+
210+
fn llvm_abi_info() -> ABIInfo {
211+
return LLVM_ABIInfo as ABIInfo;
212+
}
213+
214+

0 commit comments

Comments
 (0)