[repack] add graph_t::move_child helper function.
diff --git a/src/graph/graph.hh b/src/graph/graph.hh
index 9ebb57d..435e51a 100644
--- a/src/graph/graph.hh
+++ b/src/graph/graph.hh
@@ -80,6 +80,16 @@
       }
     }
 
+    void remove_real_link (unsigned child_index)
+    {
+      for (unsigned i = 0; i < obj.real_links.length; i++)
+      {
+        if (obj.real_links[i].objidx != child_index) continue;
+        obj.real_links.remove (i);
+        break;
+      }
+    }
+
     void remap_parents (const hb_vector_t<unsigned>& id_map)
     {
       for (unsigned i = 0; i < parents.length; i++)
@@ -516,6 +526,37 @@
   }
 
   /*
+   * Moves the child of old_parent_idx pointed to by old_offset to a new
+   * vertex at the new_offset.
+   */
+  template<typename O>
+  void move_child (unsigned old_parent_idx,
+                   const O* old_offset,
+                   unsigned new_parent_idx,
+                   const O* new_offset)
+  {
+    auto& old_v = vertices_[old_parent_idx];
+    auto& new_v = vertices_[new_parent_idx];
+
+    unsigned child_id = index_for_offset (old_parent_idx,
+                                          old_offset);
+
+    auto* new_link = new_v.obj.real_links.push ();
+    new_link->width = O::static_size;
+    new_link->objidx = child_id;
+    new_link->is_signed = 0;
+    new_link->whence = 0;
+    new_link->position = (const char*) old_offset - (const char*) new_v.obj.head;
+    new_link->bias = 0;
+
+    auto& child = vertices_[child_id];
+    child.parents.push (new_parent_idx);
+
+    old_v.remove_real_link (child_id);
+    child.remove_parent (old_parent_idx);
+  }
+
+  /*
    * duplicates all nodes in the subgraph reachable from node_idx. Does not re-assign
    * links. index_map is updated with mappings from old id to new id. If a duplication has already
    * been performed for a given index, then it will be skipped.
diff --git a/src/graph/pairpos-graph.hh b/src/graph/pairpos-graph.hh
index 380453a..4576330 100644
--- a/src/graph/pairpos-graph.hh
+++ b/src/graph/pairpos-graph.hh
@@ -104,8 +104,31 @@
                         unsigned start, unsigned end) const
   {
     printf("  cloning range [%u, %u).\n", start, end);
-    // TODO
-    return -1;
+
+    unsigned num_pair_sets = end - start;
+    unsigned prime_size = OT::Layout::GPOS_impl::PairPosFormat1_3<SmallTypes>::min_size
+                          + num_pair_sets * SmallTypes::size;
+
+    unsigned pair_pos_prime_id = c.create_node (prime_size);
+    if (pair_pos_prime_id == (unsigned) -1) return -1;
+
+    PairPosFormat1* pair_pos_prime = (PairPosFormat1*) c.graph.object (pair_pos_prime_id).head;
+    pair_pos_prime->format = this->format;
+    pair_pos_prime->valueFormat[0] = this->valueFormat[0];
+    pair_pos_prime->valueFormat[1] = this->valueFormat[1];
+    pair_pos_prime->pairSet.len = num_pair_sets;
+
+    for (unsigned i = start; i < end; i++)
+    {
+      c.graph.move_child<> (this_index,
+                            &pairSet[i],
+                            pair_pos_prime_id,
+                            &pair_pos_prime->pairSet[i - start]);
+    }
+
+
+    // TODO: serialize a new coverage table.
+    return pair_pos_prime_id;
   }
 
   unsigned pair_set_graph_index (gsubgpos_graph_context_t& c, unsigned this_index, unsigned i) const