-- SPDX-FileCopyrightText: 2025-2026 Sören Tempel <soeren+git@soeren-tempel.net>
--
-- SPDX-License-Identifier: GPL-3.0-only

module Language.QBE.Types
  ( -- * Identifiers
    UserIdent (..),
    LocalIdent (..),
    BlockIdent (..),
    GlobalIdent (..),

    -- * Types
    BaseType (..),
    baseTypeByteSize,
    baseTypeBitSize,
    ExtType (..),
    extTypeBitSize,
    extTypeByteSize,
    SubWordType (..),
    SubType (..),
    LoadType (..),
    loadByteSize,

    -- * Values
    Const (..),
    DynConst (..),
    Value (..),

    -- * Definitions
    TypeDef (..),
    DataDef (..),
    Linkage (..),
    Field,
    AggType (..),
    dataSize,
    DataObj (..),
    objAlign,
    objSize,
    DataItem (..),
    JumpInstr (..),

    -- * Functions
    FuncDef (..),
    FuncParam (..),
    FuncArg (..),
    Abity (..),
    abityToBase,
    Block (..),
    fEntry,

    -- * Instructions
    Statement (..),
    Instr (..),
    VolatileInstr (..),
    ExtArg (..),
    toExtType,
    FloatArg (..),
    f2BaseType,
    IntArg (..),
    i2BaseType,
    IntCmpOp (..),
    FloatCmpOp (..),
    Phi (..),
    AllocSize (..),
    getSize,
  )
where

import Data.Map (Map)
import Data.Map qualified as Map
import Data.Maybe (fromJust)
import Data.Word (Word64)

-- TODO: Prefix all constructors

newtype UserIdent = UserIdent {UserIdent -> String
userIdent :: String}
  deriving (UserIdent -> UserIdent -> Bool
(UserIdent -> UserIdent -> Bool)
-> (UserIdent -> UserIdent -> Bool) -> Eq UserIdent
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: UserIdent -> UserIdent -> Bool
== :: UserIdent -> UserIdent -> Bool
$c/= :: UserIdent -> UserIdent -> Bool
/= :: UserIdent -> UserIdent -> Bool
Eq, Eq UserIdent
Eq UserIdent =>
(UserIdent -> UserIdent -> Ordering)
-> (UserIdent -> UserIdent -> Bool)
-> (UserIdent -> UserIdent -> Bool)
-> (UserIdent -> UserIdent -> Bool)
-> (UserIdent -> UserIdent -> Bool)
-> (UserIdent -> UserIdent -> UserIdent)
-> (UserIdent -> UserIdent -> UserIdent)
-> Ord UserIdent
UserIdent -> UserIdent -> Bool
UserIdent -> UserIdent -> Ordering
UserIdent -> UserIdent -> UserIdent
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: UserIdent -> UserIdent -> Ordering
compare :: UserIdent -> UserIdent -> Ordering
$c< :: UserIdent -> UserIdent -> Bool
< :: UserIdent -> UserIdent -> Bool
$c<= :: UserIdent -> UserIdent -> Bool
<= :: UserIdent -> UserIdent -> Bool
$c> :: UserIdent -> UserIdent -> Bool
> :: UserIdent -> UserIdent -> Bool
$c>= :: UserIdent -> UserIdent -> Bool
>= :: UserIdent -> UserIdent -> Bool
$cmax :: UserIdent -> UserIdent -> UserIdent
max :: UserIdent -> UserIdent -> UserIdent
$cmin :: UserIdent -> UserIdent -> UserIdent
min :: UserIdent -> UserIdent -> UserIdent
Ord)

instance Show UserIdent where
  show :: UserIdent -> String
show (UserIdent String
s) = Char
':' Char -> String -> String
forall a. a -> [a] -> [a]
: String
s

newtype LocalIdent = LocalIdent {LocalIdent -> String
localIdent :: String}
  deriving (LocalIdent -> LocalIdent -> Bool
(LocalIdent -> LocalIdent -> Bool)
-> (LocalIdent -> LocalIdent -> Bool) -> Eq LocalIdent
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: LocalIdent -> LocalIdent -> Bool
== :: LocalIdent -> LocalIdent -> Bool
$c/= :: LocalIdent -> LocalIdent -> Bool
/= :: LocalIdent -> LocalIdent -> Bool
Eq, Eq LocalIdent
Eq LocalIdent =>
(LocalIdent -> LocalIdent -> Ordering)
-> (LocalIdent -> LocalIdent -> Bool)
-> (LocalIdent -> LocalIdent -> Bool)
-> (LocalIdent -> LocalIdent -> Bool)
-> (LocalIdent -> LocalIdent -> Bool)
-> (LocalIdent -> LocalIdent -> LocalIdent)
-> (LocalIdent -> LocalIdent -> LocalIdent)
-> Ord LocalIdent
LocalIdent -> LocalIdent -> Bool
LocalIdent -> LocalIdent -> Ordering
LocalIdent -> LocalIdent -> LocalIdent
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: LocalIdent -> LocalIdent -> Ordering
compare :: LocalIdent -> LocalIdent -> Ordering
$c< :: LocalIdent -> LocalIdent -> Bool
< :: LocalIdent -> LocalIdent -> Bool
$c<= :: LocalIdent -> LocalIdent -> Bool
<= :: LocalIdent -> LocalIdent -> Bool
$c> :: LocalIdent -> LocalIdent -> Bool
> :: LocalIdent -> LocalIdent -> Bool
$c>= :: LocalIdent -> LocalIdent -> Bool
>= :: LocalIdent -> LocalIdent -> Bool
$cmax :: LocalIdent -> LocalIdent -> LocalIdent
max :: LocalIdent -> LocalIdent -> LocalIdent
$cmin :: LocalIdent -> LocalIdent -> LocalIdent
min :: LocalIdent -> LocalIdent -> LocalIdent
Ord)

instance Show LocalIdent where
  show :: LocalIdent -> String
