Типы Module
и Function
- это просто тонкие обертки вокруг указателей на соответствующие объекты C ++ (то есть Module*
и Value*
):
-- LLVM.Core.Util
newtype Module = Module {
fromModule :: FFI.ModuleRef
}
deriving (Show, Typeable)
type Function a = Value (Ptr a)
newtype Value a = Value { unValue :: FFI.ValueRef }
deriving (Show, Typeable)
-- LLVM.FFI.Core
data Module
deriving (Typeable)
type ModuleRef = Ptr Module
data Value
deriving (Typeable)
type ValueRef = Ptr Value
CodeGenModule
иCodeGenFunction
типы - это части EDSL, построенные поверх модулей LLVM.FFI.*
.Они используют Function
, Module
и функции из LLVM.FFI.*
для внутренних целей и позволяют писать LLVM IR в Haskell кратко, используя do-нотацию (пример взят из блога Леннарта Огюсссона ):
mFib :: CodeGenModule (Function (Word32 -> IO Word32))
mFib = do
fib <- newFunction ExternalLinkage
defineFunction fib $ \ arg -> do
-- Create the two basic blocks.
recurse <- newBasicBlock
exit <- newBasicBlock
[...]
ret r
return fib
Вы можете представить CodeGenModule
как AST, представляющий проанализированный файл сборки LLVM (.ll
).Учитывая CodeGenModule
, вы можете, например, записать его в файл .bc
:
-- newModule :: IO Module
mod <- newModule
-- defineModule :: Module -> CodeGenModule a -> IO a
defineModule mod $ do [...]
-- writeBitcodeToFile :: FilePath -> Module -> IO ()
writeBitcodeToFile "mymodule.bc" mod
--- Alternatively, just use this function from LLVM.Util.File:
writeCodeGenModule :: FilePath -> CodeGenModule a -> IO ()
Я также рекомендую вам ознакомиться с базовыми классами LLVM , так как они также показываютчерез в Haskell API.