From 34c5dc045f2ee53b3bc8e5cece75e6ece96389e6 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Tue, 7 Aug 2018 17:14:40 +0200 Subject: [PATCH] Generalized base.rs#call_memcpy and everything that it uses Generalized operand.rs#nontemporal_store and fixed tidy issues Generalized operand.rs#nontemporal_store's implem even more With a BuilderMethod trait implemented by Builder for LLVM Cleaned builder.rs : no more code duplication, no more ValueTrait Full traitification of builder.rs --- .atom-build.yml | 1 + src/librustc_codegen_llvm/abi.rs | 24 +- src/librustc_codegen_llvm/asm.rs | 1 + src/librustc_codegen_llvm/attributes.rs | 2 +- src/librustc_codegen_llvm/back/write.rs | 3 +- src/librustc_codegen_llvm/base.rs | 38 +- src/librustc_codegen_llvm/builder.rs | 359 +++++++++--------- src/librustc_codegen_llvm/common.rs | 34 +- src/librustc_codegen_llvm/context.rs | 41 +- src/librustc_codegen_llvm/debuginfo/gdb.rs | 3 +- src/librustc_codegen_llvm/debuginfo/mod.rs | 1 + .../debuginfo/source_loc.rs | 6 +- src/librustc_codegen_llvm/declare.rs | 18 +- src/librustc_codegen_llvm/glue.rs | 8 +- src/librustc_codegen_llvm/intrinsic.rs | 30 +- src/librustc_codegen_llvm/lib.rs | 2 + src/librustc_codegen_llvm/meth.rs | 8 +- src/librustc_codegen_llvm/mir/block.rs | 28 +- src/librustc_codegen_llvm/mir/constant.rs | 1 + src/librustc_codegen_llvm/mir/mod.rs | 7 +- src/librustc_codegen_llvm/mir/operand.rs | 35 +- src/librustc_codegen_llvm/mir/place.rs | 8 +- src/librustc_codegen_llvm/mir/rvalue.rs | 30 +- src/librustc_codegen_llvm/mir/statement.rs | 1 + src/librustc_codegen_llvm/traits.rs | 283 ++++++++++++++ src/librustc_codegen_llvm/type_.rs | 114 ++++-- src/librustc_codegen_llvm/type_of.rs | 5 +- src/librustc_codegen_llvm/value.rs | 14 +- 28 files changed, 792 insertions(+), 313 deletions(-) create mode 100644 .atom-build.yml create mode 100644 src/librustc_codegen_llvm/traits.rs diff --git a/.atom-build.yml b/.atom-build.yml new file mode 100644 index 00000000000..a31bc877c9f --- /dev/null +++ b/.atom-build.yml @@ -0,0 +1 @@ +cmd: ./x.py -i check diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index 9e9467e3645..b4aa6495da8 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -19,6 +19,8 @@ use type_of::{LayoutLlvmExt, PointerKind}; use value::Value; +use traits::BuilderMethods; + use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TyLayout, Abi as LayoutAbi}; use rustc::ty::{self, Ty}; use rustc::ty::layout; @@ -119,7 +121,7 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { } } RegKind::Vector => { - Type::vector(Type::i8(cx), self.size.bytes()) + Type::vector::(Type::i8(cx), self.size.bytes()) } } } @@ -143,7 +145,7 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { // 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); } } @@ -167,7 +169,12 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, '_>) -> &'ll Type { 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<'tcx, &'ll Value>); + fn store( + &self, + bx: &Builder<'_, 'll, 'tcx>, + val: &'ll Value, + dst: PlaceRef<'tcx, &'ll Value>, + ); fn store_fn_arg( &self, bx: &Builder<'_, 'll, 'tcx>, @@ -187,7 +194,12 @@ fn memory_ty(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type { /// 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<'_, 'll, 'tcx>, val: &'ll Value, dst: PlaceRef<'tcx, &'ll Value>) { + fn store( + &self, + bx: &Builder<'_, 'll, 'tcx>, + val: &'ll Value, + dst: PlaceRef<'tcx, &'ll Value>, + ) { if self.is_ignore() { return; } @@ -663,9 +675,9 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type { } 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) } } diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs index b2671144107..441888583ea 100644 --- a/src/librustc_codegen_llvm/asm.rs +++ b/src/librustc_codegen_llvm/asm.rs @@ -16,6 +16,7 @@ use value::Value; use rustc::hir; +use traits::BuilderMethods; use mir::place::PlaceRef; use mir::operand::OperandValue; diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index f45b3728bc1..8004b7ba88e 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -127,7 +127,7 @@ pub fn llvm_target_features(sess: &Session) -> impl Iterator { .filter(|l| !l.is_empty()) } -pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { +pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_, &'ll Value>, llfn: &'ll Value) { let cpu = llvm_util::target_cpu(cx.tcx.sess); let target_cpu = CString::new(cpu).unwrap(); llvm::AddFunctionAttrStringValue( diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 8973852caa8..e8d5812816e 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -49,6 +49,7 @@ use common::{C_bytes_in_context, val_ty}; use jobserver::{Client, Acquired}; use rustc_demangle; +use value::Value; use std::any::Any; use std::ffi::{CString, CStr}; @@ -2574,7 +2575,7 @@ fn create_msvc_imps(cgcx: &CodegenContext, llcx: &llvm::Context, llmod: &llvm::M "\x01__imp_" }; unsafe { - let i8p_ty = Type::i8p_llcx(llcx); + let i8p_ty = Type::i8p_llcx::(llcx); let globals = base::iter_globals(llmod) .filter(|&val| { llvm::LLVMRustGetLinkage(val) == llvm::Linkage::ExternalLinkage && diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 50fb246a7d4..f268d3dd86f 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -75,6 +75,8 @@ use rustc_data_structures::sync::Lrc; use rustc_data_structures::indexed_vec::Idx; +use traits::BuilderMethods; + use std::any::Any; use std::cmp; use std::ffi::CString; @@ -86,7 +88,7 @@ use syntax::attr; use rustc::hir::{self, CodegenFnAttrs}; -use value::Value; +use value::{Value, ValueTrait}; use mir::operand::OperandValue; @@ -387,9 +389,14 @@ pub fn call_assume(bx: &Builder<'_, 'll, '_>, val: &'ll Value) { bx.call(assume_intrinsic, &[val], None); } -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)) +pub fn from_immediate<'a, 'll: 'a, 'tcx: 'll, + Value : ?Sized, + Builder: BuilderMethods<'a, 'll, 'tcx, Value>>( + bx: &Builder, + val: &'ll Value +) -> &'ll Value where Value : ValueTrait { + if val_ty(val) == Type::i1(bx.cx()) { + bx.zext(val, Type::i8(bx.cx())) } else { val } @@ -417,15 +424,17 @@ pub fn to_immediate_scalar( val } -pub fn call_memcpy( - bx: &Builder<'_, 'll, '_>, +pub fn call_memcpy<'a, 'll: 'a, 'tcx: 'll, + Value : ?Sized, + Builder: BuilderMethods<'a, 'll, 'tcx, Value>>( + bx: &Builder, dst: &'ll Value, dst_align: Align, src: &'ll Value, src_align: Align, n_bytes: &'ll Value, flags: MemFlags, -) { +) where Value : ValueTrait { if flags.contains(MemFlags::NONTEMPORAL) { // HACK(nox): This is inefficient but there is no nontemporal memcpy. let val = bx.load(src, src_align); @@ -433,7 +442,7 @@ pub fn call_memcpy( bx.store_with_flags(val, ptr, dst_align, flags); return; } - let cx = bx.cx; + let cx = bx.cx(); let src_ptr = bx.pointercast(src, Type::i8p(cx)); let dst_ptr = bx.pointercast(dst, Type::i8p(cx)); let size = bx.intcast(n_bytes, cx.isize_ty, false); @@ -441,21 +450,23 @@ pub fn call_memcpy( bx.memcpy(dst_ptr, dst_align.abi(), src_ptr, src_align.abi(), size, volatile); } -pub fn memcpy_ty( - bx: &Builder<'_, 'll, 'tcx>, +pub fn memcpy_ty<'a, 'll: 'a, 'tcx: 'll, + Value : ?Sized, + Builder: BuilderMethods<'a, 'll, 'tcx, Value>>( + bx: &Builder, dst: &'ll Value, dst_align: Align, src: &'ll Value, src_align: Align, layout: TyLayout<'tcx>, flags: MemFlags, -) { +) where Value : ValueTrait { let size = layout.size.bytes(); if size == 0 { return; } - call_memcpy(bx, dst, dst_align, src, src_align, C_usize(bx.cx, size), flags); + call_memcpy(bx, dst, dst_align, src, src_align, C_usize(bx.cx(), size), flags); } pub fn call_memset( @@ -545,7 +556,8 @@ fn create_entry_fn( 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 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, diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 927ad8aecd8..f8074db4388 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -19,6 +19,7 @@ use rustc::ty::layout::{Align, Size}; use rustc::session::{config, Session}; use rustc_data_structures::small_c_str::SmallCStr; +use traits::BuilderMethods; use std::borrow::Cow; use std::ops::Range; @@ -54,8 +55,12 @@ pub struct MemFlags: u8 { } } -impl Builder<'a, 'll, 'tcx> { - pub fn new_block<'b>(cx: &'a CodegenCx<'ll, 'tcx>, llfn: &'ll Value, name: &'b str) -> Self { +impl BuilderMethods<'a, 'll, 'tcx, Value> for Builder<'a, 'll, 'tcx> { + 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 = SmallCStr::new(name); @@ -69,7 +74,7 @@ pub fn new_block<'b>(cx: &'a CodegenCx<'ll, 'tcx>, llfn: &'ll Value, name: &'b s bx } - pub fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self { + fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self { // Create a fresh builder from the crate context. let llbuilder = unsafe { llvm::LLVMCreateBuilderInContext(cx.llcx) @@ -80,84 +85,84 @@ pub fn with_cx(cx: &'a CodegenCx<'ll, 'tcx>) -> Self { } } - pub fn build_sibling_block<'b>(&self, name: &'b str) -> Builder<'a, 'll, 'tcx> { + fn build_sibling_block<'b>(&self, name: &'b str) -> Self { Builder::new_block(self.cx, self.llfn(), name) } - pub fn sess(&self) -> &Session { + fn sess(&self) -> &Session { self.cx.sess() } - pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { + fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.cx.tcx } - pub fn llfn(&self) -> &'ll Value { + fn llfn(&self) -> &'ll Value { unsafe { llvm::LLVMGetBasicBlockParent(self.llbb()) } } - pub fn llbb(&self) -> &'ll BasicBlock { + fn llbb(&self) -> &'ll BasicBlock { unsafe { llvm::LLVMGetInsertBlock(self.llbuilder) } } fn count_insn(&self, category: &str) { - if self.cx.sess().codegen_stats() { - self.cx.stats.borrow_mut().n_llvm_insns += 1; + if self.cx().sess().codegen_stats() { + self.cx().stats.borrow_mut().n_llvm_insns += 1; } - if self.cx.sess().count_llvm_insns() { - *self.cx.stats - .borrow_mut() - .llvm_insns - .entry(category.to_string()) - .or_insert(0) += 1; + if self.cx().sess().count_llvm_insns() { + *self.cx().stats + .borrow_mut() + .llvm_insns + .entry(category.to_string()) + .or_insert(0) += 1; } } - pub fn set_value_name(&self, value: &'ll Value, name: &str) { + fn set_value_name(&self, value: &'ll Value, name: &str) { let cname = SmallCStr::new(name); unsafe { llvm::LLVMSetValueName(value, cname.as_ptr()); } } - pub fn position_at_end(&self, llbb: &'ll BasicBlock) { + fn position_at_end(&self, llbb: &'ll BasicBlock) { unsafe { llvm::LLVMPositionBuilderAtEnd(self.llbuilder, llbb); } } - pub fn position_at_start(&self, llbb: &'ll BasicBlock) { + fn position_at_start(&self, llbb: &'ll BasicBlock) { unsafe { llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb); } } - pub fn ret_void(&self) { + fn ret_void(&self) { self.count_insn("retvoid"); unsafe { llvm::LLVMBuildRetVoid(self.llbuilder); } } - pub fn ret(&self, v: &'ll Value) { + fn ret(&self, v: &'ll Value) { self.count_insn("ret"); unsafe { llvm::LLVMBuildRet(self.llbuilder, v); } } - pub fn br(&self, dest: &'ll BasicBlock) { + fn br(&self, dest: &'ll BasicBlock) { self.count_insn("br"); unsafe { llvm::LLVMBuildBr(self.llbuilder, dest); } } - pub fn cond_br( + fn cond_br( &self, cond: &'ll Value, then_llbb: &'ll BasicBlock, @@ -169,7 +174,7 @@ pub fn cond_br( } } - pub fn switch( + fn switch( &self, v: &'ll Value, else_llbb: &'ll BasicBlock, @@ -180,7 +185,7 @@ pub fn switch( } } - pub fn invoke(&self, + fn invoke(&self, llfn: &'ll Value, args: &[&'ll Value], then: &'ll BasicBlock, @@ -207,7 +212,7 @@ pub fn invoke(&self, } } - pub fn unreachable(&self) { + fn unreachable(&self) { self.count_insn("unreachable"); unsafe { llvm::LLVMBuildUnreachable(self.llbuilder); @@ -215,21 +220,21 @@ pub fn unreachable(&self) { } /* Arithmetic */ - pub fn add(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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 fadd(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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()); @@ -238,21 +243,21 @@ pub fn fadd_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { } } - pub fn sub(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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 fsub(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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()); @@ -261,21 +266,21 @@ pub fn fsub_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { } } - pub fn mul(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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 fmul(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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()); @@ -285,42 +290,42 @@ pub fn fmul_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { } - pub fn udiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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()); @@ -329,28 +334,28 @@ pub fn fdiv_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { } } - pub fn urem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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()); @@ -359,70 +364,70 @@ pub fn frem_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { } } - pub fn shl(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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 neg(&self, v: &'ll Value) -> &'ll Value { + fn neg(&self, v: &'ll Value) -> &'ll Value { self.count_insn("neg"); unsafe { llvm::LLVMBuildNeg(self.llbuilder, v, noname()) } } - pub fn fneg(&self, v: &'ll Value) -> &'ll Value { + fn fneg(&self, v: &'ll Value) -> &'ll Value { self.count_insn("fneg"); unsafe { llvm::LLVMBuildFNeg(self.llbuilder, v, noname()) } } - pub fn not(&self, v: &'ll Value) -> &'ll Value { + fn not(&self, v: &'ll Value) -> &'ll Value { self.count_insn("not"); unsafe { llvm::LLVMBuildNot(self.llbuilder, v, noname()) } } - pub fn alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { + 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()) @@ -430,7 +435,7 @@ pub fn alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { bx.dynamic_alloca(ty, name, align) } - pub fn dynamic_alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { + fn dynamic_alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { self.count_insn("alloca"); unsafe { let alloca = if name.is_empty() { @@ -445,7 +450,7 @@ pub fn dynamic_alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Va } } - pub fn array_alloca(&self, + fn array_alloca(&self, ty: &'ll Type, len: &'ll Value, name: &str, @@ -464,7 +469,7 @@ pub fn array_alloca(&self, } } - pub fn load(&self, ptr: &'ll Value, align: Align) -> &'ll Value { + fn load(&self, ptr: &'ll Value, align: Align) -> &'ll Value { self.count_insn("load"); unsafe { let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname()); @@ -473,7 +478,7 @@ pub fn load(&self, ptr: &'ll Value, align: Align) -> &'ll Value { } } - pub fn volatile_load(&self, ptr: &'ll Value) -> &'ll Value { + fn volatile_load(&self, ptr: &'ll Value) -> &'ll Value { self.count_insn("load.volatile"); unsafe { let insn = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname()); @@ -482,7 +487,7 @@ pub fn volatile_load(&self, ptr: &'ll Value) -> &'ll Value { } } - pub fn atomic_load(&self, ptr: &'ll Value, order: AtomicOrdering, size: Size) -> &'ll Value { + fn atomic_load(&self, ptr: &'ll Value, order: AtomicOrdering, size: Size) -> &'ll Value { self.count_insn("load.atomic"); unsafe { let load = llvm::LLVMRustBuildAtomicLoad(self.llbuilder, ptr, noname(), order); @@ -493,7 +498,7 @@ pub fn atomic_load(&self, ptr: &'ll Value, order: AtomicOrdering, size: Size) -> } - pub fn range_metadata(&self, load: &'ll Value, range: Range) { + fn range_metadata(&self, load: &'ll Value, range: Range) { if self.sess().target.target.arch == "amdgpu" { // amdgpu/LLVM does something weird and thinks a i64 value is // split into a v2i32, halving the bitwidth LLVM expects, @@ -516,18 +521,18 @@ pub fn range_metadata(&self, load: &'ll Value, range: Range) { } } - pub fn nonnull_metadata(&self, load: &'ll Value) { + 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: &'ll Value, ptr: &'ll Value, align: Align) -> &'ll Value { + 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( + fn store_with_flags( &self, val: &'ll Value, ptr: &'ll Value, @@ -561,8 +566,8 @@ pub fn store_with_flags( } } - pub fn atomic_store(&self, val: &'ll Value, ptr: &'ll Value, - order: AtomicOrdering, size: Size) { + fn atomic_store(&self, val: &'ll Value, ptr: &'ll Value, + order: AtomicOrdering, size: Size) { debug!("Store {:?} -> {:?}", val, ptr); self.count_insn("store.atomic"); let ptr = self.check_store(val, ptr); @@ -573,7 +578,7 @@ pub fn atomic_store(&self, val: &'ll Value, ptr: &'ll Value, } } - pub fn gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value { + fn gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value { self.count_insn("gep"); unsafe { llvm::LLVMBuildGEP(self.llbuilder, ptr, indices.as_ptr(), @@ -581,7 +586,7 @@ pub fn gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value { } } - pub fn inbounds_gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value { + fn inbounds_gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value { self.count_insn("inboundsgep"); unsafe { llvm::LLVMBuildInBoundsGEP( @@ -589,122 +594,108 @@ pub fn inbounds_gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Valu } } - 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 { - llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, noname()) - } - } - /* Casts */ - pub fn trunc(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { + fn trunc(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("trunc"); unsafe { llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, noname()) } } - 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, noname()) - } - } - - pub fn sext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { + fn sext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("sext"); unsafe { llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, noname()) } } - pub fn fptoui(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { + fn fptoui(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("fptoui"); unsafe { llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, noname()) } } - pub fn fptosi(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { + fn fptosi(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("fptosi"); unsafe { llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty,noname()) } } - pub fn uitofp(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { + fn uitofp(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("uitofp"); unsafe { llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, noname()) } } - pub fn sitofp(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { + fn sitofp(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("sitofp"); unsafe { llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, noname()) } } - pub fn fptrunc(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { + fn fptrunc(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("fptrunc"); unsafe { llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, noname()) } } - pub fn fpext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { + fn fpext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("fpext"); unsafe { llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, noname()) } } - pub fn ptrtoint(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { + fn ptrtoint(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("ptrtoint"); unsafe { llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, noname()) } } - pub fn inttoptr(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { + fn inttoptr(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("inttoptr"); unsafe { llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, noname()) } } - pub fn bitcast(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { + fn bitcast(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { self.count_insn("bitcast"); unsafe { llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, noname()) } } - pub fn pointercast(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { - self.count_insn("pointercast"); + + fn intcast(&self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value { + self.count_insn("intcast"); unsafe { - llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, noname()) + llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty, is_signed) } } - pub fn intcast(&self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value { - self.count_insn("intcast"); + fn pointercast(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { + self.count_insn("pointercast"); unsafe { - llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty, is_signed) + llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, noname()) } } /* Comparisons */ - pub fn icmp(&self, op: IntPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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: &'ll Value, rhs: &'ll Value) -> &'ll Value { + 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()) @@ -712,14 +703,14 @@ pub fn fcmp(&self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll } /* Miscellaneous instructions */ - pub fn empty_phi(&self, ty: &'ll Type) -> &'ll Value { + fn empty_phi(&self, ty: &'ll Type) -> &'ll Value { self.count_insn("emptyphi"); unsafe { llvm::LLVMBuildPhi(self.llbuilder, ty, noname()) } } - pub fn phi(&self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value { + 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"); @@ -731,10 +722,10 @@ pub fn phi(&self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) - } } - pub fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char, - inputs: &[&'ll Value], output: &'ll Type, - volatile: bool, alignstack: bool, - dia: AsmDialect) -> Option<&'ll Value> { + fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char, + inputs: &[&'ll Value], output: &'ll Type, + volatile: bool, alignstack: bool, + dia: AsmDialect) -> Option<&'ll Value> { self.count_insn("inlineasm"); let volatile = if volatile { llvm::True } @@ -748,7 +739,7 @@ pub fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char, }).collect::>(); debug!("Asm Output Type: {:?}", output); - let fty = Type::func(&argtys[..], output); + let fty = Type::func::(&argtys[..], output); unsafe { // Ask LLVM to verify that the constraints are well-formed. let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons); @@ -764,24 +755,7 @@ pub fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char, } } - pub fn call(&self, llfn: &'ll Value, args: &[&'ll Value], - bundle: Option<&OperandBundleDef<'ll>>) -> &'ll Value { - self.count_insn("call"); - - debug!("Call {:?} with args ({:?})", - llfn, - args); - - let args = self.check_call("call", llfn, args); - let bundle = bundle.map(|b| &*b.raw); - - unsafe { - llvm::LLVMRustBuildCall(self.llbuilder, llfn, args.as_ptr(), - args.len() as c_uint, bundle, noname()) - } - } - - pub fn memcpy(&self, dst: &'ll Value, dst_align: u64, + fn memcpy(&self, dst: &'ll Value, dst_align: u64, src: &'ll Value, src_align: u64, size: &'ll Value, is_volatile: bool) -> &'ll Value { unsafe { @@ -790,7 +764,7 @@ pub fn memcpy(&self, dst: &'ll Value, dst_align: u64, } } - pub fn memmove(&self, dst: &'ll Value, dst_align: u64, + fn memmove(&self, dst: &'ll Value, dst_align: u64, src: &'ll Value, src_align: u64, size: &'ll Value, is_volatile: bool) -> &'ll Value { unsafe { @@ -799,14 +773,14 @@ pub fn memmove(&self, dst: &'ll Value, dst_align: u64, } } - pub fn minnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { + fn minnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("minnum"); unsafe { let instr = llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs); instr.expect("LLVMRustBuildMinNum is not available in LLVM version < 6.0") } } - pub fn maxnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { + fn maxnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { self.count_insn("maxnum"); unsafe { let instr = llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs); @@ -814,7 +788,7 @@ pub fn maxnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { } } - pub fn select( + fn select( &self, cond: &'ll Value, then_val: &'ll Value, else_val: &'ll Value, @@ -826,21 +800,21 @@ pub fn select( } #[allow(dead_code)] - pub fn va_arg(&self, list: &'ll Value, ty: &'ll Type) -> &'ll Value { + fn va_arg(&self, list: &'ll Value, ty: &'ll Type) -> &'ll Value { self.count_insn("vaarg"); unsafe { llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname()) } } - pub fn extract_element(&self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value { + 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( + fn insert_element( &self, vec: &'ll Value, elt: &'ll Value, idx: &'ll Value, @@ -851,24 +825,24 @@ pub fn insert_element( } } - pub fn shuffle_vector(&self, v1: &'ll Value, v2: &'ll Value, mask: &'ll Value) -> &'ll Value { + 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: &'ll Value) -> &'ll Value { + 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)); + 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: &'ll Value, src: &'ll Value) -> &'ll Value { + 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 @@ -879,7 +853,7 @@ pub fn vector_reduce_fadd_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll instr } } - pub fn vector_reduce_fmul_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { + 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 @@ -890,35 +864,35 @@ pub fn vector_reduce_fmul_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll instr } } - pub fn vector_reduce_add(&self, src: &'ll Value) -> &'ll Value { + fn vector_reduce_add(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.add"); unsafe { llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src) } } - pub fn vector_reduce_mul(&self, src: &'ll Value) -> &'ll Value { + fn vector_reduce_mul(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.mul"); unsafe { llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src) } } - pub fn vector_reduce_and(&self, src: &'ll Value) -> &'ll Value { + fn vector_reduce_and(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.and"); unsafe { llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src) } } - pub fn vector_reduce_or(&self, src: &'ll Value) -> &'ll Value { + fn vector_reduce_or(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.or"); unsafe { llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src) } } - pub fn vector_reduce_xor(&self, src: &'ll Value) -> &'ll Value { + fn vector_reduce_xor(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.xor"); unsafe { llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src) } } - pub fn vector_reduce_fmin(&self, src: &'ll Value) -> &'ll Value { + fn vector_reduce_fmin(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.fmin"); unsafe { llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false) } } - pub fn vector_reduce_fmax(&self, src: &'ll Value) -> &'ll Value { + fn vector_reduce_fmax(&self, src: &'ll Value) -> &'ll Value { self.count_insn("vector.reduce.fmax"); unsafe { llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false) } } - pub fn vector_reduce_fmin_fast(&self, src: &'ll Value) -> &'ll Value { + 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); @@ -926,7 +900,7 @@ pub fn vector_reduce_fmin_fast(&self, src: &'ll Value) -> &'ll Value { instr } } - pub fn vector_reduce_fmax_fast(&self, src: &'ll Value) -> &'ll Value { + 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); @@ -934,16 +908,16 @@ pub fn vector_reduce_fmax_fast(&self, src: &'ll Value) -> &'ll Value { instr } } - pub fn vector_reduce_min(&self, src: &'ll Value, is_signed: bool) -> &'ll Value { + fn vector_reduce_min(&self, src: &'ll Value, is_signed: bool) -> &'ll Value { self.count_insn("vector.reduce.min"); unsafe { llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed) } } - pub fn vector_reduce_max(&self, src: &'ll Value, is_signed: bool) -> &'ll Value { + fn vector_reduce_max(&self, src: &'ll Value, is_signed: bool) -> &'ll Value { self.count_insn("vector.reduce.max"); unsafe { llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed) } } - pub fn extract_value(&self, agg_val: &'ll Value, idx: u64) -> &'ll Value { + 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 { @@ -951,7 +925,7 @@ pub fn extract_value(&self, agg_val: &'ll Value, idx: u64) -> &'ll Value { } } - pub fn insert_value(&self, agg_val: &'ll Value, elt: &'ll Value, + 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); @@ -961,7 +935,7 @@ pub fn insert_value(&self, agg_val: &'ll Value, elt: &'ll Value, } } - pub fn landing_pad(&self, ty: &'ll Type, pers_fn: &'ll Value, + fn landing_pad(&self, ty: &'ll Type, pers_fn: &'ll Value, num_clauses: usize) -> &'ll Value { self.count_insn("landingpad"); unsafe { @@ -970,27 +944,27 @@ pub fn landing_pad(&self, ty: &'ll Type, pers_fn: &'ll Value, } } - pub fn add_clause(&self, landing_pad: &'ll Value, clause: &'ll Value) { + fn add_clause(&self, landing_pad: &'ll Value, clause: &'ll Value) { unsafe { llvm::LLVMAddClause(landing_pad, clause); } } - pub fn set_cleanup(&self, landing_pad: &'ll Value) { + fn set_cleanup(&self, landing_pad: &'ll Value) { self.count_insn("setcleanup"); unsafe { llvm::LLVMSetCleanup(landing_pad, llvm::True); } } - pub fn resume(&self, exn: &'ll Value) -> &'ll Value { + fn resume(&self, exn: &'ll Value) -> &'ll Value { self.count_insn("resume"); unsafe { llvm::LLVMBuildResume(self.llbuilder, exn) } } - pub fn cleanup_pad(&self, + fn cleanup_pad(&self, parent: Option<&'ll Value>, args: &[&'ll Value]) -> &'ll Value { self.count_insn("cleanuppad"); @@ -1005,7 +979,7 @@ pub fn cleanup_pad(&self, ret.expect("LLVM does not have support for cleanuppad") } - pub fn cleanup_ret( + fn cleanup_ret( &self, cleanup: &'ll Value, unwind: Option<&'ll BasicBlock>, ) -> &'ll Value { @@ -1016,7 +990,7 @@ pub fn cleanup_ret( ret.expect("LLVM does not have support for cleanupret") } - pub fn catch_pad(&self, + fn catch_pad(&self, parent: &'ll Value, args: &[&'ll Value]) -> &'ll Value { self.count_insn("catchpad"); @@ -1029,7 +1003,7 @@ pub fn catch_pad(&self, ret.expect("LLVM does not have support for catchpad") } - pub fn catch_ret(&self, pad: &'ll Value, unwind: &'ll BasicBlock) -> &'ll Value { + 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) @@ -1037,7 +1011,7 @@ pub fn catch_ret(&self, pad: &'ll Value, unwind: &'ll BasicBlock) -> &'ll Value ret.expect("LLVM does not have support for catchret") } - pub fn catch_switch( + fn catch_switch( &self, parent: Option<&'ll Value>, unwind: Option<&'ll BasicBlock>, @@ -1053,20 +1027,20 @@ pub fn catch_switch( ret.expect("LLVM does not have support for catchswitch") } - pub fn add_handler(&self, catch_switch: &'ll Value, handler: &'ll BasicBlock) { + fn add_handler(&self, catch_switch: &'ll Value, handler: &'ll BasicBlock) { unsafe { llvm::LLVMRustAddHandler(catch_switch, handler); } } - pub fn set_personality_fn(&self, personality: &'ll Value) { + fn set_personality_fn(&self, personality: &'ll Value) { unsafe { llvm::LLVMSetPersonalityFn(self.llfn(), personality); } } // Atomic Operations - pub fn atomic_cmpxchg( + fn atomic_cmpxchg( &self, dst: &'ll Value, cmp: &'ll Value, @@ -1080,7 +1054,7 @@ pub fn atomic_cmpxchg( order, failure_order, weak) } } - pub fn atomic_rmw( + fn atomic_rmw( &self, op: AtomicRmwBinOp, dst: &'ll Value, @@ -1092,26 +1066,26 @@ pub fn atomic_rmw( } } - pub fn atomic_fence(&self, order: AtomicOrdering, scope: SynchronizationScope) { + fn atomic_fence(&self, order: AtomicOrdering, scope: SynchronizationScope) { unsafe { llvm::LLVMRustBuildAtomicFence(self.llbuilder, order, scope); } } - pub fn add_case(&self, s: &'ll Value, on_val: &'ll Value, dest: &'ll BasicBlock) { + 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: &'ll Value, val: &'ll Value, bb: &'ll BasicBlock) { + 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: &'ll Value) { + 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)); @@ -1181,11 +1155,11 @@ fn check_call<'b>(&self, Cow::Owned(casted_args) } - pub fn lifetime_start(&self, ptr: &'ll Value, size: Size) { + fn lifetime_start(&self, ptr: &'ll Value, size: Size) { self.call_lifetime_intrinsic("llvm.lifetime.start", ptr, size); } - pub fn lifetime_end(&self, ptr: &'ll Value, size: Size) { + fn lifetime_end(&self, ptr: &'ll Value, size: Size) { self.call_lifetime_intrinsic("llvm.lifetime.end", ptr, size); } @@ -1212,4 +1186,45 @@ fn call_lifetime_intrinsic(&self, intrinsic: &str, ptr: &'ll Value, size: Size) let ptr = self.pointercast(ptr, Type::i8p(self.cx)); self.call(lifetime_intrinsic, &[C_u64(self.cx, size), ptr], None); } + + fn call(&self, llfn: &'ll Value, args: &[&'ll Value], + bundle: Option<&OperandBundleDef<'ll>>) -> &'ll Value { + self.count_insn("call"); + + debug!("Call {:?} with args ({:?})", + llfn, + args); + + let args = self.check_call("call", llfn, args); + let bundle = bundle.map(|b| &*b.raw); + + unsafe { + llvm::LLVMRustBuildCall( + self.llbuilder, + llfn, + args.as_ptr() as *const &llvm::Value, + args.len() as c_uint, + bundle, noname() + ) + } + } + + fn zext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { + self.count_insn("zext"); + unsafe { + llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, noname()) + } + } + + 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 { + llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, noname()) + } + } + + fn cx(&self) -> &'a CodegenCx<'ll, 'tcx, &'ll Value> { + &self.cx + } } diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index c9b464fd8f3..66f14322fc6 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -23,11 +23,12 @@ use declare; use type_::Type; use type_of::LayoutLlvmExt; -use value::Value; +use value::{Value, ValueTrait}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::layout::{HasDataLayout, LayoutOf}; use rustc::hir; +use traits::BuilderMethods; use libc::{c_uint, c_char}; @@ -110,9 +111,9 @@ pub fn bundle(&self) -> &OperandBundleDef<'ll> { } } -pub fn val_ty(v: &'ll Value) -> &'ll Type { +pub fn val_ty(v: &'ll Value) -> &'ll Type where Value : ValueTrait { unsafe { - llvm::LLVMTypeOf(v) + llvm::LLVMTypeOf(v.to_llvm()) } } @@ -123,21 +124,21 @@ pub fn C_null(t: &'ll Type) -> &'ll Value { } } -pub fn C_undef(t: &'ll Type) -> &'ll Value { +pub fn C_undef(t: &'ll Type) -> &'ll Value where Value : ValueTrait { unsafe { - llvm::LLVMGetUndef(t) + Value::of_llvm(llvm::LLVMGetUndef(t)) } } -pub fn C_int(t: &'ll Type, i: i64) -> &'ll Value { +pub fn C_int(t: &'ll Type, i: i64) -> &'ll Value where Value : ValueTrait { unsafe { - llvm::LLVMConstInt(t, i as u64, True) + Value::of_llvm(llvm::LLVMConstInt(t, i as u64, True)) } } -pub fn C_uint(t: &'ll Type, i: u64) -> &'ll Value { +pub fn C_uint(t: &'ll Type, i: u64) -> &'ll Value where Value : ValueTrait { unsafe { - llvm::LLVMConstInt(t, i, False) + Value::of_llvm(llvm::LLVMConstInt(t, i, False)) } } @@ -148,11 +149,17 @@ pub fn C_uint_big(t: &'ll Type, u: u128) -> &'ll Value { } } -pub fn C_bool(cx: &CodegenCx<'ll, '_>, val: bool) -> &'ll Value { +pub fn C_bool( + cx: &CodegenCx<'ll, '_, &'ll Value>, + val: bool +) -> &'ll Value where Value : ValueTrait { C_uint(Type::i1(cx), val as u64) } -pub fn C_i32(cx: &CodegenCx<'ll, '_>, i: i32) -> &'ll Value { +pub fn C_i32( + cx: &CodegenCx<'ll, '_, &'ll Value>, + i: i32 +) -> &'ll Value where Value : ValueTrait { C_int(Type::i32(cx), i as i64) } @@ -164,7 +171,10 @@ pub fn C_u64(cx: &CodegenCx<'ll, '_>, i: u64) -> &'ll Value { C_uint(Type::i64(cx), i) } -pub fn C_usize(cx: &CodegenCx<'ll, '_>, i: u64) -> &'ll Value { +pub fn C_usize( + cx: &CodegenCx<'ll, '_, &'ll Value>, + i: u64 +) -> &'ll Value where Value : ValueTrait { let bit_size = cx.data_layout().pointer_size.bits(); if bit_size < 64 { // make sure it doesn't overflow diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 4c405150532..ed9a9e3209b 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -18,7 +18,7 @@ use base; use declare; use monomorphize::Instance; -use value::Value; +use value::{Value, ValueTrait}; use monomorphize::partitioning::CodegenUnit; use type_::Type; @@ -283,7 +283,7 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> { None }; - let isize_ty = Type::ix_llcx(llcx, tcx.data_layout.pointer_size.bits()); + let isize_ty = Type::ix_llcx::(llcx, tcx.data_layout.pointer_size.bits()); CodegenCx { tcx, @@ -315,7 +315,7 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> { } } -impl<'b, 'tcx> CodegenCx<'b, 'tcx> { +impl<'b, 'tcx, Value : ?Sized> CodegenCx<'b, 'tcx, &'b Value> where Value : ValueTrait { pub fn sess<'a>(&'a self) -> &'a Session { &self.tcx.sess } @@ -327,7 +327,9 @@ pub fn get_intrinsic(&self, key: &str) -> &'b Value { declare_intrinsic(self, key).unwrap_or_else(|| bug!("unknown intrinsic '{}'", key)) } +} +impl<'b, 'tcx> CodegenCx<'b, 'tcx, &'b Value> { /// Generate a new symbol name with the given prefix. This symbol name must /// only be used for definitions with `internal` or `private` linkage. pub fn generate_local_symbol_name(&self, prefix: &str) -> String { @@ -377,7 +379,7 @@ pub fn eh_personality(&self) -> &'b Value { } 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) } }; @@ -478,28 +480,31 @@ fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyLayout { } /// Declare any llvm intrinsics that you might need -fn declare_intrinsic(cx: &CodegenCx<'ll, '_>, key: &str) -> Option<&'ll Value> { +fn declare_intrinsic( + cx: &CodegenCx<'ll, '_, &'ll Value>, + key: &str +) -> Option<&'ll Value> where Value : ValueTrait { macro_rules! ifn { ($name:expr, fn() -> $ret:expr) => ( if key == $name { - let f = declare::declare_cfn(cx, $name, Type::func(&[], $ret)); - llvm::SetUnnamedAddr(f, false); + let f = declare::declare_cfn(cx, $name, Type::func::(&[], $ret)); + llvm::SetUnnamedAddr(f.to_llvm(), false); cx.intrinsics.borrow_mut().insert($name, f.clone()); return Some(f); } ); ($name:expr, fn(...) -> $ret:expr) => ( if key == $name { - let f = declare::declare_cfn(cx, $name, Type::variadic_func(&[], $ret)); - llvm::SetUnnamedAddr(f, false); + let f = declare::declare_cfn(cx, $name, Type::variadic_func::(&[], $ret)); + llvm::SetUnnamedAddr(f.to_llvm(), false); cx.intrinsics.borrow_mut().insert($name, f.clone()); return Some(f); } ); ($name:expr, fn($($arg:expr),*) -> $ret:expr) => ( if key == $name { - let f = declare::declare_cfn(cx, $name, Type::func(&[$($arg),*], $ret)); - llvm::SetUnnamedAddr(f, false); + let f = declare::declare_cfn(cx, $name, Type::func::(&[$($arg),*], $ret)); + llvm::SetUnnamedAddr(f.to_llvm(), false); cx.intrinsics.borrow_mut().insert($name, f.clone()); return Some(f); } @@ -520,14 +525,14 @@ macro_rules! mk_struct { 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.memset.p0i8.i16", fn(i8p, t_i8, t_i16, t_i32, i1) -> void); ifn!("llvm.memset.p0i8.i32", fn(i8p, t_i8, t_i32, t_i32, i1) -> void); diff --git a/src/librustc_codegen_llvm/debuginfo/gdb.rs b/src/librustc_codegen_llvm/debuginfo/gdb.rs index f6faddb894f..9d02738fcbd 100644 --- a/src/librustc_codegen_llvm/debuginfo/gdb.rs +++ b/src/librustc_codegen_llvm/debuginfo/gdb.rs @@ -18,6 +18,7 @@ use rustc::session::config::DebugInfo; use type_::Type; use value::Value; +use traits::BuilderMethods; use syntax::attr; @@ -55,7 +56,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>) 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, diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index 042e72e921e..bce722b4b43 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -45,6 +45,7 @@ use syntax::ast; use syntax::symbol::{Symbol, InternedString}; use rustc::ty::layout::{self, LayoutOf}; +use traits::BuilderMethods; pub mod gdb; mod utils; diff --git a/src/librustc_codegen_llvm/debuginfo/source_loc.rs b/src/librustc_codegen_llvm/debuginfo/source_loc.rs index 60ebcb88816..bd8c165d508 100644 --- a/src/librustc_codegen_llvm/debuginfo/source_loc.rs +++ b/src/librustc_codegen_llvm/debuginfo/source_loc.rs @@ -17,6 +17,7 @@ use llvm; use llvm::debuginfo::DIScope; use builder::Builder; +use traits::BuilderMethods; use libc::c_uint; use syntax_pos::{Span, Pos}; @@ -78,7 +79,10 @@ pub fn new(scope: &'ll DIScope, line: usize, col: usize) -> Self { } } -pub fn set_debug_location(bx: &Builder<'_, 'll, '_>, debug_location: InternalDebugLocation<'ll>) { +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. diff --git a/src/librustc_codegen_llvm/declare.rs b/src/librustc_codegen_llvm/declare.rs index f4aede55ce1..d0680151893 100644 --- a/src/librustc_codegen_llvm/declare.rs +++ b/src/librustc_codegen_llvm/declare.rs @@ -31,7 +31,7 @@ use attributes; use context::CodegenCx; use type_::Type; -use value::Value; +use value::{Value, ValueTrait}; /// Declare a global value. @@ -51,12 +51,12 @@ pub fn declare_global(cx: &CodegenCx<'ll, '_>, name: &str, ty: &'ll Type) -> &'l /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. -fn declare_raw_fn( - cx: &CodegenCx<'ll, '_>, +fn declare_raw_fn( + cx: &CodegenCx<'ll, '_, &'ll Value>, name: &str, callconv: llvm::CallConv, ty: &'ll Type, -) -> &'ll Value { +) -> &'ll Value where Value : ValueTrait { debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty); let namebuf = SmallCStr::new(name); let llfn = unsafe { @@ -105,7 +105,7 @@ fn declare_raw_fn( attributes::non_lazy_bind(cx.sess(), llfn); - llfn + Value::of_llvm(llfn) } @@ -116,7 +116,11 @@ fn declare_raw_fn( /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. -pub fn declare_cfn(cx: &CodegenCx<'ll, '_>, name: &str, fn_type: &'ll Type) -> &'ll Value { +pub fn declare_cfn( + cx: &CodegenCx<'ll, '_, &'ll Value>, + name: &str, + fn_type: &'ll Type +) -> &'ll Value where Value : ValueTrait { declare_raw_fn(cx, name, llvm::CCallConv, fn_type) } @@ -168,7 +172,7 @@ pub fn define_global(cx: &CodegenCx<'ll, '_>, name: &str, ty: &'ll Type) -> Opti /// Declare a private global /// /// Use this function when you intend to define a global without a name. -pub fn define_private_global(cx: &CodegenCx<'ll, '_>, ty: &'ll Type) -> &'ll Value { +pub fn define_private_global(cx: &CodegenCx<'ll, '_, &'ll Value>, ty: &'ll Type) -> &'ll Value { unsafe { llvm::LLVMRustInsertPrivateGlobal(cx.llmod, ty) } diff --git a/src/librustc_codegen_llvm/glue.rs b/src/librustc_codegen_llvm/glue.rs index 842bdf3cb49..9144e3f07a1 100644 --- a/src/librustc_codegen_llvm/glue.rs +++ b/src/librustc_codegen_llvm/glue.rs @@ -21,9 +21,13 @@ use rustc::ty::layout::LayoutOf; use rustc::ty::{self, Ty}; use value::Value; +use traits::BuilderMethods; -pub fn size_and_align_of_dst(bx: &Builder<'_, 'll, 'tcx>, t: Ty<'tcx>, info: Option<&'ll Value>) - -> (&'ll Value, &'ll Value) { +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, info); if bx.cx.type_is_sized(t) { diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 29831473ba2..48afda73d79 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -31,6 +31,8 @@ use builder::Builder; use value::Value; +use traits::BuilderMethods; + use rustc::session::Session; use syntax_pos::Span; @@ -591,7 +593,7 @@ fn ty_to_type(cx: &CodegenCx<'ll, '_>, t: &intrinsics::Type) -> Vec<&'ll Type> { 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() @@ -640,7 +642,10 @@ fn modify_as_needed( } 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 @@ -668,7 +673,7 @@ fn modify_as_needed( intrinsics::IntrinsicDef::Named(name) => { let f = declare::declare_cfn(cx, name, - Type::func(&inputs, outputs)); + Type::func::(&inputs, outputs)); bx.call(f, &llargs, None) } }; @@ -1155,7 +1160,7 @@ macro_rules! require_simd { } // 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())); } @@ -1296,7 +1301,7 @@ fn llvm_vector_ty(cx: &CodegenCx<'ll, '_>, elem_ty: ty::Ty, vec_len: usize, 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 +1384,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty { // 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) }; @@ -1394,8 +1399,11 @@ fn non_ptr(t: ty::Ty) -> ty::Ty { let llvm_intrinsic = format!("llvm.masked.gather.{}.{}", 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)); + Type::func::(&[ + llvm_pointer_vec_ty, + alignment_ty, + mask_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 +1484,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty { // 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) }; @@ -1493,7 +1501,7 @@ fn non_ptr(t: ty::Ty) -> ty::Ty { let llvm_intrinsic = format!("llvm.masked.scatter.{}.{}", llvm_elem_vec_str, llvm_pointer_vec_str); let f = declare::declare_cfn(bx.cx, &llvm_intrinsic, - Type::func(&[llvm_elem_vec_ty, + Type::func::(&[llvm_elem_vec_ty, llvm_pointer_vec_ty, alignment_ty, mask_ty], ret_t)); @@ -1628,7 +1636,7 @@ macro_rules! bitwise_red { // 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 d4cd2f786f8..1baab9b0c4d 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -102,6 +102,8 @@ mod back { pub mod wasm; } +mod traits; + mod abi; mod allocator; mod asm; diff --git a/src/librustc_codegen_llvm/meth.rs b/src/librustc_codegen_llvm/meth.rs index 0dc5a4ddde8..70856a99ce7 100644 --- a/src/librustc_codegen_llvm/meth.rs +++ b/src/librustc_codegen_llvm/meth.rs @@ -17,6 +17,8 @@ use type_::Type; use value::Value; +use traits::BuilderMethods; + use rustc::ty::{self, Ty}; use rustc::ty::layout::HasDataLayout; use debuginfo; @@ -48,7 +50,11 @@ pub fn get_fn(self, bx: &Builder<'a, 'll, 'tcx>, ptr } - pub fn get_usize(self, bx: &Builder<'a, 'll, 'tcx>, llvtable: &'ll Value) -> &'ll Value { + pub fn get_usize( + self, + bx: &Builder<'a, 'll, 'tcx, &'ll Value>, + llvtable: &'ll Value + ) -> &'ll Value { // Load the data pointer from the object. debug!("get_int({:?}, {:?})", llvtable, self); diff --git a/src/librustc_codegen_llvm/mir/block.rs b/src/librustc_codegen_llvm/mir/block.rs index aade8864864..5f7f138cb6e 100644 --- a/src/librustc_codegen_llvm/mir/block.rs +++ b/src/librustc_codegen_llvm/mir/block.rs @@ -26,6 +26,8 @@ use type_::Type; use value::Value; +use traits::BuilderMethods; + use syntax::symbol::Symbol; use syntax_pos::Pos; @@ -98,16 +100,17 @@ fn codegen_terminator(&mut self, } }; - 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 - // to a trampoline. - bx.cleanup_ret(cleanup_pad.unwrap(), Some(lltarget)); - } else { - bx.br(lltarget); - } - }; + let funclet_br = + |this: &mut Self, bx: Builder<'_, 'll, '_, &'ll Value>, target: mir::BasicBlock| { + let (lltarget, is_cleanupret) = lltarget(this, target); + if is_cleanupret { + // micro-optimization: generate a `ret` rather than a jump + // to a trampoline. + bx.cleanup_ret(cleanup_pad.unwrap(), Some(lltarget)); + } else { + bx.br(lltarget); + } + }; let do_call = | this: &mut Self, @@ -843,7 +846,10 @@ fn codegen_arguments_untupled(&mut self, } } - fn get_personality_slot(&mut self, bx: &Builder<'a, 'll, 'tcx>) -> PlaceRef<'tcx, &'ll Value> { + fn get_personality_slot( + &mut self, + bx: &Builder<'a, 'll, 'tcx, &'ll Value> + ) -> PlaceRef<'tcx, &'ll Value> { let cx = bx.cx; if let Some(slot) = self.personality_slot { slot diff --git a/src/librustc_codegen_llvm/mir/constant.rs b/src/librustc_codegen_llvm/mir/constant.rs index 2c241d938e5..62fce894cf7 100644 --- a/src/librustc_codegen_llvm/mir/constant.rs +++ b/src/librustc_codegen_llvm/mir/constant.rs @@ -26,6 +26,7 @@ use syntax::ast::Mutability; use syntax::source_map::Span; use value::Value; +use traits::BuilderMethods; use super::super::callee; use super::FunctionCx; diff --git a/src/librustc_codegen_llvm/mir/mod.rs b/src/librustc_codegen_llvm/mir/mod.rs index 7eda7ea0b7d..526c8f75f49 100644 --- a/src/librustc_codegen_llvm/mir/mod.rs +++ b/src/librustc_codegen_llvm/mir/mod.rs @@ -26,6 +26,7 @@ use abi::{ArgTypeExt, FnType, FnTypeExt, PassMode}; use type_::Type; use value::Value; +use traits::BuilderMethods; use syntax_pos::{DUMMY_SP, NO_EXPANSION, BytePos, Span}; use syntax::symbol::keywords; @@ -119,7 +120,11 @@ pub fn monomorphize(&self, value: &T) -> T ) } - pub fn set_debug_loc(&mut self, bx: &Builder<'_, 'll, '_>, source_info: mir::SourceInfo) { + pub fn set_debug_loc( + &mut self, + bx: &Builder<'_, 'll, '_, &'ll Value>, + source_info: mir::SourceInfo + ) { let (scope, span) = self.debug_loc(source_info); debuginfo::set_source_location(&self.debug_context, bx, scope, span); } diff --git a/src/librustc_codegen_llvm/mir/operand.rs b/src/librustc_codegen_llvm/mir/operand.rs index 32609b06952..e640b72cd44 100644 --- a/src/librustc_codegen_llvm/mir/operand.rs +++ b/src/librustc_codegen_llvm/mir/operand.rs @@ -21,6 +21,8 @@ use type_::Type; use glue; +use traits::BuilderMethods; + use std::fmt; use super::{FunctionCx, LocalRef}; @@ -260,7 +262,11 @@ pub fn store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'tcx, &'ll Value> self.store_with_flags(bx, dest, MemFlags::empty()); } - pub fn volatile_store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'tcx, &'ll Value>) { + pub fn volatile_store( + self, + bx: &Builder<'a, 'll, 'tcx, &'ll Value>, + dest: PlaceRef<'tcx, &'ll Value> + ) { self.store_with_flags(bx, dest, MemFlags::VOLATILE); } @@ -271,14 +277,23 @@ pub fn unaligned_volatile_store( ) { self.store_with_flags(bx, dest, MemFlags::VOLATILE | MemFlags::UNALIGNED); } +} - pub fn nontemporal_store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'tcx, &'ll Value>) { +impl<'a, 'll: 'a, 'tcx: 'll, Value : ?Sized> OperandValue<&'ll Value> where + Value : ValueTrait, + Builder<'a, 'll, 'tcx, &'ll Value>: BuilderMethods<'a, 'll, 'tcx, Value> +{ + pub fn nontemporal_store( + self, + bx: &Builder<'a, 'll, 'tcx, &'ll Value>, + dest: PlaceRef<'tcx, &'ll Value> + ) { self.store_with_flags(bx, dest, MemFlags::NONTEMPORAL); } - fn store_with_flags( + fn store_with_flags>( self, - bx: &Builder<'a, 'll, 'tcx>, + bx: &Builder, dest: PlaceRef<'tcx, &'ll Value>, flags: MemFlags, ) { @@ -309,11 +324,13 @@ fn store_with_flags( } } } +} +impl OperandValue<&'ll Value> { pub fn store_unsized( self, - bx: &Builder<'a, 'll, 'tcx>, - indirect_dest: PlaceRef<'tcx, &'ll Value>, + bx: &Builder<'a, 'll, 'tcx, &'ll Value>, + indirect_dest: PlaceRef<'tcx, &'ll Value> ) { debug!("OperandRef::store_unsized: operand={:?}, indirect_dest={:?}", self, indirect_dest); let flags = MemFlags::empty(); @@ -334,13 +351,13 @@ pub fn store_unsized( let min_align = Align::from_bits(8, 8).unwrap(); // Allocate an appropriate region on the stack, and copy the value into it - let (llsize, _) = glue::size_and_align_of_dst(&bx, unsized_ty, Some(llextra)); + let (llsize, _) = glue::size_and_align_of_dst(bx, unsized_ty, Some(llextra)); let lldst = bx.array_alloca(Type::i8(bx.cx), llsize, "unsized_tmp", max_align); - base::call_memcpy(&bx, lldst, max_align, llptr, min_align, llsize, flags); + base::call_memcpy(bx, lldst, max_align, llptr, min_align, llsize, flags); // Store the allocated region and the extra to the indirect place. let indirect_operand = OperandValue::Pair(lldst, llextra); - indirect_operand.store(&bx, indirect_dest); + indirect_operand.store(bx, indirect_dest); } } diff --git a/src/librustc_codegen_llvm/mir/place.rs b/src/librustc_codegen_llvm/mir/place.rs index 4dc9eeb5a9f..b9bd0749965 100644 --- a/src/librustc_codegen_llvm/mir/place.rs +++ b/src/librustc_codegen_llvm/mir/place.rs @@ -23,6 +23,8 @@ use glue; use mir::constant::const_alloc_to_llvm; +use traits::BuilderMethods; + use super::{FunctionCx, LocalRef}; use super::operand::{OperandRef, OperandValue}; @@ -280,7 +282,11 @@ pub fn project_field( } /// Obtain the actual discriminant of a value. - pub fn codegen_get_discr(self, bx: &Builder<'a, 'll, 'tcx>, cast_to: Ty<'tcx>) -> &'ll Value { + pub fn codegen_get_discr( + self, + bx: &Builder<'a, 'll, 'tcx, &'ll Value>, + cast_to: Ty<'tcx> + ) -> &'ll Value { let cast_to = bx.cx.layout_of(cast_to).immediate_llvm_type(bx.cx); if self.layout.abi.is_uninhabited() { return C_undef(cast_to); diff --git a/src/librustc_codegen_llvm/mir/rvalue.rs b/src/librustc_codegen_llvm/mir/rvalue.rs index af166fe501e..017b13410cd 100644 --- a/src/librustc_codegen_llvm/mir/rvalue.rs +++ b/src/librustc_codegen_llvm/mir/rvalue.rs @@ -28,6 +28,8 @@ use type_of::LayoutLlvmExt; use value::Value; +use traits::BuilderMethods; + use super::{FunctionCx, LocalRef}; use super::operand::{OperandRef, OperandValue}; use super::place::PlaceRef; @@ -178,12 +180,12 @@ pub fn codegen_rvalue(&mut self, } } - pub fn codegen_rvalue_unsized( - &mut self, - bx: Builder<'a, 'll, 'tcx>, - indirect_dest: PlaceRef<'tcx, &'ll Value>, - rvalue: &mir::Rvalue<'tcx>, - ) -> Builder<'a, 'll, 'tcx> { + pub fn codegen_rvalue_unsized(&mut self, + bx: Builder<'a, 'll, 'tcx, &'ll Value>, + indirect_dest: PlaceRef<'tcx, &'ll Value>, + rvalue: &mir::Rvalue<'tcx>) + -> Builder<'a, 'll, 'tcx, &'ll Value> + { debug!("codegen_rvalue_unsized(indirect_dest.llval={:?}, rvalue={:?})", indirect_dest.llval, rvalue); @@ -198,11 +200,11 @@ pub fn codegen_rvalue_unsized( } } - pub fn codegen_rvalue_operand(&mut self, - bx: Builder<'a, 'll, 'tcx>, - rvalue: &mir::Rvalue<'tcx>) - -> (Builder<'a, 'll, 'tcx>, OperandRef<'tcx, &'ll Value>) - { + pub fn codegen_rvalue_operand( + &mut self, + bx: Builder<'a, 'll, 'tcx, &'ll Value>, + rvalue: &mir::Rvalue<'tcx> + ) -> (Builder<'a, 'll, 'tcx, &'ll Value>, OperandRef<'tcx, &'ll Value>) { assert!(self.rvalue_creates_operand(rvalue), "cannot codegen {:?} to operand", rvalue); match *rvalue { @@ -750,7 +752,11 @@ enum OverflowOp { Add, Sub, Mul } -fn get_overflow_intrinsic(oop: OverflowOp, bx: &Builder<'_, 'll, '_>, ty: Ty) -> &'ll Value { +fn get_overflow_intrinsic( + oop: OverflowOp, + bx: &Builder<'_, 'll, '_, &'ll Value>, + ty: Ty +) -> &'ll Value { use syntax::ast::IntTy::*; use syntax::ast::UintTy::*; use rustc::ty::{Int, Uint}; diff --git a/src/librustc_codegen_llvm/mir/statement.rs b/src/librustc_codegen_llvm/mir/statement.rs index 8fa5a8cc551..a3aea7b9180 100644 --- a/src/librustc_codegen_llvm/mir/statement.rs +++ b/src/librustc_codegen_llvm/mir/statement.rs @@ -12,6 +12,7 @@ use asm; use builder::Builder; +use traits::BuilderMethods; use super::FunctionCx; use super::LocalRef; diff --git a/src/librustc_codegen_llvm/traits.rs b/src/librustc_codegen_llvm/traits.rs new file mode 100644 index 00000000000..2a6dbe9944d --- /dev/null +++ b/src/librustc_codegen_llvm/traits.rs @@ -0,0 +1,283 @@ +// Copyright 2018 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. + +use llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect}; +use llvm::{IntPredicate, RealPredicate, OperandBundleDef}; +use llvm::{self, BasicBlock}; +use common::*; +use type_::Type; +use libc::c_char; +use rustc::ty::TyCtxt; +use rustc::ty::layout::{Align, Size}; +use rustc::session::Session; +use builder::MemFlags; + +use std::borrow::Cow; +use std::ops::Range; + + +pub trait BuilderMethods<'a, 'll :'a, 'tcx: 'll, Value : ?Sized> { + fn new_block<'b>( + cx: &'a CodegenCx<'ll, 'tcx, &'ll Value>, + llfn: &'ll Value, + name: &'b str + ) -> Self; + fn with_cx(cx: &'a CodegenCx<'ll, 'tcx, &'ll Value>) -> Self; + fn build_sibling_block<'b>(&self, name: &'b str) -> Self; + fn sess(&self) -> &Session; + fn cx(&self) -> &'a CodegenCx<'ll, 'tcx, &'ll Value>; + fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx>; + fn llfn(&self) -> &'ll Value; + fn llbb(&self) -> &'ll BasicBlock; + fn count_insn(&self, category: &str); + + fn set_value_name(&self, value: &'ll Value, name: &str); + fn position_at_end(&self, llbb: &'ll BasicBlock); + fn position_at_start(&self, llbb: &'ll BasicBlock); + fn ret_void(&self); + fn ret(&self, v: &'ll Value); + fn br(&self, dest: &'ll BasicBlock); + fn cond_br( + &self, + cond: &'ll Value, + then_llbb: &'ll BasicBlock, + else_llbb: &'ll BasicBlock, + ); + fn switch( + &self, + v: &'ll Value, + else_llbb: &'ll BasicBlock, + num_cases: usize, + ) -> &'ll Value; + fn invoke( + &self, + llfn: &'ll Value, + args: &[&'ll Value], + then: &'ll BasicBlock, + catch: &'ll BasicBlock, + bundle: Option<&OperandBundleDef<'ll>> + ) -> &'ll Value; + fn unreachable(&self); + fn add(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn fadd(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn fadd_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn sub(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn fsub(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn fsub_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn mul(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn fmul(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn fmul_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn udiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn exactudiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn sdiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn exactsdiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn fdiv(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn fdiv_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn urem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn srem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn frem(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn frem_fast(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn shl(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn lshr(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn ashr(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn and(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn or(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn xor(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn neg(&self, v: &'ll Value) -> &'ll Value; + fn fneg(&self, v: &'ll Value) -> &'ll Value; + fn not(&self, v: &'ll Value) -> &'ll Value; + + fn alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value; + fn dynamic_alloca(&self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value; + fn array_alloca( + &self, + ty: &'ll Type, + len: &'ll Value, + name: &str, + align: Align + ) -> &'ll Value; + + fn load(&self, ptr: &'ll Value, align: Align) -> &'ll Value; + fn volatile_load(&self, ptr: &'ll Value) -> &'ll Value; + fn atomic_load(&self, ptr: &'ll Value, order: AtomicOrdering, size: Size) -> &'ll Value; + + fn range_metadata(&self, load: &'ll Value, range: Range); + fn nonnull_metadata(&self, load: &'ll Value); + + fn store(&self, val: &'ll Value, ptr: &'ll Value, align: Align) -> &'ll Value; + fn store_with_flags( + &self, + val: &'ll Value, + ptr: &'ll Value, + align: Align, + flags: MemFlags, + ) -> &'ll Value; + fn atomic_store( + &self, + val: &'ll Value, + ptr: &'ll Value, + order: AtomicOrdering, + size: Size + ); + + fn gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value; + fn inbounds_gep(&self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value; + fn struct_gep(&self, ptr: &'ll Value, idx: u64) -> &'ll Value; + + fn trunc(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value; + fn sext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value; + fn fptoui(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value; + fn fptosi(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value; + fn uitofp(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value; + fn sitofp(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value; + fn fptrunc(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value; + fn fpext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value; + fn ptrtoint(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value; + fn inttoptr(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value; + fn bitcast(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value; + fn intcast(&self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value; + fn pointercast(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value; + + fn icmp(&self, op: IntPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn fcmp(&self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + + fn empty_phi(&self, ty: &'ll Type) -> &'ll Value; + fn phi(&self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value; + fn inline_asm_call( + &self, + asm: *const c_char, + cons: *const c_char, + inputs: &[&'ll Value], + output: &'ll Type, + volatile: bool, + alignstack: bool, + dia: AsmDialect + ) -> Option<&'ll Value>; + + + fn memcpy(&self, dst: &'ll Value, dst_align: u64, + src: &'ll Value, src_align: u64, + size: &'ll Value, is_volatile: bool) -> &'ll Value; + fn memmove(&self, dst: &'ll Value, dst_align: u64, + src: &'ll Value, src_align: u64, + size: &'ll Value, is_volatile: bool) -> &'ll Value; + + fn minnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn maxnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value; + fn select( + &self, cond: &'ll Value, + then_val: &'ll Value, + else_val: &'ll Value, + ) -> &'ll Value; + + fn va_arg(&self, list: &'ll Value, ty: &'ll Type) -> &'ll Value; + fn extract_element(&self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value; + fn insert_element( + &self, vec: &'ll Value, + elt: &'ll Value, + idx: &'ll Value, + ) -> &'ll Value; + fn shuffle_vector(&self, v1: &'ll Value, v2: &'ll Value, mask: &'ll Value) -> &'ll Value; + fn vector_splat(&self, num_elts: usize, elt: &'ll Value) -> &'ll Value; + fn vector_reduce_fadd_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll Value; + fn vector_reduce_fmul_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll Value; + fn vector_reduce_add(&self, src: &'ll Value) -> &'ll Value; + fn vector_reduce_mul(&self, src: &'ll Value) -> &'ll Value; + fn vector_reduce_and(&self, src: &'ll Value) -> &'ll Value; + fn vector_reduce_or(&self, src: &'ll Value) -> &'ll Value; + fn vector_reduce_xor(&self, src: &'ll Value) -> &'ll Value; + fn vector_reduce_fmin(&self, src: &'ll Value) -> &'ll Value; + fn vector_reduce_fmax(&self, src: &'ll Value) -> &'ll Value; + fn vector_reduce_fmin_fast(&self, src: &'ll Value) -> &'ll Value; + fn vector_reduce_fmax_fast(&self, src: &'ll Value) -> &'ll Value; + fn vector_reduce_min(&self, src: &'ll Value, is_signed: bool) -> &'ll Value; + fn vector_reduce_max(&self, src: &'ll Value, is_signed: bool) -> &'ll Value; + fn extract_value(&self, agg_val: &'ll Value, idx: u64) -> &'ll Value; + fn insert_value( + &self, + agg_val: &'ll Value, + elt: &'ll Value, + idx: u64 + ) -> &'ll Value; + + fn landing_pad( + &self, + ty: &'ll Type, + pers_fn: &'ll Value, + num_clauses: usize + ) -> &'ll Value; + fn add_clause(&self, landing_pad: &'ll Value, clause: &'ll Value); + fn set_cleanup(&self, landing_pad: &'ll Value); + fn resume(&self, exn: &'ll Value) -> &'ll Value; + fn cleanup_pad( + &self, + parent: Option<&'ll Value>, + args: &[&'ll Value] + ) -> &'ll Value; + fn cleanup_ret( + &self, cleanup: &'ll Value, + unwind: Option<&'ll BasicBlock>, + ) -> &'ll Value; + fn catch_pad( + &self, + parent: &'ll Value, + args: &[&'ll Value] + ) -> &'ll Value; + fn catch_ret(&self, pad: &'ll Value, unwind: &'ll BasicBlock) -> &'ll Value; + fn catch_switch( + &self, + parent: Option<&'ll Value>, + unwind: Option<&'ll BasicBlock>, + num_handlers: usize, + ) -> &'ll Value; + fn add_handler(&self, catch_switch: &'ll Value, handler: &'ll BasicBlock); + fn set_personality_fn(&self, personality: &'ll Value); + + fn atomic_cmpxchg( + &self, + dst: &'ll Value, + cmp: &'ll Value, + src: &'ll Value, + order: AtomicOrdering, + failure_order: AtomicOrdering, + weak: llvm::Bool, + ) -> &'ll Value; + fn atomic_rmw( + &self, + op: AtomicRmwBinOp, + dst: &'ll Value, + src: &'ll Value, + order: AtomicOrdering, + ) -> &'ll Value; + fn atomic_fence(&self, order: AtomicOrdering, scope: SynchronizationScope); + fn add_case(&self, s: &'ll Value, on_val: &'ll Value, dest: &'ll BasicBlock); + fn add_incoming_to_phi(&self, phi: &'ll Value, val: &'ll Value, bb: &'ll BasicBlock); + fn set_invariant_load(&self, load: &'ll Value); + + fn check_store( + &self, + val: &'ll Value, + ptr: &'ll Value + ) -> &'ll Value; + fn check_call<'b>( + &self, + typ: &str, + llfn: &'ll Value, + args: &'b [&'ll Value] + ) -> Cow<'b, [&'ll Value]>; + fn lifetime_start(&self, ptr: &'ll Value, size: Size); + fn lifetime_end(&self, ptr: &'ll Value, size: Size); + + fn call_lifetime_intrinsic(&self, intrinsic: &str, ptr: &'ll Value, size: Size); + + fn call(&self, llfn: &'ll Value, args: &[&'ll Value], + bundle: Option<&OperandBundleDef<'ll>>) -> &'ll Value; + fn zext(&self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value; +} diff --git a/src/librustc_codegen_llvm/type_.rs b/src/librustc_codegen_llvm/type_.rs index 6fb78fe4aa5..44162ef0a50 100644 --- a/src/librustc_codegen_llvm/type_.rs +++ b/src/librustc_codegen_llvm/type_.rs @@ -16,6 +16,7 @@ use llvm::{Bool, False, True, TypeKind}; use context::CodegenCx; +use value::{Value, ValueTrait}; use syntax::ast; use rustc::ty::layout::{self, Align, Size}; @@ -40,107 +41,143 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { } impl Type { - pub fn void(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + pub fn void( + cx: &CodegenCx<'ll, '_, &'ll Value> + ) -> &'ll Type where Value : ValueTrait { unsafe { llvm::LLVMVoidTypeInContext(cx.llcx) } } - pub fn metadata(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + pub fn metadata( + cx: &CodegenCx<'ll, '_, &'ll Value> + ) -> &'ll Type where Value : ValueTrait { unsafe { llvm::LLVMRustMetadataTypeInContext(cx.llcx) } } - pub fn i1(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + pub fn i1( + cx: &CodegenCx<'ll, '_, &'ll Value> + ) -> &'ll Type where Value : ValueTrait { unsafe { llvm::LLVMInt1TypeInContext(cx.llcx) } } - pub fn i8(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + pub fn i8( + cx: &CodegenCx<'ll, '_, &'ll Value> + ) -> &'ll Type where Value : ValueTrait { unsafe { llvm::LLVMInt8TypeInContext(cx.llcx) } } - pub fn i8_llcx(llcx: &llvm::Context) -> &Type { + pub fn i8_llcx(llcx: &llvm::Context) -> &Type where Value : ValueTrait { unsafe { llvm::LLVMInt8TypeInContext(llcx) } } - pub fn i16(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + pub fn i16( + cx: &CodegenCx<'ll, '_, &'ll Value>) -> &'ll Type where Value : ValueTrait { unsafe { + llvm::LLVMInt16TypeInContext(cx.llcx) } } - pub fn i32(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + pub fn i32( + cx: &CodegenCx<'ll, '_, &'ll Value> + ) -> &'ll Type where Value : ValueTrait { unsafe { llvm::LLVMInt32TypeInContext(cx.llcx) } } - pub fn i64(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + pub fn i64( + cx: &CodegenCx<'ll, '_, &'ll Value> + ) -> &'ll Type where Value : ValueTrait { unsafe { llvm::LLVMInt64TypeInContext(cx.llcx) } } - pub fn i128(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + pub fn i128( + cx: &CodegenCx<'ll, '_, &'ll Value> + ) -> &'ll Type where Value : ValueTrait { unsafe { 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 { + pub fn ix( + cx: &CodegenCx<'ll, '_, &'ll Value>, + num_bits: u64 + ) -> &'ll Type where Value : ValueTrait { 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_llcx(llcx: &llvm::Context, num_bits: u64) -> &Type { + pub fn ix_llcx( + llcx: &llvm::Context, + num_bits: u64 + ) -> &Type where Value : ValueTrait { unsafe { llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint) } } - pub fn f32(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + pub fn f32( + cx: &CodegenCx<'ll, '_, &'ll Value> + ) -> &'ll Type where Value : ValueTrait { unsafe { llvm::LLVMFloatTypeInContext(cx.llcx) } } - pub fn f64(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + pub fn f64( + cx: &CodegenCx<'ll, '_, &'ll Value> + ) -> &'ll Type where Value : ValueTrait { unsafe { llvm::LLVMDoubleTypeInContext(cx.llcx) } } - pub fn bool(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + pub fn bool( + cx: &CodegenCx<'ll, '_, &'ll Value> + ) -> &'ll Type where Value : ValueTrait { Type::i8(cx) } - pub fn char(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + pub fn char( + cx: &CodegenCx<'ll, '_, &'ll Value> + ) -> &'ll Type where Value : ValueTrait { Type::i32(cx) } - pub fn i8p(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + pub fn i8p( + cx: &CodegenCx<'ll, '_, &'ll Value> + ) -> &'ll Type where Value : ValueTrait { Type::i8(cx).ptr_to() } - pub fn i8p_llcx(llcx: &llvm::Context) -> &Type { - Type::i8_llcx(llcx).ptr_to() + pub fn i8p_llcx(llcx: &llvm::Context) -> &Type where Value : ValueTrait { + Type::i8_llcx::(llcx).ptr_to() } - pub fn isize(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + pub fn isize( + cx: &CodegenCx<'ll, '_, &'ll Value> + ) -> &'ll Type where Value : ValueTrait { cx.isize_ty } - pub fn c_int(cx: &CodegenCx<'ll, '_>) -> &'ll Type { + pub fn c_int( + cx: &CodegenCx<'ll, '_, &'ll Value> + ) -> &'ll Type where Value : ValueTrait { match &cx.tcx.sess.target.target.target_c_int_width[..] { "16" => Type::i16(cx), "32" => Type::i32(cx), @@ -149,7 +186,10 @@ pub fn c_int(cx: &CodegenCx<'ll, '_>) -> &'ll Type { } } - pub fn int_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::IntTy) -> &'ll Type { + pub fn int_from_ty( + cx: &CodegenCx<'ll, '_, &'ll Value>, + t: ast::IntTy + ) -> &'ll Type where Value : ValueTrait { match t { ast::IntTy::Isize => cx.isize_ty, ast::IntTy::I8 => Type::i8(cx), @@ -160,7 +200,10 @@ pub fn int_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::IntTy) -> &'ll Type { } } - pub fn uint_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::UintTy) -> &'ll Type { + pub fn uint_from_ty( + cx: &CodegenCx<'ll, '_, &'ll Value>, + t: ast::UintTy + ) -> &'ll Type where Value : ValueTrait { match t { ast::UintTy::Usize => cx.isize_ty, ast::UintTy::U8 => Type::i8(cx), @@ -171,28 +214,41 @@ pub fn uint_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::UintTy) -> &'ll Type { } } - pub fn float_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::FloatTy) -> &'ll Type { + pub fn float_from_ty( + cx: &CodegenCx<'ll, '_, &'ll Value>, + t: ast::FloatTy + ) -> &'ll Type where Value : ValueTrait { match t { ast::FloatTy::F32 => Type::f32(cx), ast::FloatTy::F64 => Type::f64(cx), } } - pub fn func(args: &[&'ll Type], ret: &'ll Type) -> &'ll Type { + pub fn func( + args: &[&'ll Type], + ret: &'ll Type + ) -> &'ll Type where Value : ValueTrait { unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, False) } } - pub fn variadic_func(args: &[&'ll Type], ret: &'ll Type) -> &'ll Type { + pub fn variadic_func( + args: &[&'ll Type], + ret: &'ll Type + ) -> &'ll Type where Value : ValueTrait { unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, True) } } - pub fn struct_(cx: &CodegenCx<'ll, '_>, els: &[&'ll Type], packed: bool) -> &'ll Type { + pub fn struct_( + cx: &CodegenCx<'ll, '_, &'ll Value>, + els: &[&'ll Type], + packed: bool + ) -> &'ll Type where Value : ValueTrait { unsafe { llvm::LLVMStructTypeInContext(cx.llcx, els.as_ptr(), els.len() as c_uint, @@ -208,13 +264,13 @@ pub fn named_struct(cx: &CodegenCx<'ll, '_>, name: &str) -> &'ll Type { } - pub fn array(ty: &Type, len: u64) -> &Type { + pub fn array(ty: &Type, len: u64) -> &Type where Value : ValueTrait { unsafe { llvm::LLVMRustArrayType(ty, len) } } - pub fn vector(ty: &Type, len: u64) -> &Type { + pub fn vector(ty: &Type, len: u64) -> &Type where Value : ValueTrait { unsafe { llvm::LLVMVectorType(ty, len as c_uint) } @@ -307,7 +363,7 @@ pub fn padding_filler(cx: &CodegenCx<'ll, '_>, size: Size, align: Align) -> &'ll 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<'ll, '_>) -> &'ll Type { diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index fea02edf7be..07a0878c7a7 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -16,6 +16,7 @@ use rustc_target::abi::FloatTy; use rustc_mir::monomorphize::item::DefPathBasedNames; use type_::Type; +use value::Value; use std::fmt::Write; @@ -40,7 +41,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(..) => { @@ -93,7 +94,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 { diff --git a/src/librustc_codegen_llvm/value.rs b/src/librustc_codegen_llvm/value.rs index 357cc8fbf80..1b789f67b57 100644 --- a/src/librustc_codegen_llvm/value.rs +++ b/src/librustc_codegen_llvm/value.rs @@ -15,7 +15,10 @@ use std::fmt; use std::hash::{Hash, Hasher}; -pub trait ValueTrait: fmt::Debug {} +pub trait ValueTrait: fmt::Debug { + fn to_llvm(&self) -> &llvm::Value; + fn of_llvm(&llvm::Value) -> &Self; +} impl PartialEq for Value { fn eq(&self, other: &Self) -> bool { @@ -23,7 +26,14 @@ fn eq(&self, other: &Self) -> bool { } } -impl ValueTrait for Value {} +impl ValueTrait for Value { + fn to_llvm(&self) -> &llvm::Value { + &self + } + fn of_llvm(v: &llvm::Value) -> &Self { + &v + } +} impl Eq for Value {} -- 2.44.0