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

    -----------------------------------------------------------------------------
    --
    -- Pretty-printing assembly language
    --
    -- (c) The University of Glasgow 1993-2005
    --
    -----------------------------------------------------------------------------

    module GHC.CmmToAsm.X86.Ppr (
            pprNatCmmDecl,
            pprData,
            pprInstr,
            pprFormat,
            pprImm,
            pprDataItem,
    )

    where

    #include "HsVersions.h"

    import GHC.Prelude

    import GHC.Platform
    import GHC.Platform.Reg

    import GHC.CmmToAsm.X86.Regs
    import GHC.CmmToAsm.X86.Instr
    import GHC.CmmToAsm.X86.Cond
    import GHC.CmmToAsm.Config
    import GHC.CmmToAsm.Format
    import GHC.CmmToAsm.Types
    import GHC.CmmToAsm.Utils
    import GHC.CmmToAsm.Ppr

    import GHC.Cmm              hiding (topInfoTable)
    import GHC.Cmm.Dataflow.Collections
    import GHC.Cmm.Dataflow.Label
    import GHC.Cmm.BlockId
    import GHC.Cmm.CLabel

    import GHC.Types.Basic (Alignment, mkAlignment, alignmentBytes)
    import GHC.Types.Unique ( pprUniqueAlways )

    import GHC.Data.FastString
    import GHC.Utils.Outputable
    import GHC.Utils.Panic

    import Data.Word

    -- -----------------------------------------------------------------------------
    -- Printing this stuff out
    --
    --
    -- Note [Subsections Via Symbols]
    --
    -- If we are using the .subsections_via_symbols directive
    -- (available on recent versions of Darwin),
    -- we have to make sure that there is some kind of reference
    -- from the entry code to a label on the _top_ of the info table,
    -- so that the linker will not think it is unreferenced and dead-strip
    -- it. That's why the label is called a DeadStripPreventer (_dsp).
    --
    -- The LLVM code gen already creates `iTableSuf` symbols, where
    -- the X86 would generate the DeadStripPreventer (_dsp) symbol.
    -- Therefore all that is left for llvm code gen, is to ensure
    -- that all the `iTableSuf` symbols are marked as used.
    -- As of this writing the documentation regarding the
    -- .subsections_via_symbols and -dead_strip can be found at
    -- <https://developer.apple.com/library/mac/documentation/DeveloperTools/Reference/Assembler/040-Assembler_Directives/asm_directives.html#//apple_ref/doc/uid/TP30000823-TPXREF101>

    pprProcAlignment :: NCGConfig -> SDoc
    pprProcAlignment :: NCGConfig -> SDoc
    pprProcAlignment NCGConfig
    config = forall b a. b -> (a -> b) -> Maybe a -> b
    maybe SDoc
    empty (Platform -> Alignment -> SDoc
    pprAlign Platform
    platform forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Alignment
    mkAlignment) (NCGConfig -> Maybe Int
    ncgProcAlignment NCGConfig
    config)
       where
          platform :: Platform
    platform = NCGConfig -> Platform
    ncgPlatform NCGConfig
    config

    pprNatCmmDecl :: NCGConfig -> NatCmmDecl (Alignment, RawCmmStatics) Instr -> SDoc
    pprNatCmmDecl :: NCGConfig -> NatCmmDecl (Alignment, RawCmmStatics) Instr -> SDoc
    pprNatCmmDecl NCGConfig
    config (CmmData Section
    section (Alignment, RawCmmStatics)
    dats) =
      NCGConfig -> Section -> SDoc
    pprSectionAlign NCGConfig
    config Section
    section SDoc -> SDoc -> SDoc
    $$ NCGConfig -> (Alignment, RawCmmStatics) -> SDoc
    pprDatas NCGConfig
    config (Alignment, RawCmmStatics)
    dats

    pprNatCmmDecl NCGConfig
    config proc :: NatCmmDecl (Alignment, RawCmmStatics) Instr
    proc@(CmmProc LabelMap RawCmmStatics
    top_info CLabel
    lbl [GlobalReg]
    _ (ListGraph [GenBasicBlock Instr]
    blocks)) =
      let platform :: Platform
    platform = NCGConfig -> Platform
    ncgPlatform NCGConfig
    config in
      NCGConfig -> SDoc
    pprProcAlignment NCGConfig
    config SDoc -> SDoc -> SDoc
    $$
      case forall a i b. GenCmmDecl a (LabelMap i) (ListGraph b) -> Maybe i
    topInfoTable NatCmmDecl (Alignment, RawCmmStatics) Instr
    proc of
        Maybe RawCmmStatics
    Nothing ->
            -- special case for code without info table:
            NCGConfig -> Section -> SDoc
    pprSectionAlign NCGConfig
    config (SectionType -> CLabel -> Section
    Section SectionType
    Text CLabel
    lbl) SDoc -> SDoc -> SDoc
    $$
            NCGConfig -> SDoc
    pprProcAlignment NCGConfig
    config SDoc -> SDoc -> SDoc
    $$
            NCGConfig -> CLabel -> SDoc
    pprProcLabel NCGConfig
    config CLabel
    lbl SDoc -> SDoc -> SDoc
    $$
            Platform -> CLabel -> SDoc
    pprLabel Platform
    platform CLabel
    lbl SDoc -> SDoc -> SDoc
    $$ -- blocks guaranteed not null, so label needed
            [SDoc] -> SDoc
    vcat (forall a b. (a -> b) -> [a] -> [b]
    map (NCGConfig -> LabelMap RawCmmStatics -> GenBasicBlock Instr -> SDoc
    pprBasicBlock NCGConfig
    config LabelMap RawCmmStatics
    top_info) [GenBasicBlock Instr]
    blocks) SDoc -> SDoc -> SDoc
    $$
            Bool -> SDoc -> SDoc
    ppWhen (NCGConfig -> Bool
    ncgDwarfEnabled NCGConfig
    config) (Platform -> CLabel -> SDoc
    pprBlockEndLabel Platform
    platform CLabel
    lbl SDoc -> SDoc -> SDoc
    $$ Platform -> CLabel -> SDoc
    pprProcEndLabel Platform
    platform CLabel
    lbl) SDoc -> SDoc -> SDoc
    $$
            Platform -> CLabel -> SDoc
    pprSizeDecl Platform
    platform CLabel
    lbl

        Just (CmmStaticsRaw CLabel
    info_lbl [CmmStatic]
    _) ->
          NCGConfig -> Section -> SDoc
    pprSectionAlign NCGConfig
    config (SectionType -> CLabel -> Section
    Section SectionType
    Text CLabel
    info_lbl) SDoc -> SDoc -> SDoc
    $$
          NCGConfig -> SDoc
    pprProcAlignment NCGConfig
    config SDoc -> SDoc -> SDoc
    $$
          NCGConfig -> CLabel -> SDoc
    pprProcLabel NCGConfig
    config CLabel
    lbl SDoc -> SDoc -> SDoc
    $$
          (if Platform -> Bool
    platformHasSubsectionsViaSymbols Platform
    platform
              then forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform (CLabel -> CLabel
    mkDeadStripPreventer CLabel
    info_lbl) SDoc -> SDoc -> SDoc
    <> Char -> SDoc
    char Char
    ':'
              else SDoc
    empty) SDoc -> SDoc -> SDoc
    $$
          [SDoc] -> SDoc
    vcat (forall a b. (a -> b) -> [a] -> [b]
    map (NCGConfig -> LabelMap RawCmmStatics -> GenBasicBlock Instr -> SDoc
    pprBasicBlock NCGConfig
    config LabelMap RawCmmStatics
    top_info) [GenBasicBlock Instr]
    blocks) SDoc -> SDoc -> SDoc
    $$
          Bool -> SDoc -> SDoc
    ppWhen (NCGConfig -> Bool
    ncgDwarfEnabled NCGConfig
    config) (Platform -> CLabel -> SDoc
    pprProcEndLabel Platform
    platform CLabel
    info_lbl) SDoc -> SDoc -> SDoc
    $$
          -- above: Even the first block gets a label, because with branch-chain
          -- elimination, it might be the target of a goto.
          (if Platform -> Bool
    platformHasSubsectionsViaSymbols Platform
    platform
           then -- See Note [Subsections Via Symbols]
                    String -> SDoc
    text String
    "\t.long "
                SDoc -> SDoc -> SDoc
    <+> forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform CLabel
    info_lbl
                SDoc -> SDoc -> SDoc
    <+> Char -> SDoc
    char Char
    '-'
                SDoc -> SDoc -> SDoc
    <+> forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform (CLabel -> CLabel
    mkDeadStripPreventer CLabel
    info_lbl)
           else SDoc
    empty) SDoc -> SDoc -> SDoc
    $$
          Platform -> CLabel -> SDoc
    pprSizeDecl Platform
    platform CLabel
    info_lbl

    -- | Output an internal proc label. See Note [Internal proc labels] in CLabel.
    pprProcLabel :: NCGConfig -> CLabel -> SDoc
    pprProcLabel :: NCGConfig -> CLabel -> SDoc
    pprProcLabel NCGConfig
    config CLabel
    lbl
      | NCGConfig -> Bool
    ncgExposeInternalSymbols NCGConfig
    config
      , Just SDoc
    lbl' <- Module -> CLabel -> Maybe SDoc
    ppInternalProcLabel (NCGConfig -> Module
    ncgThisModule NCGConfig
    config) CLabel
    lbl
      = SDoc
    lbl' SDoc -> SDoc -> SDoc
    <> Char -> SDoc
    char Char
    ':'
      | Bool
    otherwise
      = SDoc
    empty

    pprProcEndLabel :: Platform -> CLabel -- ^ Procedure name
                    -> SDoc
    pprProcEndLabel :: Platform -> CLabel -> SDoc
    pprProcEndLabel Platform
    platform CLabel
    lbl =
        forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform (CLabel -> CLabel
    mkAsmTempProcEndLabel CLabel
    lbl) SDoc -> SDoc -> SDoc
    <> Char -> SDoc
    char Char
    ':'

    pprBlockEndLabel :: Platform -> CLabel -- ^ Block name
                     -> SDoc
    pprBlockEndLabel :: Platform -> CLabel -> SDoc
    pprBlockEndLabel Platform
    platform CLabel
    lbl =
        forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform (CLabel -> CLabel
    mkAsmTempEndLabel CLabel
    lbl) SDoc -> SDoc -> SDoc
    <> Char -> SDoc
    char Char
    ':'

    -- | Output the ELF .size directive.
    pprSizeDecl :: Platform -> CLabel -> SDoc
    pprSizeDecl :: Platform -> CLabel -> SDoc
    pprSizeDecl Platform
    platform CLabel
    lbl
     = if OS -> Bool
    osElfTarget (Platform -> OS
    platformOS Platform
    platform)
       then String -> SDoc
    text String
    "\t.size" SDoc -> SDoc -> SDoc
    <+> forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform CLabel
    lbl SDoc -> SDoc -> SDoc
    <> PtrString -> SDoc
    ptext (String -> PtrString
    sLit String
    ", .-") SDoc -> SDoc -> SDoc
    <> forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform CLabel
    lbl
       else SDoc
    empty

    pprBasicBlock :: NCGConfig -> LabelMap RawCmmStatics -> NatBasicBlock Instr -> SDoc
    pprBasicBlock :: NCGConfig -> LabelMap RawCmmStatics -> GenBasicBlock Instr -> SDoc
    pprBasicBlock NCGConfig
    config LabelMap RawCmmStatics
    info_env (BasicBlock BlockId
    blockid [Instr]
    instrs)
      = SDoc -> SDoc
    maybe_infotable forall a b. (a -> b) -> a -> b
    $
        Platform -> CLabel -> SDoc
    pprLabel Platform
    platform CLabel
    asmLbl SDoc -> SDoc -> SDoc
    $$
        [SDoc] -> SDoc
    vcat (forall a b. (a -> b) -> [a] -> [b]
    map (Platform -> Instr -> SDoc
    pprInstr Platform
    platform) [Instr]
    instrs) SDoc -> SDoc -> SDoc
    $$
        Bool -> SDoc -> SDoc
    ppWhen (NCGConfig -> Bool
    ncgDwarfEnabled NCGConfig
    config) (
          -- Emit both end labels since this may end up being a standalone
          -- top-level block
          Platform -> CLabel -> SDoc
    pprBlockEndLabel Platform
    platform CLabel
    asmLbl
          SDoc -> SDoc -> SDoc
    <> Platform -> CLabel -> SDoc
    pprProcEndLabel Platform
    platform CLabel
    asmLbl
        )
      where
        asmLbl :: CLabel
    asmLbl = BlockId -> CLabel
    blockLbl BlockId
    blockid
        platform :: Platform
    platform = NCGConfig -> Platform
    ncgPlatform NCGConfig
    config
        maybe_infotable :: SDoc -> SDoc
    maybe_infotable SDoc
    c = case forall (map :: * -> *) a.
    IsMap map =>
    KeyOf map -> map a -> Maybe a
    mapLookup BlockId
    blockid LabelMap RawCmmStatics
    info_env of
           Maybe RawCmmStatics
    Nothing -> SDoc
    c
           Just (CmmStaticsRaw CLabel
    infoLbl [CmmStatic]
    info) ->
               Platform -> SectionType -> SDoc
    pprAlignForSection Platform
    platform SectionType
    Text SDoc -> SDoc -> SDoc
    $$
               SDoc
    infoTableLoc SDoc -> SDoc -> SDoc
    $$
               [SDoc] -> SDoc
    vcat (forall a b. (a -> b) -> [a] -> [b]
    map (NCGConfig -> CmmStatic -> SDoc
    pprData NCGConfig
    config) [CmmStatic]
    info) SDoc -> SDoc -> SDoc
    $$
               Platform -> CLabel -> SDoc
    pprLabel Platform
    platform CLabel
    infoLbl SDoc -> SDoc -> SDoc
    $$
               SDoc
    c SDoc -> SDoc -> SDoc
    $$
               Bool -> SDoc -> SDoc
    ppWhen (NCGConfig -> Bool
    ncgDwarfEnabled NCGConfig
    config) (forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform (CLabel -> CLabel
    mkAsmTempEndLabel CLabel
    infoLbl) SDoc -> SDoc -> SDoc
    <> Char -> SDoc
    char Char
    ':')

        -- Make sure the info table has the right .loc for the block
        -- coming right after it. See [Note: Info Offset]
        infoTableLoc :: SDoc
    infoTableLoc = case [Instr]
    instrs of
          (l :: Instr
    l@LOCATION{} : [Instr]
    _) -> Platform -> Instr -> SDoc
    pprInstr Platform
    platform Instr
    l
          [Instr]
    _other             -> SDoc
    empty

    pprDatas :: NCGConfig -> (Alignment, RawCmmStatics) -> SDoc
    -- See note [emit-time elimination of static indirections] in "GHC.Cmm.CLabel".
    pprDatas :: NCGConfig -> (Alignment, RawCmmStatics) -> SDoc
    pprDatas NCGConfig
    config (Alignment
    _, CmmStaticsRaw CLabel
    alias [CmmStaticLit (CmmLabel CLabel
    lbl), CmmStaticLit CmmLit
    ind, CmmStatic
    _, CmmStatic
    _])
      | CLabel
    lbl forall a. Eq a => a -> a -> Bool
    == CLabel
    mkIndStaticInfoLabel
      , let labelInd :: CmmLit -> Maybe CLabel
    labelInd (CmmLabelOff CLabel
    l Int
    _) = forall a. a -> Maybe a
    Just CLabel
    l
            labelInd (CmmLabel CLabel
    l) = forall a. a -> Maybe a
    Just CLabel
    l
            labelInd CmmLit
    _ = forall a. Maybe a
    Nothing
      , Just CLabel
    ind' <- CmmLit -> Maybe CLabel
    labelInd CmmLit
    ind
      , CLabel
    alias CLabel -> CLabel -> Bool
    `mayRedirectTo` CLabel
    ind'
      = Platform -> CLabel -> SDoc
    pprGloblDecl (NCGConfig -> Platform
    ncgPlatform NCGConfig
    config) CLabel
    alias
        SDoc -> SDoc -> SDoc
    $$ String -> SDoc
    text String
    ".equiv" SDoc -> SDoc -> SDoc
    <+> forall env a. OutputableP env a => env -> a -> SDoc
    pdoc (NCGConfig -> Platform
    ncgPlatform NCGConfig
    config) CLabel
    alias SDoc -> SDoc -> SDoc
    <> SDoc
    comma SDoc -> SDoc -> SDoc
    <> forall env a. OutputableP env a => env -> a -> SDoc
    pdoc (NCGConfig -> Platform
    ncgPlatform NCGConfig
    config) (CLabel -> CmmLit
    CmmLabel CLabel
    ind')

    pprDatas NCGConfig
    config (Alignment
    align, (CmmStaticsRaw CLabel
    lbl [CmmStatic]
    dats))
     = [SDoc] -> SDoc
    vcat (Platform -> Alignment -> SDoc
    pprAlign Platform
    platform Alignment
    align forall a. a -> [a] -> [a]
    : Platform -> CLabel -> SDoc
    pprLabel Platform
    platform CLabel
    lbl forall a. a -> [a] -> [a]
    : forall a b. (a -> b) -> [a] -> [b]
    map (NCGConfig -> CmmStatic -> SDoc
    pprData NCGConfig
    config) [CmmStatic]
    dats)
       where
          platform :: Platform
    platform = NCGConfig -> Platform
    ncgPlatform NCGConfig
    config

    pprData :: NCGConfig -> CmmStatic -> SDoc
    pprData :: NCGConfig -> CmmStatic -> SDoc
    pprData NCGConfig
    _config (CmmString ByteString
    str) = ByteString -> SDoc
    pprString ByteString
    str
    pprData NCGConfig
    _config (CmmFileEmbed String
    path) = String -> SDoc
    pprFileEmbed String
    path

    pprData NCGConfig
    config (CmmUninitialised Int
    bytes)
     = let platform :: Platform
    platform = NCGConfig -> Platform
    ncgPlatform NCGConfig
    config
       in if Platform -> OS
    platformOS Platform
    platform forall a. Eq a => a -> a -> Bool
    == OS
    OSDarwin
             then String -> SDoc
    text String
    ".space " SDoc -> SDoc -> SDoc
    <> Int -> SDoc
    int Int
    bytes
             else String -> SDoc
    text String
    ".skip "  SDoc -> SDoc -> SDoc
    <> Int -> SDoc
    int Int
    bytes

    pprData NCGConfig
    config (CmmStaticLit CmmLit
    lit) = NCGConfig -> CmmLit -> SDoc
    pprDataItem NCGConfig
    config CmmLit
    lit

    pprGloblDecl :: Platform -> CLabel -> SDoc
    pprGloblDecl :: Platform -> CLabel -> SDoc
    pprGloblDecl Platform
    platform CLabel
    lbl
      | Bool -> Bool
    not (CLabel -> Bool
    externallyVisibleCLabel CLabel
    lbl) = SDoc
    empty
      | Bool
    otherwise = String -> SDoc
    text String
    ".globl " SDoc -> SDoc -> SDoc
    <> forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform CLabel
    lbl

    pprLabelType' :: Platform -> CLabel -> SDoc
    pprLabelType' :: Platform -> CLabel -> SDoc
    pprLabelType' Platform
    platform CLabel
    lbl =
      if CLabel -> Bool
    isCFunctionLabel CLabel
    lbl Bool -> Bool -> Bool
    || Bool
    functionOkInfoTable then
        String -> SDoc
    text String
    "@function"
      else
        String -> SDoc
    text String
    "@object"
      where
        {-
        NOTE: This is a bit hacky.

        With the `tablesNextToCode` info tables look like this:
        ```
          <info table data>
        label_info:
          <info table code>
        ```
        So actually info table label points exactly to the code and we can mark
        the label as @function. (This is required to make perf and potentially other
        tools to work on Haskell binaries).
        This usually works well but it can cause issues with a linker.
        A linker uses different algorithms for the relocation depending on
        the symbol type.For some reason, a linker will generate JUMP_SLOT relocation
        when constructor info table is referenced from a data section.
        This only happens with static constructor call so
        we mark _con_info symbols as `@object` to avoid the issue with relocations.

        @SimonMarlow hack explanation:
        "The reasoning goes like this:

        * The danger when we mark a symbol as `@function` is that the linker will
          redirect it to point to the PLT and use a `JUMP_SLOT` relocation when
          the symbol refers to something outside the current shared object.
          A PLT / JUMP_SLOT reference only works for symbols that we jump to, not
          for symbols representing data,, nor for info table symbol references which
          we expect to point directly to the info table.
        * GHC generates code that might refer to any info table symbol from the text
          segment, but that's OK, because those will be explicit GOT references
          generated by the code generator.
        * When we refer to info tables from the data segment, it's either
          * a FUN_STATIC/THUNK_STATIC local to this module
          * a `con_info` that could be from anywhere

        So, the only info table symbols that we might refer to from the data segment
        of another shared object are `con_info` symbols, so those are the ones we
        need to exclude from getting the @function treatment.
        "

        A good place to check for more
        https://gitlab.haskell.org/ghc/ghc/wikis/commentary/position-independent-code

        Another possible hack is to create an extra local function symbol for
        every code-like thing to give the needed information for to the tools
        but mess up with the relocation. https://phabricator.haskell.org/D4730
        -}
        functionOkInfoTable :: Bool
    functionOkInfoTable = Platform -> Bool
    platformTablesNextToCode Platform
    platform Bool -> Bool -> Bool
    &&
          CLabel -> Bool
    isInfoTableLabel CLabel
    lbl Bool -> Bool -> Bool
    && Bool -> Bool
    not (CLabel -> Bool
    isConInfoTableLabel CLabel
    lbl)

    pprTypeDecl :: Platform -> CLabel -> SDoc
    pprTypeDecl :: Platform -> CLabel -> SDoc
    pprTypeDecl Platform
    platform CLabel
    lbl
        = if OS -> Bool
    osElfTarget (Platform -> OS
    platformOS Platform
    platform) Bool -> Bool -> Bool
    && CLabel -> Bool
    externallyVisibleCLabel CLabel
    lbl
          then String -> SDoc
    text String
    ".type " SDoc -> SDoc -> SDoc
    <> forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform CLabel
    lbl SDoc -> SDoc -> SDoc
    <> PtrString -> SDoc
    ptext (String -> PtrString
    sLit  String
    ", ") SDoc -> SDoc -> SDoc
    <> Platform -> CLabel -> SDoc
    pprLabelType' Platform
    platform CLabel
    lbl
          else SDoc
    empty

    pprLabel :: Platform -> CLabel -> SDoc
    pprLabel :: Platform -> CLabel -> SDoc
    pprLabel Platform
    platform CLabel
    lbl =
       Platform -> CLabel -> SDoc
    pprGloblDecl Platform
    platform CLabel
    lbl
       SDoc -> SDoc -> SDoc
    $$ Platform -> CLabel -> SDoc
    pprTypeDecl Platform
    platform CLabel
    lbl
       SDoc -> SDoc -> SDoc
    $$ (forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform CLabel
    lbl SDoc -> SDoc -> SDoc
    <> Char -> SDoc
    char Char
    ':')

    pprAlign :: Platform -> Alignment -> SDoc
    pprAlign :: Platform -> Alignment -> SDoc
    pprAlign Platform
    platform Alignment
    alignment
            = String -> SDoc
    text String
    ".align " SDoc -> SDoc -> SDoc
    <> Int -> SDoc
    int (Platform -> Int
    alignmentOn Platform
    platform)
      where
            bytes :: Int
    bytes = Alignment -> Int
    alignmentBytes Alignment
    alignment
            alignmentOn :: Platform -> Int
    alignmentOn Platform
    platform = if Platform -> OS
    platformOS Platform
    platform forall a. Eq a => a -> a -> Bool
    == OS
    OSDarwin
                                   then Int -> Int
    log2 Int
    bytes
                                   else      Int
    bytes

            log2 :: Int -> Int  -- cache the common ones
            log2 :: Int -> Int
    log2 Int
    1 = Int
    0
            log2 Int
    2 = Int
    1
            log2 Int
    4 = Int
    2
            log2 Int
    8 = Int
    3
            log2 Int
    n = Int
    1 forall a. Num a => a -> a -> a
    + Int -> Int
    log2 (Int
    n forall a. Integral a => a -> a -> a
    `quot` Int
    2)

    pprReg :: Platform -> Format -> Reg -> SDoc
    pprReg :: Platform -> Format -> Reg -> SDoc
    pprReg Platform
    platform Format
    f Reg
    r
      = case Reg
    r of
          RegReal    (RealRegSingle Int
    i) ->
              if Platform -> Bool
    target32Bit Platform
    platform then Format -> Int -> SDoc
    ppr32_reg_no Format
    f Int
    i
                                      else Format -> Int -> SDoc
    ppr64_reg_no Format
    f Int
    i
          RegReal    (RealRegPair Int
    _ Int
    _) -> forall a. String -> a
    panic String
    "X86.Ppr: no reg pairs on this arch"
          RegVirtual (VirtualRegI  Unique
    u)  -> String -> SDoc
    text String
    "%vI_"   SDoc -> SDoc -> SDoc
    <> Unique -> SDoc
    pprUniqueAlways Unique
    u
          RegVirtual (VirtualRegHi Unique
    u)  -> String -> SDoc
    text String
    "%vHi_"  SDoc -> SDoc -> SDoc
    <> Unique -> SDoc
    pprUniqueAlways Unique
    u
          RegVirtual (VirtualRegF  Unique
    u)  -> String -> SDoc
    text String
    "%vF_"   SDoc -> SDoc -> SDoc
    <> Unique -> SDoc
    pprUniqueAlways Unique
    u
          RegVirtual (VirtualRegD  Unique
    u)  -> String -> SDoc
    text String
    "%vD_"   SDoc -> SDoc -> SDoc
    <> Unique -> SDoc
    pprUniqueAlways Unique
    u

      where
        ppr32_reg_no :: Format -> Int -> SDoc
        ppr32_reg_no :: Format -> Int -> SDoc
    ppr32_reg_no Format
    II8   = forall {a}. (Eq a, Num a, Show a) => a -> SDoc
    ppr32_reg_byte
        ppr32_reg_no Format
    II16  = forall {a}. (Eq a, Num a) => a -> SDoc
    ppr32_reg_word
        ppr32_reg_no Format
    _     = Int -> SDoc
    ppr32_reg_long

        ppr32_reg_byte :: a -> SDoc
    ppr32_reg_byte a
    i = PtrString -> SDoc
    ptext
          (case a
    i of {
             a
    0 -> String -> PtrString
    sLit String
    "%al";     a
    1 -> String -> PtrString
    sLit String
    "%bl";
             a
    2 -> String -> PtrString
    sLit String
    "%cl";     a
    3 -> String -> PtrString
    sLit String
    "%dl";
            a
    _  -> String -> PtrString
    sLit forall a b. (a -> b) -> a -> b
    $ String
    "very naughty I386 byte register: " forall a. [a] -> [a] -> [a]
    ++ forall a. Show a => a -> String
    show a
    i
          })

        ppr32_reg_word :: a -> SDoc
    ppr32_reg_word a
    i = PtrString -> SDoc
    ptext
          (case a
    i of {
             a
    0 -> String -> PtrString
    sLit String
    "%ax";     a
    1 -> String -> PtrString
    sLit String
    "%bx";
             a
    2 -> String -> PtrString
    sLit String
    "%cx";     a
    3 -> String -> PtrString
    sLit String
    "%dx";
             a
    4 -> String -> PtrString
    sLit String
    "%si";     a
    5 -> String -> PtrString
    sLit String
    "%di";
             a
    6 -> String -> PtrString
    sLit String
    "%bp";     a
    7 -> String -> PtrString
    sLit String
    "%sp";
            a
    _  -> String -> PtrString
    sLit String
    "very naughty I386 word register"
          })

        ppr32_reg_long :: Int -> SDoc
    ppr32_reg_long Int
    i = PtrString -> SDoc
    ptext
          (case Int
    i of {
             Int
    0 -> String -> PtrString
    sLit String
    "%eax";    Int
    1 -> String -> PtrString
    sLit String
    "%ebx";
             Int
    2 -> String -> PtrString
    sLit String
    "%ecx";    Int
    3 -> String -> PtrString
    sLit String
    "%edx";
             Int
    4 -> String -> PtrString
    sLit String
    "%esi";    Int
    5 -> String -> PtrString
    sLit String
    "%edi";
             Int
    6 -> String -> PtrString
    sLit String
    "%ebp";    Int
    7 -> String -> PtrString
    sLit String
    "%esp";
             Int
    _  -> Int -> PtrString
    ppr_reg_float Int
    i
          })

        ppr64_reg_no :: Format -> Int -> SDoc
        ppr64_reg_no :: Format -> Int -> SDoc
    ppr64_reg_no Format
    II8   = forall {a}. (Eq a, Num a, Show a) => a -> SDoc
    ppr64_reg_byte
        ppr64_reg_no Format
    II16  = forall {a}. (Eq a, Num a) => a -> SDoc
    ppr64_reg_word
        ppr64_reg_no Format
    II32  = forall {a}. (Eq a, Num a) => a -> SDoc
    ppr64_reg_long
        ppr64_reg_no Format
    _     = Int -> SDoc
    ppr64_reg_quad

        ppr64_reg_byte :: a -> SDoc
    ppr64_reg_byte a
    i = PtrString -> SDoc
    ptext
          (case a
    i of {
             a
    0 -> String -> PtrString
    sLit String
    "%al";     a
    1 -> String -> PtrString
    sLit String
    "%bl";
             a
    2 -> String -> PtrString
    sLit String
    "%cl";     a
    3 -> String -> PtrString
    sLit String
    "%dl";
             a
    4 -> String -> PtrString
    sLit String
    "%sil";    a
    5 -> String -> PtrString
    sLit String
    "%dil"; -- new 8-bit regs!
             a
    6 -> String -> PtrString
    sLit String
    "%bpl";    a
    7 -> String -> PtrString
    sLit String
    "%spl";
             a
    8 -> String -> PtrString
    sLit String
    "%r8b";    a
    9  -> String -> PtrString
    sLit String
    "%r9b";
            a
    10 -> String -> PtrString
    sLit String
    "%r10b";   a
    11 -> String -> PtrString
    sLit String
    "%r11b";
            a
    12 -> String -> PtrString
    sLit String
    "%r12b";   a
    13 -> String -> PtrString
    sLit String
    "%r13b";
            a
    14 -> String -> PtrString
    sLit String
    "%r14b";   a
    15 -> String -> PtrString
    sLit String
    "%r15b";
            a
    _  -> String -> PtrString
    sLit forall a b. (a -> b) -> a -> b
    $ String
    "very naughty x86_64 byte register: " forall a. [a] -> [a] -> [a]
    ++ forall a. Show a => a -> String
    show a
    i
          })

        ppr64_reg_word :: a -> SDoc
    ppr64_reg_word a
    i = PtrString -> SDoc
    ptext
          (case a
    i of {
             a
    0 -> String -> PtrString
    sLit String
    "%ax";     a
    1 -> String -> PtrString
    sLit String
    "%bx";
             a
    2 -> String -> PtrString
    sLit String
    "%cx";     a
    3 -> String -> PtrString
    sLit String
    "%dx";
             a
    4 -> String -> PtrString
    sLit String
    "%si";     a
    5 -> String -> PtrString
    sLit String
    "%di";
             a
    6 -> String -> PtrString
    sLit String
    "%bp";     a
    7 -> String -> PtrString
    sLit String
    "%sp";
             a
    8 -> String -> PtrString
    sLit String
    "%r8w";    a
    9  -> String -> PtrString
    sLit String
    "%r9w";
            a
    10 -> String -> PtrString
    sLit String
    "%r10w";   a
    11 -> String -> PtrString
    sLit String
    "%r11w";
            a
    12 -> String -> PtrString
    sLit String
    "%r12w";   a
    13 -> String -> PtrString
    sLit String
    "%r13w";
            a
    14 -> String -> PtrString
    sLit String
    "%r14w";   a
    15 -> String -> PtrString
    sLit String
    "%r15w";
            a
    _  -> String -> PtrString
    sLit String
    "very naughty x86_64 word register"
          })

        ppr64_reg_long :: a -> SDoc
    ppr64_reg_long a
    i = PtrString -> SDoc
    ptext
          (case a
    i of {
             a
    0 -> String -> PtrString
    sLit String
    "%eax";    a
    1  -> String -> PtrString
    sLit String
    "%ebx";
             a
    2 -> String -> PtrString
    sLit String
    "%ecx";    a
    3  -> String -> PtrString
    sLit String
    "%edx";
             a
    4 -> String -> PtrString
    sLit String
    "%esi";    a
    5  -> String -> PtrString
    sLit String
    "%edi";
             a
    6 -> String -> PtrString
    sLit String
    "%ebp";    a
    7  -> String -> PtrString
    sLit String
    "%esp";
             a
    8 -> String -> PtrString
    sLit String
    "%r8d";    a
    9  -> String -> PtrString
    sLit String
    "%r9d";
            a
    10 -> String -> PtrString
    sLit String
    "%r10d";   a
    11 -> String -> PtrString
    sLit String
    "%r11d";
            a
    12 -> String -> PtrString
    sLit String
    "%r12d";   a
    13 -> String -> PtrString
    sLit String
    "%r13d";
            a
    14 -> String -> PtrString
    sLit String
    "%r14d";   a
    15 -> String -> PtrString
    sLit String
    "%r15d";
            a
    _  -> String -> PtrString
    sLit String
    "very naughty x86_64 register"
          })

        ppr64_reg_quad :: Int -> SDoc
    ppr64_reg_quad Int
    i = PtrString -> SDoc
    ptext
          (case Int
    i of {
             Int
    0 -> String -> PtrString
    sLit String
    "%rax";      Int
    1 -> String -> PtrString
    sLit String
    "%rbx";
             Int
    2 -> String -> PtrString
    sLit String
    "%rcx";      Int
    3 -> String -> PtrString
    sLit String
    "%rdx";
             Int
    4 -> String -> PtrString
    sLit String
    "%rsi";      Int
    5 -> String -> PtrString
    sLit String
    "%rdi";
             Int
    6 -> String -> PtrString
    sLit String
    "%rbp";      Int
    7 -> String -> PtrString
    sLit String
    "%rsp";
             Int
    8 -> String -> PtrString
    sLit String
    "%r8";       Int
    9 -> String -> PtrString
    sLit String
    "%r9";
            Int
    10 -> String -> PtrString
    sLit String
    "%r10";    Int
    11 -> String -> PtrString
    sLit String
    "%r11";
            Int
    12 -> String -> PtrString
    sLit String
    "%r12";    Int
    13 -> String -> PtrString
    sLit String
    "%r13";
            Int
    14 -> String -> PtrString
    sLit String
    "%r14";    Int
    15 -> String -> PtrString
    sLit String
    "%r15";
            Int
    _  -> Int -> PtrString
    ppr_reg_float Int
    i
          })

    ppr_reg_float :: Int -> PtrString
    ppr_reg_float :: Int -> PtrString
    ppr_reg_float Int
    i = case Int
    i of
            Int
    16 -> String -> PtrString
    sLit String
    "%xmm0" ;   Int
    17 -> String -> PtrString
    sLit String
    "%xmm1"
            Int
    18 -> String -> PtrString
    sLit String
    "%xmm2" ;   Int
    19 -> String -> PtrString
    sLit String
    "%xmm3"
            Int
    20 -> String -> PtrString
    sLit String
    "%xmm4" ;   Int
    21 -> String -> PtrString
    sLit String
    "%xmm5"
            Int
    22 -> String -> PtrString
    sLit String
    "%xmm6" ;   Int
    23 -> String -> PtrString
    sLit String
    "%xmm7"
            Int
    24 -> String -> PtrString
    sLit String
    "%xmm8" ;   Int
    25 -> String -> PtrString
    sLit String
    "%xmm9"
            Int
    26 -> String -> PtrString
    sLit String
    "%xmm10";   Int
    27 -> String -> PtrString
    sLit String
    "%xmm11"
            Int
    28 -> String -> PtrString
    sLit String
    "%xmm12";   Int
    29 -> String -> PtrString
    sLit String
    "%xmm13"
            Int
    30 -> String -> PtrString
    sLit String
    "%xmm14";   Int
    31 -> String -> PtrString
    sLit String
    "%xmm15"
            Int
    _  -> String -> PtrString
    sLit String
    "very naughty x86 register"

    pprFormat :: Format -> SDoc
    pprFormat :: Format -> SDoc
    pprFormat Format
    x
     = PtrString -> SDoc
    ptext (case Format
    x of
                    Format
    II8   -> String -> PtrString
    sLit String
    "b"
                    Format
    II16  -> String -> PtrString
    sLit String
    "w"
                    Format
    II32  -> String -> PtrString
    sLit String
    "l"
                    Format
    II64  -> String -> PtrString
    sLit String
    "q"
                    Format
    FF32  -> String -> PtrString
    sLit String
    "ss"      -- "scalar single-precision float" (SSE2)
                    Format
    FF64  -> String -> PtrString
    sLit String
    "sd"      -- "scalar double-precision float" (SSE2)
                    )

    pprFormat_x87 :: Format -> SDoc
    pprFormat_x87 :: Format -> SDoc
    pprFormat_x87 Format
    x
      = PtrString -> SDoc
    ptext forall a b. (a -> b) -> a -> b
    $ case Format
    x of
                    Format
    FF32  -> String -> PtrString
    sLit String
    "s"
                    Format
    FF64  -> String -> PtrString
    sLit String
    "l"
                    Format
    _     -> forall a. String -> a
    panic String
    "X86.Ppr.pprFormat_x87"

    pprCond :: Cond -> SDoc
    pprCond :: Cond -> SDoc
    pprCond Cond
    c
     = PtrString -> SDoc
    ptext (case Cond
    c of {
                    Cond
    GEU     -> String -> PtrString
    sLit String
    "ae";   Cond
    LU    -> String -> PtrString
    sLit String
    "b";
                    Cond
    EQQ     -> String -> PtrString
    sLit String
    "e";    Cond
    GTT   -> String -> PtrString
    sLit String
    "g";
                    Cond
    GE      -> String -> PtrString
    sLit String
    "ge";   Cond
    GU    -> String -> PtrString
    sLit String
    "a";
                    Cond
    LTT     -> String -> PtrString
    sLit String
    "l";    Cond
    LE    -> String -> PtrString
    sLit String
    "le";
                    Cond
    LEU     -> String -> PtrString
    sLit String
    "be";   Cond
    NE    -> String -> PtrString
    sLit String
    "ne";
                    Cond
    NEG     -> String -> PtrString
    sLit String
    "s";    Cond
    POS   -> String -> PtrString
    sLit String
    "ns";
                    Cond
    CARRY   -> String -> PtrString
    sLit String
    "c";   Cond
    OFLO  -> String -> PtrString
    sLit String
    "o";
                    Cond
    PARITY  -> String -> PtrString
    sLit String
    "p";   Cond
    NOTPARITY -> String -> PtrString
    sLit String
    "np";
                    Cond
    ALWAYS  -> String -> PtrString
    sLit String
    "mp"})

    pprImm :: Platform -> Imm -> SDoc
    pprImm :: Platform -> Imm -> SDoc
    pprImm Platform
    platform = \case
       ImmInt Int
    i            -> Int -> SDoc
    int Int
    i
       ImmInteger Integer
    i        -> Integer -> SDoc
    integer Integer
    i
       ImmCLbl CLabel
    l           -> forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform CLabel
    l
       ImmIndex CLabel
    l Int
    i        -> forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform CLabel
    l SDoc -> SDoc -> SDoc
    <> Char -> SDoc
    char Char
    '+' SDoc -> SDoc -> SDoc
    <> Int -> SDoc
    int Int
    i
       ImmLit SDoc
    s            -> SDoc
    s
       ImmFloat Rational
    f          -> Float -> SDoc
    float forall a b. (a -> b) -> a -> b
    $ forall a. Fractional a => Rational -> a
    fromRational Rational
    f
       ImmDouble Rational
    d         -> Double -> SDoc
    double forall a b. (a -> b) -> a -> b
    $ forall a. Fractional a => Rational -> a
    fromRational Rational
    d
       ImmConstantSum Imm
    a Imm
    b  -> Platform -> Imm -> SDoc
    pprImm Platform
    platform Imm
    a SDoc -> SDoc -> SDoc
    <> Char -> SDoc
    char Char
    '+' SDoc -> SDoc -> SDoc
    <> Platform -> Imm -> SDoc
    pprImm Platform
    platform Imm
    b
       ImmConstantDiff Imm
    a Imm
    b -> Platform -> Imm -> SDoc
    pprImm Platform
    platform Imm
    a SDoc -> SDoc -> SDoc
    <> Char -> SDoc
    char Char
    '-' SDoc -> SDoc -> SDoc
    <> SDoc
    lparen SDoc -> SDoc -> SDoc
    <> Platform -> Imm -> SDoc
    pprImm Platform
    platform Imm
    b SDoc -> SDoc -> SDoc
    <> SDoc
    rparen

    pprAddr :: Platform -> AddrMode -> SDoc
    pprAddr :: Platform -> AddrMode -> SDoc
    pprAddr Platform
    platform (ImmAddr Imm
    imm Int
    off)
      = let pp_imm :: SDoc
    pp_imm = Platform -> Imm -> SDoc
    pprImm Platform
    platform Imm
    imm
        in
        if (Int
    off forall a. Eq a => a -> a -> Bool
    == Int
    0) then
            SDoc
    pp_imm
        else if (Int
    off forall a. Ord a => a -> a -> Bool
    < Int
    0) then
            SDoc
    pp_imm SDoc -> SDoc -> SDoc
    <> Int -> SDoc
    int Int
    off
        else
            SDoc
    pp_imm SDoc -> SDoc -> SDoc
    <> Char -> SDoc
    char Char
    '+' SDoc -> SDoc -> SDoc
    <> Int -> SDoc
    int Int
    off

    pprAddr Platform
    platform (AddrBaseIndex EABase
    base EAIndex
    index Imm
    displacement)
      = let
            pp_disp :: SDoc
    pp_disp  = Imm -> SDoc
    ppr_disp Imm
    displacement
            pp_off :: SDoc -> SDoc
    pp_off SDoc
    p = SDoc
    pp_disp SDoc -> SDoc -> SDoc
    <> Char -> SDoc
    char Char
    '(' SDoc -> SDoc -> SDoc
    <> SDoc
    p SDoc -> SDoc -> SDoc
    <> Char -> SDoc
    char Char
    ')'
            pp_reg :: Reg -> SDoc
    pp_reg Reg
    r = Platform -> Format -> Reg -> SDoc
    pprReg Platform
    platform (Bool -> Format
    archWordFormat (Platform -> Bool
    target32Bit Platform
    platform)) Reg
    r
        in
        case (EABase
    base, EAIndex
    index) of
          (EABase
    EABaseNone,  EAIndex
    EAIndexNone) -> SDoc
    pp_disp
          (EABaseReg Reg
    b, EAIndex
    EAIndexNone) -> SDoc -> SDoc
    pp_off (Reg -> SDoc
    pp_reg Reg
    b)
          (EABase
    EABaseRip,   EAIndex
    EAIndexNone) -> SDoc -> SDoc
    pp_off (String -> SDoc
    text String
    "%rip")
          (EABase
    EABaseNone,  EAIndex Reg
    r Int
    i) -> SDoc -> SDoc
    pp_off (SDoc
    comma SDoc -> SDoc -> SDoc
    <> Reg -> SDoc
    pp_reg Reg
    r SDoc -> SDoc -> SDoc
    <> SDoc
    comma SDoc -> SDoc -> SDoc
    <> Int -> SDoc
    int Int
    i)
          (EABaseReg Reg
    b, EAIndex Reg
    r Int
    i) -> SDoc -> SDoc
    pp_off (Reg -> SDoc
    pp_reg Reg
    b SDoc -> SDoc -> SDoc
    <> SDoc
    comma SDoc -> SDoc -> SDoc
    <> Reg -> SDoc
    pp_reg Reg
    r
                                           SDoc -> SDoc -> SDoc
    <> SDoc
    comma SDoc -> SDoc -> SDoc
    <> Int -> SDoc
    int Int
    i)
          (EABase, EAIndex)
    _                         -> forall a. String -> a
    panic String
    "X86.Ppr.pprAddr: no match"

      where
        ppr_disp :: Imm -> SDoc
    ppr_disp (ImmInt Int
    0) = SDoc
    empty
        ppr_disp Imm
    imm        = Platform -> Imm -> SDoc
    pprImm Platform
    platform Imm
    imm

    -- | Print section header and appropriate alignment for that section.
    pprSectionAlign :: NCGConfig -> Section -> SDoc
    pprSectionAlign :: NCGConfig -> Section -> SDoc
    pprSectionAlign NCGConfig
    _config (Section (OtherSection String
    _) CLabel
    _) =
         forall a. String -> a
    panic String
    "X86.Ppr.pprSectionAlign: unknown section"
    pprSectionAlign NCGConfig
    config sec :: Section
    sec@(Section SectionType
    seg CLabel
    _) =
        NCGConfig -> Section -> SDoc
    pprSectionHeader NCGConfig
    config Section
    sec SDoc -> SDoc -> SDoc
    $$
        Platform -> SectionType -> SDoc
    pprAlignForSection (NCGConfig -> Platform
    ncgPlatform NCGConfig
    config) SectionType
    seg

    -- | Print appropriate alignment for the given section type.
    pprAlignForSection :: Platform -> SectionType -> SDoc
    pprAlignForSection :: Platform -> SectionType -> SDoc
    pprAlignForSection Platform
    platform SectionType
    seg =
        String -> SDoc
    text String
    ".align " SDoc -> SDoc -> SDoc
    <>
        case Platform -> OS
    platformOS Platform
    platform of
          -- Darwin: alignments are given as shifts.
          OS
    OSDarwin
           | Platform -> Bool
    target32Bit Platform
    platform ->
              case SectionType
    seg of
               SectionType
    ReadOnlyData16    -> Int -> SDoc
    int Int
    4
               SectionType
    CString           -> Int -> SDoc
    int Int
    1
               SectionType
    _                 -> Int -> SDoc
    int Int
    2
           | Bool
    otherwise ->
              case SectionType
    seg of
               SectionType
    ReadOnlyData16    -> Int -> SDoc
    int Int
    4
               SectionType
    CString           -> Int -> SDoc
    int Int
    1
               SectionType
    _                 -> Int -> SDoc
    int Int
    3
          -- Other: alignments are given as bytes.
          OS
    _
           | Platform -> Bool
    target32Bit Platform
    platform ->
              case SectionType
    seg of
               SectionType
    Text              -> String -> SDoc
    text String
    "4,0x90"
               SectionType
    ReadOnlyData16    -> Int -> SDoc
    int Int
    16
               SectionType
    CString           -> Int -> SDoc
    int Int
    1
               SectionType
    _                 -> Int -> SDoc
    int Int
    4
           | Bool
    otherwise ->
              case SectionType
    seg of
               SectionType
    ReadOnlyData16    -> Int -> SDoc
    int Int
    16
               SectionType
    CString           -> Int -> SDoc
    int Int
    1
               SectionType
    _                 -> Int -> SDoc
    int Int
    8

    pprDataItem :: NCGConfig -> CmmLit -> SDoc
    pprDataItem :: NCGConfig -> CmmLit -> SDoc
    pprDataItem NCGConfig
    config CmmLit
    lit
      = [SDoc] -> SDoc
    vcat (Format -> CmmLit -> [SDoc]
    ppr_item (CmmType -> Format
    cmmTypeFormat forall a b. (a -> b) -> a -> b
    $ Platform -> CmmLit -> CmmType
    cmmLitType Platform
    platform CmmLit
    lit) CmmLit
    lit)
        where
            platform :: Platform
    platform = NCGConfig -> Platform
    ncgPlatform NCGConfig
    config
            imm :: Imm
    imm = CmmLit -> Imm
    litToImm CmmLit
    lit

            -- These seem to be common:
            ppr_item :: Format -> CmmLit -> [SDoc]
    ppr_item Format
    II8   CmmLit
    _ = [String -> SDoc
    text String
    "\t.byte\t" SDoc -> SDoc -> SDoc
    <> Platform -> Imm -> SDoc
    pprImm Platform
    platform Imm
    imm]
            ppr_item Format
    II16  CmmLit
    _ = [String -> SDoc
    text String
    "\t.word\t" SDoc -> SDoc -> SDoc
    <> Platform -> Imm -> SDoc
    pprImm Platform
    platform Imm
    imm]
            ppr_item Format
    II32  CmmLit
    _ = [String -> SDoc
    text String
    "\t.long\t" SDoc -> SDoc -> SDoc
    <> Platform -> Imm -> SDoc
    pprImm Platform
    platform Imm
    imm]

            ppr_item Format
    FF32 CmmLit
    _ = [String -> SDoc
    text String
    "\t.float\t" SDoc -> SDoc -> SDoc
    <> Platform -> Imm -> SDoc
    pprImm Platform
    platform Imm
    imm]
            ppr_item Format
    FF64 CmmLit
    _ = [String -> SDoc
    text String
    "\t.double\t" SDoc -> SDoc -> SDoc
    <> Platform -> Imm -> SDoc
    pprImm Platform
    platform Imm
    imm]

            ppr_item Format
    II64 CmmLit
    _
                = case Platform -> OS
    platformOS Platform
    platform of
                  OS
    OSDarwin
                   | Platform -> Bool
    target32Bit Platform
    platform ->
                      case CmmLit
    lit of
                      CmmInt Integer
    x Width
    _ ->
                          [String -> SDoc
    text String
    "\t.long\t"
                              SDoc -> SDoc -> SDoc
    <> Int -> SDoc
    int (forall a b. (Integral a, Num b) => a -> b
    fromIntegral (forall a b. (Integral a, Num b) => a -> b
    fromIntegral Integer
    x :: Word32)),
                           String -> SDoc
    text String
    "\t.long\t"
                              SDoc -> SDoc -> SDoc
    <> Int -> SDoc
    int (forall a b. (Integral a, Num b) => a -> b
    fromIntegral
                                  (forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Integer
    x forall a. Bits a => a -> Int -> a
    `shiftR` Int
    32) :: Word32))]
                      CmmLit
    _ -> forall a. String -> a
    panic String
    "X86.Ppr.ppr_item: no match for II64"
                   | Bool
    otherwise ->
                      [String -> SDoc
    text String
    "\t.quad\t" SDoc -> SDoc -> SDoc
    <> Platform -> Imm -> SDoc
    pprImm Platform
    platform Imm
    imm]
                  OS
    _
                   | Platform -> Bool
    target32Bit Platform
    platform ->
                      [String -> SDoc
    text String
    "\t.quad\t" SDoc -> SDoc -> SDoc
    <> Platform -> Imm -> SDoc
    pprImm Platform
    platform Imm
    imm]
                   | Bool
    otherwise ->
                      -- x86_64: binutils can't handle the R_X86_64_PC64
                      -- relocation type, which means we can't do
                      -- pc-relative 64-bit addresses. Fortunately we're
                      -- assuming the small memory model, in which all such
                      -- offsets will fit into 32 bits, so we have to stick
                      -- to 32-bit offset fields and modify the RTS
                      -- appropriately
                      --
                      -- See Note [x86-64-relative] in includes/rts/storage/InfoTables.h
                      --
                      case CmmLit
    lit of
                      -- A relative relocation:
                      CmmLabelDiffOff CLabel
    _ CLabel
    _ Int
    _ Width
    _ ->
                          [String -> SDoc
    text String
    "\t.long\t" SDoc -> SDoc -> SDoc
    <> Platform -> Imm -> SDoc
    pprImm Platform
    platform Imm
    imm,
                           String -> SDoc
    text String
    "\t.long\t0"]
                      CmmLit
    _ ->
                          [String -> SDoc
    text String
    "\t.quad\t" SDoc -> SDoc -> SDoc
    <> Platform -> Imm -> SDoc
    pprImm Platform
    platform Imm
    imm]

    asmComment :: SDoc -> SDoc
    asmComment :: SDoc -> SDoc
    asmComment SDoc
    c = SDoc -> SDoc
    whenPprDebug forall a b. (a -> b) -> a -> b
    $ String -> SDoc
    text String
    "# " SDoc -> SDoc -> SDoc
    <> SDoc
    c

    pprInstr :: Platform -> Instr -> SDoc
    pprInstr :: Platform -> Instr -> SDoc
    pprInstr Platform
    platform Instr
    i = case Instr
    i of
       COMMENT FastString
    s
          -> SDoc -> SDoc
    asmComment (FastString -> SDoc
    ftext FastString
    s)

       LOCATION Int
    file Int
    line Int
    col String
    _name
          -> String -> SDoc
    text String
    "\t.loc " SDoc -> SDoc -> SDoc
    <> forall a. Outputable a => a -> SDoc
    ppr Int
    file SDoc -> SDoc -> SDoc
    <+> forall a. Outputable a => a -> SDoc
    ppr Int
    line SDoc -> SDoc -> SDoc
    <+> forall a. Outputable a => a -> SDoc
    ppr Int
    col

       DELTA Int
    d
          -> SDoc -> SDoc
    asmComment forall a b. (a -> b) -> a -> b
    $ String -> SDoc
    text (String
    "\tdelta = " forall a. [a] -> [a] -> [a]
    ++ forall a. Show a => a -> String
    show Int
    d)

       NEWBLOCK BlockId
    _
          -> forall a. String -> a
    panic String
    "pprInstr: NEWBLOCK"

       UNWIND CLabel
    lbl UnwindTable
    d
          -> SDoc -> SDoc
    asmComment (String -> SDoc
    text String
    "\tunwind = " SDoc -> SDoc -> SDoc
    <> forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform UnwindTable
    d)
             SDoc -> SDoc -> SDoc
    $$ forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform CLabel
    lbl SDoc -> SDoc -> SDoc
    <> SDoc
    colon

       LDATA Section
    _ (Alignment, RawCmmStatics)
    _
          -> forall a. String -> a
    panic String
    "pprInstr: LDATA"

    {-
       SPILL reg slot
          -> hcat [
               text "\tSPILL",
               char ' ',
               pprUserReg reg,
               comma,
               text "SLOT" <> parens (int slot)]

       RELOAD slot reg
          -> hcat [
            text "\tRELOAD",
            char ' ',
            text "SLOT" <> parens (int slot),
            comma,
            pprUserReg reg]
    -}

       -- Replace 'mov $0x0,%reg' by 'xor %reg,%reg', which is smaller and cheaper.
       -- The code generator catches most of these already, but not all.
       MOV Format
    format (OpImm (ImmInt Int
    0)) dst :: Operand
    dst@(OpReg Reg
    _)
         -> Platform -> Instr -> SDoc
    pprInstr Platform
    platform (Format -> Operand -> Operand -> Instr
    XOR Format
    format' Operand
    dst Operand
    dst)
            where format' :: Format
    format' = case Format
    format of
                    Format
    II64 -> Format
    II32          -- 32-bit version is equivalent, and smaller
                    Format
    _    -> Format
    format

       MOV Format
    format Operand
    src Operand
    dst
         -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "mov") Format
    format Operand
    src Operand
    dst

       CMOV Cond
    cc Format
    format Operand
    src Reg
    dst
         -> PtrString -> Format -> Cond -> Operand -> Reg -> SDoc
    pprCondOpReg (String -> PtrString
    sLit String
    "cmov") Format
    format Cond
    cc Operand
    src Reg
    dst

       MOVZxL Format
    II32 Operand
    src Operand
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "mov") Format
    II32 Operand
    src Operand
    dst
            -- 32-to-64 bit zero extension on x86_64 is accomplished by a simple
            -- movl.  But we represent it as a MOVZxL instruction, because
            -- the reg alloc would tend to throw away a plain reg-to-reg
            -- move, and we still want it to do that.

       MOVZxL Format
    formats Operand
    src Operand
    dst
          -> PtrString -> Format -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOpCoerce (String -> PtrString
    sLit String
    "movz") Format
    formats Format
    II32 Operand
    src Operand
    dst
            -- zero-extension only needs to extend to 32 bits: on x86_64,
            -- the remaining zero-extension to 64 bits is automatic, and the 32-bit
            -- instruction is shorter.

       MOVSxL Format
    formats Operand
    src Operand
    dst
          -> PtrString -> Format -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOpCoerce (String -> PtrString
    sLit String
    "movs") Format
    formats (Bool -> Format
    archWordFormat (Platform -> Bool
    target32Bit Platform
    platform)) Operand
    src Operand
    dst

       -- here we do some patching, since the physical registers are only set late
       -- in the code generation.
       LEA Format
    format (OpAddr (AddrBaseIndex (EABaseReg Reg
    reg1) (EAIndex Reg
    reg2 Int
    1) (ImmInt Int
    0))) dst :: Operand
    dst@(OpReg Reg
    reg3)
          | Reg
    reg1 forall a. Eq a => a -> a -> Bool
    == Reg
    reg3
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "add") Format
    format (Reg -> Operand
    OpReg Reg
    reg2) Operand
    dst

       LEA Format
    format (OpAddr (AddrBaseIndex (EABaseReg Reg
    reg1) (EAIndex Reg
    reg2 Int
    1) (ImmInt Int
    0))) dst :: Operand
    dst@(OpReg Reg
    reg3)
          | Reg
    reg2 forall a. Eq a => a -> a -> Bool
    == Reg
    reg3
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "add") Format
    format (Reg -> Operand
    OpReg Reg
    reg1) Operand
    dst

       LEA Format
    format (OpAddr (AddrBaseIndex (EABaseReg Reg
    reg1) EAIndex
    EAIndexNone Imm
    displ)) dst :: Operand
    dst@(OpReg Reg
    reg3)
          | Reg
    reg1 forall a. Eq a => a -> a -> Bool
    == Reg
    reg3
          -> Platform -> Instr -> SDoc
    pprInstr Platform
    platform (Format -> Operand -> Operand -> Instr
    ADD Format
    format (Imm -> Operand
    OpImm Imm
    displ) Operand
    dst)

       LEA Format
    format Operand
    src Operand
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "lea") Format
    format Operand
    src Operand
    dst

       ADD Format
    format (OpImm (ImmInt (-1))) Operand
    dst
          -> PtrString -> Format -> Operand -> SDoc
    pprFormatOp (String -> PtrString
    sLit String
    "dec") Format
    format Operand
    dst

       ADD Format
    format (OpImm (ImmInt Int
    1)) Operand
    dst
          -> PtrString -> Format -> Operand -> SDoc
    pprFormatOp (String -> PtrString
    sLit String
    "inc") Format
    format Operand
    dst

       ADD Format
    format Operand
    src Operand
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "add") Format
    format Operand
    src Operand
    dst

       ADC Format
    format Operand
    src Operand
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "adc") Format
    format Operand
    src Operand
    dst

       SUB Format
    format Operand
    src Operand
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "sub") Format
    format Operand
    src Operand
    dst

       SBB Format
    format Operand
    src Operand
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "sbb") Format
    format Operand
    src Operand
    dst

       IMUL Format
    format Operand
    op1 Operand
    op2
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "imul") Format
    format Operand
    op1 Operand
    op2

       ADD_CC Format
    format Operand
    src Operand
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "add") Format
    format Operand
    src Operand
    dst

       SUB_CC Format
    format Operand
    src Operand
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "sub") Format
    format Operand
    src Operand
    dst

       -- Use a 32-bit instruction when possible as it saves a byte.
       -- Notably, extracting the tag bits of a pointer has this form.
       -- TODO: we could save a byte in a subsequent CMP instruction too,
       -- but need something like a peephole pass for this
       AND Format
    II64 src :: Operand
    src@(OpImm (ImmInteger Integer
    mask)) Operand
    dst
          | Integer
    0 forall a. Ord a => a -> a -> Bool
    <= Integer
    mask Bool -> Bool -> Bool
    && Integer
    mask forall a. Ord a => a -> a -> Bool
    < Integer
    0xffffffff
          -> Platform -> Instr -> SDoc
    pprInstr Platform
    platform (Format -> Operand -> Operand -> Instr
    AND Format
    II32 Operand
    src Operand
    dst)

       AND Format
    FF32 Operand
    src Operand
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprOpOp (String -> PtrString
    sLit String
    "andps") Format
    FF32 Operand
    src Operand
    dst

       AND Format
    FF64 Operand
    src Operand
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprOpOp (String -> PtrString
    sLit String
    "andpd") Format
    FF64 Operand
    src Operand
    dst

       AND Format
    format Operand
    src Operand
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "and") Format
    format Operand
    src Operand
    dst

       OR  Format
    format Operand
    src Operand
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "or")  Format
    format Operand
    src Operand
    dst

       XOR Format
    FF32 Operand
    src Operand
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprOpOp (String -> PtrString
    sLit String
    "xorps") Format
    FF32 Operand
    src Operand
    dst

       XOR Format
    FF64 Operand
    src Operand
    dst
          ->  PtrString -> Format -> Operand -> Operand -> SDoc
    pprOpOp (String -> PtrString
    sLit String
    "xorpd") Format
    FF64 Operand
    src Operand
    dst

       XOR Format
    format Operand
    src Operand
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "xor") Format
    format Operand
    src Operand
    dst

       POPCNT Format
    format Operand
    src Reg
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprOpOp (String -> PtrString
    sLit String
    "popcnt") Format
    format Operand
    src (Reg -> Operand
    OpReg Reg
    dst)

       LZCNT Format
    format Operand
    src Reg
    dst
          ->  PtrString -> Format -> Operand -> Operand -> SDoc
    pprOpOp (String -> PtrString
    sLit String
    "lzcnt") Format
    format Operand
    src (Reg -> Operand
    OpReg Reg
    dst)

       TZCNT Format
    format Operand
    src Reg
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprOpOp (String -> PtrString
    sLit String
    "tzcnt") Format
    format Operand
    src (Reg -> Operand
    OpReg Reg
    dst)

       BSF Format
    format Operand
    src Reg
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprOpOp (String -> PtrString
    sLit String
    "bsf") Format
    format Operand
    src (Reg -> Operand
    OpReg Reg
    dst)

       BSR Format
    format Operand
    src Reg
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprOpOp (String -> PtrString
    sLit String
    "bsr") Format
    format Operand
    src (Reg -> Operand
    OpReg Reg
    dst)

       PDEP Format
    format Operand
    src Operand
    mask Reg
    dst
          -> PtrString -> Format -> Operand -> Operand -> Reg -> SDoc
    pprFormatOpOpReg (String -> PtrString
    sLit String
    "pdep") Format
    format Operand
    src Operand
    mask Reg
    dst

       PEXT Format
    format Operand
    src Operand
    mask Reg
    dst
          -> PtrString -> Format -> Operand -> Operand -> Reg -> SDoc
    pprFormatOpOpReg (String -> PtrString
    sLit String
    "pext") Format
    format Operand
    src Operand
    mask Reg
    dst

       PREFETCH PrefetchVariant
    NTA Format
    format Operand
    src
          -> PtrString -> Format -> Operand -> SDoc
    pprFormatOp_ (String -> PtrString
    sLit String
    "prefetchnta") Format
    format Operand
    src

       PREFETCH PrefetchVariant
    Lvl0 Format
    format Operand
    src
          -> PtrString -> Format -> Operand -> SDoc
    pprFormatOp_ (String -> PtrString
    sLit String
    "prefetcht0") Format
    format Operand
    src

       PREFETCH PrefetchVariant
    Lvl1 Format
    format Operand
    src
          -> PtrString -> Format -> Operand -> SDoc
    pprFormatOp_ (String -> PtrString
    sLit String
    "prefetcht1") Format
    format Operand
    src

       PREFETCH PrefetchVariant
    Lvl2 Format
    format Operand
    src
          -> PtrString -> Format -> Operand -> SDoc
    pprFormatOp_ (String -> PtrString
    sLit String
    "prefetcht2") Format
    format Operand
    src

       NOT Format
    format Operand
    op
          -> PtrString -> Format -> Operand -> SDoc
    pprFormatOp (String -> PtrString
    sLit String
    "not") Format
    format Operand
    op

       BSWAP Format
    format Reg
    op
          -> PtrString -> Format -> Operand -> SDoc
    pprFormatOp (String -> PtrString
    sLit String
    "bswap") Format
    format (Reg -> Operand
    OpReg Reg
    op)

       NEGI Format
    format Operand
    op
          -> PtrString -> Format -> Operand -> SDoc
    pprFormatOp (String -> PtrString
    sLit String
    "neg") Format
    format Operand
    op

       SHL Format
    format Operand
    src Operand
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprShift (String -> PtrString
    sLit String
    "shl") Format
    format Operand
    src Operand
    dst

       SAR Format
    format Operand
    src Operand
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprShift (String -> PtrString
    sLit String
    "sar") Format
    format Operand
    src Operand
    dst

       SHR Format
    format Operand
    src Operand
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprShift (String -> PtrString
    sLit String
    "shr") Format
    format Operand
    src Operand
    dst

       BT Format
    format Imm
    imm Operand
    src
          -> PtrString -> Format -> Imm -> Operand -> SDoc
    pprFormatImmOp (String -> PtrString
    sLit String
    "bt") Format
    format Imm
    imm Operand
    src

       CMP Format
    format Operand
    src Operand
    dst
         | Format -> Bool
    isFloatFormat Format
    format -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "ucomi") Format
    format Operand
    src Operand
    dst -- SSE2
         | Bool
    otherwise            -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "cmp")   Format
    format Operand
    src Operand
    dst

       TEST Format
    format Operand
    src Operand
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "test") Format
    format' Operand
    src Operand
    dst
             where
            -- Match instructions like 'test $0x3,%esi' or 'test $0x7,%rbx'.
            -- We can replace them by equivalent, but smaller instructions
            -- by reducing the size of the immediate operand as far as possible.
            -- (We could handle masks larger than a single byte too,
            -- but it would complicate the code considerably
            -- and tag checks are by far the most common case.)
            -- The mask must have the high bit clear for this smaller encoding
            -- to be completely equivalent to the original; in particular so
            -- that the signed comparison condition bits are the same as they
            -- would be if doing a full word comparison. See #13425.
              format' :: Format
    format' = case (Operand
    src,Operand
    dst) of
               (OpImm (ImmInteger Integer
    mask), OpReg Reg
    dstReg)
                 | Integer
    0 forall a. Ord a => a -> a -> Bool
    <= Integer
    mask Bool -> Bool -> Bool
    && Integer
    mask forall a. Ord a => a -> a -> Bool
    < Integer
    128 -> Platform -> Reg -> Format
    minSizeOfReg Platform
    platform Reg
    dstReg
               (Operand, Operand)
    _ -> Format
    format
              minSizeOfReg :: Platform -> Reg -> Format
    minSizeOfReg Platform
    platform (RegReal (RealRegSingle Int
    i))
                | Platform -> Bool
    target32Bit Platform
    platform Bool -> Bool -> Bool
    && Int
    i forall a. Ord a => a -> a -> Bool
    <= Int
    3        = Format
    II8  -- al, bl, cl, dl
                | Platform -> Bool
    target32Bit Platform
    platform Bool -> Bool -> Bool
    && Int
    i forall a. Ord a => a -> a -> Bool
    <= Int
    7        = Format
    II16 -- si, di, bp, sp
                | Bool -> Bool
    not (Platform -> Bool
    target32Bit Platform
    platform) Bool -> Bool -> Bool
    && Int
    i forall a. Ord a => a -> a -> Bool
    <= Int
    15 = Format
    II8  -- al .. r15b
              minSizeOfReg Platform
    _ Reg
    _ = Format
    format                 -- other

       PUSH Format
    format Operand
    op
          -> PtrString -> Format -> Operand -> SDoc
    pprFormatOp (String -> PtrString
    sLit String
    "push") Format
    format Operand
    op

       POP Format
    format Operand
    op
          -> PtrString -> Format -> Operand -> SDoc
    pprFormatOp (String -> PtrString
    sLit String
    "pop") Format
    format Operand
    op

    -- both unused (SDM):
    -- PUSHA -> text "\tpushal"
    -- POPA  -> text "\tpopal"

       Instr
    NOP
          -> String -> SDoc
    text String
    "\tnop"

       CLTD Format
    II8
          -> String -> SDoc
    text String
    "\tcbtw"

       CLTD Format
    II16
          -> String -> SDoc
    text String
    "\tcwtd"

       CLTD Format
    II32
          -> String -> SDoc
    text String
    "\tcltd"

       CLTD Format
    II64
          -> String -> SDoc
    text String
    "\tcqto"

       CLTD Format
    x
          -> forall a. String -> a
    panic forall a b. (a -> b) -> a -> b
    $ String
    "pprInstr: CLTD " forall a. [a] -> [a] -> [a]
    ++ forall a. Show a => a -> String
    show Format
    x

       SETCC Cond
    cond Operand
    op
          -> PtrString -> Cond -> SDoc -> SDoc
    pprCondInstr (String -> PtrString
    sLit String
    "set") Cond
    cond (Platform -> Format -> Operand -> SDoc
    pprOperand Platform
    platform Format
    II8 Operand
    op)

       XCHG Format
    format Operand
    src Reg
    val
          -> PtrString -> Format -> Operand -> Reg -> SDoc
    pprFormatOpReg (String -> PtrString
    sLit String
    "xchg") Format
    format Operand
    src Reg
    val

       JXX Cond
    cond BlockId
    blockid
          -> PtrString -> Cond -> SDoc -> SDoc
    pprCondInstr (String -> PtrString
    sLit String
    "j") Cond
    cond (forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform CLabel
    lab)
             where lab :: CLabel
    lab = BlockId -> CLabel
    blockLbl BlockId
    blockid

       JXX_GBL Cond
    cond Imm
    imm
          -> PtrString -> Cond -> SDoc -> SDoc
    pprCondInstr (String -> PtrString
    sLit String
    "j") Cond
    cond (Platform -> Imm -> SDoc
    pprImm Platform
    platform Imm
    imm)

       JMP (OpImm Imm
    imm) [Reg]
    _
          -> String -> SDoc
    text String
    "\tjmp " SDoc -> SDoc -> SDoc
    <> Platform -> Imm -> SDoc
    pprImm Platform
    platform Imm
    imm

       JMP Operand
    op [Reg]
    _
          -> String -> SDoc
    text String
    "\tjmp *" SDoc -> SDoc -> SDoc
    <> Platform -> Format -> Operand -> SDoc
    pprOperand Platform
    platform (Bool -> Format
    archWordFormat (Platform -> Bool
    target32Bit Platform
    platform)) Operand
    op

       JMP_TBL Operand
    op [Maybe JumpDest]
    _ Section
    _ CLabel
    _
          -> Platform -> Instr -> SDoc
    pprInstr Platform
    platform (Operand -> [Reg] -> Instr
    JMP Operand
    op [])

       CALL (Left Imm
    imm) [Reg]
    _
          -> String -> SDoc
    text String
    "\tcall " SDoc -> SDoc -> SDoc
    <> Platform -> Imm -> SDoc
    pprImm Platform
    platform Imm
    imm

       CALL (Right Reg
    reg) [Reg]
    _
          -> String -> SDoc
    text String
    "\tcall *" SDoc -> SDoc -> SDoc
    <> Platform -> Format -> Reg -> SDoc
    pprReg Platform
    platform (Bool -> Format
    archWordFormat (Platform -> Bool
    target32Bit Platform
    platform)) Reg
    reg

       IDIV Format
    fmt Operand
    op
          -> PtrString -> Format -> Operand -> SDoc
    pprFormatOp (String -> PtrString
    sLit String
    "idiv") Format
    fmt Operand
    op

       DIV Format
    fmt Operand
    op
          -> PtrString -> Format -> Operand -> SDoc
    pprFormatOp (String -> PtrString
    sLit String
    "div")  Format
    fmt Operand
    op

       IMUL2 Format
    fmt Operand
    op
          -> PtrString -> Format -> Operand -> SDoc
    pprFormatOp (String -> PtrString
    sLit String
    "imul") Format
    fmt Operand
    op

       -- x86_64 only
       MUL Format
    format Operand
    op1 Operand
    op2
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "mul") Format
    format Operand
    op1 Operand
    op2

       MUL2 Format
    format Operand
    op
          -> PtrString -> Format -> Operand -> SDoc
    pprFormatOp (String -> PtrString
    sLit String
    "mul") Format
    format Operand
    op

       FDIV Format
    format Operand
    op1 Operand
    op2
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "div") Format
    format Operand
    op1 Operand
    op2

       SQRT Format
    format Operand
    op1 Reg
    op2
          -> PtrString -> Format -> Operand -> Reg -> SDoc
    pprFormatOpReg (String -> PtrString
    sLit String
    "sqrt") Format
    format Operand
    op1 Reg
    op2

       CVTSS2SD Reg
    from Reg
    to
          -> PtrString -> Reg -> Reg -> SDoc
    pprRegReg (String -> PtrString
    sLit String
    "cvtss2sd") Reg
    from Reg
    to

       CVTSD2SS Reg
    from Reg
    to
          -> PtrString -> Reg -> Reg -> SDoc
    pprRegReg (String -> PtrString
    sLit String
    "cvtsd2ss") Reg
    from Reg
    to

       CVTTSS2SIQ Format
    fmt Operand
    from Reg
    to
          -> PtrString -> Format -> Format -> Operand -> Reg -> SDoc
    pprFormatFormatOpReg (String -> PtrString
    sLit String
    "cvttss2si") Format
    FF32 Format
    fmt Operand
    from Reg
    to

       CVTTSD2SIQ Format
    fmt Operand
    from Reg
    to
          -> PtrString -> Format -> Format -> Operand -> Reg -> SDoc
    pprFormatFormatOpReg (String -> PtrString
    sLit String
    "cvttsd2si") Format
    FF64 Format
    fmt Operand
    from Reg
    to

       CVTSI2SS Format
    fmt Operand
    from Reg
    to
          -> PtrString -> Format -> Operand -> Reg -> SDoc
    pprFormatOpReg (String -> PtrString
    sLit String
    "cvtsi2ss") Format
    fmt Operand
    from Reg
    to

       CVTSI2SD Format
    fmt Operand
    from Reg
    to
          -> PtrString -> Format -> Operand -> Reg -> SDoc
    pprFormatOpReg (String -> PtrString
    sLit String
    "cvtsi2sd") Format
    fmt Operand
    from Reg
    to

           -- FETCHGOT for PIC on ELF platforms
       FETCHGOT Reg
    reg
          -> [SDoc] -> SDoc
    vcat [ String -> SDoc
    text String
    "\tcall 1f",
                    [SDoc] -> SDoc
    hcat [ String -> SDoc
    text String
    "1:\tpopl\t", Platform -> Format -> Reg -> SDoc
    pprReg Platform
    platform Format
    II32 Reg
    reg ],
                    [SDoc] -> SDoc
    hcat [ String -> SDoc
    text String
    "\taddl\t$_GLOBAL_OFFSET_TABLE_+(.-1b), ",
                           Platform -> Format -> Reg -> SDoc
    pprReg Platform
    platform Format
    II32 Reg
    reg ]
                  ]

        -- FETCHPC for PIC on Darwin/x86
        -- get the instruction pointer into a register
        -- (Terminology note: the IP is called Program Counter on PPC,
        --  and it's a good thing to use the same name on both platforms)
       FETCHPC Reg
    reg
          -> [SDoc] -> SDoc
    vcat [ String -> SDoc
    text String
    "\tcall 1f",
                    [SDoc] -> SDoc
    hcat [ String -> SDoc
    text String
    "1:\tpopl\t", Platform -> Format -> Reg -> SDoc
    pprReg Platform
    platform Format
    II32 Reg
    reg ]
                  ]

       -- the
       -- GST fmt src addr ==> FLD dst ; FSTPsz addr
       g :: Instr
    g@(X87Store Format
    fmt  AddrMode
    addr)
          -> Instr -> SDoc -> SDoc
    pprX87 Instr
    g ([SDoc] -> SDoc
    hcat [SDoc
    gtab, String -> SDoc
    text String
    "fstp", Format -> SDoc
    pprFormat_x87 Format
    fmt, SDoc
    gsp, Platform -> AddrMode -> SDoc
    pprAddr Platform
    platform AddrMode
    addr])

       -- Atomics
       LOCK Instr
    i
          -> String -> SDoc
    text String
    "\tlock" SDoc -> SDoc -> SDoc
    $$ Platform -> Instr -> SDoc
    pprInstr Platform
    platform Instr
    i

       Instr
    MFENCE
          -> String -> SDoc
    text String
    "\tmfence"

       XADD Format
    format Operand
    src Operand
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "xadd") Format
    format Operand
    src Operand
    dst

       CMPXCHG Format
    format Operand
    src Operand
    dst
          -> PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp (String -> PtrString
    sLit String
    "cmpxchg") Format
    format Operand
    src Operand
    dst

      where
       gtab :: SDoc
       gtab :: SDoc
    gtab  = Char -> SDoc
    char Char
    '\t'

       gsp :: SDoc
       gsp :: SDoc
    gsp   = Char -> SDoc
    char Char
    ' '

       pprX87 :: Instr -> SDoc -> SDoc
       pprX87 :: Instr -> SDoc -> SDoc
    pprX87 Instr
    fake SDoc
    actual
          = (Char -> SDoc
    char Char
    '#' SDoc -> SDoc -> SDoc
    <> Instr -> SDoc
    pprX87Instr Instr
    fake) SDoc -> SDoc -> SDoc
    $$ SDoc
    actual

       pprX87Instr :: Instr -> SDoc
       pprX87Instr :: Instr -> SDoc
    pprX87Instr (X87Store Format
    fmt AddrMode
    dst) = PtrString -> Format -> AddrMode -> SDoc
    pprFormatAddr (String -> PtrString
    sLit String
    "gst") Format
    fmt AddrMode
    dst
       pprX87Instr Instr
    _ = forall a. String -> a
    panic String
    "X86.Ppr.pprX87Instr: no match"

       pprDollImm :: Imm -> SDoc
       pprDollImm :: Imm -> SDoc
    pprDollImm Imm
    i = String -> SDoc
    text String
    "$" SDoc -> SDoc -> SDoc
    <> Platform -> Imm -> SDoc
    pprImm Platform
    platform Imm
    i

       pprOperand :: Platform -> Format -> Operand -> SDoc
       pprOperand :: Platform -> Format -> Operand -> SDoc
    pprOperand Platform
    platform Format
    f Operand
    op = case Operand
    op of
          OpReg Reg
    r   -> Platform -> Format -> Reg -> SDoc
    pprReg Platform
    platform Format
    f Reg
    r
          OpImm Imm
    i   -> Imm -> SDoc
    pprDollImm Imm
    i
          OpAddr AddrMode
    ea -> Platform -> AddrMode -> SDoc
    pprAddr Platform
    platform AddrMode
    ea

       pprMnemonic_  :: PtrString -> SDoc
       pprMnemonic_ :: PtrString -> SDoc
    pprMnemonic_ PtrString
    name =
          Char -> SDoc
    char Char
    '\t' SDoc -> SDoc -> SDoc
    <> PtrString -> SDoc
    ptext PtrString
    name SDoc -> SDoc -> SDoc
    <> SDoc
    space

       pprMnemonic  :: PtrString -> Format -> SDoc
       pprMnemonic :: PtrString -> Format -> SDoc
    pprMnemonic PtrString
    name Format
    format =
          Char -> SDoc
    char Char
    '\t' SDoc -> SDoc -> SDoc
    <> PtrString -> SDoc
    ptext PtrString
    name SDoc -> SDoc -> SDoc
    <> Format -> SDoc
    pprFormat Format
    format SDoc -> SDoc -> SDoc
    <> SDoc
    space

       pprFormatImmOp :: PtrString -> Format -> Imm -> Operand -> SDoc
       pprFormatImmOp :: PtrString -> Format -> Imm -> Operand -> SDoc
    pprFormatImmOp PtrString
    name Format
    format Imm
    imm Operand
    op1
         = [SDoc] -> SDoc
    hcat [
               PtrString -> Format -> SDoc
    pprMnemonic PtrString
    name Format
    format,
               Char -> SDoc
    char Char
    '$',
               Platform -> Imm -> SDoc
    pprImm Platform
    platform Imm
    imm,
               SDoc
    comma,
               Platform -> Format -> Operand -> SDoc
    pprOperand Platform
    platform Format
    format Operand
    op1
           ]

       pprFormatOp_ :: PtrString -> Format -> Operand -> SDoc
       pprFormatOp_ :: PtrString -> Format -> Operand -> SDoc
    pprFormatOp_ PtrString
    name Format
    format Operand
    op1
         = [SDoc] -> SDoc
    hcat [
               PtrString -> SDoc
    pprMnemonic_ PtrString
    name ,
               Platform -> Format -> Operand -> SDoc
    pprOperand Platform
    platform Format
    format Operand
    op1
           ]

       pprFormatOp :: PtrString -> Format -> Operand -> SDoc
       pprFormatOp :: PtrString -> Format -> Operand -> SDoc
    pprFormatOp PtrString
    name Format
    format Operand
    op1
         = [SDoc] -> SDoc
    hcat [
               PtrString -> Format -> SDoc
    pprMnemonic PtrString
    name Format
    format,
               Platform -> Format -> Operand -> SDoc
    pprOperand Platform
    platform Format
    format Operand
    op1
           ]

       pprFormatOpOp :: PtrString -> Format -> Operand -> Operand -> SDoc
       pprFormatOpOp :: PtrString -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOp PtrString
    name Format
    format Operand
    op1 Operand
    op2
         = [SDoc] -> SDoc
    hcat [
               PtrString -> Format -> SDoc
    pprMnemonic PtrString
    name Format
    format,
               Platform -> Format -> Operand -> SDoc
    pprOperand Platform
    platform Format
    format Operand
    op1,
               SDoc
    comma,
               Platform -> Format -> Operand -> SDoc
    pprOperand Platform
    platform Format
    format Operand
    op2
           ]

       pprOpOp :: PtrString -> Format -> Operand -> Operand -> SDoc
       pprOpOp :: PtrString -> Format -> Operand -> Operand -> SDoc
    pprOpOp PtrString
    name Format
    format Operand
    op1 Operand
    op2
         = [SDoc] -> SDoc
    hcat [
               PtrString -> SDoc
    pprMnemonic_ PtrString
    name,
               Platform -> Format -> Operand -> SDoc
    pprOperand Platform
    platform Format
    format Operand
    op1,
               SDoc
    comma,
               Platform -> Format -> Operand -> SDoc
    pprOperand Platform
    platform Format
    format Operand
    op2
           ]

       pprRegReg :: PtrString -> Reg -> Reg -> SDoc
       pprRegReg :: PtrString -> Reg -> Reg -> SDoc
    pprRegReg PtrString
    name Reg
    reg1 Reg
    reg2
         = [SDoc] -> SDoc
    hcat [
               PtrString -> SDoc
    pprMnemonic_ PtrString
    name,
               Platform -> Format -> Reg -> SDoc
    pprReg Platform
    platform (Bool -> Format
    archWordFormat (Platform -> Bool
    target32Bit Platform
    platform)) Reg
    reg1,
               SDoc
    comma,
               Platform -> Format -> Reg -> SDoc
    pprReg Platform
    platform (Bool -> Format
    archWordFormat (Platform -> Bool
    target32Bit Platform
    platform)) Reg
    reg2
           ]

       pprFormatOpReg :: PtrString -> Format -> Operand -> Reg -> SDoc
       pprFormatOpReg :: PtrString -> Format -> Operand -> Reg -> SDoc
    pprFormatOpReg PtrString
    name Format
    format Operand
    op1 Reg
    reg2
         = [SDoc] -> SDoc
    hcat [
               PtrString -> Format -> SDoc
    pprMnemonic PtrString
    name Format
    format,
               Platform -> Format -> Operand -> SDoc
    pprOperand Platform
    platform Format
    format Operand
    op1,
               SDoc
    comma,
               Platform -> Format -> Reg -> SDoc
    pprReg Platform
    platform (Bool -> Format
    archWordFormat (Platform -> Bool
    target32Bit Platform
    platform)) Reg
    reg2
           ]

       pprCondOpReg :: PtrString -> Format -> Cond -> Operand -> Reg -> SDoc
       pprCondOpReg :: PtrString -> Format -> Cond -> Operand -> Reg -> SDoc
    pprCondOpReg PtrString
    name Format
    format Cond
    cond Operand
    op1 Reg
    reg2
         = [SDoc] -> SDoc
    hcat [
               Char -> SDoc
    char Char
    '\t',
               PtrString -> SDoc
    ptext PtrString
    name,
               Cond -> SDoc
    pprCond Cond
    cond,
               SDoc
    space,
               Platform -> Format -> Operand -> SDoc
    pprOperand Platform
    platform Format
    format Operand
    op1,
               SDoc
    comma,
               Platform -> Format -> Reg -> SDoc
    pprReg Platform
    platform Format
    format Reg
    reg2
           ]

       pprFormatFormatOpReg :: PtrString -> Format -> Format -> Operand -> Reg -> SDoc
       pprFormatFormatOpReg :: PtrString -> Format -> Format -> Operand -> Reg -> SDoc
    pprFormatFormatOpReg PtrString
    name Format
    format1 Format
    format2 Operand
    op1 Reg
    reg2
         = [SDoc] -> SDoc
    hcat [
               PtrString -> Format -> SDoc
    pprMnemonic PtrString
    name Format
    format2,
               Platform -> Format -> Operand -> SDoc
    pprOperand Platform
    platform Format
    format1 Operand
    op1,
               SDoc
    comma,
               Platform -> Format -> Reg -> SDoc
    pprReg Platform
    platform Format
    format2 Reg
    reg2
           ]

       pprFormatOpOpReg :: PtrString -> Format -> Operand -> Operand -> Reg -> SDoc
       pprFormatOpOpReg :: PtrString -> Format -> Operand -> Operand -> Reg -> SDoc
    pprFormatOpOpReg PtrString
    name Format
    format Operand
    op1 Operand
    op2 Reg
    reg3
         = [SDoc] -> SDoc
    hcat [
               PtrString -> Format -> SDoc
    pprMnemonic PtrString
    name Format
    format,
               Platform -> Format -> Operand -> SDoc
    pprOperand Platform
    platform Format
    format Operand
    op1,
               SDoc
    comma,
               Platform -> Format -> Operand -> SDoc
    pprOperand Platform
    platform Format
    format Operand
    op2,
               SDoc
    comma,
               Platform -> Format -> Reg -> SDoc
    pprReg Platform
    platform Format
    format Reg
    reg3
           ]

       pprFormatAddr :: PtrString -> Format -> AddrMode -> SDoc
       pprFormatAddr :: PtrString -> Format -> AddrMode -> SDoc
    pprFormatAddr PtrString
    name Format
    format  AddrMode
    op
         = [SDoc] -> SDoc
    hcat [
               PtrString -> Format -> SDoc
    pprMnemonic PtrString
    name Format
    format,
               SDoc
    comma,
               Platform -> AddrMode -> SDoc
    pprAddr Platform
    platform AddrMode
    op
           ]

       pprShift :: PtrString -> Format -> Operand -> Operand -> SDoc
       pprShift :: PtrString -> Format -> Operand -> Operand -> SDoc
    pprShift PtrString
    name Format
    format Operand
    src Operand
    dest
         = [SDoc] -> SDoc
    hcat [
               PtrString -> Format -> SDoc
    pprMnemonic PtrString
    name Format
    format,
               Platform -> Format -> Operand -> SDoc
    pprOperand Platform
    platform Format
    II8 Operand
    src,  -- src is 8-bit sized
               SDoc
    comma,
               Platform -> Format -> Operand -> SDoc
    pprOperand Platform
    platform Format
    format Operand
    dest
           ]

       pprFormatOpOpCoerce :: PtrString -> Format -> Format -> Operand -> Operand -> SDoc
       pprFormatOpOpCoerce :: PtrString -> Format -> Format -> Operand -> Operand -> SDoc
    pprFormatOpOpCoerce PtrString
    name Format
    format1 Format
    format2 Operand
    op1 Operand
    op2
         = [SDoc] -> SDoc
    hcat [ Char -> SDoc
    char Char
    '\t', PtrString -> SDoc
    ptext PtrString
    name, Format -> SDoc
    pprFormat Format
    format1, Format -> SDoc
    pprFormat Format
    format2, SDoc
    space,
               Platform -> Format -> Operand -> SDoc
    pprOperand Platform
    platform Format
    format1 Operand
    op1,
               SDoc
    comma,
               Platform -> Format -> Operand -> SDoc
    pprOperand Platform
    platform Format
    format2 Operand
    op2
           ]

       pprCondInstr :: PtrString -> Cond -> SDoc -> SDoc
       pprCondInstr :: PtrString -> Cond -> SDoc -> SDoc
    pprCondInstr PtrString
    name Cond
    cond SDoc
    arg
         = [SDoc] -> SDoc
    hcat [ Char -> SDoc
    char Char
    '\t', PtrString -> SDoc
    ptext PtrString
    name, Cond -> SDoc
    pprCond Cond
    cond, SDoc
    space, SDoc
    arg]