show (LocalIdent String
s) = Char
'%' Char -> String -> String
forall a. a -> [a] -> [a]
: String
s

newtype BlockIdent = BlockIdent {BlockIdent -> String
blockIdent :: String}
  deriving (BlockIdent -> BlockIdent -> Bool
(BlockIdent -> BlockIdent -> Bool)
-> (BlockIdent -> BlockIdent -> Bool) -> Eq BlockIdent
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: BlockIdent -> BlockIdent -> Bool
== :: BlockIdent -> BlockIdent -> Bool
$c/= :: BlockIdent -> BlockIdent -> Bool
/= :: BlockIdent -> BlockIdent -> Bool
Eq, Eq BlockIdent
Eq BlockIdent =>
(BlockIdent -> BlockIdent -> Ordering)
-> (BlockIdent -> BlockIdent -> Bool)
-> (BlockIdent -> BlockIdent -> Bool)
-> (BlockIdent -> BlockIdent -> Bool)
-> (BlockIdent -> BlockIdent -> Bool)
-> (BlockIdent -> BlockIdent -> BlockIdent)
-> (BlockIdent -> BlockIdent -> BlockIdent)
-> Ord BlockIdent
BlockIdent -> BlockIdent -> Bool
BlockIdent -> BlockIdent -> Ordering
BlockIdent -> BlockIdent -> BlockIdent
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: BlockIdent -> BlockIdent -> Ordering
compare :: BlockIdent -> BlockIdent -> Ordering
$c< :: BlockIdent -> BlockIdent -> Bool
< :: BlockIdent -> BlockIdent -> Bool
$c<= :: BlockIdent -> BlockIdent -> Bool
<= :: BlockIdent -> BlockIdent -> Bool
$c> :: BlockIdent -> BlockIdent -> Bool
> :: BlockIdent -> BlockIdent -> Bool
$c>= :: BlockIdent -> BlockIdent -> Bool
>= :: BlockIdent -> BlockIdent -> Bool
$cmax :: BlockIdent -> BlockIdent -> BlockIdent
max :: BlockIdent -> BlockIdent -> BlockIdent
$cmin :: BlockIdent -> BlockIdent -> BlockIdent
min :: BlockIdent -> BlockIdent -> BlockIdent
Ord)

instance Show BlockIdent where
  show :: BlockIdent -> String
show (BlockIdent String
s) = Char
'@' Char -> String -> String
forall a. a -> [a] -> [a]
: String
s

newtype GlobalIdent = GlobalIdent {GlobalIdent -> String
globalIdent :: String}
  deriving (GlobalIdent -> GlobalIdent -> Bool
(GlobalIdent -> GlobalIdent -> Bool)
-> (GlobalIdent -> GlobalIdent -> Bool) -> Eq GlobalIdent
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: GlobalIdent -> GlobalIdent -> Bool
== :: GlobalIdent -> GlobalIdent -> Bool
$c/= :: GlobalIdent -> GlobalIdent -> Bool
/= :: GlobalIdent -> GlobalIdent -> Bool
Eq, Eq GlobalIdent
Eq GlobalIdent =>
(GlobalIdent -> GlobalIdent -> Ordering)
-> (GlobalIdent -> GlobalIdent -> Bool)
-> (GlobalIdent -> GlobalIdent -> Bool)
-> (GlobalIdent -> GlobalIdent -> Bool)
-> (GlobalIdent -> GlobalIdent -> Bool)
-> (GlobalIdent -> GlobalIdent -> GlobalIdent)
-> (GlobalIdent -> GlobalIdent -> GlobalIdent)
-> Ord GlobalIdent
GlobalIdent -> GlobalIdent -> Bool
GlobalIdent -> GlobalIdent -> Ordering
GlobalIdent -> GlobalIdent -> GlobalIdent
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: GlobalIdent -> GlobalIdent -> Ordering
compare :: GlobalIdent -> GlobalIdent -> Ordering
$c< :: GlobalIdent -> GlobalIdent -> Bool
< :: GlobalIdent -> GlobalIdent -> Bool
$c<= :: GlobalIdent -> GlobalIdent -> Bool
<= :: GlobalIdent -> GlobalIdent -> Bool
$c> :: GlobalIdent -> GlobalIdent -> Bool
> :: GlobalIdent -> GlobalIdent -> Bool
$c>= :: GlobalIdent -> GlobalIdent -> Bool
>= :: GlobalIdent -> GlobalIdent -> Bool
$cmax :: GlobalIdent -> GlobalIdent -> GlobalIdent
max :: GlobalIdent -> GlobalIdent -> GlobalIdent
$cmin :: GlobalIdent -> GlobalIdent -> GlobalIdent
min :: GlobalIdent -> GlobalIdent -> GlobalIdent
Ord)

instance Show GlobalIdent where
  show :: GlobalIdent -> String
show (GlobalIdent String
s) = Char
'$' Char -> String -> String
forall a. a -> [a] -> [a]
: String
s

------------------------------------------------------------------------

data BaseType
  = Word
  | Long
  | Single
  | Double
  deriving (Int -> BaseType -> String -> String
[BaseType] -> String -> String
BaseType -> String
(Int -> BaseType -> String -> String)
-> (BaseType -> String)
-> ([BaseType] -> String -> String)
-> Show BaseType
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> BaseType -> String -> String
showsPrec :: Int -> BaseType -> String -> String
$cshow :: BaseType -> String
show :: BaseType -> String
$cshowList :: [BaseType] -> String -> String
showList :: [BaseType] -> String -> String
Show, BaseType -> BaseType -> Bool
(BaseType -> BaseType -> Bool)
-> (BaseType -> BaseType -> Bool) -> Eq BaseType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: BaseType -> BaseType -> Bool
== :: BaseType -> BaseType -> Bool
$c/= :: BaseType -> BaseType -> Bool
/= :: BaseType -> BaseType -> Bool
Eq)

