2013-04-10 07:47:22 -05:00
|
|
|
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 18:48:01 -06:00
|
|
|
// 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.
|
|
|
|
|
2013-05-17 17:28:44 -05:00
|
|
|
//! Code that is useful in various trans modules.
|
2013-01-07 16:16:52 -06:00
|
|
|
|
2013-05-17 17:28:44 -05:00
|
|
|
use core::prelude::*;
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2012-12-23 16:41:37 -06:00
|
|
|
use driver::session;
|
|
|
|
use driver::session::Session;
|
2013-06-16 06:11:17 -05:00
|
|
|
use lib::llvm::{ValueRef, BasicBlockRef, BuilderRef};
|
2013-06-12 21:49:01 -05:00
|
|
|
use lib::llvm::{True, False, Bool};
|
2013-06-16 06:11:17 -05:00
|
|
|
use lib::llvm::{llvm};
|
2012-12-23 16:41:37 -06:00
|
|
|
use lib;
|
|
|
|
use middle::trans::base;
|
|
|
|
use middle::trans::build;
|
|
|
|
use middle::trans::datum;
|
|
|
|
use middle::trans::glue;
|
2013-05-04 13:29:32 -05:00
|
|
|
use middle::trans::write_guard;
|
2013-01-25 18:57:39 -06:00
|
|
|
use middle::ty::substs;
|
2012-12-23 16:41:37 -06:00
|
|
|
use middle::ty;
|
|
|
|
use middle::typeck;
|
2013-05-04 13:29:32 -05:00
|
|
|
use middle::borrowck::root_map_key;
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-09 00:54:49 -05:00
|
|
|
use util::ppaux::{Repr};
|
2012-12-23 16:41:37 -06:00
|
|
|
|
2013-06-16 05:52:44 -05:00
|
|
|
use middle::trans::type_::Type;
|
|
|
|
|
2013-04-28 12:53:42 -05:00
|
|
|
use core::cast::transmute;
|
2013-05-24 21:35:29 -05:00
|
|
|
use core::cast;
|
2013-06-12 21:49:01 -05:00
|
|
|
use core::hashmap::{HashMap};
|
2013-02-18 16:16:21 -06:00
|
|
|
use core::libc::{c_uint, c_longlong, c_ulonglong};
|
2012-12-23 16:41:37 -06:00
|
|
|
use core::to_bytes;
|
2013-05-24 21:35:29 -05:00
|
|
|
use core::vec;
|
2012-12-23 16:41:37 -06:00
|
|
|
use syntax::ast::ident;
|
2013-03-10 10:02:16 -05:00
|
|
|
use syntax::ast_map::{path, path_elt};
|
2012-12-23 16:41:37 -06:00
|
|
|
use syntax::codemap::span;
|
2013-06-04 14:34:25 -05:00
|
|
|
use syntax::parse::token;
|
2012-12-23 16:41:37 -06:00
|
|
|
use syntax::{ast, ast_map};
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2013-06-12 21:02:33 -05:00
|
|
|
pub use middle::trans::context::CrateContext;
|
|
|
|
|
2013-06-21 03:28:33 -05:00
|
|
|
pub fn gensym_name(name: &str) -> ident {
|
|
|
|
token::str_to_ident(fmt!("%s_%u", name, token::gensym(name)))
|
2011-07-21 19:27:34 -05:00
|
|
|
}
|
|
|
|
|
2013-02-04 16:02:01 -06:00
|
|
|
pub struct tydesc_info {
|
|
|
|
ty: ty::t,
|
|
|
|
tydesc: ValueRef,
|
|
|
|
size: ValueRef,
|
|
|
|
align: ValueRef,
|
|
|
|
take_glue: Option<ValueRef>,
|
|
|
|
drop_glue: Option<ValueRef>,
|
|
|
|
free_glue: Option<ValueRef>,
|
|
|
|
visit_glue: Option<ValueRef>
|
|
|
|
}
|
2011-07-21 19:27:34 -05:00
|
|
|
|
|
|
|
/*
|
2012-06-26 18:18:37 -05:00
|
|
|
* A note on nomenclature of linking: "extern", "foreign", and "upcall".
|
2011-07-21 19:27:34 -05:00
|
|
|
*
|
|
|
|
* An "extern" is an LLVM symbol we wind up emitting an undefined external
|
|
|
|
* reference to. This means "we don't have the thing in this compilation unit,
|
|
|
|
* please make sure you link it in at runtime". This could be a reference to
|
|
|
|
* C code found in a C library, or rust code found in a rust crate.
|
|
|
|
*
|
2012-06-26 18:18:37 -05:00
|
|
|
* Most "externs" are implicitly declared (automatically) as a result of a
|
|
|
|
* user declaring an extern _module_ dependency; this causes the rust driver
|
|
|
|
* to locate an extern crate, scan its compilation metadata, and emit extern
|
|
|
|
* declarations for any symbols used by the declaring crate.
|
2011-07-21 19:27:34 -05:00
|
|
|
*
|
2012-06-26 18:18:37 -05:00
|
|
|
* A "foreign" is an extern that references C (or other non-rust ABI) code.
|
|
|
|
* There is no metadata to scan for extern references so in these cases either
|
|
|
|
* a header-digester like bindgen, or manual function prototypes, have to
|
|
|
|
* serve as declarators. So these are usually given explicitly as prototype
|
|
|
|
* declarations, in rust code, with ABI attributes on them noting which ABI to
|
|
|
|
* link via.
|
|
|
|
*
|
|
|
|
* An "upcall" is a foreign call generated by the compiler (not corresponding
|
|
|
|
* to any user-written call in the code) into the runtime library, to perform
|
|
|
|
* some helper task such as bringing a task to life, allocating memory, etc.
|
2011-07-21 19:27:34 -05:00
|
|
|
*
|
|
|
|
*/
|
2012-03-22 15:44:20 -05:00
|
|
|
|
2013-02-04 16:02:01 -06:00
|
|
|
pub struct Stats {
|
|
|
|
n_static_tydescs: uint,
|
|
|
|
n_glues_created: uint,
|
|
|
|
n_null_glues: uint,
|
|
|
|
n_real_glues: uint,
|
|
|
|
n_fns: uint,
|
|
|
|
n_monos: uint,
|
|
|
|
n_inlines: uint,
|
|
|
|
n_closures: uint,
|
2013-06-13 02:19:50 -05:00
|
|
|
llvm_insns: HashMap<~str, uint>,
|
|
|
|
fn_times: ~[(~str, int)] // (ident, time)
|
2013-02-04 16:02:01 -06:00
|
|
|
}
|
2011-07-21 19:27:34 -05:00
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub struct BuilderRef_res {
|
2012-09-06 21:40:15 -05:00
|
|
|
B: BuilderRef,
|
2013-02-27 18:13:53 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for BuilderRef_res {
|
2013-06-20 20:06:13 -05:00
|
|
|
fn drop(&self) {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
llvm::LLVMDisposeBuilder(self.B);
|
|
|
|
}
|
|
|
|
}
|
2012-06-22 13:53:25 -05:00
|
|
|
}
|
2011-08-24 09:30:20 -05:00
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn BuilderRef_res(B: BuilderRef) -> BuilderRef_res {
|
2012-09-05 17:58:43 -05:00
|
|
|
BuilderRef_res {
|
|
|
|
B: B
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-13 02:19:50 -05:00
|
|
|
pub type ExternMap = HashMap<@str, ValueRef>;
|
2013-02-04 17:30:32 -06:00
|
|
|
|
2011-07-21 19:27:34 -05:00
|
|
|
// Types used for llself.
|
2013-01-30 13:46:19 -06:00
|
|
|
pub struct ValSelfData {
|
2012-09-07 16:50:47 -05:00
|
|
|
v: ValueRef,
|
|
|
|
t: ty::t,
|
|
|
|
is_owned: bool
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
2011-07-21 19:27:34 -05:00
|
|
|
|
2012-10-08 14:39:30 -05:00
|
|
|
// Here `self_ty` is the real type of the self parameter to this method. It
|
|
|
|
// will only be set in the case of default methods.
|
2013-01-30 13:46:19 -06:00
|
|
|
pub struct param_substs {
|
2013-01-06 13:16:14 -06:00
|
|
|
tys: ~[ty::t],
|
|
|
|
vtables: Option<typeck::vtable_res>,
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-09 00:54:49 -05:00
|
|
|
type_param_defs: @~[ty::TypeParameterDef],
|
2013-01-06 13:16:14 -06:00
|
|
|
self_ty: Option<ty::t>
|
|
|
|
}
|
2012-02-09 04:17:11 -06:00
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
impl param_substs {
|
|
|
|
pub fn validate(&self) {
|
2013-06-21 07:29:53 -05:00
|
|
|
for self.tys.iter().advance |t| { assert!(!ty::type_needs_infer(*t)); }
|
2013-06-10 16:50:12 -05:00
|
|
|
for self.self_ty.iter().advance |t| { assert!(!ty::type_needs_infer(*t)); }
|
2013-03-21 07:34:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-10 17:15:06 -05:00
|
|
|
fn param_substs_to_str(this: ¶m_substs, tcx: ty::ctxt) -> ~str {
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-09 00:54:49 -05:00
|
|
|
fmt!("param_substs {tys:%s, vtables:%s, type_param_defs:%s}",
|
2013-05-10 17:15:06 -05:00
|
|
|
this.tys.repr(tcx),
|
|
|
|
this.vtables.repr(tcx),
|
|
|
|
this.type_param_defs.repr(tcx))
|
2012-09-10 14:25:45 -05:00
|
|
|
}
|
|
|
|
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-09 00:54:49 -05:00
|
|
|
impl Repr for param_substs {
|
|
|
|
fn repr(&self, tcx: ty::ctxt) -> ~str {
|
|
|
|
param_substs_to_str(self, tcx)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Repr for @param_substs {
|
|
|
|
fn repr(&self, tcx: ty::ctxt) -> ~str {
|
|
|
|
param_substs_to_str(*self, tcx)
|
|
|
|
}
|
2013-03-21 07:33:52 -05:00
|
|
|
}
|
|
|
|
|
2011-08-03 17:39:43 -05:00
|
|
|
// Function context. Every LLVM function we create will have one of
|
|
|
|
// these.
|
2013-01-30 13:46:19 -06:00
|
|
|
pub struct fn_ctxt_ {
|
2011-07-27 07:19:39 -05:00
|
|
|
// The ValueRef returned from a call to llvm::LLVMAddFunction; the
|
2011-08-03 17:39:43 -05:00
|
|
|
// 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.
|
2012-02-03 06:37:55 -06:00
|
|
|
llfn: ValueRef,
|
2011-07-27 07:19:39 -05:00
|
|
|
|
2013-04-18 17:53:29 -05:00
|
|
|
// The implicit environment argument that arrives in the function we're
|
|
|
|
// creating.
|
2012-02-03 06:37:55 -06:00
|
|
|
llenv: ValueRef,
|
2013-04-18 17:53:29 -05:00
|
|
|
|
|
|
|
// The place to store the return value. If the return type is immediate,
|
|
|
|
// this is an alloca in the function. Otherwise, it's the hidden first
|
|
|
|
// parameter to the function. After function construction, this should
|
|
|
|
// always be Some.
|
|
|
|
llretptr: Option<ValueRef>,
|
2011-07-27 07:19:39 -05:00
|
|
|
|
2012-02-03 06:37:55 -06:00
|
|
|
// These elements: "hoisted basic blocks" containing
|
2011-07-27 07:19:39 -05:00
|
|
|
// administrative activities that have to happen in only one place in
|
|
|
|
// the function, due to LLVM's quirks.
|
2011-08-03 17:39:43 -05:00
|
|
|
// A block for all the function's static allocas, so that LLVM
|
|
|
|
// will coalesce them into a single alloca call.
|
2013-02-21 17:30:24 -06:00
|
|
|
llstaticallocas: BasicBlockRef,
|
2011-07-27 07:19:39 -05:00
|
|
|
// A block containing code that copies incoming arguments to space
|
2011-08-03 17:39:43 -05:00
|
|
|
// already allocated by code in one of the llallocas blocks.
|
|
|
|
// (LLVM requires that arguments be copied to local allocas before
|
|
|
|
// allowing most any operation to be performed on them.)
|
2013-02-21 17:30:24 -06:00
|
|
|
llloadenv: Option<BasicBlockRef>,
|
|
|
|
llreturn: BasicBlockRef,
|
2012-01-13 03:58:31 -06:00
|
|
|
// The 'self' value currently in use in this function, if there
|
2011-08-03 17:39:43 -05:00
|
|
|
// is one.
|
2012-10-08 14:39:30 -05:00
|
|
|
//
|
|
|
|
// NB: This is the type of the self *variable*, not the self *type*. The
|
|
|
|
// self type is set only for default methods, while the self variable is
|
|
|
|
// set for all methods.
|
2013-02-21 17:30:24 -06:00
|
|
|
llself: Option<ValSelfData>,
|
2012-02-15 06:57:29 -06:00
|
|
|
// The a value alloca'd for calls to upcalls.rust_personality. Used when
|
|
|
|
// outputting the resume instruction.
|
2013-02-21 17:30:24 -06:00
|
|
|
personality: Option<ValueRef>,
|
2012-03-27 05:33:13 -05:00
|
|
|
// If this is a for-loop body that returns, this holds the pointers needed
|
2013-02-19 01:40:42 -06:00
|
|
|
// for that (flagptr, retptr)
|
2013-02-21 17:30:24 -06:00
|
|
|
loop_ret: Option<(ValueRef, ValueRef)>,
|
2011-07-27 07:19:39 -05:00
|
|
|
|
2013-04-18 17:53:29 -05:00
|
|
|
// True if this function has an immediate return value, false otherwise.
|
|
|
|
// If this is false, the llretptr will alias the first argument of the
|
|
|
|
// function.
|
|
|
|
has_immediate_return_value: bool,
|
|
|
|
|
2011-07-27 07:19:39 -05:00
|
|
|
// Maps arguments to allocas created for them in llallocas.
|
2013-05-29 16:44:19 -05:00
|
|
|
llargs: @mut HashMap<ast::node_id, ValueRef>,
|
2011-07-27 07:19:39 -05:00
|
|
|
// Maps the def_ids for local variables to the allocas created for
|
|
|
|
// them in llallocas.
|
2013-05-29 16:44:19 -05:00
|
|
|
lllocals: @mut HashMap<ast::node_id, ValueRef>,
|
2012-02-03 06:37:55 -06:00
|
|
|
// Same as above, but for closure upvars
|
2013-04-03 08:28:36 -05:00
|
|
|
llupvars: @mut HashMap<ast::node_id, ValueRef>,
|
2011-07-27 07:19:39 -05:00
|
|
|
|
2011-08-03 17:39:43 -05:00
|
|
|
// The node_id of the function, or -1 if it doesn't correspond to
|
|
|
|
// a user-defined function.
|
2012-02-03 06:37:55 -06:00
|
|
|
id: ast::node_id,
|
|
|
|
|
2012-10-08 14:39:30 -05:00
|
|
|
// The def_id of the impl we're inside, or None if we aren't inside one.
|
|
|
|
impl_id: Option<ast::def_id>,
|
|
|
|
|
2012-02-03 06:37:55 -06:00
|
|
|
// If this function is being monomorphized, this contains the type
|
|
|
|
// substitutions used.
|
2013-02-18 14:36:30 -06:00
|
|
|
param_substs: Option<@param_substs>,
|
2012-02-03 06:37:55 -06:00
|
|
|
|
|
|
|
// The source span and nesting context where this function comes from, for
|
|
|
|
// error reporting and symbol generation.
|
2012-08-20 14:23:37 -05:00
|
|
|
span: Option<span>,
|
2012-02-03 06:37:55 -06:00
|
|
|
path: path,
|
2011-08-02 17:13:08 -05:00
|
|
|
|
2012-02-03 06:37:55 -06:00
|
|
|
// This function's enclosing crate context.
|
2013-06-13 02:19:50 -05:00
|
|
|
ccx: @mut CrateContext
|
2013-01-06 13:16:14 -06:00
|
|
|
}
|
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
impl fn_ctxt_ {
|
2013-05-27 20:33:57 -05:00
|
|
|
pub fn arg_pos(&self, arg: uint) -> uint {
|
|
|
|
if self.has_immediate_return_value {
|
|
|
|
arg + 1u
|
|
|
|
} else {
|
|
|
|
arg + 2u
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn out_arg_pos(&self) -> uint {
|
|
|
|
assert!(self.has_immediate_return_value);
|
|
|
|
0u
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn env_arg_pos(&self) -> uint {
|
|
|
|
if !self.has_immediate_return_value {
|
|
|
|
1u
|
|
|
|
} else {
|
|
|
|
0u
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-02-21 17:30:24 -06:00
|
|
|
pub type fn_ctxt = @mut fn_ctxt_;
|
2011-07-21 19:27:34 -05:00
|
|
|
|
2013-06-13 02:19:50 -05:00
|
|
|
pub fn warn_not_to_commit(ccx: &mut CrateContext, msg: &str) {
|
|
|
|
if !ccx.do_not_commit_warning_issued {
|
|
|
|
ccx.do_not_commit_warning_issued = true;
|
2013-05-23 11:09:11 -05:00
|
|
|
ccx.sess.warn(msg.to_str() + " -- do not commit like this!");
|
2012-02-01 20:52:08 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-26 15:50:43 -05:00
|
|
|
// Heap selectors. Indicate which heap something should go on.
|
2013-03-20 10:40:02 -05:00
|
|
|
#[deriving(Eq)]
|
2013-01-30 13:46:19 -06:00
|
|
|
pub enum heap {
|
2013-02-20 17:02:21 -06:00
|
|
|
heap_managed,
|
|
|
|
heap_managed_unique,
|
2012-06-26 15:50:43 -05:00
|
|
|
heap_exchange,
|
|
|
|
}
|
|
|
|
|
2013-03-20 10:40:02 -05:00
|
|
|
#[deriving(Eq)]
|
2013-01-30 13:46:19 -06:00
|
|
|
pub enum cleantype {
|
2012-03-23 19:52:20 -05:00
|
|
|
normal_exit_only,
|
|
|
|
normal_exit_and_unwind
|
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub enum cleanup {
|
2013-03-01 14:11:07 -06:00
|
|
|
clean(@fn(block) -> block, cleantype),
|
|
|
|
clean_temp(ValueRef, @fn(block) -> block, cleantype),
|
2011-07-21 19:27:34 -05:00
|
|
|
}
|
|
|
|
|
2012-02-15 06:57:29 -06:00
|
|
|
// Used to remember and reuse existing cleanup paths
|
|
|
|
// target: none means the path ends in an resume instruction
|
2013-02-19 01:40:42 -06:00
|
|
|
pub struct cleanup_path {
|
|
|
|
target: Option<BasicBlockRef>,
|
2013-06-16 07:51:50 -05:00
|
|
|
size: uint,
|
2013-02-19 01:40:42 -06:00
|
|
|
dest: BasicBlockRef
|
|
|
|
}
|
2012-02-15 06:57:29 -06:00
|
|
|
|
2013-06-16 07:51:50 -05:00
|
|
|
pub fn shrink_scope_clean(scope_info: &mut scope_info, size: uint) {
|
|
|
|
scope_info.landing_pad = None;
|
|
|
|
scope_info.cleanup_paths = scope_info.cleanup_paths.iter()
|
|
|
|
.take_while(|&cu| cu.size <= size).transform(|&x|x).collect();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn grow_scope_clean(scope_info: &mut scope_info) {
|
2012-11-06 20:41:06 -06:00
|
|
|
scope_info.landing_pad = None;
|
2012-02-15 06:57:29 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn cleanup_type(cx: ty::ctxt, ty: ty::t) -> cleantype {
|
2012-03-23 19:52:20 -05:00
|
|
|
if ty::type_needs_unwind_cleanup(cx, ty) {
|
|
|
|
normal_exit_and_unwind
|
|
|
|
} else {
|
|
|
|
normal_exit_only
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn add_clean(bcx: block, val: ValueRef, t: ty::t) {
|
2012-08-06 12:53:38 -05:00
|
|
|
if !ty::type_needs_drop(bcx.tcx(), t) { return; }
|
2013-06-16 05:52:44 -05:00
|
|
|
|
|
|
|
debug!("add_clean(%s, %s, %s)", bcx.to_str(), bcx.val_to_str(val), t.repr(bcx.tcx()));
|
|
|
|
|
2012-08-06 12:53:38 -05:00
|
|
|
let cleanup_type = cleanup_type(bcx.tcx(), t);
|
2012-11-06 20:41:06 -06:00
|
|
|
do in_scope_cx(bcx) |scope_info| {
|
2013-06-16 05:52:44 -05:00
|
|
|
scope_info.cleanups.push(clean(|a| glue::drop_ty(a, val, t), cleanup_type));
|
2013-06-16 07:51:50 -05:00
|
|
|
grow_scope_clean(scope_info);
|
2012-02-17 04:18:14 -06:00
|
|
|
}
|
2011-07-21 19:27:34 -05:00
|
|
|
}
|
2012-08-28 17:54:45 -05:00
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn add_clean_temp_immediate(cx: block, val: ValueRef, ty: ty::t) {
|
2012-08-01 19:30:05 -05:00
|
|
|
if !ty::type_needs_drop(cx.tcx(), ty) { return; }
|
2012-08-06 12:53:38 -05:00
|
|
|
debug!("add_clean_temp_immediate(%s, %s, %s)",
|
2013-06-14 22:16:03 -05:00
|
|
|
cx.to_str(), cx.val_to_str(val),
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-09 00:54:49 -05:00
|
|
|
ty.repr(cx.tcx()));
|
2012-03-23 19:52:20 -05:00
|
|
|
let cleanup_type = cleanup_type(cx.tcx(), ty);
|
2012-11-06 20:41:06 -06:00
|
|
|
do in_scope_cx(cx) |scope_info| {
|
|
|
|
scope_info.cleanups.push(
|
2012-09-26 19:33:34 -05:00
|
|
|
clean_temp(val, |a| glue::drop_ty_immediate(a, val, ty),
|
|
|
|
cleanup_type));
|
2013-06-16 07:51:50 -05:00
|
|
|
grow_scope_clean(scope_info);
|
2012-02-17 04:18:14 -06:00
|
|
|
}
|
2011-07-21 19:27:34 -05:00
|
|
|
}
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn add_clean_temp_mem(bcx: block, val: ValueRef, t: ty::t) {
|
2012-08-06 12:53:38 -05:00
|
|
|
if !ty::type_needs_drop(bcx.tcx(), t) { return; }
|
2012-08-22 19:24:52 -05:00
|
|
|
debug!("add_clean_temp_mem(%s, %s, %s)",
|
2013-06-14 22:16:03 -05:00
|
|
|
bcx.to_str(), bcx.val_to_str(val),
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-09 00:54:49 -05:00
|
|
|
t.repr(bcx.tcx()));
|
2012-08-06 12:53:38 -05:00
|
|
|
let cleanup_type = cleanup_type(bcx.tcx(), t);
|
2012-11-06 20:41:06 -06:00
|
|
|
do in_scope_cx(bcx) |scope_info| {
|
2013-06-16 05:52:44 -05:00
|
|
|
scope_info.cleanups.push(clean_temp(val, |a| glue::drop_ty(a, val, t), cleanup_type));
|
2013-06-16 07:51:50 -05:00
|
|
|
grow_scope_clean(scope_info);
|
2013-01-11 23:01:42 -06:00
|
|
|
}
|
|
|
|
}
|
2013-05-01 12:48:00 -05:00
|
|
|
pub fn add_clean_return_to_mut(bcx: block,
|
2013-05-04 13:29:32 -05:00
|
|
|
root_key: root_map_key,
|
2013-05-01 12:48:00 -05:00
|
|
|
frozen_val_ref: ValueRef,
|
2013-05-01 20:46:34 -05:00
|
|
|
bits_val_ref: ValueRef,
|
|
|
|
filename_val: ValueRef,
|
|
|
|
line_val: ValueRef) {
|
2013-05-01 12:48:00 -05:00
|
|
|
//! When an `@mut` has been frozen, we have to
|
|
|
|
//! call the lang-item `return_to_mut` when the
|
|
|
|
//! freeze goes out of scope. We need to pass
|
|
|
|
//! in both the value which was frozen (`frozen_val`) and
|
|
|
|
//! the value (`bits_val_ref`) which was returned when the
|
|
|
|
//! box was frozen initially. Here, both `frozen_val_ref` and
|
|
|
|
//! `bits_val_ref` are in fact pointers to stack slots.
|
|
|
|
|
|
|
|
debug!("add_clean_return_to_mut(%s, %s, %s)",
|
|
|
|
bcx.to_str(),
|
2013-06-14 22:16:03 -05:00
|
|
|
bcx.val_to_str(frozen_val_ref),
|
|
|
|
bcx.val_to_str(bits_val_ref));
|
2013-01-11 23:01:42 -06:00
|
|
|
do in_scope_cx(bcx) |scope_info| {
|
|
|
|
scope_info.cleanups.push(
|
2013-05-01 12:48:00 -05:00
|
|
|
clean_temp(
|
|
|
|
frozen_val_ref,
|
2013-06-16 05:52:44 -05:00
|
|
|
|bcx| write_guard::return_to_mut(bcx, root_key, frozen_val_ref, bits_val_ref,
|
|
|
|
filename_val, line_val),
|
2013-05-01 12:48:00 -05:00
|
|
|
normal_exit_only));
|
2013-06-16 07:51:50 -05:00
|
|
|
grow_scope_clean(scope_info);
|
2012-02-17 04:18:14 -06:00
|
|
|
}
|
2011-09-26 15:13:08 -05:00
|
|
|
}
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn add_clean_free(cx: block, ptr: ValueRef, heap: heap) {
|
2012-08-06 14:34:08 -05:00
|
|
|
let free_fn = match heap {
|
2013-02-20 17:02:21 -06:00
|
|
|
heap_managed | heap_managed_unique => {
|
2013-01-15 18:33:20 -06:00
|
|
|
let f: @fn(block) -> block = |a| glue::trans_free(a, ptr);
|
|
|
|
f
|
|
|
|
}
|
|
|
|
heap_exchange => {
|
2013-02-20 17:02:21 -06:00
|
|
|
let f: @fn(block) -> block = |a| glue::trans_exchange_free(a, ptr);
|
2013-01-15 18:33:20 -06:00
|
|
|
f
|
|
|
|
}
|
2012-06-26 15:50:43 -05:00
|
|
|
};
|
2012-11-06 20:41:06 -06:00
|
|
|
do in_scope_cx(cx) |scope_info| {
|
|
|
|
scope_info.cleanups.push(clean_temp(ptr, free_fn,
|
2012-09-26 19:33:34 -05:00
|
|
|
normal_exit_and_unwind));
|
2013-06-16 07:51:50 -05:00
|
|
|
grow_scope_clean(scope_info);
|
2012-02-17 04:18:14 -06:00
|
|
|
}
|
2011-09-27 06:19:55 -05:00
|
|
|
}
|
2011-07-21 19:27:34 -05:00
|
|
|
|
|
|
|
// Note that this only works for temporaries. We should, at some point, move
|
|
|
|
// to a system where we can also cancel the cleanup on local variables, but
|
|
|
|
// this will be more involved. For now, we simply zero out the local, and the
|
|
|
|
// drop glue checks whether it is zero.
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn revoke_clean(cx: block, val: ValueRef) {
|
2012-11-06 20:41:06 -06:00
|
|
|
do in_scope_cx(cx) |scope_info| {
|
2013-06-18 21:59:48 -05:00
|
|
|
let cleanup_pos = scope_info.cleanups.iter().position_(
|
2012-09-28 00:20:47 -05:00
|
|
|
|cu| match *cu {
|
2012-08-28 17:54:45 -05:00
|
|
|
clean_temp(v, _, _) if v == val => true,
|
|
|
|
_ => false
|
|
|
|
});
|
2013-06-10 16:50:12 -05:00
|
|
|
for cleanup_pos.iter().advance |i| {
|
2012-11-06 20:41:06 -06:00
|
|
|
scope_info.cleanups =
|
2013-06-27 04:48:50 -05:00
|
|
|
vec::append(scope_info.cleanups.slice(0u, *i).to_owned(),
|
|
|
|
scope_info.cleanups.slice(*i + 1u,
|
|
|
|
scope_info.cleanups.len()));
|
2013-06-16 07:51:50 -05:00
|
|
|
shrink_scope_clean(scope_info, *i);
|
2011-07-21 19:27:34 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn block_cleanups(bcx: block) -> ~[cleanup] {
|
2013-05-02 20:15:36 -05:00
|
|
|
match bcx.kind {
|
2012-08-23 19:39:07 -05:00
|
|
|
block_non_scope => ~[],
|
2013-05-02 20:15:36 -05:00
|
|
|
block_scope(inf) => /*bad*/copy inf.cleanups
|
2012-08-23 19:39:07 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub enum block_kind {
|
2012-01-28 13:49:21 -06:00
|
|
|
// A scope at the end of which temporary values created inside of it are
|
|
|
|
// cleaned up. May correspond to an actual block in the language, but also
|
|
|
|
// to an implicit scope, for example, calls introduce an implicit scope in
|
|
|
|
// which the arguments are evaluated and cleaned up.
|
2013-05-02 20:15:36 -05:00
|
|
|
block_scope(@mut scope_info),
|
2012-08-28 17:54:45 -05:00
|
|
|
|
2011-07-21 19:27:34 -05:00
|
|
|
// A non-scope block is a basic block created as a translation artifact
|
|
|
|
// from translating code that expresses conditional logic rather than by
|
|
|
|
// explicit { ... } block structure in the source language. It's called a
|
|
|
|
// non-scope block because it doesn't introduce a new variable scope.
|
2012-02-17 06:17:40 -06:00
|
|
|
block_non_scope,
|
2011-07-21 19:27:34 -05:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub struct scope_info {
|
2012-08-20 14:23:37 -05:00
|
|
|
loop_break: Option<block>,
|
2012-10-18 14:20:18 -05:00
|
|
|
loop_label: Option<ident>,
|
2012-02-17 04:18:14 -06:00
|
|
|
// A list of functions that must be run at when leaving this
|
|
|
|
// block, cleaning up any variables that were introduced in the
|
|
|
|
// block.
|
2013-02-21 13:57:20 -06:00
|
|
|
cleanups: ~[cleanup],
|
2012-02-17 04:18:14 -06:00
|
|
|
// Existing cleanup paths that may be reused, indexed by destination and
|
|
|
|
// cleared when the set of cleanups changes.
|
2013-02-21 13:57:20 -06:00
|
|
|
cleanup_paths: ~[cleanup_path],
|
2012-02-17 04:18:14 -06:00
|
|
|
// Unwinding landing pad. Also cleared when cleanups change.
|
2013-02-21 13:57:20 -06:00
|
|
|
landing_pad: Option<BasicBlockRef>,
|
2013-01-06 13:16:14 -06:00
|
|
|
}
|
2012-02-17 04:18:14 -06:00
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
impl scope_info {
|
|
|
|
pub fn empty_cleanups(&mut self) -> bool {
|
2013-05-02 20:15:36 -05:00
|
|
|
self.cleanups.is_empty()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub trait get_node_info {
|
2013-02-22 00:41:37 -06:00
|
|
|
fn info(&self) -> Option<NodeInfo>;
|
2012-07-11 17:00:40 -05:00
|
|
|
}
|
|
|
|
|
2013-06-27 08:04:22 -05:00
|
|
|
impl get_node_info for ast::expr {
|
2013-02-22 00:41:37 -06:00
|
|
|
fn info(&self) -> Option<NodeInfo> {
|
2013-03-15 14:24:24 -05:00
|
|
|
Some(NodeInfo {id: self.id,
|
2013-06-01 17:31:56 -05:00
|
|
|
callee_id: self.get_callee_id(),
|
2013-03-15 14:24:24 -05:00
|
|
|
span: self.span})
|
2012-05-14 16:24:16 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-26 19:12:00 -06:00
|
|
|
impl get_node_info for ast::blk {
|
2013-02-22 00:41:37 -06:00
|
|
|
fn info(&self) -> Option<NodeInfo> {
|
2013-03-15 14:24:24 -05:00
|
|
|
Some(NodeInfo {id: self.node.id,
|
|
|
|
callee_id: None,
|
|
|
|
span: self.span})
|
2012-05-14 16:24:16 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-28 22:30:16 -06:00
|
|
|
impl get_node_info for Option<@ast::expr> {
|
2013-02-22 00:41:37 -06:00
|
|
|
fn info(&self) -> Option<NodeInfo> {
|
2012-09-27 19:01:28 -05:00
|
|
|
self.chain_ref(|s| s.info())
|
2012-05-14 16:24:16 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub struct NodeInfo {
|
2012-05-14 16:24:16 -05:00
|
|
|
id: ast::node_id,
|
2013-03-15 14:24:24 -05:00
|
|
|
callee_id: Option<ast::node_id>,
|
2012-05-14 16:24:16 -05:00
|
|
|
span: span
|
2013-02-19 01:40:42 -06:00
|
|
|
}
|
2012-05-14 16:24:16 -05:00
|
|
|
|
2011-07-21 19:27:34 -05:00
|
|
|
// Basic block context. We create a block context for each basic block
|
|
|
|
// (single-entry, single-exit sequence of instructions) we generate from Rust
|
|
|
|
// code. Each basic block we generate is attached to a function, typically
|
|
|
|
// with many basic blocks per function. All the basic blocks attached to a
|
|
|
|
// function are organized as a directed graph.
|
2013-01-30 13:46:19 -06:00
|
|
|
pub struct block_ {
|
2011-07-27 07:19:39 -05:00
|
|
|
// The BasicBlockRef returned from a call to
|
2011-08-03 17:39:43 -05:00
|
|
|
// 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.
|
2011-09-02 17:34:58 -05:00
|
|
|
// The block pointing to this one in the function's digraph.
|
2012-09-06 21:40:15 -05:00
|
|
|
llbb: BasicBlockRef,
|
2013-02-21 13:57:20 -06:00
|
|
|
terminated: bool,
|
|
|
|
unreachable: bool,
|
2012-09-06 21:40:15 -05:00
|
|
|
parent: Option<block>,
|
2011-09-02 17:34:58 -05:00
|
|
|
// The 'kind' of basic block this is.
|
2013-05-02 20:15:36 -05:00
|
|
|
kind: block_kind,
|
2012-07-23 18:00:19 -05:00
|
|
|
// Is this block part of a landing pad?
|
2012-09-06 21:40:15 -05:00
|
|
|
is_lpad: bool,
|
2012-05-14 16:24:16 -05:00
|
|
|
// info about the AST node this block originated from, if any
|
2013-02-19 01:40:42 -06:00
|
|
|
node_info: Option<NodeInfo>,
|
2011-09-02 17:34:58 -05:00
|
|
|
// The function context for the function to which this block is
|
|
|
|
// attached.
|
2012-09-06 21:40:15 -05:00
|
|
|
fcx: fn_ctxt
|
2012-09-05 17:58:43 -05:00
|
|
|
}
|
|
|
|
|
2013-04-17 11:15:37 -05:00
|
|
|
pub fn block_(llbb: BasicBlockRef, parent: Option<block>, kind: block_kind,
|
2013-02-19 01:40:42 -06:00
|
|
|
is_lpad: bool, node_info: Option<NodeInfo>, fcx: fn_ctxt)
|
2012-09-05 17:58:43 -05:00
|
|
|
-> block_ {
|
|
|
|
|
|
|
|
block_ {
|
|
|
|
llbb: llbb,
|
|
|
|
terminated: false,
|
|
|
|
unreachable: false,
|
|
|
|
parent: parent,
|
2013-05-02 20:15:36 -05:00
|
|
|
kind: kind,
|
2012-09-05 17:58:43 -05:00
|
|
|
is_lpad: is_lpad,
|
|
|
|
node_info: node_info,
|
|
|
|
fcx: fcx
|
2012-06-12 16:55:44 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-21 13:57:20 -06:00
|
|
|
pub type block = @mut block_;
|
2012-06-12 16:55:44 -05:00
|
|
|
|
2013-04-17 11:15:37 -05:00
|
|
|
pub fn mk_block(llbb: BasicBlockRef, parent: Option<block>, kind: block_kind,
|
2013-02-19 01:40:42 -06:00
|
|
|
is_lpad: bool, node_info: Option<NodeInfo>, fcx: fn_ctxt)
|
2012-07-23 18:00:19 -05:00
|
|
|
-> block {
|
2013-02-21 13:57:20 -06:00
|
|
|
@mut block_(llbb, parent, kind, is_lpad, node_info, fcx)
|
2012-06-12 16:55:44 -05:00
|
|
|
}
|
2011-07-21 19:27:34 -05:00
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub struct Result {
|
2012-09-07 16:50:47 -05:00
|
|
|
bcx: block,
|
|
|
|
val: ValueRef
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn rslt(bcx: block, val: ValueRef) -> Result {
|
2012-08-28 17:54:45 -05:00
|
|
|
Result {bcx: bcx, val: val}
|
|
|
|
}
|
2011-07-21 19:27:34 -05:00
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
impl Result {
|
|
|
|
pub fn unpack(&self, bcx: &mut block) -> ValueRef {
|
2012-08-28 17:54:45 -05:00
|
|
|
*bcx = self.bcx;
|
|
|
|
return self.val;
|
|
|
|
}
|
2011-07-21 19:27:34 -05:00
|
|
|
}
|
|
|
|
|
2013-06-16 05:52:44 -05:00
|
|
|
pub fn val_ty(v: ValueRef) -> Type {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
2013-06-16 05:52:44 -05:00
|
|
|
Type::from_ref(llvm::LLVMTypeOf(v))
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
|
|
|
}
|
2011-07-21 19:27:34 -05:00
|
|
|
|
2013-06-27 08:04:22 -05:00
|
|
|
pub fn in_scope_cx(cx: block, f: &fn(si: &mut scope_info)) {
|
2012-03-15 08:47:03 -05:00
|
|
|
let mut cur = cx;
|
2012-03-10 22:34:17 -06:00
|
|
|
loop {
|
2013-05-02 20:15:36 -05:00
|
|
|
match cur.kind {
|
|
|
|
block_scope(inf) => {
|
|
|
|
debug!("in_scope_cx: selected cur=%s (cx=%s)",
|
|
|
|
cur.to_str(), cx.to_str());
|
|
|
|
f(inf);
|
|
|
|
return;
|
2013-02-21 13:57:20 -06:00
|
|
|
}
|
2013-05-02 20:15:36 -05:00
|
|
|
_ => ()
|
2012-02-17 04:18:14 -06:00
|
|
|
}
|
2012-02-17 06:17:40 -06:00
|
|
|
cur = block_parent(cur);
|
2011-07-21 19:27:34 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn block_parent(cx: block) -> block {
|
2012-08-06 14:34:08 -05:00
|
|
|
match cx.parent {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(b) => b,
|
|
|
|
None => cx.sess().bug(fmt!("block_parent called on root block %?",
|
2012-08-22 19:24:52 -05:00
|
|
|
cx))
|
2012-06-12 16:55:44 -05:00
|
|
|
}
|
2012-02-17 06:17:40 -06:00
|
|
|
}
|
|
|
|
|
2011-07-21 19:27:34 -05:00
|
|
|
// Accessors
|
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
impl block_ {
|
2013-06-14 22:16:03 -05:00
|
|
|
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 }
|
2012-05-14 22:32:29 -05:00
|
|
|
|
2013-06-14 22:16:03 -05:00
|
|
|
pub fn node_id_to_str(&self, id: ast::node_id) -> ~str {
|
2012-08-28 17:54:45 -05:00
|
|
|
ast_map::node_id_to_str(self.tcx().items, id, self.sess().intr())
|
|
|
|
}
|
|
|
|
|
2013-06-14 22:16:03 -05:00
|
|
|
pub fn expr_to_str(&self, e: @ast::expr) -> ~str {
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-09 00:54:49 -05:00
|
|
|
e.repr(self.tcx())
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
|
|
|
|
2013-06-27 08:04:22 -05:00
|
|
|
pub fn expr_is_lval(&self, e: &ast::expr) -> bool {
|
2012-08-28 17:54:45 -05:00
|
|
|
ty::expr_is_lval(self.tcx(), self.ccx().maps.method_map, e)
|
|
|
|
}
|
|
|
|
|
2013-06-27 08:04:22 -05:00
|
|
|
pub fn expr_kind(&self, e: &ast::expr) -> ty::ExprKind {
|
2012-08-28 17:54:45 -05:00
|
|
|
ty::expr_kind(self.tcx(), self.ccx().maps.method_map, e)
|
|
|
|
}
|
|
|
|
|
2013-06-14 22:16:03 -05:00
|
|
|
pub fn def(&self, nid: ast::node_id) -> ast::def {
|
2013-02-05 21:41:45 -06:00
|
|
|
match self.tcx().def_map.find(&nid) {
|
2013-03-22 21:26:41 -05:00
|
|
|
Some(&v) => v,
|
2012-08-28 17:54:45 -05:00
|
|
|
None => {
|
|
|
|
self.tcx().sess.bug(fmt!(
|
|
|
|
"No def associated with node id %?", nid));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-14 22:16:03 -05:00
|
|
|
pub fn val_to_str(&self, val: ValueRef) -> ~str {
|
|
|
|
self.ccx().tn.val_to_str(val)
|
2012-05-22 20:44:28 -05:00
|
|
|
}
|
2012-08-28 17:54:45 -05:00
|
|
|
|
2013-06-15 09:29:52 -05:00
|
|
|
pub fn llty_str(&self, ty: Type) -> ~str {
|
|
|
|
self.ccx().tn.type_to_str(ty)
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
|
|
|
|
2013-06-14 22:16:03 -05:00
|
|
|
pub fn ty_to_str(&self, t: ty::t) -> ~str {
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-09 00:54:49 -05:00
|
|
|
t.repr(self.tcx())
|
2012-05-22 20:44:28 -05:00
|
|
|
}
|
2013-05-31 17:17:22 -05:00
|
|
|
|
2013-06-14 22:16:03 -05:00
|
|
|
pub fn to_str(&self) -> ~str {
|
2013-04-22 16:27:30 -05:00
|
|
|
unsafe {
|
|
|
|
match self.node_info {
|
|
|
|
Some(node_info) => fmt!("[block %d]", node_info.id),
|
|
|
|
None => fmt!("[block %x]", transmute(&*self)),
|
|
|
|
}
|
2012-05-14 22:32:29 -05:00
|
|
|
}
|
|
|
|
}
|
2012-02-21 07:20:18 -06:00
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2013-06-15 09:29:52 -05:00
|
|
|
// 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).
|
|
|
|
pub fn tuplify_box_ty(tcx: ty::ctxt, t: ty::t) -> ty::t {
|
|
|
|
let ptr = ty::mk_ptr(
|
|
|
|
tcx,
|
2013-06-25 04:32:02 -05:00
|
|
|
ty::mt {ty: ty::mk_i8(), mutbl: ast::m_imm}
|
2013-06-15 09:29:52 -05:00
|
|
|
);
|
|
|
|
return ty::mk_tup(tcx, ~[ty::mk_uint(), ty::mk_type(tcx),
|
|
|
|
ptr, ptr,
|
|
|
|
t]);
|
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
|
|
|
|
|
|
|
|
// LLVM constant constructors.
|
2013-06-15 22:45:48 -05:00
|
|
|
pub fn C_null(t: Type) -> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
2013-06-15 22:45:48 -05:00
|
|
|
llvm::LLVMConstNull(t.to_ref())
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2013-06-15 22:45:48 -05:00
|
|
|
pub fn C_undef(t: Type) -> ValueRef {
|
2013-02-18 16:16:21 -06:00
|
|
|
unsafe {
|
2013-06-15 22:45:48 -05:00
|
|
|
llvm::LLVMGetUndef(t.to_ref())
|
2013-02-18 16:16:21 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-15 22:45:48 -05:00
|
|
|
pub fn C_integral(t: Type, u: u64, sign_extend: bool) -> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
2013-06-15 22:45:48 -05:00
|
|
|
llvm::LLVMConstInt(t.to_ref(), u, sign_extend as Bool)
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-06-15 22:45:48 -05:00
|
|
|
pub fn C_floating(s: &str, t: Type) -> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
2013-06-15 22:45:48 -05:00
|
|
|
do s.as_c_str |buf| {
|
|
|
|
llvm::LLVMConstRealOfString(t.to_ref(), buf)
|
|
|
|
}
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn C_nil() -> ValueRef {
|
2013-05-19 00:07:44 -05:00
|
|
|
return C_struct([]);
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-06-15 22:45:48 -05:00
|
|
|
pub fn C_bool(val: bool) -> ValueRef {
|
|
|
|
C_integral(Type::bool(), val as u64, false)
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-06-15 22:45:48 -05:00
|
|
|
pub fn C_i1(val: bool) -> ValueRef {
|
|
|
|
C_integral(Type::i1(), val as u64, false)
|
2013-02-06 16:28:02 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn C_i32(i: i32) -> ValueRef {
|
2013-06-15 22:45:48 -05:00
|
|
|
return C_integral(Type::i32(), i as u64, true);
|
2011-10-26 00:23:28 -05:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn C_i64(i: i64) -> ValueRef {
|
2013-06-15 22:45:48 -05:00
|
|
|
return C_integral(Type::i64(), i as u64, true);
|
2011-11-15 20:11:22 -06:00
|
|
|
}
|
|
|
|
|
2013-06-13 02:19:50 -05:00
|
|
|
pub fn C_int(cx: &CrateContext, i: int) -> ValueRef {
|
2013-06-15 22:45:48 -05:00
|
|
|
return C_integral(cx.int_type, i as u64, true);
|
2011-10-14 18:45:25 -05:00
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2013-06-13 02:19:50 -05:00
|
|
|
pub fn C_uint(cx: &CrateContext, i: uint) -> ValueRef {
|
2013-06-15 22:45:48 -05:00
|
|
|
return C_integral(cx.int_type, i as u64, false);
|
2011-10-14 18:45:25 -05:00
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn C_u8(i: uint) -> ValueRef {
|
2013-06-15 22:45:48 -05:00
|
|
|
return C_integral(Type::i8(), i as u64, false);
|
2013-01-30 13:46:19 -06:00
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
|
|
|
|
|
|
|
|
// This is a 'c-like' raw string, which differs from
|
|
|
|
// our boxed-and-length-annotated strings.
|
2013-06-13 02:19:50 -05:00
|
|
|
pub fn C_cstr(cx: &mut CrateContext, s: @str) -> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
2013-06-15 22:45:48 -05:00
|
|
|
match cx.const_cstr_cache.find_equiv(&s) {
|
2013-03-22 21:26:41 -05:00
|
|
|
Some(&llval) => return llval,
|
2013-02-16 12:36:09 -06:00
|
|
|
None => ()
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2012-04-21 15:23:25 -05:00
|
|
|
|
2013-06-15 22:45:48 -05:00
|
|
|
let sc = do s.as_c_str |buf| {
|
|
|
|
llvm::LLVMConstStringInContext(cx.llcx, buf, s.len() as c_uint, False)
|
|
|
|
};
|
|
|
|
|
|
|
|
let gsym = token::gensym("str");
|
2013-06-16 05:52:44 -05:00
|
|
|
let g = do fmt!("str%u", gsym).as_c_str |buf| {
|
2013-06-15 22:45:48 -05:00
|
|
|
llvm::LLVMAddGlobal(cx.llmod, val_ty(sc).to_ref(), buf)
|
2013-01-10 23:23:07 -06:00
|
|
|
};
|
|
|
|
llvm::LLVMSetInitializer(g, sc);
|
|
|
|
llvm::LLVMSetGlobalConstant(g, True);
|
|
|
|
lib::llvm::SetLinkage(g, lib::llvm::InternalLinkage);
|
2012-04-21 15:23:25 -05:00
|
|
|
|
2013-01-10 23:23:07 -06:00
|
|
|
cx.const_cstr_cache.insert(s, g);
|
2012-04-21 15:23:25 -05:00
|
|
|
|
2013-01-10 23:23:07 -06:00
|
|
|
return g;
|
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-01-05 01:06:25 -06:00
|
|
|
// 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.
|
2013-06-13 02:19:50 -05:00
|
|
|
pub fn C_estr_slice(cx: &mut CrateContext, s: @str) -> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
2013-02-10 18:33:16 -06:00
|
|
|
let len = s.len();
|
2013-06-15 22:45:48 -05:00
|
|
|
let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), Type::i8p().to_ref());
|
2013-05-19 00:07:44 -05:00
|
|
|
C_struct([cs, C_uint(cx, len + 1u /* +1 for null */)])
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2012-06-08 15:26:06 -05:00
|
|
|
}
|
|
|
|
|
2011-07-14 19:08:22 -05:00
|
|
|
// Returns a Plain Old LLVM String:
|
2013-03-05 19:36:39 -06:00
|
|
|
pub fn C_postr(s: &str) -> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
2013-06-15 22:45:48 -05:00
|
|
|
do s.as_c_str |buf| {
|
|
|
|
llvm::LLVMConstStringInContext(base::task_llcx(), buf, s.len() as c_uint, False)
|
|
|
|
}
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn C_zero_byte_arr(size: uint) -> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
let mut i = 0u;
|
|
|
|
let mut elts: ~[ValueRef] = ~[];
|
|
|
|
while i < size { elts.push(C_u8(0u)); i += 1u; }
|
2013-06-16 05:52:44 -05:00
|
|
|
return llvm::LLVMConstArray(Type::i8().to_ref(),
|
|
|
|
vec::raw::to_ptr(elts), elts.len() as c_uint);
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn C_struct(elts: &[ValueRef]) -> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
do vec::as_imm_buf(elts) |ptr, len| {
|
2013-06-15 22:45:48 -05:00
|
|
|
llvm::LLVMConstStructInContext(base::task_llcx(), ptr, len as c_uint, False)
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn C_packed_struct(elts: &[ValueRef]) -> ValueRef {
|
2013-01-23 18:25:47 -06:00
|
|
|
unsafe {
|
|
|
|
do vec::as_imm_buf(elts) |ptr, len| {
|
2013-06-15 22:45:48 -05:00
|
|
|
llvm::LLVMConstStructInContext(base::task_llcx(), ptr, len as c_uint, True)
|
2013-01-23 18:25:47 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-16 05:52:44 -05:00
|
|
|
pub fn C_named_struct(T: Type, elts: &[ValueRef]) -> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
do vec::as_imm_buf(elts) |ptr, len| {
|
2013-06-16 05:52:44 -05:00
|
|
|
llvm::LLVMConstNamedStruct(T.to_ref(), ptr, len as c_uint)
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-06-16 05:52:44 -05:00
|
|
|
pub fn C_array(ty: Type, elts: &[ValueRef]) -> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
2013-06-16 05:52:44 -05:00
|
|
|
return llvm::LLVMConstArray(ty.to_ref(), vec::raw::to_ptr(elts), elts.len() as c_uint);
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2011-07-27 17:14:59 -05:00
|
|
|
}
|
2011-08-04 12:46:10 -05:00
|
|
|
|
2013-03-05 19:36:39 -06:00
|
|
|
pub fn C_bytes(bytes: &[u8]) -> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
2013-06-15 22:45:48 -05:00
|
|
|
let ptr = cast::transmute(vec::raw::to_ptr(bytes));
|
|
|
|
return llvm::LLVMConstStringInContext(base::task_llcx(), ptr, bytes.len() as c_uint, True);
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2012-09-05 17:27:22 -05:00
|
|
|
}
|
|
|
|
|
2013-03-05 19:36:39 -06:00
|
|
|
pub fn C_bytes_plus_null(bytes: &[u8]) -> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
2013-06-21 03:28:33 -05:00
|
|
|
return llvm::LLVMConstStringInContext(base::task_llcx(),
|
|
|
|
cast::transmute(vec::raw::to_ptr(bytes)),
|
|
|
|
bytes.len() as c_uint, False);
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2011-08-04 12:46:10 -05:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn get_param(fndecl: ValueRef, param: uint) -> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
llvm::LLVMGetParam(fndecl, param as c_uint)
|
|
|
|
}
|
2012-03-21 09:42:20 -05:00
|
|
|
}
|
|
|
|
|
2013-06-13 02:19:50 -05:00
|
|
|
pub fn const_get_elt(cx: &CrateContext, v: ValueRef, us: &[c_uint])
|
2013-02-18 16:16:21 -06:00
|
|
|
-> ValueRef {
|
|
|
|
unsafe {
|
|
|
|
let r = do vec::as_imm_buf(us) |p, len| {
|
|
|
|
llvm::LLVMConstExtractValue(v, p, len as c_uint)
|
|
|
|
};
|
|
|
|
|
|
|
|
debug!("const_get_elt(v=%s, us=%?, r=%s)",
|
2013-06-14 22:16:03 -05:00
|
|
|
cx.tn.val_to_str(v), us, cx.tn.val_to_str(r));
|
2013-02-18 16:16:21 -06:00
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn const_to_int(v: ValueRef) -> c_longlong {
|
|
|
|
unsafe {
|
|
|
|
llvm::LLVMConstIntGetSExtValue(v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn const_to_uint(v: ValueRef) -> c_ulonglong {
|
|
|
|
unsafe {
|
|
|
|
llvm::LLVMConstIntGetZExtValue(v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_undef(val: ValueRef) -> bool {
|
|
|
|
unsafe {
|
|
|
|
llvm::LLVMIsUndef(val) != False
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-31 17:55:30 -05:00
|
|
|
pub fn is_null(val: ValueRef) -> bool {
|
|
|
|
unsafe {
|
|
|
|
llvm::LLVMIsNull(val) != False
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-12 10:31:22 -05:00
|
|
|
// Used to identify cached monomorphized functions and vtables
|
2013-03-20 10:40:02 -05:00
|
|
|
#[deriving(Eq)]
|
2013-01-30 13:46:19 -06:00
|
|
|
pub enum mono_param_id {
|
2013-05-17 19:27:44 -05:00
|
|
|
mono_precise(ty::t, Option<@~[mono_id]>),
|
2012-03-12 10:31:22 -05:00
|
|
|
mono_any,
|
2012-09-20 14:29:15 -05:00
|
|
|
mono_repr(uint /* size */,
|
|
|
|
uint /* align */,
|
2013-04-06 21:52:35 -05:00
|
|
|
MonoDataClass,
|
2012-09-20 14:29:15 -05:00
|
|
|
datum::DatumMode),
|
2012-03-12 10:31:22 -05:00
|
|
|
}
|
2012-08-27 18:26:35 -05:00
|
|
|
|
2013-04-06 21:52:35 -05:00
|
|
|
#[deriving(Eq)]
|
|
|
|
pub enum MonoDataClass {
|
|
|
|
MonoBits, // Anything not treated differently from arbitrary integer data
|
|
|
|
MonoNonNull, // Non-null pointers (used for optional-pointer optimization)
|
|
|
|
// FIXME(#3547)---scalars and floats are
|
|
|
|
// treated differently in most ABIs. But we
|
|
|
|
// should be doing something more detailed
|
|
|
|
// here.
|
|
|
|
MonoFloat
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn mono_data_classify(t: ty::t) -> MonoDataClass {
|
|
|
|
match ty::get(t).sty {
|
|
|
|
ty::ty_float(_) => MonoFloat,
|
|
|
|
ty::ty_rptr(*) | ty::ty_uniq(*) |
|
|
|
|
ty::ty_box(*) | ty::ty_opaque_box(*) |
|
|
|
|
ty::ty_estr(ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_uniq) |
|
|
|
|
ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) |
|
|
|
|
ty::ty_bare_fn(*) => MonoNonNull,
|
|
|
|
// Is that everything? Would closures or slices qualify?
|
|
|
|
_ => MonoBits
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-03-20 10:40:02 -05:00
|
|
|
#[deriving(Eq)]
|
2013-01-30 13:46:19 -06:00
|
|
|
pub struct mono_id_ {
|
2012-10-08 14:39:30 -05:00
|
|
|
def: ast::def_id,
|
|
|
|
params: ~[mono_param_id],
|
|
|
|
impl_did_opt: Option<ast::def_id>
|
2013-01-06 13:16:14 -06:00
|
|
|
}
|
2012-08-27 18:26:35 -05:00
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub type mono_id = @mono_id_;
|
2012-08-27 18:26:35 -05:00
|
|
|
|
2013-05-03 12:08:08 -05:00
|
|
|
impl to_bytes::IterBytes for mono_param_id {
|
|
|
|
fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
|
|
|
|
match *self {
|
2013-05-22 19:02:14 -05:00
|
|
|
mono_precise(t, ref mids) => {
|
|
|
|
0u8.iter_bytes(lsb0, f) &&
|
|
|
|
ty::type_id(t).iter_bytes(lsb0, f) &&
|
|
|
|
mids.iter_bytes(lsb0, f)
|
|
|
|
}
|
2013-05-03 12:08:08 -05:00
|
|
|
|
|
|
|
mono_any => 1u8.iter_bytes(lsb0, f),
|
2012-11-28 13:36:04 -06:00
|
|
|
|
2013-05-22 19:02:14 -05:00
|
|
|
mono_repr(ref a, ref b, ref c, ref d) => {
|
|
|
|
2u8.iter_bytes(lsb0, f) &&
|
|
|
|
a.iter_bytes(lsb0, f) &&
|
|
|
|
b.iter_bytes(lsb0, f) &&
|
|
|
|
c.iter_bytes(lsb0, f) &&
|
|
|
|
d.iter_bytes(lsb0, f)
|
|
|
|
}
|
2013-05-03 12:08:08 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl to_bytes::IterBytes for MonoDataClass {
|
|
|
|
fn iter_bytes(&self, lsb0: bool, f:to_bytes::Cb) -> bool {
|
|
|
|
(*self as u8).iter_bytes(lsb0, f)
|
|
|
|
}
|
|
|
|
}
|
2013-04-06 21:52:35 -05:00
|
|
|
|
2013-05-03 12:08:08 -05:00
|
|
|
impl to_bytes::IterBytes for mono_id_ {
|
|
|
|
fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
|
2013-05-22 19:02:14 -05:00
|
|
|
self.def.iter_bytes(lsb0, f) && self.params.iter_bytes(lsb0, f)
|
2013-05-03 12:08:08 -05:00
|
|
|
}
|
|
|
|
}
|
2012-02-02 05:37:17 -06:00
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn umax(cx: block, a: ValueRef, b: ValueRef) -> ValueRef {
|
2012-02-01 04:04:56 -06:00
|
|
|
let cond = build::ICmp(cx, lib::llvm::IntULT, a, b);
|
2012-08-01 19:30:05 -05:00
|
|
|
return build::Select(cx, cond, b, a);
|
2012-01-19 12:21:42 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn umin(cx: block, a: ValueRef, b: ValueRef) -> ValueRef {
|
2012-02-01 04:04:56 -06:00
|
|
|
let cond = build::ICmp(cx, lib::llvm::IntULT, a, b);
|
2012-08-01 19:30:05 -05:00
|
|
|
return build::Select(cx, cond, a, b);
|
2012-01-19 12:21:42 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn align_to(cx: block, off: ValueRef, align: ValueRef) -> ValueRef {
|
2012-02-21 07:20:18 -06:00
|
|
|
let mask = build::Sub(cx, align, C_int(cx.ccx(), 1));
|
2012-01-27 06:17:06 -06:00
|
|
|
let bumped = build::Add(cx, off, mask);
|
2012-08-01 19:30:05 -05:00
|
|
|
return build::And(cx, bumped, build::Not(cx, mask));
|
2012-01-19 12:21:42 -06:00
|
|
|
}
|
|
|
|
|
2013-03-10 10:02:16 -05:00
|
|
|
pub fn path_str(sess: session::Session, p: &[path_elt]) -> ~str {
|
2013-06-04 23:43:41 -05:00
|
|
|
let mut r = ~"";
|
|
|
|
let mut first = true;
|
2013-06-21 07:29:53 -05:00
|
|
|
for p.iter().advance |e| {
|
2012-09-18 23:41:37 -05:00
|
|
|
match *e {
|
|
|
|
ast_map::path_name(s) | ast_map::path_mod(s) => {
|
|
|
|
if first { first = false; }
|
2013-05-23 11:09:11 -05:00
|
|
|
else { r += "::"; }
|
2013-06-12 12:02:55 -05:00
|
|
|
r += sess.str_of(s);
|
2012-09-18 23:41:37 -05:00
|
|
|
}
|
|
|
|
}
|
2012-02-03 02:53:37 -06:00
|
|
|
}
|
|
|
|
r
|
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn monomorphize_type(bcx: block, t: ty::t) -> ty::t {
|
2013-03-20 00:17:42 -05:00
|
|
|
match bcx.fcx.param_substs {
|
2012-10-08 14:39:30 -05:00
|
|
|
Some(substs) => {
|
|
|
|
ty::subst_tps(bcx.tcx(), substs.tys, substs.self_ty, t)
|
|
|
|
}
|
2013-03-28 20:39:09 -05:00
|
|
|
_ => { assert!(!ty::type_has_params(t)); t }
|
2012-09-11 23:25:01 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn node_id_type(bcx: block, id: ast::node_id) -> ty::t {
|
2012-02-21 07:20:18 -06:00
|
|
|
let tcx = bcx.tcx();
|
2012-02-02 05:37:17 -06:00
|
|
|
let t = ty::node_id_to_type(tcx, id);
|
2012-09-11 23:25:01 -05:00
|
|
|
monomorphize_type(bcx, t)
|
2012-02-02 05:37:17 -06:00
|
|
|
}
|
2012-09-10 14:25:45 -05:00
|
|
|
|
2013-06-27 08:04:22 -05:00
|
|
|
pub fn expr_ty(bcx: block, ex: &ast::expr) -> ty::t {
|
2012-02-02 05:37:17 -06:00
|
|
|
node_id_type(bcx, ex.id)
|
|
|
|
}
|
2012-09-10 14:25:45 -05:00
|
|
|
|
2013-06-27 08:04:22 -05:00
|
|
|
pub fn expr_ty_adjusted(bcx: block, ex: &ast::expr) -> ty::t {
|
2013-02-27 18:28:37 -06:00
|
|
|
let tcx = bcx.tcx();
|
|
|
|
let t = ty::expr_ty_adjusted(tcx, ex);
|
|
|
|
monomorphize_type(bcx, t)
|
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn node_id_type_params(bcx: block, id: ast::node_id) -> ~[ty::t] {
|
2012-02-21 07:20:18 -06:00
|
|
|
let tcx = bcx.tcx();
|
2012-02-09 07:33:00 -06:00
|
|
|
let params = ty::node_id_to_type_params(tcx, id);
|
2013-03-21 07:34:18 -05:00
|
|
|
|
2013-06-17 18:43:22 -05:00
|
|
|
if !params.iter().all(|t| !ty::type_needs_infer(*t)) {
|
2013-03-21 07:34:18 -05:00
|
|
|
bcx.sess().bug(
|
|
|
|
fmt!("Type parameters for node %d include inference types: %s",
|
2013-06-10 08:25:25 -05:00
|
|
|
id, params.map(|t| bcx.ty_to_str(*t)).connect(",")));
|
2013-03-21 07:34:18 -05:00
|
|
|
}
|
|
|
|
|
2013-03-20 00:17:42 -05:00
|
|
|
match bcx.fcx.param_substs {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(substs) => {
|
2012-10-08 14:39:30 -05:00
|
|
|
do vec::map(params) |t| {
|
|
|
|
ty::subst_tps(tcx, substs.tys, substs.self_ty, *t)
|
|
|
|
}
|
2012-02-09 07:33:00 -06:00
|
|
|
}
|
2012-08-03 21:59:04 -05:00
|
|
|
_ => params
|
2012-02-09 07:33:00 -06:00
|
|
|
}
|
|
|
|
}
|
2012-02-02 05:37:17 -06:00
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn node_vtables(bcx: block, id: ast::node_id)
|
|
|
|
-> Option<typeck::vtable_res> {
|
2013-02-05 21:41:45 -06:00
|
|
|
let raw_vtables = bcx.ccx().maps.vtable_map.find(&id);
|
2012-09-10 14:25:45 -05:00
|
|
|
raw_vtables.map(
|
2013-03-22 21:26:41 -05:00
|
|
|
|&vts| resolve_vtables_in_fn_ctxt(bcx.fcx, *vts))
|
2012-09-10 14:25:45 -05:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn resolve_vtables_in_fn_ctxt(fcx: fn_ctxt, vts: typeck::vtable_res)
|
|
|
|
-> typeck::vtable_res {
|
2013-01-10 08:29:26 -06:00
|
|
|
@vec::map(*vts, |d| resolve_vtable_in_fn_ctxt(fcx, copy *d))
|
2012-09-10 14:25:45 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Apply the typaram substitutions in the fn_ctxt to a vtable. This should
|
|
|
|
// eliminate any vtable_params.
|
2013-04-17 11:15:37 -05:00
|
|
|
pub fn resolve_vtable_in_fn_ctxt(fcx: fn_ctxt, vt: typeck::vtable_origin)
|
2013-01-30 13:46:19 -06:00
|
|
|
-> typeck::vtable_origin {
|
2012-09-10 14:25:45 -05:00
|
|
|
let tcx = fcx.ccx.tcx;
|
|
|
|
match vt {
|
|
|
|
typeck::vtable_static(trait_id, tys, sub) => {
|
2013-03-20 00:17:42 -05:00
|
|
|
let tys = match fcx.param_substs {
|
2012-09-10 14:25:45 -05:00
|
|
|
Some(substs) => {
|
2012-10-08 14:39:30 -05:00
|
|
|
do vec::map(tys) |t| {
|
|
|
|
ty::subst_tps(tcx, substs.tys, substs.self_ty, *t)
|
|
|
|
}
|
2012-09-10 14:25:45 -05:00
|
|
|
}
|
|
|
|
_ => tys
|
|
|
|
};
|
|
|
|
typeck::vtable_static(trait_id, tys,
|
|
|
|
resolve_vtables_in_fn_ctxt(fcx, sub))
|
|
|
|
}
|
|
|
|
typeck::vtable_param(n_param, n_bound) => {
|
|
|
|
match fcx.param_substs {
|
2013-02-18 14:36:30 -06:00
|
|
|
Some(substs) => {
|
2012-09-10 14:25:45 -05:00
|
|
|
find_vtable(tcx, substs, n_param, n_bound)
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
tcx.sess.bug(fmt!(
|
2013-01-07 16:16:52 -06:00
|
|
|
"resolve_vtable_in_fn_ctxt: asked to lookup but \
|
|
|
|
no vtables in the fn_ctxt!"))
|
2012-09-10 14:25:45 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn find_vtable(tcx: ty::ctxt, ps: ¶m_substs,
|
2013-03-21 07:33:52 -05:00
|
|
|
n_param: uint, n_bound: uint)
|
2013-01-30 13:46:19 -06:00
|
|
|
-> typeck::vtable_origin {
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-09 00:54:49 -05:00
|
|
|
debug!("find_vtable(n_param=%u, n_bound=%u, ps=%s)",
|
|
|
|
n_param, n_bound, ps.repr(tcx));
|
2012-09-10 14:25:45 -05:00
|
|
|
|
|
|
|
// Vtables are stored in a flat array, finding the right one is
|
|
|
|
// somewhat awkward
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-09 00:54:49 -05:00
|
|
|
let first_n_type_param_defs = ps.type_param_defs.slice(0, n_param);
|
2012-11-28 14:34:30 -06:00
|
|
|
let vtables_to_skip =
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-09 00:54:49 -05:00
|
|
|
ty::count_traits_and_supertraits(tcx, first_n_type_param_defs);
|
2012-11-28 14:34:30 -06:00
|
|
|
let vtable_off = vtables_to_skip + n_bound;
|
2013-01-07 16:16:52 -06:00
|
|
|
/*bad*/ copy ps.vtables.get()[vtable_off]
|
2012-09-10 14:25:45 -05:00
|
|
|
}
|
|
|
|
|
2013-04-17 11:15:37 -05:00
|
|
|
pub fn dummy_substs(tps: ~[ty::t]) -> ty::substs {
|
2013-01-25 18:57:39 -06:00
|
|
|
substs {
|
|
|
|
self_r: Some(ty::re_bound(ty::br_self)),
|
|
|
|
self_ty: None,
|
|
|
|
tps: tps
|
|
|
|
}
|
2012-04-18 23:26:25 -05:00
|
|
|
}
|
|
|
|
|
2013-05-04 13:29:32 -05:00
|
|
|
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);
|
2013-06-12 12:02:55 -05:00
|
|
|
let filename_cstr = C_cstr(bcx.ccx(), loc.file.name);
|
2013-06-15 22:45:48 -05:00
|
|
|
let filename = build::PointerCast(bcx, filename_cstr, Type::i8p());
|
2013-05-04 13:29:32 -05:00
|
|
|
let line = C_int(bcx.ccx(), loc.line as int);
|
|
|
|
(filename, line)
|
|
|
|
}
|
|
|
|
|
2013-02-06 16:28:02 -06:00
|
|
|
// Casts a Rust bool value to an i1.
|
|
|
|
pub fn bool_to_i1(bcx: block, llval: ValueRef) -> ValueRef {
|
|
|
|
build::ICmp(bcx, lib::llvm::IntNE, llval, C_bool(false))
|
|
|
|
}
|