@@ -0,0 +1,96 @@
1+||| Types for interfacing with C.
2+module CFFI.Types
3+
4+import Data.Vect
5+import Data.HList
6+
7+%access public export
8+%default partial
9+
10+||| An universe of C types.
11+data CType = I8 | I16 | I32 | I64 | FLOAT | DOUBLE | PTR
12+ | ARRAY Int CType | STRUCT (List CType) | UNION (List CType)
13+ | PACKEDSTRUCT (List CType)
14+
15+translate : CType -> Type
16+translate I8 = Bits8
17+translate I16 = Bits16
18+translate I32 = Bits32
19+translate I64 = Bits64
20+translate FLOAT = Bits32
21+translate DOUBLE = Double
22+translate PTR = Ptr
23+translate (ARRAY n t) = Vect (toNat n) (translate t)
24+translate (STRUCT xs) = HList (map translate xs)
25+translate (UNION xs) = HList (map translate xs)
26+translate (PACKEDSTRUCT xs) = HList (map translate xs)
27+
28+mutual
29+ sizeOf : CType -> Int
30+ sizeOf I8 = 1
31+ sizeOf I16 = 2
32+ sizeOf I32 = 4
33+ sizeOf I64 = 8
34+ sizeOf FLOAT = 4
35+ sizeOf DOUBLE = 8
36+ sizeOf PTR = prim__sizeofPtr
37+ sizeOf (ARRAY n t) = n * sizeOf t
38+ sizeOf (STRUCT xs) = sizeOfStruct xs
39+ sizeOf (UNION xs) = foldl (\acc, x =>max acc $ sizeOf x) 0 xs
40+ sizeOf (PACKEDSTRUCT xs) = foldl (\acc, x => acc + sizeOf x) 0 xs
41+
42+ alignOf : CType -> Int
43+ alignOf I8 = 1
44+ alignOf I16 = 2
45+ alignOf I32 = 4
46+ alignOf I64 = prim__sizeofPtr
47+ alignOf FLOAT = 4
48+ alignOf DOUBLE = prim__sizeofPtr
49+ alignOf PTR = prim__sizeofPtr
50+ alignOf (ARRAY n t) = alignOf t
51+ alignOf (STRUCT xs) = foldl (\acc, x => max acc $ alignOf x) 0 xs
52+ alignOf (UNION xs) = foldl (\acc, x => max acc $ alignOf x) 0 xs
53+ alignOf (PACKEDSTRUCT xs) = 1
54+
55+ offsetsStruct : List CType -> List Int
56+ offsetsStruct xs = offsets' xs [] 0
57+ where
58+ offsets' : List CType -> List Int -> Int -> List Int
59+ offsets' [] acc _ = reverse acc
60+ offsets' (x::xs) ys curr = let a = alignOf x
61+ padding = let c = curr `mod` a
62+ in if c == 0 then 0 else a - c
63+ off = curr + padding
64+ in offsets' xs (off::ys) (off + sizeOf x)
65+
66+ sizeOfStruct : List CType -> Int
67+ sizeOfStruct xs = case (reverse xs, reverse (offsetsStruct xs)) of
68+ ([], _) => 0
69+ (x::_, y::_) => let end = y + sizeOf x
70+ endPadding = let c = end `mod` align in
71+ if c == 0 then 0 else align - c
72+ in end + endPadding
73+ where
74+ align : Int
75+ align = foldl (\acc, x => max acc $ alignOf x) 1 xs
76+
77+fields : CType -> Nat
78+fields (STRUCT xs) = length xs
79+fields (PACKEDSTRUCT xs) = length xs
80+fields (UNION xs) = length xs
81+fields (ARRAY n _) = toNat n
82+fields _ = 1
83+
84+offsetsPacked : List CType -> List Int
85+offsetsPacked xs = offsets' xs [] 0
86+ where
87+ offsets' : List CType -> List Int -> Int -> List Int
88+ offsets' [] acc _ = reverse acc
89+ offsets' (x::xs) acc pos = offsets' xs (pos::acc) (sizeOf x)
90+
91+offsets : CType -> List Int
92+offsets (STRUCT xs) = offsetsStruct xs
93+offsets (PACKEDSTRUCT xs) = offsetsPacked xs
94+offsets (UNION xs) = replicate (length xs) 0
95+offsets (ARRAY n t) = [ x*sizeOf t | x <- [0..n]]
96+offsets _ = [0]