{-# LANGUAGE CPP          #-}
{-# LANGUAGE MagicHash    #-}
{-# LANGUAGE TypeFamilies #-}
-- |
-- Module      : Data.Array.Accelerate.Internal.LLVM.Prim
-- Copyright   : [2016..2020] Trevor L. McDonell
-- License     : BSD3
--
-- Maintainer  : Trevor L. McDonell <trevor.mcdonell@gmail.com>
-- Stability   : experimental
-- Portability : non-portable (GHC extensions)
--
-- Primops for LLVM backends
--

module Data.Array.Accelerate.Internal.LLVM.Prim (

  -- Operators from Num2
  addWithCarryInt64#, mulWithCarryInt64#,
  addWithCarryWord64#, mulWithCarryWord64#,

  -- Operators from Num
  addInt128#, subInt128#, mulInt128#,
  addWord128#, subWord128#, mulWord128#,

  -- Operators from Integral
  quotInt128#, remInt128#, quotRemInt128#,
  quotWord128#, remWord128#, quotRemWord128#,

) where

import Data.Array.Accelerate.Error
import Data.Array.Accelerate.Sugar.Elt

import Data.Array.Accelerate.Internal.BigInt
import Data.Array.Accelerate.Internal.BigWord
import Data.Array.Accelerate.Internal.Orphans.Elt                   ()

import Data.Array.Accelerate.LLVM.CodeGen.IR                        ( Operands(..) )
import Data.Array.Accelerate.LLVM.CodeGen.Monad                     ( CodeGen, freshName, instr_ )
import Data.Array.Accelerate.LLVM.CodeGen.Sugar
import qualified LLVM.AST.Type.Name                                 as A
import qualified LLVM.AST.Type.Operand                              as A
import qualified LLVM.AST.Type.Representation                       as A
#if MIN_VERSION_accelerate_llvm(1,3,0)
import LLVM.AST.Type.Downcast                                       ( downcast )
#else
import Data.Array.Accelerate.LLVM.CodeGen.Downcast                  ( downcast )
#endif

import LLVM.AST.Constant                                            ( Constant(Int) )
import LLVM.AST.Instruction                                         hiding ( nsw, nuw )
import LLVM.AST.Name                                                ( Name(..) )
import LLVM.AST.Operand                                             ( Operand(..) )
import LLVM.AST.Type

import Data.Int
import Data.Word
import Prelude                                                      hiding ( uncurry )


uncurry :: (Operands a -> Operands b -> c) -> Operands (((), a), b) -> c
uncurry :: (Operands a -> Operands b -> c) -> Operands (((), a), b) -> c
uncurry Operands a -> Operands b -> c
f (OP_Unit `OP_Pair` x `OP_Pair` y) = Operands a -> Operands b -> c
f Operands a
x Operands b
y

-- Primitive instruction wrappers
-- ------------------------------

-- Operations from Num2
-- --------------------

addWithCarryInt64# :: IRFun1 arch () (EltR (Int64, Int64) -> EltR (Int64, Word64))
addWithCarryInt64# :: IRFun1 arch () (EltR (Int64, Int64) -> EltR (Int64, Word64))
addWithCarryInt64# = (Operands (((), Int64), Int64)
 -> IROpenExp
      arch ((), (((), Int64), Int64)) () (((), Int64), Word64))
-> IROpenFun1
     arch () () ((((), Int64), Int64) -> (((), Int64), Word64))
forall a arch env aenv b.
(Operands a -> IROpenExp arch (env, a) aenv b)
-> IROpenFun1 arch env aenv (a -> b)
IRFun1 ((Operands (((), Int64), Int64)
  -> IROpenExp
       arch ((), (((), Int64), Int64)) () (((), Int64), Word64))
 -> IROpenFun1
      arch () () ((((), Int64), Int64) -> (((), Int64), Word64)))
-> (Operands (((), Int64), Int64)
    -> IROpenExp
         arch ((), (((), Int64), Int64)) () (((), Int64), Word64))
-> IROpenFun1
     arch () () ((((), Int64), Int64) -> (((), Int64), Word64))
forall a b. (a -> b) -> a -> b
$ (Operands Int64
 -> Operands Int64
 -> IROpenExp
      arch ((), (((), Int64), Int64)) () (((), Int64), Word64))
-> Operands (((), Int64), Int64)
-> IROpenExp
     arch ((), (((), Int64), Int64)) () (((), Int64), Word64)
forall a b c.
(Operands a -> Operands b -> c) -> Operands (((), a), b) -> c
uncurry ((Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands Int64
-> Operands Int64
-> IROpenExp
     arch ((), (((), Int64), Int64)) () (((), Int64), Word64)
forall arch.
(Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands Int64
-> Operands Int64
-> CodeGen arch (Operands (((), Int64), Word64))
prim_wideningInt64 (Bool
-> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
Add Bool
nsw Bool
nuw))

mulWithCarryInt64# :: IRFun1 arch () (EltR (Int64, Int64) -> EltR (Int64, Word64))
mulWithCarryInt64# :: IRFun1 arch () (EltR (Int64, Int64) -> EltR (Int64, Word64))
mulWithCarryInt64# = (Operands (((), Int64), Int64)
 -> IROpenExp
      arch ((), (((), Int64), Int64)) () (((), Int64), Word64))
-> IROpenFun1
     arch () () ((((), Int64), Int64) -> (((), Int64), Word64))
forall a arch env aenv b.
(Operands a -> IROpenExp arch (env, a) aenv b)
-> IROpenFun1 arch env aenv (a -> b)
IRFun1 ((Operands (((), Int64), Int64)
  -> IROpenExp
       arch ((), (((), Int64), Int64)) () (((), Int64), Word64))
 -> IROpenFun1
      arch () () ((((), Int64), Int64) -> (((), Int64), Word64)))
-> (Operands (((), Int64), Int64)
    -> IROpenExp
         arch ((), (((), Int64), Int64)) () (((), Int64), Word64))
-> IROpenFun1
     arch () () ((((), Int64), Int64) -> (((), Int64), Word64))
forall a b. (a -> b) -> a -> b
$ (Operands Int64
 -> Operands Int64
 -> IROpenExp
      arch ((), (((), Int64), Int64)) () (((), Int64), Word64))
-> Operands (((), Int64), Int64)
-> IROpenExp
     arch ((), (((), Int64), Int64)) () (((), Int64), Word64)
forall a b c.
(Operands a -> Operands b -> c) -> Operands (((), a), b) -> c
uncurry ((Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands Int64
-> Operands Int64
-> IROpenExp
     arch ((), (((), Int64), Int64)) () (((), Int64), Word64)
forall arch.
(Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands Int64
-> Operands Int64
-> CodeGen arch (Operands (((), Int64), Word64))
prim_wideningInt64 (Bool
-> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
Mul Bool
nsw Bool
nuw))

addWithCarryWord64# :: IRFun1 arch () (EltR (Word64, Word64) -> EltR (Word64, Word64))
addWithCarryWord64# :: IRFun1 arch () (EltR (Word64, Word64) -> EltR (Word64, Word64))
addWithCarryWord64# = (Operands (((), Word64), Word64)
 -> IROpenExp
      arch ((), (((), Word64), Word64)) () (((), Word64), Word64))
-> IROpenFun1
     arch () () ((((), Word64), Word64) -> (((), Word64), Word64))
forall a arch env aenv b.
(Operands a -> IROpenExp arch (env, a) aenv b)
-> IROpenFun1 arch env aenv (a -> b)
IRFun1 ((Operands (((), Word64), Word64)
  -> IROpenExp
       arch ((), (((), Word64), Word64)) () (((), Word64), Word64))
 -> IROpenFun1
      arch () () ((((), Word64), Word64) -> (((), Word64), Word64)))
-> (Operands (((), Word64), Word64)
    -> IROpenExp
         arch ((), (((), Word64), Word64)) () (((), Word64), Word64))
-> IROpenFun1
     arch () () ((((), Word64), Word64) -> (((), Word64), Word64))
forall a b. (a -> b) -> a -> b
$ (Operands Word64
 -> Operands Word64
 -> IROpenExp
      arch ((), (((), Word64), Word64)) () (((), Word64), Word64))
-> Operands (((), Word64), Word64)
-> IROpenExp
     arch ((), (((), Word64), Word64)) () (((), Word64), Word64)
forall a b c.
(Operands a -> Operands b -> c) -> Operands (((), a), b) -> c
uncurry ((Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands Word64
-> Operands Word64
-> IROpenExp
     arch ((), (((), Word64), Word64)) () (((), Word64), Word64)
forall arch.
(Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands Word64
-> Operands Word64
-> CodeGen arch (Operands (((), Word64), Word64))
prim_wideningWord64 (Bool
-> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
Add Bool
nsw Bool
nuw))

mulWithCarryWord64# :: IRFun1 arch () (EltR (Word64, Word64) -> EltR (Word64, Word64))
mulWithCarryWord64# :: IRFun1 arch () (EltR (Word64, Word64) -> EltR (Word64, Word64))
mulWithCarryWord64# = (Operands (((), Word64), Word64)
 -> IROpenExp
      arch ((), (((), Word64), Word64)) () (((), Word64), Word64))
-> IROpenFun1
     arch () () ((((), Word64), Word64) -> (((), Word64), Word64))
forall a arch env aenv b.
(Operands a -> IROpenExp arch (env, a) aenv b)
-> IROpenFun1 arch env aenv (a -> b)
IRFun1 ((Operands (((), Word64), Word64)
  -> IROpenExp
       arch ((), (((), Word64), Word64)) () (((), Word64), Word64))
 -> IROpenFun1
      arch () () ((((), Word64), Word64) -> (((), Word64), Word64)))
-> (Operands (((), Word64), Word64)
    -> IROpenExp
         arch ((), (((), Word64), Word64)) () (((), Word64), Word64))
-> IROpenFun1
     arch () () ((((), Word64), Word64) -> (((), Word64), Word64))
forall a b. (a -> b) -> a -> b
$ (Operands Word64
 -> Operands Word64
 -> IROpenExp
      arch ((), (((), Word64), Word64)) () (((), Word64), Word64))
-> Operands (((), Word64), Word64)
-> IROpenExp
     arch ((), (((), Word64), Word64)) () (((), Word64), Word64)
forall a b c.
(Operands a -> Operands b -> c) -> Operands (((), a), b) -> c
uncurry ((Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands Word64
-> Operands Word64
-> IROpenExp
     arch ((), (((), Word64), Word64)) () (((), Word64), Word64)
forall arch.
(Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands Word64
-> Operands Word64
-> CodeGen arch (Operands (((), Word64), Word64))
prim_wideningWord64 (Bool
-> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
Mul Bool
nsw Bool
nuw))


prim_wideningInt64
    :: (Operand -> Operand -> InstructionMetadata -> Instruction)
    -> Operands Int64
    -> Operands Int64
    -> CodeGen arch (Operands (((), Int64), Word64))
prim_wideningInt64 :: (Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands Int64
-> Operands Int64
-> CodeGen arch (Operands (((), Int64), Word64))
prim_wideningInt64 Operand -> Operand -> InstructionMetadata -> Instruction
op (OP_Int64 x) (OP_Int64 y) = do
  Operand
a     <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Operand -> Type -> InstructionMetadata -> Instruction
SExt (Operand Int64 -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Int64
x) Type
i128 InstructionMetadata
md)
  Operand
b     <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Operand -> Type -> InstructionMetadata -> Instruction
SExt (Operand Int64 -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Int64
y) Type
i128 InstructionMetadata
md)
  Operand
c     <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Operand -> Operand -> InstructionMetadata -> Instruction
op Operand
a Operand
b InstructionMetadata
md)
  (Operand
d,Operand
e) <- Operand -> CodeGen arch (Operand, Operand)
forall arch. Operand -> CodeGen arch (Operand, Operand)
unpackInt128 Operand
c
  Operands (((), Int64), Word64)
-> CodeGen arch (Operands (((), Int64), Word64))
forall (m :: * -> *) a. Monad m => a -> m a
return (Operands (((), Int64), Word64)
 -> CodeGen arch (Operands (((), Int64), Word64)))
-> Operands (((), Int64), Word64)
-> CodeGen arch (Operands (((), Int64), Word64))
forall a b. (a -> b) -> a -> b
$ Operands ()
OP_Unit Operands () -> Operands Int64 -> Operands ((), Int64)
forall a b. Operands a -> Operands b -> Operands (a, b)
`OP_Pair` HasCallStack => Operand -> Operands Int64
Operand -> Operands Int64
upcastInt64 Operand
d Operands ((), Int64)
-> Operands Word64 -> Operands (((), Int64), Word64)
forall a b. Operands a -> Operands b -> Operands (a, b)
`OP_Pair` HasCallStack => Operand -> Operands Word64
Operand -> Operands Word64
upcastWord64 Operand
e

prim_wideningWord64
    :: (Operand -> Operand -> InstructionMetadata -> Instruction)
    -> Operands Word64
    -> Operands Word64
    -> CodeGen arch (Operands (((), Word64), Word64))
prim_wideningWord64 :: (Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands Word64
-> Operands Word64
-> CodeGen arch (Operands (((), Word64), Word64))
prim_wideningWord64 Operand -> Operand -> InstructionMetadata -> Instruction
op (OP_Word64 x) (OP_Word64 y) = do
  Operand
a     <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Operand -> Type -> InstructionMetadata -> Instruction
ZExt (Operand Word64 -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Word64
x) Type
i128 InstructionMetadata
md)
  Operand
b     <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Operand -> Type -> InstructionMetadata -> Instruction
ZExt (Operand Word64 -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Word64
y) Type
i128 InstructionMetadata
md)
  Operand
c     <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Operand -> Operand -> InstructionMetadata -> Instruction
op Operand
a Operand
b InstructionMetadata
md)
  (Operand
d,Operand
e) <- Operand -> CodeGen arch (Operand, Operand)
forall arch. Operand -> CodeGen arch (Operand, Operand)
unpackWord128 Operand
c
  Operands (((), Word64), Word64)
-> CodeGen arch (Operands (((), Word64), Word64))
forall (m :: * -> *) a. Monad m => a -> m a
return (Operands (((), Word64), Word64)
 -> CodeGen arch (Operands (((), Word64), Word64)))
-> Operands (((), Word64), Word64)
-> CodeGen arch (Operands (((), Word64), Word64))
forall a b. (a -> b) -> a -> b
$ Operands ()
OP_Unit Operands () -> Operands Word64 -> Operands ((), Word64)
forall a b. Operands a -> Operands b -> Operands (a, b)
`OP_Pair` HasCallStack => Operand -> Operands Word64
Operand -> Operands Word64
upcastWord64 Operand
d Operands ((), Word64)
-> Operands Word64 -> Operands (((), Word64), Word64)
forall a b. Operands a -> Operands b -> Operands (a, b)
`OP_Pair` HasCallStack => Operand -> Operands Word64
Operand -> Operands Word64
upcastWord64 Operand
e


-- Operations from Num
-- -------------------

addInt128# :: IRFun1 arch () (EltR (Int128, Int128) -> EltR Int128)
addInt128# :: IRFun1 arch () (EltR (Int128, Int128) -> EltR Int128)
addInt128# = (Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
 -> IROpenExp
      arch
      ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
      ()
      (((), Int64), Word64))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Int64), Word64)), (((), Int64), Word64))
      -> (((), Int64), Word64))
