fn prepare_mem(
        &self,
        op: &P<Value>,
        loc: usize
    ) -> (String, LinkedHashMap<MuID, Vec<ASMLocation>>) {
        debug_assert!(op.is_mem());

        // temps/regs used
        let mut ids: Vec<MuID> = vec![];
        // locations for temps/regs
        let mut locs: Vec<ASMLocation> = vec![];
        // resulting string for the memory operand
        let mut result_str: String = "".to_string();
        // column cursor
        let mut loc_cursor: usize = loc;

        match op.v {
            // offset(base,index,scale)
            Value_::Memory(MemoryLocation::Address {
                ref base,
                ref offset,
                ref index,
                scale
            }) => {
                // deal with offset
                if offset.is_some() {
                    let offset = offset.as_ref().unwrap();
                    match offset.v {
                        Value_::SSAVar(_) => {
                            // temp as offset
                            let (str, id, loc) = self.prepare_reg(offset, loc_cursor);

                            result_str.push_str(&str);
                            ids.push(id);
                            locs.push(loc);
                            loc_cursor += str.len();
                        }
                        Value_::Constant(Constant::Int(val)) => {
                            let str = (val as i32).to_string();

                            result_str.push_str(&str);
                            loc_cursor += str.len();
                        }
                        _ => panic!("unexpected offset type: {:?}", offset)
                    }
                }

                result_str.push('(');
                loc_cursor += 1;

                // deal with base, base is ssa
                let (str, id, loc) = self.prepare_reg(base, loc_cursor);
                result_str.push_str(&str);
                ids.push(id);
                locs.push(loc);
                loc_cursor += str.len();

                // deal with index (ssa or constant)
                if index.is_some() {
                    result_str.push(',');
                    loc_cursor += 1; // plus 1 for ,

                    let index = index.as_ref().unwrap();

                    match index.v {
                        Value_::SSAVar(_) => {
                            // temp as offset
                            let (str, id, loc) = self.prepare_reg(index, loc_cursor);

                            result_str.push_str(&str);
                            ids.push(id);
                            locs.push(loc);
                            loc_cursor += str.len();
                        }
                        Value_::Constant(Constant::Int(val)) => {
                            let str = (val as i32).to_string();

                            result_str.push_str(&str);
                            loc_cursor += str.len();
                        }
                        _ => panic!("unexpected index type: {:?}", index)
                    }

                    // scale
                    if scale.is_some() {
                        result_str.push(',');
                        loc_cursor += 1;

                        let scale = scale.unwrap();
                        let str = scale.to_string();

                        result_str.push_str(&str);
                        loc_cursor += str.len();
                    }
                }

                result_str.push(')');
                loc_cursor += 1;
            }
            Value_::Memory(MemoryLocation::Symbolic {
                ref base,
                ref label,
                is_global,
                is_native
            }) => {
                let label = if is_native {
                    "/*C*/".to_string() + label.as_str()
                } else {
                    mangle_name(label.clone())
                };
                if base.is_some() && base.as_ref().unwrap().id() == x86_64::RIP.id() && is_global {
                    // pc relative address
                    let pic_symbol = pic_symbol(&label.clone());
                    result_str.push_str(&pic_symbol);
                    loc_cursor += label.len();
                } else {
                    let symbol = symbol(&label.clone());
                    result_str.push_str(&symbol);
                    loc_cursor += label.len();
                }

                if base.is_some() {
                    result_str.push('(');
                    loc_cursor += 1;

                    let (str, id, loc) = self.prepare_reg(base.as_ref().unwrap(), loc_cursor);
                    result_str.push_str(&str);
                    ids.push(id);
                    locs.push(loc);
                    loc_cursor += str.len();

                    result_str.push(')');
                    loc_cursor += 1;
                }
            }
            _ => panic!("expect mem location as value")
        }

        let uses: LinkedHashMap<MuID, Vec<ASMLocation>> = {
            let mut map: LinkedHashMap<MuID, Vec<ASMLocation>> = linked_hashmap!{};
            for i in 0..ids.len() {
                let id = ids[i];
                let loc = locs[i].clone();

                if map.contains_key(&id) {
                    map.get_mut(&id).unwrap().push(loc);
                } else {
                    map.insert(id, vec![loc]);
                }
            }
            map
        };


        (result_str, uses)
    }
// we keep updating loc_cursor to be valid, but we may not read value in the end
we keep updating loc_cursor to be valid, but we may not read value in the end
we keep updating loc_cursor to be valid but we may not read value in the end
fn prepare_mem(
        &self,
        op: &P<Value>,
        loc: usize
    ) -> (String, LinkedHashMap<MuID, Vec<ASMLocation>>) {
        debug_assert!(op.is_mem());
        // temps/regs used
        let mut ids: Vec<MuID> = vec![];
        // locations for temps/regs
        let mut locs: Vec<ASMLocation> = vec![];
        // resulting string for the memory operand
        let mut result_str: String = "".to_string();
        // column cursor
        let mut loc_cursor: usize = loc;
        match op.v {
            // offset(base,index,scale)
            Value_::Memory(MemoryLocation::Address {
                ref base,
                ref offset,
                ref index,
                scale
            }) => {
                // deal with offset
                if offset.is_some() {
                    let offset = offset.as_ref().unwrap();
                    match offset.v {
                        Value_::SSAVar(_) => {
                            // temp as offset
                            let (str, id, loc) = self.prepare_reg(offset, loc_cursor);
                            result_str.push_str(&str);
                            ids.push(id);
                            locs.push(loc);
                            loc_cursor += str.len();
                        }
                        Value_::Constant(Constant::Int(val)) => {
                            let str = (val as i32).to_string();
                            result_str.push_str(&str);
                            loc_cursor += str.len();
                        }
                        _ => panic!("unexpected offset type: {:?}", offset)
                    }
                }
                result_str.push('(');
                loc_cursor += 1;
                // deal with base, base is ssa
                let (str, id, loc) = self.prepare_reg(base, loc_cursor);
                result_str.push_str(&str);
                ids.push(id);
                locs.push(loc);
                loc_cursor += str.len();
                // deal with index (ssa or constant)
                if index.is_some() {
                    result_str.push(',');
                    loc_cursor += 1; // plus 1 for ,
                    let index = index.as_ref().unwrap();
                    match index.v {
                        Value_::SSAVar(_) => {
                            // temp as offset
                            let (str, id, loc) = self.prepare_reg(index, loc_cursor);
                            result_str.push_str(&str);
                            ids.push(id);
                            locs.push(loc);
                            loc_cursor += str.len();
                        }
                        Value_::Constant(Constant::Int(val)) => {
                            let str = (val as i32).to_string();
                            result_str.push_str(&str);
                            loc_cursor += str.len();
                        }
                        _ => panic!("unexpected index type: {:?}", index)
                    }
                    // scale
                    if scale.is_some() {
                        result_str.push(',');
                        loc_cursor += 1;
                        let scale = scale.unwrap();
                        let str = scale.to_string();
                        result_str.push_str(&str);
                        loc_cursor += str.len();
                    }
                }
                result_str.push(')');
                loc_cursor += 1;
            }
            Value_::Memory(MemoryLocation::Symbolic {
                ref base,
                ref label,
                is_global,
                is_native
            }) => {
                let label = if is_native {
                    "/*C*/".to_string() + label.as_str()
                } else {
                    mangle_name(label.clone())
                };
                if base.is_some() && base.as_ref().unwrap().id() == x86_64::RIP.id() && is_global {
                    // pc relative address
                    let pic_symbol = pic_symbol(&label.clone());
                    result_str.push_str(&pic_symbol);
                    loc_cursor += label.len();
                } else {
                    let symbol = symbol(&label.clone());
                    result_str.push_str(&symbol);
                    loc_cursor += label.len();
                }
                if base.is_some() {
                    result_str.push('(');
                    loc_cursor += 1;
                    let (str, id, loc) = self.prepare_reg(base.as_ref().unwrap(), loc_cursor);
                    result_str.push_str(&str);
                    ids.push(id);
                    locs.push(loc);
                    loc_cursor += str.len();
                    result_str.push(')');
                    loc_cursor += 1;
                }
            }
            _ => panic!("expect mem location as value")
        }
        let uses: LinkedHashMap<MuID, Vec<ASMLocation>> = {
            let mut map: LinkedHashMap<MuID, Vec<ASMLocation>> = linked_hashmap!{};
            for i in 0..ids.len() {
                let id = ids[i];
                let loc = locs[i].clone();
                if map.contains_key(&id) {
                    map.get_mut(&id).unwrap().push(loc);
                } else {
                    map.insert(id, vec![loc]);
                }
            }
            map
        };
        (result_str, uses)
    }
fn prepare_mem ( & self , op : & P < Value > , loc : usize ) -> ( String , LinkedHashMap < MuID , Vec < ASMLocation > > ) { debug_assert ! ( op is_mem ( ) ) ; // temps/regs used let mut ids : Vec < MuID > = vec ! [ ] ; // locations for temps/regs let mut locs : Vec < ASMLocation > = vec ! [ ] ; // resulting string for the memory operand let mut result_str : String = " " . to_string ( ) ; // column cursor let mut loc_cursor : usize = loc ; match op . v { // offset(base,index,scale) Value_ :: Memory ( MemoryLocation :: Address { ref base , ref offset , ref index , scale } ) => { // deal with offset if offset . is_some ( ) { let offset = offset . as_ref ( ) . unwrap ( ) ; match offset . v { Value_ :: SSAVar ( _ ) => { // temp as offset let ( str , id , loc ) = self . prepare_reg ( offset , loc_cursor ) ; result_str . push_str ( & str ) ; ids . push ( id ) ; locs . push ( loc ) ; loc_cursor += str . len ( ) ; } Value_ :: Constant ( Constant :: Int ( val ) ) => { let str = ( val as i32 ) . to_string ( ) ; result_str . push_str ( & str ) ; loc_cursor += str . len ( ) ; } _ => panic ! ( " " offset ) } } result_str . push ( '(' ) ; loc_cursor += 1 ; // deal with base, base is ssa let ( str , id , loc ) = self . prepare_reg ( base , loc_cursor ) ; result_str . push_str ( & str ) ; ids . push ( id ) ; locs . push ( loc ) ; loc_cursor += str . len ( ) ; // deal with index (ssa or constant) if index . is_some ( ) { result_str . push ( ',' ) ; loc_cursor += 1 ; // plus 1 for , let index = index . as_ref ( ) . unwrap ( ) ; match index . v { Value_ :: SSAVar ( _ ) => { // temp as offset let ( str , id , loc ) = self . prepare_reg ( index , loc_cursor ) ; result_str . push_str ( & str ) ; ids . push ( id ) ; locs . push ( loc ) ; loc_cursor += str . len ( ) ; } Value_ :: Constant ( Constant :: Int ( val ) ) => { let str = ( val as i32 ) . to_string ( ) ; result_str . push_str ( & str ) ; loc_cursor += str . len ( ) ; } _ => panic ! ( " " index ) } // scale if scale . is_some ( ) { result_str . push ( ',' ) ; loc_cursor += 1 ; let scale = scale . unwrap ( ) ; let str = scale . to_string ( ) ; result_str . push_str ( & str ) ; loc_cursor += str . len ( ) ; } } result_str . push ( ')' ) ; loc_cursor += 1 ; } Value_ :: Memory ( MemoryLocation :: Symbolic { ref base , ref label , is_global , is_native } ) => { let label = if is_native { " " . to_string ( ) + label . as_str ( ) } else { mangle_name ( label . clone ( ) ) } ; if base . is_some ( ) && base . as_ref ( ) . unwrap ( ) . id ( ) == x86_64 :: RIP . id ( ) && is_global { // pc relative address let pic_symbol = pic_symbol ( & label . clone ( ) ) ; result_str . push_str ( & pic_symbol ) ; loc_cursor += label . len ( ) ; } else { let symbol = symbol ( & label . clone ( ) ) ; result_str . push_str ( & symbol ) ; loc_cursor += label . len ( ) ; } if base . is_some ( ) { result_str . push ( '(' ) ; loc_cursor += 1 ; let ( str , id , loc ) = self . prepare_reg ( base . as_ref ( ) . unwrap ( ) , loc_cursor ) ; result_str . push_str ( & str ) ; ids . push ( id ) ; locs . push ( loc ) ; loc_cursor += str . len ( ) ; result_str . push ( ')' ) ; loc_cursor += 1 ; } } _ => panic ! ( " " ) } let uses : LinkedHashMap < MuID , Vec < ASMLocation > > = { let mut map : LinkedHashMap < MuID , Vec < ASMLocation > > = linked_hashmap ! { } ; for i in 0 .. ids . len ( ) { let id = ids [ i ] ; let loc = locs [ i ] . clone ( ) ; if map . contains_key ( & id ) { map . get_mut ( & id ) . unwrap ( ) . push ( loc ) ; } else { map . insert ( id , vec ! [ loc ] ) ; } } map } ; ( result_str , uses ) }
we keep updating loc_cursor to be valid, but we may not read value in the end
we keep updating loc_cursor to be valid but we may not read value in the end
&self
op
&P<Value>
loc
usize
&self
op
&P<Value>
loc
usize