baseTypeByteSize :: BaseType -> Int
baseTypeByteSize :: BaseType -> Int
baseTypeByteSize BaseType
Word = Int
4
baseTypeByteSize BaseType
Long = Int
8
baseTypeByteSize BaseType
Single = Int
4
baseTypeByteSize BaseType
Double = Int
8

baseTypeBitSize :: BaseType -> Int
baseTypeBitSize :: BaseType -> Int
baseTypeBitSize BaseType
ty = BaseType -> Int
baseTypeByteSize BaseType
ty Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
8

data ExtType
  = Base BaseType
  | Byte
  | HalfWord
  deriving (Int -> ExtType -> String -> String
[ExtType] -> String -> String
ExtType -> String
(Int -> ExtType -> String -> String)
-> (ExtType -> String)
-> ([ExtType] -> String -> String)
-> Show ExtType
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> ExtType -> String -> String
showsPrec :: Int -> ExtType -> String -> String
$cshow :: ExtType -> String
show :: ExtType -> String
$cshowList :: [ExtType] -> String -> String
showList :: [ExtType] -> String -> String
Show, ExtType -> ExtType -> Bool
(ExtType -> ExtType -> Bool)
-> (ExtType -> ExtType -> Bool) -> Eq ExtType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ExtType -> ExtType -> Bool
== :: ExtType -> ExtType -> Bool
$c/= :: ExtType -> ExtType -> Bool
/= :: ExtType -> ExtType -> Bool
Eq)

extTypeByteSize :: ExtType -> Int
extTypeByteSize :: ExtType -> Int
extTypeByteSize (Base BaseType
b) = BaseType -> Int
baseTypeByteSize BaseType
b
extTypeByteSize ExtType
Byte = Int
1
extTypeByteSize ExtType
HalfWord = Int
2

extTypeBitSize :: ExtType -> Int
extTypeBitSize :: ExtType -> Int
extTypeBitSize ExtType
ty = ExtType -> Int
extTypeByteSize ExtType
ty Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
8

data SubWordType
  = SignedByte
  | UnsignedByte
  | SignedHalf
  | UnsignedHalf
  deriving (Int -> SubWordType -> String -> String
[SubWordType] -> String -> String
SubWordType -> String
(Int -> SubWordType -> String -> String)
-> (SubWordType -> String)
-> ([SubWordType] -> String -> String)
-> Show SubWordType
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> SubWordType -> String -> String
showsPrec :: Int -> SubWordType -> String -> String
$cshow :: SubWordType -> String
show :: SubWordType -> String
$cshowList :: [SubWordType] -> String -> String
showList :: [SubWordType] -> String -> String
Show, SubWordType -> SubWordType -> Bool
(SubWordType -> SubWordType -> Bool)
-> (SubWordType -> SubWordType -> Bool) -> Eq SubWordType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SubWordType -> SubWordType -> Bool
== :: SubWordType -> SubWordType -> Bool
$c/= :: SubWordType -> SubWordType -> Bool
/= :: SubWordType -> SubWordType -> Bool
Eq)

data Abity
  = ABase BaseType
  | ASubWordType SubWordType
  | AUserDef UserIdent
  deriving (Int -> Abity -> String -> String
[Abity] -> String -> String
Abity -> String
(Int -> Abity -> String -> String)
-> (Abity -> String) -> ([Abity] -> String -> String) -> Show Abity
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> Abity -> String -> String
showsPrec :: Int -> Abity -> String -> String
$cshow :: Abity -> String
show :: Abity -> String
$cshowList :: [Abity] -> String -> String
showList :: [Abity] -> String -> String
Show, Abity -> Abity -> Bool
(Abity -> Abity -> Bool) -> (Abity -> Abity -> Bool) -> Eq Abity
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Abity -> Abity -> Bool
== :: Abity -> Abity -> Bool
$c/= :: Abity -> Abity -> Bool
/= :: Abity -> Abity -> Bool
Eq)

abityToBase :: Abity -> BaseType
-- Calls with a sub-word return type define a temporary of base type
-- w with its most significant bits unspecified.
abityToBase :: Abity -> BaseType
abityToBase (ASubWordType SubWordType
_) = BaseType
Word
-- When an aggregate type is used as argument type or return type, the
-- value respectively passed or returned needs to be a pointer to a
-- memory location holding the value.
abityToBase (AUserDef UserIdent
_) = BaseType
Long
abityToBase (ABase BaseType
ty) = BaseType
ty

data Const
  = Number Word64
  | SFP Float
  | DFP Double
  | Global GlobalIdent
  deriving (Int -> Const -> String -> String
[Const] -> String -> String
Const -> String
(Int -> Const -> String -> String)
-> (Const -> String) -> ([Const] -> String -> String) -> Show Const
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> Const -> String -> String
showsPrec :: Int -> Const -> String -> String
$cshow :: Const -> String
show :: Const -> String
$cshowList :: [Const] -> String -> String
showList :: [Const] -> String -> String
Show, Const -> Const -> Bool
(Const -> Const -> Bool) -> (Const -> Const -> Bool) -> Eq Const
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Const -> Const -> Bool
== :: Const -> Const -> Bool
$c/= :: Const -> Const -> Bool
/= :: Const -> Const -> Bool
Eq)

data DynConst
  = Const Const
  | Thread GlobalIdent
  | Extern GlobalIdent
  | ExternThread GlobalIdent
  deriving (Int -> DynConst -> String -> String
[DynConst] -> String -> String
DynConst -> String
(Int -> DynConst -> String -> String)
-> (DynConst -> String)
-> ([DynConst] -> String -> String)
-> Show DynConst
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> DynConst -> String -> String
showsPrec :: Int -> DynConst -> String -> String
$cshow :: DynConst -> String
show :: DynConst -> String
$cshowList :: [DynConst] -> String -> String
showList :: [DynConst] -> String -> String
Show, DynConst -> DynConst -> Bool
(DynConst -> DynConst -> Bool)
-> (DynConst -> DynConst -> Bool) -> Eq DynConst
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: DynConst -> DynConst -> Bool
== :: DynConst -> DynConst -> Bool
$c/= :: DynConst -> DynConst -> Bool
/= :: DynConst -> DynConst -> Bool
Eq)

