about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--example/expression/graph_dataflow.py35
-rw-r--r--example/ida/depgraph.py10
-rw-r--r--example/ida/graph_ir.py250
-rw-r--r--miasm2/analysis/data_analysis.py45
-rw-r--r--miasm2/analysis/data_flow.py6
-rw-r--r--miasm2/arch/aarch64/sem.py42
-rw-r--r--miasm2/arch/arm/sem.py27
-rw-r--r--miasm2/arch/mips32/ira.py15
-rw-r--r--miasm2/arch/mips32/jit.py31
-rw-r--r--miasm2/arch/mips32/sem.py19
-rw-r--r--miasm2/arch/x86/jit.py6
-rw-r--r--miasm2/arch/x86/sem.py92
-rw-r--r--miasm2/core/asmblock.py2
-rw-r--r--miasm2/core/sembuilder.py24
-rw-r--r--miasm2/ir/analysis.py40
-rw-r--r--miasm2/ir/ir.py205
-rw-r--r--miasm2/jitter/codegen.py12
-rw-r--r--miasm2/jitter/llvmconvert.py9
18 files changed, 392 insertions, 478 deletions
diff --git a/example/expression/graph_dataflow.py b/example/expression/graph_dataflow.py
index c79cd7d4..8fe39777 100644
--- a/example/expression/graph_dataflow.py
+++ b/example/expression/graph_dataflow.py
@@ -5,7 +5,7 @@ from pprint import pprint
 from miasm2.expression.expression import get_expr_mem
 from miasm2.arch.x86.ira import ir_a_x86_32
 from miasm2.arch.x86.disasm import dis_x86_32
-from miasm2.analysis.data_analysis import intra_bloc_flow_raw, inter_bloc_flow
+from miasm2.analysis.data_analysis import intra_block_flow_raw, inter_block_flow
 from miasm2.core.graph import DiGraph
 from miasm2.ir.symbexec import SymbolicExecutionEngine
 from miasm2.analysis.data_flow import dead_simp
@@ -50,14 +50,13 @@ def get_modified_symbols(sb):
     return out
 
 
-def intra_bloc_flow_symb(ir_arch, flow_graph, irblock):
+def intra_block_flow_symb(ir_arch, flow_graph, irblock, in_nodes, out_nodes):
     symbols_init = ir_arch.arch.regs.regs_init.copy()
     sb = SymbolicExecutionEngine(ir_arch, symbols_init)
     sb.emulbloc(irblock)
     print '*' * 40
     print irblock
-    in_nodes = {}
-    out_nodes = {}
+
 
     out = get_modified_symbols(sb)
     current_nodes = {}
@@ -102,9 +101,6 @@ def intra_bloc_flow_symb(ir_arch, flow_graph, irblock):
                 flow_graph.add_node(node_n_w)
                 flow_graph.add_uniq_edge(node_n_r, node_n_w)
 
-    irblock.in_nodes = in_nodes
-    irblock.out_nodes = out_nodes
-
 
 def node2str(self, node):
     out = "%s,%s\\l\\\n%s" % node
@@ -126,16 +122,23 @@ def gen_block_data_flow_graph(ir_arch, ad, block_flow_cb):
     flow_graph = DiGraph()
     flow_graph.node2str = lambda n: node2str(flow_graph, n)
 
-    for irblock in ir_arch.blocks.values():
-        block_flow_cb(ir_arch, flow_graph, irblock)
 
-    for irblock in ir_arch.blocks.values():
-        print irblock
-        print 'IN', [str(x) for x in irblock.in_nodes]
-        print 'OUT', [str(x) for x in irblock.out_nodes]
+    irb_in_nodes = {}
+    irb_out_nodes = {}
+    for label in ir_arch.blocks:
+        irb_in_nodes[label] = {}
+        irb_out_nodes[label] = {}
+
+    for label, irblock in ir_arch.blocks.iteritems():
+        block_flow_cb(ir_arch, flow_graph, irblock, irb_in_nodes[label], irb_out_nodes[label])
+
+    for label in ir_arch.blocks:
+        print label
+        print 'IN', [str(x) for x in irb_in_nodes[label]]
+        print 'OUT', [str(x) for x in irb_out_nodes[label]]
 
     print '*' * 20, 'interblock', '*' * 20
-    inter_bloc_flow(ir_arch, flow_graph, irblock_0.label)
+    inter_block_flow(ir_arch, flow_graph, irblock_0.label, irb_in_nodes, irb_out_nodes)
 
     # from graph_qt import graph_qt
     # graph_qt(flow_graph)
@@ -166,9 +169,9 @@ for irblock in ir_arch.blocks.values():
 
 
 if args.symb:
-    block_flow_cb = intra_bloc_flow_symb
+    block_flow_cb = intra_block_flow_symb
 else:
-    block_flow_cb = intra_bloc_flow_raw
+    block_flow_cb = intra_block_flow_raw
 
 gen_block_data_flow_graph(ir_arch, ad, block_flow_cb)
 
diff --git a/example/ida/depgraph.py b/example/ida/depgraph.py
index cbd0cf0f..ab033e15 100644
--- a/example/ida/depgraph.py
+++ b/example/ida/depgraph.py
@@ -7,7 +7,7 @@ from miasm2.expression import expression as m2_expr
 
 from miasm2.expression.simplifications import expr_simp
 from miasm2.analysis.depgraph import DependencyGraph
-from miasm2.ir.ir import AssignBlock
+from miasm2.ir.ir import AssignBlock, IRBlock
 
 from utils import guess_machine
 
@@ -173,10 +173,11 @@ settings.Execute()
 label, elements, line_nb = settings.label, settings.elements, settings.line_nb
 # Simplify affectations
 for irb in ir_arch.blocks.values():
+    irs = []
     fix_stack = irb.label.offset is not None and settings.unalias_stack
-    for i, assignblk in enumerate(irb.irs):
+    for assignblk in irb.irs:
         if fix_stack:
-            stk_high = m2_expr.ExprInt(GetSpd(irb.irs[i].instr.offset), ir_arch.sp.size)
+            stk_high = m2_expr.ExprInt(GetSpd(assignblk.instr.offset), ir_arch.sp.size)
             fix_dct = {ir_arch.sp: mn.regs.regs_init[ir_arch.sp] + stk_high}
 
         new_assignblk = {}
@@ -187,7 +188,8 @@ for irb in ir_arch.blocks.values():
                     dst = dst.replace_expr(fix_dct)
             dst, src = expr_simp(dst), expr_simp(src)
             new_assignblk[dst] = src
-        irb.irs[i] = AssignBlock(new_assignblk, instr=assignblk.instr)
+        irs.append(AssignBlock(new_assignblk, instr=assignblk.instr))
+    ir_arch.blocks[irb.label] = IRBlock(irb.label, irs)
 
 # Get dependency graphs
 dg = settings.depgraph
diff --git a/example/ida/graph_ir.py b/example/ida/graph_ir.py
index 6ff4304a..678ae2ff 100644
--- a/example/ida/graph_ir.py
+++ b/example/ida/graph_ir.py
@@ -1,40 +1,55 @@
-import sys
 import os
 import tempfile
 
 from idaapi import GraphViewer
 
 from miasm2.core.bin_stream_ida import bin_stream_ida
-from miasm2.core.asmblock import *
+from miasm2.core.asmblock import expr_is_label, AsmLabel, is_int
 from miasm2.expression.simplifications import expr_simp
-from miasm2.expression.expression import *
-from miasm2.analysis.data_analysis import inter_bloc_flow, \
-    intra_bloc_flow_symbexec
 from miasm2.analysis.data_flow import dead_simp
-from miasm2.ir.ir import AssignBlock
+from miasm2.ir.ir import AssignBlock, IRBlock
 
 from utils import guess_machine, expr2colorstr
 
 
-def color_irbloc(irbloc):
-    o = []
-    lbl = '%s' % irbloc.label
-    lbl = idaapi.COLSTR(lbl, idaapi.SCOLOR_INSN)
-    o.append(lbl)
-    for assignblk in irbloc.irs:
+# Override Miasm asmblock default label naming convention to shrink block size
+# in IDA
+
+def label_init(self, name="", offset=None):
+    self.fixedblocs = False
+    if is_int(name):
+        name = "loc_%X" % (int(name) & 0xFFFFFFFFFFFFFFFF)
+    self.name = name
+    self.attrib = None
+    if offset is None:
+        self.offset = None
+    else:
+        self.offset = int(offset)
+def label_str(self):
+    if isinstance(self.offset, (int, long)):
+        return "%s:0x%x" % (self.name, self.offset)
+    else:
+        return "%s:%s" % (self.name, str(self.offset))
+
+AsmLabel.__init__ = label_init
+AsmLabel.__str__ = label_str
+
+def color_irblock(irblock):
+    out = []
+    lbl = idaapi.COLSTR(str(irblock.label), idaapi.SCOLOR_INSN)
+    out.append(lbl)
+    for assignblk in irblock.irs:
         for dst, src in sorted(assignblk.iteritems()):
             dst_f = expr2colorstr(ir_arch.arch.regs.all_regs_ids, dst)
             src_f = expr2colorstr(ir_arch.arch.regs.all_regs_ids, src)
-            s = idaapi.COLSTR("%s = %s" % (dst_f, src_f), idaapi.SCOLOR_INSN)
-            o.append('    %s' % s)
-        o.append("")
-    o.pop()
-    i = len(irbloc.irs)
-    s = str('    Dst: %s' % irbloc.dst)
-    s = idaapi.COLSTR(s, idaapi.SCOLOR_RPTCMT)
-    o.append(s)
-
-    return "\n".join(o)
+            line = idaapi.COLSTR("%s = %s" % (dst_f, src_f), idaapi.SCOLOR_INSN)
+            out.append('    %s' % line)
+        out.append("")
+    out.pop()
+    dst = str('    Dst: %s' % irblock.dst)
+    dst = idaapi.COLSTR(dst, idaapi.SCOLOR_RPTCMT)
+    out.append(dst)
+    return "\n".join(out)
 
 
 class GraphMiasmIR(GraphViewer):
