Skip to content

Commit 1968622

Browse files
author
James Miller
committed
Start refacting LLVM Type handling
1 parent 66d8e8b commit 1968622

File tree

4 files changed

+298
-18
lines changed

4 files changed

+298
-18
lines changed

src/librustc/lib/llvm.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ use core::ptr;
1717
use core::str;
1818
use core::vec;
1919

20+
use middle::trans::type_::Type;
21+
2022
pub type Opcode = u32;
2123
pub type Bool = c_uint;
2224

@@ -2121,8 +2123,8 @@ pub fn ConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef {
21212123
/* Memory-managed object interface to type handles. */
21222124

21232125
pub struct TypeNames {
2124-
type_names: HashMap<TypeRef, @str>,
2125-
named_types: HashMap<@str, TypeRef>
2126+
type_names: HashMap<TypeRef, ~str>,
2127+
named_types: HashMap<~str, TypeRef>
21262128
}
21272129

21282130
impl TypeNames {
@@ -2133,17 +2135,20 @@ impl TypeNames {
21332135
}
21342136
}
21352137

2136-
pub fn associate_type(&mut self, s: @str, t: TypeRef) {
2137-
assert!(self.type_names.insert(t, s));
2138-
assert!(self.named_types.insert(s, t));
2138+
pub fn associate_type(&mut self, s: &str, t: &Type) {
2139+
assert!(self.type_names.insert(t.to_ref(), s.to_owned()));
2140+
assert!(self.named_types.insert(s.to_owned(), t.to_ref()));
21392141
}
21402142

2141-
pub fn find_name(&self, ty: &TypeRef) -> Option<@str> {
2142-
self.type_names.find_copy(ty)
2143+
pub fn find_name<'r>(&'r self, ty: &Type) -> Option<&'r str> {
2144+
match self.type_names.find(ty.to_ref()) {
2145+
Some(a) => Some(a.slice(0, a.len())),
2146+
None => None
2147+
}
21432148
}
21442149

2145-
pub fn find_type(&self, s: &str) -> Option<TypeRef> {
2146-
self.named_types.find_equiv(&s).map_consume(|x| *x)
2150+
pub fn find_type(&self, s: &str) -> Option<Type> {
2151+
self.named_types.find_equiv(&s).map_consume(|x| Type::from_ref(*x))
21472152
}
21482153

21492154
pub fn type_to_str(&self, ty: TypeRef) -> ~str {

src/librustc/middle/trans/context.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ use middle::trans::shape;
2727
use middle::trans::type_use;
2828
use middle::ty;
2929

30+
use middle::trans::type_::Type;
31+
3032
use core::hash;
3133
use core::hashmap::{HashMap, HashSet};
3234
use core::str;
@@ -106,10 +108,10 @@ pub struct CrateContext {
106108
maps: astencode::Maps,
107109
stats: Stats,
108110
upcalls: @upcall::Upcalls,
109-
tydesc_type: TypeRef,
110-
int_type: TypeRef,
111-
float_type: TypeRef,
112-
opaque_vec_type: TypeRef,
111+
tydesc_type: Type,
112+
int_type: Type,
113+
float_type: Type,
114+
opaque_vec_type: Type,
113115
builder: BuilderRef_res,
114116
shape_cx: shape::Ctxt,
115117
crate_map: ValueRef,
@@ -145,10 +147,13 @@ impl CrateContext {
145147
if sess.opts.extra_debuginfo {
146148
base::declare_dbg_intrinsics(llmod, &mut intrinsics);
147149
}
148-
let int_type = T_int(targ_cfg);
149-
let float_type = T_float(targ_cfg);
150-
let tydesc_type = T_tydesc(targ_cfg);
151-
tn.associate_type(@"tydesc", tydesc_type);
150+
let int_type = Type::int(targ_cfg.arch);
151+
let float_type = Type::float(targ_cfg.arch);
152+
let tydesc_type = Type::tydesc(targ_cfg.arch);
153+
let opaque_vec_type = Type::opaque_vec(targ_cfg.arch);
154+
155+
tn.associate_type("tydesc", &tydesc_type);
156+
152157
let crate_map = decl_crate_map(sess, link_meta, llmod);
153158
let dbg_cx = if sess.opts.debuginfo {
154159
Some(debuginfo::DebugContext::new(llmod, name.to_owned()))
@@ -213,7 +218,7 @@ impl CrateContext {
213218
tydesc_type: tydesc_type,
214219
int_type: int_type,
215220
float_type: float_type,
216-
opaque_vec_type: T_opaque_vec(targ_cfg),
221+
opaque_vec_type: opaque_vec_type,
217222
builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
218223
shape_cx: mk_ctxt(llmod),
219224
crate_map: crate_map,

src/librustc/middle/trans/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,4 @@ pub mod reachable;
4242
pub mod machine;
4343
pub mod adt;
4444
pub mod asm;
45+
pub mod type_;

src/librustc/middle/trans/type_.rs

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
// Copyright 2013 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::prelude::*;
12+
13+
use lib::llvm::{llvm, TypeRef, Bool, False, True};
14+
15+
use middle::trans::context::CrateContext;
16+
use middle::trans::base;
17+
18+
use syntax::{ast,abi};
19+
use syntax::abi::{X86, X86_64, Arm, Mips};
20+
21+
use core::vec;
22+
23+
use core::libc::{c_uint};
24+
25+
pub struct Type {
26+
priv rf: TypeRef
27+
}
28+
29+
macro_rules! ty (
30+
($e:expr) => ( Type::from_ref(unsafe {
31+
32+
}))
33+
)
34+
35+
/**
36+
* Wrapper for LLVM TypeRef
37+
*/
38+
impl Type {
39+
pub fn from_ref(r: TypeRef) -> Type {
40+
Type {
41+
rf: r
42+
}
43+
}
44+
45+
pub fn to_ref(&self) -> TypeRef {
46+
self.rf
47+
}
48+
49+
pub fn void() -> Type {
50+
ty!(llvm::LLVMVoidTypeInContext(base::task_llcx()))
51+
}
52+
53+
pub fn nil() -> Type {
54+
Type::empty_struct()
55+
}
56+
57+
pub fn metadata() -> Type {
58+
ty!(llvm::LLVMMetadataTypeInContext(base::task_llcx()))
59+
}
60+
61+
pub fn i1() -> Type {
62+
ty!(llvm::LLVMInt1TypeInContext(base::task_llcx()))
63+
}
64+
65+
pub fn i8() -> Type {
66+
ty!(llvm::LLVMInt8TypeInContext(base::task_llcx()))
67+
}
68+
69+
pub fn i16() -> Type {
70+
ty!(llvm::LLVMInt16TypeInContext(base::task_llcx()))
71+
}
72+
73+
pub fn i32() -> Type {
74+
ty!(llvm::LLVMInt32TypeInContext(base::task_llcx()))
75+
}
76+
77+
pub fn i64() -> Type {
78+
ty!(llvm::LLVMInt64TypeInContext(base::task_llcx()))
79+
}
80+
81+
pub fn f32() -> Type {
82+
ty!(llvm::LLVMFloatTypeInContext(base::task_llcx()))
83+
}
84+
85+
pub fn f64() -> Type {
86+
ty!(llvm::LLVMDoubleTypeInContext(base::task_llcx()))
87+
}
88+
89+
pub fn bool() -> Type {
90+
Type::i8()
91+
}
92+
93+
pub fn char() -> Type {
94+
Type::i32()
95+
}
96+
97+
pub fn int(arch: abi::Architecture) -> Type {
98+
match arch {
99+
X86 | Arm | Mips => Type::i32(),
100+
X86_64 => Type::i64()
101+
}
102+
}
103+
104+
pub fn float(_: abi::Architecture) -> Type {
105+
// All architectures currently just use doubles as the default
106+
// float size
107+
Type::f64()
108+
}
109+
110+
pub fn int_from_ty(ctx: &CrateContext, t: ast::int_ty) -> Type {
111+
match t {
112+
ast::ty_i => ctx.int_type,
113+
ast::ty_char => Type::char(),
114+
ast::ty_i8 => Type::i8(),
115+
ast::ty_i16 => Type::i16(),
116+
ast::ty_i32 => Type::i32(),
117+
ast::ty_i64 => Type::i64()
118+
}
119+
}
120+
121+
pub fn uint_from_ty(ctx: &CrateContext, t: ast::uint_ty) -> Type {
122+
match t {
123+
ast::ty_u => ctx.int_type,
124+
ast::ty_u8 => Type::i8(),
125+
ast::ty_u16 => Type::i16(),
126+
ast::ty_u32 => Type::i32(),
127+
ast::ty_u64 => Type::i64()
128+
}
129+
}
130+
131+
pub fn float_from_ty(ctx: &CrateContext, t: ast::float_ty) -> Type {
132+
match t {
133+
ast::ty_f => ctx.float_ty,
134+
ast::ty_f32 => Type::f32(),
135+
ast::ty_f64 => Type::f64()
136+
}
137+
}
138+
139+
pub fn size_t(arch: abi::Architecture) -> Type {
140+
Type::int(arch)
141+
}
142+
143+
pub fn func(args: &[Type], ret: &Type) -> Type {
144+
let vec : &[TypeRef] = unsafe { cast::transmute() };
145+
ty!(llvm::LLVMFunctionType(ret.to_ref(), vec::raw::to_ptr(vec),
146+
args.len() as c_uint, False))
147+
}
148+
149+
pub fn func_pair(cx: &CrateContext, fn_ty: &Type) -> Type {
150+
assert!(fn_ty.is_func(), "`fn_ty` must be a function type");
151+
152+
Type::struct_([fn_ty.ptr_to(), Type::opaque_cbox_ptr(cx)], false)
153+
}
154+
155+
pub fn ptr(ty: Type) -> Type {
156+
ty!(llvm::LLVMPointerType(ty, 0 as c_uint))
157+
}
158+
159+
pub fn struct_(els: &[Type], packed: bool) -> Type {
160+
let els : &[TypeRef] = unsafe { cast::transmute(els) };
161+
ty!(llvm::LLVMStructType(vec::raw::to_ptr(els), els.len() as c_uint, packed as Bool))
162+
}
163+
164+
pub fn named_struct(name: &str) -> Type {
165+
let ctx = base::task_llcx();
166+
ty!(name.as_c_str(|s| llvm::LLVMStructCreateNamed(ctx, s)))
167+
}
168+
169+
pub fn empty_struct() -> Type {
170+
Type::struct_([], false)
171+
}
172+
173+
pub fn vtable() -> Type {
174+
Type::array(Type::i8().ptr_to(), 1)
175+
}
176+
177+
pub fn generic_glue_fn(cx: &mut CrateContext) -> Type {
178+
match cx.tn.find_type("glue_fn") {
179+
Some(ty) => return ty,
180+
None => ()
181+
}
182+
183+
let ty = cx.tydesc_type.get_field(abi::tydesc_field_drop_glue);
184+
cx.tn.associate_type("glue_fn", ty);
185+
186+
return ty;
187+
}
188+
189+
pub fn tydesc(arch: abi::Architecture) -> Type {
190+
let mut tydesc = Type::named_struct("tydesc");
191+
let tydescpp = tydesc.ptr_to().ptr_to();
192+
let pvoid = Type::i8().ptr_to();
193+
let glue_fn_ty = Type::func(
194+
[ Type::nil.ptr_to(), tydescpp, pvoid ],
195+
Type::void()).ptr_to();
196+
197+
let int_ty = Type::int(arch);
198+
199+
let elems = [
200+
int_type, int_type,
201+
glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty,
202+
pvoid, pvoid
203+
];
204+
205+
tydesc.set_struct_body(elems, false);
206+
207+
return tydesc;
208+
}
209+
210+
pub fn array(ty: &Type, len: uint) -> Type {
211+
ty!(llvm::LLVMArrayType(ty.to_ref(), len as c_uint))
212+
}
213+
214+
pub fn vector(ty: &Type, len: uint) -> Type {
215+
ty!(llvm::LLVMVectorType(ty.to_ref(), len as c_uint))
216+
}
217+
218+
pub fn vec(arch: abi::Architecture, ty: &Type) -> Type {
219+
Type::struct_(
220+
[ Type::int(arch), Type::int(arch), Type::array(ty, 0) ],
221+
false)
222+
}
223+
224+
pub fn opaque_vec(arch: abi::Architecture) -> Type {
225+
Type::vec(arch, Type::i8())
226+
}
227+
228+
#[inline]
229+
pub fn box_header_fields(ctx: &CrateContext) -> ~[Type] {
230+
~[
231+
ctx.int_type, ctx.tydesc_type.ptr_to(),
232+
Type::i8().ptr_to(), Type::i8().ptr_to()
233+
]
234+
}
235+
236+
pub fn box_header(ctx: &CrateContext) -> Type {
237+
Type::struct_(Type::box_header_fields(ctx), false)
238+
}
239+
240+
pub fn box(ctx: &CrateContext, ty: &Type) -> Type {
241+
Type::struct_(Type::box_header_fields(ctx) + [t], false)
242+
}
243+
244+
pub fn opaque_box(ctx: &CrateContext) -> Type {
245+
Type::box(ctx, Type::i8())
246+
}
247+
248+
pub fn unique(ctx: &CrateContext, ty: &Type) -> Type {
249+
Type::box(ctx, ty)
250+
}
251+
252+
pub fn opaque_cbox_ptr(cx: &CrateContext) -> Type {
253+
Type::opaque_box().ptr_to()
254+
}
255+
256+
pub fn enum_discrim(cx: &CrateContext) -> Type {
257+
cx.int_type
258+
}
259+
260+
pub fn set_struct_body(&mut self, els: &[Type], packed: bool) {
261+
assert!(self.is_struct(), "Type must be a struct");
262+
263+
unsafe {
264+
let vec : &[TypeRef] = cast::transmute(els);
265+
llvm::LLVMStructSetBody(self.to_ref(), to_ptr(vec),
266+
els.len() as c_uint, packed as Bool)
267+
}
268+
}
269+
}

0 commit comments

Comments
 (0)