Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pretty print llvm-general-pure ASTs as llvm-ir?

I used llvm-general-pure to build an abstract syntax trees for a program in the LLVM language.

Using the provided pretty printer, I get output that looks like

A.Module {
  A.moduleName = "main",
  A.moduleDataLayout = Nothing,
  A.moduleTargetTriple = Nothing,
  A.moduleDefinitions = [
    ...
    A.GlobalDefinition A.G.Function {
      A.G.linkage = A.L.External,
      A.G.visibility = A.V.Default,
      A.G.callingConvention = A.CC.C,
      A.G.returnAttributes = [],
      A.G.returnType = A.IntegerType {A.typeBits = 32},
      A.G.name = A.Name "Main",
      A.G.parameters = ([], False),
      A.G.functionAttributes = [],
      A.G.section = Nothing,
      A.G.alignment = 0,
      A.G.garbageCollectorName = Nothing,
      A.G.basicBlocks = [
        A.G.BasicBlock (A.Name "mainBlock") [
          A.Name "n57" A.:= A.Alloca {
            A.allocatedType = A.IntegerType {A.typeBits = 64},
            A.numElements = Nothing,
            A.alignment = 0,
            A.metadata = []
          },
...

I want output that looks like

define i32 @main() {
mainBlock:
    %n57 = alloca i64
    ...
}
...

It looks suspiciously like there's an automatically generated parser for the LLVM language in the llvm-general-quote package, but no corresponding pretty printer.

Stephen Diehl's excellent article hints at something called moduleString.

like image 584
Cirdec Avatar asked Jan 09 '15 23:01

Cirdec


1 Answers

llvm-general-pure doesn't have a pure pretty printer, we have to go through llvm-general to do this. It can print out the IR by going through withModuleFromAST on the Haskell AST to manifest the Module representation (i.e. the C++ Module) of the IR and then calling moduleLLVMAssembly to invoke the pretty printer.

moduleLLVMAssembly :: Mod.Module -> IO String
withModuleFromAST :: Context -> AST.Module -> (Mod.Module -> IO a) -> ErrorT String IO a

This isn't pure Haskell though, it's all going through the FFI to call LLVM's internal functions.

import LLVM.General.Module as Mod
import qualified LLVM.General.AST as AST

ppModule :: AST.Module -> IO ()
ppModule ast = withContext $ \ctx ->
  runExceptT $ withModuleFromAST ctx ast $ \m -> do
    llstr <- moduleLLVMAssembly m
    putStrLn llstr

There's no reason we couldn't have a pure pretty printer though and indeed I started on a project to do just this called llvm-pp, but it's just a large amount of mind-numbingly boring work to write a pretty printer for the whole LLVM specification.

like image 130
Stephen Diehl Avatar answered Oct 08 '22 21:10

Stephen Diehl