{-# LANGUAGE OverloadedStrings #-}
module Data.LLVM.BitCode (
-- * Bitcode Parsing
-- ** Without 'ParseWarning's
parseBitCode, parseBitCodeFromFile
, parseBitCodeLazy, parseBitCodeLazyFromFile
-- ** With 'ParseWarning's
, parseBitCodeWithWarnings, parseBitCodeFromFileWithWarnings
, parseBitCodeLazyWithWarnings, parseBitCodeLazyFromFileWithWarnings
-- * Re-exported
, Error(..), formatError
, ParseWarning(..), MetadataRecordSizeRange(..)
, ppParseWarnings, ppParseWarning
) where
import Data.LLVM.BitCode.Bitstream
(Bitstream,parseBitCodeBitstream,parseBitCodeBitstreamLazy)
import Data.LLVM.BitCode.IR (parseModule)
import Data.LLVM.BitCode.Parse (runParse,badRefError,Error(..),formatError,
MetadataRecordSizeRange(..),ParseWarning(..),
ParseState(..),ppParseWarning,ppParseWarnings)
import Text.LLVM.AST (Module)
import Control.Monad ((<=<))
import qualified Control.Exception as X
import qualified Data.ByteString as S
import qualified Data.ByteString.Lazy as L
import Data.Sequence (Seq)
-- | Parse the contents of an LLVM bitcode file as a strict 'S.ByteString'. If
-- parsing succeeds, return the parsed 'Module'. Otherwise, return an 'Error'
-- describing what went wrong.
--
-- See also 'parseBitCodeWithWarnings' for a version that also returns any
-- warnings that arise during parsing. This function will simply discard all
-- such warnings, which is why this function is deprecated.
parseBitCode :: S.ByteString -> IO (Either Error Module)
parseBitCode =
fmap (fmap fst) . parseBitstream . parseBitCodeBitstream
{-# DEPRECATED
parseBitCode
"Use parseBitCodeWithWarnings instead." #-}
-- | Load an LLVM bitcode file as a strict 'S.ByteString' and parse its
-- contents. If parsing succeeds, return the parsed 'Module'. Otherwise, return
-- an 'Error' describing what went wrong.
--
-- See also 'parseBitCodeFromFileWithWarnings' for a version that also returns
-- any warnings that arise during parsing. This function will simply discard all
-- such warnings, which is why this function is deprecated.
parseBitCodeFromFile :: FilePath -> IO (Either Error Module)
parseBitCodeFromFile =
parseBitCode <=< S.readFile
{-# DEPRECATED
parseBitCodeFromFile
"Use parseBitCodeFromFileWithWarnings instead." #-}
-- | Parse the contents of an LLVM bitcode file as a lazy 'L.ByteString'. If
-- parsing succeeds, return the parsed 'Module'. Otherwise, return an 'Error'
-- describing what went wrong.
--
-- See also 'parseBitCodeLazyWithWarnings' for a version that also returns any
-- warnings that arise during parsing. This function will simply discard all
-- such warnings, which is why this function is deprecated.
parseBitCodeLazy :: L.ByteString -> IO (Either Error Module)
parseBitCodeLazy =
fmap (fmap fst) . parseBitstream . parseBitCodeBitstreamLazy
{-# DEPRECATED
parseBitCodeLazy
"Use parseBitCodeLazyWithWarnings instead." #-}
-- | Load an LLVM bitcode file as a lazy 'L.ByteString' and parse its contents.
-- If parsing succeeds, return the parsed 'Module'. Otherwise, return an 'Error'
-- describing what went wrong in a 'Left' value.
--
-- See also 'parseBitCodeLazyFromFileWithWarnings' for a version that also
-- returns any warnings that arise during parsing. This function will simply
-- discard all such warnings, which is why this function is deprecated.
parseBitCodeLazyFromFile :: FilePath -> IO (Either Error Module)
parseBitCodeLazyFromFile =
parseBitCodeLazy <=< L.readFile
{-# DEPRECATED
parseBitCodeLazyFromFile
"Use parseBitCodeLazyFromFileWithWarnings instead." #-}
-- | Parse the contents of an LLVM bitcode file as a strict 'S.ByteString'. If
-- parsing succeeds, return the parsed 'Module' and any 'ParseWarning's that
-- were emitted. Otherwise, return an 'Error' describing what went wrong.
--
-- See also 'parseBitCode' for a version that discards any warnings that arise
-- during parsing.
parseBitCodeWithWarnings ::
S.ByteString -> IO (Either Error (Module, Seq ParseWarning))
parseBitCodeWithWarnings =
parseBitstream . parseBitCodeBitstream
-- | Load an LLVM bitcode file as a strict 'S.ByteString' and parse its
-- contents. If parsing succeeds, return the parsed 'Module' and any
-- 'ParseWarnings' that were emitted. Otherwise, return an 'Error' describing
-- what went wrong.
--
-- See also 'parseBitCodeFromFile' for a version that discards any warnings that
-- arise during parsing.
parseBitCodeFromFileWithWarnings ::
FilePath -> IO (Either Error (Module, Seq ParseWarning))
parseBitCodeFromFileWithWarnings =
parseBitCodeWithWarnings <=< S.readFile
-- | Parse the contents of an LLVM bitcode file as a lazy 'L.ByteString'. If
-- parsing succeeds, return the parsed 'Module' and any 'ParseWarning's that
-- were emitted. Otherwise, return an 'Error' describing what went wrong.
--
-- See also 'parseBitCodeLazy' for a version that discards any warnings that
-- arise during parsing.
parseBitCodeLazyWithWarnings ::
L.ByteString -> IO (Either Error (Module, Seq ParseWarning))
parseBitCodeLazyWithWarnings =
parseBitstream . parseBitCodeBitstreamLazy
-- | Load an LLVM bitcode file as a lazy 'L.ByteString' and parse its contents.
-- If parsing succeeds, return the parsed 'Module' and any 'ParseWarnings' that
-- were emitted. Otherwise, return an 'Error' describing what went wrong.
--
-- See also 'parseBitCodeLazyFromFile' for a version that discards any warnings
-- that arise during parsing.
parseBitCodeLazyFromFileWithWarnings ::
FilePath -> IO (Either Error (Module, Seq ParseWarning))
parseBitCodeLazyFromFileWithWarnings =
parseBitCodeLazyWithWarnings <=< L.readFile
parseBitstream ::
Either String Bitstream -> IO (Either Error (Module, Seq ParseWarning))
parseBitstream e = case e of
Left err -> mkError ["Bitstream"] err
Right bits -> do
res <- X.handle (return . Left . badRefError)
(X.evaluate (runParse (parseModule bits)))
pure $ fmap (\(m, st) -> (m, psWarnings st)) res
where
mkError cxt msg = return $ Left Error
{ errMessage = msg
, errContext = cxt
}