{-# LANGUAGE CPP                   #-}
{-# LANGUAGE DataKinds             #-}
{-# LANGUAGE FlexibleContexts      #-}
{-# LANGUAGE GADTs                 #-}
{-# LANGUAGE LambdaCase            #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes            #-}
{-# LANGUAGE TemplateHaskell       #-}
{-# LANGUAGE TypeApplications      #-}
{-# LANGUAGE TypeOperators         #-}
{-# LANGUAGE ViewPatterns          #-}
{-# OPTIONS_HADDOCK hide #-}
-- |
-- Module      : LLVM.AST.Type.Instruction
-- Copyright   : [2015..2020] The Accelerate Team
-- License     : BSD3
--
-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>
-- Stability   : experimental
-- Portability : non-portable (GHC extensions)
--

module LLVM.AST.Type.Instruction
  where

import LLVM.AST.Type.Constant
import LLVM.AST.Type.Downcast
import LLVM.AST.Type.Function
import LLVM.AST.Type.InlineAssembly
import LLVM.AST.Type.Name
import LLVM.AST.Type.Operand
import LLVM.AST.Type.Representation

import LLVM.AST.Type.Instruction.Atomic                   ( Atomicity, MemoryOrdering )
import LLVM.AST.Type.Instruction.Compare                  ( Ordering(..) )
import LLVM.AST.Type.Instruction.RMW                      ( RMWOperation )
import LLVM.AST.Type.Instruction.Volatile                 ( Volatility )

import qualified LLVM.AST.Constant                        as LLVM ( Constant(GlobalReference, Int) )
import qualified LLVM.AST.AddrSpace                       as LLVM
import qualified LLVM.AST.CallingConvention               as LLVM
import qualified LLVM.AST.FloatingPointPredicate          as FP
import qualified LLVM.AST.Instruction                     as LLVM
import qualified LLVM.AST.IntegerPredicate                as IP
import qualified LLVM.AST.Operand                         as LLVM ( Operand(..), CallableOperand )
import qualified LLVM.AST.ParameterAttribute              as LLVM ( ParameterAttribute )
import qualified LLVM.AST.Type                            as LLVM ( Type(..) )

import Data.Array.Accelerate.AST                          ( PrimBool )
import Data.Array.Accelerate.AST.Idx
import Data.Array.Accelerate.Error
import Data.Array.Accelerate.Representation.Type
import Data.Primitive.Vec

import Prelude                                            hiding ( Ordering(..), quot, rem, div, isNaN, tail )


-- | Non-terminating instructions
--
--  * <http://llvm.org/docs/LangRef.html#binary-operations>
--
--  * <http://llvm.org/docs/LangRef.html#bitwise-binary-operations>
--
--  * <http://llvm.org/docs/LangRef.html#vector-operations>
--
--  * <http://llvm.org/docs/LangRef.html#aggregate-operations>
--
--  * <http://llvm.org/docs/LangRef.html#memory-access-and-addressing-operations>
--
--  * <http://llvm.org/docs/LangRef.html#other-operations>
--
data Instruction a where
  -- Binary Operations
  -- -----------------

  -- <http://llvm.org/docs/LangRef.html#add-instruction>
  -- <http://llvm.org/docs/LangRef.html#fadd-instruction>
  --
  Add             :: NumType a
                  -> Operand a
                  -> Operand a
                  -> Instruction a

  -- <http://llvm.org/docs/LangRef.html#sub-instruction>
  -- <http://llvm.org/docs/LangRef.html#fsub-instruction>
  --
  Sub             :: NumType a
                  -> Operand a
                  -> Operand a
                  -> Instruction a

  -- <http://llvm.org/docs/LangRef.html#mul-instruction>
  -- <http://llvm.org/docs/LangRef.html#fmul-instruction>
  --
  Mul             :: NumType a
                  -> Operand a
                  -> Operand a
                  -> Instruction a

  -- <http://llvm.org/docs/LangRef.html#udiv-instruction>
  -- <http://llvm.org/docs/LangRef.html#sdiv-instruction>
  --
  Quot            :: IntegralType a
                  -> Operand a
                  -> Operand a
                  -> Instruction a

  -- <http://llvm.org/docs/LangRef.html#urem-instruction>
  -- <http://llvm.org/docs/LangRef.html#srem-instruction>
  --
  Rem             :: IntegralType a
                  -> Operand a
                  -> Operand a
                  -> Instruction a

  -- <http://llvm.org/docs/LangRef.html#fdiv-instruction>
  --
  Div             :: FloatingType a
                  -> Operand a
                  -> Operand a
                  -> Instruction a

  -- <http://llvm.org/docs/LangRef.html#shl-instruction>
  --
  ShiftL          :: IntegralType a
                  -> Operand a
                  -> Operand a
                  -> Instruction a

  -- <http://llvm.org/docs/LangRef.html#lshr-instruction>
  --
  ShiftRL         :: IntegralType a
                  -> Operand a
                  -> Operand a
                  -> Instruction a

  -- <http://llvm.org/docs/LangRef.html#ashr-instruction>
  --
  ShiftRA         :: IntegralType a
                  -> Operand a
                  -> Operand a
                  -> Instruction a

  -- Bitwise Binary Operations
  -- -------------------------

  -- <http://llvm.org/docs/LangRef.html#and-instruction>
  --
  BAnd            :: IntegralType a
                  -> Operand a
                  -> Operand a
                  -> Instruction a

  LAnd            :: Operand Bool
                  -> Operand Bool
                  -> Instruction Bool

  -- <http://llvm.org/docs/LangRef.html#or-instruction>
  --
  BOr             :: IntegralType a
                  -> Operand a
                  -> Operand a
                  -> Instruction a

  LOr             :: Operand Bool
                  -> Operand Bool
                  -> Instruction Bool

  -- <http://llvm.org/docs/LangRef.html#xor-instruction>
  --
  BXor            :: IntegralType a
                  -> Operand a
                  -> Operand a
                  -> Instruction a

  LNot            :: Operand Bool
                  -> Instruction Bool

  -- Vector Operations
  -- -----------------

  -- <http://llvm.org/docs/LangRef.html#extractelement-instruction>
  --
  ExtractElement  :: Int32  -- TupleIdx (ProdRepr (Vec n a)) a
                  -> Operand (Vec n a)
                  -> Instruction a

  -- <http://llvm.org/docs/LangRef.html#insertelement-instruction>
  --
  InsertElement   :: Int32  -- TupleIdx (ProdRepr (Vec n a)) a
                  -> Operand (Vec n a)
                  -> Operand a
                  -> Instruction (Vec n a)

  -- ShuffleVector

  -- Aggregate Operations
  -- --------------------

  -- <http://llvm.org/docs/LangRef.html#extractvalue-instruction>
  -- ExtractValue is currently restricted to pairs, we might want
  -- to allow larger structures. It is currently however only used
  -- for CmpXchg, which returns a pair so we don't need this for
  -- other structures.
  --
  ExtractValue    :: ScalarType t
                  -> PairIdx tup t
                  -> Operand tup
                  -> Instruction t

  -- <http://llvm.org/docs/LangRef.html#insertvalue-instruction>
  -- InsertValue

  -- Memory Access and Addressing Operations
  -- ---------------------------------------

  -- <http://llvm.org/docs/LangRef.html#alloca-instruction>
  -- Alloca

  -- <http://llvm.org/docs/LangRef.html#load-instruction>
  --
  Load            :: ScalarType a
                  -> Volatility
                  -> Operand (Ptr a)
                  -> Instruction a

  -- <http://llvm.org/docs/LangRef.html#store-instruction>
  --
  Store           :: Volatility
                  -> Operand (Ptr a)
                  -> Operand a
                  -> Instruction ()

  -- <http://llvm.org/docs/LangRef.html#getelementptr-instruction>
  --
  GetElementPtr   :: Operand (Ptr a)
                  -> [Operand i]
                  -> Instruction (Ptr a)

  -- <http://llvm.org/docs/LangRef.html#i-fence>
  --
  Fence           :: Atomicity
                  -> Instruction ()

  -- <http://llvm.org/docs/LangRef.html#cmpxchg-instruction>
  --
  CmpXchg         :: IntegralType a
                  -> Volatility
                  -> Operand (Ptr a)
                  -> Operand a                  -- expected value
                  -> Operand a                  -- replacement value
                  -> Atomicity                  -- on success
                  -> MemoryOrdering             -- on failure (see docs for restrictions)
                  -> Instruction (a, PrimBool)  -- should be (a, Bool)

  -- <http://llvm.org/docs/LangRef.html#atomicrmw-instruction>
  --
  AtomicRMW       :: NumType a
                  -> Volatility
                  -> RMWOperation
                  -> Operand (Ptr a)
                  -> Operand a
                  -> Atomicity
                  -> Instruction a

  -- <http://llvm.org/docs/LangRef.html#trunc-to-instruction>
  --
  Trunc           :: BoundedType a        -- precondition: BitSize a > BitSize b
                  -> BoundedType b
                  -> Operand a
                  -> Instruction b

  IntToBool       :: IntegralType a
                  -> Operand a
                  -> Instruction Bool

  -- <http://llvm.org/docs/LangRef.html#fptrunc-to-instruction>
  --
  FTrunc          :: FloatingType a       -- precondition: BitSize a > BitSize b
                  -> FloatingType b
                  -> Operand a
                  -> Instruction b

  -- <http://llvm.org/docs/LangRef.html#zext-to-instruction>
  -- <http://llvm.org/docs/LangRef.html#sext-to-instruction>
  --
  Ext             :: BoundedType a        -- precondition: BitSize a < BitSize b
                  -> BoundedType b
                  -> Operand a
                  -> Instruction b

  BoolToInt       :: IntegralType a
                  -> Operand Bool
                  -> Instruction a

  -- <http://llvm.org/docs/LangRef.html#fpext-to-instruction>
  --
  FExt            :: FloatingType a       -- precondition: BitSize a < BitSize b
                  -> FloatingType b
                  -> Operand a
                  -> Instruction b

  BoolToFP        :: FloatingType a
                  -> Operand Bool
                  -> Instruction a

  -- <http://llvm.org/docs/LangRef.html#fptoui-to-instruction>
  -- <http://llvm.org/docs/LangRef.html#fptosi-to-instruction>
  --
  FPToInt         :: FloatingType a
                  -> IntegralType b
                  -> Operand a
                  -> Instruction b

  -- <http://llvm.org/docs/LangRef.html#uitofp-to-instruction>
  -- <http://llvm.org/docs/LangRef.html#sitofp-to-instruction>
  --
  IntToFP         :: IntegralType a
                  -> FloatingType b
                  -> Operand a
                  -> Instruction b

  -- <http://llvm.org/docs/LangRef.html#bitcast-to-instruction>
  --
  BitCast         :: ScalarType b         -- precondition: BitSize a == BitSize b
                  -> Operand a
                  -> Instruction b

  PtrCast         :: PrimType (Ptr b)     -- precondition: same address space
                  -> Operand (Ptr a)
                  -> Instruction (Ptr b)

  -- PtrToInt
  -- IntToPtr
  -- AddrSpaceCast

  -- Other Operations
  -- ----------------

  -- <http://llvm.org/docs/LangRef.html#icmp-instruction>
  -- <http://llvm.org/docs/LangRef.html#fcmp-instruction>
  --
  -- We treat non-scalar types as signed/unsigned integer values.
  --
  Cmp             :: SingleType a
                  -> Ordering
                  -> Operand a
                  -> Operand a
                  -> Instruction Bool

  IsNaN           :: FloatingType a
                  -> Operand a
                  -> Instruction Bool

  -- <http://llvm.org/docs/LangRef.html#phi-instruction>
  --
  Phi             :: PrimType a
                  -> [(Operand a, Label)]
                  -> Instruction a

  -- <http://llvm.org/docs/LangRef.html#call-instruction>
  --
  Call            :: Function (Either InlineAssembly Label) args t
                  -> [Either GroupID FunctionAttribute]
                  -> Instruction t

  -- <http://llvm.org/docs/LangRef.html#select-instruction>
  --
  Select          :: SingleType a
                  -> Operand Bool
                  -> Operand a
                  -> Operand a
                  -> Instruction a

  -- VAArg
  -- LandingPad


-- | Instances of instructions may be given a name, allowing their results to be
-- referenced as Operands. Instructions returning void (e.g. function calls)
-- don't need names.
--
data Named ins a where
  (:=) :: Name a -> ins a -> Named ins a
  Do   :: ins ()          -> Named ins ()


-- | Convert to llvm-hs
--
instance Downcast (Instruction a) LLVM.Instruction where
  downcast :: Instruction a -> Instruction
downcast = \case
    Add NumType a
t Operand a
x Operand a
y             -> NumType a -> Operand -> Operand -> Instruction
forall a. NumType a -> Operand -> Operand -> Instruction
add NumType a
t (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
y)
    Sub NumType a
t Operand a
x Operand a
y             -> NumType a -> Operand -> Operand -> Instruction
forall a. NumType a -> Operand -> Operand -> Instruction
sub NumType a
t (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
y)
    Mul NumType a
t Operand a
x Operand a
y             -> NumType a -> Operand -> Operand -> Instruction
forall a. NumType a -> Operand -> Operand -> Instruction
mul NumType a
t (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
y)
    Quot IntegralType a
t Operand a
x Operand a
y            -> IntegralType a -> Operand -> Operand -> Instruction
forall a. IntegralType a -> Operand -> Operand -> Instruction
quot IntegralType a
t (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
y)
    Rem IntegralType a
t Operand a
x Operand a
y             -> IntegralType a -> Operand -> Operand -> Instruction
forall a. IntegralType a -> Operand -> Operand -> Instruction
rem IntegralType a
t (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
y)
    Div FloatingType a
_ Operand a
x Operand a
y             -> FastMathFlags
-> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.FDiv FastMathFlags
fmf (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
y) InstructionMetadata
md
    ShiftL IntegralType a
_ Operand a
x Operand a
i          -> Bool
-> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.Shl Bool
nsw Bool
nuw (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
i) InstructionMetadata
md
    ShiftRL IntegralType a
_ Operand a
x Operand a
i         -> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.LShr Bool
exact (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
i) InstructionMetadata
md
    ShiftRA IntegralType a
_ Operand a
x Operand a
i         -> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.AShr Bool
exact (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
i) InstructionMetadata
md
    BAnd IntegralType a
_ Operand a
x Operand a
y            -> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.And (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
y) InstructionMetadata
md
    LAnd Operand Bool
x Operand Bool
y              -> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.And (Operand Bool -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Bool
x) (Operand Bool -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Bool
y) InstructionMetadata
md
    BOr IntegralType a
_ Operand a
x Operand a
y             -> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.Or (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
y) InstructionMetadata
md
    LOr Operand Bool
x Operand Bool
y               -> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.Or (Operand Bool -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Bool
x) (Operand Bool -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Bool
y) InstructionMetadata
md
    BXor IntegralType a
_ Operand a
x Operand a
y            -> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.Xor (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
y) InstructionMetadata
md
    LNot Operand Bool
x                -> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.Xor (Operand Bool -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Bool
x) (Constant -> Operand
LLVM.ConstantOperand (Word32 -> Integer -> Constant
LLVM.Int Word32
1 Integer
1)) InstructionMetadata
md
    InsertElement Int32
i Operand (Vec n a)
v Operand a
x   -> Operand -> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.InsertElement (Operand (Vec n a) -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand (Vec n a)
v) (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (Int32 -> Operand
forall a. IsScalar a => a -> Operand
constant Int32
i) InstructionMetadata
md
    ExtractElement Int32
i Operand (Vec n a)
v    -> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.ExtractElement (Operand (Vec n a) -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand (Vec n a)
v) (Int32 -> Operand
forall a. IsScalar a => a -> Operand
constant Int32
i) InstructionMetadata
md
    ExtractValue ScalarType a
_ PairIdx tup a
i Operand tup
s    -> PairIdx tup a -> Operand -> Instruction
forall s t. PairIdx s t -> Operand -> Instruction
extractStruct PairIdx tup a
i (Operand tup -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand tup
s)
    Load ScalarType a
_ Volatility
v Operand (Ptr a)
p            -> Bool
-> Operand
-> Maybe Atomicity
-> Word32
-> InstructionMetadata
-> Instruction
LLVM.Load (Volatility -> Bool
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Volatility
v) (Operand (Ptr a) -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand (Ptr a)
p) Maybe Atomicity
atomicity Word32
alignment InstructionMetadata
md
    Store Volatility
v Operand (Ptr a)
p Operand a
x           -> Bool
-> Operand
-> Operand
-> Maybe Atomicity
-> Word32
-> InstructionMetadata
-> Instruction
LLVM.Store (Volatility -> Bool
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Volatility
v) (Operand (Ptr a) -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand (Ptr a)
p) (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) Maybe Atomicity
atomicity Word32
alignment InstructionMetadata
md
    GetElementPtr Operand (Ptr a)
n [Operand i]
i     -> Bool -> Operand -> [Operand] -> InstructionMetadata -> Instruction
LLVM.GetElementPtr Bool
inbounds (Operand (Ptr a) -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand (Ptr a)
n) ([Operand i] -> [Operand]
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast [Operand i]
i) InstructionMetadata
md
    Fence Atomicity
a               -> Atomicity -> InstructionMetadata -> Instruction
LLVM.Fence (Atomicity -> Atomicity
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Atomicity
a) InstructionMetadata
md
    CmpXchg IntegralType a
_ Volatility
v Operand (Ptr a)
p Operand a
x Operand a
y Atomicity
a MemoryOrdering
m -> Bool
-> Operand
-> Operand
-> Operand
-> Atomicity
-> MemoryOrdering
-> InstructionMetadata
-> Instruction
LLVM.CmpXchg (Volatility -> Bool
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Volatility
v) (Operand (Ptr a) -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand (Ptr a)
p) (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
y) (Atomicity -> Atomicity
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Atomicity
a) (MemoryOrdering -> MemoryOrdering
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast MemoryOrdering
m) InstructionMetadata
md
    AtomicRMW NumType a
t Volatility
v RMWOperation
f Operand (Ptr a)
p Operand a
x Atomicity
a -> Bool
-> RMWOperation
-> Operand
-> Operand
-> Atomicity
-> InstructionMetadata
-> Instruction
LLVM.AtomicRMW (Volatility -> Bool
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Volatility
v) ((NumType a, RMWOperation) -> RMWOperation
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast (NumType a
t,RMWOperation
f)) (Operand (Ptr a) -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand (Ptr a)
p) (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (Atomicity -> Atomicity
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Atomicity
a) InstructionMetadata
md
    Trunc BoundedType a
_ BoundedType a
t Operand a
x           -> Operand -> Type -> InstructionMetadata -> Instruction
LLVM.Trunc (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (BoundedType a -> Type
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast BoundedType a
t) InstructionMetadata
md
    IntToBool IntegralType a
_ Operand a
x         -> Operand -> Type -> InstructionMetadata -> Instruction
LLVM.Trunc (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (Word32 -> Type
LLVM.IntegerType Word32
1) InstructionMetadata
md
    FTrunc FloatingType a
_ FloatingType a
t Operand a
x          -> Operand -> Type -> InstructionMetadata -> Instruction
LLVM.FPTrunc (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (FloatingType a -> Type
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast FloatingType a
t) InstructionMetadata
md
    Ext BoundedType a
a BoundedType a
b Operand a
x             -> BoundedType a -> BoundedType a -> Operand -> Instruction
forall a b.
BoundedType a -> BoundedType b -> Operand -> Instruction
ext BoundedType a
a BoundedType a
b (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x)
    BoolToInt IntegralType a
a Operand Bool
x         -> Operand -> Type -> InstructionMetadata -> Instruction
LLVM.ZExt (Operand Bool -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Bool
x) (IntegralType a -> Type
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast IntegralType a
a) InstructionMetadata
md
    BoolToFP FloatingType a
x Operand Bool
a          -> Operand -> Type -> InstructionMetadata -> Instruction
LLVM.UIToFP (Operand Bool -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Bool
a) (FloatingType a -> Type
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast FloatingType a
x) InstructionMetadata
md
    FExt FloatingType a
_ FloatingType a
t Operand a
x            -> Operand -> Type -> InstructionMetadata -> Instruction
LLVM.FPExt (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (FloatingType a -> Type
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast FloatingType a
t) InstructionMetadata
md
    FPToInt FloatingType a
_ IntegralType a
b Operand a
x         -> IntegralType a -> Operand -> Instruction
forall b. IntegralType b -> Operand -> Instruction
float2int IntegralType a
b (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x)
    IntToFP IntegralType a
a FloatingType a
b Operand a
x         -> IntegralType a -> FloatingType a -> Operand -> Instruction
forall a b.
IntegralType a -> FloatingType b -> Operand -> Instruction
int2float IntegralType a
a FloatingType a
b (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x)
    BitCast ScalarType a
t Operand a
x           -> Operand -> Type -> InstructionMetadata -> Instruction
LLVM.BitCast (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (ScalarType a -> Type
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast ScalarType a
t) InstructionMetadata
md
    PtrCast PrimType (Ptr b)
t Operand (Ptr a)
x           -> Operand -> Type -> InstructionMetadata -> Instruction
LLVM.BitCast (Operand (Ptr a) -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand (Ptr a)
x) (PrimType (Ptr b) -> Type
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast PrimType (Ptr b)
t) InstructionMetadata
md
    Phi PrimType a
t [(Operand a, Label)]
e               -> Type -> [(Operand, Name)] -> InstructionMetadata -> Instruction
LLVM.Phi (PrimType a -> Type
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast PrimType a
t) ([(Operand a, Label)] -> [(Operand, Name)]
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast [(Operand a, Label)]
e) InstructionMetadata
md
    Select SingleType a
_ Operand Bool
p Operand a
x Operand a
y        -> Operand -> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.Select (Operand Bool -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Bool
p) (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
y) InstructionMetadata
md
    IsNaN FloatingType a
_ Operand a
x             -> Operand -> Instruction
isNaN (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x)
    Cmp SingleType a
t Ordering
p Operand a
x Operand a
y           -> SingleType a -> Ordering -> Operand -> Operand -> Instruction
forall a.
SingleType a -> Ordering -> Operand -> Operand -> Instruction
cmp SingleType a
t Ordering
p (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x) (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
y)
    Call Function (Either InlineAssembly Label) args a
f [Either GroupID FunctionAttribute]
a              -> Function (Either InlineAssembly Label) args a
-> [Either GroupID FunctionAttribute] -> Instruction
forall (args :: [*]) t.
Function (Either InlineAssembly Label) args t
-> [Either GroupID FunctionAttribute] -> Instruction
call Function (Either InlineAssembly Label) args a
f [Either GroupID FunctionAttribute]
a

    where
      nsw :: Bool       -- no signed wrap
      nsw :: Bool
nsw = Bool
False

      nuw :: Bool       -- no unsigned wrap
      nuw :: Bool
nuw = Bool
False

      exact :: Bool     -- does not lose any information
      exact :: Bool
exact = Bool
False

      inbounds :: Bool
      inbounds :: Bool
inbounds = Bool
True

      atomicity :: Maybe LLVM.Atomicity
      atomicity :: Maybe Atomicity
atomicity = Maybe Atomicity
forall a. Maybe a
Nothing

      alignment :: Word32
      alignment :: Word32
alignment = Word32
0

      fmf :: LLVM.FastMathFlags
#if MIN_VERSION_llvm_hs_pure(6,0,0)
      fmf :: FastMathFlags
fmf = FastMathFlags :: Bool
-> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> FastMathFlags
LLVM.FastMathFlags
              { allowReassoc :: Bool
LLVM.allowReassoc    = Bool
True
              , noNaNs :: Bool
LLVM.noNaNs          = Bool
True
              , noInfs :: Bool
LLVM.noInfs          = Bool
True
              , noSignedZeros :: Bool
LLVM.noSignedZeros   = Bool
True
              , allowReciprocal :: Bool
LLVM.allowReciprocal = Bool
True
              , allowContract :: Bool
LLVM.allowContract   = Bool
True
              , approxFunc :: Bool
LLVM.approxFunc      = Bool
True
              }
#else
      fmf = LLVM.UnsafeAlgebra -- allow everything
#endif

      md :: LLVM.InstructionMetadata
      md :: InstructionMetadata
md = []

      constant :: IsScalar a => a -> LLVM.Operand
      constant :: a -> Operand
constant a
x = Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast (Constant a -> Operand a
forall a. Constant a -> Operand a
ConstantOperand (ScalarType a -> a -> Constant a
forall a. ScalarType a -> a -> Constant a
ScalarConstant ScalarType a
forall a. IsScalar a => ScalarType a
scalarType a
x))

      add :: NumType a -> LLVM.Operand -> LLVM.Operand -> LLVM.Instruction
      add :: NumType a -> Operand -> Operand -> Instruction
add IntegralNumType{} Operand
x Operand
y = Bool
-> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.Add Bool
nsw Bool
nuw Operand
x Operand
y InstructionMetadata
md
      add FloatingNumType{} Operand
x Operand
y = FastMathFlags
-> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.FAdd FastMathFlags
fmf    Operand
x Operand
y InstructionMetadata
md

      sub :: NumType a -> LLVM.Operand -> LLVM.Operand -> LLVM.Instruction
      sub :: NumType a -> Operand -> Operand -> Instruction
sub IntegralNumType{} Operand
x Operand
y = Bool
-> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.Sub Bool
nsw Bool
nuw Operand
x Operand
y InstructionMetadata
md
      sub FloatingNumType{} Operand
x Operand
y = FastMathFlags
-> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.FSub FastMathFlags
fmf    Operand
x Operand
y InstructionMetadata
md

      mul :: NumType a -> LLVM.Operand -> LLVM.Operand -> LLVM.Instruction
      mul :: NumType a -> Operand -> Operand -> Instruction
mul IntegralNumType{} Operand
x Operand
y = Bool
-> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.Mul Bool
nsw Bool
nuw Operand
x Operand
y InstructionMetadata
md
      mul FloatingNumType{} Operand
x Operand
y = FastMathFlags
-> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.FMul FastMathFlags
fmf    Operand
x Operand
y InstructionMetadata
md

      quot :: IntegralType a -> LLVM.Operand -> LLVM.Operand -> LLVM.Instruction
      quot :: IntegralType a -> Operand -> Operand -> Instruction
quot IntegralType a
t Operand
x Operand
y
        | IntegralType a -> Bool
forall (dict :: * -> *) a. IsSigned dict => dict a -> Bool
signed IntegralType a
t  = Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.SDiv Bool
exact Operand
x Operand
y InstructionMetadata
md
        | Bool
otherwise = Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.UDiv Bool
exact Operand
x Operand
y InstructionMetadata
md

      rem :: IntegralType a -> LLVM.Operand -> LLVM.Operand -> LLVM.Instruction
      rem :: IntegralType a -> Operand -> Operand -> Instruction
rem IntegralType a
t Operand
x Operand
y
        | IntegralType a -> Bool
forall (dict :: * -> *) a. IsSigned dict => dict a -> Bool
signed IntegralType a
t  = Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.SRem Operand
x Operand
y InstructionMetadata
md
        | Bool
otherwise = Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.URem Operand
x Operand
y InstructionMetadata
md

      extractStruct :: PairIdx s t -> LLVM.Operand -> LLVM.Instruction
      extractStruct :: PairIdx s t -> Operand -> Instruction
extractStruct PairIdx s t
i Operand
s = Operand -> [Word32] -> InstructionMetadata -> Instruction
LLVM.ExtractValue Operand
s [Word32]
ix InstructionMetadata
md
        where
          ix :: [Word32]
ix = case PairIdx s t
i of
            PairIdx s t
PairIdxLeft  -> [Word32
0]
            PairIdx s t
PairIdxRight -> [Word32
1]

      ext :: BoundedType a -> BoundedType b -> LLVM.Operand -> LLVM.Instruction
      ext :: BoundedType a -> BoundedType b -> Operand -> Instruction
ext BoundedType a
a (BoundedType b -> Type
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast -> Type
b) Operand
x
        | BoundedType a -> Bool
forall (dict :: * -> *) a. IsSigned dict => dict a -> Bool
signed BoundedType a
a  = Operand -> Type -> InstructionMetadata -> Instruction
LLVM.SExt Operand
x Type
b InstructionMetadata
md
        | Bool
otherwise = Operand -> Type -> InstructionMetadata -> Instruction
LLVM.ZExt Operand
x Type
b InstructionMetadata
md

      float2int :: IntegralType b -> LLVM.Operand -> LLVM.Instruction
      float2int :: IntegralType b -> Operand -> Instruction
float2int t :: IntegralType b
t@(IntegralType b -> Type
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast -> Type
t') Operand
x
        | IntegralType b -> Bool
forall (dict :: * -> *) a. IsSigned dict => dict a -> Bool
signed IntegralType b
t  = Operand -> Type -> InstructionMetadata -> Instruction
LLVM.FPToSI Operand
x Type
t' InstructionMetadata
md
        | Bool
otherwise = Operand -> Type -> InstructionMetadata -> Instruction
LLVM.FPToUI Operand
x Type
t' InstructionMetadata
md

      int2float :: IntegralType a -> FloatingType b -> LLVM.Operand -> LLVM.Instruction
      int2float :: IntegralType a -> FloatingType b -> Operand -> Instruction
int2float IntegralType a
a (FloatingType b -> Type
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast -> Type
b) Operand
x
        | IntegralType a -> Bool
forall (dict :: * -> *) a. IsSigned dict => dict a -> Bool
signed IntegralType a
a  = Operand -> Type -> InstructionMetadata -> Instruction
LLVM.SIToFP Operand
x Type
b InstructionMetadata
md
        | Bool
otherwise = Operand -> Type -> InstructionMetadata -> Instruction
LLVM.UIToFP Operand
x Type
b InstructionMetadata
md

      isNaN :: LLVM.Operand -> LLVM.Instruction
      isNaN :: Operand -> Instruction
isNaN Operand
x = FloatingPointPredicate
-> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.FCmp FloatingPointPredicate
FP.UNO Operand
x Operand
x InstructionMetadata
md

      cmp :: SingleType a -> Ordering -> LLVM.Operand -> LLVM.Operand -> LLVM.Instruction
      cmp :: SingleType a -> Ordering -> Operand -> Operand -> Instruction
cmp SingleType a
t Ordering
p Operand
x Operand
y =
        case SingleType a
t of
          NumSingleType FloatingNumType{} -> FloatingPointPredicate
-> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.FCmp (Ordering -> FloatingPointPredicate
fp Ordering
p) Operand
x Operand
y InstructionMetadata
md
          SingleType a
_ | SingleType a -> Bool
forall (dict :: * -> *) a. IsSigned dict => dict a -> Bool
signed SingleType a
t                    -> IntegerPredicate
-> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.ICmp (Ordering -> IntegerPredicate
si Ordering
p) Operand
x Operand
y InstructionMetadata
md
            | Bool
otherwise                   -> IntegerPredicate
-> Operand -> Operand -> InstructionMetadata -> Instruction
LLVM.ICmp (Ordering -> IntegerPredicate
ui Ordering
p) Operand
x Operand
y InstructionMetadata
md
        where
          fp :: Ordering -> FP.FloatingPointPredicate
          fp :: Ordering -> FloatingPointPredicate
fp Ordering
EQ = FloatingPointPredicate
FP.OEQ
          fp Ordering
NE = FloatingPointPredicate
FP.ONE
          fp Ordering
LT = FloatingPointPredicate
FP.OLT
          fp Ordering
LE = FloatingPointPredicate
FP.OLE
          fp Ordering
GT = FloatingPointPredicate
FP.OGT
          fp Ordering
GE = FloatingPointPredicate
FP.OGE

          si :: Ordering -> IP.IntegerPredicate
          si :: Ordering -> IntegerPredicate
si Ordering
EQ = IntegerPredicate
IP.EQ
          si Ordering
NE = IntegerPredicate
IP.NE
          si Ordering
LT = IntegerPredicate
IP.SLT
          si Ordering
LE = IntegerPredicate
IP.SLE
          si Ordering
GT = IntegerPredicate
IP.SGT
          si Ordering
GE = IntegerPredicate
IP.SGE

          ui :: Ordering -> IP.IntegerPredicate
          ui :: Ordering -> IntegerPredicate
ui Ordering
EQ = IntegerPredicate
IP.EQ
          ui Ordering
NE = IntegerPredicate
IP.NE
          ui Ordering
LT = IntegerPredicate
IP.ULT
          ui Ordering
LE = IntegerPredicate
IP.ULE
          ui Ordering
GT = IntegerPredicate
IP.UGT
          ui Ordering
GE = IntegerPredicate
IP.UGE

      call :: Function (Either InlineAssembly Label) args t -> [Either GroupID FunctionAttribute] -> LLVM.Instruction
      call :: Function (Either InlineAssembly Label) args t
-> [Either GroupID FunctionAttribute] -> Instruction
call Function (Either InlineAssembly Label) args t
f [Either GroupID FunctionAttribute]
as = Maybe TailCallKind
-> CallingConvention
-> [ParameterAttribute]
-> CallableOperand
-> [(Operand, [ParameterAttribute])]
-> [Either GroupID FunctionAttribute]
-> InstructionMetadata
-> Instruction
LLVM.Call Maybe TailCallKind
tail CallingConvention
LLVM.C [] CallableOperand
target [(Operand, [ParameterAttribute])]
argv ([Either GroupID FunctionAttribute]
-> [Either GroupID FunctionAttribute]
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast [Either GroupID FunctionAttribute]
as) InstructionMetadata
md
        where
          trav :: Function (Either InlineAssembly Label) args t
               -> ( [LLVM.Type]                                 -- argument types
                  , [(LLVM.Operand, [LLVM.ParameterAttribute])] -- argument operands
                  , Maybe LLVM.TailCallKind                     -- calling kind
                  , LLVM.Type                                   -- return type
                  , LLVM.CallableOperand                        -- function name or inline assembly
                  )
          trav :: Function (Either InlineAssembly Label) args t
-> ([Type], [(Operand, [ParameterAttribute])], Maybe TailCallKind,
    Type, CallableOperand)
trav (Body Type t
u Maybe TailCall
k Either InlineAssembly Label
o) =
            case Either InlineAssembly Label
o of
              Left InlineAssembly
asm -> ([], [], Maybe TailCall -> Maybe TailCallKind
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Maybe TailCall
k, Type t -> Type
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Type t
u, InlineAssembly -> CallableOperand
forall a b. a -> Either a b
Left  ((Type, InlineAssembly) -> InlineAssembly
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast (Type -> [Type] -> Bool -> Type
LLVM.FunctionType Type
ret [Type]
argt Bool
False, InlineAssembly
asm)))
              Right Label
n  -> ([], [], Maybe TailCall -> Maybe TailCallKind
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Maybe TailCall
k, Type t -> Type
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Type t
u, Operand -> CallableOperand
forall a b. b -> Either a b
Right (Constant -> Operand
LLVM.ConstantOperand (Type -> Name -> Constant
LLVM.GlobalReference Type
ptr_fun_ty (Label -> Name
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Label
n))))
          trav (Lam PrimType a
t Operand a
x Function (Either InlineAssembly Label) args t
l)  =
            let ([Type]
ts, [(Operand, [ParameterAttribute])]
xs, Maybe TailCallKind
k, Type
r, CallableOperand
n)  = Function (Either InlineAssembly Label) args t
-> ([Type], [(Operand, [ParameterAttribute])], Maybe TailCallKind,
    Type, CallableOperand)
forall (args :: [*]) t.
Function (Either InlineAssembly Label) args t
-> ([Type], [(Operand, [ParameterAttribute])], Maybe TailCallKind,
    Type, CallableOperand)
trav Function (Either InlineAssembly Label) args t
l
            in  (PrimType a -> Type
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast PrimType a
t Type -> [Type] -> [Type]
forall a. a -> [a] -> [a]
: [Type]
ts, (Operand a -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand a
x, []) (Operand, [ParameterAttribute])
-> [(Operand, [ParameterAttribute])]
-> [(Operand, [ParameterAttribute])]
forall a. a -> [a] -> [a]
: [(Operand, [ParameterAttribute])]
xs, Maybe TailCallKind
k, Type
r, CallableOperand
n)

          ([Type]
argt, [(Operand, [ParameterAttribute])]
argv, Maybe TailCallKind
tail, Type
ret, CallableOperand
target) = Function (Either InlineAssembly Label) args t
-> ([Type], [(Operand, [ParameterAttribute])], Maybe TailCallKind,
    Type, CallableOperand)
forall (args :: [*]) t.
Function (Either InlineAssembly Label) args t
-> ([Type], [(Operand, [ParameterAttribute])], Maybe TailCallKind,
    Type, CallableOperand)
trav Function (Either InlineAssembly Label) args t
f
          fun_ty :: Type
fun_ty                          = Type -> [Type] -> Bool -> Type
LLVM.FunctionType Type
ret [Type]
argt Bool
False
          ptr_fun_ty :: Type
ptr_fun_ty                      = Type -> AddrSpace -> Type
LLVM.PointerType Type
fun_ty (Word32 -> AddrSpace
LLVM.AddrSpace Word32
0)


instance Downcast (i a) i' => Downcast (Named i a) (LLVM.Named i') where
  downcast :: Named i a -> Named i'
downcast (Name a
x := i a
op) = Name a -> Name
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Name a
x Name -> i' -> Named i'
forall a. Name -> a -> Named a
LLVM.:= i a -> i'
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast i a
op
  downcast (Do i ()
op)   = i' -> Named i'
forall a. a -> Named a
LLVM.Do (i () -> i'
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast i ()
op)


instance TypeOf Instruction where
  typeOf :: Instruction a -> Type a
typeOf = \case
    Add NumType a
_ Operand a
x Operand a
_             -> Operand a -> Type a
forall (f :: * -> *) a. TypeOf f => f a -> Type a
typeOf Operand a
x
    Sub NumType a
_ Operand a
x Operand a
_             -> Operand a -> Type a
forall (f :: * -> *) a. TypeOf f => f a -> Type a
typeOf Operand a
x
    Mul NumType a
_ Operand a
x Operand a
_             -> Operand a -> Type a
forall (f :: * -> *) a. TypeOf f => f a -> Type a
typeOf Operand a
x
    Quot IntegralType a
_ Operand a
x Operand a
_            -> Operand a -> Type a
forall (f :: * -> *) a. TypeOf f => f a -> Type a
typeOf Operand a
x
    Rem IntegralType a
_ Operand a
x Operand a
_             -> Operand a -> Type a
forall (f :: * -> *) a. TypeOf f => f a -> Type a
typeOf Operand a
x
    Div FloatingType a
_ Operand a
x Operand a
_             -> Operand a -> Type a
forall (f :: * -> *) a. TypeOf f => f a -> Type a
typeOf Operand a
x
    ShiftL IntegralType a
_ Operand a
x Operand a
_          -> Operand a -> Type a
forall (f :: * -> *) a. TypeOf f => f a -> Type a
typeOf Operand a
x
    ShiftRL IntegralType a
_ Operand a
x Operand a
_         -> Operand a -> Type a
forall (f :: * -> *) a. TypeOf f => f a -> Type a
typeOf Operand a
x
    ShiftRA IntegralType a
_ Operand a
x Operand a
_         -> Operand a -> Type a
forall (f :: * -> *) a. TypeOf f => f a -> Type a
typeOf Operand a
x
    BAnd IntegralType a
_ Operand a
x Operand a
_            -> Operand a -> Type a
forall (f :: * -> *) a. TypeOf f => f a -> Type a
typeOf Operand a
x
    BOr IntegralType a
_ Operand a
x Operand a
_             -> Operand a -> Type a
forall (f :: * -> *) a. TypeOf f => f a -> Type a
typeOf Operand a
x
    BXor IntegralType a
_ Operand a
x Operand a
_            -> Operand a -> Type a
forall (f :: * -> *) a. TypeOf f => f a -> Type a
typeOf Operand a
x
    LAnd Operand Bool
x Operand Bool
_              -> Operand Bool -> Type Bool
forall (f :: * -> *) a. TypeOf f => f a -> Type a
typeOf Operand Bool
x
    LOr Operand Bool
x Operand Bool
_               -> Operand Bool -> Type Bool
forall (f :: * -> *) a. TypeOf f => f a -> Type a
typeOf Operand Bool
x
    LNot Operand Bool
x                -> Operand Bool -> Type Bool
forall (f :: * -> *) a. TypeOf f => f a -> Type a
typeOf Operand Bool
x
    ExtractElement Int32
_ Operand (Vec n a)
x    -> Operand (Vec n a) -> Type a
forall (n :: Nat) a. HasCallStack => Operand (Vec n a) -> Type a
typeOfVec Operand (Vec n a)
x
    InsertElement Int32
_ Operand (Vec n a)
x Operand a
_   -> Operand (Vec n a) -> Type (Vec n a)
forall (f :: * -> *) a. TypeOf f => f a -> Type a
typeOf Operand (Vec n a)
x
    ExtractValue ScalarType a
t PairIdx tup a
_ Operand tup
_    -> ScalarType a -> Type a
forall a. ScalarType a -> Type a
scalar ScalarType a
t
    Load ScalarType a
t Volatility
_ Operand (Ptr a)
_            -> ScalarType a -> Type a
forall a. ScalarType a -> Type a
scalar ScalarType a
t
    Store{}               -> Type a
Type ()
VoidType
    GetElementPtr Operand (Ptr a)
x [Operand i]
_     -> Operand (Ptr a) -> Type (Ptr a)
forall (f :: * -> *) a. TypeOf f => f a -> Type a
typeOf Operand (Ptr a)
x
    Fence{}               -> Type a
Type ()
VoidType
    CmpXchg IntegralType a
t Volatility
_ Operand (Ptr a)
_ Operand a
_ Operand a
_ Atomicity
_ MemoryOrdering
_ -> PrimType (a, PrimBool) -> Type (a, PrimBool)
forall a. PrimType a -> Type a
PrimType (PrimType (a, PrimBool) -> Type (a, PrimBool))
-> (TypeR (a, PrimBool) -> PrimType (a, PrimBool))
-> TypeR (a, PrimBool)
-> Type (a, PrimBool)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TypeR (a, PrimBool) -> PrimType (a, PrimBool)
forall a. TypeR a -> PrimType a
StructPrimType (TypeR (a, PrimBool) -> Type (a, PrimBool))
-> TypeR (a, PrimBool) -> Type (a, PrimBool)
forall a b. (a -> b) -> a -> b
$ SingleType a -> ScalarType a
forall a. SingleType a -> ScalarType a
SingleScalarType (NumType a -> SingleType a
forall a. NumType a -> SingleType a
NumSingleType (IntegralType a -> NumType a
forall a. IntegralType a -> NumType a
IntegralNumType IntegralType a
t)) ScalarType a -> ScalarType PrimBool -> TypeR (a, PrimBool)
forall a b. ScalarType a -> ScalarType b -> TypeR (a, b)
`pair` ScalarType PrimBool
forall a. IsScalar a => ScalarType a
scalarType
    AtomicRMW NumType a
_ Volatility
_ RMWOperation
_ Operand (Ptr a)
_ Operand a
x Atomicity
_ -> Operand a -> Type a
forall (f :: * -> *) a. TypeOf f => f a -> Type a
typeOf Operand a
x
    FTrunc FloatingType a
_ FloatingType a
t Operand a
_          -> FloatingType a -> Type a
forall a. FloatingType a -> Type a
floating FloatingType a
t
    FExt FloatingType a
_ FloatingType a
t Operand a
_            -> FloatingType a -> Type a
forall a. FloatingType a -> Type a
floating FloatingType a
t
    Trunc BoundedType a
_ BoundedType a
t Operand a
_           -> BoundedType a -> Type a
forall a. BoundedType a -> Type a
bounded BoundedType a
t
    Ext BoundedType a
_ BoundedType a
t Operand a
_             -> BoundedType a -> Type a
forall a. BoundedType a -> Type a
bounded BoundedType a
t
    FPToInt FloatingType a
_ IntegralType a
t Operand a
_         -> IntegralType a -> Type a
forall a. IntegralType a -> Type a
integral IntegralType a
t
    IntToFP IntegralType a
_ FloatingType a
t Operand a
_         -> FloatingType a -> Type a
forall a. FloatingType a -> Type a
floating FloatingType a
t
    IntToBool IntegralType a
_ Operand a
_         -> Type a
forall a. IsType a => Type a
type'
    BoolToInt IntegralType a
t Operand Bool
_         -> IntegralType a -> Type a
forall a. IntegralType a -> Type a
integral IntegralType a
t
    BoolToFP FloatingType a
t Operand Bool
_          -> FloatingType a -> Type a
forall a. FloatingType a -> Type a
floating FloatingType a
t
    BitCast ScalarType a
t Operand a
_           -> ScalarType a -> Type a
forall a. ScalarType a -> Type a
scalar ScalarType a
t
    PtrCast PrimType (Ptr b)
t Operand (Ptr a)
_           -> PrimType (Ptr b) -> Type (Ptr b)
forall a. PrimType a -> Type a
PrimType PrimType (Ptr b)
t
    Cmp{}                 -> Type a
forall a. IsType a => Type a
type'
    IsNaN{}               -> Type a
forall a. IsType a => Type a
type'
    Phi PrimType a
t [(Operand a, Label)]
_               -> PrimType a -> Type a
forall a. PrimType a -> Type a
PrimType PrimType a
t
    Select SingleType a
_ Operand Bool
_ Operand a
x Operand a
_        -> Operand a -> Type a
forall (f :: * -> *) a. TypeOf f => f a -> Type a
typeOf Operand a
x
    Call Function (Either InlineAssembly Label) args a
f [Either GroupID FunctionAttribute]
_              -> Function (Either InlineAssembly Label) args a -> Type a
forall kind (args :: [*]) a. Function kind args a -> Type a
fun Function (Either InlineAssembly Label) args a
f
    where
      typeOfVec :: HasCallStack => Operand (Vec n a) -> Type a
      typeOfVec :: Operand (Vec n a) -> Type a
typeOfVec Operand (Vec n a)
x
        | PrimType PrimType (Vec n a)
p          <- Operand (Vec n a) -> Type (Vec n a)
forall (f :: * -> *) a. TypeOf f => f a -> Type a
typeOf Operand (Vec n a)
x
        , ScalarPrimType ScalarType (Vec n a)
s    <- PrimType (Vec n a)
p
        , VectorScalarType VectorType (Vec n a1)
v  <- ScalarType (Vec n a)
s
        , VectorType Int
_ SingleType a1
t      <- VectorType (Vec n a1)
v
        = PrimType a1 -> Type a1
forall a. PrimType a -> Type a
PrimType (ScalarType a1 -> PrimType a1
forall a. ScalarType a -> PrimType a
ScalarPrimType (SingleType a1 -> ScalarType a1
forall a. SingleType a -> ScalarType a
SingleScalarType SingleType a1
t))
        --
        | Bool
otherwise
        = String -> Type a
forall a. HasCallStack => String -> a
internalError String
"unexpected evaluation"

      scalar :: ScalarType a -> Type a
      scalar :: ScalarType a -> Type a
scalar = PrimType a -> Type a
forall a. PrimType a -> Type a
PrimType (PrimType a -> Type a)
-> (ScalarType a -> PrimType a) -> ScalarType a -> Type a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ScalarType a -> PrimType a
forall a. ScalarType a -> PrimType a
ScalarPrimType

      single :: SingleType a -> Type a
      single :: SingleType a -> Type a
single = ScalarType a -> Type a
forall a. ScalarType a -> Type a
scalar (ScalarType a -> Type a)
-> (SingleType a -> ScalarType a) -> SingleType a -> Type a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SingleType a -> ScalarType a
forall a. SingleType a -> ScalarType a
SingleScalarType

      floating :: FloatingType a -> Type a
      floating :: FloatingType a -> Type a
floating = SingleType a -> Type a
forall a. SingleType a -> Type a
single (SingleType a -> Type a)
-> (FloatingType a -> SingleType a) -> FloatingType a -> Type a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NumType a -> SingleType a
forall a. NumType a -> SingleType a
NumSingleType (NumType a -> SingleType a)
-> (FloatingType a -> NumType a) -> FloatingType a -> SingleType a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FloatingType a -> NumType a
forall a. FloatingType a -> NumType a
FloatingNumType

      integral :: IntegralType a -> Type a
      integral :: IntegralType a -> Type a
integral = SingleType a -> Type a
forall a. SingleType a -> Type a
single (SingleType a -> Type a)
-> (IntegralType a -> SingleType a) -> IntegralType a -> Type a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NumType a -> SingleType a
forall a. NumType a -> SingleType a
NumSingleType (NumType a -> SingleType a)
-> (IntegralType a -> NumType a) -> IntegralType a -> SingleType a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IntegralType a -> NumType a
forall a. IntegralType a -> NumType a
IntegralNumType

      pair :: ScalarType a -> ScalarType b -> TypeR (a, b)
      pair :: ScalarType a -> ScalarType b -> TypeR (a, b)
pair ScalarType a
a ScalarType b
b = ScalarType a -> TupR ScalarType a
forall (s :: * -> *) a. s a -> TupR s a
TupRsingle ScalarType a
a TupR ScalarType a -> TupR ScalarType b -> TypeR (a, b)
forall (s :: * -> *) a1 b. TupR s a1 -> TupR s b -> TupR s (a1, b)
`TupRpair` ScalarType b -> TupR ScalarType b
forall (s :: * -> *) a. s a -> TupR s a
TupRsingle ScalarType b
b

      bounded :: BoundedType a -> Type a
      bounded :: BoundedType a -> Type a
bounded (IntegralBoundedType IntegralType a
t) = IntegralType a -> Type a
forall a. IntegralType a -> Type a
integral IntegralType a
t

      fun :: Function kind args a -> Type a
      fun :: Function kind args a -> Type a
fun (Lam PrimType a
_ Operand a
_ Function kind args a
l)  = Function kind args a -> Type a
forall kind (args :: [*]) a. Function kind args a -> Type a
fun Function kind args a
l
      fun (Body Type a
t Maybe TailCall
_ kind
_) = Type a
t