data Value
  = VConst DynConst
  | VLocal LocalIdent
  deriving (Int -> Value -> String -> String
[Value] -> String -> String
Value -> String
(Int -> Value -> String -> String)
-> (Value -> String) -> ([Value] -> String -> String) -> Show Value
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> Value -> String -> String
showsPrec :: Int -> Value -> String -> String
$cshow :: Value -> String
show :: Value -> String
$cshowList :: [Value] -> String -> String
showList :: [Value] -> String -> String
Show, Value -> Value -> Bool
(Value -> Value -> Bool) -> (Value -> Value -> Bool) -> Eq Value
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Value -> Value -> Bool
== :: Value -> Value -> Bool
$c/= :: Value -> Value -> Bool
/= :: Value -> Value -> Bool
Eq)

data Linkage
  = LExport
  | LThread
  | LSection String (Maybe String)
  deriving (Int -> Linkage -> String -> String
[Linkage] -> String -> String
Linkage -> String
(Int -> Linkage -> String -> String)
-> (Linkage -> String)
-> ([Linkage] -> String -> String)
-> Show Linkage
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> Linkage -> String -> String
showsPrec :: Int -> Linkage -> String -> String
$cshow :: Linkage -> String
show :: Linkage -> String
$cshowList :: [Linkage] -> String -> String
showList :: [Linkage] -> String -> String
Show, Linkage -> Linkage -> Bool
(Linkage -> Linkage -> Bool)
-> (Linkage -> Linkage -> Bool) -> Eq Linkage
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Linkage -> Linkage -> Bool
== :: Linkage -> Linkage -> Bool
$c/= :: Linkage -> Linkage -> Bool
/= :: Linkage -> Linkage -> Bool
Eq)

data AllocSize
  = AllocWord
  | AllocLong
  | AllocLongLong
  deriving (Int -> AllocSize -> String -> String
[AllocSize] -> String -> String
AllocSize -> String
(Int -> AllocSize -> String -> String)
-> (AllocSize -> String)
-> ([AllocSize] -> String -> String)
-> Show AllocSize
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> AllocSize -> String -> String
showsPrec :: Int -> AllocSize -> String -> String
$cshow :: AllocSize -> String
show :: AllocSize -> String
$cshowList :: [AllocSize] -> String -> String
showList :: [AllocSize] -> String -> String
Show, AllocSize -> AllocSize -> Bool
(AllocSize -> AllocSize -> Bool)
-> (AllocSize -> AllocSize -> Bool) -> Eq AllocSize
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AllocSize -> AllocSize -> Bool
== :: AllocSize -> AllocSize -> Bool
$c/= :: AllocSize -> AllocSize -> Bool
/= :: AllocSize -> AllocSize -> Bool
Eq)

getSize :: AllocSize -> Int
getSize :: AllocSize -> Int
getSize AllocSize
AllocWord = Int
4
getSize AllocSize
AllocLong = Int
8
getSize AllocSize
AllocLongLong = Int
16

data TypeDef
  = TypeDef
  { TypeDef -> UserIdent
aggName :: UserIdent,
    TypeDef -> Maybe Word64
aggAlign :: Maybe Word64,
    TypeDef -> AggType
aggType :: AggType
  }
  deriving (Int -> TypeDef -> String -> String
[TypeDef] -> String -> String
TypeDef -> String
(Int -> TypeDef -> String -> String)
-> (TypeDef -> String)
-> ([TypeDef] -> String -> String)
-> Show TypeDef
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> TypeDef -> String -> String
showsPrec :: Int -> TypeDef -> String -> String
$cshow :: TypeDef -> String
show :: TypeDef -> String
$cshowList :: [TypeDef] -> String -> String
showList :: [TypeDef] -> String -> String
Show, TypeDef -> TypeDef -> Bool
(TypeDef -> TypeDef -> Bool)
-> (TypeDef -> TypeDef -> Bool) -> Eq TypeDef
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: TypeDef -> TypeDef -> Bool
== :: TypeDef -> TypeDef -> Bool
$c/= :: TypeDef -> TypeDef -> Bool
/= :: TypeDef -> TypeDef -> Bool
Eq)

data SubType
  = SExtType ExtType
  | SUserDef UserIdent
  deriving (Int -> SubType -> String -> String
[SubType] -> String -> String
SubType -> String
(Int -> SubType -> String -> String)
-> (SubType -> String)
-> ([SubType] -> String -> String)
-> Show SubType
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> SubType -> String -> String
showsPrec :: Int -> SubType -> String -> String
$cshow :: SubType -> String
show :: SubType -> String
$cshowList :: [SubType] -> String -> String
showList :: [SubType] -> String -> String
Show, SubType -> SubType -> Bool
(SubType -> SubType -> Bool)
-> (SubType -> SubType -> Bool) -> Eq SubType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SubType -> SubType -> Bool
== :: SubType -> SubType -> Bool
$c/= :: SubType -> SubType -> Bool
/= :: SubType -> SubType -> Bool
Eq)

type Field = (SubType, Maybe Word64)

-- TODO: Type for tuple
data AggType
  = ARegular [Field]
  | AUnion [[Field]]
  | AOpaque Word64
  deriving (Int -> AggType -> String -> String
[AggType] -> String -> String
AggType -> String
(Int -> AggType -> String -> String)
-> (AggType -> String)
-> ([AggType] -> String -> String)
-> Show AggType
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> AggType -> String -> String
showsPrec :: Int -> AggType -> String -> String
$cshow :: AggType -> String
show :: AggType -> String
$cshowList :: [AggType] -> String -> String
showList :: [AggType] -> String -> String
Show, AggType -> AggType -> Bool
(AggType -> AggType -> Bool)
-> (AggType -> AggType -> Bool) -> Eq AggType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AggType -> AggType -> Bool
== :: AggType -> AggType -> Bool
$c/= :: AggType -> AggType -> Bool
/= :: AggType -> AggType -> Bool
Eq)

