cmmPrimOpFunctions :: CallishMachOp -> LlvmM LMString
cmmPrimOpFunctions mop = do

  dflags <- getDynFlags
  let intrinTy1 = "p0i8.p0i8." ++ showSDoc dflags (ppr $ llvmWord dflags)
      intrinTy2 = "p0i8." ++ showSDoc dflags (ppr $ llvmWord dflags)
      unsupported = panic ("cmmPrimOpFunctions: " ++ show mop
                        ++ " not supported here")

  return $ case mop of
    MO_F32_Exp    -> fsLit "expf"
    MO_F32_Log    -> fsLit "logf"
    MO_F32_Sqrt   -> fsLit "llvm.sqrt.f32"
    MO_F32_Fabs   -> fsLit "llvm.fabs.f32"
    MO_F32_Pwr    -> fsLit "llvm.pow.f32"

    MO_F32_Sin    -> fsLit "llvm.sin.f32"
    MO_F32_Cos    -> fsLit "llvm.cos.f32"
    MO_F32_Tan    -> fsLit "tanf"

    MO_F32_Asin   -> fsLit "asinf"
    MO_F32_Acos   -> fsLit "acosf"
    MO_F32_Atan   -> fsLit "atanf"

    MO_F32_Sinh   -> fsLit "sinhf"
    MO_F32_Cosh   -> fsLit "coshf"
    MO_F32_Tanh   -> fsLit "tanhf"

    MO_F64_Exp    -> fsLit "exp"
    MO_F64_Log    -> fsLit "log"
    MO_F64_Sqrt   -> fsLit "llvm.sqrt.f64"
    MO_F64_Fabs   -> fsLit "llvm.fabs.f64"
    MO_F64_Pwr    -> fsLit "llvm.pow.f64"

    MO_F64_Sin    -> fsLit "llvm.sin.f64"
    MO_F64_Cos    -> fsLit "llvm.cos.f64"
    MO_F64_Tan    -> fsLit "tan"

    MO_F64_Asin   -> fsLit "asin"
    MO_F64_Acos   -> fsLit "acos"
    MO_F64_Atan   -> fsLit "atan"

    MO_F64_Sinh   -> fsLit "sinh"
    MO_F64_Cosh   -> fsLit "cosh"
    MO_F64_Tanh   -> fsLit "tanh"

    MO_Memcpy _   -> fsLit $ "llvm.memcpy."  ++ intrinTy1
    MO_Memmove _  -> fsLit $ "llvm.memmove." ++ intrinTy1
    MO_Memset _   -> fsLit $ "llvm.memset."  ++ intrinTy2
    MO_Memcmp _   -> fsLit $ "memcmp"

    (MO_PopCnt w) -> fsLit $ "llvm.ctpop."  ++ showSDoc dflags (ppr $ widthToLlvmInt w)
    (MO_BSwap w)  -> fsLit $ "llvm.bswap."  ++ showSDoc dflags (ppr $ widthToLlvmInt w)
    (MO_Clz w)    -> fsLit $ "llvm.ctlz."   ++ showSDoc dflags (ppr $ widthToLlvmInt w)
    (MO_Ctz w)    -> fsLit $ "llvm.cttz."   ++ showSDoc dflags (ppr $ widthToLlvmInt w)

    (MO_Prefetch_Data _ )-> fsLit "llvm.prefetch"

    MO_AddIntC w    -> fsLit $ "llvm.sadd.with.overflow."
                             ++ showSDoc dflags (ppr $ widthToLlvmInt w)
    MO_SubIntC w    -> fsLit $ "llvm.ssub.with.overflow."
                             ++ showSDoc dflags (ppr $ widthToLlvmInt w)
    MO_Add2 w       -> fsLit $ "llvm.uadd.with.overflow."
                             ++ showSDoc dflags (ppr $ widthToLlvmInt w)
    MO_SubWordC w   -> fsLit $ "llvm.usub.with.overflow."
                             ++ showSDoc dflags (ppr $ widthToLlvmInt w)

    MO_S_QuotRem {}  -> unsupported
    MO_U_QuotRem {}  -> unsupported
    MO_U_QuotRem2 {} -> unsupported
    -- We support MO_U_Mul2 through ordinary LLVM mul instruction, see the
    -- appropriate case of genCall.
    MO_U_Mul2 {}     -> unsupported
    MO_WriteBarrier  -> unsupported
    MO_Touch         -> unsupported
    MO_UF_Conv _     -> unsupported

    MO_AtomicRead _  -> unsupported
    MO_AtomicRMW _ _ -> unsupported
    MO_AtomicWrite _ -> unsupported
    MO_Cmpxchg _     -> unsupported