forall a arch env aenv b.
(Operands a -> IROpenExp arch (env, a) aenv b)
-> IROpenFun1 arch env aenv (a -> b)
IRFun1 ((Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
  -> IROpenExp
       arch
       ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
       ()
       (((), Int64), Word64))
 -> IROpenFun1
      arch
      ()
      ()
      ((((), (((), Int64), Word64)), (((), Int64), Word64))
       -> (((), Int64), Word64)))
-> (Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
    -> IROpenExp
         arch
         ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
         ()
         (((), Int64), Word64))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Int64), Word64)), (((), Int64), Word64))
      -> (((), Int64), Word64))
forall a b. (a -> b) -> a -> b
$ (Operands (((), Int64), Word64)
 -> Operands (((), Int64), Word64)
 -> IROpenExp
      arch
      ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
      ()
      (((), Int64), Word64))
-> Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
-> IROpenExp
     arch
     ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
     ()
     (((), Int64), Word64)
forall a b c.
(Operands a -> Operands b -> c) -> Operands (((), a), b) -> c
uncurry ((Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Int128)
-> Operands (EltR Int128)
-> CodeGen arch (Operands (EltR Int128))
forall arch.
(Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Int128)
-> Operands (EltR Int128)
-> CodeGen arch (Operands (EltR Int128))
prim_binaryInt128 (Bool
-> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
Add Bool
nsw Bool
nuw))

