crucible-llvm-0.6: src/Lang/Crucible/LLVM/PrettyPrint.hs
------------------------------------------------------------------------
-- |
-- Module : Lang.Crucible.LLVM.PrettyPrint
-- Description : Printing utilties for LLVM
-- Copyright : (c) Galois, Inc 2015-2016
-- License : BSD3
-- Maintainer : Rob Dockins <rdockins@galois.com>
-- Stability : provisional
--
-- This module defines several functions whose names clash with functions
-- offered elsewhere in @llvm-pretty@ (e.g., "Text.LLVM.PP") and in
-- @crucible-llvm@ (e.g., "Lang.Crucible.LLVM.MemModel.MemLog"). For this
-- reason, it is recommended to import this module qualified.
------------------------------------------------------------------------
{-# LANGUAGE ImplicitParams #-}
{-# LANGUAGE RankNTypes #-}
module Lang.Crucible.LLVM.PrettyPrint
( commaSepList
, ppIntType
, ppPtrType
, ppArrayType
, ppVectorType
, ppIntVector
-- * @llvm-pretty@ printing with the latest LLVM version
, ppLLVMLatest
, ppDeclare
, ppIdent
, ppSymbol
, ppType
, ppValue
) where
import Numeric.Natural
import Prettyprinter
import qualified Text.PrettyPrint.HughesPJ as HPJ
import qualified Text.LLVM.AST as L
import qualified Text.LLVM.PP as L
-- | Print list of documents separated by commas and spaces.
commaSepList :: [Doc ann] -> Doc ann
commaSepList l = hcat (punctuate (comma <> pretty ' ') l)
-- | Pretty print int type with width.
ppIntType :: Integral a => a -> Doc ann
ppIntType i = pretty 'i' <> pretty (toInteger i)
-- | Pretty print pointer type.
ppPtrType :: Doc ann -> Doc ann
ppPtrType tp = tp <> pretty '*'
ppArrayType :: Natural -> Doc ann -> Doc ann
ppArrayType n e = brackets (pretty (toInteger n) <+> pretty 'x' <+> e)
ppVectorType :: Natural -> Doc ann -> Doc ann
ppVectorType n e = angles (pretty (toInteger n) <+> pretty 'x' <+> e)
ppIntVector :: Integral a => Natural -> a -> Doc ann
ppIntVector n w = ppVectorType n (ppIntType w)
-- | Pretty-print an LLVM-related AST in accordance with the latest LLVM version
-- that @llvm-pretty@ currently supports (i.e., the value of 'L.llvmVlatest'.)
--
-- Note that we are mainly using the @llvm-pretty@ printer in @crucible-llvm@
-- for the sake of defining 'Show' instances and creating error messages, not
-- for creating machine-readable LLVM code. As a result, it doesn't particularly
-- matter which LLVM version we use, as any version-specific differences in
-- pretty-printer output won't be that impactful.
ppLLVMLatest :: ((?config :: L.Config) => a) -> a
ppLLVMLatest = L.withConfig (L.Config { L.cfgVer = L.llvmVlatest })
-- | Invoke 'L.ppDeclare' in accordance with the latest LLVM version that
-- @llvm-pretty@ supports.
ppDeclare :: L.Declare -> HPJ.Doc
ppDeclare = ppLLVMLatest L.ppDeclare
-- | Invoke 'L.ppIdent' in accordance with the latest LLVM version that
-- @llvm-pretty@ supports.
ppIdent :: L.Ident -> HPJ.Doc
ppIdent = ppLLVMLatest L.ppIdent
-- | Invoke 'L.ppSymbol' in accordance with the latest LLVM version that
-- @llvm-pretty@ supports.
ppSymbol :: L.Symbol -> HPJ.Doc
ppSymbol = ppLLVMLatest L.ppSymbol
-- | Invoke 'L.ppType' in accordance with the latest LLVM version that
-- @llvm-pretty@ supports.
ppType :: L.Type -> HPJ.Doc
ppType = ppLLVMLatest L.ppType
-- | Invoke 'L.ppValue' in accordance with the latest LLVM version that
-- @llvm-pretty@ supports.
ppValue :: L.Value -> HPJ.Doc
ppValue = ppLLVMLatest L.ppValue