Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

program segfaults when compiled with opt-level>0 #41888

Closed
dwrensha opened this issue May 10, 2017 · 13 comments
Closed

program segfaults when compiled with opt-level>0 #41888

dwrensha opened this issue May 10, 2017 · 13 comments
Assignees
Labels
I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics. P-high High priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@dwrensha
Copy link
Contributor

dwrensha commented May 10, 2017

The following program (reduced from shepmaster/fuzzy-pickles#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

@dwrensha
Copy link
Contributor Author

$ 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

@dwrensha
Copy link
Contributor Author

dwrensha commented May 10, 2017

Apparently panic=abort is not necessary. I still see the segfault when compiling with

rustc -C opt-level=1 parse.rs

@dwrensha dwrensha changed the title program segfaults when compiled with opt-level>0 and panic=abort program segfaults when compiled with opt-level>0 May 10, 2017
@kennytm
Copy link
Member

kennytm commented May 10, 2017

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]

@shepmaster
Copy link
Member

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.

@dwrensha
Copy link
Contributor Author

@shepmaster: I hit this bug while running cargo-fuzz with --sanitizer leak.

@kennytm
Copy link
Member

kennytm commented May 10, 2017

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  	}

@shepmaster shepmaster added the I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics. label May 10, 2017
@Mark-Simulacrum
Copy link
Member

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.

@nagisa
Copy link
Member

nagisa commented May 11, 2017

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

@arielb1 arielb1 added regression-from-stable-to-beta Performance or correctness regression from stable to beta. I-wrong labels May 11, 2017
@dwrensha
Copy link
Contributor Author

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

@arielb1 arielb1 added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. I-nominated regression-from-stable-to-stable Performance or correctness regression from one stable version to another. and removed regression-from-stable-to-beta Performance or correctness regression from stable to beta. labels May 11, 2017
@nikomatsakis
Copy link
Contributor

triage: P-high

Looks bad. @nagisa did an admirable job reducing. Hopefully that's indeed the same problem. :)

@arielb1
Copy link
Contributor

arielb1 commented May 15, 2017

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.

@lilianmoraru
Copy link

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

@nagisa
Copy link
Member

nagisa commented May 16, 2017

@lilianmoraru That’s #28728.

@bors bors closed this as completed in 68b7475 May 28, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
I-crash Issue: The compiler crashes (SIGSEGV, SIGABRT, etc). Use I-ICE instead when the compiler panics. P-high High priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

9 participants