An experimental branch of llvm-hs-pure AST that enforces the semantics of correct AST construction using the Haskell type system to prevent malformed ASTs.
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Example where
-- AST
import GHC.TypeLits
import LLVM.Prelude
import LLVM.AST.Tagged
import LLVM.AST.Constant
import LLVM.AST.Tagged.Global
import LLVM.AST.Tagged.Constant
import LLVM.AST.Tagged.Tag
import LLVM.AST.TypeLevel.Type
import qualified LLVM.AST as AST
import qualified LLVM.AST.Global as AST
c0 :: Constant ::: IntegerType' 32
c0 = int 42
named :: forall (t :: Type'). ShortByteString -> Name ::: t
named s = assertLLVMType $ AST.Name s
type ArgTys = [(IntegerType' 32), (IntegerType' 32)]
type RetTy = IntegerType' 32
defAdd :: Global
defAdd = function nm (params, False) [body, body]
where
nm :: Name ::: (PointerType' (FunctionType' (IntegerType' 32) ArgTys) ('AddrSpace' 0))
nm = named "add"
-- Types of subexpression are inferred from toplevel LLVM function signature
{-p1 :: Parameter ::: (IntegerType' 32)-}
p1 = parameter (named "a") []
{-p2 :: Parameter ::: (IntegerType' 32)-}
p2 = parameter (named "b") []
{-body :: BasicBlock ::: IntegerType' 32-}
body = basicBlock "entry" [] (ret (constantOperand c0) [])
{-params :: Parameter :::* ArgTys-}
params = p1 :* p2 :* tnil
module_ :: AST.Module
module_ = defaultModule
{ moduleName = "basic"
, moduleDefinitions = [GlobalDefinition defAdd]
}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RecursiveDo #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE OverloadedStrings #-}
module Example2 where
import GHC.TypeLits
import LLVM.Prelude
import LLVM.AST.Constant
import LLVM.AST.Tagged.Global
import LLVM.AST.Tagged.Tag
import LLVM.AST.TypeLevel.Type
import qualified LLVM.AST as AST
import qualified LLVM.AST.Type as AST
import qualified LLVM.AST.Global as AST
import qualified LLVM.AST.Tagged as AST
import LLVM.AST.Tagged.IRBuilder as TBuilder
import qualified LLVM.IRBuilder as Builder
import Data.Coerce
simple :: AST.Module
simple = Builder.buildModule "exampleModule" $ do
func
where
func :: Builder.ModuleBuilder (AST.Operand ::: IntegerType' 32)
func =
TBuilder.function "add" [(AST.i32, "a"), (AST.i32, "b")] $ \[a, b] -> do
entry <- block `named` "entry"; do
c <- add (coerce a) (coerce b)
ret c
Copyright (c) 2017, Joachim Breitner