subInt128# :: IRFun1 arch () (EltR (Int128, Int128) -> EltR Int128)
subInt128# :: IRFun1 arch () (EltR (Int128, Int128) -> EltR Int128)
subInt128# = (Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
 -> IROpenExp
      arch
      ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
      ()
      (((), Int64), Word64))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Int64), Word64)), (((), Int64), Word64))
      -> (((), Int64), Word64))
forall a arch env aenv b.
(Operands a -> IROpenExp arch (env, a) aenv b)
-> IROpenFun1 arch env aenv (a -> b)
IRFun1 ((Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
  -> IROpenExp
       arch
       ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
       ()
       (((), Int64), Word64))
 -> IROpenFun1
      arch
      ()
      ()
      ((((), (((), Int64), Word64)), (((), Int64), Word64))
       -> (((), Int64), Word64)))
-> (Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
    -> IROpenExp
         arch
         ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
         ()
         (((), Int64), Word64))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Int64), Word64)), (((), Int64), Word64))
      -> (((), Int64), Word64))
forall a b. (a -> b) -> a -> b
$ (Operands (((), Int64), Word64)
 -> Operands (((), Int64), Word64)
 -> IROpenExp
      arch
      ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
      ()
      (((), Int64), Word64))
-> Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
-> IROpenExp
     arch
     ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
     ()
     (((), Int64), Word64)
forall a b c.
(Operands a -> Operands b -> c) -> Operands (((), a), b) -> c
uncurry ((Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Int128)
-> Operands (EltR Int128)
-> CodeGen arch (Operands (EltR Int128))
forall arch.
(Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Int128)
-> Operands (EltR Int128)
-> CodeGen arch (Operands (EltR Int128))
prim_binaryInt128 (Bool
-> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
Sub Bool
nsw Bool
nuw))

mulInt128# :: IRFun1 arch () (EltR (Int128, Int128) -> EltR Int128)
mulInt128# :: IRFun1 arch () (EltR (Int128, Int128) -> EltR Int128)
mulInt128# = (Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
 -> IROpenExp
      arch
      ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
      ()
      (((), Int64), Word64))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Int64), Word64)), (((), Int64), Word64))
      -> (((), Int64), Word64))
forall a arch env aenv b.
(Operands a -> IROpenExp arch (env, a) aenv b)
-> IROpenFun1 arch env aenv (a -> b)
IRFun1 ((Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
  -> IROpenExp
       arch
       ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
       ()
       (((), Int64), Word64))
 -> IROpenFun1
      arch
      ()
      ()
      ((((), (((), Int64), Word64)), (((), Int64), Word64))
       -> (((), Int64), Word64)))
-> (Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
    -> IROpenExp
         arch
         ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
         ()
         (((), Int64), Word64))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Int64), Word64)), (((), Int64), Word64))
      -> (((), Int64), Word64))
forall a b. (a -> b) -> a -> b
$ (Operands (((), Int64), Word64)
 -> Operands (((), Int64), Word64)
 -> IROpenExp
      arch
      ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
      ()
      (((), Int64), Word64))
-> Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
-> IROpenExp
     arch
     ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
     ()
     (((), Int64), Word64)
forall a b c.
(Operands a -> Operands b -> c) -> Operands (((), a), b) -> c
uncurry ((Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Int128)
-> Operands (EltR Int128)
-> CodeGen arch (Operands (EltR Int128))
forall arch.
(Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Int128)
-> Operands (EltR Int128)
-> CodeGen arch (Operands (EltR Int128))
prim_binaryInt128 (Bool
-> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
Mul Bool
nsw Bool
nuw))

addWord128# :: IRFun1 arch () (EltR (Word128, Word128) -> EltR Word128)
addWord128# :: IRFun1 arch () (EltR (Word128, Word128) -> EltR Word128)
addWord128# = (Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
 -> IROpenExp
      arch
      ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
      ()
      (((), Word64), Word64))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Word64), Word64)), (((), Word64), Word64))
      -> (((), Word64), Word64))
forall a arch env aenv b.
(Operands a -> IROpenExp arch (env, a) aenv b)
-> IROpenFun1 arch env aenv (a -> b)
IRFun1 ((Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
  -> IROpenExp
       arch
       ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
       ()
       (((), Word64), Word64))
 -> IROpenFun1
      arch
      ()
      ()
      ((((), (((), Word64), Word64)), (((), Word64), Word64))
       -> (((), Word64), Word64)))