data DataDef
  = DataDef
  { DataDef -> [Linkage]
linkage :: [Linkage],
    DataDef -> GlobalIdent
name :: GlobalIdent,
    DataDef -> Maybe Word64
align :: Maybe Word64,
    DataDef -> [DataObj]
objs :: [DataObj]
  }
  deriving (Int -> DataDef -> String -> String
[DataDef] -> String -> String
DataDef -> String
(Int -> DataDef -> String -> String)
-> (DataDef -> String)
-> ([DataDef] -> String -> String)
-> Show DataDef
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> DataDef -> String -> String
showsPrec :: Int -> DataDef -> String -> String
$cshow :: DataDef -> String
show :: DataDef -> String
$cshowList :: [DataDef] -> String -> String
showList :: [DataDef] -> String -> String
Show, DataDef -> DataDef -> Bool
(DataDef -> DataDef -> Bool)
-> (DataDef -> DataDef -> Bool) -> Eq DataDef
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: DataDef -> DataDef -> Bool
== :: DataDef -> DataDef -> Bool
$c/= :: DataDef -> DataDef -> Bool
/= :: DataDef -> DataDef -> Bool
Eq)

dataSize :: DataDef -> Int
dataSize :: DataDef -> Int
dataSize DataDef
dataDef =
  [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ (DataObj -> Int) -> [DataObj] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map DataObj -> Int
objSize (DataDef -> [DataObj]
objs DataDef
dataDef)

data DataObj
  = OItem ExtType [DataItem]
  | OZeroFill Word64
  deriving (Int -> DataObj -> String -> String
[DataObj] -> String -> String
DataObj -> String
(Int -> DataObj -> String -> String)
-> (DataObj -> String)
-> ([DataObj] -> String -> String)
-> Show DataObj
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> DataObj -> String -> String
showsPrec :: Int -> DataObj -> String -> String
$cshow :: DataObj -> String
show :: DataObj -> String
$cshowList :: [DataObj] -> String -> String
showList :: [DataObj] -> String -> String
Show, DataObj -> DataObj -> Bool
(DataObj -> DataObj -> Bool)
-> (DataObj -> DataObj -> Bool) -> Eq DataObj
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: DataObj -> DataObj -> Bool
== :: DataObj -> DataObj -> Bool
$c/= :: DataObj -> DataObj -> Bool
/= :: DataObj -> DataObj -> Bool
Eq)

objAlign :: DataObj -> Word64
objAlign :: DataObj -> Word64
objAlign (OZeroFill Word64
_) = Word64
1 :: Word64
objAlign (OItem ExtType
ty [DataItem]
_) = Int -> Word64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word64) -> Int -> Word64
forall a b. (a -> b) -> a -> b
$ ExtType -> Int
extTypeByteSize ExtType
ty

objSize :: DataObj -> Int
objSize :: DataObj -> Int
objSize (OZeroFill Word64
n) = Word64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
n
objSize (OItem ExtType
ty [DataItem]
items) = ExtType -> Int
extTypeByteSize ExtType
ty Int -> Int -> Int
forall a. Num a => a -> a -> a
* [DataItem] -> Int
cnt [DataItem]
items
  where
    cnt :: [DataItem] -> Int
    cnt :: [DataItem] -> Int
cnt [] = Int
0
    cnt ((DString String
s) : [DataItem]
xs) = String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
s Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [DataItem] -> Int
cnt [DataItem]
xs
    cnt (DataItem
_ : [DataItem]
xs) = Int
1 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [DataItem] -> Int
cnt [DataItem]
xs

data DataItem
  = DSymOff GlobalIdent Word64
  | DString String
  | DConst Const
  deriving (Int -> DataItem -> String -> String
[DataItem] -> String -> String
DataItem -> String
(Int -> DataItem -> String -> String)
-> (DataItem -> String)
-> ([DataItem] -> String -> String)
-> Show DataItem
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> DataItem -> String -> String
showsPrec :: Int -> DataItem -> String -> String
$cshow :: DataItem -> String
show :: DataItem -> String
$cshowList :: [DataItem] -> String -> String
showList :: [DataItem] -> String -> String
Show, DataItem -> DataItem -> Bool
(DataItem -> DataItem -> Bool)
-> (DataItem -> DataItem -> Bool) -> Eq DataItem
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: DataItem -> DataItem -> Bool
== :: DataItem -> DataItem -> Bool
$c/= :: DataItem -> DataItem -> Bool
/= :: DataItem -> DataItem -> Bool
Eq)

data FuncDef
  = FuncDef
  { FuncDef -> [Linkage]
fLinkage :: [Linkage],
    FuncDef -> GlobalIdent
fName :: GlobalIdent,
    FuncDef -> BlockIdent
fStart :: BlockIdent,
    FuncDef -> Maybe Abity
fAbity :: Maybe Abity,
    FuncDef -> [FuncParam]
fParams :: [FuncParam],
    FuncDef -> Map BlockIdent Block
fBlock :: Map BlockIdent Block
  }
  deriving (Int -> FuncDef -> String -> String
[FuncDef] -> String -> String
FuncDef -> String
(Int -> FuncDef -> String -> String)
-> (FuncDef -> String)
-> ([FuncDef] -> String -> String)
-> Show FuncDef
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> FuncDef -> String -> String
showsPrec :: Int -> FuncDef -> String -> String
$cshow :: FuncDef -> String
show :: FuncDef -> String
$cshowList :: [FuncDef] -> String -> String
showList :: [FuncDef] -> String -> String
Show, FuncDef -> FuncDef -> Bool
(FuncDef -> FuncDef -> Bool)
-> (FuncDef -> FuncDef -> Bool) -> Eq FuncDef
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FuncDef -> FuncDef -> Bool
== :: FuncDef -> FuncDef -> Bool
$c/= :: FuncDef -> FuncDef -> Bool
/= :: FuncDef -> FuncDef -> Bool
Eq)

