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 assumes.

``

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)) => {

`