1-- SPDX-FileCopyrightText: 2025-2026 Sören Tempel <soeren+git@soeren-tempel.net>2--3-- SPDX-License-Identifier: GPL-3.0-only45module Language.QBE.Types6 ( -- * Identifiers7 UserIdent (..),8 LocalIdent (..),9 BlockIdent (..),10 GlobalIdent (..),1112 -- * Types13 BaseType (..),14 baseTypeByteSize,15 baseTypeBitSize,16 ExtType (..),17 extTypeBitSize,18 extTypeByteSize,19 SubWordType (..),20 SubType (..),21 LoadType (..),22 loadByteSize,2324 -- * Values25 Const (..),26 DynConst (..),27 Value (..),2829 -- * Definitions30 TypeDef (..),31 DataDef (..),32 Linkage (..),33 Field,34 AggType (..),35 dataSize,36 DataObj (..),37 objAlign,38 objSize,39 DataItem (..),40 JumpInstr (..),4142 -- * Functions43 FuncDef (..),44 FuncParam (..),45 FuncArg (..),46 Abity (..),47 abityToBase,48 Block (..),4950 -- * Instructions51 Statement (..),52 Instr (..),53 VolatileInstr (..),54 ExtArg (..),55 toExtType,56 FloatArg (..),57 f2BaseType,58 IntArg (..),59 i2BaseType,60 IntCmpOp (..),61 FloatCmpOp (..),62 Phi (..),63 AllocSize (..),64 getSize,65 )66where6768import Data.Map (Map)69import Data.Word (Word64)7071-- TODO: Prefix all constructors7273newtype UserIdent = UserIdent {userIdent :: String}74 deriving (Eq, Ord)7576instance Show UserIdent where77 show (UserIdent s) = ':' : s7879newtype LocalIdent = LocalIdent {localIdent :: String}80 deriving (Eq, Ord)8182instance Show LocalIdent where83 show (LocalIdent s) = '%' : s8485newtype BlockIdent = BlockIdent {blockIdent :: String}86 deriving (Eq, Ord)8788instance Show BlockIdent where89 show (BlockIdent s) = '@' : s9091newtype GlobalIdent = GlobalIdent {globalIdent :: String}92 deriving (Eq, Ord)9394instance Show GlobalIdent where95 show (GlobalIdent s) = '$' : s9697------------------------------------------------------------------------9899data BaseType100 = Word101 | Long102 | Single103 | Double104 deriving (Show, Eq)105106baseTypeByteSize :: BaseType -> Int107baseTypeByteSize Word = 4108baseTypeByteSize Long = 8109baseTypeByteSize Single = 4110baseTypeByteSize Double = 8111112baseTypeBitSize :: BaseType -> Int113baseTypeBitSize ty = baseTypeByteSize ty * 8114115data ExtType116 = Base BaseType117 | Byte118 | HalfWord119 deriving (Show, Eq)120121extTypeByteSize :: ExtType -> Int122extTypeByteSize (Base b) = baseTypeByteSize b123extTypeByteSize Byte = 1124extTypeByteSize HalfWord = 2125126extTypeBitSize :: ExtType -> Int127extTypeBitSize ty = extTypeByteSize ty * 8128129data SubWordType130 = SignedByte131 | UnsignedByte132 | SignedHalf133 | UnsignedHalf134 deriving (Show, Eq)135136data Abity137 = ABase BaseType138 | ASubWordType SubWordType139 | AUserDef UserIdent140 deriving (Show, Eq)141142abityToBase :: Abity -> BaseType143-- Calls with a sub-word return type define a temporary of base type144-- w with its most significant bits unspecified.145abityToBase (ASubWordType _) = Word146-- When an aggregate type is used as argument type or return type, the147-- value respectively passed or returned needs to be a pointer to a148-- memory location holding the value.149abityToBase (AUserDef _) = Long150abityToBase (ABase ty) = ty151152data Const153 = Number Word64154 | SFP Float155 | DFP Double156 | Global GlobalIdent157 deriving (Show, Eq)158159data DynConst160 = Const Const161 | Thread GlobalIdent162 | Extern GlobalIdent163 | ExternThread GlobalIdent164 deriving (Show, Eq)165166data Value167 = VConst DynConst168 | VLocal LocalIdent169 deriving (Show, Eq)170171data Linkage172 = LExport173 | LThread174 | LSection String (Maybe String)175 deriving (Show, Eq)176177data AllocSize178 = AllocWord179 | AllocLong180 | AllocLongLong181 deriving (Show, Eq)182183getSize :: AllocSize -> Int184getSize AllocWord = 4185getSize AllocLong = 8186getSize AllocLongLong = 16187188data TypeDef189 = TypeDef190 { aggName :: UserIdent,191 aggAlign :: Maybe Word64,192 aggType :: AggType193 }194 deriving (Show, Eq)195196data SubType197 = SExtType ExtType198 | SUserDef UserIdent199 deriving (Show, Eq)200201type Field = (SubType, Maybe Word64)202203-- TODO: Type for tuple204data AggType205 = ARegular [Field]206 | AUnion [[Field]]207 | AOpaque Word64208 deriving (Show, Eq)209210data DataDef211 = DataDef212 { linkage :: [Linkage],213 name :: GlobalIdent,214 align :: Maybe Word64,215 objs :: [DataObj]216 }217 deriving (Show, Eq)218219dataSize :: DataDef -> Int220dataSize dataDef =221 sum $ map objSize (objs dataDef)222223data DataObj224 = OItem ExtType [DataItem]225 | OZeroFill Word64226 deriving (Show, Eq)227228objAlign :: DataObj -> Word64229objAlign (OZeroFill _) = 1 :: Word64230objAlign (OItem ty _) = fromIntegral $ extTypeByteSize ty231232objSize :: DataObj -> Int233objSize (OZeroFill n) = fromIntegral n234objSize (OItem ty items) = extTypeByteSize ty * cnt items235 where236 cnt :: [DataItem] -> Int237 cnt [] = 0238 cnt ((DString s) : xs) = length s + cnt xs239 cnt (_ : xs) = 1 + cnt xs240241data DataItem242 = DSymOff GlobalIdent Word64243 | DString String244 | DConst Const245 deriving (Show, Eq)246247data FuncDef248 = FuncDef249 { fLinkage :: [Linkage],250 fName :: GlobalIdent,251 fAbity :: Maybe Abity,252 fParams :: [FuncParam],253 fBlock :: [Block] -- TODO: Use a Map here254 }255 deriving (Show, Eq)256257data FuncParam258 = Regular Abity LocalIdent259 | Env LocalIdent260 | Variadic261 deriving (Show, Eq)262263data FuncArg264 = ArgReg Abity Value265 | ArgEnv Value266 | ArgVar267 deriving (Show, Eq)268269data JumpInstr270 = Jump BlockIdent271 | Jnz Value BlockIdent BlockIdent272 | Return (Maybe Value)273 | Halt274 deriving (Show, Eq)275276data LoadType277 = LSubWord SubWordType278 | LBase BaseType279 deriving (Show, Eq)280281-- TODO: Could/Should define this on ExtType instead.282loadByteSize :: LoadType -> Word64283loadByteSize (LSubWord UnsignedByte) = 1284loadByteSize (LSubWord SignedByte) = 1285loadByteSize (LSubWord SignedHalf) = 2286loadByteSize (LSubWord UnsignedHalf) = 2287loadByteSize (LBase Word) = 4288loadByteSize (LBase Long) = 8289loadByteSize (LBase Single) = 4290loadByteSize (LBase Double) = 8291292data ExtArg293 = ExtSingle294 | ExtSubWord SubWordType295 | ExtSignedWord296 | ExtUnsignedWord297 deriving (Show, Eq)298299toExtType :: ExtArg -> (Bool, ExtType)300toExtType (ExtSubWord SignedByte) = (True, Byte)301toExtType (ExtSubWord UnsignedByte) = (False, Byte)302toExtType (ExtSubWord SignedHalf) = (True, HalfWord)303toExtType (ExtSubWord UnsignedHalf) = (False, HalfWord)304toExtType ExtSignedWord = (True, Base Word)305toExtType ExtUnsignedWord = (False, Base Word)306toExtType ExtSingle = (True, Base Single)307308data FloatArg = FDouble | FSingle309 deriving (Show, Eq)310311f2BaseType :: FloatArg -> BaseType312f2BaseType FSingle = Single313f2BaseType FDouble = Double314315data IntArg = IWord | ILong316 deriving (Show, Eq)317318i2BaseType :: IntArg -> BaseType319i2BaseType IWord = Word320i2BaseType ILong = Long321322-- TODO: Distinict types for floating point comparison?323data IntCmpOp324 = IEq325 | INe326 | ISle327 | ISlt328 | ISge329 | ISgt330 | IUle331 | IUlt332 | IUge333 | IUgt334 deriving (Show, Eq)335336data FloatCmpOp337 = FEq338 | FNe339 | FLe340 | FLt341 | FGe342 | FGt343 | FOrd344 | FUnord345 deriving (Show, Eq)346347data Instr348 = Add Value Value349 | Sub Value Value350 | Div Value Value351 | Mul Value Value352 | Neg Value353 | URem Value Value354 | Rem Value Value355 | UDiv Value Value356 | Or Value Value357 | Xor Value Value358 | And Value Value359 | Sar Value Value360 | Shr Value Value361 | Shl Value Value362 | Alloc AllocSize Value363 | Load LoadType Value364 | CompareInt IntArg IntCmpOp Value Value365 | CompareFloat FloatArg FloatCmpOp Value Value366 | Ext ExtArg Value367 | FloatToInt FloatArg Bool Value368 | IntToFloat IntArg Bool Value369 | TruncDouble Value370 | Cast Value371 | Copy Value372 | VAArg Value373 deriving (Show, Eq)374375data VolatileInstr376 = Store ExtType Value Value377 | VAStart Value378 | Blit Value Value Word64379 | DBGLoc Word64 Word64 (Maybe Word64)380 deriving (Show, Eq)381382data Statement383 = Assign LocalIdent BaseType Instr384 | Call (Maybe (LocalIdent, Abity)) Value [FuncArg]385 | Volatile VolatileInstr386 deriving (Show, Eq)387388data Phi389 = Phi390 { pName :: LocalIdent,391 pType :: BaseType,392 pLabels :: Map BlockIdent Value393 }394 deriving (Show, Eq)395396data Block397 = Block398 { label :: BlockIdent,399 phi :: [Phi],400 stmt :: [Statement],401 term :: JumpInstr402 }403 deriving (Show, Eq)