   liftIO $ modifyIORef r (+1)
 
   return thisId
+
+nextTypeId :: KnotMonad Int
+nextTypeId = do
+  s <- get
+  let r = typeIdSrc s
+  thisId <- liftIO $ readIORef r
+  liftIO $ modifyIORef r (+1)
+
+  return thisId
+
 
 -- | Parse the named LLVM bitcode file into the LLVM form of the IR (a
 -- 'Module').  In the case of an error, a descriptive string will be

data KnotState = KnotState { valueMap :: Map IntPtr Value
                           , typeMap :: Map IntPtr Type
                           , idSrc :: IORef Int
                           , result :: Maybe Module
                           , visitedTypes :: Set IntPtr
                           , localId :: Int
                           , constantTranslationDepth :: Int
                           }
emptyState :: IORef Int -> KnotState
emptyState r = KnotState { valueMap = M.empty
                         , typeMap = M.empty
                         , idSrc = r
                         , result = Nothing
                         , visitedTypes = S.empty
                         , localId = 0

        -- This is a cyclic reference - look it up in the final result
        (_, TYPE_NAMED) ->
          return $ M.findWithDefault (throw (TypeKnotTyingFailure tag)) ip (typeMap finalState)
        (True, _) -> do
          -- Here we have detected a cycle in a type that isn't broken
          -- up by a NamedType.  We introduce an artificial name (a
          -- type upref) to break the cycle.  This makes it a lot
          -- easier to print out types later on, as we don't have to
          -- do on-the-fly cycle detection everywhere we want to work
          -- with types.
          let innerType = M.findWithDefault (throw (TypeKnotTyingFailure tag)) ip (typeMap finalState)
          uprefName <- nextTypeId
          return $ TypeNamed (show uprefName) innerType
        _ -> translateType' finalState tp

translateType' :: KnotState -> TypePtr -> KnotMonad Type
