From 1968622798ce565fe9f3905c972513393070a78e Mon Sep 17 00:00:00 2001 From: James Miller Date: Sat, 15 Jun 2013 22:16:47 +1200 Subject: [PATCH] Start refacting LLVM Type handling --- src/librustc/lib/llvm.rs | 23 ++- src/librustc/middle/trans/context.rs | 23 ++- src/librustc/middle/trans/mod.rs | 1 + src/librustc/middle/trans/type_.rs | 269 +++++++++++++++++++++++++++ 4 files changed, 298 insertions(+), 18 deletions(-) create mode 100644 src/librustc/middle/trans/type_.rs diff --git a/src/librustc/lib/llvm.rs b/src/librustc/lib/llvm.rs index 4ed8ee6d157..14f5166b123 100644 --- a/src/librustc/lib/llvm.rs +++ b/src/librustc/lib/llvm.rs @@ -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, - named_types: HashMap<@str, TypeRef> + type_names: HashMap, + 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 { - self.named_types.find_equiv(&s).map_consume(|x| *x) + pub fn find_type(&self, s: &str) -> Option { + self.named_types.find_equiv(&s).map_consume(|x| Type::from_ref(*x)) } pub fn type_to_str(&self, ty: TypeRef) -> ~str { diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index 3a66be04585..ed5c2aa2e0b 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -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, diff --git a/src/librustc/middle/trans/mod.rs b/src/librustc/middle/trans/mod.rs index 49cadfbcc81..1345b92418e 100644 --- a/src/librustc/middle/trans/mod.rs +++ b/src/librustc/middle/trans/mod.rs @@ -42,3 +42,4 @@ pub mod reachable; pub mod machine; pub mod adt; pub mod asm; +pub mod type_; diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs new file mode 100644 index 00000000000..65f86c30ea3 --- /dev/null +++ b/src/librustc/middle/trans/type_.rs @@ -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 or the MIT license +// , 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) + } + } +}