llvm-hs-pretty
A pretty printer for llvm-hs-pure
. Goal is to be able to pretty print a
sufficiently large subset of the LLVM AST from pure Haskell without having to go
through the C++ API.
Note: It is possible to construct llvm-hs-pure ASTs that are invalid ASTs
and as such there is no meaningful way to print them. Always run the LLVM
verifier on your AST to test it is sound. If you encounter incomplete pattern
matches using this library you likely have constructed invalid IR.
Usage
There is a single function ppllvm
that maps a LLVM.AST.Module to a Text.
import LLVM.AST
import LLVM.Pretty (ppllvm)
ppllvm :: Module -> Text
Individual LLVM elements (constants, instructions) can be printed using the
the polymorphic ppll
function for any LLVM structure that implements the
PP
typeclass.
Tests
# This is only necessary for running the test suite
sudo apt-get install llvm-9-dev
The test suite currently consists of round tripping a LLVM IR from correct IR
outputted by the llc toolchain, parsing into llvm-hs AST and then printing it
back out and comparing it with the original textual form to see if the pretty
printer faithfully preserves the structure. The sample modules are in
tests/
.
Using stack:
$ stack build
$ stack test
Using cabal:
$ cabal run
$ cabal run -- tests/simple.ll
If you're using Nix then:
$ nix-shell
$ cabal run
Example
To try out the standalone example run:
$ stack repl
$ :load Example.hs
main
Consider the basic example LLVM module.
; ModuleID = 'example-llvm-module'
define i8 @f(i8 %x){
entry:
ret i8 %x
}
Using the LLVM.AST we construct the type and feed it to the pretty
printer.
module Standalone where
-- Pretty Printer
import LLVM.Pretty (ppllvm)
-- AST
import qualified LLVM.AST as AST
import qualified LLVM.AST.Linkage as Linkage
import qualified LLVM.AST.Visibility as Visibility
import qualified LLVM.AST.CallingConvention as Convention
import Data.Text.Lazy.IO as TIO
astModule :: AST.Module
astModule = AST.Module
{ AST.moduleName = "example-llvm-module"
, AST.moduleDataLayout = Nothing
, AST.moduleTargetTriple = Nothing
, AST.moduleDefinitions =
[ AST.GlobalDefinition
(AST.Function
Linkage.External
Visibility.Default
Nothing
Convention.C
[]
(AST.IntegerType 8)
(AST.Name "f")
([AST.Parameter (AST.IntegerType 8) (AST.Name "x") []], False)
[]
Nothing
Nothing
0
Nothing
Nothing
[ AST.BasicBlock
(AST.Name "entry")
[]
(AST.Do
(AST.Ret
(Just
(AST.LocalReference
(AST.IntegerType 8)
(AST.Name "x")
)
)
[]
)
)
]
)
]
}
main :: IO ()
main = TIO.putStrLn (ppllvm astModule)
License
Released under the MIT License.
Copyright (c) 2014-2020, Stephen Diehl
Copyright (c) 2015 Cedric Shock