На пути к пониманию CodeGen* в привязках Haskell LLVM

Предыстория: я пишу игрушечный интерпертер/компилятор Lisp на Haskell для собственного развлечения/назидания. Я пытаюсь добавить возможность компиляции в байт-код LLVM.

Контекст: я читал документацию по LLVM.Core и пример кода (здесь), пытаясь понять средства комбинирования и средства абстрагирования (как описано в Абельсон и Сассман Структура и интерпретация компьютерных программ.), используемые в привязках Haskell LLVM. Есть много мелких частей, и мне не ясно, как они предназначены для совместной работы. Похоже, что над базовыми машинными инструкциями LLVM существует уровень абстракции, который очевиден для тех, у кого большой опыт работы с LLVM, но не задокументирован для тех, кто вроде меня только начинает.

Вопрос. Что такое CodeGenModule и CodeGenFunction и как они используются для построения Functions и Modules?


person John F. Miller    schedule 15.06.2011    source источник


Ответы (2)


Типы 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, так как они также просматриваются в Хаскель API.

person Mikhail Glushenkov    schedule 15.06.2011

CodeGenFunction поддерживает ассемблерный код LLVM для одной функции. CodeGenModule поддерживает несколько таких функций. В пакете привязок Haskell llvm есть пример каталога с рабочим кодом.

person Lemming    schedule 25.06.2011