Auto merge of #96862 - oli-obk:enum_cast_mir, r=RalfJung · rust-lang/rust@53792b9 (original) (raw)
`@@ -12,17 +12,15 @@ use rustc_middle::ty::cast::{CastTy, IntTy};
`
12
12
`use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
`
13
13
`use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt};
`
14
14
`use rustc_span::source_map::{Span, DUMMY_SP};
`
15
``
`-
use rustc_target::abi::{Abi, Int, Variants};
`
16
15
``
17
16
`impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
`
``
17
`+
#[instrument(level = "trace", skip(self, bx))]
`
18
18
`pub fn codegen_rvalue(
`
19
19
`&mut self,
`
20
20
`mut bx: Bx,
`
21
21
`dest: PlaceRef<'tcx, Bx::Value>,
`
22
22
`rvalue: &mir::Rvalue<'tcx>,
`
23
23
`) -> Bx {
`
24
``
`-
debug!("codegen_rvalue(dest.llval={:?}, rvalue={:?})", dest.llval, rvalue);
`
25
``
-
26
24
`match *rvalue {
`
27
25
` mir::Rvalue::Use(ref operand) => {
`
28
26
`let cg_operand = self.codegen_operand(&mut bx, operand);
`
`@@ -285,74 +283,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
`
285
283
`CastTy::from_ty(operand.layout.ty).expect("bad input type for cast");
`
286
284
`let r_t_out = CastTy::from_ty(cast.ty).expect("bad output type for cast");
`
287
285
`let ll_t_in = bx.cx().immediate_backend_type(operand.layout);
`
288
``
`-
match operand.layout.variants {
`
289
``
`-
Variants::Single { index } => {
`
290
``
`-
if let Some(discr) =
`
291
``
`-
operand.layout.ty.discriminant_for_variant(bx.tcx(), index)
`
292
``
`-
{
`
293
``
`-
let discr_layout = bx.cx().layout_of(discr.ty);
`
294
``
`-
let discr_t = bx.cx().immediate_backend_type(discr_layout);
`
295
``
`-
let discr_val = bx.cx().const_uint_big(discr_t, discr.val);
`
296
``
`-
let discr_val =
`
297
``
`-
bx.intcast(discr_val, ll_t_out, discr.ty.is_signed());
`
298
``
-
299
``
`-
return (
`
300
``
`-
bx,
`
301
``
`-
OperandRef {
`
302
``
`-
val: OperandValue::Immediate(discr_val),
`
303
``
`-
layout: cast,
`
304
``
`-
},
`
305
``
`-
);
`
306
``
`-
}
`
307
``
`-
}
`
308
``
`-
Variants::Multiple { .. } => {}
`
309
``
`-
}
`
310
286
`let llval = operand.immediate();
`
311
287
``
312
``
`-
let mut signed = false;
`
313
``
`-
if let Abi::Scalar(scalar) = operand.layout.abi {
`
314
``
`-
if let Int(_, s) = scalar.primitive() {
`
315
``
`` -
// We use i1
for bytes that are always 0
or 1
,
``
316
``
`` -
// e.g., #[repr(i8)] enum E { A, B }
, but we can't
``
317
``
`` -
// let LLVM interpret the i1
as signed, because
``
318
``
`` -
// then i1 1
(i.e., E::B) is effectively i8 -1
.
``
319
``
`-
signed = !scalar.is_bool() && s;
`
320
``
-
321
``
`-
if !scalar.is_always_valid(bx.cx())
`
322
``
`-
&& scalar.valid_range(bx.cx()).end
`
323
``
`-
= scalar.valid_range(bx.cx()).start
`
324
``
`-
{
`
325
``
`` -
// We want table[e as usize ± k]
to not
``
326
``
`-
// have bound checks, and this is the most
`
327
``
`` -
// convenient place to put the assume
s.
``
328
``
`-
if scalar.valid_range(bx.cx()).start > 0 {
`
329
``
`-
let enum_value_lower_bound = bx.cx().const_uint_big(
`
330
``
`-
ll_t_in,
`
331
``
`-
scalar.valid_range(bx.cx()).start,
`
332
``
`-
);
`
333
``
`-
let cmp_start = bx.icmp(
`
334
``
`-
IntPredicate::IntUGE,
`
335
``
`-
llval,
`
336
``
`-
enum_value_lower_bound,
`
337
``
`-
);
`
338
``
`-
bx.assume(cmp_start);
`
339
``
`-
}
`
340
``
-
341
``
`-
let enum_value_upper_bound = bx
`
342
``
`-
.cx()
`
343
``
`-
.const_uint_big(ll_t_in, scalar.valid_range(bx.cx()).end);
`
344
``
`-
let cmp_end = bx.icmp(
`
345
``
`-
IntPredicate::IntULE,
`
346
``
`-
llval,
`
347
``
`-
enum_value_upper_bound,
`
348
``
`-
);
`
349
``
`-
bx.assume(cmp_end);
`
350
``
`-
}
`
351
``
`-
}
`
352
``
`-
}
`
353
``
-
354
288
`let newval = match (r_t_in, r_t_out) {
`
355
``
`-
(CastTy::Int(), CastTy::Int()) => bx.intcast(llval, ll_t_out, signed),
`
``
289
`+
(CastTy::Int(i), CastTy::Int(_)) => {
`
``
290
`+
bx.intcast(llval, ll_t_out, i.is_signed())
`
``
291
`+
}
`
356
292
`(CastTy::Float, CastTy::Float) => {
`
357
293
`let srcsz = bx.cx().float_width(ll_t_in);
`
358
294
`let dstsz = bx.cx().float_width(ll_t_out);
`
`@@ -364,8 +300,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
`
364
300
` llval
`
365
301
`}
`
366
302
`}
`
367
``
`-
(CastTy::Int(_), CastTy::Float) => {
`
368
``
`-
if signed {
`
``
303
`+
(CastTy::Int(i), CastTy::Float) => {
`
``
304
`+
if i.is_signed() {
`
369
305
` bx.sitofp(llval, ll_t_out)
`
370
306
`} else {
`
371
307
` bx.uitofp(llval, ll_t_out)
`
`@@ -374,8 +310,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
`
374
310
`(CastTy::Ptr() | CastTy::FnPtr, CastTy::Ptr()) => {
`
375
311
` bx.pointercast(llval, ll_t_out)
`
376
312
`}
`
377
``
`-
(CastTy::Int(), CastTy::Ptr()) => {
`
378
``
`-
let usize_llval = bx.intcast(llval, bx.cx().type_isize(), signed);
`
``
313
`+
(CastTy::Int(i), CastTy::Ptr(_)) => {
`
``
314
`+
let usize_llval =
`
``
315
`+
bx.intcast(llval, bx.cx().type_isize(), i.is_signed());
`
379
316
` bx.inttoptr(usize_llval, ll_t_out)
`
380
317
`}
`
381
318
`(CastTy::Float, CastTy::Int(IntTy::I)) => {
`