-> (Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
    -> IROpenExp
         arch
         ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
         ()
         (((), Word64), Word64))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Word64), Word64)), (((), Word64), Word64))
      -> (((), Word64), Word64))
forall a b. (a -> b) -> a -> b
$ (Operands (((), Word64), Word64)
 -> Operands (((), Word64), Word64)
 -> IROpenExp
      arch
      ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
      ()
      (((), Word64), Word64))
-> Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
-> IROpenExp
     arch
     ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
     ()
     (((), Word64), Word64)
forall a b c.
(Operands a -> Operands b -> c) -> Operands (((), a), b) -> c
uncurry ((Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Word128)
-> Operands (EltR Word128)
-> CodeGen arch (Operands (EltR Word128))
forall arch.
(Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Word128)
-> Operands (EltR Word128)
-> CodeGen arch (Operands (EltR Word128))
prim_binaryWord128 (Bool
-> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
Add Bool
nsw Bool
nuw))

subWord128# :: IRFun1 arch () (EltR (Word128, Word128) -> EltR Word128)
subWord128# :: IRFun1 arch () (EltR (Word128, Word128) -> EltR Word128)
subWord128# = (Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
 -> IROpenExp
      arch
      ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
      ()
      (((), Word64), Word64))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Word64), Word64)), (((), Word64), Word64))
      -> (((), Word64), Word64))
forall a arch env aenv b.
(Operands a -> IROpenExp arch (env, a) aenv b)
-> IROpenFun1 arch env aenv (a -> b)
IRFun1 ((Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
  -> IROpenExp
       arch
       ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
       ()
       (((), Word64), Word64))
 -> IROpenFun1
      arch
      ()
      ()
      ((((), (((), Word64), Word64)), (((), Word64), Word64))
       -> (((), Word64), Word64)))
-> (Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
    -> IROpenExp
         arch
         ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
         ()
         (((), Word64), Word64))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Word64), Word64)), (((), Word64), Word64))
      -> (((), Word64), Word64))
forall a b. (a -> b) -> a -> b
$ (Operands (((), Word64), Word64)
 -> Operands (((), Word64), Word64)
 -> IROpenExp
      arch
      ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
      ()
      (((), Word64), Word64))
-> Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
-> IROpenExp
     arch
     ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
     ()
     (((), Word64), Word64)
forall a b c.
(Operands a -> Operands b -> c) -> Operands (((), a), b) -> c
uncurry ((Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Word128)
-> Operands (EltR Word128)
-> CodeGen arch (Operands (EltR Word128))
forall arch.
(Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Word128)
-> Operands (EltR Word128)
-> CodeGen arch (Operands (EltR Word128))
prim_binaryWord128 (Bool
-> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
Sub Bool
nsw Bool
nuw))

mulWord128# :: IRFun1 arch () (EltR (Word128, Word128) -> EltR Word128)
mulWord128# :: IRFun1 arch () (EltR (Word128, Word128) -> EltR Word128)
mulWord128# = (Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
 -> IROpenExp
      arch
      ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
      ()
      (((), Word64), Word64))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Word64), Word64)), (((), Word64), Word64))
      -> (((), Word64), Word64))
forall a arch env aenv b.
(Operands a -> IROpenExp arch (env, a) aenv b)
-> IROpenFun1 arch env aenv (a -> b)
IRFun1 ((Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
  -> IROpenExp
       arch
       ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
       ()
       (((), Word64), Word64))
 -> IROpenFun1
      arch
      ()
      ()
      ((((), (((), Word64), Word64)), (((), Word64), Word64))
       -> (((), Word64), Word64)))
-> (Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
    -> IROpenExp
         arch
         ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
         ()
         (((), Word64), Word64))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Word64), Word64)), (((), Word64), Word64))
      -> (((), Word64), Word64))
forall a b. (a -> b) -> a -> b
$ (Operands (((), Word64), Word64)
 -> Operands (((), Word64), Word64)
 -> IROpenExp
      arch
      ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
      ()
      (((), Word64), Word64))
-> Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
-> IROpenExp
     arch
     ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
     ()
     (((), Word64), Word64)
forall a b c.
(Operands a -> Operands b -> c) -> Operands (((), a), b) -> c
uncurry ((Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Word128)
-> Operands (EltR Word128)
-> CodeGen arch (Operands (EltR Word128))
forall arch.
(Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Word128)
-> Operands (EltR Word128)
-> CodeGen arch (Operands (EltR Word128))
prim_binaryWord128 (Bool
-> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
Mul Bool
nsw Bool
nuw))


-- Operations from Integral
-- ------------------------

quotInt128# :: IRFun1 arch () (EltR (Int128, Int128) -> EltR Int128)
quotInt128# :: IRFun1 arch () (EltR (Int128, Int128) -> EltR Int128)
quotInt128# = (Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
 -> IROpenExp
      arch
      ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
      ()
      (((), Int64), Word64))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Int64), Word64)), (((), Int64), Word64))
      -> (((), Int64), Word64))
forall a arch env aenv b.
(Operands a -> IROpenExp arch (env, a) aenv b)
-> IROpenFun1 arch env aenv (a -> b)
IRFun1 ((Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
  -> IROpenExp
       arch
       ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
       ()
       (((), Int64), Word64))
 -> IROpenFun1
      arch
      ()
      ()
      ((((), (((), Int64), Word64)), (((), Int64), Word64))
       -> (((), Int64), Word64)))
-> (Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
    -> IROpenExp
         arch
         ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
         ()
         (((), Int64), Word64))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Int64), Word64)), (((), Int64), Word64))
      -> (((), Int64), Word64))
forall a b. (a -> b) -> a -> b
$ (Operands (((), Int64), Word64)
 -> Operands (((), Int64), Word64)
 -> IROpenExp
      arch
      ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
      ()
      (((), Int64), Word64))
-> Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
-> IROpenExp
     arch
     ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
     ()
     (((), Int64), Word64)
forall a b c.
(Operands a -> Operands b -> c) -> Operands (((), a), b) -> c
uncurry ((Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Int128)
-> Operands (EltR Int128)
-> CodeGen arch (Operands (EltR Int128))
forall arch.
(Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Int128)
-> Operands (EltR Int128)
-> CodeGen arch (Operands (EltR Int128))
prim_binaryInt128 (Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
SDiv Bool
False))

remInt128# :: IRFun1 arch () (EltR (Int128, Int128) -> EltR Int128)
remInt128# :: IRFun1 arch () (EltR (Int128, Int128) -> EltR Int128)
remInt128# = (Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
 -> IROpenExp
      arch
      ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
      ()
      (((), Int64), Word64))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Int64), Word64)), (((), Int64), Word64))
      -> (((), Int64), Word64))
forall a arch env aenv b.
(Operands a -> IROpenExp arch (env, a) aenv b)
-> IROpenFun1 arch env aenv (a -> b)
IRFun1 ((Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
  -> IROpenExp
       arch
       ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
       ()
       (((), Int64), Word64))
 -> IROpenFun1
      arch
      ()
      ()
      ((((), (((), Int64), Word64)), (((), Int64), Word64))
       -> (((), Int64), Word64)))
