Start refacting LLVM Type handling

This commit is contained in:
James Miller 2013-06-15 22:16:47 +12:00
parent 66d8e8b481
commit 1968622798
4 changed files with 298 additions and 18 deletions

View File

@ -17,6 +17,8 @@ use core::ptr;
use core::str;
use core::vec;
use middle::trans::type_::Type;
pub type Opcode = u32;
pub type Bool = c_uint;
@ -2121,8 +2123,8 @@ pub fn ConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef {
/* Memory-managed object interface to type handles. */
pub struct TypeNames {
type_names: HashMap<TypeRef, @str>,
named_types: HashMap<@str, TypeRef>
type_names: HashMap<TypeRef, ~str>,
named_types: HashMap<~str, TypeRef>
}
impl TypeNames {
@ -2133,17 +2135,20 @@ impl TypeNames {
}
}
pub fn associate_type(&mut self, s: @str, t: TypeRef) {
assert!(self.type_names.insert(t, s));
assert!(self.named_types.insert(s, t));
pub fn associate_type(&mut self, s: &str, t: &Type) {
assert!(self.type_names.insert(t.to_ref(), s.to_owned()));
assert!(self.named_types.insert(s.to_owned(), t.to_ref()));
}
pub fn find_name(&self, ty: &TypeRef) -> Option<@str> {
self.type_names.find_copy(ty)
pub fn find_name<'r>(&'r self, ty: &Type) -> Option<&'r str> {
match self.type_names.find(ty.to_ref()) {
Some(a) => Some(a.slice(0, a.len())),
None => None
}
}
pub fn find_type(&self, s: &str) -> Option<TypeRef> {
self.named_types.find_equiv(&s).map_consume(|x| *x)
pub fn find_type(&self, s: &str) -> Option<Type> {
self.named_types.find_equiv(&s).map_consume(|x| Type::from_ref(*x))
}
pub fn type_to_str(&self, ty: TypeRef) -> ~str {

View File

@ -27,6 +27,8 @@ use middle::trans::shape;
use middle::trans::type_use;
use middle::ty;
use middle::trans::type_::Type;
use core::hash;
use core::hashmap::{HashMap, HashSet};
use core::str;
@ -106,10 +108,10 @@ pub struct CrateContext {
maps: astencode::Maps,
stats: Stats,
upcalls: @upcall::Upcalls,
tydesc_type: TypeRef,
int_type: TypeRef,
float_type: TypeRef,
opaque_vec_type: TypeRef,
tydesc_type: Type,
int_type: Type,
float_type: Type,
opaque_vec_type: Type,
builder: BuilderRef_res,
shape_cx: shape::Ctxt,
crate_map: ValueRef,
@ -145,10 +147,13 @@ impl CrateContext {
if sess.opts.extra_debuginfo {
base::declare_dbg_intrinsics(llmod, &mut intrinsics);
}
let int_type = T_int(targ_cfg);
let float_type = T_float(targ_cfg);
let tydesc_type = T_tydesc(targ_cfg);
tn.associate_type(@"tydesc", tydesc_type);
let int_type = Type::int(targ_cfg.arch);
let float_type = Type::float(targ_cfg.arch);
let tydesc_type = Type::tydesc(targ_cfg.arch);
let opaque_vec_type = Type::opaque_vec(targ_cfg.arch);
tn.associate_type("tydesc", &tydesc_type);
let crate_map = decl_crate_map(sess, link_meta, llmod);
let dbg_cx = if sess.opts.debuginfo {
Some(debuginfo::DebugContext::new(llmod, name.to_owned()))
@ -213,7 +218,7 @@ impl CrateContext {
tydesc_type: tydesc_type,
int_type: int_type,
float_type: float_type,
opaque_vec_type: T_opaque_vec(targ_cfg),
opaque_vec_type: opaque_vec_type,
builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
shape_cx: mk_ctxt(llmod),
crate_map: crate_map,

View File

@ -42,3 +42,4 @@ pub mod reachable;
pub mod machine;
pub mod adt;
pub mod asm;
pub mod type_;

View File

@ -0,0 +1,269 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use core::prelude::*;
use lib::llvm::{llvm, TypeRef, Bool, False, True};
use middle::trans::context::CrateContext;
use middle::trans::base;
use syntax::{ast,abi};
use syntax::abi::{X86, X86_64, Arm, Mips};
use core::vec;
use core::libc::{c_uint};
pub struct Type {
priv rf: TypeRef
}
macro_rules! ty (
($e:expr) => ( Type::from_ref(unsafe {
}))
)
/**
* Wrapper for LLVM TypeRef
*/
impl Type {
pub fn from_ref(r: TypeRef) -> Type {
Type {
rf: r
}
}
pub fn to_ref(&self) -> TypeRef {
self.rf
}
pub fn void() -> Type {
ty!(llvm::LLVMVoidTypeInContext(base::task_llcx()))
}
pub fn nil() -> Type {
Type::empty_struct()
}
pub fn metadata() -> Type {
ty!(llvm::LLVMMetadataTypeInContext(base::task_llcx()))
}
pub fn i1() -> Type {
ty!(llvm::LLVMInt1TypeInContext(base::task_llcx()))
}
pub fn i8() -> Type {
ty!(llvm::LLVMInt8TypeInContext(base::task_llcx()))
}
pub fn i16() -> Type {
ty!(llvm::LLVMInt16TypeInContext(base::task_llcx()))
}
pub fn i32() -> Type {
ty!(llvm::LLVMInt32TypeInContext(base::task_llcx()))
}
pub fn i64() -> Type {
ty!(llvm::LLVMInt64TypeInContext(base::task_llcx()))
}
pub fn f32() -> Type {
ty!(llvm::LLVMFloatTypeInContext(base::task_llcx()))
}
pub fn f64() -> Type {
ty!(llvm::LLVMDoubleTypeInContext(base::task_llcx()))
}
pub fn bool() -> Type {
Type::i8()
}
pub fn char() -> Type {
Type::i32()
}
pub fn int(arch: abi::Architecture) -> Type {
match arch {
X86 | Arm | Mips => Type::i32(),
X86_64 => Type::i64()
}
}
pub fn float(_: abi::Architecture) -> Type {
// All architectures currently just use doubles as the default
// float size
Type::f64()
}
pub fn int_from_ty(ctx: &CrateContext, t: ast::int_ty) -> Type {
match t {
ast::ty_i => ctx.int_type,
ast::ty_char => Type::char(),
ast::ty_i8 => Type::i8(),
ast::ty_i16 => Type::i16(),
ast::ty_i32 => Type::i32(),
ast::ty_i64 => Type::i64()
}
}
pub fn uint_from_ty(ctx: &CrateContext, t: ast::uint_ty) -> Type {
match t {
ast::ty_u => ctx.int_type,
ast::ty_u8 => Type::i8(),
ast::ty_u16 => Type::i16(),
ast::ty_u32 => Type::i32(),
ast::ty_u64 => Type::i64()
}
}
pub fn float_from_ty(ctx: &CrateContext, t: ast::float_ty) -> Type {
match t {
ast::ty_f => ctx.float_ty,
ast::ty_f32 => Type::f32(),
ast::ty_f64 => Type::f64()
}
}
pub fn size_t(arch: abi::Architecture) -> Type {
Type::int(arch)
}
pub fn func(args: &[Type], ret: &Type) -> Type {
let vec : &[TypeRef] = unsafe { cast::transmute() };
ty!(llvm::LLVMFunctionType(ret.to_ref(), vec::raw::to_ptr(vec),
args.len() as c_uint, False))
}
pub fn func_pair(cx: &CrateContext, fn_ty: &Type) -> Type {
assert!(fn_ty.is_func(), "`fn_ty` must be a function type");
Type::struct_([fn_ty.ptr_to(), Type::opaque_cbox_ptr(cx)], false)
}
pub fn ptr(ty: Type) -> Type {
ty!(llvm::LLVMPointerType(ty, 0 as c_uint))
}
pub fn struct_(els: &[Type], packed: bool) -> Type {
let els : &[TypeRef] = unsafe { cast::transmute(els) };
ty!(llvm::LLVMStructType(vec::raw::to_ptr(els), els.len() as c_uint, packed as Bool))
}
pub fn named_struct(name: &str) -> Type {
let ctx = base::task_llcx();
ty!(name.as_c_str(|s| llvm::LLVMStructCreateNamed(ctx, s)))
}
pub fn empty_struct() -> Type {
Type::struct_([], false)
}
pub fn vtable() -> Type {
Type::array(Type::i8().ptr_to(), 1)
}
pub fn generic_glue_fn(cx: &mut CrateContext) -> Type {
match cx.tn.find_type("glue_fn") {
Some(ty) => return ty,
None => ()
}
let ty = cx.tydesc_type.get_field(abi::tydesc_field_drop_glue);
cx.tn.associate_type("glue_fn", ty);
return ty;
}
pub fn tydesc(arch: abi::Architecture) -> Type {
let mut tydesc = Type::named_struct("tydesc");
let tydescpp = tydesc.ptr_to().ptr_to();
let pvoid = Type::i8().ptr_to();
let glue_fn_ty = Type::func(
[ Type::nil.ptr_to(), tydescpp, pvoid ],
Type::void()).ptr_to();
let int_ty = Type::int(arch);
let elems = [
int_type, int_type,
glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty,
pvoid, pvoid
];
tydesc.set_struct_body(elems, false);
return tydesc;
}
pub fn array(ty: &Type, len: uint) -> Type {
ty!(llvm::LLVMArrayType(ty.to_ref(), len as c_uint))
}
pub fn vector(ty: &Type, len: uint) -> Type {
ty!(llvm::LLVMVectorType(ty.to_ref(), len as c_uint))
}
pub fn vec(arch: abi::Architecture, ty: &Type) -> Type {
Type::struct_(
[ Type::int(arch), Type::int(arch), Type::array(ty, 0) ],
false)
}
pub fn opaque_vec(arch: abi::Architecture) -> Type {
Type::vec(arch, Type::i8())
}
#[inline]
pub fn box_header_fields(ctx: &CrateContext) -> ~[Type] {
~[
ctx.int_type, ctx.tydesc_type.ptr_to(),
Type::i8().ptr_to(), Type::i8().ptr_to()
]
}
pub fn box_header(ctx: &CrateContext) -> Type {
Type::struct_(Type::box_header_fields(ctx), false)
}
pub fn box(ctx: &CrateContext, ty: &Type) -> Type {
Type::struct_(Type::box_header_fields(ctx) + [t], false)
}
pub fn opaque_box(ctx: &CrateContext) -> Type {
Type::box(ctx, Type::i8())
}
pub fn unique(ctx: &CrateContext, ty: &Type) -> Type {
Type::box(ctx, ty)
}
pub fn opaque_cbox_ptr(cx: &CrateContext) -> Type {
Type::opaque_box().ptr_to()
}
pub fn enum_discrim(cx: &CrateContext) -> Type {
cx.int_type
}
pub fn set_struct_body(&mut self, els: &[Type], packed: bool) {
assert!(self.is_struct(), "Type must be a struct");
unsafe {
let vec : &[TypeRef] = cast::transmute(els);
llvm::LLVMStructSetBody(self.to_ref(), to_ptr(vec),
els.len() as c_uint, packed as Bool)
}
}
}