fEntry :: FuncDef -> Block
fEntry :: FuncDef -> Block
fEntry FuncDef
func = Maybe Block -> Block
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe Block -> Block) -> Maybe Block -> Block
forall a b. (a -> b) -> a -> b
$ BlockIdent -> Map BlockIdent Block -> Maybe Block
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (FuncDef -> BlockIdent
fStart FuncDef
func) (FuncDef -> Map BlockIdent Block
fBlock FuncDef
func)

data FuncParam
  = Regular Abity LocalIdent
  | Env LocalIdent
  | Variadic
  deriving (Int -> FuncParam -> String -> String
[FuncParam] -> String -> String
FuncParam -> String
(Int -> FuncParam -> String -> String)
-> (FuncParam -> String)
-> ([FuncParam] -> String -> String)
-> Show FuncParam
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> FuncParam -> String -> String
showsPrec :: Int -> FuncParam -> String -> String
$cshow :: FuncParam -> String
show :: FuncParam -> String
$cshowList :: [FuncParam] -> String -> String
showList :: [FuncParam] -> String -> String
Show, FuncParam -> FuncParam -> Bool
(FuncParam -> FuncParam -> Bool)
-> (FuncParam -> FuncParam -> Bool) -> Eq FuncParam
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FuncParam -> FuncParam -> Bool
== :: FuncParam -> FuncParam -> Bool
$c/= :: FuncParam -> FuncParam -> Bool
/= :: FuncParam -> FuncParam -> Bool
Eq)

data FuncArg
  = ArgReg Abity Value
  | ArgEnv Value
  | ArgVar
  deriving (Int -> FuncArg -> String -> String
[FuncArg] -> String -> String
FuncArg -> String
(Int -> FuncArg -> String -> String)
-> (FuncArg -> String)
-> ([FuncArg] -> String -> String)
-> Show FuncArg
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> FuncArg -> String -> String
showsPrec :: Int -> FuncArg -> String -> String
$cshow :: FuncArg -> String
show :: FuncArg -> String
$cshowList :: [FuncArg] -> String -> String
showList :: [FuncArg] -> String -> String
Show, FuncArg -> FuncArg -> Bool
(FuncArg -> FuncArg -> Bool)
-> (FuncArg -> FuncArg -> Bool) -> Eq FuncArg
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FuncArg -> FuncArg -> Bool
== :: FuncArg -> FuncArg -> Bool
$c/= :: FuncArg -> FuncArg -> Bool
/= :: FuncArg -> FuncArg -> Bool
Eq)

data JumpInstr
  = Jump BlockIdent
  | Jnz Value BlockIdent BlockIdent
  | Return (Maybe Value)
  | Halt
  deriving (Int -> JumpInstr -> String -> String
[JumpInstr] -> String -> String
JumpInstr -> String
(Int -> JumpInstr -> String -> String)
-> (JumpInstr -> String)
-> ([JumpInstr] -> String -> String)
-> Show JumpInstr
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> JumpInstr -> String -> String
showsPrec :: Int -> JumpInstr -> String -> String
$cshow :: JumpInstr -> String
show :: JumpInstr -> String
$cshowList :: [JumpInstr] -> String -> String
showList :: [JumpInstr] -> String -> String
Show, JumpInstr -> JumpInstr -> Bool
(JumpInstr -> JumpInstr -> Bool)
-> (JumpInstr -> JumpInstr -> Bool) -> Eq JumpInstr
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: JumpInstr -> JumpInstr -> Bool
== :: JumpInstr -> JumpInstr -> Bool
$c/= :: JumpInstr -> JumpInstr -> Bool
/= :: JumpInstr -> JumpInstr -> Bool
Eq)

data LoadType
  = LSubWord SubWordType
  | LBase BaseType
  deriving (Int -> LoadType -> String -> String
[LoadType] -> String -> String
LoadType -> String
(Int -> LoadType -> String -> String)
-> (LoadType -> String)
-> ([LoadType] -> String -> String)
-> Show LoadType
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> LoadType -> String -> String
showsPrec :: Int -> LoadType -> String -> String
$cshow :: LoadType -> String
show :: LoadType -> String
$cshowList :: [LoadType] -> String -> String
showList :: [LoadType] -> String -> String
Show, LoadType -> LoadType -> Bool
(LoadType -> LoadType -> Bool)
-> (LoadType -> LoadType -> Bool) -> Eq LoadType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: LoadType -> LoadType -> Bool
== :: LoadType -> LoadType -> Bool
$c/= :: LoadType -> LoadType -> Bool
/= :: LoadType -> LoadType -> Bool
Eq)

-- TODO: Could/Should define this on ExtType instead.
loadByteSize :: LoadType -> Word64
loadByteSize :: LoadType -> Word64
loadByteSize (LSubWord SubWordType
UnsignedByte) = Word64
1
loadByteSize (LSubWord SubWordType
SignedByte) = Word64
1
loadByteSize (LSubWord SubWordType
SignedHalf) = Word64
2
loadByteSize (LSubWord SubWordType
UnsignedHalf) = Word64
2
loadByteSize (LBase BaseType
Word) = Word64
4
loadByteSize (LBase BaseType
Long) = Word64
8
loadByteSize (LBase BaseType
Single) = Word64
4
loadByteSize (LBase BaseType
Double) = Word64
8

data ExtArg
  = ExtSingle
  | ExtSubWord SubWordType
  | ExtSignedWord
  | ExtUnsignedWord
  deriving (Int -> ExtArg -> String -> String
[ExtArg] -> String -> String
ExtArg -> String
(Int -> ExtArg -> String -> String)
-> (ExtArg -> String)
-> ([ExtArg] -> String -> String)
-> Show ExtArg
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> ExtArg -> String -> String
showsPrec :: Int -> ExtArg -> String -> String
$cshow :: ExtArg -> String
show :: ExtArg -> String
$cshowList :: [ExtArg] -> String -> String
showList :: [ExtArg] -> String -> String
Show, ExtArg -> ExtArg -> Bool
(ExtArg -> ExtArg -> Bool)
-> (ExtArg -> ExtArg -> Bool) -> Eq ExtArg
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ExtArg -> ExtArg -> Bool
== :: ExtArg -> ExtArg -> Bool
$c/= :: ExtArg -> ExtArg -> Bool
/= :: ExtArg -> ExtArg -> Bool
Eq)

