/// Obtain the actual discriminant of a value.
Obtain the actual discriminant of a value.
Obtain the actual discriminant of a value .
pub fn codegen_get_discr(self, bx: &Builder<'a, 'll, 'tcx>, cast_to: Ty<'tcx>) -> &'ll Value {
        let cast_to = bx.cx.layout_of(cast_to).immediate_llvm_type(bx.cx);
        if self.layout.abi == layout::Abi::Uninhabited {
            return C_undef(cast_to);
        }
        match self.layout.variants {
            layout::Variants::Single { index } => {
                let discr_val = self.layout.ty.ty_adt_def().map_or(
                    index as u128,
                    |def| def.discriminant_for_variant(bx.cx.tcx, index).val);
                return C_uint_big(cast_to, discr_val);
            }
            layout::Variants::Tagged { .. } |
            layout::Variants::NicheFilling { .. } => {},
        }
        let discr = self.project_field(bx, 0);
        let lldiscr = discr.load(bx).immediate();
        match self.layout.variants {
            layout::Variants::Single { .. } => bug!(),
            layout::Variants::Tagged { ref tag, .. } => {
                let signed = match tag.value {
                    // We use `i1` for bytes that are always `0` or `1`,
                    // e.g. `#[repr(i8)] enum E { A, B }`, but we can't
                    // let LLVM interpret the `i1` as signed, because
                    // then `i1 1` (i.e. E::B) is effectively `i8 -1`.
                    layout::Int(_, signed) => !tag.is_bool() && signed,
                    _ => false
                };
                bx.intcast(lldiscr, cast_to, signed)
            }
            layout::Variants::NicheFilling {
                dataful_variant,
                ref niche_variants,
                niche_start,
                ..
            } => {
                let niche_llty = discr.layout.immediate_llvm_type(bx.cx);
                if niche_variants.start() == niche_variants.end() {
                    // FIXME(eddyb) Check the actual primitive type here.
                    let niche_llval = if niche_start == 0 {
                        // HACK(eddyb) Using `C_null` as it works on all types.
                        C_null(niche_llty)
                    } else {
                        C_uint_big(niche_llty, niche_start)
                    };
                    bx.select(bx.icmp(llvm::IntEQ, lldiscr, niche_llval),
                        C_uint(cast_to, *niche_variants.start() as u64),
                        C_uint(cast_to, dataful_variant as u64))
                } else {
                    // Rebase from niche values to discriminant values.
                    let delta = niche_start.wrapping_sub(*niche_variants.start() as u128);
                    let lldiscr = bx.sub(lldiscr, C_uint_big(niche_llty, delta));
                    let lldiscr_max = C_uint(niche_llty, *niche_variants.end() as u64);
                    bx.select(bx.icmp(llvm::IntULE, lldiscr, lldiscr_max),
                        bx.intcast(lldiscr, cast_to, false),
                        C_uint(cast_to, dataful_variant as u64))
                }
            }
        }
    }
pub fn codegen_get_discr ( self , bx : & Builder < ' a , ' ll , ' tcx > , cast_to : Ty < ' tcx > ) -> & ' ll Value { let cast_to = bx . cx . layout_of ( cast_to ) . immediate_llvm_type ( bx . cx ) ; if self . layout . abi == layout :: Abi :: Uninhabited { return C_undef ( cast_to ) ; } match self . layout . variants { layout :: Variants :: Single { index } => { let discr_val = self . layout . ty . ty_adt_def ( ) . map_or ( index as u128 , | def | def . discriminant_for_variant ( bx . cx . tcx , index ) . val ) ; return C_uint_big ( cast_to , discr_val ) ; } layout :: Variants :: Tagged { .. } | layout :: Variants :: NicheFilling { .. } => { } , } let discr = self . project_field ( bx , 0 ) ; let lldiscr = discr . load ( bx ) . immediate ( ) ; match self . layout . variants { layout :: Variants :: Single { .. } => bug ! ( ) , layout :: Variants :: Tagged { ref tag , .. } => { let signed = match tag . value { // We use `i1` for bytes that are always `0` or `1`, // e.g. `#[repr(i8)] enum E { A, B }`, but we can't // let LLVM interpret the `i1` as signed, because // then `i1 1` (i.e. E::B) is effectively `i8 -1`. layout :: Int ( _ , signed ) => ! tag . is_bool ( ) && signed , _ => false } ; bx . intcast ( lldiscr , cast_to , signed ) } layout :: Variants :: NicheFilling { dataful_variant , ref niche_variants , niche_start , .. } => { let niche_llty = discr . layout . immediate_llvm_type ( bx . cx ) ; if niche_variants . start ( ) == niche_variants . end ( ) { // FIXME(eddyb) Check the actual primitive type here. let niche_llval = if niche_start == 0 { // HACK(eddyb) Using `C_null` as it works on all types. C_null ( niche_llty ) } else { C_uint_big ( niche_llty , niche_start ) } ; bx . select ( bx . icmp ( llvm :: IntEQ , lldiscr , niche_llval ) , C_uint ( cast_to , * niche_variants . start ( ) as u64 ) , C_uint ( cast_to , dataful_variant as u64 ) ) } else { // Rebase from niche values to discriminant values. let delta = niche_start . wrapping_sub ( * niche_variants . start ( ) as u128 ) ; let lldiscr = bx . sub ( lldiscr , C_uint_big ( niche_llty , delta ) ) ; let lldiscr_max = C_uint ( niche_llty , * niche_variants . end ( ) as u64 ) ; bx . select ( bx . icmp ( llvm :: IntULE , lldiscr , lldiscr_max ) , bx . intcast ( lldiscr , cast_to , false ) , C_uint ( cast_to , dataful_variant as u64 ) ) } } } }
Obtain the actual discriminant of a value.
Obtain the actual discriminant of a value .
self
bx
&Builder<'a, 'll, 'tcx>
cast_to
Ty<'tcx>