@@ -50,30 +65,29 @@ class GraphMiasmIR(GraphViewer):
         print 'refresh'
         self.Clear()
         addr_id = {}
-        for irbloc in self.ir_arch.blocks.values():
-            id_irbloc = self.AddNode(color_irbloc(irbloc))
-            addr_id[irbloc] = id_irbloc
+        for irblock in self.ir_arch.blocks.values():
+            id_irblock = self.AddNode(color_irblock(irblock))
+            addr_id[irblock] = id_irblock
 
-        for irbloc in self.ir_arch.blocks.values():
-            if not irbloc:
+        for irblock in self.ir_arch.blocks.values():
+            if not irblock:
                 continue
-            dst = ir_arch.dst_trackback(irbloc)
-            for d in dst:
-                if not expr_is_label(d):
+            all_dst = ir_arch.dst_trackback(irblock)
+            for dst in all_dst:
+                if not expr_is_label(dst):
                     continue
 
-                d = d.name
-                if not d in self.ir_arch.blocks:
+                dst = dst.name
+                if not dst in self.ir_arch.blocks:
                     continue
-                b = self.ir_arch.blocks[d]
-                node1 = addr_id[irbloc]
-                node2 = addr_id[b]
+                dst_block = self.ir_arch.blocks[dst]
+                node1 = addr_id[irblock]
+                node2 = addr_id[dst_block]
                 self.AddEdge(node1, node2)
         return True
 
     def OnGetText(self, node_id):
-        b = self[node_id]
-        return str(b)
+        return str(self[node_id])
 
     def OnSelect(self, node_id):
         return True
@@ -109,39 +123,40 @@ mdis = dis_engine(bs)
 ir_arch = ira(mdis.symbol_pool)
 
 # populate symbols with ida names
-for ad, name in Names():
+for addr, name in Names():
     # print hex(ad), repr(name)
     if name is None:
         continue
-    mdis.symbol_pool.add_label(name, ad)
+    mdis.symbol_pool.add_label(name, addr)
 
 print "start disasm"
-ad = ScreenEA()
-print hex(ad)
+addr = ScreenEA()
+print hex(addr)
 
-ab = mdis.dis_multibloc(ad)
+blocks = mdis.dis_multibloc(addr)
 
 print "generating graph"
-open('asm_flow.dot', 'w').write(ab.dot())
-
+open('asm_flow.dot', 'w').write(blocks.dot())
 
-print "generating IR... %x" % ad
+print "generating IR... %x" % addr
 
-for block in ab:
+for block in blocks:
     print 'ADD'
     print block
     ir_arch.add_bloc(block)
 
 
-print "IR ok... %x" % ad
+print "IR ok... %x" % addr
 
 for irb in ir_arch.blocks.itervalues():
-    for i, assignblk in enumerate(irb.irs):
+    irs = []
+    for assignblk in irb.irs:
         new_assignblk = {
             expr_simp(dst): expr_simp(src)
             for dst, src in assignblk.iteritems()
         }
-        irb.irs[i] = AssignBlock(new_assignblk, instr=assignblk.instr)
+        irs.append(AssignBlock(new_assignblk, instr=assignblk.instr))
+    ir_arch.blocks[irb.label] = IRBlock(irb.label, irs)
 
 out = ir_arch.graph.dot()
 open(os.path.join(tempfile.gettempdir(), 'graph.dot'), 'wb').write(out)
@@ -151,145 +166,8 @@ open(os.path.join(tempfile.gettempdir(), 'graph.dot'), 'wb').write(out)
 
 g = GraphMiasmIR(ir_arch, "Miasm IR graph", None)
 
-
-def mycb(*test):
-    print test
-    raise NotImplementedError('not fully functional')
-
 g.cmd_a = g.AddCommand("cmd a", "x")
 g.cmd_b = g.AddCommand("cmd b", "y")
 
 g.Show()
 
-
-def node2str(n):
-    label, i, node = n
-    print n
-    # out = "%s,%s\n%s"%n
-    out = "%s" % node
-    return out
-
-
-def get_node_name(label, i, n):
-    # n_name = "%s_%d_%s"%(label.name, i, n)
-    n_name = (label.name, i, n)
-    return n_name
-
-
-def get_modified_symbols(sb):
-    # get modified IDS
-    ids = sb.symbols.symbols_id.keys()
-    ids.sort()
-    out = {}
-    for i in ids:
-        if i in sb.arch.regs.regs_init and \
-                i in sb.symbols.symbols_id and \
-                sb.symbols.symbols_id[i] == sb.arch.regs.regs_init[i]:
-            continue
-        # print i, sb.symbols.symbols_id[i]
-        out[i] = sb.symbols.symbols_id[i]
-
-    # get mem IDS
-    mems = sb.symbols.symbols_mem.values()
-    for m, v in mems:
-        # print m, v
-        out[m] = v
-    pp([(str(x[0]), str(x[1])) for x in out.items()])
-    return out
-
-
-def gen_bloc_data_flow_graph(ir_arch, in_str, ad):  # arch, attrib, pool_bin, bloc, symbol_pool):
-    out_str = ""
-
-    # dead_simp(ir_arch)
-
-    irbloc_0 = None
-    for irbloc in ir_arch.blocks.values():
-        if irbloc.label.offset == ad:
-            irbloc_0 = irbloc
-            break
-    assert(irbloc_0 is not None)
-    flow_graph = DiGraph()
-    done = set()
-    todo = set([irbloc_0.label])
-
-    bloc2w = {}
-
-    for irbloc in ir_arch.blocks.values():
-        intra_bloc_flow_symbexec(ir_arch, flow_graph, irbloc)
-        # intra_bloc_flow_symb(ir_arch, flow_graph, irbloc)
-
-    for irbloc in ir_arch.blocks.values():
-        print irbloc
-        print 'IN', [str(x) for x in irbloc.in_nodes]
-        print 'OUT', [str(x) for x in irbloc.out_nodes]
-
-    print '*' * 20, 'interbloc', '*' * 20
-    inter_bloc_flow(ir_arch, flow_graph, irbloc_0.label, False)
-
-    print 'Dataflow roots:'
-    for node in flow_graph.roots():
-        lbl, i, n = node
-        if n in ir_arch.arch.regs.all_regs_ids:
-            print node
-
-    open('data.dot', 'w').write(flow_graph.dot())
-    return flow_graph
-
-
-class GraphMiasmIRFlow(GraphViewer):
-
-    def __init__(self, flow_graph, title, result):
-        GraphViewer.__init__(self, title)
-        print 'init'
-        self.flow_graph = flow_graph
-        self.result = result
-        self.names = {}
-
-    def OnRefresh(self):
-        print 'refresh'
-        self.Clear()
-        addr_id = {}
-        for n in self.flow_graph.nodes():
-            id_n = self.AddNode(node2str(self.flow_graph, n))
-            addr_id[n] = id_n
-
-        for a, b in self.flow_graph.edges():
-                node1, node2 = addr_id[a], addr_id[b]
-                self.AddEdge(node1, node2)
-        return True
-
-    def OnGetText(self, node_id):
-        b = self[node_id]
-        return str(b).lower()
-
-    def OnSelect(self, node_id):
-        return True
-
-    def OnClick(self, node_id):
-        return True
-
-    def OnCommand(self, cmd_id):
-        if self.cmd_test == cmd_id:
-            print 'TEST!'
-            return
-        print "command:", cmd_id
-
-    def Show(self):
-        if not GraphViewer.Show(self):
-            return False
-        self.cmd_test = self.AddCommand("Test", "F2")
-        if self.cmd_test == 0:
-            print "Failed to add popup menu item!"
-        return True
-
-
-#print "gen bloc data flow"
-#flow_graph = gen_bloc_data_flow_graph(ir_arch, bs, ad)
-#def node2str(self, n):
-#    return "%s, %s\\l%s" % n
-#flow_graph.node2str = lambda n: node2str(flow_graph, n)
-#open('data_flow.dot', 'w').write(flow_graph.dot())
-
-# h =  GraphMiasmIRFlow(flow_graph, "Miasm IRFlow graph", None)
-# h.Show()
diff --git a/miasm2/analysis/data_analysis.py b/miasm2/analysis/data_analysis.py
index c67c4509..c745b6c7 100644
--- a/miasm2/analysis/data_analysis.py
+++ b/miasm2/analysis/data_analysis.py
@@ -9,12 +9,10 @@ def get_node_name(label, i, n):
     return n_name
 
 
-def intra_bloc_flow_raw(ir_arch, flow_graph, irb):
+def intra_block_flow_raw(ir_arch, flow_graph, irb, in_nodes, out_nodes):
     """
     Create data flow for an irbloc using raw IR expressions
     """
-    in_nodes = {}
-    out_nodes = {}
     current_nodes = {}
     for i, assignblk in enumerate(irb.irs):
         dict_rw = assignblk.get_rw(cst_read=True)
@@ -63,19 +61,15 @@ def intra_bloc_flow_raw(ir_arch, flow_graph, irb):
 
                 flow_graph.add_node(node_n_w)
                 flow_graph.add_uniq_edge(node_n_r, node_n_w)
-    irb.in_nodes = in_nodes
-    irb.out_nodes = out_nodes
 
 
-def intra_bloc_flow_symbexec(ir_arch, flow_graph, irb):
+def intra_block_flow_symbexec(ir_arch, flow_graph, irb, in_nodes, out_nodes):
     """
     Create data flow for an irbloc using symbolic execution
     """
