Auto merge of #115748 - RalfJung:post-mono, r=oli-obk
move required_consts check to general post-mono-check function This factors some code that is common between the interpreter and the codegen backends into shared helper functions. Also as a side-effect the interpreter now uses the same `eval` functions as everyone else to get the evaluated MIR constants. Also this is in preparation for another post-mono check that will be needed for (the current hackfix for) https://github.com/rust-lang/rust/issues/115709: ensuring that all locals are dynamically sized. I didn't expect this to change diagnostics, but it's just cycle errors that change. r? `@oli-obk`
This commit is contained in:
commit
cebb9cfd4f
76 changed files with 385 additions and 361 deletions
|
@ -595,20 +595,6 @@ pub struct InvalidWindowsSubsystem {
|
|||
pub subsystem: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_erroneous_constant)]
|
||||
pub struct ErroneousConstant {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_polymorphic_constant_too_generic)]
|
||||
pub struct PolymorphicConstantTooGeneric {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_ssa_shuffle_indices_evaluation)]
|
||||
pub struct ShuffleIndicesEvaluation {
|
||||
|
|
|
@ -1088,9 +1088,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
InlineAsmOperandRef::InOut { reg, late, in_value, out_place }
|
||||
}
|
||||
mir::InlineAsmOperand::Const { ref value } => {
|
||||
let const_value = self
|
||||
.eval_mir_constant(value)
|
||||
.unwrap_or_else(|_| span_bug!(span, "asm const cannot be resolved"));
|
||||
let const_value = self.eval_mir_constant(value);
|
||||
let string = common::asm_const_to_str(
|
||||
bx.tcx(),
|
||||
span,
|
||||
|
|
|
@ -14,34 +14,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
&self,
|
||||
bx: &mut Bx,
|
||||
constant: &mir::Constant<'tcx>,
|
||||
) -> Result<OperandRef<'tcx, Bx::Value>, ErrorHandled> {
|
||||
let val = self.eval_mir_constant(constant)?;
|
||||
) -> OperandRef<'tcx, Bx::Value> {
|
||||
let val = self.eval_mir_constant(constant);
|
||||
let ty = self.monomorphize(constant.ty());
|
||||
Ok(OperandRef::from_const(bx, val, ty))
|
||||
OperandRef::from_const(bx, val, ty)
|
||||
}
|
||||
|
||||
pub fn eval_mir_constant(
|
||||
&self,
|
||||
constant: &mir::Constant<'tcx>,
|
||||
) -> Result<ConstValue<'tcx>, ErrorHandled> {
|
||||
pub fn eval_mir_constant(&self, constant: &mir::Constant<'tcx>) -> ConstValue<'tcx> {
|
||||
self.monomorphize(constant.literal)
|
||||
.eval(self.cx.tcx(), ty::ParamEnv::reveal_all(), Some(constant.span))
|
||||
.map_err(|err| {
|
||||
match err {
|
||||
ErrorHandled::Reported(_) => {
|
||||
self.cx
|
||||
.tcx()
|
||||
.sess
|
||||
.emit_err(errors::ErroneousConstant { span: constant.span });
|
||||
}
|
||||
ErrorHandled::TooGeneric => {
|
||||
self.cx.tcx().sess.diagnostic().emit_bug(
|
||||
errors::PolymorphicConstantTooGeneric { span: constant.span },
|
||||
);
|
||||
}
|
||||
}
|
||||
err
|
||||
})
|
||||
.expect("erroneous constant not captured by required_consts")
|
||||
}
|
||||
|
||||
/// This is a convenience helper for `simd_shuffle_indices`. It has the precondition
|
||||
|
|
|
@ -579,23 +579,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
if let Some(dbg_var) = dbg_var {
|
||||
let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue };
|
||||
|
||||
if let Ok(operand) = self.eval_mir_constant_to_operand(bx, &c) {
|
||||
self.set_debug_loc(bx, var.source_info);
|
||||
let base = Self::spill_operand_to_stack(
|
||||
operand,
|
||||
Some(var.name.to_string()),
|
||||
bx,
|
||||
);
|
||||
let operand = self.eval_mir_constant_to_operand(bx, &c);
|
||||
self.set_debug_loc(bx, var.source_info);
|
||||
let base =
|
||||
Self::spill_operand_to_stack(operand, Some(var.name.to_string()), bx);
|
||||
|
||||
bx.dbg_var_addr(
|
||||
dbg_var,
|
||||
dbg_loc,
|
||||
base.llval,
|
||||
Size::ZERO,
|
||||
&[],
|
||||
fragment,
|
||||
);
|
||||
}
|
||||
bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, Size::ZERO, &[], fragment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ use crate::traits::*;
|
|||
use rustc_index::bit_set::BitSet;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::ErrorHandled;
|
||||
use rustc_middle::mir::traversal;
|
||||
use rustc_middle::mir::UnwindTerminateReason;
|
||||
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, TyAndLayout};
|
||||
|
@ -212,23 +211,14 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
|
||||
fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut start_bx);
|
||||
|
||||
// Evaluate all required consts; codegen later assumes that CTFE will never fail.
|
||||
let mut all_consts_ok = true;
|
||||
for const_ in &mir.required_consts {
|
||||
if let Err(err) = fx.eval_mir_constant(const_) {
|
||||
all_consts_ok = false;
|
||||
match err {
|
||||
// errored or at least linted
|
||||
ErrorHandled::Reported(_) => {}
|
||||
ErrorHandled::TooGeneric => {
|
||||
span_bug!(const_.span, "codegen encountered polymorphic constant: {:?}", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !all_consts_ok {
|
||||
// We leave the IR in some half-built state here, and rely on this code not even being
|
||||
// submitted to LLVM once an error was raised.
|
||||
// Rust post-monomorphization checks; we later rely on them.
|
||||
if let Err(err) =
|
||||
mir.post_mono_checks(cx.tcx(), ty::ParamEnv::reveal_all(), |c| Ok(fx.monomorphize(c)))
|
||||
{
|
||||
err.emit_err(cx.tcx());
|
||||
// This IR shouldn't ever be emitted, but let's try to guard against any of this code
|
||||
// ever running.
|
||||
start_bx.abort();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -575,12 +575,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
self.codegen_consume(bx, place.as_ref())
|
||||
}
|
||||
|
||||
mir::Operand::Constant(ref constant) => {
|
||||
// This cannot fail because we checked all required_consts in advance.
|
||||
self.eval_mir_constant_to_operand(bx, constant).unwrap_or_else(|_err| {
|
||||
span_bug!(constant.span, "erroneous constant not captured by required_consts")
|
||||
})
|
||||
}
|
||||
mir::Operand::Constant(ref constant) => self.eval_mir_constant_to_operand(bx, constant),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue