Skip to content

Commit

Permalink
auto merge of #7182 : Aatch/rust/trans-refactor-pt2, r=graydon
Browse files Browse the repository at this point in the history
This is another big refactoring of `trans` though this is unlikely to have much of an
impact on code size or speed.

The major change here is the implementation of a `Type` struct which is the new
home for all your LLVM `TypeRef` needs. It's a simple wrapper struct, with static
methods for constructing types, then regular methods for
manipulating/interrogating them. The purpose of this is mostly to make the code
surrounding them somewhat more ideomatic. A line like: `T_ptr(T_ptr(T_i8()))` is 
now `Type::i8().ptr_to().ptr_to()`,which is much more like regular Rust code.

There are a variety of smaller changes here and there:

* Remove address spaces. At least it doesn't generate them, I haven't spent much
  time looking for related code.
* Use a macro for declaring the LLVM intrinsics, makes it look much nicer.
* Make the type for a string slice actually create a named `str_slice` type in LLVM,
  this makes reading the appropriate code much easier.
* Change the way struct and enum type names are generated. This just means
  that a struct like `struct Foo { a: int }` now produces the IR 
  `%struct.Foo = type { i64 }`, which is much easier to read. Similarly, other structs
  are a bit tighter to make it easier to read.

--- --- ---

This PR did get away from me a little, as I occasionally got distracted or as I fixed
up problems with unrelated code that were stopping me from continuing. One major
thing is that this PR contains the work from #7168, since that would have conflicted
with this and it was broken anyway. Sorry for bundling it like this.

Fixes #3670 and #7063

--- --- ---

EDIT: This no longer removes the llvm insn stats.
  • Loading branch information
bors committed Jun 22, 2013
2 parents f886520 + e3ef750 commit dc4560d
Show file tree
Hide file tree
Showing 45 changed files with 2,496 additions and 2,797 deletions.
61 changes: 28 additions & 33 deletions src/librustc/back/upcall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

use driver::session;
use middle::trans::base;
use middle::trans::common::{T_fn, T_i8, T_i32, T_int, T_ptr, T_void};
use lib::llvm::{ModuleRef, ValueRef, TypeRef};
use middle::trans::type_::Type;
use lib::llvm::{ModuleRef, ValueRef};

