1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 #![allow(non_camel_case_types, non_snake_case)]
13 //! Code that is useful in various trans modules.
17 use llvm::{ValueRef, BasicBlockRef, BuilderRef, ContextRef, TypeKind};
18 use llvm::{True, False, Bool, OperandBundleDef};
19 use rustc::hir::def::Def;
20 use rustc::hir::def_id::DefId;
21 use rustc::infer::TransNormalize;
22 use rustc::util::common::MemoizationMap;
23 use middle::lang_items::LangItem;
24 use rustc::ty::subst::Substs;
25 use abi::{Abi, FnType};
32 use debuginfo::{self, DebugLoc};
39 use rustc::ty::{self, Ty, TyCtxt};
40 use rustc::ty::layout::Layout;
41 use rustc::traits::{self, SelectionContext, Reveal};
42 use rustc::ty::fold::TypeFoldable;
45 use arena::TypedArena;
46 use libc::{c_uint, c_char};
48 use std::ffi::CString;
49 use std::cell::{Cell, RefCell};
52 use syntax::parse::token::InternedString;
53 use syntax::parse::token;
54 use syntax_pos::{DUMMY_SP, Span};
56 pub use context::{CrateContext, SharedCrateContext};
58 /// Is the type's representation size known at compile time?
59 pub fn type_is_sized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
60 ty.is_sized(tcx, &tcx.empty_parameter_environment(), DUMMY_SP)
63 pub fn type_is_fat_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
65 ty::TyRawPtr(ty::TypeAndMut{ty, ..}) |
66 ty::TyRef(_, ty::TypeAndMut{ty, ..}) |
68 !type_is_sized(tcx, ty)
76 pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
77 use machine::llsize_of_alloc;
78 use type_of::sizing_type_of;
81 let simple = ty.is_scalar() ||
82 ty.is_unique() || ty.is_region_ptr() ||
84 if simple && !type_is_fat_ptr(tcx, ty) {
87 if !type_is_sized(tcx, ty) {
91 ty::TyStruct(..) | ty::TyEnum(..) | ty::TyTuple(..) | ty::TyArray(_, _) |
92 ty::TyClosure(..) => {
93 let llty = sizing_type_of(ccx, ty);
94 llsize_of_alloc(ccx, llty) <= llsize_of_alloc(ccx, ccx.int_type())
96 _ => type_is_zero_size(ccx, ty)
100 /// Returns Some([a, b]) if the type has a pair of fields with types a and b.
101 pub fn type_pair_fields<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>)
102 -> Option<[Ty<'tcx>; 2]> {
104 ty::TyEnum(adt, substs) | ty::TyStruct(adt, substs) => {
105 assert_eq!(adt.variants.len(), 1);
106 let fields = &adt.variants[0].fields;
107 if fields.len() != 2 {
110 Some([monomorphize::field_ty(ccx.tcx(), substs, &fields[0]),
111 monomorphize::field_ty(ccx.tcx(), substs, &fields[1])])
113 ty::TyClosure(_, ty::ClosureSubsts { upvar_tys: tys, .. }) |
114 ty::TyTuple(tys) => {
118 Some([tys[0], tys[1]])
124 /// Returns true if the type is represented as a pair of immediates.
125 pub fn type_is_imm_pair<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>)
127 match *ccx.layout_of(ty) {
128 Layout::FatPointer { .. } => true,
129 Layout::Univariant { ref variant, .. } => {
130 // There must be only 2 fields.
131 if variant.offset_after_field.len() != 2 {
135 match type_pair_fields(ccx, ty) {
137 type_is_immediate(ccx, a) && type_is_immediate(ccx, b)
146 /// Identify types which have size zero at runtime.
147 pub fn type_is_zero_size<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
148 use machine::llsize_of_alloc;
149 use type_of::sizing_type_of;
150 let llty = sizing_type_of(ccx, ty);
151 llsize_of_alloc(ccx, llty) == 0
154 /// Generates a unique symbol based off the name given. This is used to create
155 /// unique symbols for things like closures.
156 pub fn gensym_name(name: &str) -> ast::Name {
157 let num = token::gensym(name).0;
158 // use one colon which will get translated to a period by the mangler, and
159 // we're guaranteed that `num` is globally unique for this crate.
160 token::gensym(&format!("{}:{}", name, num))
164 * A note on nomenclature of linking: "extern", "foreign", and "upcall".
166 * An "extern" is an LLVM symbol we wind up emitting an undefined external
167 * reference to. This means "we don't have the thing in this compilation unit,
168 * please make sure you link it in at runtime". This could be a reference to
169 * C code found in a C library, or rust code found in a rust crate.
171 * Most "externs" are implicitly declared (automatically) as a result of a
172 * user declaring an extern _module_ dependency; this causes the rust driver
173 * to locate an extern crate, scan its compilation metadata, and emit extern
174 * declarations for any symbols used by the declaring crate.
176 * A "foreign" is an extern that references C (or other non-rust ABI) code.
177 * There is no metadata to scan for extern references so in these cases either
178 * a header-digester like bindgen, or manual function prototypes, have to
179 * serve as declarators. So these are usually given explicitly as prototype
180 * declarations, in rust code, with ABI attributes on them noting which ABI to
183 * An "upcall" is a foreign call generated by the compiler (not corresponding
184 * to any user-written call in the code) into the runtime library, to perform
185 * some helper task such as bringing a task to life, allocating memory, etc.
191 /// The concrete version of ty::FieldDef. The name is the field index if
192 /// the field is numeric.
193 pub struct Field<'tcx>(pub ast::Name, pub Ty<'tcx>);
195 /// The concrete version of ty::VariantDef
196 pub struct VariantInfo<'tcx> {
198 pub fields: Vec<Field<'tcx>>
201 impl<'a, 'tcx> VariantInfo<'tcx> {
202 pub fn from_ty(tcx: TyCtxt<'a, 'tcx, 'tcx>,
204 opt_def: Option<Def>)
208 ty::TyStruct(adt, substs) | ty::TyEnum(adt, substs) => {
209 let variant = match opt_def {
210 None => adt.struct_variant(),
211 Some(def) => adt.variant_of_def(def)
215 discr: Disr::from(variant.disr_val),
216 fields: variant.fields.iter().map(|f| {
217 Field(f.name, monomorphize::field_ty(tcx, substs, f))
222 ty::TyTuple(ref v) => {
225 fields: v.iter().enumerate().map(|(i, &t)| {
226 Field(token::intern(&i.to_string()), t)
232 bug!("cannot get field types from the type {:?}", ty);
238 pub struct BuilderRef_res {
242 impl Drop for BuilderRef_res {
245 llvm::LLVMDisposeBuilder(self.b);
250 pub fn BuilderRef_res(b: BuilderRef) -> BuilderRef_res {
256 pub fn validate_substs(substs: &Substs) {
257 assert!(!substs.needs_infer());
260 // Function context. Every LLVM function we create will have one of
262 pub struct FunctionContext<'a, 'tcx: 'a> {
263 // The MIR for this function. At present, this is optional because
264 // we only have MIR available for things that are local to the
266 pub mir: Option<CachedMir<'a, 'tcx>>,
268 // The ValueRef returned from a call to llvm::LLVMAddFunction; the
269 // address of the first instruction in the sequence of
270 // instructions for this function that will go in the .text
271 // section of the executable we're generating.
274 // always an empty parameter-environment NOTE: @jroesch another use of ParamEnv
275 pub param_env: ty::ParameterEnvironment<'tcx>,
277 // A pointer to where to store the return value. If the return type is
278 // immediate, this points to an alloca in the function. Otherwise, it's a
279 // pointer to the hidden first parameter of the function. After function
280 // construction, this should always be Some.
281 pub llretslotptr: Cell<Option<ValueRef>>,
283 // These pub elements: "hoisted basic blocks" containing
284 // administrative activities that have to happen in only one place in
285 // the function, due to LLVM's quirks.
286 // A marker for the place where we want to insert the function's static
287 // allocas, so that LLVM will coalesce them into a single alloca call.
288 pub alloca_insert_pt: Cell<Option<ValueRef>>,
290 // When working with landingpad-based exceptions this value is alloca'd and
291 // later loaded when using the resume instruction. This ends up being
292 // critical to chaining landing pads and resuing already-translated
295 // Note that for cleanuppad-based exceptions this is not used.
296 pub landingpad_alloca: Cell<Option<ValueRef>>,
298 // Describes the return/argument LLVM types and their ABI handling.
301 // If this function is being monomorphized, this contains the type
302 // substitutions used.
303 pub param_substs: &'tcx Substs<'tcx>,
305 // The source span and nesting context where this function comes from, for
306 // error reporting and symbol generation.
307 pub span: Option<Span>,
309 // The arena that blocks are allocated from.
310 pub block_arena: &'a TypedArena<BlockS<'a, 'tcx>>,
312 // The arena that landing pads are allocated from.
313 pub lpad_arena: TypedArena<LandingPad>,
315 // This function's enclosing crate context.
316 pub ccx: &'a CrateContext<'a, 'tcx>,
318 // Used and maintained by the debuginfo module.
319 pub debug_context: debuginfo::FunctionDebugContext,
322 pub scopes: RefCell<Vec<cleanup::CleanupScope<'tcx>>>,
325 impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
326 pub fn mir(&self) -> CachedMir<'a, 'tcx> {
327 self.mir.clone().expect("fcx.mir was empty")
330 pub fn cleanup(&self) {
332 llvm::LLVMInstructionEraseFromParent(self.alloca_insert_pt
338 pub fn new_block(&'a self,
342 let name = CString::new(name).unwrap();
343 let llbb = llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(),
346 BlockS::new(llbb, self)
350 pub fn monomorphize<T>(&self, value: &T) -> T
351 where T: TransNormalize<'tcx>
353 monomorphize::apply_param_substs(self.ccx.shared(),
358 /// This is the same as `common::type_needs_drop`, except that it
359 /// may use or update caches within this `FunctionContext`.
360 pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
361 self.ccx.tcx().type_needs_drop_given_env(ty, &self.param_env)
364 pub fn eh_personality(&self) -> ValueRef {
365 // The exception handling personality function.
367 // If our compilation unit has the `eh_personality` lang item somewhere
368 // within it, then we just need to translate that. Otherwise, we're
369 // building an rlib which will depend on some upstream implementation of
370 // this function, so we just codegen a generic reference to it. We don't
371 // specify any of the types for the function, we just make it a symbol
372 // that LLVM can later use.
374 // Note that MSVC is a little special here in that we don't use the
375 // `eh_personality` lang item at all. Currently LLVM has support for
376 // both Dwarf and SEH unwind mechanisms for MSVC targets and uses the
377 // *name of the personality function* to decide what kind of unwind side
378 // tables/landing pads to emit. It looks like Dwarf is used by default,
379 // injecting a dependency on the `_Unwind_Resume` symbol for resuming
380 // an "exception", but for MSVC we want to force SEH. This means that we
381 // can't actually have the personality function be our standard
382 // `rust_eh_personality` function, but rather we wired it up to the
383 // CRT's custom personality function, which forces LLVM to consider
384 // landing pads as "landing pads for SEH".
387 match tcx.lang_items.eh_personality() {
388 Some(def_id) if !base::wants_msvc_seh(ccx.sess()) => {
389 Callee::def(ccx, def_id, Substs::empty(tcx)).reify(ccx)
392 if let Some(llpersonality) = ccx.eh_personality().get() {
395 let name = if base::wants_msvc_seh(ccx.sess()) {
398 "rust_eh_personality"
400 let fty = Type::variadic_func(&[], &Type::i32(ccx));
401 let f = declare::declare_cfn(ccx, name, fty);
402 ccx.eh_personality().set(Some(f));
408 // Returns a ValueRef of the "eh_unwind_resume" lang item if one is defined,
409 // otherwise declares it as an external function.
410 pub fn eh_unwind_resume(&self) -> Callee<'tcx> {
414 assert!(ccx.sess().target.target.options.custom_unwind_resume);
415 if let Some(def_id) = tcx.lang_items.eh_unwind_resume() {
416 return Callee::def(ccx, def_id, Substs::empty(tcx));
419 let ty = tcx.mk_fn_ptr(tcx.mk_bare_fn(ty::BareFnTy {
420 unsafety: hir::Unsafety::Unsafe,
422 sig: ty::Binder(ty::FnSig {
423 inputs: vec![tcx.mk_mut_ptr(tcx.types.u8)],
424 output: tcx.types.never,
429 let unwresume = ccx.eh_unwind_resume();
430 if let Some(llfn) = unwresume.get() {
431 return Callee::ptr(llfn, ty);
433 let llfn = declare::declare_fn(ccx, "rust_eh_unwind_resume", ty);
434 attributes::unwind(llfn, true);
435 unwresume.set(Some(llfn));
436 Callee::ptr(llfn, ty)
440 // Basic block context. We create a block context for each basic block
441 // (single-entry, single-exit sequence of instructions) we generate from Rust
442 // code. Each basic block we generate is attached to a function, typically
443 // with many basic blocks per function. All the basic blocks attached to a
444 // function are organized as a directed graph.
445 pub struct BlockS<'blk, 'tcx: 'blk> {
446 // The BasicBlockRef returned from a call to
447 // llvm::LLVMAppendBasicBlock(llfn, name), which adds a basic
448 // block to the function pointed to by llfn. We insert
449 // instructions into that block by way of this block context.
450 // The block pointing to this one in the function's digraph.
451 pub llbb: BasicBlockRef,
452 pub terminated: Cell<bool>,
453 pub unreachable: Cell<bool>,
455 // If this block part of a landing pad, then this is `Some` indicating what
456 // kind of landing pad its in, otherwise this is none.
457 pub lpad: Cell<Option<&'blk LandingPad>>,
459 // The function context for the function to which this block is
461 pub fcx: &'blk FunctionContext<'blk, 'tcx>,
464 pub type Block<'blk, 'tcx> = &'blk BlockS<'blk, 'tcx>;
466 impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
467 pub fn new(llbb: BasicBlockRef,
468 fcx: &'blk FunctionContext<'blk, 'tcx>)
469 -> Block<'blk, 'tcx> {
470 fcx.block_arena.alloc(BlockS {
472 terminated: Cell::new(false),
473 unreachable: Cell::new(false),
474 lpad: Cell::new(None),
479 pub fn ccx(&self) -> &'blk CrateContext<'blk, 'tcx> {
482 pub fn fcx(&self) -> &'blk FunctionContext<'blk, 'tcx> {
485 pub fn tcx(&self) -> TyCtxt<'blk, 'tcx, 'tcx> {
488 pub fn sess(&self) -> &'blk Session { self.fcx.ccx.sess() }
490 pub fn lpad(&self) -> Option<&'blk LandingPad> {
494 pub fn set_lpad_ref(&self, lpad: Option<&'blk LandingPad>) {
495 // FIXME: use an IVar?
499 pub fn set_lpad(&self, lpad: Option<LandingPad>) {
500 self.set_lpad_ref(lpad.map(|p| &*self.fcx().lpad_arena.alloc(p)))
503 pub fn mir(&self) -> CachedMir<'blk, 'tcx> {
507 pub fn name(&self, name: ast::Name) -> String {
511 pub fn node_id_to_string(&self, id: ast::NodeId) -> String {
512 self.tcx().map.node_to_string(id).to_string()
515 pub fn to_str(&self) -> String {
516 format!("[block {:p}]", self)
519 pub fn monomorphize<T>(&self, value: &T) -> T
520 where T: TransNormalize<'tcx>
522 monomorphize::apply_param_substs(self.fcx.ccx.shared(),
523 self.fcx.param_substs,
527 pub fn build(&'blk self) -> BlockAndBuilder<'blk, 'tcx> {
528 BlockAndBuilder::new(self, OwnedBuilder::new_with_ccx(self.ccx()))
532 pub struct OwnedBuilder<'blk, 'tcx: 'blk> {
533 builder: Builder<'blk, 'tcx>
536 impl<'blk, 'tcx> OwnedBuilder<'blk, 'tcx> {
537 pub fn new_with_ccx(ccx: &'blk CrateContext<'blk, 'tcx>) -> Self {
538 // Create a fresh builder from the crate context.
539 let llbuilder = unsafe {
540 llvm::LLVMCreateBuilderInContext(ccx.llcx())
544 llbuilder: llbuilder,
551 impl<'blk, 'tcx> Drop for OwnedBuilder<'blk, 'tcx> {
554 llvm::LLVMDisposeBuilder(self.builder.llbuilder);
559 pub struct BlockAndBuilder<'blk, 'tcx: 'blk> {
560 bcx: Block<'blk, 'tcx>,
561 owned_builder: OwnedBuilder<'blk, 'tcx>,
564 impl<'blk, 'tcx> BlockAndBuilder<'blk, 'tcx> {
565 pub fn new(bcx: Block<'blk, 'tcx>, owned_builder: OwnedBuilder<'blk, 'tcx>) -> Self {
566 // Set the builder's position to this block's end.
567 owned_builder.builder.position_at_end(bcx.llbb);
570 owned_builder: owned_builder,
574 pub fn with_block<F, R>(&self, f: F) -> R
575 where F: FnOnce(Block<'blk, 'tcx>) -> R
577 let result = f(self.bcx);
578 self.position_at_end(self.bcx.llbb);
582 pub fn map_block<F>(self, f: F) -> Self
583 where F: FnOnce(Block<'blk, 'tcx>) -> Block<'blk, 'tcx>
585 let BlockAndBuilder { bcx, owned_builder } = self;
587 BlockAndBuilder::new(bcx, owned_builder)
590 pub fn at_start<F, R>(&self, f: F) -> R
591 where F: FnOnce(&BlockAndBuilder<'blk, 'tcx>) -> R
593 self.position_at_start(self.bcx.llbb);
595 self.position_at_end(self.bcx.llbb);
599 // Methods delegated to bcx
601 pub fn is_unreachable(&self) -> bool {
602 self.bcx.unreachable.get()
605 pub fn ccx(&self) -> &'blk CrateContext<'blk, 'tcx> {
608 pub fn fcx(&self) -> &'blk FunctionContext<'blk, 'tcx> {
611 pub fn tcx(&self) -> TyCtxt<'blk, 'tcx, 'tcx> {
614 pub fn sess(&self) -> &'blk Session {
618 pub fn llbb(&self) -> BasicBlockRef {
622 pub fn mir(&self) -> CachedMir<'blk, 'tcx> {
626 pub fn monomorphize<T>(&self, value: &T) -> T
627 where T: TransNormalize<'tcx>
629 self.bcx.monomorphize(value)
632 pub fn set_lpad(&self, lpad: Option<LandingPad>) {
633 self.bcx.set_lpad(lpad)
636 pub fn set_lpad_ref(&self, lpad: Option<&'blk LandingPad>) {
637 // FIXME: use an IVar?
638 self.bcx.set_lpad_ref(lpad);
641 pub fn lpad(&self) -> Option<&'blk LandingPad> {
646 impl<'blk, 'tcx> Deref for BlockAndBuilder<'blk, 'tcx> {
647 type Target = Builder<'blk, 'tcx>;
648 fn deref(&self) -> &Self::Target {
649 &self.owned_builder.builder
653 /// A structure representing an active landing pad for the duration of a basic
656 /// Each `Block` may contain an instance of this, indicating whether the block
657 /// is part of a landing pad or not. This is used to make decision about whether
658 /// to emit `invoke` instructions (e.g. in a landing pad we don't continue to
659 /// use `invoke`) and also about various function call metadata.
661 /// For GNU exceptions (`landingpad` + `resume` instructions) this structure is
662 /// just a bunch of `None` instances (not too interesting), but for MSVC
663 /// exceptions (`cleanuppad` + `cleanupret` instructions) this contains data.
664 /// When inside of a landing pad, each function call in LLVM IR needs to be
665 /// annotated with which landing pad it's a part of. This is accomplished via
666 /// the `OperandBundleDef` value created for MSVC landing pads.
667 pub struct LandingPad {
668 cleanuppad: Option<ValueRef>,
669 operand: Option<OperandBundleDef>,
673 pub fn gnu() -> LandingPad {
674 LandingPad { cleanuppad: None, operand: None }
677 pub fn msvc(cleanuppad: ValueRef) -> LandingPad {
679 cleanuppad: Some(cleanuppad),
680 operand: Some(OperandBundleDef::new("funclet", &[cleanuppad])),
684 pub fn bundle(&self) -> Option<&OperandBundleDef> {
685 self.operand.as_ref()
688 pub fn cleanuppad(&self) -> Option<ValueRef> {
693 impl Clone for LandingPad {
694 fn clone(&self) -> LandingPad {
696 cleanuppad: self.cleanuppad,
697 operand: self.cleanuppad.map(|p| {
698 OperandBundleDef::new("funclet", &[p])
704 pub struct Result<'blk, 'tcx: 'blk> {
705 pub bcx: Block<'blk, 'tcx>,
709 impl<'b, 'tcx> Result<'b, 'tcx> {
710 pub fn new(bcx: Block<'b, 'tcx>, val: ValueRef) -> Result<'b, 'tcx> {
718 pub fn val_ty(v: ValueRef) -> Type {
720 Type::from_ref(llvm::LLVMTypeOf(v))
724 // LLVM constant constructors.
725 pub fn C_null(t: Type) -> ValueRef {
727 llvm::LLVMConstNull(t.to_ref())
731 pub fn C_undef(t: Type) -> ValueRef {
733 llvm::LLVMGetUndef(t.to_ref())
737 pub fn C_integral(t: Type, u: u64, sign_extend: bool) -> ValueRef {
739 llvm::LLVMConstInt(t.to_ref(), u, sign_extend as Bool)
743 pub fn C_floating_f64(f: f64, t: Type) -> ValueRef {
745 llvm::LLVMConstReal(t.to_ref(), f)
749 pub fn C_nil(ccx: &CrateContext) -> ValueRef {
750 C_struct(ccx, &[], false)
753 pub fn C_bool(ccx: &CrateContext, val: bool) -> ValueRef {
754 C_integral(Type::i1(ccx), val as u64, false)
757 pub fn C_i32(ccx: &CrateContext, i: i32) -> ValueRef {
758 C_integral(Type::i32(ccx), i as u64, true)
761 pub fn C_u32(ccx: &CrateContext, i: u32) -> ValueRef {
762 C_integral(Type::i32(ccx), i as u64, false)
765 pub fn C_u64(ccx: &CrateContext, i: u64) -> ValueRef {
766 C_integral(Type::i64(ccx), i, false)
769 pub fn C_uint<I: AsU64>(ccx: &CrateContext, i: I) -> ValueRef {
772 let bit_size = machine::llbitsize_of_real(ccx, ccx.int_type());
775 // make sure it doesn't overflow
776 assert!(v < (1<<bit_size));
779 C_integral(ccx.int_type(), v, false)
782 pub trait AsI64 { fn as_i64(self) -> i64; }
783 pub trait AsU64 { fn as_u64(self) -> u64; }
785 // FIXME: remove the intptr conversions, because they
786 // are host-architecture-dependent
787 impl AsI64 for i64 { fn as_i64(self) -> i64 { self as i64 }}
788 impl AsI64 for i32 { fn as_i64(self) -> i64 { self as i64 }}
789 impl AsI64 for isize { fn as_i64(self) -> i64 { self as i64 }}
791 impl AsU64 for u64 { fn as_u64(self) -> u64 { self as u64 }}
792 impl AsU64 for u32 { fn as_u64(self) -> u64 { self as u64 }}
793 impl AsU64 for usize { fn as_u64(self) -> u64 { self as u64 }}
795 pub fn C_u8(ccx: &CrateContext, i: u8) -> ValueRef {
796 C_integral(Type::i8(ccx), i as u64, false)
800 // This is a 'c-like' raw string, which differs from
801 // our boxed-and-length-annotated strings.
802 pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> ValueRef {
804 if let Some(&llval) = cx.const_cstr_cache().borrow().get(&s) {
808 let sc = llvm::LLVMConstStringInContext(cx.llcx(),
809 s.as_ptr() as *const c_char,
811 !null_terminated as Bool);
813 let gsym = token::gensym("str");
814 let sym = format!("str{}", gsym.0);
815 let g = declare::define_global(cx, &sym[..], val_ty(sc)).unwrap_or_else(||{
816 bug!("symbol `{}` is already defined", sym);
818 llvm::LLVMSetInitializer(g, sc);
819 llvm::LLVMSetGlobalConstant(g, True);
820 llvm::LLVMSetLinkage(g, llvm::InternalLinkage);
822 cx.const_cstr_cache().borrow_mut().insert(s, g);
827 // NB: Do not use `do_spill_noroot` to make this into a constant string, or
828 // you will be kicked off fast isel. See issue #4352 for an example of this.
829 pub fn C_str_slice(cx: &CrateContext, s: InternedString) -> ValueRef {
831 let cs = consts::ptrcast(C_cstr(cx, s, false), Type::i8p(cx));
832 C_named_struct(cx.tn().find_type("str_slice").unwrap(), &[cs, C_uint(cx, len)])
835 pub fn C_struct(cx: &CrateContext, elts: &[ValueRef], packed: bool) -> ValueRef {
836 C_struct_in_context(cx.llcx(), elts, packed)
839 pub fn C_struct_in_context(llcx: ContextRef, elts: &[ValueRef], packed: bool) -> ValueRef {
841 llvm::LLVMConstStructInContext(llcx,
842 elts.as_ptr(), elts.len() as c_uint,
847 pub fn C_named_struct(t: Type, elts: &[ValueRef]) -> ValueRef {
849 llvm::LLVMConstNamedStruct(t.to_ref(), elts.as_ptr(), elts.len() as c_uint)
853 pub fn C_array(ty: Type, elts: &[ValueRef]) -> ValueRef {
855 return llvm::LLVMConstArray(ty.to_ref(), elts.as_ptr(), elts.len() as c_uint);
859 pub fn C_vector(elts: &[ValueRef]) -> ValueRef {
861 return llvm::LLVMConstVector(elts.as_ptr(), elts.len() as c_uint);
865 pub fn C_bytes(cx: &CrateContext, bytes: &[u8]) -> ValueRef {
866 C_bytes_in_context(cx.llcx(), bytes)
869 pub fn C_bytes_in_context(llcx: ContextRef, bytes: &[u8]) -> ValueRef {
871 let ptr = bytes.as_ptr() as *const c_char;
872 return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True);
876 pub fn const_get_elt(v: ValueRef, us: &[c_uint])
879 let r = llvm::LLVMConstExtractValue(v, us.as_ptr(), us.len() as c_uint);
881 debug!("const_get_elt(v={:?}, us={:?}, r={:?})",
882 Value(v), us, Value(r));
888 pub fn const_to_int(v: ValueRef) -> i64 {
890 llvm::LLVMConstIntGetSExtValue(v)
894 pub fn const_to_uint(v: ValueRef) -> u64 {
896 llvm::LLVMConstIntGetZExtValue(v)
900 fn is_const_integral(v: ValueRef) -> bool {
902 !llvm::LLVMIsAConstantInt(v).is_null()
906 pub fn const_to_opt_int(v: ValueRef) -> Option<i64> {
908 if is_const_integral(v) {
909 Some(llvm::LLVMConstIntGetSExtValue(v))
916 pub fn const_to_opt_uint(v: ValueRef) -> Option<u64> {
918 if is_const_integral(v) {
919 Some(llvm::LLVMConstIntGetZExtValue(v))
926 pub fn is_undef(val: ValueRef) -> bool {
928 llvm::LLVMIsUndef(val) != False
932 #[allow(dead_code)] // potentially useful
933 pub fn is_null(val: ValueRef) -> bool {
935 llvm::LLVMIsNull(val) != False
939 /// Attempts to resolve an obligation. The result is a shallow vtable resolution -- meaning that we
940 /// do not (necessarily) resolve all nested obligations on the impl. Note that type check should
941 /// guarantee to us that all nested obligations *could be* resolved if we wanted to.
942 pub fn fulfill_obligation<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
944 trait_ref: ty::PolyTraitRef<'tcx>)
945 -> traits::Vtable<'tcx, ()>
949 // Remove any references to regions; this helps improve caching.
950 let trait_ref = tcx.erase_regions(&trait_ref);
952 scx.trait_cache().memoize(trait_ref, || {
953 debug!("trans::fulfill_obligation(trait_ref={:?}, def_id={:?})",
954 trait_ref, trait_ref.def_id());
956 // Do the initial selection for the obligation. This yields the
957 // shallow result we are looking for -- that is, what specific impl.
958 tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| {
959 let mut selcx = SelectionContext::new(&infcx);
961 let obligation_cause = traits::ObligationCause::misc(span,
963 let obligation = traits::Obligation::new(obligation_cause,
964 trait_ref.to_poly_trait_predicate());
966 let selection = match selcx.select(&obligation) {
967 Ok(Some(selection)) => selection,
969 // Ambiguity can happen when monomorphizing during trans
970 // expands to some humongo type that never occurred
971 // statically -- this humongo type can then overflow,
972 // leading to an ambiguous result. So report this as an
973 // overflow bug, since I believe this is the only case
974 // where ambiguity can result.
975 debug!("Encountered ambiguity selecting `{:?}` during trans, \
976 presuming due to overflow",
978 tcx.sess.span_fatal(span,
979 "reached the recursion limit during monomorphization \
980 (selection ambiguity)");
983 span_bug!(span, "Encountered error `{:?}` selecting `{:?}` during trans",
988 debug!("fulfill_obligation: selection={:?}", selection);
990 // Currently, we use a fulfillment context to completely resolve
991 // all nested obligations. This is because they can inform the
992 // inference of the impl's type parameters.
993 let mut fulfill_cx = traits::FulfillmentContext::new();
994 let vtable = selection.map(|predicate| {
995 debug!("fulfill_obligation: register_predicate_obligation {:?}", predicate);
996 fulfill_cx.register_predicate_obligation(&infcx, predicate);
998 let vtable = infcx.drain_fulfillment_cx_or_panic(span, &mut fulfill_cx, &vtable);
1000 info!("Cache miss: {:?} => {:?}", trait_ref, vtable);
1006 /// Normalizes the predicates and checks whether they hold. If this
1007 /// returns false, then either normalize encountered an error or one
1008 /// of the predicates did not hold. Used when creating vtables to
1009 /// check for unsatisfiable methods.
1010 pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1011 predicates: Vec<ty::Predicate<'tcx>>)
1014 debug!("normalize_and_test_predicates(predicates={:?})",
1017 tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| {
1018 let mut selcx = SelectionContext::new(&infcx);
1019 let mut fulfill_cx = traits::FulfillmentContext::new();
1020 let cause = traits::ObligationCause::dummy();
1021 let traits::Normalized { value: predicates, obligations } =
1022 traits::normalize(&mut selcx, cause.clone(), &predicates);
1023 for obligation in obligations {
1024 fulfill_cx.register_predicate_obligation(&infcx, obligation);
1026 for predicate in predicates {
1027 let obligation = traits::Obligation::new(cause.clone(), predicate);
1028 fulfill_cx.register_predicate_obligation(&infcx, obligation);
1031 fulfill_cx.select_all_or_error(&infcx).is_ok()
1035 pub fn langcall(tcx: TyCtxt,
1040 match tcx.lang_items.require(li) {
1043 let msg = format!("{} {}", msg, s);
1045 Some(span) => tcx.sess.span_fatal(span, &msg[..]),
1046 None => tcx.sess.fatal(&msg[..]),
1052 // To avoid UB from LLVM, these two functions mask RHS with an
1053 // appropriate mask unconditionally (i.e. the fallback behavior for
1054 // all shifts). For 32- and 64-bit types, this matches the semantics
1055 // of Java. (See related discussion on #1877 and #10183.)
1057 pub fn build_unchecked_lshift<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
1060 binop_debug_loc: DebugLoc) -> ValueRef {
1061 let rhs = base::cast_shift_expr_rhs(bcx, hir::BinOp_::BiShl, lhs, rhs);
1062 // #1877, #10183: Ensure that input is always valid
1063 let rhs = shift_mask_rhs(bcx, rhs, binop_debug_loc);
1064 build::Shl(bcx, lhs, rhs, binop_debug_loc)
1067 pub fn build_unchecked_rshift<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
1071 binop_debug_loc: DebugLoc) -> ValueRef {
1072 let rhs = base::cast_shift_expr_rhs(bcx, hir::BinOp_::BiShr, lhs, rhs);
1073 // #1877, #10183: Ensure that input is always valid
1074 let rhs = shift_mask_rhs(bcx, rhs, binop_debug_loc);
1075 let is_signed = lhs_t.is_signed();
1077 build::AShr(bcx, lhs, rhs, binop_debug_loc)
1079 build::LShr(bcx, lhs, rhs, binop_debug_loc)
1083 fn shift_mask_rhs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
1085 debug_loc: DebugLoc) -> ValueRef {
1086 let rhs_llty = val_ty(rhs);
1087 build::And(bcx, rhs, shift_mask_val(bcx, rhs_llty, rhs_llty, false), debug_loc)
1090 pub fn shift_mask_val<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
1093 invert: bool) -> ValueRef {
1094 let kind = llty.kind();
1096 TypeKind::Integer => {
1097 // i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
1098 let val = llty.int_width() - 1;
1100 C_integral(mask_llty, !val, true)
1102 C_integral(mask_llty, val, false)
1105 TypeKind::Vector => {
1106 let mask = shift_mask_val(bcx, llty.element_type(), mask_llty.element_type(), invert);
1107 build::VectorSplat(bcx, mask_llty.vector_length(), mask)
1109 _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),