-    in_nodes = {}
-    out_nodes = {}
     current_nodes = {}
 
-    symbols_init = dict(ir_arch.arch.regs.all_regs_ids_init)
+    symbols_init = dict(ir_arch.arch.regs.regs_init)
 
     sb = SymbolicExecutionEngine(ir_arch, dict(symbols_init))
     sb.emulbloc(irb)
@@ -91,7 +85,7 @@ def intra_bloc_flow_symbexec(ir_arch, flow_graph, irb):
             continue
         read_values = v.get_r(cst_read=True)
         # print n_w, v, [str(x) for x in read_values]
-        node_n_w = get_node_name(irb.label, len(irb.lines), n_w)
+        node_n_w = get_node_name(irb.label, len(irb.irs), n_w)
 
         for n_r in read_values:
             if n_r in current_nodes:
@@ -104,11 +98,8 @@ def intra_bloc_flow_symbexec(ir_arch, flow_graph, irb):
             out_nodes[n_w] = node_n_w
             flow_graph.add_uniq_edge(node_n_r, node_n_w)
 
-    irb.in_nodes = in_nodes
-    irb.out_nodes = out_nodes
 
-
-def inter_bloc_flow_link(ir_arch, flow_graph, todo, link_exec_to_data):
+def inter_block_flow_link(ir_arch, flow_graph, irb_in_nodes, irb_out_nodes, todo, link_exec_to_data):
     lbl, current_nodes, exec_nodes = todo
     # print 'TODO'
     # print lbl
@@ -122,7 +113,7 @@ def inter_bloc_flow_link(ir_arch, flow_graph, todo, link_exec_to_data):
     irb = ir_arch.blocks[lbl]
     # pp(('IN', lbl, [(str(x[0]), str(x[1])) for x in current_nodes.items()]))
     to_del = set()
-    for n_r, node_n_r in irb.in_nodes.items():
+    for n_r, node_n_r in irb_in_nodes[irb.label].items():
         if not n_r in current_nodes:
             continue
         # print 'add link', current_nodes[n_r], node_n_r
@@ -132,7 +123,7 @@ def inter_bloc_flow_link(ir_arch, flow_graph, todo, link_exec_to_data):
     # if link exec to data, all nodes depends on exec nodes
     if link_exec_to_data:
         for n_x_r in exec_nodes:
-            for n_r, node_n_r in irb.in_nodes.items():
+            for n_r, node_n_r in irb_in_nodes[irb.label].items():
                 if not n_x_r in current_nodes:
                     continue
                 if isinstance(n_r, ExprInt):
@@ -140,7 +131,7 @@ def inter_bloc_flow_link(ir_arch, flow_graph, todo, link_exec_to_data):
                 flow_graph.add_uniq_edge(current_nodes[n_x_r], node_n_r)
 
     # update current nodes using bloc out_nodes
-    for n_w, node_n_w in irb.out_nodes.items():
+    for n_w, node_n_w in irb_out_nodes[irb.label].items():
         current_nodes[n_w] = node_n_w
 
     # get nodes involved in exec flow
@@ -155,7 +146,7 @@ def inter_bloc_flow_link(ir_arch, flow_graph, todo, link_exec_to_data):
     return todo
 
 
-def create_implicit_flow(ir_arch, flow_graph):
+def create_implicit_flow(ir_arch, flow_graph, irb_in_nodes, irb_out_ndes):
 
     # first fix IN/OUT
     # If a son read a node which in not in OUT, add it
@@ -168,8 +159,8 @@ def create_implicit_flow(ir_arch, flow_graph):
                 print "cannot find bloc!!", lbl
                 continue
             irb_son = ir_arch.blocks[lbl_son]
-            for n_r in irb_son.in_nodes:
-                if n_r in irb.out_nodes:
+            for n_r in irb_in_nodes[irb_son.label]:
+                if n_r in irb_out_nodes[irb.label]:
                     continue
                 if not isinstance(n_r, ExprId):
                     continue
@@ -180,11 +171,11 @@ def create_implicit_flow(ir_arch, flow_graph):
                 # print "###", irb_son
                 # print "###", 'IN', [str(x) for x in irb_son.in_nodes]
 
-                node_n_w = irb.label, len(irb.lines), n_r
-                irb.out_nodes[n_r] = node_n_w
-                if not n_r in irb.in_nodes:
-                    irb.in_nodes[n_r] = irb.label, 0, n_r
-                node_n_r = irb.in_nodes[n_r]
+                node_n_w = irb.label, len(irb.irs), n_r
+                irb_out_nodes[irb.label][n_r] = node_n_w
+                if not n_r in irb_in_nodes[irb.label]:
+                    irb_in_nodes[irb.label][n_r] = irb.label, 0, n_r
+                node_n_r = irb_in_nodes[irb.label][n_r]
                 # print "###", node_n_r
                 for lbl_p in ir_arch.graph.predecessors(irb.label):
                     todo.add(lbl_p)
@@ -192,7 +183,7 @@ def create_implicit_flow(ir_arch, flow_graph):
                 flow_graph.add_uniq_edge(node_n_r, node_n_w)
 
 
-def inter_bloc_flow(ir_arch, flow_graph, irb_0, link_exec_to_data=True):
+def inter_block_flow(ir_arch, flow_graph, irb_0, irb_in_nodes, irb_out_nodes, link_exec_to_data=True):
 
     todo = set()
     done = set()
@@ -203,7 +194,7 @@ def inter_bloc_flow(ir_arch, flow_graph, irb_0, link_exec_to_data=True):
         if state in done:
             continue
         done.add(state)
-        out = inter_bloc_flow_link(ir_arch, flow_graph, state, link_exec_to_data)
+        out = inter_block_flow_link(ir_arch, flow_graph, irb_in_nodes, irb_out_nodes, state, link_exec_to_data)
         todo.update(out)
 
 
diff --git a/miasm2/analysis/data_flow.py b/miasm2/analysis/data_flow.py
index 892a01c3..67768264 100644
--- a/miasm2/analysis/data_flow.py
+++ b/miasm2/analysis/data_flow.py
@@ -2,7 +2,7 @@
 
 from collections import namedtuple
 from miasm2.core.graph import DiGraph