toExtType :: ExtArg -> (Bool, ExtType)
toExtType :: ExtArg -> (Bool, ExtType)
toExtType (ExtSubWord SubWordType
SignedByte) = (Bool
True, ExtType
Byte)
toExtType (ExtSubWord SubWordType
UnsignedByte) = (Bool
False, ExtType
Byte)
toExtType (ExtSubWord SubWordType
SignedHalf) = (Bool
True, ExtType
HalfWord)
toExtType (ExtSubWord SubWordType
UnsignedHalf) = (Bool
False, ExtType
HalfWord)
toExtType ExtArg
ExtSignedWord = (Bool
True, BaseType -> ExtType
Base BaseType
Word)
toExtType ExtArg
ExtUnsignedWord = (Bool
False, BaseType -> ExtType
Base BaseType
Word)
toExtType ExtArg
ExtSingle = (Bool
True, BaseType -> ExtType
Base BaseType
Single)

data FloatArg = FDouble | FSingle
  deriving (Int -> FloatArg -> String -> String
[FloatArg] -> String -> String
FloatArg -> String
(Int -> FloatArg -> String -> String)
-> (FloatArg -> String)
-> ([FloatArg] -> String -> String)
-> Show FloatArg
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> FloatArg -> String -> String
showsPrec :: Int -> FloatArg -> String -> String
$cshow :: FloatArg -> String
show :: FloatArg -> String
$cshowList :: [FloatArg] -> String -> String
showList :: [FloatArg] -> String -> String
Show, FloatArg -> FloatArg -> Bool
(FloatArg -> FloatArg -> Bool)
-> (FloatArg -> FloatArg -> Bool) -> Eq FloatArg
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FloatArg -> FloatArg -> Bool
== :: FloatArg -> FloatArg -> Bool
$c/= :: FloatArg -> FloatArg -> Bool
/= :: FloatArg -> FloatArg -> Bool
Eq)

f2BaseType :: FloatArg -> BaseType
f2BaseType :: FloatArg -> BaseType
f2BaseType FloatArg
FSingle = BaseType
Single
f2BaseType FloatArg
FDouble = BaseType
Double

data IntArg = IWord | ILong
  deriving (Int -> IntArg -> String -> String
[IntArg] -> String -> String
IntArg -> String
(Int -> IntArg -> String -> String)
-> (IntArg -> String)
-> ([IntArg] -> String -> String)
-> Show IntArg
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> IntArg -> String -> String
showsPrec :: Int -> IntArg -> String -> String
$cshow :: IntArg -> String
show :: IntArg -> String
$cshowList :: [IntArg] -> String -> String
showList :: [IntArg] -> String -> String
Show, IntArg -> IntArg -> Bool
(IntArg -> IntArg -> Bool)
-> (IntArg -> IntArg -> Bool) -> Eq IntArg
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: IntArg -> IntArg -> Bool
== :: IntArg -> IntArg -> Bool
$c/= :: IntArg -> IntArg -> Bool
/= :: IntArg -> IntArg -> Bool
Eq)

i2BaseType :: IntArg -> BaseType
i2BaseType :: IntArg -> BaseType
i2BaseType IntArg
IWord = BaseType
Word
i2BaseType IntArg
ILong = BaseType
Long

-- TODO: Distinict types for floating point comparison?
data IntCmpOp
  = IEq
  | INe
  | ISle
  | ISlt
  | ISge
  | ISgt
  | IUle
  | IUlt
  | IUge
  | IUgt
  deriving (Int -> IntCmpOp -> String -> String
[IntCmpOp] -> String -> String
IntCmpOp -> String
(Int -> IntCmpOp -> String -> String)
-> (IntCmpOp -> String)
-> ([IntCmpOp] -> String -> String)
-> Show IntCmpOp
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> IntCmpOp -> String -> String
showsPrec :: Int -> IntCmpOp -> String -> String
$cshow :: IntCmpOp -> String
show :: IntCmpOp -> String
$cshowList :: [IntCmpOp] -> String -> String
showList :: [IntCmpOp] -> String -> String
Show, IntCmpOp -> IntCmpOp -> Bool
(IntCmpOp -> IntCmpOp -> Bool)
-> (IntCmpOp -> IntCmpOp -> Bool) -> Eq IntCmpOp
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: IntCmpOp -> IntCmpOp -> Bool
== :: IntCmpOp -> IntCmpOp -> Bool
$c/= :: IntCmpOp -> IntCmpOp -> Bool
/= :: IntCmpOp -> IntCmpOp -> Bool
Eq)

data FloatCmpOp
  = FEq
  | FNe
  | FLe
  | FLt
  | FGe
  | FGt
  | FOrd
  | FUnord
  deriving (Int -> FloatCmpOp -> String -> String
[FloatCmpOp] -> String -> String
FloatCmpOp -> String
(Int -> FloatCmpOp -> String -> String)
-> (FloatCmpOp -> String)
-> ([FloatCmpOp] -> String -> String)
-> Show FloatCmpOp
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> FloatCmpOp -> String -> String
showsPrec :: Int -> FloatCmpOp -> String -> String
$cshow :: FloatCmpOp -> String
show :: FloatCmpOp -> String
$cshowList :: [FloatCmpOp] -> String -> String
showList :: [FloatCmpOp] -> String -> String
Show, FloatCmpOp -> FloatCmpOp -> Bool
(FloatCmpOp -> FloatCmpOp -> Bool)
-> (FloatCmpOp -> FloatCmpOp -> Bool) -> Eq FloatCmpOp
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FloatCmpOp -> FloatCmpOp -> Bool
== :: FloatCmpOp -> FloatCmpOp -> Bool
$c/= :: FloatCmpOp -> FloatCmpOp -> Bool
/= :: FloatCmpOp -> FloatCmpOp -> Bool
Eq)

