auto merge of #7182 : Aatch/rust/trans-refactor-pt2, r=graydon
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.
This commit is contained in:
commit
dc4560dc26
@ -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,
|
||||
@ -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())
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
@ -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>
|
||||
type_names: HashMap<TypeRef, ~str>,
|
||||
named_types: 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);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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: Type) -> ~str {
|
||||
match self.find_name(&ty) {
|
||||
option::Some(name) => return name.to_owned(),
|
||||
None => ()
|
||||
}
|
||||
|
||||
let outer = vec::append_one(outer0.to_owned(), ty);
|
||||
unsafe {
|
||||
let kind = ty.kind();
|
||||
|
||||
let kind = llvm::LLVMGetTypeKind(ty);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
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)
|
||||
}
|
||||
};
|
||||
// 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!()
|
||||
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)
|
||||
}
|
||||
_ => 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,7 +259,7 @@ pub enum opt_result {
|
||||
range_result(Result, Result),
|
||||
}
|
||||
pub fn trans_opt(bcx: block, o: &Opt) -> opt_result {
|
||||
let _icx = bcx.insn_ctxt("match::trans_opt");
|
||||
let _icx = push_ctxt("match::trans_opt");
|
||||
let ccx = bcx.ccx();
|
||||
let bcx = bcx;
|
||||
match *o {
|
||||
@ -381,7 +381,7 @@ pub fn expand_nested_bindings<'r>(bcx: block,
|
||||
bcx.to_str(),
|
||||
matches_to_str(bcx, m),
|
||||
col,
|
||||
bcx.val_str(val));
|
||||
bcx.val_to_str(val));
|
||||
let _indenter = indenter();
|
||||
|
||||
do m.map |br| {
|
||||
@ -428,7 +428,7 @@ pub fn enter_match<'r>(bcx: block,
|
||||
bcx.to_str(),
|
||||
matches_to_str(bcx, m),
|
||||
col,
|
||||
bcx.val_str(val));
|
||||
bcx.val_to_str(val));
|
||||
let _indenter = indenter();
|
||||
|
||||
let mut result = ~[];
|
||||
@ -474,7 +474,7 @@ pub fn enter_default<'r>(bcx: block,
|
||||
bcx.to_str(),
|
||||
matches_to_str(bcx, m),
|
||||
col,
|
||||
bcx.val_str(val));
|
||||
bcx.val_to_str(val));
|
||||
let _indenter = indenter();
|
||||
|
||||
do enter_match(bcx, dm, m, col, val) |p| {
|
||||
@ -521,7 +521,7 @@ pub fn enter_opt<'r>(bcx: block,
|
||||
bcx.to_str(),
|
||||
matches_to_str(bcx, m),
|
||||
col,
|
||||
bcx.val_str(val));
|
||||
bcx.val_to_str(val));
|
||||
let _indenter = indenter();
|
||||
|
||||
let tcx = bcx.tcx();
|
||||
@ -632,7 +632,7 @@ pub fn enter_rec_or_struct<'r>(bcx: block,
|
||||
bcx.to_str(),
|
||||
matches_to_str(bcx, m),
|
||||
col,
|
||||
bcx.val_str(val));
|
||||
bcx.val_to_str(val));
|
||||
let _indenter = indenter();
|
||||
|
||||
let dummy = @ast::pat {id: 0, node: ast::pat_wild, span: dummy_sp()};
|
||||
@ -667,7 +667,7 @@ pub fn enter_tup<'r>(bcx: block,
|
||||
bcx.to_str(),
|
||||
matches_to_str(bcx, m),
|
||||
col,
|
||||
bcx.val_str(val));
|
||||
bcx.val_to_str(val));
|
||||
let _indenter = indenter();
|
||||
|
||||
let dummy = @ast::pat {id: 0, node: ast::pat_wild, span: dummy_sp()};
|
||||
@ -695,7 +695,7 @@ pub fn enter_tuple_struct<'r>(bcx: block,
|
||||
bcx.to_str(),
|
||||
matches_to_str(bcx, m),
|
||||
col,
|
||||
bcx.val_str(val));
|
||||
bcx.val_to_str(val));
|
||||
let _indenter = indenter();
|
||||
|
||||
let dummy = @ast::pat {id: 0, node: ast::pat_wild, span: dummy_sp()};
|
||||
@ -720,7 +720,7 @@ pub fn enter_box<'r>(bcx: block,
|
||||
bcx.to_str(),
|
||||
matches_to_str(bcx, m),
|
||||
col,
|
||||
bcx.val_str(val));
|
||||
bcx.val_to_str(val));
|
||||
let _indenter = indenter();
|
||||
|
||||
let dummy = @ast::pat {id: 0, node: ast::pat_wild, span: dummy_sp()};
|
||||
@ -747,7 +747,7 @@ pub fn enter_uniq<'r>(bcx: block,
|
||||
bcx.to_str(),
|
||||
matches_to_str(bcx, m),
|
||||
col,
|
||||
bcx.val_str(val));
|
||||
bcx.val_to_str(val));
|
||||
let _indenter = indenter();
|
||||
|
||||
let dummy = @ast::pat {id: 0, node: ast::pat_wild, span: dummy_sp()};
|
||||
@ -774,7 +774,7 @@ pub fn enter_region<'r>(bcx: block,
|
||||
bcx.to_str(),
|
||||
matches_to_str(bcx, m),
|
||||
col,
|
||||
bcx.val_str(val));
|
||||
bcx.val_to_str(val));
|
||||
let _indenter = indenter();
|
||||
|
||||
let dummy = @ast::pat { id: 0, node: ast::pat_wild, span: dummy_sp() };
|
||||
@ -870,7 +870,7 @@ pub fn extract_variant_args(bcx: block,
|
||||
disr_val: int,
|
||||
val: ValueRef)
|
||||
-> ExtractedBlock {
|
||||
let _icx = bcx.insn_ctxt("match::extract_variant_args");
|
||||
let _icx = push_ctxt("match::extract_variant_args");
|
||||
let args = do vec::from_fn(adt::num_args(repr, disr_val)) |i| {
|
||||
adt::trans_field_ptr(bcx, repr, val, disr_val, i)
|
||||
};
|
||||
@ -896,7 +896,7 @@ pub fn extract_vec_elems(bcx: block,
|
||||
val: ValueRef,
|
||||
count: ValueRef)
|
||||
-> ExtractedBlock {
|
||||
let _icx = bcx.insn_ctxt("match::extract_vec_elems");
|
||||
let _icx = push_ctxt("match::extract_vec_elems");
|
||||
let vec_datum = match_datum(bcx, val, pat_id);
|
||||
let (bcx, base, len) = vec_datum.get_vec_base_and_len(bcx, pat_span,
|
||||
pat_id, 0);
|
||||
@ -911,7 +911,7 @@ pub fn extract_vec_elems(bcx: block,
|
||||
Sub(bcx, count,
|
||||
C_int(bcx.ccx(), (elem_count - i) as int))])
|
||||
}
|
||||
_ => unsafe { llvm::LLVMGetUndef(vt.llunit_ty) }
|
||||
_ => unsafe { llvm::LLVMGetUndef(vt.llunit_ty.to_ref()) }
|
||||
}
|
||||
};
|
||||
if slice.is_some() {
|
||||
@ -1088,7 +1088,7 @@ pub fn compare_values(cx: block,
|
||||
rhs: ValueRef,
|
||||
rhs_t: ty::t)
|
||||
-> Result {
|
||||
let _icx = cx.insn_ctxt("compare_values");
|
||||
let _icx = push_ctxt("compare_values");
|
||||
if ty::type_is_scalar(rhs_t) {
|
||||
let rs = compare_scalar_types(cx, lhs, rhs, rhs_t, ast::eq);
|
||||
return rslt(rs.bcx, rs.val);
|
||||
@ -1202,9 +1202,7 @@ fn insert_lllocals(bcx: block,
|
||||
}
|
||||
};
|
||||
|
||||
debug!("binding %? to %s",
|
||||
binding_info.id,
|
||||
val_str(bcx.ccx().tn, llval));
|
||||
debug!("binding %? to %s", binding_info.id, bcx.val_to_str(llval));
|
||||
llmap.insert(binding_info.id, llval);
|
||||
}
|
||||
return bcx;
|
||||
@ -1221,7 +1219,7 @@ pub fn compile_guard(bcx: block,
|
||||
bcx.to_str(),
|
||||
bcx.expr_to_str(guard_expr),
|
||||
matches_to_str(bcx, m),
|
||||
vals.map(|v| bcx.val_str(*v)));
|
||||
vals.map(|v| bcx.val_to_str(*v)));
|
||||
let _indenter = indenter();
|
||||
|
||||
let mut bcx = bcx;
|
||||
@ -1272,14 +1270,14 @@ pub fn compile_submatch(bcx: block,
|
||||
debug!("compile_submatch(bcx=%s, m=%s, vals=%?)",
|
||||
bcx.to_str(),
|
||||
matches_to_str(bcx, m),
|
||||
vals.map(|v| bcx.val_str(*v)));
|
||||
vals.map(|v| bcx.val_to_str(*v)));
|
||||
let _indenter = indenter();
|
||||
|
||||
/*
|
||||
For an empty match, a fall-through case must exist
|
||||
*/
|
||||
assert!((m.len() > 0u || chk.is_some()));
|
||||
let _icx = bcx.insn_ctxt("match::compile_submatch");
|
||||
let _icx = push_ctxt("match::compile_submatch");
|
||||
let mut bcx = bcx;
|
||||
let tcx = bcx.tcx();
|
||||
let dm = tcx.def_map;
|
||||
@ -1391,9 +1389,7 @@ pub fn compile_submatch(bcx: block,
|
||||
if any_box_pat(m, col) {
|
||||
bcx = root_pats_as_necessary(bcx, m, col, val);
|
||||
let llbox = Load(bcx, val);
|
||||
let box_no_addrspace = non_gc_box_cast(bcx, llbox);
|
||||
let unboxed =
|
||||
GEPi(bcx, box_no_addrspace, [0u, abi::box_field_body]);
|
||||
let unboxed = GEPi(bcx, llbox, [0u, abi::box_field_body]);
|
||||
compile_submatch(bcx, enter_box(bcx, dm, m, col, val),
|
||||
vec::append(~[unboxed], vals_left), chk);
|
||||
return;
|
||||
@ -1401,9 +1397,7 @@ pub fn compile_submatch(bcx: block,
|
||||
|
||||
if any_uniq_pat(m, col) {
|
||||
let llbox = Load(bcx, val);
|
||||
let box_no_addrspace = non_gc_box_cast(bcx, llbox);
|
||||
let unboxed =
|
||||
GEPi(bcx, box_no_addrspace, [0u, abi::box_field_body]);
|
||||
let unboxed = GEPi(bcx, llbox, [0u, abi::box_field_body]);
|
||||
compile_submatch(bcx, enter_uniq(bcx, dm, m, col, val),
|
||||
vec::append(~[unboxed], vals_left), chk);
|
||||
return;
|
||||
@ -1619,7 +1613,7 @@ pub fn trans_match(bcx: block,
|
||||
discr_expr: @ast::expr,
|
||||
arms: ~[ast::arm],
|
||||
dest: Dest) -> block {
|
||||
let _icx = bcx.insn_ctxt("match::trans_match");
|
||||
let _icx = push_ctxt("match::trans_match");
|
||||
do with_scope(bcx, match_expr.info(), "match") |bcx| {
|
||||
trans_match_inner(bcx, discr_expr, arms, dest)
|
||||
}
|
||||
@ -1646,7 +1640,7 @@ fn create_bindings_map(bcx: block, pat: @ast::pat) -> BindingsMap {
|
||||
// but during matching we need to store a *T as explained
|
||||
// above
|
||||
let is_move = ccx.maps.moves_map.contains(&p_id);
|
||||
llmatch = alloca(bcx, T_ptr(llvariable_ty));
|
||||
llmatch = alloca(bcx, llvariable_ty.ptr_to());
|
||||
trmode = TrByValue(is_move, alloca(bcx, llvariable_ty));
|
||||
}
|
||||
ast::bind_by_ref(_) => {
|
||||
@ -1666,7 +1660,7 @@ pub fn trans_match_inner(scope_cx: block,
|
||||
discr_expr: @ast::expr,
|
||||
arms: &[ast::arm],
|
||||
dest: Dest) -> block {
|
||||
let _icx = scope_cx.insn_ctxt("match::trans_match_inner");
|
||||
let _icx = push_ctxt("match::trans_match_inner");
|
||||
let mut bcx = scope_cx;
|
||||
let tcx = bcx.tcx();
|
||||
|
||||
@ -1753,7 +1747,7 @@ pub fn bind_irrefutable_pat(bcx: block,
|
||||
make_copy: bool,
|
||||
binding_mode: IrrefutablePatternBindingMode)
|
||||
-> block {
|
||||
let _icx = bcx.insn_ctxt("match::bind_irrefutable_pat");
|
||||
let _icx = push_ctxt("match::bind_irrefutable_pat");
|
||||
let ccx = bcx.fcx.ccx;
|
||||
let mut bcx = bcx;
|
||||
|
||||
|
@ -49,7 +49,7 @@ use core::libc::c_ulonglong;
|
||||
use core::option::{Option, Some, None};
|
||||
use core::vec;
|
||||
|
||||
use lib::llvm::{ValueRef, TypeRef, True, IntEQ, IntNE};
|
||||
use lib::llvm::{ValueRef, True, IntEQ, IntNE};
|
||||
use middle::trans::_match;
|
||||
use middle::trans::build::*;
|
||||
use middle::trans::common::*;
|
||||
@ -59,6 +59,8 @@ use middle::ty;
|
||||
use syntax::ast;
|
||||
use util::ppaux::ty_to_str;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
|
||||
/// Representations.
|
||||
pub enum Repr {
|
||||
@ -212,7 +214,7 @@ fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr {
|
||||
|
||||
fn mk_struct(cx: &mut CrateContext, tys: &[ty::t], packed: bool) -> Struct {
|
||||
let lltys = tys.map(|&ty| type_of::sizing_type_of(cx, ty));
|
||||
let llty_rec = T_struct(lltys, packed);
|
||||
let llty_rec = Type::struct_(lltys, packed);
|
||||
Struct {
|
||||
size: machine::llsize_of_alloc(cx, llty_rec) /*bad*/as u64,
|
||||
align: machine::llalign_of_min(cx, llty_rec) /*bad*/as u64,
|
||||
@ -226,17 +228,16 @@ fn mk_struct(cx: &mut CrateContext, tys: &[ty::t], packed: bool) -> Struct {
|
||||
* All nominal types are LLVM structs, in order to be able to use
|
||||
* forward-declared opaque types to prevent circularity in `type_of`.
|
||||
*/
|
||||
pub fn fields_of(cx: &mut CrateContext, r: &Repr) -> ~[TypeRef] {
|
||||
pub fn fields_of(cx: &mut CrateContext, r: &Repr) -> ~[Type] {
|
||||
generic_fields_of(cx, r, false)
|
||||
}
|
||||
/// Like `fields_of`, but for `type_of::sizing_type_of` (q.v.).
|
||||
pub fn sizing_fields_of(cx: &mut CrateContext, r: &Repr) -> ~[TypeRef] {
|
||||
pub fn sizing_fields_of(cx: &mut CrateContext, r: &Repr) -> ~[Type] {
|
||||
generic_fields_of(cx, r, true)
|
||||
}
|
||||
fn generic_fields_of(cx: &mut CrateContext, r: &Repr, sizing: bool)
|
||||
-> ~[TypeRef] {
|
||||
fn generic_fields_of(cx: &mut CrateContext, r: &Repr, sizing: bool) -> ~[Type] {
|
||||
match *r {
|
||||
CEnum(*) => ~[T_enum_discrim(cx)],
|
||||
CEnum(*) => ~[Type::enum_discrim(cx)],
|
||||
Univariant(ref st, _dtor) => struct_llfields(cx, st, sizing),
|
||||
NullablePointer{ nonnull: ref st, _ } => struct_llfields(cx, st, sizing),
|
||||
General(ref sts) => {
|
||||
@ -262,13 +263,12 @@ fn generic_fields_of(cx: &mut CrateContext, r: &Repr, sizing: bool)
|
||||
let padding = largest_size - most_aligned.size;
|
||||
|
||||
struct_llfields(cx, most_aligned, sizing)
|
||||
+ [T_array(T_i8(), padding /*bad*/as uint)]
|
||||
+ [Type::array(&Type::i8(), padding)]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn struct_llfields(cx: &mut CrateContext, st: &Struct, sizing: bool)
|
||||
-> ~[TypeRef] {
|
||||
fn struct_llfields(cx: &mut CrateContext, st: &Struct, sizing: bool) -> ~[Type] {
|
||||
if sizing {
|
||||
st.fields.map(|&ty| type_of::sizing_type_of(cx, ty))
|
||||
} else {
|
||||
@ -309,7 +309,7 @@ pub fn trans_get_discr(bcx: block, r: &Repr, scrutinee: ValueRef)
|
||||
(cases.len() - 1) as int),
|
||||
NullablePointer{ nonnull: ref nonnull, nndiscr, ptrfield, _ } => {
|
||||
ZExt(bcx, nullable_bitdiscr(bcx, nonnull, nndiscr, ptrfield, scrutinee),
|
||||
T_enum_discrim(bcx.ccx()))
|
||||
Type::enum_discrim(bcx.ccx()))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -438,11 +438,11 @@ pub fn trans_field_ptr(bcx: block, r: &Repr, val: ValueRef, discr: int,
|
||||
} else {
|
||||
// The unit-like case might have a nonzero number of unit-like fields.
|
||||
// (e.g., Result or Either with () as one side.)
|
||||
let llty = type_of::type_of(bcx.ccx(), nullfields[ix]);
|
||||
assert_eq!(machine::llsize_of_alloc(bcx.ccx(), llty), 0);
|
||||
let ty = type_of::type_of(bcx.ccx(), nullfields[ix]);
|
||||
assert_eq!(machine::llsize_of_alloc(bcx.ccx(), ty), 0);
|
||||
// The contents of memory at this pointer can't matter, but use
|
||||
// the value that's "reasonable" in case of pointer comparison.
|
||||
PointerCast(bcx, val, T_ptr(llty))
|
||||
PointerCast(bcx, val, ty.ptr_to())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -456,8 +456,8 @@ fn struct_field_ptr(bcx: block, st: &Struct, val: ValueRef, ix: uint,
|
||||
let fields = do st.fields.map |&ty| {
|
||||
type_of::type_of(ccx, ty)
|
||||
};
|
||||
let real_llty = T_struct(fields, st.packed);
|
||||
PointerCast(bcx, val, T_ptr(real_llty))
|
||||
let real_ty = Type::struct_(fields, st.packed);
|
||||
PointerCast(bcx, val, real_ty.ptr_to())
|
||||
} else {
|
||||
val
|
||||
};
|
||||
@ -572,7 +572,7 @@ fn build_const_struct(ccx: &mut CrateContext, st: &Struct, vals: &[ValueRef])
|
||||
}
|
||||
|
||||
fn padding(size: u64) -> ValueRef {
|
||||
C_undef(T_array(T_i8(), size /*bad*/as uint))
|
||||
C_undef(Type::array(&Type::i8(), size))
|
||||
}
|
||||
|
||||
// XXX this utility routine should be somewhere more general
|
||||
|
@ -20,6 +20,8 @@ use middle::trans::callee;
|
||||
use middle::trans::common::*;
|
||||
use middle::ty;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use core::str;
|
||||
use syntax::ast;
|
||||
|
||||
@ -110,11 +112,11 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
|
||||
|
||||
// Depending on how many outputs we have, the return type is different
|
||||
let output = if numOutputs == 0 {
|
||||
T_void()
|
||||
Type::void()
|
||||
} else if numOutputs == 1 {
|
||||
val_ty(outputs[0])
|
||||
} else {
|
||||
T_struct(outputs.map(|o| val_ty(*o)), false)
|
||||
Type::struct_(outputs.map(|o| val_ty(*o)), false)
|
||||
};
|
||||
|
||||
let dialect = match ia.dialect {
|
||||
@ -130,12 +132,12 @@ pub fn trans_inline_asm(bcx: block, ia: &ast::inline_asm) -> block {
|
||||
|
||||
// Again, based on how many outputs we have
|
||||
if numOutputs == 1 {
|
||||
let op = PointerCast(bcx, aoutputs[0], T_ptr(val_ty(outputs[0])));
|
||||
let op = PointerCast(bcx, aoutputs[0], val_ty(outputs[0]).ptr_to());
|
||||
Store(bcx, r, op);
|
||||
} else {
|
||||
for aoutputs.iter().enumerate().advance |(i, o)| {
|
||||
let v = ExtractValue(bcx, r, i);
|
||||
let op = PointerCast(bcx, *o, T_ptr(val_ty(outputs[i])));
|
||||
let op = PointerCast(bcx, *o, val_ty(outputs[i]).ptr_to());
|
||||
Store(bcx, v, op);
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -13,15 +13,18 @@ use core::prelude::*;
|
||||
use lib::llvm::llvm;
|
||||
use lib::llvm::{CallConv, AtomicBinOp, AtomicOrdering, AsmDialect};
|
||||
use lib::llvm::{Opcode, IntPredicate, RealPredicate, False};
|
||||
use lib::llvm::{ValueRef, TypeRef, BasicBlockRef, BuilderRef, ModuleRef};
|
||||
use lib::llvm::{ValueRef, BasicBlockRef, BuilderRef, ModuleRef};
|
||||
use lib;
|
||||
use middle::trans::common::*;
|
||||
use middle::trans::machine::llalign_of_min;
|
||||
use syntax::codemap::span;
|
||||
|
||||
use middle::trans::base;
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use core::cast;
|
||||
use core::hashmap::HashMap;
|
||||
use core::libc::{c_uint, c_ulonglong, c_char};
|
||||
use core::hashmap::HashMap;
|
||||
use core::str;
|
||||
use core::vec;
|
||||
|
||||
@ -44,10 +47,8 @@ pub fn B(cx: block) -> BuilderRef {
|
||||
}
|
||||
|
||||
pub fn count_insn(cx: block, category: &str) {
|
||||
if cx.ccx().sess.count_llvm_insns() {
|
||||
|
||||
do base::with_insn_ctxt |v| {
|
||||
let h = &mut cx.ccx().stats.llvm_insns;
|
||||
let v : &[~str] = cx.ccx().stats.llvm_insn_ctxt;
|
||||
|
||||
// Build version of path with cycles removed.
|
||||
|
||||
@ -186,13 +187,13 @@ pub fn Invoke(cx: block,
|
||||
Catch: BasicBlockRef)
|
||||
-> ValueRef {
|
||||
if cx.unreachable {
|
||||
return C_null(T_i8());
|
||||
return C_null(Type::i8());
|
||||
}
|
||||
check_not_terminated(cx);
|
||||
terminate(cx, "Invoke");
|
||||
debug!("Invoke(%s with arguments (%s))",
|
||||
val_str(cx.ccx().tn, Fn),
|
||||
Args.map(|a| val_str(cx.ccx().tn, *a).to_owned()).connect(", "));
|
||||
cx.val_to_str(Fn),
|
||||
Args.map(|a| cx.val_to_str(*a)).connect(", "));
|
||||
unsafe {
|
||||
count_insn(cx, "invoke");
|
||||
llvm::LLVMBuildInvoke(B(cx),
|
||||
@ -232,7 +233,7 @@ pub fn Unreachable(cx: block) {
|
||||
|
||||
pub fn _Undef(val: ValueRef) -> ValueRef {
|
||||
unsafe {
|
||||
return llvm::LLVMGetUndef(val_ty(val));
|
||||
return llvm::LLVMGetUndef(val_ty(val).to_ref());
|
||||
}
|
||||
}
|
||||
|
||||
@ -486,35 +487,35 @@ pub fn Not(cx: block, V: ValueRef) -> ValueRef {
|
||||
}
|
||||
|
||||
/* Memory */
|
||||
pub fn Malloc(cx: block, Ty: TypeRef) -> ValueRef {
|
||||
pub fn Malloc(cx: block, Ty: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_i8())); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Type::i8p().to_ref()); }
|
||||
count_insn(cx, "malloc");
|
||||
return llvm::LLVMBuildMalloc(B(cx), Ty, noname());
|
||||
return llvm::LLVMBuildMalloc(B(cx), Ty.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ArrayMalloc(cx: block, Ty: TypeRef, Val: ValueRef) -> ValueRef {
|
||||
pub fn ArrayMalloc(cx: block, Ty: Type, Val: ValueRef) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_i8())); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Type::i8p().to_ref()); }
|
||||
count_insn(cx, "arraymalloc");
|
||||
return llvm::LLVMBuildArrayMalloc(B(cx), Ty, Val, noname());
|
||||
return llvm::LLVMBuildArrayMalloc(B(cx), Ty.to_ref(), Val, noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn Alloca(cx: block, Ty: TypeRef) -> ValueRef {
|
||||
pub fn Alloca(cx: block, Ty: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(Ty)); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Ty.ptr_to().to_ref()); }
|
||||
count_insn(cx, "alloca");
|
||||
return llvm::LLVMBuildAlloca(B(cx), Ty, noname());
|
||||
return llvm::LLVMBuildAlloca(B(cx), Ty.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ArrayAlloca(cx: block, Ty: TypeRef, Val: ValueRef) -> ValueRef {
|
||||
pub fn ArrayAlloca(cx: block, Ty: Type, Val: ValueRef) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(Ty)); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Ty.ptr_to().to_ref()); }
|
||||
count_insn(cx, "arrayalloca");
|
||||
return llvm::LLVMBuildArrayAlloca(B(cx), Ty, Val, noname());
|
||||
return llvm::LLVMBuildArrayAlloca(B(cx), Ty.to_ref(), Val, noname());
|
||||
}
|
||||
}
|
||||
|
||||
@ -531,9 +532,12 @@ pub fn Load(cx: block, PointerVal: ValueRef) -> ValueRef {
|
||||
let ccx = cx.fcx.ccx;
|
||||
if cx.unreachable {
|
||||
let ty = val_ty(PointerVal);
|
||||
let eltty = if llvm::LLVMGetTypeKind(ty) == lib::llvm::Array {
|
||||
llvm::LLVMGetElementType(ty) } else { ccx.int_type };
|
||||
return llvm::LLVMGetUndef(eltty);
|
||||
let eltty = if ty.kind() == lib::llvm::Array {
|
||||
ty.element_type()
|
||||
} else {
|
||||
ccx.int_type
|
||||
};
|
||||
return llvm::LLVMGetUndef(eltty.to_ref());
|
||||
}
|
||||
count_insn(cx, "load");
|
||||
return llvm::LLVMBuildLoad(B(cx), PointerVal, noname());
|
||||
@ -544,7 +548,7 @@ pub fn AtomicLoad(cx: block, PointerVal: ValueRef, order: AtomicOrdering) -> Val
|
||||
unsafe {
|
||||
let ccx = cx.fcx.ccx;
|
||||
if cx.unreachable {
|
||||
return llvm::LLVMGetUndef(ccx.int_type);
|
||||
return llvm::LLVMGetUndef(ccx.int_type.to_ref());
|
||||
}
|
||||
count_insn(cx, "load.atomic");
|
||||
let align = llalign_of_min(ccx, ccx.int_type);
|
||||
@ -576,8 +580,8 @@ pub fn Store(cx: block, Val: ValueRef, Ptr: ValueRef) {
|
||||
unsafe {
|
||||
if cx.unreachable { return; }
|
||||
debug!("Store %s -> %s",
|
||||
val_str(cx.ccx().tn, Val),
|
||||
val_str(cx.ccx().tn, Ptr));
|
||||
cx.val_to_str(Val),
|
||||
cx.val_to_str(Ptr));
|
||||
count_insn(cx, "store");
|
||||
llvm::LLVMBuildStore(B(cx), Val, Ptr);
|
||||
}
|
||||
@ -587,8 +591,8 @@ pub fn AtomicStore(cx: block, Val: ValueRef, Ptr: ValueRef, order: AtomicOrderin
|
||||
unsafe {
|
||||
if cx.unreachable { return; }
|
||||
debug!("Store %s -> %s",
|
||||
val_str(cx.ccx().tn, Val),
|
||||
val_str(cx.ccx().tn, Ptr));
|
||||
cx.val_to_str(Val),
|
||||
cx.val_to_str(Ptr));
|
||||
count_insn(cx, "store.atomic");
|
||||
let align = llalign_of_min(cx.ccx(), cx.ccx().int_type);
|
||||
llvm::LLVMBuildAtomicStore(B(cx), Val, Ptr, order, align as c_uint);
|
||||
@ -597,7 +601,7 @@ pub fn AtomicStore(cx: block, Val: ValueRef, Ptr: ValueRef, order: AtomicOrderin
|
||||
|
||||
pub fn GEP(cx: block, Pointer: ValueRef, Indices: &[ValueRef]) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_nil())); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref()); }
|
||||
count_insn(cx, "gep");
|
||||
return llvm::LLVMBuildGEP(B(cx), Pointer, vec::raw::to_ptr(Indices),
|
||||
Indices.len() as c_uint, noname());
|
||||
@ -614,21 +618,18 @@ pub fn GEPi(cx: block, base: ValueRef, ixs: &[uint]) -> ValueRef {
|
||||
return InBoundsGEP(cx, base, v);
|
||||
}
|
||||
|
||||
pub fn InBoundsGEP(cx: block, Pointer: ValueRef, Indices: &[ValueRef]) ->
|
||||
ValueRef {
|
||||
pub fn InBoundsGEP(cx: block, Pointer: ValueRef, Indices: &[ValueRef]) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_nil())); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref()); }
|
||||
count_insn(cx, "inboundsgep");
|
||||
return llvm::LLVMBuildInBoundsGEP(B(cx), Pointer,
|
||||
vec::raw::to_ptr(Indices),
|
||||
Indices.len() as c_uint,
|
||||
noname());
|
||||
return llvm::LLVMBuildInBoundsGEP(
|
||||
B(cx), Pointer, vec::raw::to_ptr(Indices), Indices.len() as c_uint, noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn StructGEP(cx: block, Pointer: ValueRef, Idx: uint) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_nil())); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref()); }
|
||||
count_insn(cx, "structgep");
|
||||
return llvm::LLVMBuildStructGEP(B(cx),
|
||||
Pointer,
|
||||
@ -639,7 +640,7 @@ pub fn StructGEP(cx: block, Pointer: ValueRef, Idx: uint) -> ValueRef {
|
||||
|
||||
pub fn GlobalString(cx: block, _Str: *c_char) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_i8())); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Type::i8p().to_ref()); }
|
||||
count_insn(cx, "globalstring");
|
||||
return llvm::LLVMBuildGlobalString(B(cx), _Str, noname());
|
||||
}
|
||||
@ -647,163 +648,163 @@ pub fn GlobalString(cx: block, _Str: *c_char) -> ValueRef {
|
||||
|
||||
pub fn GlobalStringPtr(cx: block, _Str: *c_char) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(T_ptr(T_i8())); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Type::i8p().to_ref()); }
|
||||
count_insn(cx, "globalstringptr");
|
||||
return llvm::LLVMBuildGlobalStringPtr(B(cx), _Str, noname());
|
||||
}
|
||||
}
|
||||
|
||||
/* Casts */
|
||||
pub fn Trunc(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
pub fn Trunc(cx: block, Val: ValueRef, DestTy: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); }
|
||||
count_insn(cx, "trunc");
|
||||
return llvm::LLVMBuildTrunc(B(cx), Val, DestTy, noname());
|
||||
return llvm::LLVMBuildTrunc(B(cx), Val, DestTy.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ZExt(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
pub fn ZExt(cx: block, Val: ValueRef, DestTy: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); }
|
||||
count_insn(cx, "zext");
|
||||
return llvm::LLVMBuildZExt(B(cx), Val, DestTy, noname());
|
||||
return llvm::LLVMBuildZExt(B(cx), Val, DestTy.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn SExt(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
pub fn SExt(cx: block, Val: ValueRef, DestTy: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); }
|
||||
count_insn(cx, "sext");
|
||||
return llvm::LLVMBuildSExt(B(cx), Val, DestTy, noname());
|
||||
return llvm::LLVMBuildSExt(B(cx), Val, DestTy.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn FPToUI(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
pub fn FPToUI(cx: block, Val: ValueRef, DestTy: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); }
|
||||
count_insn(cx, "fptoui");
|
||||
return llvm::LLVMBuildFPToUI(B(cx), Val, DestTy, noname());
|
||||
return llvm::LLVMBuildFPToUI(B(cx), Val, DestTy.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn FPToSI(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
pub fn FPToSI(cx: block, Val: ValueRef, DestTy: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); }
|
||||
count_insn(cx, "fptosi");
|
||||
return llvm::LLVMBuildFPToSI(B(cx), Val, DestTy, noname());
|
||||
return llvm::LLVMBuildFPToSI(B(cx), Val, DestTy.to_ref(),noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn UIToFP(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
pub fn UIToFP(cx: block, Val: ValueRef, DestTy: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); }
|
||||
count_insn(cx, "uitofp");
|
||||
return llvm::LLVMBuildUIToFP(B(cx), Val, DestTy, noname());
|
||||
return llvm::LLVMBuildUIToFP(B(cx), Val, DestTy.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn SIToFP(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
pub fn SIToFP(cx: block, Val: ValueRef, DestTy: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); }
|
||||
count_insn(cx, "sitofp");
|
||||
return llvm::LLVMBuildSIToFP(B(cx), Val, DestTy, noname());
|
||||
return llvm::LLVMBuildSIToFP(B(cx), Val, DestTy.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn FPTrunc(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
pub fn FPTrunc(cx: block, Val: ValueRef, DestTy: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); }
|
||||
count_insn(cx, "fptrunc");
|
||||
return llvm::LLVMBuildFPTrunc(B(cx), Val, DestTy, noname());
|
||||
return llvm::LLVMBuildFPTrunc(B(cx), Val, DestTy.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn FPExt(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
pub fn FPExt(cx: block, Val: ValueRef, DestTy: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); }
|
||||
count_insn(cx, "fpext");
|
||||
return llvm::LLVMBuildFPExt(B(cx), Val, DestTy, noname());
|
||||
return llvm::LLVMBuildFPExt(B(cx), Val, DestTy.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn PtrToInt(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
pub fn PtrToInt(cx: block, Val: ValueRef, DestTy: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); }
|
||||
count_insn(cx, "ptrtoint");
|
||||
return llvm::LLVMBuildPtrToInt(B(cx), Val, DestTy, noname());
|
||||
return llvm::LLVMBuildPtrToInt(B(cx), Val, DestTy.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn IntToPtr(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
pub fn IntToPtr(cx: block, Val: ValueRef, DestTy: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); }
|
||||
count_insn(cx, "inttoptr");
|
||||
return llvm::LLVMBuildIntToPtr(B(cx), Val, DestTy, noname());
|
||||
return llvm::LLVMBuildIntToPtr(B(cx), Val, DestTy.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn BitCast(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
pub fn BitCast(cx: block, Val: ValueRef, DestTy: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); }
|
||||
count_insn(cx, "bitcast");
|
||||
return llvm::LLVMBuildBitCast(B(cx), Val, DestTy, noname());
|
||||
return llvm::LLVMBuildBitCast(B(cx), Val, DestTy.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ZExtOrBitCast(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
pub fn ZExtOrBitCast(cx: block, Val: ValueRef, DestTy: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); }
|
||||
count_insn(cx, "zextorbitcast");
|
||||
return llvm::LLVMBuildZExtOrBitCast(B(cx), Val, DestTy, noname());
|
||||
return llvm::LLVMBuildZExtOrBitCast(B(cx), Val, DestTy.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn SExtOrBitCast(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
pub fn SExtOrBitCast(cx: block, Val: ValueRef, DestTy: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); }
|
||||
count_insn(cx, "sextorbitcast");
|
||||
return llvm::LLVMBuildSExtOrBitCast(B(cx), Val, DestTy, noname());
|
||||
return llvm::LLVMBuildSExtOrBitCast(B(cx), Val, DestTy.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn TruncOrBitCast(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
pub fn TruncOrBitCast(cx: block, Val: ValueRef, DestTy: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); }
|
||||
count_insn(cx, "truncorbitcast");
|
||||
return llvm::LLVMBuildTruncOrBitCast(B(cx), Val, DestTy, noname());
|
||||
return llvm::LLVMBuildTruncOrBitCast(B(cx), Val, DestTy.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn Cast(cx: block, Op: Opcode, Val: ValueRef, DestTy: TypeRef, _: *u8)
|
||||
pub fn Cast(cx: block, Op: Opcode, Val: ValueRef, DestTy: Type, _: *u8)
|
||||
-> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
||||
count_insn(cx, "cast");
|
||||
return llvm::LLVMBuildCast(B(cx), Op, Val, DestTy, noname());
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); }
|
||||
return llvm::LLVMBuildCast(B(cx), Op, Val, DestTy.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn PointerCast(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
pub fn PointerCast(cx: block, Val: ValueRef, DestTy: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); }
|
||||
count_insn(cx, "pointercast");
|
||||
return llvm::LLVMBuildPointerCast(B(cx), Val, DestTy, noname());
|
||||
return llvm::LLVMBuildPointerCast(B(cx), Val, DestTy.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn IntCast(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
pub fn IntCast(cx: block, Val: ValueRef, DestTy: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); }
|
||||
count_insn(cx, "intcast");
|
||||
return llvm::LLVMBuildIntCast(B(cx), Val, DestTy, noname());
|
||||
return llvm::LLVMBuildIntCast(B(cx), Val, DestTy.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn FPCast(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
pub fn FPCast(cx: block, Val: ValueRef, DestTy: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(DestTy.to_ref()); }
|
||||
count_insn(cx, "fpcast");
|
||||
return llvm::LLVMBuildFPCast(B(cx), Val, DestTy, noname());
|
||||
return llvm::LLVMBuildFPCast(B(cx), Val, DestTy.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
@ -812,7 +813,7 @@ pub fn FPCast(cx: block, Val: ValueRef, DestTy: TypeRef) -> ValueRef {
|
||||
pub fn ICmp(cx: block, Op: IntPredicate, LHS: ValueRef, RHS: ValueRef)
|
||||
-> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(T_i1()); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Type::i1().to_ref()); }
|
||||
count_insn(cx, "icmp");
|
||||
return llvm::LLVMBuildICmp(B(cx), Op as c_uint, LHS, RHS, noname());
|
||||
}
|
||||
@ -821,25 +822,25 @@ pub fn ICmp(cx: block, Op: IntPredicate, LHS: ValueRef, RHS: ValueRef)
|
||||
pub fn FCmp(cx: block, Op: RealPredicate, LHS: ValueRef, RHS: ValueRef)
|
||||
-> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(T_i1()); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Type::i1().to_ref()); }
|
||||
count_insn(cx, "fcmp");
|
||||
return llvm::LLVMBuildFCmp(B(cx), Op as c_uint, LHS, RHS, noname());
|
||||
}
|
||||
}
|
||||
|
||||
/* Miscellaneous instructions */
|
||||
pub fn EmptyPhi(cx: block, Ty: TypeRef) -> ValueRef {
|
||||
pub fn EmptyPhi(cx: block, Ty: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Ty); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Ty.to_ref()); }
|
||||
count_insn(cx, "emptyphi");
|
||||
return llvm::LLVMBuildPhi(B(cx), Ty, noname());
|
||||
return llvm::LLVMBuildPhi(B(cx), Ty.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn Phi(cx: block, Ty: TypeRef, vals: &[ValueRef], bbs: &[BasicBlockRef])
|
||||
pub fn Phi(cx: block, Ty: Type, vals: &[ValueRef], bbs: &[BasicBlockRef])
|
||||
-> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Ty); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Ty.to_ref()); }
|
||||
assert_eq!(vals.len(), bbs.len());
|
||||
let phi = EmptyPhi(cx, Ty);
|
||||
count_insn(cx, "addincoming");
|
||||
@ -863,10 +864,13 @@ pub fn _UndefReturn(cx: block, Fn: ValueRef) -> ValueRef {
|
||||
unsafe {
|
||||
let ccx = cx.fcx.ccx;
|
||||
let ty = val_ty(Fn);
|
||||
let retty = if llvm::LLVMGetTypeKind(ty) == lib::llvm::Integer {
|
||||
llvm::LLVMGetReturnType(ty) } else { ccx.int_type };
|
||||
count_insn(cx, "");
|
||||
return llvm::LLVMGetUndef(retty);
|
||||
let retty = if ty.kind() == lib::llvm::Integer {
|
||||
ty.return_type()
|
||||
} else {
|
||||
ccx.int_type
|
||||
};
|
||||
count_insn(cx, "ret_undef");
|
||||
return llvm::LLVMGetUndef(retty.to_ref());
|
||||
}
|
||||
}
|
||||
|
||||
@ -886,20 +890,18 @@ pub fn add_comment(bcx: block, text: &str) {
|
||||
let sanitized = text.replace("$", "");
|
||||
let comment_text = ~"# " +
|
||||
sanitized.replace("\n", "\n\t# ");
|
||||
let asm = str::as_c_str(comment_text, |c| {
|
||||
str::as_c_str("", |e| {
|
||||
count_insn(bcx, "inlineasm");
|
||||
llvm::LLVMConstInlineAsm(T_fn([], T_void()), c, e,
|
||||
False, False)
|
||||
})
|
||||
});
|
||||
count_insn(bcx, "inlineasm");
|
||||
let asm = do comment_text.as_c_str |c| {
|
||||
llvm::LLVMConstInlineAsm(Type::func([], &Type::void()).to_ref(),
|
||||
c, noname(), False, False)
|
||||
};
|
||||
Call(bcx, asm, []);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn InlineAsmCall(cx: block, asm: *c_char, cons: *c_char,
|
||||
inputs: &[ValueRef], output: TypeRef,
|
||||
inputs: &[ValueRef], output: Type,
|
||||
volatile: bool, alignstack: bool,
|
||||
dia: AsmDialect) -> ValueRef {
|
||||
unsafe {
|
||||
@ -911,14 +913,13 @@ pub fn InlineAsmCall(cx: block, asm: *c_char, cons: *c_char,
|
||||
else { lib::llvm::False };
|
||||
|
||||
let argtys = do inputs.map |v| {
|
||||
debug!("Asm Input Type: %?", val_str(cx.ccx().tn, *v));
|
||||
debug!("Asm Input Type: %?", cx.val_to_str(*v));
|
||||
val_ty(*v)
|
||||
};
|
||||
|
||||
debug!("Asm Output Type: %?", ty_str(cx.ccx().tn, output));
|
||||
let llfty = T_fn(argtys, output);
|
||||
let v = llvm::LLVMInlineAsm(llfty, asm, cons, volatile,
|
||||
alignstack, dia as c_uint);
|
||||
debug!("Asm Output Type: %?", cx.ccx().tn.type_to_str(output));
|
||||
let fty = Type::func(argtys, &output);
|
||||
let v = llvm::LLVMInlineAsm(fty.to_ref(), asm, cons, volatile, alignstack, dia as c_uint);
|
||||
|
||||
Call(cx, v, inputs)
|
||||
}
|
||||
@ -930,8 +931,8 @@ pub fn Call(cx: block, Fn: ValueRef, Args: &[ValueRef]) -> ValueRef {
|
||||
count_insn(cx, "call");
|
||||
|
||||
debug!("Call(Fn=%s, Args=%?)",
|
||||
val_str(cx.ccx().tn, Fn),
|
||||
Args.map(|arg| val_str(cx.ccx().tn, *arg)));
|
||||
cx.val_to_str(Fn),
|
||||
Args.map(|arg| cx.val_to_str(*arg)));
|
||||
|
||||
do vec::as_imm_buf(Args) |ptr, len| {
|
||||
llvm::LLVMBuildCall(B(cx), Fn, ptr, len as c_uint, noname())
|
||||
@ -971,18 +972,18 @@ pub fn Select(cx: block, If: ValueRef, Then: ValueRef, Else: ValueRef) ->
|
||||
}
|
||||
}
|
||||
|
||||
pub fn VAArg(cx: block, list: ValueRef, Ty: TypeRef) -> ValueRef {
|
||||
pub fn VAArg(cx: block, list: ValueRef, Ty: Type) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Ty); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Ty.to_ref()); }
|
||||
count_insn(cx, "vaarg");
|
||||
return llvm::LLVMBuildVAArg(B(cx), list, Ty, noname());
|
||||
return llvm::LLVMBuildVAArg(B(cx), list, Ty.to_ref(), noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ExtractElement(cx: block, VecVal: ValueRef, Index: ValueRef) ->
|
||||
ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(T_nil()); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Type::nil().to_ref()); }
|
||||
count_insn(cx, "extractelement");
|
||||
return llvm::LLVMBuildExtractElement(B(cx), VecVal, Index, noname());
|
||||
}
|
||||
@ -991,7 +992,7 @@ pub fn ExtractElement(cx: block, VecVal: ValueRef, Index: ValueRef) ->
|
||||
pub fn InsertElement(cx: block, VecVal: ValueRef, EltVal: ValueRef,
|
||||
Index: ValueRef) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(T_nil()); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Type::nil().to_ref()); }
|
||||
count_insn(cx, "insertelement");
|
||||
llvm::LLVMBuildInsertElement(B(cx), VecVal, EltVal, Index, noname())
|
||||
}
|
||||
@ -1000,7 +1001,7 @@ pub fn InsertElement(cx: block, VecVal: ValueRef, EltVal: ValueRef,
|
||||
pub fn ShuffleVector(cx: block, V1: ValueRef, V2: ValueRef,
|
||||
Mask: ValueRef) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(T_nil()); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Type::nil().to_ref()); }
|
||||
count_insn(cx, "shufflevector");
|
||||
llvm::LLVMBuildShuffleVector(B(cx), V1, V2, Mask, noname())
|
||||
}
|
||||
@ -1008,15 +1009,16 @@ pub fn ShuffleVector(cx: block, V1: ValueRef, V2: ValueRef,
|
||||
|
||||
pub fn VectorSplat(cx: block, NumElts: uint, EltVal: ValueRef) -> ValueRef {
|
||||
unsafe {
|
||||
let Undef = llvm::LLVMGetUndef(T_vector(val_ty(EltVal), NumElts));
|
||||
let elt_ty = val_ty(EltVal);
|
||||
let Undef = llvm::LLVMGetUndef(Type::vector(&elt_ty, NumElts as u64).to_ref());
|
||||
let VecVal = InsertElement(cx, Undef, EltVal, C_i32(0));
|
||||
ShuffleVector(cx, VecVal, Undef, C_null(T_vector(T_i32(), NumElts)))
|
||||
ShuffleVector(cx, VecVal, Undef, C_null(Type::vector(&Type::i32(), NumElts as u64)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ExtractValue(cx: block, AggVal: ValueRef, Index: uint) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(T_nil()); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Type::nil().to_ref()); }
|
||||
count_insn(cx, "extractvalue");
|
||||
return llvm::LLVMBuildExtractValue(
|
||||
B(cx), AggVal, Index as c_uint, noname());
|
||||
@ -1035,7 +1037,7 @@ pub fn InsertValue(cx: block, AggVal: ValueRef, EltVal: ValueRef,
|
||||
|
||||
pub fn IsNull(cx: block, Val: ValueRef) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(T_i1()); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Type::i1().to_ref()); }
|
||||
count_insn(cx, "isnull");
|
||||
return llvm::LLVMBuildIsNull(B(cx), Val, noname());
|
||||
}
|
||||
@ -1043,7 +1045,7 @@ pub fn IsNull(cx: block, Val: ValueRef) -> ValueRef {
|
||||
|
||||
pub fn IsNotNull(cx: block, Val: ValueRef) -> ValueRef {
|
||||
unsafe {
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(T_i1()); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(Type::i1().to_ref()); }
|
||||
count_insn(cx, "isnotnull");
|
||||
return llvm::LLVMBuildIsNotNull(B(cx), Val, noname());
|
||||
}
|
||||
@ -1052,7 +1054,7 @@ pub fn IsNotNull(cx: block, Val: ValueRef) -> ValueRef {
|
||||
pub fn PtrDiff(cx: block, LHS: ValueRef, RHS: ValueRef) -> ValueRef {
|
||||
unsafe {
|
||||
let ccx = cx.fcx.ccx;
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(ccx.int_type); }
|
||||
if cx.unreachable { return llvm::LLVMGetUndef(ccx.int_type.to_ref()); }
|
||||
count_insn(cx, "ptrdiff");
|
||||
return llvm::LLVMBuildPtrDiff(B(cx), LHS, RHS, noname());
|
||||
}
|
||||
@ -1071,19 +1073,18 @@ pub fn Trap(cx: block) {
|
||||
assert!((T as int != 0));
|
||||
let Args: ~[ValueRef] = ~[];
|
||||
count_insn(cx, "trap");
|
||||
llvm::LLVMBuildCall(b, T, vec::raw::to_ptr(Args),
|
||||
Args.len() as c_uint, noname());
|
||||
llvm::LLVMBuildCall(b, T, vec::raw::to_ptr(Args), Args.len() as c_uint, noname());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn LandingPad(cx: block, Ty: TypeRef, PersFn: ValueRef,
|
||||
pub fn LandingPad(cx: block, Ty: Type, PersFn: ValueRef,
|
||||
NumClauses: uint) -> ValueRef {
|
||||
unsafe {
|
||||
check_not_terminated(cx);
|
||||
assert!(!cx.unreachable);
|
||||
count_insn(cx, "landingpad");
|
||||
return llvm::LLVMBuildLandingPad(B(cx), Ty, PersFn,
|
||||
NumClauses as c_uint, noname());
|
||||
return llvm::LLVMBuildLandingPad(
|
||||
B(cx), Ty.to_ref(), PersFn, NumClauses as c_uint, noname());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,25 +8,24 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use lib::llvm::{llvm, TypeRef, ValueRef, Attribute, Void};
|
||||
use lib::llvm::{llvm, ValueRef, Attribute, Void};
|
||||
use middle::trans::base::*;
|
||||
use middle::trans::build::*;
|
||||
use middle::trans::common::*;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use core::libc::c_uint;
|
||||
use core::option;
|
||||
use core::vec;
|
||||
|
||||
pub trait ABIInfo {
|
||||
fn compute_info(&self,
|
||||
atys: &[TypeRef],
|
||||
rty: TypeRef,
|
||||
ret_def: bool) -> FnType;
|
||||
fn compute_info(&self, atys: &[Type], rty: Type, ret_def: bool) -> FnType;
|
||||
}
|
||||
|
||||
pub struct LLVMType {
|
||||
cast: bool,
|
||||
ty: TypeRef
|
||||
ty: Type
|
||||
}
|
||||
|
||||
pub struct FnType {
|
||||
@ -37,10 +36,10 @@ pub struct FnType {
|
||||
}
|
||||
|
||||
impl FnType {
|
||||
pub fn decl_fn(&self, decl: &fn(fnty: TypeRef) -> ValueRef) -> ValueRef {
|
||||
pub fn decl_fn(&self, decl: &fn(fnty: Type) -> ValueRef) -> ValueRef {
|
||||
let atys = vec::map(self.arg_tys, |t| t.ty);
|
||||
let rty = self.ret_ty.ty;
|
||||
let fnty = T_fn(atys, rty);
|
||||
let fnty = Type::func(atys, &rty);
|
||||
let llfn = decl(fnty);
|
||||
|
||||
for self.attrs.iter().enumerate().advance |(i, a)| {
|
||||
@ -57,10 +56,7 @@ impl FnType {
|
||||
return llfn;
|
||||
}
|
||||
|
||||
pub fn build_shim_args(&self,
|
||||
bcx: block,
|
||||
arg_tys: &[TypeRef],
|
||||
llargbundle: ValueRef)
|
||||
pub fn build_shim_args(&self, bcx: block, arg_tys: &[Type], llargbundle: ValueRef)
|
||||
-> ~[ValueRef] {
|
||||
let mut atys: &[LLVMType] = self.arg_tys;
|
||||
let mut attrs: &[option::Option<Attribute>] = self.attrs;
|
||||
@ -80,7 +76,7 @@ impl FnType {
|
||||
while i < n {
|
||||
let llargval = if atys[i].cast {
|
||||
let arg_ptr = GEPi(bcx, llargbundle, [0u, i]);
|
||||
let arg_ptr = BitCast(bcx, arg_ptr, T_ptr(atys[i].ty));
|
||||
let arg_ptr = BitCast(bcx, arg_ptr, atys[i].ty.ptr_to());
|
||||
Load(bcx, arg_ptr)
|
||||
} else if attrs[i].is_some() {
|
||||
GEPi(bcx, llargbundle, [0u, i])
|
||||
@ -94,19 +90,13 @@ impl FnType {
|
||||
return llargvals;
|
||||
}
|
||||
|
||||
pub fn build_shim_ret(&self,
|
||||
bcx: block,
|
||||
arg_tys: &[TypeRef],
|
||||
ret_def: bool,
|
||||
llargbundle: ValueRef,
|
||||
llretval: ValueRef) {
|
||||
pub fn build_shim_ret(&self, bcx: block, arg_tys: &[Type], ret_def: bool,
|
||||
llargbundle: ValueRef, llretval: ValueRef) {
|
||||
for self.attrs.iter().enumerate().advance |(i, a)| {
|
||||
match *a {
|
||||
option::Some(attr) => {
|
||||
unsafe {
|
||||
llvm::LLVMAddInstrAttribute(llretval,
|
||||
(i + 1u) as c_uint,
|
||||
attr as c_uint);
|
||||
llvm::LLVMAddInstrAttribute(llretval, (i + 1u) as c_uint, attr as c_uint);
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
@ -121,7 +111,7 @@ impl FnType {
|
||||
// R* llretloc = *llretptr; /* (args->r) */
|
||||
let llretloc = Load(bcx, llretptr);
|
||||
if self.ret_ty.cast {
|
||||
let tmp_ptr = BitCast(bcx, llretloc, T_ptr(self.ret_ty.ty));
|
||||
let tmp_ptr = BitCast(bcx, llretloc, self.ret_ty.ty.ptr_to());
|
||||
// *args->r = r;
|
||||
Store(bcx, llretval, tmp_ptr);
|
||||
} else {
|
||||
@ -130,11 +120,8 @@ impl FnType {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn build_wrap_args(&self,
|
||||
bcx: block,
|
||||
ret_ty: TypeRef,
|
||||
llwrapfn: ValueRef,
|
||||
llargbundle: ValueRef) {
|
||||
pub fn build_wrap_args(&self, bcx: block, ret_ty: Type,
|
||||
llwrapfn: ValueRef, llargbundle: ValueRef) {
|
||||
let mut atys: &[LLVMType] = self.arg_tys;
|
||||
let mut attrs: &[option::Option<Attribute>] = self.attrs;
|
||||
let mut j = 0u;
|
||||
@ -145,7 +132,7 @@ impl FnType {
|
||||
get_param(llwrapfn, 0u)
|
||||
} else if self.ret_ty.cast {
|
||||
let retptr = alloca(bcx, self.ret_ty.ty);
|
||||
BitCast(bcx, retptr, T_ptr(ret_ty))
|
||||
BitCast(bcx, retptr, ret_ty.ptr_to())
|
||||
} else {
|
||||
alloca(bcx, ret_ty)
|
||||
};
|
||||
@ -159,7 +146,7 @@ impl FnType {
|
||||
store_inbounds(bcx, argval, llargbundle, [0u, i]);
|
||||
} else if atys[i].cast {
|
||||
let argptr = GEPi(bcx, llargbundle, [0u, i]);
|
||||
let argptr = BitCast(bcx, argptr, T_ptr(atys[i].ty));
|
||||
let argptr = BitCast(bcx, argptr, atys[i].ty.ptr_to());
|
||||
Store(bcx, argval, argptr);
|
||||
} else {
|
||||
store_inbounds(bcx, argval, llargbundle, [0u, i]);
|
||||
@ -169,27 +156,20 @@ impl FnType {
|
||||
store_inbounds(bcx, llretptr, llargbundle, [0u, n]);
|
||||
}
|
||||
|
||||
pub fn build_wrap_ret(&self,
|
||||
bcx: block,
|
||||
arg_tys: &[TypeRef],
|
||||
llargbundle: ValueRef) {
|
||||
unsafe {
|
||||
if llvm::LLVMGetTypeKind(self.ret_ty.ty) == Void {
|
||||
return;
|
||||
}
|
||||
pub fn build_wrap_ret(&self, bcx: block, arg_tys: &[Type], llargbundle: ValueRef) {
|
||||
if self.ret_ty.ty.kind() == Void {
|
||||
return;
|
||||
}
|
||||
|
||||
if bcx.fcx.llretptr.is_some() {
|
||||
let llretval = load_inbounds(bcx, llargbundle, [ 0, arg_tys.len() ]);
|
||||
let llretval = if self.ret_ty.cast {
|
||||
let retptr = BitCast(bcx, llretval, T_ptr(self.ret_ty.ty));
|
||||
let retptr = BitCast(bcx, llretval, self.ret_ty.ty.ptr_to());
|
||||
Load(bcx, retptr)
|
||||
} else {
|
||||
Load(bcx, llretval)
|
||||
};
|
||||
let llretptr = BitCast(bcx,
|
||||
bcx.fcx.llretptr.get(),
|
||||
T_ptr(self.ret_ty.ty));
|
||||
let llretptr = BitCast(bcx, bcx.fcx.llretptr.get(), self.ret_ty.ty.ptr_to());
|
||||
Store(bcx, llretval, llretptr);
|
||||
}
|
||||
}
|
||||
|
@ -9,13 +9,10 @@
|
||||
// except according to those terms.
|
||||
|
||||
use lib::llvm::{llvm, Integer, Pointer, Float, Double, Struct, Array};
|
||||
use lib::llvm::struct_tys;
|
||||
use lib::llvm::TypeRef;
|
||||
use lib::llvm::{Attribute, StructRetAttribute};
|
||||
use lib::llvm::True;
|
||||
use middle::trans::cabi::{ABIInfo, FnType, LLVMType};
|
||||
use middle::trans::common::{T_i8, T_i16, T_i32, T_i64};
|
||||
use middle::trans::common::{T_array, T_ptr, T_void};
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use core::option::{Option, None, Some};
|
||||
use core::uint;
|
||||
@ -24,108 +21,106 @@ fn align_up_to(off: uint, a: uint) -> uint {
|
||||
return (off + a - 1u) / a * a;
|
||||
}
|
||||
|
||||
fn align(off: uint, ty: TypeRef) -> uint {
|
||||
fn align(off: uint, ty: Type) -> uint {
|
||||
let a = ty_align(ty);
|
||||
return align_up_to(off, a);
|
||||
}
|
||||
|
||||
fn ty_align(ty: TypeRef) -> uint {
|
||||
unsafe {
|
||||
return match llvm::LLVMGetTypeKind(ty) {
|
||||
Integer => {
|
||||
((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8
|
||||
fn ty_align(ty: Type) -> uint {
|
||||
match ty.kind() {
|
||||
Integer => {
|
||||
unsafe {
|
||||
((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
|
||||
}
|
||||
Pointer => 4,
|
||||
Float => 4,
|
||||
Double => 8,
|
||||
Struct => {
|
||||
if llvm::LLVMIsPackedStruct(ty) == True {
|
||||
1
|
||||
} else {
|
||||
let str_tys = struct_tys(ty);
|
||||
str_tys.iter().fold(1, |a, t| uint::max(a, ty_align(*t)))
|
||||
}
|
||||
}
|
||||
Pointer => 4,
|
||||
Float => 4,
|
||||
Double => 8,
|
||||
Struct => {
|
||||
if ty.is_packed() {
|
||||
1
|
||||
} else {
|
||||
let str_tys = ty.field_types();
|
||||
str_tys.iter().fold(1, |a, t| uint::max(a, ty_align(*t)))
|
||||
}
|
||||
Array => {
|
||||
let elt = llvm::LLVMGetElementType(ty);
|
||||
ty_align(elt)
|
||||
}
|
||||
_ => fail!("ty_align: unhandled type")
|
||||
};
|
||||
}
|
||||
Array => {
|
||||
let elt = ty.element_type();
|
||||
ty_align(elt)
|
||||
}
|
||||
_ => fail!("ty_align: unhandled type")
|
||||
}
|
||||
}
|
||||
|
||||
fn ty_size(ty: TypeRef) -> uint {
|
||||
unsafe {
|
||||
return match llvm::LLVMGetTypeKind(ty) {
|
||||
Integer => {
|
||||
((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8
|
||||
fn ty_size(ty: Type) -> uint {
|
||||
match ty.kind() {
|
||||
Integer => {
|
||||
unsafe {
|
||||
((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
|
||||
}
|
||||
Pointer => 4,
|
||||
Float => 4,
|
||||
Double => 8,
|
||||
Struct => {
|
||||
if llvm::LLVMIsPackedStruct(ty) == True {
|
||||
let str_tys = struct_tys(ty);
|
||||
str_tys.iter().fold(0, |s, t| s + ty_size(*t))
|
||||
} else {
|
||||
let str_tys = struct_tys(ty);
|
||||
let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
|
||||
align(size, ty)
|
||||
}
|
||||
}
|
||||
Pointer => 4,
|
||||
Float => 4,
|
||||
Double => 8,
|
||||
Struct => {
|
||||
if ty.is_packed() {
|
||||
let str_tys = ty.field_types();
|
||||
str_tys.iter().fold(0, |s, t| s + ty_size(*t))
|
||||
} else {
|
||||
let str_tys = ty.field_types();
|
||||
let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
|
||||
align(size, ty)
|
||||
}
|
||||
Array => {
|
||||
let len = llvm::LLVMGetArrayLength(ty) as uint;
|
||||
let elt = llvm::LLVMGetElementType(ty);
|
||||
let eltsz = ty_size(elt);
|
||||
len * eltsz
|
||||
}
|
||||
_ => fail!("ty_size: unhandled type")
|
||||
};
|
||||
}
|
||||
Array => {
|
||||
let len = ty.array_length();
|
||||
let elt = ty.element_type();
|
||||
let eltsz = ty_size(elt);
|
||||
len * eltsz
|
||||
}
|
||||
_ => fail!("ty_size: unhandled type")
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_ret_ty(ty: TypeRef) -> (LLVMType, Option<Attribute>) {
|
||||
fn classify_ret_ty(ty: Type) -> (LLVMType, Option<Attribute>) {
|
||||
if is_reg_ty(ty) {
|
||||
return (LLVMType { cast: false, ty: ty }, None);
|
||||
}
|
||||
let size = ty_size(ty);
|
||||
if size <= 4 {
|
||||
let llty = if size <= 1 {
|
||||
T_i8()
|
||||
Type::i8()
|
||||
} else if size <= 2 {
|
||||
T_i16()
|
||||
Type::i16()
|
||||
} else {
|
||||
T_i32()
|
||||
Type::i32()
|
||||
};
|
||||
return (LLVMType { cast: true, ty: llty }, None);
|
||||
}
|
||||
(LLVMType { cast: false, ty: T_ptr(ty) }, Some(StructRetAttribute))
|
||||
(LLVMType { cast: false, ty: ty.ptr_to() }, Some(StructRetAttribute))
|
||||
}
|
||||
|
||||
fn classify_arg_ty(ty: TypeRef) -> (LLVMType, Option<Attribute>) {
|
||||
fn classify_arg_ty(ty: Type) -> (LLVMType, Option<Attribute>) {
|
||||
if is_reg_ty(ty) {
|
||||
return (LLVMType { cast: false, ty: ty }, None);
|
||||
}
|
||||
let align = ty_align(ty);
|
||||
let size = ty_size(ty);
|
||||
let llty = if align <= 4 {
|
||||
T_array(T_i32(), (size + 3) / 4)
|
||||
Type::array(&Type::i32(), (size + 3) / 4 as u64)
|
||||
} else {
|
||||
T_array(T_i64(), (size + 7) / 8)
|
||||
Type::array(&Type::i64(), (size + 7) / 8 as u64)
|
||||
};
|
||||
(LLVMType { cast: true, ty: llty }, None)
|
||||
}
|
||||
|
||||
fn is_reg_ty(ty: TypeRef) -> bool {
|
||||
unsafe {
|
||||
return match llvm::LLVMGetTypeKind(ty) {
|
||||
Integer
|
||||
| Pointer
|
||||
| Float
|
||||
| Double => true,
|
||||
_ => false
|
||||
};
|
||||
fn is_reg_ty(ty: Type) -> bool {
|
||||
match ty.kind() {
|
||||
Integer
|
||||
| Pointer
|
||||
| Float
|
||||
| Double => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,8 +128,8 @@ enum ARM_ABIInfo { ARM_ABIInfo }
|
||||
|
||||
impl ABIInfo for ARM_ABIInfo {
|
||||
fn compute_info(&self,
|
||||
atys: &[TypeRef],
|
||||
rty: TypeRef,
|
||||
atys: &[Type],
|
||||
rty: Type,
|
||||
ret_def: bool) -> FnType {
|
||||
let mut arg_tys = ~[];
|
||||
let mut attrs = ~[];
|
||||
@ -147,14 +142,14 @@ impl ABIInfo for ARM_ABIInfo {
|
||||
let mut (ret_ty, ret_attr) = if ret_def {
|
||||
classify_ret_ty(rty)
|
||||
} else {
|
||||
(LLVMType { cast: false, ty: T_void() }, None)
|
||||
(LLVMType { cast: false, ty: Type::void() }, None)
|
||||
};
|
||||
|
||||
let sret = ret_attr.is_some();
|
||||
if sret {
|
||||
arg_tys.unshift(ret_ty);
|
||||
attrs.unshift(ret_attr);
|
||||
ret_ty = LLVMType { cast: false, ty: T_void() };
|
||||
ret_ty = LLVMType { cast: false, ty: Type::void() };
|
||||
}
|
||||
|
||||
return FnType {
|
||||
|
@ -11,104 +11,89 @@
|
||||
use core::prelude::*;
|
||||
|
||||
use core::libc::c_uint;
|
||||
use core::ptr;
|
||||
use core::uint;
|
||||
use core::vec;
|
||||
use lib::llvm::{llvm, TypeRef, Integer, Pointer, Float, Double};
|
||||
use lib::llvm::{Struct, Array, Attribute};
|
||||
use lib::llvm::{StructRetAttribute};
|
||||
use lib::llvm::True;
|
||||
use lib::llvm::{llvm, Integer, Pointer, Float, Double, Struct, Array};
|
||||
use lib::llvm::{Attribute, StructRetAttribute};
|
||||
use middle::trans::context::task_llcx;
|
||||
use middle::trans::common::*;
|
||||
use middle::trans::cabi::*;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
fn align_up_to(off: uint, a: uint) -> uint {
|
||||
return (off + a - 1u) / a * a;
|
||||
}
|
||||
|
||||
fn align(off: uint, ty: TypeRef) -> uint {
|
||||
fn align(off: uint, ty: Type) -> uint {
|
||||
let a = ty_align(ty);
|
||||
return align_up_to(off, a);
|
||||
}
|
||||
|
||||
fn struct_tys(ty: TypeRef) -> ~[TypeRef] {
|
||||
unsafe {
|
||||
let n = llvm::LLVMCountStructElementTypes(ty);
|
||||
if (n == 0) {
|
||||
return ~[];
|
||||
}
|
||||
let mut elts = vec::from_elem(n as uint, ptr::null());
|
||||
llvm::LLVMGetStructElementTypes(ty, &mut elts[0]);
|
||||
return elts;
|
||||
fn ty_align(ty: Type) -> uint {
|
||||
match ty.kind() {
|
||||
Integer => {
|
||||
unsafe {
|
||||
((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
|
||||
}
|
||||
}
|
||||
Pointer => 4,
|
||||
Float => 4,
|
||||
Double => 8,
|
||||
Struct => {
|
||||
if ty.is_packed() {
|
||||
1
|
||||
} else {
|
||||
let str_tys = ty.field_types();
|
||||
str_tys.iter().fold(1, |a, t| uint::max(a, ty_align(*t)))
|
||||
}
|
||||
}
|
||||
Array => {
|
||||
let elt = ty.element_type();
|
||||
ty_align(elt)
|
||||
}
|
||||
_ => fail!("ty_size: unhandled type")
|
||||
}
|
||||
}
|
||||
|
||||
fn ty_align(ty: TypeRef) -> uint {
|
||||
unsafe {
|
||||
return match llvm::LLVMGetTypeKind(ty) {
|
||||
Integer => {
|
||||
((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8
|
||||
fn ty_size(ty: Type) -> uint {
|
||||
match ty.kind() {
|
||||
Integer => {
|
||||
unsafe {
|
||||
((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
|
||||
}
|
||||
Pointer => 4,
|
||||
Float => 4,
|
||||
Double => 8,
|
||||
Struct => {
|
||||
if llvm::LLVMIsPackedStruct(ty) == True {
|
||||
1
|
||||
} else {
|
||||
let str_tys = struct_tys(ty);
|
||||
str_tys.iter().fold(1, |a, t| uint::max(a, ty_align(*t)))
|
||||
}
|
||||
}
|
||||
Pointer => 4,
|
||||
Float => 4,
|
||||
Double => 8,
|
||||
Struct => {
|
||||
if ty.is_packed() {
|
||||
let str_tys = ty.field_types();
|
||||
str_tys.iter().fold(0, |s, t| s + ty_size(*t))
|
||||
} else {
|
||||
let str_tys = ty.field_types();
|
||||
let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
|
||||
align(size, ty)
|
||||
}
|
||||
Array => {
|
||||
let elt = llvm::LLVMGetElementType(ty);
|
||||
ty_align(elt)
|
||||
}
|
||||
_ => fail!("ty_size: unhandled type")
|
||||
};
|
||||
}
|
||||
Array => {
|
||||
let len = ty.array_length();
|
||||
let elt = ty.element_type();
|
||||
let eltsz = ty_size(elt);
|
||||
len * eltsz
|
||||
}
|
||||
_ => fail!("ty_size: unhandled type")
|
||||
}
|
||||
}
|
||||
|
||||
fn ty_size(ty: TypeRef) -> uint {
|
||||
unsafe {
|
||||
return match llvm::LLVMGetTypeKind(ty) {
|
||||
Integer => {
|
||||
((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8
|
||||
}
|
||||
Pointer => 4,
|
||||
Float => 4,
|
||||
Double => 8,
|
||||
Struct => {
|
||||
if llvm::LLVMIsPackedStruct(ty) == True {
|
||||
let str_tys = struct_tys(ty);
|
||||
str_tys.iter().fold(0, |s, t| s + ty_size(*t))
|
||||
} else {
|
||||
let str_tys = struct_tys(ty);
|
||||
let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
|
||||
align(size, ty)
|
||||
}
|
||||
}
|
||||
Array => {
|
||||
let len = llvm::LLVMGetArrayLength(ty) as uint;
|
||||
let elt = llvm::LLVMGetElementType(ty);
|
||||
let eltsz = ty_size(elt);
|
||||
len * eltsz
|
||||
}
|
||||
_ => fail!("ty_size: unhandled type")
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_ret_ty(ty: TypeRef) -> (LLVMType, Option<Attribute>) {
|
||||
fn classify_ret_ty(ty: Type) -> (LLVMType, Option<Attribute>) {
|
||||
return if is_reg_ty(ty) {
|
||||
(LLVMType { cast: false, ty: ty }, None)
|
||||
} else {
|
||||
(LLVMType { cast: false, ty: T_ptr(ty) }, Some(StructRetAttribute))
|
||||
(LLVMType { cast: false, ty: ty.ptr_to() }, Some(StructRetAttribute))
|
||||
};
|
||||
}
|
||||
|
||||
fn classify_arg_ty(ty: TypeRef,
|
||||
offset: &mut uint) -> (LLVMType, Option<Attribute>) {
|
||||
fn classify_arg_ty(ty: Type, offset: &mut uint) -> (LLVMType, Option<Attribute>) {
|
||||
let orig_offset = *offset;
|
||||
let size = ty_size(ty) * 8;
|
||||
let mut align = ty_align(ty);
|
||||
@ -133,28 +118,26 @@ fn classify_arg_ty(ty: TypeRef,
|
||||
};
|
||||
}
|
||||
|
||||
fn is_reg_ty(ty: TypeRef) -> bool {
|
||||
unsafe {
|
||||
return match llvm::LLVMGetTypeKind(ty) {
|
||||
Integer
|
||||
| Pointer
|
||||
| Float
|
||||
| Double => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
fn is_reg_ty(ty: Type) -> bool {
|
||||
return match ty.kind() {
|
||||
Integer
|
||||
| Pointer
|
||||
| Float
|
||||
| Double => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
fn padding_ty(align: uint, offset: uint) -> Option<TypeRef> {
|
||||
fn padding_ty(align: uint, offset: uint) -> Option<Type> {
|
||||
if ((align - 1 ) & offset) > 0 {
|
||||
return Some(T_i32());
|
||||
return Some(Type::i32());
|
||||
}
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
fn coerce_to_int(size: uint) -> ~[TypeRef] {
|
||||
let int_ty = T_i32();
|
||||
fn coerce_to_int(size: uint) -> ~[Type] {
|
||||
let int_ty = Type::i32();
|
||||
let mut args = ~[];
|
||||
|
||||
let mut n = size / 32;
|
||||
@ -166,16 +149,16 @@ fn coerce_to_int(size: uint) -> ~[TypeRef] {
|
||||
let r = size % 32;
|
||||
if r > 0 {
|
||||
unsafe {
|
||||
args.push(llvm::LLVMIntTypeInContext(task_llcx(), r as c_uint))
|
||||
args.push(Type::from_ref(llvm::LLVMIntTypeInContext(task_llcx(), r as c_uint)));
|
||||
}
|
||||
}
|
||||
|
||||
return args;
|
||||
args
|
||||
}
|
||||
|
||||
fn struct_ty(ty: TypeRef,
|
||||
padding: Option<TypeRef>,
|
||||
coerce: bool) -> TypeRef {
|
||||
fn struct_ty(ty: Type,
|
||||
padding: Option<Type>,
|
||||
coerce: bool) -> Type {
|
||||
let size = ty_size(ty) * 8;
|
||||
let mut fields = padding.map_default(~[], |p| ~[*p]);
|
||||
|
||||
@ -185,20 +168,20 @@ fn struct_ty(ty: TypeRef,
|
||||
fields.push(ty);
|
||||
}
|
||||
|
||||
return T_struct(fields, false);
|
||||
return Type::struct_(fields, false);
|
||||
}
|
||||
|
||||
enum MIPS_ABIInfo { MIPS_ABIInfo }
|
||||
|
||||
impl ABIInfo for MIPS_ABIInfo {
|
||||
fn compute_info(&self,
|
||||
atys: &[TypeRef],
|
||||
rty: TypeRef,
|
||||
atys: &[Type],
|
||||
rty: Type,
|
||||
ret_def: bool) -> FnType {
|
||||
let mut (ret_ty, ret_attr) = if ret_def {
|
||||
classify_ret_ty(rty)
|
||||
} else {
|
||||
(LLVMType { cast: false, ty: T_void() }, None)
|
||||
(LLVMType { cast: false, ty: Type::void() }, None)
|
||||
};
|
||||
|
||||
let sret = ret_attr.is_some();
|
||||
@ -215,7 +198,7 @@ impl ABIInfo for MIPS_ABIInfo {
|
||||
if sret {
|
||||
arg_tys = vec::append(~[ret_ty], arg_tys);
|
||||
attrs = vec::append(~[ret_attr], attrs);
|
||||
ret_ty = LLVMType { cast: false, ty: T_void() };
|
||||
ret_ty = LLVMType { cast: false, ty: Type::void() };
|
||||
}
|
||||
|
||||
return FnType {
|
||||
|
@ -12,19 +12,20 @@ use core::prelude::*;
|
||||
|
||||
use driver::session::{os_win32, os_macos};
|
||||
use lib::llvm::*;
|
||||
use lib::llvm::llvm::*;
|
||||
use super::cabi::*;
|
||||
use super::common::*;
|
||||
use super::machine::*;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
struct X86_ABIInfo {
|
||||
ccx: @mut CrateContext
|
||||
}
|
||||
|
||||
impl ABIInfo for X86_ABIInfo {
|
||||
fn compute_info(&self,
|
||||
atys: &[TypeRef],
|
||||
rty: TypeRef,
|
||||
atys: &[Type],
|
||||
rty: Type,
|
||||
ret_def: bool) -> FnType {
|
||||
let mut arg_tys = do atys.map |a| {
|
||||
LLVMType { cast: false, ty: *a }
|
||||
@ -41,7 +42,7 @@ impl ABIInfo for X86_ABIInfo {
|
||||
// http://www.angelcode.com/dev/callconv/callconv.html
|
||||
// Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp
|
||||
let sret = {
|
||||
let returning_a_struct = unsafe { LLVMGetTypeKind(rty) == Struct && ret_def };
|
||||
let returning_a_struct = rty.kind() == Struct && ret_def;
|
||||
let big_struct = match self.ccx.sess.targ_cfg.os {
|
||||
os_win32 | os_macos => llsize_of_alloc(self.ccx, rty) > 8,
|
||||
_ => true
|
||||
@ -52,18 +53,18 @@ impl ABIInfo for X86_ABIInfo {
|
||||
if sret {
|
||||
let ret_ptr_ty = LLVMType {
|
||||
cast: false,
|
||||
ty: T_ptr(ret_ty.ty)
|
||||
ty: ret_ty.ty.ptr_to()
|
||||
};
|
||||
arg_tys = ~[ret_ptr_ty] + arg_tys;
|
||||
attrs = ~[Some(StructRetAttribute)] + attrs;
|
||||
ret_ty = LLVMType {
|
||||
cast: false,
|
||||
ty: T_void(),
|
||||
ty: Type::void(),
|
||||
};
|
||||
} else if !ret_def {
|
||||
ret_ty = LLVMType {
|
||||
cast: false,
|
||||
ty: T_void()
|
||||
ty: Type::void()
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -11,151 +11,169 @@
|
||||
// The classification code for the x86_64 ABI is taken from the clay language
|
||||
// https://github.com/jckarter/clay/blob/master/compiler/src/externals.cpp
|
||||
|
||||
use lib::llvm::{llvm, TypeRef, Integer, Pointer, Float, Double};
|
||||
use lib::llvm::{llvm, Integer, Pointer, Float, Double};
|
||||
use lib::llvm::{Struct, Array, Attribute};
|
||||
use lib::llvm::{StructRetAttribute, ByValAttribute};
|
||||
use lib::llvm::struct_tys;
|
||||
use lib::llvm::True;
|
||||
use middle::trans::common::*;
|
||||
use middle::trans::cabi::*;
|
||||
|
||||
use core::libc::c_uint;
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use core::option;
|
||||
use core::option::Option;
|
||||
use core::uint;
|
||||
use core::vec;
|
||||
|
||||
#[deriving(Eq)]
|
||||
enum x86_64_reg_class {
|
||||
no_class,
|
||||
integer_class,
|
||||
sse_fs_class,
|
||||
sse_fv_class,
|
||||
sse_ds_class,
|
||||
sse_dv_class,
|
||||
sse_int_class,
|
||||
sseup_class,
|
||||
x87_class,
|
||||
x87up_class,
|
||||
complex_x87_class,
|
||||
memory_class
|
||||
enum RegClass {
|
||||
NoClass,
|
||||
Int,
|
||||
SSEFs,
|
||||
SSEFv,
|
||||
SSEDs,
|
||||
SSEDv,
|
||||
SSEInt,
|
||||
SSEUp,
|
||||
X87,
|
||||
X87Up,
|
||||
ComplexX87,
|
||||
Memory
|
||||
}
|
||||
|
||||
fn is_sse(c: x86_64_reg_class) -> bool {
|
||||
return match c {
|
||||
sse_fs_class | sse_fv_class |
|
||||
sse_ds_class | sse_dv_class => true,
|
||||
_ => false
|
||||
};
|
||||
impl Type {
|
||||
fn is_reg_ty(&self) -> bool {
|
||||
match self.kind() {
|
||||
Integer | Pointer | Float | Double => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_ymm(cls: &[x86_64_reg_class]) -> bool {
|
||||
let len = cls.len();
|
||||
return (len > 2u &&
|
||||
is_sse(cls[0]) &&
|
||||
cls[1] == sseup_class &&
|
||||
cls[2] == sseup_class) ||
|
||||
(len > 3u &&
|
||||
is_sse(cls[1]) &&
|
||||
cls[2] == sseup_class &&
|
||||
cls[3] == sseup_class);
|
||||
impl RegClass {
|
||||
fn is_sse(&self) -> bool {
|
||||
match *self {
|
||||
SSEFs | SSEFv | SSEDs | SSEDv => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
|
||||
fn align(off: uint, ty: TypeRef) -> uint {
|
||||
trait ClassList {
|
||||
fn is_pass_byval(&self) -> bool;
|
||||
fn is_ret_bysret(&self) -> bool;
|
||||
}
|
||||
|
||||
impl<'self> ClassList for &'self [RegClass] {
|
||||
fn is_pass_byval(&self) -> bool {
|
||||
if self.len() == 0 { return false; }
|
||||
|
||||
let class = self[0];
|
||||
class == Memory
|
||||
|| class == X87
|
||||
|| class == ComplexX87
|
||||
}
|
||||
|
||||
fn is_ret_bysret(&self) -> bool {
|
||||
if self.len() == 0 { return false; }
|
||||
|
||||
self[0] == Memory
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_ty(ty: Type) -> ~[RegClass] {
|
||||
fn align(off: uint, ty: Type) -> uint {
|
||||
let a = ty_align(ty);
|
||||
return (off + a - 1u) / a * a;
|
||||
}
|
||||
|
||||
fn ty_align(ty: TypeRef) -> uint {
|
||||
unsafe {
|
||||
return match llvm::LLVMGetTypeKind(ty) {
|
||||
Integer => {
|
||||
((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8
|
||||
fn ty_align(ty: Type) -> uint {
|
||||
match ty.kind() {
|
||||
Integer => {
|
||||
unsafe {
|
||||
((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
|
||||
}
|
||||
Pointer => 8,
|
||||
Float => 4,
|
||||
Double => 8,
|
||||
Struct => {
|
||||
if llvm::LLVMIsPackedStruct(ty) == True {
|
||||
1
|
||||
} else {
|
||||
let str_tys = struct_tys(ty);
|
||||
str_tys.iter().fold(1, |a, t| uint::max(a, ty_align(*t)))
|
||||
}
|
||||
}
|
||||
Array => {
|
||||
let elt = llvm::LLVMGetElementType(ty);
|
||||
ty_align(elt)
|
||||
}
|
||||
_ => fail!("ty_size: unhandled type")
|
||||
};
|
||||
}
|
||||
Pointer => 8,
|
||||
Float => 4,
|
||||
Double => 8,
|
||||
Struct => {
|
||||
if ty.is_packed() {
|
||||
1
|
||||
} else {
|
||||
let str_tys = ty.field_types();
|
||||
str_tys.iter().fold(1, |a, t| uint::max(a, ty_align(*t)))
|
||||
}
|
||||
}
|
||||
Array => {
|
||||
let elt = ty.element_type();
|
||||
ty_align(elt)
|
||||
}
|
||||
_ => fail!("ty_size: unhandled type")
|
||||
}
|
||||
}
|
||||
|
||||
fn ty_size(ty: TypeRef) -> uint {
|
||||
unsafe {
|
||||
return match llvm::LLVMGetTypeKind(ty) {
|
||||
Integer => {
|
||||
((llvm::LLVMGetIntTypeWidth(ty) as uint) + 7) / 8
|
||||
fn ty_size(ty: Type) -> uint {
|
||||
match ty.kind() {
|
||||
Integer => {
|
||||
unsafe {
|
||||
((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
|
||||
}
|
||||
Pointer => 8,
|
||||
Float => 4,
|
||||
Double => 8,
|
||||
Struct => {
|
||||
if llvm::LLVMIsPackedStruct(ty) == True {
|
||||
let str_tys = struct_tys(ty);
|
||||
str_tys.iter().fold(0, |s, t| s + ty_size(*t))
|
||||
} else {
|
||||
let str_tys = struct_tys(ty);
|
||||
let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
|
||||
align(size, ty)
|
||||
}
|
||||
}
|
||||
Pointer => 8,
|
||||
Float => 4,
|
||||
Double => 8,
|
||||
Struct => {
|
||||
if ty.is_packed() {
|
||||
let str_tys = ty.field_types();
|
||||
str_tys.iter().fold(0, |s, t| s + ty_size(*t))
|
||||
} else {
|
||||
let str_tys = ty.field_types();
|
||||
let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
|
||||
align(size, ty)
|
||||
}
|
||||
Array => {
|
||||
let len = llvm::LLVMGetArrayLength(ty) as uint;
|
||||
let elt = llvm::LLVMGetElementType(ty);
|
||||
let eltsz = ty_size(elt);
|
||||
len * eltsz
|
||||
}
|
||||
_ => fail!("ty_size: unhandled type")
|
||||
};
|
||||
}
|
||||
Array => {
|
||||
let len = ty.array_length();
|
||||
let elt = ty.element_type();
|
||||
let eltsz = ty_size(elt);
|
||||
len * eltsz
|
||||
}
|
||||
_ => fail!("ty_size: unhandled type")
|
||||
}
|
||||
}
|
||||
|
||||
fn all_mem(cls: &mut [x86_64_reg_class]) {
|
||||
fn all_mem(cls: &mut [RegClass]) {
|
||||
for uint::range(0, cls.len()) |i| {
|
||||
cls[i] = memory_class;
|
||||
cls[i] = Memory;
|
||||
}
|
||||
}
|
||||
|
||||
fn unify(cls: &mut [x86_64_reg_class],
|
||||
fn unify(cls: &mut [RegClass],
|
||||
i: uint,
|
||||
newv: x86_64_reg_class) {
|
||||
newv: RegClass) {
|
||||
if cls[i] == newv {
|
||||
return;
|
||||
} else if cls[i] == no_class {
|
||||
} else if cls[i] == NoClass {
|
||||
cls[i] = newv;
|
||||
} else if newv == no_class {
|
||||
} else if newv == NoClass {
|
||||
return;
|
||||
} else if cls[i] == memory_class || newv == memory_class {
|
||||
cls[i] = memory_class;
|
||||
} else if cls[i] == integer_class || newv == integer_class {
|
||||
cls[i] = integer_class;
|
||||
} else if cls[i] == x87_class ||
|
||||
cls[i] == x87up_class ||
|
||||
cls[i] == complex_x87_class ||
|
||||
newv == x87_class ||
|
||||
newv == x87up_class ||
|
||||
newv == complex_x87_class {
|
||||
cls[i] = memory_class;
|
||||
} else if cls[i] == Memory || newv == Memory {
|
||||
cls[i] = Memory;
|
||||
} else if cls[i] == Int || newv == Int {
|
||||
cls[i] = Int;
|
||||
} else if cls[i] == X87 ||
|
||||
cls[i] == X87Up ||
|
||||
cls[i] == ComplexX87 ||
|
||||
newv == X87 ||
|
||||
newv == X87Up ||
|
||||
newv == ComplexX87 {
|
||||
cls[i] = Memory;
|
||||
} else {
|
||||
cls[i] = newv;
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_struct(tys: &[TypeRef],
|
||||
cls: &mut [x86_64_reg_class], i: uint,
|
||||
fn classify_struct(tys: &[Type],
|
||||
cls: &mut [RegClass], i: uint,
|
||||
off: uint) {
|
||||
let mut field_off = off;
|
||||
for tys.each |ty| {
|
||||
@ -165,108 +183,104 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
|
||||
}
|
||||
}
|
||||
|
||||
fn classify(ty: TypeRef,
|
||||
cls: &mut [x86_64_reg_class], ix: uint,
|
||||
fn classify(ty: Type,
|
||||
cls: &mut [RegClass], ix: uint,
|
||||
off: uint) {
|
||||
unsafe {
|
||||
let t_align = ty_align(ty);
|
||||
let t_size = ty_size(ty);
|
||||
let t_align = ty_align(ty);
|
||||
let t_size = ty_size(ty);
|
||||
|
||||
let misalign = off % t_align;
|
||||
if misalign != 0u {
|
||||
let mut i = off / 8u;
|
||||
let e = (off + t_size + 7u) / 8u;
|
||||
while i < e {
|
||||
unify(cls, ix + i, memory_class);
|
||||
let misalign = off % t_align;
|
||||
if misalign != 0u {
|
||||
let mut i = off / 8u;
|
||||
let e = (off + t_size + 7u) / 8u;
|
||||
while i < e {
|
||||
unify(cls, ix + i, Memory);
|
||||
i += 1u;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
match ty.kind() {
|
||||
Integer |
|
||||
Pointer => {
|
||||
unify(cls, ix + off / 8u, Int);
|
||||
}
|
||||
Float => {
|
||||
if off % 8u == 4u {
|
||||
unify(cls, ix + off / 8u, SSEFv);
|
||||
} else {
|
||||
unify(cls, ix + off / 8u, SSEFs);
|
||||
}
|
||||
}
|
||||
Double => {
|
||||
unify(cls, ix + off / 8u, SSEDs);
|
||||
}
|
||||
Struct => {
|
||||
classify_struct(ty.field_types(), cls, ix, off);
|
||||
}
|
||||
Array => {
|
||||
let len = ty.array_length();
|
||||
let elt = ty.element_type();
|
||||
let eltsz = ty_size(elt);
|
||||
let mut i = 0u;
|
||||
while i < len {
|
||||
classify(elt, cls, ix, off + i * eltsz);
|
||||
i += 1u;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
match llvm::LLVMGetTypeKind(ty) as int {
|
||||
8 /* integer */ |
|
||||
12 /* pointer */ => {
|
||||
unify(cls, ix + off / 8u, integer_class);
|
||||
}
|
||||
2 /* float */ => {
|
||||
if off % 8u == 4u {
|
||||
unify(cls, ix + off / 8u, sse_fv_class);
|
||||
} else {
|
||||
unify(cls, ix + off / 8u, sse_fs_class);
|
||||
}
|
||||
}
|
||||
3 /* double */ => {
|
||||
unify(cls, ix + off / 8u, sse_ds_class);
|
||||
}
|
||||
10 /* struct */ => {
|
||||
classify_struct(struct_tys(ty), cls, ix, off);
|
||||
}
|
||||
11 /* array */ => {
|
||||
let elt = llvm::LLVMGetElementType(ty);
|
||||
let eltsz = ty_size(elt);
|
||||
let len = llvm::LLVMGetArrayLength(ty) as uint;
|
||||
let mut i = 0u;
|
||||
while i < len {
|
||||
classify(elt, cls, ix, off + i * eltsz);
|
||||
i += 1u;
|
||||
}
|
||||
}
|
||||
_ => fail!("classify: unhandled type")
|
||||
}
|
||||
_ => fail!("classify: unhandled type")
|
||||
}
|
||||
}
|
||||
|
||||
fn fixup(ty: TypeRef, cls: &mut [x86_64_reg_class]) {
|
||||
unsafe {
|
||||
let mut i = 0u;
|
||||
let llty = llvm::LLVMGetTypeKind(ty) as int;
|
||||
let e = cls.len();
|
||||
if cls.len() > 2u &&
|
||||
(llty == 10 /* struct */ ||
|
||||
llty == 11 /* array */) {
|
||||
if is_sse(cls[i]) {
|
||||
i += 1u;
|
||||
while i < e {
|
||||
if cls[i] != sseup_class {
|
||||
all_mem(cls);
|
||||
return;
|
||||
}
|
||||
i += 1u;
|
||||
fn fixup(ty: Type, cls: &mut [RegClass]) {
|
||||
let mut i = 0u;
|
||||
let ty_kind = ty.kind();
|
||||
let e = cls.len();
|
||||
if cls.len() > 2u &&
|
||||
(ty_kind == Struct ||
|
||||
ty_kind == Array) {
|
||||
if cls[i].is_sse() {
|
||||
i += 1u;
|
||||
while i < e {
|
||||
if cls[i] != SSEUp {
|
||||
all_mem(cls);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
all_mem(cls);
|
||||
return
|
||||
i += 1u;
|
||||
}
|
||||
} else {
|
||||
while i < e {
|
||||
if cls[i] == memory_class {
|
||||
all_mem(cls);
|
||||
return;
|
||||
}
|
||||
if cls[i] == x87up_class {
|
||||
// for darwin
|
||||
// cls[i] = sse_ds_class;
|
||||
all_mem(cls);
|
||||
return;
|
||||
}
|
||||
if cls[i] == sseup_class {
|
||||
cls[i] = sse_int_class;
|
||||
} else if is_sse(cls[i]) {
|
||||
i += 1;
|
||||
while i != e && cls[i] == sseup_class { i += 1u; }
|
||||
} else if cls[i] == x87_class {
|
||||
i += 1;
|
||||
while i != e && cls[i] == x87up_class { i += 1u; }
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
all_mem(cls);
|
||||
return
|
||||
}
|
||||
} else {
|
||||
while i < e {
|
||||
if cls[i] == Memory {
|
||||
all_mem(cls);
|
||||
return;
|
||||
}
|
||||
if cls[i] == X87Up {
|
||||
// for darwin
|
||||
// cls[i] = SSEDs;
|
||||
all_mem(cls);
|
||||
return;
|
||||
}
|
||||
if cls[i] == SSEUp {
|
||||
cls[i] = SSEInt;
|
||||
} else if cls[i].is_sse() {
|
||||
i += 1;
|
||||
while i != e && cls[i] == SSEUp { i += 1u; }
|
||||
} else if cls[i] == X87 {
|
||||
i += 1;
|
||||
while i != e && cls[i] == X87Up { i += 1u; }
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let words = (ty_size(ty) + 7) / 8;
|
||||
let mut cls = vec::from_elem(words, no_class);
|
||||
let mut cls = vec::from_elem(words, NoClass);
|
||||
if words > 4 {
|
||||
all_mem(cls);
|
||||
let cls = cls;
|
||||
@ -277,11 +291,11 @@ fn classify_ty(ty: TypeRef) -> ~[x86_64_reg_class] {
|
||||
return cls;
|
||||
}
|
||||
|
||||
fn llreg_ty(cls: &[x86_64_reg_class]) -> TypeRef {
|
||||
fn llvec_len(cls: &[x86_64_reg_class]) -> uint {
|
||||
fn llreg_ty(cls: &[RegClass]) -> Type {
|
||||
fn llvec_len(cls: &[RegClass]) -> uint {
|
||||
let mut len = 1u;
|
||||
for cls.each |c| {
|
||||
if *c != sseup_class {
|
||||
if *c != SSEUp {
|
||||
break;
|
||||
}
|
||||
len += 1u;
|
||||
@ -289,103 +303,77 @@ fn llreg_ty(cls: &[x86_64_reg_class]) -> TypeRef {
|
||||
return len;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let mut tys = ~[];
|
||||
let mut i = 0u;
|
||||
let e = cls.len();
|
||||
while i < e {
|
||||
match cls[i] {
|
||||
integer_class => {
|
||||
tys.push(T_i64());
|
||||
}
|
||||
sse_fv_class => {
|
||||
let vec_len = llvec_len(vec::tailn(cls, i + 1u)) * 2u;
|
||||
let vec_ty = llvm::LLVMVectorType(T_f32(),
|
||||
vec_len as c_uint);
|
||||
tys.push(vec_ty);
|
||||
i += vec_len;
|
||||
loop;
|
||||
}
|
||||
sse_fs_class => {
|
||||
tys.push(T_f32());
|
||||
}
|
||||
sse_ds_class => {
|
||||
tys.push(T_f64());
|
||||
}
|
||||
_ => fail!("llregtype: unhandled class")
|
||||
let mut tys = ~[];
|
||||
let mut i = 0u;
|
||||
let e = cls.len();
|
||||
while i < e {
|
||||
match cls[i] {
|
||||
Int => {
|
||||
tys.push(Type::i64());
|
||||
}
|
||||
i += 1u;
|
||||
SSEFv => {
|
||||
let vec_len = llvec_len(vec::tailn(cls, i + 1u)) * 2u;
|
||||
let vec_ty = Type::vector(&Type::f32(), vec_len as u64);
|
||||
tys.push(vec_ty);
|
||||
i += vec_len;
|
||||
loop;
|
||||
}
|
||||
SSEFs => {
|
||||
tys.push(Type::f32());
|
||||
}
|
||||
SSEDs => {
|
||||
tys.push(Type::f64());
|
||||
}
|
||||
_ => fail!("llregtype: unhandled class")
|
||||
}
|
||||
return T_struct(tys, false);
|
||||
i += 1u;
|
||||
}
|
||||
return Type::struct_(tys, false);
|
||||
}
|
||||
|
||||
fn x86_64_tys(atys: &[TypeRef],
|
||||
rty: TypeRef,
|
||||
fn x86_64_tys(atys: &[Type],
|
||||
rty: Type,
|
||||
ret_def: bool) -> FnType {
|
||||
fn is_reg_ty(ty: TypeRef) -> bool {
|
||||
unsafe {
|
||||
return match llvm::LLVMGetTypeKind(ty) as int {
|
||||
8 /* integer */ |
|
||||
12 /* pointer */ |
|
||||
2 /* float */ |
|
||||
3 /* double */ => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn is_pass_byval(cls: &[x86_64_reg_class]) -> bool {
|
||||
return cls.len() > 0 &&
|
||||
(cls[0] == memory_class ||
|
||||
cls[0] == x87_class ||
|
||||
cls[0] == complex_x87_class);
|
||||
}
|
||||
|
||||
fn is_ret_bysret(cls: &[x86_64_reg_class]) -> bool {
|
||||
return cls.len() > 0 && cls[0] == memory_class;
|
||||
}
|
||||
|
||||
fn x86_64_ty(ty: TypeRef,
|
||||
is_mem_cls: &fn(cls: &[x86_64_reg_class]) -> bool,
|
||||
fn x86_64_ty(ty: Type,
|
||||
is_mem_cls: &fn(cls: &[RegClass]) -> bool,
|
||||
attr: Attribute) -> (LLVMType, Option<Attribute>) {
|
||||
let mut cast = false;
|
||||
let mut ty_attr = option::None;
|
||||
let mut llty = ty;
|
||||
if !is_reg_ty(ty) {
|
||||
|
||||
let (cast, attr, ty) = if !ty.is_reg_ty() {
|
||||
let cls = classify_ty(ty);
|
||||
if is_mem_cls(cls) {
|
||||
llty = T_ptr(ty);
|
||||
ty_attr = option::Some(attr);
|
||||
(false, option::Some(attr), ty.ptr_to())
|
||||
} else {
|
||||
cast = true;
|
||||
llty = llreg_ty(cls);
|
||||
(true, option::None, llreg_ty(cls))
|
||||
}
|
||||
}
|
||||
return (LLVMType { cast: cast, ty: llty }, ty_attr);
|
||||
} else {
|
||||
(false, option::None, ty)
|
||||
};
|
||||
|
||||
(LLVMType { cast: cast, ty: ty }, attr)
|
||||
}
|
||||
|
||||
let mut arg_tys = ~[];
|
||||
let mut attrs = ~[];
|
||||
for atys.each |t| {
|
||||
let (ty, attr) = x86_64_ty(*t, is_pass_byval, ByValAttribute);
|
||||
let (ty, attr) = x86_64_ty(*t, |cls| cls.is_pass_byval(), ByValAttribute);
|
||||
arg_tys.push(ty);
|
||||
attrs.push(attr);
|
||||
}
|
||||
let mut (ret_ty, ret_attr) = x86_64_ty(rty, is_ret_bysret,
|
||||
let mut (ret_ty, ret_attr) = x86_64_ty(rty, |cls| cls.is_ret_bysret(),
|
||||
StructRetAttribute);
|
||||
let sret = ret_attr.is_some();
|
||||
if sret {
|
||||
arg_tys = vec::append(~[ret_ty], arg_tys);
|
||||
ret_ty = LLVMType {
|
||||
cast: false,
|
||||
ty: T_void()
|
||||
ty: Type::void()
|
||||
};
|
||||
attrs = vec::append(~[ret_attr], attrs);
|
||||
} else if !ret_def {
|
||||
ret_ty = LLVMType {
|
||||
cast: false,
|
||||
ty: T_void()
|
||||
ty: Type::void()
|
||||
};
|
||||
}
|
||||
return FnType {
|
||||
@ -400,8 +388,8 @@ enum X86_64_ABIInfo { X86_64_ABIInfo }
|
||||
|
||||
impl ABIInfo for X86_64_ABIInfo {
|
||||
fn compute_info(&self,
|
||||
atys: &[TypeRef],
|
||||
rty: TypeRef,
|
||||
atys: &[Type],
|
||||
rty: Type,
|
||||
ret_def: bool) -> FnType {
|
||||
return x86_64_tys(atys, rty, ret_def);
|
||||
}
|
||||
|
@ -45,6 +45,8 @@ use middle::typeck;
|
||||
use middle::typeck::coherence::make_substs_for_receiver_types;
|
||||
use util::ppaux::Repr;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use core::vec;
|
||||
use syntax::ast;
|
||||
use syntax::ast_map;
|
||||
@ -76,7 +78,7 @@ pub struct Callee {
|
||||
}
|
||||
|
||||
pub fn trans(bcx: block, expr: @ast::expr) -> Callee {
|
||||
let _icx = bcx.insn_ctxt("trans_callee");
|
||||
let _icx = push_ctxt("trans_callee");
|
||||
debug!("callee::trans(expr=%s)", expr.repr(bcx.tcx()));
|
||||
|
||||
// pick out special kinds of expressions that can be called:
|
||||
@ -170,7 +172,7 @@ pub fn trans_fn_ref(bcx: block,
|
||||
* with id `def_id` into a function pointer. This may require
|
||||
* monomorphization or inlining. */
|
||||
|
||||
let _icx = bcx.insn_ctxt("trans_fn_ref");
|
||||
let _icx = push_ctxt("trans_fn_ref");
|
||||
|
||||
let type_params = node_id_type_params(bcx, ref_id);
|
||||
let vtables = node_vtables(bcx, ref_id);
|
||||
@ -214,7 +216,7 @@ pub fn trans_fn_ref_with_vtables(
|
||||
// - `type_params`: values for each of the fn/method's type parameters
|
||||
// - `vtables`: values for each bound on each of the type parameters
|
||||
|
||||
let _icx = bcx.insn_ctxt("trans_fn_ref_with_vtables");
|
||||
let _icx = push_ctxt("trans_fn_ref_with_vtables");
|
||||
let ccx = bcx.ccx();
|
||||
let tcx = ccx.tcx;
|
||||
|
||||
@ -326,7 +328,7 @@ pub fn trans_fn_ref_with_vtables(
|
||||
let ref_ty = common::node_id_type(bcx, ref_id);
|
||||
|
||||
val = PointerCast(
|
||||
bcx, val, T_ptr(type_of::type_of_fn_from_ty(ccx, ref_ty)));
|
||||
bcx, val, type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to());
|
||||
}
|
||||
return FnData {llfn: val};
|
||||
}
|
||||
@ -355,7 +357,7 @@ pub fn trans_call(in_cx: block,
|
||||
id: ast::node_id,
|
||||
dest: expr::Dest)
|
||||
-> block {
|
||||
let _icx = in_cx.insn_ctxt("trans_call");
|
||||
let _icx = push_ctxt("trans_call");
|
||||
trans_call_inner(in_cx,
|
||||
call_ex.info(),
|
||||
expr_ty(in_cx, f),
|
||||
@ -373,7 +375,7 @@ pub fn trans_method_call(in_cx: block,
|
||||
args: CallArgs,
|
||||
dest: expr::Dest)
|
||||
-> block {
|
||||
let _icx = in_cx.insn_ctxt("trans_method_call");
|
||||
let _icx = push_ctxt("trans_method_call");
|
||||
debug!("trans_method_call(call_ex=%s, rcvr=%s)",
|
||||
call_ex.repr(in_cx.tcx()),
|
||||
rcvr.repr(in_cx.tcx()));
|
||||
@ -516,7 +518,7 @@ pub fn trans_call_inner(in_cx: block,
|
||||
let mut bcx = callee.bcx;
|
||||
let ccx = cx.ccx();
|
||||
let ret_flag = if ret_in_loop {
|
||||
let flag = alloca(bcx, T_bool());
|
||||
let flag = alloca(bcx, Type::bool());
|
||||
Store(bcx, C_bool(false), flag);
|
||||
Some(flag)
|
||||
} else {
|
||||
@ -526,13 +528,13 @@ pub fn trans_call_inner(in_cx: block,
|
||||
let (llfn, llenv) = unsafe {
|
||||
match callee.data {
|
||||
Fn(d) => {
|
||||
(d.llfn, llvm::LLVMGetUndef(T_opaque_box_ptr(ccx)))
|
||||
(d.llfn, llvm::LLVMGetUndef(Type::opaque_box(ccx).ptr_to().to_ref()))
|
||||
}
|
||||
Method(d) => {
|
||||
// Weird but true: we pass self in the *environment* slot!
|
||||
let llself = PointerCast(bcx,
|
||||
d.llself,
|
||||
T_opaque_box_ptr(ccx));
|
||||
Type::opaque_box(ccx).ptr_to());
|
||||
(d.llfn, llself)
|
||||
}
|
||||
Closure(d) => {
|
||||
@ -572,9 +574,9 @@ pub fn trans_call_inner(in_cx: block,
|
||||
|
||||
// Uncomment this to debug calls.
|
||||
/*
|
||||
io::println(fmt!("calling: %s", bcx.val_str(llfn)));
|
||||
io::println(fmt!("calling: %s", bcx.val_to_str(llfn)));
|
||||
for llargs.each |llarg| {
|
||||
io::println(fmt!("arg: %s", bcx.val_str(*llarg)));
|
||||
io::println(fmt!("arg: %s", bcx.val_to_str(*llarg)));
|
||||
}
|
||||
io::println("---");
|
||||
*/
|
||||
@ -653,7 +655,7 @@ pub fn trans_ret_slot(bcx: block, fn_ty: ty::t, dest: expr::Dest)
|
||||
expr::Ignore => {
|
||||
if ty::type_is_nil(retty) {
|
||||
unsafe {
|
||||
llvm::LLVMGetUndef(T_ptr(T_nil()))
|
||||
llvm::LLVMGetUndef(Type::nil().ptr_to().to_ref())
|
||||
}
|
||||
} else {
|
||||
alloc_ty(bcx, retty)
|
||||
@ -669,7 +671,7 @@ pub fn trans_args(cx: block,
|
||||
autoref_arg: AutorefArg,
|
||||
llargs: &mut ~[ValueRef]) -> block
|
||||
{
|
||||
let _icx = cx.insn_ctxt("trans_args");
|
||||
let _icx = push_ctxt("trans_args");
|
||||
let mut temp_cleanups = ~[];
|
||||
let arg_tys = ty::ty_fn_args(fn_ty);
|
||||
|
||||
@ -723,7 +725,7 @@ pub fn trans_arg_expr(bcx: block,
|
||||
temp_cleanups: &mut ~[ValueRef],
|
||||
ret_flag: Option<ValueRef>,
|
||||
autoref_arg: AutorefArg) -> Result {
|
||||
let _icx = bcx.insn_ctxt("trans_arg_expr");
|
||||
let _icx = push_ctxt("trans_arg_expr");
|
||||
let ccx = bcx.ccx();
|
||||
|
||||
debug!("trans_arg_expr(formal_arg_ty=(%s), self_mode=%?, arg_expr=%s, \
|
||||
@ -731,7 +733,7 @@ pub fn trans_arg_expr(bcx: block,
|
||||
formal_arg_ty.repr(bcx.tcx()),
|
||||
self_mode,
|
||||
arg_expr.repr(bcx.tcx()),
|
||||
ret_flag.map(|v| bcx.val_str(*v)));
|
||||
ret_flag.map(|v| bcx.val_to_str(*v)));
|
||||
|
||||
// translate the arg expr to a datum
|
||||
let arg_datumblock = match ret_flag {
|
||||
@ -777,7 +779,7 @@ pub fn trans_arg_expr(bcx: block,
|
||||
// to have type lldestty (the callee's expected type).
|
||||
let llformal_arg_ty = type_of::type_of(ccx, formal_arg_ty);
|
||||
unsafe {
|
||||
val = llvm::LLVMGetUndef(llformal_arg_ty);
|
||||
val = llvm::LLVMGetUndef(llformal_arg_ty.to_ref());
|
||||
}
|
||||
} else {
|
||||
// FIXME(#3548) use the adjustments table
|
||||
@ -838,15 +840,15 @@ pub fn trans_arg_expr(bcx: block,
|
||||
// this could happen due to e.g. subtyping
|
||||
let llformal_arg_ty = type_of::type_of_explicit_arg(ccx, &formal_arg_ty);
|
||||
let llformal_arg_ty = match self_mode {
|
||||
ty::ByRef => T_ptr(llformal_arg_ty),
|
||||
ty::ByRef => llformal_arg_ty.ptr_to(),
|
||||
ty::ByCopy => llformal_arg_ty,
|
||||
};
|
||||
debug!("casting actual type (%s) to match formal (%s)",
|
||||
bcx.val_str(val), bcx.llty_str(llformal_arg_ty));
|
||||
bcx.val_to_str(val), bcx.llty_str(llformal_arg_ty));
|
||||
val = PointerCast(bcx, val, llformal_arg_ty);
|
||||
}
|
||||
}
|
||||
|
||||
debug!("--- trans_arg_expr passing %s", val_str(bcx.ccx().tn, val));
|
||||
debug!("--- trans_arg_expr passing %s", bcx.val_to_str(val));
|
||||
return rslt(bcx, val);
|
||||
}
|
||||
|
@ -26,6 +26,8 @@ use middle::trans::type_of::*;
|
||||
use middle::ty;
|
||||
use util::ppaux::ty_to_str;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use core::str;
|
||||
use core::vec;
|
||||
use syntax::ast;
|
||||
@ -72,7 +74,7 @@ use syntax::parse::token::special_idents;
|
||||
// closure".
|
||||
//
|
||||
// Typically an opaque closure suffices because we only manipulate it
|
||||
// by ptr. The routine common::T_opaque_box_ptr() returns an
|
||||
// by ptr. The routine Type::opaque_box().ptr_to() returns an
|
||||
// appropriate type for such an opaque closure; it allows access to
|
||||
// the box fields, but not the closure_data itself.
|
||||
//
|
||||
@ -160,15 +162,15 @@ pub fn mk_closure_tys(tcx: ty::ctxt,
|
||||
|
||||
pub fn allocate_cbox(bcx: block, sigil: ast::Sigil, cdata_ty: ty::t)
|
||||
-> Result {
|
||||
let _icx = bcx.insn_ctxt("closure::allocate_cbox");
|
||||
let _icx = push_ctxt("closure::allocate_cbox");
|
||||
let ccx = bcx.ccx();
|
||||
let tcx = ccx.tcx;
|
||||
|
||||
fn nuke_ref_count(bcx: block, llbox: ValueRef) {
|
||||
let _icx = bcx.insn_ctxt("closure::nuke_ref_count");
|
||||
let _icx = push_ctxt("closure::nuke_ref_count");
|
||||
// Initialize ref count to arbitrary value for debugging:
|
||||
let ccx = bcx.ccx();
|
||||
let llbox = PointerCast(bcx, llbox, T_opaque_box_ptr(ccx));
|
||||
let llbox = PointerCast(bcx, llbox, Type::opaque_box(ccx).ptr_to());
|
||||
let ref_cnt = GEPi(bcx, llbox, [0u, abi::box_field_refcnt]);
|
||||
let rc = C_int(ccx, 0x12345678);
|
||||
Store(bcx, rc, ref_cnt);
|
||||
@ -204,7 +206,7 @@ pub struct ClosureResult {
|
||||
pub fn store_environment(bcx: block,
|
||||
bound_values: ~[EnvValue],
|
||||
sigil: ast::Sigil) -> ClosureResult {
|
||||
let _icx = bcx.insn_ctxt("closure::store_environment");
|
||||
let _icx = push_ctxt("closure::store_environment");
|
||||
let ccx = bcx.ccx();
|
||||
let tcx = ccx.tcx;
|
||||
|
||||
@ -258,7 +260,7 @@ pub fn build_closure(bcx0: block,
|
||||
cap_vars: &[moves::CaptureVar],
|
||||
sigil: ast::Sigil,
|
||||
include_ret_handle: Option<ValueRef>) -> ClosureResult {
|
||||
let _icx = bcx0.insn_ctxt("closure::build_closure");
|
||||
let _icx = push_ctxt("closure::build_closure");
|
||||
// If we need to, package up the iterator body to call
|
||||
let bcx = bcx0;
|
||||
|
||||
@ -298,12 +300,11 @@ pub fn build_closure(bcx0: block,
|
||||
let ret_true = match bcx.fcx.loop_ret {
|
||||
Some((_, retptr)) => retptr,
|
||||
None => match bcx.fcx.llretptr {
|
||||
None => C_null(T_ptr(T_nil())),
|
||||
Some(retptr) => retptr,
|
||||
None => C_null(Type::nil().ptr_to()),
|
||||
Some(retptr) => PointerCast(bcx, retptr, Type::nil().ptr_to()),
|
||||
}
|
||||
};
|
||||
let ret_casted = PointerCast(bcx, ret_true, T_ptr(T_nil()));
|
||||
let ret_datum = Datum {val: ret_casted, ty: ty::mk_nil(),
|
||||
let ret_datum = Datum {val: ret_true, ty: ty::mk_nil(),
|
||||
mode: ByRef(ZeroMem)};
|
||||
env_vals.push(EnvValue {action: EnvRef,
|
||||
datum: ret_datum});
|
||||
@ -320,7 +321,7 @@ pub fn load_environment(fcx: fn_ctxt,
|
||||
cap_vars: &[moves::CaptureVar],
|
||||
load_ret_handle: bool,
|
||||
sigil: ast::Sigil) {
|
||||
let _icx = fcx.insn_ctxt("closure::load_environment");
|
||||
let _icx = push_ctxt("closure::load_environment");
|
||||
|
||||
let llloadenv = match fcx.llloadenv {
|
||||
Some(ll) => ll,
|
||||
@ -391,7 +392,7 @@ pub fn trans_expr_fn(bcx: block,
|
||||
(fn ptr, env) pair
|
||||
*/
|
||||
|
||||
let _icx = bcx.insn_ctxt("closure::trans_expr_fn");
|
||||
let _icx = push_ctxt("closure::trans_expr_fn");
|
||||
|
||||
let dest_addr = match dest {
|
||||
expr::SaveIn(p) => p,
|
||||
@ -468,7 +469,7 @@ pub fn make_closure_glue(
|
||||
v: ValueRef,
|
||||
t: ty::t,
|
||||
glue_fn: @fn(block, v: ValueRef, t: ty::t) -> block) -> block {
|
||||
let _icx = cx.insn_ctxt("closure::make_closure_glue");
|
||||
let _icx = push_ctxt("closure::make_closure_glue");
|
||||
let bcx = cx;
|
||||
let tcx = cx.tcx();
|
||||
|
||||
@ -492,7 +493,7 @@ pub fn make_opaque_cbox_take_glue(
|
||||
cboxptr: ValueRef) // ptr to ptr to the opaque closure
|
||||
-> block {
|
||||
// Easy cases:
|
||||
let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_take_glue");
|
||||
let _icx = push_ctxt("closure::make_opaque_cbox_take_glue");
|
||||
match sigil {
|
||||
ast::BorrowedSigil => {
|
||||
return bcx;
|
||||
@ -509,22 +510,22 @@ pub fn make_opaque_cbox_take_glue(
|
||||
// ~fn requires a deep copy.
|
||||
let ccx = bcx.ccx();
|
||||
let tcx = ccx.tcx;
|
||||
let llopaquecboxty = T_opaque_box_ptr(ccx);
|
||||
let llopaquecboxty = Type::opaque_box(ccx).ptr_to();
|
||||
let cbox_in = Load(bcx, cboxptr);
|
||||
do with_cond(bcx, IsNotNull(bcx, cbox_in)) |bcx| {
|
||||
// Load the size from the type descr found in the cbox
|
||||
let cbox_in = PointerCast(bcx, cbox_in, llopaquecboxty);
|
||||
let tydescptr = GEPi(bcx, cbox_in, [0u, abi::box_field_tydesc]);
|
||||
let tydesc = Load(bcx, tydescptr);
|
||||
let tydesc = PointerCast(bcx, tydesc, T_ptr(ccx.tydesc_type));
|
||||
let tydesc = PointerCast(bcx, tydesc, ccx.tydesc_type.ptr_to());
|
||||
let sz = Load(bcx, GEPi(bcx, tydesc, [0u, abi::tydesc_field_size]));
|
||||
|
||||
// Adjust sz to account for the rust_opaque_box header fields
|
||||
let sz = Add(bcx, sz, machine::llsize_of(ccx, T_box_header(ccx)));
|
||||
let sz = Add(bcx, sz, machine::llsize_of(ccx, Type::box_header(ccx)));
|
||||
|
||||
// Allocate memory, update original ptr, and copy existing data
|
||||
let opaque_tydesc = PointerCast(bcx, tydesc, T_ptr(T_i8()));
|
||||
let rval = alloca(bcx, T_ptr(T_i8()));
|
||||
let opaque_tydesc = PointerCast(bcx, tydesc, Type::i8p());
|
||||
let rval = alloca(bcx, Type::i8p());
|
||||
let bcx = callee::trans_lang_call(
|
||||
bcx,
|
||||
bcx.tcx().lang_items.exchange_malloc_fn(),
|
||||
@ -551,7 +552,7 @@ pub fn make_opaque_cbox_drop_glue(
|
||||
sigil: ast::Sigil,
|
||||
cboxptr: ValueRef) // ptr to the opaque closure
|
||||
-> block {
|
||||
let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_drop_glue");
|
||||
let _icx = push_ctxt("closure::make_opaque_cbox_drop_glue");
|
||||
match sigil {
|
||||
ast::BorrowedSigil => bcx,
|
||||
ast::ManagedSigil => {
|
||||
@ -572,7 +573,7 @@ pub fn make_opaque_cbox_free_glue(
|
||||
sigil: ast::Sigil,
|
||||
cbox: ValueRef) // ptr to ptr to the opaque closure
|
||||
-> block {
|
||||
let _icx = bcx.insn_ctxt("closure::make_opaque_cbox_free_glue");
|
||||
let _icx = push_ctxt("closure::make_opaque_cbox_free_glue");
|
||||
match sigil {
|
||||
ast::BorrowedSigil => {
|
||||
return bcx;
|
||||
@ -585,7 +586,7 @@ pub fn make_opaque_cbox_free_glue(
|
||||
let ccx = bcx.ccx();
|
||||
do with_cond(bcx, IsNotNull(bcx, cbox)) |bcx| {
|
||||
// Load the type descr found in the cbox
|
||||
let lltydescty = T_ptr(ccx.tydesc_type);
|
||||
let lltydescty = ccx.tydesc_type.ptr_to();
|
||||
let cbox = Load(bcx, cbox);
|
||||
let tydescptr = GEPi(bcx, cbox, [0u, abi::box_field_tydesc]);
|
||||
let tydesc = Load(bcx, tydescptr);
|
||||
|
@ -12,18 +12,16 @@
|
||||
|
||||
use core::prelude::*;
|
||||
|
||||
use back::{abi};
|
||||
use driver::session;
|
||||
use driver::session::Session;
|
||||
use lib::llvm::{ValueRef, TypeRef, BasicBlockRef, BuilderRef};
|
||||
use lib::llvm::{ValueRef, BasicBlockRef, BuilderRef};
|
||||
use lib::llvm::{True, False, Bool};
|
||||
use lib::llvm::{llvm, TypeNames, associate_type, name_has_type};
|
||||
use lib::llvm::{llvm};
|
||||
use lib;
|
||||
use middle::trans::base;
|
||||
use middle::trans::build;
|
||||
use middle::trans::datum;
|
||||
use middle::trans::glue;
|
||||
use middle::trans::type_of;
|
||||
use middle::trans::write_guard;
|
||||
use middle::ty::substs;
|
||||
use middle::ty;
|
||||
@ -31,20 +29,19 @@ use middle::typeck;
|
||||
use middle::borrowck::root_map_key;
|
||||
use util::ppaux::{Repr};
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use core::cast::transmute;
|
||||
use core::cast;
|
||||
use core::hashmap::{HashMap};
|
||||
use core::libc::{c_uint, c_longlong, c_ulonglong};
|
||||
use core::str;
|
||||
use core::to_bytes;
|
||||
use core::vec::raw::to_ptr;
|
||||
use core::vec;
|
||||
use syntax::ast::ident;
|
||||
use syntax::ast_map::{path, path_elt};
|
||||
use syntax::codemap::span;
|
||||
use syntax::parse::token;
|
||||
use syntax::{ast, ast_map};
|
||||
use syntax::abi::{X86, X86_64, Arm, Mips};
|
||||
|
||||
pub use middle::trans::context::CrateContext;
|
||||
|
||||
@ -53,36 +50,16 @@ pub use middle::trans::context::CrateContext;
|
||||
pub type namegen = @fn(s: &str) -> ident;
|
||||
pub fn new_namegen() -> namegen {
|
||||
let f: @fn(s: &str) -> ident = |prefix| {
|
||||
token::str_to_ident(fmt!("%s_%u",
|
||||
prefix,
|
||||
token::gensym(prefix)))
|
||||
token::str_to_ident(fmt!("%s_%u", prefix, token::gensym(prefix)))
|
||||
};
|
||||
f
|
||||
}
|
||||
|
||||
pub type addrspace = c_uint;
|
||||
|
||||
// Address spaces communicate to LLVM which destructors need to run for
|
||||
// specific types.
|
||||
// 0 is ignored by the GC, and is used for all non-GC'd pointers.
|
||||
// 1 is for opaque GC'd boxes.
|
||||
// >= 2 are for specific types (e.g. resources).
|
||||
pub static default_addrspace: addrspace = 0;
|
||||
pub static gc_box_addrspace: addrspace = 1;
|
||||
|
||||
pub type addrspace_gen = @fn() -> addrspace;
|
||||
pub fn new_addrspace_gen() -> addrspace_gen {
|
||||
let i = @mut 1;
|
||||
let result: addrspace_gen = || { *i += 1; *i };
|
||||
result
|
||||
}
|
||||
|
||||
pub struct tydesc_info {
|
||||
ty: ty::t,
|
||||
tydesc: ValueRef,
|
||||
size: ValueRef,
|
||||
align: ValueRef,
|
||||
addrspace: addrspace,
|
||||
take_glue: Option<ValueRef>,
|
||||
drop_glue: Option<ValueRef>,
|
||||
free_glue: Option<ValueRef>,
|
||||
@ -124,7 +101,6 @@ pub struct Stats {
|
||||
n_monos: uint,
|
||||
n_inlines: uint,
|
||||
n_closures: uint,
|
||||
llvm_insn_ctxt: ~[~str],
|
||||
llvm_insns: HashMap<~str, uint>,
|
||||
fn_times: ~[(~str, int)] // (ident, time)
|
||||
}
|
||||
@ -347,39 +323,14 @@ pub fn cleanup_type(cx: ty::ctxt, ty: ty::t) -> cleantype {
|
||||
}
|
||||
}
|
||||
|
||||
// This is not the same as datum::Datum::root(), which is used to keep copies
|
||||
// of @ values live for as long as a borrowed pointer to the interior exists.
|
||||
// In the new GC, we can identify immediates on the stack without difficulty,
|
||||
// but have trouble knowing where non-immediates are on the stack. For
|
||||
// non-immediates, we must add an additional level of indirection, which
|
||||
// allows us to alloca a pointer with the right addrspace.
|
||||
pub fn root_for_cleanup(bcx: block, v: ValueRef, t: ty::t)
|
||||
-> (ValueRef, bool) {
|
||||
let ccx = bcx.ccx();
|
||||
|
||||
let addrspace = base::get_tydesc(ccx, t).addrspace;
|
||||
if addrspace > gc_box_addrspace {
|
||||
let llty = type_of::type_of_rooted(ccx, t);
|
||||
let root = base::alloca(bcx, llty);
|
||||
build::Store(bcx, build::PointerCast(bcx, v, llty), root);
|
||||
(root, true)
|
||||
} else {
|
||||
(v, false)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_clean(bcx: block, val: ValueRef, t: ty::t) {
|
||||
if !ty::type_needs_drop(bcx.tcx(), t) { return; }
|
||||
debug!("add_clean(%s, %s, %s)",
|
||||
bcx.to_str(),
|
||||
val_str(bcx.ccx().tn, val),
|
||||
t.repr(bcx.tcx()));
|
||||
let (root, rooted) = root_for_cleanup(bcx, val, t);
|
||||
|
||||
debug!("add_clean(%s, %s, %s)", bcx.to_str(), bcx.val_to_str(val), t.repr(bcx.tcx()));
|
||||
|
||||
let cleanup_type = cleanup_type(bcx.tcx(), t);
|
||||
do in_scope_cx(bcx) |scope_info| {
|
||||
scope_info.cleanups.push(
|
||||
clean(|a| glue::drop_ty_root(a, root, rooted, t),
|
||||
cleanup_type));
|
||||
scope_info.cleanups.push(clean(|a| glue::drop_ty(a, val, t), cleanup_type));
|
||||
grow_scope_clean(scope_info);
|
||||
}
|
||||
}
|
||||
@ -387,7 +338,7 @@ pub fn add_clean(bcx: block, val: ValueRef, t: ty::t) {
|
||||
pub fn add_clean_temp_immediate(cx: block, val: ValueRef, ty: ty::t) {
|
||||
if !ty::type_needs_drop(cx.tcx(), ty) { return; }
|
||||
debug!("add_clean_temp_immediate(%s, %s, %s)",
|
||||
cx.to_str(), val_str(cx.ccx().tn, val),
|
||||
cx.to_str(), cx.val_to_str(val),
|
||||
ty.repr(cx.tcx()));
|
||||
let cleanup_type = cleanup_type(cx.tcx(), ty);
|
||||
do in_scope_cx(cx) |scope_info| {
|
||||
@ -400,14 +351,11 @@ pub fn add_clean_temp_immediate(cx: block, val: ValueRef, ty: ty::t) {
|
||||
pub fn add_clean_temp_mem(bcx: block, val: ValueRef, t: ty::t) {
|
||||
if !ty::type_needs_drop(bcx.tcx(), t) { return; }
|
||||
debug!("add_clean_temp_mem(%s, %s, %s)",
|
||||
bcx.to_str(), val_str(bcx.ccx().tn, val),
|
||||
bcx.to_str(), bcx.val_to_str(val),
|
||||
t.repr(bcx.tcx()));
|
||||
let (root, rooted) = root_for_cleanup(bcx, val, t);
|
||||
let cleanup_type = cleanup_type(bcx.tcx(), t);
|
||||
do in_scope_cx(bcx) |scope_info| {
|
||||
scope_info.cleanups.push(
|
||||
clean_temp(val, |a| glue::drop_ty_root(a, root, rooted, t),
|
||||
cleanup_type));
|
||||
scope_info.cleanups.push(clean_temp(val, |a| glue::drop_ty(a, val, t), cleanup_type));
|
||||
grow_scope_clean(scope_info);
|
||||
}
|
||||
}
|
||||
@ -427,18 +375,14 @@ pub fn add_clean_return_to_mut(bcx: block,
|
||||
|
||||
debug!("add_clean_return_to_mut(%s, %s, %s)",
|
||||
bcx.to_str(),
|
||||
val_str(bcx.ccx().tn, frozen_val_ref),
|
||||
val_str(bcx.ccx().tn, bits_val_ref));
|
||||
bcx.val_to_str(frozen_val_ref),
|
||||
bcx.val_to_str(bits_val_ref));
|
||||
do in_scope_cx(bcx) |scope_info| {
|
||||
scope_info.cleanups.push(
|
||||
clean_temp(
|
||||
frozen_val_ref,
|
||||
|bcx| write_guard::return_to_mut(bcx,
|
||||
root_key,
|
||||
frozen_val_ref,
|
||||
bits_val_ref,
|
||||
filename_val,
|
||||
line_val),
|
||||
|bcx| write_guard::return_to_mut(bcx, root_key, frozen_val_ref, bits_val_ref,
|
||||
filename_val, line_val),
|
||||
normal_exit_only));
|
||||
grow_scope_clean(scope_info);
|
||||
}
|
||||
@ -623,20 +567,12 @@ impl Result {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ty_str(tn: @TypeNames, t: TypeRef) -> @str {
|
||||
return lib::llvm::type_to_str(tn, t);
|
||||
}
|
||||
|
||||
pub fn val_ty(v: ValueRef) -> TypeRef {
|
||||
pub fn val_ty(v: ValueRef) -> Type {
|
||||
unsafe {
|
||||
return llvm::LLVMTypeOf(v);
|
||||
Type::from_ref(llvm::LLVMTypeOf(v))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn val_str(tn: @TypeNames, v: ValueRef) -> @str {
|
||||
return ty_str(tn, val_ty(v));
|
||||
}
|
||||
|
||||
pub fn in_scope_cx(cx: block, f: &fn(si: @mut scope_info)) {
|
||||
let mut cur = cx;
|
||||
loop {
|
||||
@ -664,27 +600,27 @@ pub fn block_parent(cx: block) -> block {
|
||||
// Accessors
|
||||
|
||||
impl block_ {
|
||||
pub fn ccx(@mut self) -> @mut CrateContext { self.fcx.ccx }
|
||||
pub fn tcx(@mut self) -> ty::ctxt { self.fcx.ccx.tcx }
|
||||
pub fn sess(@mut self) -> Session { self.fcx.ccx.sess }
|
||||
pub fn ccx(&self) -> @mut CrateContext { self.fcx.ccx }
|
||||
pub fn tcx(&self) -> ty::ctxt { self.fcx.ccx.tcx }
|
||||
pub fn sess(&self) -> Session { self.fcx.ccx.sess }
|
||||
|
||||
pub fn node_id_to_str(@mut self, id: ast::node_id) -> ~str {
|
||||
pub fn node_id_to_str(&self, id: ast::node_id) -> ~str {
|
||||
ast_map::node_id_to_str(self.tcx().items, id, self.sess().intr())
|
||||
}
|
||||
|
||||
pub fn expr_to_str(@mut self, e: @ast::expr) -> ~str {
|
||||
pub fn expr_to_str(&self, e: @ast::expr) -> ~str {
|
||||
e.repr(self.tcx())
|
||||
}
|
||||
|
||||
pub fn expr_is_lval(@mut self, e: @ast::expr) -> bool {
|
||||
pub fn expr_is_lval(&self, e: @ast::expr) -> bool {
|
||||
ty::expr_is_lval(self.tcx(), self.ccx().maps.method_map, e)
|
||||
}
|
||||
|
||||
pub fn expr_kind(@mut self, e: @ast::expr) -> ty::ExprKind {
|
||||
pub fn expr_kind(&self, e: @ast::expr) -> ty::ExprKind {
|
||||
ty::expr_kind(self.tcx(), self.ccx().maps.method_map, e)
|
||||
}
|
||||
|
||||
pub fn def(@mut self, nid: ast::node_id) -> ast::def {
|
||||
pub fn def(&self, nid: ast::node_id) -> ast::def {
|
||||
match self.tcx().def_map.find(&nid) {
|
||||
Some(&v) => v,
|
||||
None => {
|
||||
@ -694,19 +630,19 @@ impl block_ {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn val_str(@mut self, val: ValueRef) -> @str {
|
||||
val_str(self.ccx().tn, val)
|
||||
pub fn val_to_str(&self, val: ValueRef) -> ~str {
|
||||
self.ccx().tn.val_to_str(val)
|
||||
}
|
||||
|
||||
pub fn llty_str(@mut self, llty: TypeRef) -> @str {
|
||||
ty_str(self.ccx().tn, llty)
|
||||
pub fn llty_str(&self, ty: Type) -> ~str {
|
||||
self.ccx().tn.type_to_str(ty)
|
||||
}
|
||||
|
||||
pub fn ty_to_str(@mut self, t: ty::t) -> ~str {
|
||||
pub fn ty_to_str(&self, t: ty::t) -> ~str {
|
||||
t.repr(self.tcx())
|
||||
}
|
||||
|
||||
pub fn to_str(@mut self) -> ~str {
|
||||
pub fn to_str(&self) -> ~str {
|
||||
unsafe {
|
||||
match self.node_info {
|
||||
Some(node_info) => fmt!("[block %d]", node_info.id),
|
||||
@ -716,229 +652,6 @@ impl block_ {
|
||||
}
|
||||
}
|
||||
|
||||
// LLVM type constructors.
|
||||
pub fn T_void() -> TypeRef {
|
||||
unsafe { return llvm::LLVMVoidTypeInContext(base::task_llcx()); }
|
||||
}
|
||||
|
||||
pub fn T_nil() -> TypeRef {
|
||||
return T_struct([], false)
|
||||
}
|
||||
|
||||
pub fn T_metadata() -> TypeRef {
|
||||
unsafe { return llvm::LLVMMetadataTypeInContext(base::task_llcx()); }
|
||||
}
|
||||
|
||||
pub fn T_i1() -> TypeRef {
|
||||
unsafe { return llvm::LLVMInt1TypeInContext(base::task_llcx()); }
|
||||
}
|
||||
|
||||
pub fn T_i8() -> TypeRef {
|
||||
unsafe { return llvm::LLVMInt8TypeInContext(base::task_llcx()); }
|
||||
}
|
||||
|
||||
pub fn T_i16() -> TypeRef {
|
||||
unsafe { return llvm::LLVMInt16TypeInContext(base::task_llcx()); }
|
||||
}
|
||||
|
||||
pub fn T_i32() -> TypeRef {
|
||||
unsafe { return llvm::LLVMInt32TypeInContext(base::task_llcx()); }
|
||||
}
|
||||
|
||||
pub fn T_i64() -> TypeRef {
|
||||
unsafe { return llvm::LLVMInt64TypeInContext(base::task_llcx()); }
|
||||
}
|
||||
|
||||
pub fn T_f32() -> TypeRef {
|
||||
unsafe { return llvm::LLVMFloatTypeInContext(base::task_llcx()); }
|
||||
}
|
||||
|
||||
pub fn T_f64() -> TypeRef {
|
||||
unsafe { return llvm::LLVMDoubleTypeInContext(base::task_llcx()); }
|
||||
}
|
||||
|
||||
pub fn T_bool() -> TypeRef { return T_i8(); }
|
||||
|
||||
pub fn T_int(targ_cfg: &session::config) -> TypeRef {
|
||||
return match targ_cfg.arch {
|
||||
X86 => T_i32(),
|
||||
X86_64 => T_i64(),
|
||||
Arm => T_i32(),
|
||||
Mips => T_i32()
|
||||
};
|
||||
}
|
||||
|
||||
pub fn T_int_ty(cx: &CrateContext, t: ast::int_ty) -> TypeRef {
|
||||
match t {
|
||||
ast::ty_i => cx.int_type,
|
||||
ast::ty_char => T_char(),
|
||||
ast::ty_i8 => T_i8(),
|
||||
ast::ty_i16 => T_i16(),
|
||||
ast::ty_i32 => T_i32(),
|
||||
ast::ty_i64 => T_i64()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn T_uint_ty(cx: &CrateContext, t: ast::uint_ty) -> TypeRef {
|
||||
match t {
|
||||
ast::ty_u => cx.int_type,
|
||||
ast::ty_u8 => T_i8(),
|
||||
ast::ty_u16 => T_i16(),
|
||||
ast::ty_u32 => T_i32(),
|
||||
ast::ty_u64 => T_i64()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn T_float_ty(cx: &CrateContext, t: ast::float_ty) -> TypeRef {
|
||||
match t {
|
||||
ast::ty_f => cx.float_type,
|
||||
ast::ty_f32 => T_f32(),
|
||||
ast::ty_f64 => T_f64()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn T_float(targ_cfg: &session::config) -> TypeRef {
|
||||
return match targ_cfg.arch {
|
||||
X86 => T_f64(),
|
||||
X86_64 => T_f64(),
|
||||
Arm => T_f64(),
|
||||
Mips => T_f64()
|
||||
};
|
||||
}
|
||||
|
||||
pub fn T_char() -> TypeRef { return T_i32(); }
|
||||
|
||||
pub fn T_size_t(targ_cfg: &session::config) -> TypeRef {
|
||||
return T_int(targ_cfg);
|
||||
}
|
||||
|
||||
pub fn T_fn(inputs: &[TypeRef], output: TypeRef) -> TypeRef {
|
||||
unsafe {
|
||||
return llvm::LLVMFunctionType(output, to_ptr(inputs),
|
||||
inputs.len() as c_uint,
|
||||
False);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn T_fn_pair(cx: &CrateContext, tfn: TypeRef) -> TypeRef {
|
||||
return T_struct([T_ptr(tfn), T_opaque_cbox_ptr(cx)], false);
|
||||
}
|
||||
|
||||
pub fn T_ptr(t: TypeRef) -> TypeRef {
|
||||
unsafe {
|
||||
return llvm::LLVMPointerType(t, default_addrspace);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn T_root(t: TypeRef, addrspace: addrspace) -> TypeRef {
|
||||
unsafe {
|
||||
return llvm::LLVMPointerType(t, addrspace);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn T_struct(elts: &[TypeRef], packed: bool) -> TypeRef {
|
||||
unsafe {
|
||||
return llvm::LLVMStructTypeInContext(base::task_llcx(),
|
||||
to_ptr(elts),
|
||||
elts.len() as c_uint,
|
||||
packed as Bool);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn T_named_struct(name: &str) -> TypeRef {
|
||||
unsafe {
|
||||
return str::as_c_str(name, |buf| {
|
||||
llvm::LLVMStructCreateNamed(base::task_llcx(), buf)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_struct_body(t: TypeRef, elts: &[TypeRef], packed: bool) {
|
||||
unsafe {
|
||||
llvm::LLVMStructSetBody(t,
|
||||
to_ptr(elts),
|
||||
elts.len() as c_uint,
|
||||
packed as Bool);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn T_empty_struct() -> TypeRef { return T_struct([], false); }
|
||||
|
||||
// A vtable is, in reality, a vtable pointer followed by zero or more pointers
|
||||
// to tydescs and other vtables that it closes over. But the types and number
|
||||
// of those are rarely known to the code that needs to manipulate them, so
|
||||
// they are described by this opaque type.
|
||||
pub fn T_vtable() -> TypeRef { T_array(T_ptr(T_i8()), 1u) }
|
||||
|
||||
pub fn T_tydesc_field(cx: &CrateContext, field: uint) -> TypeRef {
|
||||
// Bit of a kludge: pick the fn typeref out of the tydesc..
|
||||
|
||||
unsafe {
|
||||
let mut tydesc_elts: ~[TypeRef] =
|
||||
vec::from_elem::<TypeRef>(abi::n_tydesc_fields,
|
||||
T_nil());
|
||||
llvm::LLVMGetStructElementTypes(cx.tydesc_type, &mut tydesc_elts[0]);
|
||||
let t = llvm::LLVMGetElementType(tydesc_elts[field]);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn T_generic_glue_fn(cx: &mut CrateContext) -> TypeRef {
|
||||
let s = @"glue_fn";
|
||||
match name_has_type(cx.tn, s) {
|
||||
Some(t) => return t,
|
||||
_ => ()
|
||||
}
|
||||
let t = T_tydesc_field(cx, abi::tydesc_field_drop_glue);
|
||||
associate_type(cx.tn, s, t);
|
||||
return t;
|
||||
}
|
||||
|
||||
pub fn T_tydesc(targ_cfg: @session::config) -> TypeRef {
|
||||
let tydesc = T_named_struct("tydesc");
|
||||
let tydescpp = T_ptr(T_ptr(tydesc));
|
||||
let pvoid = T_ptr(T_i8());
|
||||
let glue_fn_ty =
|
||||
T_ptr(T_fn([T_ptr(T_nil()), tydescpp, pvoid], T_void()));
|
||||
|
||||
let int_type = T_int(targ_cfg);
|
||||
let elems =
|
||||
~[int_type, int_type,
|
||||
glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty,
|
||||
T_ptr(T_i8()), T_ptr(T_i8())];
|
||||
set_struct_body(tydesc, elems, false);
|
||||
return tydesc;
|
||||
}
|
||||
|
||||
pub fn T_array(t: TypeRef, n: uint) -> TypeRef {
|
||||
unsafe {
|
||||
return llvm::LLVMArrayType(t, n as c_uint);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn T_vector(t: TypeRef, n: uint) -> TypeRef {
|
||||
unsafe {
|
||||
return llvm::LLVMVectorType(t, n as c_uint);
|
||||
}
|
||||
}
|
||||
|
||||
// Interior vector.
|
||||
pub fn T_vec2(targ_cfg: &session::config, t: TypeRef) -> TypeRef {
|
||||
return T_struct([T_int(targ_cfg), // fill
|
||||
T_int(targ_cfg), // alloc
|
||||
T_array(t, 0u)], // elements
|
||||
false);
|
||||
}
|
||||
|
||||
pub fn T_vec(ccx: &CrateContext, t: TypeRef) -> TypeRef {
|
||||
return T_vec2(ccx.sess.targ_cfg, t);
|
||||
}
|
||||
|
||||
// Note that the size of this one is in bytes.
|
||||
pub fn T_opaque_vec(targ_cfg: @session::config) -> TypeRef {
|
||||
return T_vec2(targ_cfg, T_i8());
|
||||
}
|
||||
|
||||
// Let T be the content of a box @T. tuplify_box_ty(t) returns the
|
||||
// representation of @T as a tuple (i.e., the ty::t version of what T_box()
|
||||
// returns).
|
||||
@ -952,111 +665,31 @@ pub fn tuplify_box_ty(tcx: ty::ctxt, t: ty::t) -> ty::t {
|
||||
t]);
|
||||
}
|
||||
|
||||
pub fn T_box_header_fields(cx: &CrateContext) -> ~[TypeRef] {
|
||||
let ptr = T_ptr(T_i8());
|
||||
return ~[cx.int_type, T_ptr(cx.tydesc_type), ptr, ptr];
|
||||
}
|
||||
|
||||
pub fn T_box_header(cx: &CrateContext) -> TypeRef {
|
||||
return T_struct(T_box_header_fields(cx), false);
|
||||
}
|
||||
|
||||
pub fn T_box(cx: &CrateContext, t: TypeRef) -> TypeRef {
|
||||
return T_struct(vec::append(T_box_header_fields(cx), [t]), false);
|
||||
}
|
||||
|
||||
pub fn T_box_ptr(t: TypeRef) -> TypeRef {
|
||||
unsafe {
|
||||
return llvm::LLVMPointerType(t, gc_box_addrspace);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn T_opaque_box(cx: &CrateContext) -> TypeRef {
|
||||
return T_box(cx, T_i8());
|
||||
}
|
||||
|
||||
pub fn T_opaque_box_ptr(cx: &CrateContext) -> TypeRef {
|
||||
return T_box_ptr(T_opaque_box(cx));
|
||||
}
|
||||
|
||||
pub fn T_unique(cx: &CrateContext, t: TypeRef) -> TypeRef {
|
||||
return T_struct(vec::append(T_box_header_fields(cx), [t]), false);
|
||||
}
|
||||
|
||||
pub fn T_unique_ptr(t: TypeRef) -> TypeRef {
|
||||
unsafe {
|
||||
return llvm::LLVMPointerType(t, gc_box_addrspace);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn T_port(cx: &CrateContext, _t: TypeRef) -> TypeRef {
|
||||
return T_struct([cx.int_type], false); // Refcount
|
||||
|
||||
}
|
||||
|
||||
pub fn T_chan(cx: &CrateContext, _t: TypeRef) -> TypeRef {
|
||||
return T_struct([cx.int_type], false); // Refcount
|
||||
|
||||
}
|
||||
|
||||
|
||||
pub fn T_opaque_cbox_ptr(cx: &CrateContext) -> TypeRef {
|
||||
// closures look like boxes (even when they are ~fn or &fn)
|
||||
// see trans_closure.rs
|
||||
return T_opaque_box_ptr(cx);
|
||||
}
|
||||
|
||||
pub fn T_enum_discrim(cx: &CrateContext) -> TypeRef {
|
||||
return cx.int_type;
|
||||
}
|
||||
|
||||
pub fn T_captured_tydescs(cx: &CrateContext, n: uint) -> TypeRef {
|
||||
return T_struct(vec::from_elem::<TypeRef>(n, T_ptr(cx.tydesc_type)), false);
|
||||
}
|
||||
|
||||
pub fn T_opaque_trait(cx: &CrateContext, store: ty::TraitStore) -> TypeRef {
|
||||
match store {
|
||||
ty::BoxTraitStore => {
|
||||
T_struct([T_ptr(cx.tydesc_type), T_opaque_box_ptr(cx)], false)
|
||||
}
|
||||
ty::UniqTraitStore => {
|
||||
T_struct([T_ptr(cx.tydesc_type),
|
||||
T_unique_ptr(T_unique(cx, T_i8()))],
|
||||
false)
|
||||
}
|
||||
ty::RegionTraitStore(_) => {
|
||||
T_struct([T_ptr(cx.tydesc_type), T_ptr(T_i8())], false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn T_opaque_port_ptr() -> TypeRef { return T_ptr(T_i8()); }
|
||||
|
||||
pub fn T_opaque_chan_ptr() -> TypeRef { return T_ptr(T_i8()); }
|
||||
|
||||
|
||||
// LLVM constant constructors.
|
||||
pub fn C_null(t: TypeRef) -> ValueRef {
|
||||
pub fn C_null(t: Type) -> ValueRef {
|
||||
unsafe {
|
||||
return llvm::LLVMConstNull(t);
|
||||
llvm::LLVMConstNull(t.to_ref())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_undef(t: TypeRef) -> ValueRef {
|
||||
pub fn C_undef(t: Type) -> ValueRef {
|
||||
unsafe {
|
||||
return llvm::LLVMGetUndef(t);
|
||||
llvm::LLVMGetUndef(t.to_ref())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_integral(t: TypeRef, u: u64, sign_extend: Bool) -> ValueRef {
|
||||
pub fn C_integral(t: Type, u: u64, sign_extend: bool) -> ValueRef {
|
||||
unsafe {
|
||||
return llvm::LLVMConstInt(t, u, sign_extend);
|
||||
llvm::LLVMConstInt(t.to_ref(), u, sign_extend as Bool)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_floating(s: &str, t: TypeRef) -> ValueRef {
|
||||
pub fn C_floating(s: &str, t: Type) -> ValueRef {
|
||||
unsafe {
|
||||
return str::as_c_str(s, |buf| llvm::LLVMConstRealOfString(t, buf));
|
||||
do s.as_c_str |buf| {
|
||||
llvm::LLVMConstRealOfString(t.to_ref(), buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1064,32 +697,32 @@ pub fn C_nil() -> ValueRef {
|
||||
return C_struct([]);
|
||||
}
|
||||
|
||||
pub fn C_bool(b: bool) -> ValueRef {
|
||||
C_integral(T_bool(), if b { 1u64 } else { 0u64 }, False)
|
||||
pub fn C_bool(val: bool) -> ValueRef {
|
||||
C_integral(Type::bool(), val as u64, false)
|
||||
}
|
||||
|
||||
pub fn C_i1(b: bool) -> ValueRef {
|
||||
return C_integral(T_i1(), if b { 1 } else { 0 }, False);
|
||||
pub fn C_i1(val: bool) -> ValueRef {
|
||||
C_integral(Type::i1(), val as u64, false)
|
||||
}
|
||||
|
||||
pub fn C_i32(i: i32) -> ValueRef {
|
||||
return C_integral(T_i32(), i as u64, True);
|
||||
return C_integral(Type::i32(), i as u64, true);
|
||||
}
|
||||
|
||||
pub fn C_i64(i: i64) -> ValueRef {
|
||||
return C_integral(T_i64(), i as u64, True);
|
||||
return C_integral(Type::i64(), i as u64, true);
|
||||
}
|
||||
|
||||
pub fn C_int(cx: &CrateContext, i: int) -> ValueRef {
|
||||
return C_integral(cx.int_type, i as u64, True);
|
||||
return C_integral(cx.int_type, i as u64, true);
|
||||
}
|
||||
|
||||
pub fn C_uint(cx: &CrateContext, i: uint) -> ValueRef {
|
||||
return C_integral(cx.int_type, i as u64, False);
|
||||
return C_integral(cx.int_type, i as u64, false);
|
||||
}
|
||||
|
||||
pub fn C_u8(i: uint) -> ValueRef {
|
||||
return C_integral(T_i8(), i as u64, False);
|
||||
return C_integral(Type::i8(), i as u64, false);
|
||||
}
|
||||
|
||||
|
||||
@ -1097,18 +730,19 @@ pub fn C_u8(i: uint) -> ValueRef {
|
||||
// our boxed-and-length-annotated strings.
|
||||
pub fn C_cstr(cx: &mut CrateContext, s: @str) -> ValueRef {
|
||||
unsafe {
|
||||
match cx.const_cstr_cache.find(&s) {
|
||||
match cx.const_cstr_cache.find_equiv(&s) {
|
||||
Some(&llval) => return llval,
|
||||
None => ()
|
||||
}
|
||||
|
||||
let sc = do str::as_c_str(s) |buf| {
|
||||
llvm::LLVMConstStringInContext(cx.llcx, buf, s.len() as c_uint,
|
||||
False)
|
||||
let sc = do s.as_c_str |buf| {
|
||||
llvm::LLVMConstStringInContext(cx.llcx, buf, s.len() as c_uint, False)
|
||||
};
|
||||
|
||||
let gsym = token::gensym("str");
|
||||
let g = do fmt!("str%u", gsym).as_c_str |buf| {
|
||||
llvm::LLVMAddGlobal(cx.llmod, val_ty(sc).to_ref(), buf)
|
||||
};
|
||||
let g =
|
||||
str::as_c_str(fmt!("str%u", (cx.names)("str").name),
|
||||
|buf| llvm::LLVMAddGlobal(cx.llmod, val_ty(sc), buf));
|
||||
llvm::LLVMSetInitializer(g, sc);
|
||||
llvm::LLVMSetGlobalConstant(g, True);
|
||||
lib::llvm::SetLinkage(g, lib::llvm::InternalLinkage);
|
||||
@ -1124,7 +758,7 @@ pub fn C_cstr(cx: &mut CrateContext, s: @str) -> ValueRef {
|
||||
pub fn C_estr_slice(cx: &mut CrateContext, s: @str) -> ValueRef {
|
||||
unsafe {
|
||||
let len = s.len();
|
||||
let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), T_ptr(T_i8()));
|
||||
let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), Type::i8p().to_ref());
|
||||
C_struct([cs, C_uint(cx, len + 1u /* +1 for null */)])
|
||||
}
|
||||
}
|
||||
@ -1132,10 +766,9 @@ pub fn C_estr_slice(cx: &mut CrateContext, s: @str) -> ValueRef {
|
||||
// Returns a Plain Old LLVM String:
|
||||
pub fn C_postr(s: &str) -> ValueRef {
|
||||
unsafe {
|
||||
return do str::as_c_str(s) |buf| {
|
||||
llvm::LLVMConstStringInContext(base::task_llcx(),
|
||||
buf, s.len() as c_uint, False)
|
||||
};
|
||||
do s.as_c_str |buf| {
|
||||
llvm::LLVMConstStringInContext(base::task_llcx(), buf, s.len() as c_uint, False)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1144,17 +777,15 @@ pub fn C_zero_byte_arr(size: uint) -> ValueRef {
|
||||
let mut i = 0u;
|
||||
let mut elts: ~[ValueRef] = ~[];
|
||||
while i < size { elts.push(C_u8(0u)); i += 1u; }
|
||||
return llvm::LLVMConstArray(T_i8(),
|
||||
vec::raw::to_ptr(elts),
|
||||
elts.len() as c_uint);
|
||||
return llvm::LLVMConstArray(Type::i8().to_ref(),
|
||||
vec::raw::to_ptr(elts), elts.len() as c_uint);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_struct(elts: &[ValueRef]) -> ValueRef {
|
||||
unsafe {
|
||||
do vec::as_imm_buf(elts) |ptr, len| {
|
||||
llvm::LLVMConstStructInContext(base::task_llcx(),
|
||||
ptr, len as c_uint, False)
|
||||
llvm::LLVMConstStructInContext(base::task_llcx(), ptr, len as c_uint, False)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1162,54 +793,50 @@ pub fn C_struct(elts: &[ValueRef]) -> ValueRef {
|
||||
pub fn C_packed_struct(elts: &[ValueRef]) -> ValueRef {
|
||||
unsafe {
|
||||
do vec::as_imm_buf(elts) |ptr, len| {
|
||||
llvm::LLVMConstStructInContext(base::task_llcx(),
|
||||
ptr, len as c_uint, True)
|
||||
llvm::LLVMConstStructInContext(base::task_llcx(), ptr, len as c_uint, True)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_named_struct(T: TypeRef, elts: &[ValueRef]) -> ValueRef {
|
||||
pub fn C_named_struct(T: Type, elts: &[ValueRef]) -> ValueRef {
|
||||
unsafe {
|
||||
do vec::as_imm_buf(elts) |ptr, len| {
|
||||
llvm::LLVMConstNamedStruct(T, ptr, len as c_uint)
|
||||
llvm::LLVMConstNamedStruct(T.to_ref(), ptr, len as c_uint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_array(ty: TypeRef, elts: &[ValueRef]) -> ValueRef {
|
||||
pub fn C_array(ty: Type, elts: &[ValueRef]) -> ValueRef {
|
||||
unsafe {
|
||||
return llvm::LLVMConstArray(ty, vec::raw::to_ptr(elts),
|
||||
elts.len() as c_uint);
|
||||
return llvm::LLVMConstArray(ty.to_ref(), vec::raw::to_ptr(elts), elts.len() as c_uint);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_bytes(bytes: &[u8]) -> ValueRef {
|
||||
unsafe {
|
||||
return llvm::LLVMConstStringInContext(base::task_llcx(),
|
||||
cast::transmute(vec::raw::to_ptr(bytes)),
|
||||
bytes.len() as c_uint, True);
|
||||
let ptr = cast::transmute(vec::raw::to_ptr(bytes));
|
||||
return llvm::LLVMConstStringInContext(base::task_llcx(), ptr, bytes.len() as c_uint, True);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_bytes_plus_null(bytes: &[u8]) -> ValueRef {
|
||||
unsafe {
|
||||
return llvm::LLVMConstStringInContext(base::task_llcx(),
|
||||
cast::transmute(vec::raw::to_ptr(bytes)),
|
||||
bytes.len() as c_uint, False);
|
||||
let ptr = cast::transmute(vec::raw::to_ptr(bytes));
|
||||
return llvm::LLVMConstStringInContext(base::task_llcx(), ptr, bytes.len() as c_uint,False);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn C_shape(ccx: &CrateContext, bytes: ~[u8]) -> ValueRef {
|
||||
unsafe {
|
||||
let llshape = C_bytes_plus_null(bytes);
|
||||
let name = fmt!("shape%u", (ccx.names)("shape").name);
|
||||
let llglobal = str::as_c_str(name, |buf| {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, val_ty(llshape), buf)
|
||||
});
|
||||
let name = fmt!("shape%u", token::gensym("shape"));
|
||||
let llglobal = do name.as_c_str |buf| {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, val_ty(llshape).to_ref(), buf)
|
||||
};
|
||||
llvm::LLVMSetInitializer(llglobal, llshape);
|
||||
llvm::LLVMSetGlobalConstant(llglobal, True);
|
||||
lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage);
|
||||
return llvm::LLVMConstPointerCast(llglobal, T_ptr(T_i8()));
|
||||
return llvm::LLVMConstPointerCast(llglobal, Type::i8p().to_ref());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1227,7 +854,7 @@ pub fn const_get_elt(cx: &CrateContext, v: ValueRef, us: &[c_uint])
|
||||
};
|
||||
|
||||
debug!("const_get_elt(v=%s, us=%?, r=%s)",
|
||||
val_str(cx.tn, v), us, val_str(cx.tn, r));
|
||||
cx.tn.val_to_str(v), us, cx.tn.val_to_str(r));
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -1484,7 +1111,7 @@ pub fn filename_and_line_num_from_span(bcx: block,
|
||||
span: span) -> (ValueRef, ValueRef) {
|
||||
let loc = bcx.sess().parse_sess.cm.lookup_char_pos(span.lo);
|
||||
let filename_cstr = C_cstr(bcx.ccx(), loc.file.name);
|
||||
let filename = build::PointerCast(bcx, filename_cstr, T_ptr(T_i8()));
|
||||
let filename = build::PointerCast(bcx, filename_cstr, Type::i8p());
|
||||
let line = C_int(bcx.ccx(), loc.line as int);
|
||||
(filename, line)
|
||||
}
|
||||
|
@ -11,8 +11,7 @@
|
||||
use core::prelude::*;
|
||||
|
||||
use back::abi;
|
||||
use lib::llvm::{llvm, ConstFCmp, ConstICmp, SetLinkage, PrivateLinkage, ValueRef, TypeRef, Bool,
|
||||
True, False};
|
||||
use lib::llvm::{llvm, ConstFCmp, ConstICmp, SetLinkage, PrivateLinkage, ValueRef, Bool, True};
|
||||
use lib::llvm::{IntEQ, IntNE, IntUGT, IntUGE, IntULT, IntULE, IntSGT, IntSGE, IntSLT, IntSLE,
|
||||
RealOEQ, RealOGT, RealOGE, RealOLT, RealOLE, RealONE};
|
||||
|
||||
@ -20,7 +19,7 @@ use metadata::csearch;
|
||||
use middle::const_eval;
|
||||
use middle::trans::adt;
|
||||
use middle::trans::base;
|
||||
use middle::trans::base::get_insn_ctxt;
|
||||
use middle::trans::base::push_ctxt;
|
||||
use middle::trans::common::*;
|
||||
use middle::trans::consts;
|
||||
use middle::trans::expr;
|
||||
@ -30,36 +29,38 @@ use middle::trans::type_of;
|
||||
use middle::ty;
|
||||
use util::ppaux::{Repr, ty_to_str};
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use core::libc::c_uint;
|
||||
use core::str;
|
||||
use syntax::{ast, ast_util, ast_map};
|
||||
|
||||
pub fn const_lit(cx: @mut CrateContext, e: @ast::expr, lit: ast::lit)
|
||||
-> ValueRef {
|
||||
let _icx = cx.insn_ctxt("trans_lit");
|
||||
let _icx = push_ctxt("trans_lit");
|
||||
match lit.node {
|
||||
ast::lit_int(i, t) => C_integral(T_int_ty(cx, t), i as u64, True),
|
||||
ast::lit_uint(u, t) => C_integral(T_uint_ty(cx, t), u, False),
|
||||
ast::lit_int(i, t) => C_integral(Type::int_from_ty(cx, t), i as u64, true),
|
||||
ast::lit_uint(u, t) => C_integral(Type::uint_from_ty(cx, t), u, false),
|
||||
ast::lit_int_unsuffixed(i) => {
|
||||
let lit_int_ty = ty::node_id_to_type(cx.tcx, e.id);
|
||||
match ty::get(lit_int_ty).sty {
|
||||
ty::ty_int(t) => {
|
||||
C_integral(T_int_ty(cx, t), i as u64, True)
|
||||
C_integral(Type::int_from_ty(cx, t), i as u64, true)
|
||||
}
|
||||
ty::ty_uint(t) => {
|
||||
C_integral(T_uint_ty(cx, t), i as u64, False)
|
||||
C_integral(Type::uint_from_ty(cx, t), i as u64, false)
|
||||
}
|
||||
_ => cx.sess.span_bug(lit.span,
|
||||
fmt!("integer literal has type %s (expected int or uint)",
|
||||
ty_to_str(cx.tcx, lit_int_ty)))
|
||||
}
|
||||
}
|
||||
ast::lit_float(fs, t) => C_floating(fs, T_float_ty(cx, t)),
|
||||
ast::lit_float(fs, t) => C_floating(fs, Type::float_from_ty(cx, t)),
|
||||
ast::lit_float_unsuffixed(fs) => {
|
||||
let lit_float_ty = ty::node_id_to_type(cx.tcx, e.id);
|
||||
match ty::get(lit_float_ty).sty {
|
||||
ty::ty_float(t) => {
|
||||
C_floating(fs, T_float_ty(cx, t))
|
||||
C_floating(fs, Type::float_from_ty(cx, t))
|
||||
}
|
||||
_ => {
|
||||
cx.sess.span_bug(lit.span,
|
||||
@ -73,16 +74,16 @@ pub fn const_lit(cx: @mut CrateContext, e: @ast::expr, lit: ast::lit)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn const_ptrcast(cx: &mut CrateContext, a: ValueRef, t: TypeRef) -> ValueRef {
|
||||
pub fn const_ptrcast(cx: &mut CrateContext, a: ValueRef, t: Type) -> ValueRef {
|
||||
unsafe {
|
||||
let b = llvm::LLVMConstPointerCast(a, T_ptr(t));
|
||||
let b = llvm::LLVMConstPointerCast(a, t.ptr_to().to_ref());
|
||||
assert!(cx.const_globals.insert(b as int, a));
|
||||
b
|
||||
}
|
||||
}
|
||||
|
||||
pub fn const_vec(cx: @mut CrateContext, e: @ast::expr, es: &[@ast::expr])
|
||||
-> (ValueRef, ValueRef, TypeRef) {
|
||||
-> (ValueRef, ValueRef, Type) {
|
||||
unsafe {
|
||||
let vec_ty = ty::expr_ty(cx.tcx, e);
|
||||
let unit_ty = ty::sequence_element_type(cx.tcx, vec_ty);
|
||||
@ -102,8 +103,8 @@ pub fn const_vec(cx: @mut CrateContext, e: @ast::expr, es: &[@ast::expr])
|
||||
|
||||
fn const_addr_of(cx: @mut CrateContext, cv: ValueRef) -> ValueRef {
|
||||
unsafe {
|
||||
let gv = do str::as_c_str("const") |name| {
|
||||
llvm::LLVMAddGlobal(cx.llmod, val_ty(cv), name)
|
||||
let gv = do "const".as_c_str |name| {
|
||||
llvm::LLVMAddGlobal(cx.llmod, val_ty(cv).to_ref(), name)
|
||||
};
|
||||
llvm::LLVMSetInitializer(gv, cv);
|
||||
llvm::LLVMSetGlobalConstant(gv, True);
|
||||
@ -180,7 +181,7 @@ pub fn const_expr(cx: @mut CrateContext, e: @ast::expr) -> ValueRef {
|
||||
match adjustment {
|
||||
None => { }
|
||||
Some(@ty::AutoAddEnv(ty::re_static, ast::BorrowedSigil)) => {
|
||||
llconst = C_struct([llconst, C_null(T_opaque_box_ptr(cx))])
|
||||
llconst = C_struct([llconst, C_null(Type::opaque_box(cx).ptr_to())])
|
||||
}
|
||||
Some(@ty::AutoAddEnv(ref r, ref s)) => {
|
||||
cx.sess.span_bug(e.span, fmt!("unexpected static function: \
|
||||
@ -248,7 +249,7 @@ pub fn const_expr(cx: @mut CrateContext, e: @ast::expr) -> ValueRef {
|
||||
|
||||
fn const_expr_unadjusted(cx: @mut CrateContext, e: @ast::expr) -> ValueRef {
|
||||
unsafe {
|
||||
let _icx = cx.insn_ctxt("const_expr");
|
||||
let _icx = push_ctxt("const_expr");
|
||||
return match e.node {
|
||||
ast::expr_lit(lit) => consts::const_lit(cx, e, *lit),
|
||||
ast::expr_binary(_, b, e1, e2) => {
|
||||
@ -349,9 +350,9 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: @ast::expr) -> ValueRef {
|
||||
ty::ty_bool => {
|
||||
// Somewhat questionable, but I believe this is
|
||||
// correct.
|
||||
let te = llvm::LLVMConstTrunc(te, T_i1());
|
||||
let te = llvm::LLVMConstTrunc(te, Type::i1().to_ref());
|
||||
let te = llvm::LLVMConstNot(te);
|
||||
llvm::LLVMConstZExt(te, T_bool())
|
||||
llvm::LLVMConstZExt(te, Type::bool().to_ref())
|
||||
}
|
||||
_ => llvm::LLVMConstNot(te),
|
||||
}
|
||||
@ -426,21 +427,21 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: @ast::expr) -> ValueRef {
|
||||
|
||||
(expr::cast_integral, expr::cast_integral) => {
|
||||
let s = ty::type_is_signed(basety) as Bool;
|
||||
llvm::LLVMConstIntCast(v, llty, s)
|
||||
llvm::LLVMConstIntCast(v, llty.to_ref(), s)
|
||||
}
|
||||
(expr::cast_integral, expr::cast_float) => {
|
||||
if ty::type_is_signed(basety) {
|
||||
llvm::LLVMConstSIToFP(v, llty)
|
||||
llvm::LLVMConstSIToFP(v, llty.to_ref())
|
||||
} else {
|
||||
llvm::LLVMConstUIToFP(v, llty)
|
||||
llvm::LLVMConstUIToFP(v, llty.to_ref())
|
||||
}
|
||||
}
|
||||
(expr::cast_float, expr::cast_float) => {
|
||||
llvm::LLVMConstFPCast(v, llty)
|
||||
llvm::LLVMConstFPCast(v, llty.to_ref())
|
||||
}
|
||||
(expr::cast_float, expr::cast_integral) => {
|
||||
if ty::type_is_signed(ety) { llvm::LLVMConstFPToSI(v, llty) }
|
||||
else { llvm::LLVMConstFPToUI(v, llty) }
|
||||
if ty::type_is_signed(ety) { llvm::LLVMConstFPToSI(v, llty.to_ref()) }
|
||||
else { llvm::LLVMConstFPToUI(v, llty.to_ref()) }
|
||||
}
|
||||
(expr::cast_enum, expr::cast_integral) |
|
||||
(expr::cast_enum, expr::cast_float) => {
|
||||
@ -451,18 +452,18 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: @ast::expr) -> ValueRef {
|
||||
match ety_cast {
|
||||
expr::cast_integral => {
|
||||
let s = ty::type_is_signed(ety) as Bool;
|
||||
llvm::LLVMConstIntCast(iv, llty, s)
|
||||
llvm::LLVMConstIntCast(iv, llty.to_ref(), s)
|
||||
}
|
||||
expr::cast_float => llvm::LLVMConstUIToFP(iv, llty),
|
||||
expr::cast_float => llvm::LLVMConstUIToFP(iv, llty.to_ref()),
|
||||
_ => cx.sess.bug("enum cast destination is not \
|
||||
integral or float")
|
||||
}
|
||||
}
|
||||
(expr::cast_pointer, expr::cast_pointer) => {
|
||||
llvm::LLVMConstPointerCast(v, llty)
|
||||
llvm::LLVMConstPointerCast(v, llty.to_ref())
|
||||
}
|
||||
(expr::cast_integral, expr::cast_pointer) => {
|
||||
llvm::LLVMConstIntToPtr(v, llty)
|
||||
llvm::LLVMConstIntToPtr(v, llty.to_ref())
|
||||
}
|
||||
_ => {
|
||||
cx.sess.impossible_case(e.span,
|
||||
@ -513,7 +514,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: @ast::expr) -> ValueRef {
|
||||
let (cv, sz, llunitty) = const_vec(cx, e, *es);
|
||||
let llty = val_ty(cv);
|
||||
let gv = do str::as_c_str("const") |name| {
|
||||
llvm::LLVMAddGlobal(cx.llmod, llty, name)
|
||||
llvm::LLVMAddGlobal(cx.llmod, llty.to_ref(), name)
|
||||
};
|
||||
llvm::LLVMSetInitializer(gv, cv);
|
||||
llvm::LLVMSetGlobalConstant(gv, True);
|
||||
@ -588,7 +589,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: @ast::expr) -> ValueRef {
|
||||
|
||||
pub fn trans_const(ccx: @mut CrateContext, _e: @ast::expr, id: ast::node_id) {
|
||||
unsafe {
|
||||
let _icx = ccx.insn_ctxt("trans_const");
|
||||
let _icx = push_ctxt("trans_const");
|
||||
let g = base::get_item_val(ccx, id);
|
||||
// At this point, get_item_val has already translated the
|
||||
// constant's initializer to determine its LLVM type.
|
||||
|
@ -12,10 +12,9 @@ use core::prelude::*;
|
||||
|
||||
use back::{upcall};
|
||||
use driver::session;
|
||||
use lib::llvm::{ContextRef, ModuleRef, ValueRef, TypeRef};
|
||||
use lib::llvm::{ContextRef, ModuleRef, ValueRef};
|
||||
use lib::llvm::{llvm, TargetData, TypeNames};
|
||||
use lib::llvm::{mk_target_data, mk_type_names};
|
||||
use lib;
|
||||
use lib::llvm::{mk_target_data};
|
||||
use metadata::common::LinkMeta;
|
||||
use middle::astencode;
|
||||
use middle::resolve;
|
||||
@ -27,15 +26,17 @@ 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;
|
||||
use core::local_data;
|
||||
use extra::time;
|
||||
use syntax::ast;
|
||||
|
||||
use middle::trans::common::{ExternMap,tydesc_info,BuilderRef_res,Stats,namegen,addrspace_gen};
|
||||
use middle::trans::common::{mono_id,T_int,T_float,T_tydesc,T_opaque_vec};
|
||||
use middle::trans::common::{new_namegen,new_addrspace_gen};
|
||||
use middle::trans::common::{ExternMap,tydesc_info,BuilderRef_res,Stats,namegen};
|
||||
use middle::trans::common::{mono_id,new_namegen};
|
||||
|
||||
use middle::trans::base::{decl_crate_map};
|
||||
|
||||
@ -46,7 +47,7 @@ pub struct CrateContext {
|
||||
llmod: ModuleRef,
|
||||
llcx: ContextRef,
|
||||
td: TargetData,
|
||||
tn: @TypeNames,
|
||||
tn: TypeNames,
|
||||
externs: ExternMap,
|
||||
intrinsics: HashMap<&'static str, ValueRef>,
|
||||
item_vals: HashMap<ast::node_id, ValueRef>,
|
||||
@ -92,11 +93,10 @@ pub struct CrateContext {
|
||||
impl_method_cache: HashMap<(ast::def_id, ast::ident), ast::def_id>,
|
||||
|
||||
module_data: HashMap<~str, ValueRef>,
|
||||
lltypes: HashMap<ty::t, TypeRef>,
|
||||
llsizingtypes: HashMap<ty::t, TypeRef>,
|
||||
lltypes: HashMap<ty::t, Type>,
|
||||
llsizingtypes: HashMap<ty::t, Type>,
|
||||
adt_reprs: HashMap<ty::t, @adt::Repr>,
|
||||
names: namegen,
|
||||
next_addrspace: addrspace_gen,
|
||||
symbol_hasher: hash::State,
|
||||
type_hashcodes: HashMap<ty::t, @str>,
|
||||
type_short_names: HashMap<ty::t, ~str>,
|
||||
@ -105,10 +105,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,
|
||||
@ -136,16 +136,25 @@ impl CrateContext {
|
||||
str::as_c_str(data_layout, |buf| llvm::LLVMSetDataLayout(llmod, buf));
|
||||
str::as_c_str(targ_triple, |buf| llvm::LLVMSetTarget(llmod, buf));
|
||||
let targ_cfg = sess.targ_cfg;
|
||||
|
||||
let td = mk_target_data(sess.targ_cfg.target_strs.data_layout);
|
||||
let tn = mk_type_names();
|
||||
let mut tn = TypeNames::new();
|
||||
|
||||
let mut intrinsics = base::declare_intrinsics(llmod);
|
||||
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);
|
||||
lib::llvm::associate_type(tn, @"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);
|
||||
|
||||
let mut str_slice_ty = Type::named_struct("str_slice");
|
||||
str_slice_ty.set_struct_body([Type::i8p(), int_type], false);
|
||||
|
||||
tn.associate_type("tydesc", &tydesc_type);
|
||||
tn.associate_type("str_slice", &str_slice_ty);
|
||||
|
||||
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()))
|
||||
@ -153,6 +162,10 @@ impl CrateContext {
|
||||
None
|
||||
};
|
||||
|
||||
if sess.count_llvm_insns() {
|
||||
base::init_insn_ctxt()
|
||||
}
|
||||
|
||||
CrateContext {
|
||||
sess: sess,
|
||||
llmod: llmod,
|
||||
@ -186,7 +199,6 @@ impl CrateContext {
|
||||
llsizingtypes: HashMap::new(),
|
||||
adt_reprs: HashMap::new(),
|
||||
names: new_namegen(),
|
||||
next_addrspace: new_addrspace_gen(),
|
||||
symbol_hasher: symbol_hasher,
|
||||
type_hashcodes: HashMap::new(),
|
||||
type_short_names: HashMap::new(),
|
||||
@ -202,7 +214,6 @@ impl CrateContext {
|
||||
n_monos: 0u,
|
||||
n_inlines: 0u,
|
||||
n_closures: 0u,
|
||||
llvm_insn_ctxt: ~[],
|
||||
llvm_insns: HashMap::new(),
|
||||
fn_times: ~[]
|
||||
},
|
||||
@ -210,7 +221,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,
|
||||
@ -220,6 +231,12 @@ impl CrateContext {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn log_fn_time(&mut self, name: ~str, start: time::Timespec, end: time::Timespec) {
|
||||
let elapsed = 1000 * ((end.sec - start.sec) as int) +
|
||||
((end.nsec as int) - (start.nsec as int)) / 1000000;
|
||||
self.stats.fn_times.push((name, elapsed));
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
@ -232,7 +249,6 @@ impl Drop for CrateContext {
|
||||
}
|
||||
|
||||
fn task_local_llcx_key(_v: @ContextRef) {}
|
||||
|
||||
pub fn task_llcx() -> ContextRef {
|
||||
let opt = unsafe { local_data::local_data_get(task_local_llcx_key) };
|
||||
*opt.expect("task-local LLVMContextRef wasn't ever set!")
|
||||
|
@ -24,6 +24,8 @@ use middle::ty;
|
||||
use util::common::indenter;
|
||||
use util::ppaux;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use core::str;
|
||||
use core::vec;
|
||||
use syntax::ast;
|
||||
@ -33,7 +35,7 @@ use syntax::ast_util;
|
||||
use syntax::codemap::span;
|
||||
|
||||
pub fn trans_block(bcx: block, b: &ast::blk, dest: expr::Dest) -> block {
|
||||
let _icx = bcx.insn_ctxt("trans_block");
|
||||
let _icx = push_ctxt("trans_block");
|
||||
let mut bcx = bcx;
|
||||
do block_locals(b) |local| {
|
||||
bcx = alloc_local(bcx, local);
|
||||
@ -65,7 +67,7 @@ pub fn trans_if(bcx: block,
|
||||
dest.to_str(bcx.ccx()));
|
||||
let _indenter = indenter();
|
||||
|
||||
let _icx = bcx.insn_ctxt("trans_if");
|
||||
let _icx = push_ctxt("trans_if");
|
||||
let Result {bcx, val: cond_val} =
|
||||
expr::trans_to_datum(bcx, cond).to_result();
|
||||
|
||||
@ -124,7 +126,7 @@ pub fn join_blocks(parent_bcx: block, in_cxs: &[block]) -> block {
|
||||
}
|
||||
|
||||
pub fn trans_while(bcx: block, cond: @ast::expr, body: &ast::blk) -> block {
|
||||
let _icx = bcx.insn_ctxt("trans_while");
|
||||
let _icx = push_ctxt("trans_while");
|
||||
let next_bcx = sub_block(bcx, "while next");
|
||||
|
||||
// bcx
|
||||
@ -166,7 +168,7 @@ pub fn trans_loop(bcx:block,
|
||||
body: &ast::blk,
|
||||
opt_label: Option<ident>)
|
||||
-> block {
|
||||
let _icx = bcx.insn_ctxt("trans_loop");
|
||||
let _icx = push_ctxt("trans_loop");
|
||||
let next_bcx = sub_block(bcx, "next");
|
||||
let body_bcx_in = loop_scope_block(bcx, next_bcx, opt_label, "`loop`",
|
||||
body.info());
|
||||
@ -180,7 +182,7 @@ pub fn trans_log(log_ex: @ast::expr,
|
||||
lvl: @ast::expr,
|
||||
bcx: block,
|
||||
e: @ast::expr) -> block {
|
||||
let _icx = bcx.insn_ctxt("trans_log");
|
||||
let _icx = push_ctxt("trans_log");
|
||||
let ccx = bcx.ccx();
|
||||
let mut bcx = bcx;
|
||||
if ty::type_is_bot(expr_ty(bcx, lvl)) {
|
||||
@ -204,10 +206,10 @@ pub fn trans_log(log_ex: @ast::expr,
|
||||
let global;
|
||||
unsafe {
|
||||
global = str::as_c_str(s, |buf| {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, T_i32(), buf)
|
||||
llvm::LLVMAddGlobal(ccx.llmod, Type::i32().to_ref(), buf)
|
||||
});
|
||||
llvm::LLVMSetGlobalConstant(global, False);
|
||||
llvm::LLVMSetInitializer(global, C_null(T_i32()));
|
||||
llvm::LLVMSetInitializer(global, C_null(Type::i32()));
|
||||
lib::llvm::SetLinkage(global, lib::llvm::InternalLinkage);
|
||||
}
|
||||
ccx.module_data.insert(modname, global);
|
||||
@ -242,7 +244,7 @@ pub fn trans_break_cont(bcx: block,
|
||||
opt_label: Option<ident>,
|
||||
to_end: bool)
|
||||
-> block {
|
||||
let _icx = bcx.insn_ctxt("trans_break_cont");
|
||||
let _icx = push_ctxt("trans_break_cont");
|
||||
// Locate closest loop block, outputting cleanup as we go.
|
||||
let mut unwind = bcx;
|
||||
let mut target;
|
||||
@ -296,7 +298,7 @@ pub fn trans_cont(bcx: block, label_opt: Option<ident>) -> block {
|
||||
}
|
||||
|
||||
pub fn trans_ret(bcx: block, e: Option<@ast::expr>) -> block {
|
||||
let _icx = bcx.insn_ctxt("trans_ret");
|
||||
let _icx = push_ctxt("trans_ret");
|
||||
let mut bcx = bcx;
|
||||
let dest = match copy bcx.fcx.loop_ret {
|
||||
Some((flagptr, retptr)) => {
|
||||
@ -307,7 +309,7 @@ pub fn trans_ret(bcx: block, e: Option<@ast::expr>) -> block {
|
||||
Store(bcx, C_bool(false), bcx.fcx.llretptr.get());
|
||||
expr::SaveIn(match e {
|
||||
Some(x) => PointerCast(bcx, retptr,
|
||||
T_ptr(type_of(bcx.ccx(), expr_ty(bcx, x)))),
|
||||
type_of(bcx.ccx(), expr_ty(bcx, x)).ptr_to()),
|
||||
None => retptr
|
||||
})
|
||||
}
|
||||
@ -331,7 +333,7 @@ pub fn trans_fail_expr(bcx: block,
|
||||
sp_opt: Option<span>,
|
||||
fail_expr: Option<@ast::expr>)
|
||||
-> block {
|
||||
let _icx = bcx.insn_ctxt("trans_fail_expr");
|
||||
let _icx = push_ctxt("trans_fail_expr");
|
||||
let mut bcx = bcx;
|
||||
match fail_expr {
|
||||
Some(arg_expr) => {
|
||||
@ -359,7 +361,7 @@ pub fn trans_fail(bcx: block,
|
||||
sp_opt: Option<span>,
|
||||
fail_str: @str)
|
||||
-> block {
|
||||
let _icx = bcx.insn_ctxt("trans_fail");
|
||||
let _icx = push_ctxt("trans_fail");
|
||||
let V_fail_str = C_cstr(bcx.ccx(), fail_str);
|
||||
return trans_fail_value(bcx, sp_opt, V_fail_str);
|
||||
}
|
||||
@ -368,7 +370,7 @@ fn trans_fail_value(bcx: block,
|
||||
sp_opt: Option<span>,
|
||||
V_fail_str: ValueRef)
|
||||
-> block {
|
||||
let _icx = bcx.insn_ctxt("trans_fail_value");
|
||||
let _icx = push_ctxt("trans_fail_value");
|
||||
let ccx = bcx.ccx();
|
||||
let (V_filename, V_line) = match sp_opt {
|
||||
Some(sp) => {
|
||||
@ -381,8 +383,8 @@ fn trans_fail_value(bcx: block,
|
||||
(C_cstr(bcx.ccx(), @"<runtime>"), 0)
|
||||
}
|
||||
};
|
||||
let V_str = PointerCast(bcx, V_fail_str, T_ptr(T_i8()));
|
||||
let V_filename = PointerCast(bcx, V_filename, T_ptr(T_i8()));
|
||||
let V_str = PointerCast(bcx, V_fail_str, Type::i8p());
|
||||
let V_filename = PointerCast(bcx, V_filename, Type::i8p());
|
||||
let args = ~[V_str, V_filename, C_int(ccx, V_line)];
|
||||
let bcx = callee::trans_lang_call(
|
||||
bcx, bcx.tcx().lang_items.fail_fn(), args, expr::Ignore);
|
||||
@ -392,7 +394,7 @@ fn trans_fail_value(bcx: block,
|
||||
|
||||
pub fn trans_fail_bounds_check(bcx: block, sp: span,
|
||||
index: ValueRef, len: ValueRef) -> block {
|
||||
let _icx = bcx.insn_ctxt("trans_fail_bounds_check");
|
||||
let _icx = push_ctxt("trans_fail_bounds_check");
|
||||
let (filename, line) = filename_and_line_num_from_span(bcx, sp);
|
||||
let args = ~[filename, line, index, len];
|
||||
let bcx = callee::trans_lang_call(
|
||||
|
@ -273,14 +273,14 @@ impl Datum {
|
||||
* `store_to()` instead, which will move if possible but copy if
|
||||
* neccessary. */
|
||||
|
||||
let _icx = bcx.insn_ctxt("copy_to");
|
||||
let _icx = push_ctxt("copy_to");
|
||||
|
||||
if ty::type_is_nil(self.ty) || ty::type_is_bot(self.ty) {
|
||||
return bcx;
|
||||
}
|
||||
|
||||
debug!("copy_to(self=%s, action=%?, dst=%s)",
|
||||
self.to_str(bcx.ccx()), action, bcx.val_str(dst));
|
||||
self.to_str(bcx.ccx()), action, bcx.val_to_str(dst));
|
||||
|
||||
// Watch out for the case where we are writing the copying the
|
||||
// value into the same location we read it out from. We want
|
||||
@ -317,7 +317,7 @@ impl Datum {
|
||||
* A helper for `copy_to()` which does not check to see if we
|
||||
* are copying to/from the same value. */
|
||||
|
||||
let _icx = bcx.insn_ctxt("copy_to_no_check");
|
||||
let _icx = push_ctxt("copy_to_no_check");
|
||||
let mut bcx = bcx;
|
||||
|
||||
if action == DROP_EXISTING {
|
||||
@ -341,11 +341,11 @@ impl Datum {
|
||||
//
|
||||
pub fn move_to(&self, bcx: block, action: CopyAction, dst: ValueRef)
|
||||
-> block {
|
||||
let _icx = bcx.insn_ctxt("move_to");
|
||||
let _icx = push_ctxt("move_to");
|
||||
let mut bcx = bcx;
|
||||
|
||||
debug!("move_to(self=%s, action=%?, dst=%s)",
|
||||
self.to_str(bcx.ccx()), action, bcx.val_str(dst));
|
||||
self.to_str(bcx.ccx()), action, bcx.val_to_str(dst));
|
||||
|
||||
if ty::type_is_nil(self.ty) || ty::type_is_bot(self.ty) {
|
||||
return bcx;
|
||||
@ -409,7 +409,7 @@ impl Datum {
|
||||
|
||||
pub fn to_str(&self, ccx: &CrateContext) -> ~str {
|
||||
fmt!("Datum { val=%s, ty=%s, mode=%? }",
|
||||
val_str(ccx.tn, self.val),
|
||||
ccx.tn.val_to_str(self.val),
|
||||
ty_to_str(ccx.tcx, self.ty),
|
||||
self.mode)
|
||||
}
|
||||
@ -474,7 +474,7 @@ impl Datum {
|
||||
ByRef(_) => self.val,
|
||||
ByValue => {
|
||||
if ty::type_is_nil(self.ty) || ty::type_is_bot(self.ty) {
|
||||
C_null(T_ptr(type_of::type_of(bcx.ccx(), self.ty)))
|
||||
C_null(type_of::type_of(bcx.ccx(), self.ty).ptr_to())
|
||||
} else {
|
||||
let slot = alloc_ty(bcx, self.ty);
|
||||
Store(bcx, self.val, slot);
|
||||
@ -740,7 +740,7 @@ impl Datum {
|
||||
expr_id: ast::node_id,
|
||||
max: uint)
|
||||
-> DatumBlock {
|
||||
let _icx = bcx.insn_ctxt("autoderef");
|
||||
let _icx = push_ctxt("autoderef");
|
||||
|
||||
debug!("autoderef(expr_id=%d, max=%?, self=%?)",
|
||||
expr_id, max, self.to_str(bcx.ccx()));
|
||||
|
@ -122,7 +122,7 @@ lvalues are *never* stored by value.
|
||||
use core::prelude::*;
|
||||
|
||||
use back::abi;
|
||||
use lib::llvm::{ValueRef, TypeRef, llvm};
|
||||
use lib::llvm::{ValueRef, llvm};
|
||||
use lib;
|
||||
use metadata::csearch;
|
||||
use middle::trans::_match;
|
||||
@ -152,6 +152,8 @@ use middle::ty;
|
||||
use util::common::indenter;
|
||||
use util::ppaux::Repr;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use core::cast::transmute;
|
||||
use core::hashmap::HashMap;
|
||||
use core::vec;
|
||||
@ -173,7 +175,7 @@ pub enum Dest {
|
||||
impl Dest {
|
||||
pub fn to_str(&self, ccx: &CrateContext) -> ~str {
|
||||
match *self {
|
||||
SaveIn(v) => fmt!("SaveIn(%s)", val_str(ccx.tn, v)),
|
||||
SaveIn(v) => fmt!("SaveIn(%s)", ccx.tn.val_to_str(v)),
|
||||
Ignore => ~"Ignore"
|
||||
}
|
||||
}
|
||||
@ -449,7 +451,7 @@ fn trans_to_datum_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
||||
}
|
||||
|
||||
fn trans_rvalue_datum_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
||||
let _icx = bcx.insn_ctxt("trans_rvalue_datum_unadjusted");
|
||||
let _icx = push_ctxt("trans_rvalue_datum_unadjusted");
|
||||
|
||||
trace_span!(bcx, expr.span, shorten(bcx.expr_to_str(expr)));
|
||||
|
||||
@ -500,7 +502,7 @@ fn trans_rvalue_datum_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
||||
|
||||
fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block {
|
||||
let mut bcx = bcx;
|
||||
let _icx = bcx.insn_ctxt("trans_rvalue_stmt");
|
||||
let _icx = push_ctxt("trans_rvalue_stmt");
|
||||
|
||||
if bcx.unreachable {
|
||||
return bcx;
|
||||
@ -556,7 +558,7 @@ fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block {
|
||||
|
||||
fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
|
||||
dest: Dest) -> block {
|
||||
let _icx = bcx.insn_ctxt("trans_rvalue_dps_unadjusted");
|
||||
let _icx = push_ctxt("trans_rvalue_dps_unadjusted");
|
||||
let tcx = bcx.tcx();
|
||||
|
||||
trace_span!(bcx, expr.span, shorten(bcx.expr_to_str(expr)));
|
||||
@ -705,7 +707,7 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
|
||||
|
||||
fn trans_def_dps_unadjusted(bcx: block, ref_expr: @ast::expr,
|
||||
def: ast::def, dest: Dest) -> block {
|
||||
let _icx = bcx.insn_ctxt("trans_def_dps_unadjusted");
|
||||
let _icx = push_ctxt("trans_def_dps_unadjusted");
|
||||
let ccx = bcx.ccx();
|
||||
|
||||
let lldest = match dest {
|
||||
@ -753,7 +755,7 @@ fn trans_def_datum_unadjusted(bcx: block,
|
||||
ref_expr: @ast::expr,
|
||||
def: ast::def) -> DatumBlock
|
||||
{
|
||||
let _icx = bcx.insn_ctxt("trans_def_datum_unadjusted");
|
||||
let _icx = push_ctxt("trans_def_datum_unadjusted");
|
||||
|
||||
match def {
|
||||
ast::def_fn(did, _) | ast::def_static_method(did, None, _) => {
|
||||
@ -794,7 +796,7 @@ fn trans_def_datum_unadjusted(bcx: block,
|
||||
ty: ty::mk_mach_uint(ast::ty_u8),
|
||||
mutbl: ast::m_imm
|
||||
}); // *u8
|
||||
(rust_ty, PointerCast(bcx, fn_data.llfn, T_ptr(T_i8())))
|
||||
(rust_ty, PointerCast(bcx, fn_data.llfn, Type::i8p()))
|
||||
} else {
|
||||
let fn_ty = expr_ty(bcx, ref_expr);
|
||||
(fn_ty, fn_data.llfn)
|
||||
@ -814,7 +816,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
||||
* Translates an lvalue expression, always yielding a by-ref
|
||||
* datum. Does not apply any adjustments. */
|
||||
|
||||
let _icx = bcx.insn_ctxt("trans_lval");
|
||||
let _icx = push_ctxt("trans_lval");
|
||||
let mut bcx = bcx;
|
||||
|
||||
debug!("trans_lvalue(expr=%s)", bcx.expr_to_str(expr));
|
||||
@ -853,7 +855,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
||||
//! Translates `base.field`.
|
||||
|
||||
let mut bcx = bcx;
|
||||
let _icx = bcx.insn_ctxt("trans_rec_field");
|
||||
let _icx = push_ctxt("trans_rec_field");
|
||||
|
||||
let base_datum = unpack_datum!(bcx, trans_to_datum(bcx, base));
|
||||
let repr = adt::represent_type(bcx.ccx(), base_datum.ty);
|
||||
@ -876,7 +878,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
||||
idx: @ast::expr) -> DatumBlock {
|
||||
//! Translates `base[idx]`.
|
||||
|
||||
let _icx = bcx.insn_ctxt("trans_index");
|
||||
let _icx = push_ctxt("trans_index");
|
||||
let ccx = bcx.ccx();
|
||||
let base_ty = expr_ty(bcx, base);
|
||||
let mut bcx = bcx;
|
||||
@ -914,8 +916,8 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
||||
len = Sub(bcx, len, C_uint(bcx.ccx(), 1u));
|
||||
}
|
||||
|
||||
debug!("trans_index: base %s", val_str(bcx.ccx().tn, base));
|
||||
debug!("trans_index: len %s", val_str(bcx.ccx().tn, len));
|
||||
debug!("trans_index: base %s", bcx.val_to_str(base));
|
||||
debug!("trans_index: len %s", bcx.val_to_str(len));
|
||||
|
||||
let bounds_check = ICmp(bcx, lib::llvm::IntUGE, scaled_ix, len);
|
||||
let bcx = do with_cond(bcx, bounds_check) |bcx| {
|
||||
@ -924,7 +926,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
||||
ix_val, unscaled_len)
|
||||
};
|
||||
let elt = InBoundsGEP(bcx, base, [ix_val]);
|
||||
let elt = PointerCast(bcx, elt, T_ptr(vt.llunit_ty));
|
||||
let elt = PointerCast(bcx, elt, vt.llunit_ty.ptr_to());
|
||||
return DatumBlock {
|
||||
bcx: bcx,
|
||||
datum: Datum {val: elt,
|
||||
@ -940,7 +942,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
||||
{
|
||||
//! Translates a reference to a path.
|
||||
|
||||
let _icx = bcx.insn_ctxt("trans_def_lvalue");
|
||||
let _icx = push_ctxt("trans_def_lvalue");
|
||||
let ccx = bcx.ccx();
|
||||
match def {
|
||||
ast::def_const(did) => {
|
||||
@ -963,7 +965,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
||||
// which may not be equal to the enum's type for
|
||||
// non-C-like enums.
|
||||
let val = base::get_item_val(bcx.ccx(), did.node);
|
||||
let pty = T_ptr(type_of(bcx.ccx(), const_ty));
|
||||
let pty = type_of(bcx.ccx(), const_ty).ptr_to();
|
||||
PointerCast(bcx, val, pty)
|
||||
} else {
|
||||
{
|
||||
@ -981,9 +983,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
||||
let symbol = csearch::get_symbol(
|
||||
bcx.ccx().sess.cstore,
|
||||
did);
|
||||
let llval = llvm::LLVMAddGlobal(
|
||||
bcx.ccx().llmod,
|
||||
llty,
|
||||
let llval = llvm::LLVMAddGlobal( bcx.ccx().llmod, llty.to_ref(),
|
||||
transmute::<&u8,*i8>(&symbol[0]));
|
||||
let extern_const_values = &mut bcx.ccx().extern_const_values;
|
||||
extern_const_values.insert(did, llval);
|
||||
@ -1012,7 +1012,7 @@ fn trans_lvalue_unadjusted(bcx: block, expr: @ast::expr) -> DatumBlock {
|
||||
}
|
||||
|
||||
pub fn trans_local_var(bcx: block, def: ast::def) -> Datum {
|
||||
let _icx = bcx.insn_ctxt("trans_local_var");
|
||||
let _icx = push_ctxt("trans_local_var");
|
||||
|
||||
return match def {
|
||||
ast::def_upvar(nid, _, _, _) => {
|
||||
@ -1054,7 +1054,7 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum {
|
||||
// This cast should not be necessary. We should cast self *once*,
|
||||
// but right now this conflicts with default methods.
|
||||
let real_self_ty = monomorphize_type(bcx, self_info.t);
|
||||
let llselfty = T_ptr(type_of::type_of(bcx.ccx(), real_self_ty));
|
||||
let llselfty = type_of::type_of(bcx.ccx(), real_self_ty).ptr_to();
|
||||
|
||||
let casted_val = PointerCast(bcx, self_info.v, llselfty);
|
||||
Datum {
|
||||
@ -1081,7 +1081,7 @@ pub fn trans_local_var(bcx: block, def: ast::def) -> Datum {
|
||||
};
|
||||
let ty = node_id_type(bcx, nid);
|
||||
debug!("take_local(nid=%?, v=%s, ty=%s)",
|
||||
nid, bcx.val_str(v), bcx.ty_to_str(ty));
|
||||
nid, bcx.val_to_str(v), bcx.ty_to_str(ty));
|
||||
Datum {
|
||||
val: v,
|
||||
ty: ty,
|
||||
@ -1143,7 +1143,7 @@ fn trans_rec_or_struct(bcx: block,
|
||||
id: ast::node_id,
|
||||
dest: Dest) -> block
|
||||
{
|
||||
let _icx = bcx.insn_ctxt("trans_rec");
|
||||
let _icx = push_ctxt("trans_rec");
|
||||
let bcx = bcx;
|
||||
|
||||
let ty = node_id_type(bcx, id);
|
||||
@ -1217,7 +1217,7 @@ fn trans_adt(bcx: block, repr: &adt::Repr, discr: int,
|
||||
fields: &[(uint, @ast::expr)],
|
||||
optbase: Option<StructBaseInfo>,
|
||||
dest: Dest) -> block {
|
||||
let _icx = bcx.insn_ctxt("trans_adt");
|
||||
let _icx = push_ctxt("trans_adt");
|
||||
let mut bcx = bcx;
|
||||
let addr = match dest {
|
||||
Ignore => {
|
||||
@ -1263,7 +1263,7 @@ fn trans_adt(bcx: block, repr: &adt::Repr, discr: int,
|
||||
fn trans_immediate_lit(bcx: block, expr: @ast::expr,
|
||||
lit: ast::lit) -> DatumBlock {
|
||||
// must not be a string constant, that is a RvalueDpsExpr
|
||||
let _icx = bcx.insn_ctxt("trans_immediate_lit");
|
||||
let _icx = push_ctxt("trans_immediate_lit");
|
||||
let ty = expr_ty(bcx, expr);
|
||||
immediate_rvalue_bcx(bcx, consts::const_lit(bcx.ccx(), expr, lit), ty)
|
||||
}
|
||||
@ -1272,7 +1272,7 @@ fn trans_unary_datum(bcx: block,
|
||||
un_expr: @ast::expr,
|
||||
op: ast::unop,
|
||||
sub_expr: @ast::expr) -> DatumBlock {
|
||||
let _icx = bcx.insn_ctxt("trans_unary_datum");
|
||||
let _icx = push_ctxt("trans_unary_datum");
|
||||
|
||||
// if deref, would be LvalueExpr
|
||||
assert!(op != ast::deref);
|
||||
@ -1333,7 +1333,7 @@ fn trans_unary_datum(bcx: block,
|
||||
contents: @ast::expr,
|
||||
contents_ty: ty::t,
|
||||
heap: heap) -> DatumBlock {
|
||||
let _icx = bcx.insn_ctxt("trans_boxed_expr");
|
||||
let _icx = push_ctxt("trans_boxed_expr");
|
||||
let base::MallocResult { bcx, box: bx, body } =
|
||||
base::malloc_general(bcx, contents_ty, heap);
|
||||
add_clean_free(bcx, bx, heap);
|
||||
@ -1345,7 +1345,7 @@ fn trans_unary_datum(bcx: block,
|
||||
|
||||
fn trans_addr_of(bcx: block, expr: @ast::expr,
|
||||
subexpr: @ast::expr) -> DatumBlock {
|
||||
let _icx = bcx.insn_ctxt("trans_addr_of");
|
||||
let _icx = push_ctxt("trans_addr_of");
|
||||
let mut bcx = bcx;
|
||||
let sub_datum = unpack_datum!(bcx, trans_to_datum(bcx, subexpr));
|
||||
let llval = sub_datum.to_ref_llval(bcx);
|
||||
@ -1361,7 +1361,7 @@ fn trans_eager_binop(bcx: block,
|
||||
lhs_datum: &Datum,
|
||||
rhs_datum: &Datum)
|
||||
-> DatumBlock {
|
||||
let _icx = bcx.insn_ctxt("trans_eager_binop");
|
||||
let _icx = push_ctxt("trans_eager_binop");
|
||||
|
||||
let lhs = lhs_datum.to_appropriate_llval(bcx);
|
||||
let lhs_t = lhs_datum.ty;
|
||||
@ -1438,7 +1438,7 @@ fn trans_eager_binop(bcx: block,
|
||||
}
|
||||
let cmpr = base::compare_scalar_types(bcx, lhs, rhs, rhs_t, op);
|
||||
bcx = cmpr.bcx;
|
||||
ZExt(bcx, cmpr.val, T_i8())
|
||||
ZExt(bcx, cmpr.val, Type::i8())
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
@ -1457,7 +1457,7 @@ fn trans_lazy_binop(bcx: block,
|
||||
op: lazy_binop_ty,
|
||||
a: @ast::expr,
|
||||
b: @ast::expr) -> DatumBlock {
|
||||
let _icx = bcx.insn_ctxt("trans_lazy_binop");
|
||||
let _icx = push_ctxt("trans_lazy_binop");
|
||||
let binop_ty = expr_ty(bcx, binop_expr);
|
||||
let bcx = bcx;
|
||||
|
||||
@ -1491,7 +1491,7 @@ fn trans_lazy_binop(bcx: block,
|
||||
}
|
||||
|
||||
Br(past_rhs, join.llbb);
|
||||
let phi = Phi(join, T_bool(), [lhs, rhs], [past_lhs.llbb,
|
||||
let phi = Phi(join, Type::bool(), [lhs, rhs], [past_lhs.llbb,
|
||||
past_rhs.llbb]);
|
||||
|
||||
return immediate_rvalue_bcx(join, phi, binop_ty);
|
||||
@ -1503,7 +1503,7 @@ fn trans_binary(bcx: block,
|
||||
lhs: @ast::expr,
|
||||
rhs: @ast::expr) -> DatumBlock
|
||||
{
|
||||
let _icx = bcx.insn_ctxt("trans_binary");
|
||||
let _icx = push_ctxt("trans_binary");
|
||||
|
||||
match op {
|
||||
ast::and => {
|
||||
@ -1548,12 +1548,12 @@ fn trans_overloaded_op(bcx: block,
|
||||
DoAutorefArg)
|
||||
}
|
||||
|
||||
fn int_cast(bcx: block, lldsttype: TypeRef, llsrctype: TypeRef,
|
||||
fn int_cast(bcx: block, lldsttype: Type, llsrctype: Type,
|
||||
llsrc: ValueRef, signed: bool) -> ValueRef {
|
||||
let _icx = bcx.insn_ctxt("int_cast");
|
||||
let _icx = push_ctxt("int_cast");
|
||||
unsafe {
|
||||
let srcsz = llvm::LLVMGetIntTypeWidth(llsrctype);
|
||||
let dstsz = llvm::LLVMGetIntTypeWidth(lldsttype);
|
||||
let srcsz = llvm::LLVMGetIntTypeWidth(llsrctype.to_ref());
|
||||
let dstsz = llvm::LLVMGetIntTypeWidth(lldsttype.to_ref());
|
||||
return if dstsz == srcsz {
|
||||
BitCast(bcx, llsrc, lldsttype)
|
||||
} else if srcsz > dstsz {
|
||||
@ -1566,11 +1566,11 @@ fn int_cast(bcx: block, lldsttype: TypeRef, llsrctype: TypeRef,
|
||||
}
|
||||
}
|
||||
|
||||
fn float_cast(bcx: block, lldsttype: TypeRef, llsrctype: TypeRef,
|
||||
fn float_cast(bcx: block, lldsttype: Type, llsrctype: Type,
|
||||
llsrc: ValueRef) -> ValueRef {
|
||||
let _icx = bcx.insn_ctxt("float_cast");
|
||||
let srcsz = lib::llvm::float_width(llsrctype);
|
||||
let dstsz = lib::llvm::float_width(lldsttype);
|
||||
let _icx = push_ctxt("float_cast");
|
||||
let srcsz = llsrctype.float_width();
|
||||
let dstsz = lldsttype.float_width();
|
||||
return if dstsz > srcsz {
|
||||
FPExt(bcx, llsrc, lldsttype)
|
||||
} else if srcsz > dstsz {
|
||||
@ -1602,7 +1602,7 @@ pub fn cast_type_kind(t: ty::t) -> cast_kind {
|
||||
|
||||
fn trans_imm_cast(bcx: block, expr: @ast::expr,
|
||||
id: ast::node_id) -> DatumBlock {
|
||||
let _icx = bcx.insn_ctxt("trans_cast");
|
||||
let _icx = push_ctxt("trans_cast");
|
||||
let ccx = bcx.ccx();
|
||||
|
||||
let t_out = node_id_type(bcx, id);
|
||||
@ -1669,7 +1669,7 @@ fn trans_assign_op(bcx: block,
|
||||
dst: @ast::expr,
|
||||
src: @ast::expr) -> block
|
||||
{
|
||||
let _icx = bcx.insn_ctxt("trans_assign_op");
|
||||
let _icx = push_ctxt("trans_assign_op");
|
||||
let mut bcx = bcx;
|
||||
|
||||
debug!("trans_assign_op(expr=%s)", bcx.expr_to_str(expr));
|
||||
|
@ -11,8 +11,7 @@
|
||||
use core::prelude::*;
|
||||
|
||||
use back::{link, abi};
|
||||
use lib::llvm::{SequentiallyConsistent, Acquire, Release, Xchg};
|
||||
use lib::llvm::{TypeRef, ValueRef};
|
||||
use lib::llvm::{ValueRef};
|
||||
use lib;
|
||||
use middle::trans::base::*;
|
||||
use middle::trans::cabi;
|
||||
@ -45,6 +44,7 @@ use syntax::parse::token;
|
||||
use syntax::abi::{X86, X86_64, Arm, Mips};
|
||||
use syntax::abi::{RustIntrinsic, Rust, Stdcall, Fastcall,
|
||||
Cdecl, Aapcs, C};
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
fn abi_info(ccx: @mut CrateContext) -> @cabi::ABIInfo {
|
||||
return match ccx.sess.targ_cfg.arch {
|
||||
@ -73,10 +73,10 @@ struct ShimTypes {
|
||||
|
||||
/// Type of the struct we will use to shuttle values back and forth.
|
||||
/// This is always derived from the llsig.
|
||||
bundle_ty: TypeRef,
|
||||
bundle_ty: Type,
|
||||
|
||||
/// Type of the shim function itself.
|
||||
shim_fn_ty: TypeRef,
|
||||
shim_fn_ty: Type,
|
||||
|
||||
/// Adapter object for handling native ABI rules (trust me, you
|
||||
/// don't want to know).
|
||||
@ -84,8 +84,8 @@ struct ShimTypes {
|
||||
}
|
||||
|
||||
struct LlvmSignature {
|
||||
llarg_tys: ~[TypeRef],
|
||||
llret_ty: TypeRef,
|
||||
llarg_tys: ~[Type],
|
||||
llret_ty: Type,
|
||||
sret: bool,
|
||||
}
|
||||
|
||||
@ -114,20 +114,16 @@ fn shim_types(ccx: @mut CrateContext, id: ast::node_id) -> ShimTypes {
|
||||
_ => ccx.sess.bug("c_arg_and_ret_lltys called on non-function type")
|
||||
};
|
||||
let llsig = foreign_signature(ccx, &fn_sig);
|
||||
let bundle_ty = T_struct(vec::append_one(copy llsig.llarg_tys,
|
||||
T_ptr(llsig.llret_ty)),
|
||||
false);
|
||||
let bundle_ty = Type::struct_(llsig.llarg_tys + [llsig.llret_ty.ptr_to()], false);
|
||||
let ret_def = !ty::type_is_bot(fn_sig.output) &&
|
||||
!ty::type_is_nil(fn_sig.output);
|
||||
let fn_ty = abi_info(ccx).compute_info(llsig.llarg_tys,
|
||||
llsig.llret_ty,
|
||||
ret_def);
|
||||
let fn_ty = abi_info(ccx).compute_info(llsig.llarg_tys, llsig.llret_ty, ret_def);
|
||||
ShimTypes {
|
||||
fn_sig: fn_sig,
|
||||
llsig: llsig,
|
||||
ret_def: ret_def,
|
||||
bundle_ty: bundle_ty,
|
||||
shim_fn_ty: T_fn([T_ptr(bundle_ty)], T_void()),
|
||||
shim_fn_ty: Type::func([bundle_ty.ptr_to()], &Type::void()),
|
||||
fn_ty: fn_ty
|
||||
}
|
||||
}
|
||||
@ -192,7 +188,7 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
|
||||
needs_c_return: bool,
|
||||
arg_builder: wrap_arg_builder,
|
||||
ret_builder: wrap_ret_builder) {
|
||||
let _icx = ccx.insn_ctxt("foreign::build_wrap_fn_");
|
||||
let _icx = push_ctxt("foreign::build_wrap_fn_");
|
||||
let fcx = new_fn_ctxt(ccx, ~[], llwrapfn, tys.fn_sig.output, None);
|
||||
|
||||
// Patch up the return type if it's not immediate and we're returning via
|
||||
@ -211,8 +207,8 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
|
||||
arg_builder(bcx, tys, llwrapfn, llargbundle);
|
||||
|
||||
// Create call itself.
|
||||
let llshimfnptr = PointerCast(bcx, llshimfn, T_ptr(T_i8()));
|
||||
let llrawargbundle = PointerCast(bcx, llargbundle, T_ptr(T_i8()));
|
||||
let llshimfnptr = PointerCast(bcx, llshimfn, Type::i8p());
|
||||
let llrawargbundle = PointerCast(bcx, llargbundle, Type::i8p());
|
||||
Call(bcx, shim_upcall, [llrawargbundle, llshimfnptr]);
|
||||
ret_builder(bcx, tys, llargbundle);
|
||||
|
||||
@ -221,28 +217,21 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
|
||||
tie_up_header_blocks(fcx, lltop);
|
||||
|
||||
// Then return according to the C ABI.
|
||||
unsafe {
|
||||
let return_context = raw_block(fcx, false, fcx.llreturn);
|
||||
let return_context = raw_block(fcx, false, fcx.llreturn);
|
||||
|
||||
let llfunctiontype = val_ty(llwrapfn);
|
||||
let llfunctiontype =
|
||||
::lib::llvm::llvm::LLVMGetElementType(llfunctiontype);
|
||||
let llfunctionreturntype =
|
||||
::lib::llvm::llvm::LLVMGetReturnType(llfunctiontype);
|
||||
if ::lib::llvm::llvm::LLVMGetTypeKind(llfunctionreturntype) ==
|
||||
::lib::llvm::Void {
|
||||
// XXX: This might be wrong if there are any functions for which
|
||||
// the C ABI specifies a void output pointer and the Rust ABI
|
||||
// does not.
|
||||
RetVoid(return_context);
|
||||
} else {
|
||||
// Cast if we have to...
|
||||
// XXX: This is ugly.
|
||||
let llretptr = BitCast(return_context,
|
||||
fcx.llretptr.get(),
|
||||
T_ptr(llfunctionreturntype));
|
||||
Ret(return_context, Load(return_context, llretptr));
|
||||
}
|
||||
let llfunctiontype = val_ty(llwrapfn);
|
||||
let llfunctiontype = llfunctiontype.element_type();
|
||||
let return_type = llfunctiontype.return_type();
|
||||
if return_type.kind() == ::lib::llvm::Void {
|
||||
// XXX: This might be wrong if there are any functions for which
|
||||
// the C ABI specifies a void output pointer and the Rust ABI
|
||||
// does not.
|
||||
RetVoid(return_context);
|
||||
} else {
|
||||
// Cast if we have to...
|
||||
// XXX: This is ugly.
|
||||
let llretptr = BitCast(return_context, fcx.llretptr.get(), return_type.ptr_to());
|
||||
Ret(return_context, Load(return_context, llretptr));
|
||||
}
|
||||
}
|
||||
|
||||
@ -285,7 +274,7 @@ fn build_wrap_fn_(ccx: @mut CrateContext,
|
||||
pub fn trans_foreign_mod(ccx: @mut CrateContext,
|
||||
path: &ast_map::path,
|
||||
foreign_mod: &ast::foreign_mod) {
|
||||
let _icx = ccx.insn_ctxt("foreign::trans_foreign_mod");
|
||||
let _icx = push_ctxt("foreign::trans_foreign_mod");
|
||||
|
||||
let arch = ccx.sess.targ_cfg.arch;
|
||||
let abi = match foreign_mod.abis.for_arch(arch) {
|
||||
@ -381,11 +370,11 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext,
|
||||
* }
|
||||
*/
|
||||
|
||||
let _icx = ccx.insn_ctxt("foreign::build_shim_fn");
|
||||
let _icx = push_ctxt("foreign::build_shim_fn");
|
||||
|
||||
fn build_args(bcx: block, tys: &ShimTypes, llargbundle: ValueRef)
|
||||
-> ~[ValueRef] {
|
||||
let _icx = bcx.insn_ctxt("foreign::shim::build_args");
|
||||
let _icx = push_ctxt("foreign::shim::build_args");
|
||||
tys.fn_ty.build_shim_args(bcx, tys.llsig.llarg_tys, llargbundle)
|
||||
}
|
||||
|
||||
@ -393,7 +382,7 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext,
|
||||
tys: &ShimTypes,
|
||||
llargbundle: ValueRef,
|
||||
llretval: ValueRef) {
|
||||
let _icx = bcx.insn_ctxt("foreign::shim::build_ret");
|
||||
let _icx = push_ctxt("foreign::shim::build_ret");
|
||||
tys.fn_ty.build_shim_ret(bcx,
|
||||
tys.llsig.llarg_tys,
|
||||
tys.ret_def,
|
||||
@ -499,7 +488,7 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext,
|
||||
* account for the Rust modes.
|
||||
*/
|
||||
|
||||
let _icx = ccx.insn_ctxt("foreign::build_wrap_fn");
|
||||
let _icx = push_ctxt("foreign::build_wrap_fn");
|
||||
|
||||
build_wrap_fn_(ccx,
|
||||
tys,
|
||||
@ -514,7 +503,7 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext,
|
||||
tys: &ShimTypes,
|
||||
llwrapfn: ValueRef,
|
||||
llargbundle: ValueRef) {
|
||||
let _icx = bcx.insn_ctxt("foreign::wrap::build_args");
|
||||
let _icx = push_ctxt("foreign::wrap::build_args");
|
||||
let ccx = bcx.ccx();
|
||||
let n = tys.llsig.llarg_tys.len();
|
||||
for uint::range(0, n) |i| {
|
||||
@ -539,7 +528,7 @@ pub fn trans_foreign_mod(ccx: @mut CrateContext,
|
||||
fn build_ret(bcx: block,
|
||||
shim_types: &ShimTypes,
|
||||
llargbundle: ValueRef) {
|
||||
let _icx = bcx.insn_ctxt("foreign::wrap::build_ret");
|
||||
let _icx = push_ctxt("foreign::wrap::build_ret");
|
||||
let arg_count = shim_types.fn_sig.inputs.len();
|
||||
for bcx.fcx.llretptr.iter().advance |&retptr| {
|
||||
let llretptr = load_inbounds(bcx, llargbundle, [0, arg_count]);
|
||||
@ -578,118 +567,76 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
||||
let mut bcx = top_scope_block(fcx, None);
|
||||
let lltop = bcx.llbb;
|
||||
let first_real_arg = fcx.arg_pos(0u);
|
||||
match ccx.sess.str_of(item.ident).as_slice() {
|
||||
"atomic_cxchg" => {
|
||||
let old = AtomicCmpXchg(bcx,
|
||||
get_param(decl, first_real_arg),
|
||||
|
||||
let nm = ccx.sess.str_of(item.ident);
|
||||
let name = nm.as_slice();
|
||||
|
||||
// This requires that atomic intrinsics follow a specific naming pattern:
|
||||
// "atomic_<operation>[_<ordering>], and no ordering means SeqCst
|
||||
if name.starts_with("atomic_") {
|
||||
let split : ~[&str] = name.split_iter('_').collect();
|
||||
assert!(split.len() >= 2, "Atomic intrinsic not correct format");
|
||||
let order = if split.len() == 2 {
|
||||
lib::llvm::SequentiallyConsistent
|
||||
} else {
|
||||
match split[2] {
|
||||
"relaxed" => lib::llvm::Monotonic,
|
||||
"acq" => lib::llvm::Acquire,
|
||||
"rel" => lib::llvm::Release,
|
||||
"acqrel" => lib::llvm::AcquireRelease,
|
||||
_ => ccx.sess.fatal("Unknown ordering in atomic intrinsic")
|
||||
}
|
||||
};
|
||||
|
||||
match split[1] {
|
||||
"cxchg" => {
|
||||
let old = AtomicCmpXchg(bcx, get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
get_param(decl, first_real_arg + 2u),
|
||||
order);
|
||||
Store(bcx, old, fcx.llretptr.get());
|
||||
}
|
||||
"load" => {
|
||||
let old = AtomicLoad(bcx, get_param(decl, first_real_arg),
|
||||
order);
|
||||
Store(bcx, old, fcx.llretptr.get());
|
||||
}
|
||||
"store" => {
|
||||
AtomicStore(bcx, get_param(decl, first_real_arg + 1u),
|
||||
get_param(decl, first_real_arg),
|
||||
order);
|
||||
}
|
||||
op => {
|
||||
// These are all AtomicRMW ops
|
||||
let atom_op = match op {
|
||||
"xchg" => lib::llvm::Xchg,
|
||||
"xadd" => lib::llvm::Add,
|
||||
"xsub" => lib::llvm::Sub,
|
||||
"and" => lib::llvm::And,
|
||||
"nand" => lib::llvm::Nand,
|
||||
"or" => lib::llvm::Or,
|
||||
"xor" => lib::llvm::Xor,
|
||||
"max" => lib::llvm::Max,
|
||||
"min" => lib::llvm::Min,
|
||||
"umax" => lib::llvm::UMax,
|
||||
"umin" => lib::llvm::UMin,
|
||||
_ => ccx.sess.fatal("Unknown atomic operation")
|
||||
};
|
||||
|
||||
let old = AtomicRMW(bcx, atom_op, get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
get_param(decl, first_real_arg + 2u),
|
||||
SequentiallyConsistent);
|
||||
Store(bcx, old, fcx.llretptr.get());
|
||||
}
|
||||
"atomic_cxchg_acq" => {
|
||||
let old = AtomicCmpXchg(bcx,
|
||||
get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
get_param(decl, first_real_arg + 2u),
|
||||
Acquire);
|
||||
Store(bcx, old, fcx.llretptr.get());
|
||||
}
|
||||
"atomic_cxchg_rel" => {
|
||||
let old = AtomicCmpXchg(bcx,
|
||||
get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
get_param(decl, first_real_arg + 2u),
|
||||
Release);
|
||||
Store(bcx, old, fcx.llretptr.get());
|
||||
}
|
||||
"atomic_load" => {
|
||||
let old = AtomicLoad(bcx,
|
||||
get_param(decl, first_real_arg),
|
||||
SequentiallyConsistent);
|
||||
Store(bcx, old, fcx.llretptr.get());
|
||||
}
|
||||
"atomic_load_acq" => {
|
||||
let old = AtomicLoad(bcx,
|
||||
get_param(decl, first_real_arg),
|
||||
Acquire);
|
||||
Store(bcx, old, fcx.llretptr.get());
|
||||
}
|
||||
"atomic_store" => {
|
||||
AtomicStore(bcx,
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
get_param(decl, first_real_arg),
|
||||
SequentiallyConsistent);
|
||||
}
|
||||
"atomic_store_rel" => {
|
||||
AtomicStore(bcx,
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
get_param(decl, first_real_arg),
|
||||
Release);
|
||||
}
|
||||
"atomic_xchg" => {
|
||||
let old = AtomicRMW(bcx, Xchg,
|
||||
get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
SequentiallyConsistent);
|
||||
Store(bcx, old, fcx.llretptr.get());
|
||||
}
|
||||
"atomic_xchg_acq" => {
|
||||
let old = AtomicRMW(bcx, Xchg,
|
||||
get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
Acquire);
|
||||
Store(bcx, old, fcx.llretptr.get());
|
||||
}
|
||||
"atomic_xchg_rel" => {
|
||||
let old = AtomicRMW(bcx, Xchg,
|
||||
get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
Release);
|
||||
Store(bcx, old, fcx.llretptr.get());
|
||||
}
|
||||
"atomic_xadd" => {
|
||||
let old = AtomicRMW(bcx, lib::llvm::Add,
|
||||
get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
SequentiallyConsistent);
|
||||
Store(bcx, old, fcx.llretptr.get());
|
||||
}
|
||||
"atomic_xadd_acq" => {
|
||||
let old = AtomicRMW(bcx, lib::llvm::Add,
|
||||
get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
Acquire);
|
||||
Store(bcx, old, fcx.llretptr.get());
|
||||
}
|
||||
"atomic_xadd_rel" => {
|
||||
let old = AtomicRMW(bcx, lib::llvm::Add,
|
||||
get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
Release);
|
||||
Store(bcx, old, fcx.llretptr.get());
|
||||
}
|
||||
"atomic_xsub" => {
|
||||
let old = AtomicRMW(bcx, lib::llvm::Sub,
|
||||
get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
SequentiallyConsistent);
|
||||
Store(bcx, old, fcx.llretptr.get());
|
||||
}
|
||||
"atomic_xsub_acq" => {
|
||||
let old = AtomicRMW(bcx, lib::llvm::Sub,
|
||||
get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
Acquire);
|
||||
Store(bcx, old, fcx.llretptr.get());
|
||||
}
|
||||
"atomic_xsub_rel" => {
|
||||
let old = AtomicRMW(bcx, lib::llvm::Sub,
|
||||
get_param(decl, first_real_arg),
|
||||
get_param(decl, first_real_arg + 1u),
|
||||
Release);
|
||||
Store(bcx, old, fcx.llretptr.get());
|
||||
order);
|
||||
Store(bcx, old, fcx.llretptr.get());
|
||||
}
|
||||
}
|
||||
|
||||
build_return(bcx);
|
||||
finish_fn(fcx, lltop);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
match name {
|
||||
"size_of" => {
|
||||
let tp_ty = substs.tys[0];
|
||||
let lltp_ty = type_of::type_of(ccx, tp_ty);
|
||||
@ -734,9 +681,9 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
||||
let static_ti = get_tydesc(ccx, tp_ty);
|
||||
glue::lazily_emit_all_tydesc_glue(ccx, static_ti);
|
||||
|
||||
// FIXME (#3727): change this to T_ptr(ccx.tydesc_ty) when the
|
||||
// FIXME (#3727): change this to ccx.tydesc_ty.ptr_to() when the
|
||||
// core::sys copy of the get_tydesc interface dies off.
|
||||
let td = PointerCast(bcx, static_ti.tydesc, T_ptr(T_nil()));
|
||||
let td = PointerCast(bcx, static_ti.tydesc, Type::nil().ptr_to());
|
||||
Store(bcx, td, fcx.llretptr.get());
|
||||
}
|
||||
"init" => {
|
||||
@ -780,7 +727,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
||||
// code bloat when `transmute` is used on large structural
|
||||
// types.
|
||||
let lldestptr = fcx.llretptr.get();
|
||||
let lldestptr = PointerCast(bcx, lldestptr, T_ptr(T_i8()));
|
||||
let lldestptr = PointerCast(bcx, lldestptr, Type::i8p());
|
||||
|
||||
let llsrcval = get_param(decl, first_real_arg);
|
||||
let llsrcptr = if ty::type_is_immediate(in_type) {
|
||||
@ -790,7 +737,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
||||
} else {
|
||||
llsrcval
|
||||
};
|
||||
let llsrcptr = PointerCast(bcx, llsrcptr, T_ptr(T_i8()));
|
||||
let llsrcptr = PointerCast(bcx, llsrcptr, Type::i8p());
|
||||
|
||||
let llsize = llsize_of(ccx, llintype);
|
||||
call_memcpy(bcx, lldestptr, llsrcptr, llsize, 1);
|
||||
@ -807,12 +754,9 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
||||
let visitor = get_param(decl, first_real_arg + 1u);
|
||||
//let llvisitorptr = alloca(bcx, val_ty(visitor));
|
||||
//Store(bcx, visitor, llvisitorptr);
|
||||
let td = PointerCast(bcx, td, T_ptr(ccx.tydesc_type));
|
||||
glue::call_tydesc_glue_full(bcx,
|
||||
visitor,
|
||||
td,
|
||||
abi::tydesc_field_visit_glue,
|
||||
None);
|
||||
let td = PointerCast(bcx, td, ccx.tydesc_type.ptr_to());
|
||||
glue::call_tydesc_glue_full(bcx, visitor, td,
|
||||
abi::tydesc_field_visit_glue, None);
|
||||
}
|
||||
"frame_address" => {
|
||||
let frameaddress = ccx.intrinsics.get_copy(& &"llvm.frameaddress");
|
||||
@ -847,8 +791,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
||||
let llfty = type_of_fn(bcx.ccx(), [], ty::mk_nil());
|
||||
let morestack_addr = decl_cdecl_fn(
|
||||
bcx.ccx().llmod, "__morestack", llfty);
|
||||
let morestack_addr = PointerCast(bcx, morestack_addr,
|
||||
T_ptr(T_nil()));
|
||||
let morestack_addr = PointerCast(bcx, morestack_addr, Type::nil().ptr_to());
|
||||
Store(bcx, morestack_addr, fcx.llretptr.get());
|
||||
}
|
||||
"memcpy32" => {
|
||||
@ -857,8 +800,8 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
||||
let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
|
||||
let size = C_i32(machine::llsize_of_real(ccx, lltp_ty) as i32);
|
||||
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8()));
|
||||
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), T_ptr(T_i8()));
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), Type::i8p());
|
||||
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), Type::i8p());
|
||||
let count = get_param(decl, first_real_arg + 2);
|
||||
let volatile = C_i1(false);
|
||||
let llfn = bcx.ccx().intrinsics.get_copy(& &"llvm.memcpy.p0i8.p0i8.i32");
|
||||
@ -870,8 +813,8 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
||||
let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
|
||||
let size = C_i64(machine::llsize_of_real(ccx, lltp_ty) as i64);
|
||||
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8()));
|
||||
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), T_ptr(T_i8()));
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), Type::i8p());
|
||||
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), Type::i8p());
|
||||
let count = get_param(decl, first_real_arg + 2);
|
||||
let volatile = C_i1(false);
|
||||
let llfn = bcx.ccx().intrinsics.get_copy(& &"llvm.memcpy.p0i8.p0i8.i64");
|
||||
@ -883,8 +826,8 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
||||
let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
|
||||
let size = C_i32(machine::llsize_of_real(ccx, lltp_ty) as i32);
|
||||
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8()));
|
||||
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), T_ptr(T_i8()));
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), Type::i8p());
|
||||
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), Type::i8p());
|
||||
let count = get_param(decl, first_real_arg + 2);
|
||||
let volatile = C_i1(false);
|
||||
let llfn = bcx.ccx().intrinsics.get_copy(& &"llvm.memmove.p0i8.p0i8.i32");
|
||||
@ -896,8 +839,8 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
||||
let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
|
||||
let size = C_i64(machine::llsize_of_real(ccx, lltp_ty) as i64);
|
||||
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8()));
|
||||
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), T_ptr(T_i8()));
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), Type::i8p());
|
||||
let src_ptr = PointerCast(bcx, get_param(decl, first_real_arg + 1), Type::i8p());
|
||||
let count = get_param(decl, first_real_arg + 2);
|
||||
let volatile = C_i1(false);
|
||||
let llfn = bcx.ccx().intrinsics.get_copy(& &"llvm.memmove.p0i8.p0i8.i64");
|
||||
@ -909,7 +852,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
||||
let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
|
||||
let size = C_i32(machine::llsize_of_real(ccx, lltp_ty) as i32);
|
||||
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8()));
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), Type::i8p());
|
||||
let val = get_param(decl, first_real_arg + 1);
|
||||
let count = get_param(decl, first_real_arg + 2);
|
||||
let volatile = C_i1(false);
|
||||
@ -922,7 +865,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
||||
let align = C_i32(machine::llalign_of_min(ccx, lltp_ty) as i32);
|
||||
let size = C_i64(machine::llsize_of_real(ccx, lltp_ty) as i64);
|
||||
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), T_ptr(T_i8()));
|
||||
let dst_ptr = PointerCast(bcx, get_param(decl, first_real_arg), Type::i8p());
|
||||
let val = get_param(decl, first_real_arg + 1);
|
||||
let count = get_param(decl, first_real_arg + 2);
|
||||
let volatile = C_i1(false);
|
||||
@ -1212,7 +1155,7 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
|
||||
body: &ast::blk,
|
||||
llwrapfn: ValueRef,
|
||||
id: ast::node_id) {
|
||||
let _icx = ccx.insn_ctxt("foreign::build_foreign_fn");
|
||||
let _icx = push_ctxt("foreign::build_foreign_fn");
|
||||
|
||||
fn build_rust_fn(ccx: @mut CrateContext,
|
||||
path: ast_map::path,
|
||||
@ -1220,7 +1163,7 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
|
||||
body: &ast::blk,
|
||||
id: ast::node_id)
|
||||
-> ValueRef {
|
||||
let _icx = ccx.insn_ctxt("foreign::foreign::build_rust_fn");
|
||||
let _icx = push_ctxt("foreign::foreign::build_rust_fn");
|
||||
let t = ty::node_id_to_type(ccx.tcx, id);
|
||||
// XXX: Bad copy.
|
||||
let ps = link::mangle_internal_name_by_path(
|
||||
@ -1262,11 +1205,11 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
|
||||
* one of those types that is passed by pointer in Rust.
|
||||
*/
|
||||
|
||||
let _icx = ccx.insn_ctxt("foreign::foreign::build_shim_fn");
|
||||
let _icx = push_ctxt("foreign::foreign::build_shim_fn");
|
||||
|
||||
fn build_args(bcx: block, tys: &ShimTypes, llargbundle: ValueRef)
|
||||
-> ~[ValueRef] {
|
||||
let _icx = bcx.insn_ctxt("foreign::extern::shim::build_args");
|
||||
let _icx = push_ctxt("foreign::extern::shim::build_args");
|
||||
let ccx = bcx.ccx();
|
||||
let mut llargvals = ~[];
|
||||
let mut i = 0u;
|
||||
@ -1277,7 +1220,7 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
|
||||
llargvals.push(llretptr);
|
||||
}
|
||||
|
||||
let llenvptr = C_null(T_opaque_box_ptr(bcx.ccx()));
|
||||
let llenvptr = C_null(Type::opaque_box(bcx.ccx()).ptr_to());
|
||||
llargvals.push(llenvptr);
|
||||
while i < n {
|
||||
// Get a pointer to the argument:
|
||||
@ -1341,7 +1284,7 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
|
||||
* }
|
||||
*/
|
||||
|
||||
let _icx = ccx.insn_ctxt("foreign::foreign::build_wrap_fn");
|
||||
let _icx = push_ctxt("foreign::foreign::build_wrap_fn");
|
||||
|
||||
build_wrap_fn_(ccx,
|
||||
tys,
|
||||
@ -1356,7 +1299,7 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
|
||||
tys: &ShimTypes,
|
||||
llwrapfn: ValueRef,
|
||||
llargbundle: ValueRef) {
|
||||
let _icx = bcx.insn_ctxt("foreign::foreign::wrap::build_args");
|
||||
let _icx = push_ctxt("foreign::foreign::wrap::build_args");
|
||||
tys.fn_ty.build_wrap_args(bcx,
|
||||
tys.llsig.llret_ty,
|
||||
llwrapfn,
|
||||
@ -1364,7 +1307,7 @@ pub fn trans_foreign_fn(ccx: @mut CrateContext,
|
||||
}
|
||||
|
||||
fn build_ret(bcx: block, tys: &ShimTypes, llargbundle: ValueRef) {
|
||||
let _icx = bcx.insn_ctxt("foreign::foreign::wrap::build_ret");
|
||||
let _icx = push_ctxt("foreign::foreign::wrap::build_ret");
|
||||
tys.fn_ty.build_wrap_ret(bcx, tys.llsig.llarg_tys, llargbundle);
|
||||
build_return(bcx);
|
||||
}
|
||||
@ -1386,7 +1329,7 @@ pub fn register_foreign_fn(ccx: @mut CrateContext,
|
||||
node_id: ast::node_id,
|
||||
attrs: &[ast::attribute])
|
||||
-> ValueRef {
|
||||
let _icx = ccx.insn_ctxt("foreign::register_foreign_fn");
|
||||
let _icx = push_ctxt("foreign::register_foreign_fn");
|
||||
|
||||
let t = ty::node_id_to_type(ccx.tcx, node_id);
|
||||
|
||||
|
@ -18,7 +18,7 @@ use back::abi;
|
||||
use back::link::*;
|
||||
use driver::session;
|
||||
use lib;
|
||||
use lib::llvm::{llvm, ValueRef, TypeRef, True};
|
||||
use lib::llvm::{llvm, ValueRef, True};
|
||||
use middle::trans::adt;
|
||||
use middle::trans::base::*;
|
||||
use middle::trans::callee;
|
||||
@ -29,12 +29,14 @@ use middle::trans::expr;
|
||||
use middle::trans::machine::*;
|
||||
use middle::trans::reflect;
|
||||
use middle::trans::tvec;
|
||||
use middle::trans::type_of::{type_of, type_of_glue_fn};
|
||||
use middle::trans::type_of::type_of;
|
||||
use middle::trans::uniq;
|
||||
use middle::ty;
|
||||
use util::ppaux;
|
||||
use util::ppaux::ty_to_short_str;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use core::io;
|
||||
use core::libc::c_uint;
|
||||
use core::str;
|
||||
@ -43,26 +45,24 @@ use extra::time;
|
||||
use syntax::ast;
|
||||
|
||||
pub fn trans_free(cx: block, v: ValueRef) -> block {
|
||||
let _icx = cx.insn_ctxt("trans_free");
|
||||
callee::trans_lang_call(
|
||||
cx,
|
||||
let _icx = push_ctxt("trans_free");
|
||||
callee::trans_lang_call(cx,
|
||||
cx.tcx().lang_items.free_fn(),
|
||||
[PointerCast(cx, v, T_ptr(T_i8()))],
|
||||
[PointerCast(cx, v, Type::i8p())],
|
||||
expr::Ignore)
|
||||
}
|
||||
|
||||
pub fn trans_exchange_free(cx: block, v: ValueRef) -> block {
|
||||
let _icx = cx.insn_ctxt("trans_exchange_free");
|
||||
callee::trans_lang_call(
|
||||
cx,
|
||||
let _icx = push_ctxt("trans_exchange_free");
|
||||
callee::trans_lang_call(cx,
|
||||
cx.tcx().lang_items.exchange_free_fn(),
|
||||
[PointerCast(cx, v, T_ptr(T_i8()))],
|
||||
[PointerCast(cx, v, Type::i8p())],
|
||||
expr::Ignore)
|
||||
}
|
||||
|
||||
pub fn take_ty(cx: block, v: ValueRef, t: ty::t) -> block {
|
||||
// NB: v is an *alias* of type t here, not a direct value.
|
||||
let _icx = cx.insn_ctxt("take_ty");
|
||||
let _icx = push_ctxt("take_ty");
|
||||
if ty::type_needs_drop(cx.tcx(), t) {
|
||||
return call_tydesc_glue(cx, v, t, abi::tydesc_field_take_glue);
|
||||
}
|
||||
@ -71,38 +71,24 @@ pub fn take_ty(cx: block, v: ValueRef, t: ty::t) -> block {
|
||||
|
||||
pub fn drop_ty(cx: block, v: ValueRef, t: ty::t) -> block {
|
||||
// NB: v is an *alias* of type t here, not a direct value.
|
||||
let _icx = cx.insn_ctxt("drop_ty");
|
||||
let _icx = push_ctxt("drop_ty");
|
||||
if ty::type_needs_drop(cx.tcx(), t) {
|
||||
return call_tydesc_glue(cx, v, t, abi::tydesc_field_drop_glue);
|
||||
}
|
||||
return cx;
|
||||
}
|
||||
|
||||
pub fn drop_ty_root(bcx: block,
|
||||
v: ValueRef,
|
||||
rooted: bool,
|
||||
t: ty::t)
|
||||
-> block {
|
||||
if rooted {
|
||||
// NB: v is a raw ptr to an addrspace'd ptr to the value.
|
||||
let v = PointerCast(bcx, Load(bcx, v), T_ptr(type_of(bcx.ccx(), t)));
|
||||
drop_ty(bcx, v, t)
|
||||
} else {
|
||||
drop_ty(bcx, v, t)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn drop_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> block {
|
||||
let _icx = bcx.insn_ctxt("drop_ty_immediate");
|
||||
let _icx = push_ctxt("drop_ty_immediate");
|
||||
match ty::get(t).sty {
|
||||
ty::ty_uniq(_) |
|
||||
ty::ty_evec(_, ty::vstore_uniq) |
|
||||
ty::ty_estr(ty::vstore_uniq) => {
|
||||
ty::ty_uniq(_)
|
||||
| ty::ty_evec(_, ty::vstore_uniq)
|
||||
| ty::ty_estr(ty::vstore_uniq) => {
|
||||
free_ty_immediate(bcx, v, t)
|
||||
}
|
||||
ty::ty_box(_) | ty::ty_opaque_box |
|
||||
ty::ty_evec(_, ty::vstore_box) |
|
||||
ty::ty_estr(ty::vstore_box) => {
|
||||
ty::ty_box(_) | ty::ty_opaque_box
|
||||
| ty::ty_evec(_, ty::vstore_box)
|
||||
| ty::ty_estr(ty::vstore_box) => {
|
||||
decr_refcnt_maybe_free(bcx, v, None, t)
|
||||
}
|
||||
_ => bcx.tcx().sess.bug("drop_ty_immediate: non-box ty")
|
||||
@ -110,7 +96,7 @@ pub fn drop_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> block {
|
||||
}
|
||||
|
||||
pub fn take_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> Result {
|
||||
let _icx = bcx.insn_ctxt("take_ty_immediate");
|
||||
let _icx = push_ctxt("take_ty_immediate");
|
||||
match ty::get(t).sty {
|
||||
ty::ty_box(_) | ty::ty_opaque_box |
|
||||
ty::ty_evec(_, ty::vstore_box) |
|
||||
@ -131,7 +117,7 @@ pub fn take_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> Result {
|
||||
|
||||
pub fn free_ty(cx: block, v: ValueRef, t: ty::t) -> block {
|
||||
// NB: v is an *alias* of type t here, not a direct value.
|
||||
let _icx = cx.insn_ctxt("free_ty");
|
||||
let _icx = push_ctxt("free_ty");
|
||||
if ty::type_needs_drop(cx.tcx(), t) {
|
||||
return call_tydesc_glue(cx, v, t, abi::tydesc_field_free_glue);
|
||||
}
|
||||
@ -139,7 +125,7 @@ pub fn free_ty(cx: block, v: ValueRef, t: ty::t) -> block {
|
||||
}
|
||||
|
||||
pub fn free_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> block {
|
||||
let _icx = bcx.insn_ctxt("free_ty_immediate");
|
||||
let _icx = push_ctxt("free_ty_immediate");
|
||||
match ty::get(t).sty {
|
||||
ty::ty_uniq(_) |
|
||||
ty::ty_evec(_, ty::vstore_uniq) |
|
||||
@ -221,7 +207,7 @@ pub fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t {
|
||||
pub fn lazily_emit_simplified_tydesc_glue(ccx: @mut CrateContext,
|
||||
field: uint,
|
||||
ti: @mut tydesc_info) -> bool {
|
||||
let _icx = ccx.insn_ctxt("lazily_emit_simplified_tydesc_glue");
|
||||
let _icx = push_ctxt("lazily_emit_simplified_tydesc_glue");
|
||||
let simpl = simplified_glue_type(ccx.tcx, field, ti.ty);
|
||||
if simpl != ti.ty {
|
||||
let simpl_ti = get_tydesc(ccx, simpl);
|
||||
@ -246,7 +232,7 @@ pub fn lazily_emit_simplified_tydesc_glue(ccx: @mut CrateContext,
|
||||
pub fn lazily_emit_tydesc_glue(ccx: @mut CrateContext,
|
||||
field: uint,
|
||||
ti: @mut tydesc_info) {
|
||||
let _icx = ccx.insn_ctxt("lazily_emit_tydesc_glue");
|
||||
let _icx = push_ctxt("lazily_emit_tydesc_glue");
|
||||
let llfnty = type_of_glue_fn(ccx);
|
||||
|
||||
if lazily_emit_simplified_tydesc_glue(ccx, field, ti) {
|
||||
@ -314,7 +300,7 @@ pub fn call_tydesc_glue_full(bcx: block,
|
||||
tydesc: ValueRef,
|
||||
field: uint,
|
||||
static_ti: Option<@mut tydesc_info>) {
|
||||
let _icx = bcx.insn_ctxt("call_tydesc_glue_full");
|
||||
let _icx = push_ctxt("call_tydesc_glue_full");
|
||||
let ccx = bcx.ccx();
|
||||
// NB: Don't short-circuit even if this block is unreachable because
|
||||
// GC-based cleanup needs to the see that the roots are live.
|
||||
@ -340,7 +326,7 @@ pub fn call_tydesc_glue_full(bcx: block,
|
||||
}
|
||||
};
|
||||
|
||||
let llrawptr = PointerCast(bcx, v, T_ptr(T_i8()));
|
||||
let llrawptr = PointerCast(bcx, v, Type::i8p());
|
||||
|
||||
let llfn = {
|
||||
match static_glue_fn {
|
||||
@ -353,26 +339,26 @@ pub fn call_tydesc_glue_full(bcx: block,
|
||||
}
|
||||
};
|
||||
|
||||
Call(bcx, llfn, [C_null(T_ptr(T_nil())),
|
||||
C_null(T_ptr(T_ptr(bcx.ccx().tydesc_type))),
|
||||
Call(bcx, llfn, [C_null(Type::nil().ptr_to()),
|
||||
C_null(bcx.ccx().tydesc_type.ptr_to().ptr_to()),
|
||||
llrawptr]);
|
||||
}
|
||||
|
||||
// See [Note-arg-mode]
|
||||
pub fn call_tydesc_glue(cx: block, v: ValueRef, t: ty::t, field: uint)
|
||||
-> block {
|
||||
let _icx = cx.insn_ctxt("call_tydesc_glue");
|
||||
let _icx = push_ctxt("call_tydesc_glue");
|
||||
let ti = get_tydesc(cx.ccx(), t);
|
||||
call_tydesc_glue_full(cx, v, ti.tydesc, field, Some(ti));
|
||||
return cx;
|
||||
}
|
||||
|
||||
pub fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) {
|
||||
let _icx = bcx.insn_ctxt("make_visit_glue");
|
||||
let _icx = push_ctxt("make_visit_glue");
|
||||
let bcx = do with_scope(bcx, None, "visitor cleanup") |bcx| {
|
||||
let mut bcx = bcx;
|
||||
let (visitor_trait, object_ty) = ty::visitor_object_ty(bcx.tcx());
|
||||
let v = PointerCast(bcx, v, T_ptr(type_of::type_of(bcx.ccx(), object_ty)));
|
||||
let v = PointerCast(bcx, v, type_of::type_of(bcx.ccx(), object_ty).ptr_to());
|
||||
bcx = reflect::emit_calls_to_trait_visit_ty(bcx, t, v, visitor_trait.def_id);
|
||||
// The visitor is a boxed object and needs to be dropped
|
||||
add_clean(bcx, v, object_ty);
|
||||
@ -383,14 +369,11 @@ pub fn make_visit_glue(bcx: block, v: ValueRef, t: ty::t) {
|
||||
|
||||
pub fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
|
||||
// NB: v0 is an *alias* of type t here, not a direct value.
|
||||
let _icx = bcx.insn_ctxt("make_free_glue");
|
||||
let ccx = bcx.ccx();
|
||||
let _icx = push_ctxt("make_free_glue");
|
||||
let bcx = match ty::get(t).sty {
|
||||
ty::ty_box(body_mt) => {
|
||||
let v = Load(bcx, v);
|
||||
let body = GEPi(bcx, v, [0u, abi::box_field_body]);
|
||||
// Cast away the addrspace of the box pointer.
|
||||
let body = PointerCast(bcx, body, T_ptr(type_of(ccx, body_mt.ty)));
|
||||
let bcx = drop_ty(bcx, body, body_mt.ty);
|
||||
trans_free(bcx, v)
|
||||
}
|
||||
@ -442,8 +425,8 @@ pub fn trans_struct_drop(bcx: block,
|
||||
|
||||
// The second argument is the "self" argument for drop
|
||||
let params = unsafe {
|
||||
lib::llvm::fn_ty_param_tys(
|
||||
llvm::LLVMGetElementType(llvm::LLVMTypeOf(dtor_addr)))
|
||||
let ty = Type::from_ref(llvm::LLVMTypeOf(dtor_addr));
|
||||
ty.element_type().func_params()
|
||||
};
|
||||
|
||||
// Class dtors have no explicit args, so the params should
|
||||
@ -475,7 +458,7 @@ pub fn trans_struct_drop(bcx: block,
|
||||
|
||||
pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
|
||||
// NB: v0 is an *alias* of type t here, not a direct value.
|
||||
let _icx = bcx.insn_ctxt("make_drop_glue");
|
||||
let _icx = push_ctxt("make_drop_glue");
|
||||
let ccx = bcx.ccx();
|
||||
let bcx = match ty::get(t).sty {
|
||||
ty::ty_box(_) | ty::ty_opaque_box |
|
||||
@ -517,9 +500,8 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
|
||||
let llvtable = Load(bcx, GEPi(bcx, v0, [0, abi::trt_field_vtable]));
|
||||
|
||||
// Cast the vtable to a pointer to a pointer to a tydesc.
|
||||
let llvtable = PointerCast(bcx,
|
||||
llvtable,
|
||||
T_ptr(T_ptr(ccx.tydesc_type)));
|
||||
let llvtable = PointerCast(bcx, llvtable,
|
||||
ccx.tydesc_type.ptr_to().ptr_to());
|
||||
let lltydesc = Load(bcx, llvtable);
|
||||
call_tydesc_glue_full(bcx,
|
||||
lluniquevalue,
|
||||
@ -547,7 +529,7 @@ pub fn decr_refcnt_maybe_free(bcx: block, box_ptr: ValueRef,
|
||||
box_ptr_ptr: Option<ValueRef>,
|
||||
t: ty::t)
|
||||
-> block {
|
||||
let _icx = bcx.insn_ctxt("decr_refcnt_maybe_free");
|
||||
let _icx = push_ctxt("decr_refcnt_maybe_free");
|
||||
let ccx = bcx.ccx();
|
||||
|
||||
do with_cond(bcx, IsNotNull(bcx, box_ptr)) |bcx| {
|
||||
@ -566,7 +548,7 @@ pub fn decr_refcnt_maybe_free(bcx: block, box_ptr: ValueRef,
|
||||
|
||||
|
||||
pub fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) {
|
||||
let _icx = bcx.insn_ctxt("make_take_glue");
|
||||
let _icx = push_ctxt("make_take_glue");
|
||||
// NB: v is a *pointer* to type t here, not a direct value.
|
||||
let bcx = match ty::get(t).sty {
|
||||
ty::ty_box(_) | ty::ty_opaque_box |
|
||||
@ -615,7 +597,7 @@ pub fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) {
|
||||
}
|
||||
|
||||
pub fn incr_refcnt_of_boxed(cx: block, box_ptr: ValueRef) {
|
||||
let _icx = cx.insn_ctxt("incr_refcnt_of_boxed");
|
||||
let _icx = push_ctxt("incr_refcnt_of_boxed");
|
||||
let ccx = cx.ccx();
|
||||
let rc_ptr = GEPi(cx, box_ptr, [0u, abi::box_field_refcnt]);
|
||||
let rc = Load(cx, rc_ptr);
|
||||
@ -624,20 +606,6 @@ pub fn incr_refcnt_of_boxed(cx: block, box_ptr: ValueRef) {
|
||||
}
|
||||
|
||||
|
||||
// Chooses the addrspace for newly declared types.
|
||||
pub fn declare_tydesc_addrspace(ccx: &CrateContext, t: ty::t) -> addrspace {
|
||||
if !ty::type_needs_drop(ccx.tcx, t) {
|
||||
return default_addrspace;
|
||||
} else if ty::type_is_immediate(t) {
|
||||
// For immediate types, we don't actually need an addrspace, because
|
||||
// e.g. boxed types include pointers to their contents which are
|
||||
// already correctly tagged with addrspaces.
|
||||
return default_addrspace;
|
||||
} else {
|
||||
return (ccx.next_addrspace)();
|
||||
}
|
||||
}
|
||||
|
||||
// Generates the declaration for (but doesn't emit) a type descriptor.
|
||||
pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info {
|
||||
// If emit_tydescs already ran, then we shouldn't be creating any new
|
||||
@ -647,20 +615,18 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info {
|
||||
let llty = type_of(ccx, t);
|
||||
|
||||
if ccx.sess.count_type_sizes() {
|
||||
io::println(fmt!("%u\t%s",
|
||||
llsize_of_real(ccx, llty),
|
||||
io::println(fmt!("%u\t%s", llsize_of_real(ccx, llty),
|
||||
ppaux::ty_to_str(ccx.tcx, t)));
|
||||
}
|
||||
|
||||
let llsize = llsize_of(ccx, llty);
|
||||
let llalign = llalign_of(ccx, llty);
|
||||
let addrspace = declare_tydesc_addrspace(ccx, t);
|
||||
let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc").to_managed();
|
||||
note_unique_llvm_symbol(ccx, name);
|
||||
debug!("+++ declare_tydesc %s %s", ppaux::ty_to_str(ccx.tcx, t), name);
|
||||
let gvar = str::as_c_str(name, |buf| {
|
||||
unsafe {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type, buf)
|
||||
llvm::LLVMAddGlobal(ccx.llmod, ccx.tydesc_type.to_ref(), buf)
|
||||
}
|
||||
});
|
||||
let inf = @mut tydesc_info {
|
||||
@ -668,7 +634,6 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info {
|
||||
tydesc: gvar,
|
||||
size: llsize,
|
||||
align: llalign,
|
||||
addrspace: addrspace,
|
||||
take_glue: None,
|
||||
drop_glue: None,
|
||||
free_glue: None,
|
||||
@ -680,9 +645,9 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info {
|
||||
|
||||
pub type glue_helper = @fn(block, ValueRef, ty::t);
|
||||
|
||||
pub fn declare_generic_glue(ccx: @mut CrateContext, t: ty::t, llfnty: TypeRef,
|
||||
pub fn declare_generic_glue(ccx: @mut CrateContext, t: ty::t, llfnty: Type,
|
||||
name: ~str) -> ValueRef {
|
||||
let _icx = ccx.insn_ctxt("declare_generic_glue");
|
||||
let _icx = push_ctxt("declare_generic_glue");
|
||||
let name = name;
|
||||
let fn_nm = mangle_internal_name_by_type_and_seq(ccx, t, (~"glue_" + name)).to_managed();
|
||||
debug!("%s is for type %s", fn_nm, ppaux::ty_to_str(ccx.tcx, t));
|
||||
@ -697,7 +662,7 @@ pub fn make_generic_glue_inner(ccx: @mut CrateContext,
|
||||
llfn: ValueRef,
|
||||
helper: glue_helper)
|
||||
-> ValueRef {
|
||||
let _icx = ccx.insn_ctxt("make_generic_glue_inner");
|
||||
let _icx = push_ctxt("make_generic_glue_inner");
|
||||
let fcx = new_fn_ctxt(ccx, ~[], llfn, ty::mk_nil(), None);
|
||||
lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
|
||||
ccx.stats.n_glues_created += 1u;
|
||||
@ -711,9 +676,13 @@ pub fn make_generic_glue_inner(ccx: @mut CrateContext,
|
||||
let rawptr0_arg = fcx.arg_pos(1u);
|
||||
let llrawptr0 = unsafe { llvm::LLVMGetParam(llfn, rawptr0_arg as c_uint) };
|
||||
let llty = type_of(ccx, t);
|
||||
let llrawptr0 = PointerCast(bcx, llrawptr0, T_ptr(llty));
|
||||
let llrawptr0 = PointerCast(bcx, llrawptr0, llty.ptr_to());
|
||||
helper(bcx, llrawptr0, t);
|
||||
finish_fn(fcx, lltop);
|
||||
|
||||
// This is from the general finish fn, but that emits a ret {} that we don't want
|
||||
Br(raw_block(fcx, false, fcx.llstaticallocas), lltop);
|
||||
RetVoid(raw_block(fcx, false, fcx.llreturn));
|
||||
|
||||
return llfn;
|
||||
}
|
||||
|
||||
@ -723,7 +692,7 @@ pub fn make_generic_glue(ccx: @mut CrateContext,
|
||||
helper: glue_helper,
|
||||
name: &str)
|
||||
-> ValueRef {
|
||||
let _icx = ccx.insn_ctxt("make_generic_glue");
|
||||
let _icx = push_ctxt("make_generic_glue");
|
||||
if !ccx.sess.trans_stats() {
|
||||
return make_generic_glue_inner(ccx, t, llfn, helper);
|
||||
}
|
||||
@ -731,18 +700,15 @@ pub fn make_generic_glue(ccx: @mut CrateContext,
|
||||
let start = time::get_time();
|
||||
let llval = make_generic_glue_inner(ccx, t, llfn, helper);
|
||||
let end = time::get_time();
|
||||
log_fn_time(ccx,
|
||||
fmt!("glue %s %s", name, ty_to_short_str(ccx.tcx, t)),
|
||||
start,
|
||||
end);
|
||||
ccx.log_fn_time(fmt!("glue %s %s", name, ty_to_short_str(ccx.tcx, t)), start, end);
|
||||
return llval;
|
||||
}
|
||||
|
||||
pub fn emit_tydescs(ccx: &mut CrateContext) {
|
||||
//let _icx = ccx.insn_ctxt("emit_tydescs");
|
||||
let _icx = push_ctxt("emit_tydescs");
|
||||
// As of this point, allow no more tydescs to be created.
|
||||
ccx.finished_tydescs = true;
|
||||
let glue_fn_ty = T_ptr(T_generic_glue_fn(ccx));
|
||||
let glue_fn_ty = Type::generic_glue_fn(ccx);
|
||||
let tyds = &mut ccx.tydescs;
|
||||
for tyds.each_value |&val| {
|
||||
let ti = val;
|
||||
@ -757,7 +723,7 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
|
||||
Some(v) => {
|
||||
unsafe {
|
||||
ccx.stats.n_real_glues += 1u;
|
||||
llvm::LLVMConstPointerCast(v, glue_fn_ty)
|
||||
llvm::LLVMConstPointerCast(v, glue_fn_ty.to_ref())
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -767,7 +733,7 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
|
||||
Some(v) => {
|
||||
unsafe {
|
||||
ccx.stats.n_real_glues += 1u;
|
||||
llvm::LLVMConstPointerCast(v, glue_fn_ty)
|
||||
llvm::LLVMConstPointerCast(v, glue_fn_ty.to_ref())
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -777,7 +743,7 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
|
||||
Some(v) => {
|
||||
unsafe {
|
||||
ccx.stats.n_real_glues += 1u;
|
||||
llvm::LLVMConstPointerCast(v, glue_fn_ty)
|
||||
llvm::LLVMConstPointerCast(v, glue_fn_ty.to_ref())
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -787,16 +753,16 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
|
||||
Some(v) => {
|
||||
unsafe {
|
||||
ccx.stats.n_real_glues += 1u;
|
||||
llvm::LLVMConstPointerCast(v, glue_fn_ty)
|
||||
llvm::LLVMConstPointerCast(v, glue_fn_ty.to_ref())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let shape = C_null(T_ptr(T_i8()));
|
||||
let shape_tables = C_null(T_ptr(T_i8()));
|
||||
|
||||
let tydesc =
|
||||
C_named_struct(ccx.tydesc_type,
|
||||
let shape = C_null(Type::i8p());
|
||||
let shape_tables = C_null(Type::i8p());
|
||||
|
||||
let tydesc = C_named_struct(ccx.tydesc_type,
|
||||
[ti.size, // size
|
||||
ti.align, // align
|
||||
take_glue, // take_glue
|
||||
@ -812,18 +778,11 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
|
||||
llvm::LLVMSetGlobalConstant(gvar, True);
|
||||
lib::llvm::SetLinkage(gvar, lib::llvm::InternalLinkage);
|
||||
|
||||
// Index tydesc by addrspace.
|
||||
if ti.addrspace > gc_box_addrspace {
|
||||
let llty = T_ptr(ccx.tydesc_type);
|
||||
let addrspace_name = fmt!("_gc_addrspace_metadata_%u",
|
||||
ti.addrspace as uint);
|
||||
let addrspace_gvar = str::as_c_str(addrspace_name, |buf| {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, llty, buf)
|
||||
});
|
||||
lib::llvm::SetLinkage(addrspace_gvar,
|
||||
lib::llvm::InternalLinkage);
|
||||
llvm::LLVMSetInitializer(addrspace_gvar, gvar);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn type_of_glue_fn(ccx: &CrateContext) -> Type {
|
||||
let tydescpp = ccx.tydesc_type.ptr_to().ptr_to();
|
||||
Type::func([ Type::nil().ptr_to(), tydescpp, Type::i8p() ], &Type::void())
|
||||
}
|
||||
|
@ -12,8 +12,7 @@ use core::prelude::*;
|
||||
|
||||
use metadata::csearch;
|
||||
use middle::astencode;
|
||||
use middle::trans::base::{get_insn_ctxt};
|
||||
use middle::trans::base::{impl_owned_self, impl_self, no_self};
|
||||
use middle::trans::base::{push_ctxt,impl_owned_self, impl_self, no_self};
|
||||
use middle::trans::base::{trans_item, get_item_val, trans_fn};
|
||||
use middle::trans::common::*;
|
||||
use middle::ty;
|
||||
@ -30,7 +29,7 @@ use syntax::ast_util::local_def;
|
||||
pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::def_id,
|
||||
translate: bool)
|
||||
-> ast::def_id {
|
||||
let _icx = ccx.insn_ctxt("maybe_instantiate_inline");
|
||||
let _icx = push_ctxt("maybe_instantiate_inline");
|
||||
match ccx.external.find(&fn_id) {
|
||||
Some(&Some(node_id)) => {
|
||||
// Already inline
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
// Information concerning the machine representation of various types.
|
||||
|
||||
use lib::llvm::{ValueRef, TypeRef};
|
||||
use lib::llvm::{ValueRef};
|
||||
use lib::llvm::False;
|
||||
use lib::llvm::llvm;
|
||||
use middle::trans::common::*;
|
||||
@ -18,21 +18,23 @@ use middle::trans::type_of;
|
||||
use middle::ty;
|
||||
use util::ppaux::ty_to_str;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
// ______________________________________________________________________
|
||||
// compute sizeof / alignof
|
||||
|
||||
// Returns the number of bytes clobbered by a Store to this type.
|
||||
pub fn llsize_of_store(cx: &CrateContext, t: TypeRef) -> uint {
|
||||
pub fn llsize_of_store(cx: &CrateContext, ty: Type) -> uint {
|
||||
unsafe {
|
||||
return llvm::LLVMStoreSizeOfType(cx.td.lltd, t) as uint;
|
||||
return llvm::LLVMStoreSizeOfType(cx.td.lltd, ty.to_ref()) as uint;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the number of bytes between successive elements of type T in an
|
||||
// array of T. This is the "ABI" size. It includes any ABI-mandated padding.
|
||||
pub fn llsize_of_alloc(cx: &CrateContext, t: TypeRef) -> uint {
|
||||
pub fn llsize_of_alloc(cx: &CrateContext, ty: Type) -> uint {
|
||||
unsafe {
|
||||
return llvm::LLVMABISizeOfType(cx.td.lltd, t) as uint;
|
||||
return llvm::LLVMABISizeOfType(cx.td.lltd, ty.to_ref()) as uint;
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,9 +46,9 @@ pub fn llsize_of_alloc(cx: &CrateContext, t: TypeRef) -> uint {
|
||||
// that LLVM *does* distinguish between e.g. a 1-bit value and an 8-bit value
|
||||
// at the codegen level! In general you should prefer `llbitsize_of_real`
|
||||
// below.
|
||||
pub fn llsize_of_real(cx: &CrateContext, t: TypeRef) -> uint {
|
||||
pub fn llsize_of_real(cx: &CrateContext, ty: Type) -> uint {
|
||||
unsafe {
|
||||
let nbits = llvm::LLVMSizeOfTypeInBits(cx.td.lltd, t) as uint;
|
||||
let nbits = llvm::LLVMSizeOfTypeInBits(cx.td.lltd, ty.to_ref()) as uint;
|
||||
if nbits & 7u != 0u {
|
||||
// Not an even number of bytes, spills into "next" byte.
|
||||
1u + (nbits >> 3)
|
||||
@ -57,14 +59,14 @@ pub fn llsize_of_real(cx: &CrateContext, t: TypeRef) -> uint {
|
||||
}
|
||||
|
||||
/// Returns the "real" size of the type in bits.
|
||||
pub fn llbitsize_of_real(cx: &CrateContext, t: TypeRef) -> uint {
|
||||
pub fn llbitsize_of_real(cx: &CrateContext, ty: Type) -> uint {
|
||||
unsafe {
|
||||
llvm::LLVMSizeOfTypeInBits(cx.td.lltd, t) as uint
|
||||
llvm::LLVMSizeOfTypeInBits(cx.td.lltd, ty.to_ref()) as uint
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the size of the type as an LLVM constant integer value.
|
||||
pub fn llsize_of(cx: &CrateContext, t: TypeRef) -> ValueRef {
|
||||
pub fn llsize_of(cx: &CrateContext, ty: Type) -> ValueRef {
|
||||
// Once upon a time, this called LLVMSizeOf, which does a
|
||||
// getelementptr(1) on a null pointer and casts to an int, in
|
||||
// order to obtain the type size as a value without requiring the
|
||||
@ -72,17 +74,17 @@ pub fn llsize_of(cx: &CrateContext, t: TypeRef) -> ValueRef {
|
||||
// there's no need for that contrivance. The instruction
|
||||
// selection DAG generator would flatten that GEP(1) node into a
|
||||
// constant of the type's alloc size, so let's save it some work.
|
||||
return C_uint(cx, llsize_of_alloc(cx, t));
|
||||
return C_uint(cx, llsize_of_alloc(cx, ty));
|
||||
}
|
||||
|
||||
// Returns the "default" size of t (see above), or 1 if the size would
|
||||
// be zero. This is important for things like vectors that expect
|
||||
// space to be consumed.
|
||||
pub fn nonzero_llsize_of(cx: &CrateContext, t: TypeRef) -> ValueRef {
|
||||
if llbitsize_of_real(cx, t) == 0 {
|
||||
unsafe { llvm::LLVMConstInt(cx.int_type, 1, False) }
|
||||
pub fn nonzero_llsize_of(cx: &CrateContext, ty: Type) -> ValueRef {
|
||||
if llbitsize_of_real(cx, ty) == 0 {
|
||||
unsafe { llvm::LLVMConstInt(cx.int_type.to_ref(), 1, False) }
|
||||
} else {
|
||||
llsize_of(cx, t)
|
||||
llsize_of(cx, ty)
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,28 +92,28 @@ pub fn nonzero_llsize_of(cx: &CrateContext, t: TypeRef) -> ValueRef {
|
||||
// The preferred alignment may be larger than the alignment used when
|
||||
// packing the type into structs. This will be used for things like
|
||||
// allocations inside a stack frame, which LLVM has a free hand in.
|
||||
pub fn llalign_of_pref(cx: &CrateContext, t: TypeRef) -> uint {
|
||||
pub fn llalign_of_pref(cx: &CrateContext, ty: Type) -> uint {
|
||||
unsafe {
|
||||
return llvm::LLVMPreferredAlignmentOfType(cx.td.lltd, t) as uint;
|
||||
return llvm::LLVMPreferredAlignmentOfType(cx.td.lltd, ty.to_ref()) as uint;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the minimum alignment of a type required by the platform.
|
||||
// This is the alignment that will be used for struct fields, arrays,
|
||||
// and similar ABI-mandated things.
|
||||
pub fn llalign_of_min(cx: &CrateContext, t: TypeRef) -> uint {
|
||||
pub fn llalign_of_min(cx: &CrateContext, ty: Type) -> uint {
|
||||
unsafe {
|
||||
return llvm::LLVMABIAlignmentOfType(cx.td.lltd, t) as uint;
|
||||
return llvm::LLVMABIAlignmentOfType(cx.td.lltd, ty.to_ref()) as uint;
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the "default" alignment of t, which is calculated by casting
|
||||
// null to a record containing a single-bit followed by a t value, then
|
||||
// doing gep(0,1) to get at the trailing (and presumably padded) t cell.
|
||||
pub fn llalign_of(cx: &CrateContext, t: TypeRef) -> ValueRef {
|
||||
pub fn llalign_of(cx: &CrateContext, ty: Type) -> ValueRef {
|
||||
unsafe {
|
||||
return llvm::LLVMConstIntCast(
|
||||
llvm::LLVMAlignOf(t), cx.int_type, False);
|
||||
llvm::LLVMAlignOf(ty.to_ref()), cx.int_type.to_ref(), False);
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,9 +142,9 @@ pub fn static_size_of_enum(cx: &mut CrateContext, t: ty::t) -> uint {
|
||||
|
||||
debug!("static_size_of_enum: variant %s type %s",
|
||||
cx.tcx.sess.str_of(variant.name),
|
||||
ty_str(cx.tn, T_struct(lltypes, false)));
|
||||
cx.tn.type_to_str(Type::struct_(lltypes, false)));
|
||||
|
||||
let this_size = llsize_of_real(cx, T_struct(lltypes, false));
|
||||
let this_size = llsize_of_real(cx, Type::struct_(lltypes, false));
|
||||
if max_size < this_size {
|
||||
max_size = this_size;
|
||||
}
|
||||
|
@ -30,6 +30,8 @@ use middle::typeck;
|
||||
use util::common::indenter;
|
||||
use util::ppaux::Repr;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use core::str;
|
||||
use core::vec;
|
||||
use syntax::ast_map::{path, path_mod, path_name};
|
||||
@ -49,7 +51,7 @@ pub fn trans_impl(ccx: @mut CrateContext,
|
||||
generics: &ast::Generics,
|
||||
self_ty: Option<ty::t>,
|
||||
id: ast::node_id) {
|
||||
let _icx = ccx.insn_ctxt("impl::trans_impl");
|
||||
let _icx = push_ctxt("impl::trans_impl");
|
||||
let tcx = ccx.tcx;
|
||||
|
||||
debug!("trans_impl(path=%s, name=%s, self_ty=%s, id=%?)",
|
||||
@ -157,7 +159,7 @@ pub fn trans_method(ccx: @mut CrateContext,
|
||||
pub fn trans_self_arg(bcx: block,
|
||||
base: @ast::expr,
|
||||
mentry: typeck::method_map_entry) -> Result {
|
||||
let _icx = bcx.insn_ctxt("impl::trans_self_arg");
|
||||
let _icx = push_ctxt("impl::trans_self_arg");
|
||||
let mut temp_cleanups = ~[];
|
||||
|
||||
// Compute the type of self.
|
||||
@ -185,7 +187,7 @@ pub fn trans_method_callee(bcx: block,
|
||||
this: @ast::expr,
|
||||
mentry: typeck::method_map_entry)
|
||||
-> Callee {
|
||||
let _icx = bcx.insn_ctxt("impl::trans_method_callee");
|
||||
let _icx = push_ctxt("impl::trans_method_callee");
|
||||
let tcx = bcx.tcx();
|
||||
|
||||
debug!("trans_method_callee(callee_id=%?, this=%s, mentry=%s)",
|
||||
@ -291,7 +293,7 @@ pub fn trans_static_method_callee(bcx: block,
|
||||
trait_id: ast::def_id,
|
||||
callee_id: ast::node_id)
|
||||
-> FnData {
|
||||
let _icx = bcx.insn_ctxt("impl::trans_static_method_callee");
|
||||
let _icx = push_ctxt("impl::trans_static_method_callee");
|
||||
let ccx = bcx.ccx();
|
||||
|
||||
debug!("trans_static_method_callee(method_id=%?, trait_id=%s, \
|
||||
@ -363,7 +365,7 @@ pub fn trans_static_method_callee(bcx: block,
|
||||
Some(callee_origins));
|
||||
|
||||
let callee_ty = node_id_type(bcx, callee_id);
|
||||
let llty = T_ptr(type_of_fn_from_ty(ccx, callee_ty));
|
||||
let llty = type_of_fn_from_ty(ccx, callee_ty).ptr_to();
|
||||
FnData {llfn: PointerCast(bcx, lval, llty)}
|
||||
}
|
||||
_ => {
|
||||
@ -435,7 +437,7 @@ pub fn trans_monomorphized_callee(bcx: block,
|
||||
n_method: uint,
|
||||
vtbl: typeck::vtable_origin)
|
||||
-> Callee {
|
||||
let _icx = bcx.insn_ctxt("impl::trans_monomorphized_callee");
|
||||
let _icx = push_ctxt("impl::trans_monomorphized_callee");
|
||||
return match vtbl {
|
||||
typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
|
||||
let ccx = bcx.ccx();
|
||||
@ -463,7 +465,7 @@ pub fn trans_monomorphized_callee(bcx: block,
|
||||
|
||||
// create a llvalue that represents the fn ptr
|
||||
let fn_ty = node_id_type(bcx, callee_id);
|
||||
let llfn_ty = T_ptr(type_of_fn_from_ty(ccx, fn_ty));
|
||||
let llfn_ty = type_of_fn_from_ty(ccx, fn_ty).ptr_to();
|
||||
let llfn_val = PointerCast(bcx, callee.llfn, llfn_ty);
|
||||
|
||||
// combine the self environment with the rest
|
||||
@ -584,7 +586,7 @@ pub fn trans_trait_callee(bcx: block,
|
||||
// first evaluate the self expression (expected a by-ref result) and then
|
||||
// extract the self data and vtable out of the pair.
|
||||
|
||||
let _icx = bcx.insn_ctxt("impl::trans_trait_callee");
|
||||
let _icx = push_ctxt("impl::trans_trait_callee");
|
||||
let mut bcx = bcx;
|
||||
let self_datum = unpack_datum!(bcx,
|
||||
expr::trans_to_datum(bcx, self_expr));
|
||||
@ -617,18 +619,18 @@ pub fn trans_trait_callee_from_llval(bcx: block,
|
||||
// Same as `trans_trait_callee()` above, except that it is given
|
||||
// a by-ref pointer to the @Trait pair.
|
||||
|
||||
let _icx = bcx.insn_ctxt("impl::trans_trait_callee");
|
||||
let _icx = push_ctxt("impl::trans_trait_callee");
|
||||
let ccx = bcx.ccx();
|
||||
let mut bcx = bcx;
|
||||
|
||||
// Load the vtable from the @Trait pair
|
||||
debug!("(translating trait callee) loading vtable from pair %s",
|
||||
val_str(bcx.ccx().tn, llpair));
|
||||
bcx.val_to_str(llpair));
|
||||
let llvtable = Load(bcx,
|
||||
PointerCast(bcx,
|
||||
GEPi(bcx, llpair,
|
||||
[0u, abi::trt_field_vtable]),
|
||||
T_ptr(T_ptr(T_vtable()))));
|
||||
Type::vtable().ptr_to().ptr_to()));
|
||||
|
||||
// Load the box from the @Trait pair and GEP over the box header if
|
||||
// necessary:
|
||||
@ -705,7 +707,7 @@ pub fn trans_trait_callee_from_llval(bcx: block,
|
||||
// Plus one in order to skip past the type descriptor.
|
||||
let mptr = Load(bcx, GEPi(bcx, llvtable, [0u, n_method + 1]));
|
||||
|
||||
let mptr = PointerCast(bcx, mptr, T_ptr(llcallee_ty));
|
||||
let mptr = PointerCast(bcx, mptr, llcallee_ty.ptr_to());
|
||||
|
||||
return Callee {
|
||||
bcx: bcx,
|
||||
@ -768,7 +770,7 @@ pub fn make_vtable(ccx: @mut CrateContext,
|
||||
ptrs: &[ValueRef])
|
||||
-> ValueRef {
|
||||
unsafe {
|
||||
let _icx = ccx.insn_ctxt("impl::make_vtable");
|
||||
let _icx = push_ctxt("impl::make_vtable");
|
||||
|
||||
let mut components = ~[ tydesc.tydesc ];
|
||||
for ptrs.each |&ptr| {
|
||||
@ -778,7 +780,7 @@ pub fn make_vtable(ccx: @mut CrateContext,
|
||||
let tbl = C_struct(components);
|
||||
let vtable = ccx.sess.str_of((ccx.names)("vtable"));
|
||||
let vt_gvar = do str::as_c_str(vtable) |buf| {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, val_ty(tbl), buf)
|
||||
llvm::LLVMAddGlobal(ccx.llmod, val_ty(tbl).to_ref(), buf)
|
||||
};
|
||||
llvm::LLVMSetInitializer(vt_gvar, tbl);
|
||||
llvm::LLVMSetGlobalConstant(vt_gvar, lib::llvm::True);
|
||||
@ -795,7 +797,7 @@ pub fn make_impl_vtable(bcx: block,
|
||||
vtables: typeck::vtable_res)
|
||||
-> ValueRef {
|
||||
let ccx = bcx.ccx();
|
||||
let _icx = ccx.insn_ctxt("impl::make_impl_vtable");
|
||||
let _icx = push_ctxt("impl::make_impl_vtable");
|
||||
let tcx = ccx.tcx;
|
||||
|
||||
let trt_id = match ty::impl_trait_ref(tcx, impl_id) {
|
||||
@ -814,7 +816,7 @@ pub fn make_impl_vtable(bcx: block,
|
||||
if im.generics.has_type_params() || ty::type_has_self(fty) {
|
||||
debug!("(making impl vtable) method has self or type params: %s",
|
||||
tcx.sess.str_of(im.ident));
|
||||
C_null(T_ptr(T_nil()))
|
||||
C_null(Type::nil().ptr_to())
|
||||
} else {
|
||||
debug!("(making impl vtable) adding method to vtable: %s",
|
||||
tcx.sess.str_of(im.ident));
|
||||
@ -839,7 +841,7 @@ pub fn trans_trait_cast(bcx: block,
|
||||
_store: ty::TraitStore)
|
||||
-> block {
|
||||
let mut bcx = bcx;
|
||||
let _icx = bcx.insn_ctxt("impl::trans_cast");
|
||||
let _icx = push_ctxt("impl::trans_cast");
|
||||
|
||||
let lldest = match dest {
|
||||
Ignore => {
|
||||
@ -857,7 +859,7 @@ pub fn trans_trait_cast(bcx: block,
|
||||
// have no type descriptor field.)
|
||||
llboxdest = PointerCast(bcx,
|
||||
llboxdest,
|
||||
T_ptr(type_of(bcx.ccx(), v_ty)));
|
||||
type_of(bcx.ccx(), v_ty).ptr_to());
|
||||
bcx = expr::trans_into(bcx, val, SaveIn(llboxdest));
|
||||
|
||||
// Store the vtable into the pair or triple.
|
||||
@ -866,7 +868,7 @@ pub fn trans_trait_cast(bcx: block,
|
||||
let vtable = get_vtable(bcx, v_ty, orig);
|
||||
Store(bcx, vtable, PointerCast(bcx,
|
||||
GEPi(bcx, lldest, [0u, abi::trt_field_vtable]),
|
||||
T_ptr(val_ty(vtable))));
|
||||
val_ty(vtable).ptr_to()));
|
||||
|
||||
bcx
|
||||
}
|
||||
|
@ -42,3 +42,4 @@ pub mod reachable;
|
||||
pub mod machine;
|
||||
pub mod adt;
|
||||
pub mod asm;
|
||||
pub mod type_;
|
||||
|
@ -13,9 +13,8 @@ use core::prelude::*;
|
||||
use back::link::mangle_exported_name;
|
||||
use driver::session;
|
||||
use lib::llvm::ValueRef;
|
||||
use middle::trans::base::{get_insn_ctxt};
|
||||
use middle::trans::base::{set_inline_hint_if_appr, set_inline_hint};
|
||||
use middle::trans::base::{trans_enum_variant};
|
||||
use middle::trans::base::{trans_enum_variant,push_ctxt};
|
||||
use middle::trans::base::{trans_fn, decl_internal_cdecl_fn};
|
||||
use middle::trans::base::{get_item_val, no_self};
|
||||
use middle::trans::base;
|
||||
@ -61,7 +60,7 @@ pub fn monomorphic_fn(ccx: @mut CrateContext,
|
||||
ref_id);
|
||||
|
||||
assert!(real_substs.tps.iter().all(|t| !ty::type_needs_infer(*t)));
|
||||
let _icx = ccx.insn_ctxt("monomorphic_fn");
|
||||
let _icx = push_ctxt("monomorphic_fn");
|
||||
let mut must_cast = false;
|
||||
let substs = vec::map(real_substs.tps, |t| {
|
||||
match normalize_for_monomorphization(ccx.tcx, *t) {
|
||||
|
@ -9,7 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
use back::link::mangle_internal_name_by_path_and_seq;
|
||||
use lib::llvm::{TypeRef, ValueRef, llvm};
|
||||
use lib::llvm::{ValueRef, llvm};
|
||||
use middle::trans::adt;
|
||||
use middle::trans::base::*;
|
||||
use middle::trans::build::*;
|
||||
@ -33,11 +33,13 @@ use syntax::ast;
|
||||
use syntax::ast_map::path_name;
|
||||
use syntax::parse::token::special_idents;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
pub struct Reflector {
|
||||
visitor_val: ValueRef,
|
||||
visitor_methods: @~[@ty::Method],
|
||||
final_bcx: block,
|
||||
tydesc_ty: TypeRef,
|
||||
tydesc_ty: Type,
|
||||
bcx: block
|
||||
}
|
||||
|
||||
@ -58,7 +60,7 @@ impl Reflector {
|
||||
let str_ty = ty::mk_estr(bcx.tcx(), str_vstore);
|
||||
let scratch = scratch_datum(bcx, str_ty, false);
|
||||
let len = C_uint(bcx.ccx(), s.len() + 1);
|
||||
let c_str = PointerCast(bcx, C_cstr(bcx.ccx(), s), T_ptr(T_i8()));
|
||||
let c_str = PointerCast(bcx, C_cstr(bcx.ccx(), s), Type::i8p());
|
||||
Store(bcx, c_str, GEPi(bcx, scratch.val, [ 0, 0 ]));
|
||||
Store(bcx, len, GEPi(bcx, scratch.val, [ 0, 1 ]));
|
||||
scratch.val
|
||||
@ -76,7 +78,7 @@ impl Reflector {
|
||||
let bcx = self.bcx;
|
||||
let static_ti = get_tydesc(bcx.ccx(), t);
|
||||
glue::lazily_emit_all_tydesc_glue(bcx.ccx(), static_ti);
|
||||
PointerCast(bcx, static_ti.tydesc, T_ptr(self.tydesc_ty))
|
||||
PointerCast(bcx, static_ti.tydesc, self.tydesc_ty.ptr_to())
|
||||
}
|
||||
|
||||
pub fn c_mt(&mut self, mt: &ty::mt) -> ~[ValueRef] {
|
||||
@ -96,7 +98,7 @@ impl Reflector {
|
||||
debug!("passing %u args:", args.len());
|
||||
let bcx = self.bcx;
|
||||
for args.iter().enumerate().advance |(i, a)| {
|
||||
debug!("arg %u: %s", i, val_str(bcx.ccx().tn, *a));
|
||||
debug!("arg %u: %s", i, bcx.val_to_str(*a));
|
||||
}
|
||||
let bool_ty = ty::mk_bool();
|
||||
let scratch = scratch_datum(bcx, bool_ty, false);
|
||||
@ -271,7 +273,7 @@ impl Reflector {
|
||||
let ccx = bcx.ccx();
|
||||
let repr = adt::represent_type(bcx.ccx(), t);
|
||||
let variants = ty::substd_enum_variants(ccx.tcx, did, substs);
|
||||
let llptrty = T_ptr(type_of(ccx, t));
|
||||
let llptrty = type_of(ccx, t).ptr_to();
|
||||
let (_, opaquety) =
|
||||
ccx.tcx.intrinsic_defs.find_copy(&ccx.sess.ident_of("Opaque"))
|
||||
.expect("Failed to resolve intrinsic::Opaque");
|
||||
|
@ -15,7 +15,8 @@
|
||||
use lib::llvm::llvm;
|
||||
use lib::llvm::{True, ModuleRef, ValueRef};
|
||||
use middle::trans::common::*;
|
||||
use middle::trans;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use core::str;
|
||||
|
||||
@ -32,7 +33,7 @@ pub fn mk_global(ccx: &CrateContext,
|
||||
-> ValueRef {
|
||||
unsafe {
|
||||
let llglobal = do str::as_c_str(name) |buf| {
|
||||
llvm::LLVMAddGlobal(ccx.llmod, val_ty(llval), buf)
|
||||
llvm::LLVMAddGlobal(ccx.llmod, val_ty(llval).to_ref(), buf)
|
||||
};
|
||||
llvm::LLVMSetInitializer(llglobal, llval);
|
||||
llvm::LLVMSetGlobalConstant(llglobal, True);
|
||||
@ -48,28 +49,15 @@ pub fn mk_global(ccx: &CrateContext,
|
||||
|
||||
pub fn mk_ctxt(llmod: ModuleRef) -> Ctxt {
|
||||
unsafe {
|
||||
let llshapetablesty = trans::common::T_named_struct("shapes");
|
||||
let _llshapetables = str::as_c_str("shapes", |buf| {
|
||||
llvm::LLVMAddGlobal(llmod, llshapetablesty, buf)
|
||||
});
|
||||
let llshapetablesty = Type::named_struct("shapes");
|
||||
do "shapes".as_c_str |buf| {
|
||||
llvm::LLVMAddGlobal(llmod, llshapetablesty.to_ref(), buf)
|
||||
};
|
||||
|
||||
return Ctxt {
|
||||
Ctxt {
|
||||
next_tag_id: 0u16,
|
||||
pad: 0u16,
|
||||
pad2: 0u32
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Although these two functions are never called, they are here
|
||||
for a VERY GOOD REASON. See #3670
|
||||
*/
|
||||
pub fn add_u16(dest: &mut ~[u8], val: u16) {
|
||||
*dest += [(val & 0xffu16) as u8, (val >> 8u16) as u8];
|
||||
}
|
||||
|
||||
pub fn add_substr(dest: &mut ~[u8], src: ~[u8]) {
|
||||
add_u16(&mut *dest, src.len() as u16);
|
||||
*dest += src;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
use back::abi;
|
||||
use lib;
|
||||
use lib::llvm::{llvm, ValueRef, TypeRef};
|
||||
use lib::llvm::{llvm, ValueRef};
|
||||
use middle::trans::base;
|
||||
use middle::trans::base::*;
|
||||
use middle::trans::build::*;
|
||||
@ -27,6 +27,8 @@ use middle::ty;
|
||||
use util::common::indenter;
|
||||
use util::ppaux::ty_to_str;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use core::option::None;
|
||||
use syntax::ast;
|
||||
use syntax::codemap;
|
||||
@ -51,7 +53,7 @@ pub fn expand_boxed_vec_ty(tcx: ty::ctxt, t: ty::t) -> ty::t {
|
||||
}
|
||||
|
||||
pub fn get_fill(bcx: block, vptr: ValueRef) -> ValueRef {
|
||||
let _icx = bcx.insn_ctxt("tvec::get_fill");
|
||||
let _icx = push_ctxt("tvec::get_fill");
|
||||
Load(bcx, GEPi(bcx, vptr, [0u, abi::vec_elt_fill]))
|
||||
}
|
||||
pub fn set_fill(bcx: block, vptr: ValueRef, fill: ValueRef) {
|
||||
@ -62,24 +64,24 @@ pub fn get_alloc(bcx: block, vptr: ValueRef) -> ValueRef {
|
||||
}
|
||||
|
||||
pub fn get_bodyptr(bcx: block, vptr: ValueRef) -> ValueRef {
|
||||
base::non_gc_box_cast(bcx, GEPi(bcx, vptr, [0u, abi::box_field_body]))
|
||||
GEPi(bcx, vptr, [0u, abi::box_field_body])
|
||||
}
|
||||
|
||||
pub fn get_dataptr(bcx: block, vptr: ValueRef) -> ValueRef {
|
||||
let _icx = bcx.insn_ctxt("tvec::get_dataptr");
|
||||
let _icx = push_ctxt("tvec::get_dataptr");
|
||||
GEPi(bcx, vptr, [0u, abi::vec_elt_elems, 0u])
|
||||
}
|
||||
|
||||
pub fn pointer_add(bcx: block, ptr: ValueRef, bytes: ValueRef) -> ValueRef {
|
||||
let _icx = bcx.insn_ctxt("tvec::pointer_add");
|
||||
let _icx = push_ctxt("tvec::pointer_add");
|
||||
let old_ty = val_ty(ptr);
|
||||
let bptr = PointerCast(bcx, ptr, T_ptr(T_i8()));
|
||||
let bptr = PointerCast(bcx, ptr, Type::i8p());
|
||||
return PointerCast(bcx, InBoundsGEP(bcx, bptr, [bytes]), old_ty);
|
||||
}
|
||||
|
||||
pub fn alloc_raw(bcx: block, unit_ty: ty::t,
|
||||
fill: ValueRef, alloc: ValueRef, heap: heap) -> Result {
|
||||
let _icx = bcx.insn_ctxt("tvec::alloc_uniq");
|
||||
let _icx = push_ctxt("tvec::alloc_uniq");
|
||||
let ccx = bcx.ccx();
|
||||
|
||||
let vecbodyty = ty::mk_mut_unboxed_vec(bcx.tcx(), unit_ty);
|
||||
@ -103,7 +105,7 @@ pub fn alloc_vec(bcx: block,
|
||||
elts: uint,
|
||||
heap: heap)
|
||||
-> Result {
|
||||
let _icx = bcx.insn_ctxt("tvec::alloc_uniq");
|
||||
let _icx = push_ctxt("tvec::alloc_uniq");
|
||||
let ccx = bcx.ccx();
|
||||
let llunitty = type_of::type_of(ccx, unit_ty);
|
||||
let unit_sz = nonzero_llsize_of(ccx, llunitty);
|
||||
@ -117,7 +119,7 @@ pub fn alloc_vec(bcx: block,
|
||||
}
|
||||
|
||||
pub fn duplicate_uniq(bcx: block, vptr: ValueRef, vec_ty: ty::t) -> Result {
|
||||
let _icx = bcx.insn_ctxt("tvec::duplicate_uniq");
|
||||
let _icx = push_ctxt("tvec::duplicate_uniq");
|
||||
|
||||
let fill = get_fill(bcx, get_bodyptr(bcx, vptr));
|
||||
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
|
||||
@ -135,7 +137,7 @@ pub fn duplicate_uniq(bcx: block, vptr: ValueRef, vec_ty: ty::t) -> Result {
|
||||
|
||||
pub fn make_drop_glue_unboxed(bcx: block, vptr: ValueRef, vec_ty: ty::t) ->
|
||||
block {
|
||||
let _icx = bcx.insn_ctxt("tvec::make_drop_glue_unboxed");
|
||||
let _icx = push_ctxt("tvec::make_drop_glue_unboxed");
|
||||
let tcx = bcx.tcx();
|
||||
let unit_ty = ty::sequence_element_type(tcx, vec_ty);
|
||||
if ty::type_needs_drop(tcx, unit_ty) {
|
||||
@ -146,7 +148,7 @@ pub fn make_drop_glue_unboxed(bcx: block, vptr: ValueRef, vec_ty: ty::t) ->
|
||||
pub struct VecTypes {
|
||||
vec_ty: ty::t,
|
||||
unit_ty: ty::t,
|
||||
llunit_ty: TypeRef,
|
||||
llunit_ty: Type,
|
||||
llunit_size: ValueRef
|
||||
}
|
||||
|
||||
@ -155,8 +157,8 @@ impl VecTypes {
|
||||
fmt!("VecTypes {vec_ty=%s, unit_ty=%s, llunit_ty=%s, llunit_size=%s}",
|
||||
ty_to_str(ccx.tcx, self.vec_ty),
|
||||
ty_to_str(ccx.tcx, self.unit_ty),
|
||||
ty_str(ccx.tn, self.llunit_ty),
|
||||
val_str(ccx.tn, self.llunit_size))
|
||||
ccx.tn.type_to_str(self.llunit_ty),
|
||||
ccx.tn.val_to_str(self.llunit_size))
|
||||
}
|
||||
}
|
||||
|
||||
@ -227,7 +229,7 @@ pub fn trans_slice_vstore(bcx: block,
|
||||
let fixed_ty = ty::mk_evec(bcx.tcx(),
|
||||
ty::mt {ty: vt.unit_ty, mutbl: ast::m_mutbl},
|
||||
ty::vstore_fixed(count));
|
||||
let llfixed_ty = T_ptr(type_of::type_of(bcx.ccx(), fixed_ty));
|
||||
let llfixed_ty = type_of::type_of(bcx.ccx(), fixed_ty).ptr_to();
|
||||
let llfixed_casted = BitCast(bcx, llfixed, llfixed_ty);
|
||||
add_clean(bcx, llfixed_casted, fixed_ty);
|
||||
|
||||
@ -271,13 +273,10 @@ pub fn trans_lit_str(bcx: block,
|
||||
let bytes = str_lit.len() + 1; // count null-terminator too
|
||||
let llbytes = C_uint(bcx.ccx(), bytes);
|
||||
let llcstr = C_cstr(bcx.ccx(), str_lit);
|
||||
let llcstr = llvm::LLVMConstPointerCast(llcstr,
|
||||
T_ptr(T_i8()));
|
||||
Store(bcx,
|
||||
llcstr,
|
||||
let llcstr = llvm::LLVMConstPointerCast(llcstr, Type::i8p().to_ref());
|
||||
Store(bcx, llcstr,
|
||||
GEPi(bcx, lldest, [0u, abi::slice_elt_base]));
|
||||
Store(bcx,
|
||||
llbytes,
|
||||
Store(bcx, llbytes,
|
||||
GEPi(bcx, lldest, [0u, abi::slice_elt_len]));
|
||||
bcx
|
||||
}
|
||||
@ -286,9 +285,7 @@ pub fn trans_lit_str(bcx: block,
|
||||
}
|
||||
|
||||
|
||||
pub fn trans_uniq_or_managed_vstore(bcx: block,
|
||||
heap: heap,
|
||||
vstore_expr: @ast::expr,
|
||||
pub fn trans_uniq_or_managed_vstore(bcx: block, heap: heap, vstore_expr: @ast::expr,
|
||||
content_expr: @ast::expr) -> DatumBlock {
|
||||
//!
|
||||
//
|
||||
@ -307,7 +304,7 @@ pub fn trans_uniq_or_managed_vstore(bcx: block,
|
||||
node: ast::lit_str(s), _
|
||||
}) => {
|
||||
let llptrval = C_cstr(bcx.ccx(), s);
|
||||
let llptrval = PointerCast(bcx, llptrval, T_ptr(T_i8()));
|
||||
let llptrval = PointerCast(bcx, llptrval, Type::i8p());
|
||||
let llsizeval = C_uint(bcx.ccx(), s.len());
|
||||
let typ = ty::mk_estr(bcx.tcx(), ty::vstore_uniq);
|
||||
let lldestval = scratch_datum(bcx, typ, false);
|
||||
@ -336,7 +333,7 @@ pub fn trans_uniq_or_managed_vstore(bcx: block,
|
||||
let dataptr = get_dataptr(bcx, get_bodyptr(bcx, val));
|
||||
|
||||
debug!("alloc_vec() returned val=%s, dataptr=%s",
|
||||
bcx.val_str(val), bcx.val_str(dataptr));
|
||||
bcx.val_to_str(val), bcx.val_to_str(dataptr));
|
||||
|
||||
let bcx = write_content(bcx, &vt, vstore_expr,
|
||||
content_expr, SaveIn(dataptr));
|
||||
@ -352,7 +349,7 @@ pub fn write_content(bcx: block,
|
||||
content_expr: @ast::expr,
|
||||
dest: Dest)
|
||||
-> block {
|
||||
let _icx = bcx.insn_ctxt("tvec::write_content");
|
||||
let _icx = push_ctxt("tvec::write_content");
|
||||
let mut bcx = bcx;
|
||||
|
||||
debug!("write_content(vt=%s, dest=%s, vstore_expr=%?)",
|
||||
@ -389,7 +386,7 @@ pub fn write_content(bcx: block,
|
||||
for elements.iter().enumerate().advance |(i, element)| {
|
||||
let lleltptr = GEPi(bcx, lldest, [i]);
|
||||
debug!("writing index %? with lleltptr=%?",
|
||||
i, bcx.val_str(lleltptr));
|
||||
i, bcx.val_to_str(lleltptr));
|
||||
bcx = expr::trans_into(bcx, *element,
|
||||
SaveIn(lleltptr));
|
||||
add_clean_temp_mem(bcx, lleltptr, vt.unit_ty);
|
||||
@ -551,7 +548,7 @@ pub type iter_vec_block<'self> = &'self fn(block, ValueRef, ty::t) -> block;
|
||||
|
||||
pub fn iter_vec_raw(bcx: block, data_ptr: ValueRef, vec_ty: ty::t,
|
||||
fill: ValueRef, f: iter_vec_block) -> block {
|
||||
let _icx = bcx.insn_ctxt("tvec::iter_vec_raw");
|
||||
let _icx = push_ctxt("tvec::iter_vec_raw");
|
||||
|
||||
let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
|
||||
|
||||
@ -582,14 +579,14 @@ pub fn iter_vec_raw(bcx: block, data_ptr: ValueRef, vec_ty: ty::t,
|
||||
|
||||
pub fn iter_vec_uniq(bcx: block, vptr: ValueRef, vec_ty: ty::t,
|
||||
fill: ValueRef, f: iter_vec_block) -> block {
|
||||
let _icx = bcx.insn_ctxt("tvec::iter_vec_uniq");
|
||||
let _icx = push_ctxt("tvec::iter_vec_uniq");
|
||||
let data_ptr = get_dataptr(bcx, get_bodyptr(bcx, vptr));
|
||||
iter_vec_raw(bcx, data_ptr, vec_ty, fill, f)
|
||||
}
|
||||
|
||||
pub fn iter_vec_unboxed(bcx: block, body_ptr: ValueRef, vec_ty: ty::t,
|
||||
f: iter_vec_block) -> block {
|
||||
let _icx = bcx.insn_ctxt("tvec::iter_vec_unboxed");
|
||||
let _icx = push_ctxt("tvec::iter_vec_unboxed");
|
||||
let fill = get_fill(bcx, body_ptr);
|
||||
let dataptr = get_dataptr(bcx, body_ptr);
|
||||
return iter_vec_raw(bcx, dataptr, vec_ty, fill, f);
|
||||
|
374
src/librustc/middle/trans/type_.rs
Normal file
374
src/librustc/middle/trans/type_.rs
Normal file
@ -0,0 +1,374 @@
|
||||
// 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, TypeKind};
|
||||
use lib::llvm::{Float, Double, X86_FP80, PPC_FP128, FP128};
|
||||
|
||||
use middle::ty;
|
||||
|
||||
use middle::trans::context::CrateContext;
|
||||
use middle::trans::base;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::abi::{Architecture, X86, X86_64, Arm, Mips};
|
||||
use back::abi;
|
||||
|
||||
use core::vec;
|
||||
use core::cast;
|
||||
|
||||
use core::libc::{c_uint};
|
||||
|
||||
#[deriving(Eq)]
|
||||
pub struct Type {
|
||||
priv rf: TypeRef
|
||||
}
|
||||
|
||||
macro_rules! ty (
|
||||
($e:expr) => ( Type::from_ref(unsafe { $e }))
|
||||
)
|
||||
|
||||
/**
|
||||
* Wrapper for LLVM TypeRef
|
||||
*/
|
||||
impl Type {
|
||||
#[inline(always)]
|
||||
pub fn from_ref(r: TypeRef) -> Type {
|
||||
Type {
|
||||
rf: r
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)] // So it doesn't kill --opt-level=0 builds of the compiler
|
||||
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 i8p() -> Type {
|
||||
Type::i8().ptr_to()
|
||||
}
|
||||
|
||||
pub fn int(arch: Architecture) -> Type {
|
||||
match arch {
|
||||
X86 | Arm | Mips => Type::i32(),
|
||||
X86_64 => Type::i64()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn float(_: 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_type,
|
||||
ast::ty_f32 => Type::f32(),
|
||||
ast::ty_f64 => Type::f64()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn size_t(arch: Architecture) -> Type {
|
||||
Type::int(arch)
|
||||
}
|
||||
|
||||
pub fn func(args: &[Type], ret: &Type) -> Type {
|
||||
let vec : &[TypeRef] = unsafe { cast::transmute(args) };
|
||||
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 {
|
||||
Type::struct_([fn_ty.ptr_to(), Type::opaque_cbox_ptr(cx)], false)
|
||||
}
|
||||
|
||||
pub fn ptr(ty: Type) -> Type {
|
||||
ty!(llvm::LLVMPointerType(ty.to_ref(), 0 as c_uint))
|
||||
}
|
||||
|
||||
pub fn struct_(els: &[Type], packed: bool) -> Type {
|
||||
let els : &[TypeRef] = unsafe { cast::transmute(els) };
|
||||
ty!(llvm::LLVMStructTypeInContext(base::task_llcx(), 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: Architecture) -> Type {
|
||||
let mut tydesc = Type::named_struct("tydesc");
|
||||
let tydescpp = tydesc.ptr_to().ptr_to();
|
||||
let pvoid = Type::i8p();
|
||||
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_ty, int_ty,
|
||||
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: u64) -> Type {
|
||||
ty!(llvm::LLVMArrayType(ty.to_ref(), len as c_uint))
|
||||
}
|
||||
|
||||
pub fn vector(ty: &Type, len: u64) -> Type {
|
||||
ty!(llvm::LLVMVectorType(ty.to_ref(), len as c_uint))
|
||||
}
|
||||
|
||||
pub fn vec(arch: Architecture, ty: &Type) -> Type {
|
||||
Type::struct_(
|
||||
[ Type::int(arch), Type::int(arch), Type::array(ty, 0) ],
|
||||
false)
|
||||
}
|
||||
|
||||
pub fn opaque_vec(arch: 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) + [*ty], 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(cx).ptr_to()
|
||||
}
|
||||
|
||||
pub fn enum_discrim(cx: &CrateContext) -> Type {
|
||||
cx.int_type
|
||||
}
|
||||
|
||||
pub fn captured_tydescs(ctx: &CrateContext, num: uint) -> Type {
|
||||
Type::struct_(vec::from_elem(num, ctx.tydesc_type.ptr_to()), false)
|
||||
}
|
||||
|
||||
pub fn opaque_trait(ctx: &CrateContext, store: ty::TraitStore) -> Type {
|
||||
let tydesc_ptr = ctx.tydesc_type.ptr_to();
|
||||
match store {
|
||||
ty::BoxTraitStore => {
|
||||
Type::struct_(
|
||||
[ tydesc_ptr, Type::opaque_box(ctx).ptr_to() ],
|
||||
false)
|
||||
}
|
||||
ty::UniqTraitStore => {
|
||||
Type::struct_(
|
||||
[ tydesc_ptr, Type::unique(ctx, &Type::i8()).ptr_to()],
|
||||
false)
|
||||
}
|
||||
ty::RegionTraitStore(*) => {
|
||||
Type::struct_(
|
||||
[ tydesc_ptr, Type::i8().ptr_to() ],
|
||||
false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn kind(&self) -> TypeKind {
|
||||
unsafe {
|
||||
llvm::LLVMGetTypeKind(self.to_ref())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_struct_body(&mut self, els: &[Type], packed: bool) {
|
||||
unsafe {
|
||||
let vec : &[TypeRef] = cast::transmute(els);
|
||||
llvm::LLVMStructSetBody(self.to_ref(), vec::raw::to_ptr(vec),
|
||||
els.len() as c_uint, packed as Bool)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ptr_to(&self) -> Type {
|
||||
ty!(llvm::LLVMPointerType(self.to_ref(), 0))
|
||||
}
|
||||
|
||||
pub fn get_field(&self, idx: uint) -> Type {
|
||||
unsafe {
|
||||
let num_fields = llvm::LLVMCountStructElementTypes(self.to_ref()) as uint;
|
||||
let mut elems = vec::from_elem(num_fields, 0 as TypeRef);
|
||||
|
||||
llvm::LLVMGetStructElementTypes(self.to_ref(), vec::raw::to_mut_ptr(elems));
|
||||
|
||||
Type::from_ref(elems[idx])
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_packed(&self) -> bool {
|
||||
unsafe {
|
||||
llvm::LLVMIsPackedStruct(self.to_ref()) == True
|
||||
}
|
||||
}
|
||||
|
||||
pub fn element_type(&self) -> Type {
|
||||
unsafe {
|
||||
Type::from_ref(llvm::LLVMGetElementType(self.to_ref()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn array_length(&self) -> uint {
|
||||
unsafe {
|
||||
llvm::LLVMGetArrayLength(self.to_ref()) as uint
|
||||
}
|
||||
}
|
||||
|
||||
pub fn field_types(&self) -> ~[Type] {
|
||||
unsafe {
|
||||
let n_elts = llvm::LLVMCountStructElementTypes(self.to_ref()) as uint;
|
||||
if n_elts == 0 {
|
||||
return ~[];
|
||||
}
|
||||
let mut elts = vec::from_elem(n_elts, 0 as TypeRef);
|
||||
llvm::LLVMGetStructElementTypes(self.to_ref(), &mut elts[0]);
|
||||
cast::transmute(elts)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn return_type(&self) -> Type {
|
||||
ty!(llvm::LLVMGetReturnType(self.to_ref()))
|
||||
}
|
||||
|
||||
pub fn func_params(&self) -> ~[Type] {
|
||||
unsafe {
|
||||
let n_args = llvm::LLVMCountParamTypes(self.to_ref()) as uint;
|
||||
let args = vec::from_elem(n_args, 0 as TypeRef);
|
||||
llvm::LLVMGetParamTypes(self.to_ref(), vec::raw::to_ptr(args));
|
||||
cast::transmute(args)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn float_width(&self) -> uint {
|
||||
match self.kind() {
|
||||
Float => 32,
|
||||
Double => 64,
|
||||
X86_FP80 => 80,
|
||||
FP128 | PPC_FP128 => 128,
|
||||
_ => fail!("llvm_float_width called on a non-float type")
|
||||
}
|
||||
}
|
||||
}
|
@ -10,61 +10,60 @@
|
||||
|
||||
use core::prelude::*;
|
||||
|
||||
use lib::llvm::llvm;
|
||||
use lib::llvm::{TypeRef};
|
||||
use middle::trans::adt;
|
||||
use middle::trans::base;
|
||||
use middle::trans::common::*;
|
||||
use middle::trans::common;
|
||||
use middle::ty;
|
||||
use util::ppaux;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use syntax::ast;
|
||||
|
||||
pub fn arg_is_indirect(_: &CrateContext, arg_ty: &ty::t) -> bool {
|
||||
!ty::type_is_immediate(*arg_ty)
|
||||
}
|
||||
|
||||
pub fn type_of_explicit_arg(ccx: &mut CrateContext, arg_ty: &ty::t) -> TypeRef {
|
||||
pub fn type_of_explicit_arg(ccx: &mut CrateContext, arg_ty: &ty::t) -> Type {
|
||||
let llty = type_of(ccx, *arg_ty);
|
||||
if arg_is_indirect(ccx, arg_ty) {T_ptr(llty)} else {llty}
|
||||
if arg_is_indirect(ccx, arg_ty) {
|
||||
llty.ptr_to()
|
||||
} else {
|
||||
llty
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_of_explicit_args(ccx: &mut CrateContext,
|
||||
inputs: &[ty::t]) -> ~[TypeRef] {
|
||||
inputs: &[ty::t]) -> ~[Type] {
|
||||
inputs.map(|arg_ty| type_of_explicit_arg(ccx, arg_ty))
|
||||
}
|
||||
|
||||
pub fn type_of_fn(cx: &mut CrateContext, inputs: &[ty::t], output: ty::t)
|
||||
-> TypeRef {
|
||||
unsafe {
|
||||
let mut atys: ~[TypeRef] = ~[];
|
||||
pub fn type_of_fn(cx: &mut CrateContext, inputs: &[ty::t], output: ty::t) -> Type {
|
||||
let mut atys: ~[Type] = ~[];
|
||||
|
||||
// Arg 0: Output pointer.
|
||||
// (if the output type is non-immediate)
|
||||
let output_is_immediate = ty::type_is_immediate(output);
|
||||
let lloutputtype = type_of(cx, output);
|
||||
if !output_is_immediate {
|
||||
atys.push(T_ptr(lloutputtype));
|
||||
}
|
||||
// Arg 0: Output pointer.
|
||||
// (if the output type is non-immediate)
|
||||
let output_is_immediate = ty::type_is_immediate(output);
|
||||
let lloutputtype = type_of(cx, output);
|
||||
if !output_is_immediate {
|
||||
atys.push(lloutputtype.ptr_to());
|
||||
}
|
||||
|
||||
// Arg 1: Environment
|
||||
atys.push(T_opaque_box_ptr(cx));
|
||||
// Arg 1: Environment
|
||||
atys.push(Type::opaque_box(cx).ptr_to());
|
||||
|
||||
// ... then explicit args.
|
||||
atys.push_all(type_of_explicit_args(cx, inputs));
|
||||
// ... then explicit args.
|
||||
atys.push_all(type_of_explicit_args(cx, inputs));
|
||||
|
||||
// Use the output as the actual return value if it's immediate.
|
||||
if output_is_immediate && !ty::type_is_nil(output) {
|
||||
T_fn(atys, lloutputtype)
|
||||
} else {
|
||||
T_fn(atys, llvm::LLVMVoidTypeInContext(cx.llcx))
|
||||
}
|
||||
// Use the output as the actual return value if it's immediate.
|
||||
if output_is_immediate && !ty::type_is_nil(output) {
|
||||
Type::func(atys, &lloutputtype)
|
||||
} else {
|
||||
Type::func(atys, &Type::void())
|
||||
}
|
||||
}
|
||||
|
||||
// Given a function type and a count of ty params, construct an llvm type
|
||||
pub fn type_of_fn_from_ty(cx: &mut CrateContext, fty: ty::t) -> TypeRef {
|
||||
pub fn type_of_fn_from_ty(cx: &mut CrateContext, fty: ty::t) -> Type {
|
||||
match ty::get(fty).sty {
|
||||
ty::ty_closure(ref f) => type_of_fn(cx, f.sig.inputs, f.sig.output),
|
||||
ty::ty_bare_fn(ref f) => type_of_fn(cx, f.sig.inputs, f.sig.output),
|
||||
@ -74,7 +73,7 @@ pub fn type_of_fn_from_ty(cx: &mut CrateContext, fty: ty::t) -> TypeRef {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_of_non_gc_box(cx: &mut CrateContext, t: ty::t) -> TypeRef {
|
||||
pub fn type_of_non_gc_box(cx: &mut CrateContext, t: ty::t) -> Type {
|
||||
assert!(!ty::type_needs_infer(t));
|
||||
|
||||
let t_norm = ty::normalize_ty(cx.tcx, t);
|
||||
@ -84,11 +83,11 @@ pub fn type_of_non_gc_box(cx: &mut CrateContext, t: ty::t) -> TypeRef {
|
||||
match ty::get(t).sty {
|
||||
ty::ty_box(mt) => {
|
||||
let ty = type_of(cx, mt.ty);
|
||||
T_ptr(T_box(cx, ty))
|
||||
Type::box(cx, &ty).ptr_to()
|
||||
}
|
||||
ty::ty_uniq(mt) => {
|
||||
let ty = type_of(cx, mt.ty);
|
||||
T_ptr(T_unique(cx, ty))
|
||||
Type::unique(cx, &ty).ptr_to()
|
||||
}
|
||||
_ => {
|
||||
cx.sess.bug("non-box in type_of_non_gc_box");
|
||||
@ -109,18 +108,18 @@ pub fn type_of_non_gc_box(cx: &mut CrateContext, t: ty::t) -> TypeRef {
|
||||
// recursive types. For example, `static_size_of_enum()` relies on this
|
||||
// behavior.
|
||||
|
||||
pub fn sizing_type_of(cx: &mut CrateContext, t: ty::t) -> TypeRef {
|
||||
match cx.llsizingtypes.find(&t) {
|
||||
Some(t) => return *t,
|
||||
pub fn sizing_type_of(cx: &mut CrateContext, t: ty::t) -> Type {
|
||||
match cx.llsizingtypes.find_copy(&t) {
|
||||
Some(t) => return t,
|
||||
None => ()
|
||||
}
|
||||
|
||||
let llsizingty = match ty::get(t).sty {
|
||||
ty::ty_nil | ty::ty_bot => T_nil(),
|
||||
ty::ty_bool => T_bool(),
|
||||
ty::ty_int(t) => T_int_ty(cx, t),
|
||||
ty::ty_uint(t) => T_uint_ty(cx, t),
|
||||
ty::ty_float(t) => T_float_ty(cx, t),
|
||||
ty::ty_nil | ty::ty_bot => Type::nil(),
|
||||
ty::ty_bool => Type::bool(),
|
||||
ty::ty_int(t) => Type::int_from_ty(cx, t),
|
||||
ty::ty_uint(t) => Type::uint_from_ty(cx, t),
|
||||
ty::ty_float(t) => Type::float_from_ty(cx, t),
|
||||
|
||||
ty::ty_estr(ty::vstore_uniq) |
|
||||
ty::ty_estr(ty::vstore_box) |
|
||||
@ -132,48 +131,46 @@ pub fn sizing_type_of(cx: &mut CrateContext, t: ty::t) -> TypeRef {
|
||||
ty::ty_ptr(*) |
|
||||
ty::ty_rptr(*) |
|
||||
ty::ty_type |
|
||||
ty::ty_opaque_closure_ptr(*) => T_ptr(T_i8()),
|
||||
ty::ty_opaque_closure_ptr(*) => Type::i8p(),
|
||||
|
||||
ty::ty_estr(ty::vstore_slice(*)) |
|
||||
ty::ty_evec(_, ty::vstore_slice(*)) => {
|
||||
T_struct([T_ptr(T_i8()), T_ptr(T_i8())], false)
|
||||
Type::struct_([Type::i8p(), Type::i8p()], false)
|
||||
}
|
||||
|
||||
ty::ty_bare_fn(*) => T_ptr(T_i8()),
|
||||
ty::ty_closure(*) => T_struct([T_ptr(T_i8()), T_ptr(T_i8())], false),
|
||||
ty::ty_trait(_, _, store, _) => T_opaque_trait(cx, store),
|
||||
ty::ty_bare_fn(*) => Type::i8p(),
|
||||
ty::ty_closure(*) => Type::struct_([Type::i8p(), Type::i8p()], false),
|
||||
ty::ty_trait(_, _, store, _) => Type::opaque_trait(cx, store),
|
||||
|
||||
ty::ty_estr(ty::vstore_fixed(size)) => T_array(T_i8(), size),
|
||||
ty::ty_estr(ty::vstore_fixed(size)) => Type::array(&Type::i8(), size as u64),
|
||||
ty::ty_evec(mt, ty::vstore_fixed(size)) => {
|
||||
T_array(sizing_type_of(cx, mt.ty), size)
|
||||
Type::array(&sizing_type_of(cx, mt.ty), size as u64)
|
||||
}
|
||||
|
||||
ty::ty_unboxed_vec(mt) => {
|
||||
let sz_ty = sizing_type_of(cx, mt.ty);
|
||||
T_vec(cx, sz_ty)
|
||||
Type::vec(cx.sess.targ_cfg.arch, &sz_ty)
|
||||
}
|
||||
|
||||
ty::ty_tup(*) | ty::ty_enum(*) => {
|
||||
let repr = adt::represent_type(cx, t);
|
||||
T_struct(adt::sizing_fields_of(cx, repr), false)
|
||||
Type::struct_(adt::sizing_fields_of(cx, repr), false)
|
||||
}
|
||||
|
||||
ty::ty_struct(did, _) => {
|
||||
if ty::type_is_simd(cx.tcx, t) {
|
||||
let et = ty::simd_type(cx.tcx, t);
|
||||
let n = ty::simd_size(cx.tcx, t);
|
||||
T_vector(type_of(cx, et), n)
|
||||
Type::vector(&type_of(cx, et), n as u64)
|
||||
} else {
|
||||
let repr = adt::represent_type(cx, t);
|
||||
let packed = ty::lookup_packed(cx.tcx, did);
|
||||
T_struct(adt::sizing_fields_of(cx, repr), packed)
|
||||
Type::struct_(adt::sizing_fields_of(cx, repr), packed)
|
||||
}
|
||||
}
|
||||
|
||||
ty::ty_self(_) | ty::ty_infer(*) | ty::ty_param(*) | ty::ty_err(*) => {
|
||||
cx.tcx.sess.bug(
|
||||
fmt!("fictitious type %? in sizing_type_of()",
|
||||
ty::get(t).sty))
|
||||
cx.tcx.sess.bug(fmt!("fictitious type %? in sizing_type_of()", ty::get(t).sty))
|
||||
}
|
||||
};
|
||||
|
||||
@ -182,7 +179,7 @@ pub fn sizing_type_of(cx: &mut CrateContext, t: ty::t) -> TypeRef {
|
||||
}
|
||||
|
||||
// NB: If you update this, be sure to update `sizing_type_of()` as well.
|
||||
pub fn type_of(cx: &mut CrateContext, t: ty::t) -> TypeRef {
|
||||
pub fn type_of(cx: &mut CrateContext, t: ty::t) -> Type {
|
||||
debug!("type_of %?: %?", t, ty::get(t));
|
||||
|
||||
// Check the cache.
|
||||
@ -204,14 +201,14 @@ pub fn type_of(cx: &mut CrateContext, t: ty::t) -> TypeRef {
|
||||
return llty;
|
||||
}
|
||||
|
||||
let llty = match ty::get(t).sty {
|
||||
ty::ty_nil | ty::ty_bot => T_nil(),
|
||||
ty::ty_bool => T_bool(),
|
||||
ty::ty_int(t) => T_int_ty(cx, t),
|
||||
ty::ty_uint(t) => T_uint_ty(cx, t),
|
||||
ty::ty_float(t) => T_float_ty(cx, t),
|
||||
let mut llty = match ty::get(t).sty {
|
||||
ty::ty_nil | ty::ty_bot => Type::nil(),
|
||||
ty::ty_bool => Type::bool(),
|
||||
ty::ty_int(t) => Type::int_from_ty(cx, t),
|
||||
ty::ty_uint(t) => Type::uint_from_ty(cx, t),
|
||||
ty::ty_float(t) => Type::float_from_ty(cx, t),
|
||||
ty::ty_estr(ty::vstore_uniq) => {
|
||||
T_unique_ptr(T_unique(cx, T_vec(cx, T_i8())))
|
||||
Type::unique(cx, &Type::vec(cx.sess.targ_cfg.arch, &Type::i8())).ptr_to()
|
||||
}
|
||||
ty::ty_enum(did, ref substs) => {
|
||||
// Only create the named struct, but don't fill it in. We
|
||||
@ -219,84 +216,79 @@ pub fn type_of(cx: &mut CrateContext, t: ty::t) -> TypeRef {
|
||||
// avoids creating more than one copy of the enum when one
|
||||
// of the enum's variants refers to the enum itself.
|
||||
|
||||
common::T_named_struct(llvm_type_name(cx,
|
||||
an_enum,
|
||||
did,
|
||||
substs.tps))
|
||||
Type::named_struct(llvm_type_name(cx, an_enum, did, substs.tps))
|
||||
}
|
||||
ty::ty_estr(ty::vstore_box) => {
|
||||
T_box_ptr(T_box(cx, T_vec(cx, T_i8())))
|
||||
Type::box(cx, &Type::vec(cx.sess.targ_cfg.arch, &Type::i8())).ptr_to()
|
||||
}
|
||||
ty::ty_evec(ref mt, ty::vstore_box) => {
|
||||
let e_ty = type_of(cx, mt.ty);
|
||||
let v_ty = T_vec(cx, e_ty);
|
||||
T_box_ptr(T_box(cx, v_ty))
|
||||
let v_ty = Type::vec(cx.sess.targ_cfg.arch, &e_ty);
|
||||
Type::box(cx, &v_ty).ptr_to()
|
||||
}
|
||||
ty::ty_box(ref mt) => {
|
||||
let ty = type_of(cx, mt.ty);
|
||||
T_box_ptr(T_box(cx, ty))
|
||||
Type::box(cx, &ty).ptr_to()
|
||||
}
|
||||
ty::ty_opaque_box => T_box_ptr(T_box(cx, T_i8())),
|
||||
ty::ty_opaque_box => Type::opaque_box(cx).ptr_to(),
|
||||
ty::ty_uniq(ref mt) => {
|
||||
let ty = type_of(cx, mt.ty);
|
||||
T_unique_ptr(T_unique(cx, ty))
|
||||
Type::unique(cx, &ty).ptr_to()
|
||||
}
|
||||
ty::ty_evec(ref mt, ty::vstore_uniq) => {
|
||||
let ty = type_of(cx, mt.ty);
|
||||
let ty = T_vec(cx, ty);
|
||||
T_unique_ptr(T_unique(cx, ty))
|
||||
let ty = Type::vec(cx.sess.targ_cfg.arch, &ty);
|
||||
Type::unique(cx, &ty).ptr_to()
|
||||
}
|
||||
ty::ty_unboxed_vec(ref mt) => {
|
||||
let ty = type_of(cx, mt.ty);
|
||||
T_vec(cx, ty)
|
||||
Type::vec(cx.sess.targ_cfg.arch, &ty)
|
||||
}
|
||||
ty::ty_ptr(ref mt) => T_ptr(type_of(cx, mt.ty)),
|
||||
ty::ty_rptr(_, ref mt) => T_ptr(type_of(cx, mt.ty)),
|
||||
ty::ty_ptr(ref mt) => type_of(cx, mt.ty).ptr_to(),
|
||||
ty::ty_rptr(_, ref mt) => type_of(cx, mt.ty).ptr_to(),
|
||||
|
||||
ty::ty_evec(ref mt, ty::vstore_slice(_)) => {
|
||||
let p_ty = T_ptr(type_of(cx, mt.ty));
|
||||
let u_ty = T_uint_ty(cx, ast::ty_u);
|
||||
T_struct([p_ty, u_ty], false)
|
||||
let p_ty = type_of(cx, mt.ty).ptr_to();
|
||||
let u_ty = Type::uint_from_ty(cx, ast::ty_u);
|
||||
Type::struct_([p_ty, u_ty], false)
|
||||
}
|
||||
|
||||
ty::ty_estr(ty::vstore_slice(_)) => {
|
||||
T_struct([T_ptr(T_i8()), T_uint_ty(cx, ast::ty_u)], false)
|
||||
// This means we get a nicer name in the output
|
||||
cx.tn.find_type("str_slice").get()
|
||||
}
|
||||
|
||||
ty::ty_estr(ty::vstore_fixed(n)) => {
|
||||
T_array(T_i8(), n + 1u /* +1 for trailing null */)
|
||||
Type::array(&Type::i8(), (n + 1u) as u64)
|
||||
}
|
||||
|
||||
ty::ty_evec(ref mt, ty::vstore_fixed(n)) => {
|
||||
T_array(type_of(cx, mt.ty), n)
|
||||
Type::array(&type_of(cx, mt.ty), n as u64)
|
||||
}
|
||||
|
||||
ty::ty_bare_fn(_) => T_ptr(type_of_fn_from_ty(cx, t)),
|
||||
ty::ty_bare_fn(_) => type_of_fn_from_ty(cx, t).ptr_to(),
|
||||
ty::ty_closure(_) => {
|
||||
let ty = type_of_fn_from_ty(cx, t);
|
||||
T_fn_pair(cx, ty)
|
||||
Type::func_pair(cx, &ty)
|
||||
}
|
||||
ty::ty_trait(_, _, store, _) => T_opaque_trait(cx, store),
|
||||
ty::ty_type => T_ptr(cx.tydesc_type),
|
||||
ty::ty_trait(_, _, store, _) => Type::opaque_trait(cx, store),
|
||||
ty::ty_type => cx.tydesc_type.ptr_to(),
|
||||
ty::ty_tup(*) => {
|
||||
let repr = adt::represent_type(cx, t);
|
||||
T_struct(adt::fields_of(cx, repr), false)
|
||||
Type::struct_(adt::fields_of(cx, repr), false)
|
||||
}
|
||||
ty::ty_opaque_closure_ptr(_) => T_opaque_box_ptr(cx),
|
||||
ty::ty_opaque_closure_ptr(_) => Type::opaque_box(cx).ptr_to(),
|
||||
ty::ty_struct(did, ref substs) => {
|
||||
if ty::type_is_simd(cx.tcx, t) {
|
||||
let et = ty::simd_type(cx.tcx, t);
|
||||
let n = ty::simd_size(cx.tcx, t);
|
||||
T_vector(type_of(cx, et), n)
|
||||
} else {
|
||||
// Only create the named struct, but don't fill it in. We fill it
|
||||
// in *after* placing it into the type cache. This prevents
|
||||
// infinite recursion with recursive struct types.
|
||||
T_named_struct(llvm_type_name(cx,
|
||||
a_struct,
|
||||
did,
|
||||
substs.tps))
|
||||
}
|
||||
if ty::type_is_simd(cx.tcx, t) {
|
||||
let et = ty::simd_type(cx.tcx, t);
|
||||
let n = ty::simd_size(cx.tcx, t);
|
||||
Type::vector(&type_of(cx, et), n as u64)
|
||||
} else {
|
||||
// Only create the named struct, but don't fill it in. We fill it
|
||||
// in *after* placing it into the type cache. This prevents
|
||||
// infinite recursion with recursive struct types.
|
||||
Type::named_struct(llvm_type_name(cx, a_struct, did, substs.tps))
|
||||
}
|
||||
}
|
||||
ty::ty_self(*) => cx.tcx.sess.unimpl("type_of: ty_self"),
|
||||
ty::ty_infer(*) => cx.tcx.sess.bug("type_of with ty_infer"),
|
||||
@ -310,16 +302,14 @@ pub fn type_of(cx: &mut CrateContext, t: ty::t) -> TypeRef {
|
||||
match ty::get(t).sty {
|
||||
ty::ty_enum(*) => {
|
||||
let repr = adt::represent_type(cx, t);
|
||||
common::set_struct_body(llty, adt::fields_of(cx, repr),
|
||||
false);
|
||||
llty.set_struct_body(adt::fields_of(cx, repr), false);
|
||||
}
|
||||
|
||||
ty::ty_struct(did, _) => {
|
||||
if !ty::type_is_simd(cx.tcx, t) {
|
||||
let repr = adt::represent_type(cx, t);
|
||||
let packed = ty::lookup_packed(cx.tcx, did);
|
||||
common::set_struct_body(llty, adt::fields_of(cx, repr),
|
||||
packed);
|
||||
llty.set_struct_body(adt::fields_of(cx, repr), packed);
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
@ -336,33 +326,18 @@ pub fn llvm_type_name(cx: &CrateContext,
|
||||
did: ast::def_id,
|
||||
tps: &[ty::t]) -> ~str {
|
||||
let name = match what {
|
||||
a_struct => { "~struct" }
|
||||
an_enum => { "~enum" }
|
||||
a_struct => { "struct" }
|
||||
an_enum => { "enum" }
|
||||
};
|
||||
return fmt!(
|
||||
"%s %s[#%d]",
|
||||
name,
|
||||
ppaux::parameterized(
|
||||
cx.tcx,
|
||||
ty::item_path_str(cx.tcx, did),
|
||||
None,
|
||||
tps),
|
||||
did.crate
|
||||
);
|
||||
let tstr = ppaux::parameterized(cx.tcx, ty::item_path_str(cx.tcx, did), None, tps);
|
||||
if did.crate == 0 {
|
||||
fmt!("%s.%s", name, tstr)
|
||||
} else {
|
||||
fmt!("%s.%s[#%d]", name, tstr, did.crate)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_of_dtor(ccx: &mut CrateContext, self_ty: ty::t) -> TypeRef {
|
||||
T_fn([T_ptr(type_of(ccx, self_ty))] /* self */, T_void())
|
||||
}
|
||||
|
||||
pub fn type_of_rooted(ccx: &mut CrateContext, t: ty::t) -> TypeRef {
|
||||
let addrspace = base::get_tydesc(ccx, t).addrspace;
|
||||
debug!("type_of_rooted %s in addrspace %u",
|
||||
ppaux::ty_to_str(ccx.tcx, t), addrspace as uint);
|
||||
return T_root(type_of(ccx, t), addrspace);
|
||||
}
|
||||
|
||||
pub fn type_of_glue_fn(ccx: &CrateContext) -> TypeRef {
|
||||
let tydescpp = T_ptr(T_ptr(ccx.tydesc_type));
|
||||
return T_fn([T_ptr(T_nil()), tydescpp, T_ptr(T_i8())], T_void());
|
||||
pub fn type_of_dtor(ccx: &mut CrateContext, self_ty: ty::t) -> Type {
|
||||
let self_ty = type_of(ccx, self_ty).ptr_to();
|
||||
Type::func([self_ty], &Type::void())
|
||||
}
|
||||
|
@ -117,46 +117,43 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
|
||||
_,
|
||||
_) => {
|
||||
if abi.is_intrinsic() {
|
||||
let flags = match cx.ccx.sess.str_of(i.ident).as_slice() {
|
||||
"size_of" | "pref_align_of" | "min_align_of" |
|
||||
"uninit" | "init" | "transmute" | "move_val" |
|
||||
"move_val_init" => use_repr,
|
||||
let nm = cx.ccx.sess.str_of(i.ident);
|
||||
let name = nm.as_slice();
|
||||
let flags = if name.starts_with("atomic_") {
|
||||
0
|
||||
} else {
|
||||
match name {
|
||||
"size_of" | "pref_align_of" | "min_align_of" |
|
||||
"uninit" | "init" | "transmute" | "move_val" |
|
||||
"move_val_init" => use_repr,
|
||||
|
||||
"get_tydesc" | "needs_drop" => use_tydesc,
|
||||
"get_tydesc" | "needs_drop" => use_tydesc,
|
||||
|
||||
"atomic_cxchg" | "atomic_cxchg_acq"|
|
||||
"atomic_cxchg_rel"| "atomic_load" |
|
||||
"atomic_load_acq" | "atomic_store" |
|
||||
"atomic_store_rel"| "atomic_xchg" |
|
||||
"atomic_xadd" | "atomic_xsub" |
|
||||
"atomic_xchg_acq" | "atomic_xadd_acq" |
|
||||
"atomic_xsub_acq" | "atomic_xchg_rel" |
|
||||
"atomic_xadd_rel" | "atomic_xsub_rel" => 0,
|
||||
"visit_tydesc" | "forget" | "frame_address" |
|
||||
"morestack_addr" => 0,
|
||||
|
||||
"visit_tydesc" | "forget" | "frame_address" |
|
||||
"morestack_addr" => 0,
|
||||
"memcpy32" | "memcpy64" | "memmove32" | "memmove64" |
|
||||
"memset32" | "memset64" => use_repr,
|
||||
|
||||
"memcpy32" | "memcpy64" | "memmove32" | "memmove64" |
|
||||
"memset32" | "memset64" => use_repr,
|
||||
"sqrtf32" | "sqrtf64" | "powif32" | "powif64" |
|
||||
"sinf32" | "sinf64" | "cosf32" | "cosf64" |
|
||||
"powf32" | "powf64" | "expf32" | "expf64" |
|
||||
"exp2f32" | "exp2f64" | "logf32" | "logf64" |
|
||||
"log10f32"| "log10f64"| "log2f32" | "log2f64" |
|
||||
"fmaf32" | "fmaf64" | "fabsf32" | "fabsf64" |
|
||||
"floorf32"| "floorf64"| "ceilf32" | "ceilf64" |
|
||||
"truncf32"| "truncf64" => 0,
|
||||
|
||||
"sqrtf32" | "sqrtf64" | "powif32" | "powif64" |
|
||||
"sinf32" | "sinf64" | "cosf32" | "cosf64" |
|
||||
"powf32" | "powf64" | "expf32" | "expf64" |
|
||||
"exp2f32" | "exp2f64" | "logf32" | "logf64" |
|
||||
"log10f32"| "log10f64"| "log2f32" | "log2f64" |
|
||||
"fmaf32" | "fmaf64" | "fabsf32" | "fabsf64" |
|
||||
"floorf32"| "floorf64"| "ceilf32" | "ceilf64" |
|
||||
"truncf32"| "truncf64" => 0,
|
||||
"ctpop8" | "ctpop16" | "ctpop32" | "ctpop64" => 0,
|
||||
|
||||
"ctpop8" | "ctpop16" | "ctpop32" | "ctpop64" => 0,
|
||||
"ctlz8" | "ctlz16" | "ctlz32" | "ctlz64" => 0,
|
||||
"cttz8" | "cttz16" | "cttz32" | "cttz64" => 0,
|
||||
|
||||
"ctlz8" | "ctlz16" | "ctlz32" | "ctlz64" => 0,
|
||||
"cttz8" | "cttz16" | "cttz32" | "cttz64" => 0,
|
||||
"bswap16" | "bswap32" | "bswap64" => 0,
|
||||
|
||||
"bswap16" | "bswap32" | "bswap64" => 0,
|
||||
|
||||
// would be cool to make these an enum instead of strings!
|
||||
_ => fail!("unknown intrinsic in type_use")
|
||||
// would be cool to make these an enum instead of strings!
|
||||
_ => fail!("unknown intrinsic in type_use")
|
||||
}
|
||||
};
|
||||
for uint::range(0u, n_tps) |n| { cx.uses[n] |= flags;}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ use middle::ty;
|
||||
|
||||
pub fn make_free_glue(bcx: block, vptrptr: ValueRef, box_ty: ty::t)
|
||||
-> block {
|
||||
let _icx = bcx.insn_ctxt("uniq::make_free_glue");
|
||||
let _icx = push_ctxt("uniq::make_free_glue");
|
||||
let box_datum = immediate_rvalue(Load(bcx, vptrptr), box_ty);
|
||||
|
||||
let not_null = IsNotNull(bcx, box_datum.val);
|
||||
@ -38,7 +38,7 @@ pub fn make_free_glue(bcx: block, vptrptr: ValueRef, box_ty: ty::t)
|
||||
}
|
||||
|
||||
pub fn duplicate(bcx: block, src_box: ValueRef, src_ty: ty::t) -> Result {
|
||||
let _icx = bcx.insn_ctxt("uniq::duplicate");
|
||||
let _icx = push_ctxt("uniq::duplicate");
|
||||
|
||||
// Load the body of the source (*src)
|
||||
let src_datum = immediate_rvalue(src_box, src_ty);
|
||||
|
@ -28,6 +28,8 @@ use middle::ty;
|
||||
use syntax::codemap::span;
|
||||
use syntax::ast;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
pub fn root_and_write_guard(datum: &Datum,
|
||||
mut bcx: block,
|
||||
span: span,
|
||||
@ -64,20 +66,15 @@ pub fn return_to_mut(mut bcx: block,
|
||||
debug!("write_guard::return_to_mut(root_key=%?, %s, %s, %s)",
|
||||
root_key,
|
||||
bcx.to_str(),
|
||||
val_str(bcx.ccx().tn, frozen_val_ref),
|
||||
val_str(bcx.ccx().tn, bits_val_ref));
|
||||
bcx.val_to_str(frozen_val_ref),
|
||||
bcx.val_to_str(bits_val_ref));
|
||||
|
||||
let box_ptr =
|
||||
Load(bcx, PointerCast(bcx,
|
||||
frozen_val_ref,
|
||||
T_ptr(T_ptr(T_i8()))));
|
||||
let box_ptr = Load(bcx, PointerCast(bcx, frozen_val_ref, Type::i8p().ptr_to()));
|
||||
|
||||
let bits_val =
|
||||
Load(bcx, bits_val_ref);
|
||||
let bits_val = Load(bcx, bits_val_ref);
|
||||
|
||||
if bcx.tcx().sess.debug_borrows() {
|
||||
bcx = callee::trans_lang_call(
|
||||
bcx,
|
||||
bcx = callee::trans_lang_call( bcx,
|
||||
bcx.tcx().lang_items.unrecord_borrow_fn(),
|
||||
[
|
||||
box_ptr,
|
||||
@ -146,10 +143,7 @@ fn root(datum: &Datum,
|
||||
DynaMut => bcx.tcx().lang_items.borrow_as_mut_fn(),
|
||||
};
|
||||
|
||||
let box_ptr = Load(bcx,
|
||||
PointerCast(bcx,
|
||||
scratch.val,
|
||||
T_ptr(T_ptr(T_i8()))));
|
||||
let box_ptr = Load(bcx, PointerCast(bcx, scratch.val, Type::i8p().ptr_to()));
|
||||
|
||||
bcx = callee::trans_lang_call(
|
||||
bcx,
|
||||
@ -194,6 +188,6 @@ fn perform_write_guard(datum: &Datum,
|
||||
callee::trans_lang_call(
|
||||
bcx,
|
||||
bcx.tcx().lang_items.check_not_borrowed_fn(),
|
||||
[PointerCast(bcx, llval, T_ptr(T_i8())), filename, line],
|
||||
[PointerCast(bcx, llval, Type::i8p()), filename, line],
|
||||
expr::Ignore)
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ use middle::ty;
|
||||
use middle::subst::Subst;
|
||||
use middle::typeck;
|
||||
use middle;
|
||||
use util::ppaux::{note_and_explain_region, bound_region_to_str};
|
||||
use util::ppaux::{note_and_explain_region, bound_region_to_str, bound_region_ptr_to_str};
|
||||
use util::ppaux::{trait_store_to_str, ty_to_str, vstore_to_str};
|
||||
use util::ppaux::{Repr, UserString};
|
||||
use util::common::{indenter};
|
||||
@ -3531,12 +3531,12 @@ pub fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
|
||||
terr_regions_insufficiently_polymorphic(br, _) => {
|
||||
fmt!("expected bound lifetime parameter %s, \
|
||||
but found concrete lifetime",
|
||||
bound_region_to_str(cx, br))
|
||||
bound_region_ptr_to_str(cx, br))
|
||||
}
|
||||
terr_regions_overly_polymorphic(br, _) => {
|
||||
fmt!("expected concrete lifetime, \
|
||||
but found bound lifetime parameter %s",
|
||||
bound_region_to_str(cx, br))
|
||||
bound_region_ptr_to_str(cx, br))
|
||||
}
|
||||
terr_vstores_differ(k, ref values) => {
|
||||
fmt!("%s storage differs: expected %s but found %s",
|
||||
|
@ -107,7 +107,7 @@ use middle::typeck::{isr_alist, lookup_def_ccx};
|
||||
use middle::typeck::no_params;
|
||||
use middle::typeck::{require_same_types, method_map, vtable_map};
|
||||
use util::common::{block_query, indenter, loop_query};
|
||||
use util::ppaux::{bound_region_to_str};
|
||||
use util::ppaux::{bound_region_to_str,bound_region_ptr_to_str};
|
||||
use util::ppaux;
|
||||
|
||||
|
||||
@ -680,7 +680,7 @@ impl FnCtxt {
|
||||
} else {
|
||||
result::Err(RegionError {
|
||||
msg: fmt!("named region `%s` not in scope here",
|
||||
bound_region_to_str(self.tcx(), br)),
|
||||
bound_region_ptr_to_str(self.tcx(), br)),
|
||||
replacement: self.infcx().next_region_var_nb(span)
|
||||
})
|
||||
}
|
||||
@ -3434,252 +3434,268 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
|
||||
}
|
||||
|
||||
let tcx = ccx.tcx;
|
||||
let str = ccx.tcx.sess.str_of(it.ident);
|
||||
let (n_tps, inputs, output) = match str.as_slice() {
|
||||
"size_of" |
|
||||
"pref_align_of" | "min_align_of" => (1u, ~[], ty::mk_uint()),
|
||||
"init" => (1u, ~[], param(ccx, 0u)),
|
||||
"uninit" => (1u, ~[], param(ccx, 0u)),
|
||||
"forget" => (1u, ~[ param(ccx, 0) ], ty::mk_nil()),
|
||||
"transmute" => (2, ~[ param(ccx, 0) ], param(ccx, 1)),
|
||||
"move_val" | "move_val_init" => {
|
||||
(1u,
|
||||
~[
|
||||
ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), param(ccx, 0)),
|
||||
param(ccx, 0u)
|
||||
],
|
||||
ty::mk_nil())
|
||||
}
|
||||
"needs_drop" => (1u, ~[], ty::mk_bool()),
|
||||
let nm = ccx.tcx.sess.str_of(it.ident);
|
||||
let name = nm.as_slice();
|
||||
let (n_tps, inputs, output) = if name.starts_with("atomic_") {
|
||||
let split : ~[&str] = name.split_iter('_').collect();
|
||||
assert!(split.len() >= 2, "Atomic intrinsic not correct format");
|
||||
|
||||
"atomic_cxchg" | "atomic_cxchg_acq"| "atomic_cxchg_rel" => {
|
||||
(0,
|
||||
~[
|
||||
ty::mk_mut_rptr(tcx,
|
||||
ty::re_bound(ty::br_anon(0)),
|
||||
ty::mk_int()),
|
||||
ty::mk_int(),
|
||||
ty::mk_int()
|
||||
],
|
||||
ty::mk_int())
|
||||
}
|
||||
"atomic_load" | "atomic_load_acq" => {
|
||||
(0,
|
||||
~[
|
||||
ty::mk_imm_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int())
|
||||
],
|
||||
ty::mk_int())
|
||||
}
|
||||
"atomic_store" | "atomic_store_rel" => {
|
||||
(0,
|
||||
~[
|
||||
ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()),
|
||||
ty::mk_int()
|
||||
],
|
||||
ty::mk_nil())
|
||||
}
|
||||
"atomic_xchg" | "atomic_xadd" | "atomic_xsub" |
|
||||
"atomic_xchg_acq" | "atomic_xadd_acq" | "atomic_xsub_acq" |
|
||||
"atomic_xchg_rel" | "atomic_xadd_rel" | "atomic_xsub_rel" => {
|
||||
(0,
|
||||
~[
|
||||
ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()),
|
||||
ty::mk_int()
|
||||
],
|
||||
ty::mk_int())
|
||||
//We only care about the operation here
|
||||
match split[1] {
|
||||
"cxchg" => (0, ~[ty::mk_mut_rptr(tcx,
|
||||
ty::re_bound(ty::br_anon(0)),
|
||||
ty::mk_int()),
|
||||
ty::mk_int(),
|
||||
ty::mk_int()
|
||||
], ty::mk_int()),
|
||||
"load" => (0,
|
||||
~[
|
||||
ty::mk_imm_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int())
|
||||
],
|
||||
ty::mk_int()),
|
||||
"store" => (0,
|
||||
~[
|
||||
ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()),
|
||||
ty::mk_int()
|
||||
],
|
||||
ty::mk_nil()),
|
||||
|
||||
"xchg" | "xadd" | "xsub" | "and" | "nand" | "or" | "xor" | "max" |
|
||||
"min" | "umax" | "umin" => {
|
||||
(0, ~[ty::mk_mut_rptr(tcx,
|
||||
ty::re_bound(ty::br_anon(0)),
|
||||
ty::mk_int()), ty::mk_int() ], ty::mk_int())
|
||||
}
|
||||
|
||||
op => {
|
||||
tcx.sess.span_err(it.span,
|
||||
fmt!("unrecognized atomic operation function: `%s`",
|
||||
op));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
"get_tydesc" => {
|
||||
// FIXME (#3730): return *intrinsic::tydesc, not *()
|
||||
(1u, ~[], ty::mk_nil_ptr(ccx.tcx))
|
||||
}
|
||||
"visit_tydesc" => {
|
||||
let tydesc_name = special_idents::tydesc;
|
||||
assert!(tcx.intrinsic_defs.contains_key(&tydesc_name));
|
||||
let (_, tydesc_ty) = tcx.intrinsic_defs.get_copy(&tydesc_name);
|
||||
let (_, visitor_object_ty) = ty::visitor_object_ty(tcx);
|
||||
let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
|
||||
ty: tydesc_ty,
|
||||
mutbl: ast::m_imm
|
||||
});
|
||||
(0, ~[ td_ptr, visitor_object_ty ], ty::mk_nil())
|
||||
}
|
||||
"frame_address" => {
|
||||
let fty = ty::mk_closure(ccx.tcx, ty::ClosureTy {
|
||||
purity: ast::impure_fn,
|
||||
sigil: ast::BorrowedSigil,
|
||||
onceness: ast::Once,
|
||||
region: ty::re_bound(ty::br_anon(0)),
|
||||
bounds: ty::EmptyBuiltinBounds(),
|
||||
sig: ty::FnSig {
|
||||
bound_lifetime_names: opt_vec::Empty,
|
||||
inputs: ~[ty::mk_imm_ptr(ccx.tcx, ty::mk_mach_uint(ast::ty_u8))],
|
||||
output: ty::mk_nil()
|
||||
}
|
||||
});
|
||||
(0u, ~[fty], ty::mk_nil())
|
||||
}
|
||||
"morestack_addr" => {
|
||||
(0u, ~[], ty::mk_nil_ptr(ccx.tcx))
|
||||
}
|
||||
"memcpy32" => {
|
||||
(1,
|
||||
~[
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_mutbl
|
||||
}),
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
} else {
|
||||
match name {
|
||||
"size_of" |
|
||||
"pref_align_of" | "min_align_of" => (1u, ~[], ty::mk_uint()),
|
||||
"init" => (1u, ~[], param(ccx, 0u)),
|
||||
"uninit" => (1u, ~[], param(ccx, 0u)),
|
||||
"forget" => (1u, ~[ param(ccx, 0) ], ty::mk_nil()),
|
||||
"transmute" => (2, ~[ param(ccx, 0) ], param(ccx, 1)),
|
||||
"move_val" | "move_val_init" => {
|
||||
(1u,
|
||||
~[
|
||||
ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), param(ccx, 0)),
|
||||
param(ccx, 0u)
|
||||
],
|
||||
ty::mk_nil())
|
||||
}
|
||||
"needs_drop" => (1u, ~[], ty::mk_bool()),
|
||||
|
||||
"atomic_xchg" | "atomic_xadd" | "atomic_xsub" |
|
||||
"atomic_xchg_acq" | "atomic_xadd_acq" | "atomic_xsub_acq" |
|
||||
"atomic_xchg_rel" | "atomic_xadd_rel" | "atomic_xsub_rel" => {
|
||||
(0,
|
||||
~[
|
||||
ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()),
|
||||
ty::mk_int()
|
||||
],
|
||||
ty::mk_int())
|
||||
}
|
||||
|
||||
"get_tydesc" => {
|
||||
// FIXME (#3730): return *intrinsic::tydesc, not *()
|
||||
(1u, ~[], ty::mk_nil_ptr(ccx.tcx))
|
||||
}
|
||||
"visit_tydesc" => {
|
||||
let tydesc_name = special_idents::tydesc;
|
||||
assert!(tcx.intrinsic_defs.contains_key(&tydesc_name));
|
||||
let (_, tydesc_ty) = tcx.intrinsic_defs.get_copy(&tydesc_name);
|
||||
let (_, visitor_object_ty) = ty::visitor_object_ty(tcx);
|
||||
let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
|
||||
ty: tydesc_ty,
|
||||
mutbl: ast::m_imm
|
||||
}),
|
||||
ty::mk_u32()
|
||||
],
|
||||
ty::mk_nil())
|
||||
}
|
||||
"memcpy64" => {
|
||||
(1,
|
||||
~[
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_mutbl
|
||||
}),
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_imm
|
||||
}),
|
||||
ty::mk_u64()
|
||||
],
|
||||
ty::mk_nil())
|
||||
}
|
||||
"memmove32" => {
|
||||
(1,
|
||||
~[
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_mutbl
|
||||
}),
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_imm
|
||||
}),
|
||||
ty::mk_u32()
|
||||
],
|
||||
ty::mk_nil())
|
||||
}
|
||||
"memmove64" => {
|
||||
(1,
|
||||
~[
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_mutbl
|
||||
}),
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_imm
|
||||
}),
|
||||
ty::mk_u64()
|
||||
],
|
||||
ty::mk_nil())
|
||||
}
|
||||
"memset32" => {
|
||||
(1,
|
||||
~[
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_mutbl
|
||||
}),
|
||||
ty::mk_u8(),
|
||||
ty::mk_u32()
|
||||
],
|
||||
ty::mk_nil())
|
||||
}
|
||||
"memset64" => {
|
||||
(1,
|
||||
~[
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_mutbl
|
||||
}),
|
||||
ty::mk_u8(),
|
||||
ty::mk_u64()
|
||||
],
|
||||
ty::mk_nil())
|
||||
}
|
||||
"sqrtf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"sqrtf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"powif32" => {
|
||||
(0,
|
||||
~[ ty::mk_f32(), ty::mk_i32() ],
|
||||
ty::mk_f32())
|
||||
}
|
||||
"powif64" => {
|
||||
(0,
|
||||
~[ ty::mk_f64(), ty::mk_i32() ],
|
||||
ty::mk_f64())
|
||||
}
|
||||
"sinf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"sinf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"cosf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"cosf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"powf32" => {
|
||||
(0,
|
||||
~[ ty::mk_f32(), ty::mk_f32() ],
|
||||
ty::mk_f32())
|
||||
}
|
||||
"powf64" => {
|
||||
(0,
|
||||
~[ ty::mk_f64(), ty::mk_f64() ],
|
||||
ty::mk_f64())
|
||||
}
|
||||
"expf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"expf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"exp2f32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"exp2f64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"logf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"logf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"log10f32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"log10f64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"log2f32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"log2f64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"fmaf32" => {
|
||||
(0,
|
||||
~[ ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ],
|
||||
ty::mk_f32())
|
||||
}
|
||||
"fmaf64" => {
|
||||
(0,
|
||||
~[ ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ],
|
||||
ty::mk_f64())
|
||||
}
|
||||
"fabsf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"fabsf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"floorf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"floorf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"ceilf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"ceilf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"truncf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"truncf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"ctpop8" => (0, ~[ ty::mk_i8() ], ty::mk_i8()),
|
||||
"ctpop16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()),
|
||||
"ctpop32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()),
|
||||
"ctpop64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()),
|
||||
"ctlz8" => (0, ~[ ty::mk_i8() ], ty::mk_i8()),
|
||||
"ctlz16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()),
|
||||
"ctlz32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()),
|
||||
"ctlz64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()),
|
||||
"cttz8" => (0, ~[ ty::mk_i8() ], ty::mk_i8()),
|
||||
"cttz16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()),
|
||||
"cttz32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()),
|
||||
"cttz64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()),
|
||||
"bswap16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()),
|
||||
"bswap32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()),
|
||||
"bswap64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()),
|
||||
ref other => {
|
||||
tcx.sess.span_err(it.span,
|
||||
fmt!("unrecognized intrinsic function: `%s`",
|
||||
*other));
|
||||
return;
|
||||
});
|
||||
(0, ~[ td_ptr, visitor_object_ty ], ty::mk_nil())
|
||||
}
|
||||
"frame_address" => {
|
||||
let fty = ty::mk_closure(ccx.tcx, ty::ClosureTy {
|
||||
purity: ast::impure_fn,
|
||||
sigil: ast::BorrowedSigil,
|
||||
onceness: ast::Once,
|
||||
region: ty::re_bound(ty::br_anon(0)),
|
||||
bounds: ty::EmptyBuiltinBounds(),
|
||||
sig: ty::FnSig {
|
||||
bound_lifetime_names: opt_vec::Empty,
|
||||
inputs: ~[ty::mk_imm_ptr(ccx.tcx, ty::mk_mach_uint(ast::ty_u8))],
|
||||
output: ty::mk_nil()
|
||||
}
|
||||
});
|
||||
(0u, ~[fty], ty::mk_nil())
|
||||
}
|
||||
"morestack_addr" => {
|
||||
(0u, ~[], ty::mk_nil_ptr(ccx.tcx))
|
||||
}
|
||||
"memcpy32" => {
|
||||
(1,
|
||||
~[
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_mutbl
|
||||
}),
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_imm
|
||||
}),
|
||||
ty::mk_u32()
|
||||
],
|
||||
ty::mk_nil())
|
||||
}
|
||||
"memcpy64" => {
|
||||
(1,
|
||||
~[
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_mutbl
|
||||
}),
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_imm
|
||||
}),
|
||||
ty::mk_u64()
|
||||
],
|
||||
ty::mk_nil())
|
||||
}
|
||||
"memmove32" => {
|
||||
(1,
|
||||
~[
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_mutbl
|
||||
}),
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_imm
|
||||
}),
|
||||
ty::mk_u32()
|
||||
],
|
||||
ty::mk_nil())
|
||||
}
|
||||
"memmove64" => {
|
||||
(1,
|
||||
~[
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_mutbl
|
||||
}),
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_imm
|
||||
}),
|
||||
ty::mk_u64()
|
||||
],
|
||||
ty::mk_nil())
|
||||
}
|
||||
"memset32" => {
|
||||
(1,
|
||||
~[
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_mutbl
|
||||
}),
|
||||
ty::mk_u8(),
|
||||
ty::mk_u32()
|
||||
],
|
||||
ty::mk_nil())
|
||||
}
|
||||
"memset64" => {
|
||||
(1,
|
||||
~[
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_mutbl
|
||||
}),
|
||||
ty::mk_u8(),
|
||||
ty::mk_u64()
|
||||
],
|
||||
ty::mk_nil())
|
||||
}
|
||||
"sqrtf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"sqrtf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"powif32" => {
|
||||
(0,
|
||||
~[ ty::mk_f32(), ty::mk_i32() ],
|
||||
ty::mk_f32())
|
||||
}
|
||||
"powif64" => {
|
||||
(0,
|
||||
~[ ty::mk_f64(), ty::mk_i32() ],
|
||||
ty::mk_f64())
|
||||
}
|
||||
"sinf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"sinf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"cosf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"cosf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"powf32" => {
|
||||
(0,
|
||||
~[ ty::mk_f32(), ty::mk_f32() ],
|
||||
ty::mk_f32())
|
||||
}
|
||||
"powf64" => {
|
||||
(0,
|
||||
~[ ty::mk_f64(), ty::mk_f64() ],
|
||||
ty::mk_f64())
|
||||
}
|
||||
"expf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"expf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"exp2f32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"exp2f64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"logf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"logf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"log10f32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"log10f64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"log2f32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"log2f64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"fmaf32" => {
|
||||
(0,
|
||||
~[ ty::mk_f32(), ty::mk_f32(), ty::mk_f32() ],
|
||||
ty::mk_f32())
|
||||
}
|
||||
"fmaf64" => {
|
||||
(0,
|
||||
~[ ty::mk_f64(), ty::mk_f64(), ty::mk_f64() ],
|
||||
ty::mk_f64())
|
||||
}
|
||||
"fabsf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"fabsf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"floorf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"floorf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"ceilf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"ceilf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"truncf32" => (0, ~[ ty::mk_f32() ], ty::mk_f32()),
|
||||
"truncf64" => (0, ~[ ty::mk_f64() ], ty::mk_f64()),
|
||||
"ctpop8" => (0, ~[ ty::mk_i8() ], ty::mk_i8()),
|
||||
"ctpop16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()),
|
||||
"ctpop32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()),
|
||||
"ctpop64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()),
|
||||
"ctlz8" => (0, ~[ ty::mk_i8() ], ty::mk_i8()),
|
||||
"ctlz16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()),
|
||||
"ctlz32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()),
|
||||
"ctlz64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()),
|
||||
"cttz8" => (0, ~[ ty::mk_i8() ], ty::mk_i8()),
|
||||
"cttz16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()),
|
||||
"cttz32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()),
|
||||
"cttz64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()),
|
||||
"bswap16" => (0, ~[ ty::mk_i16() ], ty::mk_i16()),
|
||||
"bswap32" => (0, ~[ ty::mk_i32() ], ty::mk_i32()),
|
||||
"bswap64" => (0, ~[ ty::mk_i64() ], ty::mk_i64()),
|
||||
ref other => {
|
||||
tcx.sess.span_err(it.span,
|
||||
fmt!("unrecognized intrinsic function: `%s`",
|
||||
*other));
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
|
||||
|
@ -690,13 +690,13 @@ fn constrain_regions_in_type(
|
||||
let tcx = rcx.fcx.ccx.tcx;
|
||||
|
||||
debug!("constrain_regions_in_type(minimum_lifetime=%s, ty=%s)",
|
||||
region_to_str(tcx, minimum_lifetime),
|
||||
region_to_str(tcx, "", false, minimum_lifetime),
|
||||
ty_to_str(tcx, ty));
|
||||
|
||||
do relate_nested_regions(tcx, Some(minimum_lifetime), ty) |r_sub, r_sup| {
|
||||
debug!("relate(r_sub=%s, r_sup=%s)",
|
||||
region_to_str(tcx, r_sub),
|
||||
region_to_str(tcx, r_sup));
|
||||
region_to_str(tcx, "", false, r_sub),
|
||||
region_to_str(tcx, "", false, r_sup));
|
||||
|
||||
if r_sup.is_bound() || r_sub.is_bound() {
|
||||
// a bound region is one which appears inside an fn type.
|
||||
|
@ -149,7 +149,7 @@ pub fn replace_bound_regions_in_fn_sig(
|
||||
tcx.sess.bug(
|
||||
fmt!("Bound region not found in \
|
||||
in_scope_regions list: %s",
|
||||
region_to_str(tcx, r)));
|
||||
region_to_str(tcx, "", false, r)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -821,7 +821,7 @@ impl InferCtxt {
|
||||
// debug message.
|
||||
let rvar = self.next_region_var_nb(span);
|
||||
debug!("Bound region %s maps to %?",
|
||||
bound_region_to_str(self.tcx, br),
|
||||
bound_region_to_str(self.tcx, "", false, br),
|
||||
rvar);
|
||||
rvar
|
||||
});
|
||||
|
@ -179,7 +179,7 @@ impl Combine for Sub {
|
||||
None, b) |br| {
|
||||
let skol = self.infcx.region_vars.new_skolemized(br);
|
||||
debug!("Bound region %s skolemized to %?",
|
||||
bound_region_to_str(self.infcx.tcx, br),
|
||||
bound_region_to_str(self.infcx.tcx, "", false, br),
|
||||
skol);
|
||||
skol
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ pub fn explain_region_and_span(cx: ctxt, region: ty::Region)
|
||||
idx + 1),
|
||||
br_fresh(_) => fmt!("an anonymous lifetime defined on"),
|
||||
_ => fmt!("the lifetime %s as defined on",
|
||||
bound_region_to_str(cx, fr.bound_region))
|
||||
bound_region_ptr_to_str(cx, fr.bound_region))
|
||||
};
|
||||
|
||||
match cx.items.find(&fr.scope_id) {
|
||||
@ -147,22 +147,23 @@ pub fn explain_region_and_span(cx: ctxt, region: ty::Region)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bound_region_to_str(cx: ctxt, br: bound_region) -> ~str {
|
||||
bound_region_to_str_space(cx, "&", br)
|
||||
pub fn bound_region_ptr_to_str(cx: ctxt, br: bound_region) -> ~str {
|
||||
bound_region_to_str(cx, "&", true, br)
|
||||
}
|
||||
|
||||
pub fn bound_region_to_str_space(cx: ctxt,
|
||||
prefix: &str,
|
||||
br: bound_region)
|
||||
-> ~str {
|
||||
if cx.sess.verbose() { return fmt!("%s%? ", prefix, br); }
|
||||
pub fn bound_region_to_str(cx: ctxt,
|
||||
prefix: &str, space: bool,
|
||||
br: bound_region) -> ~str {
|
||||
let space_str = if space { " " } else { "" };
|
||||
|
||||
if cx.sess.verbose() { return fmt!("%s%?%s", prefix, br, space_str); }
|
||||
|
||||
match br {
|
||||
br_named(id) => fmt!("%s'%s ", prefix, cx.sess.str_of(id)),
|
||||
br_self => fmt!("%s'self ", prefix),
|
||||
br_named(id) => fmt!("%s'%s%s", prefix, cx.sess.str_of(id), space_str),
|
||||
br_self => fmt!("%s'self%s", prefix, space_str),
|
||||
br_anon(_) => prefix.to_str(),
|
||||
br_fresh(_) => prefix.to_str(),
|
||||
br_cap_avoid(_, br) => bound_region_to_str_space(cx, prefix, *br)
|
||||
br_cap_avoid(_, br) => bound_region_to_str(cx, prefix, space, *br)
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,13 +209,15 @@ pub fn re_scope_id_to_str(cx: ctxt, node_id: ast::node_id) -> ~str {
|
||||
// In general, if you are giving a region error message,
|
||||
// you should use `explain_region()` or, better yet,
|
||||
// `note_and_explain_region()`
|
||||
pub fn region_to_str(cx: ctxt, region: Region) -> ~str {
|
||||
region_to_str_space(cx, "&", region)
|
||||
pub fn region_ptr_to_str(cx: ctxt, region: Region) -> ~str {
|
||||
region_to_str(cx, "&", true, region)
|
||||
}
|
||||
|
||||
pub fn region_to_str_space(cx: ctxt, prefix: &str, region: Region) -> ~str {
|
||||
pub fn region_to_str(cx: ctxt, prefix: &str, space: bool, region: Region) -> ~str {
|
||||
let space_str = if space { " " } else { "" };
|
||||
|
||||
if cx.sess.verbose() {
|
||||
return fmt!("%s%? ", prefix, region);
|
||||
return fmt!("%s%?%s", prefix, region, space_str);
|
||||
}
|
||||
|
||||
// These printouts are concise. They do not contain all the information
|
||||
@ -223,14 +226,14 @@ pub fn region_to_str_space(cx: ctxt, prefix: &str, region: Region) -> ~str {
|
||||
// `explain_region()` or `note_and_explain_region()`.
|
||||
match region {
|
||||
re_scope(_) => prefix.to_str(),
|
||||
re_bound(br) => bound_region_to_str_space(cx, prefix, br),
|
||||
re_free(ref fr) => bound_region_to_str_space(cx, prefix, fr.bound_region),
|
||||
re_bound(br) => bound_region_to_str(cx, prefix, space, br),
|
||||
re_free(ref fr) => bound_region_to_str(cx, prefix, space, fr.bound_region),
|
||||
re_infer(ReSkolemized(_, br)) => {
|
||||
bound_region_to_str_space(cx, prefix, br)
|
||||
bound_region_to_str(cx, prefix, space, br)
|
||||
}
|
||||
re_infer(ReVar(_)) => prefix.to_str(),
|
||||
re_static => fmt!("%s'static ", prefix),
|
||||
re_empty => fmt!("%s'<empty> ", prefix)
|
||||
re_static => fmt!("%s'static%s", prefix, space_str),
|
||||
re_empty => fmt!("%s'<empty>%s", prefix, space_str)
|
||||
}
|
||||
}
|
||||
|
||||
@ -256,7 +259,7 @@ pub fn vstore_to_str(cx: ctxt, vs: ty::vstore) -> ~str {
|
||||
ty::vstore_fixed(n) => fmt!("%u", n),
|
||||
ty::vstore_uniq => ~"~",
|
||||
ty::vstore_box => ~"@",
|
||||
ty::vstore_slice(r) => region_to_str_space(cx, "&", r)
|
||||
ty::vstore_slice(r) => region_ptr_to_str(cx, r)
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,7 +267,7 @@ pub fn trait_store_to_str(cx: ctxt, s: ty::TraitStore) -> ~str {
|
||||
match s {
|
||||
ty::UniqTraitStore => ~"~",
|
||||
ty::BoxTraitStore => ~"@",
|
||||
ty::RegionTraitStore(r) => region_to_str_space(cx, "&", r)
|
||||
ty::RegionTraitStore(r) => region_ptr_to_str(cx, r)
|
||||
}
|
||||
}
|
||||
|
||||
@ -340,7 +343,7 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
|
||||
(ast::OwnedSigil, ty::re_static) => {}
|
||||
|
||||
(_, region) => {
|
||||
s.push_str(region_to_str_space(cx, "", region));
|
||||
s.push_str(region_to_str(cx, "", true, region));
|
||||
}
|
||||
}
|
||||
|
||||
@ -414,7 +417,7 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
|
||||
ty_uniq(ref tm) => ~"~" + mt_to_str(cx, tm),
|
||||
ty_ptr(ref tm) => ~"*" + mt_to_str(cx, tm),
|
||||
ty_rptr(r, ref tm) => {
|
||||
region_to_str_space(cx, "&", r) + mt_to_str(cx, tm)
|
||||
region_ptr_to_str(cx, r) + mt_to_str(cx, tm)
|
||||
}
|
||||
ty_unboxed_vec(ref tm) => { fmt!("unboxed_vec<%s>", mt_to_str(cx, tm)) }
|
||||
ty_type => ~"type",
|
||||
@ -431,13 +434,15 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
|
||||
ty_infer(infer_ty) => infer_ty.to_str(),
|
||||
ty_err => ~"[type error]",
|
||||
ty_param(param_ty {idx: id, def_id: did}) => {
|
||||
let mut parm = (('T' as uint) + id) as char;
|
||||
if (parm as uint) > ('Z' as uint) {
|
||||
parm = (parm as uint - 26) as char;
|
||||
}
|
||||
|
||||
if cx.sess.verbose() {
|
||||
fmt!("'%s:%?",
|
||||
str::from_bytes([('a' as u8) + (id as u8)]),
|
||||
did)
|
||||
fmt!("%c:%?", parm, did)
|
||||
} else {
|
||||
fmt!("'%s",
|
||||
str::from_bytes([('a' as u8) + (id as u8)]))
|
||||
fmt!("%c", parm)
|
||||
}
|
||||
}
|
||||
ty_self(*) => ~"Self",
|
||||
@ -457,9 +462,9 @@ pub fn ty_to_str(cx: ctxt, typ: t) -> ~str {
|
||||
}
|
||||
ty_estr(vs) => fmt!("%s%s", vstore_to_str(cx, vs), "str"),
|
||||
ty_opaque_box => ~"@?",
|
||||
ty_opaque_closure_ptr(ast::BorrowedSigil) => ~"closure&",
|
||||
ty_opaque_closure_ptr(ast::ManagedSigil) => ~"closure@",
|
||||
ty_opaque_closure_ptr(ast::OwnedSigil) => ~"closure~",
|
||||
ty_opaque_closure_ptr(ast::BorrowedSigil) => ~"&closure",
|
||||
ty_opaque_closure_ptr(ast::ManagedSigil) => ~"@closure",
|
||||
ty_opaque_closure_ptr(ast::OwnedSigil) => ~"~closure",
|
||||
}
|
||||
}
|
||||
|
||||
@ -468,18 +473,20 @@ pub fn parameterized(cx: ctxt,
|
||||
self_r: Option<ty::Region>,
|
||||
tps: &[ty::t]) -> ~str {
|
||||
|
||||
let r_str = match self_r {
|
||||
None => ~"",
|
||||
Some(r) => {
|
||||
fmt!("/%s", region_to_str(cx, r))
|
||||
}
|
||||
let mut strs = ~[];
|
||||
match self_r {
|
||||
None => (),
|
||||
Some(r) => {
|
||||
strs.push(region_to_str(cx, "", false, r))
|
||||
}
|
||||
};
|
||||
|
||||
if tps.len() > 0u {
|
||||
let strs = vec::map(tps, |t| ty_to_str(cx, *t));
|
||||
fmt!("%s%s<%s>", base, r_str, strs.connect(","))
|
||||
strs += vec::map(tps, |t| ty_to_str(cx, *t));
|
||||
|
||||
if strs.len() > 0u {
|
||||
fmt!("%s<%s>", base, strs.connect(","))
|
||||
} else {
|
||||
fmt!("%s%s", base, r_str)
|
||||
fmt!("%s", base)
|
||||
}
|
||||
}
|
||||
|
||||
@ -597,7 +604,7 @@ impl Repr for @ast::pat {
|
||||
|
||||
impl Repr for ty::Region {
|
||||
fn repr(&self, tcx: ctxt) -> ~str {
|
||||
region_to_str(tcx, *self)
|
||||
region_to_str(tcx, "", false, *self)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,22 +42,38 @@ pub extern "rust-intrinsic" {
|
||||
/// Atomic compare and exchange, release ordering.
|
||||
pub fn atomic_cxchg_rel(dst: &mut int, old: int, src: int) -> int;
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_cxchg_acqrel(dst: &mut int, old: int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_cxchg_relaxed(dst: &mut int, old: int, src: int) -> int;
|
||||
|
||||
|
||||
/// Atomic load, sequentially consistent.
|
||||
pub fn atomic_load(src: &int) -> int;
|
||||
/// Atomic load, acquire ordering.
|
||||
pub fn atomic_load_acq(src: &int) -> int;
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_load_relaxed(src: &int) -> int;
|
||||
|
||||
/// Atomic store, sequentially consistent.
|
||||
pub fn atomic_store(dst: &mut int, val: int);
|
||||
/// Atomic store, release ordering.
|
||||
pub fn atomic_store_rel(dst: &mut int, val: int);
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_store_relaxed(dst: &mut int, val: int);
|
||||
|
||||
/// Atomic exchange, sequentially consistent.
|
||||
pub fn atomic_xchg(dst: &mut int, src: int) -> int;
|
||||
/// Atomic exchange, acquire ordering.
|
||||
pub fn atomic_xchg_acq(dst: &mut int, src: int) -> int;
|
||||
/// Atomic exchange, release ordering.
|
||||
pub fn atomic_xchg_rel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_xchg_acqrel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_xchg_relaxed(dst: &mut int, src: int) -> int;
|
||||
|
||||
/// Atomic addition, sequentially consistent.
|
||||
pub fn atomic_xadd(dst: &mut int, src: int) -> int;
|
||||
@ -65,6 +81,10 @@ pub extern "rust-intrinsic" {
|
||||
pub fn atomic_xadd_acq(dst: &mut int, src: int) -> int;
|
||||
/// Atomic addition, release ordering.
|
||||
pub fn atomic_xadd_rel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_xadd_acqrel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_xadd_relaxed(dst: &mut int, src: int) -> int;
|
||||
|
||||
/// Atomic subtraction, sequentially consistent.
|
||||
pub fn atomic_xsub(dst: &mut int, src: int) -> int;
|
||||
@ -72,6 +92,98 @@ pub extern "rust-intrinsic" {
|
||||
pub fn atomic_xsub_acq(dst: &mut int, src: int) -> int;
|
||||
/// Atomic subtraction, release ordering.
|
||||
pub fn atomic_xsub_rel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_xsub_acqrel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_xsub_relaxed(dst: &mut int, src: int) -> int;
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_and(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_and_acq(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_and_rel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_and_acqrel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_and_relaxed(dst: &mut int, src: int) -> int;
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_nand(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_nand_acq(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_nand_rel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_nand_acqrel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_nand_relaxed(dst: &mut int, src: int) -> int;
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_or(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_or_acq(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_or_rel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_or_acqrel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_or_relaxed(dst: &mut int, src: int) -> int;
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_xor(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_xor_acq(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_xor_rel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_xor_acqrel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_xor_relaxed(dst: &mut int, src: int) -> int;
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_max(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_max_acq(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_max_rel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_max_acqrel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_max_relaxed(dst: &mut int, src: int) -> int;
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_min(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_min_acq(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_min_rel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_min_acqrel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_min_relaxed(dst: &mut int, src: int) -> int;
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_umin(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_umin_acq(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_umin_rel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_umin_acqrel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_umin_relaxed(dst: &mut int, src: int) -> int;
|
||||
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_umax(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_umax_acq(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_umax_rel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_umax_acqrel(dst: &mut int, src: int) -> int;
|
||||
#[cfg(not(stage0))]
|
||||
pub fn atomic_umax_relaxed(dst: &mut int, src: int) -> int;
|
||||
|
||||
/// The size of a type in bytes.
|
||||
///
|
||||
|
@ -16,11 +16,11 @@ struct an_enum<'self>(&'self int);
|
||||
struct a_class<'self> { x:&'self int }
|
||||
|
||||
fn a_fn1<'a,'b>(e: an_enum<'a>) -> an_enum<'b> {
|
||||
return e; //~ ERROR mismatched types: expected `an_enum/&'b ` but found `an_enum/&'a `
|
||||
return e; //~ ERROR mismatched types: expected `an_enum<'b>` but found `an_enum<'a>`
|
||||
}
|
||||
|
||||
fn a_fn3<'a,'b>(e: a_class<'a>) -> a_class<'b> {
|
||||
return e; //~ ERROR mismatched types: expected `a_class/&'b ` but found `a_class/&'a `
|
||||
return e; //~ ERROR mismatched types: expected `a_class<'b>` but found `a_class<'a>`
|
||||
}
|
||||
|
||||
fn a_fn4<'a,'b>() {
|
||||
|
Loading…
Reference in New Issue
Block a user