packages feed

llvm-tools-0.2.0.0: tools/TypeUnificationCheck.hs

-- | Take a single bitcode file and pump it through opt -S and parse
-- out the named type definitions (structs, unions, and classes).
-- Sort them and print them.
--
-- Then use llvm-data-interop to parse the bitcode and print its
-- sorted type list.  It will be apparent if types were properly
-- unified or not.
module Main ( main ) where

import Control.Monad ( forM_ )
import Data.Attoparsec.ByteString.Char8
import Data.Conduit
import Data.Conduit.Attoparsec
import Data.Conduit.Process as P
import Data.List ( sort )
import Data.Monoid
import Data.ByteString.Char8 ( ByteString )
import qualified Data.ByteString.Char8 as BS
import System.Environment ( getArgs )
import Text.Printf

import LLVM.Analysis
-- import LLVM.Analysis.Util.Environment
import LLVM.Parse

llvmTypesParser :: Parser [ByteString]
llvmTypesParser = do
  skipWhile (/='%')
  res <- many1 typeLineParser
  skipWhile (const True)
  return res

typePrefix :: Parser ByteString
typePrefix = choice [ string (BS.pack "%struct")
                    , string (BS.pack "%union")
                    , string (BS.pack "%class")
                    ]

typeLineParser :: Parser ByteString
typeLineParser = do
  pfx <- typePrefix
  suffix <- takeTill (=='\n')
  endOfLine
  return $ pfx `mappend` suffix

main :: IO ()
main = do
  [bcfile] <- getArgs

  -- First, get the output of opt.  This uses process-conduit and
  -- attoparsec-conduit to parse the output of opt in constant space.
  typeLines <- runResourceT $ do
    sourceProcess (P.proc "opt" ["-S", bcfile]) $$ sinkParser llvmTypesParser

  let typeDefs = sort typeLines

  _ <- printf "opt types: %d\n" (length typeDefs)
  forM_ typeDefs $ \td -> BS.putStrLn (BS.pack "  " `mappend` td)

  m <- parseLLVMFile defaultParserOptions bcfile
  let ts = sort $ map show $ filter isStructType (moduleRetainedTypes m)
  _ <- printf "unified types: %d\n" (length ts)
  forM_ ts $ \td -> putStrLn ("  " ++ td)

isStructType :: Type -> Bool
isStructType t =
  case t of
    TypeStruct (Right _) _ _ -> True
    _ -> False