Skip to content

Commit 894c724

Browse files
authored
Unrolled build for rust-lang#118172
Rollup merge of rust-lang#118172 - ouz-a:improve_emit_stable1, r=celinval Add `pretty_terminator` to pretty stable-mir ~Because we don't have successors in `stable_mir` this is somewhat lacking but it's better than nothing~, also fixed bug(?) with `Opaque` which printed extra `"` when we try to print opaqued `String`. **Edit**: Added successors so this covers Terminators as a whole. r? `@celinval`
2 parents 49b3924 + 15f9bab commit 894c724

File tree

4 files changed

+286
-18
lines changed

4 files changed

+286
-18
lines changed

compiler/rustc_smir/src/rustc_smir/convert/mir.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -578,13 +578,13 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
578578
}
579579
mir::TerminatorKind::SwitchInt { discr, targets } => TerminatorKind::SwitchInt {
580580
discr: discr.stable(tables),
581-
targets: targets
582-
.iter()
583-
.map(|(value, target)| stable_mir::mir::SwitchTarget {
584-
value,
585-
target: target.as_usize(),
586-
})
587-
.collect(),
581+
targets: {
582+
let (value_vec, mut target_vec): (Vec<_>, Vec<_>) =
583+
targets.iter().map(|(value, target)| (value, target.as_usize())).unzip();
584+
// We need to push otherwise as last element to ensure it's same as in MIR.
585+
target_vec.push(targets.otherwise().as_usize());
586+
stable_mir::mir::SwitchTargets { value: value_vec, targets: target_vec }
587+
},
588588
otherwise: targets.otherwise().as_usize(),
589589
},
590590
mir::TerminatorKind::UnwindResume => TerminatorKind::Resume,

compiler/stable_mir/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
//!
1717
//! The goal is to eventually be published on
1818
//! [crates.io](https://crates.io).
19-
19+
#![feature(type_alias_impl_trait)]
2020
#[macro_use]
2121
extern crate scoped_tls;
2222

@@ -184,7 +184,7 @@ impl std::fmt::Display for Opaque {
184184

185185
impl std::fmt::Debug for Opaque {
186186
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
187-
write!(f, "{:?}", self.0)
187+
write!(f, "{}", self.0)
188188
}
189189
}
190190

compiler/stable_mir/src/mir/body.rs

+69-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
use crate::mir::pretty::{function_body, pretty_statement};
1+
use crate::mir::pretty::{function_body, pretty_statement, pretty_terminator};
22
use crate::ty::{
33
AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind,
44
};
55
use crate::{Error, Opaque, Span, Symbol};
6-
use std::io;
7-
6+
use std::{io, slice};
87
/// The SMIR representation of a single function.
98
#[derive(Clone, Debug)]
109
pub struct Body {
@@ -83,6 +82,8 @@ impl Body {
8382
Ok(())
8483
})
8584
.collect::<Vec<_>>();
85+
pretty_terminator(&block.terminator.kind, w)?;
86+
writeln!(w, "").unwrap();
8687
writeln!(w, " }}").unwrap();
8788
Ok(())
8889
})
@@ -100,7 +101,7 @@ pub struct LocalDecl {
100101
pub mutability: Mutability,
101102
}
102103

103-
#[derive(Clone, Debug)]
104+
#[derive(Clone, PartialEq, Eq, Debug)]
104105
pub struct BasicBlock {
105106
pub statements: Vec<Statement>,
106107
pub terminator: Terminator,
@@ -112,14 +113,22 @@ pub struct Terminator {
112113
pub span: Span,
113114
}
114115

116+
impl Terminator {
117+
pub fn successors(&self) -> Successors<'_> {
118+
self.kind.successors()
119+
}
120+
}
121+
122+
pub type Successors<'a> = impl Iterator<Item = usize> + 'a;
123+
115124
#[derive(Clone, Debug, Eq, PartialEq)]
116125
pub enum TerminatorKind {
117126
Goto {
118127
target: usize,
119128
},
120129
SwitchInt {
121130
discr: Operand,
122-
targets: Vec<SwitchTarget>,
131+
targets: SwitchTargets,
123132
otherwise: usize,
124133
},
125134
Resume,
@@ -156,6 +165,58 @@ pub enum TerminatorKind {
156165
},
157166
}
158167

