feat: Data instances
All checks were successful
build / build (push) Successful in 6s

This commit is contained in:
2026-04-30 17:36:59 -06:00
parent 25b62cb69d
commit e61853e7a6

View File

@@ -4,6 +4,8 @@
{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE GADTs #-}
{-| {-|
Module : Language.QBE Module : Language.QBE
Description : Types and Pretty instances for the QBE IL Description : Types and Pretty instances for the QBE IL
@@ -92,6 +94,7 @@ import Prettyprinter
import Data.Hashable (Hashable) import Data.Hashable (Hashable)
import Control.DeepSeq (NFData) import Control.DeepSeq (NFData)
import Data.String (IsString) import Data.String (IsString)
import Data.Data (Data)
-- * Identifiers -- * Identifiers
---------------- ----------------
@@ -100,12 +103,12 @@ import Data.String (IsString)
type RawIdent = ShortText type RawIdent = ShortText
-- | Sigils are used to differentiate the verious types of 'Ident'ifier. -- | Sigils are used to differentiate the verious types of 'Ident'ifier.
data Sigil data Sigil where
= AggregateTy -- ^ @:@ AggregateTy :: Sigil
| Global -- ^ @$@ Global :: Sigil
| Temporary -- ^ @%@ Temporary :: Sigil
| Label -- ^ @\@@ Label :: Sigil
deriving (Show, Eq) deriving (Show, Eq, Data)
-- | QBE identifiers. The sigil is represented at the type level, so that -- | QBE identifiers. The sigil is represented at the type level, so that
-- mixing incompatible identifiers is impossible. -- mixing incompatible identifiers is impossible.
@@ -124,7 +127,7 @@ data Sigil
-- In the second argument of ($), namely Jmp $ Ident @'Global "a" -- In the second argument of ($), namely Jmp $ Ident @'Global "a"
-- In the expression: pretty $ Jmp $ Ident @'Global "a" -- In the expression: pretty $ Jmp $ Ident @'Global "a"
newtype Ident (t :: Sigil) = Ident RawIdent newtype Ident (t :: Sigil) = Ident RawIdent
deriving (Show, Eq, Ord, IsString, NFData, Hashable) deriving (Show, Eq, Ord, IsString, NFData, Hashable, Data)
instance Pretty (Ident 'AggregateTy) where instance Pretty (Ident 'AggregateTy) where
pretty (Ident raw) = pretty ':' <> pretty (TS.toText raw) pretty (Ident raw) = pretty ':' <> pretty (TS.toText raw)
@@ -144,7 +147,7 @@ data BaseTy
| Long -- ^ @l@ | Long -- ^ @l@
| Single -- ^ @s@ | Single -- ^ @s@
| Double -- ^ @d@ | Double -- ^ @d@
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty BaseTy where instance Pretty BaseTy where
pretty Word = pretty 'w' pretty Word = pretty 'w'
@@ -157,7 +160,7 @@ data ExtTy
= BaseTy BaseTy = BaseTy BaseTy
| Byte -- ^ @b@ | Byte -- ^ @b@
| HalfWord -- ^ @h@ | HalfWord -- ^ @h@
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty ExtTy where instance Pretty ExtTy where
pretty (BaseTy baseTy) = pretty baseTy pretty (BaseTy baseTy) = pretty baseTy
@@ -174,7 +177,7 @@ data Const
| CSingle Float -- ^ Single-precision float | CSingle Float -- ^ Single-precision float
| CDouble Double -- ^ Double-precision float | CDouble Double -- ^ Double-precision float
| CGlobal (Ident 'Global) -- ^ Global symbol | CGlobal (Ident 'Global) -- ^ Global symbol
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty Const where instance Pretty Const where
pretty (CInt int) = pretty int pretty (CInt int) = pretty int
@@ -188,7 +191,7 @@ instance Pretty Const where
data Linkage data Linkage
= Export -- ^ Marks the defined item as visible outside the current file's scope = Export -- ^ Marks the defined item as visible outside the current file's scope
| Section ShortText (Maybe Text) -- ^ Section name, with optional linker flags | Section ShortText (Maybe Text) -- ^ Section name, with optional linker flags
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty Linkage where instance Pretty Linkage where
pretty Export = "export" pretty Export = "export"
@@ -210,7 +213,7 @@ type Amount = Word64
data TypeDef data TypeDef
= TypeDef (Ident 'AggregateTy) (Maybe Alignment) [(SubTy, Maybe Amount)] = TypeDef (Ident 'AggregateTy) (Maybe Alignment) [(SubTy, Maybe Amount)]
| Opaque (Ident 'AggregateTy) Alignment Size | Opaque (Ident 'AggregateTy) Alignment Size
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty TypeDef where instance Pretty TypeDef where
pretty (TypeDef ident alignment def) = pretty (TypeDef ident alignment def) =
@@ -228,7 +231,7 @@ instance Pretty TypeDef where
data SubTy data SubTy
= SubExtTy ExtTy = SubExtTy ExtTy
| SubAggregateTy (Ident 'AggregateTy) | SubAggregateTy (Ident 'AggregateTy)
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty SubTy where instance Pretty SubTy where
pretty (SubExtTy extTy) = pretty extTy pretty (SubExtTy extTy) = pretty extTy
@@ -239,7 +242,7 @@ instance Pretty SubTy where
-- | Global object definition -- | Global object definition
data DataDef = DataDef [Linkage] (Ident 'Global) (Maybe Alignment) [Field] data DataDef = DataDef [Linkage] (Ident 'Global) (Maybe Alignment) [Field]
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty DataDef where instance Pretty DataDef where
pretty (DataDef linkage ident alignment fields) = vsep pretty (DataDef linkage ident alignment fields) = vsep
@@ -253,7 +256,7 @@ data DataItem
= Symbol (Ident 'Global) (Maybe Alignment) = Symbol (Ident 'Global) (Maybe Alignment)
| String ByteString | String ByteString
| Const Const | Const Const
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty DataItem where instance Pretty DataItem where
pretty (Symbol ident alignment) = pretty (Symbol ident alignment) =
@@ -264,7 +267,7 @@ instance Pretty DataItem where
data Field data Field
= FieldExtTy ExtTy (NonEmpty DataItem) = FieldExtTy ExtTy (NonEmpty DataItem)
| FieldZero Size | FieldZero Size
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty Field where instance Pretty Field where
pretty (FieldExtTy extTy items) = pretty extTy <+> hsep (toList $ pretty <$> items) pretty (FieldExtTy extTy items) = pretty extTy <+> hsep (toList $ pretty <$> items)
@@ -276,7 +279,7 @@ instance Pretty Field where
-- TODO use record syntax on long types like this one -- TODO use record syntax on long types like this one
-- | Function definition. The 'Maybe (Ident \'Temporary)' is the environment -- | Function definition. The 'Maybe (Ident \'Temporary)' is the environment
data FuncDef = FuncDef [Linkage] (Maybe AbiTy) (Ident 'Global) (Maybe (Ident 'Temporary)) [Param] Variadic (NonEmpty Block) data FuncDef = FuncDef [Linkage] (Maybe AbiTy) (Ident 'Global) (Maybe (Ident 'Temporary)) [Param] Variadic (NonEmpty Block)
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty FuncDef where instance Pretty FuncDef where
pretty (FuncDef linkage abiTy ident env params variadic blocks) = vsep pretty (FuncDef linkage abiTy ident env params variadic blocks) = vsep
@@ -291,7 +294,7 @@ instance Pretty FuncDef where
] ]
data AbiTy = AbiBaseTy BaseTy | AbiAggregateTy (Ident 'AggregateTy) data AbiTy = AbiBaseTy BaseTy | AbiAggregateTy (Ident 'AggregateTy)
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty AbiTy where instance Pretty AbiTy where
pretty (AbiBaseTy baseTy) = pretty baseTy pretty (AbiBaseTy baseTy) = pretty baseTy
@@ -299,14 +302,14 @@ instance Pretty AbiTy where
-- | Function parameter -- | Function parameter
data Param = Param AbiTy (Ident 'Temporary) data Param = Param AbiTy (Ident 'Temporary)
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty Param where instance Pretty Param where
pretty (Param abiTy ident) = pretty abiTy <+> pretty ident pretty (Param abiTy ident) = pretty abiTy <+> pretty ident
-- | Indicates the presence or absence of a variadic marker -- | Indicates the presence or absence of a variadic marker
data Variadic = Variadic | NoVariadic data Variadic = Variadic | NoVariadic
deriving (Show, Eq) deriving (Show, Eq, Data)
-- | 'Variadic' → @Just "..."@ -- | 'Variadic' → @Just "..."@
-- 'NoVariadic' → @Nothing@ -- 'NoVariadic' → @Nothing@
@@ -322,7 +325,7 @@ data Val
= ValConst Const = ValConst Const
| ValTemporary (Ident 'Temporary) | ValTemporary (Ident 'Temporary)
| ValGlobal (Ident 'Global) | ValGlobal (Ident 'Global)
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty Val where instance Pretty Val where
pretty (ValConst c) = pretty c pretty (ValConst c) = pretty c
@@ -331,7 +334,7 @@ instance Pretty Val where
-- | Block of instructions beginning with a label and ending with a jump -- | Block of instructions beginning with a label and ending with a jump
data Block = Block (Ident 'Label) [Phi] [Inst] Jump data Block = Block (Ident 'Label) [Phi] [Inst] Jump
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty Block where instance Pretty Block where
pretty (Block ident phis insts jump) = hang 4 $ vsep $ concat pretty (Block ident phis insts jump) = hang 4 $ vsep $ concat
@@ -346,7 +349,7 @@ data Jump
= Jmp (Ident 'Label) -- ^ Unconditional jump = Jmp (Ident 'Label) -- ^ Unconditional jump
| Jnz Val (Ident 'Label) (Ident 'Label) -- ^ Conditional jump | Jnz Val (Ident 'Label) (Ident 'Label) -- ^ Conditional jump
| Ret (Maybe Val) -- ^ Function return | Ret (Maybe Val) -- ^ Function return
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty Jump where instance Pretty Jump where
pretty (Jmp ident) = "jmp" <+> pretty ident pretty (Jmp ident) = "jmp" <+> pretty ident
@@ -362,7 +365,7 @@ instance Pretty Jump where
-- MAYBE change [PhiArg] to Map (Ident 'Label) Val -- MAYBE change [PhiArg] to Map (Ident 'Label) Val
-- | Phi instruction -- | Phi instruction
data Phi = Phi Assignment [PhiArg] data Phi = Phi Assignment [PhiArg]
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty Phi where instance Pretty Phi where
pretty (Phi assignment args) = pretty (Phi assignment args) =
@@ -370,7 +373,7 @@ instance Pretty Phi where
-- | Phi instruction argument, associating a 'Val' to a 'Label' -- | Phi instruction argument, associating a 'Val' to a 'Label'
data PhiArg = PhiArg (Ident 'Label) Val data PhiArg = PhiArg (Ident 'Label) Val
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty PhiArg where instance Pretty PhiArg where
pretty (PhiArg label val) = pretty label <+> pretty val pretty (PhiArg label val) = pretty label <+> pretty val
@@ -429,7 +432,7 @@ data Inst
| VaStart (Ident 'Temporary) | VaStart (Ident 'Temporary)
-- | @vaarg@, fetches the next argument from a variable argument list -- | @vaarg@, fetches the next argument from a variable argument list
| VaArg Assignment (Ident 'Temporary) | VaArg Assignment (Ident 'Temporary)
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty Inst where instance Pretty Inst where
pretty (BinaryOp assignment op v1 v2) = pretty (BinaryOp assignment op v1 v2) =
@@ -478,7 +481,7 @@ instance Pretty Inst where
-- | Represents the @%x =t@ part of an instruction. -- | Represents the @%x =t@ part of an instruction.
data Assignment = Assignment (Ident 'Temporary) BaseTy data Assignment = Assignment (Ident 'Temporary) BaseTy
deriving (Show, Eq) deriving (Show, Eq, Data)
-- | Infix synonym of 'Assignment' -- | Infix synonym of 'Assignment'
pattern (:=) :: Ident 'Temporary -> BaseTy -> Assignment pattern (:=) :: Ident 'Temporary -> BaseTy -> Assignment
@@ -489,7 +492,7 @@ instance Pretty Assignment where
-- | Integer representation -- | Integer representation
data IntRepr = Signed | Unsigned data IntRepr = Signed | Unsigned
deriving (Show, Eq) deriving (Show, Eq, Data)
-- | Binary arithmetic and bit operations -- | Binary arithmetic and bit operations
data BinaryOp data BinaryOp
@@ -516,7 +519,7 @@ data BinaryOp
| Shr | Shr
-- | @shl@ -- | @shl@
| Shl | Shl
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty BinaryOp where instance Pretty BinaryOp where
pretty Add = "add" pretty Add = "add"
@@ -548,7 +551,7 @@ data Comparison
-- Floating point only comparison -- Floating point only comparison
| O -- ^ ordered (no operand is a NaN) (floating point only) | O -- ^ ordered (no operand is a NaN) (floating point only)
| Uo -- ^ unordered (at least one operand is a NaN) (floating point only) | Uo -- ^ unordered (at least one operand is a NaN) (floating point only)
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty Comparison where instance Pretty Comparison where
pretty Eq = "eq" pretty Eq = "eq"
@@ -566,7 +569,7 @@ instance Pretty IntRepr where
-- | Function argument -- | Function argument
data Arg = Arg AbiTy Val data Arg = Arg AbiTy Val
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty Arg where instance Pretty Arg where
pretty (Arg abiTy val) = pretty abiTy <+> pretty val pretty (Arg abiTy val) = pretty abiTy <+> pretty val
@@ -576,7 +579,7 @@ instance Pretty Arg where
-- | Datatypre representing a QBE IL source file -- | Datatypre representing a QBE IL source file
data Program = Program [TypeDef] [DataDef] [FuncDef] data Program = Program [TypeDef] [DataDef] [FuncDef]
deriving (Show, Eq) deriving (Show, Eq, Data)
instance Pretty Program where instance Pretty Program where
pretty (Program typeDefs dataDefs funcDefs) = vsep $ concat pretty (Program typeDefs dataDefs funcDefs) = vsep $ concat