The following program (reduced from https://github.com/shepmaster/fuzzy-pickles/issues/62) segfaults when compiled with optimizations in panic=abort mode using beta or nightly rustc.
code
// parse.rs
fn main() {
let tokens = &[Token::Ident, Token::AmpersandEquals, Token::Ident];
let _ = expression(Point::new(tokens));
}
struct Progress<'s, T> {
point: Point<'s>,
status: Result<T, ()>,
}
impl<'s, T> Progress<'s, T> {
pub fn success(point: Point<'s>, val: T) -> Self {
Progress { point: point, status: Ok(val) }
}
pub fn failure(point: Point<'s>) -> Self {
Progress { point: point, status: Err(()) }
}
pub fn map<F, T2>(self, f: F) -> Progress<'s, T2>
where F: FnOnce(T) -> T2
{
Progress { point: self.point, status: self.status.map(f) }
}
}
#[derive(Copy, Clone)]
enum Token {
AmpersandEquals,
Ident,
}
impl Token {
fn into_ident(self) -> Option<Extent> {
match self {
Token::Ident => Some((0,0)),
_ => None,
}
}
fn into_ampersand_equals(self) -> Option<Extent> {
match self {
Token::AmpersandEquals => Some((0,0)),
_ => None,
}
}
}
#[derive(Copy, Clone)]
struct Point<'s> {
pub offset: usize,
pub s: &'s [Token],
}
impl<'s> Point<'s> {
fn new(slice: &'s [Token]) -> Self {
Point {
offset: 0,
s: slice,
}
}
fn advance_by(&self, offset: usize) -> Self {
Point {
offset: self.offset + offset,
s: &self.s[offset..],
}
}
}
pub type Extent = (usize, usize);
enum Expression {
AsType(AsType),
Binary(Binary),
Call(Call),
FieldAccess(FieldAccess),
Slice(Slice),
Value(Value),
}
struct FieldAccess {
target: Box<Expression>,
}
pub struct Value;
pub struct Call {
extent: Extent,
target: Box<Expression>,
args: Vec<Expression>,
}
pub struct Binary {
lhs: Box<Expression>,
rhs: Box<Expression>,
}
struct AsType {
extent: Extent,
target: Box<Expression>,
}
struct Slice {
target: Box<Expression>,
index: Box<Expression>,
}
fn token<'s, F, T>(token_convert: F, pt: Point<'s>) ->
Progress<'s, T>
where F: Fn(Token) -> Option<T>,
{
let original_token = match pt.s.first() {
Some(&token) => token,
None => return Progress::failure(pt),
};
match token_convert(original_token) {
Some(v) => {
Progress::success(pt.advance_by(1), v)
}
None => {
Progress::failure(pt)
}
}
}
enum OperatorInfix {
BitwiseAndAssign(Extent),
}
enum OperatorPostfix {
AsType { typ: () },
Call { args: Vec<Expression> },
FieldAccess { field: () },
Slice { index: Expression },
}
enum OperatorKind {
Infix(OperatorInfix),
Postfix(OperatorPostfix),
}
impl OperatorKind {
fn precedence(&self) -> u8 {
match *self {
OperatorKind::Infix(_) => 10,
OperatorKind::Postfix(OperatorPostfix::Call { .. }) => 10,
OperatorKind::Postfix(_) => 20,
}
}
}
enum InfixOrPostfix {
Infix(OperatorInfix),
Postfix(OperatorPostfix),
}
struct ShuntCar<'s, T> {
value: T,
spt: Point<'s>,
ept: Point<'s>,
}
struct ShuntingYard<'s> {
operators: Vec<ShuntCar<'s, OperatorKind>>,
result: Vec<ShuntCar<'s, Expression>>,
}
type PointRange<'s> = std::ops::Range<Point<'s>>;
type ExprResult<'s, T> = std::result::Result<T, Point<'s>>;
impl<'s> ShuntingYard<'s> {
fn add_infix(&mut self, op: OperatorInfix, spt: Point<'s>, ept: Point<'s>) -> ExprResult<'s, ()>
{
let op = OperatorKind::Infix(op);
self.apply_precedence(&op)?;
self.operators.push(ShuntCar { value: op, spt, ept });
Ok(())
}
fn apply_precedence(&mut self, operator: &OperatorKind) -> ExprResult<'s, ()> {
let op_precedence = operator.precedence();
while self.operators.last().map_or(false, |&ShuntCar { value: ref top, .. }| top.precedence() > op_precedence) {
let ShuntCar { value: _, spt, ept } = self.operators.pop().unwrap();
self.apply_binary(spt..ept)?;
}
Ok(())
}
fn apply_all(&mut self) -> ExprResult<'s, ()> {
while let Some(ShuntCar { value: _, spt, ept }) = self.operators.pop() {
self.apply_binary(spt..ept)?;
}
Ok(())
}
fn apply_infix<F>(&mut self, op_range: PointRange<'s>, f: F) ->
ExprResult<'s, ()>
where F: FnOnce(Expression, Expression) -> Expression
{
let ShuntCar { value: rhs, ept: rexpr_ept, .. } = self.pop_expression(op_range.end)?;
let ShuntCar { value: lhs, spt: lexpr_spt, .. } = self.pop_expression(op_range.start)?;
let new_expr = f(lhs, rhs);
self.result.push(ShuntCar { value: new_expr, spt: lexpr_spt, ept: rexpr_ept });
Ok(())
}
fn apply_binary(&mut self, op_range: PointRange<'s>) ->
ExprResult<'s, ()>
{
self.apply_infix(op_range, |lhs, rhs| {
Expression::Binary(Binary {
lhs: Box::new(lhs),
rhs: Box::new(rhs),
})
})
}
fn pop_expression(&mut self, location: Point<'s>) ->
ExprResult<'s, ShuntCar<'s, Expression>>
{
self.result.pop().ok_or(location)
}
}
enum ExpressionState {
Prefix, // Also "beginning of expression"
Infix,
Atom,
}
fn expression<'s>(pt: Point<'s>) -> Progress<'s, Expression> {
match expression_x(pt) {
Ok(ShuntCar { value: expr, ept, .. }) => Progress::success(ept, expr),
Err(failure_point) => Progress::failure(failure_point),
}
}
fn expression_x<'s>(mut pt: Point<'s>) ->
ExprResult<'s, ShuntCar<'s, Expression>>
{
let mut shunting_yard = ShuntingYard { operators: Vec::new(), result: Vec::new() };
let mut state = ExpressionState::Prefix;
loop {
println!("expression_x loop");
match state {
ExpressionState::Prefix |
ExpressionState::Infix => {
println!("branch 1");
let Progress { point, .. } =
token(Token::into_ident, pt).map(|_| Value).map(Expression::Value);
state = ExpressionState::Atom;
pt = point;
}
ExpressionState::Atom => {
println!("branch 2");
match token(Token::into_ampersand_equals, pt)
.map(OperatorInfix::BitwiseAndAssign).map(InfixOrPostfix::Infix) {
Progress { status: Ok(infix_or_postfix), point } => {
match infix_or_postfix {
InfixOrPostfix::Infix(op) => {
shunting_yard.add_infix(op, pt, point)?;
state = ExpressionState::Infix;
}
InfixOrPostfix::Postfix(_) => unimplemented!(),
}
pt = point;
}
_ => shunting_yard.apply_all()?,
}
}
}
}
}
$ rustc --version
rustc 1.18.0-beta.1 (4dce67253 2017-04-25)
$ rustc -C opt-level=1 -C panic=abort parse.rs
[...]
$ ./parse
expression_x loop
branch 1
expression_x loop
branch 2
expression_x loop
branch 1
expression_x loop
branch 2
Segmentation fault
$ valgrind ./parse
==1034== Memcheck, a memory error detector
==1034== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==1034== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==1034== Command: ./parse
==1034==
expression_x loop
branch 1
expression_x loop
branch 2
expression_x loop
branch 1
expression_x loop
branch 2
==1034== Invalid read of size 8
==1034== at 0x10F2C0: core::ptr::drop_in_place::h4d1aff9439cb72f2 (in /home/dwrensha/Desktop/peresil-segfault/parse)
==1034== by 0x1: ???
==1034== by 0x1442C3: ??? (in /home/dwrensha/Desktop/peresil-segfault/parse)
==1034== Address 0x1 is not stack'd, malloc'd or (recently) free'd
==1034==
==1034==
==1034== Process terminating with default action of signal 11 (SIGSEGV)
==1034== Access not within mapped region at address 0x1
==1034== at 0x10F2C0: core::ptr::drop_in_place::h4d1aff9439cb72f2 (in /home/dwrensha/Desktop/peresil-segfault/parse)
==1034== by 0x1: ???
==1034== by 0x1442C3: ??? (in /home/dwrensha/Desktop/peresil-segfault/parse)
==1034== If you believe this happened as a result of a stack
==1034== overflow in your program's main thread (unlikely but
==1034== possible), you can try to increase the size of the
==1034== main thread stack using the --main-stacksize= flag.
==1034== The main thread stack size used in this run was 8388608.
==1034==
==1034== HEAP SUMMARY:
==1034== in use at exit: 64 bytes in 2 blocks
==1034== total heap usage: 7 allocs, 5 frees, 2,032 bytes allocated
==1034==
==1034== LEAK SUMMARY:
==1034== definitely lost: 0 bytes in 0 blocks
==1034== indirectly lost: 0 bytes in 0 blocks
==1034== possibly lost: 0 bytes in 0 blocks
==1034== still reachable: 64 bytes in 2 blocks
==1034== suppressed: 0 bytes in 0 blocks
==1034== Rerun with --leak-check=full to see details of leaked memory
==1034==
==1034== For counts of detected and suppressed errors, rerun with: -v
==1034== ERROR SUMMARY: 2 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault
Apparently panic=abort is not necessary. I still see the segfault when compiling with
rustc -C opt-level=1 parse.rs
Without -Cpanic=abort, segfault only happens at opt-level=1. No repro at 0, 2 or 3.
With -Cpanic=abort, segfault happens at opt-level=1,2,3.
No repro when -Zsanitizer=address is enabled 😒
LLDB stack trace (-Cpanic=abort -Copt-level=3)
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
* frame #0: 0x0000000100000e39 1`core::ptr::drop_in_place<1::Expression>((null)=0x0000000000000000) at ptr.rs:61 [opt]
frame #1: 0x0000000100000e72 1`core::ptr::drop_in_place<1::Expression> [inlined] core::ptr::drop_in_place<alloc::boxed::Box<1::Expression>> at ptr.rs:61 [opt]
frame #2: 0x0000000100000e69 1`core::ptr::drop_in_place<1::Expression> [inlined] core::ptr::drop_in_place<1::Binary> at ptr.rs:61 [opt]
frame #3: 0x0000000100000e69 1`core::ptr::drop_in_place<1::Expression>((null)=0x00007fff5fbff470) at ptr.rs:61 [opt]
frame #4: 0x0000000100001672 1`_ZN114mainE [inlined] core::ptr::drop_in_place<1::InfixOrPostfix> at ptr.rs:61 [opt]
frame #5: 0x0000000100001666 1`_ZN114mainE at 1.rs:273 [opt]
frame #6: 0x0000000100000ef4 1`_ZN114mainE [inlined] _ZN1110expressionE at 1.rs:236 [opt]
frame #7: 0x0000000100000ef4 1`_ZN114mainE at 1.rs:5 [opt]
frame #8: 0x000000010000b45c 1`panic_abort::__rust_maybe_catch_panic at lib.rs:40 [opt]
frame #9: 0x000000010000b172 1`std::rt::lang_start [inlined] std::panicking::try<(),fn()> at panicking.rs:433 [opt]
frame #10: 0x000000010000b143 1`std::rt::lang_start [inlined] std::panic::catch_unwind<fn(),()> at panic.rs:361 [opt]
frame #11: 0x000000010000b143 1`std::rt::lang_start at rt.rs:57 [opt]
frame #12: 0x00007fffc988b235 libdyld.dylib`start + 1
frame #13: 0x00007fffc988b235 libdyld.dylib`start + 1
(lldb) fr s 7
frame #7: 0x0000000100000ef4 1`_ZN114mainE at 1.rs:5 [opt]
2
3 fn main() {
4 let tokens = &[Token::Ident, Token::AmpersandEquals, Token::Ident];
-> 5 let _ = expression(Point::new(tokens));
6 }
7
8 struct Progress<'s, T> {
(lldb) fr s 6
frame #6: 0x0000000100000ef4 1`_ZN114mainE [inlined] _ZN1110expressionE at 1.rs:236 [opt]
233 }
234
235 fn expression<'s>(pt: Point<'s>) -> Progress<'s, Expression> {
-> 236 match expression_x(pt) {
237 Ok(ShuntCar { value: expr, ept, .. }) => Progress::success(ept, expr),
238 Err(failure_point) => Progress::failure(failure_point),
239 }
(lldb) fr s 5
frame #5: 0x0000000100001666 1`_ZN114mainE at 1.rs:273 [opt]
270 pt = point;
271 }
272 _ => shunting_yard.apply_all()?,
-> 273 }
274 }
275 }
276 }
(lldb) fr s 4
frame #4: 0x0000000100001672 1`_ZN114mainE [inlined] core::ptr::drop_in_place<1::InfixOrPostfix> at ptr.rs:61 [opt]
(lldb) fr s 3
frame #3: 0x0000000100000e69 1`core::ptr::drop_in_place<1::Expression>((null)=0x00007fff5fbff470) at ptr.rs:61 [opt]
(lldb) fr s 2
frame #2: 0x0000000100000e69 1`core::ptr::drop_in_place<1::Expression> [inlined] core::ptr::drop_in_place<1::Binary> at ptr.rs:61 [opt]
(lldb) fr s 1
frame #1: 0x0000000100000e72 1`core::ptr::drop_in_place<1::Expression> [inlined] core::ptr::drop_in_place<alloc::boxed::Box<1::Expression>> at ptr.rs:61 [opt]
(lldb) fr s 0
frame #0: 0x0000000100000e39 1`core::ptr::drop_in_place<1::Expression>((null)=0x0000000000000000) at ptr.rs:61 [opt]
No repro when -Zsanitizer=address is enabled
@dwrensha and I have been fuzzing my library. I assumed that was the source of this issue, so I'm surprised about that.
@shepmaster: I hit this bug while running cargo-fuzz with --sanitizer leak.
Somewhat reduced, but only repro in -Copt-level=1 -Cpanic=abort in nightly (interestingly, also in -Copt-level=2,3 -Cpanic=abort in stable):
fn main() {
let _ = g((0, 0));
}
type P = (u32, u8); // one field must be ≥u32, the other field must be ≥u8
type R = Result<(), P>;
#[allow(dead_code)]
enum X {
A(Box<X>),
B(Box<X>),
C, // B and C can be omitted, but they are added to ensure well-formed semantic
}
enum K {
D
}
enum E {
F(K), // must not be built-in type
#[allow(dead_code)]
G([X; 2]), // must present, can also be Vec<X> or (X, X), but not X or [X; 1] ...
}
fn g(mut pt: P) -> R {
let mut y = None;
loop {
let status = if pt.0 == 0 {
Some(E::F(K::D))
} else {
None
};
pt.0 = 1;
match status {
Some(infix_or_postfix) => {
if let E::F(_op) = infix_or_postfix { // <- must be captured by value
y = Some(pt);
Ok(())?; // <- yes this line is needed
}
}
_ => {
Err(y.unwrap())? // <-- must use `?`, return Err won't trigger segfault
}
}
}
}
Versions
$ rustc +nightly -vV
rustc 1.19.0-nightly (f1140a331 2017-05-08)
binary: rustc
commit-hash: f1140a33176a5fb2e91e26ea3ae42a834dd9bfdf
commit-date: 2017-05-08
host: x86_64-apple-darwin
release: 1.19.0-nightly
LLVM version: 4.0
$ rustc +stable -vV
rustc 1.17.0 (56124baa9 2017-04-24)
binary: rustc
commit-hash: 56124baa9e73f28c0709e59e74783cf234a978cf
commit-date: 2017-04-24
host: x86_64-apple-darwin
release: 1.17.0
LLVM version: 3.9
MIR
// WARNING: This output format is intended for human consumers only
// and is subject to change without notice. Knock yourself out.
fn X::A(_1: std::boxed::Box<X>) -> X {
let mut _0: X; // return pointer
bb0: {
_0 = X::A(_1,); // scope 0 at 1.rs:12:5: 12:14
return; // scope 0 at 1.rs:12:5: 12:14
}
}
fn E::G(_1: [X; 2]) -> E {
let mut _0: E; // return pointer
bb0: {
_0 = E::G(_1,); // scope 0 at 1.rs:24:5: 24:14
return; // scope 0 at 1.rs:24:5: 24:14
}
}
fn X::B(_1: std::boxed::Box<X>) -> X {
let mut _0: X; // return pointer
bb0: {
_0 = X::B(_1,); // scope 0 at 1.rs:13:5: 13:14
return; // scope 0 at 1.rs:13:5: 13:14
}
}
const E::{{initializer}}: usize = {
let mut _0: usize; // return pointer
bb0: {
_0 = const 2usize; // scope 0 at 1.rs:24:11: 24:12
return; // scope 0 at 1.rs:24:11: 24:12
}
}
fn g(_1: (u32, u8)) -> std::result::Result<(), (u32, u8)> {
let mut _0: std::result::Result<(), (u32, u8)>; // return pointer
scope 1 {
let mut _2: (u32, u8); // "pt" in scope 1 at 1.rs:27:6: 27:12
scope 2 {
let mut _3: std::option::Option<(u32, u8)>; // "y" in scope 2 at 1.rs:28:9: 28:14
scope 3 {
let _5: std::option::Option<E>; // "status" in scope 3 at 1.rs:30:13: 30:19
scope 4 {
let _10: E; // "infix_or_postfix" in scope 4 at 1.rs:38:18: 38:34
scope 5 {
let _12: K; // "_op" in scope 5 at 1.rs:39:29: 39:32
scope 6 {
let _19: (u32, u8); // "err" in scope 6 at 1.rs:41:21: 41:28
}
scope 7 {
let _20: (); // "val" in scope 7 at 1.rs:41:21: 41:28
}
}
}
scope 8 {
let _29: (u32, u8); // "err" in scope 8 at 1.rs:45:17: 45:33
}
scope 9 {
let _30: (); // "val" in scope 9 at 1.rs:45:17: 45:33
}
}
}
}
let mut _4: ();
let mut _6: bool;
let mut _7: u32;
let mut _8: E;
let mut _9: K;
let mut _11: isize;
let mut _13: isize;
let mut _14: (u32, u8);
let mut _15: ();
let mut _16: std::result::Result<(), (u32, u8)>;
let mut _17: std::result::Result<(), (u32, u8)>;
let mut _18: ();
let mut _21: isize;
let mut _22: (u32, u8);
let mut _23: (u32, u8);
let mut _24: ();
let mut _25: std::result::Result<(), (u32, u8)>;
let mut _26: std::result::Result<(), (u32, u8)>;
let mut _27: (u32, u8);
let mut _28: std::option::Option<(u32, u8)>;
let mut _31: isize;
let mut _32: (u32, u8);
let mut _33: (u32, u8);
let mut _34: ();
let mut _35: bool;
let mut _36: bool;
let mut _37: bool;
let mut _38: bool;
let mut _39: isize;
let mut _40: isize;
let mut _41: isize;
let mut _42: isize;
bb0: {
_37 = const false; // scope 0 at 1.rs:27:6: 27:12
_36 = const false; // scope 0 at 1.rs:27:6: 27:12
_35 = const false; // scope 0 at 1.rs:27:6: 27:12
_38 = const false; // scope 0 at 1.rs:27:6: 27:12
StorageLive(_2); // scope 0 at 1.rs:27:6: 27:12
_2 = _1; // scope 0 at 1.rs:27:6: 27:12
StorageLive(_3); // scope 1 at 1.rs:28:9: 28:14
_3 = std::option::Option<(u32, u8)>::None; // scope 1 at 1.rs:28:17: 28:21
goto -> bb1; // scope 2 at 1.rs:29:5: 48:6
}
bb1: {
StorageLive(_5); // scope 2 at 1.rs:30:13: 30:19
StorageLive(_6); // scope 2 at 1.rs:30:25: 30:34
StorageLive(_7); // scope 2 at 1.rs:30:25: 30:29
_7 = (_2.0: u32); // scope 2 at 1.rs:30:25: 30:29
_6 = Eq(_7, const 0u32); // scope 2 at 1.rs:30:25: 30:34
StorageDead(_7); // scope 2 at 1.rs:30:34: 30:34
switchInt(_6) -> [0u8: bb3, otherwise: bb2]; // scope 2 at 1.rs:30:22: 34:10
}
bb2: {
StorageLive(_8); // scope 2 at 1.rs:31:18: 31:28
StorageLive(_9); // scope 2 at 1.rs:31:23: 31:27
_9 = K::D; // scope 2 at 1.rs:31:23: 31:27
_8 = E::F(_9,); // scope 2 at 1.rs:31:18: 31:28
StorageDead(_9); // scope 2 at 1.rs:31:28: 31:28
_38 = const true; // scope 2 at 1.rs:31:13: 31:29
_5 = std::option::Option<E>::Some(_8,); // scope 2 at 1.rs:31:13: 31:29
StorageDead(_8); // scope 2 at 1.rs:31:29: 31:29
goto -> bb4; // scope 2 at 1.rs:30:22: 34:10
}
bb3: {
_38 = const true; // scope 2 at 1.rs:33:13: 33:17
_5 = std::option::Option<E>::None; // scope 2 at 1.rs:33:13: 33:17
goto -> bb4; // scope 2 at 1.rs:30:22: 34:10
}
bb4: {
StorageDead(_6); // scope 2 at 1.rs:34:10: 34:10
(_2.0: u32) = const 1u32; // scope 3 at 1.rs:35:9: 35:17
_11 = discriminant(_5); // scope 3 at 1.rs:38:13: 38:35
switchInt(_11) -> [1isize: bb6, otherwise: bb5]; // scope 3 at 1.rs:38:13: 38:35
}
bb5: {
StorageLive(_25); // scope 3 at 1.rs:45:17: 45:33
StorageLive(_26); // scope 3 at 1.rs:45:17: 45:32
StorageLive(_27); // scope 3 at 1.rs:45:21: 45:31
StorageLive(_28); // scope 3 at 1.rs:45:21: 45:22
_28 = _3; // scope 3 at 1.rs:45:21: 45:22
_27 = const <std::option::Option<T>>::unwrap(_28) -> bb18; // scope 3 at 1.rs:45:21: 45:31
}
bb6: {
StorageLive(_10); // scope 3 at 1.rs:38:18: 38:34
_38 = const false; // scope 3 at 1.rs:38:18: 38:34
_35 = const true; // scope 3 at 1.rs:38:18: 38:34
_36 = const true; // scope 3 at 1.rs:38:18: 38:34
_37 = const true; // scope 3 at 1.rs:38:18: 38:34
_10 = ((_5 as Some).0: E); // scope 3 at 1.rs:38:18: 38:34
_13 = discriminant(_10); // scope 4 at 1.rs:39:24: 39:33
switchInt(_13) -> [0isize: bb9, otherwise: bb8]; // scope 4 at 1.rs:39:24: 39:33
}
bb7: {
switchInt(_35) -> [0u8: bb24, otherwise: bb28]; // scope 3 at 1.rs:47:10: 47:10
}
bb8: {
_4 = (); // scope 4 at 1.rs:39:17: 42:18
goto -> bb10; // scope 4 at 1.rs:39:17: 42:18
}
bb9: {
StorageLive(_12); // scope 4 at 1.rs:39:29: 39:32
_37 = const false; // scope 4 at 1.rs:39:29: 39:32
_12 = ((_10 as F).0: K); // scope 4 at 1.rs:39:29: 39:32
StorageLive(_14); // scope 5 at 1.rs:40:30: 40:32
_14 = _2; // scope 5 at 1.rs:40:30: 40:32
_3 = std::option::Option<(u32, u8)>::Some(_14,); // scope 5 at 1.rs:40:21: 40:33
StorageDead(_14); // scope 5 at 1.rs:40:33: 40:33
StorageLive(_16); // scope 5 at 1.rs:41:21: 41:28
StorageLive(_17); // scope 5 at 1.rs:41:21: 41:27
StorageLive(_18); // scope 5 at 1.rs:41:24: 41:26
_18 = (); // scope 5 at 1.rs:41:24: 41:26
_17 = std::result::Result<(), (u32, u8)>::Ok(_18,); // scope 5 at 1.rs:41:21: 41:27
StorageDead(_18); // scope 5 at 1.rs:41:27: 41:27
_16 = const std::ops::Carrier::translate(_17) -> bb11; // scope 5 at 1.rs:41:21: 41:28
}
bb10: {
StorageDead(_12); // scope 4 at 1.rs:42:18: 42:18
goto -> bb7; // scope 3 at 1.rs:37:9: 47:10
}
bb11: {
StorageDead(_17); // scope 5 at 1.rs:41:28: 41:28
_21 = discriminant(_16); // scope 5 at 1.rs:41:21: 41:28
switchInt(_21) -> [0isize: bb12, otherwise: bb13]; // scope 5 at 1.rs:41:21: 41:28
}
bb12: {
StorageLive(_20); // scope 5 at 1.rs:41:21: 41:28
_20 = ((_16 as Ok).0: ()); // scope 5 at 1.rs:41:21: 41:28
StorageLive(_24); // scope 7 at 1.rs:41:21: 41:28
_24 = _20; // scope 7 at 1.rs:41:21: 41:28
_15 = _24; // scope 7 at 1.rs:41:21: 41:28
StorageDead(_24); // scope 7 at 1.rs:41:28: 41:28
StorageDead(_19); // scope 5 at 1.rs:41:28: 41:28
StorageDead(_20); // scope 5 at 1.rs:41:28: 41:28
StorageDead(_16); // scope 5 at 1.rs:41:29: 41:29
_4 = (); // scope 5 at 1.rs:39:53: 42:18
goto -> bb10; // scope 4 at 1.rs:39:17: 42:18
}
bb13: {
StorageLive(_19); // scope 5 at 1.rs:41:21: 41:28
_19 = ((_16 as Err).0: (u32, u8)); // scope 5 at 1.rs:41:21: 41:28
StorageLive(_22); // scope 6 at 1.rs:41:21: 41:28
StorageLive(_23); // scope 6 at 1.rs:41:21: 41:28
_23 = _19; // scope 6 at 1.rs:41:21: 41:28
_22 = const std::convert::From::from(_23) -> bb14; // scope 6 at 1.rs:41:21: 41:28
}
bb14: {
StorageDead(_23); // scope 6 at 1.rs:41:28: 41:28
_0 = const std::ops::Carrier::from_error(_22) -> bb15; // scope 6 at 1.rs:41:21: 41:28
}
bb15: {
StorageDead(_22); // scope 6 at 1.rs:41:28: 41:28
StorageDead(_19); // scope 5 at 1.rs:41:28: 41:28
StorageDead(_20); // scope 5 at 1.rs:41:28: 41:28
StorageDead(_16); // scope 5 at 1.rs:41:29: 41:29
StorageDead(_12); // scope 4 at 1.rs:42:18: 42:18
goto -> bb32; // scope 3 at 1.rs:41:21: 41:28
}
bb16: {
StorageDead(_10); // scope 3 at 1.rs:47:10: 47:10
_41 = discriminant(_5); // scope 2 at 1.rs:48:6: 48:6
switchInt(_41) -> [1isize: bb34, otherwise: bb33]; // scope 2 at 1.rs:48:6: 48:6
}
bb17: {
StorageDead(_5); // scope 2 at 1.rs:48:6: 48:6
StorageDead(_3); // scope 1 at 1.rs:49:2: 49:2
StorageDead(_2); // scope 0 at 1.rs:49:2: 49:2
return; // scope 1 at 1.rs:49:2: 49:2
}
bb18: {
StorageDead(_28); // scope 3 at 1.rs:45:31: 45:31
_26 = std::result::Result<(), (u32, u8)>::Err(_27,); // scope 3 at 1.rs:45:17: 45:32
StorageDead(_27); // scope 3 at 1.rs:45:32: 45:32
_25 = const std::ops::Carrier::translate(_26) -> bb19; // scope 3 at 1.rs:45:17: 45:33
}
bb19: {
StorageDead(_26); // scope 3 at 1.rs:45:33: 45:33
_31 = discriminant(_25); // scope 3 at 1.rs:45:17: 45:33
switchInt(_31) -> [0isize: bb20, otherwise: bb21]; // scope 3 at 1.rs:45:17: 45:33
}
bb20: {
StorageLive(_30); // scope 3 at 1.rs:45:17: 45:33
_30 = ((_25 as Ok).0: ()); // scope 3 at 1.rs:45:17: 45:33
StorageLive(_34); // scope 9 at 1.rs:45:17: 45:33
_34 = _30; // scope 9 at 1.rs:45:17: 45:33
_4 = _34; // scope 9 at 1.rs:45:17: 45:33
StorageDead(_34); // scope 9 at 1.rs:45:33: 45:33
StorageDead(_29); // scope 3 at 1.rs:45:33: 45:33
StorageDead(_30); // scope 3 at 1.rs:45:33: 45:33
StorageDead(_25); // scope 3 at 1.rs:46:14: 46:14
goto -> bb7; // scope 3 at 1.rs:37:9: 47:10
}
bb21: {
StorageLive(_29); // scope 3 at 1.rs:45:17: 45:33
_29 = ((_25 as Err).0: (u32, u8)); // scope 3 at 1.rs:45:17: 45:33
StorageLive(_32); // scope 8 at 1.rs:45:17: 45:33
StorageLive(_33); // scope 8 at 1.rs:45:17: 45:33
_33 = _29; // scope 8 at 1.rs:45:17: 45:33
_32 = const std::convert::From::from(_33) -> bb22; // scope 8 at 1.rs:45:17: 45:33
}
bb22: {
StorageDead(_33); // scope 8 at 1.rs:45:33: 45:33
_0 = const std::ops::Carrier::from_error(_32) -> bb23; // scope 8 at 1.rs:45:17: 45:33
}
bb23: {
StorageDead(_32); // scope 8 at 1.rs:45:33: 45:33
StorageDead(_29); // scope 3 at 1.rs:45:33: 45:33
StorageDead(_30); // scope 3 at 1.rs:45:33: 45:33
StorageDead(_25); // scope 3 at 1.rs:46:14: 46:14
goto -> bb32; // scope 3 at 1.rs:45:17: 45:33
}
bb24: {
StorageDead(_10); // scope 3 at 1.rs:47:10: 47:10
_42 = discriminant(_5); // scope 2 at 1.rs:48:6: 48:6
switchInt(_42) -> [1isize: bb37, otherwise: bb36]; // scope 2 at 1.rs:48:6: 48:6
}
bb25: {
StorageDead(_5); // scope 2 at 1.rs:48:6: 48:6
goto -> bb1; // scope 2 at 1.rs:29:5: 48:6
}
bb26: {
_35 = const false; // scope 3 at 1.rs:47:10: 47:10
drop(_10) -> bb24; // scope 3 at 1.rs:47:10: 47:10
}
bb27: {
switchInt(_35) -> [0u8: bb24, otherwise: bb26]; // scope 3 at 1.rs:47:10: 47:10
}
bb28: {
_39 = discriminant(_10); // scope 3 at 1.rs:47:10: 47:10
switchInt(_39) -> [0isize: bb24, otherwise: bb27]; // scope 3 at 1.rs:47:10: 47:10
}
bb29: {
_35 = const false; // scope 3 at 1.rs:47:10: 47:10
drop(_10) -> bb16; // scope 3 at 1.rs:47:10: 47:10
}
bb30: {
switchInt(_35) -> [0u8: bb16, otherwise: bb29]; // scope 3 at 1.rs:47:10: 47:10
}
bb31: {
_40 = discriminant(_10); // scope 3 at 1.rs:47:10: 47:10
switchInt(_40) -> [0isize: bb16, otherwise: bb30]; // scope 3 at 1.rs:47:10: 47:10
}
bb32: {
switchInt(_35) -> [0u8: bb16, otherwise: bb31]; // scope 3 at 1.rs:47:10: 47:10
}
bb33: {
drop(_5) -> bb17; // scope 2 at 1.rs:48:6: 48:6
}
bb34: {
switchInt(_38) -> [0u8: bb17, otherwise: bb35]; // scope 2 at 1.rs:48:6: 48:6
}
bb35: {
_38 = const false; // scope 2 at 1.rs:48:6: 48:6
drop(((_5 as Some).0: E)) -> bb17; // scope 2 at 1.rs:48:6: 48:6
}
bb36: {
drop(_5) -> bb25; // scope 2 at 1.rs:48:6: 48:6
}
bb37: {
switchInt(_38) -> [0u8: bb25, otherwise: bb38]; // scope 2 at 1.rs:48:6: 48:6
}
bb38: {
_38 = const false; // scope 2 at 1.rs:48:6: 48:6
drop(((_5 as Some).0: E)) -> bb25; // scope 2 at 1.rs:48:6: 48:6
}
}
fn E::F(_1: K) -> E {
let mut _0: E; // return pointer
bb0: {
_0 = E::F(_1,); // scope 0 at 1.rs:22:5: 22:9
return; // scope 0 at 1.rs:22:5: 22:9
}
}
fn main() -> () {
let mut _0: (); // return pointer
let mut _1: std::result::Result<(), (u32, u8)>;
let mut _2: (u32, u8);
bb0: {
StorageLive(_1); // scope 0 at 1.rs:4:13: 4:22
StorageLive(_2); // scope 0 at 1.rs:4:15: 4:21
_2 = (const 0u32, const 0u8); // scope 0 at 1.rs:4:15: 4:21
_1 = const g(_2) -> bb1; // scope 0 at 1.rs:4:13: 4:22
}
bb1: {
StorageDead(_2); // scope 0 at 1.rs:4:22: 4:22
StorageDead(_1); // scope 0 at 1.rs:4:23: 4:23
_0 = (); // scope 0 at 1.rs:3:11: 5:2
return; // scope 0 at 1.rs:5:2: 5:2
}
}
LLVM-IR
; ModuleID = '1.cgu-0.rs'
source_filename = "1.cgu-0.rs"
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-darwin"
%str_slice = type { i8*, i64 }
%"core::option::Option<(u32, u8)>" = type { i32, [0 x i32], [2 x i32] }
%X = type { i64, [0 x i64], [1 x i64] }
%"core::option::Option<E>" = type { i64, [0 x i64], [5 x i64] }
%E = type { i8, [7 x i8], [4 x i64] }
%"core::result::Result<(), (u32, u8)>" = type { i32, [0 x i32], [2 x i32] }
%"unwind::libunwind::_Unwind_Exception" = type { i64, [0 x i8], void (i32, %"unwind::libunwind::_Unwind_Exception"*)*, [0 x i8], [6 x i64], [0 x i8] }
%"unwind::libunwind::_Unwind_Context" = type {}
@"_ZN38_$LT$core..option..Option$LT$T$GT$$GT$6unwrap14_MSG_FILE_LINE17he9e3266a381f7b99E" = external global { %str_slice, [0 x i8], %str_slice, [0 x i8], i32, [4 x i8] }
; Function Attrs: inlinehint
define internal fastcc i64 @"_ZN38_$LT$core..option..Option$LT$T$GT$$GT$6unwrap17hdbd5a86115aeeb48E"(%"core::option::Option<(u32, u8)>"* noalias nocapture readonly dereferenceable(12)) unnamed_addr #0 personality i32 (i32, i32, i64, %"unwind::libunwind::_Unwind_Exception"*, %"unwind::libunwind::_Unwind_Context"*)* @rust_eh_personality {
start:
%self.sroa.0.0..sroa_idx = getelementptr inbounds %"core::option::Option<(u32, u8)>", %"core::option::Option<(u32, u8)>"* %0, i64 0, i32 0
%self.sroa.0.0.copyload = load i32, i32* %self.sroa.0.0..sroa_idx, align 4
%cond = icmp eq i32 %self.sroa.0.0.copyload, 0
br i1 %cond, label %bb3, label %bb4
bb3: ; preds = %start
tail call void @_ZN4core9panicking5panic17hafbe89720e5223c3E({ %str_slice, [0 x i8], %str_slice, [0 x i8], i32, [4 x i8] }* noalias nonnull readonly dereferenceable(40) @"_ZN38_$LT$core..option..Option$LT$T$GT$$GT$6unwrap14_MSG_FILE_LINE17he9e3266a381f7b99E")
unreachable
bb4: ; preds = %start
%self.sroa.5.0..sroa_idx = getelementptr inbounds %"core::option::Option<(u32, u8)>", %"core::option::Option<(u32, u8)>"* %0, i64 0, i32 2, i64 1
%self.sroa.5.0..sroa_cast = bitcast i32* %self.sroa.5.0..sroa_idx to i8*
%self.sroa.5.0.copyload = load i8, i8* %self.sroa.5.0..sroa_cast, align 4
%self.sroa.4.0..sroa_idx3 = getelementptr inbounds %"core::option::Option<(u32, u8)>", %"core::option::Option<(u32, u8)>"* %0, i64 0, i32 2, i64 0
%self.sroa.4.0.copyload = load i32, i32* %self.sroa.4.0..sroa_idx3, align 4
%ret.sroa.2.0.insert.ext = zext i8 %self.sroa.5.0.copyload to i64
%ret.sroa.2.0.insert.shift = shl nuw nsw i64 %ret.sroa.2.0.insert.ext, 32
%ret.sroa.0.0.insert.ext = zext i32 %self.sroa.4.0.copyload to i64
%ret.sroa.0.0.insert.insert = or i64 %ret.sroa.2.0.insert.shift, %ret.sroa.0.0.insert.ext
ret i64 %ret.sroa.0.0.insert.insert
}
; Function Attrs: inlinehint nounwind
define internal fastcc void @_ZN4core3ptr13drop_in_place17h187871343964cdfcE(%X** nocapture readonly) unnamed_addr #1 {
start:
%1 = load %X*, %X** %0, align 8, !nonnull !1
tail call fastcc void @_ZN4core3ptr13drop_in_place17h48c9e5bc21e188aaE(%X* nonnull %1)
%2 = load %X*, %X** %0, align 8, !nonnull !1
tail call fastcc void @_ZN5alloc4heap8box_free17h52fcf778f557f0b4E(%X* nonnull %2)
ret void
}
; Function Attrs: inlinehint nounwind
define internal fastcc void @_ZN4core3ptr13drop_in_place17h31d8df590941a85fE(%"core::option::Option<E>"* readonly) unnamed_addr #1 {
start:
%1 = getelementptr inbounds %"core::option::Option<E>", %"core::option::Option<E>"* %0, i64 0, i32 0
%2 = load i64, i64* %1, align 8, !range !2
%cond = icmp eq i64 %2, 0
br i1 %cond, label %bb1, label %bb2
bb1: ; preds = %start, %bb2
ret void
bb2: ; preds = %start
%3 = getelementptr inbounds %"core::option::Option<E>", %"core::option::Option<E>"* %0, i64 0, i32 2
%4 = bitcast [5 x i64]* %3 to %E*
tail call fastcc void @_ZN4core3ptr13drop_in_place17hbf6cf7e003a035e6E(%E* %4)
br label %bb1
}
; Function Attrs: inlinehint nounwind
define internal fastcc void @_ZN4core3ptr13drop_in_place17h48c9e5bc21e188aaE(%X* nocapture readonly) unnamed_addr #1 {
start:
%1 = getelementptr inbounds %X, %X* %0, i64 0, i32 0
%2 = load i64, i64* %1, align 8, !range !3
%trunc = trunc i64 %2 to i2
switch i2 %trunc, label %bb1 [
i2 0, label %bb2
i2 1, label %bb3
]
bb1: ; preds = %bb2, %bb3, %start
ret void
bb2: ; preds = %start
%3 = getelementptr inbounds %X, %X* %0, i64 0, i32 2
%4 = bitcast [1 x i64]* %3 to %X**
tail call fastcc void @_ZN4core3ptr13drop_in_place17h187871343964cdfcE(%X** %4)
br label %bb1
bb3: ; preds = %start
%5 = getelementptr inbounds %X, %X* %0, i64 0, i32 2
%6 = bitcast [1 x i64]* %5 to %X**
tail call fastcc void @_ZN4core3ptr13drop_in_place17h187871343964cdfcE(%X** %6)
br label %bb1
}
; Function Attrs: inlinehint nounwind
define internal fastcc void @_ZN4core3ptr13drop_in_place17hbf6cf7e003a035e6E(%E* readonly) unnamed_addr #1 {
start:
%1 = getelementptr inbounds %E, %E* %0, i64 0, i32 0
%2 = load i8, i8* %1, align 1, !range !4
%cond = icmp eq i8 %2, 0
br i1 %cond, label %bb1, label %slice_loop_body
bb1: ; preds = %slice_loop_body, %start
ret void
slice_loop_body: ; preds = %start
%3 = getelementptr inbounds %E, %E* %0, i64 0, i32 2
%4 = bitcast [4 x i64]* %3 to %X*
%5 = getelementptr inbounds %E, %E* %0, i64 0, i32 2, i64 2
%6 = bitcast i64* %5 to %X*
tail call fastcc void @_ZN4core3ptr13drop_in_place17h48c9e5bc21e188aaE(%X* %4)
tail call fastcc void @_ZN4core3ptr13drop_in_place17h48c9e5bc21e188aaE(%X* %6)
br label %bb1
}
; Function Attrs: norecurse nounwind readnone
define internal fastcc i64 @"_ZN50_$LT$T$u20$as$u20$core..convert..From$LT$T$GT$$GT$4from17hd676c2e417a31d76E"(i64) unnamed_addr #2 {
start:
%ret.sroa.0.0.insert.insert = and i64 %0, 1099511627775
ret i64 %ret.sroa.0.0.insert.insert
}
; Function Attrs: inlinehint nounwind
define internal fastcc void @_ZN5alloc4heap10deallocate17h0cf606d4dc6542b7E(i8*) unnamed_addr #1 {
start:
tail call void @__rust_deallocate(i8* %0, i64 16, i64 8)
ret void
}
; Function Attrs: inlinehint nounwind
define internal fastcc void @_ZN5alloc4heap8box_free17h52fcf778f557f0b4E(%X*) unnamed_addr #1 {
start:
%1 = bitcast %X* %0 to i8*
tail call fastcc void @_ZN5alloc4heap10deallocate17h0cf606d4dc6542b7E(i8* %1)
ret void
}
; Function Attrs: norecurse nounwind
define internal fastcc void @"_ZN77_$LT$core..result..Result$LT$U$C$$u20$V$GT$$u20$as$u20$core..ops..Carrier$GT$10from_error17h983ed059e5df6262E"(%"core::result::Result<(), (u32, u8)>"* noalias nocapture sret dereferenceable(12), i64) unnamed_addr #3 {
start:
%abi_cast.sroa.0.0.extract.trunc = trunc i64 %1 to i32
%abi_cast.sroa.4.0.extract.shift = lshr i64 %1, 32
%abi_cast.sroa.4.0.extract.trunc = trunc i64 %abi_cast.sroa.4.0.extract.shift to i8
%2 = getelementptr inbounds %"core::result::Result<(), (u32, u8)>", %"core::result::Result<(), (u32, u8)>"* %0, i64 0, i32 0
store i32 1, i32* %2, align 4
%3 = getelementptr inbounds %"core::result::Result<(), (u32, u8)>", %"core::result::Result<(), (u32, u8)>"* %0, i64 0, i32 2, i64 0
store i32 %abi_cast.sroa.0.0.extract.trunc, i32* %3, align 4
%4 = getelementptr inbounds %"core::result::Result<(), (u32, u8)>", %"core::result::Result<(), (u32, u8)>"* %0, i64 0, i32 2, i64 1
%5 = bitcast i32* %4 to i8*
store i8 %abi_cast.sroa.4.0.extract.trunc, i8* %5, align 4
ret void
}
; Function Attrs: norecurse nounwind
define internal fastcc void @"_ZN77_$LT$core..result..Result$LT$U$C$$u20$V$GT$$u20$as$u20$core..ops..Carrier$GT$12from_success17h4169241993d9016dE"(%"core::result::Result<(), (u32, u8)>"* noalias nocapture sret dereferenceable(12)) unnamed_addr #3 {
start:
%1 = getelementptr inbounds %"core::result::Result<(), (u32, u8)>", %"core::result::Result<(), (u32, u8)>"* %0, i64 0, i32 0
store i32 0, i32* %1, align 4
ret void
}
; Function Attrs: norecurse nounwind
define internal fastcc void @"_ZN77_$LT$core..result..Result$LT$U$C$$u20$V$GT$$u20$as$u20$core..ops..Carrier$GT$9translate17had4b200d2ffbc2e9E"(%"core::result::Result<(), (u32, u8)>"* noalias nocapture sret dereferenceable(12), %"core::result::Result<(), (u32, u8)>"* noalias nocapture readonly dereferenceable(12)) unnamed_addr #3 personality i32 (i32, i32, i64, %"unwind::libunwind::_Unwind_Exception"*, %"unwind::libunwind::_Unwind_Context"*)* @rust_eh_personality {
start:
%self.sroa.0.0..sroa_idx = getelementptr inbounds %"core::result::Result<(), (u32, u8)>", %"core::result::Result<(), (u32, u8)>"* %1, i64 0, i32 0
%self.sroa.0.0.copyload = load i32, i32* %self.sroa.0.0..sroa_idx, align 4
%cond = icmp eq i32 %self.sroa.0.0.copyload, 0
br i1 %cond, label %bb3, label %bb4
bb3: ; preds = %start
tail call fastcc void @"_ZN77_$LT$core..result..Result$LT$U$C$$u20$V$GT$$u20$as$u20$core..ops..Carrier$GT$12from_success17h4169241993d9016dE"(%"core::result::Result<(), (u32, u8)>"* noalias nocapture nonnull sret dereferenceable(12) %0)
br label %bb5
bb4: ; preds = %start
%self.sroa.7.0..sroa_idx = getelementptr inbounds %"core::result::Result<(), (u32, u8)>", %"core::result::Result<(), (u32, u8)>"* %1, i64 0, i32 2, i64 1
%self.sroa.7.0..sroa_cast = bitcast i32* %self.sroa.7.0..sroa_idx to i8*
%self.sroa.7.0.copyload = load i8, i8* %self.sroa.7.0..sroa_cast, align 4
%self.sroa.6.0..sroa_idx6 = getelementptr inbounds %"core::result::Result<(), (u32, u8)>", %"core::result::Result<(), (u32, u8)>"* %1, i64 0, i32 2, i64 0
%self.sroa.6.0.copyload = load i32, i32* %self.sroa.6.0..sroa_idx6, align 4
%arg.sroa.2.0.insert.ext = zext i8 %self.sroa.7.0.copyload to i64
%arg.sroa.2.0.insert.shift = shl nuw nsw i64 %arg.sroa.2.0.insert.ext, 32
%arg.sroa.0.0.insert.ext = zext i32 %self.sroa.6.0.copyload to i64
%arg.sroa.0.0.insert.insert = or i64 %arg.sroa.2.0.insert.shift, %arg.sroa.0.0.insert.ext
tail call fastcc void @"_ZN77_$LT$core..result..Result$LT$U$C$$u20$V$GT$$u20$as$u20$core..ops..Carrier$GT$10from_error17h983ed059e5df6262E"(%"core::result::Result<(), (u32, u8)>"* noalias nocapture nonnull sret dereferenceable(12) %0, i64 %arg.sroa.0.0.insert.insert)
br label %bb5
bb5: ; preds = %bb4, %bb3
ret void
}
define internal void @_ZN2_14main17hb2ffcf74c477bad3E() unnamed_addr #4 {
start:
%_1 = alloca %"core::result::Result<(), (u32, u8)>", align 8
%0 = bitcast %"core::result::Result<(), (u32, u8)>"* %_1 to i8*
call void @llvm.lifetime.start(i64 12, i8* nonnull %0)
call fastcc void @_ZN2_11g17h62cbbaab7a2481a3E(%"core::result::Result<(), (u32, u8)>"* noalias nocapture nonnull sret dereferenceable(12) %_1)
call void @llvm.lifetime.end(i64 12, i8* nonnull %0)
ret void
}
define internal fastcc void @_ZN2_11g17h62cbbaab7a2481a3E(%"core::result::Result<(), (u32, u8)>"* noalias nocapture sret dereferenceable(12)) unnamed_addr #4 {
start:
%_28 = alloca %"core::option::Option<(u32, u8)>", align 8
%_26 = alloca %"core::result::Result<(), (u32, u8)>", align 8
%_25 = alloca %"core::result::Result<(), (u32, u8)>", align 8
%_17 = alloca %"core::result::Result<(), (u32, u8)>", align 8
%_16 = alloca %"core::result::Result<(), (u32, u8)>", align 8
%infix_or_postfix = alloca %E, align 8
%status = alloca %"core::option::Option<E>", align 8
%y.sroa.7 = alloca [3 x i8], align 1
%y.sroa.7.0..sroa_idx27 = getelementptr inbounds [3 x i8], [3 x i8]* %y.sroa.7, i64 0, i64 0
call void @llvm.lifetime.start(i64 3, i8* nonnull %y.sroa.7.0..sroa_idx27)
%1 = bitcast %"core::option::Option<E>"* %status to i8*
%2 = getelementptr inbounds %"core::option::Option<E>", %"core::option::Option<E>"* %status, i64 0, i32 0
%3 = bitcast %"core::option::Option<E>"* %status to { i64, [0 x i8], %E, [0 x i8] }*
%_8.sroa.0.0..sroa_idx = getelementptr inbounds %"core::option::Option<E>", %"core::option::Option<E>"* %status, i64 0, i32 2
%4 = bitcast [5 x i64]* %_8.sroa.0.0..sroa_idx to i8*
%_8.sroa.4.0..sroa_idx = getelementptr inbounds { i64, [0 x i8], %E, [0 x i8] }, { i64, [0 x i8], %E, [0 x i8] }* %3, i64 0, i32 2, i32 1, i64 0
%5 = getelementptr inbounds %"core::option::Option<E>", %"core::option::Option<E>"* %status, i64 0, i32 0
%6 = getelementptr inbounds %E, %E* %infix_or_postfix, i64 0, i32 0
%7 = getelementptr inbounds %"core::option::Option<E>", %"core::option::Option<E>"* %status, i64 0, i32 2
%8 = bitcast [5 x i64]* %7 to i8*
%9 = bitcast %"core::result::Result<(), (u32, u8)>"* %_16 to i8*
%10 = bitcast %"core::result::Result<(), (u32, u8)>"* %_17 to i8*
%11 = getelementptr inbounds %"core::result::Result<(), (u32, u8)>", %"core::result::Result<(), (u32, u8)>"* %_17, i64 0, i32 0
%12 = getelementptr inbounds %"core::result::Result<(), (u32, u8)>", %"core::result::Result<(), (u32, u8)>"* %_16, i64 0, i32 0
%13 = getelementptr inbounds %E, %E* %infix_or_postfix, i64 0, i32 0
%14 = getelementptr inbounds %E, %E* %infix_or_postfix, i64 0, i32 0
%15 = getelementptr inbounds %"core::option::Option<E>", %"core::option::Option<E>"* %status, i64 0, i32 2
%16 = bitcast [5 x i64]* %15 to %E*
%17 = bitcast %"core::result::Result<(), (u32, u8)>"* %_25 to i8*
%18 = bitcast %"core::result::Result<(), (u32, u8)>"* %_26 to i8*
%19 = bitcast %"core::option::Option<(u32, u8)>"* %_28 to i8*
%y.sroa.0.0..sroa_idx = getelementptr inbounds %"core::option::Option<(u32, u8)>", %"core::option::Option<(u32, u8)>"* %_28, i64 0, i32 0
%y.sroa.5.0..sroa_idx23 = getelementptr inbounds %"core::option::Option<(u32, u8)>", %"core::option::Option<(u32, u8)>"* %_28, i64 0, i32 2, i64 0
%y.sroa.6.0..sroa_idx = getelementptr inbounds %"core::option::Option<(u32, u8)>", %"core::option::Option<(u32, u8)>"* %_28, i64 0, i32 2, i64 1
%y.sroa.6.0..sroa_cast = bitcast i32* %y.sroa.6.0..sroa_idx to i8*
%y.sroa.7.0..sroa_raw_idx = getelementptr inbounds i8, i8* %19, i64 9
%20 = getelementptr inbounds %"core::result::Result<(), (u32, u8)>", %"core::result::Result<(), (u32, u8)>"* %_26, i64 0, i32 0
%21 = getelementptr inbounds %"core::result::Result<(), (u32, u8)>", %"core::result::Result<(), (u32, u8)>"* %_26, i64 0, i32 2, i64 0
%22 = getelementptr inbounds %"core::result::Result<(), (u32, u8)>", %"core::result::Result<(), (u32, u8)>"* %_26, i64 0, i32 2, i64 1
%23 = bitcast i32* %22 to i8*
%24 = getelementptr inbounds %"core::result::Result<(), (u32, u8)>", %"core::result::Result<(), (u32, u8)>"* %_25, i64 0, i32 0
%25 = getelementptr inbounds %"core::option::Option<E>", %"core::option::Option<E>"* %status, i64 0, i32 0
br label %bb1
bb1: ; preds = %bb25, %start
%y.sroa.0.0 = phi i32 [ 0, %start ], [ %y.sroa.0.14, %bb25 ]
%pt.sroa.0.0 = phi i1 [ true, %start ], [ false, %bb25 ]
%_35.0 = phi i8 [ 0, %start ], [ %_35.2, %bb25 ]
call void @llvm.lifetime.start(i64 48, i8* nonnull %1)
br i1 %pt.sroa.0.0, label %bb4, label %bb4.thread
bb4.thread: ; preds = %bb1
store i64 0, i64* %25, align 8
call void @llvm.lifetime.start(i64 12, i8* nonnull %17)
call void @llvm.lifetime.start(i64 12, i8* nonnull %18)
call void @llvm.lifetime.start(i64 12, i8* nonnull %19)
store i32 %y.sroa.0.0, i32* %y.sroa.0.0..sroa_idx, align 8
store i32 1, i32* %y.sroa.5.0..sroa_idx23, align 4
store i8 0, i8* %y.sroa.6.0..sroa_cast, align 4
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %y.sroa.7.0..sroa_raw_idx, i8* nonnull %y.sroa.7.0..sroa_idx27, i64 3, i32 1, i1 false)
%26 = call fastcc i64 @"_ZN38_$LT$core..option..Option$LT$T$GT$$GT$6unwrap17hdbd5a86115aeeb48E"(%"core::option::Option<(u32, u8)>"* noalias nocapture nonnull dereferenceable(12) %_28)
%abi_cast1.sroa.0.0.extract.trunc = trunc i64 %26 to i32
%abi_cast1.sroa.4.0.extract.shift = lshr i64 %26, 32
%abi_cast1.sroa.4.0.extract.trunc = trunc i64 %abi_cast1.sroa.4.0.extract.shift to i8
call void @llvm.lifetime.end(i64 12, i8* nonnull %19)
store i32 1, i32* %20, align 8
store i32 %abi_cast1.sroa.0.0.extract.trunc, i32* %21, align 4
store i8 %abi_cast1.sroa.4.0.extract.trunc, i8* %23, align 4
call fastcc void @"_ZN77_$LT$core..result..Result$LT$U$C$$u20$V$GT$$u20$as$u20$core..ops..Carrier$GT$9translate17had4b200d2ffbc2e9E"(%"core::result::Result<(), (u32, u8)>"* noalias nocapture nonnull sret dereferenceable(12) %_25, %"core::result::Result<(), (u32, u8)>"* noalias nocapture nonnull dereferenceable(12) %_26)
call void @llvm.lifetime.end(i64 12, i8* nonnull %18)
%27 = load i32, i32* %24, align 8, !range !5
%cond9 = icmp eq i32 %27, 0
br i1 %cond9, label %bb7, label %bb32
bb4: ; preds = %bb1
store i64 1, i64* %2, align 8
store i8 0, i8* %4, align 8
store i8 0, i8* %_8.sroa.4.0..sroa_idx, align 1
call void @llvm.lifetime.start(i64 40, i8* nonnull %6)
call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull %6, i8* nonnull %8, i64 40, i32 8, i1 false)
%28 = load i8, i8* %6, align 8, !range !4
%cond14 = icmp eq i8 %28, 0
br i1 %cond14, label %bb9, label %bb27
bb7: ; preds = %bb4.thread
call void @llvm.lifetime.end(i64 12, i8* nonnull %17)
%29 = and i8 %_35.0, 1
%30 = icmp eq i8 %29, 0
br i1 %30, label %bb24, label %bb28
bb9: ; preds = %bb4
call void @llvm.lifetime.start(i64 12, i8* nonnull %9)
call void @llvm.lifetime.start(i64 12, i8* nonnull %10)
store i32 0, i32* %11, align 8
call fastcc void @"_ZN77_$LT$core..result..Result$LT$U$C$$u20$V$GT$$u20$as$u20$core..ops..Carrier$GT$9translate17had4b200d2ffbc2e9E"(%"core::result::Result<(), (u32, u8)>"* noalias nocapture nonnull sret dereferenceable(12) %_16, %"core::result::Result<(), (u32, u8)>"* noalias nocapture nonnull dereferenceable(12) %_17)
call void @llvm.lifetime.end(i64 12, i8* nonnull %10)
%31 = load i32, i32* %12, align 8, !range !5
%cond15 = icmp eq i32 %31, 0
br i1 %cond15, label %bb12, label %bb32.thread
bb12: ; preds = %bb9
call void @llvm.lifetime.end(i64 12, i8* nonnull %9)
br label %bb28
bb32.thread: ; preds = %bb9
%32 = getelementptr inbounds %"core::result::Result<(), (u32, u8)>", %"core::result::Result<(), (u32, u8)>"* %_16, i64 0, i32 2, i64 0
%33 = getelementptr inbounds %"core::result::Result<(), (u32, u8)>", %"core::result::Result<(), (u32, u8)>"* %_16, i64 0, i32 2, i64 1
%34 = bitcast i32* %33 to i8*
%35 = load i32, i32* %32, align 4
%36 = load i8, i8* %34, align 4
%arg5.sroa.2.0.insert.ext = zext i8 %36 to i64
%arg5.sroa.2.0.insert.shift = shl nuw nsw i64 %arg5.sroa.2.0.insert.ext, 32
%arg5.sroa.0.0.insert.ext = zext i32 %35 to i64
%arg5.sroa.0.0.insert.insert = or i64 %arg5.sroa.2.0.insert.shift, %arg5.sroa.0.0.insert.ext
%37 = call fastcc i64 @"_ZN50_$LT$T$u20$as$u20$core..convert..From$LT$T$GT$$GT$4from17hd676c2e417a31d76E"(i64 %arg5.sroa.0.0.insert.insert)
%arg8.sroa.0.0.insert.insert = and i64 %37, 1099511627775
call fastcc void @"_ZN77_$LT$core..result..Result$LT$U$C$$u20$V$GT$$u20$as$u20$core..ops..Carrier$GT$10from_error17h983ed059e5df6262E"(%"core::result::Result<(), (u32, u8)>"* noalias nocapture nonnull sret dereferenceable(12) %0, i64 %arg8.sroa.0.0.insert.insert)
call void @llvm.lifetime.end(i64 12, i8* nonnull %9)
br label %bb31
bb16: ; preds = %bb32, %bb31, %bb30
%_38.29 = phi i1 [ true, %bb32 ], [ %_38.28, %bb31 ], [ %_38.28, %bb30 ]
%38 = getelementptr inbounds %E, %E* %infix_or_postfix, i64 0, i32 0
call void @llvm.lifetime.end(i64 40, i8* nonnull %38)
%39 = load i64, i64* %5, align 8, !range !2
%cond10 = icmp eq i64 %39, 1
br i1 %cond10, label %bb34, label %bb33
bb17: ; preds = %bb35, %bb34, %bb33
call void @llvm.lifetime.end(i64 48, i8* nonnull %1)
call void @llvm.lifetime.end(i64 3, i8* nonnull %y.sroa.7.0..sroa_idx27)
ret void
bb24: ; preds = %bb7, %bb28, %bb27
%_38.17 = phi i1 [ %_38.16.ph, %bb28 ], [ %_38.1620, %bb27 ], [ true, %bb7 ]
%y.sroa.0.14 = phi i32 [ %y.sroa.0.13.ph, %bb28 ], [ %y.sroa.0.1321, %bb27 ], [ %y.sroa.0.0, %bb7 ]
%_35.2 = phi i8 [ %_35.15.ph, %bb28 ], [ 0, %bb27 ], [ %_35.0, %bb7 ]
call void @llvm.lifetime.end(i64 40, i8* nonnull %14)
%40 = load i64, i64* %5, align 8, !range !2
%cond12 = icmp eq i64 %40, 1
br i1 %cond12, label %bb37, label %bb36
bb25: ; preds = %bb38, %bb37, %bb36
call void @llvm.lifetime.end(i64 48, i8* nonnull %1)
br label %bb1
bb27: ; preds = %bb4, %bb28
%y.sroa.0.1321 = phi i32 [ %y.sroa.0.13.ph, %bb28 ], [ %y.sroa.0.0, %bb4 ]
%_38.1620 = phi i1 [ %_38.16.ph, %bb28 ], [ false, %bb4 ]
call fastcc void @_ZN4core3ptr13drop_in_place17hbf6cf7e003a035e6E(%E* nonnull %infix_or_postfix)
br label %bb24
bb28: ; preds = %bb12, %bb7
%_38.16.ph = phi i1 [ false, %bb12 ], [ true, %bb7 ]
%_35.15.ph = phi i8 [ 1, %bb12 ], [ %_35.0, %bb7 ]
%y.sroa.0.13.ph = phi i32 [ 1, %bb12 ], [ %y.sroa.0.0, %bb7 ]
%.pr18 = load i8, i8* %13, align 8
%cond13 = icmp eq i8 %.pr18, 0
br i1 %cond13, label %bb24, label %bb27
bb30: ; preds = %bb31
call fastcc void @_ZN4core3ptr13drop_in_place17hbf6cf7e003a035e6E(%E* nonnull %infix_or_postfix)
br label %bb16
bb31: ; preds = %bb32.thread, %bb32
%_38.28 = phi i1 [ false, %bb32.thread ], [ true, %bb32 ]
%41 = getelementptr inbounds %E, %E* %infix_or_postfix, i64 0, i32 0
%42 = load i8, i8* %41, align 8, !range !4
%cond11 = icmp eq i8 %42, 0
br i1 %cond11, label %bb16, label %bb30
bb32: ; preds = %bb4.thread
%43 = getelementptr inbounds %"core::result::Result<(), (u32, u8)>", %"core::result::Result<(), (u32, u8)>"* %_25, i64 0, i32 2, i64 0
%44 = getelementptr inbounds %"core::result::Result<(), (u32, u8)>", %"core::result::Result<(), (u32, u8)>"* %_25, i64 0, i32 2, i64 1
%45 = bitcast i32* %44 to i8*
%46 = load i32, i32* %43, align 4
%47 = load i8, i8* %45, align 4
%arg.sroa.2.0.insert.ext = zext i8 %47 to i64
%arg.sroa.2.0.insert.shift = shl nuw nsw i64 %arg.sroa.2.0.insert.ext, 32
%arg.sroa.0.0.insert.ext = zext i32 %46 to i64
%arg.sroa.0.0.insert.insert = or i64 %arg.sroa.2.0.insert.shift, %arg.sroa.0.0.insert.ext
%48 = call fastcc i64 @"_ZN50_$LT$T$u20$as$u20$core..convert..From$LT$T$GT$$GT$4from17hd676c2e417a31d76E"(i64 %arg.sroa.0.0.insert.insert)
%arg4.sroa.0.0.insert.insert = and i64 %48, 1099511627775
call fastcc void @"_ZN77_$LT$core..result..Result$LT$U$C$$u20$V$GT$$u20$as$u20$core..ops..Carrier$GT$10from_error17h983ed059e5df6262E"(%"core::result::Result<(), (u32, u8)>"* noalias nocapture nonnull sret dereferenceable(12) %0, i64 %arg4.sroa.0.0.insert.insert)
call void @llvm.lifetime.end(i64 12, i8* nonnull %17)
%49 = and i8 %_35.0, 1
%50 = icmp eq i8 %49, 0
br i1 %50, label %bb16, label %bb31
bb33: ; preds = %bb16
call fastcc void @_ZN4core3ptr13drop_in_place17h31d8df590941a85fE(%"core::option::Option<E>"* nonnull %status)
br label %bb17
bb34: ; preds = %bb16
br i1 %_38.29, label %bb35, label %bb17
bb35: ; preds = %bb34
%51 = getelementptr inbounds %"core::option::Option<E>", %"core::option::Option<E>"* %status, i64 0, i32 2
%52 = bitcast [5 x i64]* %51 to %E*
call fastcc void @_ZN4core3ptr13drop_in_place17hbf6cf7e003a035e6E(%E* %52)
br label %bb17
bb36: ; preds = %bb24
call fastcc void @_ZN4core3ptr13drop_in_place17h31d8df590941a85fE(%"core::option::Option<E>"* nonnull %status)
br label %bb25
bb37: ; preds = %bb24
br i1 %_38.17, label %bb38, label %bb25
bb38: ; preds = %bb37
call fastcc void @_ZN4core3ptr13drop_in_place17hbf6cf7e003a035e6E(%E* nonnull %16)
br label %bb25
}
declare i32 @rust_eh_personality(i32, i32, i64, %"unwind::libunwind::_Unwind_Exception"*, %"unwind::libunwind::_Unwind_Context"*) unnamed_addr #4
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.start(i64, i8* nocapture) #5
; Function Attrs: argmemonly nounwind
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) #5
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.end(i64, i8* nocapture) #5
; Function Attrs: cold noinline noreturn
declare void @_ZN4core9panicking5panic17hafbe89720e5223c3E({ %str_slice, [0 x i8], %str_slice, [0 x i8], i32, [4 x i8] }* noalias readonly dereferenceable(40)) unnamed_addr #6
; Function Attrs: nounwind
declare void @__rust_deallocate(i8*, i64, i64) unnamed_addr #7
define i64 @main(i64, i8**) unnamed_addr #4 {
top:
%2 = tail call i64 @_ZN3std2rt10lang_start17hbda94898b2b88ae4E(i8* bitcast (void ()* @_ZN2_14main17hb2ffcf74c477bad3E to i8*), i64 %0, i8** %1)
ret i64 %2
}
declare i64 @_ZN3std2rt10lang_start17hbda94898b2b88ae4E(i8*, i64, i8**) unnamed_addr #4
attributes #0 = { inlinehint "no-frame-pointer-elim"="true" }
attributes #1 = { inlinehint nounwind "no-frame-pointer-elim"="true" }
attributes #2 = { norecurse nounwind readnone "no-frame-pointer-elim"="true" }
attributes #3 = { norecurse nounwind "no-frame-pointer-elim"="true" }
attributes #4 = { "no-frame-pointer-elim"="true" }
attributes #5 = { argmemonly nounwind }
attributes #6 = { cold noinline noreturn "no-frame-pointer-elim"="true" }
attributes #7 = { nounwind "no-frame-pointer-elim"="true" }
!llvm.module.flags = !{!0}
!0 = !{i32 1, !"PIE Level", i32 2}
!1 = !{}
!2 = !{i64 0, i64 2}
!3 = !{i64 0, i64 3}
!4 = !{i8 0, i8 2}
!5 = !{i32 0, i32 2}
ASM
.section __TEXT,__text,regular,pure_instructions
.p2align 4, 0x90
__ZN38_$LT$core..option..Option$LT$T$GT$$GT$6unwrap17hdbd5a86115aeeb48E:
.cfi_startproc
cmpl $0, (%rdi)
je LBB0_2
movzbl 8(%rdi), %ecx
shlq $32, %rcx
movl 4(%rdi), %eax
orq %rcx, %rax
retq
LBB0_2:
pushq %rbp
Lcfi0:
.cfi_def_cfa_offset 16
Lcfi1:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Lcfi2:
.cfi_def_cfa_register %rbp
movq __ZN38_$LT$core..option..Option$LT$T$GT$$GT$6unwrap14_MSG_FILE_LINE17he9e3266a381f7b99E@GOTPCREL(%rip), %rdi
callq __ZN4core9panicking5panic17hafbe89720e5223c3E
.cfi_endproc
.p2align 4, 0x90
__ZN4core3ptr13drop_in_place17h187871343964cdfcE:
pushq %rbp
movq %rsp, %rbp
pushq %rbx
pushq %rax
movq %rdi, %rbx
movq (%rbx), %rdi
callq __ZN4core3ptr13drop_in_place17h48c9e5bc21e188aaE
movq (%rbx), %rdi
addq $8, %rsp
popq %rbx
popq %rbp
jmp __ZN5alloc4heap8box_free17h52fcf778f557f0b4E
.p2align 4, 0x90
__ZN4core3ptr13drop_in_place17h31d8df590941a85fE:
pushq %rbp
movq %rsp, %rbp
cmpq $0, (%rdi)
je LBB2_1
addq $8, %rdi
popq %rbp
jmp __ZN4core3ptr13drop_in_place17hbf6cf7e003a035e6E
LBB2_1:
popq %rbp
retq
.p2align 4, 0x90
__ZN4core3ptr13drop_in_place17h48c9e5bc21e188aaE:
pushq %rbp
movq %rsp, %rbp
movb (%rdi), %al
testb %al, %al
je LBB3_3
cmpb $1, %al
jne LBB3_2
LBB3_3:
addq $8, %rdi
popq %rbp
jmp __ZN4core3ptr13drop_in_place17h187871343964cdfcE
LBB3_2:
popq %rbp
retq
.p2align 4, 0x90
__ZN4core3ptr13drop_in_place17hbf6cf7e003a035e6E:
pushq %rbp
movq %rsp, %rbp
pushq %rbx
pushq %rax
movq %rdi, %rbx
cmpb $0, (%rbx)
je LBB4_1
leaq 8(%rbx), %rdi
addq $24, %rbx
callq __ZN4core3ptr13drop_in_place17h48c9e5bc21e188aaE
movq %rbx, %rdi
addq $8, %rsp
popq %rbx
popq %rbp
jmp __ZN4core3ptr13drop_in_place17h48c9e5bc21e188aaE
LBB4_1:
addq $8, %rsp
popq %rbx
popq %rbp
retq
.p2align 4, 0x90
__ZN50_$LT$T$u20$as$u20$core..convert..From$LT$T$GT$$GT$4from17hd676c2e417a31d76E:
pushq %rbp
movq %rsp, %rbp
movabsq $1099511627775, %rax
andq %rdi, %rax
popq %rbp
retq
.p2align 4, 0x90
__ZN5alloc4heap10deallocate17h0cf606d4dc6542b7E:
pushq %rbp
movq %rsp, %rbp
movl $16, %esi
movl $8, %edx
popq %rbp
jmp ___rust_deallocate
.p2align 4, 0x90
__ZN5alloc4heap8box_free17h52fcf778f557f0b4E:
pushq %rbp
movq %rsp, %rbp
popq %rbp
jmp __ZN5alloc4heap10deallocate17h0cf606d4dc6542b7E
.p2align 4, 0x90
__ZN77_$LT$core..result..Result$LT$U$C$$u20$V$GT$$u20$as$u20$core..ops..Carrier$GT$10from_error17h983ed059e5df6262E:
pushq %rbp
movq %rsp, %rbp
movl $1, (%rdi)
movl %esi, 4(%rdi)
shrq $32, %rsi
movb %sil, 8(%rdi)
movq %rdi, %rax
popq %rbp
retq
.p2align 4, 0x90
__ZN77_$LT$core..result..Result$LT$U$C$$u20$V$GT$$u20$as$u20$core..ops..Carrier$GT$12from_success17h4169241993d9016dE:
pushq %rbp
movq %rsp, %rbp
movl $0, (%rdi)
movq %rdi, %rax
popq %rbp
retq
.p2align 4, 0x90
__ZN77_$LT$core..result..Result$LT$U$C$$u20$V$GT$$u20$as$u20$core..ops..Carrier$GT$9translate17had4b200d2ffbc2e9E:
pushq %rbp
movq %rsp, %rbp
pushq %rbx
pushq %rax
movq %rdi, %rbx
cmpl $0, (%rsi)
je LBB10_1
movzbl 8(%rsi), %eax
shlq $32, %rax
movl 4(%rsi), %esi
orq %rax, %rsi
movq %rbx, %rdi
callq __ZN77_$LT$core..result..Result$LT$U$C$$u20$V$GT$$u20$as$u20$core..ops..Carrier$GT$10from_error17h983ed059e5df6262E
jmp LBB10_2
LBB10_1:
movq %rbx, %rdi
callq __ZN77_$LT$core..result..Result$LT$U$C$$u20$V$GT$$u20$as$u20$core..ops..Carrier$GT$12from_success17h4169241993d9016dE
LBB10_2:
movq %rbx, %rax
addq $8, %rsp
popq %rbx
popq %rbp
retq
.p2align 4, 0x90
__ZN2_14main17hb2ffcf74c477bad3E:
.cfi_startproc
pushq %rbp
Lcfi3:
.cfi_def_cfa_offset 16
Lcfi4:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Lcfi5:
.cfi_def_cfa_register %rbp
subq $16, %rsp
leaq -16(%rbp), %rdi
callq __ZN2_11g17h62cbbaab7a2481a3E
addq $16, %rsp
popq %rbp
retq
.cfi_endproc
.p2align 4, 0x90
__ZN2_11g17h62cbbaab7a2481a3E:
.cfi_startproc
pushq %rbp
Lcfi6:
.cfi_def_cfa_offset 16
Lcfi7:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Lcfi8:
.cfi_def_cfa_register %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $136, %rsp
Lcfi9:
.cfi_offset %rbx, -56
Lcfi10:
.cfi_offset %r12, -48
Lcfi11:
.cfi_offset %r13, -40
Lcfi12:
.cfi_offset %r14, -32
Lcfi13:
.cfi_offset %r15, -24
movq %rdi, -104(%rbp)
leaq -160(%rbp), %rbx
movb $1, %al
xorl %r14d, %r14d
leaq -96(%rbp), %r15
xorl %r13d, %r13d
testb $1, %al
je LBB12_2
jmp LBB12_6
.p2align 4, 0x90
LBB12_3:
movb $1, %r12b
testb $1, %r13b
jne LBB12_10
jmp LBB12_4
.p2align 4, 0x90
LBB12_6:
movq $1, -168(%rbp)
movw $0, -160(%rbp)
movq 32(%rbx), %rax
movq %rax, -64(%rbp)
movq 24(%rbx), %rax
movq %rax, -72(%rbp)
movq 16(%rbx), %rax
movq %rax, -80(%rbp)
movq (%rbx), %rax
movq 8(%rbx), %rcx
movq %rcx, -88(%rbp)
movq %rax, -96(%rbp)
cmpb $0, -96(%rbp)
je LBB12_8
xorl %r12d, %r12d
jmp LBB12_11
.p2align 4, 0x90
LBB12_8:
movl $0, -56(%rbp)
leaq -120(%rbp), %rdi
leaq -56(%rbp), %rsi
callq __ZN77_$LT$core..result..Result$LT$U$C$$u20$V$GT$$u20$as$u20$core..ops..Carrier$GT$9translate17had4b200d2ffbc2e9E
cmpl $0, -120(%rbp)
jne LBB12_15
movl $1, %r14d
movb $1, %r13b
xorl %r12d, %r12d
LBB12_10:
cmpb $0, -96(%rbp)
je LBB12_4
LBB12_11:
movq %r15, %rdi
callq __ZN4core3ptr13drop_in_place17hbf6cf7e003a035e6E
xorl %r13d, %r13d
cmpq $1, -168(%rbp)
jne LBB12_5
jmp LBB12_12
.p2align 4, 0x90
LBB12_4:
cmpq $1, -168(%rbp)
jne LBB12_5
LBB12_12:
testb %r12b, %r12b
je LBB12_1
movq %rbx, %rdi
callq __ZN4core3ptr13drop_in_place17hbf6cf7e003a035e6E
jmp LBB12_1
.p2align 4, 0x90
LBB12_5:
leaq -168(%rbp), %rdi
callq __ZN4core3ptr13drop_in_place17h31d8df590941a85fE
LBB12_1:
xorl %eax, %eax
testb $1, %al
jne LBB12_6
LBB12_2:
movq $0, -168(%rbp)
movl %r14d, -96(%rbp)
movl $1, -92(%rbp)
movb $0, -88(%rbp)
movb -41(%rbp), %al
leaq -87(%rbp), %rcx
movb %al, 2(%rcx)
movzwl -43(%rbp), %eax
movw %ax, (%rcx)
movq %r15, %rdi
callq __ZN38_$LT$core..option..Option$LT$T$GT$$GT$6unwrap17hdbd5a86115aeeb48E
movl $1, -96(%rbp)
movl %eax, -92(%rbp)
shrq $32, %rax
movb %al, -88(%rbp)
leaq -56(%rbp), %rdi
movq %r15, %rsi
callq __ZN77_$LT$core..result..Result$LT$U$C$$u20$V$GT$$u20$as$u20$core..ops..Carrier$GT$9translate17had4b200d2ffbc2e9E
cmpl $0, -56(%rbp)
je LBB12_3
movzbl -48(%rbp), %eax
shlq $32, %rax
movl -52(%rbp), %edi
orq %rax, %rdi
callq __ZN50_$LT$T$u20$as$u20$core..convert..From$LT$T$GT$$GT$4from17hd676c2e417a31d76E
movabsq $1099511627775, %rsi
andq %rax, %rsi
movq -104(%rbp), %rbx
movq %rbx, %rdi
callq __ZN77_$LT$core..result..Result$LT$U$C$$u20$V$GT$$u20$as$u20$core..ops..Carrier$GT$10from_error17h983ed059e5df6262E
movb $1, %r14b
testb $1, %r13b
jne LBB12_16
jmp LBB12_18
LBB12_15:
movzbl -112(%rbp), %eax
shlq $32, %rax
movl -116(%rbp), %edi
orq %rax, %rdi
callq __ZN50_$LT$T$u20$as$u20$core..convert..From$LT$T$GT$$GT$4from17hd676c2e417a31d76E
movabsq $1099511627775, %rsi
andq %rax, %rsi
movq -104(%rbp), %rbx
movq %rbx, %rdi
callq __ZN77_$LT$core..result..Result$LT$U$C$$u20$V$GT$$u20$as$u20$core..ops..Carrier$GT$10from_error17h983ed059e5df6262E
xorl %r14d, %r14d
LBB12_16:
cmpb $0, -96(%rbp)
je LBB12_18
leaq -96(%rbp), %rdi
callq __ZN4core3ptr13drop_in_place17hbf6cf7e003a035e6E
LBB12_18:
cmpq $1, -168(%rbp)
jne LBB12_21
testb %r14b, %r14b
je LBB12_22
leaq -160(%rbp), %rdi
callq __ZN4core3ptr13drop_in_place17hbf6cf7e003a035e6E
jmp LBB12_22
LBB12_21:
leaq -168(%rbp), %rdi
callq __ZN4core3ptr13drop_in_place17h31d8df590941a85fE
LBB12_22:
movq %rbx, %rax
addq $136, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
.cfi_endproc
.globl _main
.p2align 4, 0x90
_main:
.cfi_startproc
pushq %rbp
Lcfi14:
.cfi_def_cfa_offset 16
Lcfi15:
.cfi_offset %rbp, -16
movq %rsp, %rbp
Lcfi16:
.cfi_def_cfa_register %rbp
movq %rsi, %rax
movq %rdi, %rcx
leaq __ZN2_14main17hb2ffcf74c477bad3E(%rip), %rdi
movq %rcx, %rsi
movq %rax, %rdx
popq %rbp
jmp __ZN3std2rt10lang_start17hbda94898b2b88ae4E
.cfi_endproc
.subsections_via_symbols
LLDB
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
* frame #0: 0x0000000100001864 1`core::ptr::drop_in_place<1::X>((null)=0x0000000000000000) at ptr.rs:61 [opt]
frame #1: 0x0000000100001831 1`core::ptr::drop_in_place<alloc::boxed::Box<1::X>>((null)=0x00007fff5fbff610) at ptr.rs:61 [opt]
frame #2: 0x000000010000189b 1`core::ptr::drop_in_place<1::E>((null)=<unavailable>) at ptr.rs:61 [opt]
frame #3: 0x0000000100001b95 1`_ZN111gE(pt=<unavailable>) at 1.rs:47 [opt]
frame #4: 0x0000000100001981 1`_ZN114mainE at 1.rs:4 [opt]
frame #5: 0x0000000100008ccc 1`panic_abort::__rust_maybe_catch_panic at lib.rs:40 [opt]
frame #6: 0x00000001000089e2 1`std::rt::lang_start [inlined] std::panicking::try<(),fn()> at panicking.rs:433 [opt]
frame #7: 0x00000001000089b3 1`std::rt::lang_start [inlined] std::panic::catch_unwind<fn(),()> at panic.rs:361 [opt]
frame #8: 0x00000001000089b3 1`std::rt::lang_start at rt.rs:57 [opt]
frame #9: 0x00007fffc988b235 libdyld.dylib`start + 1
(lldb) fr s 3
frame #3: 0x0000000100001b95 1`_ZN111gE(pt=<unavailable>) at 1.rs:47 [opt]
44 _ => {
45 Err(y.unwrap())? // <-- must use `?`, return Err won't trigger segfault
46 }
-> 47 }
48 }
49 }
Bisection isn't quite working for me, for various reasons (unrelated to the segfault), but I think the failure might have been introduced in the rollup PR #39199. I haven't investigated beyond that, though, and this might be completely wrong.
This slightly more minimised sample
fn main() { let _ = g(Some(E::F(K))); }
type R = Result<(), ()>;
struct K;
enum E {
F(K), // must not be built-in type
#[allow(dead_code)]
G(Box<E>, Box<E>),
}
fn translate(x: R) -> R { x }
fn g(mut status: Option<E>) -> R {
loop {
match status {
Some(infix_or_postfix) => match infix_or_postfix {
E::F(_op) => { // <- must be captured by value
match Ok(()) {
Err(err) => return Err(err),
Ok(_) => {},
};
}
_ => (),
},
_ => match translate(Err(())) {
Err(err) => return Err(err),
Ok(_) => {},
}
}
status = None;
}
}
results in read of uninitialized memory:
define internal void @_ZN5test24main17hd4f6b2920169b984E() unnamed_addr #1 personality i32 (i32, i32, i64, %"unwind::libunwind::_Unwind_Exception"*, %"unwind::libunwind::_Unwind_Context"*)* @rust_eh_personality {
start:
%infix_or_postfix.i = alloca %E, align 8 ; alloca a stack slot
%0 = bitcast %E* %infix_or_postfix.i to i8* ; for lifetime.end later on
%1 = getelementptr inbounds %E, %E* %infix_or_postfix.i, i64 0, i32 0 ; discriminant
%2 = load i64, i64* %1, align 8, !noalias !2 ; read the discriminant
%cond11.i = icmp eq i64 %2, 0 ; …
br i1 %cond11.i, label %_ZN5test21g17h3e85430d2d279929E.exit, label %bb3.i21.i ; russian roulette at this point
bb3.i21.i: ; preds = %start
%3 = getelementptr inbounds %E, %E* %infix_or_postfix.i, i64 0, i32 2
%4 = bitcast [2 x i64]* %3 to %X*
call fastcc void @_ZN4core3ptr13drop_in_place17h1a08b1322ab8b0ffE(%X* nonnull %4)
br label %_ZN5test21g17h3e85430d2d279929E.exit
_ZN5test21g17h3e85430d2d279929E.exit: ; preds = %bb3.i21.i, %start
call void @llvm.lifetime.end(i64 24, i8* nonnull %0), !noalias !2
ret void
@nagisa's program reproduces the problem on rustc stable 1.12.1, but not on 1.11.0, suggesting that the problem was introduced when rustc switched to MIR.
triage: P-high
Looks bad. @nagisa did an admirable job reducing. Hopefully that's indeed the same problem. :)
Turns out we have to clear the ADT master drop flag even if we have 0 variants. Fixed as a commit in #41917 because I am already refactoring this and I don't want to write things twice.
I am not sure if it is the same issue but it is related(opt-level > 0 = SIGSEGV or SIGILL).
This happens on both stable(rustc 1.17.0 (56124baa9 2017-04-24)) and nightly(rustc 1.19.0-nightly (75b056812 2017-05-15))
In Cargo.toml I have only:
[package]
name = "load_cpu"
#...
[dependencies]
num_cpus = "1.4.0"
In main.rs:
#![allow(unused_variables)]
extern crate num_cpus;
fn main() {
let cpus = num_cpus::get();
let mut threads = Vec::with_capacity(cpus);
for i in 0..cpus {
threads.push(::std::thread::spawn(|| {
loop {
let number = 20000_f64;
let using = number.sqrt();
}
}));
}
for thread in threads {
thread.join().unwrap();
}
}
If I set in Cargo.toml:
[profile.release]
opt-level = 0
And build through cargo build --release - running the binary is ok.
If I set opt-level = 1, I get SIGILL with the messages:
fatal runtime error: out of memory
fatal runtime error: out of memory
Illegal instruction
and this GDB stacktrace:
#0 std::sys::imp::init::oom_handler () at /checkout/src/libstd/sys/unix/mod.rs:89
#1 0x000055555556f4bd in alloc::oom::imp::oom () at /checkout/src/liballoc/oom.rs:41
#2 alloc::oom::oom () at /checkout/src/liballoc/oom.rs:27
#3 0x000055555555b973 in _$LT$alloc..raw_vec..RawVec$LT$T$GT$$GT$::allocate::h98ae98b690b5a3d6 ()
#4 0x000055555555b859 in _$LT$alloc..raw_vec..RawVec$LT$T$GT$$GT$::with_capacity::h646536492684a6cd
()
#5 0x000055555556f2eb in panic_unwind::__rust_maybe_catch_panic ()
at /checkout/src/libpanic_unwind/lib.rs:98
#6 0x000055555555b815 in std::panicking::try::h9f2efeaaffe7c6c4 ()
#7 0x000055555555b469 in std::panic::catch_unwind::h3b627ac82596e62b ()
#8 0x000055555555b751 in std::thread::Builder::spawn::_$u7b$$u7b$closure$u7d$$u7d$::h99fd97c22f4dc633 ()
#9 0x000055555555c519 in _$LT$F$u20$as$u20$alloc..boxed..FnBox$LT$A$GT$$GT$::call_box::h53150036c5a896a3 ()
#10 0x0000555555566626 in alloc::boxed::{{impl}}::call_once<(),()> ()
at /checkout/src/liballoc/boxed.rs:658
#11 std::sys_common::thread::start_thread () at /checkout/src/libstd/sys_common/thread.rs:21
#12 std::sys::imp::thread::{{impl}}::new::thread_start ()
at /checkout/src/libstd/sys/unix/thread.rs:84
#13 0x00007ffff77b56ba in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
#14 0x00007ffff72d582d in clone () from /lib/x86_64-linux-gnu/libc.so.6
With opt-level > 1, I get always SIGSEGV(Segmentation fault), always seeing jemalloc here - GDB stacktrace(opt-level = 2 and opt-level = 3):
#0 je_rtree_get (dependent=true, key=key@entry=3, rtree=<optimized out>) at /checkout/src/liballoc_jemalloc/../jemalloc/include/jemalloc/internal/rtree.h:325
#1 je_chunk_lookup (dependent=true, ptr=<optimized out>) at /checkout/src/liballoc_jemalloc/../jemalloc/include/jemalloc/internal/chunk.h:89
#2 huge_node_get (ptr=<optimized out>) at /checkout/src/liballoc_jemalloc/../jemalloc/src/huge.c:11
#3 je_huge_salloc (tsdn=<optimized out>, ptr=ptr@entry=0x0) at /checkout/src/liballoc_jemalloc/../jemalloc/src/huge.c:455
#4 0x0000555555573953 in je_arena_salloc (demote=false, ptr=0x0, tsdn=<optimized out>) at /checkout/src/liballoc_jemalloc/../jemalloc/include/jemalloc/internal/arena.h:1417
#5 je_isalloc (demote=false, ptr=0x0, tsdn=<optimized out>) at include/jemalloc/internal/jemalloc_internal.h:1054
#6 rallocx (ptr=0x0, size=9007189332333568, flags=<optimized out>) at /checkout/src/liballoc_jemalloc/../jemalloc/src/jemalloc.c:2401
#7 0x000055555555b1ff in _$LT$alloc..raw_vec..RawVec$LT$T$GT$$GT$::double::h51d74fc503deb7ce ()
#8 0x000055555556e44b in panic_unwind::__rust_maybe_catch_panic () at /checkout/src/libpanic_unwind/lib.rs:98
#9 0x000055555555b612 in _$LT$F$u20$as$u20$alloc..boxed..FnBox$LT$A$GT$$GT$::call_box::hc72d94f6aec109ae ()
#10 0x0000555555565786 in alloc::boxed::{{impl}}::call_once<(),()> () at /checkout/src/liballoc/boxed.rs:658
#11 std::sys_common::thread::start_thread () at /checkout/src/libstd/sys_common/thread.rs:21
#12 std::sys::imp::thread::{{impl}}::new::thread_start () at /checkout/src/libstd/sys/unix/thread.rs:84
#13 0x00007ffff77b56ba in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
#14 0x00007ffff72d582d in clone () from /lib/x86_64-linux-gnu/libc.so.6
@lilianmoraru That’s https://github.com/rust-lang/rust/issues/28728.
Most helpful comment
Turns out we have to clear the ADT master drop flag even if we have 0 variants. Fixed as a commit in #41917 because I am already refactoring this and I don't want to write things twice.