-- | Tail function calls
cmmPrimOpFunctions :: CallishMachOp -> LlvmM LMString
cmmPrimOpFunctions mop = do

  dflags <- getDynFlags
  let intrinTy1 = "p0i8.p0i8." ++ showSDoc dflags (ppr $ llvmWord dflags)
      intrinTy2 = "p0i8." ++ showSDoc dflags (ppr $ llvmWord dflags)
      unsupported = panic ("cmmPrimOpFunctions: " ++ show mop
                        ++ " not supported here")

  return $ case mop of
    MO_F32_Exp    -> fsLit "expf"
    MO_F32_Log    -> fsLit "logf"
    MO_F32_Sqrt   -> fsLit "llvm.sqrt.f32"
    MO_F32_Fabs   -> fsLit "llvm.fabs.f32"
    MO_F32_Pwr    -> fsLit "llvm.pow.f32"

    MO_F32_Sin    -> fsLit "llvm.sin.f32"
    MO_F32_Cos    -> fsLit "llvm.cos.f32"
    MO_F32_Tan    -> fsLit "tanf"

    MO_F32_Asin   -> fsLit "asinf"
    MO_F32_Acos   -> fsLit "acosf"
    MO_F32_Atan   -> fsLit "atanf"

    MO_F32_Sinh   -> fsLit "sinhf"
    MO_F32_Cosh   -> fsLit "coshf"
    MO_F32_Tanh   -> fsLit "tanhf"

    MO_F64_Exp    -> fsLit "exp"
    MO_F64_Log    -> fsLit "log"
    MO_F64_Sqrt   -> fsLit "llvm.sqrt.f64"
    MO_F64_Fabs   -> fsLit "llvm.fabs.f64"
    MO_F64_Pwr    -> fsLit "llvm.pow.f64"

    MO_F64_Sin    -> fsLit "llvm.sin.f64"
    MO_F64_Cos    -> fsLit "llvm.cos.f64"
    MO_F64_Tan    -> fsLit "tan"

    MO_F64_Asin   -> fsLit "asin"
    MO_F64_Acos   -> fsLit "acos"
    MO_F64_Atan   -> fsLit "atan"

    MO_F64_Sinh   -> fsLit "sinh"
    MO_F64_Cosh   -> fsLit "cosh"
    MO_F64_Tanh   -> fsLit "tanh"

    MO_Memcpy _   -> fsLit $ "llvm.memcpy."  ++ intrinTy1
    MO_Memmove _  -> fsLit $ "llvm.memmove." ++ intrinTy1
    MO_Memset _   -> fsLit $ "llvm.memset."  ++ intrinTy2
    MO_Memcmp _   -> fsLit $ "memcmp"

    (MO_PopCnt w) -> fsLit $ "llvm.ctpop."  ++ showSDoc dflags (ppr $ widthToLlvmInt w)
    (MO_BSwap w)  -> fsLit $ "llvm.bswap."  ++ showSDoc dflags (ppr $ widthToLlvmInt w)
    (MO_Clz w)    -> fsLit $ "llvm.ctlz."   ++ showSDoc dflags (ppr $ widthToLlvmInt w)
    (MO_Ctz w)    -> fsLit $ "llvm.cttz."   ++ showSDoc dflags (ppr $ widthToLlvmInt w)

    (MO_Prefetch_Data _ )-> fsLit "llvm.prefetch"

    MO_AddIntC w    -> fsLit $ "llvm.sadd.with.overflow."
                             ++ showSDoc dflags (ppr $ widthToLlvmInt w)
    MO_SubIntC w    -> fsLit $ "llvm.ssub.with.overflow."
                             ++ showSDoc dflags (ppr $ widthToLlvmInt w)
    MO_Add2 w       -> fsLit $ "llvm.uadd.with.overflow."
                             ++ showSDoc dflags (ppr $ widthToLlvmInt w)
    MO_SubWordC w   -> fsLit $ "llvm.usub.with.overflow."
                             ++ showSDoc dflags (ppr $ widthToLlvmInt w)

    MO_S_QuotRem {}  -> unsupported
    MO_U_QuotRem {}  -> unsupported
    MO_U_QuotRem2 {} -> unsupported
    -- We support MO_U_Mul2 through ordinary LLVM mul instruction, see the
    -- appropriate case of genCall.
    MO_U_Mul2 {}     -> unsupported
    MO_WriteBarrier  -> unsupported
    MO_Touch         -> unsupported
    MO_UF_Conv _     -> unsupported

    MO_AtomicRead _  -> unsupported
    MO_AtomicRMW _ _ -> unsupported
    MO_AtomicWrite _ -> unsupported
    MO_Cmpxchg _     -> unsupported