-from miasm2.ir.ir import AssignBlock
+from miasm2.ir.ir import AssignBlock, IRBlock
 
 class ReachingDefinitions(dict):
     """
@@ -248,11 +248,13 @@ def dead_simp(ir_a):
     defuse = DiGraphDefUse(reaching_defs, deref_mem=True)
     useful = set(dead_simp_useful_instrs(defuse, reaching_defs))
     for block in ir_a.blocks.itervalues():
+        irs = []
         for idx, assignblk in enumerate(block.irs):
             new_assignblk = dict(assignblk)
             for lval in assignblk:
                 if InstrNode(block.label, idx, lval) not in useful:
                     del new_assignblk[lval]
                     modified = True
-            block.irs[idx] = AssignBlock(new_assignblk, assignblk.instr)
+            irs.append(AssignBlock(new_assignblk, assignblk.instr))
+        ir_a.blocks[block.label] = IRBlock(block.label, irs)
     return modified
diff --git a/miasm2/arch/aarch64/sem.py b/miasm2/arch/aarch64/sem.py
index 79c72d32..d5209e3e 100644
--- a/miasm2/arch/aarch64/sem.py
+++ b/miasm2/arch/aarch64/sem.py
@@ -782,14 +782,14 @@ class ir_aarch64l(IntermediateRepresentation):
         src = self.expr_fix_regs_for_mode(e.src)
         return m2_expr.ExprAff(dst, src)
 
-    def irbloc_fix_regs_for_mode(self, irbloc, mode=64):
-        for idx, assignblk in enumerate(irbloc.irs):
+    def irbloc_fix_regs_for_mode(self, irblock, mode=64):
+        irs = []
+        for assignblk in irblock.irs:
             new_assignblk = dict(assignblk)
             for dst, src in assignblk.iteritems():
                 del(new_assignblk[dst])
                 # Special case for 64 bits:
                 # If destination is a 32 bit reg, zero extend the 64 bit reg
-
                 if (isinstance(dst, m2_expr.ExprId) and
                     dst.size == 32 and
                     dst in replace_regs):
@@ -799,27 +799,24 @@ class ir_aarch64l(IntermediateRepresentation):
                 dst = self.expr_fix_regs_for_mode(dst)
                 src = self.expr_fix_regs_for_mode(src)
                 new_assignblk[dst] = src
-            irbloc.irs[idx] = AssignBlock(new_assignblk, assignblk.instr)
-        if irbloc.dst is not None:
-            irbloc.dst = self.expr_fix_regs_for_mode(irbloc.dst)
+            irs.append(AssignBlock(new_assignblk, assignblk.instr))
+        return IRBlock(irblock.label, irs)
 
     def mod_pc(self, instr, instr_ir, extra_ir):
         "Replace PC by the instruction's offset"
         cur_offset = m2_expr.ExprInt(instr.offset, 64)
+        pc_fixed = {self.pc: cur_offset}
         for i, expr in enumerate(instr_ir):
             dst, src = expr.dst, expr.src
             if dst != self.pc:
-                dst = dst.replace_expr({self.pc: cur_offset})
-            src = src.replace_expr({self.pc: cur_offset})
+                dst = dst.replace_expr(pc_fixed)
+            src = src.replace_expr(pc_fixed)
             instr_ir[i] = m2_expr.ExprAff(dst, src)
-        for irblock in extra_ir:
-            for irs in irblock.irs:
-                for i, expr in enumerate(irs):
-                    dst, src = expr.dst, expr.src
-                    if dst != self.pc:
-                        dst = dst.replace_expr({self.pc: cur_offset})
-                    src = src.replace_expr({self.pc: cur_offset})
-                    irs[i] = m2_expr.ExprAff(dst, src)
+
+        for idx, irblock in enumerate(extra_ir):
+            extra_ir[idx] = irblock.modify_exprs(lambda expr: expr.replace_expr(pc_fixed) \
+                                                 if expr != self.pc else expr,
+                                                 lambda expr: expr.replace_expr(pc_fixed))
 
 
     def del_dst_zr(self, instr, instr_ir, extra_ir):
@@ -827,11 +824,16 @@ class ir_aarch64l(IntermediateRepresentation):
         regs_to_fix = [WZR, XZR]
         instr_ir = [expr for expr in instr_ir if expr.dst not in regs_to_fix]
 
+        new_irblocks = []
         for irblock in extra_ir:
-            for i, irs in enumerate(irblock.irs):
-                irblock.irs[i] = [expr for expr in irs if expr.dst not in regs_to_fix]
-
-        return instr_ir, extra_ir
+            irs = []
+            for assignblk in irblock.irs:
+                new_dsts = {dst:src for dst, src in assignblk.iteritems()
+                                if dst not in regs_to_fix}
+                irs.append(AssignBlock(new_dsts, assignblk.instr))
+            new_irblocks.append(IRBlock(irblock.label, irs))
+
+        return instr_ir, new_irblocks
 
 
 class ir_aarch64b(ir_aarch64l):
diff --git a/miasm2/arch/arm/sem.py b/miasm2/arch/arm/sem.py
index 710cdc9f..29b25538 100644
--- a/miasm2/arch/arm/sem.py
+++ b/miasm2/arch/arm/sem.py
@@ -1,5 +1,5 @@
 from miasm2.expression.expression import *
-from miasm2.ir.ir import IntermediateRepresentation, IRBlock
+from miasm2.ir.ir import IntermediateRepresentation, IRBlock, AssignBlock
 from miasm2.arch.arm.arch import mn_arm, mn_armt
 from miasm2.arch.arm.regs import *
 
@@ -1055,7 +1055,7 @@ def add_condition_expr(ir, instr, cond, instr_ir):
             break
     if not has_irdst:
         instr_ir.append(ExprAff(ir.IRDst, lbl_next))
-    e_do = IRBlock(lbl_do.name, [instr_ir])
+    e_do = IRBlock(lbl_do.name, [AssignBlock(instr_ir, instr)])
     e = [ExprAff(ir.IRDst, dst_cond)]
     return e, [e_do]
 
@@ -1246,20 +1246,15 @@ class ir_arml(IntermediateRepresentation):
                                   args[-1].args[0],
                                   args[-1].args[-1][:8].zeroExtend(32))
         instr_ir, extra_ir = get_mnemo_expr(self, instr, *args)
-        # if self.name.startswith('B'):
-        #    return instr_ir, extra_ir
-        for i, x in enumerate(instr_ir):
-            x = ExprAff(x.dst, x.src.replace_expr(
-                {self.pc: ExprInt(instr.offset + 8, 32)}))
-            instr_ir[i] = x
-        for irblock in extra_ir:
-            for irs in irblock.irs:
-                for i, x in enumerate(irs):
-                    x = ExprAff(x.dst, x.src.replace_expr(
-                        {self.pc: ExprInt(instr.offset + 8, 32)}))
-                    irs[i] = x
-        # return out_ir, extra_ir
-        return instr_ir, extra_ir
+
+        pc_fixed = {self.pc: ExprInt(instr.offset + 8, 32)}
+        for i, expr in enumerate(instr_ir):
+            instr_ir[i] = ExprAff(expr.dst, expr.src.replace_expr(pc_fixed))
+
+        new_extra_ir = [irblock.modify_exprs(mod_src=lambda expr: expr.replace_expr(pc_fixed))
+                        for irblock in extra_ir]
+
+        return instr_ir, new_extra_ir
 
 
 class ir_armb(ir_arml):
diff --git a/miasm2/arch/mips32/ira.py b/miasm2/arch/mips32/ira.py
index a2eab4fb..e342a6fd 100644
--- a/miasm2/arch/mips32/ira.py
+++ b/miasm2/arch/mips32/ira.py
@@ -11,12 +11,13 @@ class ir_a_mips32l(ir_mips32l, ira):
         ir_mips32l.__init__(self, symbol_pool)
         self.ret_reg = self.arch.regs.V0
 
-    def pre_add_instr(self, block, instr, irb_cur, ir_blocks_all, gen_pc_updt):
+    def pre_add_instr(self, block, instr, assignments, ir_blocks_all, gen_pc_updt):
         # Avoid adding side effects, already done in post_add_bloc
-        return irb_cur
+        return False
 
     def post_add_bloc(self, block, ir_blocks):
         IntermediateRepresentation.post_add_bloc(self, block, ir_blocks)
+        new_irblocks = []
         for irb in ir_blocks:
             pc_val = None
             lr_val = None
@@ -25,13 +26,15 @@ class ir_a_mips32l(ir_mips32l, ira):
                 lr_val = assignblk.get(self.arch.regs.RA, lr_val)
 
             if pc_val is None or lr_val is None:
+                new_irblocks.append(irb)
                 continue
             if not expr_is_int_or_label(lr_val):
+                new_irblocks.append(irb)
                 continue
             if expr_is_label(lr_val):
                 lr_val = ExprInt(lr_val.name.offset, 32)
 
-            instr = block.irs[-2].instr
+            instr = block.lines[-2]
             if lr_val.arg != instr.offset + 8:
                 raise ValueError("Wrong arg")
 
@@ -42,9 +45,9 @@ class ir_a_mips32l(ir_mips32l, ira):
             irs.append(AssignBlock([ExprAff(self.IRDst,
                                             ExprId(lbl, size=self.pc.size))],
                                    instr))
-            nblock = IRBlock(new_lbl, irs)
-            self.blocks[new_lbl] = nblock
-            irb.dst = ExprId(new_lbl, size=self.pc.size)
+            new_irblocks.append(IRBlock(new_lbl, irs))
+            new_irblocks.append(irb.set_dst(ExprId(new_lbl, size=self.pc.size)))
+        return new_irblocks
 
     def get_out_regs(self, _):
         return set([self.ret_reg, self.sp])
diff --git a/miasm2/arch/mips32/jit.py b/miasm2/arch/mips32/jit.py
index 9b46589f..493da595 100644
--- a/miasm2/arch/mips32/jit.py
+++ b/miasm2/arch/mips32/jit.py
@@ -5,7 +5,7 @@ from miasm2.core import asmblock
 from miasm2.core.utils import pck32, upck32
 from miasm2.arch.mips32.sem import ir_mips32l, ir_mips32b
 from miasm2.jitter.codegen import CGen
-from miasm2.ir.ir import AssignBlock
+from miasm2.ir.ir import AssignBlock, IRBlock
 import miasm2.expression.expression as m2_expr
 
 log = logging.getLogger('jit_mips32')
@@ -40,24 +40,27 @@ class mipsCGen(CGen):
 
     def block2assignblks(self, block):
         irblocks_list = super(mipsCGen, self).block2assignblks(block)
-        for instr, irblocks in zip(block.lines, irblocks_list):
-            if not instr.breakflow():
-                continue
-            for irblock in irblocks:
-                for idx, assignblock in enumerate(irblock.irs):
+        for irblocks in irblocks_list:
+            for blk_idx, irblock in enumerate(irblocks):
+                has_breakflow = any(assignblock.instr.breakflow() for assignblock in irblock.irs)
+                if not has_breakflow:
+                    continue
+
+                irs = []
+                for assignblock in irblock.irs:
                     if self.ir_arch.pc not in assignblock:
+                        irs.append(AssignBlock(assignments, assignblock.instr))
                         continue
-                    new_assignblock = dict(assignblock)
+                    assignments = dict(assignblock)
                     # Add internal branch destination
-                    new_assignblock[self.delay_slot_dst] = assignblock[
+                    assignments[self.delay_slot_dst] = assignblock[
                         self.ir_arch.pc]
-                    new_assignblock[self.delay_slot_set] = m2_expr.ExprInt(1, 32)
+                    assignments[self.delay_slot_set] = m2_expr.ExprInt(1, 32)
                     # Replace IRDst with next instruction
-                    new_assignblock[self.ir_arch.IRDst] = m2_expr.ExprId(
-                        self.ir_arch.get_next_instr(instr))
-                    irblock.dst = m2_expr.ExprId(
-                        self.ir_arch.get_next_instr(instr))
-                    irblock.irs[idx] = AssignBlock(new_assignblock, assignblock.instr)
+                    assignments[self.ir_arch.IRDst] = m2_expr.ExprId(
+                        self.ir_arch.get_next_instr(assignblock.instr))
+                    irs.append(AssignBlock(assignments, assignblock.instr))
+                irblocks[blk_idx] = IRBlock(irblock.label, irs)
 
         return irblocks_list
 
diff --git a/miasm2/arch/mips32/sem.py b/miasm2/arch/mips32/sem.py
index bc050b38..645f9a4f 100644
--- a/miasm2/arch/mips32/sem.py
+++ b/miasm2/arch/mips32/sem.py
@@ -441,17 +441,14 @@ class ir_mips32l(IntermediateRepresentation):
         args = instr.args
         instr_ir, extra_ir = get_mnemo_expr(self, instr, *args)
 
-        for i, x in enumerate(instr_ir):
-            x = m2_expr.ExprAff(x.dst, x.src.replace_expr(
-                {self.pc: m2_expr.ExprInt(instr.offset + 4, 32)}))
-            instr_ir[i] = x
-        for irblock in extra_ir:
-            for irs in irblock.irs:
-                for i, x in enumerate(irs):
-                    x = m2_expr.ExprAff(x.dst, x.src.replace_expr(
-                        {self.pc: m2_expr.ExprInt(instr.offset + 4, 32)}))
-                    irs[i] = x
-        return instr_ir, extra_ir
+        pc_fixed = {self.pc: m2_expr.ExprInt(instr.offset + 4, 32)}
+
+        instr_ir = [m2_expr.ExprAff(expr.dst, expr.src.replace_expr(pc_fixed))
+                    for expr in instr_ir]
+
+        new_extra_ir = [irblock.modify_exprs(mod_src=lambda expr: expr.replace_expr(pc_fixed))
+                        for irblock in extra_ir]
+        return instr_ir, new_extra_ir
 
     def get_next_instr(self, instr):
         return self.symbol_pool.getby_offset_create(instr.offset  + 4)
diff --git a/miasm2/arch/x86/jit.py b/miasm2/arch/x86/jit.py
index 9ffd8a82..d39f1f38 100644
--- a/miasm2/arch/x86/jit.py
+++ b/miasm2/arch/x86/jit.py
@@ -45,7 +45,7 @@ class jitter_x86_16(jitter):
         self.ir_arch.irbloc_fix_regs_for_mode = self.ir_archbloc_fix_regs_for_mode
 
     def ir_archbloc_fix_regs_for_mode(self, irblock, attrib=64):
-        self.orig_irbloc_fix_regs_for_mode(irblock, 64)
+        return self.orig_irbloc_fix_regs_for_mode(irblock, 64)
 
     def push_uint16_t(self, value):
         self.cpu.SP -= self.ir_arch.sp.size / 8
@@ -78,7 +78,7 @@ class jitter_x86_32(jitter):
         self.ir_arch.irbloc_fix_regs_for_mode = self.ir_archbloc_fix_regs_for_mode
 
     def ir_archbloc_fix_regs_for_mode(self, irblock, attrib=64):
-        self.orig_irbloc_fix_regs_for_mode(irblock, 64)
+        return self.orig_irbloc_fix_regs_for_mode(irblock, 64)
 
     def push_uint16_t(self, value):
         self.cpu.ESP -= self.ir_arch.sp.size / 8
@@ -192,7 +192,7 @@ class jitter_x86_64(jitter):
         self.ir_arch.irbloc_fix_regs_for_mode = self.ir_archbloc_fix_regs_for_mode
 
     def ir_archbloc_fix_regs_for_mode(self, irblock, attrib=64):
-        self.orig_irbloc_fix_regs_for_mode(irblock, 64)
+        return self.orig_irbloc_fix_regs_for_mode(irblock, 64)
 
     def push_uint64_t(self, value):
         self.cpu.RSP -= self.ir_arch.sp.size / 8
diff --git a/miasm2/arch/x86/sem.py b/miasm2/arch/x86/sem.py
index 70927435..b3dfb3ef 100644
--- a/miasm2/arch/x86/sem.py
+++ b/miasm2/arch/x86/sem.py
@@ -263,7 +263,7 @@ def gen_fcmov(ir, instr, cond, arg1, arg2, mov_if):
     e_do, extra_irs = [m2_expr.ExprAff(arg1, arg2)], []
     e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
     e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(cond, dstA, dstB)))
-    return e, [IRBlock(lbl_do.name, [e_do])]
+    return e, [IRBlock(lbl_do.name, [AssignBlock(e_do, instr)])]
 
 
 def gen_cmov(ir, instr, cond, dst, src, mov_if):
@@ -283,7 +283,7 @@ def gen_cmov(ir, instr, cond, dst, src, mov_if):
     e_do, extra_irs = mov(ir, instr, dst, src)
     e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
     e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(cond, dstA, dstB)))
-    return e, [IRBlock(lbl_do.name, [e_do])]
+    return e, [IRBlock(lbl_do.name, [AssignBlock(e_do, instr)])]
 
 
 def mov(_, instr, dst, src):
@@ -504,7 +504,7 @@ def _rotate_tpl(ir, instr, dst, src, op, left=False, include_cf=False):
     e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
     e.append(m2_expr.ExprAff(
         ir.IRDst, m2_expr.ExprCond(shifter, lbl_do, lbl_skip)))
-    return (e, [IRBlock(lbl_do.name, [e_do])])
+    return (e, [IRBlock(lbl_do.name, [AssignBlock(e_do, instr)])])
 
 
 def l_rol(ir, instr, dst, src):
@@ -601,7 +601,7 @@ def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False,
     e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip))
     e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(shifter, lbl_do,
                                                         lbl_skip)))
-    return e, [IRBlock(lbl_do.name, [e_do])]
+    return e, [IRBlock(lbl_do.name, [AssignBlock(e_do, instr)])]
 
 
 def sar(ir, instr, dst, src):
@@ -957,13 +957,13 @@ def cmps(ir, instr, size):
     e0.append(m2_expr.ExprAff(src1, src1 + offset))
     e0.append(m2_expr.ExprAff(src2, src2 + offset))
     e0.append(m2_expr.ExprAff(ir.IRDst, lbl_next))
-    e0 = IRBlock(lbl_df_0.name, [e0])
+    e0 = IRBlock(lbl_df_0.name, [AssignBlock(e0, instr)])
 
     e1 = []
     e1.append(m2_expr.ExprAff(src1, src1 - offset))
     e1.append(m2_expr.ExprAff(src2, src2 - offset))
     e1.append(m2_expr.ExprAff(ir.IRDst, lbl_next))
-    e1 = IRBlock(lbl_df_1.name, [e1])
+    e1 = IRBlock(lbl_df_1.name, [AssignBlock(e1, instr)])
 
     e.append(m2_expr.ExprAff(ir.IRDst,
                              m2_expr.ExprCond(df, lbl_df_1, lbl_df_0)))
@@ -993,12 +993,12 @@ def scas(ir, instr, size):
     e0.append(m2_expr.ExprAff(src, src + offset))
 
     e0.append(m2_expr.ExprAff(ir.IRDst, lbl_next))
-    e0 = IRBlock(lbl_df_0.name, [e0])
+    e0 = IRBlock(lbl_df_0.name, [AssignBlock(e0, instr)])
 
     e1 = []
     e1.append(m2_expr.ExprAff(src, src - offset))
     e1.append(m2_expr.ExprAff(ir.IRDst, lbl_next))
-    e1 = IRBlock(lbl_df_1.name, [e1])
+    e1 = IRBlock(lbl_df_1.name, [AssignBlock(e1, instr)])
 
     e.append(m2_expr.ExprAff(ir.IRDst,
                              m2_expr.ExprCond(df, lbl_df_1, lbl_df_0)))
@@ -1467,13 +1467,13 @@ def div(ir, instr, src1):
     do_div = []
     do_div += e
     do_div.append(m2_expr.ExprAff(ir.IRDst, lbl_next))
-    blk_div = IRBlock(lbl_div.name, [do_div])
+    blk_div = IRBlock(lbl_div.name, [AssignBlock(do_div, instr)])
 
     do_except = []
     do_except.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(
         EXCEPT_DIV_BY_ZERO, exception_flags.size)))
     do_except.append(m2_expr.ExprAff(ir.IRDst, lbl_next))
-    blk_except = IRBlock(lbl_except.name, [do_except])
+    blk_except = IRBlock(lbl_except.name, [AssignBlock(do_except, instr)])
 
     e = []
     e.append(m2_expr.ExprAff(ir.IRDst,
@@ -1513,13 +1513,13 @@ def idiv(ir, instr, src1):
     do_div = []
     do_div += e
     do_div.append(m2_expr.ExprAff(ir.IRDst, lbl_next))
-    blk_div = IRBlock(lbl_div.name, [do_div])
+    blk_div = IRBlock(lbl_div.name, [AssignBlock(do_div, instr)])
 
     do_except = []
     do_except.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(
         EXCEPT_DIV_BY_ZERO, exception_flags.size)))
     do_except.append(m2_expr.ExprAff(ir.IRDst, lbl_next))
-    blk_except = IRBlock(lbl_except.name, [do_except])
+    blk_except = IRBlock(lbl_except.name, [AssignBlock(do_except, instr)])
 
     e = []
     e.append(m2_expr.ExprAff(ir.IRDst,
@@ -1679,12 +1679,12 @@ def stos(ir, instr, size):
     e0 = []
     e0.append(m2_expr.ExprAff(addr_o, addr_p))
     e0.append(m2_expr.ExprAff(ir.IRDst, lbl_next))
-    e0 = IRBlock(lbl_df_0.name, [e0])
+    e0 = IRBlock(lbl_df_0.name, [AssignBlock(e0, instr)])
 
     e1 = []
     e1.append(m2_expr.ExprAff(addr_o, addr_m))
     e1.append(m2_expr.ExprAff(ir.IRDst, lbl_next))
-    e1 = IRBlock(lbl_df_1.name, [e1])
+    e1 = IRBlock(lbl_df_1.name, [AssignBlock(e1, instr)])
 
     e = []
     e.append(m2_expr.ExprAff(ir.ExprMem(addr, size), b))
@@ -1714,12 +1714,12 @@ def lods(ir, instr, size):
     e0 = []
     e0.append(m2_expr.ExprAff(addr_o, addr_p))
     e0.append(m2_expr.ExprAff(ir.IRDst, lbl_next))
-    e0 = IRBlock(lbl_df_0.name, [e0])
+    e0 = IRBlock(lbl_df_0.name, [AssignBlock(e0, instr)])
 
     e1 = []
     e1.append(m2_expr.ExprAff(addr_o, addr_m))
     e1.append(m2_expr.ExprAff(ir.IRDst, lbl_next))
-    e1 = IRBlock(lbl_df_1.name, [e1])
+    e1 = IRBlock(lbl_df_1.name, [AssignBlock(e1, instr)])
 
     e = []
     if instr.mode == 64 and b.size == 32:
@@ -1761,13 +1761,13 @@ def movs(ir, instr, size):
     e0.append(m2_expr.ExprAff(src, src + offset))
     e0.append(m2_expr.ExprAff(dst, dst + offset))
     e0.append(m2_expr.ExprAff(ir.IRDst, lbl_next))
-    e0 = IRBlock(lbl_df_0.name, [e0])
+    e0 = IRBlock(lbl_df_0.name, [AssignBlock(e0, instr)])
 
     e1 = []
     e1.append(m2_expr.ExprAff(src, src - offset))
     e1.append(m2_expr.ExprAff(dst, dst - offset))
     e1.append(m2_expr.ExprAff(ir.IRDst, lbl_next))
-    e1 = IRBlock(lbl_df_1.name, [e1])
+    e1 = IRBlock(lbl_df_1.name, [AssignBlock(e1, instr)])
 
     e.append(m2_expr.ExprAff(ir.IRDst,
                              m2_expr.ExprCond(df, lbl_df_1, lbl_df_0)))
@@ -2800,8 +2800,8 @@ def bsr_bsf(ir, instr, dst, src, op_name):
     e_src_not_null.append(m2_expr.ExprAff(dst, m2_expr.ExprOp(op_name, src)))
     e_src_not_null.append(aff_dst)
 
-    return e, [IRBlock(lbl_src_null.name, [e_src_null]),
-               IRBlock(lbl_src_not_null.name, [e_src_not_null])]
+    return e, [IRBlock(lbl_src_null.name, [AssignBlock(e_src_null, instr)]),
+               IRBlock(lbl_src_not_null.name, [AssignBlock(e_src_not_null, instr)])]
 
 
 def bsf(ir, instr, dst, src):
@@ -3699,7 +3699,8 @@ def ps_rl_ll(ir, instr, dst, src, op, size):
     e_do = []
     e.append(m2_expr.ExprAff(dst[0:dst.size], m2_expr.ExprCompose(*slices)))
     e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_next))
-    return e, [IRBlock(lbl_do.name, [e_do]), IRBlock(lbl_zero.name, [e_zero])]
+    return e, [IRBlock(lbl_do.name, [AssignBlock(e_do, instr)]),
+               IRBlock(lbl_zero.name, [AssignBlock(e_zero, instr)])]
 
 
 def psrlw(ir, instr, dst, src):
@@ -4615,11 +4616,10 @@ class ir_x86_16(IntermediateRepresentation):
         lbl_skip = m2_expr.ExprId(self.get_next_label(instr), self.IRDst.size)
         lbl_next = m2_expr.ExprId(self.get_next_label(instr), self.IRDst.size)
 
-        for irblock in extra_ir:
-            for ir in irblock.irs:
-                for i, e in enumerate(ir):
-                    src = e.src.replace_expr({lbl_next: lbl_end})
-                    ir[i] = m2_expr.ExprAff(e.dst, src)
+        fix_next_lbl = {lbl_next: lbl_end}
+        new_extra_ir = [irblock.modify_exprs(mod_src=lambda expr: expr.replace_expr(fix_next_lbl))
+                        for irblock in extra_ir]
+
         cond_bloc = []
         cond_bloc.append(m2_expr.ExprAff(c_reg,
                                          c_reg - m2_expr.ExprInt(1,
@@ -4627,14 +4627,13 @@ class ir_x86_16(IntermediateRepresentation):
         cond_bloc.append(m2_expr.ExprAff(self.IRDst, m2_expr.ExprCond(c_cond,
                                                                       lbl_skip,
                                                                       lbl_do)))
-        cond_bloc = IRBlock(lbl_end.name, [cond_bloc])
+        cond_bloc = IRBlock(lbl_end.name, [AssignBlock(cond_bloc, instr)])
         e_do = instr_ir
 
-        c = IRBlock(lbl_do.name, [e_do])
-        c.except_automod = False
+        c = IRBlock(lbl_do.name, [AssignBlock(e_do, instr)])
         e_n = [m2_expr.ExprAff(self.IRDst, m2_expr.ExprCond(c_reg, lbl_do,
                                                             lbl_skip))]
-        return e_n, [cond_bloc, c] + extra_ir
+        return e_n, [cond_bloc, c] + new_extra_ir
 
     def expr_fix_regs_for_mode(self, e, mode=64):
         return e.replace_expr(replace_regs[mode])
@@ -4644,8 +4643,9 @@ class ir_x86_16(IntermediateRepresentation):
         src = self.expr_fix_regs_for_mode(e.src, mode)
         return m2_expr.ExprAff(dst, src)
 
-    def irbloc_fix_regs_for_mode(self, irbloc, mode=64):
-        for idx, assignblk in enumerate(irbloc.irs):
+    def irbloc_fix_regs_for_mode(self, irblock, mode=64):
+        irs = []
+        for assignblk in irblock.irs:
             new_assignblk = dict(assignblk)
             for dst, src in assignblk.iteritems():
                 del new_assignblk[dst]
@@ -4660,9 +4660,8 @@ class ir_x86_16(IntermediateRepresentation):
                 dst = self.expr_fix_regs_for_mode(dst, mode)
                 src = self.expr_fix_regs_for_mode(src, mode)
                 new_assignblk[dst] = src
-            irbloc.irs[idx] = AssignBlock(new_assignblk, assignblk.instr)
-        if irbloc.dst is not None:
-            irbloc.dst = self.expr_fix_regs_for_mode(irbloc.dst, mode)
+            irs.append(AssignBlock(new_assignblk, assignblk.instr))
+        return IRBlock(irblock.label, irs)
 
 
 class ir_x86_32(ir_x86_16):
@@ -4694,21 +4693,16 @@ class ir_x86_64(ir_x86_16):
 
     def mod_pc(self, instr, instr_ir, extra_ir):
         # fix RIP for 64 bit
+        pc_fixed = {self.pc: m2_expr.ExprInt(instr.offset + instr.l, 64)}
+
         for i, expr in enumerate(instr_ir):
             dst, src = expr.dst, expr.src
             if dst != self.pc:
-                dst = dst.replace_expr(
-                    {self.pc: m2_expr.ExprInt(instr.offset + instr.l, 64)})
-            src = src.replace_expr(
-                {self.pc: m2_expr.ExprInt(instr.offset + instr.l, 64)})
+                dst = dst.replace_expr(pc_fixed)
+            src = src.replace_expr(pc_fixed)
             instr_ir[i] = m2_expr.ExprAff(dst, src)
-        for irblock in extra_ir:
-            for irs in irblock.irs:
-                for i, expr in enumerate(irs):
-                    dst, src = expr.dst, expr.src
-                    if dst != self.pc:
-                        new_pc = m2_expr.ExprInt(instr.offset + instr.l, 64)
-                        dst = dst.replace_expr({self.pc: new_pc})
-                    src = src.replace_expr(
-                        {self.pc: m2_expr.ExprInt(instr.offset + instr.l, 64)})
-                    irs[i] = m2_expr.ExprAff(dst, src)
+
+        for idx, irblock in enumerate(extra_ir):
+            extra_ir[idx] = irblock.modify_exprs(lambda expr: expr.replace_expr(pc_fixed) \
+                                                 if expr != self.pc else expr,
+                                                 lambda expr: expr.replace_expr(pc_fixed))
diff --git a/miasm2/core/asmblock.py b/miasm2/core/asmblock.py
index 72f259f9..965b22c4 100644
--- a/miasm2/core/asmblock.py
+++ b/miasm2/core/asmblock.py
@@ -45,7 +45,7 @@ class AsmLabel(object):
         self.name = name
         self.attrib = None
         if offset is None:
-            self.offset = offset
+            self.offset = None
         else:
             self.offset = int(offset)
 
diff --git a/miasm2/core/sembuilder.py b/miasm2/core/sembuilder.py
index 138e4552..8d6d3e07 100644
--- a/miasm2/core/sembuilder.py
+++ b/miasm2/core/sembuilder.py
@@ -5,7 +5,7 @@ import ast
 import re
 
 import miasm2.expression.expression as m2_expr
-from miasm2.ir.ir import IRBlock
+from miasm2.ir.ir import IRBlock, AssignBlock
 
 
 class MiasmTransformer(ast.NodeTransformer):
@@ -127,6 +127,7 @@ class SemBuilder(object):
         self.transformer = MiasmTransformer()
         self._ctx = dict(m2_expr.__dict__)
         self._ctx["IRBlock"] = IRBlock
+        self._ctx["AssignBlock"] = AssignBlock
         self._functions = {}
 
         # Update context
@@ -246,20 +247,31 @@ class SemBuilder(object):
                                        starargs=None,
                                        kwargs=None)
                     sub_blocks[-1][-1].append(jmp_end)
-                    sub_blocks[-1][-1] = ast.List(elts=sub_blocks[-1][-1],
-                                                  ctx=ast.Load())
-                    sub_blocks[-1] = ast.List(elts=sub_blocks[-1],
-                                              ctx=ast.Load())
+
+
+                    instr = ast.Name(id='instr', ctx=ast.Load())
+                    effects = ast.List(elts=sub_blocks[-1][-1],
+                                       ctx=ast.Load())
+                    assignblk = ast.Call(func=ast.Name(id='AssignBlock',
+                                                       ctx=ast.Load()),
+                                         args=[effects, instr],
+                                         keywords=[],
+                                         starargs=None,
+                                         kwargs=None)
+
 
                     ## Replace the block with a call to 'IRBlock'
                     lbl_if_name = ast.Attribute(value=ast.Name(id=lbl_name,
                                                                ctx=ast.Load()),
                                                 attr='name', ctx=ast.Load())
 
+                    assignblks = ast.List(elts=[assignblk],
+                                          ctx=ast.Load())
+
                     sub_blocks[-1] = ast.Call(func=ast.Name(id='IRBlock',
                                                             ctx=ast.Load()),
                                               args=[lbl_if_name,
-                                                    sub_blocks[-1]],
+                                                    assignblks],
                                               keywords=[],
                                               starargs=None,
                                               kwargs=None)
diff --git a/miasm2/ir/analysis.py b/miasm2/ir/analysis.py
index 1d9310fc..fc0c81c9 100644
--- a/miasm2/ir/analysis.py
+++ b/miasm2/ir/analysis.py
@@ -1,13 +1,12 @@
 #-*- coding:utf-8 -*-
 
+import warnings
 import logging
 
 from miasm2.ir.symbexec import SymbolicExecutionEngine
 from miasm2.ir.ir import IntermediateRepresentation, AssignBlock
-from miasm2.expression.expression \
-    import ExprAff, ExprCond, ExprId, ExprInt, ExprMem, ExprOp
+from miasm2.expression.expression import ExprAff, ExprOp
 from miasm2.analysis.data_flow import dead_simp as new_dead_simp_imp
-import warnings
 
 log = logging.getLogger("analysis")
 console_handler = logging.StreamHandler()
@@ -29,47 +28,30 @@ class ira(IntermediateRepresentation):
 
     """
 
