Rust: program segfaults when compiled with opt-level>0

Created on 10 May 2017  Â·  13Comments  Â·  Source: rust-lang/rust

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

I-crash P-high T-compiler regression-from-stable-to-stable

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.

All 13 comments

$ 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
Was this page helpful?
0 / 5 - 0 ratings