Skip to content

Commit c2a61d7

Browse files
crabtwbrson
authored andcommitted
rustc: implement MIPS O32 ABI
1 parent 5150b98 commit c2a61d7

File tree

4 files changed

+226
-1
lines changed

4 files changed

+226
-1
lines changed

src/librustc/back/mips.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use back::target_strs;
1212
use driver::session;
13-
use session::sess_os_to_meta_os;
13+
use driver::session::sess_os_to_meta_os;
1414
use metadata::loader::meta_section_name;
1515

1616
pub fn get_target_strs(target_os: session::os) -> target_strs::t {
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
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 core::{ptr, vec, uint};
12+
use core::option::*;
13+
use core::libc::c_uint;
14+
use lib::llvm::{llvm, TypeRef, ValueRef, Integer, Pointer, Float, Double};
15+
use lib::llvm::{Struct, Array, Attribute};
16+
use lib::llvm::{StructRetAttribute, ByValAttribute};
17+
use middle::trans::common::*;
18+
use middle::trans::cabi::*;
19+
20+
fn align_up_to(off: uint, a: uint) -> uint {
21+
return (off + a - 1u) / a * a;
22+
}
23+
24+
fn align(off: uint, ty: TypeRef) -> uint {
25+
let a = ty_align(ty);
26+
return align_up_to(off, a);
27+
}
28+
29+
fn struct_tys(ty: TypeRef) -> ~[TypeRef] {
30+
unsafe {
31+
let n = llvm::LLVMCountStructElementTypes(ty);
32+
if (n == 0) {
33+
return ~[];
34+
}
35+
let mut elts = vec::from_elem(n as uint, ptr::null());
36+
llvm::LLVMGetStructElementTypes(ty,
37+
ptr::to_mut_unsafe_ptr(&mut elts[0]));
38+
return elts;
39+
}
40+
}
41+
42+
fn ty_align(ty: TypeRef) -> uint {
43+
unsafe {
44+
return match llvm::LLVMGetTypeKind(ty) {
45+
Integer => {
46+
((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8
47+
}
48+
Pointer => 4,
49+
Float => 4,
50+
Double => 8,
51+
Struct => {
52+
do vec::foldl(1, struct_tys(ty)) |a, t| {
53+
uint::max(a, ty_align(*t))
54+
}
55+
}
56+
Array => {
57+
let elt = llvm::LLVMGetElementType(ty);
58+
ty_align(elt)
59+
}
60+
_ => fail!(~"ty_size: unhandled type")
61+
};
62+
}
63+
}
64+
65+
fn ty_size(ty: TypeRef) -> uint {
66+
unsafe {
67+
return match llvm::LLVMGetTypeKind(ty) {
68+
Integer => {
69+
((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8
70+
}
71+
Pointer => 4,
72+
Float => 4,
73+
Double => 8,
74+
Struct => {
75+
let size = do vec::foldl(0, struct_tys(ty)) |s, t| {
76+
align(s, *t) + ty_size(*t)
77+
};
78+
align(size, ty)
79+
}
80+
Array => {
81+
let len = llvm::LLVMGetArrayLength(ty) as uint;
82+
let elt = llvm::LLVMGetElementType(ty);
83+
let eltsz = ty_size(elt);
84+
len * eltsz
85+
}
86+
_ => fail!(~"ty_size: unhandled type")
87+
};
88+
}
89+
}
90+
91+
fn classify_ret_ty(ty: TypeRef) -> (LLVMType, Option<Attribute>) {
92+
return if is_reg_ty(ty) {
93+
(LLVMType { cast: false, ty: ty }, None)
94+
} else {
95+
(LLVMType { cast: false, ty: T_ptr(ty) }, Some(StructRetAttribute))
96+
};
97+
}
98+
99+
fn classify_arg_ty(ty: TypeRef,
100+
offset: &mut uint) -> (LLVMType, Option<Attribute>) {
101+
let orig_offset = *offset;
102+
let size = ty_size(ty) * 8;
103+
let mut align = ty_align(ty);
104+
105+
align = uint::min(uint::max(align, 4), 8);
106+
*offset = align_up_to(*offset, align);
107+
*offset += align_up_to(size, align * 8) / 8;
108+
109+
let padding = padding_ty(align, orig_offset);
110+
return if !is_reg_ty(ty) {
111+
(LLVMType {
112+
cast: true,
113+
ty: struct_ty(ty, padding, true)
114+
}, None)
115+
} else if padding.is_some() {
116+
(LLVMType {
117+
cast: true,
118+
ty: struct_ty(ty, padding, false)
119+
}, None)
120+
} else {
121+
(LLVMType { cast: false, ty: ty }, None)
122+
};
123+
}
124+
125+
fn is_reg_ty(ty: TypeRef) -> bool {
126+
unsafe {
127+
return match llvm::LLVMGetTypeKind(ty) {
128+
Integer
129+
| Pointer
130+
| Float
131+
| Double => true,
132+
_ => false
133+
};
134+
}
135+
}
136+
137+
fn padding_ty(align: uint, offset: uint) -> Option<TypeRef> {
138+
if ((align - 1 ) & offset) > 0 {
139+
return Some(T_i32());
140+
}
141+
142+
return None;
143+
}
144+
145+
fn coerce_to_int(size: uint) -> ~[TypeRef] {
146+
let int_ty = T_i32();
147+
let mut args = ~[];
148+
149+
let mut n = size / 32;
150+
while n > 0 {
151+
args.push(int_ty);
152+
n -= 1;
153+
}
154+
155+
let r = size % 32;
156+
if r > 0 {
157+
unsafe {
158+
args.push(llvm::LLVMIntType(r as c_uint))
159+
}
160+
}
161+
162+
return args;
163+
}
164+
165+
fn struct_ty(ty: TypeRef,
166+
padding: Option<TypeRef>,
167+
coerce: bool) -> TypeRef {
168+
let size = ty_size(ty) * 8;
169+
let mut fields = padding.map_default(~[], |p| ~[*p]);
170+
171+
if coerce {
172+
fields = vec::append(fields, coerce_to_int(size));
173+
} else {
174+
fields.push(ty);
175+
}
176+
177+
return T_struct(fields);
178+
}
179+
180+
enum MIPS_ABIInfo { MIPS_ABIInfo }
181+
182+
impl ABIInfo for MIPS_ABIInfo {
183+
fn compute_info(&self,
184+
atys: &[TypeRef],
185+
rty: TypeRef,
186+
ret_def: bool) -> FnType {
187+
let mut (ret_ty, ret_attr) = if ret_def {
188+
classify_ret_ty(rty)
189+
} else {
190+
(LLVMType { cast: false, ty: T_void() }, None)
191+
};
192+
193+
let sret = ret_attr.is_some();
194+
let mut arg_tys = ~[];
195+
let mut attrs = ~[];
196+
let mut offset = if sret { 4 } else { 0 };
197+
198+
for atys.each() |aty| {
199+
let (ty, attr) = classify_arg_ty(*aty, &mut offset);
200+
arg_tys.push(ty);
201+
attrs.push(attr);
202+
};
203+
204+
if sret {
205+
arg_tys = vec::append(~[ret_ty], arg_tys);
206+
attrs = vec::append(~[ret_attr], attrs);
207+
ret_ty = LLVMType { cast: false, ty: T_void() };
208+
}
209+
210+
return FnType {
211+
arg_tys: arg_tys,
212+
ret_ty: ret_ty,
213+
attrs: attrs,
214+
sret: sret
215+
};
216+
}
217+
}
218+
219+
pub fn mips_abi_info() -> @ABIInfo {
220+
return @MIPS_ABIInfo as @ABIInfo;
221+
}

src/librustc/middle/trans/foreign.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use back::{link, abi};
1414
use driver::session;
1515
use driver::session::arch_x86_64;
1616
use driver::session::arch_arm;
17+
use driver::session::arch_mips;
1718
use lib::llvm::{SequentiallyConsistent, Acquire, Release, Xchg};
1819
use lib::llvm::{Struct, Array, ModuleRef, CallConv, Attribute};
1920
use lib::llvm::{StructRetAttribute, ByValAttribute};
@@ -23,6 +24,7 @@ use middle::trans::base::*;
2324
use middle::trans::cabi;
2425
use middle::trans::cabi_x86_64::*;
2526
use middle::trans::cabi_arm;
27+
use middle::trans::cabi_mips::*;
2628
use middle::trans::build::*;
2729
use middle::trans::callee::*;
2830
use middle::trans::common::*;
@@ -48,6 +50,7 @@ fn abi_info(arch: session::arch) -> cabi::ABIInfo {
4850
return match arch {
4951
arch_x86_64 => x86_64_abi_info(),
5052
arch_arm => cabi_arm::abi_info(),
53+
arch_mips => mips_abi_info(),
5154
_ => cabi::llvm_abi_info()
5255
}
5356
}

src/librustc/rustc.rc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ pub mod middle {
7070
pub mod cabi;
7171
pub mod cabi_x86_64;
7272
pub mod cabi_arm;
73+
pub mod cabi_mips;
7374
pub mod foreign;
7475
pub mod reflect;
7576
pub mod shape;

0 commit comments

Comments
 (0)