-> (Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
    -> IROpenExp
         arch
         ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
         ()
         (((), Int64), Word64))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Int64), Word64)), (((), Int64), Word64))
      -> (((), Int64), Word64))
forall a b. (a -> b) -> a -> b
$ (Operands (((), Int64), Word64)
 -> Operands (((), Int64), Word64)
 -> IROpenExp
      arch
      ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
      ()
      (((), Int64), Word64))
-> Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
-> IROpenExp
     arch
     ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
     ()
     (((), Int64), Word64)
forall a b c.
(Operands a -> Operands b -> c) -> Operands (((), a), b) -> c
uncurry ((Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Int128)
-> Operands (EltR Int128)
-> CodeGen arch (Operands (EltR Int128))
forall arch.
(Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Int128)
-> Operands (EltR Int128)
-> CodeGen arch (Operands (EltR Int128))
prim_binaryInt128 Operand -> Operand -> InstructionMetadata -> Instruction
SRem)

quotRemInt128# :: IRFun1 arch () (EltR (Int128, Int128) -> EltR (Int128, Int128))
quotRemInt128# :: IRFun1 arch () (EltR (Int128, Int128) -> EltR (Int128, Int128))
quotRemInt128# = (Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
 -> IROpenExp
      arch
      ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
      ()
      (((), (((), Int64), Word64)), (((), Int64), Word64)))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Int64), Word64)), (((), Int64), Word64))
      -> (((), (((), Int64), Word64)), (((), Int64), Word64)))
forall a arch env aenv b.
(Operands a -> IROpenExp arch (env, a) aenv b)
-> IROpenFun1 arch env aenv (a -> b)
IRFun1 ((Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
  -> IROpenExp
       arch
       ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
       ()
       (((), (((), Int64), Word64)), (((), Int64), Word64)))
 -> IROpenFun1
      arch
      ()
      ()
      ((((), (((), Int64), Word64)), (((), Int64), Word64))
       -> (((), (((), Int64), Word64)), (((), Int64), Word64))))
-> (Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
    -> IROpenExp
         arch
         ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
         ()
         (((), (((), Int64), Word64)), (((), Int64), Word64)))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Int64), Word64)), (((), Int64), Word64))
      -> (((), (((), Int64), Word64)), (((), Int64), Word64)))
forall a b. (a -> b) -> a -> b
$ (Operands (((), Int64), Word64)
 -> Operands (((), Int64), Word64)
 -> IROpenExp
      arch
      ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
      ()
      (((), (((), Int64), Word64)), (((), Int64), Word64)))
-> Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
-> IROpenExp
     arch
     ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
     ()
     (((), (((), Int64), Word64)), (((), Int64), Word64))
forall a b c.
(Operands a -> Operands b -> c) -> Operands (((), a), b) -> c
uncurry Operands (((), Int64), Word64)
-> Operands (((), Int64), Word64)
-> IROpenExp
     arch
     ((), (((), (((), Int64), Word64)), (((), Int64), Word64)))
     ()
     (((), (((), Int64), Word64)), (((), Int64), Word64))
forall arch.
Operands (EltR Int128)
-> Operands (EltR Int128)
-> CodeGen arch (Operands (EltR (Int128, Int128)))
quotRem'
  where
    quotRem' :: Operands (EltR Int128) -> Operands (EltR Int128) -> CodeGen arch (Operands (EltR (Int128, Int128)))
    quotRem' :: Operands (EltR Int128)
-> Operands (EltR Int128)
-> CodeGen arch (Operands (EltR (Int128, Int128)))
quotRem' Operands (EltR Int128)
xx Operands (EltR Int128)
yy
      | OP_Pair (OP_Pair OP_Unit (OP_Int64 xh)) (OP_Word64 xl) <- Operands (EltR Int128)
xx
      , OP_Pair (OP_Pair OP_Unit (OP_Int64 yh)) (OP_Word64 yl) <- Operands (EltR Int128)
yy
      = do
        Operand
x       <- Operand -> Operand -> CodeGen arch Operand
forall arch. Operand -> Operand -> CodeGen arch Operand
packWord128 (Operand Int64 -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Int64
xh) (Operand Word64 -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Word64
xl)
        Operand
y       <- Operand -> Operand -> CodeGen arch Operand
forall arch. Operand -> Operand -> CodeGen arch Operand
packWord128 (Operand Int64 -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Int64
yh) (Operand Word64 -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Word64
yl)
        Operand
q       <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
SDiv Bool
False Operand
x Operand
y InstructionMetadata
md)
        Operand
z       <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Bool
-> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
Mul Bool
nsw Bool
nuw Operand
y Operand
q InstructionMetadata
md)
        Operand
r       <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Bool
-> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
Sub Bool
nsw Bool
nuw Operand
x Operand
z InstructionMetadata
md)
        (Operand
qh,Operand
ql) <- Operand -> CodeGen arch (Operand, Operand)
forall arch. Operand -> CodeGen arch (Operand, Operand)
unpackInt128 Operand
q
        (Operand
rh,Operand
rl) <- Operand -> CodeGen arch (Operand, Operand)
forall arch. Operand -> CodeGen arch (Operand, Operand)
unpackInt128 Operand
r
        Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
-> CodeGen
     arch
     (Operands (((), (((), Int64), Word64)), (((), Int64), Word64)))
forall (m :: * -> *) a. Monad m => a -> m a
return (Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
 -> CodeGen
      arch
      (Operands (((), (((), Int64), Word64)), (((), Int64), Word64))))
-> Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
-> CodeGen
     arch
     (Operands (((), (((), Int64), Word64)), (((), Int64), Word64)))
forall a b. (a -> b) -> a -> b
$ Operands ()
OP_Unit Operands ()
-> Operands (((), Int64), Word64)
-> Operands ((), (((), Int64), Word64))
forall a b. Operands a -> Operands b -> Operands (a, b)
`OP_Pair` Operand -> Operand -> Operands (EltR Int128)
upcastInt128 Operand
qh Operand
ql Operands ((), (((), Int64), Word64))
-> Operands (((), Int64), Word64)
-> Operands (((), (((), Int64), Word64)), (((), Int64), Word64))
forall a b. Operands a -> Operands b -> Operands (a, b)
`OP_Pair` Operand -> Operand -> Operands (EltR Int128)
upcastInt128 Operand
rh Operand
rl


quotWord128# :: IRFun1 arch () (EltR (Word128, Word128) -> EltR Word128)
quotWord128# :: IRFun1 arch () (EltR (Word128, Word128) -> EltR Word128)
quotWord128# = (Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
 -> IROpenExp
      arch
      ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
      ()
      (((), Word64), Word64))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Word64), Word64)), (((), Word64), Word64))
      -> (((), Word64), Word64))
forall a arch env aenv b.
(Operands a -> IROpenExp arch (env, a) aenv b)
-> IROpenFun1 arch env aenv (a -> b)
IRFun1 ((Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
  -> IROpenExp
       arch
       ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
       ()
       (((), Word64), Word64))
 -> IROpenFun1
      arch
      ()
      ()
      ((((), (((), Word64), Word64)), (((), Word64), Word64))
       -> (((), Word64), Word64)))
-> (Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
    -> IROpenExp
         arch
         ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
         ()
         (((), Word64), Word64))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Word64), Word64)), (((), Word64), Word64))
      -> (((), Word64), Word64))
forall a b. (a -> b) -> a -> b
$ (Operands (((), Word64), Word64)
 -> Operands (((), Word64), Word64)
 -> IROpenExp
      arch
      ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
      ()
      (((), Word64), Word64))
-> Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
-> IROpenExp
     arch
     ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
     ()
     (((), Word64), Word64)
forall a b c.
(Operands a -> Operands b -> c) -> Operands (((), a), b) -> c
uncurry ((Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Word128)
-> Operands (EltR Word128)
-> CodeGen arch (Operands (EltR Word128))
forall arch.
(Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Word128)
-> Operands (EltR Word128)
-> CodeGen arch (Operands (EltR Word128))
prim_binaryWord128 (Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
UDiv Bool
False))

remWord128# :: IRFun1 arch () (EltR (Word128, Word128) -> EltR Word128)
remWord128# :: IRFun1 arch () (EltR (Word128, Word128) -> EltR Word128)
remWord128# = (Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
 -> IROpenExp
      arch
      ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
      ()
      (((), Word64), Word64))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Word64), Word64)), (((), Word64), Word64))
      -> (((), Word64), Word64))
forall a arch env aenv b.
(Operands a -> IROpenExp arch (env, a) aenv b)
-> IROpenFun1 arch env aenv (a -> b)
IRFun1 ((Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
  -> IROpenExp
       arch
       ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
       ()
       (((), Word64), Word64))
 -> IROpenFun1
      arch
      ()
      ()
      ((((), (((), Word64), Word64)), (((), Word64), Word64))
       -> (((), Word64), Word64)))
-> (Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
    -> IROpenExp
         arch
         ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
         ()
         (((), Word64), Word64))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Word64), Word64)), (((), Word64), Word64))
      -> (((), Word64), Word64))
forall a b. (a -> b) -> a -> b
$ (Operands (((), Word64), Word64)
 -> Operands (((), Word64), Word64)
 -> IROpenExp
      arch
      ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
      ()
      (((), Word64), Word64))
-> Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
-> IROpenExp
     arch
     ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
     ()
     (((), Word64), Word64)
forall a b c.
(Operands a -> Operands b -> c) -> Operands (((), a), b) -> c
uncurry ((Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Word128)
-> Operands (EltR Word128)
-> CodeGen arch (Operands (EltR Word128))
forall arch.
(Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Word128)
-> Operands (EltR Word128)
-> CodeGen arch (Operands (EltR Word128))
prim_binaryWord128 Operand -> Operand -> InstructionMetadata -> Instruction
URem)

quotRemWord128# :: IRFun1 arch () (EltR (Word128, Word128) -> EltR (Word128, Word128))
quotRemWord128# :: IRFun1 arch () (EltR (Word128, Word128) -> EltR (Word128, Word128))
quotRemWord128# = (Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
 -> IROpenExp
      arch
      ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
      ()
      (((), (((), Word64), Word64)), (((), Word64), Word64)))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Word64), Word64)), (((), Word64), Word64))
      -> (((), (((), Word64), Word64)), (((), Word64), Word64)))
forall a arch env aenv b.
(Operands a -> IROpenExp arch (env, a) aenv b)
-> IROpenFun1 arch env aenv (a -> b)
IRFun1 ((Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
  -> IROpenExp
       arch
       ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
       ()
       (((), (((), Word64), Word64)), (((), Word64), Word64)))
 -> IROpenFun1
      arch
      ()
      ()
      ((((), (((), Word64), Word64)), (((), Word64), Word64))
       -> (((), (((), Word64), Word64)), (((), Word64), Word64))))
-> (Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
    -> IROpenExp
         arch
         ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
         ()
         (((), (((), Word64), Word64)), (((), Word64), Word64)))
-> IROpenFun1
     arch
     ()
     ()
     ((((), (((), Word64), Word64)), (((), Word64), Word64))
      -> (((), (((), Word64), Word64)), (((), Word64), Word64)))
forall a b. (a -> b) -> a -> b
$ (Operands (((), Word64), Word64)
 -> Operands (((), Word64), Word64)
 -> IROpenExp
      arch
      ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
      ()
      (((), (((), Word64), Word64)), (((), Word64), Word64)))
-> Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
-> IROpenExp
     arch
     ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
     ()
     (((), (((), Word64), Word64)), (((), Word64), Word64))
forall a b c.
(Operands a -> Operands b -> c) -> Operands (((), a), b) -> c
uncurry Operands (((), Word64), Word64)
-> Operands (((), Word64), Word64)
-> IROpenExp
     arch
     ((), (((), (((), Word64), Word64)), (((), Word64), Word64)))
     ()
     (((), (((), Word64), Word64)), (((), Word64), Word64))
forall arch.
Operands (EltR Word128)
-> Operands (EltR Word128)
-> CodeGen arch (Operands (EltR (Word128, Word128)))
quotRem'
  where
    quotRem' :: Operands (EltR Word128) -> Operands (EltR Word128) -> CodeGen arch (Operands (EltR (Word128, Word128)))
    quotRem' :: Operands (EltR Word128)
-> Operands (EltR Word128)
-> CodeGen arch (Operands (EltR (Word128, Word128)))
quotRem' Operands (EltR Word128)
xx Operands (EltR Word128)
yy
      | OP_Pair (OP_Pair OP_Unit (OP_Word64 xh)) (OP_Word64 xl) <- Operands (EltR Word128)
xx
      , OP_Pair (OP_Pair OP_Unit (OP_Word64 yh)) (OP_Word64 yl) <- Operands (EltR Word128)
yy
      = do
        Operand
x       <- Operand -> Operand -> CodeGen arch Operand
forall arch. Operand -> Operand -> CodeGen arch Operand
packWord128 (Operand Word64 -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Word64
xh) (Operand Word64 -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Word64
xl)
        Operand
y       <- Operand -> Operand -> CodeGen arch Operand
forall arch. Operand -> Operand -> CodeGen arch Operand
packWord128 (Operand Word64 -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Word64
yh) (Operand Word64 -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Word64
yl)
        Operand
q       <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
UDiv Bool
False Operand
x Operand
y InstructionMetadata
md)
        Operand
z       <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Bool
-> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
Mul Bool
nsw Bool
nuw Operand
y Operand
q InstructionMetadata
md)
        Operand
r       <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Bool
-> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
Sub Bool
nsw Bool
nuw Operand
x Operand
z InstructionMetadata
md)
        (Operand
qh,Operand
ql) <- Operand -> CodeGen arch (Operand, Operand)
forall arch. Operand -> CodeGen arch (Operand, Operand)
unpackWord128 Operand
q
        (Operand
rh,Operand
rl) <- Operand -> CodeGen arch (Operand, Operand)
forall arch. Operand -> CodeGen arch (Operand, Operand)
unpackWord128 Operand
r
        Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
-> CodeGen
     arch
     (Operands (((), (((), Word64), Word64)), (((), Word64), Word64)))
forall (m :: * -> *) a. Monad m => a -> m a
return (Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
 -> CodeGen
      arch
      (Operands (((), (((), Word64), Word64)), (((), Word64), Word64))))
-> Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
-> CodeGen
     arch
     (Operands (((), (((), Word64), Word64)), (((), Word64), Word64)))
forall a b. (a -> b) -> a -> b
$ Operands ()
OP_Unit Operands ()
-> Operands (((), Word64), Word64)
-> Operands ((), (((), Word64), Word64))
forall a b. Operands a -> Operands b -> Operands (a, b)
`OP_Pair` Operand -> Operand -> Operands (EltR Word128)
upcastWord128 Operand
qh Operand
ql Operands ((), (((), Word64), Word64))
-> Operands (((), Word64), Word64)
-> Operands (((), (((), Word64), Word64)), (((), Word64), Word64))
forall a b. Operands a -> Operands b -> Operands (a, b)
`OP_Pair` Operand -> Operand -> Operands (EltR Word128)
upcastWord128 Operand
rh Operand
rl


-- Helpers

prim_binaryWord128
    :: (Operand -> Operand -> InstructionMetadata -> Instruction)
    -> Operands (EltR Word128)
    -> Operands (EltR Word128)
    -> CodeGen arch (Operands (EltR Word128))
prim_binaryWord128 :: (Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Word128)
-> Operands (EltR Word128)
-> CodeGen arch (Operands (EltR Word128))
prim_binaryWord128 Operand -> Operand -> InstructionMetadata -> Instruction
op Operands (EltR Word128)
xx Operands (EltR Word128)
yy
  | OP_Pair (OP_Pair OP_Unit (OP_Word64 xh)) (OP_Word64 xl) <- Operands (EltR Word128)
xx
  , OP_Pair (OP_Pair OP_Unit (OP_Word64 yh)) (OP_Word64 yl) <- Operands (EltR Word128)
yy
  = do
      Operand
x'      <- Operand -> Operand -> CodeGen arch Operand
forall arch. Operand -> Operand -> CodeGen arch Operand
packWord128 (Operand Word64 -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Word64
xh) (Operand Word64 -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Word64
xl)
      Operand
y'      <- Operand -> Operand -> CodeGen arch Operand
forall arch. Operand -> Operand -> CodeGen arch Operand
packWord128 (Operand Word64 -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Word64
yh) (Operand Word64 -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Word64
yl)
      Operand
r       <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Operand -> Operand -> InstructionMetadata -> Instruction
op Operand
x' Operand
y' InstructionMetadata
md)
      (Operand
hi,Operand
lo) <- Operand -> CodeGen arch (Operand, Operand)
forall arch. Operand -> CodeGen arch (Operand, Operand)
unpackWord128 Operand
r
      Operands (((), Word64), Word64)
-> CodeGen arch (Operands (((), Word64), Word64))
forall (m :: * -> *) a. Monad m => a -> m a
return (Operands (((), Word64), Word64)
 -> CodeGen arch (Operands (((), Word64), Word64)))
-> Operands (((), Word64), Word64)
-> CodeGen arch (Operands (((), Word64), Word64))
forall a b. (a -> b) -> a -> b
$ Operand -> Operand -> Operands (EltR Word128)
upcastWord128 Operand
hi Operand
lo

prim_binaryInt128
    :: (Operand -> Operand -> InstructionMetadata -> Instruction)
    -> Operands (EltR Int128)
    -> Operands (EltR Int128)
    -> CodeGen arch (Operands (EltR Int128))
prim_binaryInt128 :: (Operand -> Operand -> InstructionMetadata -> Instruction)
-> Operands (EltR Int128)
-> Operands (EltR Int128)
-> CodeGen arch (Operands (EltR Int128))
prim_binaryInt128 Operand -> Operand -> InstructionMetadata -> Instruction
op Operands (EltR Int128)
xx Operands (EltR Int128)
yy
  | OP_Pair (OP_Pair OP_Unit (OP_Int64 xh)) (OP_Word64 xl) <- Operands (EltR Int128)
xx
  , OP_Pair (OP_Pair OP_Unit (OP_Int64 yh)) (OP_Word64 yl) <- Operands (EltR Int128)
yy
  = do
      Operand
x'      <- Operand -> Operand -> CodeGen arch Operand
forall arch. Operand -> Operand -> CodeGen arch Operand
packInt128 (Operand Int64 -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Int64
xh) (Operand Word64 -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Word64
xl)
      Operand
y'      <- Operand -> Operand -> CodeGen arch Operand
forall arch. Operand -> Operand -> CodeGen arch Operand
packInt128 (Operand Int64 -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Int64
yh) (Operand Word64 -> Operand
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast Operand Word64
yl)
      Operand
r       <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Operand -> Operand -> InstructionMetadata -> Instruction
op Operand
x' Operand
y' InstructionMetadata
md)
      (Operand
hi,Operand
lo) <- Operand -> CodeGen arch (Operand, Operand)
forall arch. Operand -> CodeGen arch (Operand, Operand)
unpackInt128 Operand
r
      Operands (((), Int64), Word64)
-> CodeGen arch (Operands (((), Int64), Word64))
forall (m :: * -> *) a. Monad m => a -> m a
return (Operands (((), Int64), Word64)
 -> CodeGen arch (Operands (((), Int64), Word64)))
-> Operands (((), Int64), Word64)
-> CodeGen arch (Operands (((), Int64), Word64))
forall a b. (a -> b) -> a -> b
$ Operand -> Operand -> Operands (EltR Int128)
upcastInt128 Operand
hi Operand
lo


-- Prim
-- ----

nsw :: Bool
nsw :: Bool
nsw = Bool
False

nuw :: Bool
nuw :: Bool
nuw = Bool
False

md :: InstructionMetadata
md :: InstructionMetadata
md = []

fresh :: CodeGen arch Name
fresh :: CodeGen arch Name
fresh = Name Any -> Name
forall typed untyped.
(Downcast typed untyped, HasCallStack) =>
typed -> untyped
downcast (Name Any -> Name) -> CodeGen arch (Name Any) -> CodeGen arch Name
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> CodeGen arch (Name Any)
forall arch a. CodeGen arch (Name a)
freshName

instr :: Type -> Instruction -> CodeGen arch Operand
instr :: Type -> Instruction -> CodeGen arch Operand
instr Type
ty Instruction
ins = do
  Name
name <- CodeGen arch Name
forall arch. CodeGen arch Name
fresh
  Named Instruction -> CodeGen arch ()
forall arch. HasCallStack => Named Instruction -> CodeGen arch ()
instr_ (Name
name Name -> Instruction -> Named Instruction
forall a. Name -> a -> Named a
:= Instruction
ins)
  Operand -> CodeGen arch Operand
forall (m :: * -> *) a. Monad m => a -> m a
return (Type -> Name -> Operand
LocalReference Type
ty Name
name)

packInt128 :: Operand -> Operand -> CodeGen arch Operand
packInt128 :: Operand -> Operand -> CodeGen arch Operand
packInt128 Operand
hi Operand
lo = do
  Operand
a <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Operand -> Type -> InstructionMetadata -> Instruction
SExt Operand
hi Type
i128 InstructionMetadata
md)
  Operand
b <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Bool
-> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
Shl  Bool
nsw Bool
nuw Operand
a (Constant -> Operand
ConstantOperand (Word32 -> Integer -> Constant
Int Word32
128 Integer
64)) InstructionMetadata
md)
  Operand
c <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Operand -> Type -> InstructionMetadata -> Instruction
ZExt Operand
lo Type
i128 InstructionMetadata
md)
  Operand
d <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Operand -> Operand -> InstructionMetadata -> Instruction
Or Operand
b Operand
c InstructionMetadata
md)
  Operand -> CodeGen arch Operand
forall (m :: * -> *) a. Monad m => a -> m a
return Operand
d

packWord128 :: Operand -> Operand -> CodeGen arch Operand
packWord128 :: Operand -> Operand -> CodeGen arch Operand
packWord128 Operand
hi Operand
lo = do
  Operand
a <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Operand -> Type -> InstructionMetadata -> Instruction
ZExt Operand
hi Type
i128 InstructionMetadata
md)
  Operand
b <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Bool
-> Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
Shl  Bool
nsw Bool
nuw Operand
a (Constant -> Operand
ConstantOperand (Word32 -> Integer -> Constant
Int Word32
128 Integer
64)) InstructionMetadata
md)
  Operand
c <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Operand -> Type -> InstructionMetadata -> Instruction
ZExt Operand
lo Type
i128 InstructionMetadata
md)
  Operand
d <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Operand -> Operand -> InstructionMetadata -> Instruction
Or Operand
b Operand
c InstructionMetadata
md)
  Operand -> CodeGen arch Operand
forall (m :: * -> *) a. Monad m => a -> m a
return Operand
d

unpackInt128 :: Operand -> CodeGen arch (Operand,Operand)
unpackInt128 :: Operand -> CodeGen arch (Operand, Operand)
unpackInt128 Operand
x = do
  Operand
a <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
AShr Bool
False Operand
x (Constant -> Operand
ConstantOperand (Word32 -> Integer -> Constant
Int Word32
128 Integer
64)) InstructionMetadata
md)
  Operand
b <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i64 (Operand -> Type -> InstructionMetadata -> Instruction
Trunc Operand
a Type
i64 InstructionMetadata
md)
  Operand
c <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i64 (Operand -> Type -> InstructionMetadata -> Instruction
Trunc Operand
x Type
i64 InstructionMetadata
md)
  (Operand, Operand) -> CodeGen arch (Operand, Operand)
forall (m :: * -> *) a. Monad m => a -> m a
return (Operand
b,Operand
c)

unpackWord128 :: Operand -> CodeGen arch (Operand,Operand)
unpackWord128 :: Operand -> CodeGen arch (Operand, Operand)
unpackWord128 Operand
x = do
  Operand
a <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i128 (Bool -> Operand -> Operand -> InstructionMetadata -> Instruction
LShr Bool
False Operand
x (Constant -> Operand
ConstantOperand (Word32 -> Integer -> Constant
Int Word32
128 Integer
64)) InstructionMetadata
md)
  Operand
b <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i64 (Operand -> Type -> InstructionMetadata -> Instruction
Trunc Operand
a Type
i64 InstructionMetadata
md)
  Operand
c <- Type -> Instruction -> CodeGen arch Operand
forall arch. Type -> Instruction -> CodeGen arch Operand
instr Type
i64 (Operand -> Type -> InstructionMetadata -> Instruction
Trunc Operand
x Type
i64 InstructionMetadata
md)
  (Operand, Operand) -> CodeGen arch (Operand, Operand)
forall (m :: * -> *) a. Monad m => a -> m a
return (Operand
b,Operand
c)

upcastInt64 :: HasCallStack => Operand -> Operands Int64
upcastInt64 :: Operand -> Operands Int64
upcastInt64 (LocalReference (IntegerType Word32
64) (UnName Word
x)) = Operand Int64 -> Operands Int64
OP_Int64 (Type Int64 -> Name Int64 -> Operand Int64
forall a. Type a -> Name a -> Operand a
A.LocalReference Type Int64
forall a. IsType a => Type a
A.type' (Word -> Name Int64
forall a. Word -> Name a
A.UnName Word
x))
upcastInt64 Operand
_ = String -> Operands Int64
forall a. HasCallStack => String -> a
internalError String
"expected local reference"

upcastWord64 :: HasCallStack => Operand -> Operands Word64
upcastWord64 :: Operand -> Operands Word64
upcastWord64 (LocalReference (IntegerType Word32
64) (UnName Word
x)) = Operand Word64 -> Operands Word64
OP_Word64 (Type Word64 -> Name Word64 -> Operand Word64
forall a. Type a -> Name a -> Operand a
A.LocalReference Type Word64
forall a. IsType a => Type a
A.type' (Word -> Name Word64
forall a. Word -> Name a
A.UnName Word
x))
upcastWord64 Operand
_ = String -> Operands Word64
forall a. HasCallStack => String -> a
internalError String
"expected local reference"

upcastInt128 :: Operand -> Operand -> Operands (EltR Int128)
upcastInt128 :: Operand -> Operand -> Operands (EltR Int128)
upcastInt128 Operand
hi Operand
lo = Operands ((), Int64)
-> Operands Word64 -> Operands (((), Int64), Word64)
forall a b. Operands a -> Operands b -> Operands (a, b)
OP_Pair (Operands () -> Operands Int64 -> Operands ((), Int64)
forall a b. Operands a -> Operands b -> Operands (a, b)
OP_Pair Operands ()
OP_Unit (HasCallStack => Operand -> Operands Int64
Operand -> Operands Int64
upcastInt64 Operand
hi)) (HasCallStack => Operand -> Operands Word64
Operand -> Operands Word64
upcastWord64 Operand
lo)

upcastWord128 :: Operand -> Operand -> Operands (EltR Word128)
upcastWord128 :: Operand -> Operand -> Operands (EltR Word128)
upcastWord128 Operand
hi Operand
lo = Operands ((), Word64)
-> Operands Word64 -> Operands (((), Word64), Word64)
forall a b. Operands a -> Operands b -> Operands (a, b)
OP_Pair (Operands () -> Operands Word64 -> Operands ((), Word64)
forall a b. Operands a -> Operands b -> Operands (a, b)
OP_Pair Operands ()
OP_Unit (HasCallStack => Operand -> Operands Word64
Operand -> Operands Word64
upcastWord64 Operand
hi)) (HasCallStack => Operand -> Operands Word64
Operand -> Operands Word64
upcastWord64 Operand
lo)