    {-# LANGUAGE CPP #-}
    {-# LANGUAGE LambdaCase #-}

    -- Workaround for #21972. It can be removed once the minimal bootstrapping
    -- compiler has a fix for this bug.
    #if defined(darwin_HOST_OS)
    {-# OPTIONS_GHC -fno-asm-shortcutting #-}
    #endif

    --------------------------------------------------------------------------------
    -- | The LLVM Type System.
    --

    module GHC.Llvm.Types where

    import GHC.Prelude

    import Data.Char
    import Numeric

    import GHC.Platform
    import GHC.Data.FastString
    import GHC.Utils.Outputable
    import GHC.Utils.Panic
    import GHC.Types.Unique

    -- from NCG
    import GHC.CmmToAsm.Ppr

    import GHC.Float

    -- -----------------------------------------------------------------------------
    -- * LLVM Basic Types and Variables
    --

    -- | A global mutable variable. Maybe defined or external
    data LMGlobal = LMGlobal {
      LMGlobal -> LlvmVar
    getGlobalVar :: LlvmVar,          -- ^ Returns the variable of the 'LMGlobal'
      LMGlobal -> Maybe LlvmStatic
    getGlobalValue :: Maybe LlvmStatic -- ^ Return the value of the 'LMGlobal'
      }

    -- | A String in LLVM
    type LMString = FastString

    -- | A type alias
    type LlvmAlias = (LMString, LlvmType)

    -- | Llvm Types
    data LlvmType
      = LMInt Int             -- ^ An integer with a given width in bits.
      | LMFloat               -- ^ 32 bit floating point
      | LMDouble              -- ^ 64 bit floating point
      | LMFloat80             -- ^ 80 bit (x86 only) floating point
      | LMFloat128            -- ^ 128 bit floating point
      | LMPointer LlvmType    -- ^ A pointer to a 'LlvmType'
      | LMArray Int LlvmType  -- ^ An array of 'LlvmType'
      | LMVector Int LlvmType -- ^ A vector of 'LlvmType'
      | LMLabel               -- ^ A 'LlvmVar' can represent a label (address)
      | LMVoid                -- ^ Void type
      | LMStruct [LlvmType]   -- ^ Packed structure type
      | LMStructU [LlvmType]  -- ^ Unpacked structure type
      | LMAlias LlvmAlias     -- ^ A type alias
      | LMMetadata            -- ^ LLVM Metadata

      -- | Function type, used to create pointers to functions
      | LMFunction LlvmFunctionDecl
      deriving (LlvmType -> LlvmType -> Bool
    (LlvmType -> LlvmType -> Bool)
    -> (LlvmType -> LlvmType -> Bool) -> Eq LlvmType
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: LlvmType -> LlvmType -> Bool
    == :: LlvmType -> LlvmType -> Bool
    $c/= :: LlvmType -> LlvmType -> Bool
    /= :: LlvmType -> LlvmType -> Bool
    Eq)

    instance Outputable LlvmType where
      ppr :: LlvmType -> SDoc
    ppr = LlvmType -> SDoc
    forall doc. IsLine doc => LlvmType -> doc
    ppLlvmType

    ppLlvmType :: IsLine doc => LlvmType -> doc
    ppLlvmType :: forall doc. IsLine doc => LlvmType -> doc
    ppLlvmType LlvmType
    t = case LlvmType
    t of
      LMInt Int
    size     -> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    'i' doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Int -> doc
    forall doc. IsLine doc => Int -> doc
    int Int
    size
      LlvmType
    LMFloat        -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "float"
      LlvmType
    LMDouble       -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "double"
      LlvmType
    LMFloat80      -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "x86_fp80"
      LlvmType
    LMFloat128     -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "fp128"
      LMPointer LlvmType
    x    -> LlvmType -> doc
    forall doc. IsLine doc => LlvmType -> doc
    ppLlvmType LlvmType
    x doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '*'
      LMArray Int
    nr LlvmType
    tp  -> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '[' doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Int -> doc
    forall doc. IsLine doc => Int -> doc
    int Int
    nr doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    " x " doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> LlvmType -> doc
    forall doc. IsLine doc => LlvmType -> doc
    ppLlvmType LlvmType
    tp doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    ']'
      LMVector Int
    nr LlvmType
    tp -> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '<' doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Int -> doc
    forall doc. IsLine doc => Int -> doc
    int Int
    nr doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    " x " doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> LlvmType -> doc
    forall doc. IsLine doc => LlvmType -> doc
    ppLlvmType LlvmType
    tp doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '>'
      LlvmType
    LMLabel        -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "label"
      LlvmType
    LMVoid         -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "void"
      LMStruct [LlvmType]
    tys   -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "<{" doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> (LlvmType -> doc) -> [LlvmType] -> doc
    forall doc a. IsLine doc => (a -> doc) -> [a] -> doc
    ppCommaJoin LlvmType -> doc
    forall doc. IsLine doc => LlvmType -> doc
    ppLlvmType [LlvmType]
    tys doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "}>"
      LMStructU [LlvmType]
    tys  -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "{" doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> (LlvmType -> doc) -> [LlvmType] -> doc
    forall doc a. IsLine doc => (a -> doc) -> [a] -> doc
    ppCommaJoin LlvmType -> doc
    forall doc. IsLine doc => LlvmType -> doc
    ppLlvmType [LlvmType]
    tys doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "}"
      LlvmType
    LMMetadata     -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "metadata"
      LMAlias (FastString
    s,LlvmType
    _)  -> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '%' doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> FastString -> doc
    forall doc. IsLine doc => FastString -> doc
    ftext FastString
    s
      LMFunction (LlvmFunctionDecl FastString
    _ LlvmLinkageType
    _ LlvmCallConvention
    _ LlvmType
    r LlvmParameterListType
    varg [LlvmParameter]
    p LMAlign
    _)
        -> LlvmType -> doc
    forall doc. IsLine doc => LlvmType -> doc
    ppLlvmType LlvmType
    r doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> doc
    forall doc. IsLine doc => doc
    lparen doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> LlvmParameterListType -> [LlvmParameter] -> doc
    forall doc.
    IsLine doc =>
    LlvmParameterListType -> [LlvmParameter] -> doc
    ppParams LlvmParameterListType
    varg [LlvmParameter]
    p doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> doc
    forall doc. IsLine doc => doc
    rparen
    {-# SPECIALIZE ppLlvmType :: LlvmType -> SDoc #-}
    {-# SPECIALIZE ppLlvmType :: LlvmType -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable

    ppParams :: IsLine doc => LlvmParameterListType -> [LlvmParameter] -> doc
    ppParams :: forall doc.
    IsLine doc =>
    LlvmParameterListType -> [LlvmParameter] -> doc
    ppParams LlvmParameterListType
    varg [LlvmParameter]
    p
      = let varg' :: doc
    varg' = case LlvmParameterListType
    varg of
              LlvmParameterListType
    VarArgs | [LlvmType] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [LlvmType]
    args -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "..."
                      | Bool
    otherwise -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    ", ..."
              LlvmParameterListType
    _otherwise          -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    ""
            -- by default we don't print param attributes
            args :: [LlvmType]
    args = (LlvmParameter -> LlvmType) -> [LlvmParameter] -> [LlvmType]
    forall a b. (a -> b) -> [a] -> [b]
    map LlvmParameter -> LlvmType
    forall a b. (a, b) -> a
    fst [LlvmParameter]
    p
        in (LlvmType -> doc) -> [LlvmType] -> doc
    forall doc a. IsLine doc => (a -> doc) -> [a] -> doc
    ppCommaJoin LlvmType -> doc
    forall doc. IsLine doc => LlvmType -> doc
    ppLlvmType [LlvmType]
    args doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> doc
    varg'
    {-# SPECIALIZE ppParams :: LlvmParameterListType -> [LlvmParameter] -> SDoc #-}
    {-# SPECIALIZE ppParams :: LlvmParameterListType -> [LlvmParameter] -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable

    -- | An LLVM section definition. If Nothing then let LLVM decide the section
    type LMSection = Maybe LMString
    type LMAlign = Maybe Int

    data LMConst = Global      -- ^ Mutable global variable
                 | Constant    -- ^ Constant global variable
                 | Alias       -- ^ Alias of another variable
                 deriving (LMConst -> LMConst -> Bool
    (LMConst -> LMConst -> Bool)
    -> (LMConst -> LMConst -> Bool) -> Eq LMConst
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: LMConst -> LMConst -> Bool
    == :: LMConst -> LMConst -> Bool
    $c/= :: LMConst -> LMConst -> Bool
    /= :: LMConst -> LMConst -> Bool
    Eq)

    -- | LLVM Variables
    data LlvmVar
      -- | Variables with a global scope.
      = LMGlobalVar LMString LlvmType LlvmLinkageType LMSection LMAlign LMConst
      -- | Variables local to a function or parameters.
      | LMLocalVar Unique LlvmType
      -- | Named local variables. Sometimes we need to be able to explicitly name
      -- variables (e.g for function arguments).
      | LMNLocalVar LMString LlvmType
      -- | A constant variable
      | LMLitVar LlvmLit
      deriving (LlvmVar -> LlvmVar -> Bool
    (LlvmVar -> LlvmVar -> Bool)
    -> (LlvmVar -> LlvmVar -> Bool) -> Eq LlvmVar
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: LlvmVar -> LlvmVar -> Bool
    == :: LlvmVar -> LlvmVar -> Bool
    $c/= :: LlvmVar -> LlvmVar -> Bool
    /= :: LlvmVar -> LlvmVar -> Bool
    Eq)

    -- | Llvm Literal Data.
    --
    -- These can be used inline in expressions.
    data LlvmLit
      -- | Refers to an integer constant (i64 42).
      = LMIntLit Integer LlvmType
      -- | Floating point literal
      | LMFloatLit Double LlvmType
      -- | Literal NULL, only applicable to pointer types
      | LMNullLit LlvmType
      -- | Vector literal
      | LMVectorLit [LlvmLit]
      -- | Undefined value, random bit pattern. Useful for optimisations.
      | LMUndefLit LlvmType
      deriving (LlvmLit -> LlvmLit -> Bool
    (LlvmLit -> LlvmLit -> Bool)
    -> (LlvmLit -> LlvmLit -> Bool) -> Eq LlvmLit
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: LlvmLit -> LlvmLit -> Bool
    == :: LlvmLit -> LlvmLit -> Bool
    $c/= :: LlvmLit -> LlvmLit -> Bool
    /= :: LlvmLit -> LlvmLit -> Bool
    Eq)

    -- | Llvm Static Data.
    --
    -- These represent the possible global level variables and constants.
    data LlvmStatic
      = LMComment LMString                  -- ^ A comment in a static section
      | LMStaticLit LlvmLit                 -- ^ A static variant of a literal value
      | LMUninitType LlvmType               -- ^ For uninitialised data
      | LMStaticStr LMString LlvmType       -- ^ Defines a static 'LMString'
      | LMStaticArray [LlvmStatic] LlvmType -- ^ A static array
      | LMStaticStruc [LlvmStatic] LlvmType -- ^ A static structure type
      | LMStaticStrucU [LlvmStatic] LlvmType -- ^ A static structure type
      | LMStaticPointer LlvmVar             -- ^ A pointer to other data

      -- static expressions, could split out but leave
      -- for moment for ease of use. Not many of them.

      | LMTrunc LlvmStatic LlvmType        -- ^ Truncate
      | LMBitc LlvmStatic LlvmType         -- ^ Pointer to Pointer conversion
      | LMPtoI LlvmStatic LlvmType         -- ^ Pointer to Integer conversion
      | LMAdd LlvmStatic LlvmStatic        -- ^ Constant addition operation
      | LMSub LlvmStatic LlvmStatic        -- ^ Constant subtraction operation

    -- -----------------------------------------------------------------------------
    -- ** Operations on LLVM Basic Types and Variables
    --

    garbageLit :: LlvmType -> Maybe LlvmLit
    garbageLit :: LlvmType -> Maybe LlvmLit
    garbageLit t :: LlvmType
    t@(LMInt Int
    w)     = LlvmLit -> Maybe LlvmLit
    forall a. a -> Maybe a
    Just (Integer -> LlvmType -> LlvmLit
    LMIntLit (Integer
    0xbbbbbbbbbbbbbbb0 Integer -> Integer -> Integer
    forall a. Integral a => a -> a -> a
    `mod` (Integer
    2Integer -> Int -> Integer
    forall a b. (Num a, Integral b) => a -> b -> a
    ^Int
    w)) LlvmType
    t)
      -- Use a value that looks like an untagged pointer, so we are more
      -- likely to try to enter it
    garbageLit LlvmType
    t
      | LlvmType -> Bool
    isFloat LlvmType
    t              = LlvmLit -> Maybe LlvmLit
    forall a. a -> Maybe a
    Just (Double -> LlvmType -> LlvmLit
    LMFloatLit Double
    12345678.9 LlvmType
    t)
    garbageLit t :: LlvmType
    t@(LMPointer LlvmType
    _) = LlvmLit -> Maybe LlvmLit
    forall a. a -> Maybe a
    Just (LlvmType -> LlvmLit
    LMNullLit LlvmType
    t)
      -- Using null isn't totally ideal, since some functions may check for null.
      -- But producing another value is inconvenient since it needs a cast,
      -- and the knowledge for how to format casts is in PpLlvm.
    garbageLit LlvmType
    _               = Maybe LlvmLit
    forall a. Maybe a
    Nothing
      -- More cases could be added, but this should do for now.

    -- | Return the 'LlvmType' of the 'LlvmVar'
    getVarType :: LlvmVar -> LlvmType
    getVarType :: LlvmVar -> LlvmType
    getVarType (LMGlobalVar FastString
    _ LlvmType
    y LlvmLinkageType
    _ LMSection
    _ LMAlign
    _ LMConst
    _) = LlvmType
    y
    getVarType (LMLocalVar  Unique
    _ LlvmType
    y        ) = LlvmType
    y
    getVarType (LMNLocalVar FastString
    _ LlvmType
    y        ) = LlvmType
    y
    getVarType (LMLitVar    LlvmLit
    l          ) = LlvmLit -> LlvmType
    getLitType LlvmLit
    l

    -- | Return the 'LlvmType' of a 'LlvmLit'
    getLitType :: LlvmLit -> LlvmType
    getLitType :: LlvmLit -> LlvmType
    getLitType (LMIntLit   Integer
    _ LlvmType
    t) = LlvmType
    t
    getLitType (LMFloatLit Double
    _ LlvmType
    t) = LlvmType
    t
    getLitType (LMVectorLit [])  = String -> LlvmType
    forall a. HasCallStack => String -> a
    panic String
    "getLitType"
    getLitType (LMVectorLit ls :: [LlvmLit]
    ls@(LlvmLit
    l:[LlvmLit]
    _))  = Int -> LlvmType -> LlvmType
    LMVector ([LlvmLit] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [LlvmLit]
    ls) (LlvmLit -> LlvmType
    getLitType LlvmLit
    l)
    getLitType (LMNullLit    LlvmType
    t) = LlvmType
    t
    getLitType (LMUndefLit   LlvmType
    t) = LlvmType
    t

    -- | Return the 'LlvmType' of the 'LlvmStatic'
    getStatType :: LlvmStatic -> LlvmType
    getStatType :: LlvmStatic -> LlvmType
    getStatType (LMStaticLit   LlvmLit
    l  ) = LlvmLit -> LlvmType
    getLitType LlvmLit
    l
    getStatType (LMUninitType    LlvmType
    t) = LlvmType
    t
    getStatType (LMStaticStr   FastString
    _ LlvmType
    t) = LlvmType
    t
    getStatType (LMStaticArray [LlvmStatic]
    _ LlvmType
    t) = LlvmType
    t
    getStatType (LMStaticStruc [LlvmStatic]
    _ LlvmType
    t) = LlvmType
    t
    getStatType (LMStaticStrucU [LlvmStatic]
    _ LlvmType
    t) = LlvmType
    t
    getStatType (LMStaticPointer LlvmVar
    v) = LlvmVar -> LlvmType
    getVarType LlvmVar
    v
    getStatType (LMTrunc       LlvmStatic
    _ LlvmType
    t) = LlvmType
    t
    getStatType (LMBitc        LlvmStatic
    _ LlvmType
    t) = LlvmType
    t
    getStatType (LMPtoI        LlvmStatic
    _ LlvmType
    t) = LlvmType
    t
    getStatType (LMAdd         LlvmStatic
    t LlvmStatic
    _) = LlvmStatic -> LlvmType
    getStatType LlvmStatic
    t
    getStatType (LMSub         LlvmStatic
    t LlvmStatic
    _) = LlvmStatic -> LlvmType
    getStatType LlvmStatic
    t
    getStatType (LMComment       FastString
    _) = String -> LlvmType
    forall a. HasCallStack => String -> a
    error String
    "Can't call getStatType on LMComment!"

    -- | Return the 'LlvmLinkageType' for a 'LlvmVar'
    getLink :: LlvmVar -> LlvmLinkageType
    getLink :: LlvmVar -> LlvmLinkageType
    getLink (LMGlobalVar FastString
    _ LlvmType
    _ LlvmLinkageType
    l LMSection
    _ LMAlign
    _ LMConst
    _) = LlvmLinkageType
    l
    getLink LlvmVar
    _                         = LlvmLinkageType
    Internal

    -- | Add a pointer indirection to the supplied type. 'LMLabel' and 'LMVoid'
    -- cannot be lifted.
    pLift :: LlvmType -> LlvmType
    pLift :: LlvmType -> LlvmType
    pLift LlvmType
    LMLabel    = String -> LlvmType
    forall a. HasCallStack => String -> a
    error String
    "Labels are unliftable"
    pLift LlvmType
    LMVoid     = String -> LlvmType
    forall a. HasCallStack => String -> a
    error String
    "Voids are unliftable"
    pLift LlvmType
    LMMetadata = String -> LlvmType
    forall a. HasCallStack => String -> a
    error String
    "Metadatas are unliftable"
    pLift LlvmType
    x          = LlvmType -> LlvmType
    LMPointer LlvmType
    x

    -- | Lift a variable to 'LMPointer' type.
    pVarLift :: LlvmVar -> LlvmVar
    pVarLift :: LlvmVar -> LlvmVar
    pVarLift (LMGlobalVar FastString
    s LlvmType
    t LlvmLinkageType
    l LMSection
    x LMAlign
    a LMConst
    c) = FastString
    -> LlvmType
    -> LlvmLinkageType
    -> LMSection
    -> LMAlign
    -> LMConst
    -> LlvmVar
    LMGlobalVar FastString
    s (LlvmType -> LlvmType
    pLift LlvmType
    t) LlvmLinkageType
    l LMSection
    x LMAlign
    a LMConst
    c
    pVarLift (LMLocalVar  Unique
    s LlvmType
    t        ) = Unique -> LlvmType -> LlvmVar
    LMLocalVar  Unique
    s (LlvmType -> LlvmType
    pLift LlvmType
    t)
    pVarLift (LMNLocalVar FastString
    s LlvmType
    t        ) = FastString -> LlvmType -> LlvmVar
    LMNLocalVar FastString
    s (LlvmType -> LlvmType
    pLift LlvmType
    t)
    pVarLift (LMLitVar    LlvmLit
    _          ) = String -> LlvmVar
    forall a. HasCallStack => String -> a
    error (String -> LlvmVar) -> String -> LlvmVar
    forall a b. (a -> b) -> a -> b
    $ String
    "Can't lower a literal type!"

    -- | Remove the pointer indirection of the supplied type. Only 'LMPointer'
    -- constructors can be lowered.
    pLower :: LlvmType -> LlvmType
    pLower :: LlvmType -> LlvmType
    pLower (LMPointer LlvmType
    x) = LlvmType
    x
    pLower LlvmType
    x  = String -> SDoc -> LlvmType
    forall a. HasCallStack => String -> SDoc -> a
    pprPanic String
    "llvmGen(pLower)"
                (SDoc -> LlvmType) -> SDoc -> LlvmType
    forall a b. (a -> b) -> a -> b
    $ LlvmType -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr LlvmType
    x SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    " is a unlowerable type, need a pointer"

    -- | Lower a variable of 'LMPointer' type.
    pVarLower :: LlvmVar -> LlvmVar
    pVarLower :: LlvmVar -> LlvmVar
    pVarLower (LMGlobalVar FastString
    s LlvmType
    t LlvmLinkageType
    l LMSection
    x LMAlign
    a LMConst
    c) = FastString
    -> LlvmType
    -> LlvmLinkageType
    -> LMSection
    -> LMAlign
    -> LMConst
    -> LlvmVar
    LMGlobalVar FastString
    s (LlvmType -> LlvmType
    pLower LlvmType
    t) LlvmLinkageType
    l LMSection
    x LMAlign
    a LMConst
    c
    pVarLower (LMLocalVar  Unique
    s LlvmType
    t        ) = Unique -> LlvmType -> LlvmVar
    LMLocalVar  Unique
    s (LlvmType -> LlvmType
    pLower LlvmType
    t)
    pVarLower (LMNLocalVar FastString
    s LlvmType
    t        ) = FastString -> LlvmType -> LlvmVar
    LMNLocalVar FastString
    s (LlvmType -> LlvmType
    pLower LlvmType
    t)
    pVarLower (LMLitVar    LlvmLit
    _          ) = String -> LlvmVar
    forall a. HasCallStack => String -> a
    error (String -> LlvmVar) -> String -> LlvmVar
    forall a b. (a -> b) -> a -> b
    $ String
    "Can't lower a literal type!"

    -- | Test if the given 'LlvmType' is an integer
    isInt :: LlvmType -> Bool
    isInt :: LlvmType -> Bool
    isInt (LMInt Int
    _) = Bool
    True
    isInt LlvmType
    _         = Bool
    False

    -- | Test if the given 'LlvmType' is a floating point type
    isFloat :: LlvmType -> Bool
    isFloat :: LlvmType -> Bool
    isFloat LlvmType
    LMFloat    = Bool
    True
    isFloat LlvmType
    LMDouble   = Bool
    True
    isFloat LlvmType
    LMFloat80  = Bool
    True
    isFloat LlvmType
    LMFloat128 = Bool
    True
    isFloat LlvmType
    _          = Bool
    False

    -- | Test if the given 'LlvmType' is an 'LMPointer' construct
    isPointer :: LlvmType -> Bool
    isPointer :: LlvmType -> Bool
    isPointer (LMPointer LlvmType
    _) = Bool
    True
    isPointer LlvmType
    _             = Bool
    False

    -- | Test if the given 'LlvmType' is an 'LMVector' construct
    isVector :: LlvmType -> Bool
    isVector :: LlvmType -> Bool
    isVector (LMVector {}) = Bool
    True
    isVector LlvmType
    _             = Bool
    False

    -- | Test if a 'LlvmVar' is global.
    isGlobal :: LlvmVar -> Bool
    isGlobal :: LlvmVar -> Bool
    isGlobal (LMGlobalVar FastString
    _ LlvmType
    _ LlvmLinkageType
    _ LMSection
    _ LMAlign
    _ LMConst
    _) = Bool
    True
    isGlobal LlvmVar
    _                         = Bool
    False

    -- | Width in bits of an 'LlvmType', returns 0 if not applicable
    llvmWidthInBits :: Platform -> LlvmType -> Int
    llvmWidthInBits :: Platform -> LlvmType -> Int
    llvmWidthInBits Platform
    platform = \case
       (LMInt Int
    n)       -> Int
    n
       (LlvmType
    LMFloat)       -> Int
    32
       (LlvmType
    LMDouble)      -> Int
    64
       (LlvmType
    LMFloat80)     -> Int
    80
       (LlvmType
    LMFloat128)    -> Int
    128
       -- Could return either a pointer width here or the width of what
       -- it points to. We will go with the former for now.
       -- PMW: At least judging by the way LLVM outputs constants, pointers
       --      should use the former, but arrays the latter.
       (LMPointer LlvmType
    _)   -> Platform -> LlvmType -> Int
    llvmWidthInBits Platform
    platform (Platform -> LlvmType
    llvmWord Platform
    platform)
       (LMArray Int
    n LlvmType
    t)   -> Int
    n Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Platform -> LlvmType -> Int
    llvmWidthInBits Platform
    platform LlvmType
    t
       (LMVector Int
    n LlvmType
    ty) -> Int
    n Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Platform -> LlvmType -> Int
    llvmWidthInBits Platform
    platform LlvmType
    ty
       LlvmType
    LMLabel         -> Int
    0
       LlvmType
    LMVoid          -> Int
    0
       (LMStruct [LlvmType]
    tys)  -> [Int] -> Int
    forall a. Num a => [a] -> a
    forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
    sum ([Int] -> Int) -> [Int] -> Int
    forall a b. (a -> b) -> a -> b
    $ (LlvmType -> Int) -> [LlvmType] -> [Int]
    forall a b. (a -> b) -> [a] -> [b]
    map (Platform -> LlvmType -> Int
    llvmWidthInBits Platform
    platform) [LlvmType]
    tys
       (LMStructU [LlvmType]
    _)   ->
        -- It's not trivial to calculate the bit width of the unpacked structs,
        -- since they will be aligned depending on the specified datalayout (
        -- http://llvm.org/docs/LangRef.html#data-layout ). One way we could support
        -- this could be to make the GHC.CmmToLlvm.Ppr.moduleLayout be a data type
        -- that exposes the alignment information. However, currently the only place
        -- we use unpacked structs is LLVM intrinsics that return them (e.g.,
        -- llvm.sadd.with.overflow.*), so we don't actually need to compute their
        -- bit width.
        String -> Int
    forall a. HasCallStack => String -> a
    panic String
    "llvmWidthInBits: not implemented for LMStructU"
       (LMFunction  LlvmFunctionDecl
    _) -> Int
    0
       (LMAlias (FastString
    _,LlvmType
    t)) -> Platform -> LlvmType -> Int
    llvmWidthInBits Platform
    platform LlvmType
    t
       LlvmType
    LMMetadata      -> String -> Int
    forall a. HasCallStack => String -> a
    panic String
    "llvmWidthInBits: Meta-data has no runtime representation!"

    -- -----------------------------------------------------------------------------
    -- ** Shortcut for Common Types
    --

    i128, i64, i32, i16, i8, i1, i8Ptr :: LlvmType
    i128 :: LlvmType
    i128  = Int -> LlvmType
    LMInt Int
    128
    i64 :: LlvmType
    i64   = Int -> LlvmType
    LMInt  Int
    64
    i32 :: LlvmType
    i32   = Int -> LlvmType
    LMInt  Int
    32
    i16 :: LlvmType
    i16   = Int -> LlvmType
    LMInt  Int
    16
    i8 :: LlvmType
    i8    = Int -> LlvmType
    LMInt   Int
    8
    i1 :: LlvmType
    i1    = Int -> LlvmType
    LMInt   Int
    1
    i8Ptr :: LlvmType
    i8Ptr = LlvmType -> LlvmType
    pLift LlvmType
    i8

    -- | The target architectures word size
    llvmWord, llvmWordPtr :: Platform -> LlvmType
    llvmWord :: Platform -> LlvmType
    llvmWord    Platform
    platform = Int -> LlvmType
    LMInt (Platform -> Int
    platformWordSizeInBytes Platform
    platform Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    8)
    llvmWordPtr :: Platform -> LlvmType
    llvmWordPtr Platform
    platform = LlvmType -> LlvmType
    pLift (Platform -> LlvmType
    llvmWord Platform
    platform)

    -- -----------------------------------------------------------------------------
    -- * LLVM Function Types
    --

    -- | An LLVM Function
    data LlvmFunctionDecl = LlvmFunctionDecl {
            -- | Unique identifier of the function
            LlvmFunctionDecl -> FastString
    decName       :: LMString,
            -- | LinkageType of the function
            LlvmFunctionDecl -> LlvmLinkageType
    funcLinkage   :: LlvmLinkageType,
            -- | The calling convention of the function
            LlvmFunctionDecl -> LlvmCallConvention
    funcCc        :: LlvmCallConvention,
            -- | Type of the returned value
            LlvmFunctionDecl -> LlvmType
    decReturnType :: LlvmType,
            -- | Indicates if this function uses varargs
            LlvmFunctionDecl -> LlvmParameterListType
    decVarargs    :: LlvmParameterListType,
            -- | Parameter types and attributes
            LlvmFunctionDecl -> [LlvmParameter]
    decParams     :: [LlvmParameter],
            -- | Function align value, must be power of 2
            LlvmFunctionDecl -> LMAlign
    funcAlign     :: LMAlign
      }
      deriving (LlvmFunctionDecl -> LlvmFunctionDecl -> Bool
    (LlvmFunctionDecl -> LlvmFunctionDecl -> Bool)
    -> (LlvmFunctionDecl -> LlvmFunctionDecl -> Bool)
    -> Eq LlvmFunctionDecl
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: LlvmFunctionDecl -> LlvmFunctionDecl -> Bool
    == :: LlvmFunctionDecl -> LlvmFunctionDecl -> Bool
    $c/= :: LlvmFunctionDecl -> LlvmFunctionDecl -> Bool
    /= :: LlvmFunctionDecl -> LlvmFunctionDecl -> Bool
    Eq)

    type LlvmFunctionDecls = [LlvmFunctionDecl]

    type LlvmParameter = (LlvmType, [LlvmParamAttr])

    -- | LLVM Parameter Attributes.
    --
    -- Parameter attributes are used to communicate additional information about
    -- the result or parameters of a function
    data LlvmParamAttr
      -- | This indicates to the code generator that the parameter or return value
      -- should be zero-extended to a 32-bit value by the caller (for a parameter)
      -- or the callee (for a return value).
      = ZeroExt
      -- | This indicates to the code generator that the parameter or return value
      -- should be sign-extended to a 32-bit value by the caller (for a parameter)
      -- or the callee (for a return value).
      | SignExt
      -- | This indicates that this parameter or return value should be treated in
      -- a special target-dependent fashion during while emitting code for a
      -- function call or return (usually, by putting it in a register as opposed
      -- to memory).
      | InReg
      -- | This indicates that the pointer parameter should really be passed by
      -- value to the function.
      | ByVal
      -- | This indicates that the pointer parameter specifies the address of a
      -- structure that is the return value of the function in the source program.
      | SRet
      -- | This indicates that the pointer does not alias any global or any other
      -- parameter.
      | NoAlias
      -- | This indicates that the callee does not make any copies of the pointer
      -- that outlive the callee itself
      | NoCapture
      -- | This indicates that the pointer parameter can be excised using the
      -- trampoline intrinsics.
      | Nest
      deriving (LlvmParamAttr -> LlvmParamAttr -> Bool
    (LlvmParamAttr -> LlvmParamAttr -> Bool)
    -> (LlvmParamAttr -> LlvmParamAttr -> Bool) -> Eq LlvmParamAttr
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: LlvmParamAttr -> LlvmParamAttr -> Bool
    == :: LlvmParamAttr -> LlvmParamAttr -> Bool
    $c/= :: LlvmParamAttr -> LlvmParamAttr -> Bool
    /= :: LlvmParamAttr -> LlvmParamAttr -> Bool
    Eq)

    instance Outputable LlvmParamAttr where
      ppr :: LlvmParamAttr -> SDoc
    ppr = LlvmParamAttr -> SDoc
    forall doc. IsLine doc => LlvmParamAttr -> doc
    ppLlvmParamAttr

    ppLlvmParamAttr :: IsLine doc => LlvmParamAttr -> doc
    ppLlvmParamAttr :: forall doc. IsLine doc => LlvmParamAttr -> doc
    ppLlvmParamAttr LlvmParamAttr
    ZeroExt   = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "zeroext"
    ppLlvmParamAttr LlvmParamAttr
    SignExt   = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "signext"
    ppLlvmParamAttr LlvmParamAttr
    InReg     = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "inreg"
    ppLlvmParamAttr LlvmParamAttr
    ByVal     = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "byval"
    ppLlvmParamAttr LlvmParamAttr
    SRet      = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "sret"
    ppLlvmParamAttr LlvmParamAttr
    NoAlias   = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "noalias"
    ppLlvmParamAttr LlvmParamAttr
    NoCapture = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "nocapture"
    ppLlvmParamAttr LlvmParamAttr
    Nest      = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "nest"
    {-# SPECIALIZE ppLlvmParamAttr :: LlvmParamAttr -> SDoc #-}
    {-# SPECIALIZE ppLlvmParamAttr :: LlvmParamAttr -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable

    -- | Llvm Function Attributes.
    --
    -- Function attributes are set to communicate additional information about a
    -- function. Function attributes are considered to be part of the function,
    -- not of the function type, so functions with different parameter attributes
    -- can have the same function type. Functions can have multiple attributes.
    --
    -- Descriptions taken from <http://llvm.org/docs/LangRef.html#fnattrs>
    data LlvmFuncAttr
      -- | This attribute indicates that the inliner should attempt to inline this
      -- function into callers whenever possible, ignoring any active inlining
      -- size threshold for this caller.
      = AlwaysInline
      -- | This attribute indicates that the source code contained a hint that
      -- inlining this function is desirable (such as the \"inline\" keyword in
      -- C/C++). It is just a hint; it imposes no requirements on the inliner.
      | InlineHint
      -- | This attribute indicates that the inliner should never inline this
      -- function in any situation. This attribute may not be used together
      -- with the alwaysinline attribute.
      | NoInline
      -- | This attribute suggests that optimization passes and code generator
      -- passes make choices that keep the code size of this function low, and
      -- otherwise do optimizations specifically to reduce code size.
      | OptSize
      -- | This function attribute indicates that the function never returns
      -- normally. This produces undefined behavior at runtime if the function
      -- ever does dynamically return.
      | NoReturn
      -- | This function attribute indicates that the function never returns with
      -- an unwind or exceptional control flow. If the function does unwind, its
      -- runtime behavior is undefined.
      | NoUnwind
      -- | This attribute indicates that the function computes its result (or
      -- decides to unwind an exception) based strictly on its arguments, without
      -- dereferencing any pointer arguments or otherwise accessing any mutable
      -- state (e.g. memory, control registers, etc) visible to caller functions.
      -- It does not write through any pointer arguments (including byval
      -- arguments) and never changes any state visible to callers. This means
      -- that it cannot unwind exceptions by calling the C++ exception throwing
      -- methods, but could use the unwind instruction.
      | ReadNone
      -- | This attribute indicates that the function does not write through any
      -- pointer arguments (including byval arguments) or otherwise modify any
      -- state (e.g. memory, control registers, etc) visible to caller functions.
      -- It may dereference pointer arguments and read state that may be set in
      -- the caller. A readonly function always returns the same value (or unwinds
      -- an exception identically) when called with the same set of arguments and
      -- global state. It cannot unwind an exception by calling the C++ exception
      -- throwing methods, but may use the unwind instruction.
      | ReadOnly
      -- | This attribute indicates that the function should emit a stack smashing
      -- protector. It is in the form of a \"canary\"—a random value placed on the
      -- stack before the local variables that's checked upon return from the
      -- function to see if it has been overwritten. A heuristic is used to
      -- determine if a function needs stack protectors or not.
      --
      -- If a function that has an ssp attribute is inlined into a function that
      -- doesn't have an ssp attribute, then the resulting function will have an
      -- ssp attribute.
      | Ssp
      -- | This attribute indicates that the function should always emit a stack
      -- smashing protector. This overrides the ssp function attribute.
      --
      -- If a function that has an sspreq attribute is inlined into a function
      -- that doesn't have an sspreq attribute or which has an ssp attribute,
      -- then the resulting function will have an sspreq attribute.
      | SspReq
      -- | This attribute indicates that the code generator should not use a red
      -- zone, even if the target-specific ABI normally permits it.
      | NoRedZone
      -- | This attributes disables implicit floating point instructions.
      | NoImplicitFloat
      -- | This attribute disables prologue / epilogue emission for the function.
      -- This can have very system-specific consequences.
      | Naked
      deriving (LlvmFuncAttr -> LlvmFuncAttr -> Bool
    (LlvmFuncAttr -> LlvmFuncAttr -> Bool)
    -> (LlvmFuncAttr -> LlvmFuncAttr -> Bool) -> Eq LlvmFuncAttr
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: LlvmFuncAttr -> LlvmFuncAttr -> Bool
    == :: LlvmFuncAttr -> LlvmFuncAttr -> Bool
    $c/= :: LlvmFuncAttr -> LlvmFuncAttr -> Bool
    /= :: LlvmFuncAttr -> LlvmFuncAttr -> Bool
    Eq)

    instance Outputable LlvmFuncAttr where
      ppr :: LlvmFuncAttr -> SDoc
    ppr = LlvmFuncAttr -> SDoc
    forall doc. IsLine doc => LlvmFuncAttr -> doc
    ppLlvmFuncAttr

    ppLlvmFuncAttr :: IsLine doc => LlvmFuncAttr -> doc
    ppLlvmFuncAttr :: forall doc. IsLine doc => LlvmFuncAttr -> doc
    ppLlvmFuncAttr LlvmFuncAttr
    AlwaysInline       = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "alwaysinline"
    ppLlvmFuncAttr LlvmFuncAttr
    InlineHint         = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "inlinehint"
    ppLlvmFuncAttr LlvmFuncAttr
    NoInline           = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "noinline"
    ppLlvmFuncAttr LlvmFuncAttr
    OptSize            = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "optsize"
    ppLlvmFuncAttr LlvmFuncAttr
    NoReturn           = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "noreturn"
    ppLlvmFuncAttr LlvmFuncAttr
    NoUnwind           = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "nounwind"
    ppLlvmFuncAttr LlvmFuncAttr
    ReadNone           = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "readnone"
    ppLlvmFuncAttr LlvmFuncAttr
    ReadOnly           = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "readonly"
    ppLlvmFuncAttr LlvmFuncAttr
    Ssp                = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "ssp"
    ppLlvmFuncAttr LlvmFuncAttr
    SspReq             = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "ssqreq"
    ppLlvmFuncAttr LlvmFuncAttr
    NoRedZone          = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "noredzone"
    ppLlvmFuncAttr LlvmFuncAttr
    NoImplicitFloat    = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "noimplicitfloat"
    ppLlvmFuncAttr LlvmFuncAttr
    Naked              = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "naked"
    {-# SPECIALIZE ppLlvmFuncAttr :: LlvmFuncAttr -> SDoc #-}
    {-# SPECIALIZE ppLlvmFuncAttr :: LlvmFuncAttr -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable

    -- | Different types to call a function.
    data LlvmCallType
      -- | Normal call, allocate a new stack frame.
      = StdCall
      -- | Tail call, perform the call in the current stack frame.
      | TailCall
      deriving (LlvmCallType -> LlvmCallType -> Bool
    (LlvmCallType -> LlvmCallType -> Bool)
    -> (LlvmCallType -> LlvmCallType -> Bool) -> Eq LlvmCallType
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: LlvmCallType -> LlvmCallType -> Bool
    == :: LlvmCallType -> LlvmCallType -> Bool
    $c/= :: LlvmCallType -> LlvmCallType -> Bool
    /= :: LlvmCallType -> LlvmCallType -> Bool
    Eq,Int -> LlvmCallType -> ShowS
    [LlvmCallType] -> ShowS
    LlvmCallType -> String
    (Int -> LlvmCallType -> ShowS)
    -> (LlvmCallType -> String)
    -> ([LlvmCallType] -> ShowS)
    -> Show LlvmCallType
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> LlvmCallType -> ShowS
    showsPrec :: Int -> LlvmCallType -> ShowS
    $cshow :: LlvmCallType -> String
    show :: LlvmCallType -> String
    $cshowList :: [LlvmCallType] -> ShowS
    showList :: [LlvmCallType] -> ShowS
    Show)

    -- | Different calling conventions a function can use.
    data LlvmCallConvention
      -- | The C calling convention.
      -- This calling convention (the default if no other calling convention is
      -- specified) matches the target C calling conventions. This calling
      -- convention supports varargs function calls and tolerates some mismatch in
      -- the declared prototype and implemented declaration of the function (as
      -- does normal C).
      = CC_Ccc
      -- | This calling convention attempts to make calls as fast as possible
      -- (e.g. by passing things in registers). This calling convention allows
      -- the target to use whatever tricks it wants to produce fast code for the
      -- target, without having to conform to an externally specified ABI
      -- (Application Binary Interface). Implementations of this convention should
      -- allow arbitrary tail call optimization to be supported. This calling
      -- convention does not support varargs and requires the prototype of al
      -- callees to exactly match the prototype of the function definition.
      | CC_Fastcc
      -- | This calling convention attempts to make code in the caller as efficient
      -- as possible under the assumption that the call is not commonly executed.
      -- As such, these calls often preserve all registers so that the call does
      -- not break any live ranges in the caller side. This calling convention
      -- does not support varargs and requires the prototype of all callees to
      -- exactly match the prototype of the function definition.
      | CC_Coldcc
      -- | The GHC-specific 'registerised' calling convention.
      | CC_Ghc
      -- | Any calling convention may be specified by number, allowing
      -- target-specific calling conventions to be used. Target specific calling
      -- conventions start at 64.
      | CC_Ncc Int
      -- | X86 Specific 'StdCall' convention. LLVM includes a specific alias for it
      -- rather than just using CC_Ncc.
      | CC_X86_Stdcc
      deriving (LlvmCallConvention -> LlvmCallConvention -> Bool
    (LlvmCallConvention -> LlvmCallConvention -> Bool)
    -> (LlvmCallConvention -> LlvmCallConvention -> Bool)
    -> Eq LlvmCallConvention
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: LlvmCallConvention -> LlvmCallConvention -> Bool
    == :: LlvmCallConvention -> LlvmCallConvention -> Bool
    $c/= :: LlvmCallConvention -> LlvmCallConvention -> Bool
    /= :: LlvmCallConvention -> LlvmCallConvention -> Bool
    Eq)

    instance Outputable LlvmCallConvention where
      ppr :: LlvmCallConvention -> SDoc
    ppr = LlvmCallConvention -> SDoc
    forall doc. IsLine doc => LlvmCallConvention -> doc
    ppLlvmCallConvention

    ppLlvmCallConvention :: IsLine doc => LlvmCallConvention -> doc
    ppLlvmCallConvention :: forall doc. IsLine doc => LlvmCallConvention -> doc
    ppLlvmCallConvention LlvmCallConvention
    CC_Ccc       = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "ccc"
    ppLlvmCallConvention LlvmCallConvention
    CC_Fastcc    = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "fastcc"
    ppLlvmCallConvention LlvmCallConvention
    CC_Coldcc    = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "coldcc"
    ppLlvmCallConvention LlvmCallConvention
    CC_Ghc       = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "ghccc"
    ppLlvmCallConvention (CC_Ncc Int
    i)   = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "cc " doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Int -> doc
    forall doc. IsLine doc => Int -> doc
    int Int
    i
    ppLlvmCallConvention LlvmCallConvention
    CC_X86_Stdcc = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "x86_stdcallcc"
    {-# SPECIALIZE ppLlvmCallConvention :: LlvmCallConvention -> SDoc #-}
    {-# SPECIALIZE ppLlvmCallConvention :: LlvmCallConvention -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable

    -- | Functions can have a fixed amount of parameters, or a variable amount.
    data LlvmParameterListType
      -- Fixed amount of arguments.
      = FixedArgs
      -- Variable amount of arguments.
      | VarArgs
      deriving (LlvmParameterListType -> LlvmParameterListType -> Bool
    (LlvmParameterListType -> LlvmParameterListType -> Bool)
    -> (LlvmParameterListType -> LlvmParameterListType -> Bool)
    -> Eq LlvmParameterListType
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: LlvmParameterListType -> LlvmParameterListType -> Bool
    == :: LlvmParameterListType -> LlvmParameterListType -> Bool
    $c/= :: LlvmParameterListType -> LlvmParameterListType -> Bool
    /= :: LlvmParameterListType -> LlvmParameterListType -> Bool
    Eq,Int -> LlvmParameterListType -> ShowS
    [LlvmParameterListType] -> ShowS
    LlvmParameterListType -> String
    (Int -> LlvmParameterListType -> ShowS)
    -> (LlvmParameterListType -> String)
    -> ([LlvmParameterListType] -> ShowS)
    -> Show LlvmParameterListType
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> LlvmParameterListType -> ShowS
    showsPrec :: Int -> LlvmParameterListType -> ShowS
    $cshow :: LlvmParameterListType -> String
    show :: LlvmParameterListType -> String
    $cshowList :: [LlvmParameterListType] -> ShowS
    showList :: [LlvmParameterListType] -> ShowS
    Show)

    -- | Linkage type of a symbol.
    --
    -- The description of the constructors is copied from the Llvm Assembly Language
    -- Reference Manual <http://www.llvm.org/docs/LangRef.html#linkage>, because
    -- they correspond to the Llvm linkage types.
    data LlvmLinkageType
      -- | Global values with internal linkage are only directly accessible by
      -- objects in the current module. In particular, linking code into a module
      -- with an internal global value may cause the internal to be renamed as
      -- necessary to avoid collisions. Because the symbol is internal to the
      -- module, all references can be updated. This corresponds to the notion
      -- of the @static@ keyword in C.
      = Internal
      -- | Globals with @linkonce@ linkage are merged with other globals of the
      -- same name when linkage occurs. This is typically used to implement
      -- inline functions, templates, or other code which must be generated
      -- in each translation unit that uses it. Unreferenced linkonce globals are
      -- allowed to be discarded.
      | LinkOnce
      -- | @weak@ linkage is exactly the same as linkonce linkage, except that
      -- unreferenced weak globals may not be discarded. This is used for globals
      -- that may be emitted in multiple translation units, but that are not
      -- guaranteed to be emitted into every translation unit that uses them. One
      -- example of this are common globals in C, such as @int X;@ at global
      -- scope.
      | Weak
      -- | @appending@ linkage may only be applied to global variables of pointer
      -- to array type. When two global variables with appending linkage are
      -- linked together, the two global arrays are appended together. This is
      -- the Llvm, typesafe, equivalent of having the system linker append
      -- together @sections@ with identical names when .o files are linked.
      | Appending
      -- | The semantics of this linkage follow the ELF model: the symbol is weak
      -- until linked, if not linked, the symbol becomes null instead of being an
      -- undefined reference.
      | ExternWeak
      -- | The symbol participates in linkage and can be used to resolve external
      --  symbol references.
      | ExternallyVisible
      -- | Alias for 'ExternallyVisible' but with explicit textual form in LLVM
      --  assembly.
      | External
      -- | Symbol is private to the module and should not appear in the symbol table
      | Private
      deriving (LlvmLinkageType -> LlvmLinkageType -> Bool
    (LlvmLinkageType -> LlvmLinkageType -> Bool)
    -> (LlvmLinkageType -> LlvmLinkageType -> Bool)
    -> Eq LlvmLinkageType
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: LlvmLinkageType -> LlvmLinkageType -> Bool
    == :: LlvmLinkageType -> LlvmLinkageType -> Bool
    $c/= :: LlvmLinkageType -> LlvmLinkageType -> Bool
    /= :: LlvmLinkageType -> LlvmLinkageType -> Bool
    Eq)

    instance Outputable LlvmLinkageType where
      ppr :: LlvmLinkageType -> SDoc
    ppr = LlvmLinkageType -> SDoc
    forall doc. IsLine doc => LlvmLinkageType -> doc
    ppLlvmLinkageType

    ppLlvmLinkageType :: IsLine doc => LlvmLinkageType -> doc
    ppLlvmLinkageType :: forall doc. IsLine doc => LlvmLinkageType -> doc
    ppLlvmLinkageType LlvmLinkageType
    Internal          = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "internal"
    ppLlvmLinkageType LlvmLinkageType
    LinkOnce          = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "linkonce"
    ppLlvmLinkageType LlvmLinkageType
    Weak              = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "weak"
    ppLlvmLinkageType LlvmLinkageType
    Appending         = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "appending"
    ppLlvmLinkageType LlvmLinkageType
    ExternWeak        = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "extern_weak"
    -- ExternallyVisible does not have a textual representation, it is
    -- the linkage type a function resolves to if no other is specified
    -- in Llvm.
    ppLlvmLinkageType LlvmLinkageType
    ExternallyVisible = doc
    forall doc. IsOutput doc => doc
    empty
    ppLlvmLinkageType LlvmLinkageType
    External          = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "external"
    ppLlvmLinkageType LlvmLinkageType
    Private           = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "private"
    {-# SPECIALIZE ppLlvmLinkageType :: LlvmLinkageType -> SDoc #-}
    {-# SPECIALIZE ppLlvmLinkageType :: LlvmLinkageType -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable

    -- -----------------------------------------------------------------------------
    -- * LLVM Operations
    --

    -- | Llvm binary operators machine operations.
    data LlvmMachOp
      = LM_MO_Add  -- ^ add two integer, floating point or vector values.
      | LM_MO_Sub  -- ^ subtract two ...
      | LM_MO_Mul  -- ^ multiply ..
      | LM_MO_UDiv -- ^ unsigned integer or vector division.
      | LM_MO_SDiv -- ^ signed integer ..
      | LM_MO_URem -- ^ unsigned integer or vector remainder (mod)
      | LM_MO_SRem -- ^ signed ...

      | LM_MO_FAdd -- ^ add two floating point or vector values.
      | LM_MO_FSub -- ^ subtract two ...
      | LM_MO_FMul -- ^ multiply ...
      | LM_MO_FDiv -- ^ divide ...
      | LM_MO_FRem -- ^ remainder ...

      -- | Left shift
      | LM_MO_Shl
      -- | Logical shift right
      -- Shift right, filling with zero
      | LM_MO_LShr
      -- | Arithmetic shift right
      -- The most significant bits of the result will be equal to the sign bit of
      -- the left operand.
      | LM_MO_AShr

      | LM_MO_And -- ^ AND bitwise logical operation.
      | LM_MO_Or  -- ^ OR bitwise logical operation.
      | LM_MO_Xor -- ^ XOR bitwise logical operation.
      deriving (LlvmMachOp -> LlvmMachOp -> Bool
    (LlvmMachOp -> LlvmMachOp -> Bool)
    -> (LlvmMachOp -> LlvmMachOp -> Bool) -> Eq LlvmMachOp
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: LlvmMachOp -> LlvmMachOp -> Bool
    == :: LlvmMachOp -> LlvmMachOp -> Bool
    $c/= :: LlvmMachOp -> LlvmMachOp -> Bool
    /= :: LlvmMachOp -> LlvmMachOp -> Bool
    Eq)

    instance Outputable LlvmMachOp where
      ppr :: LlvmMachOp -> SDoc
    ppr = LlvmMachOp -> SDoc
    forall doc. IsLine doc => LlvmMachOp -> doc
    ppLlvmMachOp

    ppLlvmMachOp :: IsLine doc => LlvmMachOp -> doc
    ppLlvmMachOp :: forall doc. IsLine doc => LlvmMachOp -> doc
    ppLlvmMachOp LlvmMachOp
    LM_MO_Add  = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "add"
    ppLlvmMachOp LlvmMachOp
    LM_MO_Sub  = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "sub"
    ppLlvmMachOp LlvmMachOp
    LM_MO_Mul  = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "mul"
    ppLlvmMachOp LlvmMachOp
    LM_MO_UDiv = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "udiv"
    ppLlvmMachOp LlvmMachOp
    LM_MO_SDiv = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "sdiv"
    ppLlvmMachOp LlvmMachOp
    LM_MO_URem = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "urem"
    ppLlvmMachOp LlvmMachOp
    LM_MO_SRem = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "srem"
    ppLlvmMachOp LlvmMachOp
    LM_MO_FAdd = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "fadd"
    ppLlvmMachOp LlvmMachOp
    LM_MO_FSub = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "fsub"
    ppLlvmMachOp LlvmMachOp
    LM_MO_FMul = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "fmul"
    ppLlvmMachOp LlvmMachOp
    LM_MO_FDiv = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "fdiv"
    ppLlvmMachOp LlvmMachOp
    LM_MO_FRem = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "frem"
    ppLlvmMachOp LlvmMachOp
    LM_MO_Shl  = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "shl"
    ppLlvmMachOp LlvmMachOp
    LM_MO_LShr = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "lshr"
    ppLlvmMachOp LlvmMachOp
    LM_MO_AShr = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "ashr"
    ppLlvmMachOp LlvmMachOp
    LM_MO_And  = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "and"
    ppLlvmMachOp LlvmMachOp
    LM_MO_Or   = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "or"
    ppLlvmMachOp LlvmMachOp
    LM_MO_Xor  = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "xor"
    {-# SPECIALIZE ppLlvmMachOp :: LlvmMachOp -> SDoc #-}
    {-# SPECIALIZE ppLlvmMachOp :: LlvmMachOp -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable

    -- | Llvm compare operations.
    data LlvmCmpOp
      = LM_CMP_Eq  -- ^ Equal (Signed and Unsigned)
      | LM_CMP_Ne  -- ^ Not equal (Signed and Unsigned)
      | LM_CMP_Ugt -- ^ Unsigned greater than
      | LM_CMP_Uge -- ^ Unsigned greater than or equal
      | LM_CMP_Ult -- ^ Unsigned less than
      | LM_CMP_Ule -- ^ Unsigned less than or equal
      | LM_CMP_Sgt -- ^ Signed greater than
      | LM_CMP_Sge -- ^ Signed greater than or equal
      | LM_CMP_Slt -- ^ Signed less than
      | LM_CMP_Sle -- ^ Signed less than or equal

      -- Float comparisons. GHC uses a mix of ordered and unordered float
      -- comparisons.
      | LM_CMP_Feq -- ^ Float equal
      | LM_CMP_Fne -- ^ Float not equal
      | LM_CMP_Fgt -- ^ Float greater than
      | LM_CMP_Fge -- ^ Float greater than or equal
      | LM_CMP_Flt -- ^ Float less than
      | LM_CMP_Fle -- ^ Float less than or equal
      deriving (LlvmCmpOp -> LlvmCmpOp -> Bool
    (LlvmCmpOp -> LlvmCmpOp -> Bool)
    -> (LlvmCmpOp -> LlvmCmpOp -> Bool) -> Eq LlvmCmpOp
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: LlvmCmpOp -> LlvmCmpOp -> Bool
    == :: LlvmCmpOp -> LlvmCmpOp -> Bool
    $c/= :: LlvmCmpOp -> LlvmCmpOp -> Bool
    /= :: LlvmCmpOp -> LlvmCmpOp -> Bool
    Eq)

    instance Outputable LlvmCmpOp where
      ppr :: LlvmCmpOp -> SDoc
    ppr = LlvmCmpOp -> SDoc
    forall doc. IsLine doc => LlvmCmpOp -> doc
    ppLlvmCmpOp

    ppLlvmCmpOp :: IsLine doc => LlvmCmpOp -> doc
    ppLlvmCmpOp :: forall doc. IsLine doc => LlvmCmpOp -> doc
    ppLlvmCmpOp LlvmCmpOp
    LM_CMP_Eq  = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "eq"
    ppLlvmCmpOp LlvmCmpOp
    LM_CMP_Ne  = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "ne"
    ppLlvmCmpOp LlvmCmpOp
    LM_CMP_Ugt = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "ugt"
    ppLlvmCmpOp LlvmCmpOp
    LM_CMP_Uge = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "uge"
    ppLlvmCmpOp LlvmCmpOp
    LM_CMP_Ult = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "ult"
    ppLlvmCmpOp LlvmCmpOp
    LM_CMP_Ule = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "ule"
    ppLlvmCmpOp LlvmCmpOp
    LM_CMP_Sgt = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "sgt"
    ppLlvmCmpOp LlvmCmpOp
    LM_CMP_Sge = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "sge"
    ppLlvmCmpOp LlvmCmpOp
    LM_CMP_Slt = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "slt"
    ppLlvmCmpOp LlvmCmpOp
    LM_CMP_Sle = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "sle"
    ppLlvmCmpOp LlvmCmpOp
    LM_CMP_Feq = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "oeq"
    ppLlvmCmpOp LlvmCmpOp
    LM_CMP_Fne = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "une"
    ppLlvmCmpOp LlvmCmpOp
    LM_CMP_Fgt = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "ogt"
    ppLlvmCmpOp LlvmCmpOp
    LM_CMP_Fge = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "oge"
    ppLlvmCmpOp LlvmCmpOp
    LM_CMP_Flt = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "olt"
    ppLlvmCmpOp LlvmCmpOp
    LM_CMP_Fle = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "ole"
    {-# SPECIALIZE ppLlvmCmpOp :: LlvmCmpOp -> SDoc #-}
    {-# SPECIALIZE ppLlvmCmpOp :: LlvmCmpOp -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable

    -- | Llvm cast operations.
    data LlvmCastOp
      = LM_Trunc    -- ^ Integer truncate
      | LM_Zext     -- ^ Integer extend (zero fill)
      | LM_Sext     -- ^ Integer extend (sign fill)
      | LM_Fptrunc  -- ^ Float truncate
      | LM_Fpext    -- ^ Float extend
      | LM_Fptoui   -- ^ Float to unsigned Integer
      | LM_Fptosi   -- ^ Float to signed Integer
      | LM_Uitofp   -- ^ Unsigned Integer to Float
      | LM_Sitofp   -- ^ Signed Int to Float
      | LM_Ptrtoint -- ^ Pointer to Integer
      | LM_Inttoptr -- ^ Integer to Pointer
      | LM_Bitcast  -- ^ Cast between types where no bit manipulation is needed
      deriving (LlvmCastOp -> LlvmCastOp -> Bool
    (LlvmCastOp -> LlvmCastOp -> Bool)
    -> (LlvmCastOp -> LlvmCastOp -> Bool) -> Eq LlvmCastOp
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: LlvmCastOp -> LlvmCastOp -> Bool
    == :: LlvmCastOp -> LlvmCastOp -> Bool
    $c/= :: LlvmCastOp -> LlvmCastOp -> Bool
    /= :: LlvmCastOp -> LlvmCastOp -> Bool
    Eq)

    instance Outputable LlvmCastOp where
      ppr :: LlvmCastOp -> SDoc
    ppr = LlvmCastOp -> SDoc
    forall doc. IsLine doc => LlvmCastOp -> doc
    ppLlvmCastOp

    ppLlvmCastOp :: IsLine doc => LlvmCastOp -> doc
    ppLlvmCastOp :: forall doc. IsLine doc => LlvmCastOp -> doc
    ppLlvmCastOp LlvmCastOp
    LM_Trunc    = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "trunc"
    ppLlvmCastOp LlvmCastOp
    LM_Zext     = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "zext"
    ppLlvmCastOp LlvmCastOp
    LM_Sext     = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "sext"
    ppLlvmCastOp LlvmCastOp
    LM_Fptrunc  = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "fptrunc"
    ppLlvmCastOp LlvmCastOp
    LM_Fpext    = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "fpext"
    ppLlvmCastOp LlvmCastOp
    LM_Fptoui   = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "fptoui"
    ppLlvmCastOp LlvmCastOp
    LM_Fptosi   = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "fptosi"
    ppLlvmCastOp LlvmCastOp
    LM_Uitofp   = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "uitofp"
    ppLlvmCastOp LlvmCastOp
    LM_Sitofp   = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "sitofp"
    ppLlvmCastOp LlvmCastOp
    LM_Ptrtoint = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "ptrtoint"
    ppLlvmCastOp LlvmCastOp
    LM_Inttoptr = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "inttoptr"
    ppLlvmCastOp LlvmCastOp
    LM_Bitcast  = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "bitcast"
    {-# SPECIALIZE ppLlvmCastOp :: LlvmCastOp -> SDoc #-}
    {-# SPECIALIZE ppLlvmCastOp :: LlvmCastOp -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable

    -- -----------------------------------------------------------------------------
    -- * Floating point conversion
    --

    -- | Convert a Haskell Double to an LLVM hex encoded floating point form. In
    -- Llvm float literals can be printed in a big-endian hexadecimal format,
    -- regardless of underlying architecture.
    --
    -- See Note [LLVM Float Types].
    ppDouble :: IsLine doc => Platform -> Double -> doc
    ppDouble :: forall doc. IsLine doc => Platform -> Double -> doc
    ppDouble Platform
    platform Double
    d
      = let bs :: [Word8]
    bs     = Double -> [Word8]
    doubleToBytes Double
    d
            hex :: a -> String
    hex a
    d' = case a -> ShowS
    forall a. Integral a => a -> ShowS
    showHex a
    d' String
    "" of
                []    -> ShowS
    forall a. HasCallStack => String -> a
    error String
    "ppDouble: too few hex digits for float"
                [Char
    x]   -> [Char
    '0',Char
    x]
                [Char
    x,Char
    y] -> [Char
    x,Char
    y]
                String
    _     -> ShowS
    forall a. HasCallStack => String -> a
    error String
    "ppDouble: too many hex digits for float"

            fixEndian :: [String] -> [String]
    fixEndian = case Platform -> ByteOrder
    platformByteOrder Platform
    platform of
                ByteOrder
    BigEndian    -> [String] -> [String]
    forall a. a -> a
    id
                ByteOrder
    LittleEndian -> [String] -> [String]
    forall a. [a] -> [a]
    reverse
            str :: String
    str       = (Char -> Char) -> ShowS
    forall a b. (a -> b) -> [a] -> [b]
    map Char -> Char
    toUpper ShowS -> ShowS
    forall a b. (a -> b) -> a -> b
    $ [String] -> String
    forall (t :: * -> *) a. Foldable t => t [a] -> [a]
    concat ([String] -> String) -> [String] -> String
    forall a b. (a -> b) -> a -> b
    $ [String] -> [String]
    fixEndian ([String] -> [String]) -> [String] -> [String]
    forall a b. (a -> b) -> a -> b
    $ (Word8 -> String) -> [Word8] -> [String]
    forall a b. (a -> b) -> [a] -> [b]
    map Word8 -> String
    forall {a}. Integral a => a -> String
    hex [Word8]
    bs
        in String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "0x" doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    str
    {-# SPECIALIZE ppDouble :: Platform -> Double -> SDoc #-}
    {-# SPECIALIZE ppDouble :: Platform -> Double -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable

    -- Note [LLVM Float Types]
    -- ~~~~~~~~~~~~~~~~~~~~~~~
    -- We use 'ppDouble' for both printing Float and Double floating point types. This is
    -- as LLVM expects all floating point constants (single & double) to be in IEEE
    -- 754 Double precision format. However, for single precision numbers (Float)
    -- they should be *representable* in IEEE 754 Single precision format. So the
    -- easiest way to do this is to narrow and widen again.
    -- (i.e., Double -> Float -> Double). We must be careful doing this that GHC
    -- doesn't optimize that away.

    -- Note [narrowFp & widenFp]
    -- ~~~~~~~~~~~~~~~~~~~~~~~~~
    -- NOTE: we use float2Double & co directly as GHC likes to optimize away
    -- successive calls of 'realToFrac', defeating the narrowing. (Bug #7600).
    -- 'realToFrac' has inconsistent behaviour with optimisation as well that can
    -- also cause issues, these methods don't.

    narrowFp :: Double -> Float
    {-# NOINLINE narrowFp #-}
    narrowFp :: Double -> Float
    narrowFp = Double -> Float
    double2Float

    widenFp :: Float -> Double
    {-# NOINLINE widenFp #-}
    widenFp :: Float -> Double
    widenFp = Float -> Double
    float2Double

    ppFloat :: IsLine doc => Platform -> Float -> doc
    ppFloat :: forall doc. IsLine doc => Platform -> Float -> doc
    ppFloat Platform
    platform = Platform -> Double -> doc
    forall doc. IsLine doc => Platform -> Double -> doc
    ppDouble Platform
    platform (Double -> doc) -> (Float -> Double) -> Float -> doc
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Float -> Double
    widenFp
    {-# SPECIALIZE ppFloat :: Platform -> Float -> SDoc #-}
    {-# SPECIALIZE ppFloat :: Platform -> Float -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable

    --------------------------------------------------------------------------------
    -- * Misc functions
    --------------------------------------------------------------------------------

    ppCommaJoin :: IsLine doc => (a -> doc) -> [a] -> doc
    ppCommaJoin :: forall doc a. IsLine doc => (a -> doc) -> [a] -> doc
    ppCommaJoin a -> doc
    ppr [a]
    strs = [doc] -> doc
    forall doc. IsLine doc => [doc] -> doc
    hsep ([doc] -> doc) -> [doc] -> doc
    forall a b. (a -> b) -> a -> b
    $ doc -> [doc] -> [doc]
    forall doc. IsLine doc => doc -> [doc] -> [doc]
    punctuate doc
    forall doc. IsLine doc => doc
    comma ((a -> doc) -> [a] -> [doc]
    forall a b. (a -> b) -> [a] -> [b]
    map a -> doc
    ppr [a]
    strs)
    {-# SPECIALIZE ppCommaJoin :: (a -> SDoc) -> [a] -> SDoc #-}
    {-# SPECIALIZE ppCommaJoin :: (a -> HLine) -> [a] -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable

    ppSpaceJoin :: IsLine doc => (a -> doc) -> [a] -> doc
    ppSpaceJoin :: forall doc a. IsLine doc => (a -> doc) -> [a] -> doc
    ppSpaceJoin a -> doc
    ppr [a]
    strs = [doc] -> doc
    forall doc. IsLine doc => [doc] -> doc
    hsep ((a -> doc) -> [a] -> [doc]
    forall a b. (a -> b) -> [a] -> [b]
    map a -> doc
    ppr [a]
    strs)
    {-# SPECIALIZE ppSpaceJoin :: (a -> SDoc) -> [a] -> SDoc #-}
    {-# SPECIALIZE ppSpaceJoin :: (a -> HLine) -> [a] -> HLine #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable