Commit 04c10e0b authored by qinsoon's avatar qinsoon

fixed all tests. Now using a lock for MuName

parent b20cc1a4
...@@ -8,6 +8,7 @@ use utils::vec_utils; ...@@ -8,6 +8,7 @@ use utils::vec_utils;
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt; use std::fmt;
use std::default; use std::default;
use std::sync::RwLock;
use std::cell::Cell; use std::cell::Cell;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
...@@ -55,8 +56,7 @@ pub fn new_internal_id() -> MuID { ...@@ -55,8 +56,7 @@ pub fn new_internal_id() -> MuID {
#[derive(Debug)] #[derive(Debug)]
pub struct MuFunction { pub struct MuFunction {
pub id: MuID, pub hdr: MuEntityHeader,
pub name: Option<MuName>,
pub sig: P<MuFuncSig>, pub sig: P<MuFuncSig>,
pub cur_ver: Option<MuID>, pub cur_ver: Option<MuID>,
...@@ -66,8 +66,7 @@ pub struct MuFunction { ...@@ -66,8 +66,7 @@ pub struct MuFunction {
impl MuFunction { impl MuFunction {
pub fn new(id: MuID, sig: P<MuFuncSig>) -> MuFunction { pub fn new(id: MuID, sig: P<MuFuncSig>) -> MuFunction {
MuFunction { MuFunction {
id: id, hdr: MuEntityHeader::unnamed(id),
name: None,
sig: sig, sig: sig,
cur_ver: None, cur_ver: None,
all_vers: vec![] all_vers: vec![]
...@@ -77,18 +76,13 @@ impl MuFunction { ...@@ -77,18 +76,13 @@ impl MuFunction {
impl fmt::Display for MuFunction { impl fmt::Display for MuFunction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.name.is_none() { write!(f, "Func {}", self.hdr)
write!(f, "Func #{}", self.id)
} else {
write!(f, "Func {}#{}", self.name.unwrap(), self.id)
}
} }
} }
#[derive(Debug)] #[derive(Debug)]
pub struct MuFunctionVersion { pub struct MuFunctionVersion {
pub id: MuID, pub hdr: MuEntityHeader,
pub name: Option<MuName>,
pub func_id: MuID, pub func_id: MuID,
pub sig: P<MuFuncSig>, pub sig: P<MuFuncSig>,
...@@ -100,19 +94,14 @@ pub struct MuFunctionVersion { ...@@ -100,19 +94,14 @@ pub struct MuFunctionVersion {
impl fmt::Display for MuFunctionVersion { impl fmt::Display for MuFunctionVersion {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.name.is_none() { write!(f, "FuncVer {} of Func #{}", self.hdr, self.func_id)
write!(f, "FuncVer #{} of Func#{}", self.id, self.func_id)
} else {
write!(f, "FuncVer {}#{} of Func#{}", self.name.unwrap(), self.id, self.func_id)
}
} }
} }
impl MuFunctionVersion { impl MuFunctionVersion {
pub fn new(id: MuID, func: MuID, sig: P<MuFuncSig>) -> MuFunctionVersion { pub fn new(id: MuID, func: MuID, sig: P<MuFuncSig>) -> MuFunctionVersion {
MuFunctionVersion{ MuFunctionVersion{
id: id, hdr: MuEntityHeader::unnamed(id),
name: None,
func_id: func, func_id: func,
sig: sig, sig: sig,
content: None, content: None,
...@@ -129,12 +118,10 @@ impl MuFunctionVersion { ...@@ -129,12 +118,10 @@ impl MuFunctionVersion {
self.context.values.insert(id, SSAVarEntry{id: id, name: Some(tag), ty: ty.clone(), use_count: Cell::new(0), expr: None}); self.context.values.insert(id, SSAVarEntry{id: id, name: Some(tag), ty: ty.clone(), use_count: Cell::new(0), expr: None});
P(TreeNode { P(TreeNode {
id: id, hdr: MuEntityHeader::unnamed(id),
name: None,
op: pick_op_code_for_ssa(&ty), op: pick_op_code_for_ssa(&ty),
v: TreeNode_::Value(P(Value{ v: TreeNode_::Value(P(Value{
id: id, hdr: MuEntityHeader::named(id, tag),
name: Some(tag),
ty: ty, ty: ty,
v: Value_::SSAVar(id) v: Value_::SSAVar(id)
})) }))
...@@ -143,8 +130,7 @@ impl MuFunctionVersion { ...@@ -143,8 +130,7 @@ impl MuFunctionVersion {
pub fn new_constant(&mut self, id: MuID, v: P<Value>) -> P<TreeNode> { pub fn new_constant(&mut self, id: MuID, v: P<Value>) -> P<TreeNode> {
P(TreeNode{ P(TreeNode{
id: id, hdr: MuEntityHeader::unnamed(id),
name: None,
op: pick_op_code_for_value(&v.ty), op: pick_op_code_for_value(&v.ty),
v: TreeNode_::Value(v) v: TreeNode_::Value(v)
}) })
...@@ -152,8 +138,7 @@ impl MuFunctionVersion { ...@@ -152,8 +138,7 @@ impl MuFunctionVersion {
pub fn new_global(&mut self, id: MuID, v: P<Value>) -> P<TreeNode> { pub fn new_global(&mut self, id: MuID, v: P<Value>) -> P<TreeNode> {
P(TreeNode{ P(TreeNode{
id: id, hdr: MuEntityHeader::unnamed(id),
name: None,
op: pick_op_code_for_value(&v.ty), op: pick_op_code_for_value(&v.ty),
v: TreeNode_::Value(v) v: TreeNode_::Value(v)
}) })
...@@ -161,8 +146,7 @@ impl MuFunctionVersion { ...@@ -161,8 +146,7 @@ impl MuFunctionVersion {
pub fn new_inst(&mut self, id: MuID, v: Instruction) -> P<TreeNode> { pub fn new_inst(&mut self, id: MuID, v: Instruction) -> P<TreeNode> {
P(TreeNode{ P(TreeNode{
id: id, hdr: MuEntityHeader::unnamed(id),
name: None,
op: pick_op_code_for_inst(&v), op: pick_op_code_for_inst(&v),
v: TreeNode_::Instruction(v), v: TreeNode_::Instruction(v),
}) })
...@@ -243,15 +227,14 @@ impl FunctionContext { ...@@ -243,15 +227,14 @@ impl FunctionContext {
#[derive(Debug)] #[derive(Debug)]
pub struct Block { pub struct Block {
pub id: MuID, pub hdr: MuEntityHeader,
pub name: Option<MuName>,
pub content: Option<BlockContent>, pub content: Option<BlockContent>,
pub control_flow: ControlFlow pub control_flow: ControlFlow
} }
impl Block { impl Block {
pub fn new(id: MuID) -> Block { pub fn new(id: MuID) -> Block {
Block{id: id, name: None, content: None, control_flow: ControlFlow::default()} Block{hdr: MuEntityHeader::unnamed(id), content: None, control_flow: ControlFlow::default()}
} }
} }
...@@ -391,11 +374,10 @@ impl BlockContent { ...@@ -391,11 +374,10 @@ impl BlockContent {
} }
} }
#[derive(Debug, Clone)] #[derive(Debug)]
/// always use with P<TreeNode> /// always use with P<TreeNode>
pub struct TreeNode { pub struct TreeNode {
pub id: MuID, pub hdr: MuEntityHeader,
pub name: Option<MuName>,
pub op: OpCode, pub op: OpCode,
pub v: TreeNode_, pub v: TreeNode_,
} }
...@@ -404,8 +386,7 @@ impl TreeNode { ...@@ -404,8 +386,7 @@ impl TreeNode {
// this is a hack to allow creating TreeNode without using a &mut MuFunctionVersion // this is a hack to allow creating TreeNode without using a &mut MuFunctionVersion
pub fn new_inst(id: MuID, v: Instruction) -> P<TreeNode> { pub fn new_inst(id: MuID, v: Instruction) -> P<TreeNode> {
P(TreeNode{ P(TreeNode{
id: id, hdr: MuEntityHeader::unnamed(id),
name: None,
op: pick_op_code_for_inst(&v), op: pick_op_code_for_inst(&v),
v: TreeNode_::Instruction(v), v: TreeNode_::Instruction(v),
}) })
...@@ -464,10 +445,9 @@ pub enum TreeNode_ { ...@@ -464,10 +445,9 @@ pub enum TreeNode_ {
} }
/// always use with P<Value> /// always use with P<Value>
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, PartialEq)]
pub struct Value { pub struct Value {
pub id: MuID, pub hdr: MuEntityHeader,
pub name: Option<MuName>,
pub ty: P<MuType>, pub ty: P<MuType>,
pub v: Value_ pub v: Value_
} }
...@@ -522,25 +502,18 @@ impl Value { ...@@ -522,25 +502,18 @@ impl Value {
impl fmt::Display for Value { impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let tag = {
if self.name.is_some() {
self.name.unwrap()
} else {
"???"
}
};
match self.v { match self.v {
Value_::SSAVar(id) => { Value_::SSAVar(id) => {
write!(f, "+({} %{}#{})", self.ty, tag, id) write!(f, "+({} %{})", self.ty, self.hdr)
}, },
Value_::Constant(ref c) => { Value_::Constant(ref c) => {
write!(f, "+({} {})", self.ty, c) write!(f, "+({} {} @{})", self.ty, c, self.hdr)
}, },
Value_::Global => { Value_::Global(ref ty) => {
write!(f, "+(GLOBAL {} @{})", self.ty, self.name.unwrap()) write!(f, "+(GLOBAL {} @{})", ty, self.hdr)
}, },
Value_::Memory(ref mem) => { Value_::Memory(ref mem) => {
write!(f, "+({})", mem) write!(f, "+(MEM {} %{})", mem, self.hdr)
} }
} }
} }
...@@ -550,7 +523,7 @@ impl fmt::Display for Value { ...@@ -550,7 +523,7 @@ impl fmt::Display for Value {
pub enum Value_ { pub enum Value_ {
SSAVar(MuID), SSAVar(MuID),
Constant(Constant), Constant(Constant),
Global, Global(P<MuType>), // what type is this global (without IRef)
Memory(MemoryLocation) Memory(MemoryLocation)
} }
...@@ -649,30 +622,74 @@ impl fmt::Display for MemoryLocation { ...@@ -649,30 +622,74 @@ impl fmt::Display for MemoryLocation {
} }
} }
#[derive(Debug)] // Display, PartialEq
pub struct MuEntityHeader {
id: MuID,
name: RwLock<Option<MuName>>
}
impl MuEntityHeader {
pub fn unnamed(id: MuID) -> MuEntityHeader {
MuEntityHeader {
id: id,
name: RwLock::new(None)
}
}
pub fn named(id: MuID, name: MuName) -> MuEntityHeader {
MuEntityHeader {
id: id,
name: RwLock::new(Some(name))
}
}
pub fn id(&self) -> MuID {
self.id
}
pub fn name(&self) -> Option<MuName> {
*self.name.read().unwrap()
}
}
impl PartialEq for MuEntityHeader {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl fmt::Display for MuEntityHeader {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.name().is_none() {
write!(f, "#{}", self.id)
} else {
write!(f, "{} #{}", self.name().unwrap(), self.id)
}
}
}
pub trait MuEntity { pub trait MuEntity {
fn id(&self) -> MuID; fn id(&self) -> MuID;
fn name(&self) -> Option<MuName>; fn name(&self) -> Option<MuName>;
fn set_name(&mut self, name: MuName); fn set_name(&self, name: MuName);
fn as_entity(&self) -> &MuEntity; fn as_entity(&self) -> &MuEntity;
fn as_entity_mut(&mut self) -> &mut MuEntity;
} }
macro_rules! impl_mu_entity { macro_rules! impl_mu_entity {
($entity: ty) => { ($entity: ty) => {
impl MuEntity for $entity { impl MuEntity for $entity {
#[inline(always)] #[inline(always)]
fn id(&self) -> MuID {self.id} fn id(&self) -> MuID {self.hdr.id}
#[inline(always)] #[inline(always)]
fn name(&self) -> Option<MuName> {self.name} fn name(&self) -> Option<MuName> {self.hdr.name()}
fn set_name(&mut self, name: MuName) {self.name = Some(name);} fn set_name(&self, name: MuName) {
let mut write_guard = self.hdr.name.write().unwrap();
*write_guard = Some(name);
}
fn as_entity(&self) -> &MuEntity { fn as_entity(&self) -> &MuEntity {
let ref_ty : &$entity = self; let ref_ty : &$entity = self;
ref_ty as &MuEntity ref_ty as &MuEntity
} }
fn as_entity_mut(&mut self) -> &mut MuEntity {
let ref_ty : &mut $entity = self;
ref_ty as &mut MuEntity
}
} }
} }
} }
......
...@@ -41,76 +41,78 @@ use std::hash::{Hash, Hasher}; ...@@ -41,76 +41,78 @@ use std::hash::{Hash, Hasher};
use std::ops::Deref; use std::ops::Deref;
use std::ops::DerefMut; use std::ops::DerefMut;
/// An owned smart pointer. use std::sync::Arc;
pub struct P<T> {
ptr: Box<T> pub type P<T> = Arc<T>;
}
///// An owned smart pointer.
//pub struct P<T> {
// ptr: Box<T>
//}
#[allow(non_snake_case)] #[allow(non_snake_case)]
/// Construct a `P<T>` from a `T` value. /// Construct a `P<T>` from a `T` value.
pub fn P<T: 'static>(value: T) -> P<T> { pub fn P<T: 'static>(value: T) -> P<T> {
P { Arc::new(value)
ptr: Box::new(value)
}
}
impl<T: 'static> P<T> {
/// Move out of the pointer.
/// Intended for chaining transformations not covered by `map`.
pub fn and_then<U, F>(self, f: F) -> U where
F: FnOnce(T) -> U,
{
f(*self.ptr)
}
}
impl<T> Deref for P<T> {
type Target = T;
fn deref<'a>(&'a self) -> &'a T {
&*self.ptr
}
}
impl<T> DerefMut for P<T> {
fn deref_mut<'a>(&'a mut self) -> &'a mut T {
&mut *self.ptr
}
}
impl<T: 'static + Clone> Clone for P<T> {
fn clone(&self) -> P<T> {
P((**self).clone())
}
}
impl<T: PartialEq> PartialEq for P<T> {
fn eq(&self, other: &P<T>) -> bool {
**self == **other
}
}
impl<T: Eq> Eq for P<T> {}
impl<T: Debug> Debug for P<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&**self, f)
}
}
impl<T: Display> Display for P<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&**self, f)
}
}
impl<T> fmt::Pointer for P<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Pointer::fmt(&self.ptr, f)
}
} }
impl<T: Hash> Hash for P<T> { //impl<T: 'static> P<T> {
fn hash<H: Hasher>(&self, state: &mut H) { // /// Move out of the pointer.
(**self).hash(state); // /// Intended for chaining transformations not covered by `map`.
} // pub fn and_then<U, F>(self, f: F) -> U where
} // F: FnOnce(T) -> U,
// {
// f(*self.ptr)
// }
//}
//
//impl<T> Deref for P<T> {
// type Target = T;
//
// fn deref<'a>(&'a self) -> &'a T {
// &*self.ptr
// }
//}
//
//impl<T> DerefMut for P<T> {
// fn deref_mut<'a>(&'a mut self) -> &'a mut T {
// &mut *self.ptr
// }
//}
//
//impl<T: 'static + Clone> Clone for P<T> {
// fn clone(&self) -> P<T> {
// P((**self).clone())
// }
//}
//
//impl<T: PartialEq> PartialEq for P<T> {
// fn eq(&self, other: &P<T>) -> bool {
// **self == **other
// }
//}
//
//impl<T: Eq> Eq for P<T> {}
//
//impl<T: Debug> Debug for P<T> {
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Debug::fmt(&**self, f)
// }
//}
//impl<T: Display> Display for P<T> {
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Display::fmt(&**self, f)
// }
//}
//
//impl<T> fmt::Pointer for P<T> {
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// fmt::Pointer::fmt(&self.ptr, f)
// }
//}
//
//impl<T: Hash> Hash for P<T> {
// fn hash<H: Hasher>(&self, state: &mut H) {
// (**self).hash(state);
// }
//}
...@@ -6,24 +6,22 @@ use std::fmt; ...@@ -6,24 +6,22 @@ use std::fmt;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::RwLock; use std::sync::RwLock;
#[derive(Clone, PartialEq, Eq, Debug, Hash)] #[derive(PartialEq, Debug)]
pub struct MuType { pub struct MuType {
pub id: MuID, pub hdr: MuEntityHeader,
pub name: Option<MuName>,
pub v: MuType_ pub v: MuType_
} }
impl MuType { impl MuType {
pub fn new(id: MuID, v: MuType_) -> MuType { pub fn new(id: MuID, v: MuType_) -> MuType {
MuType { MuType {
id: id, hdr: MuEntityHeader::unnamed(id),
name: None,
v: v v: v
} }
} }
} }
#[derive(Clone, PartialEq, Eq, Debug, Hash)] #[derive(PartialEq, Debug)]
pub enum MuType_ { pub enum MuType_ {
/// int <length> /// int <length>
Int (usize), Int (usize),
...@@ -107,7 +105,7 @@ lazy_static! { ...@@ -107,7 +105,7 @@ lazy_static! {
pub static ref STRUCT_TAG_MAP : RwLock<HashMap<MuName, StructType_>> = RwLock::new(HashMap::new()); pub static ref STRUCT_TAG_MAP : RwLock<HashMap<MuName, StructType_>> = RwLock::new(HashMap::new());
} }
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(PartialEq, Debug)]
pub struct StructType_ { pub struct StructType_ {
tys: Vec<P<MuType>> tys: Vec<P<MuType>>
} }
...@@ -325,10 +323,9 @@ macro_rules! is_type ( ...@@ -325,10 +323,9 @@ macro_rules! is_type (
) )
); );
#[derive(Clone, PartialEq, Eq, Debug, Hash)] #[derive(PartialEq, Debug)]
pub struct MuFuncSig { pub struct MuFuncSig {
pub id: MuID, pub hdr: MuEntityHeader,
pub name: Option<MuName>,
pub ret_tys : Vec<P<MuType>>, pub ret_tys : Vec<P<MuType>>,
pub arg_tys: Vec<P<MuType>> pub arg_tys: Vec<P<MuType>>
} }
......
...@@ -77,7 +77,7 @@ impl MachineCode for ASMCode { ...@@ -77,7 +77,7 @@ impl MachineCode for ASMCode {
} }
fn replace_reg(&mut self, from: MuID, to: MuID) { fn replace_reg(&mut self, from: MuID, to: MuID) {
let to_reg_tag : MuName = backend::all_regs()[to].name.unwrap(); let to_reg_tag : MuName = backend::all_regs().get(&to).unwrap().name().unwrap();
let to_reg_string = "%".to_string() + to_reg_tag; let to_reg_string = "%".to_string() + to_reg_tag;
match self.reg_defines.get(&from) { match self.reg_defines.get(&from) {
...@@ -498,7 +498,7 @@ impl ASMCodeGen { ...@@ -498,7 +498,7 @@ impl ASMCodeGen {
let id = op.extract_ssa_id().unwrap(); let id = op.extract_ssa_id().unwrap();
if id < MACHINE_ID_END { if id < MACHINE_ID_END {
// machine reg // machine reg
format!("%{}", op.name.unwrap()) format!("%{}", op.name().unwrap())
} else { } else {
// virtual register, use place holder // virtual register, use place holder
REG_PLACEHOLDER.clone() REG_PLACEHOLDER.clone()
...@@ -921,7 +921,7 @@ impl CodeGenerator for ASMCodeGen { ...@@ -921,7 +921,7 @@ impl CodeGenerator for ASMCodeGen {
} }
fn emit_jmp(&mut self, dest: &Block) { fn emit_jmp(&mut self, dest: &Block) {
let dest_name = dest.name.unwrap(); let dest_name = dest.name().unwrap();
trace!("emit: jmp {}", dest_name); trace!("emit: jmp {}", dest_name);
// symbolic label, we dont need to patch it // symbolic label, we dont need to patch it
...@@ -930,7 +930,7 @@ impl CodeGenerator for ASMCodeGen { ...@@ -930,7 +930,7 @@ impl CodeGenerator for ASMCodeGen {
} }
fn emit_je(&mut self, dest: &Block) { fn emit_je(&mut self, dest: &Block) {
let dest_name = dest.name.unwrap(); let dest_name = dest.name().unwrap();
trace!("emit: je {}", dest_name); trace!("emit: je {}", dest_name);
let asm = format!("je {}", self.asm_block_label(dest_name)); let asm = format!("je {}", self.asm_block_label(dest_name));
...@@ -938,7 +938,7 @@ impl CodeGenerator for ASMCodeGen { ...@@ -938,7 +938,7 @@ impl CodeGenerator for ASMCodeGen {
} }
fn emit_jne(&mut self, dest: &Block) { fn emit_jne(&mut self, dest: &Block) {
let dest_name = dest.name.unwrap(); let dest_name = dest.name().unwrap();
trace!("emit: jne {}", dest_name); trace!("emit: jne {}", dest_name);
let asm = format!("jne {}", self.asm_block_label(dest_name)); let asm = format!("jne {}", self.asm_block_label(dest_name));
...@@ -946,7 +946,7 @@ impl CodeGenerator for ASMCodeGen { ...@@ -946,7 +946,7 @@ impl CodeGenerator for ASMCodeGen {
} }
fn emit_ja(&mut self, dest: &Block) { fn emit_ja(&mut self, dest: &Block) {
let dest_name = dest.name.unwrap(); let dest_name = dest.name().unwrap();
trace!("emit: ja {}", dest_name); trace!("emit: ja {}", dest_name);
let asm = format!("ja {}", self.asm_block_label(dest_name)); let asm = format!("ja {}", self.asm_block_label(dest_name));
...@@ -954,7 +954,7 @@ impl CodeGenerator for ASMCodeGen { ...@@ -954,7 +954,7 @@ impl CodeGenerator for ASMCodeGen {
} }
fn emit_jae(&mut self, dest: &Block) { fn emit_jae(&mut self, dest: &Block) {
let dest_name = dest.name.unwrap(); let dest_name = dest.name().unwrap();
trace!("emit: jae {}", dest_name); trace!("emit: jae {}", dest_name);
let asm = format!("jae {}", self.asm_block_label(dest_name)); let asm = format!("jae {}", self.asm_block_label(dest_name));
...@@ -962,7 +962,7 @@ impl CodeGenerator for ASMCodeGen { ...@@ -962,7 +962,7 @@ impl CodeGenerator for ASMCodeGen {
} }
fn emit_jb(&mut self, dest: &Block) { fn emit_jb(&mut self, dest: &Block) {
let dest_name = dest.name.unwrap(); let dest_name = dest.name().unwrap();
trace!("emit: jb {}", dest_name); trace!("emit: jb {}", dest_name);
let asm = format!("jb {}", self.asm_block_label(dest_name)); let asm = format!("jb {}", self.asm_block_label(dest_name));
...@@ -970,7 +970,7 @@ impl CodeGenerator for ASMCodeGen { ...@@ -970,7 +970,7 @@ impl CodeGenerator for ASMCodeGen {
} }
fn emit_jbe(&mut self, dest: &Block) { fn emit_jbe(&mut self, dest: &Block) {
let dest_name = dest.name.unwrap(); let dest_name = dest.name().unwrap();
trace!("emit: jbe {}", dest_name);