data Instr
  = Add Value Value
  | Sub Value Value
  | Div Value Value
  | Mul Value Value
  | Neg Value
  | URem Value Value
  | Rem Value Value
  | UDiv Value Value
  | Or Value Value
  | Xor Value Value
  | And Value Value
  | Sar Value Value
  | Shr Value Value
  | Shl Value Value
  | Alloc AllocSize Value
  | Load LoadType Value
  | CompareInt IntArg IntCmpOp Value Value
  | CompareFloat FloatArg FloatCmpOp Value Value
  | Ext ExtArg Value
  | FloatToInt FloatArg Bool Value
  | IntToFloat IntArg Bool Value
  | TruncDouble Value
  | Cast Value
  | Copy Value
  | VAArg Value
  deriving (Int -> Instr -> String -> String
[Instr] -> String -> String
Instr -> String
(Int -> Instr -> String -> String)
-> (Instr -> String) -> ([Instr] -> String -> String) -> Show Instr
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> Instr -> String -> String
showsPrec :: Int -> Instr -> String -> String
$cshow :: Instr -> String
show :: Instr -> String
$cshowList :: [Instr] -> String -> String
showList :: [Instr] -> String -> String
Show, Instr -> Instr -> Bool
(Instr -> Instr -> Bool) -> (Instr -> Instr -> Bool) -> Eq Instr
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Instr -> Instr -> Bool
== :: Instr -> Instr -> Bool
$c/= :: Instr -> Instr -> Bool
/= :: Instr -> Instr -> Bool
Eq)

data VolatileInstr
  = Store ExtType Value Value
  | VAStart Value
  | Blit Value Value Word64
  | DBGLoc Word64 Word64 (Maybe Word64)
  deriving (Int -> VolatileInstr -> String -> String
[VolatileInstr] -> String -> String
VolatileInstr -> String
(Int -> VolatileInstr -> String -> String)
-> (VolatileInstr -> String)
-> ([VolatileInstr] -> String -> String)
-> Show VolatileInstr
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> VolatileInstr -> String -> String
showsPrec :: Int -> VolatileInstr -> String -> String
$cshow :: VolatileInstr -> String
show :: VolatileInstr -> String
$cshowList :: [VolatileInstr] -> String -> String
showList :: [VolatileInstr] -> String -> String
Show, VolatileInstr -> VolatileInstr -> Bool
(VolatileInstr -> VolatileInstr -> Bool)
-> (VolatileInstr -> VolatileInstr -> Bool) -> Eq VolatileInstr
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: VolatileInstr -> VolatileInstr -> Bool
== :: VolatileInstr -> VolatileInstr -> Bool
$c/= :: VolatileInstr -> VolatileInstr -> Bool
/= :: VolatileInstr -> VolatileInstr -> Bool
Eq)

data Statement
  = Assign LocalIdent BaseType Instr
  | Call (Maybe (LocalIdent, Abity)) Value [FuncArg]
  | Volatile VolatileInstr
  deriving (Int -> Statement -> String -> String
[Statement] -> String -> String
Statement -> String
(Int -> Statement -> String -> String)
-> (Statement -> String)
-> ([Statement] -> String -> String)
-> Show Statement
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> Statement -> String -> String
showsPrec :: Int -> Statement -> String -> String
$cshow :: Statement -> String
show :: Statement -> String
$cshowList :: [Statement] -> String -> String
showList :: [Statement] -> String -> String
Show, Statement -> Statement -> Bool
(Statement -> Statement -> Bool)
-> (Statement -> Statement -> Bool) -> Eq Statement
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Statement -> Statement -> Bool
== :: Statement -> Statement -> Bool
$c/= :: Statement -> Statement -> Bool
/= :: Statement -> Statement -> Bool
Eq)

data Phi
  = Phi
  { Phi -> LocalIdent
pName :: LocalIdent,
    Phi -> BaseType
pType :: BaseType,
    Phi -> Map BlockIdent Value
pLabels :: Map BlockIdent Value
  }
  deriving (Int -> Phi -> String -> String
[Phi] -> String -> String
Phi -> String
(Int -> Phi -> String -> String)
-> (Phi -> String) -> ([Phi] -> String -> String) -> Show Phi
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> Phi -> String -> String
showsPrec :: Int -> Phi -> String -> String
$cshow :: Phi -> String
show :: Phi -> String
$cshowList :: [Phi] -> String -> String
showList :: [Phi] -> String -> String
Show, Phi -> Phi -> Bool
(Phi -> Phi -> Bool) -> (Phi -> Phi -> Bool) -> Eq Phi
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Phi -> Phi -> Bool
== :: Phi -> Phi -> Bool
$c/= :: Phi -> Phi -> Bool
/= :: Phi -> Phi -> Bool
Eq)

data Block
  = Block
  { Block -> BlockIdent
label :: BlockIdent, -- TODO: Consider removing this (part of the Map)
    Block -> [Phi]
phi :: [Phi],
    Block -> [Statement]
stmt :: [Statement],
    Block -> JumpInstr
term :: JumpInstr
  }
  deriving (Int -> Block -> String -> String
[Block] -> String -> String
Block -> String
(Int -> Block -> String -> String)
-> (Block -> String) -> ([Block] -> String -> String) -> Show Block
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> Block -> String -> String
showsPrec :: Int -> Block -> String -> String
$cshow :: Block -> String
show :: Block -> String
$cshowList :: [Block] -> String -> String
showList :: [Block] -> String -> String
Show, Block -> Block -> Bool
(Block -> Block -> Bool) -> (Block -> Block -> Bool) -> Eq Block
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Block -> Block -> Bool
== :: Block -> Block -> Bool
$c/= :: Block -> Block -> Bool
/= :: Block -> Block -> Bool
Eq)