mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-25 23:14:12 +00:00
Start refacting LLVM Type handling
This commit is contained in:
parent
66d8e8b481
commit
1968622798
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -42,3 +42,4 @@ pub mod reachable;
|
||||
pub mod machine;
|
||||
pub mod adt;
|
||||
pub mod asm;
|
||||
pub mod type_;
|
||||
|
269
src/librustc/middle/trans/type_.rs
Normal file
269
src/librustc/middle/trans/type_.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user