pub struct Upcalls {
trace: ValueRef,
Expand All @@ -22,40 +22,35 @@ pub struct Upcalls {
reset_stack_limit: ValueRef
}

pub fn declare_upcalls(targ_cfg: @session::config,
llmod: ModuleRef) -> @Upcalls {
fn decl(llmod: ModuleRef, prefix: ~str, name: ~str,
tys: ~[TypeRef], rv: TypeRef) ->
ValueRef {
let arg_tys = tys.map(|t| *t);
let fn_ty = T_fn(arg_tys, rv);
return base::decl_cdecl_fn(llmod, prefix + name, fn_ty);
}
fn nothrow(f: ValueRef) -> ValueRef {
base::set_no_unwind(f); f
}
let d: &fn(a: ~str, b: ~[TypeRef], c: TypeRef) -> ValueRef =
|a,b,c| decl(llmod, ~"upcall_", a, b, c);
let dv: &fn(a: ~str, b: ~[TypeRef]) -> ValueRef =
|a,b| decl(llmod, ~"upcall_", a, b, T_void());
macro_rules! upcall (
(fn $name:ident($($arg:expr),+) -> $ret:expr) => ({
let fn_ty = Type::func([ $($arg),* ], &$ret);
base::decl_cdecl_fn(llmod, ~"upcall_" + stringify!($name), fn_ty)
});
(nothrow fn $name:ident($($arg:expr),+) -> $ret:expr) => ({
let fn_ty = Type::func([ $($arg),* ], &$ret);
let decl = base::decl_cdecl_fn(llmod, ~"upcall_" + stringify!($name), fn_ty);
base::set_no_unwind(decl);
decl
});
(nothrow fn $name:ident -> $ret:expr) => ({
let fn_ty = Type::func([], &$ret);
let decl = base::decl_cdecl_fn(llmod, ~"upcall_" + stringify!($name), fn_ty);
base::set_no_unwind(decl);
decl
})
)

let int_t = T_int(targ_cfg);
pub fn declare_upcalls(targ_cfg: @session::config, llmod: ModuleRef) -> @Upcalls {
let opaque_ptr = Type::i8().ptr_to();
let int_ty = Type::int(targ_cfg.arch);

@Upcalls {
trace: dv(~"trace", ~[T_ptr(T_i8()),
T_ptr(T_i8()),
int_t]),
call_shim_on_c_stack:
d(~"call_shim_on_c_stack",
// arguments: void *args, void *fn_ptr
~[T_ptr(T_i8()), T_ptr(T_i8())],
int_t),
trace: upcall!(fn trace(opaque_ptr, opaque_ptr, int_ty) -> Type::void()),
call_shim_on_c_stack: upcall!(fn call_shim_on_c_stack(opaque_ptr, opaque_ptr) -> int_ty),
call_shim_on_rust_stack:
d(~"call_shim_on_rust_stack",
~[T_ptr(T_i8()), T_ptr(T_i8())], int_t),
rust_personality:
nothrow(d(~"rust_personality", ~[], T_i32())),
reset_stack_limit:
nothrow(dv(~"reset_stack_limit", ~[]))
upcall!(fn call_shim_on_rust_stack(opaque_ptr, opaque_ptr) -> int_ty),
rust_personality: upcall!(nothrow fn rust_personality -> Type::i32()),
reset_stack_limit: upcall!(nothrow fn reset_stack_limit -> Type::void())
}
}
205 changes: 70 additions & 135 deletions src/librustc/lib/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ use core::prelude::*;
use core::hashmap::HashMap;
use core::libc::{c_uint, c_ushort};
use core::option;
use core::ptr;
use core::str;
use core::vec;

use middle::trans::type_::Type;

pub type Opcode = u32;
pub type Bool = c_uint;
Expand Down Expand Up @@ -2121,155 +2121,90 @@ pub fn ConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef {
/* Memory-managed object interface to type handles. */

pub struct TypeNames {
type_names: @mut HashMap<TypeRef, @str>,
named_types: @mut HashMap<@str, TypeRef>
}

pub fn associate_type(tn: @TypeNames, s: @str, t: TypeRef) {
assert!(tn.type_names.insert(t, s));
assert!(tn.named_types.insert(s, t));
}

pub fn type_has_name(tn: @TypeNames, t: TypeRef) -> Option<@str> {
return tn.type_names.find(&t).map_consume(|x| *x);
type_names: HashMap<TypeRef, ~str>,
named_types: HashMap<~str, TypeRef>
}

pub fn name_has_type(tn: @TypeNames, s: @str) -> Option<TypeRef> {
return tn.named_types.find(&s).map_consume(|x| *x);
}

pub fn mk_type_names() -> @TypeNames {
@TypeNames {
type_names: @mut HashMap::new(),
named_types: @mut HashMap::new()
impl TypeNames {
pub fn new() -> TypeNames {
TypeNames {
type_names: HashMap::new(),
named_types: HashMap::new()
}
}
}

pub fn type_to_str(names: @TypeNames, ty: TypeRef) -> @str {
return type_to_str_inner(names, [], ty);
}
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 type_to_str_inner(names: @TypeNames, outer0: &[TypeRef], ty: TypeRef)
-> @str {
unsafe {
match type_has_name(names, ty) {
option::Some(n) => return n,
_ => {}
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
}
}

let outer = vec::append_one(outer0.to_owned(), ty);

let kind = llvm::LLVMGetTypeKind(ty);
pub fn find_type(&self, s: &str) -> Option<Type> {
self.named_types.find_equiv(&s).map_consume(|x| Type::from_ref(*x))
}

fn tys_str(names: @TypeNames, outer: &[TypeRef],
tys: ~[TypeRef]) -> @str {
let mut s = ~"";
let mut first: bool = true;
for tys.each |t| {
if first { first = false; } else { s += ", "; }
s += type_to_str_inner(names, outer, *t);
}
// [Note at-str] FIXME #2543: Could rewrite this without the copy,
// but need better @str support.
return s.to_managed();
pub fn type_to_str(&self, ty: Type) -> ~str {
match self.find_name(&ty) {
option::Some(name) => return name.to_owned(),
None => ()
}

match kind {
Void => return @"Void",
Half => return @"Half",
Float => return @"Float",
Double => return @"Double",
X86_FP80 => return @"X86_FP80",
FP128 => return @"FP128",
PPC_FP128 => return @"PPC_FP128",
Label => return @"Label",
Integer => {
// See [Note at-str]
return fmt!("i%d", llvm::LLVMGetIntTypeWidth(ty)
as int).to_managed();
}
Function => {
let out_ty: TypeRef = llvm::LLVMGetReturnType(ty);
let n_args = llvm::LLVMCountParamTypes(ty) as uint;
let args = vec::from_elem(n_args, 0 as TypeRef);
llvm::LLVMGetParamTypes(ty, vec::raw::to_ptr(args));
// See [Note at-str]
return fmt!("fn(%s) -> %s",
tys_str(names, outer, args),
type_to_str_inner(names, outer, out_ty)).to_managed();
}
Struct => {
let elts = struct_tys(ty);
// See [Note at-str]
return fmt!("{%s}", tys_str(names, outer, elts)).to_managed();
}
Array => {
let el_ty = llvm::LLVMGetElementType(ty);
// See [Note at-str]
return fmt!("[%s@ x %u", type_to_str_inner(names, outer, el_ty),
llvm::LLVMGetArrayLength(ty) as uint).to_managed();
}
Pointer => {
let mut i = 0;
for outer0.each |tout| {
i += 1;
if *tout as int == ty as int {
let n = outer0.len() - i;
// See [Note at-str]
return fmt!("*\\%d", n as int).to_managed();
unsafe {
let kind = ty.kind();

match kind {
Void => ~"Void",
Half => ~"Half",
Double => ~"Double",
X86_FP80 => ~"X86_FP80",
FP128 => ~"FP128",
PPC_FP128 => ~"PPC_FP128",
Label => ~"Label",
Vector => ~"Vector",
Metadata => ~"Metadata",
X86_MMX => ~"X86_MMAX",
Integer => {
fmt!("i%d", llvm::LLVMGetIntTypeWidth(ty.to_ref()) as int)
}
}
let addrstr = {
let addrspace = llvm::LLVMGetPointerAddressSpace(ty) as uint;
if addrspace == 0 {
~""
} else {
fmt!("addrspace(%u)", addrspace)
Function => {
let out_ty = ty.return_type();
let args = ty.func_params();
let args = args.map(|&ty| self.type_to_str(ty)).connect(", ");
let out_ty = self.type_to_str(out_ty);
fmt!("fn(%s) -> %s", args, out_ty)
}
Struct => {
let tys = ty.field_types();
let tys = tys.map(|&ty| self.type_to_str(ty)).connect(", ");
fmt!("{%s}", tys)
}
Array => {
let el_ty = ty.element_type();
let el_ty = self.type_to_str(el_ty);
let len = ty.array_length();
fmt!("[%s x %u]", el_ty, len)
}
Pointer => {
let el_ty = ty.element_type();
let el_ty = self.type_to_str(el_ty);
fmt!("*%s", el_ty)
}
};
// See [Note at-str]
return fmt!("%s*%s", addrstr, type_to_str_inner(names,
outer,
llvm::LLVMGetElementType(ty))).to_managed();
}
Vector => return @"Vector",
Metadata => return @"Metadata",
X86_MMX => return @"X86_MMAX",
_ => fail!()
_ => fail!("Unknown Type Kind (%u)", kind as uint)
}
}
}
}

pub fn float_width(llt: TypeRef) -> uint {
unsafe {
return match llvm::LLVMGetTypeKind(llt) as int {
1 => 32u,
2 => 64u,
3 => 80u,
4 | 5 => 128u,
_ => fail!("llvm_float_width called on a non-float type")
};
}
}

pub fn fn_ty_param_tys(fn_ty: TypeRef) -> ~[TypeRef] {
unsafe {
let args = vec::from_elem(llvm::LLVMCountParamTypes(fn_ty) as uint,
0 as TypeRef);
llvm::LLVMGetParamTypes(fn_ty, vec::raw::to_ptr(args));
return args;
}
}

pub fn struct_tys(struct_ty: TypeRef) -> ~[TypeRef] {
unsafe {
let n_elts = llvm::LLVMCountStructElementTypes(struct_ty) as uint;
if n_elts == 0 {
return ~[];
pub fn val_to_str(&self, val: ValueRef) -> ~str {
unsafe {
let ty = Type::from_ref(llvm::LLVMTypeOf(val));
self.type_to_str(ty)
}
let mut elts = vec::from_elem(n_elts, ptr::null());
llvm::LLVMGetStructElementTypes(struct_ty, &mut elts[0]);
return elts;
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ use core::prelude::*;

use middle::ty;
use middle::typeck;
use util::ppaux::{ty_to_str, region_to_str, Repr};
use util::ppaux::{ty_to_str, region_ptr_to_str, Repr};
use util::common::indenter;

use core::uint;
Expand Down Expand Up @@ -1026,7 +1026,7 @@ impl mem_categorization_ctxt {
}

pub fn region_to_str(&self, r: ty::Region) -> ~str {
region_to_str(self.tcx, r)
region_ptr_to_str(self.tcx, r)
}
}

Expand Down
Loading

0 comments on commit dc4560d

Please sign in to comment.