-    def call_effects(self, ad, instr):
-        """Default modelisation of a function call to @ad. This may be used to:
+    def call_effects(self, addr, instr):
+        """Default modelisation of a function call to @addr. This may be used to:
 
         * insert dependencies to arguments (stack base, registers, ...)
         * add some side effects (stack clean, return value, ...)
 
-        @ad: (Expr) address of the called function
+        @addr: (Expr) address of the called function
         @instr: native instruction which is responsible of the call
         """
 
         assignblk = AssignBlock({
-            self.ret_reg: ExprOp('call_func_ret', ad, self.sp),
-            self.sp: ExprOp('call_func_stack', ad, self.sp)},
+            self.ret_reg: ExprOp('call_func_ret', addr, self.sp),
+            self.sp: ExprOp('call_func_stack', addr, self.sp)},
             instr)
         return [assignblk]
 
-    def pre_add_instr(self, block, instr, irb_cur, ir_blocks_all, gen_pc_update):
+    def pre_add_instr(self, block, instr, assignments, ir_blocks_all, gen_pc_update):
         """Replace function call with corresponding call effects,
         inside the IR block"""
         if not instr.is_subcall():
-            return irb_cur
+            return False
         call_effects = self.call_effects(instr.args[0], instr)
-        for assignblk in call_effects:
-            irb_cur.irs.append(assignblk)
-        return None
-
-    def gen_equations(self):
-        for irb in self.blocks.values():
-            symbols_init = dict(self.arch.regs.all_regs_ids_init)
-
-            sb = SymbolicExecutionEngine(self, dict(symbols_init))
-            sb.emulbloc(irb)
-            eqs = []
-            for n_w in sb.symbols:
-                v = sb.symbols[n_w]
-                if n_w in symbols_init and symbols_init[n_w] == v:
-                    continue
-                eqs.append(ExprAff(n_w, v))
-            print '*' * 40
-            print irb
-            irb.irs = [AssignBlock(eqs)]
+        assignments+= call_effects
+        return True
 
     def sizeof_char(self):
         "Return the size of a char in bits"
diff --git a/miasm2/ir/ir.py b/miasm2/ir/ir.py
index 8154d4da..2509e901 100644
--- a/miasm2/ir/ir.py
+++ b/miasm2/ir/ir.py
@@ -258,6 +258,8 @@ class IRBlock(object):
     Stand for an intermediate representation  basic block.
     """
 
