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:
bors 2013-06-21 19:19:58 -07:00
commit dc4560dc26
45 changed files with 2492 additions and 2793 deletions

View file

@ -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())
}
}

View file

@ -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;
}
}

View file

@ -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)
}
}

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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());
}
}

View file

@ -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);
}
}

View file

@ -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 {

View file

@ -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 {

View file

@ -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()
};
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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)
}

View file

@ -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.

View file

@ -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!")

View file

@ -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(

View file

@ -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()));

View file

@ -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));

View file

@ -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);

View file

@ -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())
}

View file

@ -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

View file

@ -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;
}

View file

@ -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
}

View file

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

View file

@ -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) {

View file

@ -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");

View file

@ -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;
}

View file

@ -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);

View 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")
}
}
}

View file

@ -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())
}

View file

@ -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;}
}

View file

@ -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);

View file

@ -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)
}

View file

@ -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",

View file

@ -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 {

View file

@ -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.

View file

@ -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)));
}
}
}

View file

@ -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
});

View file

@ -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
}

View file

@ -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)
}
}

View file

@ -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.
///

View file

@ -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>() {