Skip to content

Commit 29bb38c

Browse files
committed
typed-irbuilder: try to make function pass typed args
This doesn't go as far as using singletons, currently we have to pass function arguments with the TypeApplication. We need some massaging to make it look nicer. Also it used unsafeCoerce under the hood. But it let's you avoid coerce, function arguments in the body do-block have the right type tags right away. Example2 is changed to use new function, also added bigger Example3.
1 parent cb090b7 commit 29bb38c

File tree

5 files changed

+76
-8
lines changed

5 files changed

+76
-8
lines changed

Example2.hs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
{-# LANGUAGE RecursiveDo #-}
44
{-# LANGUAGE TypeOperators #-}
55
{-# LANGUAGE OverloadedStrings #-}
6+
{-# LANGUAGE TypeApplications #-}
7+
{-# LANGUAGE TypeFamilies #-}
68

79
module Example2 where
810

@@ -20,15 +22,15 @@ import qualified LLVM.AST.Tagged as AST
2022
import LLVM.AST.Tagged.IRBuilder as TBuilder
2123
import qualified LLVM.IRBuilder as Builder
2224

23-
import Data.Coerce
25+
import Data.HVect
2426

2527
simple :: AST.Module
2628
simple = Builder.buildModule "exampleModule" $ do
2729
func
2830
where
2931
func :: Builder.ModuleBuilder (AST.Operand ::: IntegerType' 32)
3032
func =
31-
TBuilder.function "add" [(AST.i32, "a"), (AST.i32, "b")] $ \[a, b] -> do
33+
TBuilder.function @(IntegerType' 32) @'[ '(IntegerType' 32, 'ParameterName' "a"), '(IntegerType' 32, 'ParameterName' "b")] "add" $ \(a :&: b :&: HNil) -> do
3234
entry <- block `named` "entry"; do
33-
c <- add (coerce a) (coerce b)
35+
c <- add a b
3436
ret c

Example3.hs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{-# LANGUAGE TypeApplications #-}
2+
{-# LANGUAGE RecursiveDo #-}
3+
{-# LANGUAGE DataKinds #-}
4+
{-# LANGUAGE PolyKinds #-}
5+
{-# LANGUAGE TypeOperators #-}
6+
{-# LANGUAGE OverloadedStrings #-}
7+
{-# LANGUAGE TypeFamilies #-}
8+
9+
module Main where
10+
11+
import GHC.TypeLits
12+
import LLVM.Prelude
13+
import LLVM.AST.Tagged.Operand
14+
import qualified LLVM.AST.Tagged.Constant as TC
15+
import LLVM.AST.Tagged.Global
16+
import LLVM.AST.Tagged.Tag
17+
import LLVM.AST.TypeLevel.Type
18+
import qualified LLVM.AST as AST
19+
import qualified LLVM.AST.Type as AST
20+
import qualified LLVM.AST.Float as F
21+
import qualified LLVM.AST.Constant as C
22+
import qualified LLVM.AST.IntegerPredicate as P
23+
24+
import LLVM.AST.Tagged.IRBuilder as TBuilder
25+
import qualified LLVM.IRBuilder as Builder
26+
27+
import Data.HVect
28+
29+
simple :: AST.Module
30+
simple = Builder.buildModule "exampleModule" $ mdo
31+
TBuilder.function @(IntegerType' 32) @'[ '(IntegerType' 32, 'ParameterName' "a")] "f" $ \(a :&: HNil) -> mdo
32+
entry <- block `named` "entry"
33+
cond <- icmp P.EQ a (constantOperand (TC.int 0))
34+
condBr cond ifThen ifElse
35+
ifThen <- block
36+
trVal <- add a (constantOperand (TC.int 0))
37+
br ifExit
38+
ifElse <- block `named` "if.else"
39+
flVal <- add a (constantOperand (TC.int 0))
40+
br ifExit
41+
ifExit <- block `named` "if.exit"
42+
r <- phi [(trVal, ifThen), (flVal, ifElse)]
43+
ret r
44+
45+
main :: IO ()
46+
main = print simple

llvm-hs-typed.cabal

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ library
5757
llvm-hs-pure == 5.1.*,
5858
llvm-hs-pretty >= 0.2,
5959
bytestring >= 0.10 && < 0.11,
60-
encode-string == 0.1.*
60+
encode-string == 0.1.*,
61+
hvect == 0.4.*
6162
hs-source-dirs: src
6263
default-language: Haskell2010

src/LLVM/AST/Tagged/IRBuilder.hs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ import qualified LLVM.AST.FloatingPointPredicate as FP
111111
import GHC.TypeLits
112112
import GHC.Exts (Constraint)
113113
import Data.Coerce
114+
import Unsafe.Coerce
115+
import Data.HVect hiding (Nat)
114116
import qualified LLVM.IRBuilder as IR
115117

116118
-------------------------------------------------------------------------------
@@ -144,13 +146,20 @@ freshUnName = IR.freshUnName >>= pure . coerce
144146
named :: IR.MonadIRBuilder m => m (r ::: t) -> ShortByteString -> m (r ::: t)
145147
named m = IR.named m
146148

149+
-- partially applied Map
150+
type family MapOp (as :: [(Type', ParameterName')]) where
151+
MapOp '[] = '[]
152+
MapOp ('(t, _) ': xs) = (Operand :::: t) ': MapOp xs
153+
147154
function
148-
:: forall (t :: Type') m. (Known t, IR.MonadModuleBuilder m)
155+
:: forall (t :: Type') -- ^ Function return type
156+
(as :: [(Type', ParameterName')]) -- ^ Function arguments
157+
m.
158+
(Known t, Known as, IR.MonadModuleBuilder m)
149159
=> Name -- ^ Function name
150-
-> [(Type, IR.ParameterName)] -- ^ Parameter types and name suggestions
151-
-> ([Operand] -> IR.IRBuilderT m ()) -- ^ Function body builder
160+
-> (HVect (MapOp as) -> IR.IRBuilderT m ()) -- ^ Function body builder
152161
-> m (Operand ::: t)
153-
function nm params m = IR.function nm params (val @_ @t) m >>= pure . coerce
162+
function nm m = IR.function nm (val @_ @as) (val @_ @t) (unsafeCoerce m) >>= pure . coerce
154163

155164
-------------------------------------------------------------------------------
156165
-- Types

src/LLVM/AST/TypeLevel/Type.hs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,14 @@ import qualified Data.ByteString.Short as BS
3636
import LLVM.AST.Type
3737
import LLVM.AST.AddrSpace
3838
import LLVM.AST.Name
39+
import qualified LLVM.IRBuilder as IR
3940

4041
data Name' = Name' Symbol | UnName' Nat
4142

4243
data AddrSpace' = AddrSpace' Nat
4344

45+
data ParameterName' = ParameterName' Symbol
46+
4447
-- | A copy of 'Type', suitable to be used on the type level
4548
data Type'
4649
= VoidType'
@@ -103,6 +106,8 @@ type instance Value FloatingPointType = FloatingPointType
103106
type instance Value Bool = Bool
104107
type instance Value Symbol = String
105108
type instance Value Nat = Integer
109+
type instance Value ParameterName' = IR.ParameterName
110+
type instance Value (a, b) = (Value a, Value b)
106111

107112
word32Val :: forall (n::Nat). Known n => Word32
108113
word32Val = fromIntegral (val @_ @n)
@@ -153,6 +158,11 @@ instance Known s => Known ('Name' s) where
153158
val = Name (byteStringVal @s)
154159
instance Known n => Known (UnName' n) where
155160
val = UnName (wordVal @n)
161+
instance Known s => Known ('ParameterName' s) where
162+
val = IR.ParameterName (byteStringVal @s)
163+
164+
instance (Known a, Known b) => Known '(a, b) where
165+
val = (val @_ @a, val @_ @b)
156166

157167
instance Known HalfFP where val = HalfFP
158168
instance Known FloatFP where val = FloatFP

0 commit comments

Comments
 (0)