+    __slots__ = ["label", "_assignments", "_dst", "_dst_linenb"]
+
     def __init__(self, label, irs):
         """
         @label: AsmLabel of the IR basic block
@@ -266,15 +268,20 @@ class IRBlock(object):
 
         assert isinstance(label, AsmLabel)
         self.label = label
-        self.irs = irs
-        self.except_automod = True
+        for assignblk in irs:
+            assert isinstance(assignblk, AssignBlock)
+        self._assignments = tuple(irs)
         self._dst = None
         self._dst_linenb = None
 
-    def _get_dst(self):
-        """Find the IRDst affectation and update dst, dst_linenb accordingly"""
-        if self._dst is not None:
-            return self._dst
+    @property
+    def irs(self):
+        return self._assignments
+
+    def is_dst_set(self):
+        return self._dst is not None
+
+    def cache_dst(self):
         final_dst = None
         final_linenb = None
         for linenb, assignblk in enumerate(self.irs):
@@ -288,25 +295,34 @@ class IRBlock(object):
         self._dst_linenb = final_linenb
         return final_dst
 
-    def _set_dst(self, value):
-        """Find and replace the IRDst affectation's source by @value"""
-        if self._dst_linenb is None:
-            self._get_dst()
+    @property
+    def dst(self):
+        """Return the value of IRDst for the IRBlock"""
+        if self.is_dst_set():
+            return self._dst
+        return self.cache_dst()
 
