diff --git a/src/Cargo.lock b/src/Cargo.lock index 89daa8e09c7d1..be32872dad80a 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2222,11 +2222,8 @@ dependencies = [ name = "rustc_llvm" version = "0.0.0" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "build_helper 0.1.0", "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_cratesio_shim 0.0.0", ] [[package]] diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index f1a6e9913d6bd..44982eee86b3c 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::{self, ValueRef, AttributePlace}; +use llvm::{self, AttributePlace}; use base; use builder::{Builder, MemFlags}; use common::{ty_fn_sig, C_usize}; @@ -17,6 +17,7 @@ use mir::place::PlaceRef; use mir::operand::OperandValue; use type_::Type; use type_of::{LayoutLlvmExt, PointerKind}; +use value::Value; use rustc_target::abi::{LayoutOf, Size, TyLayout}; use rustc::ty::{self, Ty}; @@ -46,12 +47,12 @@ impl ArgAttributeExt for ArgAttribute { } pub trait ArgAttributesExt { - fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef); - fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef); + fn apply_llfn(&self, idx: AttributePlace, llfn: &Value); + fn apply_callsite(&self, idx: AttributePlace, callsite: &Value); } impl ArgAttributesExt for ArgAttributes { - fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) { + fn apply_llfn(&self, idx: AttributePlace, llfn: &Value) { let mut regular = self.regular; unsafe { let deref = self.pointee_size.bytes(); @@ -76,7 +77,7 @@ impl ArgAttributesExt for ArgAttributes { } } - fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) { + fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) { let mut regular = self.regular; unsafe { let deref = self.pointee_size.bytes(); @@ -103,11 +104,11 @@ impl ArgAttributesExt for ArgAttributes { } pub trait LlvmType { - fn llvm_type(&self, cx: &CodegenCx) -> Type; + fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type; } impl LlvmType for Reg { - fn llvm_type(&self, cx: &CodegenCx) -> Type { + fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { match self.kind { RegKind::Integer => Type::ix(cx, self.size.bits()), RegKind::Float => { @@ -118,14 +119,14 @@ impl LlvmType for Reg { } } RegKind::Vector => { - Type::vector(&Type::i8(cx), self.size.bytes()) + Type::vector(Type::i8(cx), self.size.bytes()) } } } } impl LlvmType for CastTarget { - fn llvm_type(&self, cx: &CodegenCx) -> Type { + fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { let rest_ll_unit = self.rest.unit.llvm_type(cx); let (rest_count, rem_bytes) = if self.rest.unit.size.bytes() == 0 { (0, 0) @@ -142,7 +143,7 @@ impl LlvmType for CastTarget { // Simplify to array when all chunks are the same size and type if rem_bytes == 0 { - return Type::array(&rest_ll_unit, rest_count); + return Type::array(rest_ll_unit, rest_count); } } @@ -164,16 +165,16 @@ impl LlvmType for CastTarget { } } -pub trait ArgTypeExt<'a, 'tcx> { - fn memory_ty(&self, cx: &CodegenCx<'a, 'tcx>) -> Type; - fn store(&self, bx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>); - fn store_fn_arg(&self, bx: &Builder<'a, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx>); +pub trait ArgTypeExt<'ll, 'tcx> { + fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; + fn store(&self, bx: &Builder<'_, 'll, 'tcx>, val: &'ll Value, dst: PlaceRef<'ll, 'tcx>); + fn store_fn_arg(&self, bx: &Builder<'_, 'll, 'tcx>, idx: &mut usize, dst: PlaceRef<'ll, 'tcx>); } -impl<'a, 'tcx> ArgTypeExt<'a, 'tcx> for ArgType<'tcx, Ty<'tcx>> { +impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> { /// Get the LLVM type for a place of the original Rust type of /// this argument/return, i.e. the result of `type_of::type_of`. - fn memory_ty(&self, cx: &CodegenCx<'a, 'tcx>) -> Type { + fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type { self.layout.llvm_type(cx) } @@ -181,7 +182,7 @@ impl<'a, 'tcx> ArgTypeExt<'a, 'tcx> for ArgType<'tcx, Ty<'tcx>> { /// place for the original Rust type of this argument/return. /// Can be used for both storing formal arguments into Rust variables /// or results of call/invoke instructions into their destinations. - fn store(&self, bx: &Builder<'a, 'tcx>, val: ValueRef, dst: PlaceRef<'tcx>) { + fn store(&self, bx: &Builder<'_, 'll, 'tcx>, val: &'ll Value, dst: PlaceRef<'ll, 'tcx>) { if self.is_ignore() { return; } @@ -234,7 +235,7 @@ impl<'a, 'tcx> ArgTypeExt<'a, 'tcx> for ArgType<'tcx, Ty<'tcx>> { } } - fn store_fn_arg(&self, bx: &Builder<'a, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx>) { + fn store_fn_arg(&self, bx: &Builder<'a, 'll, 'tcx>, idx: &mut usize, dst: PlaceRef<'ll, 'tcx>) { let mut next = || { let val = llvm::get_param(bx.llfn(), *idx as c_uint); *idx += 1; @@ -252,32 +253,32 @@ impl<'a, 'tcx> ArgTypeExt<'a, 'tcx> for ArgType<'tcx, Ty<'tcx>> { } } -pub trait FnTypeExt<'a, 'tcx> { - fn of_instance(cx: &CodegenCx<'a, 'tcx>, instance: &ty::Instance<'tcx>) +pub trait FnTypeExt<'tcx> { + fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>) -> Self; - fn new(cx: &CodegenCx<'a, 'tcx>, + fn new(cx: &CodegenCx<'ll, 'tcx>, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; - fn new_vtable(cx: &CodegenCx<'a, 'tcx>, + fn new_vtable(cx: &CodegenCx<'ll, 'tcx>, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self; fn new_internal( - cx: &CodegenCx<'a, 'tcx>, + cx: &CodegenCx<'ll, 'tcx>, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>], mk_arg_type: impl Fn(Ty<'tcx>, Option) -> ArgType<'tcx, Ty<'tcx>>, ) -> Self; fn adjust_for_abi(&mut self, - cx: &CodegenCx<'a, 'tcx>, + cx: &CodegenCx<'ll, 'tcx>, abi: Abi); - fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type; + fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type; fn llvm_cconv(&self) -> llvm::CallConv; - fn apply_attrs_llfn(&self, llfn: ValueRef); - fn apply_attrs_callsite(&self, bx: &Builder<'a, 'tcx>, callsite: ValueRef); + fn apply_attrs_llfn(&self, llfn: &'ll Value); + fn apply_attrs_callsite(&self, bx: &Builder<'a, 'll, 'tcx>, callsite: &'ll Value); } -impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { - fn of_instance(cx: &CodegenCx<'a, 'tcx>, instance: &ty::Instance<'tcx>) +impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> { + fn of_instance(cx: &CodegenCx<'ll, 'tcx>, instance: &ty::Instance<'tcx>) -> Self { let fn_ty = instance.ty(cx.tcx); let sig = ty_fn_sig(cx, fn_ty); @@ -285,7 +286,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { FnType::new(cx, sig, &[]) } - fn new(cx: &CodegenCx<'a, 'tcx>, + fn new(cx: &CodegenCx<'ll, 'tcx>, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { FnType::new_internal(cx, sig, extra_args, |ty, _| { @@ -293,7 +294,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { }) } - fn new_vtable(cx: &CodegenCx<'a, 'tcx>, + fn new_vtable(cx: &CodegenCx<'ll, 'tcx>, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>]) -> Self { FnType::new_internal(cx, sig, extra_args, |ty, arg_idx| { @@ -316,7 +317,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { } fn new_internal( - cx: &CodegenCx<'a, 'tcx>, + cx: &CodegenCx<'ll, 'tcx>, sig: ty::FnSig<'tcx>, extra_args: &[Ty<'tcx>], mk_arg_type: impl Fn(Ty<'tcx>, Option) -> ArgType<'tcx, Ty<'tcx>>, @@ -497,7 +498,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { } fn adjust_for_abi(&mut self, - cx: &CodegenCx<'a, 'tcx>, + cx: &CodegenCx<'ll, 'tcx>, abi: Abi) { if abi == Abi::Unadjusted { return } @@ -564,7 +565,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { } } - fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type { + fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type { let args_capacity: usize = self.args.iter().map(|arg| if arg.pad.is_some() { 1 } else { 0 } + if let PassMode::Pair(_, _) = arg.mode { 2 } else { 1 } @@ -606,9 +607,9 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { } if self.variadic { - Type::variadic_func(&llargument_tys, &llreturn_ty) + Type::variadic_func(&llargument_tys, llreturn_ty) } else { - Type::func(&llargument_tys, &llreturn_ty) + Type::func(&llargument_tys, llreturn_ty) } } @@ -629,7 +630,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { } } - fn apply_attrs_llfn(&self, llfn: ValueRef) { + fn apply_attrs_llfn(&self, llfn: &'ll Value) { let mut i = 0; let mut apply = |attrs: &ArgAttributes| { attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn); @@ -659,7 +660,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { } } - fn apply_attrs_callsite(&self, bx: &Builder<'a, 'tcx>, callsite: ValueRef) { + fn apply_attrs_callsite(&self, bx: &Builder<'a, 'll, 'tcx>, callsite: &'ll Value) { let mut i = 0; let mut apply = |attrs: &ArgAttributes| { attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite); diff --git a/src/librustc_codegen_llvm/allocator.rs b/src/librustc_codegen_llvm/allocator.rs index eeb02e948f1cc..2d401da958b13 100644 --- a/src/librustc_codegen_llvm/allocator.rs +++ b/src/librustc_codegen_llvm/allocator.rs @@ -9,7 +9,6 @@ // except according to those terms. use std::ffi::CString; -use std::ptr; use attributes; use libc::c_uint; @@ -21,8 +20,8 @@ use ModuleLlvm; use llvm::{self, False, True}; pub(crate) unsafe fn codegen(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) { - let llcx = mods.llcx; - let llmod = mods.llmod; + let llcx = &*mods.llcx; + let llmod = mods.llmod(); let usize = match &tcx.sess.target.target.target_pointer_width[..] { "16" => llvm::LLVMInt16TypeInContext(llcx), "32" => llvm::LLVMInt32TypeInContext(llcx), @@ -90,7 +89,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind callee, args.as_ptr(), args.len() as c_uint, - ptr::null_mut(), + None, "\0".as_ptr() as *const _); llvm::LLVMSetTailCall(ret, True); if output.is_some() { diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs index 82f068106ff71..5d27f8eab3ece 100644 --- a/src/librustc_codegen_llvm/asm.rs +++ b/src/librustc_codegen_llvm/asm.rs @@ -8,11 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::{self, ValueRef}; +use llvm; use common::*; use type_::Type; use type_of::LayoutLlvmExt; use builder::Builder; +use value::Value; use rustc::hir; @@ -24,11 +25,11 @@ use syntax::ast::AsmDialect; use libc::{c_uint, c_char}; // Take an inline assembly expression and splat it out via LLVM -pub fn codegen_inline_asm<'a, 'tcx>( - bx: &Builder<'a, 'tcx>, +pub fn codegen_inline_asm( + bx: &Builder<'a, 'll, 'tcx>, ia: &hir::InlineAsm, - outputs: Vec>, - mut inputs: Vec + outputs: Vec>, + mut inputs: Vec<&'ll Value> ) { let mut ext_constraints = vec![]; let mut output_types = vec![]; @@ -111,7 +112,7 @@ pub fn codegen_inline_asm<'a, 'tcx>( let kind = llvm::LLVMGetMDKindIDInContext(bx.cx.llcx, key.as_ptr() as *const c_char, key.len() as c_uint); - let val: llvm::ValueRef = C_i32(bx.cx, ia.ctxt.outer().as_u32() as i32); + let val: &'ll Value = C_i32(bx.cx, ia.ctxt.outer().as_u32() as i32); llvm::LLVMSetMetadata(r, kind, llvm::LLVMMDNodeInContext(bx.cx.llcx, &val, 1)); diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 3b5f927d52f00..c52f894410899 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -22,15 +22,17 @@ use rustc_data_structures::fx::FxHashMap; use rustc_target::spec::PanicStrategy; use attributes; -use llvm::{self, Attribute, ValueRef}; +use llvm::{self, Attribute}; use llvm::AttributePlace::Function; use llvm_util; pub use syntax::attr::{self, InlineAttr}; + use context::CodegenCx; +use value::Value; /// Mark LLVM function to use provided inline heuristic. #[inline] -pub fn inline(val: ValueRef, inline: InlineAttr) { +pub fn inline(val: &'ll Value, inline: InlineAttr) { use self::InlineAttr::*; match inline { Hint => Attribute::InlineHint.apply_llfn(Function, val), @@ -46,30 +48,30 @@ pub fn inline(val: ValueRef, inline: InlineAttr) { /// Tell LLVM to emit or not emit the information necessary to unwind the stack for the function. #[inline] -pub fn emit_uwtable(val: ValueRef, emit: bool) { +pub fn emit_uwtable(val: &'ll Value, emit: bool) { Attribute::UWTable.toggle_llfn(Function, val, emit); } /// Tell LLVM whether the function can or cannot unwind. #[inline] -pub fn unwind(val: ValueRef, can_unwind: bool) { +pub fn unwind(val: &'ll Value, can_unwind: bool) { Attribute::NoUnwind.toggle_llfn(Function, val, !can_unwind); } /// Tell LLVM whether it should optimize function for size. #[inline] #[allow(dead_code)] // possibly useful function -pub fn set_optimize_for_size(val: ValueRef, optimize: bool) { +pub fn set_optimize_for_size(val: &'ll Value, optimize: bool) { Attribute::OptimizeForSize.toggle_llfn(Function, val, optimize); } /// Tell LLVM if this function should be 'naked', i.e. skip the epilogue and prologue. #[inline] -pub fn naked(val: ValueRef, is_naked: bool) { +pub fn naked(val: &'ll Value, is_naked: bool) { Attribute::Naked.toggle_llfn(Function, val, is_naked); } -pub fn set_frame_pointer_elimination(cx: &CodegenCx, llfn: ValueRef) { +pub fn set_frame_pointer_elimination(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { if cx.sess().must_not_eliminate_frame_pointers() { llvm::AddFunctionAttrStringValue( llfn, llvm::AttributePlace::Function, @@ -77,7 +79,7 @@ pub fn set_frame_pointer_elimination(cx: &CodegenCx, llfn: ValueRef) { } } -pub fn set_probestack(cx: &CodegenCx, llfn: ValueRef) { +pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { // Only use stack probes if the target specification indicates that we // should be using stack probes if !cx.sess().target.target.options.stack_probes { @@ -123,7 +125,7 @@ pub fn llvm_target_features(sess: &Session) -> impl Iterator { /// Composite function which sets LLVM attributes for function depending on its AST (#[attribute]) /// attributes. -pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) { +pub fn from_fn_attrs(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value, id: DefId) { let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(id); inline(llfn, codegen_fn_attrs.inline); diff --git a/src/librustc_codegen_llvm/back/archive.rs b/src/librustc_codegen_llvm/back/archive.rs index b99835cb5c649..af9efc6d7c417 100644 --- a/src/librustc_codegen_llvm/back/archive.rs +++ b/src/librustc_codegen_llvm/back/archive.rs @@ -226,10 +226,13 @@ impl<'a> ArchiveBuilder<'a> { } fn build_with_llvm(&mut self, kind: ArchiveKind) -> io::Result<()> { - let mut archives = Vec::new(); + let removals = mem::replace(&mut self.removals, Vec::new()); + let mut additions = mem::replace(&mut self.additions, Vec::new()); let mut strings = Vec::new(); let mut members = Vec::new(); - let removals = mem::replace(&mut self.removals, Vec::new()); + + let dst = CString::new(self.config.dst.to_str().unwrap())?; + let should_update_symbols = self.should_update_symbols; unsafe { if let Some(archive) = self.src_archive() { @@ -246,22 +249,22 @@ impl<'a> ArchiveBuilder<'a> { let name = CString::new(child_name)?; members.push(llvm::LLVMRustArchiveMemberNew(ptr::null(), name.as_ptr(), - child.raw())); + Some(child.raw))); strings.push(name); } } - for addition in mem::replace(&mut self.additions, Vec::new()) { + for addition in &mut additions { match addition { Addition::File { path, name_in_archive } => { let path = CString::new(path.to_str().unwrap())?; - let name = CString::new(name_in_archive)?; + let name = CString::new(name_in_archive.clone())?; members.push(llvm::LLVMRustArchiveMemberNew(path.as_ptr(), name.as_ptr(), - ptr::null_mut())); + None)); strings.push(path); strings.push(name); } - Addition::Archive { archive, mut skip } => { + Addition::Archive { archive, skip } => { for child in archive.iter() { let child = child.map_err(string_to_io_error)?; if !is_relevant_child(&child) { @@ -284,21 +287,18 @@ impl<'a> ArchiveBuilder<'a> { let name = CString::new(child_name)?; let m = llvm::LLVMRustArchiveMemberNew(ptr::null(), name.as_ptr(), - child.raw()); + Some(child.raw)); members.push(m); strings.push(name); } - archives.push(archive); } } } - let dst = self.config.dst.to_str().unwrap().as_bytes(); - let dst = CString::new(dst)?; let r = llvm::LLVMRustWriteArchive(dst.as_ptr(), members.len() as libc::size_t, - members.as_ptr(), - self.should_update_symbols, + members.as_ptr() as *const &_, + should_update_symbols, kind); let ret = if r.into_result().is_err() { let err = llvm::LLVMRustGetLastError(); diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index 93cb9eb976765..daa2fb0528064 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -14,7 +14,7 @@ use back::write::{ModuleConfig, with_llvm_pmb, CodegenContext}; use back::write; use errors::{FatalError, Handler}; use llvm::archive_ro::ArchiveRO; -use llvm::{ModuleRef, TargetMachineRef, True, False}; +use llvm::{True, False}; use llvm; use rustc::hir::def_id::LOCAL_CRATE; use rustc::middle::exported_symbols::SymbolExportLevel; @@ -73,11 +73,13 @@ impl LtoModuleCodegen { match *self { LtoModuleCodegen::Fat { ref mut module, .. } => { let module = module.take().unwrap(); - let config = cgcx.config(module.kind); - let llmod = module.llvm().unwrap().llmod; - let tm = module.llvm().unwrap().tm; - run_pass_manager(cgcx, tm, llmod, config, false); - timeline.record("fat-done"); + { + let config = cgcx.config(module.kind); + let llmod = module.llvm().unwrap().llmod(); + let tm = &*module.llvm().unwrap().tm; + run_pass_manager(cgcx, tm, llmod, config, false); + timeline.record("fat-done"); + } Ok(module) } LtoModuleCodegen::Thin(ref mut thin) => thin.optimize(cgcx, timeline), @@ -223,66 +225,68 @@ fn fat_lto(cgcx: &CodegenContext, .filter(|&(_, module)| module.kind == ModuleKind::Regular) .map(|(i, module)| { let cost = unsafe { - llvm::LLVMRustModuleCost(module.llvm().unwrap().llmod) + llvm::LLVMRustModuleCost(module.llvm().unwrap().llmod()) }; (cost, i) }) .max() .expect("must be codegen'ing at least one module"); let module = modules.remove(costliest_module); - let llmod = module.llvm().expect("can't lto pre-codegened modules").llmod; - info!("using {:?} as a base module", module.llmod_id); - - // For all other modules we codegened we'll need to link them into our own - // bitcode. All modules were codegened in their own LLVM context, however, - // and we want to move everything to the same LLVM context. Currently the - // way we know of to do that is to serialize them to a string and them parse - // them later. Not great but hey, that's why it's "fat" LTO, right? - for module in modules { - let llvm = module.llvm().expect("can't lto pre-codegened modules"); - let buffer = ModuleBuffer::new(llvm.llmod); - let llmod_id = CString::new(&module.llmod_id[..]).unwrap(); - serialized_modules.push((SerializedModule::Local(buffer), llmod_id)); - } - - // For all serialized bitcode files we parse them and link them in as we did - // above, this is all mostly handled in C++. Like above, though, we don't - // know much about the memory management here so we err on the side of being - // save and persist everything with the original module. let mut serialized_bitcode = Vec::new(); - let mut linker = Linker::new(llmod); - for (bc_decoded, name) in serialized_modules { - info!("linking {:?}", name); - time_ext(cgcx.time_passes, None, &format!("ll link {:?}", name), || { - let data = bc_decoded.data(); - linker.add(&data).map_err(|()| { - let msg = format!("failed to load bc of {:?}", name); - write::llvm_err(&diag_handler, msg) - }) - })?; - timeline.record(&format!("link {:?}", name)); - serialized_bitcode.push(bc_decoded); - } - drop(linker); - cgcx.save_temp_bitcode(&module, "lto.input"); + { + let llmod = module.llvm().expect("can't lto pre-codegened modules").llmod(); + info!("using {:?} as a base module", module.llmod_id); + + // For all other modules we codegened we'll need to link them into our own + // bitcode. All modules were codegened in their own LLVM context, however, + // and we want to move everything to the same LLVM context. Currently the + // way we know of to do that is to serialize them to a string and them parse + // them later. Not great but hey, that's why it's "fat" LTO, right? + for module in modules { + let llvm = module.llvm().expect("can't lto pre-codegened modules"); + let buffer = ModuleBuffer::new(llvm.llmod()); + let llmod_id = CString::new(&module.llmod_id[..]).unwrap(); + serialized_modules.push((SerializedModule::Local(buffer), llmod_id)); + } - // Internalize everything that *isn't* in our whitelist to help strip out - // more modules and such - unsafe { - let ptr = symbol_white_list.as_ptr(); - llvm::LLVMRustRunRestrictionPass(llmod, - ptr as *const *const libc::c_char, - symbol_white_list.len() as libc::size_t); - cgcx.save_temp_bitcode(&module, "lto.after-restriction"); - } + // For all serialized bitcode files we parse them and link them in as we did + // above, this is all mostly handled in C++. Like above, though, we don't + // know much about the memory management here so we err on the side of being + // save and persist everything with the original module. + let mut linker = Linker::new(llmod); + for (bc_decoded, name) in serialized_modules { + info!("linking {:?}", name); + time_ext(cgcx.time_passes, None, &format!("ll link {:?}", name), || { + let data = bc_decoded.data(); + linker.add(&data).map_err(|()| { + let msg = format!("failed to load bc of {:?}", name); + write::llvm_err(&diag_handler, msg) + }) + })?; + timeline.record(&format!("link {:?}", name)); + serialized_bitcode.push(bc_decoded); + } + drop(linker); + cgcx.save_temp_bitcode(&module, "lto.input"); - if cgcx.no_landing_pads { + // Internalize everything that *isn't* in our whitelist to help strip out + // more modules and such unsafe { - llvm::LLVMRustMarkAllFunctionsNounwind(llmod); + let ptr = symbol_white_list.as_ptr(); + llvm::LLVMRustRunRestrictionPass(llmod, + ptr as *const *const libc::c_char, + symbol_white_list.len() as libc::size_t); + cgcx.save_temp_bitcode(&module, "lto.after-restriction"); + } + + if cgcx.no_landing_pads { + unsafe { + llvm::LLVMRustMarkAllFunctionsNounwind(llmod); + } + cgcx.save_temp_bitcode(&module, "lto.after-nounwind"); } - cgcx.save_temp_bitcode(&module, "lto.after-nounwind"); + timeline.record("passes"); } - timeline.record("passes"); Ok(vec![LtoModuleCodegen::Fat { module: Some(module), @@ -290,10 +294,10 @@ fn fat_lto(cgcx: &CodegenContext, }]) } -struct Linker(llvm::LinkerRef); +struct Linker<'a>(&'a mut llvm::Linker<'a>); -impl Linker { - fn new(llmod: ModuleRef) -> Linker { +impl Linker<'a> { + fn new(llmod: &'a llvm::Module) -> Self { unsafe { Linker(llvm::LLVMRustLinkerNew(llmod)) } } @@ -310,9 +314,9 @@ impl Linker { } } -impl Drop for Linker { +impl Drop for Linker<'a> { fn drop(&mut self) { - unsafe { llvm::LLVMRustLinkerFree(self.0); } + unsafe { llvm::LLVMRustLinkerFree(&mut *(self.0 as *mut _)); } } } @@ -371,7 +375,7 @@ fn thin_lto(diag_handler: &Handler, info!("local module: {} - {}", i, module.llmod_id); let llvm = module.llvm().expect("can't lto precodegened module"); let name = CString::new(module.llmod_id.clone()).unwrap(); - let buffer = ThinBuffer::new(llvm.llmod); + let buffer = ThinBuffer::new(llvm.llmod()); thin_modules.push(llvm::ThinLTOModule { identifier: name.as_ptr(), data: buffer.data().as_ptr(), @@ -419,11 +423,10 @@ fn thin_lto(diag_handler: &Handler, thin_modules.len() as u32, symbol_white_list.as_ptr(), symbol_white_list.len() as u32, - ); - if data.is_null() { - let msg = "failed to prepare thin LTO context".to_string(); - return Err(write::llvm_err(&diag_handler, msg)) - } + ).ok_or_else(|| { + write::llvm_err(&diag_handler, "failed to prepare thin LTO context".to_string()) + })?; + let data = ThinData(data); info!("thin LTO data created"); timeline.record("data"); @@ -448,8 +451,8 @@ fn thin_lto(diag_handler: &Handler, } fn run_pass_manager(cgcx: &CodegenContext, - tm: TargetMachineRef, - llmod: ModuleRef, + tm: &llvm::TargetMachine, + llmod: &llvm::Module, config: &ModuleConfig, thin: bool) { // Now we have one massive module inside of llmod. Time to run the @@ -464,8 +467,7 @@ fn run_pass_manager(cgcx: &CodegenContext, if config.verify_llvm_ir { let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _); - assert!(!pass.is_null()); - llvm::LLVMRustAddPass(pm, pass); + llvm::LLVMRustAddPass(pm, pass.unwrap()); } // When optimizing for LTO we don't actually pass in `-O0`, but we force @@ -499,8 +501,7 @@ fn run_pass_manager(cgcx: &CodegenContext, if config.verify_llvm_ir { let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _); - assert!(!pass.is_null()); - llvm::LLVMRustAddPass(pm, pass); + llvm::LLVMRustAddPass(pm, pass.unwrap()); } time_ext(cgcx.time_passes, None, "LTO passes", || @@ -525,13 +526,13 @@ impl SerializedModule { } } -pub struct ModuleBuffer(*mut llvm::ModuleBuffer); +pub struct ModuleBuffer(&'static mut llvm::ModuleBuffer); unsafe impl Send for ModuleBuffer {} unsafe impl Sync for ModuleBuffer {} impl ModuleBuffer { - pub fn new(m: ModuleRef) -> ModuleBuffer { + pub fn new(m: &llvm::Module) -> ModuleBuffer { ModuleBuffer(unsafe { llvm::LLVMRustModuleBufferCreate(m) }) @@ -548,7 +549,7 @@ impl ModuleBuffer { impl Drop for ModuleBuffer { fn drop(&mut self) { - unsafe { llvm::LLVMRustModuleBufferFree(self.0); } + unsafe { llvm::LLVMRustModuleBufferFree(&mut *(self.0 as *mut _)); } } } @@ -564,7 +565,7 @@ struct ThinShared { module_names: Vec, } -struct ThinData(*mut llvm::ThinLTOData); +struct ThinData(&'static mut llvm::ThinLTOData); unsafe impl Send for ThinData {} unsafe impl Sync for ThinData {} @@ -572,18 +573,18 @@ unsafe impl Sync for ThinData {} impl Drop for ThinData { fn drop(&mut self) { unsafe { - llvm::LLVMRustFreeThinLTOData(self.0); + llvm::LLVMRustFreeThinLTOData(&mut *(self.0 as *mut _)); } } } -pub struct ThinBuffer(*mut llvm::ThinLTOBuffer); +pub struct ThinBuffer(&'static mut llvm::ThinLTOBuffer); unsafe impl Send for ThinBuffer {} unsafe impl Sync for ThinBuffer {} impl ThinBuffer { - pub fn new(m: ModuleRef) -> ThinBuffer { + pub fn new(m: &llvm::Module) -> ThinBuffer { unsafe { let buffer = llvm::LLVMRustThinLTOBufferCreate(m); ThinBuffer(buffer) @@ -602,7 +603,7 @@ impl ThinBuffer { impl Drop for ThinBuffer { fn drop(&mut self) { unsafe { - llvm::LLVMRustThinLTOBufferFree(self.0); + llvm::LLVMRustThinLTOBufferFree(&mut *(self.0 as *mut _)); } } } @@ -640,19 +641,18 @@ impl ThinModule { // crates but for locally codegened modules we may be able to reuse // that LLVM Context and Module. let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names); - let llmod = llvm::LLVMRustParseBitcodeForThinLTO( + let llmod_raw = llvm::LLVMRustParseBitcodeForThinLTO( llcx, self.data().as_ptr(), self.data().len(), self.shared.module_names[self.idx].as_ptr(), - ); - if llmod.is_null() { + ).ok_or_else(|| { let msg = "failed to parse bitcode for thin LTO module".to_string(); - return Err(write::llvm_err(&diag_handler, msg)); - } + write::llvm_err(&diag_handler, msg) + })? as *const _; let module = ModuleCodegen { source: ModuleSource::Codegened(ModuleLlvm { - llmod, + llmod_raw, llcx, tm, }), @@ -660,104 +660,107 @@ impl ThinModule { name: self.name().to_string(), kind: ModuleKind::Regular, }; - cgcx.save_temp_bitcode(&module, "thin-lto-input"); - - // Before we do much else find the "main" `DICompileUnit` that we'll be - // using below. If we find more than one though then rustc has changed - // in a way we're not ready for, so generate an ICE by returning - // an error. - let mut cu1 = ptr::null_mut(); - let mut cu2 = ptr::null_mut(); - llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2); - if !cu2.is_null() { - let msg = "multiple source DICompileUnits found".to_string(); - return Err(write::llvm_err(&diag_handler, msg)) - } + { + let llmod = module.llvm().unwrap().llmod(); + cgcx.save_temp_bitcode(&module, "thin-lto-input"); + + // Before we do much else find the "main" `DICompileUnit` that we'll be + // using below. If we find more than one though then rustc has changed + // in a way we're not ready for, so generate an ICE by returning + // an error. + let mut cu1 = ptr::null_mut(); + let mut cu2 = ptr::null_mut(); + llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2); + if !cu2.is_null() { + let msg = "multiple source DICompileUnits found".to_string(); + return Err(write::llvm_err(&diag_handler, msg)) + } - // Like with "fat" LTO, get some better optimizations if landing pads - // are disabled by removing all landing pads. - if cgcx.no_landing_pads { - llvm::LLVMRustMarkAllFunctionsNounwind(llmod); - cgcx.save_temp_bitcode(&module, "thin-lto-after-nounwind"); - timeline.record("nounwind"); - } + // Like with "fat" LTO, get some better optimizations if landing pads + // are disabled by removing all landing pads. + if cgcx.no_landing_pads { + llvm::LLVMRustMarkAllFunctionsNounwind(llmod); + cgcx.save_temp_bitcode(&module, "thin-lto-after-nounwind"); + timeline.record("nounwind"); + } - // Up next comes the per-module local analyses that we do for Thin LTO. - // Each of these functions is basically copied from the LLVM - // implementation and then tailored to suit this implementation. Ideally - // each of these would be supported by upstream LLVM but that's perhaps - // a patch for another day! - // - // You can find some more comments about these functions in the LLVM - // bindings we've got (currently `PassWrapper.cpp`) - if !llvm::LLVMRustPrepareThinLTORename(self.shared.data.0, llmod) { - let msg = "failed to prepare thin LTO module".to_string(); - return Err(write::llvm_err(&diag_handler, msg)) - } - cgcx.save_temp_bitcode(&module, "thin-lto-after-rename"); - timeline.record("rename"); - if !llvm::LLVMRustPrepareThinLTOResolveWeak(self.shared.data.0, llmod) { - let msg = "failed to prepare thin LTO module".to_string(); - return Err(write::llvm_err(&diag_handler, msg)) - } - cgcx.save_temp_bitcode(&module, "thin-lto-after-resolve"); - timeline.record("resolve"); - if !llvm::LLVMRustPrepareThinLTOInternalize(self.shared.data.0, llmod) { - let msg = "failed to prepare thin LTO module".to_string(); - return Err(write::llvm_err(&diag_handler, msg)) - } - cgcx.save_temp_bitcode(&module, "thin-lto-after-internalize"); - timeline.record("internalize"); - if !llvm::LLVMRustPrepareThinLTOImport(self.shared.data.0, llmod) { - let msg = "failed to prepare thin LTO module".to_string(); - return Err(write::llvm_err(&diag_handler, msg)) + // Up next comes the per-module local analyses that we do for Thin LTO. + // Each of these functions is basically copied from the LLVM + // implementation and then tailored to suit this implementation. Ideally + // each of these would be supported by upstream LLVM but that's perhaps + // a patch for another day! + // + // You can find some more comments about these functions in the LLVM + // bindings we've got (currently `PassWrapper.cpp`) + if !llvm::LLVMRustPrepareThinLTORename(self.shared.data.0, llmod) { + let msg = "failed to prepare thin LTO module".to_string(); + return Err(write::llvm_err(&diag_handler, msg)) + } + cgcx.save_temp_bitcode(&module, "thin-lto-after-rename"); + timeline.record("rename"); + if !llvm::LLVMRustPrepareThinLTOResolveWeak(self.shared.data.0, llmod) { + let msg = "failed to prepare thin LTO module".to_string(); + return Err(write::llvm_err(&diag_handler, msg)) + } + cgcx.save_temp_bitcode(&module, "thin-lto-after-resolve"); + timeline.record("resolve"); + if !llvm::LLVMRustPrepareThinLTOInternalize(self.shared.data.0, llmod) { + let msg = "failed to prepare thin LTO module".to_string(); + return Err(write::llvm_err(&diag_handler, msg)) + } + cgcx.save_temp_bitcode(&module, "thin-lto-after-internalize"); + timeline.record("internalize"); + if !llvm::LLVMRustPrepareThinLTOImport(self.shared.data.0, llmod) { + let msg = "failed to prepare thin LTO module".to_string(); + return Err(write::llvm_err(&diag_handler, msg)) + } + cgcx.save_temp_bitcode(&module, "thin-lto-after-import"); + timeline.record("import"); + + // Ok now this is a bit unfortunate. This is also something you won't + // find upstream in LLVM's ThinLTO passes! This is a hack for now to + // work around bugs in LLVM. + // + // First discovered in #45511 it was found that as part of ThinLTO + // importing passes LLVM will import `DICompileUnit` metadata + // information across modules. This means that we'll be working with one + // LLVM module that has multiple `DICompileUnit` instances in it (a + // bunch of `llvm.dbg.cu` members). Unfortunately there's a number of + // bugs in LLVM's backend which generates invalid DWARF in a situation + // like this: + // + // https://bugs.llvm.org/show_bug.cgi?id=35212 + // https://bugs.llvm.org/show_bug.cgi?id=35562 + // + // While the first bug there is fixed the second ended up causing #46346 + // which was basically a resurgence of #45511 after LLVM's bug 35212 was + // fixed. + // + // This function below is a huge hack around this problem. The function + // below is defined in `PassWrapper.cpp` and will basically "merge" + // all `DICompileUnit` instances in a module. Basically it'll take all + // the objects, rewrite all pointers of `DISubprogram` to point to the + // first `DICompileUnit`, and then delete all the other units. + // + // This is probably mangling to the debug info slightly (but hopefully + // not too much) but for now at least gets LLVM to emit valid DWARF (or + // so it appears). Hopefully we can remove this once upstream bugs are + // fixed in LLVM. + llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1); + cgcx.save_temp_bitcode(&module, "thin-lto-after-patch"); + timeline.record("patch"); + + // Alright now that we've done everything related to the ThinLTO + // analysis it's time to run some optimizations! Here we use the same + // `run_pass_manager` as the "fat" LTO above except that we tell it to + // populate a thin-specific pass manager, which presumably LLVM treats a + // little differently. + info!("running thin lto passes over {}", module.name); + let config = cgcx.config(module.kind); + run_pass_manager(cgcx, module.llvm().unwrap().tm, llmod, config, true); + cgcx.save_temp_bitcode(&module, "thin-lto-after-pm"); + timeline.record("thin-done"); } - cgcx.save_temp_bitcode(&module, "thin-lto-after-import"); - timeline.record("import"); - - // Ok now this is a bit unfortunate. This is also something you won't - // find upstream in LLVM's ThinLTO passes! This is a hack for now to - // work around bugs in LLVM. - // - // First discovered in #45511 it was found that as part of ThinLTO - // importing passes LLVM will import `DICompileUnit` metadata - // information across modules. This means that we'll be working with one - // LLVM module that has multiple `DICompileUnit` instances in it (a - // bunch of `llvm.dbg.cu` members). Unfortunately there's a number of - // bugs in LLVM's backend which generates invalid DWARF in a situation - // like this: - // - // https://bugs.llvm.org/show_bug.cgi?id=35212 - // https://bugs.llvm.org/show_bug.cgi?id=35562 - // - // While the first bug there is fixed the second ended up causing #46346 - // which was basically a resurgence of #45511 after LLVM's bug 35212 was - // fixed. - // - // This function below is a huge hack around this problem. The function - // below is defined in `PassWrapper.cpp` and will basically "merge" - // all `DICompileUnit` instances in a module. Basically it'll take all - // the objects, rewrite all pointers of `DISubprogram` to point to the - // first `DICompileUnit`, and then delete all the other units. - // - // This is probably mangling to the debug info slightly (but hopefully - // not too much) but for now at least gets LLVM to emit valid DWARF (or - // so it appears). Hopefully we can remove this once upstream bugs are - // fixed in LLVM. - llvm::LLVMRustThinLTOPatchDICompileUnit(llmod, cu1); - cgcx.save_temp_bitcode(&module, "thin-lto-after-patch"); - timeline.record("patch"); - - // Alright now that we've done everything related to the ThinLTO - // analysis it's time to run some optimizations! Here we use the same - // `run_pass_manager` as the "fat" LTO above except that we tell it to - // populate a thin-specific pass manager, which presumably LLVM treats a - // little differently. - info!("running thin lto passes over {}", module.name); - let config = cgcx.config(module.kind); - run_pass_manager(cgcx, tm, llmod, config, true); - cgcx.save_temp_bitcode(&module, "thin-lto-after-pm"); - timeline.record("thin-done"); Ok(module) } diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index d36142af56c65..db044878fe745 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -25,9 +25,7 @@ use rustc::session::config::{self, OutputFilenames, OutputType, Passes, SomePass use rustc::session::Session; use rustc::util::nodemap::FxHashMap; use time_graph::{self, TimeGraph, Timeline}; -use llvm; -use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef}; -use llvm::{SMDiagnosticRef, ContextRef}; +use llvm::{self, DiagnosticInfo, PassManager, SMDiagnostic}; use {CodegenResults, ModuleSource, ModuleCodegen, CompiledModule, ModuleKind}; use CrateInfo; use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; @@ -94,9 +92,9 @@ pub fn llvm_err(handler: &errors::Handler, msg: String) -> FatalError { pub fn write_output_file( handler: &errors::Handler, - target: llvm::TargetMachineRef, - pm: llvm::PassManagerRef, - m: ModuleRef, + target: &'ll llvm::TargetMachine, + pm: &llvm::PassManager<'ll>, + m: &'ll llvm::Module, output: &Path, file_type: llvm::FileType) -> Result<(), FatalError> { unsafe { @@ -130,7 +128,10 @@ fn get_llvm_opt_size(optimize: config::OptLevel) -> llvm::CodeGenOptSize { } } -pub fn create_target_machine(sess: &Session, find_features: bool) -> TargetMachineRef { +pub fn create_target_machine( + sess: &Session, + find_features: bool, +) -> &'static mut llvm::TargetMachine { target_machine_factory(sess, find_features)().unwrap_or_else(|err| { llvm_err(sess.diagnostic(), err).raise() }) @@ -140,7 +141,7 @@ pub fn create_target_machine(sess: &Session, find_features: bool) -> TargetMachi // that `is_pie_binary` is false. When we discover LLVM target features // `sess.crate_types` is uninitialized so we cannot access it. pub fn target_machine_factory(sess: &Session, find_features: bool) - -> Arc Result + Send + Sync> + -> Arc Result<&'static mut llvm::TargetMachine, String> + Send + Sync> { let reloc_model = get_reloc_model(sess); @@ -199,12 +200,10 @@ pub fn target_machine_factory(sess: &Session, find_features: bool) ) }; - if tm.is_null() { - Err(format!("Could not create LLVM TargetMachine for triple: {}", - triple.to_str().unwrap())) - } else { - Ok(tm) - } + tm.ok_or_else(|| { + format!("Could not create LLVM TargetMachine for triple: {}", + triple.to_str().unwrap()) + }) }) } @@ -343,7 +342,7 @@ pub struct CodegenContext { regular_module_config: Arc, metadata_module_config: Arc, allocator_module_config: Arc, - pub tm_factory: Arc Result + Send + Sync>, + pub tm_factory: Arc Result<&'static mut llvm::TargetMachine, String> + Send + Sync>, pub msvc_imps_needed: bool, pub target_pointer_width: String, debuginfo: config::DebugInfoLevel, @@ -392,7 +391,7 @@ impl CodegenContext { let cgu = Some(&module.name[..]); let path = self.output_filenames.temp_path_ext(&ext, cgu); let cstr = path2cstr(&path); - let llmod = module.llvm().unwrap().llmod; + let llmod = module.llvm().unwrap().llmod(); llvm::LLVMWriteBitcodeToFile(llmod, cstr.as_ptr()); } } @@ -400,13 +399,13 @@ impl CodegenContext { struct DiagnosticHandlers<'a> { data: *mut (&'a CodegenContext, &'a Handler), - llcx: ContextRef, + llcx: &'a llvm::Context, } impl<'a> DiagnosticHandlers<'a> { fn new(cgcx: &'a CodegenContext, handler: &'a Handler, - llcx: ContextRef) -> DiagnosticHandlers<'a> { + llcx: &'a llvm::Context) -> Self { let data = Box::into_raw(Box::new((cgcx, handler))); unsafe { llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, data as *mut _); @@ -433,7 +432,7 @@ unsafe extern "C" fn report_inline_asm<'a, 'b>(cgcx: &'a CodegenContext, cgcx.diag_emitter.inline_asm_error(cookie as u32, msg.to_string()); } -unsafe extern "C" fn inline_asm_handler(diag: SMDiagnosticRef, +unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void, cookie: c_uint) { if user.is_null() { @@ -447,7 +446,7 @@ unsafe extern "C" fn inline_asm_handler(diag: SMDiagnosticRef, report_inline_asm(cgcx, &msg, cookie); } -unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_void) { +unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) { if user.is_null() { return } @@ -495,7 +494,7 @@ unsafe fn optimize(cgcx: &CodegenContext, -> Result<(), FatalError> { let (llmod, llcx, tm) = match module.source { - ModuleSource::Codegened(ref llvm) => (llvm.llmod, llvm.llcx, llvm.tm), + ModuleSource::Codegened(ref llvm) => (llvm.llmod(), &*llvm.llcx, &*llvm.tm), ModuleSource::Preexisting(_) => { bug!("optimize_and_codegen: called with ModuleSource::Preexisting") } @@ -520,50 +519,52 @@ unsafe fn optimize(cgcx: &CodegenContext, let fpm = llvm::LLVMCreateFunctionPassManagerForModule(llmod); let mpm = llvm::LLVMCreatePassManager(); - // If we're verifying or linting, add them to the function pass - // manager. - let addpass = |pass_name: &str| { - let pass_name = CString::new(pass_name).unwrap(); - let pass = llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr()); - if pass.is_null() { - return false; - } - let pass_manager = match llvm::LLVMRustPassKind(pass) { - llvm::PassKind::Function => fpm, - llvm::PassKind::Module => mpm, - llvm::PassKind::Other => { - diag_handler.err("Encountered LLVM pass kind we can't handle"); - return true - }, + { + // If we're verifying or linting, add them to the function pass + // manager. + let addpass = |pass_name: &str| { + let pass_name = CString::new(pass_name).unwrap(); + let pass = match llvm::LLVMRustFindAndCreatePass(pass_name.as_ptr()) { + Some(pass) => pass, + None => return false, + }; + let pass_manager = match llvm::LLVMRustPassKind(pass) { + llvm::PassKind::Function => &*fpm, + llvm::PassKind::Module => &*mpm, + llvm::PassKind::Other => { + diag_handler.err("Encountered LLVM pass kind we can't handle"); + return true + }, + }; + llvm::LLVMRustAddPass(pass_manager, pass); + true }; - llvm::LLVMRustAddPass(pass_manager, pass); - true - }; - if config.verify_llvm_ir { assert!(addpass("verify")); } - if !config.no_prepopulate_passes { - llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod); - llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod); - let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None); - let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal; - with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| { - llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm); - llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm); - }) - } + if config.verify_llvm_ir { assert!(addpass("verify")); } + if !config.no_prepopulate_passes { + llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod); + llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod); + let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None); + let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal; + with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| { + llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm); + llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm); + }) + } - for pass in &config.passes { - if !addpass(pass) { - diag_handler.warn(&format!("unknown pass `{}`, ignoring", - pass)); + for pass in &config.passes { + if !addpass(pass) { + diag_handler.warn(&format!("unknown pass `{}`, ignoring", + pass)); + } } - } - for pass in &cgcx.plugin_passes { - if !addpass(pass) { - diag_handler.err(&format!("a plugin asked for LLVM pass \ - `{}` but LLVM does not \ - recognize it", pass)); + for pass in &cgcx.plugin_passes { + if !addpass(pass) { + diag_handler.err(&format!("a plugin asked for LLVM pass \ + `{}` but LLVM does not \ + recognize it", pass)); + } } } @@ -617,192 +618,191 @@ unsafe fn codegen(cgcx: &CodegenContext, -> Result { timeline.record("codegen"); - let (llmod, llcx, tm) = match module.source { - ModuleSource::Codegened(ref llvm) => (llvm.llmod, llvm.llcx, llvm.tm), - ModuleSource::Preexisting(_) => { - bug!("codegen: called with ModuleSource::Preexisting") - } - }; - let module_name = module.name.clone(); - let module_name = Some(&module_name[..]); - let handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx); - - if cgcx.msvc_imps_needed { - create_msvc_imps(cgcx, llcx, llmod); - } - - // A codegen-specific pass manager is used to generate object - // files for an LLVM module. - // - // Apparently each of these pass managers is a one-shot kind of - // thing, so we create a new one for each type of output. The - // pass manager passed to the closure should be ensured to not - // escape the closure itself, and the manager should only be - // used once. - unsafe fn with_codegen(tm: TargetMachineRef, - llmod: ModuleRef, - no_builtins: bool, - f: F) -> R - where F: FnOnce(PassManagerRef) -> R, { - let cpm = llvm::LLVMCreatePassManager(); - llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod); - llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins); - f(cpm) - } - - // If we don't have the integrated assembler, then we need to emit asm - // from LLVM and use `gcc` to create the object file. - let asm_to_obj = config.emit_obj && config.no_integrated_as; - - // Change what we write and cleanup based on whether obj files are - // just llvm bitcode. In that case write bitcode, and possibly - // delete the bitcode if it wasn't requested. Don't generate the - // machine code, instead copy the .o file from the .bc - let write_bc = config.emit_bc || config.obj_is_bitcode; - let rm_bc = !config.emit_bc && config.obj_is_bitcode; - let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm_to_obj; - let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode; - - let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); - let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); - - - if write_bc || config.emit_bc_compressed || config.embed_bitcode { - let thin; - let old; - let data = if llvm::LLVMRustThinLTOAvailable() { - thin = ThinBuffer::new(llmod); - thin.data() - } else { - old = ModuleBuffer::new(llmod); - old.data() + let (llmod, llcx, tm) = match module.source { + ModuleSource::Codegened(ref llvm) => (llvm.llmod(), &*llvm.llcx, &*llvm.tm), + ModuleSource::Preexisting(_) => { + bug!("codegen: called with ModuleSource::Preexisting") + } }; - timeline.record("make-bc"); + let module_name = module.name.clone(); + let module_name = Some(&module_name[..]); + let handlers = DiagnosticHandlers::new(cgcx, diag_handler, llcx); - if write_bc { - if let Err(e) = fs::write(&bc_out, data) { - diag_handler.err(&format!("failed to write bytecode: {}", e)); - } - timeline.record("write-bc"); + if cgcx.msvc_imps_needed { + create_msvc_imps(cgcx, llcx, llmod); } - if config.embed_bitcode { - embed_bitcode(cgcx, llcx, llmod, Some(data)); - timeline.record("embed-bc"); - } + // A codegen-specific pass manager is used to generate object + // files for an LLVM module. + // + // Apparently each of these pass managers is a one-shot kind of + // thing, so we create a new one for each type of output. The + // pass manager passed to the closure should be ensured to not + // escape the closure itself, and the manager should only be + // used once. + unsafe fn with_codegen<'ll, F, R>(tm: &'ll llvm::TargetMachine, + llmod: &'ll llvm::Module, + no_builtins: bool, + f: F) -> R + where F: FnOnce(&'ll mut PassManager<'ll>) -> R, + { + let cpm = llvm::LLVMCreatePassManager(); + llvm::LLVMRustAddAnalysisPasses(tm, cpm, llmod); + llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins); + f(cpm) + } + + // If we don't have the integrated assembler, then we need to emit asm + // from LLVM and use `gcc` to create the object file. + let asm_to_obj = config.emit_obj && config.no_integrated_as; + + // Change what we write and cleanup based on whether obj files are + // just llvm bitcode. In that case write bitcode, and possibly + // delete the bitcode if it wasn't requested. Don't generate the + // machine code, instead copy the .o file from the .bc + let write_bc = config.emit_bc || config.obj_is_bitcode; + let rm_bc = !config.emit_bc && config.obj_is_bitcode; + let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm_to_obj; + let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode; + + let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name); + let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name); + + + if write_bc || config.emit_bc_compressed || config.embed_bitcode { + let thin; + let old; + let data = if llvm::LLVMRustThinLTOAvailable() { + thin = ThinBuffer::new(llmod); + thin.data() + } else { + old = ModuleBuffer::new(llmod); + old.data() + }; + timeline.record("make-bc"); - if config.emit_bc_compressed { - let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION); - let data = bytecode::encode(&module.llmod_id, data); - if let Err(e) = fs::write(&dst, data) { - diag_handler.err(&format!("failed to write bytecode: {}", e)); + if write_bc { + if let Err(e) = fs::write(&bc_out, data) { + diag_handler.err(&format!("failed to write bytecode: {}", e)); + } + timeline.record("write-bc"); } - timeline.record("compress-bc"); - } - } else if config.embed_bitcode_marker { - embed_bitcode(cgcx, llcx, llmod, None); - } - time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()), - || -> Result<(), FatalError> { - if config.emit_ir { - let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); - let out = path2cstr(&out); - - extern "C" fn demangle_callback(input_ptr: *const c_char, - input_len: size_t, - output_ptr: *mut c_char, - output_len: size_t) -> size_t { - let input = unsafe { - slice::from_raw_parts(input_ptr as *const u8, input_len as usize) - }; + if config.embed_bitcode { + embed_bitcode(cgcx, llcx, llmod, Some(data)); + timeline.record("embed-bc"); + } - let input = match str::from_utf8(input) { - Ok(s) => s, - Err(_) => return 0, - }; + if config.emit_bc_compressed { + let dst = bc_out.with_extension(RLIB_BYTECODE_EXTENSION); + let data = bytecode::encode(&module.llmod_id, data); + if let Err(e) = fs::write(&dst, data) { + diag_handler.err(&format!("failed to write bytecode: {}", e)); + } + timeline.record("compress-bc"); + } + } else if config.embed_bitcode_marker { + embed_bitcode(cgcx, llcx, llmod, None); + } + + time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()), + || -> Result<(), FatalError> { + if config.emit_ir { + let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name); + let out = path2cstr(&out); + + extern "C" fn demangle_callback(input_ptr: *const c_char, + input_len: size_t, + output_ptr: *mut c_char, + output_len: size_t) -> size_t { + let input = unsafe { + slice::from_raw_parts(input_ptr as *const u8, input_len as usize) + }; - let output = unsafe { - slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize) - }; - let mut cursor = io::Cursor::new(output); + let input = match str::from_utf8(input) { + Ok(s) => s, + Err(_) => return 0, + }; - let demangled = match rustc_demangle::try_demangle(input) { - Ok(d) => d, - Err(_) => return 0, - }; + let output = unsafe { + slice::from_raw_parts_mut(output_ptr as *mut u8, output_len as usize) + }; + let mut cursor = io::Cursor::new(output); + + let demangled = match rustc_demangle::try_demangle(input) { + Ok(d) => d, + Err(_) => return 0, + }; + + if let Err(_) = write!(cursor, "{:#}", demangled) { + // Possible only if provided buffer is not big enough + return 0; + } - if let Err(_) = write!(cursor, "{:#}", demangled) { - // Possible only if provided buffer is not big enough - return 0; + cursor.position() as size_t } - cursor.position() as size_t + with_codegen(tm, llmod, config.no_builtins, |cpm| { + llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback); + llvm::LLVMDisposePassManager(cpm); + }); + timeline.record("ir"); } - with_codegen(tm, llmod, config.no_builtins, |cpm| { - llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr(), demangle_callback); - llvm::LLVMDisposePassManager(cpm); - }); - timeline.record("ir"); - } - - if config.emit_asm || asm_to_obj { - let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); + if config.emit_asm || asm_to_obj { + let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); - // We can't use the same module for asm and binary output, because that triggers - // various errors like invalid IR or broken binaries, so we might have to clone the - // module to produce the asm output - let llmod = if config.emit_obj { - llvm::LLVMCloneModule(llmod) - } else { - llmod - }; - with_codegen(tm, llmod, config.no_builtins, |cpm| { - write_output_file(diag_handler, tm, cpm, llmod, &path, - llvm::FileType::AssemblyFile) - })?; - if config.emit_obj { - llvm::LLVMDisposeModule(llmod); + // We can't use the same module for asm and binary output, because that triggers + // various errors like invalid IR or broken binaries, so we might have to clone the + // module to produce the asm output + let llmod = if config.emit_obj { + llvm::LLVMCloneModule(llmod) + } else { + llmod + }; + with_codegen(tm, llmod, config.no_builtins, |cpm| { + write_output_file(diag_handler, tm, cpm, llmod, &path, + llvm::FileType::AssemblyFile) + })?; + timeline.record("asm"); } - timeline.record("asm"); - } - if write_obj { - with_codegen(tm, llmod, config.no_builtins, |cpm| { - write_output_file(diag_handler, tm, cpm, llmod, &obj_out, - llvm::FileType::ObjectFile) - })?; - timeline.record("obj"); - } else if asm_to_obj { - let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); - run_assembler(cgcx, diag_handler, &assembly, &obj_out); - timeline.record("asm_to_obj"); - - if !config.emit_asm && !cgcx.save_temps { - drop(fs::remove_file(&assembly)); + if write_obj { + with_codegen(tm, llmod, config.no_builtins, |cpm| { + write_output_file(diag_handler, tm, cpm, llmod, &obj_out, + llvm::FileType::ObjectFile) + })?; + timeline.record("obj"); + } else if asm_to_obj { + let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name); + run_assembler(cgcx, diag_handler, &assembly, &obj_out); + timeline.record("asm_to_obj"); + + if !config.emit_asm && !cgcx.save_temps { + drop(fs::remove_file(&assembly)); + } } - } - Ok(()) - })?; + Ok(()) + })?; - if copy_bc_to_obj { - debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out); - if let Err(e) = link_or_copy(&bc_out, &obj_out) { - diag_handler.err(&format!("failed to copy bitcode to object file: {}", e)); + if copy_bc_to_obj { + debug!("copying bitcode {:?} to obj {:?}", bc_out, obj_out); + if let Err(e) = link_or_copy(&bc_out, &obj_out) { + diag_handler.err(&format!("failed to copy bitcode to object file: {}", e)); + } } - } - if rm_bc { - debug!("removing_bitcode {:?}", bc_out); - if let Err(e) = fs::remove_file(&bc_out) { - diag_handler.err(&format!("failed to remove bitcode: {}", e)); + if rm_bc { + debug!("removing_bitcode {:?}", bc_out); + if let Err(e) = fs::remove_file(&bc_out) { + diag_handler.err(&format!("failed to remove bitcode: {}", e)); + } } - } - drop(handlers); + drop(handlers); + } Ok(module.into_compiled_module(config.emit_obj, config.emit_bc, config.emit_bc_compressed, @@ -828,13 +828,13 @@ unsafe fn codegen(cgcx: &CodegenContext, /// Basically all of this is us attempting to follow in the footsteps of clang /// on iOS. See #35968 for lots more info. unsafe fn embed_bitcode(cgcx: &CodegenContext, - llcx: ContextRef, - llmod: ModuleRef, + llcx: &llvm::Context, + llmod: &llvm::Module, bitcode: Option<&[u8]>) { let llconst = C_bytes_in_context(llcx, bitcode.unwrap_or(&[])); let llglobal = llvm::LLVMAddGlobal( llmod, - val_ty(llconst).to_ref(), + val_ty(llconst), "rustc.embedded.module\0".as_ptr() as *const _, ); llvm::LLVMSetInitializer(llglobal, llconst); @@ -854,7 +854,7 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext, let llconst = C_bytes_in_context(llcx, &[]); let llglobal = llvm::LLVMAddGlobal( llmod, - val_ty(llconst).to_ref(), + val_ty(llconst), "rustc.embedded.cmdline\0".as_ptr() as *const _, ); llvm::LLVMSetInitializer(llglobal, llconst); @@ -2050,11 +2050,11 @@ pub fn run_assembler(cgcx: &CodegenContext, handler: &Handler, assembly: &Path, } } -pub unsafe fn with_llvm_pmb(llmod: ModuleRef, +pub unsafe fn with_llvm_pmb(llmod: &llvm::Module, config: &ModuleConfig, opt_level: llvm::CodeGenOptLevel, prepare_for_thin_lto: bool, - f: &mut dyn FnMut(llvm::PassManagerBuilderRef)) { + f: &mut dyn FnMut(&llvm::PassManagerBuilder)) { use std::ptr; // Create the PassManagerBuilder for LLVM. We configure it with @@ -2353,7 +2353,7 @@ fn msvc_imps_needed(tcx: TyCtxt) -> bool { // when using MSVC linker. We do this only for data, as linker can fix up // code references on its own. // See #26591, #27438 -fn create_msvc_imps(cgcx: &CodegenContext, llcx: ContextRef, llmod: ModuleRef) { +fn create_msvc_imps(cgcx: &CodegenContext, llcx: &llvm::Context, llmod: &llvm::Module) { if !cgcx.msvc_imps_needed { return } @@ -2383,7 +2383,7 @@ fn create_msvc_imps(cgcx: &CodegenContext, llcx: ContextRef, llmod: ModuleRef) { .collect::>(); for (imp_name, val) in globals { let imp = llvm::LLVMAddGlobal(llmod, - i8p_ty.to_ref(), + i8p_ty, imp_name.as_ptr() as *const _); llvm::LLVMSetInitializer(imp, consts::ptrcast(val, i8p_ty)); llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage); diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 223c04f420f3f..8278b443a4c83 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -17,11 +17,11 @@ //! //! Hopefully useful general knowledge about codegen: //! -//! * There's no way to find out the Ty type of a ValueRef. Doing so +//! * There's no way to find out the Ty type of a Value. Doing so //! would be "trying to get the eggs out of an omelette" (credit: -//! pcwalton). You can, instead, find out its TypeRef by calling val_ty, -//! but one TypeRef corresponds to many `Ty`s; for instance, tup(int, int, -//! int) and rec(x=int, y=int, z=int) will have the same TypeRef. +//! pcwalton). You can, instead, find out its llvm::Type by calling val_ty, +//! but one llvm::Type corresponds to many `Ty`s; for instance, tup(int, int, +//! int) and rec(x=int, y=int, z=int) will have the same llvm::Type. use super::ModuleLlvm; use super::ModuleSource; @@ -30,9 +30,8 @@ use super::ModuleKind; use abi; use back::link; -use back::write::{self, OngoingCodegen, create_target_machine}; -use llvm::{ContextRef, ModuleRef, ValueRef, Vector, get_param}; -use llvm; +use back::write::{self, OngoingCodegen}; +use llvm::{self, TypeKind, get_param}; use metadata; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::middle::lang_items::StartFnLangItem; @@ -59,7 +58,7 @@ use rustc_mir::monomorphize::collector::{self, MonoItemCollectionMode}; use rustc_mir::monomorphize::item::DefPathBasedNames; use common::{self, C_struct_in_context, C_array, val_ty}; use consts; -use context::{self, CodegenCx}; +use context::CodegenCx; use debuginfo; use declare; use meth; @@ -77,7 +76,6 @@ use rustc_data_structures::sync::Lrc; use std::any::Any; use std::ffi::CString; -use std::str; use std::sync::Arc; use std::time::{Instant, Duration}; use std::i32; @@ -88,18 +86,20 @@ use syntax_pos::symbol::InternedString; use syntax::attr; use rustc::hir::{self, CodegenFnAttrs}; +use value::Value; + use mir::operand::OperandValue; use rustc_codegen_utils::check_for_rustc_errors_attr; -pub struct StatRecorder<'a, 'tcx: 'a> { - cx: &'a CodegenCx<'a, 'tcx>, +pub struct StatRecorder<'a, 'll: 'a, 'tcx: 'll> { + cx: &'a CodegenCx<'ll, 'tcx>, name: Option, istart: usize, } -impl<'a, 'tcx> StatRecorder<'a, 'tcx> { - pub fn new(cx: &'a CodegenCx<'a, 'tcx>, name: String) -> StatRecorder<'a, 'tcx> { +impl StatRecorder<'a, 'll, 'tcx> { + pub fn new(cx: &'a CodegenCx<'ll, 'tcx>, name: String) -> Self { let istart = cx.stats.borrow().n_llvm_insns; StatRecorder { cx, @@ -109,7 +109,7 @@ impl<'a, 'tcx> StatRecorder<'a, 'tcx> { } } -impl<'a, 'tcx> Drop for StatRecorder<'a, 'tcx> { +impl Drop for StatRecorder<'a, 'll, 'tcx> { fn drop(&mut self) { if self.cx.sess().codegen_stats() { let mut stats = self.cx.stats.borrow_mut(); @@ -156,14 +156,14 @@ pub fn bin_op_to_fcmp_predicate(op: hir::BinOpKind) -> llvm::RealPredicate { } } -pub fn compare_simd_types<'a, 'tcx>( - bx: &Builder<'a, 'tcx>, - lhs: ValueRef, - rhs: ValueRef, +pub fn compare_simd_types( + bx: &Builder<'a, 'll, 'tcx>, + lhs: &'ll Value, + rhs: &'ll Value, t: Ty<'tcx>, - ret_ty: Type, + ret_ty: &'ll Type, op: hir::BinOpKind -) -> ValueRef { +) -> &'ll Value { let signed = match t.sty { ty::TyFloat(_) => { let cmp = bin_op_to_fcmp_predicate(op); @@ -188,11 +188,12 @@ pub fn compare_simd_types<'a, 'tcx>( /// The `old_info` argument is a bit funny. It is intended for use /// in an upcast, where the new vtable for an object will be derived /// from the old one. -pub fn unsized_info<'cx, 'tcx>(cx: &CodegenCx<'cx, 'tcx>, - source: Ty<'tcx>, - target: Ty<'tcx>, - old_info: Option) - -> ValueRef { +pub fn unsized_info( + cx: &CodegenCx<'ll, 'tcx>, + source: Ty<'tcx>, + target: Ty<'tcx>, + old_info: Option<&'ll Value>, +) -> &'ll Value { let (source, target) = cx.tcx.struct_lockstep_tails(source, target); match (&source.sty, &target.sty) { (&ty::TyArray(_, len), &ty::TySlice(_)) => { @@ -217,12 +218,12 @@ pub fn unsized_info<'cx, 'tcx>(cx: &CodegenCx<'cx, 'tcx>, } /// Coerce `src` to `dst_ty`. `src_ty` must be a thin pointer. -pub fn unsize_thin_ptr<'a, 'tcx>( - bx: &Builder<'a, 'tcx>, - src: ValueRef, +pub fn unsize_thin_ptr( + bx: &Builder<'a, 'll, 'tcx>, + src: &'ll Value, src_ty: Ty<'tcx>, dst_ty: Ty<'tcx> -) -> (ValueRef, ValueRef) { +) -> (&'ll Value, &'ll Value) { debug!("unsize_thin_ptr: {:?} => {:?}", src_ty, dst_ty); match (&src_ty.sty, &dst_ty.sty) { (&ty::TyRef(_, a, _), @@ -272,9 +273,11 @@ pub fn unsize_thin_ptr<'a, 'tcx>( /// Coerce `src`, which is a reference to a value of type `src_ty`, /// to a value of type `dst_ty` and store the result in `dst` -pub fn coerce_unsized_into<'a, 'tcx>(bx: &Builder<'a, 'tcx>, - src: PlaceRef<'tcx>, - dst: PlaceRef<'tcx>) { +pub fn coerce_unsized_into( + bx: &Builder<'a, 'll, 'tcx>, + src: PlaceRef<'ll, 'tcx>, + dst: PlaceRef<'ll, 'tcx> +) { let src_ty = src.layout.ty; let dst_ty = dst.layout.ty; let coerce_ptr = || { @@ -330,28 +333,28 @@ pub fn coerce_unsized_into<'a, 'tcx>(bx: &Builder<'a, 'tcx>, } pub fn cast_shift_expr_rhs( - cx: &Builder, op: hir::BinOpKind, lhs: ValueRef, rhs: ValueRef -) -> ValueRef { + cx: &Builder<'_, 'll, '_>, op: hir::BinOpKind, lhs: &'ll Value, rhs: &'ll Value +) -> &'ll Value { cast_shift_rhs(op, lhs, rhs, |a, b| cx.trunc(a, b), |a, b| cx.zext(a, b)) } -fn cast_shift_rhs(op: hir::BinOpKind, - lhs: ValueRef, - rhs: ValueRef, +fn cast_shift_rhs<'ll, F, G>(op: hir::BinOpKind, + lhs: &'ll Value, + rhs: &'ll Value, trunc: F, zext: G) - -> ValueRef - where F: FnOnce(ValueRef, Type) -> ValueRef, - G: FnOnce(ValueRef, Type) -> ValueRef + -> &'ll Value + where F: FnOnce(&'ll Value, &'ll Type) -> &'ll Value, + G: FnOnce(&'ll Value, &'ll Type) -> &'ll Value { // Shifts may have any size int on the rhs if op.is_shift() { let mut rhs_llty = val_ty(rhs); let mut lhs_llty = val_ty(lhs); - if rhs_llty.kind() == Vector { + if rhs_llty.kind() == TypeKind::Vector { rhs_llty = rhs_llty.element_type() } - if lhs_llty.kind() == Vector { + if lhs_llty.kind() == TypeKind::Vector { lhs_llty = lhs_llty.element_type() } let rhs_sz = rhs_llty.int_width(); @@ -379,12 +382,12 @@ pub fn wants_msvc_seh(sess: &Session) -> bool { sess.target.target.options.is_like_msvc } -pub fn call_assume<'a, 'tcx>(bx: &Builder<'a, 'tcx>, val: ValueRef) { +pub fn call_assume(bx: &Builder<'_, 'll, '_>, val: &'ll Value) { let assume_intrinsic = bx.cx.get_intrinsic("llvm.assume"); bx.call(assume_intrinsic, &[val], None); } -pub fn from_immediate(bx: &Builder, val: ValueRef) -> ValueRef { +pub fn from_immediate(bx: &Builder<'_, 'll, '_>, val: &'ll Value) -> &'ll Value { if val_ty(val) == Type::i1(bx.cx) { bx.zext(val, Type::i8(bx.cx)) } else { @@ -392,26 +395,36 @@ pub fn from_immediate(bx: &Builder, val: ValueRef) -> ValueRef { } } -pub fn to_immediate(bx: &Builder, val: ValueRef, layout: layout::TyLayout) -> ValueRef { +pub fn to_immediate( + bx: &Builder<'_, 'll, '_>, + val: &'ll Value, + layout: layout::TyLayout, +) -> &'ll Value { if let layout::Abi::Scalar(ref scalar) = layout.abi { return to_immediate_scalar(bx, val, scalar); } val } -pub fn to_immediate_scalar(bx: &Builder, val: ValueRef, scalar: &layout::Scalar) -> ValueRef { +pub fn to_immediate_scalar( + bx: &Builder<'_, 'll, '_>, + val: &'ll Value, + scalar: &layout::Scalar, +) -> &'ll Value { if scalar.is_bool() { return bx.trunc(val, Type::i1(bx.cx)); } val } -pub fn call_memcpy(bx: &Builder, - dst: ValueRef, - src: ValueRef, - n_bytes: ValueRef, - align: Align, - flags: MemFlags) { +pub fn call_memcpy( + bx: &Builder<'_, 'll, '_>, + dst: &'ll Value, + src: &'ll Value, + n_bytes: &'ll Value, + align: Align, + flags: MemFlags, +) { if flags.contains(MemFlags::NONTEMPORAL) { // HACK(nox): This is inefficient but there is no nontemporal memcpy. let val = bx.load(src, align); @@ -431,10 +444,10 @@ pub fn call_memcpy(bx: &Builder, bx.call(memcpy, &[dst_ptr, src_ptr, size, align, volatile], None); } -pub fn memcpy_ty<'a, 'tcx>( - bx: &Builder<'a, 'tcx>, - dst: ValueRef, - src: ValueRef, +pub fn memcpy_ty( + bx: &Builder<'_, 'll, 'tcx>, + dst: &'ll Value, + src: &'ll Value, layout: TyLayout<'tcx>, align: Align, flags: MemFlags, @@ -447,12 +460,14 @@ pub fn memcpy_ty<'a, 'tcx>( call_memcpy(bx, dst, src, C_usize(bx.cx, size), align, flags); } -pub fn call_memset<'a, 'tcx>(bx: &Builder<'a, 'tcx>, - ptr: ValueRef, - fill_byte: ValueRef, - size: ValueRef, - align: ValueRef, - volatile: bool) -> ValueRef { +pub fn call_memset( + bx: &Builder<'_, 'll, '_>, + ptr: &'ll Value, + fill_byte: &'ll Value, + size: &'ll Value, + align: &'ll Value, + volatile: bool, +) -> &'ll Value { let ptr_width = &bx.cx.sess().target.target.target_pointer_width; let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width); let llintrinsicfn = bx.cx.get_intrinsic(&intrinsic_key); @@ -511,7 +526,7 @@ pub fn codegen_instance<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, instance: Instance<' mir::codegen_mir(cx, lldecl, &mir, instance, sig); } -pub fn set_link_section(llval: ValueRef, attrs: &CodegenFnAttrs) { +pub fn set_link_section(llval: &Value, attrs: &CodegenFnAttrs) { let sect = match attrs.link_section { Some(name) => name, None => return, @@ -549,12 +564,14 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) { None => {} // Do nothing. } - fn create_entry_fn<'cx>(cx: &'cx CodegenCx, - sp: Span, - rust_main: ValueRef, - rust_main_def_id: DefId, - use_start_lang_item: bool) { - let llfty = Type::func(&[Type::c_int(cx), Type::i8p(cx).ptr_to()], &Type::c_int(cx)); + fn create_entry_fn( + cx: &CodegenCx<'ll, '_>, + sp: Span, + rust_main: &'ll Value, + rust_main_def_id: DefId, + use_start_lang_item: bool, + ) { + let llfty = Type::func(&[Type::c_int(cx), Type::i8p(cx).ptr_to()], Type::c_int(cx)); let main_ret_ty = cx.tcx.fn_sig(rust_main_def_id).output(); // Given that `main()` has no arguments, @@ -609,16 +626,14 @@ fn maybe_create_entry_wrapper(cx: &CodegenCx) { } fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, - llmod_id: &str, + llvm_module: &ModuleLlvm, link_meta: &LinkMeta) - -> (ContextRef, ModuleRef, EncodedMetadata) { + -> EncodedMetadata { use std::io::Write; use flate2::Compression; use flate2::write::DeflateEncoder; - let (metadata_llcx, metadata_llmod) = unsafe { - context::create_context_and_module(tcx.sess, llmod_id) - }; + let (metadata_llcx, metadata_llmod) = (&*llvm_module.llcx, llvm_module.llmod()); #[derive(PartialEq, Eq, PartialOrd, Ord)] enum MetadataKind { @@ -641,14 +656,12 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, }).max().unwrap_or(MetadataKind::None); if kind == MetadataKind::None { - return (metadata_llcx, - metadata_llmod, - EncodedMetadata::new()); + return EncodedMetadata::new(); } let metadata = tcx.encode_metadata(link_meta); if kind == MetadataKind::Uncompressed { - return (metadata_llcx, metadata_llmod, metadata); + return metadata; } assert!(kind == MetadataKind::Compressed); @@ -661,7 +674,7 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, let name = exported_symbols::metadata_symbol_name(tcx); let buf = CString::new(name).unwrap(); let llglobal = unsafe { - llvm::LLVMAddGlobal(metadata_llmod, val_ty(llconst).to_ref(), buf.as_ptr()) + llvm::LLVMAddGlobal(metadata_llmod, val_ty(llconst), buf.as_ptr()) }; unsafe { llvm::LLVMSetInitializer(llglobal, llconst); @@ -676,29 +689,27 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, let directive = CString::new(directive).unwrap(); llvm::LLVMSetModuleInlineAsm(metadata_llmod, directive.as_ptr()) } - return (metadata_llcx, metadata_llmod, metadata); + return metadata; } -pub struct ValueIter { - cur: ValueRef, - step: unsafe extern "C" fn(ValueRef) -> ValueRef, +pub struct ValueIter<'ll> { + cur: Option<&'ll Value>, + step: unsafe extern "C" fn(&'ll Value) -> Option<&'ll Value>, } -impl Iterator for ValueIter { - type Item = ValueRef; +impl Iterator for ValueIter<'ll> { + type Item = &'ll Value; - fn next(&mut self) -> Option { + fn next(&mut self) -> Option<&'ll Value> { let old = self.cur; - if !old.is_null() { + if let Some(old) = old { self.cur = unsafe { (self.step)(old) }; - Some(old) - } else { - None } + old } } -pub fn iter_globals(llmod: llvm::ModuleRef) -> ValueIter { +pub fn iter_globals(llmod: &'ll llvm::Module) -> ValueIter<'ll> { unsafe { ValueIter { cur: llvm::LLVMGetFirstGlobal(llmod), @@ -731,19 +742,15 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Codegen the metadata. let llmod_id = "metadata"; - let (metadata_llcx, metadata_llmod, metadata) = - time(tcx.sess, "write metadata", || { - write_metadata(tcx, llmod_id, &link_meta) - }); + let metadata_llvm_module = ModuleLlvm::new(tcx.sess, llmod_id); + let metadata = time(tcx.sess, "write metadata", || { + write_metadata(tcx, &metadata_llvm_module, &link_meta) + }); let metadata_module = ModuleCodegen { name: link::METADATA_MODULE_NAME.to_string(), llmod_id: llmod_id.to_string(), - source: ModuleSource::Codegened(ModuleLlvm { - llcx: metadata_llcx, - llmod: metadata_llmod, - tm: create_target_machine(tcx.sess, false), - }), + source: ModuleSource::Codegened(metadata_llvm_module), kind: ModuleKind::Metadata, }; @@ -803,13 +810,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let allocator_module = if let Some(kind) = *tcx.sess.allocator_kind.get() { unsafe { let llmod_id = "allocator"; - let (llcx, llmod) = - context::create_context_and_module(tcx.sess, llmod_id); - let modules = ModuleLlvm { - llmod, - llcx, - tm: create_target_machine(tcx.sess, false), - }; + let modules = ModuleLlvm::new(tcx.sess, llmod_id); time(tcx.sess, "write allocator module", || { allocator::codegen(tcx, &modules, kind) }); @@ -1200,8 +1201,9 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .to_fingerprint().to_hex()); // Instantiate monomorphizations without filling out definitions yet... - let cx = CodegenCx::new(tcx, cgu, &llmod_id); - let module = { + let llvm_module = ModuleLlvm::new(tcx.sess, &llmod_id); + let stats = { + let cx = CodegenCx::new(tcx, cgu, &llvm_module); let mono_items = cx.codegen_unit .items_in_deterministic_order(cx.tcx); for &(mono_item, (linkage, visibility)) in &mono_items { @@ -1220,7 +1222,7 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Run replace-all-uses-with for statics that need it for &(old_g, new_g) in cx.statics_to_rauw.borrow().iter() { unsafe { - let bitcast = llvm::LLVMConstPointerCast(new_g, llvm::LLVMTypeOf(old_g)); + let bitcast = llvm::LLVMConstPointerCast(new_g, val_ty(old_g)); llvm::LLVMReplaceAllUsesWith(old_g, bitcast); llvm::LLVMDeleteGlobal(old_g); } @@ -1235,7 +1237,7 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, unsafe { let g = llvm::LLVMAddGlobal(cx.llmod, - val_ty(array).to_ref(), + val_ty(array), name.as_ptr()); llvm::LLVMSetInitializer(g, array); llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage); @@ -1248,21 +1250,15 @@ fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debuginfo::finalize(&cx); } - let llvm_module = ModuleLlvm { - llcx: cx.llcx, - llmod: cx.llmod, - tm: create_target_machine(cx.sess(), false), - }; - - ModuleCodegen { - name: cgu_name, - source: ModuleSource::Codegened(llvm_module), - kind: ModuleKind::Regular, - llmod_id, - } + cx.stats.into_inner() }; - (cx.into_stats(), module) + (stats, ModuleCodegen { + name: cgu_name, + source: ModuleSource::Codegened(llvm_module), + kind: ModuleKind::Regular, + llmod_id, + }) } } diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index b34d0f1cd9070..b174cd8c7ac76 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -8,12 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(dead_code)] // FFI wrappers - -use llvm; use llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect}; -use llvm::{Opcode, IntPredicate, RealPredicate, False, OperandBundleDef}; -use llvm::{ValueRef, BasicBlockRef, BuilderRef}; +use llvm::{IntPredicate, RealPredicate, False, OperandBundleDef}; +use llvm::{self, BasicBlock}; use common::*; use type_::Type; use value::Value; @@ -26,19 +23,18 @@ use std::borrow::Cow; use std::ffi::CString; use std::ops::Range; use std::ptr; -use syntax_pos::Span; // All Builders must have an llfn associated with them #[must_use] -pub struct Builder<'a, 'tcx: 'a> { - pub llbuilder: BuilderRef, - pub cx: &'a CodegenCx<'a, 'tcx>, +pub struct Builder<'a, 'll: 'a, 'tcx: 'll> { + pub llbuilder: &'ll mut llvm::Builder<'ll>, + pub cx: &'a CodegenCx<'ll, 'tcx>, } -impl<'a, 'tcx> Drop for Builder<'a, 'tcx> { +impl Drop for Builder<'a, 'll, 'tcx> { fn drop(&mut self) { unsafe { - llvm::LLVMDisposeBuilder(self.llbuilder); + llvm::LLVMDisposeBuilder(&mut *(self.llbuilder as *mut _)); } } } @@ -58,8 +54,8 @@ bitflags! { } } -impl<'a, 'tcx> Builder<'a, 'tcx> { - pub fn new_block<'b>(cx: &'a CodegenCx<'a, 'tcx>, llfn: ValueRef, name: &'b str) -> Self { +impl Builder<'a, 'll, 'tcx> { + pub fn new_block<'b>(cx: &'a CodegenCx<'ll, 'tcx>, llfn: &'ll Value, name: &'b str) -> Self { let bx = Builder::with_cx(cx); let llbb = unsafe { let name = CString::new(name).unwrap(); @@ -73,7 +69,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { bx } - pub fn with_cx(cx: &'a CodegenCx<'a, 'tcx>) -> Self { + pub fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self { // Create a fresh builder from the crate context. let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(cx.llcx) @@ -84,7 +80,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn build_sibling_block<'b>(&self, name: &'b str) -> Builder<'a, 'tcx> { + pub fn build_sibling_block<'b>(&self, name: &'b str) -> Builder<'a, 'll, 'tcx> { Builder::new_block(self.cx, self.llfn(), name) } @@ -96,13 +92,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cx.tcx } - pub fn llfn(&self) -> ValueRef { + pub fn llfn(&self) -> &'ll Value { unsafe { llvm::LLVMGetBasicBlockParent(self.llbb()) } } - pub fn llbb(&self) -> BasicBlockRef { + pub fn llbb(&self) -> &'ll BasicBlock { unsafe { llvm::LLVMGetInsertBlock(self.llbuilder) } @@ -121,26 +117,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn set_value_name(&self, value: ValueRef, name: &str) { + pub fn set_value_name(&self, value: &'ll Value, name: &str) { let cname = CString::new(name.as_bytes()).unwrap(); unsafe { llvm::LLVMSetValueName(value, cname.as_ptr()); } } - pub fn position_before(&self, insn: ValueRef) { - unsafe { - llvm::LLVMPositionBuilderBefore(self.llbuilder, insn); - } - } - - pub fn position_at_end(&self, llbb: BasicBlockRef) { + pub fn position_at_end(&self, llbb: &'ll BasicBlock) { unsafe { llvm::LLVMPositionBuilderAtEnd(self.llbuilder, llbb); } } - pub fn position_at_start(&self, llbb: BasicBlockRef) { + pub fn position_at_start(&self, llbb: &'ll BasicBlock) { unsafe { llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb); } @@ -153,65 +143,57 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn ret(&self, v: ValueRef) { + pub fn ret(&self, v: &'ll Value) { self.count_insn("ret"); unsafe { llvm::LLVMBuildRet(self.llbuilder, v); } } - pub fn aggregate_ret(&self, ret_vals: &[ValueRef]) { - unsafe { - llvm::LLVMBuildAggregateRet(self.llbuilder, - ret_vals.as_ptr(), - ret_vals.len() as c_uint); - } - } - - pub fn br(&self, dest: BasicBlockRef) { + pub fn br(&self, dest: &'ll BasicBlock) { self.count_insn("br"); unsafe { llvm::LLVMBuildBr(self.llbuilder, dest); } } - pub fn cond_br(&self, cond: ValueRef, then_llbb: BasicBlockRef, else_llbb: BasicBlockRef) { + pub fn cond_br( + &self, + cond: &'ll Value, + then_llbb: &'ll BasicBlock, + else_llbb: &'ll BasicBlock, + ) { self.count_insn("condbr"); unsafe { llvm::LLVMBuildCondBr(self.llbuilder, cond, then_llbb, else_llbb); } } - pub fn switch(&self, v: ValueRef, else_llbb: BasicBlockRef, num_cases: usize) -> ValueRef { + pub fn switch( + &self, + v: &'ll Value, + else_llbb: &'ll BasicBlock, + num_cases: usize, + ) -> &'ll Value { unsafe { llvm::LLVMBuildSwitch(self.llbuilder, v, else_llbb, num_cases as c_uint) } } - pub fn indirect_br(&self, addr: ValueRef, num_dests: usize) { - self.count_insn("indirectbr"); - unsafe { - llvm::LLVMBuildIndirectBr(self.llbuilder, addr, num_dests as c_uint); - } - } - pub fn invoke(&self, - llfn: ValueRef, - args: &[ValueRef], - then: BasicBlockRef, - catch: BasicBlockRef, - bundle: Option<&OperandBundleDef>) -> ValueRef { + llfn: &'ll Value, + args: &[&'ll Value], + then: &'ll BasicBlock, + catch: &'ll BasicBlock, + bundle: Option<&OperandBundleDef<'ll>>) -> &'ll Value { self.count_insn("invoke"); - debug!("Invoke {:?} with args ({})", - Value(llfn), - args.iter() - .map(|&v| format!("{:?}", Value(v))) - .collect::>() - .join(", ")); + debug!("Invoke {:?} with args ({:?})", + llfn, + args); let args = self.check_call("invoke", llfn, args); - let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut()); + let bundle = bundle.map(|b| &*b.raw); unsafe { llvm::LLVMRustBuildInvoke(self.llbuilder, @@ -233,35 +215,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } /* Arithmetic */ - pub fn add(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn add(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("add"); unsafe { llvm::LLVMBuildAdd(self.llbuilder, lhs, rhs, noname()) } } - pub fn nswadd(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - self.count_insn("nswadd"); - unsafe { - llvm::LLVMBuildNSWAdd(self.llbuilder, lhs, rhs, noname()) - } - } - - pub fn nuwadd(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - self.count_insn("nuwadd"); - unsafe { - llvm::LLVMBuildNUWAdd(self.llbuilder, lhs, rhs, noname()) - } - } - - pub fn fadd(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn fadd(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("fadd"); unsafe { llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname()) } } - pub fn fadd_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn fadd_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("fadd"); unsafe { let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname()); @@ -270,35 +238,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn sub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn sub(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("sub"); unsafe { llvm::LLVMBuildSub(self.llbuilder, lhs, rhs, noname()) } } - pub fn nswsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - self.count_insn("nswsub"); - unsafe { - llvm::LLVMBuildNSWSub(self.llbuilder, lhs, rhs, noname()) - } - } - - pub fn nuwsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - self.count_insn("nuwsub"); - unsafe { - llvm::LLVMBuildNUWSub(self.llbuilder, lhs, rhs, noname()) - } - } - - pub fn fsub(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn fsub(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("fsub"); unsafe { llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname()) } } - pub fn fsub_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn fsub_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("fsub"); unsafe { let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname()); @@ -307,35 +261,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn mul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn mul(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("mul"); unsafe { llvm::LLVMBuildMul(self.llbuilder, lhs, rhs, noname()) } } - pub fn nswmul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - self.count_insn("nswmul"); - unsafe { - llvm::LLVMBuildNSWMul(self.llbuilder, lhs, rhs, noname()) - } - } - - pub fn nuwmul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - self.count_insn("nuwmul"); - unsafe { - llvm::LLVMBuildNUWMul(self.llbuilder, lhs, rhs, noname()) - } - } - - pub fn fmul(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn fmul(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("fmul"); unsafe { llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname()) } } - pub fn fmul_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn fmul_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("fmul"); unsafe { let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname()); @@ -345,42 +285,42 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } - pub fn udiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn udiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("udiv"); unsafe { llvm::LLVMBuildUDiv(self.llbuilder, lhs, rhs, noname()) } } - pub fn exactudiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn exactudiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("exactudiv"); unsafe { llvm::LLVMBuildExactUDiv(self.llbuilder, lhs, rhs, noname()) } } - pub fn sdiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn sdiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("sdiv"); unsafe { llvm::LLVMBuildSDiv(self.llbuilder, lhs, rhs, noname()) } } - pub fn exactsdiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn exactsdiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("exactsdiv"); unsafe { llvm::LLVMBuildExactSDiv(self.llbuilder, lhs, rhs, noname()) } } - pub fn fdiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn fdiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("fdiv"); unsafe { llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname()) } } - pub fn fdiv_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn fdiv_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("fdiv"); unsafe { let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname()); @@ -389,28 +329,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn urem(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn urem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("urem"); unsafe { llvm::LLVMBuildURem(self.llbuilder, lhs, rhs, noname()) } } - pub fn srem(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn srem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("srem"); unsafe { llvm::LLVMBuildSRem(self.llbuilder, lhs, rhs, noname()) } } - pub fn frem(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn frem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("frem"); unsafe { llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname()) } } - pub fn frem_fast(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn frem_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("frem"); unsafe { let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname()); @@ -419,91 +359,70 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn shl(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn shl(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("shl"); unsafe { llvm::LLVMBuildShl(self.llbuilder, lhs, rhs, noname()) } } - pub fn lshr(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn lshr(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("lshr"); unsafe { llvm::LLVMBuildLShr(self.llbuilder, lhs, rhs, noname()) } } - pub fn ashr(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn ashr(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("ashr"); unsafe { llvm::LLVMBuildAShr(self.llbuilder, lhs, rhs, noname()) } } - pub fn and(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn and(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("and"); unsafe { llvm::LLVMBuildAnd(self.llbuilder, lhs, rhs, noname()) } } - pub fn or(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn or(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("or"); unsafe { llvm::LLVMBuildOr(self.llbuilder, lhs, rhs, noname()) } } - pub fn xor(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn xor(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("xor"); unsafe { llvm::LLVMBuildXor(self.llbuilder, lhs, rhs, noname()) } } - pub fn binop(&self, op: Opcode, lhs: ValueRef, rhs: ValueRef) - -> ValueRef { - self.count_insn("binop"); - unsafe { - llvm::LLVMBuildBinOp(self.llbuilder, op, lhs, rhs, noname()) - } - } - - pub fn neg(&self, v: ValueRef) -> ValueRef { + pub fn neg(&self, v: &'ll Value) -> &'ll Value { self.count_insn("neg"); unsafe { llvm::LLVMBuildNeg(self.llbuilder, v, noname()) } } - pub fn nswneg(&self, v: ValueRef) -> ValueRef { - self.count_insn("nswneg"); - unsafe { - llvm::LLVMBuildNSWNeg(self.llbuilder, v, noname()) - } - } - - pub fn nuwneg(&self, v: ValueRef) -> ValueRef { - self.count_insn("nuwneg"); - unsafe { - llvm::LLVMBuildNUWNeg(self.llbuilder, v, noname()) - } - } - pub fn fneg(&self, v: ValueRef) -> ValueRef { + pub fn fneg(&self, v: &'ll Value) -> &'ll Value { self.count_insn("fneg"); unsafe { llvm::LLVMBuildFNeg(self.llbuilder, v, noname()) } } - pub fn not(&self, v: ValueRef) -> ValueRef { + pub fn not(&self, v: &'ll Value) -> &'ll Value { self.count_insn("not"); unsafe { llvm::LLVMBuildNot(self.llbuilder, v, noname()) } } - pub fn alloca(&self, ty: Type, name: &str, align: Align) -> ValueRef { + pub fn alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { let bx = Builder::with_cx(self.cx); bx.position_at_start(unsafe { llvm::LLVMGetFirstBasicBlock(self.llfn()) @@ -511,14 +430,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { bx.dynamic_alloca(ty, name, align) } - pub fn dynamic_alloca(&self, ty: Type, name: &str, align: Align) -> ValueRef { + pub fn dynamic_alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { self.count_insn("alloca"); unsafe { let alloca = if name.is_empty() { - llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), noname()) + llvm::LLVMBuildAlloca(self.llbuilder, ty, noname()) } else { let name = CString::new(name).unwrap(); - llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), + llvm::LLVMBuildAlloca(self.llbuilder, ty, name.as_ptr()) }; llvm::LLVMSetAlignment(alloca, align.abi() as c_uint); @@ -526,14 +445,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn free(&self, ptr: ValueRef) { - self.count_insn("free"); - unsafe { - llvm::LLVMBuildFree(self.llbuilder, ptr); - } - } - - pub fn load(&self, ptr: ValueRef, align: Align) -> ValueRef { + pub fn load(&self, ptr: &'ll Value, align: Align) -> &'ll Value { self.count_insn("load"); unsafe { let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname()); @@ -542,7 +454,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn volatile_load(&self, ptr: ValueRef) -> ValueRef { + pub fn volatile_load(&self, ptr: &'ll Value) -> &'ll Value { self.count_insn("load.volatile"); unsafe { let insn = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname()); @@ -551,7 +463,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn atomic_load(&self, ptr: ValueRef, order: AtomicOrdering, align: Align) -> ValueRef { + pub fn atomic_load(&self, ptr: &'ll Value, order: AtomicOrdering, align: Align) -> &'ll Value { self.count_insn("load.atomic"); unsafe { let load = llvm::LLVMRustBuildAtomicLoad(self.llbuilder, ptr, noname(), order); @@ -564,7 +476,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } - pub fn range_metadata(&self, load: ValueRef, range: Range) { + pub fn range_metadata(&self, load: &'ll Value, range: Range) { unsafe { let llty = val_ty(load); let v = [ @@ -579,26 +491,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn nonnull_metadata(&self, load: ValueRef) { + pub fn nonnull_metadata(&self, load: &'ll Value) { unsafe { llvm::LLVMSetMetadata(load, llvm::MD_nonnull as c_uint, llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0)); } } - pub fn store(&self, val: ValueRef, ptr: ValueRef, align: Align) -> ValueRef { + pub fn store(&self, val: &'ll Value, ptr: &'ll Value, align: Align) -> &'ll Value { self.store_with_flags(val, ptr, align, MemFlags::empty()) } pub fn store_with_flags( &self, - val: ValueRef, - ptr: ValueRef, + val: &'ll Value, + ptr: &'ll Value, align: Align, flags: MemFlags, - ) -> ValueRef { - debug!("Store {:?} -> {:?} ({:?})", Value(val), Value(ptr), flags); - assert!(!self.llbuilder.is_null()); + ) -> &'ll Value { + debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags); self.count_insn("store"); let ptr = self.check_store(val, ptr); unsafe { @@ -625,9 +536,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn atomic_store(&self, val: ValueRef, ptr: ValueRef, + pub fn atomic_store(&self, val: &'ll Value, ptr: &'ll Value, order: AtomicOrdering, align: Align) { - debug!("Store {:?} -> {:?}", Value(val), Value(ptr)); + debug!("Store {:?} -> {:?}", val, ptr); self.count_insn("store.atomic"); let ptr = self.check_store(val, ptr); unsafe { @@ -638,7 +549,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn gep(&self, ptr: ValueRef, indices: &[ValueRef]) -> ValueRef { + pub fn gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value { self.count_insn("gep"); unsafe { llvm::LLVMBuildGEP(self.llbuilder, ptr, indices.as_ptr(), @@ -646,7 +557,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn inbounds_gep(&self, ptr: ValueRef, indices: &[ValueRef]) -> ValueRef { + pub fn inbounds_gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value { self.count_insn("inboundsgep"); unsafe { llvm::LLVMBuildInBoundsGEP( @@ -654,7 +565,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn struct_gep(&self, ptr: ValueRef, idx: u64) -> ValueRef { + pub fn struct_gep(&self, ptr: &'ll Value, idx: u64) -> &'ll Value { self.count_insn("structgep"); assert_eq!(idx as c_uint as u64, idx); unsafe { @@ -662,164 +573,114 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn global_string(&self, _str: *const c_char) -> ValueRef { - self.count_insn("globalstring"); - unsafe { - llvm::LLVMBuildGlobalString(self.llbuilder, _str, noname()) - } - } - - pub fn global_string_ptr(&self, _str: *const c_char) -> ValueRef { - self.count_insn("globalstringptr"); - unsafe { - llvm::LLVMBuildGlobalStringPtr(self.llbuilder, _str, noname()) - } - } - /* Casts */ - pub fn trunc(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn trunc(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("trunc"); unsafe { - llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, noname()) } } - pub fn zext(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn zext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("zext"); unsafe { - llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, noname()) } } - pub fn sext(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn sext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("sext"); unsafe { - llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, noname()) } } - pub fn fptoui(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn fptoui(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("fptoui"); unsafe { - llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, noname()) } } - pub fn fptosi(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn fptosi(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("fptosi"); unsafe { - llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty.to_ref(),noname()) + llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty,noname()) } } - pub fn uitofp(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn uitofp(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("uitofp"); unsafe { - llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, noname()) } } - pub fn sitofp(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn sitofp(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("sitofp"); unsafe { - llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, noname()) } } - pub fn fptrunc(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn fptrunc(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("fptrunc"); unsafe { - llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, noname()) } } - pub fn fpext(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn fpext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("fpext"); unsafe { - llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, noname()) } } - pub fn ptrtoint(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn ptrtoint(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("ptrtoint"); unsafe { - llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, noname()) } } - pub fn inttoptr(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn inttoptr(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("inttoptr"); unsafe { - llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, noname()) } } - pub fn bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn bitcast(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("bitcast"); unsafe { - llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty.to_ref(), noname()) - } - } - - pub fn zext_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef { - self.count_insn("zextorbitcast"); - unsafe { - llvm::LLVMBuildZExtOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, noname()) } } - pub fn sext_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef { - self.count_insn("sextorbitcast"); - unsafe { - llvm::LLVMBuildSExtOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname()) - } - } - - pub fn trunc_or_bitcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef { - self.count_insn("truncorbitcast"); - unsafe { - llvm::LLVMBuildTruncOrBitCast(self.llbuilder, val, dest_ty.to_ref(), noname()) - } - } - - pub fn cast(&self, op: Opcode, val: ValueRef, dest_ty: Type) -> ValueRef { - self.count_insn("cast"); - unsafe { - llvm::LLVMBuildCast(self.llbuilder, op, val, dest_ty.to_ref(), noname()) - } - } - - pub fn pointercast(&self, val: ValueRef, dest_ty: Type) -> ValueRef { + pub fn pointercast(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("pointercast"); unsafe { - llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, noname()) } } - pub fn intcast(&self, val: ValueRef, dest_ty: Type, is_signed: bool) -> ValueRef { + pub fn intcast(&self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value { self.count_insn("intcast"); unsafe { - llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty.to_ref(), is_signed) - } - } - - pub fn fpcast(&self, val: ValueRef, dest_ty: Type) -> ValueRef { - self.count_insn("fpcast"); - unsafe { - llvm::LLVMBuildFPCast(self.llbuilder, val, dest_ty.to_ref(), noname()) + llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty, is_signed) } } - /* Comparisons */ - pub fn icmp(&self, op: IntPredicate, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn icmp(&self, op: IntPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("icmp"); unsafe { llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, noname()) } } - pub fn fcmp(&self, op: RealPredicate, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn fcmp(&self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("fcmp"); unsafe { llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, noname()) @@ -827,14 +688,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } /* Miscellaneous instructions */ - pub fn empty_phi(&self, ty: Type) -> ValueRef { + pub fn empty_phi(&self, ty: &'ll Type) -> &'ll Value { self.count_insn("emptyphi"); unsafe { - llvm::LLVMBuildPhi(self.llbuilder, ty.to_ref(), noname()) + llvm::LLVMBuildPhi(self.llbuilder, ty, noname()) } } - pub fn phi(&self, ty: Type, vals: &[ValueRef], bbs: &[BasicBlockRef]) -> ValueRef { + pub fn phi(&self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value { assert_eq!(vals.len(), bbs.len()); let phi = self.empty_phi(ty); self.count_insn("addincoming"); @@ -846,36 +707,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn add_span_comment(&self, sp: Span, text: &str) { - if self.cx.sess().asm_comments() { - let s = format!("{} ({})", - text, - self.cx.sess().codemap().span_to_string(sp)); - debug!("{}", s); - self.add_comment(&s); - } - } - - pub fn add_comment(&self, text: &str) { - if self.cx.sess().asm_comments() { - let sanitized = text.replace("$", ""); - let comment_text = format!("{} {}", "#", - sanitized.replace("\n", "\n\t# ")); - self.count_insn("inlineasm"); - let comment_text = CString::new(comment_text).unwrap(); - let asm = unsafe { - llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.cx)).to_ref(), - comment_text.as_ptr(), noname(), False, - False) - }; - self.call(asm, &[], None); - } - } - pub fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char, - inputs: &[ValueRef], output: Type, + inputs: &[&'ll Value], output: &'ll Type, volatile: bool, alignstack: bool, - dia: AsmDialect) -> ValueRef { + dia: AsmDialect) -> &'ll Value { self.count_insn("inlineasm"); let volatile = if volatile { llvm::True } @@ -884,32 +719,29 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { else { llvm::False }; let argtys = inputs.iter().map(|v| { - debug!("Asm Input Type: {:?}", Value(*v)); + debug!("Asm Input Type: {:?}", *v); val_ty(*v) }).collect::>(); debug!("Asm Output Type: {:?}", output); - let fty = Type::func(&argtys[..], &output); + let fty = Type::func(&argtys[..], output); unsafe { let v = llvm::LLVMRustInlineAsm( - fty.to_ref(), asm, cons, volatile, alignstack, dia); + fty, asm, cons, volatile, alignstack, dia); self.call(v, inputs, None) } } - pub fn call(&self, llfn: ValueRef, args: &[ValueRef], - bundle: Option<&OperandBundleDef>) -> ValueRef { + pub fn call(&self, llfn: &'ll Value, args: &[&'ll Value], + bundle: Option<&OperandBundleDef<'ll>>) -> &'ll Value { self.count_insn("call"); - debug!("Call {:?} with args ({})", - Value(llfn), - args.iter() - .map(|&v| format!("{:?}", Value(v))) - .collect::>() - .join(", ")); + debug!("Call {:?} with args ({:?})", + llfn, + args); let args = self.check_call("call", llfn, args); - let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut()); + let bundle = bundle.map(|b| &*b.raw); unsafe { llvm::LLVMRustBuildCall(self.llbuilder, llfn, args.as_ptr(), @@ -917,214 +749,182 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn minnum(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn minnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("minnum"); unsafe { let instr = llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs); - if instr.is_null() { - bug!("LLVMRustBuildMinNum is not available in LLVM version < 6.0"); - } - instr + instr.expect("LLVMRustBuildMinNum is not available in LLVM version < 6.0") } } - pub fn maxnum(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { + pub fn maxnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("maxnum"); unsafe { let instr = llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs); - if instr.is_null() { - bug!("LLVMRustBuildMaxNum is not available in LLVM version < 6.0"); - } - instr + instr.expect("LLVMRustBuildMaxNum is not available in LLVM version < 6.0") } } - pub fn select(&self, cond: ValueRef, then_val: ValueRef, else_val: ValueRef) -> ValueRef { + pub fn select( + &self, cond: &'ll Value, + then_val: &'ll Value, + else_val: &'ll Value, + ) -> &'ll Value { self.count_insn("select"); unsafe { llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, noname()) } } - pub fn va_arg(&self, list: ValueRef, ty: Type) -> ValueRef { + #[allow(dead_code)] + pub fn va_arg(&self, list: &'ll Value, ty: &'ll Type) -> &'ll Value { self.count_insn("vaarg"); unsafe { - llvm::LLVMBuildVAArg(self.llbuilder, list, ty.to_ref(), noname()) + llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname()) } } - pub fn extract_element(&self, vec: ValueRef, idx: ValueRef) -> ValueRef { + pub fn extract_element(&self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value { self.count_insn("extractelement"); unsafe { llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, noname()) } } - pub fn insert_element(&self, vec: ValueRef, elt: ValueRef, idx: ValueRef) -> ValueRef { + pub fn insert_element( + &self, vec: &'ll Value, + elt: &'ll Value, + idx: &'ll Value, + ) -> &'ll Value { self.count_insn("insertelement"); unsafe { llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname()) } } - pub fn shuffle_vector(&self, v1: ValueRef, v2: ValueRef, mask: ValueRef) -> ValueRef { + pub fn shuffle_vector(&self, v1: &'ll Value, v2: &'ll Value, mask: &'ll Value) -> &'ll Value { self.count_insn("shufflevector"); unsafe { llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname()) } } - pub fn vector_splat(&self, num_elts: usize, elt: ValueRef) -> ValueRef { + pub fn vector_splat(&self, num_elts: usize, elt: &'ll Value) -> &'ll Value { unsafe { let elt_ty = val_ty(elt); - let undef = llvm::LLVMGetUndef(Type::vector(&elt_ty, num_elts as u64).to_ref()); + let undef = llvm::LLVMGetUndef(Type::vector(elt_ty, num_elts as u64)); let vec = self.insert_element(undef, elt, C_i32(self.cx, 0)); - let vec_i32_ty = Type::vector(&Type::i32(self.cx), num_elts as u64); + let vec_i32_ty = Type::vector(Type::i32(self.cx), num_elts as u64); self.shuffle_vector(vec, undef, C_null(vec_i32_ty)) } } - pub fn vector_reduce_fadd_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef { + pub fn vector_reduce_fadd_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.fadd_fast"); unsafe { // FIXME: add a non-fast math version once // https://bugs.llvm.org/show_bug.cgi?id=36732 // is fixed. - let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceFAdd is not available in LLVM version < 5.0"); - } + let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src) + .expect("LLVMRustBuildVectorReduceFAdd is not available in LLVM version < 5.0"); llvm::LLVMRustSetHasUnsafeAlgebra(instr); instr } } - pub fn vector_reduce_fmul_fast(&self, acc: ValueRef, src: ValueRef) -> ValueRef { + pub fn vector_reduce_fmul_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.fmul_fast"); unsafe { // FIXME: add a non-fast math version once // https://bugs.llvm.org/show_bug.cgi?id=36732 // is fixed. - let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceFMul is not available in LLVM version < 5.0"); - } + let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src) + .expect("LLVMRustBuildVectorReduceFMul is not available in LLVM version < 5.0"); llvm::LLVMRustSetHasUnsafeAlgebra(instr); instr } } - pub fn vector_reduce_add(&self, src: ValueRef) -> ValueRef { + pub fn vector_reduce_add(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.add"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceAdd is not available in LLVM version < 5.0"); - } - instr + instr.expect("LLVMRustBuildVectorReduceAdd is not available in LLVM version < 5.0") } } - pub fn vector_reduce_mul(&self, src: ValueRef) -> ValueRef { + pub fn vector_reduce_mul(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.mul"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceMul is not available in LLVM version < 5.0"); - } - instr + instr.expect("LLVMRustBuildVectorReduceMul is not available in LLVM version < 5.0") } } - pub fn vector_reduce_and(&self, src: ValueRef) -> ValueRef { + pub fn vector_reduce_and(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.and"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceAnd is not available in LLVM version < 5.0"); - } - instr + instr.expect("LLVMRustBuildVectorReduceAnd is not available in LLVM version < 5.0") } } - pub fn vector_reduce_or(&self, src: ValueRef) -> ValueRef { + pub fn vector_reduce_or(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.or"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceOr is not available in LLVM version < 5.0"); - } - instr + instr.expect("LLVMRustBuildVectorReduceOr is not available in LLVM version < 5.0") } } - pub fn vector_reduce_xor(&self, src: ValueRef) -> ValueRef { + pub fn vector_reduce_xor(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.xor"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceXor is not available in LLVM version < 5.0"); - } - instr + instr.expect("LLVMRustBuildVectorReduceXor is not available in LLVM version < 5.0") } } - pub fn vector_reduce_fmin(&self, src: ValueRef) -> ValueRef { + pub fn vector_reduce_fmin(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.fmin"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0"); - } - instr + instr.expect("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0") } } - pub fn vector_reduce_fmax(&self, src: ValueRef) -> ValueRef { + pub fn vector_reduce_fmax(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.fmax"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0"); - } - instr + instr.expect("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0") } } - pub fn vector_reduce_fmin_fast(&self, src: ValueRef) -> ValueRef { + pub fn vector_reduce_fmin_fast(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.fmin_fast"); unsafe { - let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0"); - } + let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true) + .expect("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0"); llvm::LLVMRustSetHasUnsafeAlgebra(instr); instr } } - pub fn vector_reduce_fmax_fast(&self, src: ValueRef) -> ValueRef { + pub fn vector_reduce_fmax_fast(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.fmax_fast"); unsafe { - let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0"); - } + let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true) + .expect("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0"); llvm::LLVMRustSetHasUnsafeAlgebra(instr); instr } } - pub fn vector_reduce_min(&self, src: ValueRef, is_signed: bool) -> ValueRef { + pub fn vector_reduce_min(&self, src: &'ll Value, is_signed: bool) -> &'ll Value { self.count_insn("vector.reduce.min"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceMin is not available in LLVM version < 5.0"); - } - instr + instr.expect("LLVMRustBuildVectorReduceMin is not available in LLVM version < 5.0") } } - pub fn vector_reduce_max(&self, src: ValueRef, is_signed: bool) -> ValueRef { + pub fn vector_reduce_max(&self, src: &'ll Value, is_signed: bool) -> &'ll Value { self.count_insn("vector.reduce.max"); unsafe { let instr = llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed); - if instr.is_null() { - bug!("LLVMRustBuildVectorReduceMax is not available in LLVM version < 5.0"); - } - instr + instr.expect("LLVMRustBuildVectorReduceMax is not available in LLVM version < 5.0") } } - pub fn extract_value(&self, agg_val: ValueRef, idx: u64) -> ValueRef { + pub fn extract_value(&self, agg_val: &'ll Value, idx: u64) -> &'ll Value { self.count_insn("extractvalue"); assert_eq!(idx as c_uint as u64, idx); unsafe { @@ -1132,8 +932,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn insert_value(&self, agg_val: ValueRef, elt: ValueRef, - idx: u64) -> ValueRef { + pub fn insert_value(&self, agg_val: &'ll Value, elt: &'ll Value, + idx: u64) -> &'ll Value { self.count_insn("insertvalue"); assert_eq!(idx as c_uint as u64, idx); unsafe { @@ -1142,50 +942,29 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn is_null(&self, val: ValueRef) -> ValueRef { - self.count_insn("isnull"); - unsafe { - llvm::LLVMBuildIsNull(self.llbuilder, val, noname()) - } - } - - pub fn is_not_null(&self, val: ValueRef) -> ValueRef { - self.count_insn("isnotnull"); - unsafe { - llvm::LLVMBuildIsNotNull(self.llbuilder, val, noname()) - } - } - - pub fn ptrdiff(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef { - self.count_insn("ptrdiff"); - unsafe { - llvm::LLVMBuildPtrDiff(self.llbuilder, lhs, rhs, noname()) - } - } - - pub fn landing_pad(&self, ty: Type, pers_fn: ValueRef, - num_clauses: usize) -> ValueRef { + pub fn landing_pad(&self, ty: &'ll Type, pers_fn: &'ll Value, + num_clauses: usize) -> &'ll Value { self.count_insn("landingpad"); unsafe { - llvm::LLVMBuildLandingPad(self.llbuilder, ty.to_ref(), pers_fn, + llvm::LLVMBuildLandingPad(self.llbuilder, ty, pers_fn, num_clauses as c_uint, noname()) } } - pub fn add_clause(&self, landing_pad: ValueRef, clause: ValueRef) { + pub fn add_clause(&self, landing_pad: &'ll Value, clause: &'ll Value) { unsafe { llvm::LLVMAddClause(landing_pad, clause); } } - pub fn set_cleanup(&self, landing_pad: ValueRef) { + pub fn set_cleanup(&self, landing_pad: &'ll Value) { self.count_insn("setcleanup"); unsafe { llvm::LLVMSetCleanup(landing_pad, llvm::True); } } - pub fn resume(&self, exn: ValueRef) -> ValueRef { + pub fn resume(&self, exn: &'ll Value) -> &'ll Value { self.count_insn("resume"); unsafe { llvm::LLVMBuildResume(self.llbuilder, exn) @@ -1193,10 +972,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } pub fn cleanup_pad(&self, - parent: Option, - args: &[ValueRef]) -> ValueRef { + parent: Option<&'ll Value>, + args: &[&'ll Value]) -> &'ll Value { self.count_insn("cleanuppad"); - let parent = parent.unwrap_or(ptr::null_mut()); let name = CString::new("cleanuppad").unwrap(); let ret = unsafe { llvm::LLVMRustBuildCleanupPad(self.llbuilder, @@ -1205,24 +983,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { args.as_ptr(), name.as_ptr()) }; - assert!(!ret.is_null(), "LLVM does not have support for cleanuppad"); - return ret + ret.expect("LLVM does not have support for cleanuppad") } - pub fn cleanup_ret(&self, cleanup: ValueRef, - unwind: Option) -> ValueRef { + pub fn cleanup_ret( + &self, cleanup: &'ll Value, + unwind: Option<&'ll BasicBlock>, + ) -> &'ll Value { self.count_insn("cleanupret"); - let unwind = unwind.unwrap_or(ptr::null_mut()); let ret = unsafe { llvm::LLVMRustBuildCleanupRet(self.llbuilder, cleanup, unwind) }; - assert!(!ret.is_null(), "LLVM does not have support for cleanupret"); - return ret + ret.expect("LLVM does not have support for cleanupret") } pub fn catch_pad(&self, - parent: ValueRef, - args: &[ValueRef]) -> ValueRef { + parent: &'ll Value, + args: &[&'ll Value]) -> &'ll Value { self.count_insn("catchpad"); let name = CString::new("catchpad").unwrap(); let ret = unsafe { @@ -1230,62 +1007,67 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { args.len() as c_uint, args.as_ptr(), name.as_ptr()) }; - assert!(!ret.is_null(), "LLVM does not have support for catchpad"); - return ret + ret.expect("LLVM does not have support for catchpad") } - pub fn catch_ret(&self, pad: ValueRef, unwind: BasicBlockRef) -> ValueRef { + pub fn catch_ret(&self, pad: &'ll Value, unwind: &'ll BasicBlock) -> &'ll Value { self.count_insn("catchret"); let ret = unsafe { llvm::LLVMRustBuildCatchRet(self.llbuilder, pad, unwind) }; - assert!(!ret.is_null(), "LLVM does not have support for catchret"); - return ret + ret.expect("LLVM does not have support for catchret") } - pub fn catch_switch(&self, - parent: Option, - unwind: Option, - num_handlers: usize) -> ValueRef { + pub fn catch_switch( + &self, + parent: Option<&'ll Value>, + unwind: Option<&'ll BasicBlock>, + num_handlers: usize, + ) -> &'ll Value { self.count_insn("catchswitch"); - let parent = parent.unwrap_or(ptr::null_mut()); - let unwind = unwind.unwrap_or(ptr::null_mut()); let name = CString::new("catchswitch").unwrap(); let ret = unsafe { llvm::LLVMRustBuildCatchSwitch(self.llbuilder, parent, unwind, num_handlers as c_uint, name.as_ptr()) }; - assert!(!ret.is_null(), "LLVM does not have support for catchswitch"); - return ret + ret.expect("LLVM does not have support for catchswitch") } - pub fn add_handler(&self, catch_switch: ValueRef, handler: BasicBlockRef) { + pub fn add_handler(&self, catch_switch: &'ll Value, handler: &'ll BasicBlock) { unsafe { llvm::LLVMRustAddHandler(catch_switch, handler); } } - pub fn set_personality_fn(&self, personality: ValueRef) { + pub fn set_personality_fn(&self, personality: &'ll Value) { unsafe { llvm::LLVMSetPersonalityFn(self.llfn(), personality); } } // Atomic Operations - pub fn atomic_cmpxchg(&self, dst: ValueRef, - cmp: ValueRef, src: ValueRef, - order: AtomicOrdering, - failure_order: AtomicOrdering, - weak: llvm::Bool) -> ValueRef { + pub fn atomic_cmpxchg( + &self, + dst: &'ll Value, + cmp: &'ll Value, + src: &'ll Value, + order: AtomicOrdering, + failure_order: AtomicOrdering, + weak: llvm::Bool, + ) -> &'ll Value { unsafe { llvm::LLVMRustBuildAtomicCmpXchg(self.llbuilder, dst, cmp, src, order, failure_order, weak) } } - pub fn atomic_rmw(&self, op: AtomicRmwBinOp, - dst: ValueRef, src: ValueRef, - order: AtomicOrdering) -> ValueRef { + pub fn atomic_rmw( + &self, + op: AtomicRmwBinOp, + dst: &'ll Value, + src: &'ll Value, + order: AtomicOrdering, + ) -> &'ll Value { unsafe { llvm::LLVMBuildAtomicRMW(self.llbuilder, op, dst, src, order, False) } @@ -1297,20 +1079,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - pub fn add_case(&self, s: ValueRef, on_val: ValueRef, dest: BasicBlockRef) { + pub fn add_case(&self, s: &'ll Value, on_val: &'ll Value, dest: &'ll BasicBlock) { unsafe { llvm::LLVMAddCase(s, on_val, dest) } } - pub fn add_incoming_to_phi(&self, phi: ValueRef, val: ValueRef, bb: BasicBlockRef) { + pub fn add_incoming_to_phi(&self, phi: &'ll Value, val: &'ll Value, bb: &'ll BasicBlock) { self.count_insn("addincoming"); unsafe { llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint); } } - pub fn set_invariant_load(&self, load: ValueRef) { + pub fn set_invariant_load(&self, load: &'ll Value) { unsafe { llvm::LLVMSetMetadata(load, llvm::MD_invariant_load as c_uint, llvm::LLVMMDNodeInContext(self.cx.llcx, ptr::null(), 0)); @@ -1319,8 +1101,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Returns the ptr value that should be used for storing `val`. fn check_store<'b>(&self, - val: ValueRef, - ptr: ValueRef) -> ValueRef { + val: &'ll Value, + ptr: &'ll Value) -> &'ll Value { let dest_ptr_ty = val_ty(ptr); let stored_ty = val_ty(val); let stored_ptr_ty = stored_ty.ptr_to(); @@ -1340,8 +1122,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Returns the args that should be used for a call to `llfn`. fn check_call<'b>(&self, typ: &str, - llfn: ValueRef, - args: &'b [ValueRef]) -> Cow<'b, [ValueRef]> { + llfn: &'ll Value, + args: &'b [&'ll Value]) -> Cow<'b, [&'ll Value]> { let mut fn_ty = val_ty(llfn); // Strip off pointers while fn_ty.kind() == llvm::TypeKind::Pointer { @@ -1369,8 +1151,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if expected_ty != actual_ty { debug!("Type mismatch in function call of {:?}. \ Expected {:?} for param {}, got {:?}; injecting bitcast", - Value(llfn), - expected_ty, i, actual_ty); + llfn, expected_ty, i, actual_ty); self.bitcast(actual_val, expected_ty) } else { actual_val @@ -1381,11 +1162,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { return Cow::Owned(casted_args); } - pub fn lifetime_start(&self, ptr: ValueRef, size: Size) { + pub fn lifetime_start(&self, ptr: &'ll Value, size: Size) { self.call_lifetime_intrinsic("llvm.lifetime.start", ptr, size); } - pub fn lifetime_end(&self, ptr: ValueRef, size: Size) { + pub fn lifetime_end(&self, ptr: &'ll Value, size: Size) { self.call_lifetime_intrinsic("llvm.lifetime.end", ptr, size); } @@ -1397,7 +1178,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// /// If LLVM lifetime intrinsic support is disabled (i.e. optimizations /// off) or `ptr` is zero-sized, then no-op (does not call `emit`). - fn call_lifetime_intrinsic(&self, intrinsic: &str, ptr: ValueRef, size: Size) { + fn call_lifetime_intrinsic(&self, intrinsic: &str, ptr: &'ll Value, size: Size) { if self.cx.sess().opts.optimize == config::OptLevel::No { return; } diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index 2c01bd42cc77a..e64dedac55a24 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -18,9 +18,10 @@ use attributes; use common::{self, CodegenCx}; use consts; use declare; -use llvm::{self, ValueRef}; +use llvm; use monomorphize::Instance; use type_of::LayoutLlvmExt; +use value::Value; use rustc::hir::def_id::DefId; use rustc::ty::{self, TypeFoldable}; @@ -34,10 +35,10 @@ use rustc::ty::subst::Substs; /// /// - `cx`: the crate context /// - `instance`: the instance to be instantiated -pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - instance: Instance<'tcx>) - -> ValueRef -{ +pub fn get_fn( + cx: &CodegenCx<'ll, 'tcx>, + instance: Instance<'tcx>, +) -> &'ll Value { let tcx = cx.tcx; debug!("get_fn(instance={:?})", instance); @@ -204,11 +205,11 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, llfn } -pub fn resolve_and_get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - def_id: DefId, - substs: &'tcx Substs<'tcx>) - -> ValueRef -{ +pub fn resolve_and_get_fn( + cx: &CodegenCx<'ll, 'tcx>, + def_id: DefId, + substs: &'tcx Substs<'tcx>, +) -> &'ll Value { get_fn( cx, ty::Instance::resolve( diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index 60bba635a7887..51fc610408b52 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -12,8 +12,7 @@ //! Code that is useful in various codegen modules. -use llvm; -use llvm::{ValueRef, ContextRef, TypeKind}; +use llvm::{self, TypeKind}; use llvm::{True, False, Bool, OperandBundleDef}; use rustc::hir::def_id::DefId; use rustc::middle::lang_items::LangItem; @@ -25,6 +24,7 @@ use declare; use type_::Type; use type_of::LayoutLlvmExt; use value::Value; + use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::layout::{HasDataLayout, LayoutOf}; use rustc::hir; @@ -90,83 +90,83 @@ pub fn type_is_freeze<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bo /// When inside of a landing pad, each function call in LLVM IR needs to be /// annotated with which landing pad it's a part of. This is accomplished via /// the `OperandBundleDef` value created for MSVC landing pads. -pub struct Funclet { - cleanuppad: ValueRef, - operand: OperandBundleDef, +pub struct Funclet<'ll> { + cleanuppad: &'ll Value, + operand: OperandBundleDef<'ll>, } -impl Funclet { - pub fn new(cleanuppad: ValueRef) -> Funclet { +impl Funclet<'ll> { + pub fn new(cleanuppad: &'ll Value) -> Self { Funclet { cleanuppad, operand: OperandBundleDef::new("funclet", &[cleanuppad]), } } - pub fn cleanuppad(&self) -> ValueRef { + pub fn cleanuppad(&self) -> &'ll Value { self.cleanuppad } - pub fn bundle(&self) -> &OperandBundleDef { + pub fn bundle(&self) -> &OperandBundleDef<'ll> { &self.operand } } -pub fn val_ty(v: ValueRef) -> Type { +pub fn val_ty(v: &'ll Value) -> &'ll Type { unsafe { - Type::from_ref(llvm::LLVMTypeOf(v)) + llvm::LLVMTypeOf(v) } } // LLVM constant constructors. -pub fn C_null(t: Type) -> ValueRef { +pub fn C_null(t: &'ll Type) -> &'ll Value { unsafe { - llvm::LLVMConstNull(t.to_ref()) + llvm::LLVMConstNull(t) } } -pub fn C_undef(t: Type) -> ValueRef { +pub fn C_undef(t: &'ll Type) -> &'ll Value { unsafe { - llvm::LLVMGetUndef(t.to_ref()) + llvm::LLVMGetUndef(t) } } -pub fn C_int(t: Type, i: i64) -> ValueRef { +pub fn C_int(t: &'ll Type, i: i64) -> &'ll Value { unsafe { - llvm::LLVMConstInt(t.to_ref(), i as u64, True) + llvm::LLVMConstInt(t, i as u64, True) } } -pub fn C_uint(t: Type, i: u64) -> ValueRef { +pub fn C_uint(t: &'ll Type, i: u64) -> &'ll Value { unsafe { - llvm::LLVMConstInt(t.to_ref(), i, False) + llvm::LLVMConstInt(t, i, False) } } -pub fn C_uint_big(t: Type, u: u128) -> ValueRef { +pub fn C_uint_big(t: &'ll Type, u: u128) -> &'ll Value { unsafe { let words = [u as u64, (u >> 64) as u64]; - llvm::LLVMConstIntOfArbitraryPrecision(t.to_ref(), 2, words.as_ptr()) + llvm::LLVMConstIntOfArbitraryPrecision(t, 2, words.as_ptr()) } } -pub fn C_bool(cx: &CodegenCx, val: bool) -> ValueRef { +pub fn C_bool(cx: &CodegenCx<'ll, '_>, val: bool) -> &'ll Value { C_uint(Type::i1(cx), val as u64) } -pub fn C_i32(cx: &CodegenCx, i: i32) -> ValueRef { +pub fn C_i32(cx: &CodegenCx<'ll, '_>, i: i32) -> &'ll Value { C_int(Type::i32(cx), i as i64) } -pub fn C_u32(cx: &CodegenCx, i: u32) -> ValueRef { +pub fn C_u32(cx: &CodegenCx<'ll, '_>, i: u32) -> &'ll Value { C_uint(Type::i32(cx), i as u64) } -pub fn C_u64(cx: &CodegenCx, i: u64) -> ValueRef { +pub fn C_u64(cx: &CodegenCx<'ll, '_>, i: u64) -> &'ll Value { C_uint(Type::i64(cx), i) } -pub fn C_usize(cx: &CodegenCx, i: u64) -> ValueRef { +pub fn C_usize(cx: &CodegenCx<'ll, '_>, i: u64) -> &'ll Value { let bit_size = cx.data_layout().pointer_size.bits(); if bit_size < 64 { // make sure it doesn't overflow @@ -176,14 +176,18 @@ pub fn C_usize(cx: &CodegenCx, i: u64) -> ValueRef { C_uint(cx.isize_ty, i) } -pub fn C_u8(cx: &CodegenCx, i: u8) -> ValueRef { +pub fn C_u8(cx: &CodegenCx<'ll, '_>, i: u8) -> &'ll Value { C_uint(Type::i8(cx), i as u64) } // This is a 'c-like' raw string, which differs from // our boxed-and-length-annotated strings. -pub fn C_cstr(cx: &CodegenCx, s: LocalInternedString, null_terminated: bool) -> ValueRef { +pub fn C_cstr( + cx: &CodegenCx<'ll, '_>, + s: LocalInternedString, + null_terminated: bool, +) -> &'ll Value { unsafe { if let Some(&llval) = cx.const_cstr_cache.borrow().get(&s) { return llval; @@ -208,24 +212,28 @@ pub fn C_cstr(cx: &CodegenCx, s: LocalInternedString, null_terminated: bool) -> // NB: Do not use `do_spill_noroot` to make this into a constant string, or // you will be kicked off fast isel. See issue #4352 for an example of this. -pub fn C_str_slice(cx: &CodegenCx, s: LocalInternedString) -> ValueRef { +pub fn C_str_slice(cx: &CodegenCx<'ll, '_>, s: LocalInternedString) -> &'ll Value { let len = s.len(); let cs = consts::ptrcast(C_cstr(cx, s, false), cx.layout_of(cx.tcx.mk_str()).llvm_type(cx).ptr_to()); C_fat_ptr(cx, cs, C_usize(cx, len as u64)) } -pub fn C_fat_ptr(cx: &CodegenCx, ptr: ValueRef, meta: ValueRef) -> ValueRef { +pub fn C_fat_ptr(cx: &CodegenCx<'ll, '_>, ptr: &'ll Value, meta: &'ll Value) -> &'ll Value { assert_eq!(abi::FAT_PTR_ADDR, 0); assert_eq!(abi::FAT_PTR_EXTRA, 1); C_struct(cx, &[ptr, meta], false) } -pub fn C_struct(cx: &CodegenCx, elts: &[ValueRef], packed: bool) -> ValueRef { +pub fn C_struct(cx: &CodegenCx<'ll, '_>, elts: &[&'ll Value], packed: bool) -> &'ll Value { C_struct_in_context(cx.llcx, elts, packed) } -pub fn C_struct_in_context(llcx: ContextRef, elts: &[ValueRef], packed: bool) -> ValueRef { +pub fn C_struct_in_context( + llcx: &'ll llvm::Context, + elts: &[&'ll Value], + packed: bool, +) -> &'ll Value { unsafe { llvm::LLVMConstStructInContext(llcx, elts.as_ptr(), elts.len() as c_uint, @@ -233,47 +241,47 @@ pub fn C_struct_in_context(llcx: ContextRef, elts: &[ValueRef], packed: bool) -> } } -pub fn C_array(ty: Type, elts: &[ValueRef]) -> ValueRef { +pub fn C_array(ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value { unsafe { - return llvm::LLVMConstArray(ty.to_ref(), elts.as_ptr(), elts.len() as c_uint); + return llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint); } } -pub fn C_vector(elts: &[ValueRef]) -> ValueRef { +pub fn C_vector(elts: &[&'ll Value]) -> &'ll Value { unsafe { return llvm::LLVMConstVector(elts.as_ptr(), elts.len() as c_uint); } } -pub fn C_bytes(cx: &CodegenCx, bytes: &[u8]) -> ValueRef { +pub fn C_bytes(cx: &CodegenCx<'ll, '_>, bytes: &[u8]) -> &'ll Value { C_bytes_in_context(cx.llcx, bytes) } -pub fn C_bytes_in_context(llcx: ContextRef, bytes: &[u8]) -> ValueRef { +pub fn C_bytes_in_context(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value { unsafe { let ptr = bytes.as_ptr() as *const c_char; return llvm::LLVMConstStringInContext(llcx, ptr, bytes.len() as c_uint, True); } } -pub fn const_get_elt(v: ValueRef, idx: u64) -> ValueRef { +pub fn const_get_elt(v: &'ll Value, idx: u64) -> &'ll Value { unsafe { assert_eq!(idx as c_uint as u64, idx); let us = &[idx as c_uint]; let r = llvm::LLVMConstExtractValue(v, us.as_ptr(), us.len() as c_uint); debug!("const_get_elt(v={:?}, idx={}, r={:?})", - Value(v), idx, Value(r)); + v, idx, r); r } } -pub fn const_get_real(v: ValueRef) -> Option<(f64, bool)> { +pub fn const_get_real(v: &'ll Value) -> Option<(f64, bool)> { unsafe { if is_const_real(v) { let mut loses_info: llvm::Bool = ::std::mem::uninitialized(); - let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info as *mut llvm::Bool); + let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info); let loses_info = if loses_info == 1 { true } else { false }; Some((r, loses_info)) } else { @@ -282,21 +290,21 @@ pub fn const_get_real(v: ValueRef) -> Option<(f64, bool)> { } } -pub fn const_to_uint(v: ValueRef) -> u64 { +pub fn const_to_uint(v: &'ll Value) -> u64 { unsafe { llvm::LLVMConstIntGetZExtValue(v) } } -pub fn is_const_integral(v: ValueRef) -> bool { +pub fn is_const_integral(v: &'ll Value) -> bool { unsafe { - !llvm::LLVMIsAConstantInt(v).is_null() + llvm::LLVMIsAConstantInt(v).is_some() } } -pub fn is_const_real(v: ValueRef) -> bool { +pub fn is_const_real(v: &'ll Value) -> bool { unsafe { - !llvm::LLVMIsAConstantFP(v).is_null() + llvm::LLVMIsAConstantFP(v).is_some() } } @@ -306,12 +314,12 @@ fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 { ((hi as u128) << 64) | (lo as u128) } -pub fn const_to_opt_u128(v: ValueRef, sign_ext: bool) -> Option { +pub fn const_to_opt_u128(v: &'ll Value, sign_ext: bool) -> Option { unsafe { if is_const_integral(v) { let (mut lo, mut hi) = (0u64, 0u64); let success = llvm::LLVMRustConstInt128Get(v, sign_ext, - &mut hi as *mut u64, &mut lo as *mut u64); + &mut hi, &mut lo); if success { Some(hi_lo_to_u128(lo, hi)) } else { @@ -345,20 +353,20 @@ pub fn langcall(tcx: TyCtxt, // all shifts). For 32- and 64-bit types, this matches the semantics // of Java. (See related discussion on #1877 and #10183.) -pub fn build_unchecked_lshift<'a, 'tcx>( - bx: &Builder<'a, 'tcx>, - lhs: ValueRef, - rhs: ValueRef -) -> ValueRef { +pub fn build_unchecked_lshift( + bx: &Builder<'a, 'll, 'tcx>, + lhs: &'ll Value, + rhs: &'ll Value +) -> &'ll Value { let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shl, lhs, rhs); // #1877, #10183: Ensure that input is always valid let rhs = shift_mask_rhs(bx, rhs); bx.shl(lhs, rhs) } -pub fn build_unchecked_rshift<'a, 'tcx>( - bx: &Builder<'a, 'tcx>, lhs_t: Ty<'tcx>, lhs: ValueRef, rhs: ValueRef -) -> ValueRef { +pub fn build_unchecked_rshift( + bx: &Builder<'a, 'll, 'tcx>, lhs_t: Ty<'tcx>, lhs: &'ll Value, rhs: &'ll Value +) -> &'ll Value { let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shr, lhs, rhs); // #1877, #10183: Ensure that input is always valid let rhs = shift_mask_rhs(bx, rhs); @@ -370,17 +378,17 @@ pub fn build_unchecked_rshift<'a, 'tcx>( } } -fn shift_mask_rhs<'a, 'tcx>(bx: &Builder<'a, 'tcx>, rhs: ValueRef) -> ValueRef { +fn shift_mask_rhs(bx: &Builder<'a, 'll, 'tcx>, rhs: &'ll Value) -> &'ll Value { let rhs_llty = val_ty(rhs); bx.and(rhs, shift_mask_val(bx, rhs_llty, rhs_llty, false)) } -pub fn shift_mask_val<'a, 'tcx>( - bx: &Builder<'a, 'tcx>, - llty: Type, - mask_llty: Type, +pub fn shift_mask_val( + bx: &Builder<'a, 'll, 'tcx>, + llty: &'ll Type, + mask_llty: &'ll Type, invert: bool -) -> ValueRef { +) -> &'ll Value { let kind = llty.kind(); match kind { TypeKind::Integer => { diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index f0b5f4b887971..72ff65361cada 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -9,9 +9,7 @@ // except according to those terms. use libc::c_uint; -use llvm; -use llvm::{SetUnnamedAddr}; -use llvm::{ValueRef, True}; +use llvm::{self, SetUnnamedAddr, True}; use rustc::hir::def_id::DefId; use rustc::hir::map as hir_map; use debuginfo; @@ -24,27 +22,29 @@ use syntax_pos::Span; use syntax_pos::symbol::LocalInternedString; use type_::Type; use type_of::LayoutLlvmExt; +use value::Value; use rustc::ty::{self, Ty}; + use rustc::ty::layout::{Align, LayoutOf}; use rustc::hir::{self, CodegenFnAttrs, CodegenFnAttrFlags}; use std::ffi::{CStr, CString}; -pub fn ptrcast(val: ValueRef, ty: Type) -> ValueRef { +pub fn ptrcast(val: &'ll Value, ty: &'ll Type) -> &'ll Value { unsafe { - llvm::LLVMConstPointerCast(val, ty.to_ref()) + llvm::LLVMConstPointerCast(val, ty) } } -pub fn bitcast(val: ValueRef, ty: Type) -> ValueRef { +pub fn bitcast(val: &'ll Value, ty: &'ll Type) -> &'ll Value { unsafe { - llvm::LLVMConstBitCast(val, ty.to_ref()) + llvm::LLVMConstBitCast(val, ty) } } -fn set_global_alignment(cx: &CodegenCx, - gv: ValueRef, +fn set_global_alignment(cx: &CodegenCx<'ll, '_>, + gv: &'ll Value, mut align: Align) { // The target may require greater alignment for globals than the type does. // Note: GCC and Clang also allow `__attribute__((aligned))` on variables, @@ -62,11 +62,12 @@ fn set_global_alignment(cx: &CodegenCx, } } -pub fn addr_of_mut(cx: &CodegenCx, - cv: ValueRef, - align: Align, - kind: &str) - -> ValueRef { +pub fn addr_of_mut( + cx: &CodegenCx<'ll, '_>, + cv: &'ll Value, + align: Align, + kind: &str, +) -> &'ll Value { unsafe { let name = cx.generate_local_symbol_name(kind); let gv = declare::define_global(cx, &name[..], val_ty(cv)).unwrap_or_else(||{ @@ -80,11 +81,12 @@ pub fn addr_of_mut(cx: &CodegenCx, } } -pub fn addr_of(cx: &CodegenCx, - cv: ValueRef, - align: Align, - kind: &str) - -> ValueRef { +pub fn addr_of( + cx: &CodegenCx<'ll, '_>, + cv: &'ll Value, + align: Align, + kind: &str, +) -> &'ll Value { if let Some(&gv) = cx.const_globals.borrow().get(&cv) { unsafe { // Upgrade the alignment in cases where the same constant is used with different @@ -104,7 +106,7 @@ pub fn addr_of(cx: &CodegenCx, gv } -pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { +pub fn get_static(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll Value { let instance = Instance::mono(cx.tcx, def_id); if let Some(&g) = cx.instances.borrow().get(&instance) { return g; @@ -213,13 +215,13 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { g } -fn check_and_apply_linkage<'tcx>( - cx: &CodegenCx<'_, 'tcx>, +fn check_and_apply_linkage( + cx: &CodegenCx<'ll, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: LocalInternedString, span: Option -) -> ValueRef { +) -> &'ll Value { let llty = cx.layout_of(ty).llvm_type(cx); if let Some(linkage) = attrs.linkage { debug!("get_static: sym={} linkage={:?}", sym, linkage); @@ -294,7 +296,7 @@ pub fn codegen_static<'a, 'tcx>( let mut val_llty = val_ty(v); let v = if val_llty == Type::i1(cx) { val_llty = Type::i8(cx); - llvm::LLVMConstZExt(v, val_llty.to_ref()) + llvm::LLVMConstZExt(v, val_llty) } else { v }; @@ -316,7 +318,7 @@ pub fn codegen_static<'a, 'tcx>( let visibility = llvm::LLVMRustGetVisibility(g); let new_g = llvm::LLVMRustGetOrInsertGlobal( - cx.llmod, name_string.as_ptr(), val_llty.to_ref()); + cx.llmod, name_string.as_ptr(), val_llty); llvm::LLVMRustSetLinkage(new_g, linkage); llvm::LLVMRustSetVisibility(new_g, visibility); @@ -411,7 +413,7 @@ pub fn codegen_static<'a, 'tcx>( if attrs.flags.contains(CodegenFnAttrFlags::USED) { // This static will be stored in the llvm.used variable which is an array of i8* - let cast = llvm::LLVMConstPointerCast(g, Type::i8p(cx).to_ref()); + let cast = llvm::LLVMConstPointerCast(g, Type::i8p(cx)); cx.used_statics.borrow_mut().push(cast); } } diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index b774d7c5def21..11f8e75831eed 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -10,7 +10,6 @@ use common; use llvm; -use llvm::{ContextRef, ModuleRef, ValueRef}; use rustc::dep_graph::DepGraphSafe; use rustc::hir; use rustc::hir::def_id::DefId; @@ -19,6 +18,7 @@ use callee; use base; use declare; use monomorphize::Instance; +use value::Value; use monomorphize::partitioning::CodegenUnit; use type_::Type; @@ -35,7 +35,6 @@ use rustc_target::spec::{HasTargetSpec, Target}; use std::ffi::{CStr, CString}; use std::cell::{Cell, RefCell}; -use std::ptr; use std::iter; use std::str; use std::sync::Arc; @@ -43,65 +42,65 @@ use syntax::symbol::LocalInternedString; use abi::Abi; /// There is one `CodegenCx` per compilation unit. Each one has its own LLVM -/// `ContextRef` so that several compilation units may be optimized in parallel. -/// All other LLVM data structures in the `CodegenCx` are tied to that `ContextRef`. +/// `llvm::Context` so that several compilation units may be optimized in parallel. +/// All other LLVM data structures in the `CodegenCx` are tied to that `llvm::Context`. pub struct CodegenCx<'a, 'tcx: 'a> { pub tcx: TyCtxt<'a, 'tcx, 'tcx>, pub check_overflow: bool, pub use_dll_storage_attrs: bool, pub tls_model: llvm::ThreadLocalMode, - pub llmod: ModuleRef, - pub llcx: ContextRef, + pub llmod: &'a llvm::Module, + pub llcx: &'a llvm::Context, pub stats: RefCell, pub codegen_unit: Arc>, /// Cache instances of monomorphic and polymorphic items - pub instances: RefCell, ValueRef>>, + pub instances: RefCell, &'a Value>>, /// Cache generated vtables pub vtables: RefCell, - Option>), ValueRef>>, + Option>), &'a Value>>, /// Cache of constant strings, - pub const_cstr_cache: RefCell>, + pub const_cstr_cache: RefCell>, /// Reverse-direction for const ptrs cast from globals. - /// Key is a ValueRef holding a *T, - /// Val is a ValueRef holding a *[T]. + /// Key is a Value holding a *T, + /// Val is a Value holding a *[T]. /// /// Needed because LLVM loses pointer->pointee association /// when we ptrcast, and we have to ptrcast during codegen /// of a [T] const because we form a slice, a (*T,usize) pair, not /// a pointer to an LLVM array type. Similar for trait objects. - pub const_unsized: RefCell>, + pub const_unsized: RefCell>, /// Cache of emitted const globals (value -> global) - pub const_globals: RefCell>, + pub const_globals: RefCell>, /// Mapping from static definitions to their DefId's. - pub statics: RefCell>, + pub statics: RefCell>, /// List of globals for static variables which need to be passed to the /// LLVM function ReplaceAllUsesWith (RAUW) when codegen is complete. - /// (We have to make sure we don't invalidate any ValueRefs referring + /// (We have to make sure we don't invalidate any Values referring /// to constants.) - pub statics_to_rauw: RefCell>, + pub statics_to_rauw: RefCell>, /// Statics that will be placed in the llvm.used variable /// See http://llvm.org/docs/LangRef.html#the-llvm-used-global-variable for details - pub used_statics: RefCell>, + pub used_statics: RefCell>, - pub lltypes: RefCell, Option), Type>>, - pub scalar_lltypes: RefCell, Type>>, + pub lltypes: RefCell, Option), &'a Type>>, + pub scalar_lltypes: RefCell, &'a Type>>, pub pointee_infos: RefCell, Size), Option>>, - pub isize_ty: Type, + pub isize_ty: &'a Type, - pub dbg_cx: Option>, + pub dbg_cx: Option>, - eh_personality: Cell>, - eh_unwind_resume: Cell>, - pub rust_try_fn: Cell>, + eh_personality: Cell>, + eh_unwind_resume: Cell>, + pub rust_try_fn: Cell>, - intrinsics: RefCell>, + intrinsics: RefCell>, /// A counter that is used for generating local symbol names local_gen_sym_counter: Cell, @@ -156,8 +155,11 @@ pub fn is_pie_binary(sess: &Session) -> bool { !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC } -pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) { - let llcx = llvm::LLVMRustContextCreate(sess.fewer_names()); +pub unsafe fn create_module( + sess: &Session, + llcx: &'ll llvm::Context, + mod_name: &str, +) -> &'ll llvm::Module { let mod_name = CString::new(mod_name).unwrap(); let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx); @@ -209,13 +211,13 @@ pub unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (Cont llvm::LLVMRustSetModulePIELevel(llmod); } - (llcx, llmod) + llmod } impl<'a, 'tcx> CodegenCx<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, + crate fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, codegen_unit: Arc>, - llmod_id: &str) + llvm_module: &'a ::ModuleLlvm) -> CodegenCx<'a, 'tcx> { // An interesting part of Windows which MSVC forces our hand on (and // apparently MinGW didn't) is the usage of `dllimport` and `dllexport` @@ -266,55 +268,48 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> { let tls_model = get_tls_model(&tcx.sess); - unsafe { - let (llcx, llmod) = create_context_and_module(&tcx.sess, - &llmod_id[..]); - - let dbg_cx = if tcx.sess.opts.debuginfo != NoDebugInfo { - let dctx = debuginfo::CrateDebugContext::new(llmod); - debuginfo::metadata::compile_unit_metadata(tcx, - &codegen_unit.name().as_str(), - &dctx); - Some(dctx) - } else { - None - }; - - let mut cx = CodegenCx { - tcx, - check_overflow, - use_dll_storage_attrs, - tls_model, - llmod, - llcx, - stats: RefCell::new(Stats::default()), - codegen_unit, - instances: RefCell::new(FxHashMap()), - vtables: RefCell::new(FxHashMap()), - const_cstr_cache: RefCell::new(FxHashMap()), - const_unsized: RefCell::new(FxHashMap()), - const_globals: RefCell::new(FxHashMap()), - statics: RefCell::new(FxHashMap()), - statics_to_rauw: RefCell::new(Vec::new()), - used_statics: RefCell::new(Vec::new()), - lltypes: RefCell::new(FxHashMap()), - scalar_lltypes: RefCell::new(FxHashMap()), - pointee_infos: RefCell::new(FxHashMap()), - isize_ty: Type::from_ref(ptr::null_mut()), - dbg_cx, - eh_personality: Cell::new(None), - eh_unwind_resume: Cell::new(None), - rust_try_fn: Cell::new(None), - intrinsics: RefCell::new(FxHashMap()), - local_gen_sym_counter: Cell::new(0), - }; - cx.isize_ty = Type::isize(&cx); - cx - } - } + let (llcx, llmod) = (&*llvm_module.llcx, llvm_module.llmod()); - pub fn into_stats(self) -> Stats { - self.stats.into_inner() + let dbg_cx = if tcx.sess.opts.debuginfo != NoDebugInfo { + let dctx = debuginfo::CrateDebugContext::new(llmod); + debuginfo::metadata::compile_unit_metadata(tcx, + &codegen_unit.name().as_str(), + &dctx); + Some(dctx) + } else { + None + }; + + let isize_ty = Type::ix_llcx(llcx, tcx.data_layout.pointer_size.bits()); + + CodegenCx { + tcx, + check_overflow, + use_dll_storage_attrs, + tls_model, + llmod, + llcx, + stats: RefCell::new(Stats::default()), + codegen_unit, + instances: RefCell::new(FxHashMap()), + vtables: RefCell::new(FxHashMap()), + const_cstr_cache: RefCell::new(FxHashMap()), + const_unsized: RefCell::new(FxHashMap()), + const_globals: RefCell::new(FxHashMap()), + statics: RefCell::new(FxHashMap()), + statics_to_rauw: RefCell::new(Vec::new()), + used_statics: RefCell::new(Vec::new()), + lltypes: RefCell::new(FxHashMap()), + scalar_lltypes: RefCell::new(FxHashMap()), + pointee_infos: RefCell::new(FxHashMap()), + isize_ty, + dbg_cx, + eh_personality: Cell::new(None), + eh_unwind_resume: Cell::new(None), + rust_try_fn: Cell::new(None), + intrinsics: RefCell::new(FxHashMap()), + local_gen_sym_counter: Cell::new(0), + } } } @@ -323,7 +318,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { &self.tcx.sess } - pub fn get_intrinsic(&self, key: &str) -> ValueRef { + pub fn get_intrinsic(&self, key: &str) -> &'b Value { if let Some(v) = self.intrinsics.borrow().get(key).cloned() { return v; } @@ -347,7 +342,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { name } - pub fn eh_personality(&self) -> ValueRef { + pub fn eh_personality(&self) -> &'b Value { // The exception handling personality function. // // If our compilation unit has the `eh_personality` lang item somewhere @@ -382,7 +377,7 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { } else { "rust_eh_personality" }; - let fty = Type::variadic_func(&[], &Type::i32(self)); + let fty = Type::variadic_func(&[], Type::i32(self)); declare::declare_cfn(self, name, fty) } }; @@ -390,9 +385,9 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { llfn } - // Returns a ValueRef of the "eh_unwind_resume" lang item if one is defined, + // Returns a Value of the "eh_unwind_resume" lang item if one is defined, // otherwise declares it as an external function. - pub fn eh_unwind_resume(&self) -> ValueRef { + pub fn eh_unwind_resume(&self) -> &'b Value { use attributes; let unwresume = &self.eh_unwind_resume; if let Some(llfn) = unwresume.get() { @@ -448,25 +443,25 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { } } -impl<'a, 'tcx> ty::layout::HasDataLayout for &'a CodegenCx<'a, 'tcx> { +impl ty::layout::HasDataLayout for &'a CodegenCx<'ll, 'tcx> { fn data_layout(&self) -> &ty::layout::TargetDataLayout { &self.tcx.data_layout } } -impl<'a, 'tcx> HasTargetSpec for &'a CodegenCx<'a, 'tcx> { +impl HasTargetSpec for &'a CodegenCx<'ll, 'tcx> { fn target_spec(&self) -> &Target { &self.tcx.sess.target.target } } -impl<'a, 'tcx> ty::layout::HasTyCtxt<'tcx> for &'a CodegenCx<'a, 'tcx> { +impl ty::layout::HasTyCtxt<'tcx> for &'a CodegenCx<'ll, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { self.tcx } } -impl<'a, 'tcx> LayoutOf for &'a CodegenCx<'a, 'tcx> { +impl LayoutOf for &'a CodegenCx<'ll, 'tcx> { type Ty = Ty<'tcx>; type TyLayout = TyLayout<'tcx>; @@ -480,11 +475,11 @@ impl<'a, 'tcx> LayoutOf for &'a CodegenCx<'a, 'tcx> { } /// Declare any llvm intrinsics that you might need -fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option { +fn declare_intrinsic(cx: &CodegenCx<'ll, '_>, key: &str) -> Option<&'ll Value> { macro_rules! ifn { ($name:expr, fn() -> $ret:expr) => ( if key == $name { - let f = declare::declare_cfn(cx, $name, Type::func(&[], &$ret)); + let f = declare::declare_cfn(cx, $name, Type::func(&[], $ret)); llvm::SetUnnamedAddr(f, false); cx.intrinsics.borrow_mut().insert($name, f.clone()); return Some(f); @@ -492,7 +487,7 @@ fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option { ); ($name:expr, fn(...) -> $ret:expr) => ( if key == $name { - let f = declare::declare_cfn(cx, $name, Type::variadic_func(&[], &$ret)); + let f = declare::declare_cfn(cx, $name, Type::variadic_func(&[], $ret)); llvm::SetUnnamedAddr(f, false); cx.intrinsics.borrow_mut().insert($name, f.clone()); return Some(f); @@ -500,7 +495,7 @@ fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option { ); ($name:expr, fn($($arg:expr),*) -> $ret:expr) => ( if key == $name { - let f = declare::declare_cfn(cx, $name, Type::func(&[$($arg),*], &$ret)); + let f = declare::declare_cfn(cx, $name, Type::func(&[$($arg),*], $ret)); llvm::SetUnnamedAddr(f, false); cx.intrinsics.borrow_mut().insert($name, f.clone()); return Some(f); @@ -522,14 +517,14 @@ fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option { let t_f32 = Type::f32(cx); let t_f64 = Type::f64(cx); - let t_v2f32 = Type::vector(&t_f32, 2); - let t_v4f32 = Type::vector(&t_f32, 4); - let t_v8f32 = Type::vector(&t_f32, 8); - let t_v16f32 = Type::vector(&t_f32, 16); + let t_v2f32 = Type::vector(t_f32, 2); + let t_v4f32 = Type::vector(t_f32, 4); + let t_v8f32 = Type::vector(t_f32, 8); + let t_v16f32 = Type::vector(t_f32, 16); - let t_v2f64 = Type::vector(&t_f64, 2); - let t_v4f64 = Type::vector(&t_f64, 4); - let t_v8f64 = Type::vector(&t_f64, 8); + let t_v2f64 = Type::vector(t_f64, 2); + let t_v4f64 = Type::vector(t_f64, 4); + let t_v8f64 = Type::vector(t_f64, 8); ifn!("llvm.memcpy.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void); ifn!("llvm.memcpy.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void); diff --git a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs index fcde7f9bbc33d..5273032f2d7f5 100644 --- a/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs +++ b/src/librustc_codegen_llvm/debuginfo/create_scope_map.rs @@ -18,7 +18,6 @@ use common::CodegenCx; use rustc::mir::{Mir, SourceScope}; use libc::c_uint; -use std::ptr; use syntax_pos::Pos; @@ -28,26 +27,29 @@ use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use syntax_pos::BytePos; #[derive(Clone, Copy, Debug)] -pub struct MirDebugScope { - pub scope_metadata: DIScope, +pub struct MirDebugScope<'ll> { + pub scope_metadata: Option<&'ll DIScope>, // Start and end offsets of the file to which this DIScope belongs. // These are used to quickly determine whether some span refers to the same file. pub file_start_pos: BytePos, pub file_end_pos: BytePos, } -impl MirDebugScope { +impl MirDebugScope<'ll> { pub fn is_valid(&self) -> bool { - !self.scope_metadata.is_null() + !self.scope_metadata.is_none() } } /// Produce DIScope DIEs for each MIR Scope which has variables defined in it. /// If debuginfo is disabled, the returned vector is empty. -pub fn create_mir_scopes(cx: &CodegenCx, mir: &Mir, debug_context: &FunctionDebugContext) - -> IndexVec { +pub fn create_mir_scopes( + cx: &CodegenCx<'ll, '_>, + mir: &Mir, + debug_context: &FunctionDebugContext<'ll>, +) -> IndexVec> { let null_scope = MirDebugScope { - scope_metadata: ptr::null_mut(), + scope_metadata: None, file_start_pos: BytePos(0), file_end_pos: BytePos(0) }; @@ -77,12 +79,12 @@ pub fn create_mir_scopes(cx: &CodegenCx, mir: &Mir, debug_context: &FunctionDebu scopes } -fn make_mir_scope(cx: &CodegenCx, +fn make_mir_scope(cx: &CodegenCx<'ll, '_>, mir: &Mir, has_variables: &BitVector, - debug_context: &FunctionDebugContextData, + debug_context: &FunctionDebugContextData<'ll>, scope: SourceScope, - scopes: &mut IndexVec) { + scopes: &mut IndexVec>) { if scopes[scope].is_valid() { return; } @@ -95,7 +97,7 @@ fn make_mir_scope(cx: &CodegenCx, // The root is the function itself. let loc = span_start(cx, mir.span); scopes[scope] = MirDebugScope { - scope_metadata: debug_context.fn_metadata, + scope_metadata: Some(debug_context.fn_metadata), file_start_pos: loc.file.start_pos, file_end_pos: loc.file.end_pos, }; @@ -109,7 +111,7 @@ fn make_mir_scope(cx: &CodegenCx, // However, we don't skip creating a nested scope if // our parent is the root, because we might want to // put arguments in the root and not have shadowing. - if parent_scope.scope_metadata != debug_context.fn_metadata { + if parent_scope.scope_metadata.unwrap() != debug_context.fn_metadata { scopes[scope] = parent_scope; return; } @@ -121,12 +123,12 @@ fn make_mir_scope(cx: &CodegenCx, debug_context.defining_crate); let scope_metadata = unsafe { - llvm::LLVMRustDIBuilderCreateLexicalBlock( + Some(llvm::LLVMRustDIBuilderCreateLexicalBlock( DIB(cx), - parent_scope.scope_metadata, + parent_scope.scope_metadata.unwrap(), file_metadata, loc.line as c_uint, - loc.col.to_usize() as c_uint) + loc.col.to_usize() as c_uint)) }; scopes[scope] = MirDebugScope { scope_metadata, diff --git a/src/librustc_codegen_llvm/debuginfo/gdb.rs b/src/librustc_codegen_llvm/debuginfo/gdb.rs index 0b4858c7ab051..08128a729b5f0 100644 --- a/src/librustc_codegen_llvm/debuginfo/gdb.rs +++ b/src/librustc_codegen_llvm/debuginfo/gdb.rs @@ -15,10 +15,10 @@ use llvm; use common::{C_bytes, CodegenCx, C_i32}; use builder::Builder; use declare; -use type_::Type; use rustc::session::config::NoDebugInfo; +use type_::Type; +use value::Value; -use std::ptr; use syntax::attr; @@ -40,8 +40,8 @@ pub fn insert_reference_to_gdb_debug_scripts_section_global(bx: &Builder) { /// Allocates the global variable responsible for the .debug_gdb_scripts binary /// section. -pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx) - -> llvm::ValueRef { +pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>) + -> &'ll Value { let c_section_var_name = "__rustc_debug_gdb_scripts_section__\0"; let section_var_name = &c_section_var_name[..c_section_var_name.len()-1]; @@ -50,12 +50,12 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx) c_section_var_name.as_ptr() as *const _) }; - if section_var == ptr::null_mut() { + section_var.unwrap_or_else(|| { let section_name = b".debug_gdb_scripts\0"; let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0"; unsafe { - let llvm_type = Type::array(&Type::i8(cx), + let llvm_type = Type::array(Type::i8(cx), section_contents.len() as u64); let section_var = declare::define_global(cx, section_var_name, @@ -72,9 +72,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx) llvm::LLVMSetAlignment(section_var, 1); section_var } - } else { - section_var - } + }) } pub fn needs_gdb_debug_scripts_section(cx: &CodegenCx) -> bool { diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 2f4dd5a7ce5bb..69ef92ed98e52 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -18,8 +18,9 @@ use super::namespace::mangled_name_of_instance; use super::type_names::compute_debuginfo_type_name; use super::{CrateDebugContext}; use abi; +use value::Value; -use llvm::{self, ValueRef}; +use llvm; use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType, DILexicalBlock, DIFlags}; @@ -38,7 +39,8 @@ use rustc::util::common::path2cstr; use libc::{c_uint, c_longlong}; use std::ffi::CString; -use std::fmt::Write; +use std::fmt::{self, Write}; +use std::hash::{Hash, Hasher}; use std::iter; use std::ptr; use std::path::{Path, PathBuf}; @@ -46,6 +48,25 @@ use syntax::ast; use syntax::symbol::{Interner, InternedString, Symbol}; use syntax_pos::{self, Span, FileName}; +impl PartialEq for llvm::Metadata { + fn eq(&self, other: &Self) -> bool { + self as *const _ == other as *const _ + } +} + +impl Eq for llvm::Metadata {} + +impl Hash for llvm::Metadata { + fn hash(&self, hasher: &mut H) { + (self as *const Self).hash(hasher); + } +} + +impl fmt::Debug for llvm::Metadata { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + (self as *const Self).fmt(f) + } +} // From DWARF 5. // See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1 @@ -64,8 +85,7 @@ const DW_ATE_unsigned_char: c_uint = 0x08; pub const UNKNOWN_LINE_NUMBER: c_uint = 0; pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0; -// ptr::null() doesn't work :( -pub const NO_SCOPE_METADATA: DIScope = (0 as DIScope); +pub const NO_SCOPE_METADATA: Option<&DIScope> = None; #[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)] pub struct UniqueTypeId(ast::Name); @@ -74,19 +94,19 @@ pub struct UniqueTypeId(ast::Name); // created so far. The metadata nodes are indexed by UniqueTypeId, and, for // faster lookup, also by Ty. The TypeMap is responsible for creating // UniqueTypeIds. -pub struct TypeMap<'tcx> { +pub struct TypeMap<'ll, 'tcx> { // The UniqueTypeIds created so far unique_id_interner: Interner, // A map from UniqueTypeId to debuginfo metadata for that type. This is a 1:1 mapping. - unique_id_to_metadata: FxHashMap, + unique_id_to_metadata: FxHashMap, // A map from types to debuginfo metadata. This is a N:1 mapping. - type_to_metadata: FxHashMap, DIType>, + type_to_metadata: FxHashMap, &'ll DIType>, // A map from types to UniqueTypeId. This is a N:1 mapping. type_to_unique_id: FxHashMap, UniqueTypeId> } -impl<'tcx> TypeMap<'tcx> { - pub fn new() -> TypeMap<'tcx> { +impl TypeMap<'ll, 'tcx> { + pub fn new() -> Self { TypeMap { unique_id_interner: Interner::new(), type_to_metadata: FxHashMap(), @@ -97,9 +117,11 @@ impl<'tcx> TypeMap<'tcx> { // Adds a Ty to metadata mapping to the TypeMap. The method will fail if // the mapping already exists. - fn register_type_with_metadata<'a>(&mut self, - type_: Ty<'tcx>, - metadata: DIType) { + fn register_type_with_metadata( + &mut self, + type_: Ty<'tcx>, + metadata: &'ll DIType, + ) { if self.type_to_metadata.insert(type_, metadata).is_some() { bug!("Type metadata for Ty '{}' is already in the TypeMap!", type_); } @@ -107,20 +129,22 @@ impl<'tcx> TypeMap<'tcx> { // Adds a UniqueTypeId to metadata mapping to the TypeMap. The method will // fail if the mapping already exists. - fn register_unique_id_with_metadata(&mut self, - unique_type_id: UniqueTypeId, - metadata: DIType) { + fn register_unique_id_with_metadata( + &mut self, + unique_type_id: UniqueTypeId, + metadata: &'ll DIType, + ) { if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() { bug!("Type metadata for unique id '{}' is already in the TypeMap!", self.get_unique_type_id_as_string(unique_type_id)); } } - fn find_metadata_for_type(&self, type_: Ty<'tcx>) -> Option { + fn find_metadata_for_type(&self, type_: Ty<'tcx>) -> Option<&'ll DIType> { self.type_to_metadata.get(&type_).cloned() } - fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option { + fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option<&'ll DIType> { self.unique_id_to_metadata.get(&unique_type_id).cloned() } @@ -182,23 +206,23 @@ impl<'tcx> TypeMap<'tcx> { // needed to generate the missing parts of the description. See the // documentation section on Recursive Types at the top of this file for more // information. -enum RecursiveTypeDescription<'tcx> { +enum RecursiveTypeDescription<'ll, 'tcx> { UnfinishedMetadata { unfinished_type: Ty<'tcx>, unique_type_id: UniqueTypeId, - metadata_stub: DICompositeType, - member_description_factory: MemberDescriptionFactory<'tcx>, + metadata_stub: &'ll DICompositeType, + member_description_factory: MemberDescriptionFactory<'ll, 'tcx>, }, - FinalMetadata(DICompositeType) + FinalMetadata(&'ll DICompositeType) } -fn create_and_register_recursive_type_forward_declaration<'a, 'tcx>( - cx: &CodegenCx<'a, 'tcx>, +fn create_and_register_recursive_type_forward_declaration( + cx: &CodegenCx<'ll, 'tcx>, unfinished_type: Ty<'tcx>, unique_type_id: UniqueTypeId, - metadata_stub: DICompositeType, - member_description_factory: MemberDescriptionFactory<'tcx>) - -> RecursiveTypeDescription<'tcx> { + metadata_stub: &'ll DICompositeType, + member_description_factory: MemberDescriptionFactory<'ll, 'tcx>, +) -> RecursiveTypeDescription<'ll, 'tcx> { // Insert the stub into the TypeMap in order to allow for recursive references let mut type_map = debug_context(cx).type_map.borrow_mut(); @@ -213,11 +237,11 @@ fn create_and_register_recursive_type_forward_declaration<'a, 'tcx>( } } -impl<'tcx> RecursiveTypeDescription<'tcx> { +impl RecursiveTypeDescription<'ll, 'tcx> { // Finishes up the description of the type in question (mostly by providing // descriptions of the fields of the given type) and returns the final type // metadata. - fn finalize<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> MetadataCreationResult { + fn finalize(&self, cx: &CodegenCx<'ll, 'tcx>) -> MetadataCreationResult<'ll> { match *self { FinalMetadata(metadata) => MetadataCreationResult::new(metadata, false), UnfinishedMetadata { @@ -269,12 +293,13 @@ macro_rules! return_if_metadata_created_in_meantime { ) } -fn fixed_vec_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - unique_type_id: UniqueTypeId, - array_or_slice_type: Ty<'tcx>, - element_type: Ty<'tcx>, - span: Span) - -> MetadataCreationResult { +fn fixed_vec_metadata( + cx: &CodegenCx<'ll, 'tcx>, + unique_type_id: UniqueTypeId, + array_or_slice_type: Ty<'tcx>, + element_type: Ty<'tcx>, + span: Span, +) -> MetadataCreationResult<'ll> { let element_type_metadata = type_metadata(cx, element_type, span); return_if_metadata_created_in_meantime!(cx, unique_type_id); @@ -289,7 +314,7 @@ fn fixed_vec_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, }; let subrange = unsafe { - llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound) + Some(llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)) }; let subscripts = create_DIArray(DIB(cx), &[subrange]); @@ -305,12 +330,13 @@ fn fixed_vec_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, return MetadataCreationResult::new(metadata, false); } -fn vec_slice_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - slice_ptr_type: Ty<'tcx>, - element_type: Ty<'tcx>, - unique_type_id: UniqueTypeId, - span: Span) - -> MetadataCreationResult { +fn vec_slice_metadata( + cx: &CodegenCx<'ll, 'tcx>, + slice_ptr_type: Ty<'tcx>, + element_type: Ty<'tcx>, + unique_type_id: UniqueTypeId, + span: Span, +) -> MetadataCreationResult<'ll> { let data_ptr_type = cx.tcx.mk_imm_ptr(element_type); let data_ptr_metadata = type_metadata(cx, data_ptr_type, span); @@ -354,26 +380,28 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, MetadataCreationResult::new(metadata, false) } -fn subroutine_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - unique_type_id: UniqueTypeId, - signature: ty::PolyFnSig<'tcx>, - span: Span) - -> MetadataCreationResult -{ +fn subroutine_type_metadata( + cx: &CodegenCx<'ll, 'tcx>, + unique_type_id: UniqueTypeId, + signature: ty::PolyFnSig<'tcx>, + span: Span, +) -> MetadataCreationResult<'ll> { let signature = cx.tcx.normalize_erasing_late_bound_regions( ty::ParamEnv::reveal_all(), &signature, ); - let signature_metadata: Vec = iter::once( + let signature_metadata: Vec<_> = iter::once( // return type match signature.output().sty { - ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(), - _ => type_metadata(cx, signature.output(), span) + ty::TyTuple(ref tys) if tys.is_empty() => None, + _ => Some(type_metadata(cx, signature.output(), span)) } ).chain( // regular arguments - signature.inputs().iter().map(|argument_type| type_metadata(cx, argument_type, span)) + signature.inputs().iter().map(|argument_type| { + Some(type_metadata(cx, argument_type, span)) + }) ).collect(); return_if_metadata_created_in_meantime!(cx, unique_type_id); @@ -394,11 +422,12 @@ fn subroutine_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, // trait_type should be the actual trait (e.g., Trait). Where the trait is part // of a DST struct, there is no trait_object_type and the results of this // function will be a little bit weird. -fn trait_pointer_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - trait_type: Ty<'tcx>, - trait_object_type: Option>, - unique_type_id: UniqueTypeId) - -> DIType { +fn trait_pointer_metadata( + cx: &CodegenCx<'ll, 'tcx>, + trait_type: Ty<'tcx>, + trait_object_type: Option>, + unique_type_id: UniqueTypeId, +) -> &'ll DIType { // The implementation provided here is a stub. It makes sure that the trait // type is assigned the correct name, size, namespace, and source location. // But it does not describe the trait's methods. @@ -406,7 +435,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let containing_scope = match trait_type.sty { ty::TyDynamic(ref data, ..) => if let Some(principal) = data.principal() { let def_id = principal.def_id(); - get_namespace_for_item(cx, def_id) + Some(get_namespace_for_item(cx, def_id)) } else { NO_SCOPE_METADATA }, @@ -461,10 +490,11 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, syntax_pos::DUMMY_SP) } -pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - t: Ty<'tcx>, - usage_site_span: Span) - -> DIType { +pub fn type_metadata( + cx: &CodegenCx<'ll, 'tcx>, + t: Ty<'tcx>, + usage_site_span: Span, +) -> &'ll DIType { // Get the unique type id of this type. let unique_type_id = { let mut type_map = debug_context(cx).type_map.borrow_mut(); @@ -681,9 +711,9 @@ pub fn type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, metadata } -pub fn file_metadata(cx: &CodegenCx, +pub fn file_metadata(cx: &CodegenCx<'ll, '_>, file_name: &FileName, - defining_crate: CrateNum) -> DIFile { + defining_crate: CrateNum) -> &'ll DIFile { debug!("file_metadata: file_name: {}, defining_crate: {}", file_name, defining_crate); @@ -699,14 +729,14 @@ pub fn file_metadata(cx: &CodegenCx, file_metadata_raw(cx, &file_name.to_string(), &directory.to_string_lossy()) } -pub fn unknown_file_metadata(cx: &CodegenCx) -> DIFile { +pub fn unknown_file_metadata(cx: &CodegenCx<'ll, '_>) -> &'ll DIFile { file_metadata_raw(cx, "", "") } -fn file_metadata_raw(cx: &CodegenCx, +fn file_metadata_raw(cx: &CodegenCx<'ll, '_>, file_name: &str, directory: &str) - -> DIFile { + -> &'ll DIFile { let key = (Symbol::intern(file_name), Symbol::intern(directory)); if let Some(file_metadata) = debug_context(cx).created_files.borrow().get(&key) { @@ -729,9 +759,7 @@ fn file_metadata_raw(cx: &CodegenCx, file_metadata } -fn basic_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - t: Ty<'tcx>) -> DIType { - +fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { debug!("basic_type_metadata: {:?}", t); let (name, encoding) = match t.sty { @@ -766,19 +794,22 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, return ty_metadata; } -fn foreign_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - t: Ty<'tcx>, - unique_type_id: UniqueTypeId) -> DIType { +fn foreign_type_metadata( + cx: &CodegenCx<'ll, 'tcx>, + t: Ty<'tcx>, + unique_type_id: UniqueTypeId, +) -> &'ll DIType { debug!("foreign_type_metadata: {:?}", t); let name = compute_debuginfo_type_name(cx, t, false); create_struct_stub(cx, t, &name, unique_type_id, NO_SCOPE_METADATA) } -fn pointer_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - pointer_type: Ty<'tcx>, - pointee_type_metadata: DIType) - -> DIType { +fn pointer_type_metadata( + cx: &CodegenCx<'ll, 'tcx>, + pointer_type: Ty<'tcx>, + pointee_type_metadata: &'ll DIType, +) -> &'ll DIType { let (pointer_size, pointer_align) = cx.size_and_align_of(pointer_type); let name = compute_debuginfo_type_name(cx, pointer_type, false); let name = CString::new(name).unwrap(); @@ -794,8 +825,8 @@ fn pointer_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, pub fn compile_unit_metadata(tcx: TyCtxt, codegen_unit_name: &str, - debug_context: &CrateDebugContext) - -> DIDescriptor { + debug_context: &CrateDebugContext<'ll, '_>) + -> &'ll DIDescriptor { let mut name_in_debuginfo = match tcx.sess.local_crate_source_file { Some(ref path) => path.clone(), None => PathBuf::from(&*tcx.crate_name(LOCAL_CRATE).as_str()), @@ -860,7 +891,7 @@ pub fn compile_unit_metadata(tcx: TyCtxt, return unit_metadata; }; - fn path_to_mdstring(llcx: llvm::ContextRef, path: &Path) -> llvm::ValueRef { + fn path_to_mdstring(llcx: &'ll llvm::Context, path: &Path) -> &'ll Value { let path_str = path2cstr(path); unsafe { llvm::LLVMMDStringInContext(llcx, @@ -870,13 +901,13 @@ pub fn compile_unit_metadata(tcx: TyCtxt, } } -struct MetadataCreationResult { - metadata: DIType, +struct MetadataCreationResult<'ll> { + metadata: &'ll DIType, already_stored_in_typemap: bool } -impl MetadataCreationResult { - fn new(metadata: DIType, already_stored_in_typemap: bool) -> MetadataCreationResult { +impl MetadataCreationResult<'ll> { + fn new(metadata: &'ll DIType, already_stored_in_typemap: bool) -> Self { MetadataCreationResult { metadata, already_stored_in_typemap, @@ -887,9 +918,9 @@ impl MetadataCreationResult { // Description of a type member, which can either be a regular field (as in // structs or tuples) or an enum variant. #[derive(Debug)] -struct MemberDescription { +struct MemberDescription<'ll> { name: String, - type_metadata: DIType, + type_metadata: &'ll DIType, offset: Size, size: Size, align: Align, @@ -900,17 +931,17 @@ struct MemberDescription { // for some record-like type. MemberDescriptionFactories are used to defer the // creation of type member descriptions in order to break cycles arising from // recursive type definitions. -enum MemberDescriptionFactory<'tcx> { +enum MemberDescriptionFactory<'ll, 'tcx> { StructMDF(StructMemberDescriptionFactory<'tcx>), TupleMDF(TupleMemberDescriptionFactory<'tcx>), - EnumMDF(EnumMemberDescriptionFactory<'tcx>), + EnumMDF(EnumMemberDescriptionFactory<'ll, 'tcx>), UnionMDF(UnionMemberDescriptionFactory<'tcx>), - VariantMDF(VariantMemberDescriptionFactory<'tcx>) + VariantMDF(VariantMemberDescriptionFactory<'ll, 'tcx>) } -impl<'tcx> MemberDescriptionFactory<'tcx> { - fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>) - -> Vec { +impl MemberDescriptionFactory<'ll, 'tcx> { + fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) + -> Vec> { match *self { StructMDF(ref this) => { this.create_member_descriptions(cx) @@ -943,8 +974,8 @@ struct StructMemberDescriptionFactory<'tcx> { } impl<'tcx> StructMemberDescriptionFactory<'tcx> { - fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>) - -> Vec { + fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) + -> Vec> { let layout = cx.layout_of(self.ty); self.variant.fields.iter().enumerate().map(|(i, f)| { let name = if self.variant.ctor_kind == CtorKind::Fn { @@ -967,11 +998,12 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> { } -fn prepare_struct_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - struct_type: Ty<'tcx>, - unique_type_id: UniqueTypeId, - span: Span) - -> RecursiveTypeDescription<'tcx> { +fn prepare_struct_metadata( + cx: &CodegenCx<'ll, 'tcx>, + struct_type: Ty<'tcx>, + unique_type_id: UniqueTypeId, + span: Span, +) -> RecursiveTypeDescription<'ll, 'tcx> { let struct_name = compute_debuginfo_type_name(cx, struct_type, false); let (struct_def_id, variant) = match struct_type.sty { @@ -985,7 +1017,7 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, struct_type, &struct_name, unique_type_id, - containing_scope); + Some(containing_scope)); create_and_register_recursive_type_forward_declaration( cx, @@ -1012,8 +1044,8 @@ struct TupleMemberDescriptionFactory<'tcx> { } impl<'tcx> TupleMemberDescriptionFactory<'tcx> { - fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>) - -> Vec { + fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) + -> Vec> { let layout = cx.layout_of(self.ty); self.component_types.iter().enumerate().map(|(i, &component_type)| { let (size, align) = cx.size_and_align_of(component_type); @@ -1029,12 +1061,13 @@ impl<'tcx> TupleMemberDescriptionFactory<'tcx> { } } -fn prepare_tuple_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - tuple_type: Ty<'tcx>, - component_types: &[Ty<'tcx>], - unique_type_id: UniqueTypeId, - span: Span) - -> RecursiveTypeDescription<'tcx> { +fn prepare_tuple_metadata( + cx: &CodegenCx<'ll, 'tcx>, + tuple_type: Ty<'tcx>, + component_types: &[Ty<'tcx>], + unique_type_id: UniqueTypeId, + span: Span, +) -> RecursiveTypeDescription<'ll, 'tcx> { let tuple_name = compute_debuginfo_type_name(cx, tuple_type, false); create_and_register_recursive_type_forward_declaration( @@ -1065,8 +1098,8 @@ struct UnionMemberDescriptionFactory<'tcx> { } impl<'tcx> UnionMemberDescriptionFactory<'tcx> { - fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>) - -> Vec { + fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) + -> Vec> { self.variant.fields.iter().enumerate().map(|(i, f)| { let field = self.layout.field(cx, i); let (size, align) = field.size_and_align(); @@ -1082,11 +1115,12 @@ impl<'tcx> UnionMemberDescriptionFactory<'tcx> { } } -fn prepare_union_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - union_type: Ty<'tcx>, - unique_type_id: UniqueTypeId, - span: Span) - -> RecursiveTypeDescription<'tcx> { +fn prepare_union_metadata( + cx: &CodegenCx<'ll, 'tcx>, + union_type: Ty<'tcx>, + unique_type_id: UniqueTypeId, + span: Span, +) -> RecursiveTypeDescription<'ll, 'tcx> { let union_name = compute_debuginfo_type_name(cx, union_type, false); let (union_def_id, variant) = match union_type.sty { @@ -1124,17 +1158,17 @@ fn prepare_union_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, // the members of this union; so for every variant of the given enum, this // factory will produce one MemberDescription (all with no name and a fixed // offset of zero bytes). -struct EnumMemberDescriptionFactory<'tcx> { +struct EnumMemberDescriptionFactory<'ll, 'tcx> { enum_type: Ty<'tcx>, layout: TyLayout<'tcx>, - discriminant_type_metadata: Option, - containing_scope: DIScope, + discriminant_type_metadata: Option<&'ll DIType>, + containing_scope: &'ll DIScope, span: Span, } -impl<'tcx> EnumMemberDescriptionFactory<'tcx> { - fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>) - -> Vec { +impl EnumMemberDescriptionFactory<'ll, 'tcx> { + fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) + -> Vec> { let adt = &self.enum_type.ty_adt_def().unwrap(); match self.layout.variants { layout::Variants::Single { .. } if adt.variants.is_empty() => vec![], @@ -1259,17 +1293,17 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { } // Creates MemberDescriptions for the fields of a single enum variant. -struct VariantMemberDescriptionFactory<'tcx> { +struct VariantMemberDescriptionFactory<'ll, 'tcx> { // Cloned from the layout::Struct describing the variant. offsets: Vec, args: Vec<(String, Ty<'tcx>)>, - discriminant_type_metadata: Option, + discriminant_type_metadata: Option<&'ll DIType>, span: Span, } -impl<'tcx> VariantMemberDescriptionFactory<'tcx> { - fn create_member_descriptions<'a>(&self, cx: &CodegenCx<'a, 'tcx>) - -> Vec { +impl VariantMemberDescriptionFactory<'ll, 'tcx> { + fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>) + -> Vec> { self.args.iter().enumerate().map(|(i, &(ref name, ty))| { let (size, align) = cx.size_and_align_of(ty); MemberDescription { @@ -1288,8 +1322,8 @@ impl<'tcx> VariantMemberDescriptionFactory<'tcx> { } #[derive(Copy, Clone)] -enum EnumDiscriminantInfo { - RegularDiscriminant(DIType), +enum EnumDiscriminantInfo<'ll> { + RegularDiscriminant(&'ll DIType), OptimizedDiscriminant, NoDiscriminant } @@ -1298,13 +1332,14 @@ enum EnumDiscriminantInfo { // of the variant, and (3) a MemberDescriptionFactory for producing the // descriptions of the fields of the variant. This is a rudimentary version of a // full RecursiveTypeDescription. -fn describe_enum_variant<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - layout: layout::TyLayout<'tcx>, - variant: &'tcx ty::VariantDef, - discriminant_info: EnumDiscriminantInfo, - containing_scope: DIScope, - span: Span) - -> (DICompositeType, MemberDescriptionFactory<'tcx>) { +fn describe_enum_variant( + cx: &CodegenCx<'ll, 'tcx>, + layout: layout::TyLayout<'tcx>, + variant: &'tcx ty::VariantDef, + discriminant_info: EnumDiscriminantInfo<'ll>, + containing_scope: &'ll DIScope, + span: Span, +) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) { let variant_name = variant.name.as_str(); let unique_type_id = debug_context(cx).type_map .borrow_mut() @@ -1317,7 +1352,7 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, layout.ty, &variant_name, unique_type_id, - containing_scope); + Some(containing_scope)); // If this is not a univariant enum, there is also the discriminant field. let (discr_offset, discr_arg) = match discriminant_info { @@ -1358,12 +1393,13 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, (metadata_stub, member_description_factory) } -fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - enum_type: Ty<'tcx>, - enum_def_id: DefId, - unique_type_id: UniqueTypeId, - span: Span) - -> RecursiveTypeDescription<'tcx> { +fn prepare_enum_metadata( + cx: &CodegenCx<'ll, 'tcx>, + enum_type: Ty<'tcx>, + enum_def_id: DefId, + unique_type_id: UniqueTypeId, + span: Span, +) -> RecursiveTypeDescription<'ll, 'tcx> { let enum_name = compute_debuginfo_type_name(cx, enum_type, false); let containing_scope = get_namespace_for_item(cx, enum_def_id); @@ -1376,17 +1412,17 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, let file_metadata = unknown_file_metadata(cx); let def = enum_type.ty_adt_def().unwrap(); - let enumerators_metadata: Vec = def.discriminants(cx.tcx) + let enumerators_metadata: Vec<_> = def.discriminants(cx.tcx) .zip(&def.variants) .map(|(discr, v)| { let token = v.name.as_str(); let name = CString::new(token.as_bytes()).unwrap(); unsafe { - llvm::LLVMRustDIBuilderCreateEnumerator( + Some(llvm::LLVMRustDIBuilderCreateEnumerator( DIB(cx), name.as_ptr(), // FIXME: what if enumeration has i128 discriminant? - discr.val as u64) + discr.val as u64)) } }) .collect(); @@ -1459,7 +1495,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, enum_type_size.bits(), enum_type_align.abi_bits() as u32, DIFlags::FlagZero, - ptr::null_mut(), + None, 0, // RuntimeLang unique_type_id_str.as_ptr()) }; @@ -1489,18 +1525,19 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, /// results in a LLVM struct. /// /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums. -fn composite_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - composite_type: Ty<'tcx>, - composite_type_name: &str, - composite_type_unique_id: UniqueTypeId, - member_descriptions: &[MemberDescription], - containing_scope: DIScope, - - // Ignore source location information as long as it - // can't be reconstructed for non-local crates. - _file_metadata: DIFile, - _definition_span: Span) - -> DICompositeType { +fn composite_type_metadata( + cx: &CodegenCx<'ll, 'tcx>, + composite_type: Ty<'tcx>, + composite_type_name: &str, + composite_type_unique_id: UniqueTypeId, + member_descriptions: &[MemberDescription<'ll>], + containing_scope: Option<&'ll DIScope>, + + // Ignore source location information as long as it + // can't be reconstructed for non-local crates. + _file_metadata: &'ll DIFile, + _definition_span: Span, +) -> &'ll DICompositeType { // Create the (empty) struct metadata node ... let composite_type_metadata = create_struct_stub(cx, composite_type, @@ -1515,9 +1552,9 @@ fn composite_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, return composite_type_metadata; } -fn set_members_of_composite_type(cx: &CodegenCx, - composite_type_metadata: DICompositeType, - member_descriptions: &[MemberDescription]) { +fn set_members_of_composite_type(cx: &CodegenCx<'ll, '_>, + composite_type_metadata: &'ll DICompositeType, + member_descriptions: &[MemberDescription<'ll>]) { // In some rare cases LLVM metadata uniquing would lead to an existing type // description being used instead of a new one created in // create_struct_stub. This would cause a hard to trace assertion in @@ -1535,13 +1572,13 @@ fn set_members_of_composite_type(cx: &CodegenCx, } } - let member_metadata: Vec = member_descriptions + let member_metadata: Vec<_> = member_descriptions .iter() .map(|member_description| { let member_name = member_description.name.as_bytes(); let member_name = CString::new(member_name).unwrap(); unsafe { - llvm::LLVMRustDIBuilderCreateMemberType( + Some(llvm::LLVMRustDIBuilderCreateMemberType( DIB(cx), composite_type_metadata, member_name.as_ptr(), @@ -1551,7 +1588,7 @@ fn set_members_of_composite_type(cx: &CodegenCx, member_description.align.abi_bits() as u32, member_description.offset.bits(), member_description.flags, - member_description.type_metadata) + member_description.type_metadata)) } }) .collect(); @@ -1566,12 +1603,13 @@ fn set_members_of_composite_type(cx: &CodegenCx, // A convenience wrapper around LLVMRustDIBuilderCreateStructType(). Does not do // any caching, does not add any fields to the struct. This can be done later // with set_members_of_composite_type(). -fn create_struct_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - struct_type: Ty<'tcx>, - struct_type_name: &str, - unique_type_id: UniqueTypeId, - containing_scope: DIScope) - -> DICompositeType { +fn create_struct_stub( + cx: &CodegenCx<'ll, 'tcx>, + struct_type: Ty<'tcx>, + struct_type_name: &str, + unique_type_id: UniqueTypeId, + containing_scope: Option<&'ll DIScope>, +) -> &'ll DICompositeType { let (struct_size, struct_align) = cx.size_and_align_of(struct_type); let name = CString::new(struct_type_name).unwrap(); @@ -1593,22 +1631,23 @@ fn create_struct_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, struct_size.bits(), struct_align.abi_bits() as u32, DIFlags::FlagZero, - ptr::null_mut(), + None, empty_array, 0, - ptr::null_mut(), + None, unique_type_id.as_ptr()) }; return metadata_stub; } -fn create_union_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - union_type: Ty<'tcx>, - union_type_name: &str, - unique_type_id: UniqueTypeId, - containing_scope: DIScope) - -> DICompositeType { +fn create_union_stub( + cx: &CodegenCx<'ll, 'tcx>, + union_type: Ty<'tcx>, + union_type_name: &str, + unique_type_id: UniqueTypeId, + containing_scope: &'ll DIScope, +) -> &'ll DICompositeType { let (union_size, union_align) = cx.size_and_align_of(union_type); let name = CString::new(union_type_name).unwrap(); @@ -1630,7 +1669,7 @@ fn create_union_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, union_size.bits(), union_align.abi_bits() as u32, DIFlags::FlagZero, - empty_array, + Some(empty_array), 0, // RuntimeLang unique_type_id.as_ptr()) }; @@ -1641,9 +1680,11 @@ fn create_union_stub<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, /// Creates debug information for the given global variable. /// /// Adds the created metadata nodes directly to the crate's IR. -pub fn create_global_var_metadata(cx: &CodegenCx, - def_id: DefId, - global: ValueRef) { +pub fn create_global_var_metadata( + cx: &CodegenCx<'ll, '_>, + def_id: DefId, + global: &'ll Value, +) { if cx.dbg_cx.is_none() { return; } @@ -1684,7 +1725,7 @@ pub fn create_global_var_metadata(cx: &CodegenCx, unsafe { llvm::LLVMRustDIBuilderCreateStaticVariable(DIB(cx), - var_scope, + Some(var_scope), var_name.as_ptr(), // If null, linkage_name field is omitted, // which is what we want for no_mangle statics @@ -1695,18 +1736,19 @@ pub fn create_global_var_metadata(cx: &CodegenCx, type_metadata, is_local_to_unit, global, - ptr::null_mut(), + None, global_align.abi() as u32, ); } } // Creates an "extension" of an existing DIScope into another file. -pub fn extend_scope_to_file(cx: &CodegenCx, - scope_metadata: DIScope, - file: &syntax_pos::FileMap, - defining_crate: CrateNum) - -> DILexicalBlock { +pub fn extend_scope_to_file( + cx: &CodegenCx<'ll, '_>, + scope_metadata: &'ll DIScope, + file: &syntax_pos::FileMap, + defining_crate: CrateNum, +) -> &'ll DILexicalBlock { let file_metadata = file_metadata(cx, &file.name, defining_crate); unsafe { llvm::LLVMRustDIBuilderCreateLexicalBlockFile( @@ -1720,9 +1762,11 @@ pub fn extend_scope_to_file(cx: &CodegenCx, /// given type. /// /// Adds the created metadata nodes directly to the crate's IR. -pub fn create_vtable_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - ty: ty::Ty<'tcx>, - vtable: ValueRef) { +pub fn create_vtable_metadata( + cx: &CodegenCx<'ll, 'tcx>, + ty: ty::Ty<'tcx>, + vtable: &'ll Value, +) { if cx.dbg_cx.is_none() { return; } @@ -1749,10 +1793,10 @@ pub fn create_vtable_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, Size::ZERO.bits(), cx.tcx.data_layout.pointer_align.abi_bits() as u32, DIFlags::FlagArtificial, - ptr::null_mut(), + None, empty_array, 0, - type_metadata, + Some(type_metadata), name.as_ptr() ); @@ -1771,7 +1815,7 @@ pub fn create_vtable_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, vtable_type, true, vtable, - ptr::null_mut(), + None, 0); } } diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index 9671db75baffe..143b122a5a172 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -21,8 +21,7 @@ use self::metadata::{type_metadata, file_metadata, TypeMap}; use self::source_loc::InternalDebugLocation::{self, UnknownLocation}; use llvm; -use llvm::{ModuleRef, ContextRef, ValueRef}; -use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray, DIFlags}; +use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilder, DISubprogram, DIArray, DIFlags}; use rustc::hir::CodegenFnAttrFlags; use rustc::hir::def_id::{DefId, CrateNum}; use rustc::ty::subst::{Substs, UnpackedKind}; @@ -35,11 +34,11 @@ use rustc::ty::{self, ParamEnv, Ty, InstanceDef}; use rustc::mir; use rustc::session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo}; use rustc::util::nodemap::{DefIdMap, FxHashMap, FxHashSet}; +use value::Value; use libc::c_uint; use std::cell::{Cell, RefCell}; use std::ffi::CString; -use std::ptr; use syntax_pos::{self, Span, Pos}; use syntax::ast; @@ -67,23 +66,31 @@ const DW_TAG_auto_variable: c_uint = 0x100; const DW_TAG_arg_variable: c_uint = 0x101; /// A context object for maintaining all state needed by the debuginfo module. -pub struct CrateDebugContext<'tcx> { - llcontext: ContextRef, - llmod: ModuleRef, - builder: DIBuilderRef, - created_files: RefCell>, - created_enum_disr_types: RefCell>, +pub struct CrateDebugContext<'a, 'tcx> { + llcontext: &'a llvm::Context, + llmod: &'a llvm::Module, + builder: &'a mut DIBuilder<'a>, + created_files: RefCell>, + created_enum_disr_types: RefCell>, - type_map: RefCell>, - namespace_map: RefCell>, + type_map: RefCell>, + namespace_map: RefCell>, // This collection is used to assert that composite types (structs, enums, // ...) have their members only set once: - composite_types_completed: RefCell>, + composite_types_completed: RefCell>, } -impl<'tcx> CrateDebugContext<'tcx> { - pub fn new(llmod: ModuleRef) -> CrateDebugContext<'tcx> { +impl Drop for CrateDebugContext<'a, 'tcx> { + fn drop(&mut self) { + unsafe { + llvm::LLVMRustDIBuilderDispose(&mut *(self.builder as *mut _)); + } + } +} + +impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> { + pub fn new(llmod: &'a llvm::Module) -> Self { debug!("CrateDebugContext::new"); let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) }; // DIBuilder inherits context from the module, so we'd better use the same one @@ -101,14 +108,14 @@ impl<'tcx> CrateDebugContext<'tcx> { } } -pub enum FunctionDebugContext { - RegularContext(FunctionDebugContextData), +pub enum FunctionDebugContext<'ll> { + RegularContext(FunctionDebugContextData<'ll>), DebugInfoDisabled, FunctionWithoutDebugInfo, } -impl FunctionDebugContext { - pub fn get_ref<'a>(&'a self, span: Span) -> &'a FunctionDebugContextData { +impl FunctionDebugContext<'ll> { + pub fn get_ref<'a>(&'a self, span: Span) -> &'a FunctionDebugContextData<'ll> { match *self { FunctionDebugContext::RegularContext(ref data) => data, FunctionDebugContext::DebugInfoDisabled => { @@ -130,18 +137,18 @@ impl FunctionDebugContext { } } -pub struct FunctionDebugContextData { - fn_metadata: DISubprogram, +pub struct FunctionDebugContextData<'ll> { + fn_metadata: &'ll DISubprogram, source_locations_enabled: Cell, pub defining_crate: CrateNum, } -pub enum VariableAccess<'a> { +pub enum VariableAccess<'a, 'll> { // The llptr given is an alloca containing the variable's value - DirectVariable { alloca: ValueRef }, + DirectVariable { alloca: &'ll Value }, // The llptr given is an alloca containing the start of some pointer chain // leading to the variable's content. - IndirectVariable { alloca: ValueRef, address_operations: &'a [i64] } + IndirectVariable { alloca: &'ll Value, address_operations: &'a [i64] } } pub enum VariableKind { @@ -167,7 +174,6 @@ pub fn finalize(cx: &CodegenCx) { unsafe { llvm::LLVMRustDIBuilderFinalize(DIB(cx)); - llvm::LLVMRustDIBuilderDispose(DIB(cx)); // Debuginfo generation in LLVM by default uses a higher // version of dwarf than macOS currently understands. We can // instruct LLVM to emit an older version of dwarf, however, @@ -201,11 +207,13 @@ pub fn finalize(cx: &CodegenCx) { /// for debug info creation. The function may also return another variant of the /// FunctionDebugContext enum which indicates why no debuginfo should be created /// for the function. -pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - instance: Instance<'tcx>, - sig: ty::FnSig<'tcx>, - llfn: ValueRef, - mir: &mir::Mir) -> FunctionDebugContext { +pub fn create_function_debug_context( + cx: &CodegenCx<'ll, 'tcx>, + instance: Instance<'tcx>, + sig: ty::FnSig<'tcx>, + llfn: &'ll Value, + mir: &mir::Mir, +) -> FunctionDebugContext<'ll> { if cx.sess().opts.debuginfo == NoDebugInfo { return FunctionDebugContext::DebugInfoDisabled; } @@ -290,7 +298,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, cx.sess().opts.optimize != config::OptLevel::No, llfn, template_parameters, - ptr::null_mut()) + None) }; // Initialize fn debug context (including scope map and namespace map) @@ -302,8 +310,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, return FunctionDebugContext::RegularContext(fn_debug_context); - fn get_function_signature<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - sig: ty::FnSig<'tcx>) -> DIArray { + fn get_function_signature( + cx: &CodegenCx<'ll, 'tcx>, + sig: ty::FnSig<'tcx>, + ) -> &'ll DIArray { if cx.sess().opts.debuginfo == LimitedDebugInfo { return create_DIArray(DIB(cx), &[]); } @@ -312,8 +322,8 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, // Return type -- llvm::DIBuilder wants this at index 0 signature.push(match sig.output().sty { - ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(), - _ => type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP) + ty::TyTuple(ref tys) if tys.is_empty() => None, + _ => Some(type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP)) }); let inputs = if sig.abi == Abi::RustCall { @@ -342,19 +352,20 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } _ => t }; - type_metadata(cx, t, syntax_pos::DUMMY_SP) + Some(type_metadata(cx, t, syntax_pos::DUMMY_SP)) })); } else { signature.extend(inputs.iter().map(|t| { - type_metadata(cx, t, syntax_pos::DUMMY_SP) + Some(type_metadata(cx, t, syntax_pos::DUMMY_SP)) })); } if sig.abi == Abi::RustCall && !sig.inputs().is_empty() { if let ty::TyTuple(args) = sig.inputs()[sig.inputs().len() - 1].sty { signature.extend( - args.iter().map(|argument_type| - type_metadata(cx, argument_type, syntax_pos::DUMMY_SP)) + args.iter().map(|argument_type| { + Some(type_metadata(cx, argument_type, syntax_pos::DUMMY_SP)) + }) ); } } @@ -362,13 +373,13 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, return create_DIArray(DIB(cx), &signature[..]); } - fn get_template_parameters<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - generics: &ty::Generics, - substs: &Substs<'tcx>, - file_metadata: DIFile, - name_to_append_suffix_to: &mut String) - -> DIArray - { + fn get_template_parameters( + cx: &CodegenCx<'ll, 'tcx>, + generics: &ty::Generics, + substs: &Substs<'tcx>, + file_metadata: &'ll DIFile, + name_to_append_suffix_to: &mut String, + ) -> &'ll DIArray { if substs.types().next().is_none() { return create_DIArray(DIB(cx), &[]); } @@ -398,14 +409,15 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, type_metadata(cx, actual_type, syntax_pos::DUMMY_SP); let name = CString::new(name.as_str().as_bytes()).unwrap(); Some(unsafe { - llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( + Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( DIB(cx), - ptr::null_mut(), + None, name.as_ptr(), actual_type_metadata, file_metadata, 0, - 0) + 0, + )) }) } else { None @@ -428,9 +440,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, names } - fn get_containing_scope<'cx, 'tcx>(cx: &CodegenCx<'cx, 'tcx>, - instance: Instance<'tcx>) - -> DIScope { + fn get_containing_scope( + cx: &CodegenCx<'ll, 'tcx>, + instance: Instance<'tcx>, + ) -> &'ll DIScope { // First, let's see if this is a method within an inherent impl. Because // if yes, we want to make the result subroutine DIE a child of the // subroutine's self-type. @@ -470,14 +483,16 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } } -pub fn declare_local<'a, 'tcx>(bx: &Builder<'a, 'tcx>, - dbg_context: &FunctionDebugContext, - variable_name: ast::Name, - variable_type: Ty<'tcx>, - scope_metadata: DIScope, - variable_access: VariableAccess, - variable_kind: VariableKind, - span: Span) { +pub fn declare_local( + bx: &Builder<'a, 'll, 'tcx>, + dbg_context: &FunctionDebugContext<'ll>, + variable_name: ast::Name, + variable_type: Ty<'tcx>, + scope_metadata: &'ll DIScope, + variable_access: VariableAccess<'_, 'll>, + variable_kind: VariableKind, + span: Span, +) { assert!(!dbg_context.get_ref(span).source_locations_enabled.get()); let cx = bx.cx; diff --git a/src/librustc_codegen_llvm/debuginfo/namespace.rs b/src/librustc_codegen_llvm/debuginfo/namespace.rs index 51c45de9dc22a..9f1141a7e7db0 100644 --- a/src/librustc_codegen_llvm/debuginfo/namespace.rs +++ b/src/librustc_codegen_llvm/debuginfo/namespace.rs @@ -22,7 +22,6 @@ use rustc::hir::map::DefPathData; use common::CodegenCx; use std::ffi::CString; -use std::ptr; pub fn mangled_name_of_instance<'a, 'tcx>( cx: &CodegenCx<'a, 'tcx>, @@ -32,13 +31,13 @@ pub fn mangled_name_of_instance<'a, 'tcx>( tcx.symbol_name(instance) } -pub fn item_namespace(cx: &CodegenCx, def_id: DefId) -> DIScope { +pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { if let Some(&scope) = debug_context(cx).namespace_map.borrow().get(&def_id) { return scope; } let def_key = cx.tcx.def_key(def_id); - let parent_scope = def_key.parent.map_or(ptr::null_mut(), |parent| { + let parent_scope = def_key.parent.map(|parent| { item_namespace(cx, DefId { krate: def_id.krate, index: parent diff --git a/src/librustc_codegen_llvm/debuginfo/source_loc.rs b/src/librustc_codegen_llvm/debuginfo/source_loc.rs index 958d09413edfa..55cf139394344 100644 --- a/src/librustc_codegen_llvm/debuginfo/source_loc.rs +++ b/src/librustc_codegen_llvm/debuginfo/source_loc.rs @@ -19,14 +19,16 @@ use llvm::debuginfo::DIScope; use builder::Builder; use libc::c_uint; -use std::ptr; use syntax_pos::{Span, Pos}; /// Sets the current debug location at the beginning of the span. /// /// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...). pub fn set_source_location( - debug_context: &FunctionDebugContext, bx: &Builder, scope: DIScope, span: Span + debug_context: &FunctionDebugContext<'ll>, + bx: &Builder<'_, 'll, '_>, + scope: Option<&'ll DIScope>, + span: Span, ) { let function_debug_context = match *debug_context { FunctionDebugContext::DebugInfoDisabled => return, @@ -40,7 +42,7 @@ pub fn set_source_location( let dbg_loc = if function_debug_context.source_locations_enabled.get() { debug!("set_source_location: {}", bx.sess().codemap().span_to_string(span)); let loc = span_start(bx.cx, span); - InternalDebugLocation::new(scope, loc.line, loc.col.to_usize()) + InternalDebugLocation::new(scope.unwrap(), loc.line, loc.col.to_usize()) } else { UnknownLocation }; @@ -53,7 +55,7 @@ pub fn set_source_location( /// they are disabled when beginning to codegen a new function. This functions /// switches source location emitting on and must therefore be called before the /// first real statement/expression of the function is codegened. -pub fn start_emitting_source_locations(dbg_context: &FunctionDebugContext) { +pub fn start_emitting_source_locations(dbg_context: &FunctionDebugContext<'ll>) { match *dbg_context { FunctionDebugContext::RegularContext(ref data) => { data.source_locations_enabled.set(true) @@ -64,13 +66,13 @@ pub fn start_emitting_source_locations(dbg_context: &FunctionDebugContext) { #[derive(Copy, Clone, PartialEq)] -pub enum InternalDebugLocation { - KnownLocation { scope: DIScope, line: usize, col: usize }, +pub enum InternalDebugLocation<'ll> { + KnownLocation { scope: &'ll DIScope, line: usize, col: usize }, UnknownLocation } -impl InternalDebugLocation { - pub fn new(scope: DIScope, line: usize, col: usize) -> InternalDebugLocation { +impl InternalDebugLocation<'ll> { + pub fn new(scope: &'ll DIScope, line: usize, col: usize) -> Self { KnownLocation { scope, line, @@ -79,7 +81,7 @@ impl InternalDebugLocation { } } -pub fn set_debug_location(bx: &Builder, debug_location: InternalDebugLocation) { +pub fn set_debug_location(bx: &Builder<'_, 'll, '_>, debug_location: InternalDebugLocation<'ll>) { let metadata_node = match debug_location { KnownLocation { scope, line, col } => { // For MSVC, set the column number to zero. @@ -93,17 +95,17 @@ pub fn set_debug_location(bx: &Builder, debug_location: InternalDebugLocation) { debug!("setting debug location to {} {}", line, col); unsafe { - llvm::LLVMRustDIBuilderCreateDebugLocation( + Some(llvm::LLVMRustDIBuilderCreateDebugLocation( debug_context(bx.cx).llcontext, line as c_uint, col_used, scope, - ptr::null_mut()) + None)) } } UnknownLocation => { debug!("clearing debug location "); - ptr::null_mut() + None } }; diff --git a/src/librustc_codegen_llvm/debuginfo/utils.rs b/src/librustc_codegen_llvm/debuginfo/utils.rs index 9d37f99cb2a59..9f4a555082ad4 100644 --- a/src/librustc_codegen_llvm/debuginfo/utils.rs +++ b/src/librustc_codegen_llvm/debuginfo/utils.rs @@ -17,7 +17,7 @@ use rustc::hir::def_id::DefId; use rustc::ty::DefIdTree; use llvm; -use llvm::debuginfo::{DIScope, DIBuilderRef, DIDescriptor, DIArray}; +use llvm::debuginfo::{DIScope, DIBuilder, DIDescriptor, DIArray}; use common::{CodegenCx}; use syntax_pos::{self, Span}; @@ -36,7 +36,10 @@ pub fn is_node_local_to_unit(cx: &CodegenCx, def_id: DefId) -> bool } #[allow(non_snake_case)] -pub fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray { +pub fn create_DIArray( + builder: &DIBuilder<'ll>, + arr: &[Option<&'ll DIDescriptor>], +) -> &'ll DIArray { return unsafe { llvm::LLVMRustDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32) }; @@ -48,18 +51,17 @@ pub fn span_start(cx: &CodegenCx, span: Span) -> syntax_pos::Loc { } #[inline] -pub fn debug_context<'a, 'tcx>(cx: &'a CodegenCx<'a, 'tcx>) - -> &'a CrateDebugContext<'tcx> { +pub fn debug_context(cx: &'a CodegenCx<'ll, 'tcx>) -> &'a CrateDebugContext<'ll, 'tcx> { cx.dbg_cx.as_ref().unwrap() } #[inline] #[allow(non_snake_case)] -pub fn DIB(cx: &CodegenCx) -> DIBuilderRef { +pub fn DIB(cx: &'a CodegenCx<'ll, '_>) -> &'a DIBuilder<'ll> { cx.dbg_cx.as_ref().unwrap().builder } -pub fn get_namespace_for_item(cx: &CodegenCx, def_id: DefId) -> DIScope { +pub fn get_namespace_for_item(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { item_namespace(cx, cx.tcx.parent(def_id) .expect("get_namespace_for_item: missing parent?")) } diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs index fdc84f914f502..9812d7f9a41a2 100644 --- a/src/librustc_codegen_llvm/declare.rs +++ b/src/librustc_codegen_llvm/declare.rs @@ -16,11 +16,11 @@ //! Some useful guidelines: //! //! * Use declare_* family of methods if you are declaring, but are not -//! interested in defining the ValueRef they return. -//! * Use define_* family of methods when you might be defining the ValueRef. +//! interested in defining the Value they return. +//! * Use define_* family of methods when you might be defining the Value. //! * When in doubt, define. -use llvm::{self, ValueRef}; +use llvm; use llvm::AttributePlace::Function; use rustc::ty::{self, Ty}; use rustc::ty::layout::{self, LayoutOf}; @@ -39,14 +39,14 @@ use std::ffi::CString; /// Declare a global value. /// /// If there’s a value with the same name already declared, the function will -/// return its ValueRef instead. -pub fn declare_global(cx: &CodegenCx, name: &str, ty: Type) -> llvm::ValueRef { +/// return its Value instead. +pub fn declare_global(cx: &CodegenCx<'ll, '_>, name: &str, ty: &'ll Type) -> &'ll Value { debug!("declare_global(name={:?})", name); let namebuf = CString::new(name).unwrap_or_else(|_|{ bug!("name {:?} contains an interior null byte", name) }); unsafe { - llvm::LLVMRustGetOrInsertGlobal(cx.llmod, namebuf.as_ptr(), ty.to_ref()) + llvm::LLVMRustGetOrInsertGlobal(cx.llmod, namebuf.as_ptr(), ty) } } @@ -54,14 +54,19 @@ pub fn declare_global(cx: &CodegenCx, name: &str, ty: Type) -> llvm::ValueRef { /// Declare a function. /// /// If there’s a value with the same name already declared, the function will -/// update the declaration and return existing ValueRef instead. -fn declare_raw_fn(cx: &CodegenCx, name: &str, callconv: llvm::CallConv, ty: Type) -> ValueRef { +/// update the declaration and return existing Value instead. +fn declare_raw_fn( + cx: &CodegenCx<'ll, '_>, + name: &str, + callconv: llvm::CallConv, + ty: &'ll Type, +) -> &'ll Value { debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty); let namebuf = CString::new(name).unwrap_or_else(|_|{ bug!("name {:?} contains an interior null byte", name) }); let llfn = unsafe { - llvm::LLVMRustGetOrInsertFunction(cx.llmod, namebuf.as_ptr(), ty.to_ref()) + llvm::LLVMRustGetOrInsertFunction(cx.llmod, namebuf.as_ptr(), ty) }; llvm::SetFunctionCallConv(llfn, callconv); @@ -114,8 +119,8 @@ fn declare_raw_fn(cx: &CodegenCx, name: &str, callconv: llvm::CallConv, ty: Type /// `declare_fn` instead. /// /// If there’s a value with the same name already declared, the function will -/// update the declaration and return existing ValueRef instead. -pub fn declare_cfn(cx: &CodegenCx, name: &str, fn_type: Type) -> ValueRef { +/// update the declaration and return existing Value instead. +pub fn declare_cfn(cx: &CodegenCx<'ll, '_>, name: &str, fn_type: &'ll Type) -> &'ll Value { declare_raw_fn(cx, name, llvm::CCallConv, fn_type) } @@ -123,9 +128,12 @@ pub fn declare_cfn(cx: &CodegenCx, name: &str, fn_type: Type) -> ValueRef { /// Declare a Rust function. /// /// If there’s a value with the same name already declared, the function will -/// update the declaration and return existing ValueRef instead. -pub fn declare_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, name: &str, - fn_type: Ty<'tcx>) -> ValueRef { +/// update the declaration and return existing Value instead. +pub fn declare_fn( + cx: &CodegenCx<'ll, 'tcx>, + name: &str, + fn_type: Ty<'tcx>, +) -> &'ll Value { debug!("declare_rust_fn(name={:?}, fn_type={:?})", name, fn_type); let sig = common::ty_fn_sig(cx, fn_type); let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); @@ -154,7 +162,7 @@ pub fn declare_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, name: &str, /// return None if the name already has a definition associated with it. In that /// case an error should be reported to the user, because it usually happens due /// to user’s fault (e.g. misuse of #[no_mangle] or #[export_name] attributes). -pub fn define_global(cx: &CodegenCx, name: &str, ty: Type) -> Option { +pub fn define_global(cx: &CodegenCx<'ll, '_>, name: &str, ty: &'ll Type) -> Option<&'ll Value> { if get_defined_value(cx, name).is_some() { None } else { @@ -167,9 +175,11 @@ pub fn define_global(cx: &CodegenCx, name: &str, ty: Type) -> Option { /// Use this function when you intend to define a function. This function will /// return panic if the name already has a definition associated with it. This /// can happen with #[no_mangle] or #[export_name], for example. -pub fn define_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - name: &str, - fn_type: Ty<'tcx>) -> ValueRef { +pub fn define_fn( + cx: &CodegenCx<'ll, 'tcx>, + name: &str, + fn_type: Ty<'tcx>, +) -> &'ll Value { if get_defined_value(cx, name).is_some() { cx.sess().fatal(&format!("symbol `{}` already defined", name)) } else { @@ -182,9 +192,11 @@ pub fn define_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, /// Use this function when you intend to define a function. This function will /// return panic if the name already has a definition associated with it. This /// can happen with #[no_mangle] or #[export_name], for example. -pub fn define_internal_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - name: &str, - fn_type: Ty<'tcx>) -> ValueRef { +pub fn define_internal_fn( + cx: &CodegenCx<'ll, 'tcx>, + name: &str, + fn_type: Ty<'tcx>, +) -> &'ll Value { let llfn = define_fn(cx, name, fn_type); unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) }; llfn @@ -192,24 +204,17 @@ pub fn define_internal_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, /// Get declared value by name. -pub fn get_declared_value(cx: &CodegenCx, name: &str) -> Option { +pub fn get_declared_value(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Value> { debug!("get_declared_value(name={:?})", name); let namebuf = CString::new(name).unwrap_or_else(|_|{ bug!("name {:?} contains an interior null byte", name) }); - let val = unsafe { llvm::LLVMRustGetNamedValue(cx.llmod, namebuf.as_ptr()) }; - if val.is_null() { - debug!("get_declared_value: {:?} value is null", name); - None - } else { - debug!("get_declared_value: {:?} => {:?}", name, Value(val)); - Some(val) - } + unsafe { llvm::LLVMRustGetNamedValue(cx.llmod, namebuf.as_ptr()) } } /// Get defined or externally defined (AvailableExternally linkage) value by /// name. -pub fn get_defined_value(cx: &CodegenCx, name: &str) -> Option { +pub fn get_defined_value(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Value> { get_declared_value(cx, name).and_then(|val|{ let declaration = unsafe { llvm::LLVMIsDeclaration(val) != 0 diff --git a/src/librustc_codegen_llvm/glue.rs b/src/librustc_codegen_llvm/glue.rs index c7275d0940185..37ce51da77823 100644 --- a/src/librustc_codegen_llvm/glue.rs +++ b/src/librustc_codegen_llvm/glue.rs @@ -16,37 +16,36 @@ use std; use builder::Builder; use common::*; -use llvm::{ValueRef}; use llvm; use meth; use rustc::ty::layout::LayoutOf; use rustc::ty::{self, Ty}; use value::Value; -pub fn size_and_align_of_dst<'a, 'tcx>(bx: &Builder<'a, 'tcx>, t: Ty<'tcx>, info: ValueRef) - -> (ValueRef, ValueRef) { +pub fn size_and_align_of_dst(bx: &Builder<'_, 'll, 'tcx>, t: Ty<'tcx>, info: Option<&'ll Value>) + -> (&'ll Value, &'ll Value) { debug!("calculate size of DST: {}; with lost info: {:?}", - t, Value(info)); + t, info); if bx.cx.type_is_sized(t) { let (size, align) = bx.cx.size_and_align_of(t); debug!("size_and_align_of_dst t={} info={:?} size: {:?} align: {:?}", - t, Value(info), size, align); + t, info, size, align); let size = C_usize(bx.cx, size.bytes()); let align = C_usize(bx.cx, align.abi()); return (size, align); } - assert!(!info.is_null()); match t.sty { ty::TyDynamic(..) => { // load size/align from vtable - (meth::SIZE.get_usize(bx, info), meth::ALIGN.get_usize(bx, info)) + let vtable = info.unwrap(); + (meth::SIZE.get_usize(bx, vtable), meth::ALIGN.get_usize(bx, vtable)) } ty::TySlice(_) | ty::TyStr => { let unit = t.sequence_element_type(bx.tcx()); // The info in this case is the length of the str, so the size is that // times the unit size. let (size, align) = bx.cx.size_and_align_of(unit); - (bx.mul(info, C_usize(bx.cx, size.bytes())), + (bx.mul(info.unwrap(), C_usize(bx.cx, size.bytes())), C_usize(bx.cx, align.abi())) } _ => { diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 9c5c0f730c161..06a5c34a4cae0 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -11,8 +11,7 @@ #![allow(non_upper_case_globals)] use intrinsics::{self, Intrinsic}; -use llvm; -use llvm::{ValueRef}; +use llvm::{self, TypeKind}; use abi::{Abi, FnType, LlvmType, PassMode}; use mir::place::PlaceRef; use mir::operand::{OperandRef, OperandValue}; @@ -28,6 +27,7 @@ use rustc::hir; use syntax::ast; use syntax::symbol::Symbol; use builder::Builder; +use value::Value; use rustc::session::Session; use syntax_pos::Span; @@ -35,7 +35,7 @@ use syntax_pos::Span; use std::cmp::Ordering; use std::iter; -fn get_simple_intrinsic(cx: &CodegenCx, name: &str) -> Option { +fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: &str) -> Option<&'ll Value> { let llvm_name = match name { "sqrtf32" => "llvm.sqrt.f32", "sqrtf64" => "llvm.sqrt.f64", @@ -85,12 +85,14 @@ fn get_simple_intrinsic(cx: &CodegenCx, name: &str) -> Option { /// Remember to add all intrinsics here, in librustc_typeck/check/mod.rs, /// and in libcore/intrinsics.rs; if you need access to any llvm intrinsics, /// add them to librustc_codegen_llvm/context.rs -pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, - callee_ty: Ty<'tcx>, - fn_ty: &FnType<'tcx, Ty<'tcx>>, - args: &[OperandRef<'tcx>], - llresult: ValueRef, - span: Span) { +pub fn codegen_intrinsic_call( + bx: &Builder<'a, 'll, 'tcx>, + callee_ty: Ty<'tcx>, + fn_ty: &FnType<'tcx, Ty<'tcx>>, + args: &[OperandRef<'ll, 'tcx>], + llresult: &'ll Value, + span: Span, +) { let cx = bx.cx; let tcx = cx.tcx; @@ -146,7 +148,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, let tp_ty = substs.type_at(0); if let OperandValue::Pair(_, meta) = args[0].val { let (llsize, _) = - glue::size_and_align_of_dst(bx, tp_ty, meta); + glue::size_and_align_of_dst(bx, tp_ty, Some(meta)); llsize } else { C_usize(cx, cx.size_of(tp_ty).bytes()) @@ -160,7 +162,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, let tp_ty = substs.type_at(0); if let OperandValue::Pair(_, meta) = args[0].val { let (_, llalign) = - glue::size_and_align_of_dst(bx, tp_ty, meta); + glue::size_and_align_of_dst(bx, tp_ty, Some(meta)); llalign } else { C_usize(cx, cx.align_of(tp_ty).abi()) @@ -545,7 +547,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, assert_eq!(x.len(), 1); x.into_iter().next().unwrap() } - fn ty_to_type(cx: &CodegenCx, t: &intrinsics::Type) -> Vec { + fn ty_to_type(cx: &CodegenCx<'ll, '_>, t: &intrinsics::Type) -> Vec<&'ll Type> { use intrinsics::Type::*; match *t { Void => vec![Type::void(cx)], @@ -567,7 +569,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, Vector(ref t, ref llvm_elem, length) => { let t = llvm_elem.as_ref().unwrap_or(t); let elem = one(ty_to_type(cx, t)); - vec![Type::vector(&elem, length as u64)] + vec![Type::vector(elem, length as u64)] } Aggregate(false, ref contents) => { let elems = contents.iter() @@ -587,11 +589,11 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, // qux` to be converted into `foo, bar, baz, qux`, integer // arguments to be truncated as needed and pointers to be // cast. - fn modify_as_needed<'a, 'tcx>(bx: &Builder<'a, 'tcx>, - t: &intrinsics::Type, - arg: &OperandRef<'tcx>) - -> Vec - { + fn modify_as_needed( + bx: &Builder<'a, 'll, 'tcx>, + t: &intrinsics::Type, + arg: &OperandRef<'ll, 'tcx>, + ) -> Vec<&'ll Value> { match *t { intrinsics::Type::Aggregate(true, ref contents) => { // We found a tuple that needs squishing! So @@ -616,7 +618,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, } intrinsics::Type::Vector(_, Some(ref llvm_elem), length) => { let llvm_elem = one(ty_to_type(bx.cx, llvm_elem)); - vec![bx.bitcast(arg.immediate(), Type::vector(&llvm_elem, length as u64))] + vec![bx.bitcast(arg.immediate(), Type::vector(llvm_elem, length as u64))] } intrinsics::Type::Integer(_, width, llvm_width) if width != llvm_width => { // the LLVM intrinsic uses a smaller integer @@ -644,7 +646,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, intrinsics::IntrinsicDef::Named(name) => { let f = declare::declare_cfn(cx, name, - Type::func(&inputs, &outputs)); + Type::func(&inputs, outputs)); bx.call(f, &llargs, None) } }; @@ -677,14 +679,15 @@ pub fn codegen_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, } } -fn copy_intrinsic<'a, 'tcx>(bx: &Builder<'a, 'tcx>, - allow_overlap: bool, - volatile: bool, - ty: Ty<'tcx>, - dst: ValueRef, - src: ValueRef, - count: ValueRef) - -> ValueRef { +fn copy_intrinsic( + bx: &Builder<'a, 'll, 'tcx>, + allow_overlap: bool, + volatile: bool, + ty: Ty<'tcx>, + dst: &'ll Value, + src: &'ll Value, + count: &'ll Value, +) -> &'ll Value { let cx = bx.cx; let (size, align) = cx.size_and_align_of(ty); let size = C_usize(cx, size.bytes()); @@ -712,14 +715,14 @@ fn copy_intrinsic<'a, 'tcx>(bx: &Builder<'a, 'tcx>, None) } -fn memset_intrinsic<'a, 'tcx>( - bx: &Builder<'a, 'tcx>, +fn memset_intrinsic( + bx: &Builder<'a, 'll, 'tcx>, volatile: bool, ty: Ty<'tcx>, - dst: ValueRef, - val: ValueRef, - count: ValueRef -) -> ValueRef { + dst: &'ll Value, + val: &'ll Value, + count: &'ll Value +) -> &'ll Value { let cx = bx.cx; let (size, align) = cx.size_and_align_of(ty); let size = C_usize(cx, size.bytes()); @@ -728,13 +731,13 @@ fn memset_intrinsic<'a, 'tcx>( call_memset(bx, dst, val, bx.mul(size, count), align, volatile) } -fn try_intrinsic<'a, 'tcx>( - bx: &Builder<'a, 'tcx>, - cx: &CodegenCx, - func: ValueRef, - data: ValueRef, - local_ptr: ValueRef, - dest: ValueRef, +fn try_intrinsic( + bx: &Builder<'a, 'll, 'tcx>, + cx: &CodegenCx<'ll, 'tcx>, + func: &'ll Value, + data: &'ll Value, + local_ptr: &'ll Value, + dest: &'ll Value, ) { if bx.sess().no_landing_pads() { bx.call(func, &[data], None); @@ -754,12 +757,14 @@ fn try_intrinsic<'a, 'tcx>( // instructions are meant to work for all targets, as of the time of this // writing, however, LLVM does not recommend the usage of these new instructions // as the old ones are still more optimized. -fn codegen_msvc_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>, - cx: &CodegenCx, - func: ValueRef, - data: ValueRef, - local_ptr: ValueRef, - dest: ValueRef) { +fn codegen_msvc_try( + bx: &Builder<'a, 'll, 'tcx>, + cx: &CodegenCx<'ll, 'tcx>, + func: &'ll Value, + data: &'ll Value, + local_ptr: &'ll Value, + dest: &'ll Value, +) { let llfn = get_rust_try_fn(cx, &mut |bx| { let cx = bx.cx; @@ -862,12 +867,14 @@ fn codegen_msvc_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>, // function calling it, and that function may already have other personality // functions in play. By calling a shim we're guaranteed that our shim will have // the right personality function. -fn codegen_gnu_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>, - cx: &CodegenCx, - func: ValueRef, - data: ValueRef, - local_ptr: ValueRef, - dest: ValueRef) { +fn codegen_gnu_try( + bx: &Builder<'a, 'll, 'tcx>, + cx: &CodegenCx<'ll, 'tcx>, + func: &'ll Value, + data: &'ll Value, + local_ptr: &'ll Value, + dest: &'ll Value, +) { let llfn = get_rust_try_fn(cx, &mut |bx| { let cx = bx.cx; @@ -922,12 +929,13 @@ fn codegen_gnu_try<'a, 'tcx>(bx: &Builder<'a, 'tcx>, // Helper function to give a Block to a closure to codegen a shim function. // This is currently primarily used for the `try` intrinsic functions above. -fn gen_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - name: &str, - inputs: Vec>, - output: Ty<'tcx>, - codegen: &mut dyn for<'b> FnMut(Builder<'b, 'tcx>)) - -> ValueRef { +fn gen_fn<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + name: &str, + inputs: Vec>, + output: Ty<'tcx>, + codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>), +) -> &'ll Value { let rust_fn_ty = cx.tcx.mk_fn_ptr(ty::Binder::bind(cx.tcx.mk_fn_sig( inputs.into_iter(), output, @@ -945,9 +953,10 @@ fn gen_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, // catch exceptions. // // This function is only generated once and is then cached. -fn get_rust_try_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - codegen: &mut dyn for<'b> FnMut(Builder<'b, 'tcx>)) - -> ValueRef { +fn get_rust_try_fn<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + codegen: &mut dyn FnMut(Builder<'_, 'll, 'tcx>), +) -> &'ll Value { if let Some(llfn) = cx.rust_try_fn.get() { return llfn; } @@ -972,15 +981,15 @@ fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) { span_err!(a, b, E0511, "{}", c); } -fn generic_simd_intrinsic<'a, 'tcx>( - bx: &Builder<'a, 'tcx>, +fn generic_simd_intrinsic( + bx: &Builder<'a, 'll, 'tcx>, name: &str, callee_ty: Ty<'tcx>, - args: &[OperandRef<'tcx>], + args: &[OperandRef<'ll, 'tcx>], ret_ty: Ty<'tcx>, - llret_ty: Type, + llret_ty: &'ll Type, span: Span -) -> Result { +) -> Result<&'ll Value, ()> { // macros for error handling: macro_rules! emit_error { ($msg: tt) => { @@ -1050,7 +1059,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( found `{}` with length {}", in_len, in_ty, ret_ty, out_len); - require!(llret_ty.element_type().kind() == llvm::Integer, + require!(llret_ty.element_type().kind() == TypeKind::Integer, "expected return type with integer elements, found `{}` with non-integer `{}`", ret_ty, ret_ty.simd_type(tcx)); @@ -1145,19 +1154,20 @@ fn generic_simd_intrinsic<'a, 'tcx>( } // truncate the mask to a vector of i1s let i1 = Type::i1(bx.cx); - let i1xn = Type::vector(&i1, m_len as u64); + let i1xn = Type::vector(i1, m_len as u64); let m_i1s = bx.trunc(args[0].immediate(), i1xn); return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate())); } - fn simd_simple_float_intrinsic<'a, 'tcx>(name: &str, - in_elem: &::rustc::ty::TyS, - in_ty: &::rustc::ty::TyS, - in_len: usize, - bx: &Builder<'a, 'tcx>, - span: Span, - args: &[OperandRef<'tcx>]) - -> Result { + fn simd_simple_float_intrinsic( + name: &str, + in_elem: &::rustc::ty::TyS, + in_ty: &::rustc::ty::TyS, + in_len: usize, + bx: &Builder<'a, 'll, 'tcx>, + span: Span, + args: &[OperandRef<'ll, 'tcx>], + ) -> Result<&'ll Value, ()> { macro_rules! emit_error { ($msg: tt) => { emit_error!($msg, ) @@ -1283,8 +1293,8 @@ fn generic_simd_intrinsic<'a, 'tcx>( } } - fn llvm_vector_ty(cx: &CodegenCx, elem_ty: ty::Ty, vec_len: usize, - mut no_pointers: usize) -> Type { + fn llvm_vector_ty(cx: &CodegenCx<'ll, '_>, elem_ty: ty::Ty, vec_len: usize, + mut no_pointers: usize) -> &'ll Type { // FIXME: use cx.layout_of(ty).llvm_type() ? let mut elem_ty = match elem_ty.sty { ty::TyInt(v) => Type::int_from_ty(cx, v), @@ -1296,7 +1306,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( elem_ty = elem_ty.ptr_to(); no_pointers -= 1; } - Type::vector(&elem_ty, vec_len as u64) + Type::vector(elem_ty, vec_len as u64) } @@ -1379,7 +1389,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( // Truncate the mask vector to a vector of i1s: let (mask, mask_ty) = { let i1 = Type::i1(bx.cx); - let i1xn = Type::vector(&i1, in_len as u64); + let i1xn = Type::vector(i1, in_len as u64); (bx.trunc(args[2].immediate(), i1xn), i1xn) }; @@ -1395,7 +1405,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( llvm_elem_vec_str, llvm_pointer_vec_str); let f = declare::declare_cfn(bx.cx, &llvm_intrinsic, Type::func(&[llvm_pointer_vec_ty, alignment_ty, mask_ty, - llvm_elem_vec_ty], &llvm_elem_vec_ty)); + llvm_elem_vec_ty], llvm_elem_vec_ty)); llvm::SetUnnamedAddr(f, false); let v = bx.call(f, &[args[1].immediate(), alignment, mask, args[0].immediate()], None); @@ -1476,7 +1486,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( // Truncate the mask vector to a vector of i1s: let (mask, mask_ty) = { let i1 = Type::i1(bx.cx); - let i1xn = Type::vector(&i1, in_len as u64); + let i1xn = Type::vector(i1, in_len as u64); (bx.trunc(args[2].immediate(), i1xn), i1xn) }; @@ -1496,7 +1506,7 @@ fn generic_simd_intrinsic<'a, 'tcx>( Type::func(&[llvm_elem_vec_ty, llvm_pointer_vec_ty, alignment_ty, - mask_ty], &ret_t)); + mask_ty], ret_t)); llvm::SetUnnamedAddr(f, false); let v = bx.call(f, &[args[0].immediate(), args[1].immediate(), alignment, mask], None); @@ -1629,7 +1639,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, // boolean reductions operate on vectors of i1s: let i1 = Type::i1(bx.cx); - let i1xn = Type::vector(&i1, in_len as u64); + let i1xn = Type::vector(i1, in_len as u64); bx.trunc(args[0].immediate(), i1xn) }; return match in_elem.sty { diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 90f96c9687bc1..724a2e3e65f42 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -20,8 +20,11 @@ #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(crate_visibility_modifier)] #![feature(custom_attribute)] +#![feature(extern_types)] #![feature(fs_read_write)] +#![feature(in_band_lifetimes)] #![allow(unused_attributes)] #![feature(libc)] #![feature(quote)] @@ -29,7 +32,11 @@ #![feature(rustc_diagnostic_macros)] #![feature(slice_sort_by_cached_key)] #![feature(optin_builtin_traits)] +#![feature(concat_idents)] +#![feature(link_args)] +#![feature(static_nobundle)] +use back::write::create_target_machine; use rustc::dep_graph::WorkProduct; use syntax_pos::symbol::Symbol; @@ -46,7 +53,7 @@ extern crate rustc_target; #[macro_use] extern crate rustc_data_structures; extern crate rustc_demangle; extern crate rustc_incremental; -extern crate rustc_llvm as llvm; +extern crate rustc_llvm; extern crate rustc_platform_intrinsics as intrinsics; extern crate rustc_codegen_utils; @@ -110,6 +117,7 @@ mod debuginfo; mod declare; mod glue; mod intrinsic; +pub mod llvm; mod llvm_util; mod metadata; mod meth; @@ -335,22 +343,41 @@ enum ModuleSource { Codegened(ModuleLlvm), } -#[derive(Debug)] struct ModuleLlvm { - llcx: llvm::ContextRef, - llmod: llvm::ModuleRef, - tm: llvm::TargetMachineRef, + llcx: &'static mut llvm::Context, + llmod_raw: *const llvm::Module, + tm: &'static mut llvm::TargetMachine, } unsafe impl Send for ModuleLlvm { } unsafe impl Sync for ModuleLlvm { } +impl ModuleLlvm { + fn new(sess: &Session, mod_name: &str) -> Self { + unsafe { + let llcx = llvm::LLVMRustContextCreate(sess.fewer_names()); + let llmod_raw = context::create_module(sess, llcx, mod_name) as *const _; + + ModuleLlvm { + llmod_raw, + llcx, + tm: create_target_machine(sess, false), + } + } + } + + fn llmod(&self) -> &llvm::Module { + unsafe { + &*self.llmod_raw + } + } +} + impl Drop for ModuleLlvm { fn drop(&mut self) { unsafe { - llvm::LLVMDisposeModule(self.llmod); - llvm::LLVMContextDispose(self.llcx); - llvm::LLVMRustDisposeTargetMachine(self.tm); + llvm::LLVMContextDispose(&mut *(self.llcx as *mut _)); + llvm::LLVMRustDisposeTargetMachine(&mut *(self.tm as *mut _)); } } } diff --git a/src/librustc_llvm/archive_ro.rs b/src/librustc_codegen_llvm/llvm/archive_ro.rs similarity index 69% rename from src/librustc_llvm/archive_ro.rs rename to src/librustc_codegen_llvm/llvm/archive_ro.rs index 9d8690072709b..4cbf0d92d7b99 100644 --- a/src/librustc_llvm/archive_ro.rs +++ b/src/librustc_codegen_llvm/llvm/archive_ro.rs @@ -10,28 +10,23 @@ //! A wrapper around LLVM's archive (.a) code -use ArchiveRef; - use std::ffi::CString; -use std::marker; use std::path::Path; use std::slice; use std::str; pub struct ArchiveRO { - ptr: ArchiveRef, + pub raw: &'static mut super::Archive, } unsafe impl Send for ArchiveRO {} pub struct Iter<'a> { - archive: &'a ArchiveRO, - ptr: ::ArchiveIteratorRef, + raw: &'a mut super::ArchiveIterator<'a>, } pub struct Child<'a> { - ptr: ::ArchiveChildRef, - _data: marker::PhantomData<&'a ArchiveRO>, + pub raw: &'a mut super::ArchiveChild<'a>, } impl ArchiveRO { @@ -44,12 +39,10 @@ impl ArchiveRO { pub fn open(dst: &Path) -> Result { return unsafe { let s = path2cstr(dst); - let ar = ::LLVMRustOpenArchive(s.as_ptr()); - if ar.is_null() { - Err(::last_error().unwrap_or("failed to open archive".to_string())) - } else { - Ok(ArchiveRO { ptr: ar }) - } + let ar = super::LLVMRustOpenArchive(s.as_ptr()).ok_or_else(|| { + super::last_error().unwrap_or("failed to open archive".to_string()) + })?; + Ok(ArchiveRO { raw: ar }) }; #[cfg(unix)] @@ -65,15 +58,10 @@ impl ArchiveRO { } } - pub fn raw(&self) -> ArchiveRef { - self.ptr - } - pub fn iter(&self) -> Iter { unsafe { Iter { - ptr: ::LLVMRustArchiveIteratorNew(self.ptr), - archive: self, + raw: super::LLVMRustArchiveIteratorNew(self.raw), } } } @@ -82,7 +70,7 @@ impl ArchiveRO { impl Drop for ArchiveRO { fn drop(&mut self) { unsafe { - ::LLVMRustDestroyArchive(self.ptr); + super::LLVMRustDestroyArchive(&mut *(self.raw as *mut _)); } } } @@ -91,14 +79,11 @@ impl<'a> Iterator for Iter<'a> { type Item = Result, String>; fn next(&mut self) -> Option, String>> { - let ptr = unsafe { ::LLVMRustArchiveIteratorNext(self.ptr) }; - if ptr.is_null() { - ::last_error().map(Err) - } else { - Some(Ok(Child { - ptr, - _data: marker::PhantomData, - })) + unsafe { + match super::LLVMRustArchiveIteratorNext(self.raw) { + Some(raw) => Some(Ok(Child { raw })), + None => super::last_error().map(Err), + } } } } @@ -106,7 +91,7 @@ impl<'a> Iterator for Iter<'a> { impl<'a> Drop for Iter<'a> { fn drop(&mut self) { unsafe { - ::LLVMRustArchiveIteratorFree(self.ptr); + super::LLVMRustArchiveIteratorFree(&mut *(self.raw as *mut _)); } } } @@ -115,7 +100,7 @@ impl<'a> Child<'a> { pub fn name(&self) -> Option<&'a str> { unsafe { let mut name_len = 0; - let name_ptr = ::LLVMRustArchiveChildName(self.ptr, &mut name_len); + let name_ptr = super::LLVMRustArchiveChildName(self.raw, &mut name_len); if name_ptr.is_null() { None } else { @@ -128,23 +113,19 @@ impl<'a> Child<'a> { pub fn data(&self) -> &'a [u8] { unsafe { let mut data_len = 0; - let data_ptr = ::LLVMRustArchiveChildData(self.ptr, &mut data_len); + let data_ptr = super::LLVMRustArchiveChildData(self.raw, &mut data_len); if data_ptr.is_null() { panic!("failed to read data from archive child"); } slice::from_raw_parts(data_ptr as *const u8, data_len as usize) } } - - pub fn raw(&self) -> ::ArchiveChildRef { - self.ptr - } } impl<'a> Drop for Child<'a> { fn drop(&mut self) { unsafe { - ::LLVMRustArchiveChildFree(self.ptr); + super::LLVMRustArchiveChildFree(&mut *(self.raw as *mut _)); } } } diff --git a/src/librustc_llvm/diagnostic.rs b/src/librustc_codegen_llvm/llvm/diagnostic.rs similarity index 77% rename from src/librustc_llvm/diagnostic.rs rename to src/librustc_codegen_llvm/llvm/diagnostic.rs index e73c570ed8231..7f2a9d6984a15 100644 --- a/src/librustc_llvm/diagnostic.rs +++ b/src/librustc_codegen_llvm/llvm/diagnostic.rs @@ -14,9 +14,9 @@ pub use self::OptimizationDiagnosticKind::*; pub use self::Diagnostic::*; use libc::c_uint; -use std::ptr; +use value::Value; -use {DiagnosticInfoRef, TwineRef, ValueRef}; +use super::{DiagnosticInfo, Twine}; #[derive(Copy, Clone)] pub enum OptimizationDiagnosticKind { @@ -42,21 +42,22 @@ impl OptimizationDiagnosticKind { } } -pub struct OptimizationDiagnostic { +pub struct OptimizationDiagnostic<'ll> { pub kind: OptimizationDiagnosticKind, pub pass_name: String, - pub function: ValueRef, + pub function: &'ll Value, pub line: c_uint, pub column: c_uint, pub filename: String, pub message: String, } -impl OptimizationDiagnostic { - unsafe fn unpack(kind: OptimizationDiagnosticKind, - di: DiagnosticInfoRef) - -> OptimizationDiagnostic { - let mut function = ptr::null_mut(); +impl OptimizationDiagnostic<'ll> { + unsafe fn unpack( + kind: OptimizationDiagnosticKind, + di: &'ll DiagnosticInfo, + ) -> Self { + let mut function = None; let mut line = 0; let mut column = 0; @@ -72,9 +73,9 @@ impl OptimizationDiagnostic { &mut column, filename, message) - ) - ) - ); + ).ok() + ).ok() + ).ok(); let mut filename = filename.unwrap_or(String::new()); if filename.is_empty() { @@ -84,7 +85,7 @@ impl OptimizationDiagnostic { OptimizationDiagnostic { kind, pass_name: pass_name.expect("got a non-UTF8 pass name from LLVM"), - function, + function: function.unwrap(), line, column, filename, @@ -94,41 +95,44 @@ impl OptimizationDiagnostic { } #[derive(Copy, Clone)] -pub struct InlineAsmDiagnostic { +pub struct InlineAsmDiagnostic<'ll> { pub cookie: c_uint, - pub message: TwineRef, - pub instruction: ValueRef, + pub message: &'ll Twine, + pub instruction: &'ll Value, } -impl InlineAsmDiagnostic { - unsafe fn unpack(di: DiagnosticInfoRef) -> InlineAsmDiagnostic { - - let mut opt = InlineAsmDiagnostic { - cookie: 0, - message: ptr::null_mut(), - instruction: ptr::null_mut(), - }; +impl InlineAsmDiagnostic<'ll> { + unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self { + let mut cookie = 0; + let mut message = None; + let mut instruction = None; - super::LLVMRustUnpackInlineAsmDiagnostic(di, - &mut opt.cookie, - &mut opt.message, - &mut opt.instruction); + super::LLVMRustUnpackInlineAsmDiagnostic( + di, + &mut cookie, + &mut message, + &mut instruction, + ); - opt + InlineAsmDiagnostic { + cookie, + message: message.unwrap(), + instruction: instruction.unwrap(), + } } } -pub enum Diagnostic { - Optimization(OptimizationDiagnostic), - InlineAsm(InlineAsmDiagnostic), - PGO(DiagnosticInfoRef), +pub enum Diagnostic<'ll> { + Optimization(OptimizationDiagnostic<'ll>), + InlineAsm(InlineAsmDiagnostic<'ll>), + PGO(&'ll DiagnosticInfo), /// LLVM has other types that we do not wrap here. - UnknownDiagnostic(DiagnosticInfoRef), + UnknownDiagnostic(&'ll DiagnosticInfo), } -impl Diagnostic { - pub unsafe fn unpack(di: DiagnosticInfoRef) -> Diagnostic { +impl Diagnostic<'ll> { + pub unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self { use super::DiagnosticKind as Dk; let kind = super::LLVMRustGetDiagInfoKind(di); diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs new file mode 100644 index 0000000000000..898d3d6735363 --- /dev/null +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -0,0 +1,1633 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// FIXME: Rename 'DIGlobalVariable' to 'DIGlobalVariableExpression' +// once support for LLVM 3.9 is dropped. +// +// This method was changed in this LLVM patch: +// https://reviews.llvm.org/D26769 + +use super::debuginfo::{ + DIBuilder, DIDescriptor, DIFile, DILexicalBlock, DISubprogram, DIType, + DIBasicType, DIDerivedType, DICompositeType, DIScope, DIVariable, + DIGlobalVariable, DIArray, DISubrange, DITemplateTypeParameter, DIEnumerator, + DINameSpace, DIFlags, +}; + +use libc::{c_uint, c_int, size_t, c_char}; +use libc::{c_ulonglong, c_void}; + +use std::marker::PhantomData; + +use super::RustString; + +pub type Bool = c_uint; + +pub const True: Bool = 1 as Bool; +pub const False: Bool = 0 as Bool; + +#[derive(Copy, Clone, PartialEq)] +#[repr(C)] +#[allow(dead_code)] // Variants constructed by C++. +pub enum LLVMRustResult { + Success, + Failure, +} +// Consts for the LLVM CallConv type, pre-cast to usize. + +/// LLVM CallingConv::ID. Should we wrap this? +#[derive(Copy, Clone, PartialEq, Debug)] +#[repr(C)] +pub enum CallConv { + CCallConv = 0, + FastCallConv = 8, + ColdCallConv = 9, + X86StdcallCallConv = 64, + X86FastcallCallConv = 65, + ArmAapcsCallConv = 67, + Msp430Intr = 69, + X86_ThisCall = 70, + PtxKernel = 71, + X86_64_SysV = 78, + X86_64_Win64 = 79, + X86_VectorCall = 80, + X86_Intr = 83, + AmdGpuKernel = 91, +} + +/// LLVMRustLinkage +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[repr(C)] +pub enum Linkage { + ExternalLinkage = 0, + AvailableExternallyLinkage = 1, + LinkOnceAnyLinkage = 2, + LinkOnceODRLinkage = 3, + WeakAnyLinkage = 4, + WeakODRLinkage = 5, + AppendingLinkage = 6, + InternalLinkage = 7, + PrivateLinkage = 8, + ExternalWeakLinkage = 9, + CommonLinkage = 10, +} + +// LLVMRustVisibility +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[repr(C)] +pub enum Visibility { + Default = 0, + Hidden = 1, + Protected = 2, +} + +/// LLVMDLLStorageClass +#[derive(Copy, Clone)] +#[repr(C)] +pub enum DLLStorageClass { + #[allow(dead_code)] + Default = 0, + DllImport = 1, // Function to be imported from DLL. + #[allow(dead_code)] + DllExport = 2, // Function to be accessible from DLL. +} + +/// Matches LLVMRustAttribute in rustllvm.h +/// Semantically a subset of the C++ enum llvm::Attribute::AttrKind, +/// though it is not ABI compatible (since it's a C++ enum) +#[repr(C)] +#[derive(Copy, Clone, Debug)] +pub enum Attribute { + AlwaysInline = 0, + ByVal = 1, + Cold = 2, + InlineHint = 3, + MinSize = 4, + Naked = 5, + NoAlias = 6, + NoCapture = 7, + NoInline = 8, + NonNull = 9, + NoRedZone = 10, + NoReturn = 11, + NoUnwind = 12, + OptimizeForSize = 13, + ReadOnly = 14, + SExt = 15, + StructRet = 16, + UWTable = 17, + ZExt = 18, + InReg = 19, + SanitizeThread = 20, + SanitizeAddress = 21, + SanitizeMemory = 22, +} + +/// LLVMIntPredicate +#[derive(Copy, Clone)] +#[repr(C)] +pub enum IntPredicate { + IntEQ = 32, + IntNE = 33, + IntUGT = 34, + IntUGE = 35, + IntULT = 36, + IntULE = 37, + IntSGT = 38, + IntSGE = 39, + IntSLT = 40, + IntSLE = 41, +} + +/// LLVMRealPredicate +#[derive(Copy, Clone)] +#[repr(C)] +pub enum RealPredicate { + RealPredicateFalse = 0, + RealOEQ = 1, + RealOGT = 2, + RealOGE = 3, + RealOLT = 4, + RealOLE = 5, + RealONE = 6, + RealORD = 7, + RealUNO = 8, + RealUEQ = 9, + RealUGT = 10, + RealUGE = 11, + RealULT = 12, + RealULE = 13, + RealUNE = 14, + RealPredicateTrue = 15, +} + +/// LLVMTypeKind +#[derive(Copy, Clone, PartialEq, Debug)] +#[repr(C)] +pub enum TypeKind { + Void = 0, + Half = 1, + Float = 2, + Double = 3, + X86_FP80 = 4, + FP128 = 5, + PPC_FP128 = 6, + Label = 7, + Integer = 8, + Function = 9, + Struct = 10, + Array = 11, + Pointer = 12, + Vector = 13, + Metadata = 14, + X86_MMX = 15, + Token = 16, +} + +/// LLVMAtomicRmwBinOp +#[derive(Copy, Clone)] +#[repr(C)] +pub enum AtomicRmwBinOp { + AtomicXchg = 0, + AtomicAdd = 1, + AtomicSub = 2, + AtomicAnd = 3, + AtomicNand = 4, + AtomicOr = 5, + AtomicXor = 6, + AtomicMax = 7, + AtomicMin = 8, + AtomicUMax = 9, + AtomicUMin = 10, +} + +/// LLVMAtomicOrdering +#[derive(Copy, Clone)] +#[repr(C)] +pub enum AtomicOrdering { + #[allow(dead_code)] + NotAtomic = 0, + Unordered = 1, + Monotonic = 2, + // Consume = 3, // Not specified yet. + Acquire = 4, + Release = 5, + AcquireRelease = 6, + SequentiallyConsistent = 7, +} + +/// LLVMRustSynchronizationScope +#[derive(Copy, Clone)] +#[repr(C)] +pub enum SynchronizationScope { + // FIXME: figure out if this variant is needed at all. + #[allow(dead_code)] + Other, + SingleThread, + CrossThread, +} + +/// LLVMRustFileType +#[derive(Copy, Clone)] +#[repr(C)] +pub enum FileType { + // FIXME: figure out if this variant is needed at all. + #[allow(dead_code)] + Other, + AssemblyFile, + ObjectFile, +} + +/// LLVMMetadataType +#[derive(Copy, Clone)] +#[repr(C)] +pub enum MetadataType { + MD_dbg = 0, + MD_tbaa = 1, + MD_prof = 2, + MD_fpmath = 3, + MD_range = 4, + MD_tbaa_struct = 5, + MD_invariant_load = 6, + MD_alias_scope = 7, + MD_noalias = 8, + MD_nontemporal = 9, + MD_mem_parallel_loop_access = 10, + MD_nonnull = 11, +} + +/// LLVMRustAsmDialect +#[derive(Copy, Clone)] +#[repr(C)] +pub enum AsmDialect { + // FIXME: figure out if this variant is needed at all. + #[allow(dead_code)] + Other, + Att, + Intel, +} + +/// LLVMRustCodeGenOptLevel +#[derive(Copy, Clone, PartialEq)] +#[repr(C)] +pub enum CodeGenOptLevel { + // FIXME: figure out if this variant is needed at all. + #[allow(dead_code)] + Other, + None, + Less, + Default, + Aggressive, +} + +/// LLVMRelocMode +#[derive(Copy, Clone, PartialEq)] +#[repr(C)] +pub enum RelocMode { + Default, + Static, + PIC, + DynamicNoPic, + ROPI, + RWPI, + ROPI_RWPI, +} + +/// LLVMRustCodeModel +#[derive(Copy, Clone)] +#[repr(C)] +pub enum CodeModel { + // FIXME: figure out if this variant is needed at all. + #[allow(dead_code)] + Other, + Small, + Kernel, + Medium, + Large, + None, +} + +/// LLVMRustDiagnosticKind +#[derive(Copy, Clone)] +#[repr(C)] +#[allow(dead_code)] // Variants constructed by C++. +pub enum DiagnosticKind { + Other, + InlineAsm, + StackSize, + DebugMetadataVersion, + SampleProfile, + OptimizationRemark, + OptimizationRemarkMissed, + OptimizationRemarkAnalysis, + OptimizationRemarkAnalysisFPCommute, + OptimizationRemarkAnalysisAliasing, + OptimizationRemarkOther, + OptimizationFailure, + PGOProfile, +} + +/// LLVMRustArchiveKind +#[derive(Copy, Clone)] +#[repr(C)] +pub enum ArchiveKind { + // FIXME: figure out if this variant is needed at all. + #[allow(dead_code)] + Other, + K_GNU, + K_BSD, + K_COFF, +} + +/// LLVMRustPassKind +#[derive(Copy, Clone, PartialEq, Debug)] +#[repr(C)] +#[allow(dead_code)] // Variants constructed by C++. +pub enum PassKind { + Other, + Function, + Module, +} + +/// LLVMRustThinLTOData +extern { pub type ThinLTOData; } + +/// LLVMRustThinLTOBuffer +extern { pub type ThinLTOBuffer; } + +/// LLVMRustThinLTOModule +#[repr(C)] +pub struct ThinLTOModule { + pub identifier: *const c_char, + pub data: *const u8, + pub len: usize, +} + +/// LLVMThreadLocalMode +#[derive(Copy, Clone)] +#[repr(C)] +pub enum ThreadLocalMode { + NotThreadLocal, + GeneralDynamic, + LocalDynamic, + InitialExec, + LocalExec +} + +extern { type Opaque; } +#[repr(C)] +struct InvariantOpaque<'a> { + _marker: PhantomData<&'a mut &'a ()>, + _opaque: Opaque, +} + +// Opaque pointer types +extern { pub type Module; } +extern { pub type Context; } +extern { pub type Type; } +extern { pub type Value; } +extern { pub type Metadata; } +extern { pub type BasicBlock; } +#[repr(C)] +pub struct Builder<'a>(InvariantOpaque<'a>); +extern { pub type MemoryBuffer; } +#[repr(C)] +pub struct PassManager<'a>(InvariantOpaque<'a>); +extern { pub type PassManagerBuilder; } +extern { pub type ObjectFile; } +#[repr(C)] +pub struct SectionIterator<'a>(InvariantOpaque<'a>); +extern { pub type Pass; } +extern { pub type TargetMachine; } +extern { pub type Archive; } +#[repr(C)] +pub struct ArchiveIterator<'a>(InvariantOpaque<'a>); +#[repr(C)] +pub struct ArchiveChild<'a>(InvariantOpaque<'a>); +extern { pub type Twine; } +extern { pub type DiagnosticInfo; } +extern { pub type SMDiagnostic; } +#[repr(C)] +pub struct RustArchiveMember<'a>(InvariantOpaque<'a>); +#[repr(C)] +pub struct OperandBundleDef<'a>(InvariantOpaque<'a>); +#[repr(C)] +pub struct Linker<'a>(InvariantOpaque<'a>); + +pub type DiagnosticHandler = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void); +pub type InlineAsmDiagHandler = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint); + + +pub mod debuginfo { + use super::{InvariantOpaque, Metadata}; + + #[repr(C)] + pub struct DIBuilder<'a>(InvariantOpaque<'a>); + + pub type DIDescriptor = Metadata; + pub type DIScope = DIDescriptor; + pub type DIFile = DIScope; + pub type DILexicalBlock = DIScope; + pub type DISubprogram = DIScope; + pub type DINameSpace = DIScope; + pub type DIType = DIDescriptor; + pub type DIBasicType = DIType; + pub type DIDerivedType = DIType; + pub type DICompositeType = DIDerivedType; + pub type DIVariable = DIDescriptor; + pub type DIGlobalVariable = DIDescriptor; + pub type DIArray = DIDescriptor; + pub type DISubrange = DIDescriptor; + pub type DIEnumerator = DIDescriptor; + pub type DITemplateTypeParameter = DIDescriptor; + + // These values **must** match with LLVMRustDIFlags!! + bitflags! { + #[repr(C)] + #[derive(Default)] + pub struct DIFlags: ::libc::uint32_t { + const FlagZero = 0; + const FlagPrivate = 1; + const FlagProtected = 2; + const FlagPublic = 3; + const FlagFwdDecl = (1 << 2); + const FlagAppleBlock = (1 << 3); + const FlagBlockByrefStruct = (1 << 4); + const FlagVirtual = (1 << 5); + const FlagArtificial = (1 << 6); + const FlagExplicit = (1 << 7); + const FlagPrototyped = (1 << 8); + const FlagObjcClassComplete = (1 << 9); + const FlagObjectPointer = (1 << 10); + const FlagVector = (1 << 11); + const FlagStaticMember = (1 << 12); + const FlagLValueReference = (1 << 13); + const FlagRValueReference = (1 << 14); + const FlagExternalTypeRef = (1 << 15); + const FlagIntroducedVirtual = (1 << 18); + const FlagBitField = (1 << 19); + const FlagNoReturn = (1 << 20); + const FlagMainSubprogram = (1 << 21); + } + } +} + +extern { pub type ModuleBuffer; } + +extern "C" { + // Create and destroy contexts. + pub fn LLVMRustContextCreate(shouldDiscardNames: bool) -> &'static mut Context; + pub fn LLVMContextDispose(C: &'static mut Context); + pub fn LLVMGetMDKindIDInContext(C: &Context, Name: *const c_char, SLen: c_uint) -> c_uint; + + // Create modules. + pub fn LLVMModuleCreateWithNameInContext(ModuleID: *const c_char, C: &Context) -> &Module; + pub fn LLVMGetModuleContext(M: &Module) -> &Context; + pub fn LLVMCloneModule(M: &Module) -> &Module; + + /// Data layout. See Module::getDataLayout. + pub fn LLVMGetDataLayout(M: &Module) -> *const c_char; + pub fn LLVMSetDataLayout(M: &Module, Triple: *const c_char); + + /// See Module::setModuleInlineAsm. + pub fn LLVMSetModuleInlineAsm(M: &Module, Asm: *const c_char); + pub fn LLVMRustAppendModuleInlineAsm(M: &Module, Asm: *const c_char); + + /// See llvm::LLVMTypeKind::getTypeID. + pub fn LLVMRustGetTypeKind(Ty: &Type) -> TypeKind; + + // Operations on integer types + pub fn LLVMInt1TypeInContext(C: &Context) -> &Type; + pub fn LLVMInt8TypeInContext(C: &Context) -> &Type; + pub fn LLVMInt16TypeInContext(C: &Context) -> &Type; + pub fn LLVMInt32TypeInContext(C: &Context) -> &Type; + pub fn LLVMInt64TypeInContext(C: &Context) -> &Type; + pub fn LLVMIntTypeInContext(C: &Context, NumBits: c_uint) -> &Type; + + pub fn LLVMGetIntTypeWidth(IntegerTy: &Type) -> c_uint; + + // Operations on real types + pub fn LLVMFloatTypeInContext(C: &Context) -> &Type; + pub fn LLVMDoubleTypeInContext(C: &Context) -> &Type; + + // Operations on function types + pub fn LLVMFunctionType(ReturnType: &'a Type, + ParamTypes: *const &'a Type, + ParamCount: c_uint, + IsVarArg: Bool) + -> &'a Type; + pub fn LLVMCountParamTypes(FunctionTy: &Type) -> c_uint; + pub fn LLVMGetParamTypes(FunctionTy: &'a Type, Dest: *mut &'a Type); + + // Operations on struct types + pub fn LLVMStructTypeInContext(C: &'a Context, + ElementTypes: *const &'a Type, + ElementCount: c_uint, + Packed: Bool) + -> &'a Type; + + // Operations on array, pointer, and vector types (sequence types) + pub fn LLVMRustArrayType(ElementType: &Type, ElementCount: u64) -> &Type; + pub fn LLVMPointerType(ElementType: &Type, AddressSpace: c_uint) -> &Type; + pub fn LLVMVectorType(ElementType: &Type, ElementCount: c_uint) -> &Type; + + pub fn LLVMGetElementType(Ty: &Type) -> &Type; + pub fn LLVMGetVectorSize(VectorTy: &Type) -> c_uint; + + // Operations on other types + pub fn LLVMVoidTypeInContext(C: &Context) -> &Type; + pub fn LLVMX86MMXTypeInContext(C: &Context) -> &Type; + pub fn LLVMRustMetadataTypeInContext(C: &Context) -> &Type; + + // Operations on all values + pub fn LLVMTypeOf(Val: &Value) -> &Type; + pub fn LLVMGetValueName(Val: &Value) -> *const c_char; + pub fn LLVMSetValueName(Val: &Value, Name: *const c_char); + pub fn LLVMReplaceAllUsesWith(OldVal: &'a Value, NewVal: &'a Value); + pub fn LLVMSetMetadata(Val: &'a Value, KindID: c_uint, Node: &'a Value); + + // Operations on constants of any type + pub fn LLVMConstNull(Ty: &Type) -> &Value; + pub fn LLVMGetUndef(Ty: &Type) -> &Value; + + // Operations on metadata + pub fn LLVMMDStringInContext(C: &Context, Str: *const c_char, SLen: c_uint) -> &Value; + pub fn LLVMMDNodeInContext(C: &'a Context, Vals: *const &'a Value, Count: c_uint) -> &'a Value; + pub fn LLVMAddNamedMetadataOperand(M: &'a Module, Name: *const c_char, Val: &'a Value); + + // Operations on scalar constants + pub fn LLVMConstInt(IntTy: &Type, N: c_ulonglong, SignExtend: Bool) -> &Value; + pub fn LLVMConstIntOfArbitraryPrecision(IntTy: &Type, Wn: c_uint, Ws: *const u64) -> &Value; + pub fn LLVMConstIntGetZExtValue(ConstantVal: &Value) -> c_ulonglong; + pub fn LLVMRustConstInt128Get(ConstantVal: &Value, SExt: bool, + high: &mut u64, low: &mut u64) -> bool; + pub fn LLVMConstRealGetDouble (ConstantVal: &Value, losesInfo: &mut Bool) -> f64; + + + // Operations on composite constants + pub fn LLVMConstStringInContext(C: &Context, + Str: *const c_char, + Length: c_uint, + DontNullTerminate: Bool) + -> &Value; + pub fn LLVMConstStructInContext(C: &'a Context, + ConstantVals: *const &'a Value, + Count: c_uint, + Packed: Bool) + -> &'a Value; + + pub fn LLVMConstArray(ElementTy: &'a Type, + ConstantVals: *const &'a Value, + Length: c_uint) + -> &'a Value; + pub fn LLVMConstVector(ScalarConstantVals: *const &Value, Size: c_uint) -> &Value; + + // Constant expressions + pub fn LLVMConstInBoundsGEP( + ConstantVal: &'a Value, + ConstantIndices: *const &'a Value, + NumIndices: c_uint, + ) -> &'a Value; + pub fn LLVMConstZExt(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; + pub fn LLVMConstPtrToInt(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; + pub fn LLVMConstIntToPtr(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; + pub fn LLVMConstBitCast(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; + pub fn LLVMConstPointerCast(ConstantVal: &'a Value, ToType: &'a Type) -> &'a Value; + pub fn LLVMConstExtractValue(AggConstant: &Value, + IdxList: *const c_uint, + NumIdx: c_uint) + -> &Value; + + // Operations on global variables, functions, and aliases (globals) + pub fn LLVMIsDeclaration(Global: &Value) -> Bool; + pub fn LLVMRustGetLinkage(Global: &Value) -> Linkage; + pub fn LLVMRustSetLinkage(Global: &Value, RustLinkage: Linkage); + pub fn LLVMSetSection(Global: &Value, Section: *const c_char); + pub fn LLVMRustGetVisibility(Global: &Value) -> Visibility; + pub fn LLVMRustSetVisibility(Global: &Value, Viz: Visibility); + pub fn LLVMGetAlignment(Global: &Value) -> c_uint; + pub fn LLVMSetAlignment(Global: &Value, Bytes: c_uint); + pub fn LLVMSetDLLStorageClass(V: &Value, C: DLLStorageClass); + + + // Operations on global variables + pub fn LLVMIsAGlobalVariable(GlobalVar: &Value) -> Option<&Value>; + pub fn LLVMAddGlobal(M: &'a Module, Ty: &'a Type, Name: *const c_char) -> &'a Value; + pub fn LLVMGetNamedGlobal(M: &Module, Name: *const c_char) -> Option<&Value>; + pub fn LLVMRustGetOrInsertGlobal(M: &'a Module, Name: *const c_char, T: &'a Type) -> &'a Value; + pub fn LLVMGetFirstGlobal(M: &Module) -> Option<&Value>; + pub fn LLVMGetNextGlobal(GlobalVar: &Value) -> Option<&Value>; + pub fn LLVMDeleteGlobal(GlobalVar: &Value); + pub fn LLVMGetInitializer(GlobalVar: &Value) -> Option<&Value>; + pub fn LLVMSetInitializer(GlobalVar: &'a Value, ConstantVal: &'a Value); + pub fn LLVMSetThreadLocal(GlobalVar: &Value, IsThreadLocal: Bool); + pub fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode); + pub fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool; + pub fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool); + pub fn LLVMRustGetNamedValue(M: &Module, Name: *const c_char) -> Option<&Value>; + pub fn LLVMSetTailCall(CallInst: &Value, IsTailCall: Bool); + + // Operations on functions + pub fn LLVMRustGetOrInsertFunction(M: &'a Module, + Name: *const c_char, + FunctionTy: &'a Type) + -> &'a Value; + pub fn LLVMSetFunctionCallConv(Fn: &Value, CC: c_uint); + pub fn LLVMRustAddAlignmentAttr(Fn: &Value, index: c_uint, bytes: u32); + pub fn LLVMRustAddDereferenceableAttr(Fn: &Value, index: c_uint, bytes: u64); + pub fn LLVMRustAddDereferenceableOrNullAttr(Fn: &Value, index: c_uint, bytes: u64); + pub fn LLVMRustAddFunctionAttribute(Fn: &Value, index: c_uint, attr: Attribute); + pub fn LLVMRustAddFunctionAttrStringValue(Fn: &Value, + index: c_uint, + Name: *const c_char, + Value: *const c_char); + pub fn LLVMRustRemoveFunctionAttributes(Fn: &Value, index: c_uint, attr: Attribute); + + // Operations on parameters + pub fn LLVMCountParams(Fn: &Value) -> c_uint; + pub fn LLVMGetParam(Fn: &Value, Index: c_uint) -> &Value; + + // Operations on basic blocks + pub fn LLVMGetBasicBlockParent(BB: &BasicBlock) -> &Value; + pub fn LLVMAppendBasicBlockInContext(C: &'a Context, + Fn: &'a Value, + Name: *const c_char) + -> &'a BasicBlock; + pub fn LLVMDeleteBasicBlock(BB: &BasicBlock); + + // Operations on instructions + pub fn LLVMGetFirstBasicBlock(Fn: &Value) -> &BasicBlock; + + // Operations on call sites + pub fn LLVMSetInstructionCallConv(Instr: &Value, CC: c_uint); + pub fn LLVMRustAddCallSiteAttribute(Instr: &Value, index: c_uint, attr: Attribute); + pub fn LLVMRustAddAlignmentCallSiteAttr(Instr: &Value, index: c_uint, bytes: u32); + pub fn LLVMRustAddDereferenceableCallSiteAttr(Instr: &Value, index: c_uint, bytes: u64); + pub fn LLVMRustAddDereferenceableOrNullCallSiteAttr(Instr: &Value, + index: c_uint, + bytes: u64); + + // Operations on load/store instructions (only) + pub fn LLVMSetVolatile(MemoryAccessInst: &Value, volatile: Bool); + + // Operations on phi nodes + pub fn LLVMAddIncoming(PhiNode: &'a Value, + IncomingValues: *const &'a Value, + IncomingBlocks: *const &'a BasicBlock, + Count: c_uint); + + // Instruction builders + pub fn LLVMCreateBuilderInContext(C: &'a Context) -> &'a mut Builder<'a>; + pub fn LLVMPositionBuilderAtEnd(Builder: &Builder<'a>, Block: &'a BasicBlock); + pub fn LLVMGetInsertBlock(Builder: &Builder<'a>) -> &'a BasicBlock; + pub fn LLVMDisposeBuilder(Builder: &'a mut Builder<'a>); + + // Metadata + pub fn LLVMSetCurrentDebugLocation(Builder: &Builder<'a>, L: Option<&'a Value>); + pub fn LLVMGetCurrentDebugLocation(Builder: &Builder<'a>) -> &'a Value; + pub fn LLVMSetInstDebugLocation(Builder: &Builder<'a>, Inst: &'a Value); + + // Terminators + pub fn LLVMBuildRetVoid(B: &Builder<'a>) -> &'a Value; + pub fn LLVMBuildRet(B: &Builder<'a>, V: &'a Value) -> &'a Value; + pub fn LLVMBuildBr(B: &Builder<'a>, Dest: &'a BasicBlock) -> &'a Value; + pub fn LLVMBuildCondBr(B: &Builder<'a>, + If: &'a Value, + Then: &'a BasicBlock, + Else: &'a BasicBlock) + -> &'a Value; + pub fn LLVMBuildSwitch(B: &Builder<'a>, + V: &'a Value, + Else: &'a BasicBlock, + NumCases: c_uint) + -> &'a Value; + pub fn LLVMRustBuildInvoke(B: &Builder<'a>, + Fn: &'a Value, + Args: *const &'a Value, + NumArgs: c_uint, + Then: &'a BasicBlock, + Catch: &'a BasicBlock, + Bundle: Option<&OperandBundleDef<'a>>, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildLandingPad(B: &Builder<'a>, + Ty: &'a Type, + PersFn: &'a Value, + NumClauses: c_uint, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildResume(B: &Builder<'a>, Exn: &'a Value) -> &'a Value; + pub fn LLVMBuildUnreachable(B: &Builder<'a>) -> &'a Value; + + pub fn LLVMRustBuildCleanupPad(B: &Builder<'a>, + ParentPad: Option<&'a Value>, + ArgCnt: c_uint, + Args: *const &'a Value, + Name: *const c_char) + -> Option<&'a Value>; + pub fn LLVMRustBuildCleanupRet(B: &Builder<'a>, + CleanupPad: &'a Value, + UnwindBB: Option<&'a BasicBlock>) + -> Option<&'a Value>; + pub fn LLVMRustBuildCatchPad(B: &Builder<'a>, + ParentPad: &'a Value, + ArgCnt: c_uint, + Args: *const &'a Value, + Name: *const c_char) + -> Option<&'a Value>; + pub fn LLVMRustBuildCatchRet( + B: &Builder<'a>, + Pad: &'a Value, + BB: &'a BasicBlock, + ) -> Option<&'a Value>; + pub fn LLVMRustBuildCatchSwitch(Builder: &Builder<'a>, + ParentPad: Option<&'a Value>, + BB: Option<&'a BasicBlock>, + NumHandlers: c_uint, + Name: *const c_char) + -> Option<&'a Value>; + pub fn LLVMRustAddHandler(CatchSwitch: &'a Value, Handler: &'a BasicBlock); + pub fn LLVMSetPersonalityFn(Func: &'a Value, Pers: &'a Value); + + // Add a case to the switch instruction + pub fn LLVMAddCase(Switch: &'a Value, OnVal: &'a Value, Dest: &'a BasicBlock); + + // Add a clause to the landing pad instruction + pub fn LLVMAddClause(LandingPad: &'a Value, ClauseVal: &'a Value); + + // Set the cleanup on a landing pad instruction + pub fn LLVMSetCleanup(LandingPad: &Value, Val: Bool); + + // Arithmetic + pub fn LLVMBuildAdd(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildFAdd(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildSub(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildFSub(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildMul(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildFMul(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildUDiv(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildExactUDiv(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildSDiv(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildExactSDiv(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildFDiv(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildURem(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildSRem(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildFRem(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildShl(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildLShr(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildAShr(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildAnd(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildOr(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildXor(B: &Builder<'a>, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildNeg(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; + pub fn LLVMBuildFNeg(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; + pub fn LLVMBuildNot(B: &Builder<'a>, V: &'a Value, Name: *const c_char) -> &'a Value; + pub fn LLVMRustSetHasUnsafeAlgebra(Instr: &Value); + + // Memory + pub fn LLVMBuildAlloca(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value; + pub fn LLVMBuildLoad(B: &Builder<'a>, PointerVal: &'a Value, Name: *const c_char) -> &'a Value; + + pub fn LLVMBuildStore(B: &Builder<'a>, Val: &'a Value, Ptr: &'a Value) -> &'a Value; + + pub fn LLVMBuildGEP(B: &Builder<'a>, + Pointer: &'a Value, + Indices: *const &'a Value, + NumIndices: c_uint, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildInBoundsGEP(B: &Builder<'a>, + Pointer: &'a Value, + Indices: *const &'a Value, + NumIndices: c_uint, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildStructGEP(B: &Builder<'a>, + Pointer: &'a Value, + Idx: c_uint, + Name: *const c_char) + -> &'a Value; + + // Casts + pub fn LLVMBuildTrunc(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildZExt(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildSExt(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildFPToUI(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildFPToSI(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildUIToFP(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildSIToFP(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildFPTrunc(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildFPExt(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildPtrToInt(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildIntToPtr(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildBitCast(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildPointerCast(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMRustBuildIntCast(B: &Builder<'a>, + Val: &'a Value, + DestTy: &'a Type, + IsSized: bool) + -> &'a Value; + + // Comparisons + pub fn LLVMBuildICmp(B: &Builder<'a>, + Op: c_uint, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildFCmp(B: &Builder<'a>, + Op: c_uint, + LHS: &'a Value, + RHS: &'a Value, + Name: *const c_char) + -> &'a Value; + + // Miscellaneous instructions + pub fn LLVMBuildPhi(B: &Builder<'a>, Ty: &'a Type, Name: *const c_char) -> &'a Value; + pub fn LLVMRustBuildCall(B: &Builder<'a>, + Fn: &'a Value, + Args: *const &'a Value, + NumArgs: c_uint, + Bundle: Option<&OperandBundleDef<'a>>, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildSelect(B: &Builder<'a>, + If: &'a Value, + Then: &'a Value, + Else: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildVAArg(B: &Builder<'a>, + list: &'a Value, + Ty: &'a Type, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildExtractElement(B: &Builder<'a>, + VecVal: &'a Value, + Index: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildInsertElement(B: &Builder<'a>, + VecVal: &'a Value, + EltVal: &'a Value, + Index: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildShuffleVector(B: &Builder<'a>, + V1: &'a Value, + V2: &'a Value, + Mask: &'a Value, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildExtractValue(B: &Builder<'a>, + AggVal: &'a Value, + Index: c_uint, + Name: *const c_char) + -> &'a Value; + pub fn LLVMBuildInsertValue(B: &Builder<'a>, + AggVal: &'a Value, + EltVal: &'a Value, + Index: c_uint, + Name: *const c_char) + -> &'a Value; + + pub fn LLVMRustBuildVectorReduceFAdd(B: &Builder<'a>, + Acc: &'a Value, + Src: &'a Value) + -> Option<&'a Value>; + pub fn LLVMRustBuildVectorReduceFMul(B: &Builder<'a>, + Acc: &'a Value, + Src: &'a Value) + -> Option<&'a Value>; + pub fn LLVMRustBuildVectorReduceAdd(B: &Builder<'a>, + Src: &'a Value) + -> Option<&'a Value>; + pub fn LLVMRustBuildVectorReduceMul(B: &Builder<'a>, + Src: &'a Value) + -> Option<&'a Value>; + pub fn LLVMRustBuildVectorReduceAnd(B: &Builder<'a>, + Src: &'a Value) + -> Option<&'a Value>; + pub fn LLVMRustBuildVectorReduceOr(B: &Builder<'a>, + Src: &'a Value) + -> Option<&'a Value>; + pub fn LLVMRustBuildVectorReduceXor(B: &Builder<'a>, + Src: &'a Value) + -> Option<&'a Value>; + pub fn LLVMRustBuildVectorReduceMin(B: &Builder<'a>, + Src: &'a Value, + IsSigned: bool) + -> Option<&'a Value>; + pub fn LLVMRustBuildVectorReduceMax(B: &Builder<'a>, + Src: &'a Value, + IsSigned: bool) + -> Option<&'a Value>; + pub fn LLVMRustBuildVectorReduceFMin(B: &Builder<'a>, + Src: &'a Value, + IsNaN: bool) + -> Option<&'a Value>; + pub fn LLVMRustBuildVectorReduceFMax(B: &Builder<'a>, + Src: &'a Value, + IsNaN: bool) + -> Option<&'a Value>; + + pub fn LLVMRustBuildMinNum( + B: &Builder<'a>, + LHS: &'a Value, + LHS: &'a Value, + ) -> Option<&'a Value>; + pub fn LLVMRustBuildMaxNum( + B: &Builder<'a>, + LHS: &'a Value, + LHS: &'a Value, + ) -> Option<&'a Value>; + + // Atomic Operations + pub fn LLVMRustBuildAtomicLoad(B: &Builder<'a>, + PointerVal: &'a Value, + Name: *const c_char, + Order: AtomicOrdering) + -> &'a Value; + + pub fn LLVMRustBuildAtomicStore(B: &Builder<'a>, + Val: &'a Value, + Ptr: &'a Value, + Order: AtomicOrdering) + -> &'a Value; + + pub fn LLVMRustBuildAtomicCmpXchg(B: &Builder<'a>, + LHS: &'a Value, + CMP: &'a Value, + RHS: &'a Value, + Order: AtomicOrdering, + FailureOrder: AtomicOrdering, + Weak: Bool) + -> &'a Value; + + pub fn LLVMBuildAtomicRMW(B: &Builder<'a>, + Op: AtomicRmwBinOp, + LHS: &'a Value, + RHS: &'a Value, + Order: AtomicOrdering, + SingleThreaded: Bool) + -> &'a Value; + + pub fn LLVMRustBuildAtomicFence(B: &Builder, + Order: AtomicOrdering, + Scope: SynchronizationScope); + + /// Writes a module to the specified path. Returns 0 on success. + pub fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int; + + /// Creates a pass manager. + pub fn LLVMCreatePassManager() -> &'a mut PassManager<'a>; + + /// Creates a function-by-function pass manager + pub fn LLVMCreateFunctionPassManagerForModule(M: &'a Module) -> &'a mut PassManager<'a>; + + /// Disposes a pass manager. + pub fn LLVMDisposePassManager(PM: &'a mut PassManager<'a>); + + /// Runs a pass manager on a module. + pub fn LLVMRunPassManager(PM: &PassManager<'a>, M: &'a Module) -> Bool; + + pub fn LLVMInitializePasses(); + + pub fn LLVMPassManagerBuilderCreate() -> &'static mut PassManagerBuilder; + pub fn LLVMPassManagerBuilderDispose(PMB: &'static mut PassManagerBuilder); + pub fn LLVMPassManagerBuilderSetSizeLevel(PMB: &PassManagerBuilder, Value: Bool); + pub fn LLVMPassManagerBuilderSetDisableUnrollLoops(PMB: &PassManagerBuilder, Value: Bool); + pub fn LLVMPassManagerBuilderUseInlinerWithThreshold(PMB: &PassManagerBuilder, + threshold: c_uint); + pub fn LLVMPassManagerBuilderPopulateModulePassManager(PMB: &PassManagerBuilder, + PM: &PassManager); + + pub fn LLVMPassManagerBuilderPopulateFunctionPassManager(PMB: &PassManagerBuilder, + PM: &PassManager); + pub fn LLVMPassManagerBuilderPopulateLTOPassManager(PMB: &PassManagerBuilder, + PM: &PassManager, + Internalize: Bool, + RunInliner: Bool); + pub fn LLVMRustPassManagerBuilderPopulateThinLTOPassManager( + PMB: &PassManagerBuilder, + PM: &PassManager) -> bool; + + // Stuff that's in rustllvm/ because it's not upstream yet. + + /// Opens an object file. + pub fn LLVMCreateObjectFile( + MemBuf: &'static mut MemoryBuffer, + ) -> Option<&'static mut ObjectFile>; + /// Closes an object file. + pub fn LLVMDisposeObjectFile(ObjFile: &'static mut ObjectFile); + + /// Enumerates the sections in an object file. + pub fn LLVMGetSections(ObjFile: &'a ObjectFile) -> &'a mut SectionIterator<'a>; + /// Destroys a section iterator. + pub fn LLVMDisposeSectionIterator(SI: &'a mut SectionIterator<'a>); + /// Returns true if the section iterator is at the end of the section + /// list: + pub fn LLVMIsSectionIteratorAtEnd(ObjFile: &'a ObjectFile, SI: &SectionIterator<'a>) -> Bool; + /// Moves the section iterator to point to the next section. + pub fn LLVMMoveToNextSection(SI: &SectionIterator); + /// Returns the current section size. + pub fn LLVMGetSectionSize(SI: &SectionIterator) -> c_ulonglong; + /// Returns the current section contents as a string buffer. + pub fn LLVMGetSectionContents(SI: &SectionIterator) -> *const c_char; + + /// Reads the given file and returns it as a memory buffer. Use + /// LLVMDisposeMemoryBuffer() to get rid of it. + pub fn LLVMRustCreateMemoryBufferWithContentsOfFile( + Path: *const c_char, + ) -> Option<&'static mut MemoryBuffer>; + + pub fn LLVMStartMultithreaded() -> Bool; + + /// Returns a string describing the last error caused by an LLVMRust* call. + pub fn LLVMRustGetLastError() -> *const c_char; + + /// Print the pass timings since static dtors aren't picking them up. + pub fn LLVMRustPrintPassTimings(); + + pub fn LLVMStructCreateNamed(C: &Context, Name: *const c_char) -> &Type; + + pub fn LLVMStructSetBody(StructTy: &'a Type, + ElementTypes: *const &'a Type, + ElementCount: c_uint, + Packed: Bool); + + /// Prepares inline assembly. + pub fn LLVMRustInlineAsm(Ty: &Type, + AsmString: *const c_char, + Constraints: *const c_char, + SideEffects: Bool, + AlignStack: Bool, + Dialect: AsmDialect) + -> &Value; + + pub fn LLVMRustDebugMetadataVersion() -> u32; + pub fn LLVMRustVersionMajor() -> u32; + pub fn LLVMRustVersionMinor() -> u32; + + pub fn LLVMRustAddModuleFlag(M: &Module, name: *const c_char, value: u32); + + pub fn LLVMRustMetadataAsValue(C: &'a Context, MD: &'a Metadata) -> &'a Value; + + pub fn LLVMRustDIBuilderCreate(M: &'a Module) -> &'a mut DIBuilder<'a>; + + pub fn LLVMRustDIBuilderDispose(Builder: &'a mut DIBuilder<'a>); + + pub fn LLVMRustDIBuilderFinalize(Builder: &DIBuilder); + + pub fn LLVMRustDIBuilderCreateCompileUnit(Builder: &DIBuilder<'a>, + Lang: c_uint, + File: &'a DIFile, + Producer: *const c_char, + isOptimized: bool, + Flags: *const c_char, + RuntimeVer: c_uint, + SplitName: *const c_char) + -> &'a DIDescriptor; + + pub fn LLVMRustDIBuilderCreateFile(Builder: &DIBuilder<'a>, + Filename: *const c_char, + Directory: *const c_char) + -> &'a DIFile; + + pub fn LLVMRustDIBuilderCreateSubroutineType(Builder: &DIBuilder<'a>, + File: &'a DIFile, + ParameterTypes: &'a DIArray) + -> &'a DICompositeType; + + pub fn LLVMRustDIBuilderCreateFunction(Builder: &DIBuilder<'a>, + Scope: &'a DIDescriptor, + Name: *const c_char, + LinkageName: *const c_char, + File: &'a DIFile, + LineNo: c_uint, + Ty: &'a DIType, + isLocalToUnit: bool, + isDefinition: bool, + ScopeLine: c_uint, + Flags: DIFlags, + isOptimized: bool, + Fn: &'a Value, + TParam: &'a DIArray, + Decl: Option<&'a DIDescriptor>) + -> &'a DISubprogram; + + pub fn LLVMRustDIBuilderCreateBasicType(Builder: &DIBuilder<'a>, + Name: *const c_char, + SizeInBits: u64, + AlignInBits: u32, + Encoding: c_uint) + -> &'a DIBasicType; + + pub fn LLVMRustDIBuilderCreatePointerType(Builder: &DIBuilder<'a>, + PointeeTy: &'a DIType, + SizeInBits: u64, + AlignInBits: u32, + Name: *const c_char) + -> &'a DIDerivedType; + + pub fn LLVMRustDIBuilderCreateStructType(Builder: &DIBuilder<'a>, + Scope: Option<&'a DIDescriptor>, + Name: *const c_char, + File: &'a DIFile, + LineNumber: c_uint, + SizeInBits: u64, + AlignInBits: u32, + Flags: DIFlags, + DerivedFrom: Option<&'a DIType>, + Elements: &'a DIArray, + RunTimeLang: c_uint, + VTableHolder: Option<&'a DIType>, + UniqueId: *const c_char) + -> &'a DICompositeType; + + pub fn LLVMRustDIBuilderCreateMemberType(Builder: &DIBuilder<'a>, + Scope: &'a DIDescriptor, + Name: *const c_char, + File: &'a DIFile, + LineNo: c_uint, + SizeInBits: u64, + AlignInBits: u32, + OffsetInBits: u64, + Flags: DIFlags, + Ty: &'a DIType) + -> &'a DIDerivedType; + + pub fn LLVMRustDIBuilderCreateLexicalBlock(Builder: &DIBuilder<'a>, + Scope: &'a DIScope, + File: &'a DIFile, + Line: c_uint, + Col: c_uint) + -> &'a DILexicalBlock; + + pub fn LLVMRustDIBuilderCreateLexicalBlockFile(Builder: &DIBuilder<'a>, + Scope: &'a DIScope, + File: &'a DIFile) + -> &'a DILexicalBlock; + + pub fn LLVMRustDIBuilderCreateStaticVariable(Builder: &DIBuilder<'a>, + Context: Option<&'a DIScope>, + Name: *const c_char, + LinkageName: *const c_char, + File: &'a DIFile, + LineNo: c_uint, + Ty: &'a DIType, + isLocalToUnit: bool, + Val: &'a Value, + Decl: Option<&'a DIDescriptor>, + AlignInBits: u32) + -> &'a DIGlobalVariable; + + pub fn LLVMRustDIBuilderCreateVariable(Builder: &DIBuilder<'a>, + Tag: c_uint, + Scope: &'a DIDescriptor, + Name: *const c_char, + File: &'a DIFile, + LineNo: c_uint, + Ty: &'a DIType, + AlwaysPreserve: bool, + Flags: DIFlags, + ArgNo: c_uint, + AlignInBits: u32) + -> &'a DIVariable; + + pub fn LLVMRustDIBuilderCreateArrayType(Builder: &DIBuilder<'a>, + Size: u64, + AlignInBits: u32, + Ty: &'a DIType, + Subscripts: &'a DIArray) + -> &'a DIType; + + pub fn LLVMRustDIBuilderGetOrCreateSubrange(Builder: &DIBuilder<'a>, + Lo: i64, + Count: i64) + -> &'a DISubrange; + + pub fn LLVMRustDIBuilderGetOrCreateArray(Builder: &DIBuilder<'a>, + Ptr: *const Option<&'a DIDescriptor>, + Count: c_uint) + -> &'a DIArray; + + pub fn LLVMRustDIBuilderInsertDeclareAtEnd(Builder: &DIBuilder<'a>, + Val: &'a Value, + VarInfo: &'a DIVariable, + AddrOps: *const i64, + AddrOpsCount: c_uint, + DL: &'a Value, + InsertAtEnd: &'a BasicBlock) + -> &'a Value; + + pub fn LLVMRustDIBuilderCreateEnumerator(Builder: &DIBuilder<'a>, + Name: *const c_char, + Val: u64) + -> &'a DIEnumerator; + + pub fn LLVMRustDIBuilderCreateEnumerationType(Builder: &DIBuilder<'a>, + Scope: &'a DIScope, + Name: *const c_char, + File: &'a DIFile, + LineNumber: c_uint, + SizeInBits: u64, + AlignInBits: u32, + Elements: &'a DIArray, + ClassType: &'a DIType) + -> &'a DIType; + + pub fn LLVMRustDIBuilderCreateUnionType(Builder: &DIBuilder<'a>, + Scope: &'a DIScope, + Name: *const c_char, + File: &'a DIFile, + LineNumber: c_uint, + SizeInBits: u64, + AlignInBits: u32, + Flags: DIFlags, + Elements: Option<&'a DIArray>, + RunTimeLang: c_uint, + UniqueId: *const c_char) + -> &'a DIType; + + pub fn LLVMSetUnnamedAddr(GlobalVar: &Value, UnnamedAddr: Bool); + + pub fn LLVMRustDIBuilderCreateTemplateTypeParameter(Builder: &DIBuilder<'a>, + Scope: Option<&'a DIScope>, + Name: *const c_char, + Ty: &'a DIType, + File: &'a DIFile, + LineNo: c_uint, + ColumnNo: c_uint) + -> &'a DITemplateTypeParameter; + + + pub fn LLVMRustDIBuilderCreateNameSpace(Builder: &DIBuilder<'a>, + Scope: Option<&'a DIScope>, + Name: *const c_char, + File: &'a DIFile, + LineNo: c_uint) + -> &'a DINameSpace; + + pub fn LLVMRustDICompositeTypeSetTypeArray(Builder: &DIBuilder<'a>, + CompositeType: &'a DIType, + TypeArray: &'a DIArray); + + + pub fn LLVMRustDIBuilderCreateDebugLocation(Context: &'a Context, + Line: c_uint, + Column: c_uint, + Scope: &'a DIScope, + InlinedAt: Option<&'a Metadata>) + -> &'a Value; + pub fn LLVMRustDIBuilderCreateOpDeref() -> i64; + pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> i64; +} + +#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString. +extern "C" { + pub fn LLVMRustWriteTypeToString(Type: &Type, s: &RustString); + pub fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString); +} + +extern "C" { + pub fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&Value>; + pub fn LLVMIsAConstantFP(value_ref: &Value) -> Option<&Value>; + + pub fn LLVMRustPassKind(Pass: &Pass) -> PassKind; + pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> Option<&'static mut Pass>; + pub fn LLVMRustAddPass(PM: &PassManager, Pass: &'static mut Pass); + + pub fn LLVMRustHasFeature(T: &TargetMachine, s: *const c_char) -> bool; + + pub fn LLVMRustPrintTargetCPUs(T: &TargetMachine); + pub fn LLVMRustPrintTargetFeatures(T: &TargetMachine); + + pub fn LLVMRustCreateTargetMachine(Triple: *const c_char, + CPU: *const c_char, + Features: *const c_char, + Model: CodeModel, + Reloc: RelocMode, + Level: CodeGenOptLevel, + UseSoftFP: bool, + PositionIndependentExecutable: bool, + FunctionSections: bool, + DataSections: bool, + TrapUnreachable: bool, + Singlethread: bool) + -> Option<&'static mut TargetMachine>; + pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine); + pub fn LLVMRustAddAnalysisPasses(T: &'a TargetMachine, PM: &PassManager<'a>, M: &'a Module); + pub fn LLVMRustAddBuilderLibraryInfo(PMB: &'a PassManagerBuilder, + M: &'a Module, + DisableSimplifyLibCalls: bool); + pub fn LLVMRustConfigurePassManagerBuilder(PMB: &PassManagerBuilder, + OptLevel: CodeGenOptLevel, + MergeFunctions: bool, + SLPVectorize: bool, + LoopVectorize: bool, + PrepareForThinLTO: bool, + PGOGenPath: *const c_char, + PGOUsePath: *const c_char); + pub fn LLVMRustAddLibraryInfo(PM: &PassManager<'a>, + M: &'a Module, + DisableSimplifyLibCalls: bool); + pub fn LLVMRustRunFunctionPassManager(PM: &PassManager<'a>, M: &'a Module); + pub fn LLVMRustWriteOutputFile(T: &'a TargetMachine, + PM: &PassManager<'a>, + M: &'a Module, + Output: *const c_char, + FileType: FileType) + -> LLVMRustResult; + pub fn LLVMRustPrintModule(PM: &PassManager<'a>, + M: &'a Module, + Output: *const c_char, + Demangle: extern fn(*const c_char, + size_t, + *mut c_char, + size_t) -> size_t); + pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char); + pub fn LLVMRustPrintPasses(); + pub fn LLVMRustSetNormalizedTarget(M: &Module, triple: *const c_char); + pub fn LLVMRustAddAlwaysInlinePass(P: &PassManagerBuilder, AddLifetimes: bool); + pub fn LLVMRustRunRestrictionPass(M: &Module, syms: *const *const c_char, len: size_t); + pub fn LLVMRustMarkAllFunctionsNounwind(M: &Module); + + pub fn LLVMRustOpenArchive(path: *const c_char) -> Option<&'static mut Archive>; + pub fn LLVMRustArchiveIteratorNew(AR: &'a Archive) -> &'a mut ArchiveIterator<'a>; + pub fn LLVMRustArchiveIteratorNext( + AIR: &ArchiveIterator<'a>, + ) -> Option<&'a mut ArchiveChild<'a>>; + pub fn LLVMRustArchiveChildName(ACR: &ArchiveChild, size: &mut size_t) -> *const c_char; + pub fn LLVMRustArchiveChildData(ACR: &ArchiveChild, size: &mut size_t) -> *const c_char; + pub fn LLVMRustArchiveChildFree(ACR: &'a mut ArchiveChild<'a>); + pub fn LLVMRustArchiveIteratorFree(AIR: &'a mut ArchiveIterator<'a>); + pub fn LLVMRustDestroyArchive(AR: &'static mut Archive); + + pub fn LLVMRustGetSectionName(SI: &SectionIterator, data: &mut *const c_char) -> size_t; +} + +#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString. +extern "C" { + pub fn LLVMRustWriteTwineToString(T: &Twine, s: &RustString); +} + +extern "C" { + pub fn LLVMContextSetDiagnosticHandler(C: &Context, + Handler: DiagnosticHandler, + DiagnosticContext: *mut c_void); +} + +#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString. +extern "C" { + pub fn LLVMRustUnpackOptimizationDiagnostic(DI: &'a DiagnosticInfo, + pass_name_out: &RustString, + function_out: &mut Option<&'a Value>, + loc_line_out: &mut c_uint, + loc_column_out: &mut c_uint, + loc_filename_out: &RustString, + message_out: &RustString); +} + +extern "C" { + pub fn LLVMRustUnpackInlineAsmDiagnostic(DI: &'a DiagnosticInfo, + cookie_out: &mut c_uint, + message_out: &mut Option<&'a Twine>, + instruction_out: &mut Option<&'a Value>); +} + +#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString. +extern "C" { + pub fn LLVMRustWriteDiagnosticInfoToString(DI: &DiagnosticInfo, s: &RustString); +} + +extern "C" { + pub fn LLVMRustGetDiagInfoKind(DI: &DiagnosticInfo) -> DiagnosticKind; + + pub fn LLVMRustSetInlineAsmDiagnosticHandler(C: &Context, + H: InlineAsmDiagHandler, + CX: *mut c_void); +} + +#[allow(improper_ctypes)] // FIXME(#52456) needed for RustString. +extern "C" { + pub fn LLVMRustWriteSMDiagnosticToString(d: &SMDiagnostic, s: &RustString); +} + +extern "C" { + pub fn LLVMRustWriteArchive(Dst: *const c_char, + NumMembers: size_t, + Members: *const &RustArchiveMember, + WriteSymbtab: bool, + Kind: ArchiveKind) + -> LLVMRustResult; + pub fn LLVMRustArchiveMemberNew(Filename: *const c_char, + Name: *const c_char, + Child: Option<&'a ArchiveChild>) + -> &'a mut RustArchiveMember<'a>; + pub fn LLVMRustArchiveMemberFree(Member: &'a mut RustArchiveMember<'a>); + + pub fn LLVMRustSetDataLayoutFromTargetMachine(M: &'a Module, TM: &'a TargetMachine); + + pub fn LLVMRustBuildOperandBundleDef(Name: *const c_char, + Inputs: *const &'a Value, + NumInputs: c_uint) + -> &'a mut OperandBundleDef<'a>; + pub fn LLVMRustFreeOperandBundleDef(Bundle: &'a mut OperandBundleDef<'a>); + + pub fn LLVMRustPositionBuilderAtStart(B: &Builder<'a>, BB: &'a BasicBlock); + + pub fn LLVMRustSetComdat(M: &'a Module, V: &'a Value, Name: *const c_char); + pub fn LLVMRustUnsetComdat(V: &Value); + pub fn LLVMRustSetModulePIELevel(M: &Module); + pub fn LLVMRustModuleBufferCreate(M: &Module) -> &'static mut ModuleBuffer; + pub fn LLVMRustModuleBufferPtr(p: &ModuleBuffer) -> *const u8; + pub fn LLVMRustModuleBufferLen(p: &ModuleBuffer) -> usize; + pub fn LLVMRustModuleBufferFree(p: &'static mut ModuleBuffer); + pub fn LLVMRustModuleCost(M: &Module) -> u64; + + pub fn LLVMRustThinLTOAvailable() -> bool; + pub fn LLVMRustPGOAvailable() -> bool; + pub fn LLVMRustThinLTOBufferCreate(M: &Module) -> &'static mut ThinLTOBuffer; + pub fn LLVMRustThinLTOBufferFree(M: &'static mut ThinLTOBuffer); + pub fn LLVMRustThinLTOBufferPtr(M: &ThinLTOBuffer) -> *const c_char; + pub fn LLVMRustThinLTOBufferLen(M: &ThinLTOBuffer) -> size_t; + pub fn LLVMRustCreateThinLTOData( + Modules: *const ThinLTOModule, + NumModules: c_uint, + PreservedSymbols: *const *const c_char, + PreservedSymbolsLen: c_uint, + ) -> Option<&'static mut ThinLTOData>; + pub fn LLVMRustPrepareThinLTORename( + Data: &ThinLTOData, + Module: &Module, + ) -> bool; + pub fn LLVMRustPrepareThinLTOResolveWeak( + Data: &ThinLTOData, + Module: &Module, + ) -> bool; + pub fn LLVMRustPrepareThinLTOInternalize( + Data: &ThinLTOData, + Module: &Module, + ) -> bool; + pub fn LLVMRustPrepareThinLTOImport( + Data: &ThinLTOData, + Module: &Module, + ) -> bool; + pub fn LLVMRustFreeThinLTOData(Data: &'static mut ThinLTOData); + pub fn LLVMRustParseBitcodeForThinLTO( + Context: &Context, + Data: *const u8, + len: usize, + Identifier: *const c_char, + ) -> Option<&Module>; + pub fn LLVMRustThinLTOGetDICompileUnit(M: &Module, + CU1: &mut *mut c_void, + CU2: &mut *mut c_void); + pub fn LLVMRustThinLTOPatchDICompileUnit(M: &Module, CU: *mut c_void); + + pub fn LLVMRustLinkerNew(M: &'a Module) -> &'a mut Linker<'a>; + pub fn LLVMRustLinkerAdd(linker: &Linker, + bytecode: *const c_char, + bytecode_len: usize) -> bool; + pub fn LLVMRustLinkerFree(linker: &'a mut Linker<'a>); +} diff --git a/src/librustc_codegen_llvm/llvm/mod.rs b/src/librustc_codegen_llvm/llvm/mod.rs new file mode 100644 index 0000000000000..558d2a2bc87b3 --- /dev/null +++ b/src/librustc_codegen_llvm/llvm/mod.rs @@ -0,0 +1,281 @@ +// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![deny(bare_trait_objects)] + +pub use self::IntPredicate::*; +pub use self::RealPredicate::*; +pub use self::AtomicRmwBinOp::*; +pub use self::MetadataType::*; +pub use self::CodeGenOptSize::*; +pub use self::CallConv::*; +pub use self::Linkage::*; + +use std::str::FromStr; +use std::string::FromUtf8Error; +use std::slice; +use std::ffi::{CString, CStr}; +use std::cell::RefCell; +use libc::{self, c_uint, c_char, size_t}; + +pub mod archive_ro; +pub mod diagnostic; +mod ffi; + +pub use self::ffi::*; + +impl LLVMRustResult { + pub fn into_result(self) -> Result<(), ()> { + match self { + LLVMRustResult::Success => Ok(()), + LLVMRustResult::Failure => Err(()), + } + } +} + +pub fn AddFunctionAttrStringValue(llfn: &'a Value, + idx: AttributePlace, + attr: &CStr, + value: &CStr) { + unsafe { + LLVMRustAddFunctionAttrStringValue(llfn, + idx.as_uint(), + attr.as_ptr(), + value.as_ptr()) + } +} + +#[derive(Copy, Clone)] +pub enum AttributePlace { + ReturnValue, + Argument(u32), + Function, +} + +impl AttributePlace { + pub fn as_uint(self) -> c_uint { + match self { + AttributePlace::ReturnValue => 0, + AttributePlace::Argument(i) => 1 + i, + AttributePlace::Function => !0, + } + } +} + +#[derive(Copy, Clone, PartialEq)] +#[repr(C)] +pub enum CodeGenOptSize { + CodeGenOptSizeNone = 0, + CodeGenOptSizeDefault = 1, + CodeGenOptSizeAggressive = 2, +} + +impl FromStr for ArchiveKind { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + "gnu" => Ok(ArchiveKind::K_GNU), + "bsd" => Ok(ArchiveKind::K_BSD), + "coff" => Ok(ArchiveKind::K_COFF), + _ => Err(()), + } + } +} + +#[repr(C)] +pub struct RustString { + bytes: RefCell>, +} + +/// Appending to a Rust string -- used by RawRustStringOstream. +#[no_mangle] +pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: &RustString, + ptr: *const c_char, + size: size_t) { + let slice = slice::from_raw_parts(ptr as *const u8, size as usize); + + sr.bytes.borrow_mut().extend_from_slice(slice); +} + +pub fn SetInstructionCallConv(instr: &'a Value, cc: CallConv) { + unsafe { + LLVMSetInstructionCallConv(instr, cc as c_uint); + } +} +pub fn SetFunctionCallConv(fn_: &'a Value, cc: CallConv) { + unsafe { + LLVMSetFunctionCallConv(fn_, cc as c_uint); + } +} + +// Externally visible symbols that might appear in multiple codegen units need to appear in +// their own comdat section so that the duplicates can be discarded at link time. This can for +// example happen for generics when using multiple codegen units. This function simply uses the +// value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the +// function. +// For more details on COMDAT sections see e.g. http://www.airs.com/blog/archives/52 +pub fn SetUniqueComdat(llmod: &Module, val: &'a Value) { + unsafe { + LLVMRustSetComdat(llmod, val, LLVMGetValueName(val)); + } +} + +pub fn UnsetComdat(val: &'a Value) { + unsafe { + LLVMRustUnsetComdat(val); + } +} + +pub fn SetUnnamedAddr(global: &'a Value, unnamed: bool) { + unsafe { + LLVMSetUnnamedAddr(global, unnamed as Bool); + } +} + +pub fn set_thread_local(global: &'a Value, is_thread_local: bool) { + unsafe { + LLVMSetThreadLocal(global, is_thread_local as Bool); + } +} +pub fn set_thread_local_mode(global: &'a Value, mode: ThreadLocalMode) { + unsafe { + LLVMSetThreadLocalMode(global, mode); + } +} + +impl Attribute { + pub fn apply_llfn(&self, idx: AttributePlace, llfn: &Value) { + unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) } + } + + pub fn apply_callsite(&self, idx: AttributePlace, callsite: &Value) { + unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) } + } + + pub fn unapply_llfn(&self, idx: AttributePlace, llfn: &Value) { + unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), *self) } + } + + pub fn toggle_llfn(&self, idx: AttributePlace, llfn: &Value, set: bool) { + if set { + self.apply_llfn(idx, llfn); + } else { + self.unapply_llfn(idx, llfn); + } + } +} + +// Memory-managed interface to object files. + +pub struct ObjectFile { + pub llof: &'static mut ffi::ObjectFile, +} + +unsafe impl Send for ObjectFile {} + +impl ObjectFile { + // This will take ownership of llmb + pub fn new(llmb: &'static mut MemoryBuffer) -> Option { + unsafe { + let llof = LLVMCreateObjectFile(llmb)?; + Some(ObjectFile { llof: llof }) + } + } +} + +impl Drop for ObjectFile { + fn drop(&mut self) { + unsafe { + LLVMDisposeObjectFile(&mut *(self.llof as *mut _)); + } + } +} + +// Memory-managed interface to section iterators. + +pub struct SectionIter<'a> { + pub llsi: &'a mut SectionIterator<'a>, +} + +impl Drop for SectionIter<'a> { + fn drop(&mut self) { + unsafe { + LLVMDisposeSectionIterator(&mut *(self.llsi as *mut _)); + } + } +} + +pub fn mk_section_iter(llof: &'a ffi::ObjectFile) -> SectionIter<'a> { + unsafe { SectionIter { llsi: LLVMGetSections(llof) } } +} + +/// Safe wrapper around `LLVMGetParam`, because segfaults are no fun. +pub fn get_param(llfn: &'a Value, index: c_uint) -> &'a Value { + unsafe { + assert!(index < LLVMCountParams(llfn), + "out of bounds argument access: {} out of {} arguments", index, LLVMCountParams(llfn)); + LLVMGetParam(llfn, index) + } +} + +pub fn build_string(f: impl FnOnce(&RustString)) -> Result { + let sr = RustString { + bytes: RefCell::new(Vec::new()), + }; + f(&sr); + String::from_utf8(sr.bytes.into_inner()) +} + +pub fn twine_to_string(tr: &Twine) -> String { + unsafe { + build_string(|s| LLVMRustWriteTwineToString(tr, s)) + .expect("got a non-UTF8 Twine from LLVM") + } +} + +pub fn last_error() -> Option { + unsafe { + let cstr = LLVMRustGetLastError(); + if cstr.is_null() { + None + } else { + let err = CStr::from_ptr(cstr).to_bytes(); + let err = String::from_utf8_lossy(err).to_string(); + libc::free(cstr as *mut _); + Some(err) + } + } +} + +pub struct OperandBundleDef<'a> { + pub raw: &'a mut ffi::OperandBundleDef<'a>, +} + +impl OperandBundleDef<'a> { + pub fn new(name: &str, vals: &[&'a Value]) -> Self { + let name = CString::new(name).unwrap(); + let def = unsafe { + LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint) + }; + OperandBundleDef { raw: def } + } +} + +impl Drop for OperandBundleDef<'a> { + fn drop(&mut self) { + unsafe { + LLVMRustFreeOperandBundleDef(&mut *(self.raw as *mut _)); + } + } +} diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index e941998098d00..441fff5f08c8f 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -73,7 +73,7 @@ unsafe fn configure_llvm(sess: &Session) { llvm::LLVMInitializePasses(); - llvm::initialize_available_targets(); + ::rustc_llvm::initialize_available_targets(); llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr()); diff --git a/src/librustc_codegen_llvm/metadata.rs b/src/librustc_codegen_llvm/metadata.rs index 144baa65c1bfa..fcb704413ef11 100644 --- a/src/librustc_codegen_llvm/metadata.rs +++ b/src/librustc_codegen_llvm/metadata.rs @@ -58,10 +58,8 @@ impl MetadataLoader for LlvmMetadataLoader { -> Result { unsafe { let buf = common::path2cstr(filename); - let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr()); - if mb as isize == 0 { - return Err(format!("error reading library: '{}'", filename.display())); - } + let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr()) + .ok_or_else(|| format!("error reading library: '{}'", filename.display()))?; let of = ObjectFile::new(mb) .map(|of| OwningRef::new(box of)) .ok_or_else(|| format!("provided path not an object file: '{}'", diff --git a/src/librustc_codegen_llvm/meth.rs b/src/librustc_codegen_llvm/meth.rs index 21bbdf31dcb52..9c0dd0dc3d8b5 100644 --- a/src/librustc_codegen_llvm/meth.rs +++ b/src/librustc_codegen_llvm/meth.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::ValueRef; use abi::{FnType, FnTypeExt}; use callee; use common::*; @@ -17,6 +16,7 @@ use consts; use monomorphize; use type_::Type; use value::Value; + use rustc::ty::{self, Ty}; use rustc::ty::layout::HasDataLayout; use debuginfo; @@ -33,11 +33,11 @@ impl<'a, 'tcx> VirtualIndex { VirtualIndex(index as u64 + 3) } - pub fn get_fn(self, bx: &Builder<'a, 'tcx>, - llvtable: ValueRef, - fn_ty: &FnType<'tcx, Ty<'tcx>>) -> ValueRef { + pub fn get_fn(self, bx: &Builder<'a, 'll, 'tcx>, + llvtable: &'ll Value, + fn_ty: &FnType<'tcx, Ty<'tcx>>) -> &'ll Value { // Load the data pointer from the object. - debug!("get_fn({:?}, {:?})", Value(llvtable), self); + debug!("get_fn({:?}, {:?})", llvtable, self); let llvtable = bx.pointercast(llvtable, fn_ty.llvm_type(bx.cx).ptr_to().ptr_to()); let ptr_align = bx.tcx().data_layout.pointer_align; @@ -48,9 +48,9 @@ impl<'a, 'tcx> VirtualIndex { ptr } - pub fn get_usize(self, bx: &Builder<'a, 'tcx>, llvtable: ValueRef) -> ValueRef { + pub fn get_usize(self, bx: &Builder<'a, 'll, 'tcx>, llvtable: &'ll Value) -> &'ll Value { // Load the data pointer from the object. - debug!("get_int({:?}, {:?})", Value(llvtable), self); + debug!("get_int({:?}, {:?})", llvtable, self); let llvtable = bx.pointercast(llvtable, Type::isize(bx.cx).ptr_to()); let usize_align = bx.tcx().data_layout.pointer_align; @@ -69,11 +69,11 @@ impl<'a, 'tcx> VirtualIndex { /// The `trait_ref` encodes the erased self type. Hence if we are /// making an object `Foo` from a value of type `Foo`, then /// `trait_ref` would map `T:Trait`. -pub fn get_vtable<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, - ty: Ty<'tcx>, - trait_ref: Option>) - -> ValueRef -{ +pub fn get_vtable( + cx: &CodegenCx<'ll, 'tcx>, + ty: Ty<'tcx>, + trait_ref: Option>, +) -> &'ll Value { let tcx = cx.tcx; debug!("get_vtable(ty={:?}, trait_ref={:?})", ty, trait_ref); diff --git a/src/librustc_codegen_llvm/mir/analyze.rs b/src/librustc_codegen_llvm/mir/analyze.rs index e105baba8aa2e..2c2058035241f 100644 --- a/src/librustc_codegen_llvm/mir/analyze.rs +++ b/src/librustc_codegen_llvm/mir/analyze.rs @@ -22,7 +22,7 @@ use rustc::ty::layout::LayoutOf; use type_of::LayoutLlvmExt; use super::FunctionCx; -pub fn non_ssa_locals<'a, 'tcx>(fx: &FunctionCx<'a, 'tcx>) -> BitVector { +pub fn non_ssa_locals(fx: &FunctionCx<'a, 'll, 'tcx>) -> BitVector { let mir = fx.mir; let mut analyzer = LocalAnalyzer::new(fx); @@ -34,7 +34,7 @@ pub fn non_ssa_locals<'a, 'tcx>(fx: &FunctionCx<'a, 'tcx>) -> BitVector(fx: &FunctionCx<'a, 'tcx>) -> BitVector { - fx: &'mir FunctionCx<'a, 'tcx>, +struct LocalAnalyzer<'mir, 'a: 'mir, 'll: 'a, 'tcx: 'll> { + fx: &'mir FunctionCx<'a, 'll, 'tcx>, dominators: Dominators, non_ssa_locals: BitVector, // The location of the first visited direct assignment to each @@ -60,8 +60,8 @@ struct LocalAnalyzer<'mir, 'a: 'mir, 'tcx: 'a> { first_assignment: IndexVec } -impl<'mir, 'a, 'tcx> LocalAnalyzer<'mir, 'a, 'tcx> { - fn new(fx: &'mir FunctionCx<'a, 'tcx>) -> LocalAnalyzer<'mir, 'a, 'tcx> { +impl LocalAnalyzer<'mir, 'a, 'll, 'tcx> { + fn new(fx: &'mir FunctionCx<'a, 'll, 'tcx>) -> Self { let invalid_location = mir::BasicBlock::new(fx.mir.basic_blocks().len()).start_location(); let mut analyzer = LocalAnalyzer { @@ -102,7 +102,7 @@ impl<'mir, 'a, 'tcx> LocalAnalyzer<'mir, 'a, 'tcx> { } } -impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> { +impl Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'll, 'tcx> { fn visit_assign(&mut self, block: mir::BasicBlock, place: &mir::Place<'tcx>, diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs index dc4b9e0ae99d8..684ecfaeec8f1 100644 --- a/src/librustc_codegen_llvm/mir/block.rs +++ b/src/librustc_codegen_llvm/mir/block.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::{self, ValueRef, BasicBlockRef}; +use llvm::{self, BasicBlock}; use rustc::middle::lang_items; use rustc::ty::{self, Ty, TypeFoldable}; use rustc::ty::layout::{self, LayoutOf}; @@ -24,6 +24,7 @@ use meth; use monomorphize; use type_of::LayoutLlvmExt; use type_::Type; +use value::Value; use syntax::symbol::Symbol; use syntax_pos::Pos; @@ -33,7 +34,7 @@ use super::place::PlaceRef; use super::operand::OperandRef; use super::operand::OperandValue::{Pair, Ref, Immediate}; -impl<'a, 'tcx> FunctionCx<'a, 'tcx> { +impl FunctionCx<'a, 'll, 'tcx> { pub fn codegen_block(&mut self, bb: mir::BasicBlock) { let mut bx = self.build_block(bb); let data = &self.mir[bb]; @@ -48,7 +49,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } fn codegen_terminator(&mut self, - mut bx: Builder<'a, 'tcx>, + mut bx: Builder<'a, 'll, 'tcx>, bb: mir::BasicBlock, terminator: &mir::Terminator<'tcx>) { @@ -97,7 +98,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } }; - let funclet_br = |this: &mut Self, bx: Builder, target: mir::BasicBlock| { + let funclet_br = |this: &mut Self, bx: Builder<'_, 'll, '_>, target: mir::BasicBlock| { let (lltarget, is_cleanupret) = lltarget(this, target); if is_cleanupret { // micro-optimization: generate a `ret` rather than a jump @@ -110,11 +111,11 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { let do_call = | this: &mut Self, - bx: Builder<'a, 'tcx>, + bx: Builder<'a, 'll, 'tcx>, fn_ty: FnType<'tcx, Ty<'tcx>>, - fn_ptr: ValueRef, - llargs: &[ValueRef], - destination: Option<(ReturnDest<'tcx>, mir::BasicBlock)>, + fn_ptr: &'ll Value, + llargs: &[&'ll Value], + destination: Option<(ReturnDest<'ll, 'tcx>, mir::BasicBlock)>, cleanup: Option | { if let Some(cleanup) = cleanup { @@ -285,8 +286,14 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } let place = self.codegen_place(&bx, location); - let mut args: &[_] = &[place.llval, place.llextra]; - args = &args[..1 + place.has_extra() as usize]; + let (args1, args2); + let mut args = if let Some(llextra) = place.llextra { + args2 = [place.llval, llextra]; + &args2[..] + } else { + args1 = [place.llval]; + &args1[..] + }; let (drop_fn, fn_ty) = match ty.sty { ty::TyDynamic(..) => { let fn_ty = drop_fn.ty(bx.cx.tcx); @@ -296,8 +303,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { &sig, ); let fn_ty = FnType::new_vtable(bx.cx, sig, &[]); + let vtable = args[1]; args = &args[..1]; - (meth::DESTRUCTOR.get_fn(&bx, place.llextra, &fn_ty), fn_ty) + (meth::DESTRUCTOR.get_fn(&bx, vtable, &fn_ty), fn_ty) } _ => { (callee::get_fn(bx.cx, drop_fn), @@ -627,9 +635,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } fn codegen_argument(&mut self, - bx: &Builder<'a, 'tcx>, - op: OperandRef<'tcx>, - llargs: &mut Vec, + bx: &Builder<'a, 'll, 'tcx>, + op: OperandRef<'ll, 'tcx>, + llargs: &mut Vec<&'ll Value>, arg: &ArgType<'tcx, Ty<'tcx>>) { // Fill padding with undef value, where applicable. if let Some(ty) = arg.pad { @@ -706,9 +714,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } fn codegen_arguments_untupled(&mut self, - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, operand: &mir::Operand<'tcx>, - llargs: &mut Vec, + llargs: &mut Vec<&'ll Value>, args: &[ArgType<'tcx, Ty<'tcx>>]) { let tuple = self.codegen_operand(bx, operand); @@ -728,7 +736,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } } - fn get_personality_slot(&mut self, bx: &Builder<'a, 'tcx>) -> PlaceRef<'tcx> { + fn get_personality_slot(&mut self, bx: &Builder<'a, 'll, 'tcx>) -> PlaceRef<'ll, 'tcx> { let cx = bx.cx; if let Some(slot) = self.personality_slot { slot @@ -746,7 +754,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { /// Return the landingpad wrapper around the given basic block /// /// No-op in MSVC SEH scheme. - fn landing_pad_to(&mut self, target_bb: mir::BasicBlock) -> BasicBlockRef { + fn landing_pad_to(&mut self, target_bb: mir::BasicBlock) -> &'ll BasicBlock { if let Some(block) = self.landing_pads[target_bb] { return block; } @@ -757,7 +765,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { landing_pad } - fn landing_pad_uncached(&mut self, target_bb: BasicBlockRef) -> BasicBlockRef { + fn landing_pad_uncached(&mut self, target_bb: &'ll BasicBlock) -> &'ll BasicBlock { if base::wants_msvc_seh(self.cx.sess()) { span_bug!(self.mir.span, "landing pad was not inserted?") } @@ -777,12 +785,12 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { bx.llbb() } - fn landing_pad_type(&self) -> Type { + fn landing_pad_type(&self) -> &'ll Type { let cx = self.cx; Type::struct_(cx, &[Type::i8p(cx), Type::i32(cx)], false) } - fn unreachable_block(&mut self) -> BasicBlockRef { + fn unreachable_block(&mut self) -> &'ll BasicBlock { self.unreachable_block.unwrap_or_else(|| { let bl = self.new_block("unreachable"); bl.unreachable(); @@ -791,20 +799,20 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { }) } - pub fn new_block(&self, name: &str) -> Builder<'a, 'tcx> { + pub fn new_block(&self, name: &str) -> Builder<'a, 'll, 'tcx> { Builder::new_block(self.cx, self.llfn, name) } - pub fn build_block(&self, bb: mir::BasicBlock) -> Builder<'a, 'tcx> { + pub fn build_block(&self, bb: mir::BasicBlock) -> Builder<'a, 'll, 'tcx> { let bx = Builder::with_cx(self.cx); bx.position_at_end(self.blocks[bb]); bx } - fn make_return_dest(&mut self, bx: &Builder<'a, 'tcx>, + fn make_return_dest(&mut self, bx: &Builder<'a, 'll, 'tcx>, dest: &mir::Place<'tcx>, fn_ret: &ArgType<'tcx, Ty<'tcx>>, - llargs: &mut Vec, is_intrinsic: bool) - -> ReturnDest<'tcx> { + llargs: &mut Vec<&'ll Value>, is_intrinsic: bool) + -> ReturnDest<'ll, 'tcx> { // If the return is ignored, we can just return a do-nothing ReturnDest if fn_ret.is_ignore() { return ReturnDest::Nothing; @@ -857,7 +865,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } } - fn codegen_transmute(&mut self, bx: &Builder<'a, 'tcx>, + fn codegen_transmute(&mut self, bx: &Builder<'a, 'll, 'tcx>, src: &mir::Operand<'tcx>, dst: &mir::Place<'tcx>) { if let mir::Place::Local(index) = *dst { @@ -884,9 +892,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } } - fn codegen_transmute_into(&mut self, bx: &Builder<'a, 'tcx>, + fn codegen_transmute_into(&mut self, bx: &Builder<'a, 'll, 'tcx>, src: &mir::Operand<'tcx>, - dst: PlaceRef<'tcx>) { + dst: PlaceRef<'ll, 'tcx>) { let src = self.codegen_operand(bx, src); let llty = src.layout.llvm_type(bx.cx); let cast_ptr = bx.pointercast(dst.llval, llty.ptr_to()); @@ -897,10 +905,10 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { // Stores the return value of a function call into it's final location. fn store_return(&mut self, - bx: &Builder<'a, 'tcx>, - dest: ReturnDest<'tcx>, + bx: &Builder<'a, 'll, 'tcx>, + dest: ReturnDest<'ll, 'tcx>, ret_ty: &ArgType<'tcx, Ty<'tcx>>, - llval: ValueRef) { + llval: &'ll Value) { use self::ReturnDest::*; match dest { @@ -929,13 +937,13 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } } -enum ReturnDest<'tcx> { +enum ReturnDest<'ll, 'tcx> { // Do nothing, the return value is indirect or ignored Nothing, // Store the return value to the pointer - Store(PlaceRef<'tcx>), + Store(PlaceRef<'ll, 'tcx>), // Stores an indirect return value to an operand local place - IndirectOperand(PlaceRef<'tcx>, mir::Local), + IndirectOperand(PlaceRef<'ll, 'tcx>, mir::Local), // Stores a direct return value to an operand local place DirectOperand(mir::Local) } diff --git a/src/librustc_codegen_llvm/mir/constant.rs b/src/librustc_codegen_llvm/mir/constant.rs index 0d682d5d6f6a1..341ed9df64b59 100644 --- a/src/librustc_codegen_llvm/mir/constant.rs +++ b/src/librustc_codegen_llvm/mir/constant.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::{self, ValueRef}; +use llvm; use rustc::mir::interpret::ConstEvalErr; use rustc_mir::interpret::{read_target_uint, const_val_field}; use rustc::hir::def_id::DefId; @@ -26,14 +26,17 @@ use type_of::LayoutLlvmExt; use type_::Type; use syntax::ast::Mutability; use syntax::codemap::Span; +use value::Value; use super::super::callee; use super::FunctionCx; -pub fn scalar_to_llvm(cx: &CodegenCx, - cv: Scalar, - layout: &layout::Scalar, - llty: Type) -> ValueRef { +pub fn scalar_to_llvm( + cx: &CodegenCx<'ll, '_>, + cv: Scalar, + layout: &layout::Scalar, + llty: &'ll Type, +) -> &'ll Value { let bitsize = if layout.is_bool() { 1 } else { layout.value.size(cx).bits() }; match cv { Scalar::Bits { defined, .. } if (defined as u64) < bitsize || defined == 0 => { @@ -42,7 +45,7 @@ pub fn scalar_to_llvm(cx: &CodegenCx, Scalar::Bits { bits, .. } => { let llval = C_uint_big(Type::ix(cx, bitsize), bits); if layout.value == layout::Pointer { - unsafe { llvm::LLVMConstIntToPtr(llval, llty.to_ref()) } + unsafe { llvm::LLVMConstIntToPtr(llval, llty) } } else { consts::bitcast(llval, llty) } @@ -73,7 +76,7 @@ pub fn scalar_to_llvm(cx: &CodegenCx, 1, ) }; if layout.value != layout::Pointer { - unsafe { llvm::LLVMConstPtrToInt(llval, llty.to_ref()) } + unsafe { llvm::LLVMConstPtrToInt(llval, llty) } } else { consts::bitcast(llval, llty) } @@ -81,7 +84,7 @@ pub fn scalar_to_llvm(cx: &CodegenCx, } } -pub fn const_alloc_to_llvm(cx: &CodegenCx, alloc: &Allocation) -> ValueRef { +pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value { let mut llvals = Vec::with_capacity(alloc.relocations.len() + 1); let layout = cx.data_layout(); let pointer_size = layout.pointer_size.bytes() as usize; @@ -116,10 +119,10 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx, alloc: &Allocation) -> ValueRef { C_struct(cx, &llvals, true) } -pub fn codegen_static_initializer<'a, 'tcx>( - cx: &CodegenCx<'a, 'tcx>, +pub fn codegen_static_initializer( + cx: &CodegenCx<'ll, 'tcx>, def_id: DefId, -) -> Result<(ValueRef, &'tcx Allocation), Lrc>> { +) -> Result<(&'ll Value, &'tcx Allocation), Lrc>> { let instance = ty::Instance::mono(cx.tcx, def_id); let cid = GlobalId { instance, @@ -135,10 +138,10 @@ pub fn codegen_static_initializer<'a, 'tcx>( Ok((const_alloc_to_llvm(cx, alloc), alloc)) } -impl<'a, 'tcx> FunctionCx<'a, 'tcx> { +impl FunctionCx<'a, 'll, 'tcx> { fn fully_evaluate( &mut self, - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, constant: &'tcx ty::Const<'tcx>, ) -> Result<&'tcx ty::Const<'tcx>, Lrc>> { match constant.val { @@ -158,7 +161,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { pub fn eval_mir_constant( &mut self, - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, constant: &mir::Constant<'tcx>, ) -> Result<&'tcx ty::Const<'tcx>, Lrc>> { let c = self.monomorphize(&constant.literal); @@ -168,11 +171,11 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { /// process constant containing SIMD shuffle indices pub fn simd_shuffle_indices( &mut self, - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, span: Span, ty: Ty<'tcx>, constant: Result<&'tcx ty::Const<'tcx>, Lrc>>, - ) -> (ValueRef, Ty<'tcx>) { + ) -> (&'ll Value, Ty<'tcx>) { constant .and_then(|c| { let field_ty = c.ty.builtin_index().unwrap(); @@ -180,7 +183,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { ty::TyArray(_, n) => n.unwrap_usize(bx.tcx()), ref other => bug!("invalid simd shuffle type: {}", other), }; - let values: Result, Lrc<_>> = (0..fields).map(|field| { + let values: Result, Lrc<_>> = (0..fields).map(|field| { let field = const_val_field( bx.tcx(), ty::ParamEnv::reveal_all(), diff --git a/src/librustc_codegen_llvm/mir/mod.rs b/src/librustc_codegen_llvm/mir/mod.rs index 312939408c62c..8cdd0398eff96 100644 --- a/src/librustc_codegen_llvm/mir/mod.rs +++ b/src/librustc_codegen_llvm/mir/mod.rs @@ -10,7 +10,7 @@ use common::{C_i32, C_null}; use libc::c_uint; -use llvm::{self, ValueRef, BasicBlockRef}; +use llvm::{self, BasicBlock}; use llvm::debuginfo::DIScope; use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts}; use rustc::ty::layout::{LayoutOf, TyLayout}; @@ -24,6 +24,7 @@ use debuginfo::{self, declare_local, VariableAccess, VariableKind, FunctionDebug use monomorphize::Instance; use abi::{ArgTypeExt, FnType, FnTypeExt, PassMode}; use type_::Type; +use value::Value; use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span}; use syntax::symbol::keywords; @@ -42,16 +43,16 @@ use rustc::mir::traversal; use self::operand::{OperandRef, OperandValue}; /// Master context for codegenning from MIR. -pub struct FunctionCx<'a, 'tcx:'a> { +pub struct FunctionCx<'a, 'll: 'a, 'tcx: 'll> { instance: Instance<'tcx>, mir: &'a mir::Mir<'tcx>, - debug_context: debuginfo::FunctionDebugContext, + debug_context: FunctionDebugContext<'ll>, - llfn: ValueRef, + llfn: &'ll Value, - cx: &'a CodegenCx<'a, 'tcx>, + cx: &'a CodegenCx<'ll, 'tcx>, fn_ty: FnType<'tcx, Ty<'tcx>>, @@ -62,24 +63,24 @@ pub struct FunctionCx<'a, 'tcx:'a> { /// don't really care about it very much. Anyway, this value /// contains an alloca into which the personality is stored and /// then later loaded when generating the DIVERGE_BLOCK. - personality_slot: Option>, + personality_slot: Option>, /// A `Block` for each MIR `BasicBlock` - blocks: IndexVec, + blocks: IndexVec, /// The funclet status of each basic block cleanup_kinds: IndexVec, /// When targeting MSVC, this stores the cleanup info for each funclet /// BB. This is initialized as we compute the funclets' head block in RPO. - funclets: &'a IndexVec>, + funclets: &'a IndexVec>>, /// This stores the landing-pad block for a given BB, computed lazily on GNU /// and eagerly on MSVC. - landing_pads: IndexVec>, + landing_pads: IndexVec>, /// Cached unreachable block - unreachable_block: Option, + unreachable_block: Option<&'ll BasicBlock>, /// The location where each MIR arg/var/tmp/ret is stored. This is /// usually an `PlaceRef` representing an alloca, but not always: @@ -96,16 +97,16 @@ pub struct FunctionCx<'a, 'tcx:'a> { /// /// Avoiding allocs can also be important for certain intrinsics, /// notably `expect`. - locals: IndexVec>, + locals: IndexVec>, /// Debug information for MIR scopes. - scopes: IndexVec, + scopes: IndexVec>, /// If this function is being monomorphized, this contains the type substitutions used. param_substs: &'tcx Substs<'tcx>, } -impl<'a, 'tcx> FunctionCx<'a, 'tcx> { +impl FunctionCx<'a, 'll, 'tcx> { pub fn monomorphize(&self, value: &T) -> T where T: TypeFoldable<'tcx> { @@ -116,12 +117,12 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { ) } - pub fn set_debug_loc(&mut self, bx: &Builder, source_info: mir::SourceInfo) { + pub fn set_debug_loc(&mut self, bx: &Builder<'_, 'll, '_>, source_info: mir::SourceInfo) { let (scope, span) = self.debug_loc(source_info); debuginfo::set_source_location(&self.debug_context, bx, scope, span); } - pub fn debug_loc(&mut self, source_info: mir::SourceInfo) -> (DIScope, Span) { + pub fn debug_loc(&mut self, source_info: mir::SourceInfo) -> (Option<&'ll DIScope>, Span) { // Bail out if debug info emission is not enabled. match self.debug_context { FunctionDebugContext::DebugInfoDisabled | @@ -161,29 +162,29 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { // corresponding to span's containing source scope. If so, we need to create a DIScope // "extension" into that file. fn scope_metadata_for_loc(&self, scope_id: mir::SourceScope, pos: BytePos) - -> llvm::debuginfo::DIScope { + -> Option<&'ll DIScope> { let scope_metadata = self.scopes[scope_id].scope_metadata; if pos < self.scopes[scope_id].file_start_pos || pos >= self.scopes[scope_id].file_end_pos { let cm = self.cx.sess().codemap(); let defining_crate = self.debug_context.get_ref(DUMMY_SP).defining_crate; - debuginfo::extend_scope_to_file(self.cx, - scope_metadata, + Some(debuginfo::extend_scope_to_file(self.cx, + scope_metadata.unwrap(), &cm.lookup_char_pos(pos).file, - defining_crate) + defining_crate)) } else { scope_metadata } } } -enum LocalRef<'tcx> { - Place(PlaceRef<'tcx>), - Operand(Option>), +enum LocalRef<'ll, 'tcx> { + Place(PlaceRef<'ll, 'tcx>), + Operand(Option>), } -impl<'a, 'tcx> LocalRef<'tcx> { - fn new_operand(cx: &CodegenCx<'a, 'tcx>, layout: TyLayout<'tcx>) -> LocalRef<'tcx> { +impl LocalRef<'ll, 'tcx> { + fn new_operand(cx: &CodegenCx<'ll, 'tcx>, layout: TyLayout<'tcx>) -> LocalRef<'ll, 'tcx> { if layout.is_zst() { // Zero-size temporaries aren't always initialized, which // doesn't matter because they don't contain data, but @@ -197,9 +198,9 @@ impl<'a, 'tcx> LocalRef<'tcx> { /////////////////////////////////////////////////////////////////////////// -pub fn codegen_mir<'a, 'tcx: 'a>( - cx: &'a CodegenCx<'a, 'tcx>, - llfn: ValueRef, +pub fn codegen_mir( + cx: &'a CodegenCx<'ll, 'tcx>, + llfn: &'ll Value, mir: &'a Mir<'tcx>, instance: Instance<'tcx>, sig: ty::FnSig<'tcx>, @@ -218,7 +219,7 @@ pub fn codegen_mir<'a, 'tcx: 'a>( // Allocate a `Block` for every basic block, except // the start block, if nothing loops back to it. let reentrant_start_block = !mir.predecessors_for(mir::START_BLOCK).is_empty(); - let block_bxs: IndexVec = + let block_bxs: IndexVec = mir.basic_blocks().indices().map(|bb| { if bb == mir::START_BLOCK && !reentrant_start_block { bx.llbb() @@ -280,7 +281,7 @@ pub fn codegen_mir<'a, 'tcx: 'a>( span: decl.source_info.span, scope: decl.visibility_scope, }); - declare_local(&bx, &fx.debug_context, name, layout.ty, scope, + declare_local(&bx, &fx.debug_context, name, layout.ty, scope.unwrap(), VariableAccess::DirectVariable { alloca: place.llval }, VariableKind::LocalVariable, span); } @@ -343,13 +344,13 @@ pub fn codegen_mir<'a, 'tcx: 'a>( } } -fn create_funclets<'a, 'tcx>( +fn create_funclets( mir: &'a Mir<'tcx>, - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, cleanup_kinds: &IndexVec, - block_bxs: &IndexVec) - -> (IndexVec>, - IndexVec>) + block_bxs: &IndexVec) + -> (IndexVec>, + IndexVec>>) { block_bxs.iter_enumerated().zip(cleanup_kinds).map(|((bb, &llbb), cleanup_kind)| { match *cleanup_kind { @@ -409,14 +410,15 @@ fn create_funclets<'a, 'tcx>( }).unzip() } -/// Produce, for each argument, a `ValueRef` pointing at the +/// Produce, for each argument, a `Value` pointing at the /// argument's value. As arguments are places, these are always /// indirect. -fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>, - fx: &FunctionCx<'a, 'tcx>, - scopes: &IndexVec, - memory_locals: &BitVector) - -> Vec> { +fn arg_local_refs( + bx: &Builder<'a, 'll, 'tcx>, + fx: &FunctionCx<'a, 'll, 'tcx>, + scopes: &IndexVec>, + memory_locals: &BitVector, +) -> Vec> { let mir = fx.mir; let tcx = bx.tcx(); let mut idx = 0; @@ -424,8 +426,8 @@ fn arg_local_refs<'a, 'tcx>(bx: &Builder<'a, 'tcx>, // Get the argument scope, if it exists and if we need it. let arg_scope = scopes[mir::OUTERMOST_SOURCE_SCOPE]; - let arg_scope = if arg_scope.is_valid() && bx.sess().opts.debuginfo == FullDebugInfo { - Some(arg_scope.scope_metadata) + let arg_scope = if bx.sess().opts.debuginfo == FullDebugInfo { + arg_scope.scope_metadata } else { None }; diff --git a/src/librustc_codegen_llvm/mir/operand.rs b/src/librustc_codegen_llvm/mir/operand.rs index c433df51110e3..1296f5e4b144e 100644 --- a/src/librustc_codegen_llvm/mir/operand.rs +++ b/src/librustc_codegen_llvm/mir/operand.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::ValueRef; use rustc::mir::interpret::ConstEvalErr; use rustc::mir; use rustc::mir::interpret::ConstValue; @@ -24,7 +23,6 @@ use value::Value; use type_of::LayoutLlvmExt; use std::fmt; -use std::ptr; use super::{FunctionCx, LocalRef}; use super::constant::scalar_to_llvm; @@ -33,31 +31,15 @@ use super::place::PlaceRef; /// The representation of a Rust value. The enum variant is in fact /// uniquely determined by the value's type, but is kept as a /// safety check. -#[derive(Copy, Clone)] -pub enum OperandValue { +#[derive(Copy, Clone, Debug)] +pub enum OperandValue<'ll> { /// A reference to the actual operand. The data is guaranteed /// to be valid for the operand's lifetime. - Ref(ValueRef, Align), + Ref(&'ll Value, Align), /// A single LLVM value. - Immediate(ValueRef), + Immediate(&'ll Value), /// A pair of immediate LLVM values. Used by fat pointers too. - Pair(ValueRef, ValueRef) -} - -impl fmt::Debug for OperandValue { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - OperandValue::Ref(r, align) => { - write!(f, "Ref({:?}, {:?})", Value(r), align) - } - OperandValue::Immediate(i) => { - write!(f, "Immediate({:?})", Value(i)) - } - OperandValue::Pair(a, b) => { - write!(f, "Pair({:?}, {:?})", Value(a), Value(b)) - } - } - } + Pair(&'ll Value, &'ll Value) } /// An `OperandRef` is an "SSA" reference to a Rust value, along with @@ -69,23 +51,23 @@ impl fmt::Debug for OperandValue { /// directly is sure to cause problems -- use `OperandRef::store` /// instead. #[derive(Copy, Clone)] -pub struct OperandRef<'tcx> { +pub struct OperandRef<'ll, 'tcx> { // The value. - pub val: OperandValue, + pub val: OperandValue<'ll>, // The layout of value, based on its Rust type. pub layout: TyLayout<'tcx>, } -impl<'tcx> fmt::Debug for OperandRef<'tcx> { +impl fmt::Debug for OperandRef<'ll, 'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "OperandRef({:?} @ {:?})", self.val, self.layout) } } -impl<'a, 'tcx> OperandRef<'tcx> { - pub fn new_zst(cx: &CodegenCx<'a, 'tcx>, - layout: TyLayout<'tcx>) -> OperandRef<'tcx> { +impl OperandRef<'ll, 'tcx> { + pub fn new_zst(cx: &CodegenCx<'ll, 'tcx>, + layout: TyLayout<'tcx>) -> OperandRef<'ll, 'tcx> { assert!(layout.is_zst()); OperandRef { val: OperandValue::Immediate(C_undef(layout.immediate_llvm_type(cx))), @@ -93,9 +75,9 @@ impl<'a, 'tcx> OperandRef<'tcx> { } } - pub fn from_const(bx: &Builder<'a, 'tcx>, + pub fn from_const(bx: &Builder<'a, 'll, 'tcx>, val: &'tcx ty::Const<'tcx>) - -> Result, Lrc>> { + -> Result, Lrc>> { let layout = bx.cx.layout_of(val.ty); if layout.is_zst() { @@ -149,19 +131,19 @@ impl<'a, 'tcx> OperandRef<'tcx> { /// Asserts that this operand refers to a scalar and returns /// a reference to its value. - pub fn immediate(self) -> ValueRef { + pub fn immediate(self) -> &'ll Value { match self.val { OperandValue::Immediate(s) => s, _ => bug!("not immediate: {:?}", self) } } - pub fn deref(self, cx: &CodegenCx<'a, 'tcx>) -> PlaceRef<'tcx> { + pub fn deref(self, cx: &CodegenCx<'ll, 'tcx>) -> PlaceRef<'ll, 'tcx> { let projected_ty = self.layout.ty.builtin_deref(true) .unwrap_or_else(|| bug!("deref of non-pointer {:?}", self)).ty; let (llptr, llextra) = match self.val { - OperandValue::Immediate(llptr) => (llptr, ptr::null_mut()), - OperandValue::Pair(llptr, llextra) => (llptr, llextra), + OperandValue::Immediate(llptr) => (llptr, None), + OperandValue::Pair(llptr, llextra) => (llptr, Some(llextra)), OperandValue::Ref(..) => bug!("Deref of by-Ref operand {:?}", self) }; let layout = cx.layout_of(projected_ty); @@ -175,7 +157,7 @@ impl<'a, 'tcx> OperandRef<'tcx> { /// If this operand is a `Pair`, we return an aggregate with the two values. /// For other cases, see `immediate`. - pub fn immediate_or_packed_pair(self, bx: &Builder<'a, 'tcx>) -> ValueRef { + pub fn immediate_or_packed_pair(self, bx: &Builder<'a, 'll, 'tcx>) -> &'ll Value { if let OperandValue::Pair(a, b) = self.val { let llty = self.layout.llvm_type(bx.cx); debug!("Operand::immediate_or_packed_pair: packing {:?} into {:?}", @@ -191,10 +173,10 @@ impl<'a, 'tcx> OperandRef<'tcx> { } /// If the type is a pair, we return a `Pair`, otherwise, an `Immediate`. - pub fn from_immediate_or_packed_pair(bx: &Builder<'a, 'tcx>, - llval: ValueRef, + pub fn from_immediate_or_packed_pair(bx: &Builder<'a, 'll, 'tcx>, + llval: &'ll Value, layout: TyLayout<'tcx>) - -> OperandRef<'tcx> { + -> OperandRef<'ll, 'tcx> { let val = if let layout::Abi::ScalarPair(ref a, ref b) = layout.abi { debug!("Operand::from_immediate_or_packed_pair: unpacking {:?} @ {:?}", llval, layout); @@ -209,7 +191,7 @@ impl<'a, 'tcx> OperandRef<'tcx> { OperandRef { val, layout } } - pub fn extract_field(&self, bx: &Builder<'a, 'tcx>, i: usize) -> OperandRef<'tcx> { + pub fn extract_field(&self, bx: &Builder<'a, 'll, 'tcx>, i: usize) -> OperandRef<'ll, 'tcx> { let field = self.layout.field(bx.cx, i); let offset = self.layout.fields.offset(i); @@ -267,24 +249,29 @@ impl<'a, 'tcx> OperandRef<'tcx> { } } -impl<'a, 'tcx> OperandValue { - pub fn store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) { +impl OperandValue<'ll> { + pub fn store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'ll, 'tcx>) { self.store_with_flags(bx, dest, MemFlags::empty()); } - pub fn volatile_store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) { + pub fn volatile_store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'ll, 'tcx>) { self.store_with_flags(bx, dest, MemFlags::VOLATILE); } - pub fn unaligned_volatile_store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) { + pub fn unaligned_volatile_store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'ll, 'tcx>) { self.store_with_flags(bx, dest, MemFlags::VOLATILE | MemFlags::UNALIGNED); } - pub fn nontemporal_store(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>) { + pub fn nontemporal_store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'ll, 'tcx>) { self.store_with_flags(bx, dest, MemFlags::NONTEMPORAL); } - fn store_with_flags(self, bx: &Builder<'a, 'tcx>, dest: PlaceRef<'tcx>, flags: MemFlags) { + fn store_with_flags( + self, + bx: &Builder<'a, 'll, 'tcx>, + dest: PlaceRef<'ll, 'tcx>, + flags: MemFlags, + ) { debug!("OperandRef::store: operand={:?}, dest={:?}", self, dest); // Avoid generating stores of zero-sized values, because the only way to have a zero-sized // value is through `undef`, and store itself is useless. @@ -311,11 +298,11 @@ impl<'a, 'tcx> OperandValue { } } -impl<'a, 'tcx> FunctionCx<'a, 'tcx> { +impl FunctionCx<'a, 'll, 'tcx> { fn maybe_codegen_consume_direct(&mut self, - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, place: &mir::Place<'tcx>) - -> Option> + -> Option> { debug!("maybe_codegen_consume_direct(place={:?})", place); @@ -361,9 +348,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } pub fn codegen_consume(&mut self, - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, place: &mir::Place<'tcx>) - -> OperandRef<'tcx> + -> OperandRef<'ll, 'tcx> { debug!("codegen_consume(place={:?})", place); @@ -385,9 +372,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } pub fn codegen_operand(&mut self, - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, operand: &mir::Operand<'tcx>) - -> OperandRef<'tcx> + -> OperandRef<'ll, 'tcx> { debug!("codegen_operand(operand={:?})", operand); diff --git a/src/librustc_codegen_llvm/mir/place.rs b/src/librustc_codegen_llvm/mir/place.rs index 9abf9077a9577..abc3dbdab2f5b 100644 --- a/src/librustc_codegen_llvm/mir/place.rs +++ b/src/librustc_codegen_llvm/mir/place.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::{self, ValueRef, LLVMConstInBoundsGEP}; +use llvm::{self, LLVMConstInBoundsGEP}; use rustc::ty::{self, Ty}; use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, Size}; use rustc::mir; @@ -24,18 +24,16 @@ use value::Value; use glue; use mir::constant::const_alloc_to_llvm; -use std::ptr; - use super::{FunctionCx, LocalRef}; use super::operand::{OperandRef, OperandValue}; #[derive(Copy, Clone, Debug)] -pub struct PlaceRef<'tcx> { +pub struct PlaceRef<'ll, 'tcx> { /// Pointer to the contents of the place - pub llval: ValueRef, + pub llval: &'ll Value, /// This place's extra data if it is unsized, or null - pub llextra: ValueRef, + pub llextra: Option<&'ll Value>, /// Monomorphized type of this place, including variant information pub layout: TyLayout<'tcx>, @@ -44,25 +42,26 @@ pub struct PlaceRef<'tcx> { pub align: Align, } -impl<'a, 'tcx> PlaceRef<'tcx> { - pub fn new_sized(llval: ValueRef, - layout: TyLayout<'tcx>, - align: Align) - -> PlaceRef<'tcx> { +impl PlaceRef<'ll, 'tcx> { + pub fn new_sized( + llval: &'ll Value, + layout: TyLayout<'tcx>, + align: Align, + ) -> PlaceRef<'ll, 'tcx> { PlaceRef { llval, - llextra: ptr::null_mut(), + llextra: None, layout, align } } pub fn from_const_alloc( - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, layout: TyLayout<'tcx>, alloc: &mir::interpret::Allocation, offset: Size, - ) -> PlaceRef<'tcx> { + ) -> PlaceRef<'ll, 'tcx> { let init = const_alloc_to_llvm(bx.cx, alloc); let base_addr = consts::addr_of(bx.cx, init, layout.align, "byte_str"); @@ -75,19 +74,18 @@ impl<'a, 'tcx> PlaceRef<'tcx> { PlaceRef::new_sized(llval, layout, alloc.align) } - pub fn alloca(bx: &Builder<'a, 'tcx>, layout: TyLayout<'tcx>, name: &str) - -> PlaceRef<'tcx> { + pub fn alloca(bx: &Builder<'a, 'll, 'tcx>, layout: TyLayout<'tcx>, name: &str) + -> PlaceRef<'ll, 'tcx> { debug!("alloca({:?}: {:?})", name, layout); let tmp = bx.alloca(layout.llvm_type(bx.cx), name, layout.align); Self::new_sized(tmp, layout, layout.align) } - pub fn len(&self, cx: &CodegenCx<'a, 'tcx>) -> ValueRef { + pub fn len(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Value { if let layout::FieldPlacement::Array { count, .. } = self.layout.fields { if self.layout.is_unsized() { - assert!(self.has_extra()); assert_eq!(count, 0); - self.llextra + self.llextra.unwrap() } else { C_usize(cx, count) } @@ -96,14 +94,10 @@ impl<'a, 'tcx> PlaceRef<'tcx> { } } - pub fn has_extra(&self) -> bool { - !self.llextra.is_null() - } - - pub fn load(&self, bx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> { + pub fn load(&self, bx: &Builder<'a, 'll, 'tcx>) -> OperandRef<'ll, 'tcx> { debug!("PlaceRef::load: {:?}", self); - assert!(!self.has_extra()); + assert_eq!(self.llextra, None); if self.layout.is_zst() { return OperandRef::new_zst(bx.cx, self.layout); @@ -126,23 +120,21 @@ impl<'a, 'tcx> PlaceRef<'tcx> { }; let val = if self.layout.is_llvm_immediate() { - let mut const_llval = ptr::null_mut(); + let mut const_llval = None; unsafe { - let global = llvm::LLVMIsAGlobalVariable(self.llval); - if !global.is_null() && llvm::LLVMIsGlobalConstant(global) == llvm::True { - const_llval = llvm::LLVMGetInitializer(global); + if let Some(global) = llvm::LLVMIsAGlobalVariable(self.llval) { + if llvm::LLVMIsGlobalConstant(global) == llvm::True { + const_llval = llvm::LLVMGetInitializer(global); + } } } - - let llval = if !const_llval.is_null() { - const_llval - } else { + let llval = const_llval.unwrap_or_else(|| { let load = bx.load(self.llval, self.align); if let layout::Abi::Scalar(ref scalar) = self.layout.abi { scalar_load_metadata(load, scalar); } load - }; + }); OperandValue::Immediate(base::to_immediate(bx, llval, self.layout)) } else if let layout::Abi::ScalarPair(ref a, ref b) = self.layout.abi { let load = |i, scalar: &layout::Scalar| { @@ -164,7 +156,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> { } /// Access a field, at a point when the value's case is known. - pub fn project_field(self, bx: &Builder<'a, 'tcx>, ix: usize) -> PlaceRef<'tcx> { + pub fn project_field(self, bx: &Builder<'a, 'll, 'tcx>, ix: usize) -> PlaceRef<'ll, 'tcx> { let cx = bx.cx; let field = self.layout.field(cx, ix); let offset = self.layout.fields.offset(ix); @@ -187,7 +179,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> { llextra: if cx.type_has_metadata(field.ty) { self.llextra } else { - ptr::null_mut() + None }, layout: field, align, @@ -199,9 +191,9 @@ impl<'a, 'tcx> PlaceRef<'tcx> { // * known alignment - sized types, [T], str or a foreign type // * packed struct - there is no alignment padding match field.ty.sty { - _ if !self.has_extra() => { + _ if self.llextra.is_none() => { debug!("Unsized field `{}`, of `{:?}` has no metadata for adjustment", - ix, Value(self.llval)); + ix, self.llval); return simple(); } _ if !field.is_unsized() => return simple(), @@ -249,7 +241,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> { let offset = bx.and(bx.add(unaligned_offset, align_sub_1), bx.neg(unsized_align)); - debug!("struct_field_ptr: DST field offset: {:?}", Value(offset)); + debug!("struct_field_ptr: DST field offset: {:?}", offset); // Cast and adjust pointer let byte_ptr = bx.pointercast(self.llval, Type::i8p(cx)); @@ -268,7 +260,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> { } /// Obtain the actual discriminant of a value. - pub fn codegen_get_discr(self, bx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> ValueRef { + pub fn codegen_get_discr(self, bx: &Builder<'a, 'll, 'tcx>, cast_to: Ty<'tcx>) -> &'ll Value { let cast_to = bx.cx.layout_of(cast_to).immediate_llvm_type(bx.cx); if self.layout.abi == layout::Abi::Uninhabited { return C_undef(cast_to); @@ -332,7 +324,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> { /// Set the discriminant for a new value of the given case of the given /// representation. - pub fn codegen_set_discr(&self, bx: &Builder<'a, 'tcx>, variant_index: usize) { + pub fn codegen_set_discr(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: usize) { if self.layout.for_variant(bx.cx, variant_index).abi == layout::Abi::Uninhabited { return; } @@ -386,18 +378,18 @@ impl<'a, 'tcx> PlaceRef<'tcx> { } } - pub fn project_index(&self, bx: &Builder<'a, 'tcx>, llindex: ValueRef) - -> PlaceRef<'tcx> { + pub fn project_index(&self, bx: &Builder<'a, 'll, 'tcx>, llindex: &'ll Value) + -> PlaceRef<'ll, 'tcx> { PlaceRef { llval: bx.inbounds_gep(self.llval, &[C_usize(bx.cx, 0), llindex]), - llextra: ptr::null_mut(), + llextra: None, layout: self.layout.field(bx.cx, 0), align: self.align } } - pub fn project_downcast(&self, bx: &Builder<'a, 'tcx>, variant_index: usize) - -> PlaceRef<'tcx> { + pub fn project_downcast(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: usize) + -> PlaceRef<'ll, 'tcx> { let mut downcast = *self; downcast.layout = self.layout.for_variant(bx.cx, variant_index); @@ -408,20 +400,20 @@ impl<'a, 'tcx> PlaceRef<'tcx> { downcast } - pub fn storage_live(&self, bx: &Builder<'a, 'tcx>) { + pub fn storage_live(&self, bx: &Builder<'a, 'll, 'tcx>) { bx.lifetime_start(self.llval, self.layout.size); } - pub fn storage_dead(&self, bx: &Builder<'a, 'tcx>) { + pub fn storage_dead(&self, bx: &Builder<'a, 'll, 'tcx>) { bx.lifetime_end(self.llval, self.layout.size); } } -impl<'a, 'tcx> FunctionCx<'a, 'tcx> { +impl FunctionCx<'a, 'll, 'tcx> { pub fn codegen_place(&mut self, - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, place: &mir::Place<'tcx>) - -> PlaceRef<'tcx> { + -> PlaceRef<'ll, 'tcx> { debug!("codegen_place(place={:?})", place); let cx = bx.cx; @@ -513,9 +505,8 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { subslice.layout = bx.cx.layout_of(self.monomorphize(&projected_ty)); if subslice.layout.is_unsized() { - assert!(cg_base.has_extra()); - subslice.llextra = bx.sub(cg_base.llextra, - C_usize(bx.cx, (from as u64) + (to as u64))); + subslice.llextra = Some(bx.sub(cg_base.llextra.unwrap(), + C_usize(bx.cx, (from as u64) + (to as u64)))); } // Cast the place pointer type to the new diff --git a/src/librustc_codegen_llvm/mir/rvalue.rs b/src/librustc_codegen_llvm/mir/rvalue.rs index 2e81fc16a5838..02b5c27840eab 100644 --- a/src/librustc_codegen_llvm/mir/rvalue.rs +++ b/src/librustc_codegen_llvm/mir/rvalue.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use llvm::{self, ValueRef}; +use llvm; use rustc::ty::{self, Ty}; use rustc::ty::cast::{CastTy, IntTy}; use rustc::ty::layout::{self, LayoutOf}; @@ -32,15 +32,15 @@ use super::{FunctionCx, LocalRef}; use super::operand::{OperandRef, OperandValue}; use super::place::PlaceRef; -impl<'a, 'tcx> FunctionCx<'a, 'tcx> { +impl FunctionCx<'a, 'll, 'tcx> { pub fn codegen_rvalue(&mut self, - bx: Builder<'a, 'tcx>, - dest: PlaceRef<'tcx>, + bx: Builder<'a, 'll, 'tcx>, + dest: PlaceRef<'ll, 'tcx>, rvalue: &mir::Rvalue<'tcx>) - -> Builder<'a, 'tcx> + -> Builder<'a, 'll, 'tcx> { debug!("codegen_rvalue(dest.llval={:?}, rvalue={:?})", - Value(dest.llval), rvalue); + dest.llval, rvalue); match *rvalue { mir::Rvalue::Use(ref operand) => { @@ -176,9 +176,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } pub fn codegen_rvalue_operand(&mut self, - bx: Builder<'a, 'tcx>, + bx: Builder<'a, 'll, 'tcx>, rvalue: &mir::Rvalue<'tcx>) - -> (Builder<'a, 'tcx>, OperandRef<'tcx>) + -> (Builder<'a, 'll, 'tcx>, OperandRef<'ll, 'tcx>) { assert!(self.rvalue_creates_operand(rvalue), "cannot codegen {:?} to operand", rvalue); @@ -371,7 +371,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { let val = if !bx.cx.type_has_metadata(ty) { OperandValue::Immediate(cg_place.llval) } else { - OperandValue::Pair(cg_place.llval, cg_place.llextra) + OperandValue::Pair(cg_place.llval, cg_place.llextra.unwrap()) }; (bx, OperandRef { val, @@ -511,10 +511,11 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } } - fn evaluate_array_len(&mut self, - bx: &Builder<'a, 'tcx>, - place: &mir::Place<'tcx>) -> ValueRef - { + fn evaluate_array_len( + &mut self, + bx: &Builder<'a, 'll, 'tcx>, + place: &mir::Place<'tcx>, + ) -> &'ll Value { // ZST are passed as operands and require special handling // because codegen_place() panics if Local is operand. if let mir::Place::Local(index) = *place { @@ -530,12 +531,14 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { return cg_value.len(bx.cx); } - pub fn codegen_scalar_binop(&mut self, - bx: &Builder<'a, 'tcx>, - op: mir::BinOp, - lhs: ValueRef, - rhs: ValueRef, - input_ty: Ty<'tcx>) -> ValueRef { + pub fn codegen_scalar_binop( + &mut self, + bx: &Builder<'a, 'll, 'tcx>, + op: mir::BinOp, + lhs: &'ll Value, + rhs: &'ll Value, + input_ty: Ty<'tcx>, + ) -> &'ll Value { let is_float = input_ty.is_fp(); let is_signed = input_ty.is_signed(); let is_nil = input_ty.is_nil(); @@ -596,15 +599,16 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } } - pub fn codegen_fat_ptr_binop(&mut self, - bx: &Builder<'a, 'tcx>, - op: mir::BinOp, - lhs_addr: ValueRef, - lhs_extra: ValueRef, - rhs_addr: ValueRef, - rhs_extra: ValueRef, - _input_ty: Ty<'tcx>) - -> ValueRef { + pub fn codegen_fat_ptr_binop( + &mut self, + bx: &Builder<'a, 'll, 'tcx>, + op: mir::BinOp, + lhs_addr: &'ll Value, + lhs_extra: &'ll Value, + rhs_addr: &'ll Value, + rhs_extra: &'ll Value, + _input_ty: Ty<'tcx>, + ) -> &'ll Value { match op { mir::BinOp::Eq => { bx.and( @@ -644,11 +648,11 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } pub fn codegen_scalar_checked_binop(&mut self, - bx: &Builder<'a, 'tcx>, + bx: &Builder<'a, 'll, 'tcx>, op: mir::BinOp, - lhs: ValueRef, - rhs: ValueRef, - input_ty: Ty<'tcx>) -> OperandValue { + lhs: &'ll Value, + rhs: &'ll Value, + input_ty: Ty<'tcx>) -> OperandValue<'ll> { // This case can currently arise only from functions marked // with #[rustc_inherit_overflow_checks] and inlined from // another crate (mostly core::num generic/#[inline] fns), @@ -721,7 +725,7 @@ enum OverflowOp { Add, Sub, Mul } -fn get_overflow_intrinsic(oop: OverflowOp, bx: &Builder, ty: Ty) -> ValueRef { +fn get_overflow_intrinsic(oop: OverflowOp, bx: &Builder<'_, 'll, '_>, ty: Ty) -> &'ll Value { use syntax::ast::IntTy::*; use syntax::ast::UintTy::*; use rustc::ty::{TyInt, TyUint}; @@ -796,11 +800,11 @@ fn get_overflow_intrinsic(oop: OverflowOp, bx: &Builder, ty: Ty) -> ValueRef { bx.cx.get_intrinsic(&name) } -fn cast_int_to_float(bx: &Builder, +fn cast_int_to_float(bx: &Builder<'_, 'll, '_>, signed: bool, - x: ValueRef, - int_ty: Type, - float_ty: Type) -> ValueRef { + x: &'ll Value, + int_ty: &'ll Type, + float_ty: &'ll Type) -> &'ll Value { // Most integer types, even i128, fit into [-f32::MAX, f32::MAX] after rounding. // It's only u128 -> f32 that can cause overflows (i.e., should yield infinity). // LLVM's uitofp produces undef in those cases, so we manually check for that case. @@ -826,11 +830,11 @@ fn cast_int_to_float(bx: &Builder, } } -fn cast_float_to_int(bx: &Builder, +fn cast_float_to_int(bx: &Builder<'_, 'll, '_>, signed: bool, - x: ValueRef, - float_ty: Type, - int_ty: Type) -> ValueRef { + x: &'ll Value, + float_ty: &'ll Type, + int_ty: &'ll Type) -> &'ll Value { let fptosui_result = if signed { bx.fptosi(x, int_ty) } else { @@ -859,14 +863,14 @@ fn cast_float_to_int(bx: &Builder, // On the other hand, f_max works even if int_ty::MAX is greater than float_ty::MAX. Because // we're rounding towards zero, we just get float_ty::MAX (which is always an integer). // This already happens today with u128::MAX = 2^128 - 1 > f32::MAX. - fn compute_clamp_bounds(signed: bool, int_ty: Type) -> (u128, u128) { + fn compute_clamp_bounds(signed: bool, int_ty: &Type) -> (u128, u128) { let rounded_min = F::from_i128_r(int_min(signed, int_ty), Round::TowardZero); assert_eq!(rounded_min.status, Status::OK); let rounded_max = F::from_u128_r(int_max(signed, int_ty), Round::TowardZero); assert!(rounded_max.value.is_finite()); (rounded_min.value.to_bits(), rounded_max.value.to_bits()) } - fn int_max(signed: bool, int_ty: Type) -> u128 { + fn int_max(signed: bool, int_ty: &Type) -> u128 { let shift_amount = 128 - int_ty.int_width(); if signed { i128::MAX as u128 >> shift_amount @@ -874,7 +878,7 @@ fn cast_float_to_int(bx: &Builder, u128::MAX >> shift_amount } } - fn int_min(signed: bool, int_ty: Type) -> i128 { + fn int_min(signed: bool, int_ty: &Type) -> i128 { if signed { i128::MIN >> (128 - int_ty.int_width()) } else { diff --git a/src/librustc_codegen_llvm/mir/statement.rs b/src/librustc_codegen_llvm/mir/statement.rs index c0cce297ef6a9..06340a3e5d8b4 100644 --- a/src/librustc_codegen_llvm/mir/statement.rs +++ b/src/librustc_codegen_llvm/mir/statement.rs @@ -16,11 +16,11 @@ use builder::Builder; use super::FunctionCx; use super::LocalRef; -impl<'a, 'tcx> FunctionCx<'a, 'tcx> { +impl FunctionCx<'a, 'll, 'tcx> { pub fn codegen_statement(&mut self, - bx: Builder<'a, 'tcx>, + bx: Builder<'a, 'll, 'tcx>, statement: &mir::Statement<'tcx>) - -> Builder<'a, 'tcx> { + -> Builder<'a, 'll, 'tcx> { debug!("codegen_statement(statement={:?})", statement); self.set_debug_loc(&bx, statement.source_info); diff --git a/src/librustc_codegen_llvm/type_.rs b/src/librustc_codegen_llvm/type_.rs index a77acc4f1756f..9fa7cc46aee5e 100644 --- a/src/librustc_codegen_llvm/type_.rs +++ b/src/librustc_codegen_llvm/type_.rs @@ -10,9 +10,10 @@ #![allow(non_upper_case_globals)] +pub use llvm::Type; + use llvm; -use llvm::{ContextRef, TypeRef, Bool, False, True, TypeKind}; -use llvm::{Float, Double, X86_FP80, PPC_FP128, FP128}; +use llvm::{Bool, False, True, TypeKind}; use context::CodegenCx; @@ -21,122 +22,125 @@ use rustc::ty::layout::{self, Align, Size}; use std::ffi::CString; use std::fmt; -use std::mem; -use std::ptr; use libc::c_uint; -#[derive(Clone, Copy, PartialEq)] -#[repr(C)] -pub struct Type { - rf: TypeRef +impl PartialEq for Type { + fn eq(&self, other: &Self) -> bool { + self as *const _ == other as *const _ + } } impl fmt::Debug for Type { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(&llvm::build_string(|s| unsafe { - llvm::LLVMRustWriteTypeToString(self.to_ref(), s); + llvm::LLVMRustWriteTypeToString(self, s); }).expect("non-UTF8 type description from LLVM")) } } -macro_rules! ty { - ($e:expr) => ( Type::from_ref(unsafe { $e })) -} - -/// Wrapper for LLVM TypeRef impl Type { - #[inline(always)] - pub fn from_ref(r: TypeRef) -> Type { - Type { - rf: r + pub fn void(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMVoidTypeInContext(cx.llcx) } } - #[inline(always)] // So it doesn't kill --opt-level=0 builds of the compiler - pub fn to_ref(&self) -> TypeRef { - self.rf - } - - pub fn to_ref_slice(slice: &[Type]) -> &[TypeRef] { - unsafe { mem::transmute(slice) } - } - - pub fn void(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMVoidTypeInContext(cx.llcx)) + pub fn metadata(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMRustMetadataTypeInContext(cx.llcx) + } } - pub fn metadata(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMRustMetadataTypeInContext(cx.llcx)) + pub fn i1(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMInt1TypeInContext(cx.llcx) + } } - pub fn i1(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMInt1TypeInContext(cx.llcx)) + pub fn i8(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMInt8TypeInContext(cx.llcx) + } } - pub fn i8(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMInt8TypeInContext(cx.llcx)) + pub fn i8_llcx(llcx: &llvm::Context) -> &Type { + unsafe { + llvm::LLVMInt8TypeInContext(llcx) + } } - pub fn i8_llcx(llcx: ContextRef) -> Type { - ty!(llvm::LLVMInt8TypeInContext(llcx)) + pub fn i16(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMInt16TypeInContext(cx.llcx) + } } - pub fn i16(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMInt16TypeInContext(cx.llcx)) + pub fn i32(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMInt32TypeInContext(cx.llcx) + } } - pub fn i32(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMInt32TypeInContext(cx.llcx)) + pub fn i64(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMInt64TypeInContext(cx.llcx) + } } - pub fn i64(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMInt64TypeInContext(cx.llcx)) + pub fn i128(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMIntTypeInContext(cx.llcx, 128) + } } - pub fn i128(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMIntTypeInContext(cx.llcx, 128)) + // Creates an integer type with the given number of bits, e.g. i24 + pub fn ix(cx: &CodegenCx<'ll, '_>, num_bits: u64) -> &'ll Type { + unsafe { + llvm::LLVMIntTypeInContext(cx.llcx, num_bits as c_uint) + } } // Creates an integer type with the given number of bits, e.g. i24 - pub fn ix(cx: &CodegenCx, num_bits: u64) -> Type { - ty!(llvm::LLVMIntTypeInContext(cx.llcx, num_bits as c_uint)) + pub fn ix_llcx(llcx: &llvm::Context, num_bits: u64) -> &Type { + unsafe { + llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint) + } } - pub fn f32(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMFloatTypeInContext(cx.llcx)) + pub fn f32(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMFloatTypeInContext(cx.llcx) + } } - pub fn f64(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMDoubleTypeInContext(cx.llcx)) + pub fn f64(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMDoubleTypeInContext(cx.llcx) + } } - pub fn bool(cx: &CodegenCx) -> Type { + pub fn bool(cx: &CodegenCx<'ll, '_>) -> &'ll Type { Type::i8(cx) } - pub fn char(cx: &CodegenCx) -> Type { + pub fn char(cx: &CodegenCx<'ll, '_>) -> &'ll Type { Type::i32(cx) } - pub fn i8p(cx: &CodegenCx) -> Type { + pub fn i8p(cx: &CodegenCx<'ll, '_>) -> &'ll Type { Type::i8(cx).ptr_to() } - pub fn i8p_llcx(llcx: ContextRef) -> Type { + pub fn i8p_llcx(llcx: &llvm::Context) -> &Type { Type::i8_llcx(llcx).ptr_to() } - pub fn isize(cx: &CodegenCx) -> Type { - match &cx.tcx.sess.target.target.target_pointer_width[..] { - "16" => Type::i16(cx), - "32" => Type::i32(cx), - "64" => Type::i64(cx), - tws => bug!("Unsupported target word size for int: {}", tws), - } + pub fn isize(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + cx.isize_ty } - pub fn c_int(cx: &CodegenCx) -> Type { + pub fn c_int(cx: &CodegenCx<'ll, '_>) -> &'ll Type { match &cx.tcx.sess.target.target.target_c_int_width[..] { "16" => Type::i16(cx), "32" => Type::i32(cx), @@ -145,7 +149,7 @@ impl Type { } } - pub fn int_from_ty(cx: &CodegenCx, t: ast::IntTy) -> Type { + pub fn int_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::IntTy) -> &'ll Type { match t { ast::IntTy::Isize => cx.isize_ty, ast::IntTy::I8 => Type::i8(cx), @@ -156,7 +160,7 @@ impl Type { } } - pub fn uint_from_ty(cx: &CodegenCx, t: ast::UintTy) -> Type { + pub fn uint_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::UintTy) -> &'ll Type { match t { ast::UintTy::Usize => cx.isize_ty, ast::UintTy::U8 => Type::i8(cx), @@ -167,93 +171,103 @@ impl Type { } } - pub fn float_from_ty(cx: &CodegenCx, t: ast::FloatTy) -> Type { + pub fn float_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::FloatTy) -> &'ll Type { match t { ast::FloatTy::F32 => Type::f32(cx), ast::FloatTy::F64 => Type::f64(cx), } } - pub fn func(args: &[Type], ret: &Type) -> Type { - let slice: &[TypeRef] = Type::to_ref_slice(args); - ty!(llvm::LLVMFunctionType(ret.to_ref(), slice.as_ptr(), - args.len() as c_uint, False)) + pub fn func(args: &[&'ll Type], ret: &'ll Type) -> &'ll Type { + unsafe { + llvm::LLVMFunctionType(ret, args.as_ptr(), + args.len() as c_uint, False) + } } - pub fn variadic_func(args: &[Type], ret: &Type) -> Type { - let slice: &[TypeRef] = Type::to_ref_slice(args); - ty!(llvm::LLVMFunctionType(ret.to_ref(), slice.as_ptr(), - args.len() as c_uint, True)) + pub fn variadic_func(args: &[&'ll Type], ret: &'ll Type) -> &'ll Type { + unsafe { + llvm::LLVMFunctionType(ret, args.as_ptr(), + args.len() as c_uint, True) + } } - pub fn struct_(cx: &CodegenCx, els: &[Type], packed: bool) -> Type { - let els: &[TypeRef] = Type::to_ref_slice(els); - ty!(llvm::LLVMStructTypeInContext(cx.llcx, els.as_ptr(), + pub fn struct_(cx: &CodegenCx<'ll, '_>, els: &[&'ll Type], packed: bool) -> &'ll Type { + unsafe { + llvm::LLVMStructTypeInContext(cx.llcx, els.as_ptr(), els.len() as c_uint, - packed as Bool)) + packed as Bool) + } } - pub fn named_struct(cx: &CodegenCx, name: &str) -> Type { + pub fn named_struct(cx: &CodegenCx<'ll, '_>, name: &str) -> &'ll Type { let name = CString::new(name).unwrap(); - ty!(llvm::LLVMStructCreateNamed(cx.llcx, name.as_ptr())) + unsafe { + llvm::LLVMStructCreateNamed(cx.llcx, name.as_ptr()) + } } - pub fn array(ty: &Type, len: u64) -> Type { - ty!(llvm::LLVMRustArrayType(ty.to_ref(), len)) + pub fn array(ty: &Type, len: u64) -> &Type { + unsafe { + llvm::LLVMRustArrayType(ty, len) + } } - pub fn vector(ty: &Type, len: u64) -> Type { - ty!(llvm::LLVMVectorType(ty.to_ref(), len as c_uint)) + pub fn vector(ty: &Type, len: u64) -> &Type { + unsafe { + llvm::LLVMVectorType(ty, len as c_uint) + } } pub fn kind(&self) -> TypeKind { unsafe { - llvm::LLVMRustGetTypeKind(self.to_ref()) + llvm::LLVMRustGetTypeKind(self) } } - pub fn set_struct_body(&mut self, els: &[Type], packed: bool) { - let slice: &[TypeRef] = Type::to_ref_slice(els); + pub fn set_struct_body(&'ll self, els: &[&'ll Type], packed: bool) { unsafe { - llvm::LLVMStructSetBody(self.to_ref(), slice.as_ptr(), + llvm::LLVMStructSetBody(self, els.as_ptr(), els.len() as c_uint, packed as Bool) } } - pub fn ptr_to(&self) -> Type { - ty!(llvm::LLVMPointerType(self.to_ref(), 0)) + pub fn ptr_to(&self) -> &Type { + unsafe { + llvm::LLVMPointerType(self, 0) + } } - pub fn element_type(&self) -> Type { + pub fn element_type(&self) -> &Type { unsafe { - Type::from_ref(llvm::LLVMGetElementType(self.to_ref())) + llvm::LLVMGetElementType(self) } } /// Return the number of elements in `self` if it is a LLVM vector type. pub fn vector_length(&self) -> usize { unsafe { - llvm::LLVMGetVectorSize(self.to_ref()) as usize + llvm::LLVMGetVectorSize(self) as usize } } - pub fn func_params(&self) -> Vec { + pub fn func_params(&self) -> Vec<&Type> { unsafe { - let n_args = llvm::LLVMCountParamTypes(self.to_ref()) as usize; - let mut args = vec![Type { rf: ptr::null_mut() }; n_args]; - llvm::LLVMGetParamTypes(self.to_ref(), - args.as_mut_ptr() as *mut TypeRef); + let n_args = llvm::LLVMCountParamTypes(self) as usize; + let mut args = Vec::with_capacity(n_args); + llvm::LLVMGetParamTypes(self, args.as_mut_ptr()); + args.set_len(n_args); args } } pub fn float_width(&self) -> usize { match self.kind() { - Float => 32, - Double => 64, - X86_FP80 => 80, - FP128 | PPC_FP128 => 128, + TypeKind::Float => 32, + TypeKind::Double => 64, + TypeKind::X86_FP80 => 80, + TypeKind::FP128 | TypeKind::PPC_FP128 => 128, _ => bug!("llvm_float_width called on a non-float type") } } @@ -261,11 +275,11 @@ impl Type { /// Retrieve the bit width of the integer type `self`. pub fn int_width(&self) -> u64 { unsafe { - llvm::LLVMGetIntTypeWidth(self.to_ref()) as u64 + llvm::LLVMGetIntTypeWidth(self) as u64 } } - pub fn from_integer(cx: &CodegenCx, i: layout::Integer) -> Type { + pub fn from_integer(cx: &CodegenCx<'ll, '_>, i: layout::Integer) -> &'ll Type { use rustc::ty::layout::Integer::*; match i { I8 => Type::i8(cx), @@ -278,7 +292,7 @@ impl Type { /// Return a LLVM type that has at most the required alignment, /// as a conservative approximation for unknown pointee types. - pub fn pointee_for_abi_align(cx: &CodegenCx, align: Align) -> Type { + pub fn pointee_for_abi_align(cx: &CodegenCx<'ll, '_>, align: Align) -> &'ll Type { // FIXME(eddyb) We could find a better approximation if ity.align < align. let ity = layout::Integer::approximate_abi_align(cx, align); Type::from_integer(cx, ity) @@ -286,15 +300,17 @@ impl Type { /// Return a LLVM type that has at most the required alignment, /// and exactly the required size, as a best-effort padding array. - pub fn padding_filler(cx: &CodegenCx, size: Size, align: Align) -> Type { + pub fn padding_filler(cx: &CodegenCx<'ll, '_>, size: Size, align: Align) -> &'ll Type { let unit = layout::Integer::approximate_abi_align(cx, align); let size = size.bytes(); let unit_size = unit.size().bytes(); assert_eq!(size % unit_size, 0); - Type::array(&Type::from_integer(cx, unit), size / unit_size) + Type::array(Type::from_integer(cx, unit), size / unit_size) } - pub fn x86_mmx(cx: &CodegenCx) -> Type { - ty!(llvm::LLVMX86MMXTypeInContext(cx.llcx)) + pub fn x86_mmx(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + unsafe { + llvm::LLVMX86MMXTypeInContext(cx.llcx) + } } } diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index 4728d7717a1e1..5fd4f15acd157 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -23,8 +23,8 @@ use std::fmt::Write; fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, layout: TyLayout<'tcx>, - defer: &mut Option<(Type, TyLayout<'tcx>)>) - -> Type { + defer: &mut Option<(&'a Type, TyLayout<'tcx>)>) + -> &'a Type { match layout.abi { layout::Abi::Scalar(_) => bug!("handled elsewhere"), layout::Abi::Vector { ref element, count } => { @@ -42,7 +42,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, return Type::x86_mmx(cx) } else { let element = layout.scalar_llvm_type_at(cx, element, Size::ZERO); - return Type::vector(&element, count); + return Type::vector(element, count); } } layout::Abi::ScalarPair(..) => { @@ -96,7 +96,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } } layout::FieldPlacement::Array { count, .. } => { - Type::array(&layout.field(cx, 0).llvm_type(cx), count) + Type::array(layout.field(cx, 0).llvm_type(cx), count) } layout::FieldPlacement::Arbitrary { .. } => { match name { @@ -116,14 +116,14 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fn struct_llfields<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, layout: TyLayout<'tcx>) - -> (Vec, bool) { + -> (Vec<&'a Type>, bool) { debug!("struct_llfields: {:#?}", layout); let field_count = layout.fields.count(); let mut packed = false; let mut offset = Size::ZERO; let mut prev_align = layout.align; - let mut result: Vec = Vec::with_capacity(1 + field_count * 2); + let mut result: Vec<_> = Vec::with_capacity(1 + field_count * 2); for i in layout.fields.index_by_increasing_offset() { let field = layout.field(cx, i); packed |= layout.align.abi() < field.align.abi(); @@ -201,12 +201,12 @@ pub struct PointeeInfo { pub trait LayoutLlvmExt<'tcx> { fn is_llvm_immediate(&self) -> bool; fn is_llvm_scalar_pair<'a>(&self) -> bool; - fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type; - fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type; + fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type; + fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type; fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, - scalar: &layout::Scalar, offset: Size) -> Type; + scalar: &layout::Scalar, offset: Size) -> &'a Type; fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>, - index: usize, immediate: bool) -> Type; + index: usize, immediate: bool) -> &'a Type; fn llvm_field_index(&self, index: usize) -> u64; fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size) -> Option; @@ -244,7 +244,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { /// with the inner-most trailing unsized field using the "minimal unit" /// of that field's type - this is useful for taking the address of /// that field and ensuring the struct has the right alignment. - fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type { + fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type { if let layout::Abi::Scalar(ref scalar) = self.abi { // Use a different cache for scalars because pointers to DSTs // can be either fat or thin (data pointers of fat pointers). @@ -304,7 +304,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { cx.lltypes.borrow_mut().insert((self.ty, variant_index), llty); - if let Some((mut llty, layout)) = defer { + if let Some((llty, layout)) = defer { let (llfields, packed) = struct_llfields(cx, layout); llty.set_struct_body(&llfields, packed) } @@ -312,7 +312,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { llty } - fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> Type { + fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type { if let layout::Abi::Scalar(ref scalar) = self.abi { if scalar.is_bool() { return Type::i1(cx); @@ -322,7 +322,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { } fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, - scalar: &layout::Scalar, offset: Size) -> Type { + scalar: &layout::Scalar, offset: Size) -> &'a Type { match scalar.value { layout::Int(i, _) => Type::from_integer(cx, i), layout::Float(FloatTy::F32) => Type::f32(cx), @@ -340,7 +340,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> { } fn scalar_pair_element_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>, - index: usize, immediate: bool) -> Type { + index: usize, immediate: bool) -> &'a Type { // HACK(eddyb) special-case fat pointers until LLVM removes // pointee types, to avoid bitcasting every `OperandRef::deref`. match self.ty.sty { diff --git a/src/librustc_codegen_llvm/value.rs b/src/librustc_codegen_llvm/value.rs index 287ad87caacf9..3328948c2951e 100644 --- a/src/librustc_codegen_llvm/value.rs +++ b/src/librustc_codegen_llvm/value.rs @@ -8,17 +8,32 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +pub use llvm::Value; + use llvm; use std::fmt; +use std::hash::{Hash, Hasher}; + +impl PartialEq for Value { + fn eq(&self, other: &Self) -> bool { + self as *const _ == other as *const _ + } +} + +impl Eq for Value {} + +impl Hash for Value { + fn hash(&self, hasher: &mut H) { + (self as *const Self).hash(hasher); + } +} -#[derive(Copy, Clone, PartialEq)] -pub struct Value(pub llvm::ValueRef); impl fmt::Debug for Value { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str(&llvm::build_string(|s| unsafe { - llvm::LLVMRustWriteValueToString(self.0, s); + llvm::LLVMRustWriteValueToString(self, s); }).expect("nun-UTF8 value description from LLVM")) } } diff --git a/src/librustc_llvm/Cargo.toml b/src/librustc_llvm/Cargo.toml index 0978c2ceb141d..013badb71cc5a 100644 --- a/src/librustc_llvm/Cargo.toml +++ b/src/librustc_llvm/Cargo.toml @@ -12,11 +12,6 @@ path = "lib.rs" static-libstdcpp = [] emscripten = [] -[dependencies] -bitflags = "1.0" -libc = "0.2" -rustc_cratesio_shim = { path = "../librustc_cratesio_shim" } - [build-dependencies] build_helper = { path = "../build_helper" } cc = "1.0.1" diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 1619637b827df..5910e55def396 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -271,5 +271,6 @@ fn main() { if target.contains("windows-gnu") { println!("cargo:rustc-link-lib=static-nobundle=gcc_s"); println!("cargo:rustc-link-lib=static-nobundle=pthread"); + println!("cargo:rustc-link-lib=dylib=uuid"); } } diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs deleted file mode 100644 index 8d04438eea290..0000000000000 --- a/src/librustc_llvm/ffi.rs +++ /dev/null @@ -1,1800 +0,0 @@ -// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// FIXME: Rename 'DIGlobalVariable' to 'DIGlobalVariableExpression' -// once support for LLVM 3.9 is dropped. -// -// This method was changed in this LLVM patch: -// https://reviews.llvm.org/D26769 - -use debuginfo::{DIBuilderRef, DIDescriptor, DIFile, DILexicalBlock, DISubprogram, DIType, - DIBasicType, DIDerivedType, DICompositeType, DIScope, DIVariable, - DIGlobalVariable, DIArray, DISubrange, DITemplateTypeParameter, DIEnumerator, - DINameSpace, DIFlags}; - -use libc::{c_uint, c_int, size_t, c_char}; -use libc::{c_longlong, c_ulonglong, c_void}; - -use RustStringRef; - -pub type Opcode = u32; -pub type Bool = c_uint; - -pub const True: Bool = 1 as Bool; -pub const False: Bool = 0 as Bool; - -#[derive(Copy, Clone, PartialEq)] -#[repr(C)] -pub enum LLVMRustResult { - Success, - Failure, -} -// Consts for the LLVM CallConv type, pre-cast to usize. - -/// LLVM CallingConv::ID. Should we wrap this? -#[derive(Copy, Clone, PartialEq, Debug)] -#[repr(C)] -pub enum CallConv { - CCallConv = 0, - FastCallConv = 8, - ColdCallConv = 9, - X86StdcallCallConv = 64, - X86FastcallCallConv = 65, - ArmAapcsCallConv = 67, - Msp430Intr = 69, - X86_ThisCall = 70, - PtxKernel = 71, - X86_64_SysV = 78, - X86_64_Win64 = 79, - X86_VectorCall = 80, - X86_Intr = 83, - AmdGpuKernel = 91, -} - -/// LLVMRustLinkage -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -#[repr(C)] -pub enum Linkage { - ExternalLinkage = 0, - AvailableExternallyLinkage = 1, - LinkOnceAnyLinkage = 2, - LinkOnceODRLinkage = 3, - WeakAnyLinkage = 4, - WeakODRLinkage = 5, - AppendingLinkage = 6, - InternalLinkage = 7, - PrivateLinkage = 8, - ExternalWeakLinkage = 9, - CommonLinkage = 10, -} - -// LLVMRustVisibility -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -#[repr(C)] -pub enum Visibility { - Default = 0, - Hidden = 1, - Protected = 2, -} - -/// LLVMDiagnosticSeverity -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub enum DiagnosticSeverity { - Error = 0, - Warning = 1, - Remark = 2, - Note = 3, -} - -/// LLVMDLLStorageClass -#[derive(Copy, Clone)] -#[repr(C)] -pub enum DLLStorageClass { - Default = 0, - DllImport = 1, // Function to be imported from DLL. - DllExport = 2, // Function to be accessible from DLL. -} - -/// Matches LLVMRustAttribute in rustllvm.h -/// Semantically a subset of the C++ enum llvm::Attribute::AttrKind, -/// though it is not ABI compatible (since it's a C++ enum) -#[repr(C)] -#[derive(Copy, Clone, Debug)] -pub enum Attribute { - AlwaysInline = 0, - ByVal = 1, - Cold = 2, - InlineHint = 3, - MinSize = 4, - Naked = 5, - NoAlias = 6, - NoCapture = 7, - NoInline = 8, - NonNull = 9, - NoRedZone = 10, - NoReturn = 11, - NoUnwind = 12, - OptimizeForSize = 13, - ReadOnly = 14, - SExt = 15, - StructRet = 16, - UWTable = 17, - ZExt = 18, - InReg = 19, - SanitizeThread = 20, - SanitizeAddress = 21, - SanitizeMemory = 22, -} - -/// LLVMIntPredicate -#[derive(Copy, Clone)] -#[repr(C)] -pub enum IntPredicate { - IntEQ = 32, - IntNE = 33, - IntUGT = 34, - IntUGE = 35, - IntULT = 36, - IntULE = 37, - IntSGT = 38, - IntSGE = 39, - IntSLT = 40, - IntSLE = 41, -} - -/// LLVMRealPredicate -#[derive(Copy, Clone)] -#[repr(C)] -pub enum RealPredicate { - RealPredicateFalse = 0, - RealOEQ = 1, - RealOGT = 2, - RealOGE = 3, - RealOLT = 4, - RealOLE = 5, - RealONE = 6, - RealORD = 7, - RealUNO = 8, - RealUEQ = 9, - RealUGT = 10, - RealUGE = 11, - RealULT = 12, - RealULE = 13, - RealUNE = 14, - RealPredicateTrue = 15, -} - -/// LLVMTypeKind -#[derive(Copy, Clone, PartialEq, Debug)] -#[repr(C)] -pub enum TypeKind { - Void = 0, - Half = 1, - Float = 2, - Double = 3, - X86_FP80 = 4, - FP128 = 5, - PPC_FP128 = 6, - Label = 7, - Integer = 8, - Function = 9, - Struct = 10, - Array = 11, - Pointer = 12, - Vector = 13, - Metadata = 14, - X86_MMX = 15, - Token = 16, -} - -/// LLVMAtomicRmwBinOp -#[derive(Copy, Clone)] -#[repr(C)] -pub enum AtomicRmwBinOp { - AtomicXchg = 0, - AtomicAdd = 1, - AtomicSub = 2, - AtomicAnd = 3, - AtomicNand = 4, - AtomicOr = 5, - AtomicXor = 6, - AtomicMax = 7, - AtomicMin = 8, - AtomicUMax = 9, - AtomicUMin = 10, -} - -/// LLVMAtomicOrdering -#[derive(Copy, Clone)] -#[repr(C)] -pub enum AtomicOrdering { - NotAtomic = 0, - Unordered = 1, - Monotonic = 2, - // Consume = 3, // Not specified yet. - Acquire = 4, - Release = 5, - AcquireRelease = 6, - SequentiallyConsistent = 7, -} - -/// LLVMRustSynchronizationScope -#[derive(Copy, Clone)] -#[repr(C)] -pub enum SynchronizationScope { - Other, - SingleThread, - CrossThread, -} - -/// LLVMRustFileType -#[derive(Copy, Clone)] -#[repr(C)] -pub enum FileType { - Other, - AssemblyFile, - ObjectFile, -} - -/// LLVMMetadataType -#[derive(Copy, Clone)] -#[repr(C)] -pub enum MetadataType { - MD_dbg = 0, - MD_tbaa = 1, - MD_prof = 2, - MD_fpmath = 3, - MD_range = 4, - MD_tbaa_struct = 5, - MD_invariant_load = 6, - MD_alias_scope = 7, - MD_noalias = 8, - MD_nontemporal = 9, - MD_mem_parallel_loop_access = 10, - MD_nonnull = 11, -} - -/// LLVMRustAsmDialect -#[derive(Copy, Clone)] -#[repr(C)] -pub enum AsmDialect { - Other, - Att, - Intel, -} - -/// LLVMRustCodeGenOptLevel -#[derive(Copy, Clone, PartialEq)] -#[repr(C)] -pub enum CodeGenOptLevel { - Other, - None, - Less, - Default, - Aggressive, -} - -/// LLVMRelocMode -#[derive(Copy, Clone, PartialEq)] -#[repr(C)] -pub enum RelocMode { - Default, - Static, - PIC, - DynamicNoPic, - ROPI, - RWPI, - ROPI_RWPI, -} - -/// LLVMRustCodeModel -#[derive(Copy, Clone)] -#[repr(C)] -pub enum CodeModel { - Other, - Small, - Kernel, - Medium, - Large, - None, -} - -/// LLVMRustDiagnosticKind -#[derive(Copy, Clone)] -#[repr(C)] -pub enum DiagnosticKind { - Other, - InlineAsm, - StackSize, - DebugMetadataVersion, - SampleProfile, - OptimizationRemark, - OptimizationRemarkMissed, - OptimizationRemarkAnalysis, - OptimizationRemarkAnalysisFPCommute, - OptimizationRemarkAnalysisAliasing, - OptimizationRemarkOther, - OptimizationFailure, - PGOProfile, -} - -/// LLVMRustArchiveKind -#[derive(Copy, Clone)] -#[repr(C)] -pub enum ArchiveKind { - Other, - K_GNU, - K_BSD, - K_COFF, -} - -/// LLVMRustPassKind -#[derive(Copy, Clone, PartialEq, Debug)] -#[repr(C)] -pub enum PassKind { - Other, - Function, - Module, -} - -/// LLVMRustThinLTOData -pub enum ThinLTOData {} - -/// LLVMRustThinLTOBuffer -pub enum ThinLTOBuffer {} - -/// LLVMRustThinLTOModule -#[repr(C)] -pub struct ThinLTOModule { - pub identifier: *const c_char, - pub data: *const u8, - pub len: usize, -} - -/// LLVMThreadLocalMode -#[derive(Copy, Clone)] -#[repr(C)] -pub enum ThreadLocalMode { - NotThreadLocal, - GeneralDynamic, - LocalDynamic, - InitialExec, - LocalExec -} - -// Opaque pointer types -#[allow(missing_copy_implementations)] -pub enum Module_opaque {} -pub type ModuleRef = *mut Module_opaque; -#[allow(missing_copy_implementations)] -pub enum Context_opaque {} -pub type ContextRef = *mut Context_opaque; -#[allow(missing_copy_implementations)] -pub enum Type_opaque {} -pub type TypeRef = *mut Type_opaque; -#[allow(missing_copy_implementations)] -pub enum Value_opaque {} -pub type ValueRef = *mut Value_opaque; -#[allow(missing_copy_implementations)] -pub enum Metadata_opaque {} -pub type MetadataRef = *mut Metadata_opaque; -#[allow(missing_copy_implementations)] -pub enum BasicBlock_opaque {} -pub type BasicBlockRef = *mut BasicBlock_opaque; -#[allow(missing_copy_implementations)] -pub enum Builder_opaque {} -pub type BuilderRef = *mut Builder_opaque; -#[allow(missing_copy_implementations)] -pub enum ExecutionEngine_opaque {} -pub type ExecutionEngineRef = *mut ExecutionEngine_opaque; -#[allow(missing_copy_implementations)] -pub enum MemoryBuffer_opaque {} -pub type MemoryBufferRef = *mut MemoryBuffer_opaque; -#[allow(missing_copy_implementations)] -pub enum PassManager_opaque {} -pub type PassManagerRef = *mut PassManager_opaque; -#[allow(missing_copy_implementations)] -pub enum PassManagerBuilder_opaque {} -pub type PassManagerBuilderRef = *mut PassManagerBuilder_opaque; -#[allow(missing_copy_implementations)] -pub enum Use_opaque {} -pub type UseRef = *mut Use_opaque; -#[allow(missing_copy_implementations)] -pub enum TargetData_opaque {} -pub type TargetDataRef = *mut TargetData_opaque; -#[allow(missing_copy_implementations)] -pub enum ObjectFile_opaque {} -pub type ObjectFileRef = *mut ObjectFile_opaque; -#[allow(missing_copy_implementations)] -pub enum SectionIterator_opaque {} -pub type SectionIteratorRef = *mut SectionIterator_opaque; -#[allow(missing_copy_implementations)] -pub enum Pass_opaque {} -pub type PassRef = *mut Pass_opaque; -#[allow(missing_copy_implementations)] -pub enum TargetMachine_opaque {} -pub type TargetMachineRef = *mut TargetMachine_opaque; -pub enum Archive_opaque {} -pub type ArchiveRef = *mut Archive_opaque; -pub enum ArchiveIterator_opaque {} -pub type ArchiveIteratorRef = *mut ArchiveIterator_opaque; -pub enum ArchiveChild_opaque {} -pub type ArchiveChildRef = *mut ArchiveChild_opaque; -#[allow(missing_copy_implementations)] -pub enum Twine_opaque {} -pub type TwineRef = *mut Twine_opaque; -#[allow(missing_copy_implementations)] -pub enum DiagnosticInfo_opaque {} -pub type DiagnosticInfoRef = *mut DiagnosticInfo_opaque; -#[allow(missing_copy_implementations)] -pub enum DebugLoc_opaque {} -pub type DebugLocRef = *mut DebugLoc_opaque; -#[allow(missing_copy_implementations)] -pub enum SMDiagnostic_opaque {} -pub type SMDiagnosticRef = *mut SMDiagnostic_opaque; -#[allow(missing_copy_implementations)] -pub enum RustArchiveMember_opaque {} -pub type RustArchiveMemberRef = *mut RustArchiveMember_opaque; -#[allow(missing_copy_implementations)] -pub enum OperandBundleDef_opaque {} -pub type OperandBundleDefRef = *mut OperandBundleDef_opaque; -#[allow(missing_copy_implementations)] -pub enum Linker_opaque {} -pub type LinkerRef = *mut Linker_opaque; - -pub type DiagnosticHandler = unsafe extern "C" fn(DiagnosticInfoRef, *mut c_void); -pub type InlineAsmDiagHandler = unsafe extern "C" fn(SMDiagnosticRef, *const c_void, c_uint); - - -pub mod debuginfo { - use super::MetadataRef; - - #[allow(missing_copy_implementations)] - pub enum DIBuilder_opaque {} - pub type DIBuilderRef = *mut DIBuilder_opaque; - - pub type DIDescriptor = MetadataRef; - pub type DIScope = DIDescriptor; - pub type DILocation = DIDescriptor; - pub type DIFile = DIScope; - pub type DILexicalBlock = DIScope; - pub type DISubprogram = DIScope; - pub type DINameSpace = DIScope; - pub type DIType = DIDescriptor; - pub type DIBasicType = DIType; - pub type DIDerivedType = DIType; - pub type DICompositeType = DIDerivedType; - pub type DIVariable = DIDescriptor; - pub type DIGlobalVariable = DIDescriptor; - pub type DIArray = DIDescriptor; - pub type DISubrange = DIDescriptor; - pub type DIEnumerator = DIDescriptor; - pub type DITemplateTypeParameter = DIDescriptor; - - // These values **must** match with LLVMRustDIFlags!! - bitflags! { - #[repr(C)] - #[derive(Default)] - pub struct DIFlags: ::libc::uint32_t { - const FlagZero = 0; - const FlagPrivate = 1; - const FlagProtected = 2; - const FlagPublic = 3; - const FlagFwdDecl = (1 << 2); - const FlagAppleBlock = (1 << 3); - const FlagBlockByrefStruct = (1 << 4); - const FlagVirtual = (1 << 5); - const FlagArtificial = (1 << 6); - const FlagExplicit = (1 << 7); - const FlagPrototyped = (1 << 8); - const FlagObjcClassComplete = (1 << 9); - const FlagObjectPointer = (1 << 10); - const FlagVector = (1 << 11); - const FlagStaticMember = (1 << 12); - const FlagLValueReference = (1 << 13); - const FlagRValueReference = (1 << 14); - const FlagExternalTypeRef = (1 << 15); - const FlagIntroducedVirtual = (1 << 18); - const FlagBitField = (1 << 19); - const FlagNoReturn = (1 << 20); - const FlagMainSubprogram = (1 << 21); - } - } -} - -pub enum ModuleBuffer {} - -// This annotation is primarily needed for MSVC where attributes like -// dllimport/dllexport are applied and need to be correct for everything to -// link successfully. The #[link] annotation here says "these symbols are -// included statically" which means that they're all exported with dllexport -// and from the rustc_llvm dynamic library. Otherwise the rustc_codegen_llvm dynamic -// library would not be able to access these symbols. -#[link(name = "rustllvm", kind = "static")] -extern "C" { - // Create and destroy contexts. - pub fn LLVMRustContextCreate(shouldDiscardNames: bool) -> ContextRef; - pub fn LLVMContextDispose(C: ContextRef); - pub fn LLVMGetMDKindIDInContext(C: ContextRef, Name: *const c_char, SLen: c_uint) -> c_uint; - - // Create and destroy modules. - pub fn LLVMModuleCreateWithNameInContext(ModuleID: *const c_char, C: ContextRef) -> ModuleRef; - pub fn LLVMGetModuleContext(M: ModuleRef) -> ContextRef; - pub fn LLVMCloneModule(M: ModuleRef) -> ModuleRef; - pub fn LLVMDisposeModule(M: ModuleRef); - - /// Data layout. See Module::getDataLayout. - pub fn LLVMGetDataLayout(M: ModuleRef) -> *const c_char; - pub fn LLVMSetDataLayout(M: ModuleRef, Triple: *const c_char); - - /// See Module::dump. - pub fn LLVMDumpModule(M: ModuleRef); - - /// See Module::setModuleInlineAsm. - pub fn LLVMSetModuleInlineAsm(M: ModuleRef, Asm: *const c_char); - pub fn LLVMRustAppendModuleInlineAsm(M: ModuleRef, Asm: *const c_char); - - /// See llvm::LLVMTypeKind::getTypeID. - pub fn LLVMRustGetTypeKind(Ty: TypeRef) -> TypeKind; - - // Operations on integer types - pub fn LLVMInt1TypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMInt8TypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMInt16TypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMInt32TypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMInt64TypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMIntTypeInContext(C: ContextRef, NumBits: c_uint) -> TypeRef; - - pub fn LLVMGetIntTypeWidth(IntegerTy: TypeRef) -> c_uint; - - // Operations on real types - pub fn LLVMFloatTypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMDoubleTypeInContext(C: ContextRef) -> TypeRef; - - // Operations on function types - pub fn LLVMFunctionType(ReturnType: TypeRef, - ParamTypes: *const TypeRef, - ParamCount: c_uint, - IsVarArg: Bool) - -> TypeRef; - pub fn LLVMGetReturnType(FunctionTy: TypeRef) -> TypeRef; - pub fn LLVMCountParamTypes(FunctionTy: TypeRef) -> c_uint; - pub fn LLVMGetParamTypes(FunctionTy: TypeRef, Dest: *mut TypeRef); - - // Operations on struct types - pub fn LLVMStructTypeInContext(C: ContextRef, - ElementTypes: *const TypeRef, - ElementCount: c_uint, - Packed: Bool) - -> TypeRef; - pub fn LLVMIsPackedStruct(StructTy: TypeRef) -> Bool; - - // Operations on array, pointer, and vector types (sequence types) - pub fn LLVMRustArrayType(ElementType: TypeRef, ElementCount: u64) -> TypeRef; - pub fn LLVMPointerType(ElementType: TypeRef, AddressSpace: c_uint) -> TypeRef; - pub fn LLVMVectorType(ElementType: TypeRef, ElementCount: c_uint) -> TypeRef; - - pub fn LLVMGetElementType(Ty: TypeRef) -> TypeRef; - pub fn LLVMGetVectorSize(VectorTy: TypeRef) -> c_uint; - - // Operations on other types - pub fn LLVMVoidTypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMX86MMXTypeInContext(C: ContextRef) -> TypeRef; - pub fn LLVMRustMetadataTypeInContext(C: ContextRef) -> TypeRef; - - // Operations on all values - pub fn LLVMTypeOf(Val: ValueRef) -> TypeRef; - pub fn LLVMGetValueName(Val: ValueRef) -> *const c_char; - pub fn LLVMSetValueName(Val: ValueRef, Name: *const c_char); - pub fn LLVMReplaceAllUsesWith(OldVal: ValueRef, NewVal: ValueRef); - pub fn LLVMSetMetadata(Val: ValueRef, KindID: c_uint, Node: ValueRef); - - // Operations on Uses - pub fn LLVMGetFirstUse(Val: ValueRef) -> UseRef; - pub fn LLVMGetNextUse(U: UseRef) -> UseRef; - pub fn LLVMGetUser(U: UseRef) -> ValueRef; - - // Operations on Users - pub fn LLVMGetOperand(Val: ValueRef, Index: c_uint) -> ValueRef; - - // Operations on constants of any type - pub fn LLVMConstNull(Ty: TypeRef) -> ValueRef; - pub fn LLVMConstICmp(Pred: IntPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef; - pub fn LLVMConstFCmp(Pred: RealPredicate, V1: ValueRef, V2: ValueRef) -> ValueRef; - pub fn LLVMGetUndef(Ty: TypeRef) -> ValueRef; - - // Operations on metadata - pub fn LLVMMDStringInContext(C: ContextRef, Str: *const c_char, SLen: c_uint) -> ValueRef; - pub fn LLVMMDNodeInContext(C: ContextRef, Vals: *const ValueRef, Count: c_uint) -> ValueRef; - pub fn LLVMAddNamedMetadataOperand(M: ModuleRef, Name: *const c_char, Val: ValueRef); - - // Operations on scalar constants - pub fn LLVMConstInt(IntTy: TypeRef, N: c_ulonglong, SignExtend: Bool) -> ValueRef; - pub fn LLVMConstIntOfArbitraryPrecision(IntTy: TypeRef, Wn: c_uint, Ws: *const u64) -> ValueRef; - pub fn LLVMConstIntGetZExtValue(ConstantVal: ValueRef) -> c_ulonglong; - pub fn LLVMConstIntGetSExtValue(ConstantVal: ValueRef) -> c_longlong; - pub fn LLVMRustConstInt128Get(ConstantVal: ValueRef, SExt: bool, - high: *mut u64, low: *mut u64) -> bool; - pub fn LLVMConstRealGetDouble (ConstantVal: ValueRef, losesInfo: *mut Bool) -> f64; - - - // Operations on composite constants - pub fn LLVMConstStringInContext(C: ContextRef, - Str: *const c_char, - Length: c_uint, - DontNullTerminate: Bool) - -> ValueRef; - pub fn LLVMConstStructInContext(C: ContextRef, - ConstantVals: *const ValueRef, - Count: c_uint, - Packed: Bool) - -> ValueRef; - - pub fn LLVMConstArray(ElementTy: TypeRef, - ConstantVals: *const ValueRef, - Length: c_uint) - -> ValueRef; - pub fn LLVMConstVector(ScalarConstantVals: *const ValueRef, Size: c_uint) -> ValueRef; - - // Constant expressions - pub fn LLVMSizeOf(Ty: TypeRef) -> ValueRef; - pub fn LLVMConstNeg(ConstantVal: ValueRef) -> ValueRef; - pub fn LLVMConstFNeg(ConstantVal: ValueRef) -> ValueRef; - pub fn LLVMConstNot(ConstantVal: ValueRef) -> ValueRef; - pub fn LLVMConstAdd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstFAdd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstSub(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstFSub(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstMul(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstFMul(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstUDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstSDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstFDiv(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstURem(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstSRem(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstFRem(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstAnd(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstOr(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstXor(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstShl(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstLShr(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstAShr(LHSConstant: ValueRef, RHSConstant: ValueRef) -> ValueRef; - pub fn LLVMConstGEP( - ConstantVal: ValueRef, - ConstantIndices: *const ValueRef, - NumIndices: c_uint, - ) -> ValueRef; - pub fn LLVMConstInBoundsGEP( - ConstantVal: ValueRef, - ConstantIndices: *const ValueRef, - NumIndices: c_uint, - ) -> ValueRef; - pub fn LLVMConstTrunc(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstZExt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstUIToFP(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstSIToFP(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstFPToUI(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstFPToSI(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstPtrToInt(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstIntToPtr(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstBitCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstPointerCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstIntCast(ConstantVal: ValueRef, ToType: TypeRef, isSigned: Bool) -> ValueRef; - pub fn LLVMConstFPCast(ConstantVal: ValueRef, ToType: TypeRef) -> ValueRef; - pub fn LLVMConstExtractValue(AggConstant: ValueRef, - IdxList: *const c_uint, - NumIdx: c_uint) - -> ValueRef; - pub fn LLVMConstInlineAsm(Ty: TypeRef, - AsmString: *const c_char, - Constraints: *const c_char, - HasSideEffects: Bool, - IsAlignStack: Bool) - -> ValueRef; - - - // Operations on global variables, functions, and aliases (globals) - pub fn LLVMGetGlobalParent(Global: ValueRef) -> ModuleRef; - pub fn LLVMIsDeclaration(Global: ValueRef) -> Bool; - pub fn LLVMRustGetLinkage(Global: ValueRef) -> Linkage; - pub fn LLVMRustSetLinkage(Global: ValueRef, RustLinkage: Linkage); - pub fn LLVMGetSection(Global: ValueRef) -> *const c_char; - pub fn LLVMSetSection(Global: ValueRef, Section: *const c_char); - pub fn LLVMRustGetVisibility(Global: ValueRef) -> Visibility; - pub fn LLVMRustSetVisibility(Global: ValueRef, Viz: Visibility); - pub fn LLVMGetAlignment(Global: ValueRef) -> c_uint; - pub fn LLVMSetAlignment(Global: ValueRef, Bytes: c_uint); - pub fn LLVMSetDLLStorageClass(V: ValueRef, C: DLLStorageClass); - - - // Operations on global variables - pub fn LLVMIsAGlobalVariable(GlobalVar: ValueRef) -> ValueRef; - pub fn LLVMAddGlobal(M: ModuleRef, Ty: TypeRef, Name: *const c_char) -> ValueRef; - pub fn LLVMGetNamedGlobal(M: ModuleRef, Name: *const c_char) -> ValueRef; - pub fn LLVMRustGetOrInsertGlobal(M: ModuleRef, Name: *const c_char, T: TypeRef) -> ValueRef; - pub fn LLVMGetFirstGlobal(M: ModuleRef) -> ValueRef; - pub fn LLVMGetNextGlobal(GlobalVar: ValueRef) -> ValueRef; - pub fn LLVMDeleteGlobal(GlobalVar: ValueRef); - pub fn LLVMGetInitializer(GlobalVar: ValueRef) -> ValueRef; - pub fn LLVMSetInitializer(GlobalVar: ValueRef, ConstantVal: ValueRef); - pub fn LLVMSetThreadLocal(GlobalVar: ValueRef, IsThreadLocal: Bool); - pub fn LLVMSetThreadLocalMode(GlobalVar: ValueRef, Mode: ThreadLocalMode); - pub fn LLVMIsGlobalConstant(GlobalVar: ValueRef) -> Bool; - pub fn LLVMSetGlobalConstant(GlobalVar: ValueRef, IsConstant: Bool); - pub fn LLVMRustGetNamedValue(M: ModuleRef, Name: *const c_char) -> ValueRef; - pub fn LLVMSetTailCall(CallInst: ValueRef, IsTailCall: Bool); - - // Operations on functions - pub fn LLVMAddFunction(M: ModuleRef, Name: *const c_char, FunctionTy: TypeRef) -> ValueRef; - pub fn LLVMGetNamedFunction(M: ModuleRef, Name: *const c_char) -> ValueRef; - pub fn LLVMGetFirstFunction(M: ModuleRef) -> ValueRef; - pub fn LLVMGetNextFunction(Fn: ValueRef) -> ValueRef; - pub fn LLVMRustGetOrInsertFunction(M: ModuleRef, - Name: *const c_char, - FunctionTy: TypeRef) - -> ValueRef; - pub fn LLVMSetFunctionCallConv(Fn: ValueRef, CC: c_uint); - pub fn LLVMRustAddAlignmentAttr(Fn: ValueRef, index: c_uint, bytes: u32); - pub fn LLVMRustAddDereferenceableAttr(Fn: ValueRef, index: c_uint, bytes: u64); - pub fn LLVMRustAddDereferenceableOrNullAttr(Fn: ValueRef, index: c_uint, bytes: u64); - pub fn LLVMRustAddFunctionAttribute(Fn: ValueRef, index: c_uint, attr: Attribute); - pub fn LLVMRustAddFunctionAttrStringValue(Fn: ValueRef, - index: c_uint, - Name: *const c_char, - Value: *const c_char); - pub fn LLVMRustRemoveFunctionAttributes(Fn: ValueRef, index: c_uint, attr: Attribute); - - // Operations on parameters - pub fn LLVMCountParams(Fn: ValueRef) -> c_uint; - pub fn LLVMGetParam(Fn: ValueRef, Index: c_uint) -> ValueRef; - - // Operations on basic blocks - pub fn LLVMBasicBlockAsValue(BB: BasicBlockRef) -> ValueRef; - pub fn LLVMGetBasicBlockParent(BB: BasicBlockRef) -> ValueRef; - pub fn LLVMAppendBasicBlockInContext(C: ContextRef, - Fn: ValueRef, - Name: *const c_char) - -> BasicBlockRef; - pub fn LLVMDeleteBasicBlock(BB: BasicBlockRef); - - // Operations on instructions - pub fn LLVMGetInstructionParent(Inst: ValueRef) -> BasicBlockRef; - pub fn LLVMGetFirstBasicBlock(Fn: ValueRef) -> BasicBlockRef; - pub fn LLVMGetFirstInstruction(BB: BasicBlockRef) -> ValueRef; - pub fn LLVMInstructionEraseFromParent(Inst: ValueRef); - - // Operations on call sites - pub fn LLVMSetInstructionCallConv(Instr: ValueRef, CC: c_uint); - pub fn LLVMRustAddCallSiteAttribute(Instr: ValueRef, index: c_uint, attr: Attribute); - pub fn LLVMRustAddAlignmentCallSiteAttr(Instr: ValueRef, index: c_uint, bytes: u32); - pub fn LLVMRustAddDereferenceableCallSiteAttr(Instr: ValueRef, index: c_uint, bytes: u64); - pub fn LLVMRustAddDereferenceableOrNullCallSiteAttr(Instr: ValueRef, - index: c_uint, - bytes: u64); - - // Operations on load/store instructions (only) - pub fn LLVMSetVolatile(MemoryAccessInst: ValueRef, volatile: Bool); - - // Operations on phi nodes - pub fn LLVMAddIncoming(PhiNode: ValueRef, - IncomingValues: *const ValueRef, - IncomingBlocks: *const BasicBlockRef, - Count: c_uint); - - // Instruction builders - pub fn LLVMCreateBuilderInContext(C: ContextRef) -> BuilderRef; - pub fn LLVMPositionBuilder(Builder: BuilderRef, Block: BasicBlockRef, Instr: ValueRef); - pub fn LLVMPositionBuilderBefore(Builder: BuilderRef, Instr: ValueRef); - pub fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef); - pub fn LLVMGetInsertBlock(Builder: BuilderRef) -> BasicBlockRef; - pub fn LLVMDisposeBuilder(Builder: BuilderRef); - - // Metadata - pub fn LLVMSetCurrentDebugLocation(Builder: BuilderRef, L: ValueRef); - pub fn LLVMGetCurrentDebugLocation(Builder: BuilderRef) -> ValueRef; - pub fn LLVMSetInstDebugLocation(Builder: BuilderRef, Inst: ValueRef); - - // Terminators - pub fn LLVMBuildRetVoid(B: BuilderRef) -> ValueRef; - pub fn LLVMBuildRet(B: BuilderRef, V: ValueRef) -> ValueRef; - pub fn LLVMBuildAggregateRet(B: BuilderRef, RetVals: *const ValueRef, N: c_uint) -> ValueRef; - pub fn LLVMBuildBr(B: BuilderRef, Dest: BasicBlockRef) -> ValueRef; - pub fn LLVMBuildCondBr(B: BuilderRef, - If: ValueRef, - Then: BasicBlockRef, - Else: BasicBlockRef) - -> ValueRef; - pub fn LLVMBuildSwitch(B: BuilderRef, - V: ValueRef, - Else: BasicBlockRef, - NumCases: c_uint) - -> ValueRef; - pub fn LLVMBuildIndirectBr(B: BuilderRef, Addr: ValueRef, NumDests: c_uint) -> ValueRef; - pub fn LLVMRustBuildInvoke(B: BuilderRef, - Fn: ValueRef, - Args: *const ValueRef, - NumArgs: c_uint, - Then: BasicBlockRef, - Catch: BasicBlockRef, - Bundle: OperandBundleDefRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildLandingPad(B: BuilderRef, - Ty: TypeRef, - PersFn: ValueRef, - NumClauses: c_uint, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildResume(B: BuilderRef, Exn: ValueRef) -> ValueRef; - pub fn LLVMBuildUnreachable(B: BuilderRef) -> ValueRef; - - pub fn LLVMRustBuildCleanupPad(B: BuilderRef, - ParentPad: ValueRef, - ArgCnt: c_uint, - Args: *const ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMRustBuildCleanupRet(B: BuilderRef, - CleanupPad: ValueRef, - UnwindBB: BasicBlockRef) - -> ValueRef; - pub fn LLVMRustBuildCatchPad(B: BuilderRef, - ParentPad: ValueRef, - ArgCnt: c_uint, - Args: *const ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMRustBuildCatchRet(B: BuilderRef, Pad: ValueRef, BB: BasicBlockRef) -> ValueRef; - pub fn LLVMRustBuildCatchSwitch(Builder: BuilderRef, - ParentPad: ValueRef, - BB: BasicBlockRef, - NumHandlers: c_uint, - Name: *const c_char) - -> ValueRef; - pub fn LLVMRustAddHandler(CatchSwitch: ValueRef, Handler: BasicBlockRef); - pub fn LLVMSetPersonalityFn(Func: ValueRef, Pers: ValueRef); - - // Add a case to the switch instruction - pub fn LLVMAddCase(Switch: ValueRef, OnVal: ValueRef, Dest: BasicBlockRef); - - // Add a clause to the landing pad instruction - pub fn LLVMAddClause(LandingPad: ValueRef, ClauseVal: ValueRef); - - // Set the cleanup on a landing pad instruction - pub fn LLVMSetCleanup(LandingPad: ValueRef, Val: Bool); - - // Arithmetic - pub fn LLVMBuildAdd(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildNSWAdd(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildNUWAdd(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildFAdd(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildSub(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildNSWSub(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildNUWSub(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildFSub(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildMul(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildNSWMul(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildNUWMul(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildFMul(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildUDiv(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildExactUDiv(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildSDiv(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildExactSDiv(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildFDiv(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildURem(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildSRem(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildFRem(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildShl(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildLShr(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildAShr(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildAnd(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildOr(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildXor(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildBinOp(B: BuilderRef, - Op: Opcode, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildNeg(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef; - pub fn LLVMBuildNSWNeg(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef; - pub fn LLVMBuildNUWNeg(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef; - pub fn LLVMBuildFNeg(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef; - pub fn LLVMBuildNot(B: BuilderRef, V: ValueRef, Name: *const c_char) -> ValueRef; - pub fn LLVMRustSetHasUnsafeAlgebra(Instr: ValueRef); - - // Memory - pub fn LLVMBuildAlloca(B: BuilderRef, Ty: TypeRef, Name: *const c_char) -> ValueRef; - pub fn LLVMBuildFree(B: BuilderRef, PointerVal: ValueRef) -> ValueRef; - pub fn LLVMBuildLoad(B: BuilderRef, PointerVal: ValueRef, Name: *const c_char) -> ValueRef; - - pub fn LLVMBuildStore(B: BuilderRef, Val: ValueRef, Ptr: ValueRef) -> ValueRef; - - pub fn LLVMBuildGEP(B: BuilderRef, - Pointer: ValueRef, - Indices: *const ValueRef, - NumIndices: c_uint, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildInBoundsGEP(B: BuilderRef, - Pointer: ValueRef, - Indices: *const ValueRef, - NumIndices: c_uint, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildStructGEP(B: BuilderRef, - Pointer: ValueRef, - Idx: c_uint, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildGlobalString(B: BuilderRef, - Str: *const c_char, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildGlobalStringPtr(B: BuilderRef, - Str: *const c_char, - Name: *const c_char) - -> ValueRef; - - // Casts - pub fn LLVMBuildTrunc(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildZExt(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildSExt(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildFPToUI(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildFPToSI(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildUIToFP(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildSIToFP(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildFPTrunc(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildFPExt(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildPtrToInt(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildIntToPtr(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildBitCast(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildZExtOrBitCast(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildSExtOrBitCast(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildTruncOrBitCast(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildCast(B: BuilderRef, - Op: Opcode, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildPointerCast(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMRustBuildIntCast(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - IsSized: bool) - -> ValueRef; - pub fn LLVMBuildFPCast(B: BuilderRef, - Val: ValueRef, - DestTy: TypeRef, - Name: *const c_char) - -> ValueRef; - - // Comparisons - pub fn LLVMBuildICmp(B: BuilderRef, - Op: c_uint, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildFCmp(B: BuilderRef, - Op: c_uint, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - - // Miscellaneous instructions - pub fn LLVMBuildPhi(B: BuilderRef, Ty: TypeRef, Name: *const c_char) -> ValueRef; - pub fn LLVMRustBuildCall(B: BuilderRef, - Fn: ValueRef, - Args: *const ValueRef, - NumArgs: c_uint, - Bundle: OperandBundleDefRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildSelect(B: BuilderRef, - If: ValueRef, - Then: ValueRef, - Else: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildVAArg(B: BuilderRef, - list: ValueRef, - Ty: TypeRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildExtractElement(B: BuilderRef, - VecVal: ValueRef, - Index: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildInsertElement(B: BuilderRef, - VecVal: ValueRef, - EltVal: ValueRef, - Index: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildShuffleVector(B: BuilderRef, - V1: ValueRef, - V2: ValueRef, - Mask: ValueRef, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildExtractValue(B: BuilderRef, - AggVal: ValueRef, - Index: c_uint, - Name: *const c_char) - -> ValueRef; - pub fn LLVMBuildInsertValue(B: BuilderRef, - AggVal: ValueRef, - EltVal: ValueRef, - Index: c_uint, - Name: *const c_char) - -> ValueRef; - - pub fn LLVMRustBuildVectorReduceFAdd(B: BuilderRef, - Acc: ValueRef, - Src: ValueRef) - -> ValueRef; - pub fn LLVMRustBuildVectorReduceFMul(B: BuilderRef, - Acc: ValueRef, - Src: ValueRef) - -> ValueRef; - pub fn LLVMRustBuildVectorReduceAdd(B: BuilderRef, - Src: ValueRef) - -> ValueRef; - pub fn LLVMRustBuildVectorReduceMul(B: BuilderRef, - Src: ValueRef) - -> ValueRef; - pub fn LLVMRustBuildVectorReduceAnd(B: BuilderRef, - Src: ValueRef) - -> ValueRef; - pub fn LLVMRustBuildVectorReduceOr(B: BuilderRef, - Src: ValueRef) - -> ValueRef; - pub fn LLVMRustBuildVectorReduceXor(B: BuilderRef, - Src: ValueRef) - -> ValueRef; - pub fn LLVMRustBuildVectorReduceMin(B: BuilderRef, - Src: ValueRef, - IsSigned: bool) - -> ValueRef; - pub fn LLVMRustBuildVectorReduceMax(B: BuilderRef, - Src: ValueRef, - IsSigned: bool) - -> ValueRef; - pub fn LLVMRustBuildVectorReduceFMin(B: BuilderRef, - Src: ValueRef, - IsNaN: bool) - -> ValueRef; - pub fn LLVMRustBuildVectorReduceFMax(B: BuilderRef, - Src: ValueRef, - IsNaN: bool) - -> ValueRef; - - pub fn LLVMRustBuildMinNum(B: BuilderRef, LHS: ValueRef, LHS: ValueRef) -> ValueRef; - pub fn LLVMRustBuildMaxNum(B: BuilderRef, LHS: ValueRef, LHS: ValueRef) -> ValueRef; - - pub fn LLVMBuildIsNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef; - pub fn LLVMBuildIsNotNull(B: BuilderRef, Val: ValueRef, Name: *const c_char) -> ValueRef; - pub fn LLVMBuildPtrDiff(B: BuilderRef, - LHS: ValueRef, - RHS: ValueRef, - Name: *const c_char) - -> ValueRef; - - // Atomic Operations - pub fn LLVMRustBuildAtomicLoad(B: BuilderRef, - PointerVal: ValueRef, - Name: *const c_char, - Order: AtomicOrdering) - -> ValueRef; - - pub fn LLVMRustBuildAtomicStore(B: BuilderRef, - Val: ValueRef, - Ptr: ValueRef, - Order: AtomicOrdering) - -> ValueRef; - - pub fn LLVMRustBuildAtomicCmpXchg(B: BuilderRef, - LHS: ValueRef, - CMP: ValueRef, - RHS: ValueRef, - Order: AtomicOrdering, - FailureOrder: AtomicOrdering, - Weak: Bool) - -> ValueRef; - - pub fn LLVMBuildAtomicRMW(B: BuilderRef, - Op: AtomicRmwBinOp, - LHS: ValueRef, - RHS: ValueRef, - Order: AtomicOrdering, - SingleThreaded: Bool) - -> ValueRef; - - pub fn LLVMRustBuildAtomicFence(B: BuilderRef, - Order: AtomicOrdering, - Scope: SynchronizationScope); - - - // Selected entries from the downcasts. - pub fn LLVMIsATerminatorInst(Inst: ValueRef) -> ValueRef; - pub fn LLVMIsAStoreInst(Inst: ValueRef) -> ValueRef; - - /// Writes a module to the specified path. Returns 0 on success. - pub fn LLVMWriteBitcodeToFile(M: ModuleRef, Path: *const c_char) -> c_int; - - /// Creates target data from a target layout string. - pub fn LLVMCreateTargetData(StringRep: *const c_char) -> TargetDataRef; - - /// Disposes target data. - pub fn LLVMDisposeTargetData(TD: TargetDataRef); - - /// Creates a pass manager. - pub fn LLVMCreatePassManager() -> PassManagerRef; - - /// Creates a function-by-function pass manager - pub fn LLVMCreateFunctionPassManagerForModule(M: ModuleRef) -> PassManagerRef; - - /// Disposes a pass manager. - pub fn LLVMDisposePassManager(PM: PassManagerRef); - - /// Runs a pass manager on a module. - pub fn LLVMRunPassManager(PM: PassManagerRef, M: ModuleRef) -> Bool; - - pub fn LLVMInitializePasses(); - - pub fn LLVMPassManagerBuilderCreate() -> PassManagerBuilderRef; - pub fn LLVMPassManagerBuilderDispose(PMB: PassManagerBuilderRef); - pub fn LLVMPassManagerBuilderSetSizeLevel(PMB: PassManagerBuilderRef, Value: Bool); - pub fn LLVMPassManagerBuilderSetDisableUnrollLoops(PMB: PassManagerBuilderRef, Value: Bool); - pub fn LLVMPassManagerBuilderUseInlinerWithThreshold(PMB: PassManagerBuilderRef, - threshold: c_uint); - pub fn LLVMPassManagerBuilderPopulateModulePassManager(PMB: PassManagerBuilderRef, - PM: PassManagerRef); - - pub fn LLVMPassManagerBuilderPopulateFunctionPassManager(PMB: PassManagerBuilderRef, - PM: PassManagerRef); - pub fn LLVMPassManagerBuilderPopulateLTOPassManager(PMB: PassManagerBuilderRef, - PM: PassManagerRef, - Internalize: Bool, - RunInliner: Bool); - pub fn LLVMRustPassManagerBuilderPopulateThinLTOPassManager( - PMB: PassManagerBuilderRef, - PM: PassManagerRef) -> bool; - - // Stuff that's in rustllvm/ because it's not upstream yet. - - /// Opens an object file. - pub fn LLVMCreateObjectFile(MemBuf: MemoryBufferRef) -> ObjectFileRef; - /// Closes an object file. - pub fn LLVMDisposeObjectFile(ObjFile: ObjectFileRef); - - /// Enumerates the sections in an object file. - pub fn LLVMGetSections(ObjFile: ObjectFileRef) -> SectionIteratorRef; - /// Destroys a section iterator. - pub fn LLVMDisposeSectionIterator(SI: SectionIteratorRef); - /// Returns true if the section iterator is at the end of the section - /// list: - pub fn LLVMIsSectionIteratorAtEnd(ObjFile: ObjectFileRef, SI: SectionIteratorRef) -> Bool; - /// Moves the section iterator to point to the next section. - pub fn LLVMMoveToNextSection(SI: SectionIteratorRef); - /// Returns the current section size. - pub fn LLVMGetSectionSize(SI: SectionIteratorRef) -> c_ulonglong; - /// Returns the current section contents as a string buffer. - pub fn LLVMGetSectionContents(SI: SectionIteratorRef) -> *const c_char; - - /// Reads the given file and returns it as a memory buffer. Use - /// LLVMDisposeMemoryBuffer() to get rid of it. - pub fn LLVMRustCreateMemoryBufferWithContentsOfFile(Path: *const c_char) -> MemoryBufferRef; - - pub fn LLVMStartMultithreaded() -> Bool; - - /// Returns a string describing the last error caused by an LLVMRust* call. - pub fn LLVMRustGetLastError() -> *const c_char; - - /// Print the pass timings since static dtors aren't picking them up. - pub fn LLVMRustPrintPassTimings(); - - pub fn LLVMStructCreateNamed(C: ContextRef, Name: *const c_char) -> TypeRef; - - pub fn LLVMStructSetBody(StructTy: TypeRef, - ElementTypes: *const TypeRef, - ElementCount: c_uint, - Packed: Bool); - - /// Prepares inline assembly. - pub fn LLVMRustInlineAsm(Ty: TypeRef, - AsmString: *const c_char, - Constraints: *const c_char, - SideEffects: Bool, - AlignStack: Bool, - Dialect: AsmDialect) - -> ValueRef; - - pub fn LLVMRustDebugMetadataVersion() -> u32; - pub fn LLVMRustVersionMajor() -> u32; - pub fn LLVMRustVersionMinor() -> u32; - - pub fn LLVMRustAddModuleFlag(M: ModuleRef, name: *const c_char, value: u32); - - pub fn LLVMRustMetadataAsValue(C: ContextRef, MD: MetadataRef) -> ValueRef; - - pub fn LLVMRustDIBuilderCreate(M: ModuleRef) -> DIBuilderRef; - - pub fn LLVMRustDIBuilderDispose(Builder: DIBuilderRef); - - pub fn LLVMRustDIBuilderFinalize(Builder: DIBuilderRef); - - pub fn LLVMRustDIBuilderCreateCompileUnit(Builder: DIBuilderRef, - Lang: c_uint, - File: DIFile, - Producer: *const c_char, - isOptimized: bool, - Flags: *const c_char, - RuntimeVer: c_uint, - SplitName: *const c_char) - -> DIDescriptor; - - pub fn LLVMRustDIBuilderCreateFile(Builder: DIBuilderRef, - Filename: *const c_char, - Directory: *const c_char) - -> DIFile; - - pub fn LLVMRustDIBuilderCreateSubroutineType(Builder: DIBuilderRef, - File: DIFile, - ParameterTypes: DIArray) - -> DICompositeType; - - pub fn LLVMRustDIBuilderCreateFunction(Builder: DIBuilderRef, - Scope: DIDescriptor, - Name: *const c_char, - LinkageName: *const c_char, - File: DIFile, - LineNo: c_uint, - Ty: DIType, - isLocalToUnit: bool, - isDefinition: bool, - ScopeLine: c_uint, - Flags: DIFlags, - isOptimized: bool, - Fn: ValueRef, - TParam: DIArray, - Decl: DIDescriptor) - -> DISubprogram; - - pub fn LLVMRustDIBuilderCreateBasicType(Builder: DIBuilderRef, - Name: *const c_char, - SizeInBits: u64, - AlignInBits: u32, - Encoding: c_uint) - -> DIBasicType; - - pub fn LLVMRustDIBuilderCreatePointerType(Builder: DIBuilderRef, - PointeeTy: DIType, - SizeInBits: u64, - AlignInBits: u32, - Name: *const c_char) - -> DIDerivedType; - - pub fn LLVMRustDIBuilderCreateStructType(Builder: DIBuilderRef, - Scope: DIDescriptor, - Name: *const c_char, - File: DIFile, - LineNumber: c_uint, - SizeInBits: u64, - AlignInBits: u32, - Flags: DIFlags, - DerivedFrom: DIType, - Elements: DIArray, - RunTimeLang: c_uint, - VTableHolder: DIType, - UniqueId: *const c_char) - -> DICompositeType; - - pub fn LLVMRustDIBuilderCreateMemberType(Builder: DIBuilderRef, - Scope: DIDescriptor, - Name: *const c_char, - File: DIFile, - LineNo: c_uint, - SizeInBits: u64, - AlignInBits: u32, - OffsetInBits: u64, - Flags: DIFlags, - Ty: DIType) - -> DIDerivedType; - - pub fn LLVMRustDIBuilderCreateLexicalBlock(Builder: DIBuilderRef, - Scope: DIScope, - File: DIFile, - Line: c_uint, - Col: c_uint) - -> DILexicalBlock; - - pub fn LLVMRustDIBuilderCreateLexicalBlockFile(Builder: DIBuilderRef, - Scope: DIScope, - File: DIFile) - -> DILexicalBlock; - - pub fn LLVMRustDIBuilderCreateStaticVariable(Builder: DIBuilderRef, - Context: DIScope, - Name: *const c_char, - LinkageName: *const c_char, - File: DIFile, - LineNo: c_uint, - Ty: DIType, - isLocalToUnit: bool, - Val: ValueRef, - Decl: DIDescriptor, - AlignInBits: u32) - -> DIGlobalVariable; - - pub fn LLVMRustDIBuilderCreateVariable(Builder: DIBuilderRef, - Tag: c_uint, - Scope: DIDescriptor, - Name: *const c_char, - File: DIFile, - LineNo: c_uint, - Ty: DIType, - AlwaysPreserve: bool, - Flags: DIFlags, - ArgNo: c_uint, - AlignInBits: u32) - -> DIVariable; - - pub fn LLVMRustDIBuilderCreateArrayType(Builder: DIBuilderRef, - Size: u64, - AlignInBits: u32, - Ty: DIType, - Subscripts: DIArray) - -> DIType; - - pub fn LLVMRustDIBuilderCreateVectorType(Builder: DIBuilderRef, - Size: u64, - AlignInBits: u32, - Ty: DIType, - Subscripts: DIArray) - -> DIType; - - pub fn LLVMRustDIBuilderGetOrCreateSubrange(Builder: DIBuilderRef, - Lo: i64, - Count: i64) - -> DISubrange; - - pub fn LLVMRustDIBuilderGetOrCreateArray(Builder: DIBuilderRef, - Ptr: *const DIDescriptor, - Count: c_uint) - -> DIArray; - - pub fn LLVMRustDIBuilderInsertDeclareAtEnd(Builder: DIBuilderRef, - Val: ValueRef, - VarInfo: DIVariable, - AddrOps: *const i64, - AddrOpsCount: c_uint, - DL: ValueRef, - InsertAtEnd: BasicBlockRef) - -> ValueRef; - - pub fn LLVMRustDIBuilderCreateEnumerator(Builder: DIBuilderRef, - Name: *const c_char, - Val: u64) - -> DIEnumerator; - - pub fn LLVMRustDIBuilderCreateEnumerationType(Builder: DIBuilderRef, - Scope: DIScope, - Name: *const c_char, - File: DIFile, - LineNumber: c_uint, - SizeInBits: u64, - AlignInBits: u32, - Elements: DIArray, - ClassType: DIType) - -> DIType; - - pub fn LLVMRustDIBuilderCreateUnionType(Builder: DIBuilderRef, - Scope: DIScope, - Name: *const c_char, - File: DIFile, - LineNumber: c_uint, - SizeInBits: u64, - AlignInBits: u32, - Flags: DIFlags, - Elements: DIArray, - RunTimeLang: c_uint, - UniqueId: *const c_char) - -> DIType; - - pub fn LLVMSetUnnamedAddr(GlobalVar: ValueRef, UnnamedAddr: Bool); - - pub fn LLVMRustDIBuilderCreateTemplateTypeParameter(Builder: DIBuilderRef, - Scope: DIScope, - Name: *const c_char, - Ty: DIType, - File: DIFile, - LineNo: c_uint, - ColumnNo: c_uint) - -> DITemplateTypeParameter; - - - pub fn LLVMRustDIBuilderCreateNameSpace(Builder: DIBuilderRef, - Scope: DIScope, - Name: *const c_char, - File: DIFile, - LineNo: c_uint) - -> DINameSpace; - pub fn LLVMRustDICompositeTypeSetTypeArray(Builder: DIBuilderRef, - CompositeType: DIType, - TypeArray: DIArray); - - - pub fn LLVMRustDIBuilderCreateDebugLocation(Context: ContextRef, - Line: c_uint, - Column: c_uint, - Scope: DIScope, - InlinedAt: MetadataRef) - -> ValueRef; - pub fn LLVMRustDIBuilderCreateOpDeref() -> i64; - pub fn LLVMRustDIBuilderCreateOpPlusUconst() -> i64; - - pub fn LLVMRustWriteTypeToString(Type: TypeRef, s: RustStringRef); - pub fn LLVMRustWriteValueToString(value_ref: ValueRef, s: RustStringRef); - - pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef; - pub fn LLVMIsAConstantFP(value_ref: ValueRef) -> ValueRef; - - pub fn LLVMRustPassKind(Pass: PassRef) -> PassKind; - pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef; - pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: PassRef); - - pub fn LLVMRustHasFeature(T: TargetMachineRef, s: *const c_char) -> bool; - - pub fn LLVMRustPrintTargetCPUs(T: TargetMachineRef); - pub fn LLVMRustPrintTargetFeatures(T: TargetMachineRef); - - pub fn LLVMRustCreateTargetMachine(Triple: *const c_char, - CPU: *const c_char, - Features: *const c_char, - Model: CodeModel, - Reloc: RelocMode, - Level: CodeGenOptLevel, - UseSoftFP: bool, - PositionIndependentExecutable: bool, - FunctionSections: bool, - DataSections: bool, - TrapUnreachable: bool, - Singlethread: bool) - -> TargetMachineRef; - pub fn LLVMRustDisposeTargetMachine(T: TargetMachineRef); - pub fn LLVMRustAddAnalysisPasses(T: TargetMachineRef, PM: PassManagerRef, M: ModuleRef); - pub fn LLVMRustAddBuilderLibraryInfo(PMB: PassManagerBuilderRef, - M: ModuleRef, - DisableSimplifyLibCalls: bool); - pub fn LLVMRustConfigurePassManagerBuilder(PMB: PassManagerBuilderRef, - OptLevel: CodeGenOptLevel, - MergeFunctions: bool, - SLPVectorize: bool, - LoopVectorize: bool, - PrepareForThinLTO: bool, - PGOGenPath: *const c_char, - PGOUsePath: *const c_char); - pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef, - M: ModuleRef, - DisableSimplifyLibCalls: bool); - pub fn LLVMRustRunFunctionPassManager(PM: PassManagerRef, M: ModuleRef); - pub fn LLVMRustWriteOutputFile(T: TargetMachineRef, - PM: PassManagerRef, - M: ModuleRef, - Output: *const c_char, - FileType: FileType) - -> LLVMRustResult; - pub fn LLVMRustPrintModule(PM: PassManagerRef, - M: ModuleRef, - Output: *const c_char, - Demangle: extern fn(*const c_char, - size_t, - *mut c_char, - size_t) -> size_t); - pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char); - pub fn LLVMRustPrintPasses(); - pub fn LLVMRustSetNormalizedTarget(M: ModuleRef, triple: *const c_char); - pub fn LLVMRustAddAlwaysInlinePass(P: PassManagerBuilderRef, AddLifetimes: bool); - pub fn LLVMRustRunRestrictionPass(M: ModuleRef, syms: *const *const c_char, len: size_t); - pub fn LLVMRustMarkAllFunctionsNounwind(M: ModuleRef); - - pub fn LLVMRustOpenArchive(path: *const c_char) -> ArchiveRef; - pub fn LLVMRustArchiveIteratorNew(AR: ArchiveRef) -> ArchiveIteratorRef; - pub fn LLVMRustArchiveIteratorNext(AIR: ArchiveIteratorRef) -> ArchiveChildRef; - pub fn LLVMRustArchiveChildName(ACR: ArchiveChildRef, size: *mut size_t) -> *const c_char; - pub fn LLVMRustArchiveChildData(ACR: ArchiveChildRef, size: *mut size_t) -> *const c_char; - pub fn LLVMRustArchiveChildFree(ACR: ArchiveChildRef); - pub fn LLVMRustArchiveIteratorFree(AIR: ArchiveIteratorRef); - pub fn LLVMRustDestroyArchive(AR: ArchiveRef); - - pub fn LLVMRustGetSectionName(SI: SectionIteratorRef, data: *mut *const c_char) -> size_t; - - pub fn LLVMRustWriteTwineToString(T: TwineRef, s: RustStringRef); - - pub fn LLVMContextSetDiagnosticHandler(C: ContextRef, - Handler: DiagnosticHandler, - DiagnosticContext: *mut c_void); - - pub fn LLVMRustUnpackOptimizationDiagnostic(DI: DiagnosticInfoRef, - pass_name_out: RustStringRef, - function_out: *mut ValueRef, - loc_line_out: *mut c_uint, - loc_column_out: *mut c_uint, - loc_filename_out: RustStringRef, - message_out: RustStringRef); - pub fn LLVMRustUnpackInlineAsmDiagnostic(DI: DiagnosticInfoRef, - cookie_out: *mut c_uint, - message_out: *mut TwineRef, - instruction_out: *mut ValueRef); - - pub fn LLVMRustWriteDiagnosticInfoToString(DI: DiagnosticInfoRef, s: RustStringRef); - pub fn LLVMRustGetDiagInfoKind(DI: DiagnosticInfoRef) -> DiagnosticKind; - - pub fn LLVMRustSetInlineAsmDiagnosticHandler(C: ContextRef, - H: InlineAsmDiagHandler, - CX: *mut c_void); - - pub fn LLVMRustWriteSMDiagnosticToString(d: SMDiagnosticRef, s: RustStringRef); - - pub fn LLVMRustWriteArchive(Dst: *const c_char, - NumMembers: size_t, - Members: *const RustArchiveMemberRef, - WriteSymbtab: bool, - Kind: ArchiveKind) - -> LLVMRustResult; - pub fn LLVMRustArchiveMemberNew(Filename: *const c_char, - Name: *const c_char, - Child: ArchiveChildRef) - -> RustArchiveMemberRef; - pub fn LLVMRustArchiveMemberFree(Member: RustArchiveMemberRef); - - pub fn LLVMRustSetDataLayoutFromTargetMachine(M: ModuleRef, TM: TargetMachineRef); - - pub fn LLVMRustBuildOperandBundleDef(Name: *const c_char, - Inputs: *const ValueRef, - NumInputs: c_uint) - -> OperandBundleDefRef; - pub fn LLVMRustFreeOperandBundleDef(Bundle: OperandBundleDefRef); - - pub fn LLVMRustPositionBuilderAtStart(B: BuilderRef, BB: BasicBlockRef); - - pub fn LLVMRustSetComdat(M: ModuleRef, V: ValueRef, Name: *const c_char); - pub fn LLVMRustUnsetComdat(V: ValueRef); - pub fn LLVMRustSetModulePIELevel(M: ModuleRef); - pub fn LLVMRustModuleBufferCreate(M: ModuleRef) -> *mut ModuleBuffer; - pub fn LLVMRustModuleBufferPtr(p: *const ModuleBuffer) -> *const u8; - pub fn LLVMRustModuleBufferLen(p: *const ModuleBuffer) -> usize; - pub fn LLVMRustModuleBufferFree(p: *mut ModuleBuffer); - pub fn LLVMRustModuleCost(M: ModuleRef) -> u64; - - pub fn LLVMRustThinLTOAvailable() -> bool; - pub fn LLVMRustPGOAvailable() -> bool; - pub fn LLVMRustWriteThinBitcodeToFile(PMR: PassManagerRef, - M: ModuleRef, - BC: *const c_char) -> bool; - pub fn LLVMRustThinLTOBufferCreate(M: ModuleRef) -> *mut ThinLTOBuffer; - pub fn LLVMRustThinLTOBufferFree(M: *mut ThinLTOBuffer); - pub fn LLVMRustThinLTOBufferPtr(M: *const ThinLTOBuffer) -> *const c_char; - pub fn LLVMRustThinLTOBufferLen(M: *const ThinLTOBuffer) -> size_t; - pub fn LLVMRustCreateThinLTOData( - Modules: *const ThinLTOModule, - NumModules: c_uint, - PreservedSymbols: *const *const c_char, - PreservedSymbolsLen: c_uint, - ) -> *mut ThinLTOData; - pub fn LLVMRustPrepareThinLTORename( - Data: *const ThinLTOData, - Module: ModuleRef, - ) -> bool; - pub fn LLVMRustPrepareThinLTOResolveWeak( - Data: *const ThinLTOData, - Module: ModuleRef, - ) -> bool; - pub fn LLVMRustPrepareThinLTOInternalize( - Data: *const ThinLTOData, - Module: ModuleRef, - ) -> bool; - pub fn LLVMRustPrepareThinLTOImport( - Data: *const ThinLTOData, - Module: ModuleRef, - ) -> bool; - pub fn LLVMRustFreeThinLTOData(Data: *mut ThinLTOData); - pub fn LLVMRustParseBitcodeForThinLTO( - Context: ContextRef, - Data: *const u8, - len: usize, - Identifier: *const c_char, - ) -> ModuleRef; - pub fn LLVMGetModuleIdentifier(M: ModuleRef, size: *mut usize) -> *const c_char; - pub fn LLVMRustThinLTOGetDICompileUnit(M: ModuleRef, - CU1: *mut *mut c_void, - CU2: *mut *mut c_void); - pub fn LLVMRustThinLTOPatchDICompileUnit(M: ModuleRef, CU: *mut c_void); - - pub fn LLVMRustLinkerNew(M: ModuleRef) -> LinkerRef; - pub fn LLVMRustLinkerAdd(linker: LinkerRef, - bytecode: *const c_char, - bytecode_len: usize) -> bool; - pub fn LLVMRustLinkerFree(linker: LinkerRef); -} diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 91f9b4ac03b86..05f6b5b5fbd28 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -8,290 +8,20 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(non_upper_case_globals)] -#![allow(non_camel_case_types)] -#![allow(non_snake_case)] -#![allow(dead_code)] +#![feature(static_nobundle)] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -#![feature(box_syntax)] -#![feature(concat_idents)] -#![feature(libc)] -#![feature(link_args)] -#![feature(static_nobundle)] - // See librustc_cratesio_shim/Cargo.toml for a comment explaining this. #[allow(unused_extern_crates)] extern crate rustc_cratesio_shim; -#[macro_use] -extern crate bitflags; -extern crate libc; - -pub use self::IntPredicate::*; -pub use self::RealPredicate::*; -pub use self::TypeKind::*; -pub use self::AtomicRmwBinOp::*; -pub use self::MetadataType::*; -pub use self::CodeGenOptSize::*; -pub use self::CallConv::*; -pub use self::Linkage::*; - -use std::str::FromStr; -use std::slice; -use std::ffi::{CString, CStr}; -use std::cell::RefCell; -use libc::{c_uint, c_char, size_t}; - -pub mod archive_ro; -pub mod diagnostic; -mod ffi; - -pub use ffi::*; - -impl LLVMRustResult { - pub fn into_result(self) -> Result<(), ()> { - match self { - LLVMRustResult::Success => Ok(()), - LLVMRustResult::Failure => Err(()), - } - } -} - -pub fn AddFunctionAttrStringValue(llfn: ValueRef, - idx: AttributePlace, - attr: &CStr, - value: &CStr) { - unsafe { - LLVMRustAddFunctionAttrStringValue(llfn, - idx.as_uint(), - attr.as_ptr(), - value.as_ptr()) - } -} - -#[derive(Copy, Clone)] -pub enum AttributePlace { - ReturnValue, - Argument(u32), - Function, -} - -impl AttributePlace { - pub fn as_uint(self) -> c_uint { - match self { - AttributePlace::ReturnValue => 0, - AttributePlace::Argument(i) => 1 + i, - AttributePlace::Function => !0, - } - } -} - -#[derive(Copy, Clone, PartialEq)] -#[repr(C)] -pub enum CodeGenOptSize { - CodeGenOptSizeNone = 0, - CodeGenOptSizeDefault = 1, - CodeGenOptSizeAggressive = 2, -} - -impl FromStr for ArchiveKind { - type Err = (); - - fn from_str(s: &str) -> Result { - match s { - "gnu" => Ok(ArchiveKind::K_GNU), - "bsd" => Ok(ArchiveKind::K_BSD), - "coff" => Ok(ArchiveKind::K_COFF), - _ => Err(()), - } - } -} - -#[allow(missing_copy_implementations)] -pub enum RustString_opaque {} -type RustStringRef = *mut RustString_opaque; -type RustStringRepr = *mut RefCell>; - -/// Appending to a Rust string -- used by RawRustStringOstream. -#[no_mangle] -pub unsafe extern "C" fn LLVMRustStringWriteImpl(sr: RustStringRef, - ptr: *const c_char, - size: size_t) { - let slice = slice::from_raw_parts(ptr as *const u8, size as usize); - - let sr = sr as RustStringRepr; - (*sr).borrow_mut().extend_from_slice(slice); -} - -pub fn SetInstructionCallConv(instr: ValueRef, cc: CallConv) { - unsafe { - LLVMSetInstructionCallConv(instr, cc as c_uint); - } -} -pub fn SetFunctionCallConv(fn_: ValueRef, cc: CallConv) { - unsafe { - LLVMSetFunctionCallConv(fn_, cc as c_uint); - } -} - -// Externally visible symbols that might appear in multiple codegen units need to appear in -// their own comdat section so that the duplicates can be discarded at link time. This can for -// example happen for generics when using multiple codegen units. This function simply uses the -// value's name as the comdat value to make sure that it is in a 1-to-1 relationship to the -// function. -// For more details on COMDAT sections see e.g. http://www.airs.com/blog/archives/52 -pub fn SetUniqueComdat(llmod: ModuleRef, val: ValueRef) { - unsafe { - LLVMRustSetComdat(llmod, val, LLVMGetValueName(val)); - } -} - -pub fn UnsetComdat(val: ValueRef) { - unsafe { - LLVMRustUnsetComdat(val); - } -} - -pub fn SetUnnamedAddr(global: ValueRef, unnamed: bool) { - unsafe { - LLVMSetUnnamedAddr(global, unnamed as Bool); - } -} - -pub fn set_thread_local(global: ValueRef, is_thread_local: bool) { - unsafe { - LLVMSetThreadLocal(global, is_thread_local as Bool); - } -} -pub fn set_thread_local_mode(global: ValueRef, mode: ThreadLocalMode) { - unsafe { - LLVMSetThreadLocalMode(global, mode); - } -} - -impl Attribute { - pub fn apply_llfn(&self, idx: AttributePlace, llfn: ValueRef) { - unsafe { LLVMRustAddFunctionAttribute(llfn, idx.as_uint(), *self) } - } - - pub fn apply_callsite(&self, idx: AttributePlace, callsite: ValueRef) { - unsafe { LLVMRustAddCallSiteAttribute(callsite, idx.as_uint(), *self) } - } - - pub fn unapply_llfn(&self, idx: AttributePlace, llfn: ValueRef) { - unsafe { LLVMRustRemoveFunctionAttributes(llfn, idx.as_uint(), *self) } - } - - pub fn toggle_llfn(&self, idx: AttributePlace, llfn: ValueRef, set: bool) { - if set { - self.apply_llfn(idx, llfn); - } else { - self.unapply_llfn(idx, llfn); - } - } -} - -// Memory-managed interface to target data. - -struct TargetData { - lltd: TargetDataRef, -} - -impl Drop for TargetData { - fn drop(&mut self) { - unsafe { - LLVMDisposeTargetData(self.lltd); - } - } -} - -fn mk_target_data(string_rep: &str) -> TargetData { - let string_rep = CString::new(string_rep).unwrap(); - TargetData { lltd: unsafe { LLVMCreateTargetData(string_rep.as_ptr()) } } -} - -// Memory-managed interface to object files. - -pub struct ObjectFile { - pub llof: ObjectFileRef, -} - -unsafe impl Send for ObjectFile {} - -impl ObjectFile { - // This will take ownership of llmb - pub fn new(llmb: MemoryBufferRef) -> Option { - unsafe { - let llof = LLVMCreateObjectFile(llmb); - if llof as isize == 0 { - // LLVMCreateObjectFile took ownership of llmb - return None; - } - - Some(ObjectFile { llof: llof }) - } - } -} - -impl Drop for ObjectFile { - fn drop(&mut self) { - unsafe { - LLVMDisposeObjectFile(self.llof); - } - } -} - -// Memory-managed interface to section iterators. - -pub struct SectionIter { - pub llsi: SectionIteratorRef, -} - -impl Drop for SectionIter { - fn drop(&mut self) { - unsafe { - LLVMDisposeSectionIterator(self.llsi); - } - } -} - -pub fn mk_section_iter(llof: ObjectFileRef) -> SectionIter { - unsafe { SectionIter { llsi: LLVMGetSections(llof) } } -} - -/// Safe wrapper around `LLVMGetParam`, because segfaults are no fun. -pub fn get_param(llfn: ValueRef, index: c_uint) -> ValueRef { - unsafe { - assert!(index < LLVMCountParams(llfn), - "out of bounds argument access: {} out of {} arguments", index, LLVMCountParams(llfn)); - LLVMGetParam(llfn, index) - } -} - -fn get_params(llfn: ValueRef) -> Vec { - unsafe { - let num_params = LLVMCountParams(llfn); - - (0..num_params).map(|idx| LLVMGetParam(llfn, idx)).collect() - } -} - -pub fn build_string(f: F) -> Option - where F: FnOnce(RustStringRef) -{ - let mut buf = RefCell::new(Vec::new()); - f(&mut buf as RustStringRepr as RustStringRef); - String::from_utf8(buf.into_inner()).ok() -} - -pub unsafe fn twine_to_string(tr: TwineRef) -> String { - build_string(|s| LLVMRustWriteTwineToString(tr, s)).expect("got a non-UTF8 Twine from LLVM") -} +// NOTE: This crate only exists to allow linking on mingw targets. +/// Initialize targets enabled by the build script via `cfg(llvm_component = "...")`. +/// NB: this function can't be moved to `rustc_codegen_llvm` because of the `cfg`s. pub fn initialize_available_targets() { macro_rules! init_target( ($cfg:meta, $($method:ident),*) => { { @@ -383,43 +113,3 @@ pub fn initialize_available_targets() { LLVMInitializeWebAssemblyTargetMC, LLVMInitializeWebAssemblyAsmPrinter); } - -pub fn last_error() -> Option { - unsafe { - let cstr = LLVMRustGetLastError(); - if cstr.is_null() { - None - } else { - let err = CStr::from_ptr(cstr).to_bytes(); - let err = String::from_utf8_lossy(err).to_string(); - libc::free(cstr as *mut _); - Some(err) - } - } -} - -pub struct OperandBundleDef { - inner: OperandBundleDefRef, -} - -impl OperandBundleDef { - pub fn new(name: &str, vals: &[ValueRef]) -> OperandBundleDef { - let name = CString::new(name).unwrap(); - let def = unsafe { - LLVMRustBuildOperandBundleDef(name.as_ptr(), vals.as_ptr(), vals.len() as c_uint) - }; - OperandBundleDef { inner: def } - } - - pub fn raw(&self) -> OperandBundleDefRef { - self.inner - } -} - -impl Drop for OperandBundleDef { - fn drop(&mut self) { - unsafe { - LLVMRustFreeOperandBundleDef(self.inner); - } - } -} diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs index 8f4911574398b..a50a5a2d1cbe7 100644 --- a/src/librustc_target/lib.rs +++ b/src/librustc_target/lib.rs @@ -15,11 +15,7 @@ //! is really just odds-and-ends relating to code gen and linking. //! This crate mostly exists to make rustc smaller, so we might put //! more 'stuff' here in the future. It does not have a dependency on -//! rustc_llvm. -//! -//! FIXME: Split this into two crates: one that has deps on syntax, and -//! one that doesn't; the one that doesn't might get decent parallel -//! build speedups. +//! LLVM. #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp index 93157cd681942..49a4962858ca7 100644 --- a/src/rustllvm/ArchiveWrapper.cpp +++ b/src/rustllvm/ArchiveWrapper.cpp @@ -148,7 +148,7 @@ LLVMRustArchiveChildName(LLVMRustArchiveChildConstRef Child, size_t *Size) { #if LLVM_VERSION_GE(4, 0) Expected NameOrErr = Child->getName(); if (!NameOrErr) { - // rustc_llvm currently doesn't use this error string, but it might be + // rustc_codegen_llvm currently doesn't use this error string, but it might be // useful in the future, and in the mean time this tells LLVM that the // error was not ignored and that it shouldn't abort the process. LLVMRustSetLastError(toString(NameOrErr.takeError()).c_str()); diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 85fbc4bf378a5..3f5550bf95fd2 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -828,23 +828,6 @@ LLVMRustPGOAvailable() { // and various online resources about ThinLTO to make heads or tails of all // this. -extern "C" bool -LLVMRustWriteThinBitcodeToFile(LLVMPassManagerRef PMR, - LLVMModuleRef M, - const char *BcFile) { - llvm::legacy::PassManager *PM = unwrap(PMR); - std::error_code EC; - llvm::raw_fd_ostream bc(BcFile, EC, llvm::sys::fs::F_None); - if (EC) { - LLVMRustSetLastError(EC.message().c_str()); - return false; - } - PM->add(createWriteThinLTOBitcodePass(bc)); - PM->run(*unwrap(M)); - delete PM; - return true; -} - // This is a shared data structure which *must* be threadsafe to share // read-only amongst threads. This also corresponds basically to the arguments // of the `ProcessThinLTOModule` function in the LLVM source. @@ -1259,13 +1242,6 @@ LLVMRustThinLTOPatchDICompileUnit(LLVMModuleRef Mod, DICompileUnit *Unit) { #else -extern "C" bool -LLVMRustWriteThinBitcodeToFile(LLVMPassManagerRef PMR, - LLVMModuleRef M, - const char *BcFile) { - report_fatal_error("ThinLTO not available"); -} - struct LLVMRustThinLTOData { }; diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index d82410618d04b..f2b5297285ca7 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -750,15 +750,6 @@ LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size, DINodeArray(unwrapDI(Subscripts)))); } -extern "C" LLVMMetadataRef -LLVMRustDIBuilderCreateVectorType(LLVMRustDIBuilderRef Builder, uint64_t Size, - uint32_t AlignInBits, LLVMMetadataRef Ty, - LLVMMetadataRef Subscripts) { - return wrap( - Builder->createVectorType(Size, AlignInBits, unwrapDI(Ty), - DINodeArray(unwrapDI(Subscripts)))); -} - extern "C" LLVMMetadataRef LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo, int64_t Count) {