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
|
|
|
|
2013-03-26 15:38:07 -05:00
|
|
|
use back::{abi, upcall};
|
2012-12-23 16:41:37 -06:00
|
|
|
use driver::session;
|
|
|
|
use driver::session::Session;
|
2012-09-04 13:54:36 -05:00
|
|
|
use lib::llvm::{ModuleRef, ValueRef, TypeRef, BasicBlockRef, BuilderRef};
|
|
|
|
use lib::llvm::{True, False, Bool};
|
2013-02-19 01:40:42 -06:00
|
|
|
use lib::llvm::{llvm, TargetData, TypeNames, associate_type, name_has_type};
|
2012-12-23 16:41:37 -06:00
|
|
|
use lib;
|
2013-02-19 01:40:42 -06:00
|
|
|
use metadata::common::LinkMeta;
|
2012-12-23 16:41:37 -06:00
|
|
|
use middle::astencode;
|
|
|
|
use middle::resolve;
|
2013-02-25 03:49:21 -06:00
|
|
|
use middle::trans::adt;
|
2012-12-23 16:41:37 -06:00
|
|
|
use middle::trans::base;
|
|
|
|
use middle::trans::build;
|
|
|
|
use middle::trans::datum;
|
|
|
|
use middle::trans::debuginfo;
|
|
|
|
use middle::trans::glue;
|
|
|
|
use middle::trans::reachable;
|
|
|
|
use middle::trans::shape;
|
|
|
|
use middle::trans::type_of;
|
|
|
|
use middle::trans::type_use;
|
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-04-28 12:53:42 -05:00
|
|
|
use core::cast::transmute;
|
2013-05-24 21:35:29 -05:00
|
|
|
use core::cast;
|
2012-12-23 16:41:37 -06:00
|
|
|
use core::hash;
|
2013-04-03 08:28:36 -05:00
|
|
|
use core::hashmap::{HashMap, HashSet};
|
2013-02-18 16:16:21 -06:00
|
|
|
use core::libc::{c_uint, c_longlong, c_ulonglong};
|
2013-05-24 21:35:29 -05:00
|
|
|
use core::ptr;
|
|
|
|
use core::str;
|
2012-12-23 16:41:37 -06:00
|
|
|
use core::to_bytes;
|
|
|
|
use core::vec::raw::to_ptr;
|
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;
|
2012-09-04 13:54:36 -05:00
|
|
|
use syntax::parse::token::ident_interner;
|
2012-12-23 16:41:37 -06:00
|
|
|
use syntax::{ast, ast_map};
|
2013-03-13 21:25:28 -05:00
|
|
|
use syntax::abi::{X86, X86_64, Arm, Mips};
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2013-05-02 03:16:07 -05:00
|
|
|
pub type namegen = @fn(s: &str) -> ident;
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn new_namegen(intr: @ident_interner) -> namegen {
|
2013-05-02 03:16:07 -05:00
|
|
|
let f: @fn(s: &str) -> ident = |prefix| {
|
|
|
|
intr.gensym(fmt!("%s_%u",
|
2013-03-01 14:11:07 -06:00
|
|
|
prefix,
|
2013-05-02 03:16:07 -05:00
|
|
|
intr.gensym(prefix).repr))
|
2012-07-18 18:18:02 -05:00
|
|
|
};
|
2013-03-01 14:11:07 -06:00
|
|
|
f
|
2011-07-21 19:27:34 -05:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub type addrspace = c_uint;
|
2012-08-06 12:53:38 -05:00
|
|
|
|
|
|
|
// Address spaces communicate to LLVM which destructors need to run for
|
2013-01-30 13:46:19 -06:00
|
|
|
// specific types.
|
2012-08-06 12:53:38 -05:00
|
|
|
// 0 is ignored by the GC, and is used for all non-GC'd pointers.
|
|
|
|
// 1 is for opaque GC'd boxes.
|
|
|
|
// >= 2 are for specific types (e.g. resources).
|
2013-03-22 16:00:15 -05:00
|
|
|
pub static default_addrspace: addrspace = 0;
|
|
|
|
pub static gc_box_addrspace: addrspace = 1;
|
2012-08-06 12:53:38 -05:00
|
|
|
|
2013-03-01 14:11:07 -06:00
|
|
|
pub type addrspace_gen = @fn() -> addrspace;
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn new_addrspace_gen() -> addrspace_gen {
|
2012-08-06 12:53:38 -05:00
|
|
|
let i = @mut 1;
|
2013-03-01 14:11:07 -06:00
|
|
|
let result: addrspace_gen = || { *i += 1; *i };
|
|
|
|
result
|
2012-08-06 12:53:38 -05:00
|
|
|
}
|
|
|
|
|
2013-02-04 16:02:01 -06:00
|
|
|
pub struct tydesc_info {
|
|
|
|
ty: ty::t,
|
|
|
|
tydesc: ValueRef,
|
|
|
|
size: ValueRef,
|
|
|
|
align: ValueRef,
|
|
|
|
addrspace: addrspace,
|
|
|
|
take_glue: Option<ValueRef>,
|
|
|
|
drop_glue: Option<ValueRef>,
|
|
|
|
free_glue: Option<ValueRef>,
|
|
|
|
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,
|
|
|
|
llvm_insn_ctxt: @mut ~[~str],
|
2013-04-03 08:28:36 -05:00
|
|
|
llvm_insns: @mut HashMap<~str, uint>,
|
2013-02-19 01:40:42 -06:00
|
|
|
fn_times: @mut ~[(~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 {
|
|
|
|
fn finalize(&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-04-03 08:28:36 -05:00
|
|
|
pub type ExternMap = @mut HashMap<@str, ValueRef>;
|
2013-02-04 17:30:32 -06:00
|
|
|
|
2011-07-21 19:27:34 -05:00
|
|
|
// Crate context. Every crate we compile has one of these.
|
2013-02-19 01:40:42 -06:00
|
|
|
pub struct CrateContext {
|
2012-10-15 16:56:42 -05:00
|
|
|
sess: session::Session,
|
2011-08-19 17:16:48 -05:00
|
|
|
llmod: ModuleRef,
|
2013-02-19 01:40:42 -06:00
|
|
|
td: TargetData,
|
|
|
|
tn: @TypeNames,
|
2013-02-04 17:30:32 -06:00
|
|
|
externs: ExternMap,
|
2013-04-03 08:28:36 -05:00
|
|
|
intrinsics: HashMap<~str, ValueRef>,
|
|
|
|
item_vals: @mut HashMap<ast::node_id, ValueRef>,
|
2012-08-29 15:26:26 -05:00
|
|
|
exp_map2: resolve::ExportMap2,
|
2012-03-20 06:28:46 -05:00
|
|
|
reachable: reachable::map,
|
2013-04-03 08:28:36 -05:00
|
|
|
item_symbols: @mut HashMap<ast::node_id, ~str>,
|
2013-02-19 01:40:42 -06:00
|
|
|
link_meta: LinkMeta,
|
2013-04-03 08:28:36 -05:00
|
|
|
enum_sizes: @mut HashMap<ty::t, uint>,
|
|
|
|
discrims: @mut HashMap<ast::def_id, ValueRef>,
|
2013-04-15 21:06:36 -05:00
|
|
|
discrim_symbols: @mut HashMap<ast::node_id, @~str>,
|
2013-04-03 08:28:36 -05:00
|
|
|
tydescs: @mut HashMap<ty::t, @mut tydesc_info>,
|
2012-08-24 17:31:33 -05:00
|
|
|
// Set when running emit_tydescs to enforce that no more tydescs are
|
|
|
|
// created.
|
2013-02-21 17:30:24 -06:00
|
|
|
finished_tydescs: @mut bool,
|
2012-03-06 04:33:25 -06:00
|
|
|
// Track mapping of external ids to local items imported for inlining
|
2013-04-03 08:28:36 -05:00
|
|
|
external: @mut HashMap<ast::def_id, Option<ast::node_id>>,
|
2012-03-06 04:33:25 -06:00
|
|
|
// Cache instances of monomorphized functions
|
2013-04-03 08:28:36 -05:00
|
|
|
monomorphized: @mut HashMap<mono_id, ValueRef>,
|
|
|
|
monomorphizing: @mut HashMap<ast::def_id, uint>,
|
2012-03-12 10:31:22 -05:00
|
|
|
// Cache computed type parameter uses (see type_use.rs)
|
2013-04-16 19:30:31 -05:00
|
|
|
type_use_cache: @mut HashMap<ast::def_id, @~[type_use::type_uses]>,
|
2012-03-08 09:10:25 -06:00
|
|
|
// Cache generated vtables
|
2013-04-03 08:28:36 -05:00
|
|
|
vtables: @mut HashMap<mono_id, ValueRef>,
|
2012-04-21 15:23:25 -05:00
|
|
|
// Cache of constant strings,
|
2013-04-03 08:28:36 -05:00
|
|
|
const_cstr_cache: @mut HashMap<@~str, ValueRef>,
|
2012-11-06 19:13:52 -06:00
|
|
|
|
|
|
|
// Reverse-direction for const ptrs cast from globals.
|
|
|
|
// Key is an int, cast from a ValueRef holding a *T,
|
|
|
|
// Val is a ValueRef holding a *[T].
|
|
|
|
//
|
|
|
|
// Needed because LLVM loses pointer->pointee association
|
|
|
|
// when we ptrcast, and we have to ptrcast during translation
|
|
|
|
// of a [T] const because we form a slice, a [*T,int] pair, not
|
|
|
|
// a pointer to an LLVM array type.
|
2013-04-03 08:28:36 -05:00
|
|
|
const_globals: @mut HashMap<int, ValueRef>,
|
2012-11-06 19:13:52 -06:00
|
|
|
|
|
|
|
// Cache of emitted const values
|
2013-04-03 08:28:36 -05:00
|
|
|
const_values: @mut HashMap<ast::node_id, ValueRef>,
|
2013-03-27 17:41:43 -05:00
|
|
|
|
|
|
|
// Cache of external const values
|
2013-04-03 08:28:36 -05:00
|
|
|
extern_const_values: @mut HashMap<ast::def_id, ValueRef>,
|
2013-03-27 17:41:43 -05:00
|
|
|
|
2013-04-03 08:28:36 -05:00
|
|
|
module_data: @mut HashMap<~str, ValueRef>,
|
|
|
|
lltypes: @mut HashMap<ty::t, TypeRef>,
|
|
|
|
llsizingtypes: @mut HashMap<ty::t, TypeRef>,
|
|
|
|
adt_reprs: @mut HashMap<ty::t, @adt::Repr>,
|
2011-08-19 17:16:48 -05:00
|
|
|
names: namegen,
|
2012-08-06 12:53:38 -05:00
|
|
|
next_addrspace: addrspace_gen,
|
2013-05-03 13:30:30 -05:00
|
|
|
symbol_hasher: @mut hash::State,
|
2013-04-03 08:28:36 -05:00
|
|
|
type_hashcodes: @mut HashMap<ty::t, @str>,
|
|
|
|
type_short_names: @mut HashMap<ty::t, ~str>,
|
2013-04-15 21:06:36 -05:00
|
|
|
all_llvm_symbols: @mut HashSet<@~str>,
|
2011-08-19 17:16:48 -05:00
|
|
|
tcx: ty::ctxt,
|
2013-01-10 12:59:58 -06:00
|
|
|
maps: astencode::Maps,
|
2013-02-04 16:02:01 -06:00
|
|
|
stats: @mut Stats,
|
2013-02-19 01:40:42 -06:00
|
|
|
upcalls: @upcall::Upcalls,
|
2011-08-19 17:16:48 -05:00
|
|
|
tydesc_type: TypeRef,
|
2011-10-14 19:00:17 -05:00
|
|
|
int_type: TypeRef,
|
|
|
|
float_type: TypeRef,
|
2011-08-19 17:16:48 -05:00
|
|
|
task_type: TypeRef,
|
2011-10-14 22:38:24 -05:00
|
|
|
opaque_vec_type: TypeRef,
|
2011-08-24 09:30:20 -05:00
|
|
|
builder: BuilderRef_res,
|
2013-02-04 16:02:01 -06:00
|
|
|
shape_cx: shape::Ctxt,
|
2011-11-09 23:55:09 -06:00
|
|
|
crate_map: ValueRef,
|
2012-07-16 14:28:15 -05:00
|
|
|
// Set when at least one function uses GC. Needed so that
|
|
|
|
// decl_gc_metadata knows whether to link to the module metadata, which
|
|
|
|
// is not emitted by LLVM's GC pass when no functions use GC.
|
2013-02-21 17:30:24 -06:00
|
|
|
uses_gc: @mut bool,
|
2013-02-19 01:40:42 -06:00
|
|
|
dbg_cx: Option<debuginfo::DebugContext>,
|
2013-02-21 17:30:24 -06:00
|
|
|
do_not_commit_warning_issued: @mut bool
|
2013-01-06 13:16:14 -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-03-28 20:39:09 -05:00
|
|
|
for self.tys.each |t| { assert!(!ty::type_needs_infer(*t)); }
|
|
|
|
for self.self_ty.each |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-02-21 17:30:24 -06:00
|
|
|
ccx: @@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-03-05 19:36:39 -06:00
|
|
|
pub fn warn_not_to_commit(ccx: @CrateContext, msg: &str) {
|
2013-02-21 17:30:24 -06:00
|
|
|
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>,
|
|
|
|
dest: BasicBlockRef
|
|
|
|
}
|
2012-02-15 06:57:29 -06:00
|
|
|
|
2013-04-17 11:15:37 -05:00
|
|
|
pub fn scope_clean_changed(scope_info: &mut scope_info) {
|
2012-11-06 20:41:06 -06:00
|
|
|
if scope_info.cleanup_paths.len() > 0u { scope_info.cleanup_paths = ~[]; }
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-28 17:54:45 -05:00
|
|
|
// This is not the same as datum::Datum::root(), which is used to keep copies
|
|
|
|
// of @ values live for as long as a borrowed pointer to the interior exists.
|
|
|
|
// In the new GC, we can identify immediates on the stack without difficulty,
|
|
|
|
// but have trouble knowing where non-immediates are on the stack. For
|
|
|
|
// non-immediates, we must add an additional level of indirection, which
|
|
|
|
// allows us to alloca a pointer with the right addrspace.
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn root_for_cleanup(bcx: block, v: ValueRef, t: ty::t)
|
2013-02-19 01:40:42 -06:00
|
|
|
-> (ValueRef, bool) {
|
2012-08-06 12:53:38 -05:00
|
|
|
let ccx = bcx.ccx();
|
|
|
|
|
|
|
|
let addrspace = base::get_tydesc(ccx, t).addrspace;
|
|
|
|
if addrspace > gc_box_addrspace {
|
|
|
|
let llty = type_of::type_of_rooted(ccx, t);
|
|
|
|
let root = base::alloca(bcx, llty);
|
|
|
|
build::Store(bcx, build::PointerCast(bcx, v, llty), root);
|
2013-02-19 01:40:42 -06:00
|
|
|
(root, true)
|
2012-08-06 12:53:38 -05:00
|
|
|
} else {
|
2013-02-19 01:40:42 -06:00
|
|
|
(v, false)
|
2012-08-06 12:53:38 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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; }
|
2012-08-22 19:24:52 -05:00
|
|
|
debug!("add_clean(%s, %s, %s)",
|
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
|
|
|
bcx.to_str(),
|
|
|
|
val_str(bcx.ccx().tn, val),
|
|
|
|
t.repr(bcx.tcx()));
|
2013-02-19 01:40:42 -06:00
|
|
|
let (root, rooted) = root_for_cleanup(bcx, val, t);
|
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| {
|
|
|
|
scope_info.cleanups.push(
|
2012-09-26 19:33:34 -05:00
|
|
|
clean(|a| glue::drop_ty_root(a, root, rooted, t),
|
|
|
|
cleanup_type));
|
2012-11-06 20:41:06 -06:00
|
|
|
scope_clean_changed(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)",
|
2012-05-14 22:32:29 -05:00
|
|
|
cx.to_str(), val_str(cx.ccx().tn, 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));
|
2012-11-06 20:41:06 -06:00
|
|
|
scope_clean_changed(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)",
|
2012-08-06 12:53:38 -05:00
|
|
|
bcx.to_str(), val_str(bcx.ccx().tn, 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()));
|
2013-02-19 01:40:42 -06:00
|
|
|
let (root, rooted) = root_for_cleanup(bcx, val, t);
|
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| {
|
|
|
|
scope_info.cleanups.push(
|
2012-09-26 19:33:34 -05:00
|
|
|
clean_temp(val, |a| glue::drop_ty_root(a, root, rooted, t),
|
|
|
|
cleanup_type));
|
2013-01-11 23:01:42 -06:00
|
|
|
scope_clean_changed(scope_info);
|
|
|
|
}
|
|
|
|
}
|
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(),
|
|
|
|
val_str(bcx.ccx().tn, frozen_val_ref),
|
|
|
|
val_str(bcx.ccx().tn, 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-05-04 13:29:32 -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));
|
2012-11-06 20:41:06 -06:00
|
|
|
scope_clean_changed(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));
|
2012-11-06 20:41:06 -06:00
|
|
|
scope_clean_changed(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-05-02 20:15:36 -05:00
|
|
|
let scope_info = &mut *scope_info; // FIXME(#5074) workaround borrowck
|
2012-08-28 17:54:45 -05:00
|
|
|
let cleanup_pos = vec::position(
|
2012-11-06 20:41:06 -06:00
|
|
|
scope_info.cleanups,
|
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
|
|
|
|
});
|
|
|
|
for cleanup_pos.each |i| {
|
2012-11-06 20:41:06 -06:00
|
|
|
scope_info.cleanups =
|
2013-02-08 13:28:20 -06:00
|
|
|
vec::append(vec::slice(scope_info.cleanups, 0u, *i).to_vec(),
|
|
|
|
vec::slice(scope_info.cleanups,
|
2012-09-19 18:55:01 -05:00
|
|
|
*i + 1u,
|
2012-11-06 20:41:06 -06:00
|
|
|
scope_info.cleanups.len()));
|
|
|
|
scope_clean_changed(scope_info);
|
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-02-26 19:12:00 -06: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,
|
|
|
|
callee_id: Some(self.callee_id),
|
|
|
|
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-02-19 01:40:42 -06:00
|
|
|
pub fn ty_str(tn: @TypeNames, t: TypeRef) -> @str {
|
2012-08-01 19:30:05 -05:00
|
|
|
return lib::llvm::type_to_str(tn, t);
|
2011-07-21 19:27:34 -05:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn val_ty(v: ValueRef) -> TypeRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
return llvm::LLVMTypeOf(v);
|
|
|
|
}
|
|
|
|
}
|
2011-07-21 19:27:34 -05:00
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn val_str(tn: @TypeNames, v: ValueRef) -> @str {
|
2012-08-01 19:30:05 -05:00
|
|
|
return ty_str(tn, val_ty(v));
|
|
|
|
}
|
2011-07-21 19:27:34 -05:00
|
|
|
|
2013-05-02 20:15:36 -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_ {
|
|
|
|
pub fn ccx(@mut self) -> @CrateContext { *self.fcx.ccx }
|
|
|
|
pub fn tcx(@mut self) -> ty::ctxt { self.fcx.ccx.tcx }
|
|
|
|
pub fn sess(@mut self) -> Session { self.fcx.ccx.sess }
|
2012-05-14 22:32:29 -05:00
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn node_id_to_str(@mut 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-05-31 17:17:22 -05:00
|
|
|
pub fn expr_to_str(@mut 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-05-31 17:17:22 -05:00
|
|
|
pub fn expr_is_lval(@mut 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-05-31 17:17:22 -05:00
|
|
|
pub fn expr_kind(@mut 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-05-31 17:17:22 -05:00
|
|
|
pub fn def(@mut 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-05-31 17:17:22 -05:00
|
|
|
pub fn val_str(@mut self, val: ValueRef) -> @str {
|
2012-05-22 20:44:28 -05:00
|
|
|
val_str(self.ccx().tn, val)
|
|
|
|
}
|
2012-08-28 17:54:45 -05:00
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn llty_str(@mut self, llty: TypeRef) -> @str {
|
2012-08-28 17:54:45 -05:00
|
|
|
ty_str(self.ccx().tn, llty)
|
|
|
|
}
|
|
|
|
|
2013-05-31 17:17:22 -05:00
|
|
|
pub fn ty_to_str(@mut 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
|
|
|
|
|
|
|
pub fn to_str(@mut 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
|
|
|
|
|
|
|
// LLVM type constructors.
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_void() -> TypeRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
return llvm::LLVMVoidType();
|
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_nil() -> TypeRef {
|
2013-05-19 00:07:44 -05:00
|
|
|
return T_struct([], false)
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_metadata() -> TypeRef { unsafe { return llvm::LLVMMetadataType(); } }
|
2011-11-15 20:11:22 -06:00
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_i1() -> TypeRef { unsafe { return llvm::LLVMInt1Type(); } }
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_i8() -> TypeRef { unsafe { return llvm::LLVMInt8Type(); } }
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_i16() -> TypeRef { unsafe { return llvm::LLVMInt16Type(); } }
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_i32() -> TypeRef { unsafe { return llvm::LLVMInt32Type(); } }
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_i64() -> TypeRef { unsafe { return llvm::LLVMInt64Type(); } }
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_f32() -> TypeRef { unsafe { return llvm::LLVMFloatType(); } }
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_f64() -> TypeRef { unsafe { return llvm::LLVMDoubleType(); } }
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2013-02-06 16:28:02 -06:00
|
|
|
pub fn T_bool() -> TypeRef { return T_i8(); }
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_int(targ_cfg: @session::config) -> TypeRef {
|
2012-08-06 14:34:08 -05:00
|
|
|
return match targ_cfg.arch {
|
2013-03-13 21:25:28 -05:00
|
|
|
X86 => T_i32(),
|
|
|
|
X86_64 => T_i64(),
|
|
|
|
Arm => T_i32(),
|
|
|
|
Mips => T_i32()
|
2011-10-14 18:45:25 -05:00
|
|
|
};
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn T_int_ty(cx: @CrateContext, t: ast::int_ty) -> TypeRef {
|
2012-08-06 14:34:08 -05:00
|
|
|
match t {
|
2012-08-03 21:59:04 -05:00
|
|
|
ast::ty_i => cx.int_type,
|
|
|
|
ast::ty_char => T_char(),
|
|
|
|
ast::ty_i8 => T_i8(),
|
|
|
|
ast::ty_i16 => T_i16(),
|
|
|
|
ast::ty_i32 => T_i32(),
|
|
|
|
ast::ty_i64 => T_i64()
|
2011-12-07 14:06:12 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn T_uint_ty(cx: @CrateContext, t: ast::uint_ty) -> TypeRef {
|
2012-08-06 14:34:08 -05:00
|
|
|
match t {
|
2012-08-03 21:59:04 -05:00
|
|
|
ast::ty_u => cx.int_type,
|
|
|
|
ast::ty_u8 => T_i8(),
|
|
|
|
ast::ty_u16 => T_i16(),
|
|
|
|
ast::ty_u32 => T_i32(),
|
|
|
|
ast::ty_u64 => T_i64()
|
2011-12-07 14:06:12 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn T_float_ty(cx: @CrateContext, t: ast::float_ty) -> TypeRef {
|
2012-08-06 14:34:08 -05:00
|
|
|
match t {
|
2012-08-03 21:59:04 -05:00
|
|
|
ast::ty_f => cx.float_type,
|
|
|
|
ast::ty_f32 => T_f32(),
|
|
|
|
ast::ty_f64 => T_f64()
|
2011-12-07 14:06:12 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_float(targ_cfg: @session::config) -> TypeRef {
|
2012-08-06 14:34:08 -05:00
|
|
|
return match targ_cfg.arch {
|
2013-03-13 21:25:28 -05:00
|
|
|
X86 => T_f64(),
|
|
|
|
X86_64 => T_f64(),
|
|
|
|
Arm => T_f64(),
|
|
|
|
Mips => T_f64()
|
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 T_char() -> TypeRef { return T_i32(); }
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_size_t(targ_cfg: @session::config) -> TypeRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
return T_int(targ_cfg);
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-03-05 19:36:39 -06:00
|
|
|
pub fn T_fn(inputs: &[TypeRef], output: TypeRef) -> TypeRef {
|
2013-01-23 13:43:58 -06:00
|
|
|
unsafe {
|
|
|
|
return llvm::LLVMFunctionType(output, to_ptr(inputs),
|
|
|
|
inputs.len() as c_uint,
|
|
|
|
False);
|
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn T_fn_pair(cx: @CrateContext, tfn: TypeRef) -> TypeRef {
|
2013-05-19 00:07:44 -05:00
|
|
|
return T_struct([T_ptr(tfn), T_opaque_cbox_ptr(cx)], false);
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_ptr(t: TypeRef) -> TypeRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
return llvm::LLVMPointerType(t, default_addrspace);
|
|
|
|
}
|
2012-08-06 12:53:38 -05:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_root(t: TypeRef, addrspace: addrspace) -> TypeRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
return llvm::LLVMPointerType(t, addrspace);
|
|
|
|
}
|
2012-01-16 04:21:01 -06:00
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2013-04-10 07:47:22 -05:00
|
|
|
pub fn T_struct(elts: &[TypeRef], packed: bool) -> TypeRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
return llvm::LLVMStructType(to_ptr(elts),
|
|
|
|
elts.len() as c_uint,
|
2013-04-10 07:47:22 -05:00
|
|
|
packed as Bool);
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-03-05 19:36:39 -06:00
|
|
|
pub fn T_named_struct(name: &str) -> TypeRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
let c = llvm::LLVMGetGlobalContext();
|
|
|
|
return str::as_c_str(name, |buf| llvm::LLVMStructCreateNamed(c, buf));
|
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-04-10 07:47:22 -05:00
|
|
|
pub fn set_struct_body(t: TypeRef, elts: &[TypeRef], packed: bool) {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
llvm::LLVMStructSetBody(t,
|
|
|
|
to_ptr(elts),
|
|
|
|
elts.len() as c_uint,
|
2013-04-10 07:47:22 -05:00
|
|
|
packed as Bool);
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-05-19 00:07:44 -05:00
|
|
|
pub fn T_empty_struct() -> TypeRef { return T_struct([], false); }
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2012-03-08 09:17:59 -06:00
|
|
|
// A vtable is, in reality, a vtable pointer followed by zero or more pointers
|
2012-03-08 16:37:45 -06:00
|
|
|
// to tydescs and other vtables that it closes over. But the types and number
|
|
|
|
// of those are rarely known to the code that needs to manipulate them, so
|
|
|
|
// they are described by this opaque type.
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_vtable() -> TypeRef { T_array(T_ptr(T_i8()), 1u) }
|
2012-01-02 09:50:51 -06:00
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_task(targ_cfg: @session::config) -> TypeRef {
|
2013-05-19 00:07:44 -05:00
|
|
|
let t = T_named_struct("task");
|
2011-07-27 07:19:39 -05:00
|
|
|
|
2011-09-02 17:34:58 -05:00
|
|
|
// Refcount
|
|
|
|
// Delegate pointer
|
|
|
|
// Stack segment pointer
|
|
|
|
// Runtime SP
|
|
|
|
// Rust SP
|
|
|
|
// GC chain
|
2011-08-19 17:16:48 -05:00
|
|
|
|
|
|
|
|
2011-09-02 17:34:58 -05:00
|
|
|
// Domain pointer
|
|
|
|
// Crate cache pointer
|
2011-08-19 17:16:48 -05:00
|
|
|
|
2011-10-14 22:38:24 -05:00
|
|
|
let t_int = T_int(targ_cfg);
|
2011-08-19 17:16:48 -05:00
|
|
|
let elems =
|
2012-06-29 18:26:56 -05:00
|
|
|
~[t_int, t_int, t_int, t_int,
|
|
|
|
t_int, t_int, t_int, t_int];
|
2013-04-10 07:47:22 -05:00
|
|
|
set_struct_body(t, elems, false);
|
2012-08-01 19:30:05 -05:00
|
|
|
return t;
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn T_tydesc_field(cx: @CrateContext, field: uint) -> TypeRef {
|
2011-07-14 19:08:22 -05:00
|
|
|
// Bit of a kludge: pick the fn typeref out of the tydesc..
|
|
|
|
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
let mut tydesc_elts: ~[TypeRef] =
|
|
|
|
vec::from_elem::<TypeRef>(abi::n_tydesc_fields,
|
|
|
|
T_nil());
|
|
|
|
llvm::LLVMGetStructElementTypes(
|
|
|
|
cx.tydesc_type,
|
|
|
|
ptr::to_mut_unsafe_ptr(&mut tydesc_elts[0]));
|
|
|
|
let t = llvm::LLVMGetElementType(tydesc_elts[field]);
|
|
|
|
return t;
|
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn T_generic_glue_fn(cx: @CrateContext) -> TypeRef {
|
2013-01-18 16:30:29 -06:00
|
|
|
let s = @"glue_fn";
|
2012-08-06 14:34:08 -05:00
|
|
|
match name_has_type(cx.tn, s) {
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(t) => return t,
|
2012-08-03 21:59:04 -05:00
|
|
|
_ => ()
|
|
|
|
}
|
2011-07-27 07:19:39 -05:00
|
|
|
let t = T_tydesc_field(cx, abi::tydesc_field_drop_glue);
|
2012-01-13 02:32:05 -06:00
|
|
|
associate_type(cx.tn, s, t);
|
2012-08-01 19:30:05 -05:00
|
|
|
return t;
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_tydesc(targ_cfg: @session::config) -> TypeRef {
|
2013-05-19 00:07:44 -05:00
|
|
|
let tydesc = T_named_struct("tydesc");
|
2011-07-27 07:19:39 -05:00
|
|
|
let tydescpp = T_ptr(T_ptr(tydesc));
|
|
|
|
let pvoid = T_ptr(T_i8());
|
|
|
|
let glue_fn_ty =
|
2013-05-22 01:17:04 -05:00
|
|
|
T_ptr(T_fn([T_ptr(T_nil()), tydescpp, pvoid], T_void()));
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2011-10-14 22:38:24 -05:00
|
|
|
let int_type = T_int(targ_cfg);
|
2011-08-04 13:25:09 -05:00
|
|
|
let elems =
|
2012-07-09 16:56:11 -05:00
|
|
|
~[int_type, int_type,
|
|
|
|
glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty,
|
|
|
|
T_ptr(T_i8()), T_ptr(T_i8())];
|
2013-04-10 07:47:22 -05:00
|
|
|
set_struct_body(tydesc, elems, false);
|
2012-08-01 19:30:05 -05:00
|
|
|
return tydesc;
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_array(t: TypeRef, n: uint) -> TypeRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
return llvm::LLVMArrayType(t, n as c_uint);
|
|
|
|
}
|
2012-01-16 04:21:01 -06:00
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2013-05-02 02:59:26 -05:00
|
|
|
pub fn T_vector(t: TypeRef, n: uint) -> TypeRef {
|
|
|
|
unsafe {
|
|
|
|
return llvm::LLVMVectorType(t, n as c_uint);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-07-14 19:08:22 -05:00
|
|
|
// Interior vector.
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_vec2(targ_cfg: @session::config, t: TypeRef) -> TypeRef {
|
2013-05-19 00:07:44 -05:00
|
|
|
return T_struct([T_int(targ_cfg), // fill
|
|
|
|
T_int(targ_cfg), // alloc
|
|
|
|
T_array(t, 0u)], // elements
|
2013-04-10 07:47:22 -05:00
|
|
|
false);
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn T_vec(ccx: @CrateContext, t: TypeRef) -> TypeRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
return T_vec2(ccx.sess.targ_cfg, t);
|
2011-10-14 22:38:24 -05:00
|
|
|
}
|
|
|
|
|
2011-07-14 19:08:22 -05:00
|
|
|
// Note that the size of this one is in bytes.
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_opaque_vec(targ_cfg: @session::config) -> TypeRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
return T_vec2(targ_cfg, T_i8());
|
2011-10-14 22:38:24 -05:00
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2012-02-01 20:52:08 -06: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).
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn tuplify_box_ty(tcx: ty::ctxt, t: ty::t) -> ty::t {
|
2013-01-14 23:36:27 -06:00
|
|
|
let ptr = ty::mk_ptr(
|
|
|
|
tcx,
|
2013-04-22 22:19:05 -05:00
|
|
|
ty::mt {ty: ty::mk_nil(), mutbl: ast::m_imm}
|
2013-01-14 23:36:27 -06:00
|
|
|
);
|
2013-04-22 22:19:05 -05:00
|
|
|
return ty::mk_tup(tcx, ~[ty::mk_uint(), ty::mk_type(tcx),
|
2012-02-01 20:52:08 -06:00
|
|
|
ptr, ptr,
|
2012-06-29 18:26:56 -05:00
|
|
|
t]);
|
2012-02-01 20:52:08 -06:00
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn T_box_header_fields(cx: @CrateContext) -> ~[TypeRef] {
|
2012-02-01 20:52:08 -06:00
|
|
|
let ptr = T_ptr(T_i8());
|
2012-08-01 19:30:05 -05:00
|
|
|
return ~[cx.int_type, T_ptr(cx.tydesc_type), ptr, ptr];
|
2012-02-01 20:52:08 -06:00
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn T_box_header(cx: @CrateContext) -> TypeRef {
|
2013-04-10 07:47:22 -05:00
|
|
|
return T_struct(T_box_header_fields(cx), false);
|
2012-02-01 20:52:08 -06:00
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn T_box(cx: @CrateContext, t: TypeRef) -> TypeRef {
|
2013-05-19 00:07:44 -05:00
|
|
|
return T_struct(vec::append(T_box_header_fields(cx), [t]), false);
|
2012-02-01 20:52:08 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_box_ptr(t: TypeRef) -> TypeRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
return llvm::LLVMPointerType(t, gc_box_addrspace);
|
|
|
|
}
|
2012-05-07 16:27:43 -05:00
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn T_opaque_box(cx: @CrateContext) -> TypeRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
return T_box(cx, T_i8());
|
2012-02-01 20:52:08 -06:00
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn T_opaque_box_ptr(cx: @CrateContext) -> TypeRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
return T_box_ptr(T_opaque_box(cx));
|
2011-10-14 18:45:25 -05:00
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn T_unique(cx: @CrateContext, t: TypeRef) -> TypeRef {
|
2013-05-19 00:07:44 -05:00
|
|
|
return T_struct(vec::append(T_box_header_fields(cx), [t]), false);
|
2012-05-09 16:11:46 -05:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_unique_ptr(t: TypeRef) -> TypeRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
return llvm::LLVMPointerType(t, gc_box_addrspace);
|
|
|
|
}
|
2012-05-09 16:11:46 -05:00
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn T_port(cx: @CrateContext, _t: TypeRef) -> TypeRef {
|
2013-05-19 00:07:44 -05:00
|
|
|
return T_struct([cx.int_type], false); // Refcount
|
2011-07-14 19:08:22 -05:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn T_chan(cx: @CrateContext, _t: TypeRef) -> TypeRef {
|
2013-05-19 00:07:44 -05:00
|
|
|
return T_struct([cx.int_type], false); // Refcount
|
2011-07-14 19:08:22 -05:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn T_taskptr(cx: @CrateContext) -> TypeRef { return T_ptr(cx.task_type); }
|
2011-07-14 19:08:22 -05:00
|
|
|
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn T_opaque_cbox_ptr(cx: @CrateContext) -> TypeRef {
|
2013-03-01 14:11:07 -06:00
|
|
|
// closures look like boxes (even when they are ~fn or &fn)
|
2012-02-01 20:52:08 -06:00
|
|
|
// see trans_closure.rs
|
2012-08-01 19:30:05 -05:00
|
|
|
return T_opaque_box_ptr(cx);
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn T_enum_discrim(cx: @CrateContext) -> TypeRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
return cx.int_type;
|
2011-11-23 14:01:15 -06:00
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn T_captured_tydescs(cx: @CrateContext, n: uint) -> TypeRef {
|
2013-04-10 07:47:22 -05:00
|
|
|
return T_struct(vec::from_elem::<TypeRef>(n, T_ptr(cx.tydesc_type)), false);
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-03-08 23:16:09 -06:00
|
|
|
pub fn T_opaque_trait(cx: @CrateContext, store: ty::TraitStore) -> TypeRef {
|
|
|
|
match store {
|
2013-03-12 15:00:50 -05:00
|
|
|
ty::BoxTraitStore => {
|
2013-05-19 00:07:44 -05:00
|
|
|
T_struct([T_ptr(cx.tydesc_type), T_opaque_box_ptr(cx)], false)
|
2012-10-31 17:09:26 -05:00
|
|
|
}
|
2013-03-08 23:16:09 -06:00
|
|
|
ty::UniqTraitStore => {
|
2013-05-19 00:07:44 -05:00
|
|
|
T_struct([T_ptr(cx.tydesc_type),
|
2013-05-15 19:38:52 -05:00
|
|
|
T_unique_ptr(T_unique(cx, T_i8()))],
|
2013-04-10 07:47:22 -05:00
|
|
|
false)
|
2012-10-31 17:09:26 -05:00
|
|
|
}
|
2013-03-08 23:16:09 -06:00
|
|
|
ty::RegionTraitStore(_) => {
|
2013-05-19 00:07:44 -05:00
|
|
|
T_struct([T_ptr(cx.tydesc_type), T_ptr(T_i8())], false)
|
2013-03-08 23:16:09 -06:00
|
|
|
}
|
2012-10-05 18:55:42 -05:00
|
|
|
}
|
2012-01-07 15:44:14 -06:00
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_opaque_port_ptr() -> TypeRef { return T_ptr(T_i8()); }
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn T_opaque_chan_ptr() -> TypeRef { return T_ptr(T_i8()); }
|
2011-07-14 19:08:22 -05:00
|
|
|
|
|
|
|
|
|
|
|
// LLVM constant constructors.
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn C_null(t: TypeRef) -> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
return llvm::LLVMConstNull(t);
|
|
|
|
}
|
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
|
2013-02-18 16:16:21 -06:00
|
|
|
pub fn C_undef(t: TypeRef) -> ValueRef {
|
|
|
|
unsafe {
|
|
|
|
return llvm::LLVMGetUndef(t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn C_integral(t: TypeRef, u: u64, sign_extend: Bool) -> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
return llvm::LLVMConstInt(t, u, sign_extend);
|
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-03-05 19:36:39 -06:00
|
|
|
pub fn C_floating(s: &str, t: TypeRef) -> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
return str::as_c_str(s, |buf| llvm::LLVMConstRealOfString(t, buf));
|
|
|
|
}
|
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-01-30 13:46:19 -06:00
|
|
|
pub fn C_bool(b: bool) -> ValueRef {
|
2012-03-26 09:09:27 -05:00
|
|
|
C_integral(T_bool(), if b { 1u64 } else { 0u64 }, False)
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-02-06 16:28:02 -06:00
|
|
|
pub fn C_i1(b: bool) -> ValueRef {
|
|
|
|
return C_integral(T_i1(), if b { 1 } else { 0 }, False);
|
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn C_i32(i: i32) -> ValueRef {
|
2012-08-01 19:30:05 -05:00
|
|
|
return C_integral(T_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 {
|
2012-08-01 19:30:05 -05:00
|
|
|
return C_integral(T_i64(), i as u64, True);
|
2011-11-15 20:11:22 -06:00
|
|
|
}
|
|
|
|
|
2013-02-19 01:40:42 -06:00
|
|
|
pub fn C_int(cx: @CrateContext, i: int) -> ValueRef {
|
2012-08-01 19:30:05 -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-02-19 01:40:42 -06:00
|
|
|
pub fn C_uint(cx: @CrateContext, i: uint) -> ValueRef {
|
2012-08-01 19:30:05 -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 {
|
|
|
|
return C_integral(T_i8(), i as u64, False);
|
|
|
|
}
|
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-02-19 01:40:42 -06:00
|
|
|
pub fn C_cstr(cx: @CrateContext, s: @~str) -> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
2013-02-05 21:41:45 -06:00
|
|
|
match cx.const_cstr_cache.find(&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-02-10 18:33:16 -06:00
|
|
|
let sc = do str::as_c_str(*s) |buf| {
|
2013-02-16 12:36:09 -06:00
|
|
|
llvm::LLVMConstString(buf, s.len() as c_uint, False)
|
2013-01-10 23:23:07 -06:00
|
|
|
};
|
|
|
|
let g =
|
2013-05-02 03:16:07 -05:00
|
|
|
str::as_c_str(fmt!("str%u", (cx.names)("str").repr),
|
2013-01-10 23:23:07 -06:00
|
|
|
|buf| llvm::LLVMAddGlobal(cx.llmod, val_ty(sc), buf));
|
|
|
|
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-02-19 01:40:42 -06:00
|
|
|
pub fn C_estr_slice(cx: @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-01-10 23:23:07 -06:00
|
|
|
let cs = llvm::LLVMConstPointerCast(C_cstr(cx, s), T_ptr(T_i8()));
|
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 {
|
|
|
|
return do str::as_c_str(s) |buf| {
|
|
|
|
llvm::LLVMConstString(buf, str::len(s) as c_uint, False)
|
|
|
|
};
|
|
|
|
}
|
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; }
|
|
|
|
return llvm::LLVMConstArray(T_i8(),
|
|
|
|
vec::raw::to_ptr(elts),
|
|
|
|
elts.len() as c_uint);
|
|
|
|
}
|
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| {
|
|
|
|
llvm::LLVMConstStruct(ptr, len as c_uint, False)
|
|
|
|
}
|
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| {
|
|
|
|
llvm::LLVMConstStruct(ptr, len as c_uint, True)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-30 13:46:19 -06:00
|
|
|
pub fn C_named_struct(T: TypeRef, elts: &[ValueRef]) -> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
do vec::as_imm_buf(elts) |ptr, len| {
|
|
|
|
llvm::LLVMConstNamedStruct(T, ptr, len as c_uint)
|
|
|
|
}
|
2012-08-28 17:54:45 -05:00
|
|
|
}
|
2011-07-14 19:08:22 -05:00
|
|
|
}
|
|
|
|
|
2013-03-05 19:36:39 -06:00
|
|
|
pub fn C_array(ty: TypeRef, elts: &[ValueRef]) -> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
return llvm::LLVMConstArray(ty, vec::raw::to_ptr(elts),
|
|
|
|
elts.len() as c_uint);
|
|
|
|
}
|
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 {
|
|
|
|
return llvm::LLVMConstString(
|
2013-04-20 09:27:16 -05:00
|
|
|
cast::transmute(vec::raw::to_ptr(bytes)),
|
2013-01-10 23:23:07 -06:00
|
|
|
bytes.len() as c_uint, True);
|
|
|
|
}
|
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 {
|
|
|
|
return llvm::LLVMConstString(
|
2013-04-20 09:27:16 -05:00
|
|
|
cast::transmute(vec::raw::to_ptr(bytes)),
|
2013-01-10 23:23:07 -06:00
|
|
|
bytes.len() as c_uint, False);
|
|
|
|
}
|
2011-08-04 12:46:10 -05:00
|
|
|
}
|
|
|
|
|
2013-04-17 11:15:37 -05:00
|
|
|
pub fn C_shape(ccx: @CrateContext, bytes: ~[u8]) -> ValueRef {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
let llshape = C_bytes_plus_null(bytes);
|
2013-05-02 03:16:07 -05:00
|
|
|
let name = fmt!("shape%u", (ccx.names)("shape").repr);
|
2013-01-10 23:23:07 -06:00
|
|
|
let llglobal = str::as_c_str(name, |buf| {
|
|
|
|
llvm::LLVMAddGlobal(ccx.llmod, val_ty(llshape), buf)
|
|
|
|
});
|
|
|
|
llvm::LLVMSetInitializer(llglobal, llshape);
|
|
|
|
llvm::LLVMSetGlobalConstant(llglobal, True);
|
|
|
|
lib::llvm::SetLinkage(llglobal, lib::llvm::InternalLinkage);
|
|
|
|
return llvm::LLVMConstPointerCast(llglobal, T_ptr(T_i8()));
|
|
|
|
}
|
2011-08-04 13:25:09 -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-02-18 16:16:21 -06:00
|
|
|
pub fn const_get_elt(cx: @CrateContext, v: ValueRef, us: &[c_uint])
|
|
|
|
-> 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)",
|
|
|
|
val_str(cx.tn, v), us, val_str(cx.tn, r));
|
|
|
|
|
|
|
|
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 {
|
2012-07-14 00:57:48 -05:00
|
|
|
let mut r = ~"", first = true;
|
2013-03-10 10:02:16 -05:00
|
|
|
for p.each |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-02-10 18:33:16 -06: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-01-30 13:46:19 -06: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-02-27 18:28:37 -06:00
|
|
|
pub fn expr_ty_adjusted(bcx: block, ex: @ast::expr) -> ty::t {
|
|
|
|
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
|
|
|
|
|
|
|
if !params.all(|t| !ty::type_needs_infer(*t)) {
|
|
|
|
bcx.sess().bug(
|
|
|
|
fmt!("Type parameters for node %d include inference types: %s",
|
|
|
|
id, str::connect(params.map(|t| bcx.ty_to_str(*t)), ",")));
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
let filename_cstr = C_cstr(bcx.ccx(), @/*bad*/copy loc.file.name);
|
|
|
|
let filename = build::PointerCast(bcx, filename_cstr, T_ptr(T_i8()));
|
|
|
|
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))
|
|
|
|
}
|