168+
impl TerminatorKind {
169+
pub fn successors(&self) -> Successors<'_> {
170+
use self::TerminatorKind::*;
171+
match *self {
172+
Call { target: Some(t), unwind: UnwindAction::Cleanup(ref u), .. }
173+
| Drop { target: t, unwind: UnwindAction::Cleanup(ref u), .. }
174+
| Assert { target: t, unwind: UnwindAction::Cleanup(ref u), .. }
175+
| InlineAsm { destination: Some(t), unwind: UnwindAction::Cleanup(ref u), .. } => {
176+
Some(t).into_iter().chain(slice::from_ref(u).into_iter().copied())
177+
}
178+
Goto { target: t }
179+
| Call { target: None, unwind: UnwindAction::Cleanup(t), .. }
180+
| Call { target: Some(t), unwind: _, .. }
181+
| Drop { target: t, unwind: _, .. }
182+
| Assert { target: t, unwind: _, .. }
183+
| InlineAsm { destination: None, unwind: UnwindAction::Cleanup(t), .. }
184+
| InlineAsm { destination: Some(t), unwind: _, .. } => {
185+
Some(t).into_iter().chain((&[]).into_iter().copied())
186+
}
187+
188+
CoroutineDrop
189+
| Return
190+
| Resume
191+
| Abort
192+
| Unreachable
193+
| Call { target: None, unwind: _, .. }
194+
| InlineAsm { destination: None, unwind: _, .. } => {
195+
None.into_iter().chain((&[]).into_iter().copied())
196+
}
197+
SwitchInt { ref targets, .. } => {
198+
None.into_iter().chain(targets.targets.iter().copied())
199+
}
200+
}
201+
}
202+
203+
pub fn unwind(&self) -> Option<&UnwindAction> {
204+
match *self {
205+
TerminatorKind::Goto { .. }
206+
| TerminatorKind::Return
207+
| TerminatorKind::Unreachable
208+
| TerminatorKind::CoroutineDrop
209+
| TerminatorKind::Resume
210+
| TerminatorKind::Abort
211+
| TerminatorKind::SwitchInt { .. } => None,
212+
TerminatorKind::Call { ref unwind, .. }
213+
| TerminatorKind::Assert { ref unwind, .. }
214+
| TerminatorKind::Drop { ref unwind, .. }
215+
| TerminatorKind::InlineAsm { ref unwind, .. } => Some(unwind),
216+
}
217+
}
218+
}
219+
159220
#[derive(Clone, Debug, Eq, PartialEq)]
160221
pub struct InlineAsmOperand {
161222
pub in_value: Option<Operand>,
@@ -602,9 +663,9 @@ pub struct Constant {
602663
}
603664

604665
#[derive(Clone, Debug, Eq, PartialEq)]
605-
pub struct SwitchTarget {
606-
pub value: u128,
607-
pub target: usize,
666+
pub struct SwitchTargets {
667+
pub value: Vec<u128>,
668+
pub targets: Vec<usize>,
608669
}
609670

610671
#[derive(Copy, Clone, Debug, Eq, PartialEq)]

compiler/stable_mir/src/mir/pretty.rs

+208-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
use crate::crate_def::CrateDef;
2-
use crate::mir::{Operand, Rvalue, StatementKind};
2+
use crate::mir::{Operand, Rvalue, StatementKind, UnwindAction};
33
use crate::ty::{DynKind, FloatTy, IntTy, RigidTy, TyKind, UintTy};
44
use crate::{with, Body, CrateItem, Mutability};
5+
use std::io::Write;
6+
use std::{io, iter};
7+
8+
use super::{AssertMessage, BinOp, TerminatorKind};
59

610
pub fn function_name(item: CrateItem) -> String {
711
let mut pretty_name = String::new();
@@ -70,6 +74,209 @@ pub fn pretty_statement(statement: &StatementKind) -> String {
7074
pretty
7175
}
7276

77+
pub fn pretty_terminator<W: io::Write>(terminator: &TerminatorKind, w: &mut W) -> io::Result<()> {
78+
write!(w, "{}", pretty_terminator_head(terminator))?;
79+
let successor_count = terminator.successors().count();
80+
let labels = pretty_successor_labels(terminator);
81+
82+
let show_unwind = !matches!(terminator.unwind(), None | Some(UnwindAction::Cleanup(_)));
83+
let fmt_unwind = |fmt: &mut dyn Write| -> io::Result<()> {
84+
write!(fmt, "unwind ")?;
85+
match terminator.unwind() {
86+
None | Some(UnwindAction::Cleanup(_)) => unreachable!(),
87+
Some(UnwindAction::Continue) => write!(fmt, "continue"),
88+
Some(UnwindAction::Unreachable) => write!(fmt, "unreachable"),
89+
Some(UnwindAction::Terminate) => write!(fmt, "terminate"),
90+
}
91+
};
92+
93+
match (successor_count, show_unwind) {
94+
(0, false) => Ok(()),
95+
(0, true) => {
96+
write!(w, " -> ")?;
97+
fmt_unwind(w)?;
98+
Ok(())
99+
}
100+
(1, false) => {
101+
write!(w, " -> {:?}", terminator.successors().next().unwrap())?;
102+
Ok(())
103+
}
104+
_ => {
105+
write!(w, " -> [")?;
106+
for (i, target) in terminator.successors().enumerate() {
107+
if i > 0 {
108+
write!(w, ", ")?;
109+
}
110+
write!(w, "{}: bb{:?}", labels[i], target)?;
111+
}
112+
if show_unwind {
113+
write!(w, ", ")?;
114+
fmt_unwind(w)?;
115+
}
116+
write!(w, "]")
117+
}
118+
}?;
119+
120+
Ok(())
121+
}
122+
123+
pub fn pretty_terminator_head(terminator: &TerminatorKind) -> String {
124+
use self::TerminatorKind::*;
125+
let mut pretty = String::new();
126+
match terminator {
127+
Goto { .. } => format!(" goto"),
128+
SwitchInt { discr, .. } => {
129+
format!(" switchInt(_{})", pretty_operand(discr))
130+
}
131+
Resume => format!(" resume"),
132+
Abort => format!(" abort"),
133+
Return => format!(" return"),
134+
Unreachable => format!(" unreachable"),
135+
Drop { place, .. } => format!(" drop(_{:?})", place.local),
136+
Call { func, args, destination, .. } => {
137+
pretty.push_str(" ");
138+
pretty.push_str(format!("_{} = ", destination.local).as_str());
139+
pretty.push_str(&pretty_operand(func));
140+
pretty.push_str("(");
141+
args.iter().enumerate().for_each(|(i, arg)| {
142+
if i > 0 {
143+
pretty.push_str(", ");
144+
}
145+
pretty.push_str(&pretty_operand(arg));
146+
});
147+
pretty.push_str(")");
148+
pretty
149+
}
150+
Assert { cond, expected, msg, target: _, unwind: _ } => {
151+
pretty.push_str(" assert(");
152+
if !expected {
153+
pretty.push_str("!");
154+
}
155+
pretty.push_str(format!("{} bool),", &pretty_operand(cond)).as_str());
156+
pretty.push_str(&pretty_assert_message(msg));
157+
pretty.push_str(")");
158+
pretty
159+
}
160+
CoroutineDrop => format!(" coroutine_drop"),
161+
InlineAsm { .. } => todo!(),
162+
}
163+
}
164+
165+
pub fn pretty_successor_labels(terminator: &TerminatorKind) -> Vec<String> {
166+
use self::TerminatorKind::*;
167+
match terminator {
168+
Resume | Abort | Return | Unreachable | CoroutineDrop => vec![],
169+
Goto { .. } => vec!["".to_string()],
170+
SwitchInt { targets, .. } => targets
171+
.value
172+
.iter()
173+
.map(|target| format!("{}", target))
174+
.chain(iter::once("otherwise".into()))
175+
.collect(),
176+
Drop { unwind: UnwindAction::Cleanup(_), .. } => vec!["return".into(), "unwind".into()],
177+
Drop { unwind: _, .. } => vec!["return".into()],
178+
Call { target: Some(_), unwind: UnwindAction::Cleanup(_), .. } => {
179+
vec!["return".into(), "unwind".into()]
180+
}
181+
Call { target: Some(_), unwind: _, .. } => vec!["return".into()],
182+
Call { target: None, unwind: UnwindAction::Cleanup(_), .. } => vec!["unwind".into()],
183+
Call { target: None, unwind: _, .. } => vec![],
184+
Assert { unwind: UnwindAction::Cleanup(_), .. } => {
185+
vec!["success".into(), "unwind".into()]
186+
}
187+
Assert { unwind: _, .. } => vec!["success".into()],
188+
InlineAsm { .. } => todo!(),
189+
}
190+
}
191+
192+
pub fn pretty_assert_message(msg: &AssertMessage) -> String {
193+
let mut pretty = String::new();
194+
match msg {
195+
AssertMessage::BoundsCheck { len, index } => {
196+
let pretty_len = pretty_operand(len);
197+
let pretty_index = pretty_operand(index);
198+
pretty.push_str(format!("\"index out of bounds: the length is {{}} but the index is {{}}\", {pretty_len}, {pretty_index}").as_str());
199+
pretty
200+
}
201+
AssertMessage::Overflow(BinOp::Add, l, r) => {
202+
let pretty_l = pretty_operand(l);
203+
let pretty_r = pretty_operand(r);
204+
pretty.push_str(format!("\"attempt to compute `{{}} + {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
205+
pretty
206+
}
207+
AssertMessage::Overflow(BinOp::Sub, l, r) => {
208+
let pretty_l = pretty_operand(l);
209+
let pretty_r = pretty_operand(r);
210+
pretty.push_str(format!("\"attempt to compute `{{}} - {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
211+
pretty
212+
}
213+
AssertMessage::Overflow(BinOp::Mul, l, r) => {
214+
let pretty_l = pretty_operand(l);
215+
let pretty_r = pretty_operand(r);
216+
pretty.push_str(format!("\"attempt to compute `{{}} * {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
217+
pretty
218+
}
219+
AssertMessage::Overflow(BinOp::Div, l, r) => {
220+
let pretty_l = pretty_operand(l);
221+
let pretty_r = pretty_operand(r);
222+
pretty.push_str(format!("\"attempt to compute `{{}} / {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
223+
pretty
224+
}
225+
AssertMessage::Overflow(BinOp::Rem, l, r) => {
226+
let pretty_l = pretty_operand(l);
227+
let pretty_r = pretty_operand(r);
228+
pretty.push_str(format!("\"attempt to compute `{{}} % {{}}`, which would overflow\", {pretty_l}, {pretty_r}").as_str());
229+
pretty
230+
}
231+
AssertMessage::Overflow(BinOp::Shr, _, r) => {
232+
let pretty_r = pretty_operand(r);
233+
pretty.push_str(
234+
format!("\"attempt to shift right by `{{}}`, which would overflow\", {pretty_r}")
235+
.as_str(),
236+
);
237+
pretty
238+
}
239+
AssertMessage::Overflow(BinOp::Shl, _, r) => {
240+
let pretty_r = pretty_operand(r);
241+
pretty.push_str(
242+
format!("\"attempt to shift left by `{{}}`, which would overflow\", {pretty_r}")
243+
.as_str(),
244+
);
245+
pretty
246+
}
247+
AssertMessage::OverflowNeg(op) => {
248+
let pretty_op = pretty_operand(op);
249+
pretty.push_str(
250+
format!("\"attempt to negate `{{}}`, which would overflow\", {pretty_op}").as_str(),
251+
);
252+
pretty
253+
}
254+
AssertMessage::DivisionByZero(op) => {
255+
let pretty_op = pretty_operand(op);
256+
pretty.push_str(format!("\"attempt to divide `{{}}` by zero\", {pretty_op}").as_str());
257+
pretty
258+
}
259+
AssertMessage::RemainderByZero(op) => {
260+
let pretty_op = pretty_operand(op);
261+
pretty.push_str(
262+
format!("\"attempt to calculate the remainder of `{{}}` with a divisor of zero\", {pretty_op}").as_str(),
263+
);
264+
pretty
265+
}
266+
AssertMessage::ResumedAfterReturn(_) => {
267+
format!("attempt to resume a generator after completion")
268+
}
269+
AssertMessage::ResumedAfterPanic(_) => format!("attempt to resume a panicked generator"),
270+
AssertMessage::MisalignedPointerDereference { required, found } => {
271+
let pretty_required = pretty_operand(required);
272+
let pretty_found = pretty_operand(found);
273+
pretty.push_str(format!("\"misaligned pointer dereference: address must be a multiple of {{}} but is {{}}\",{pretty_required}, {pretty_found}").as_str());
274+
pretty
275+
}
276+
_ => todo!(),
277+
}
278+
}
279+
73280
pub fn pretty_operand(operand: &Operand) -> String {
74281
let mut pretty = String::new();
75282
match operand {

0 commit comments

Comments
 (0)