Skip to content

rustc_codegen_llvm: begin generalizing over backend values. #52987

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions src/librustc_codegen_llvm/abi.rs
Original file line number Diff line number Diff line change
@@ -167,8 +167,13 @@ impl LlvmType for CastTarget {

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>);
fn store(&self, bx: &Builder<'_, 'll, 'tcx>, val: &'ll Value, dst: PlaceRef<'tcx, &'ll Value>);
fn store_fn_arg(
&self,
bx: &Builder<'_, 'll, 'tcx>,
idx: &mut usize,
dst: PlaceRef<'tcx, &'ll Value>,
);
}

impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
@@ -182,7 +187,7 @@ impl ArgTypeExt<'ll, '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<'_, 'll, 'tcx>, val: &'ll Value, dst: PlaceRef<'ll, 'tcx>) {
fn store(&self, bx: &Builder<'_, 'll, 'tcx>, val: &'ll Value, dst: PlaceRef<'tcx, &'ll Value>) {
if self.is_ignore() {
return;
}
@@ -235,7 +240,12 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
}
}

fn store_fn_arg(&self, bx: &Builder<'a, 'll, 'tcx>, idx: &mut usize, dst: PlaceRef<'ll, 'tcx>) {
fn store_fn_arg(
&self,
bx: &Builder<'a, 'll, 'tcx>,
idx: &mut usize,
dst: PlaceRef<'tcx, &'ll Value>,
) {
let mut next = || {
let val = llvm::get_param(bx.llfn(), *idx as c_uint);
*idx += 1;
2 changes: 1 addition & 1 deletion src/librustc_codegen_llvm/asm.rs
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@ use libc::{c_uint, c_char};
pub fn codegen_inline_asm(
bx: &Builder<'a, 'll, 'tcx>,
ia: &hir::InlineAsm,
outputs: Vec<PlaceRef<'ll, 'tcx>>,
outputs: Vec<PlaceRef<'tcx, &'ll Value>>,
mut inputs: Vec<&'ll Value>
) {
let mut ext_constraints = vec![];
4 changes: 2 additions & 2 deletions src/librustc_codegen_llvm/base.rs
Original file line number Diff line number Diff line change
@@ -275,8 +275,8 @@ pub fn unsize_thin_ptr(
/// to a value of type `dst_ty` and store the result in `dst`
pub fn coerce_unsized_into(
bx: &Builder<'a, 'll, 'tcx>,
src: PlaceRef<'ll, 'tcx>,
dst: PlaceRef<'ll, 'tcx>
src: PlaceRef<'tcx, &'ll Value>,
dst: PlaceRef<'tcx, &'ll Value>
) {
let src_ty = src.layout.ty;
let dst_ty = dst.layout.ty;
8 changes: 4 additions & 4 deletions src/librustc_codegen_llvm/intrinsic.rs
Original file line number Diff line number Diff line change
@@ -89,7 +89,7 @@ pub fn codegen_intrinsic_call(
bx: &Builder<'a, 'll, 'tcx>,
callee_ty: Ty<'tcx>,
fn_ty: &FnType<'tcx, Ty<'tcx>>,
args: &[OperandRef<'ll, 'tcx>],
args: &[OperandRef<'tcx, &'ll Value>],
llresult: &'ll Value,
span: Span,
) {
@@ -592,7 +592,7 @@ pub fn codegen_intrinsic_call(
fn modify_as_needed(
bx: &Builder<'a, 'll, 'tcx>,
t: &intrinsics::Type,
arg: &OperandRef<'ll, 'tcx>,
arg: &OperandRef<'tcx, &'ll Value>,
) -> Vec<&'ll Value> {
match *t {
intrinsics::Type::Aggregate(true, ref contents) => {
@@ -985,7 +985,7 @@ fn generic_simd_intrinsic(
bx: &Builder<'a, 'll, 'tcx>,
name: &str,
callee_ty: Ty<'tcx>,
args: &[OperandRef<'ll, 'tcx>],
args: &[OperandRef<'tcx, &'ll Value>],
ret_ty: Ty<'tcx>,
llret_ty: &'ll Type,
span: Span
@@ -1166,7 +1166,7 @@ fn generic_simd_intrinsic(
in_len: usize,
bx: &Builder<'a, 'll, 'tcx>,
span: Span,
args: &[OperandRef<'ll, 'tcx>],
args: &[OperandRef<'tcx, &'ll Value>],
) -> Result<&'ll Value, ()> {
macro_rules! emit_error {
($msg: tt) => {
18 changes: 9 additions & 9 deletions src/librustc_codegen_llvm/mir/block.rs
Original file line number Diff line number Diff line change
@@ -115,7 +115,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
fn_ty: FnType<'tcx, Ty<'tcx>>,
fn_ptr: &'ll Value,
llargs: &[&'ll Value],
destination: Option<(ReturnDest<'ll, 'tcx>, mir::BasicBlock)>,
destination: Option<(ReturnDest<'tcx, &'ll Value>, mir::BasicBlock)>,
cleanup: Option<mir::BasicBlock>
| {
if let Some(cleanup) = cleanup {
@@ -636,7 +636,7 @@ impl FunctionCx<'a, 'll, 'tcx> {

fn codegen_argument(&mut self,
bx: &Builder<'a, 'll, 'tcx>,
op: OperandRef<'ll, 'tcx>,
op: OperandRef<'tcx, &'ll Value>,
llargs: &mut Vec<&'ll Value>,
arg: &ArgType<'tcx, Ty<'tcx>>) {
// Fill padding with undef value, where applicable.
@@ -736,7 +736,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
}
}

fn get_personality_slot(&mut self, bx: &Builder<'a, 'll, 'tcx>) -> PlaceRef<'ll, 'tcx> {
fn get_personality_slot(&mut self, bx: &Builder<'a, 'll, 'tcx>) -> PlaceRef<'tcx, &'ll Value> {
let cx = bx.cx;
if let Some(slot) = self.personality_slot {
slot
@@ -812,7 +812,7 @@ impl FunctionCx<'a, 'll, '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<&'ll Value>, is_intrinsic: bool)
-> ReturnDest<'ll, 'tcx> {
-> ReturnDest<'tcx, &'ll Value> {
// If the return is ignored, we can just return a do-nothing ReturnDest
if fn_ret.is_ignore() {
return ReturnDest::Nothing;
@@ -894,7 +894,7 @@ impl FunctionCx<'a, 'll, 'tcx> {

fn codegen_transmute_into(&mut self, bx: &Builder<'a, 'll, 'tcx>,
src: &mir::Operand<'tcx>,
dst: PlaceRef<'ll, 'tcx>) {
dst: PlaceRef<'tcx, &'ll Value>) {
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());
@@ -906,7 +906,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
// Stores the return value of a function call into it's final location.
fn store_return(&mut self,
bx: &Builder<'a, 'll, 'tcx>,
dest: ReturnDest<'ll, 'tcx>,
dest: ReturnDest<'tcx, &'ll Value>,
ret_ty: &ArgType<'tcx, Ty<'tcx>>,
llval: &'ll Value) {
use self::ReturnDest::*;
@@ -937,13 +937,13 @@ impl FunctionCx<'a, 'll, 'tcx> {
}
}

enum ReturnDest<'ll, 'tcx> {
enum ReturnDest<'tcx, V> {
// Do nothing, the return value is indirect or ignored
Nothing,
// Store the return value to the pointer
Store(PlaceRef<'ll, 'tcx>),
Store(PlaceRef<'tcx, V>),
// Stores an indirect return value to an operand local place
IndirectOperand(PlaceRef<'ll, 'tcx>, mir::Local),
IndirectOperand(PlaceRef<'tcx, V>, mir::Local),
// Stores a direct return value to an operand local place
DirectOperand(mir::Local)
}
19 changes: 11 additions & 8 deletions src/librustc_codegen_llvm/mir/mod.rs
Original file line number Diff line number Diff line change
@@ -63,7 +63,7 @@ pub struct FunctionCx<'a, 'll: 'a, 'tcx: 'll> {
/// 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<PlaceRef<'ll, 'tcx>>,
personality_slot: Option<PlaceRef<'tcx, &'ll Value>>,

/// A `Block` for each MIR `BasicBlock`
blocks: IndexVec<mir::BasicBlock, &'ll BasicBlock>,
@@ -97,7 +97,7 @@ pub struct FunctionCx<'a, 'll: 'a, 'tcx: 'll> {
///
/// Avoiding allocs can also be important for certain intrinsics,
/// notably `expect`.
locals: IndexVec<mir::Local, LocalRef<'ll, 'tcx>>,
locals: IndexVec<mir::Local, LocalRef<'tcx, &'ll Value>>,

/// Debug information for MIR scopes.
scopes: IndexVec<mir::SourceScope, debuginfo::MirDebugScope<'ll>>,
@@ -178,13 +178,16 @@ impl FunctionCx<'a, 'll, 'tcx> {
}
}

enum LocalRef<'ll, 'tcx> {
Place(PlaceRef<'ll, 'tcx>),
Operand(Option<OperandRef<'ll, 'tcx>>),
enum LocalRef<'tcx, V> {
Place(PlaceRef<'tcx, V>),
Operand(Option<OperandRef<'tcx, V>>),
}

impl LocalRef<'ll, 'tcx> {
fn new_operand(cx: &CodegenCx<'ll, 'tcx>, layout: TyLayout<'tcx>) -> LocalRef<'ll, 'tcx> {
impl LocalRef<'tcx, &'ll Value> {
fn new_operand(
cx: &CodegenCx<'ll, 'tcx>,
layout: TyLayout<'tcx>,
) -> LocalRef<'tcx, &'ll Value> {
if layout.is_zst() {
// Zero-size temporaries aren't always initialized, which
// doesn't matter because they don't contain data, but
@@ -418,7 +421,7 @@ fn arg_local_refs(
fx: &FunctionCx<'a, 'll, 'tcx>,
scopes: &IndexVec<mir::SourceScope, debuginfo::MirDebugScope<'ll>>,
memory_locals: &BitArray<mir::Local>,
) -> Vec<LocalRef<'ll, 'tcx>> {
) -> Vec<LocalRef<'tcx, &'ll Value>> {
let mir = fx.mir;
let tcx = bx.tcx();
let mut idx = 0;
53 changes: 31 additions & 22 deletions src/librustc_codegen_llvm/mir/operand.rs
Original file line number Diff line number Diff line change
@@ -32,14 +32,14 @@ use super::place::PlaceRef;
/// uniquely determined by the value's type, but is kept as a
/// safety check.
#[derive(Copy, Clone, Debug)]
pub enum OperandValue<'ll> {
pub enum OperandValue<V> {
/// A reference to the actual operand. The data is guaranteed
/// to be valid for the operand's lifetime.
Ref(&'ll Value, Align),
Ref(V, Align),
/// A single LLVM value.
Immediate(&'ll Value),
Immediate(V),
/// A pair of immediate LLVM values. Used by fat pointers too.
Pair(&'ll Value, &'ll Value)
Pair(V, V)
}

/// An `OperandRef` is an "SSA" reference to a Rust value, along with
@@ -51,23 +51,23 @@ pub enum OperandValue<'ll> {
/// directly is sure to cause problems -- use `OperandRef::store`
/// instead.
#[derive(Copy, Clone)]
pub struct OperandRef<'ll, 'tcx> {
pub struct OperandRef<'tcx, V> {
// The value.
pub val: OperandValue<'ll>,
pub val: OperandValue<V>,

// The layout of value, based on its Rust type.
pub layout: TyLayout<'tcx>,
}

impl fmt::Debug for OperandRef<'ll, 'tcx> {
impl fmt::Debug for OperandRef<'tcx, &'ll Value> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "OperandRef({:?} @ {:?})", self.val, self.layout)
}
}

impl OperandRef<'ll, 'tcx> {
impl OperandRef<'tcx, &'ll Value> {
pub fn new_zst(cx: &CodegenCx<'ll, 'tcx>,
layout: TyLayout<'tcx>) -> OperandRef<'ll, 'tcx> {
layout: TyLayout<'tcx>) -> OperandRef<'tcx, &'ll Value> {
assert!(layout.is_zst());
OperandRef {
val: OperandValue::Immediate(C_undef(layout.immediate_llvm_type(cx))),
@@ -77,7 +77,7 @@ impl OperandRef<'ll, 'tcx> {

pub fn from_const(bx: &Builder<'a, 'll, 'tcx>,
val: &'tcx ty::Const<'tcx>)
-> Result<OperandRef<'ll, 'tcx>, Lrc<ConstEvalErr<'tcx>>> {
-> Result<OperandRef<'tcx, &'ll Value>, Lrc<ConstEvalErr<'tcx>>> {
let layout = bx.cx.layout_of(val.ty);

if layout.is_zst() {
@@ -138,7 +138,7 @@ impl OperandRef<'ll, 'tcx> {
}
}

pub fn deref(self, cx: &CodegenCx<'ll, 'tcx>) -> PlaceRef<'ll, 'tcx> {
pub fn deref(self, cx: &CodegenCx<'ll, 'tcx>) -> PlaceRef<'tcx, &'ll Value> {
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 {
@@ -176,7 +176,7 @@ impl OperandRef<'ll, 'tcx> {
pub fn from_immediate_or_packed_pair(bx: &Builder<'a, 'll, 'tcx>,
llval: &'ll Value,
layout: TyLayout<'tcx>)
-> OperandRef<'ll, 'tcx> {
-> OperandRef<'tcx, &'ll Value> {
let val = if let layout::Abi::ScalarPair(ref a, ref b) = layout.abi {
debug!("Operand::from_immediate_or_packed_pair: unpacking {:?} @ {:?}",
llval, layout);
@@ -191,7 +191,11 @@ impl OperandRef<'ll, 'tcx> {
OperandRef { val, layout }
}

pub fn extract_field(&self, bx: &Builder<'a, 'll, 'tcx>, i: usize) -> OperandRef<'ll, 'tcx> {
pub fn extract_field(
&self,
bx: &Builder<'a, 'll, 'tcx>,
i: usize,
) -> OperandRef<'tcx, &'ll Value> {
let field = self.layout.field(bx.cx, i);
let offset = self.layout.fields.offset(i);

@@ -249,27 +253,32 @@ impl OperandRef<'ll, 'tcx> {
}
}

impl OperandValue<'ll> {
pub fn store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'ll, 'tcx>) {
impl OperandValue<&'ll Value> {
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<'ll, 'tcx>) {
pub fn volatile_store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'tcx, &'ll Value>) {
self.store_with_flags(bx, dest, MemFlags::VOLATILE);
}

pub fn unaligned_volatile_store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'ll, 'tcx>) {
pub fn unaligned_volatile_store(
self,
bx: &Builder<'a, 'll, 'tcx>,
dest: PlaceRef<'tcx,
&'ll Value>,
) {
self.store_with_flags(bx, dest, MemFlags::VOLATILE | MemFlags::UNALIGNED);
}

pub fn nontemporal_store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'ll, 'tcx>) {
pub fn nontemporal_store(self, bx: &Builder<'a, 'll, 'tcx>, dest: PlaceRef<'tcx, &'ll Value>) {
self.store_with_flags(bx, dest, MemFlags::NONTEMPORAL);
}

fn store_with_flags(
self,
bx: &Builder<'a, 'll, 'tcx>,
dest: PlaceRef<'ll, 'tcx>,
dest: PlaceRef<'tcx, &'ll Value>,
flags: MemFlags,
) {
debug!("OperandRef::store: operand={:?}, dest={:?}", self, dest);
@@ -302,7 +311,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
fn maybe_codegen_consume_direct(&mut self,
bx: &Builder<'a, 'll, 'tcx>,
place: &mir::Place<'tcx>)
-> Option<OperandRef<'ll, 'tcx>>
-> Option<OperandRef<'tcx, &'ll Value>>
{
debug!("maybe_codegen_consume_direct(place={:?})", place);

@@ -350,7 +359,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
pub fn codegen_consume(&mut self,
bx: &Builder<'a, 'll, 'tcx>,
place: &mir::Place<'tcx>)
-> OperandRef<'ll, 'tcx>
-> OperandRef<'tcx, &'ll Value>
{
debug!("codegen_consume(place={:?})", place);

@@ -374,7 +383,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
pub fn codegen_operand(&mut self,
bx: &Builder<'a, 'll, 'tcx>,
operand: &mir::Operand<'tcx>)
-> OperandRef<'ll, 'tcx>
-> OperandRef<'tcx, &'ll Value>
{
debug!("codegen_operand(operand={:?})", operand);

28 changes: 16 additions & 12 deletions src/librustc_codegen_llvm/mir/place.rs
Original file line number Diff line number Diff line change
@@ -28,12 +28,12 @@ use super::{FunctionCx, LocalRef};
use super::operand::{OperandRef, OperandValue};

#[derive(Copy, Clone, Debug)]
pub struct PlaceRef<'ll, 'tcx> {
pub struct PlaceRef<'tcx, V> {
/// Pointer to the contents of the place
pub llval: &'ll Value,
pub llval: V,

/// This place's extra data if it is unsized, or null
pub llextra: Option<&'ll Value>,
pub llextra: Option<V>,

/// Monomorphized type of this place, including variant information
pub layout: TyLayout<'tcx>,
@@ -42,12 +42,12 @@ pub struct PlaceRef<'ll, 'tcx> {
pub align: Align,
}

impl PlaceRef<'ll, 'tcx> {
impl PlaceRef<'tcx, &'ll Value> {
pub fn new_sized(
llval: &'ll Value,
layout: TyLayout<'tcx>,
align: Align,
) -> PlaceRef<'ll, 'tcx> {
) -> PlaceRef<'tcx, &'ll Value> {
PlaceRef {
llval,
llextra: None,
@@ -61,7 +61,7 @@ impl PlaceRef<'ll, 'tcx> {
layout: TyLayout<'tcx>,
alloc: &mir::interpret::Allocation,
offset: Size,
) -> PlaceRef<'ll, 'tcx> {
) -> PlaceRef<'tcx, &'ll Value> {
let init = const_alloc_to_llvm(bx.cx, alloc);
let base_addr = consts::addr_of(bx.cx, init, layout.align, "byte_str");

@@ -75,7 +75,7 @@ impl PlaceRef<'ll, 'tcx> {
}

pub fn alloca(bx: &Builder<'a, 'll, 'tcx>, layout: TyLayout<'tcx>, name: &str)
-> PlaceRef<'ll, 'tcx> {
-> PlaceRef<'tcx, &'ll Value> {
debug!("alloca({:?}: {:?})", name, layout);
let tmp = bx.alloca(layout.llvm_type(bx.cx), name, layout.align);
Self::new_sized(tmp, layout, layout.align)
@@ -94,7 +94,7 @@ impl PlaceRef<'ll, 'tcx> {
}
}

pub fn load(&self, bx: &Builder<'a, 'll, 'tcx>) -> OperandRef<'ll, 'tcx> {
pub fn load(&self, bx: &Builder<'a, 'll, 'tcx>) -> OperandRef<'tcx, &'ll Value> {
debug!("PlaceRef::load: {:?}", self);

assert_eq!(self.llextra, None);
@@ -156,7 +156,11 @@ impl PlaceRef<'ll, 'tcx> {
}

/// Access a field, at a point when the value's case is known.
pub fn project_field(self, bx: &Builder<'a, 'll, 'tcx>, ix: usize) -> PlaceRef<'ll, 'tcx> {
pub fn project_field(
self,
bx: &Builder<'a, 'll, 'tcx>,
ix: usize,
) -> PlaceRef<'tcx, &'ll Value> {
let cx = bx.cx;
let field = self.layout.field(cx, ix);
let offset = self.layout.fields.offset(ix);
@@ -379,7 +383,7 @@ impl PlaceRef<'ll, 'tcx> {
}

pub fn project_index(&self, bx: &Builder<'a, 'll, 'tcx>, llindex: &'ll Value)
-> PlaceRef<'ll, 'tcx> {
-> PlaceRef<'tcx, &'ll Value> {
PlaceRef {
llval: bx.inbounds_gep(self.llval, &[C_usize(bx.cx, 0), llindex]),
llextra: None,
@@ -389,7 +393,7 @@ impl PlaceRef<'ll, 'tcx> {
}

pub fn project_downcast(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: usize)
-> PlaceRef<'ll, 'tcx> {
-> PlaceRef<'tcx, &'ll Value> {
let mut downcast = *self;
downcast.layout = self.layout.for_variant(bx.cx, variant_index);

@@ -413,7 +417,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
pub fn codegen_place(&mut self,
bx: &Builder<'a, 'll, 'tcx>,
place: &mir::Place<'tcx>)
-> PlaceRef<'ll, 'tcx> {
-> PlaceRef<'tcx, &'ll Value> {
debug!("codegen_place(place={:?})", place);

let cx = bx.cx;
6 changes: 3 additions & 3 deletions src/librustc_codegen_llvm/mir/rvalue.rs
Original file line number Diff line number Diff line change
@@ -35,7 +35,7 @@ use super::place::PlaceRef;
impl FunctionCx<'a, 'll, 'tcx> {
pub fn codegen_rvalue(&mut self,
bx: Builder<'a, 'll, 'tcx>,
dest: PlaceRef<'ll, 'tcx>,
dest: PlaceRef<'tcx, &'ll Value>,
rvalue: &mir::Rvalue<'tcx>)
-> Builder<'a, 'll, 'tcx>
{
@@ -178,7 +178,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
pub fn codegen_rvalue_operand(&mut self,
bx: Builder<'a, 'll, 'tcx>,
rvalue: &mir::Rvalue<'tcx>)
-> (Builder<'a, 'll, 'tcx>, OperandRef<'ll, 'tcx>)
-> (Builder<'a, 'll, 'tcx>, OperandRef<'tcx, &'ll Value>)
{
assert!(self.rvalue_creates_operand(rvalue), "cannot codegen {:?} to operand", rvalue);

@@ -652,7 +652,7 @@ impl FunctionCx<'a, 'll, 'tcx> {
op: mir::BinOp,
lhs: &'ll Value,
rhs: &'ll Value,
input_ty: Ty<'tcx>) -> OperandValue<'ll> {
input_ty: Ty<'tcx>) -> OperandValue<&'ll Value> {
// 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),