-- | Tail function calls
cmmPrimOpFunctions mop = do

  dflags <- getDynFlags
  let intrinTy1 = "p0i8.p0i8." ++ showSDoc dflags (ppr $ llvmWord dflags)
      intrinTy2 = "p0i8." ++ showSDoc dflags (ppr $ llvmWord dflags)
      unsupported = panic ("cmmPrimOpFunctions: " ++ show mop
                        ++ " not supported here")

  return $ case mop of
    MO_F32_Exp    -> fsLit "expf"
    MO_F32_Log    -> fsLit "logf"
    MO_F32_Sqrt   -> fsLit "llvm.sqrt.f32"
    MO_F32_Fabs   -> fsLit "llvm.fabs.f32"
    MO_F32_Pwr    -> fsLit "llvm.pow.f32"

    MO_F32_Sin    -> fsLit "llvm.sin.f32"
    MO_F32_Cos    -> fsLit "llvm.cos.f32"
    MO_F32_Tan    -> fsLit "tanf"

    MO_F32_Asin   -> fsLit "asinf"
    MO_F32_Acos   -> fsLit "acosf"
    MO_F32_Atan   -> fsLit "atanf"

    MO_F32_Sinh   -> fsLit "sinhf"
    MO_F32_Cosh   -> fsLit "coshf"
    MO_F32_Tanh   -> fsLit "tanhf"

    MO_F64_Exp    -> fsLit "exp"
    MO_F64_Log    -> fsLit "log"
    MO_F64_Sqrt   -> fsLit "llvm.sqrt.f64"
    MO_F64_Fabs   -> fsLit "llvm.fabs.f64"
    MO_F64_Pwr    -> fsLit "llvm.pow.f64"

    MO_F64_Sin    -> fsLit "llvm.sin.f64"
    MO_F64_Cos    -> fsLit "llvm.cos.f64"
    MO_F64_Tan    -> fsLit "tan"

    MO_F64_Asin   -> fsLit "asin"
    MO_F64_Acos   -> fsLit "acos"
    MO_F64_Atan   -> fsLit "atan"

    MO_F64_Sinh   -> fsLit "sinh"
    MO_F64_Cosh   -> fsLit "cosh"
    MO_F64_Tanh   -> fsLit "tanh"

    MO_Memcpy _   -> fsLit $ "llvm.memcpy."  ++ intrinTy1
    MO_Memmove _  -> fsLit $ "llvm.memmove." ++ intrinTy1
    MO_Memset _   -> fsLit $ "llvm.memset."  ++ intrinTy2
    MO_Memcmp _   -> fsLit $ "memcmp"

    (MO_PopCnt w) -> fsLit $ "llvm.ctpop."  ++ showSDoc dflags (ppr $ widthToLlvmInt w)
    (MO_BSwap w)  -> fsLit $ "llvm.bswap."  ++ showSDoc dflags (ppr $ widthToLlvmInt w)
    (MO_Clz w)    -> fsLit $ "llvm.ctlz."   ++ showSDoc dflags (ppr $ widthToLlvmInt w)
    (MO_Ctz w)    -> fsLit $ "llvm.cttz."   ++ showSDoc dflags (ppr $ widthToLlvmInt w)

    (MO_Prefetch_Data _ )-> fsLit "llvm.prefetch"

    MO_AddIntC w    -> fsLit $ "llvm.sadd.with.overflow."
                             ++ showSDoc dflags (ppr $ widthToLlvmInt w)
    MO_SubIntC w    -> fsLit $ "llvm.ssub.with.overflow."
                             ++ showSDoc dflags (ppr $ widthToLlvmInt w)
    MO_Add2 w       -> fsLit $ "llvm.uadd.with.overflow."
                             ++ showSDoc dflags (ppr $ widthToLlvmInt w)
    MO_SubWordC w   -> fsLit $ "llvm.usub.with.overflow."
                             ++ showSDoc dflags (ppr $ widthToLlvmInt w)

    MO_S_QuotRem {}  -> unsupported
    MO_U_QuotRem {}  -> unsupported
    MO_U_QuotRem2 {} -> unsupported
    -- We support MO_U_Mul2 through ordinary LLVM mul instruction, see the
    -- appropriate case of genCall.
    MO_U_Mul2 {}     -> unsupported
    MO_WriteBarrier  -> unsupported
    MO_Touch         -> unsupported
    MO_UF_Conv _     -> unsupported

    MO_AtomicRead _  -> unsupported
    MO_AtomicRMW _ _ -> unsupported
    MO_AtomicWrite _ -> unsupported
    MO_Cmpxchg _     -> unsupported

-- | Tail function calls