{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE NamedFieldPuns #-}
module Data.LLVM.BitCode.IR where
import Data.LLVM.BitCode.Bitstream
import Data.LLVM.BitCode.BitString
import Data.LLVM.BitCode.IR.Module (parseModuleBlock)
import Data.LLVM.BitCode.Match
import Data.LLVM.BitCode.Parse
import Text.LLVM.AST
import Control.Monad ((<=<),unless)
import Data.Monoid (mappend)
import Data.Word (Word16)
-- Module Parsing --------------------------------------------------------------
-- | The magic number that identifies a @Bitstream@ structure as LLVM IR.
llvmIrMagic :: Word16
llvmIrMagic = fromBitString (toBitString 8 0xc0 `mappend` toBitString 8 0xde)
-- | Block selector for the top-level module block.
moduleBlock :: Match Entry [Entry]
moduleBlock = fmap blockEntries . hasBlockId 8 <=< block
-- | Parse an LLVM Module out of a Bitstream object.
parseModule :: Bitstream -> Parse Module
parseModule Bitstream { bsAppMagic, bsEntries } = label "Bitstream" $ do
unless (bsAppMagic == llvmIrMagic) (fail "Bitstream is not an llvm-ir")
parseTopLevel bsEntries
-- | The only top-level block that we parse currently is the module block. The
-- Identification block that's introduced in 3.8 is ignored. In the future, it
-- might be advantageous to parse it, as it could include information that would
-- aid error reporting.
parseTopLevel :: [Entry] -> Parse Module
parseTopLevel (EntryBlock Block { blockId = 8, blockEntries } : _) =
parseModuleBlock blockEntries
parseTopLevel (_ : rest) =
parseTopLevel rest
parseTopLevel [] =
fail "MODULE_BLOCK missing"