}
pub fn lltype_is_sized<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
-match ty.sty {
- ty::ty_open(_) => true,
- _ => type_is_sized(cx, ty),
-}
+ match ty.sty {
+ ty::ty_open(_) => true,
+ _ => type_is_sized(cx, ty),
+ }
}
pub fn type_is_fat_ptr<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
-match ty.sty {
- ty::ty_ptr(ty::mt{ty, ..}) |
- ty::ty_rptr(_, ty::mt{ty, ..}) |
- ty::ty_uniq(ty) => {
- !type_is_sized(cx, ty)
- }
- _ => {
- false
+ match ty.sty {
+ ty::ty_ptr(ty::mt{ty, ..}) |
+ ty::ty_rptr(_, ty::mt{ty, ..}) |
+ ty::ty_uniq(ty) => {
+ !type_is_sized(cx, ty)
+ }
+ _ => {
+ false
+ }
}
}
-}
// Return the smallest part of `ty` which is unsized. Fails if `ty` is sized.
// 'Smallest' here means component of the static representation of the type; not
// the size of an object at runtime.
pub fn unsized_part_of_type<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
-match ty.sty {
- ty::ty_str | ty::ty_trait(..) | ty::ty_vec(..) => ty,
- ty::ty_struct(def_id, substs) => {
- let unsized_fields: Vec<_> =
- ty::struct_fields(cx, def_id, substs)
- .iter()
- .map(|f| f.mt.ty)
- .filter(|ty| !type_is_sized(cx, *ty))
- .collect();
-
- // Exactly one of the fields must be unsized.
- assert!(unsized_fields.len() == 1);
-
- unsized_part_of_type(cx, unsized_fields[0])
- }
- _ => {
- assert!(type_is_sized(cx, ty),
- "unsized_part_of_type failed even though ty is unsized");
- panic!("called unsized_part_of_type with sized ty");
+ match ty.sty {
+ ty::ty_str | ty::ty_trait(..) | ty::ty_vec(..) => ty,
+ ty::ty_struct(def_id, substs) => {
+ let unsized_fields: Vec<_> =
+ ty::struct_fields(cx, def_id, substs)
+ .iter()
+ .map(|f| f.mt.ty)
+ .filter(|ty| !type_is_sized(cx, *ty))
+ .collect();
+
+ // Exactly one of the fields must be unsized.
+ assert!(unsized_fields.len() == 1);
+
+ unsized_part_of_type(cx, unsized_fields[0])
+ }
+ _ => {
+ assert!(type_is_sized(cx, ty),
+ "unsized_part_of_type failed even though ty is unsized");
+ panic!("called unsized_part_of_type with sized ty");
+ }
}
}
-}
// Some things don't need cleanups during unwinding because the
// task can free them all at once later. Currently only things
// that only contain scalars and shared boxes can avoid unwind
// cleanups.
pub fn type_needs_unwind_cleanup<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
-return memoized(ccx.needs_unwind_cleanup_cache(), ty, |ty| {
- type_needs_unwind_cleanup_(ccx.tcx(), ty, &mut FnvHashSet::new())
-});
-
-fn type_needs_unwind_cleanup_<'tcx>(tcx: &ty::ctxt<'tcx>,
- ty: Ty<'tcx>,
- tycache: &mut FnvHashSet<Ty<'tcx>>)
- -> bool
-{
- // Prevent infinite recursion
- if !tycache.insert(ty) {
- return false;
- }
-
- let mut needs_unwind_cleanup = false;
- ty::maybe_walk_ty(ty, |ty| {
- needs_unwind_cleanup |= match ty.sty {
- ty::ty_bool | ty::ty_int(_) | ty::ty_uint(_) |
- ty::ty_float(_) | ty::ty_tup(_) | ty::ty_ptr(_) => false,
+ return memoized(ccx.needs_unwind_cleanup_cache(), ty, |ty| {
+ type_needs_unwind_cleanup_(ccx.tcx(), ty, &mut FnvHashSet::new())
+ });
- ty::ty_enum(did, substs) =>
- ty::enum_variants(tcx, did).iter().any(|v|
- v.args.iter().any(|&aty| {
- let t = aty.subst(tcx, substs);
- type_needs_unwind_cleanup_(tcx, t, tycache)
- })
- ),
+ fn type_needs_unwind_cleanup_<'tcx>(tcx: &ty::ctxt<'tcx>,
+ ty: Ty<'tcx>,
+ tycache: &mut FnvHashSet<Ty<'tcx>>)
+ -> bool
+ {
+ // Prevent infinite recursion
+ if !tycache.insert(ty) {
+ return false;
+ }
- _ => true
- };
- !needs_unwind_cleanup
- });
- needs_unwind_cleanup
-}
+ let mut needs_unwind_cleanup = false;
+ ty::maybe_walk_ty(ty, |ty| {
+ needs_unwind_cleanup |= match ty.sty {
+ ty::ty_bool | ty::ty_int(_) | ty::ty_uint(_) |
+ ty::ty_float(_) | ty::ty_tup(_) | ty::ty_ptr(_) => false,
+
+ ty::ty_enum(did, substs) =>
+ ty::enum_variants(tcx, did).iter().any(|v|
+ v.args.iter().any(|&aty| {
+ let t = aty.subst(tcx, substs);
+ type_needs_unwind_cleanup_(tcx, t, tycache)
+ })
+ ),
+
+ _ => true
+ };
+ !needs_unwind_cleanup
+ });
+ needs_unwind_cleanup
+ }
}
pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>,
ty: Ty<'tcx>)
-> bool {
-ty::type_contents(cx, ty).needs_drop(cx)
+ ty::type_contents(cx, ty).needs_drop(cx)
}
fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
ty: Ty<'tcx>) -> bool {
-match ty.sty {
- ty::ty_struct(def_id, substs) => {
- let fields = ty::struct_fields(ccx.tcx(), def_id, substs);
- fields.len() == 1 &&
- fields[0].name ==
- token::special_idents::unnamed_field.name &&
- type_is_immediate(ccx, fields[0].mt.ty)
+ match ty.sty {
+ ty::ty_struct(def_id, substs) => {
+ let fields = ty::struct_fields(ccx.tcx(), def_id, substs);
+ fields.len() == 1 &&
+ fields[0].name ==
+ token::special_idents::unnamed_field.name &&
+ type_is_immediate(ccx, fields[0].mt.ty)
+ }
+ _ => false
}
- _ => false
-}
}
pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
-use trans::machine::llsize_of_alloc;
-use trans::type_of::sizing_type_of;
-
-let tcx = ccx.tcx();
-let simple = ty::type_is_scalar(ty) ||
- ty::type_is_unique(ty) || ty::type_is_region_ptr(ty) ||
- type_is_newtype_immediate(ccx, ty) ||
- ty::type_is_simd(tcx, ty);
-if simple && !type_is_fat_ptr(tcx, ty) {
- return true;
-}
-if !type_is_sized(tcx, ty) {
- return false;
-}
-match ty.sty {
- ty::ty_struct(..) | ty::ty_enum(..) | ty::ty_tup(..) |
- ty::ty_unboxed_closure(..) => {
- let llty = sizing_type_of(ccx, ty);
- llsize_of_alloc(ccx, llty) <= llsize_of_alloc(ccx, ccx.int_type())
+ use trans::machine::llsize_of_alloc;
+ use trans::type_of::sizing_type_of;
+
+ let tcx = ccx.tcx();
+ let simple = ty::type_is_scalar(ty) ||
+ ty::type_is_unique(ty) || ty::type_is_region_ptr(ty) ||
+ type_is_newtype_immediate(ccx, ty) ||
+ ty::type_is_simd(tcx, ty);
+ if simple && !type_is_fat_ptr(tcx, ty) {
+ return true;
+ }
+ if !type_is_sized(tcx, ty) {
+ return false;
+ }
+ match ty.sty {
+ ty::ty_struct(..) | ty::ty_enum(..) | ty::ty_tup(..) |
+ ty::ty_unboxed_closure(..) => {
+ let llty = sizing_type_of(ccx, ty);
+ llsize_of_alloc(ccx, llty) <= llsize_of_alloc(ccx, ccx.int_type())
+ }
+ _ => type_is_zero_size(ccx, ty)
}
- _ => type_is_zero_size(ccx, ty)
-}
}
/// Identify types which have size zero at runtime.
pub fn type_is_zero_size<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
-use trans::machine::llsize_of_alloc;
-use trans::type_of::sizing_type_of;
-let llty = sizing_type_of(ccx, ty);
-llsize_of_alloc(ccx, llty) == 0
+ use trans::machine::llsize_of_alloc;
+ use trans::type_of::sizing_type_of;
+ let llty = sizing_type_of(ccx, ty);
+ llsize_of_alloc(ccx, llty) == 0
}
/// Identifies types which we declare to be equivalent to `void` in C for the purpose of function
/// zero-size, but not all zero-size types use a `void` return type (in order to aid with C ABI
/// compatibility).
pub fn return_type_is_void(ccx: &CrateContext, ty: Ty) -> bool {
-ty::type_is_nil(ty) || ty::type_is_empty(ccx.tcx(), ty)
+ ty::type_is_nil(ty) || ty::type_is_empty(ccx.tcx(), ty)
}
/// Generates a unique symbol based off the name given. This is used to create
/// unique symbols for things like closures.
pub fn gensym_name(name: &str) -> PathElem {
-let num = token::gensym(name).uint();
-// use one colon which will get translated to a period by the mangler, and
-// we're guaranteed that `num` is globally unique for this crate.
-PathName(token::gensym(&format!("{}:{}", name, num)[]))
+ let num = token::gensym(name).uint();
+ // use one colon which will get translated to a period by the mangler, and
+ // we're guaranteed that `num` is globally unique for this crate.
+ PathName(token::gensym(&format!("{}:{}", name, num)[]))
}
#[derive(Copy)]
pub struct tydesc_info<'tcx> {
-pub ty: Ty<'tcx>,
-pub tydesc: ValueRef,
-pub size: ValueRef,
-pub align: ValueRef,
-pub name: ValueRef,
+ pub ty: Ty<'tcx>,
+ pub tydesc: ValueRef,
+ pub size: ValueRef,
+ pub align: ValueRef,
+ pub name: ValueRef,
}
/*
#[derive(Copy)]
pub struct NodeInfo {
-pub id: ast::NodeId,
-pub span: Span,
+ pub id: ast::NodeId,
+ pub span: Span,
}
pub fn expr_info(expr: &ast::Expr) -> NodeInfo {
-NodeInfo { id: expr.id, span: expr.span }
+ NodeInfo { id: expr.id, span: expr.span }
}
pub struct BuilderRef_res {
-pub b: BuilderRef,
+ pub b: BuilderRef,
}
impl Drop for BuilderRef_res {
-fn drop(&mut self) {
- unsafe {
- llvm::LLVMDisposeBuilder(self.b);
+ fn drop(&mut self) {
+ unsafe {
+ llvm::LLVMDisposeBuilder(self.b);
+ }
}
}
-}
pub fn BuilderRef_res(b: BuilderRef) -> BuilderRef_res {
-BuilderRef_res {
- b: b
-}
+ BuilderRef_res {
+ b: b
+ }
}
pub type ExternMap = FnvHashMap<String, ValueRef>;
pub fn validate_substs(substs: &Substs) {
-assert!(substs.types.all(|t| !ty::type_needs_infer(*t)));
+ assert!(substs.types.all(|t| !ty::type_needs_infer(*t)));
}
// work around bizarre resolve errors
// Function context. Every LLVM function we create will have one of
// these.
pub struct FunctionContext<'a, 'tcx: 'a> {
-// The ValueRef returned from a call to llvm::LLVMAddFunction; the
-// address of the first instruction in the sequence of
-// instructions for this function that will go in the .text
-// section of the executable we're generating.
-pub llfn: ValueRef,
+ // The ValueRef returned from a call to llvm::LLVMAddFunction; the
+ // address of the first instruction in the sequence of
+ // instructions for this function that will go in the .text
+ // section of the executable we're generating.
+ pub llfn: ValueRef,
-// always an empty parameter-environment
-pub param_env: ty::ParameterEnvironment<'a, 'tcx>,
+ // always an empty parameter-environment
+ pub param_env: ty::ParameterEnvironment<'a, 'tcx>,
-// The environment argument in a closure.
-pub llenv: Option<ValueRef>,
+ // The environment argument in a closure.
+ pub llenv: Option<ValueRef>,
-// A pointer to where to store the return value. If the return type is
-// immediate, this points to an alloca in the function. Otherwise, it's a
-// pointer to the hidden first parameter of the function. After function
-// construction, this should always be Some.
-pub llretslotptr: Cell<Option<ValueRef>>,
+ // A pointer to where to store the return value. If the return type is
+ // immediate, this points to an alloca in the function. Otherwise, it's a
+ // pointer to the hidden first parameter of the function. After function
+ // construction, this should always be Some.
+ pub llretslotptr: Cell<Option<ValueRef>>,
-// These pub elements: "hoisted basic blocks" containing
-// administrative activities that have to happen in only one place in
-// the function, due to LLVM's quirks.
-// A marker for the place where we want to insert the function's static
-// allocas, so that LLVM will coalesce them into a single alloca call.
-pub alloca_insert_pt: Cell<Option<ValueRef>>,
-pub llreturn: Cell<Option<BasicBlockRef>>,
+ // These pub elements: "hoisted basic blocks" containing
+ // administrative activities that have to happen in only one place in
+ // the function, due to LLVM's quirks.
+ // A marker for the place where we want to insert the function's static
+ // allocas, so that LLVM will coalesce them into a single alloca call.
+ pub alloca_insert_pt: Cell<Option<ValueRef>>,
+ pub llreturn: Cell<Option<BasicBlockRef>>,
-// If the function has any nested return's, including something like:
-// fn foo() -> Option<Foo> { Some(Foo { x: return None }) }, then
-// we use a separate alloca for each return
-pub needs_ret_allocas: bool,
+ // If the function has any nested return's, including something like:
+ // fn foo() -> Option<Foo> { Some(Foo { x: return None }) }, then
+ // we use a separate alloca for each return
+ pub needs_ret_allocas: bool,
-// The a value alloca'd for calls to upcalls.rust_personality. Used when
-// outputting the resume instruction.
-pub personality: Cell<Option<ValueRef>>,
+ // The a value alloca'd for calls to upcalls.rust_personality. Used when
+ // outputting the resume instruction.
+ pub personality: Cell<Option<ValueRef>>,
-// True if the caller expects this fn to use the out pointer to
-// return. Either way, your code should write into the slot llretslotptr
-// points to, but if this value is false, that slot will be a local alloca.
-pub caller_expects_out_pointer: bool,
+ // True if the caller expects this fn to use the out pointer to
+ // return. Either way, your code should write into the slot llretslotptr
+ // points to, but if this value is false, that slot will be a local alloca.
+ pub caller_expects_out_pointer: bool,
-// Maps the DefId's for local variables to the allocas created for
-// them in llallocas.
-pub lllocals: RefCell<NodeMap<LvalueDatum<'tcx>>>,
+ // Maps the DefId's for local variables to the allocas created for
+ // them in llallocas.
+ pub lllocals: RefCell<NodeMap<LvalueDatum<'tcx>>>,
-// Same as above, but for closure upvars
-pub llupvars: RefCell<NodeMap<ValueRef>>,
+ // Same as above, but for closure upvars
+ pub llupvars: RefCell<NodeMap<ValueRef>>,
-// The NodeId of the function, or -1 if it doesn't correspond to
-// a user-defined function.
-pub id: ast::NodeId,
+ // The NodeId of the function, or -1 if it doesn't correspond to
+ // a user-defined function.
+ pub id: ast::NodeId,
-// If this function is being monomorphized, this contains the type
-// substitutions used.
-pub param_substs: &'a Substs<'tcx>,
+ // If this function is being monomorphized, this contains the type
+ // substitutions used.
+ pub param_substs: &'a Substs<'tcx>,
-// The source span and nesting context where this function comes from, for
-// error reporting and symbol generation.
-pub span: Option<Span>,
+ // The source span and nesting context where this function comes from, for
+ // error reporting and symbol generation.
+ pub span: Option<Span>,
-// The arena that blocks are allocated from.
-pub block_arena: &'a TypedArena<BlockS<'a, 'tcx>>,
+ // The arena that blocks are allocated from.
+ pub block_arena: &'a TypedArena<BlockS<'a, 'tcx>>,
-// This function's enclosing crate context.
-pub ccx: &'a CrateContext<'a, 'tcx>,
+ // This function's enclosing crate context.
+ pub ccx: &'a CrateContext<'a, 'tcx>,
-// Used and maintained by the debuginfo module.
-pub debug_context: debuginfo::FunctionDebugContext,
+ // Used and maintained by the debuginfo module.
+ pub debug_context: debuginfo::FunctionDebugContext,
-// Cleanup scopes.
-pub scopes: RefCell<Vec<cleanup::CleanupScope<'a, 'tcx>>>,
+ // Cleanup scopes.
+ pub scopes: RefCell<Vec<cleanup::CleanupScope<'a, 'tcx>>>,
-pub cfg: Option<cfg::CFG>,
+ pub cfg: Option<cfg::CFG>,
}
impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
-pub fn arg_pos(&self, arg: uint) -> uint {
- let arg = self.env_arg_pos() + arg;
- if self.llenv.is_some() {
- arg + 1
- } else {
- arg
+ pub fn arg_pos(&self, arg: uint) -> uint {
+ let arg = self.env_arg_pos() + arg;
+ if self.llenv.is_some() {
+ arg + 1
+ } else {
+ arg
+ }
}
-}
-pub fn env_arg_pos(&self) -> uint {
- if self.caller_expects_out_pointer {
- 1u
- } else {
- 0u
+ pub fn env_arg_pos(&self) -> uint {
+ if self.caller_expects_out_pointer {
+ 1u
+ } else {
+ 0u
+ }
}
-}
-pub fn cleanup(&self) {
- unsafe {
- llvm::LLVMInstructionEraseFromParent(self.alloca_insert_pt
- .get()
- .unwrap());
+ pub fn cleanup(&self) {
+ unsafe {
+ llvm::LLVMInstructionEraseFromParent(self.alloca_insert_pt
+ .get()
+ .unwrap());
+ }
}
-}
-pub fn get_llreturn(&self) -> BasicBlockRef {
- if self.llreturn.get().is_none() {
+ pub fn get_llreturn(&self) -> BasicBlockRef {
+ if self.llreturn.get().is_none() {
- self.llreturn.set(Some(unsafe {
- llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(), self.llfn,
- "return\0".as_ptr() as *const _)
- }))
- }
+ self.llreturn.set(Some(unsafe {
+ llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(), self.llfn,
+ "return\0".as_ptr() as *const _)
+ }))
+ }
- self.llreturn.get().unwrap()
-}
+ self.llreturn.get().unwrap()
+ }
-pub fn get_ret_slot(&self, bcx: Block<'a, 'tcx>,
- output: ty::FnOutput<'tcx>,
- name: &str) -> ValueRef {
- if self.needs_ret_allocas {
- base::alloca_no_lifetime(bcx, match output {
- ty::FnConverging(output_type) => type_of::type_of(bcx.ccx(), output_type),
- ty::FnDiverging => Type::void(bcx.ccx())
- }, name)
- } else {
- self.llretslotptr.get().unwrap()
+ pub fn get_ret_slot(&self, bcx: Block<'a, 'tcx>,
+ output: ty::FnOutput<'tcx>,
+ name: &str) -> ValueRef {
+ if self.needs_ret_allocas {
+ base::alloca_no_lifetime(bcx, match output {
+ ty::FnConverging(output_type) => type_of::type_of(bcx.ccx(), output_type),
+ ty::FnDiverging => Type::void(bcx.ccx())
+ }, name)
+ } else {
+ self.llretslotptr.get().unwrap()
+ }
}
-}
-pub fn new_block(&'a self,
- is_lpad: bool,
- name: &str,
- opt_node_id: Option<ast::NodeId>)
- -> Block<'a, 'tcx> {
- unsafe {
- let name = CString::from_slice(name.as_bytes());
- let llbb = llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(),
- self.llfn,
- name.as_ptr());
- BlockS::new(llbb, is_lpad, opt_node_id, self)
+ pub fn new_block(&'a self,
+ is_lpad: bool,
+ name: &str,
+ opt_node_id: Option<ast::NodeId>)
+ -> Block<'a, 'tcx> {
+ unsafe {
+ let name = CString::from_slice(name.as_bytes());
+ let llbb = llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(),
+ self.llfn,
+ name.as_ptr());
+ BlockS::new(llbb, is_lpad, opt_node_id, self)
+ }
}
-}
-pub fn new_id_block(&'a self,
- name: &str,
- node_id: ast::NodeId)
- -> Block<'a, 'tcx> {
- self.new_block(false, name, Some(node_id))
-}
+ pub fn new_id_block(&'a self,
+ name: &str,
+ node_id: ast::NodeId)
+ -> Block<'a, 'tcx> {
+ self.new_block(false, name, Some(node_id))
+ }
-pub fn new_temp_block(&'a self,
- name: &str)
- -> Block<'a, 'tcx> {
- self.new_block(false, name, None)
-}
+ pub fn new_temp_block(&'a self,
+ name: &str)
+ -> Block<'a, 'tcx> {
+ self.new_block(false, name, None)
+ }
-pub fn join_blocks(&'a self,
- id: ast::NodeId,
- in_cxs: &[Block<'a, 'tcx>])
- -> Block<'a, 'tcx> {
- let out = self.new_id_block("join", id);
- let mut reachable = false;
- for bcx in in_cxs.iter() {
- if !bcx.unreachable.get() {
- build::Br(*bcx, out.llbb);
- reachable = true;
+ pub fn join_blocks(&'a self,
+ id: ast::NodeId,
+ in_cxs: &[Block<'a, 'tcx>])
+ -> Block<'a, 'tcx> {
+ let out = self.new_id_block("join", id);
+ let mut reachable = false;
+ for bcx in in_cxs.iter() {
+ if !bcx.unreachable.get() {
+ build::Br(*bcx, out.llbb);
+ reachable = true;
+ }
}
+ if !reachable {
+ build::Unreachable(out);
+ }
+ return out;
}
- if !reachable {
- build::Unreachable(out);
- }
- return out;
-}
-pub fn monomorphize<T>(&self, value: &T) -> T
- where T : TypeFoldable<'tcx> + Repr<'tcx> + HasProjectionTypes + Clone
-{
- monomorphize::apply_param_substs(self.ccx.tcx(),
- self.param_substs,
- value)
-}
+ pub fn monomorphize<T>(&self, value: &T) -> T
+ where T : TypeFoldable<'tcx> + Repr<'tcx> + HasProjectionTypes + Clone
+ {
+ monomorphize::apply_param_substs(self.ccx.tcx(),
+ self.param_substs,
+ value)
+ }
}
// Basic block context. We create a block context for each basic block
// with many basic blocks per function. All the basic blocks attached to a
// function are organized as a directed graph.
pub struct BlockS<'blk, 'tcx: 'blk> {
-// The BasicBlockRef returned from a call to
-// llvm::LLVMAppendBasicBlock(llfn, name), which adds a basic
-// block to the function pointed to by llfn. We insert
-// instructions into that block by way of this block context.
-// The block pointing to this one in the function's digraph.
-pub llbb: BasicBlockRef,
-pub terminated: Cell<bool>,
-pub unreachable: Cell<bool>,
+ // The BasicBlockRef returned from a call to
+ // llvm::LLVMAppendBasicBlock(llfn, name), which adds a basic
+ // block to the function pointed to by llfn. We insert
+ // instructions into that block by way of this block context.
+ // The block pointing to this one in the function's digraph.
+ pub llbb: BasicBlockRef,
+ pub terminated: Cell<bool>,
+ pub unreachable: Cell<bool>,
-// Is this block part of a landing pad?
-pub is_lpad: bool,
+ // Is this block part of a landing pad?
+ pub is_lpad: bool,
-// AST node-id associated with this block, if any. Used for
-// debugging purposes only.
-pub opt_node_id: Option<ast::NodeId>,
+ // AST node-id associated with this block, if any. Used for
+ // debugging purposes only.
+ pub opt_node_id: Option<ast::NodeId>,
-// The function context for the function to which this block is
-// attached.
-pub fcx: &'blk FunctionContext<'blk, 'tcx>,
+ // The function context for the function to which this block is
+ // attached.
+ pub fcx: &'blk FunctionContext<'blk, 'tcx>,
}
pub type Block<'blk, 'tcx> = &'blk BlockS<'blk, 'tcx>;
impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
-pub fn new(llbb: BasicBlockRef,
- is_lpad: bool,
- opt_node_id: Option<ast::NodeId>,
- fcx: &'blk FunctionContext<'blk, 'tcx>)
- -> Block<'blk, 'tcx> {
- fcx.block_arena.alloc(BlockS {
- llbb: llbb,
- terminated: Cell::new(false),
- unreachable: Cell::new(false),
- is_lpad: is_lpad,
- opt_node_id: opt_node_id,
- fcx: fcx
- })
-}
+ pub fn new(llbb: BasicBlockRef,
+ is_lpad: bool,
+ opt_node_id: Option<ast::NodeId>,
+ fcx: &'blk FunctionContext<'blk, 'tcx>)
+ -> Block<'blk, 'tcx> {
+ fcx.block_arena.alloc(BlockS {
+ llbb: llbb,
+ terminated: Cell::new(false),
+ unreachable: Cell::new(false),
+ is_lpad: is_lpad,
+ opt_node_id: opt_node_id,
+ fcx: fcx
+ })
+ }
-pub fn ccx(&self) -> &'blk CrateContext<'blk, 'tcx> {
- self.fcx.ccx
-}
-pub fn tcx(&self) -> &'blk ty::ctxt<'tcx> {
- self.fcx.ccx.tcx()
-}
-pub fn sess(&self) -> &'blk Session { self.fcx.ccx.sess() }
+ pub fn ccx(&self) -> &'blk CrateContext<'blk, 'tcx> {
+ self.fcx.ccx
+ }
+ pub fn tcx(&self) -> &'blk ty::ctxt<'tcx> {
+ self.fcx.ccx.tcx()
+ }
+ pub fn sess(&self) -> &'blk Session { self.fcx.ccx.sess() }
-pub fn ident(&self, ident: Ident) -> String {
- token::get_ident(ident).get().to_string()
-}
+ pub fn ident(&self, ident: Ident) -> String {
+ token::get_ident(ident).get().to_string()
+ }
-pub fn node_id_to_string(&self, id: ast::NodeId) -> String {
- self.tcx().map.node_to_string(id).to_string()
-}
+ pub fn node_id_to_string(&self, id: ast::NodeId) -> String {
+ self.tcx().map.node_to_string(id).to_string()
+ }
-pub fn expr_to_string(&self, e: &ast::Expr) -> String {
- e.repr(self.tcx())
-}
+ pub fn expr_to_string(&self, e: &ast::Expr) -> String {
+ e.repr(self.tcx())
+ }
-pub fn def(&self, nid: ast::NodeId) -> def::Def {
- match self.tcx().def_map.borrow().get(&nid) {
- Some(v) => v.clone(),
- None => {
- self.tcx().sess.bug(&format!(
- "no def associated with node id {}", nid)[]);
+ pub fn def(&self, nid: ast::NodeId) -> def::Def {
+ match self.tcx().def_map.borrow().get(&nid) {
+ Some(v) => v.clone(),
+ None => {
+ self.tcx().sess.bug(&format!(
+ "no def associated with node id {}", nid)[]);
+ }
}
}
-}
-pub fn val_to_string(&self, val: ValueRef) -> String {
- self.ccx().tn().val_to_string(val)
-}
+ pub fn val_to_string(&self, val: ValueRef) -> String {
+ self.ccx().tn().val_to_string(val)
+ }
-pub fn llty_str(&self, ty: Type) -> String {
- self.ccx().tn().type_to_string(ty)
-}
+ pub fn llty_str(&self, ty: Type) -> String {
+ self.ccx().tn().type_to_string(ty)
+ }
-pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {
- t.repr(self.tcx())
-}
+ pub fn ty_to_string(&self, t: Ty<'tcx>) -> String {
+ t.repr(self.tcx())
+ }
-pub fn to_str(&self) -> String {
- format!("[block {:p}]", self)
-}
+ pub fn to_str(&self) -> String {
+ format!("[block {:p}]", self)
+ }
-pub fn monomorphize<T>(&self, value: &T) -> T
- where T : TypeFoldable<'tcx> + Repr<'tcx> + HasProjectionTypes + Clone
-{
- monomorphize::apply_param_substs(self.tcx(),
- self.fcx.param_substs,
- value)
-}
+ pub fn monomorphize<T>(&self, value: &T) -> T
+ where T : TypeFoldable<'tcx> + Repr<'tcx> + HasProjectionTypes + Clone
+ {
+ monomorphize::apply_param_substs(self.tcx(),
+ self.fcx.param_substs,
+ value)
+ }
}
impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> {
-fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
- self.tcx()
-}
+ fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
+ self.tcx()
+ }
-fn node_ty(&self, id: ast::NodeId) -> mc::McResult<Ty<'tcx>> {
- Ok(node_id_type(self, id))
-}
+ fn node_ty(&self, id: ast::NodeId) -> mc::McResult<Ty<'tcx>> {
+ Ok(node_id_type(self, id))
+ }
-fn expr_ty_adjusted(&self, expr: &ast::Expr) -> mc::McResult<Ty<'tcx>> {
- Ok(expr_ty_adjusted(self, expr))
-}
+ fn expr_ty_adjusted(&self, expr: &ast::Expr) -> mc::McResult<Ty<'tcx>> {
+ Ok(expr_ty_adjusted(self, expr))
+ }
-fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>> {
- self.tcx()
- .method_map
- .borrow()
- .get(&method_call)
- .map(|method| monomorphize_type(self, method.ty))
-}
+ fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>> {
+ self.tcx()
+ .method_map
+ .borrow()
+ .get(&method_call)
+ .map(|method| monomorphize_type(self, method.ty))
+ }
-fn node_method_origin(&self, method_call: ty::MethodCall)
- -> Option<ty::MethodOrigin<'tcx>>
-{
- self.tcx()
- .method_map
- .borrow()
- .get(&method_call)
- .map(|method| method.origin.clone())
-}
+ fn node_method_origin(&self, method_call: ty::MethodCall)
+ -> Option<ty::MethodOrigin<'tcx>>
+ {
+ self.tcx()
+ .method_map
+ .borrow()
+ .get(&method_call)
+ .map(|method| method.origin.clone())
+ }
-fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
- &self.tcx().adjustments
-}
+ fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
+ &self.tcx().adjustments
+ }
-fn is_method_call(&self, id: ast::NodeId) -> bool {
- self.tcx().method_map.borrow().contains_key(&ty::MethodCall::expr(id))
-}
+ fn is_method_call(&self, id: ast::NodeId) -> bool {
+ self.tcx().method_map.borrow().contains_key(&ty::MethodCall::expr(id))
+ }
-fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent> {
- self.tcx().region_maps.temporary_scope(rvalue_id)
-}
+ fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent> {
+ self.tcx().region_maps.temporary_scope(rvalue_id)
+ }
-fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarBorrow> {
- Some(self.tcx().upvar_borrow_map.borrow()[upvar_id].clone())
-}
+ fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarBorrow> {
+ Some(self.tcx().upvar_borrow_map.borrow()[upvar_id].clone())
+ }
-fn capture_mode(&self, closure_expr_id: ast::NodeId)
- -> ast::CaptureClause {
- self.tcx().capture_modes.borrow()[closure_expr_id].clone()
-}
+ fn capture_mode(&self, closure_expr_id: ast::NodeId)
+ -> ast::CaptureClause {
+ self.tcx().capture_modes.borrow()[closure_expr_id].clone()
+ }
-fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool {
- self.fcx.param_env.type_moves_by_default(span, ty)
-}
+ fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool {
+ self.fcx.param_env.type_moves_by_default(span, ty)
+ }
}
impl<'blk, 'tcx> ty::UnboxedClosureTyper<'tcx> for BlockS<'blk, 'tcx> {
-fn param_env<'a>(&'a self) -> &'a ty::ParameterEnvironment<'a, 'tcx> {
- &self.fcx.param_env
-}
+ fn param_env<'a>(&'a self) -> &'a ty::ParameterEnvironment<'a, 'tcx> {
+ &self.fcx.param_env
+ }
-fn unboxed_closure_kind(&self,
- def_id: ast::DefId)
- -> ty::UnboxedClosureKind
-{
- let typer = NormalizingUnboxedClosureTyper::new(self.tcx());
- typer.unboxed_closure_kind(def_id)
-}
+ fn unboxed_closure_kind(&self,
+ def_id: ast::DefId)
+ -> ty::UnboxedClosureKind
+ {
+ let typer = NormalizingUnboxedClosureTyper::new(self.tcx());
+ typer.unboxed_closure_kind(def_id)
+ }
-fn unboxed_closure_type(&self,
- def_id: ast::DefId,
- substs: &subst::Substs<'tcx>)
- -> ty::ClosureTy<'tcx>
-{
- let typer = NormalizingUnboxedClosureTyper::new(self.tcx());
- typer.unboxed_closure_type(def_id, substs)
-}
+ fn unboxed_closure_type(&self,
+ def_id: ast::DefId,
+ substs: &subst::Substs<'tcx>)
+ -> ty::ClosureTy<'tcx>
+ {
+ let typer = NormalizingUnboxedClosureTyper::new(self.tcx());
+ typer.unboxed_closure_type(def_id, substs)
+ }
-fn unboxed_closure_upvars(&self,
- def_id: ast::DefId,
- substs: &Substs<'tcx>)
- -> Option<Vec<ty::UnboxedClosureUpvar<'tcx>>>
-{
- let typer = NormalizingUnboxedClosureTyper::new(self.tcx());
- typer.unboxed_closure_upvars(def_id, substs)
-}
+ fn unboxed_closure_upvars(&self,
+ def_id: ast::DefId,
+ substs: &Substs<'tcx>)
+ -> Option<Vec<ty::UnboxedClosureUpvar<'tcx>>>
+ {
+ let typer = NormalizingUnboxedClosureTyper::new(self.tcx());
+ typer.unboxed_closure_upvars(def_id, substs)
+ }
}
pub struct Result<'blk, 'tcx: 'blk> {
-pub bcx: Block<'blk, 'tcx>,
-pub val: ValueRef
+ pub bcx: Block<'blk, 'tcx>,
+ pub val: ValueRef
}
impl<'b, 'tcx> Result<'b, 'tcx> {
-pub fn new(bcx: Block<'b, 'tcx>, val: ValueRef) -> Result<'b, 'tcx> {
- Result {
- bcx: bcx,
- val: val,
+ pub fn new(bcx: Block<'b, 'tcx>, val: ValueRef) -> Result<'b, 'tcx> {
+ Result {
+ bcx: bcx,
+ val: val,
+ }
}
}
-}
pub fn val_ty(v: ValueRef) -> Type {
-unsafe {
- Type::from_ref(llvm::LLVMTypeOf(v))
-}
+ unsafe {
+ Type::from_ref(llvm::LLVMTypeOf(v))
+ }
}
// LLVM constant constructors.
pub fn C_null(t: Type) -> ValueRef {
-unsafe {
- llvm::LLVMConstNull(t.to_ref())
-}
+ unsafe {
+ llvm::LLVMConstNull(t.to_ref())
+ }
}
pub fn C_undef(t: Type) -> ValueRef {
-unsafe {
- llvm::LLVMGetUndef(t.to_ref())
-}
+ unsafe {
+ llvm::LLVMGetUndef(t.to_ref())
+ }
}
pub fn C_integral(t: Type, u: u64, sign_extend: bool) -> ValueRef {
-unsafe {
- llvm::LLVMConstInt(t.to_ref(), u, sign_extend as Bool)
-}
+ unsafe {
+ llvm::LLVMConstInt(t.to_ref(), u, sign_extend as Bool)
+ }
}
pub fn C_floating(s: &str, t: Type) -> ValueRef {
-unsafe {
- let s = CString::from_slice(s.as_bytes());
- llvm::LLVMConstRealOfString(t.to_ref(), s.as_ptr())
-}
+ unsafe {
+ let s = CString::from_slice(s.as_bytes());
+ llvm::LLVMConstRealOfString(t.to_ref(), s.as_ptr())
+ }
}
pub fn C_nil(ccx: &CrateContext) -> ValueRef {
-C_struct(ccx, &[], false)
+ C_struct(ccx, &[], false)
}
pub fn C_bool(ccx: &CrateContext, val: bool) -> ValueRef {
-C_integral(Type::i1(ccx), val as u64, false)
+ C_integral(Type::i1(ccx), val as u64, false)
}
pub fn C_i32(ccx: &CrateContext, i: i32) -> ValueRef {
-C_integral(Type::i32(ccx), i as u64, true)
+ C_integral(Type::i32(ccx), i as u64, true)
}
pub fn C_i64(ccx: &CrateContext, i: i64) -> ValueRef {
-C_integral(Type::i64(ccx), i as u64, true)
+ C_integral(Type::i64(ccx), i as u64, true)
}
pub fn C_u64(ccx: &CrateContext, i: u64) -> ValueRef {
-C_integral(Type::i64(ccx), i, false)
+ C_integral(Type::i64(ccx), i, false)
}
pub fn C_int<I: AsI64>(ccx: &CrateContext, i: I) -> ValueRef {
-let v = i.as_i64();
+ let v = i.as_i64();
-match machine::llbitsize_of_real(ccx, ccx.int_type()) {
- 32 => assert!(v < (1<<31) && v >= -(1<<31)),
- 64 => {},
- n => panic!("unsupported target size: {}", n)
-}
+ match machine::llbitsize_of_real(ccx, ccx.int_type()) {
+ 32 => assert!(v < (1<<31) && v >= -(1<<31)),
+ 64 => {},
+ n => panic!("unsupported target size: {}", n)
+ }
-C_integral(ccx.int_type(), v as u64, true)
+ C_integral(ccx.int_type(), v as u64, true)
}
pub fn C_uint<I: AsU64>(ccx: &CrateContext, i: I) -> ValueRef {
-let v = i.as_u64();
+ let v = i.as_u64();
-match machine::llbitsize_of_real(ccx, ccx.int_type()) {
- 32 => assert!(v < (1<<32)),
- 64 => {},
- n => panic!("unsupported target size: {}", n)
-}
+ match machine::llbitsize_of_real(ccx, ccx.int_type()) {
+ 32 => assert!(v < (1<<32)),
+ 64 => {},
+ n => panic!("unsupported target size: {}", n)
+ }
-C_integral(ccx.int_type(), v, false)
+ C_integral(ccx.int_type(), v, false)
}
pub trait AsI64 { fn as_i64(self) -> i64; }
impl AsU64 for uint { fn as_u64(self) -> u64 { self as u64 }}
pub fn C_u8(ccx: &CrateContext, i: uint) -> ValueRef {
-C_integral(Type::i8(ccx), i as u64, false)
+ C_integral(Type::i8(ccx), i as u64, false)
}
// This is a 'c-like' raw string, which differs from
// our boxed-and-length-annotated strings.
pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> ValueRef {
-unsafe {
- match cx.const_cstr_cache().borrow().get(&s) {
- Some(&llval) => return llval,
- None => ()
- }
+ unsafe {
+ match cx.const_cstr_cache().borrow().get(&s) {
+ Some(&llval) => return llval,
+ None => ()
+ }
- let sc = llvm::LLVMConstStringInContext(cx.llcx(),
- s.get().as_ptr() as *const c_char,
- s.get().len() as c_uint,
- !null_terminated as Bool);
+ let sc = llvm::LLVMConstStringInContext(cx.llcx(),
+ s.get().as_ptr() as *const c_char,
+ s.get().len() as c_uint,
+ !null_terminated as Bool);
- let gsym = token::gensym("str");
- let buf = CString::from_vec(format!("str{}", gsym.uint()).into_bytes());
- let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf.as_ptr());
- llvm::LLVMSetInitializer(g, sc);
- llvm::LLVMSetGlobalConstant(g, True);
- llvm::SetLinkage(g, llvm::InternalLinkage);
+ let gsym = token::gensym("str");
+ let buf = CString::from_vec(format!("str{}", gsym.uint()).into_bytes());
+ let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf.as_ptr());
+ llvm::LLVMSetInitializer(g, sc);
+ llvm::LLVMSetGlobalConstant(g, True);
+ llvm::SetLinkage(g, llvm::InternalLinkage);
- cx.const_cstr_cache().borrow_mut().insert(s, g);
- g
-}
+ cx.const_cstr_cache().borrow_mut().insert(s, g);
+ g
+ }
}
// NB: Do not use `do_spill_noroot` to make this into a constant string, or
// you will be kicked off fast isel. See issue #4352 for an example of this.
pub fn C_str_slice(cx: &CrateContext, s: InternedString) -> ValueRef {
-let len = s.get().len();
-let cs = consts::ptrcast(C_cstr(cx, s, false), Type::i8p(cx));
-C_named_struct(cx.tn().find_type("str_slice").unwrap(), &[cs, C_uint(cx, len)])
+ let len = s.get().len();
+ let cs = consts::ptrcast(C_cstr(cx, s, false), Type::i8p(cx));
+ C_named_struct(cx.tn().find_type("str_slice").unwrap(), &[cs, C_uint(cx, len)])
}
pub fn C_binary_slice(cx: &CrateContext, data: &[u8]) -> ValueRef {
-unsafe {
- let len = data.len();
- let lldata = C_bytes(cx, data);
-
- let gsym = token::gensym("binary");
- let name = format!("binary{}", gsym.uint());
- let name = CString::from_vec(name.into_bytes());
- let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(lldata).to_ref(),
- name.as_ptr());
- llvm::LLVMSetInitializer(g, lldata);
- llvm::LLVMSetGlobalConstant(g, True);
- llvm::SetLinkage(g, llvm::InternalLinkage);
-
- let cs = consts::ptrcast(g, Type::i8p(cx));
- C_struct(cx, &[cs, C_uint(cx, len)], false)
-}
+ unsafe {
+ let len = data.len();
+ let lldata = C_bytes(cx, data);
+
+ let gsym = token::gensym("binary");
+ let name = format!("binary{}", gsym.uint());
+ let name = CString::from_vec(name.into_bytes());
+ let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(lldata).to_ref(),
+ name.as_ptr());
+ llvm::LLVMSetInitializer(g, lldata);
+ llvm::LLVMSetGlobalConstant(g, True);
+ llvm::SetLinkage(g, llvm::InternalLinkage);
+
+ let cs = consts::ptrcast(g, Type::i8p(cx));
+ C_struct(cx, &[cs, C_uint(cx, len)], false)
+ }
}
pub fn C_struct(cx: &CrateContext, elts: &[ValueRef], packed: bool) -> ValueRef {
-C_struct_in_context(cx.llcx(), elts, packed)
+ C_struct_in_context(cx.llcx(), elts, packed)
}
pub fn C_struct_in_context(llcx: ContextRef, elts: &[ValueRef], packed: bool) -> ValueRef {
-unsafe {
- llvm::LLVMConstStructInContext(llcx,
- elts.as_ptr(), elts.len() as c_uint,
- packed as Bool)
-}
+ unsafe {
+ llvm::LLVMConstStructInContext(llcx,
+ elts.as_ptr(), elts.len() as c_uint,
+ packed as Bool)
+ }
}
pub fn C_named_struct(t: Type, elts: &[ValueRef]) -> ValueRef {
-unsafe {
- llvm::LLVMConstNamedStruct(t.to_ref(), elts.as_ptr(), elts.len() as c_uint)
-}
+ unsafe {
+ llvm::LLVMConstNamedStruct(t.to_ref(), elts.as_ptr(), elts.len() as c_uint)
+ }
}
pub fn C_array(ty: Type, elts: &[ValueRef]) -> ValueRef {
-unsafe {
- return llvm::LLVMConstArray(ty.to_ref(), elts.as_ptr(), elts.len() as c_uint);
-}
+ unsafe {
+ return llvm::LLVMConstArray(ty.to_ref(), elts.as_ptr(), elts.len() as c_uint);
+ }
}
pub fn C_bytes(cx: &CrateContext, bytes: &[u8]) -> ValueRef {
-C_bytes_in_context(cx.llcx(), bytes)
+ C_bytes_in_context(cx.llcx(), bytes)
}
pub fn C_bytes_in_context(llcx: ContextRef, bytes: &[u8]) -> ValueRef {
-unsafe {
- let ptr = bytes.as_ptr() as *const c_char;
- return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True);
-}
+ unsafe {
+ let ptr = bytes.as_ptr() as *const c_char;
+ return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True);
+ }
}
pub fn const_get_elt(cx: &CrateContext, v: ValueRef, us: &[c_uint])
-> ValueRef {
-unsafe {
- let r = llvm::LLVMConstExtractValue(v, us.as_ptr(), us.len() as c_uint);
+ unsafe {
+ let r = llvm::LLVMConstExtractValue(v, us.as_ptr(), us.len() as c_uint);
- debug!("const_get_elt(v={}, us={:?}, r={})",
- cx.tn().val_to_string(v), us, cx.tn().val_to_string(r));
+ debug!("const_get_elt(v={}, us={:?}, r={})",
+ cx.tn().val_to_string(v), us, cx.tn().val_to_string(r));
- return r;
-}
+ return r;
+ }
}
pub fn is_const(v: ValueRef) -> bool {
-unsafe {
- llvm::LLVMIsConstant(v) == True
-}
+ unsafe {
+ llvm::LLVMIsConstant(v) == True
+ }
}
pub fn const_to_int(v: ValueRef) -> i64 {
-unsafe {
- llvm::LLVMConstIntGetSExtValue(v)
-}
+ unsafe {
+ llvm::LLVMConstIntGetSExtValue(v)
+ }
}
pub fn const_to_uint(v: ValueRef) -> u64 {
-unsafe {
- llvm::LLVMConstIntGetZExtValue(v)
-}
+ unsafe {
+ llvm::LLVMConstIntGetZExtValue(v)
+ }
}
pub fn is_undef(val: ValueRef) -> bool {
-unsafe {
- llvm::LLVMIsUndef(val) != False
-}
+ unsafe {
+ llvm::LLVMIsUndef(val) != False
+ }
}
#[allow(dead_code)] // potentially useful
pub fn is_null(val: ValueRef) -> bool {
-unsafe {
- llvm::LLVMIsNull(val) != False
-}
+ unsafe {
+ llvm::LLVMIsNull(val) != False
+ }
}
pub fn monomorphize_type<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, t: Ty<'tcx>) -> Ty<'tcx> {
-bcx.fcx.monomorphize(&t)
+ bcx.fcx.monomorphize(&t)
}
pub fn node_id_type<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, id: ast::NodeId) -> Ty<'tcx> {
-let tcx = bcx.tcx();
-let t = ty::node_id_to_type(tcx, id);
-monomorphize_type(bcx, t)
+ let tcx = bcx.tcx();
+ let t = ty::node_id_to_type(tcx, id);
+ monomorphize_type(bcx, t)
}
pub fn expr_ty<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, ex: &ast::Expr) -> Ty<'tcx> {
-node_id_type(bcx, ex.id)
+ node_id_type(bcx, ex.id)
}
pub fn expr_ty_adjusted<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, ex: &ast::Expr) -> Ty<'tcx> {
-monomorphize_type(bcx, ty::expr_ty_adjusted(bcx.tcx(), ex))
+ monomorphize_type(bcx, ty::expr_ty_adjusted(bcx.tcx(), ex))
}
/// Attempts to resolve an obligation. The result is a shallow vtable resolution -- meaning that we
trait_ref: ty::PolyTraitRef<'tcx>)
-> traits::Vtable<'tcx, ()>
{
-let tcx = ccx.tcx();
-
-// Remove any references to regions; this helps improve caching.
-let trait_ref = erase_regions(tcx, &trait_ref);
-
-// First check the cache.
-match ccx.trait_cache().borrow().get(&trait_ref) {
- Some(vtable) => {
- info!("Cache hit: {}", trait_ref.repr(ccx.tcx()));
- return (*vtable).clone();
- }
- None => { }
-}
-
-debug!("trans fulfill_obligation: trait_ref={}", trait_ref.repr(ccx.tcx()));
-
-ty::populate_implementations_for_trait_if_necessary(tcx, trait_ref.def_id());
-let infcx = infer::new_infer_ctxt(tcx);
-
-// Do the initial selection for the obligation. This yields the
-// shallow result we are looking for -- that is, what specific impl.
-let typer = NormalizingUnboxedClosureTyper::new(tcx);
-let mut selcx = traits::SelectionContext::new(&infcx, &typer);
-let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
- trait_ref.to_poly_trait_predicate());
-let selection = match selcx.select(&obligation) {
- Ok(Some(selection)) => selection,
- Ok(None) => {
- // Ambiguity can happen when monomorphizing during trans
- // expands to some humongo type that never occurred
- // statically -- this humongo type can then overflow,
- // leading to an ambiguous result. So report this as an
- // overflow bug, since I believe this is the only case
- // where ambiguity can result.
- debug!("Encountered ambiguity selecting `{}` during trans, \
- presuming due to overflow",
- trait_ref.repr(tcx));
- ccx.sess().span_fatal(
- span,
- "reached the recursion limit during monomorphization");
- }
- Err(e) => {
- tcx.sess.span_bug(
- span,
- &format!("Encountered error `{}` selecting `{}` during trans",
- e.repr(tcx),
- trait_ref.repr(tcx))[])
- }
-};
-
-// Currently, we use a fulfillment context to completely resolve
-// all nested obligations. This is because they can inform the
-// inference of the impl's type parameters.
-let mut fulfill_cx = traits::FulfillmentContext::new();
-let vtable = selection.map_move_nested(|predicate| {
- fulfill_cx.register_predicate_obligation(&infcx, predicate);
-});
-let vtable = drain_fulfillment_cx(span, &infcx, &mut fulfill_cx, &vtable);
-
-info!("Cache miss: {}", trait_ref.repr(ccx.tcx()));
-ccx.trait_cache().borrow_mut().insert(trait_ref,
- vtable.clone());
-
-vtable
+ let tcx = ccx.tcx();
+
+ // Remove any references to regions; this helps improve caching.
+ let trait_ref = erase_regions(tcx, &trait_ref);
+
+ // First check the cache.
+ match ccx.trait_cache().borrow().get(&trait_ref) {
+ Some(vtable) => {
+ info!("Cache hit: {}", trait_ref.repr(ccx.tcx()));
+ return (*vtable).clone();
+ }
+ None => { }
+ }
+
+ debug!("trans fulfill_obligation: trait_ref={}", trait_ref.repr(ccx.tcx()));
+
+ ty::populate_implementations_for_trait_if_necessary(tcx, trait_ref.def_id());
+ let infcx = infer::new_infer_ctxt(tcx);
+
+ // Do the initial selection for the obligation. This yields the
+ // shallow result we are looking for -- that is, what specific impl.
+ let typer = NormalizingUnboxedClosureTyper::new(tcx);
+ let mut selcx = traits::SelectionContext::new(&infcx, &typer);
+ let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
+ trait_ref.to_poly_trait_predicate());
+ let selection = match selcx.select(&obligation) {
+ Ok(Some(selection)) => selection,
+ Ok(None) => {
+ // Ambiguity can happen when monomorphizing during trans
+ // expands to some humongo type that never occurred
+ // statically -- this humongo type can then overflow,
+ // leading to an ambiguous result. So report this as an
+ // overflow bug, since I believe this is the only case
+ // where ambiguity can result.
+ debug!("Encountered ambiguity selecting `{}` during trans, \
+ presuming due to overflow",
+ trait_ref.repr(tcx));
+ ccx.sess().span_fatal(
+ span,
+ "reached the recursion limit during monomorphization");
+ }
+ Err(e) => {
+ tcx.sess.span_bug(
+ span,
+ &format!("Encountered error `{}` selecting `{}` during trans",
+ e.repr(tcx),
+ trait_ref.repr(tcx))[])
+ }
+ };
+
+ // Currently, we use a fulfillment context to completely resolve
+ // all nested obligations. This is because they can inform the
+ // inference of the impl's type parameters.
+ let mut fulfill_cx = traits::FulfillmentContext::new();
+ let vtable = selection.map_move_nested(|predicate| {
+ fulfill_cx.register_predicate_obligation(&infcx, predicate);
+ });
+ let vtable = drain_fulfillment_cx(span, &infcx, &mut fulfill_cx, &vtable);
+
+ info!("Cache miss: {}", trait_ref.repr(ccx.tcx()));
+ ccx.trait_cache().borrow_mut().insert(trait_ref,
+ vtable.clone());
+
+ vtable
}
pub struct NormalizingUnboxedClosureTyper<'a,'tcx:'a> {
-param_env: ty::ParameterEnvironment<'a, 'tcx>
+ param_env: ty::ParameterEnvironment<'a, 'tcx>
}
impl<'a,'tcx> NormalizingUnboxedClosureTyper<'a,'tcx> {
-pub fn new(tcx: &'a ty::ctxt<'tcx>) -> NormalizingUnboxedClosureTyper<'a,'tcx> {
- // Parameter environment is used to give details about type parameters,
- // but since we are in trans, everything is fully monomorphized.
- NormalizingUnboxedClosureTyper { param_env: ty::empty_parameter_environment(tcx) }
-}
+ pub fn new(tcx: &'a ty::ctxt<'tcx>) -> NormalizingUnboxedClosureTyper<'a,'tcx> {
+ // Parameter environment is used to give details about type parameters,
+ // but since we are in trans, everything is fully monomorphized.
+ NormalizingUnboxedClosureTyper { param_env: ty::empty_parameter_environment(tcx) }
+ }
}
impl<'a,'tcx> ty::UnboxedClosureTyper<'tcx> for NormalizingUnboxedClosureTyper<'a,'tcx> {
-fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
- &self.param_env
-}
+ fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> {
+ &self.param_env
+ }
-fn unboxed_closure_kind(&self,
- def_id: ast::DefId)
- -> ty::UnboxedClosureKind
-{
- self.param_env.tcx.unboxed_closure_kind(def_id)
-}
+ fn unboxed_closure_kind(&self,
+ def_id: ast::DefId)
+ -> ty::UnboxedClosureKind
+ {
+ self.param_env.tcx.unboxed_closure_kind(def_id)
+ }
-fn unboxed_closure_type(&self,
- def_id: ast::DefId,
- substs: &subst::Substs<'tcx>)
- -> ty::ClosureTy<'tcx>
-{
- // the substitutions in `substs` are already monomorphized,
- // but we still must normalize associated types
- let closure_ty = self.param_env.tcx.unboxed_closure_type(def_id, substs);
- monomorphize::normalize_associated_type(self.param_env.tcx, &closure_ty)
-}
+ fn unboxed_closure_type(&self,
+ def_id: ast::DefId,
+ substs: &subst::Substs<'tcx>)
+ -> ty::ClosureTy<'tcx>
+ {
+ // the substitutions in `substs` are already monomorphized,
+ // but we still must normalize associated types
+ let closure_ty = self.param_env.tcx.unboxed_closure_type(def_id, substs);
+ monomorphize::normalize_associated_type(self.param_env.tcx, &closure_ty)
+ }
-fn unboxed_closure_upvars(&self,
- def_id: ast::DefId,
- substs: &Substs<'tcx>)
- -> Option<Vec<ty::UnboxedClosureUpvar<'tcx>>>
-{
- // the substitutions in `substs` are already monomorphized,
- // but we still must normalize associated types
- let result = ty::unboxed_closure_upvars(&self.param_env, def_id, substs);
- monomorphize::normalize_associated_type(self.param_env.tcx, &result)
-}
+ fn unboxed_closure_upvars(&self,
+ def_id: ast::DefId,
+ substs: &Substs<'tcx>)
+ -> Option<Vec<ty::UnboxedClosureUpvar<'tcx>>>
+ {
+ // the substitutions in `substs` are already monomorphized,
+ // but we still must normalize associated types
+ let result = ty::unboxed_closure_upvars(&self.param_env, def_id, substs);
+ monomorphize::normalize_associated_type(self.param_env.tcx, &result)
+ }
}
pub fn drain_fulfillment_cx<'a,'tcx,T>(span: Span,
fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
result: &T)
-> T
-where T : TypeFoldable<'tcx> + Repr<'tcx>
+ where T : TypeFoldable<'tcx> + Repr<'tcx>
{
-debug!("drain_fulfillment_cx(result={})",
- result.repr(infcx.tcx));
-
-// In principle, we only need to do this so long as `result`
-// contains unbound type parameters. It could be a slight
-// optimization to stop iterating early.
-let typer = NormalizingUnboxedClosureTyper::new(infcx.tcx);
-match fulfill_cx.select_all_or_error(infcx, &typer) {
- Ok(()) => { }
- Err(errors) => {
- if errors.iter().all(|e| e.is_overflow()) {
- // See Ok(None) case above.
- infcx.tcx.sess.span_fatal(
- span,
- "reached the recursion limit during monomorphization");
- } else {
- infcx.tcx.sess.span_bug(
- span,
- &format!("Encountered errors `{}` fulfilling during trans",
- errors.repr(infcx.tcx))[]);
+ debug!("drain_fulfillment_cx(result={})",
+ result.repr(infcx.tcx));
+
+ // In principle, we only need to do this so long as `result`
+ // contains unbound type parameters. It could be a slight
+ // optimization to stop iterating early.
+ let typer = NormalizingUnboxedClosureTyper::new(infcx.tcx);
+ match fulfill_cx.select_all_or_error(infcx, &typer) {
+ Ok(()) => { }
+ Err(errors) => {
+ if errors.iter().all(|e| e.is_overflow()) {
+ // See Ok(None) case above.
+ infcx.tcx.sess.span_fatal(
+ span,
+ "reached the recursion limit during monomorphization");
+ } else {
+ infcx.tcx.sess.span_bug(
+ span,
+ &format!("Encountered errors `{}` fulfilling during trans",
+ errors.repr(infcx.tcx))[]);
+ }
}
}
-}
-// Use freshen to simultaneously replace all type variables with
-// their bindings and replace all regions with 'static. This is
-// sort of overkill because we do not expect there to be any
-// unbound type variables, hence no `TyFresh` types should ever be
-// inserted.
-result.fold_with(&mut infcx.freshener())
+ // Use freshen to simultaneously replace all type variables with
+ // their bindings and replace all regions with 'static. This is
+ // sort of overkill because we do not expect there to be any
+ // unbound type variables, hence no `TyFresh` types should ever be
+ // inserted.
+ result.fold_with(&mut infcx.freshener())
}
// Key used to lookup values supplied for type parameters in an expr.
#[derive(Copy, PartialEq, Show)]
pub enum ExprOrMethodCall {
-// Type parameters for a path like `None::<int>`
-ExprId(ast::NodeId),
+ // Type parameters for a path like `None::<int>`
+ ExprId(ast::NodeId),
-// Type parameters for a method call like `a.foo::<int>()`
-MethodCallKey(ty::MethodCall)
+ // Type parameters for a method call like `a.foo::<int>()`
+ MethodCallKey(ty::MethodCall)
}
pub fn node_id_substs<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
node: ExprOrMethodCall,
param_substs: &subst::Substs<'tcx>)
-> subst::Substs<'tcx> {
-let tcx = ccx.tcx();
+ let tcx = ccx.tcx();
-let substs = match node {
- ExprId(id) => {
- ty::node_id_item_substs(tcx, id).substs
- }
- MethodCallKey(method_call) => {
- (*tcx.method_map.borrow())[method_call].substs.clone()
- }
-};
+ let substs = match node {
+ ExprId(id) => {
+ ty::node_id_item_substs(tcx, id).substs
+ }
+ MethodCallKey(method_call) => {
+ (*tcx.method_map.borrow())[method_call].substs.clone()
+ }
+ };
-if substs.types.any(|t| ty::type_needs_infer(*t)) {
- tcx.sess.bug(&format!("type parameters for node {:?} include inference types: {:?}",
- node, substs.repr(tcx))[]);
- }
+ if substs.types.any(|t| ty::type_needs_infer(*t)) {
+ tcx.sess.bug(&format!("type parameters for node {:?} include inference types: {:?}",
+ node, substs.repr(tcx))[]);
+ }
- monomorphize::apply_param_substs(tcx,
- param_substs,
- &substs.erase_regions())
+ monomorphize::apply_param_substs(tcx,
+ param_substs,
+ &substs.erase_regions())
}
pub fn langcall(bcx: Block,