-        new_assignblk = dict(self.irs[self._dst_linenb])
-        for dst in new_assignblk:
-            if dst.is_id("IRDst"):
-                new_assignblk[dst] = value
-                # Sanity check is already done in _get_dst
-                break
-        self._dst = value
-        instr = self.irs[self._dst_linenb].instr
-        self.irs[self._dst_linenb] = AssignBlock(new_assignblk, instr)
-    dst = property(_get_dst, _set_dst)
+    def set_dst(self, value):
+        """Generate a new IRBlock with a dst (IRBlock) fixed to @value"""
+        irs = []
+        dst_found = False
+        for assignblk in self.irs:
+            new_assignblk = {}
+            for dst, src in assignblk.iteritems():
+                if dst.is_id("IRDst"):
+                    assert dst_found is False
+                    dst_found = True
+                    new_assignblk[dst] = value
+                else:
+                    new_assignblk[dst] = src
+            irs.append(AssignBlock(new_assignblk, assignblk.instr))
+        return IRBlock(self.label, irs)
 
     @property
     def dst_linenb(self):
         """Line number of the IRDst setting statement in the current irs"""
+        if not self.is_dst_set():
+            self.cache_dst()
         return self._dst_linenb
 
     def __str__(self):
@@ -319,6 +335,28 @@ class IRBlock(object):
         return "\n".join(out)
 
 
+    def modify_exprs(self, mod_dst=None, mod_src=None):
+        """
+        Generate a new IRBlock with its AssignBlock expressions modified
+        according to @mod_dst and @mod_src
+        @mod_dst: function called to modify Expression destination
+        @mod_src: function called to modify Expression source
+        """
+
+        if mod_dst is None:
+            mod_dst = lambda expr:expr
+        if mod_src is None:
+            mod_src = lambda expr:expr
+
+        assignblks = []
+        for assignblk in self.irs:
+            new_assignblk = {}
+            for dst, src in assignblk.iteritems():
+                new_assignblk[mod_dst(dst)] = mod_src(src)
+            assignblks.append(AssignBlock(new_assignblk, assignblk.instr))
+        return IRBlock(self.label, assignblks)
+
+
 class irbloc(IRBlock):
     """
     DEPRECATED object
@@ -415,14 +453,14 @@ class IntermediateRepresentation(object):
         raise NotImplementedError("Abstract Method")
 
     def instr2ir(self, instr):
-        ir_bloc_cur, extra_assignblk = self.get_ir(instr)
-        for irb in extra_assignblk:
+        ir_bloc_cur, extra_irblocks = self.get_ir(instr)
+        for index, irb in enumerate(extra_irblocks):
             irs = []
             for assignblk in irb.irs:
                 irs.append(AssignBlock(assignblk, instr))
-            irb.irs = irs
+            extra_irblocks[index] = IRBlock(irb.label, irs)
         assignblk = AssignBlock(ir_bloc_cur, instr)
-        return assignblk, extra_assignblk
+        return assignblk, extra_irblocks
 
     def get_label(self, addr):
         """Transforms an ExprId/ExprInt/label/int into a label
@@ -460,16 +498,18 @@ class IntermediateRepresentation(object):
                     out.add(irb)
         return out
 
-    def gen_pc_update(self, irblock, instr):
-        irblock.irs.append(AssignBlock({self.pc: m2_expr.ExprInt(instr.offset, self.pc.size)},
-                                       instr))
+    def gen_pc_update(self, assignments, instr):
+        offset = m2_expr.ExprInt(instr.offset, self.pc.size)
+        assignments.append(AssignBlock({self.pc:offset}, instr))
 
-    def pre_add_instr(self, block, instr, irb_cur, ir_blocks_all, gen_pc_updt):
+    def pre_add_instr(self, block, instr, assignments, ir_blocks_all, gen_pc_updt):
         """Function called before adding an instruction from the the native @block to
         the current irbloc.
 
-        Returns None if the addition needs an irblock split, @irb_cur in other
-        cases.
+        Returns a couple. The first element is the new irblock. The second the a
+        bool:
+        * True if the current irblock must be split
+        * False in other cases.
 
         @block: native block source
         @instr: native instruction
@@ -479,14 +519,16 @@ class IntermediateRepresentation(object):
 
         """
 
-        return irb_cur
+        return False
 
-    def add_instr_to_irblock(self, block, instr, irb_cur, ir_blocks_all, gen_pc_updt):
+    def add_instr_to_irblock(self, block, instr, assignments, ir_blocks_all, gen_pc_updt):
         """
         Add the IR effects of an instruction to the current irblock.
 
-        Returns None if the addition needs an irblock split, @irb_cur in other
-        cases.
+        Returns a couple. The first element is the new irblock. The second the a
+        bool:
+        * True if the current irblock must be split
+        * False in other cases.
 
         @block: native block source
         @instr: native instruction
@@ -495,21 +537,20 @@ class IntermediateRepresentation(object):
         @gen_pc_updt: insert PC update effects between instructions
         """
 
