1-- SPDX-FileCopyrightText: 2025 Sören Tempel <soeren+git@soeren-tempel.net>
2--
3-- SPDX-License-Identifier: GPL-3.0-only
4
5module Language.QBE.Types where
6
7import Data.Word (Word64)
8
9-- TODO: Prefix all constructors
10
11newtype UserIdent = UserIdent {userIdent :: String}
12 deriving (Eq, Ord)
13
14instance Show UserIdent where
15 show (UserIdent s) = ':' : s
16
17newtype LocalIdent = LocalIdent {localIdent :: String}
18 deriving (Eq, Ord)
19
20instance Show LocalIdent where
21 show (LocalIdent s) = '%' : s
22
23newtype BlockIdent = BlockIdent {blockIdent :: String}
24 deriving (Eq, Ord)
25
26instance Show BlockIdent where
27 show (BlockIdent s) = '@' : s
28
29newtype GlobalIdent = GlobalIdent {globalIdent :: String}
30 deriving (Eq, Ord)
31
32instance Show GlobalIdent where
33 show (GlobalIdent s) = '$' : s
34
35------------------------------------------------------------------------
36
37data BaseType
38 = Word
39 | Long
40 | Single
41 | Double
42 deriving (Show, Eq)
43
44baseTypeByteSize :: BaseType -> Int
45baseTypeByteSize Word = 4
46baseTypeByteSize Long = 8
47baseTypeByteSize Single = 4
48baseTypeByteSize Double = 8
49
50baseTypeBitSize :: BaseType -> Int
51baseTypeBitSize ty = baseTypeByteSize ty * 8
52
53data ExtType
54 = Base BaseType
55 | Byte
56 | HalfWord
57 deriving (Show, Eq)
58
59extTypeByteSize :: ExtType -> Int
60extTypeByteSize (Base b) = baseTypeByteSize b
61extTypeByteSize Byte = 1
62extTypeByteSize HalfWord = 2
63
64extTypeBitSize :: ExtType -> Int
65extTypeBitSize ty = extTypeByteSize ty * 8
66
67data SubWordType
68 = SignedByte
69 | UnsignedByte
70 | SignedHalf
71 | UnsignedHalf
72 deriving (Show, Eq)
73
74data Abity
75 = ABase BaseType
76 | ASubWordType SubWordType
77 | AUserDef UserIdent
78 deriving (Show, Eq)
79
80abityToBase :: Abity -> BaseType
81-- Calls with a sub-word return type define a temporary of base type
82-- w with its most significant bits unspecified.
83abityToBase (ASubWordType _) = Word
84-- When an aggregate type is used as argument type or return type, the
85-- value respectively passed or returned needs to be a pointer to a
86-- memory location holding the value.
87abityToBase (AUserDef _) = Long
88abityToBase (ABase ty) = ty
89
90data Const
91 = Number Word64
92 | SFP Float
93 | DFP Double
94 | Global GlobalIdent
95 deriving (Show, Eq)
96
97data DynConst
98 = Const Const
99 | Thread GlobalIdent
100 deriving (Show, Eq)
101
102data Value
103 = VConst DynConst
104 | VLocal LocalIdent
105 deriving (Show, Eq)
106
107data Linkage
108 = LExport
109 | LThread
110 | LSection String (Maybe String)
111 deriving (Show, Eq)
112
113data AllocSize
114 = AlignWord
115 | AlignLong
116 | AlignLongLong
117 deriving (Show, Eq)
118
119getSize :: AllocSize -> Int
120getSize AlignWord = 4
121getSize AlignLong = 8
122getSize AlignLongLong = 16
123
124data TypeDef
125 = TypeDef
126 { aggName :: UserIdent,
127 aggAlign :: Maybe AllocSize,
128 aggType :: AggType
129 }
130 deriving (Show, Eq)
131
132data SubType
133 = SExtType ExtType
134 | SUserDef UserIdent
135 deriving (Show, Eq)
136
137type Field = (SubType, Maybe Word64)
138
139-- TODO: Type for tuple
140data AggType
141 = ARegular [Field]
142 | AUnion [[Field]]
143 | AOpaque Word64
144 deriving (Show, Eq)
145
146data DataDef
147 = DataDef
148 { linkage :: [Linkage],
149 name :: GlobalIdent,
150 align :: Maybe AllocSize,
151 objs :: [DataObj]
152 }
153 deriving (Show, Eq)
154
155data DataObj
156 = OItem ExtType [DataItem]
157 | OZeroFill Word64
158 deriving (Show, Eq)
159
160data DataItem
161 = DSymbol GlobalIdent (Maybe Word64)
162 | DString String
163 | DConst Const
164 deriving (Show, Eq)
165
166data FuncDef
167 = FuncDef
168 { fLinkage :: [Linkage],
169 fName :: GlobalIdent,
170 fAbity :: Maybe Abity,
171 fParams :: [FuncParam],
172 fBlock :: [Block] -- TODO: Use a Map here
173 }
174 deriving (Show, Eq)
175
176data FuncParam
177 = Regular Abity LocalIdent
178 | Env LocalIdent
179 | Variadic
180 deriving (Show, Eq)
181
182data JumpInstr
183 = Jump BlockIdent
184 | Jnz Value BlockIdent BlockIdent
185 | Return (Maybe Value)
186 | Halt
187 deriving (Show, Eq)
188
189data LoadType
190 = LSubWord SubWordType
191 | LBase BaseType
192 deriving (Show, Eq)
193
194-- TODO: Could/Should define this on ExtType instead.
195loadByteSize :: LoadType -> Word64
196loadByteSize (LSubWord UnsignedByte) = 1
197loadByteSize (LSubWord SignedByte) = 1
198loadByteSize (LSubWord SignedHalf) = 2
199loadByteSize (LSubWord UnsignedHalf) = 2
200loadByteSize (LBase Word) = 4
201loadByteSize (LBase Long) = 8
202loadByteSize (LBase Single) = 4
203loadByteSize (LBase Double) = 8
204
205loadToExtType :: LoadType -> ExtType
206loadToExtType (LSubWord UnsignedByte) = Byte
207loadToExtType (LSubWord SignedByte) = Byte
208loadToExtType (LSubWord SignedHalf) = HalfWord
209loadToExtType (LSubWord UnsignedHalf) = HalfWord
210loadToExtType (LBase Word) = Base Word
211loadToExtType (LBase Long) = Base Long
212loadToExtType (LBase Single) = Base Single
213loadToExtType (LBase Double) = Base Double
214
215data Instr
216 = Add Value Value
217 | Sub Value Value
218 | Alloc AllocSize Word64
219 | Load LoadType Value
220 deriving (Show, Eq)
221
222data VolatileInstr
223 = Store ExtType Value Value
224 | Blit Value Value Word64
225 deriving (Show, Eq)
226
227data Statement
228 = Assign LocalIdent BaseType Instr
229 | Call (Maybe (LocalIdent, Abity)) Value [FuncParam]
230 | Volatile VolatileInstr
231 deriving (Show, Eq)
232
233data Block
234 = Block
235 { label :: BlockIdent,
236 -- TODO: phi
237 stmt :: [Statement],
238 term :: JumpInstr
239 }
240 deriving (Show, Eq)