quebex

A software analysis framework built around the QBE intermediate language

git clone https://git.8pit.net/quebex.git

  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)