-        irb_cur = self.pre_add_instr(block, instr, irb_cur, ir_blocks_all, gen_pc_updt)
-        if irb_cur is None:
-            return None
+        split = self.pre_add_instr(block, instr, assignments, ir_blocks_all, gen_pc_updt)
+        if split:
+            return True
 
         assignblk, ir_blocks_extra = self.instr2ir(instr)
 
         if gen_pc_updt is not False:
-            self.gen_pc_update(irb_cur, instr)
-
-        irb_cur.irs.append(assignblk)
+            self.gen_pc_update(assignments, instr)
 
+        assignments.append(assignblk)
+        ir_blocks_all += ir_blocks_extra
         if ir_blocks_extra:
-            ir_blocks_all += ir_blocks_extra
-            irb_cur = None
-        return irb_cur
+            return True
+        return False
 
     def add_bloc(self, block, gen_pc_updt=False):
         """
@@ -518,17 +559,25 @@ class IntermediateRepresentation(object):
         @gen_pc_updt: insert PC update effects between instructions
         """
 
-        irb_cur = None
+        label = None
         ir_blocks_all = []
         for instr in block.lines:
-            if irb_cur is None:
+            if label is None:
+                assignments = []
                 label = self.get_instr_label(instr)
-                irb_cur = IRBlock(label, [])
-                ir_blocks_all.append(irb_cur)
-            irb_cur = self.add_instr_to_irblock(block, instr, irb_cur,
-                                                ir_blocks_all, gen_pc_updt)
-        self.post_add_bloc(block, ir_blocks_all)
-        return ir_blocks_all
+            split = self.add_instr_to_irblock(block, instr, assignments,
+                                              ir_blocks_all, gen_pc_updt)
+            if split:
+                ir_blocks_all.append(IRBlock(label, assignments))
+                label = None
+                assignments = []
+        if label is not None:
+            ir_blocks_all.append(IRBlock(label, assignments))
+
+        new_ir_blocks_all = self.post_add_bloc(block, ir_blocks_all)
+        for irblock in new_ir_blocks_all:
+            self.blocks[irblock.label] = irblock
+        return new_ir_blocks_all
 
     def expr_fix_regs_for_mode(self, expr, *args, **kwargs):
         return expr
@@ -536,8 +585,8 @@ class IntermediateRepresentation(object):
     def expraff_fix_regs_for_mode(self, expr, *args, **kwargs):
         return expr
 
-    def irbloc_fix_regs_for_mode(self, irbloc, *args, **kwargs):
-        return
+    def irbloc_fix_regs_for_mode(self, irblock, *args, **kwargs):
+        return irblock
 
     def is_pc_written(self, block):
         all_pc = self.arch.pc.values()
@@ -548,7 +597,7 @@ class IntermediateRepresentation(object):
         return None
 
     def set_empty_dst_to_next(self, block, ir_blocks):
-        for irblock in ir_blocks:
+        for index, irblock in enumerate(ir_blocks):
             if irblock.dst is not None:
                 continue
             next_lbl = block.get_next()
@@ -558,18 +607,20 @@ class IntermediateRepresentation(object):
             else:
                 dst = m2_expr.ExprId(next_lbl,
                                      self.pc.size)
-            irblock.irs.append(AssignBlock({self.IRDst: dst},
-                                           irblock.irs[-1].instr))
+            assignblk = AssignBlock({self.IRDst: dst}, irblock.irs[-1].instr)
+            ir_blocks[index] = IRBlock(irblock.label, list(irblock.irs) + [assignblk])
 
     def post_add_bloc(self, block, ir_blocks):
         self.set_empty_dst_to_next(block, ir_blocks)
 
+        new_irblocks = []
         for irblock in ir_blocks:
-            self.irbloc_fix_regs_for_mode(irblock, self.attrib)
-            self.blocks[irblock.label] = irblock
-
+            new_irblock = self.irbloc_fix_regs_for_mode(irblock, self.attrib)
+            self.blocks[irblock.label] = new_irblock
+            new_irblocks.append(new_irblock)
         # Forget graph if any
         self._graph = None
+        return new_irblocks
 
     def get_instr_label(self, instr):
         """Returns the label associated to an instruction
@@ -683,16 +734,14 @@ class IntermediateRepresentation(object):
 
     def remove_empty_assignblks(self):
         modified = False
-        for block in self.blocks.itervalues():
-            to_del = []
-            for idx, assignblk in enumerate(block.irs):
-                if len(assignblk) == 0:
-                    to_del.append(idx)
-            for idx in reversed(to_del):
-                del block.irs[idx]
-                block._dst_linenb = None
-                block._dst = None
-                modified = True
+        for label, block in self.blocks.iteritems():
+            irs = []
+            for assignblk in block.irs:
+                if len(assignblk):
+                    irs.append(assignblk)
+                else:
+                    modified = True
+            self.blocks[label] = IRBlock(label, irs)
         return modified
 
     def remove_jmp_blocks(self):
@@ -714,11 +763,12 @@ class IntermediateRepresentation(object):
                 continue
             if not expr_is_label(assignblk[self.IRDst]):
                 continue
-            jmp_blocks.add(block)
+            jmp_blocks.add(block.label)
 
         # Remove them, relink graph
         modified = False
-        for block in jmp_blocks:
+        for label in jmp_blocks:
+            block = self.blocks[label]
             dst_label = block.dst.name
             parents = self.graph.predecessors(block.label)
             for lbl in parents:
@@ -752,13 +802,14 @@ class IntermediateRepresentation(object):
                         dst = src1
                 else:
                     continue
-                parent.dst = dst
+                new_parent = parent.set_dst(dst)
+                self.blocks[parent.label] = new_parent
 
         # Remove unlinked useless nodes
-        for block in jmp_blocks:
-            if (len(self.graph.predecessors(block.label)) == 0 and
-                len(self.graph.successors(block.label)) == 0):
-                self.graph.del_node(block.label)
+        for label in jmp_blocks:
+            if (len(self.graph.predecessors(label)) == 0 and
+                len(self.graph.successors(label)) == 0):
+                self.graph.del_node(label)
         return modified
 
     def merge_blocks(self):
@@ -782,7 +833,7 @@ class IntermediateRepresentation(object):
                 continue
             # Block has one son, son has one parent => merge
             assignblks =[]
-            for linenb, assignblk in enumerate(self.blocks[block].irs):
+            for assignblk in self.blocks[block].irs:
                 if self.IRDst not in assignblk:
                     assignblks.append(assignblk)
                     continue
diff --git a/miasm2/jitter/codegen.py b/miasm2/jitter/codegen.py
index 15f172ee..61a9a784 100644
--- a/miasm2/jitter/codegen.py
+++ b/miasm2/jitter/codegen.py
@@ -577,18 +577,16 @@ class CGen(object):
             instr_attrib, irblocks_attributes = self.get_attributes(instr, irblocks, log_mn, log_regs)
 
             for index, irblock in enumerate(irblocks):
-                self.ir_arch.irbloc_fix_regs_for_mode(
-                    irblock, self.ir_arch.attrib)
-
-                if irblock.label.offset is None:
+                new_irblock = self.ir_arch.irbloc_fix_regs_for_mode(irblock, self.ir_arch.attrib)
+                if new_irblock.label.offset is None:
                     out.append("%-40s // %.16X %s" %
-                               (str(irblock.label.name) + ":", instr.offset, instr))
+                               (str(new_irblock.label.name) + ":", instr.offset, instr))
                 else:
                     out.append("%-40s // %.16X %s" %
-                               (self.label_to_jitlabel(irblock.label) + ":", instr.offset, instr))
+                               (self.label_to_jitlabel(new_irblock.label) + ":", instr.offset, instr))
                 if index == 0:
                     out += self.gen_pre_code(instr_attrib)
-                out += self.gen_irblock(instr_attrib, irblocks_attributes[index], instr_offsets, irblock)
+                out += self.gen_irblock(instr_attrib, irblocks_attributes[index], instr_offsets, new_irblock)
 
         out += self.gen_finalize(block)
         return ['\t' + line for line in out]
diff --git a/miasm2/jitter/llvmconvert.py b/miasm2/jitter/llvmconvert.py
index ae018c18..ed55aff8 100644
--- a/miasm2/jitter/llvmconvert.py
+++ b/miasm2/jitter/llvmconvert.py
@@ -1299,7 +1299,8 @@ class LLVMFunction():
 
 
         for instr, irblocks in zip(asmblock.lines, irblocks_list):
-            instr_attrib, irblocks_attributes = codegen.get_attributes(instr, irblocks, self.log_mn,
+            instr_attrib, irblocks_attributes = codegen.get_attributes(instr, irblocks,
+                                                                       self.log_mn,
                                                                        self.log_regs)
 
             # Pre-create basic blocks
@@ -1308,16 +1309,16 @@ class LLVMFunction():
 
             # Generate the corresponding code
             for index, irblock in enumerate(irblocks):
-                self.llvm_context.ir_arch.irbloc_fix_regs_for_mode(
+                new_irblock = self.llvm_context.ir_arch.irbloc_fix_regs_for_mode(
                     irblock, self.llvm_context.ir_arch.attrib)
 
                 # Set the builder at the begining of the correct bbl
-                name = self.canonize_label_name(irblock.label)
+                name = self.canonize_label_name(new_irblock.label)
                 self.builder.position_at_end(self.get_basic_bloc_by_label(name))
 
                 if index == 0:
                     self.gen_pre_code(instr_attrib)
-                self.gen_irblock(instr_attrib, irblocks_attributes[index], instr_offsets, irblock)
+                self.gen_irblock(instr_attrib, irblocks_attributes[index], instr_offsets, new_irblock)
 
         # Gen finalize (see codegen::CGen) is unrecheable, except with delayslot
         self.gen_finalize(asmblock, codegen)