    {-# OPTIONS_GHC -fno-warn-orphans #-}
    {-# LANGUAGE CPP #-}

    module GHC.CmmToAsm.AArch64.Ppr (pprNatCmmDecl, pprInstr, pprBasicBlock) where

    import GHC.Prelude hiding (EQ)

    import GHC.CmmToAsm.AArch64.Instr
    import GHC.CmmToAsm.AArch64.Regs
    import GHC.CmmToAsm.AArch64.Cond
    import GHC.CmmToAsm.Ppr
    import GHC.CmmToAsm.Format
    import GHC.Platform.Reg
    import GHC.CmmToAsm.Config
    import GHC.CmmToAsm.Types
    import GHC.CmmToAsm.Utils

    import GHC.Cmm hiding (topInfoTable)
    import GHC.Cmm.Dataflow.Label

    import GHC.Cmm.BlockId
    import GHC.Cmm.CLabel

    import GHC.Types.Unique ( pprUniqueAlways, getUnique )
    import GHC.Platform
    import GHC.Utils.Outputable

    import GHC.Utils.Panic

    pprNatCmmDecl :: IsDoc doc => NCGConfig -> NatCmmDecl RawCmmStatics Instr -> doc
    pprNatCmmDecl :: forall doc.
    IsDoc doc =>
    NCGConfig -> NatCmmDecl RawCmmStatics Instr -> doc
    pprNatCmmDecl NCGConfig
    config (CmmData Section
    section RawCmmStatics
    dats) =
      let platform :: Platform
    platform = NCGConfig -> Platform
    ncgPlatform NCGConfig
    config
      in
      NCGConfig -> Section -> doc
    forall doc. IsDoc doc => NCGConfig -> Section -> doc
    pprSectionAlign NCGConfig
    config Section
    section doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ Platform -> RawCmmStatics -> doc
    forall doc. IsDoc doc => Platform -> RawCmmStatics -> doc
    pprDatas Platform
    platform RawCmmStatics
    dats

    pprNatCmmDecl NCGConfig
    config proc :: NatCmmDecl RawCmmStatics Instr
    proc@(CmmProc LabelMap RawCmmStatics
    top_info CLabel
    lbl [GlobalReg]
    _ (ListGraph [GenBasicBlock Instr]
    blocks)) =
      let platform :: Platform
    platform = NCGConfig -> Platform
    ncgPlatform NCGConfig
    config
          with_dwarf :: Bool
    with_dwarf = NCGConfig -> Bool
    ncgDwarfEnabled NCGConfig
    config
      in
      case NatCmmDecl RawCmmStatics Instr -> Maybe RawCmmStatics
    forall a i b. GenCmmDecl a (LabelMap i) (ListGraph b) -> Maybe i
    topInfoTable NatCmmDecl RawCmmStatics Instr
    proc of
        Maybe RawCmmStatics
    Nothing ->
            -- special case for code without info table:
            NCGConfig -> Section -> doc
    forall doc. IsDoc doc => NCGConfig -> Section -> doc
    pprSectionAlign NCGConfig
    config (SectionType -> CLabel -> Section
    Section SectionType
    Text CLabel
    lbl) doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
            -- do not
            -- pprProcAlignment config $$
            Platform -> CLabel -> doc
    forall doc. IsDoc doc => Platform -> CLabel -> doc
    pprLabel Platform
    platform CLabel
    lbl doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ -- blocks guaranteed not null, so label needed
            [doc] -> doc
    forall doc. IsDoc doc => [doc] -> doc
    vcat ((GenBasicBlock Instr -> doc) -> [GenBasicBlock Instr] -> [doc]
    forall a b. (a -> b) -> [a] -> [b]
    map (Platform
    -> Bool -> LabelMap RawCmmStatics -> GenBasicBlock Instr -> doc
    forall doc.
    IsDoc doc =>
    Platform
    -> Bool -> LabelMap RawCmmStatics -> GenBasicBlock Instr -> doc
    pprBasicBlock Platform
    platform Bool
    with_dwarf LabelMap RawCmmStatics
    top_info) [GenBasicBlock Instr]
    blocks) doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
            (if NCGConfig -> Bool
    ncgDwarfEnabled NCGConfig
    config
             then Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform (CLabel -> CLabel
    mkAsmTempEndLabel CLabel
    lbl) Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Char -> Line doc
    forall doc. IsLine doc => Char -> doc
    char Char
    ':') else doc
    forall doc. IsOutput doc => doc
    empty) doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
            Platform -> CLabel -> doc
    forall doc. IsDoc doc => Platform -> CLabel -> doc
    pprSizeDecl Platform
    platform CLabel
    lbl

        Just (CmmStaticsRaw CLabel
    info_lbl [CmmStatic]
    _) ->
          NCGConfig -> Section -> doc
    forall doc. IsDoc doc => NCGConfig -> Section -> doc
    pprSectionAlign NCGConfig
    config (SectionType -> CLabel -> Section
    Section SectionType
    Text CLabel
    info_lbl) doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
          -- pprProcAlignment config $$
          (if Platform -> Bool
    platformHasSubsectionsViaSymbols Platform
    platform
              then Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform (CLabel -> CLabel
    mkDeadStripPreventer CLabel
    info_lbl) Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Char -> Line doc
    forall doc. IsLine doc => Char -> doc
    char Char
    ':')
              else doc
    forall doc. IsOutput doc => doc
    empty) doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
          [doc] -> doc
    forall doc. IsDoc doc => [doc] -> doc
    vcat ((GenBasicBlock Instr -> doc) -> [GenBasicBlock Instr] -> [doc]
    forall a b. (a -> b) -> [a] -> [b]
    map (Platform
    -> Bool -> LabelMap RawCmmStatics -> GenBasicBlock Instr -> doc
    forall doc.
    IsDoc doc =>
    Platform
    -> Bool -> LabelMap RawCmmStatics -> GenBasicBlock Instr -> doc
    pprBasicBlock Platform
    platform Bool
    with_dwarf LabelMap RawCmmStatics
    top_info) [GenBasicBlock Instr]
    blocks) doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
          -- 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]
                    Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line
                  (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\t.long "
                Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    info_lbl
                Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Char -> Line doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '-'
                Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform (CLabel -> CLabel
    mkDeadStripPreventer CLabel
    info_lbl)
           else doc
    forall doc. IsOutput doc => doc
    empty) doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
          Platform -> CLabel -> doc
    forall doc. IsDoc doc => Platform -> CLabel -> doc
    pprSizeDecl Platform
    platform CLabel
    info_lbl
    {-# SPECIALIZE pprNatCmmDecl :: NCGConfig -> NatCmmDecl RawCmmStatics Instr -> SDoc #-}
    {-# SPECIALIZE pprNatCmmDecl :: NCGConfig -> NatCmmDecl RawCmmStatics Instr -> HDoc #-} -- see Note [SPECIALIZE to HDoc] in GHC.Utils.Outputable

    pprLabel :: IsDoc doc => Platform -> CLabel -> doc
    pprLabel :: forall doc. IsDoc doc => Platform -> CLabel -> doc
    pprLabel Platform
    platform CLabel
    lbl =
       Platform -> CLabel -> doc
    forall doc. IsDoc doc => Platform -> CLabel -> doc
    pprGloblDecl Platform
    platform CLabel
    lbl
       doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ Platform -> CLabel -> doc
    forall doc. IsDoc doc => Platform -> CLabel -> doc
    pprTypeDecl Platform
    platform CLabel
    lbl
       doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Char -> Line doc
    forall doc. IsLine doc => Char -> doc
    char Char
    ':')

    -- | Print appropriate alignment for the given section type.
    pprAlignForSection :: IsDoc doc => Platform -> SectionType -> doc
    pprAlignForSection :: forall doc. IsDoc doc => Platform -> SectionType -> doc
    pprAlignForSection Platform
    _platform SectionType
    _seg
        -- .balign is stable, whereas .align is platform dependent.
        = Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\t.balign 8") --  always 8

    -- | Print section header and appropriate alignment for that section.
    --
    -- This one will emit the header:
    --
    --     .section .text
    --     .balign 8
    --
    pprSectionAlign :: IsDoc doc => NCGConfig -> Section -> doc
    pprSectionAlign :: forall doc. IsDoc doc => NCGConfig -> Section -> doc
    pprSectionAlign NCGConfig
    _config (Section (OtherSection String
    _) CLabel
    _) =
         String -> doc
    forall a. HasCallStack => String -> a
    panic String
    "AArch64.Ppr.pprSectionAlign: unknown section"
    pprSectionAlign NCGConfig
    config sec :: Section
    sec@(Section SectionType
    seg CLabel
    _) =
        Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (NCGConfig -> Section -> Line doc
    forall doc. IsLine doc => NCGConfig -> Section -> doc
    pprSectionHeader NCGConfig
    config Section
    sec)
        doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ Platform -> SectionType -> doc
    forall doc. IsDoc doc => Platform -> SectionType -> doc
    pprAlignForSection (NCGConfig -> Platform
    ncgPlatform NCGConfig
    config) SectionType
    seg

    -- | Output the ELF .size directive.
    pprSizeDecl :: IsDoc doc => Platform -> CLabel -> doc
    pprSizeDecl :: forall doc. IsDoc doc => Platform -> CLabel -> doc
    pprSizeDecl Platform
    platform CLabel
    lbl
     = if OS -> Bool
    osElfTarget (Platform -> OS
    platformOS Platform
    platform)
       then Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\t.size" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    ", .-" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl)
       else doc
    forall doc. IsOutput doc => doc
    empty

    pprBasicBlock :: IsDoc doc => Platform -> {- dwarf enabled -} Bool -> LabelMap RawCmmStatics -> NatBasicBlock Instr
                  -> doc
    pprBasicBlock :: forall doc.
    IsDoc doc =>
    Platform
    -> Bool -> LabelMap RawCmmStatics -> GenBasicBlock Instr -> doc
    pprBasicBlock Platform
    platform Bool
    with_dwarf LabelMap RawCmmStatics
    info_env (BasicBlock BlockId
    blockid [Instr]
    instrs)
      = doc -> doc
    maybe_infotable (doc -> doc) -> doc -> doc
    forall a b. (a -> b) -> a -> b
    $
        Platform -> CLabel -> doc
    forall doc. IsDoc doc => Platform -> CLabel -> doc
    pprLabel Platform
    platform CLabel
    asmLbl doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
        [doc] -> doc
    forall doc. IsDoc doc => [doc] -> doc
    vcat ((Instr -> doc) -> [Instr] -> [doc]
    forall a b. (a -> b) -> [a] -> [b]
    map (Platform -> Instr -> doc
    forall doc. IsDoc doc => Platform -> Instr -> doc
    pprInstr Platform
    platform) ([Instr] -> [Instr]
    forall a. a -> a
    id {-detectTrivialDeadlock-} [Instr]
    optInstrs)) doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
        (if  Bool
    with_dwarf
          then Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform (CLabel -> CLabel
    mkAsmTempEndLabel CLabel
    asmLbl) Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Char -> Line doc
    forall doc. IsLine doc => Char -> doc
    char Char
    ':')
          else doc
    forall doc. IsOutput doc => doc
    empty
        )
      where
        -- Filter out identity moves. E.g. mov x18, x18 will be dropped.
        optInstrs :: [Instr]
    optInstrs = (Instr -> Bool) -> [Instr] -> [Instr]
    forall a. (a -> Bool) -> [a] -> [a]
    filter Instr -> Bool
    f [Instr]
    instrs
          where f :: Instr -> Bool
    f (MOV Operand
    o1 Operand
    o2) | Operand
    o1 Operand -> Operand -> Bool
    forall a. Eq a => a -> a -> Bool
    == Operand
    o2 = Bool
    False
                f Instr
    _ = Bool
    True

        asmLbl :: CLabel
    asmLbl = BlockId -> CLabel
    blockLbl BlockId
    blockid
        maybe_infotable :: doc -> doc
    maybe_infotable doc
    c = case BlockId -> LabelMap RawCmmStatics -> Maybe RawCmmStatics
    forall a. BlockId -> LabelMap a -> Maybe a
    mapLookup BlockId
    blockid LabelMap RawCmmStatics
    info_env of
           Maybe RawCmmStatics
    Nothing   -> doc
    c
           Just (CmmStaticsRaw CLabel
    info_lbl [CmmStatic]
    info) ->
              --  pprAlignForSection platform Text $$
               doc
    infoTableLoc doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
               [doc] -> doc
    forall doc. IsDoc doc => [doc] -> doc
    vcat ((CmmStatic -> doc) -> [CmmStatic] -> [doc]
    forall a b. (a -> b) -> [a] -> [b]
    map (Platform -> CmmStatic -> doc
    forall doc. IsDoc doc => Platform -> CmmStatic -> doc
    pprData Platform
    platform) [CmmStatic]
    info) doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
               Platform -> CLabel -> doc
    forall doc. IsDoc doc => Platform -> CLabel -> doc
    pprLabel Platform
    platform CLabel
    info_lbl doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
               doc
    c doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
               (if Bool
    with_dwarf
                 then Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform (CLabel -> CLabel
    mkAsmTempEndLabel CLabel
    info_lbl) Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Char -> Line doc
    forall doc. IsLine doc => Char -> doc
    char Char
    ':')
                 else doc
    forall doc. IsOutput doc => doc
    empty)
        -- Make sure the info table has the right .loc for the block
        -- coming right after it. See Note [Info Offset]
        infoTableLoc :: doc
    infoTableLoc = case [Instr]
    instrs of
          (l :: Instr
    l@LOCATION{} : [Instr]
    _) -> Platform -> Instr -> doc
    forall doc. IsDoc doc => Platform -> Instr -> doc
    pprInstr Platform
    platform Instr
    l
          [Instr]
    _other             -> doc
    forall doc. IsOutput doc => doc
    empty

    pprDatas :: IsDoc doc => Platform -> RawCmmStatics -> doc
    -- See Note [emit-time elimination of static indirections] in "GHC.Cmm.CLabel".
    pprDatas :: forall doc. IsDoc doc => Platform -> RawCmmStatics -> doc
    pprDatas Platform
    platform (CmmStaticsRaw CLabel
    alias [CmmStaticLit (CmmLabel CLabel
    lbl), CmmStaticLit CmmLit
    ind, CmmStatic
    _, CmmStatic
    _])
      | CLabel
    lbl CLabel -> CLabel -> Bool
    forall a. Eq a => a -> a -> Bool
    == CLabel
    mkIndStaticInfoLabel
      , let labelInd :: CmmLit -> Maybe CLabel
    labelInd (CmmLabelOff CLabel
    l RegNo
    _) = CLabel -> Maybe CLabel
    forall a. a -> Maybe a
    Just CLabel
    l
            labelInd (CmmLabel CLabel
    l) = CLabel -> Maybe CLabel
    forall a. a -> Maybe a
    Just CLabel
    l
            labelInd CmmLit
    _ = Maybe CLabel
    forall a. Maybe a
    Nothing
      , Just CLabel
    ind' <- CmmLit -> Maybe CLabel
    labelInd CmmLit
    ind
      , CLabel
    alias CLabel -> CLabel -> Bool
    `mayRedirectTo` CLabel
    ind'
      = Platform -> CLabel -> doc
    forall doc. IsDoc doc => Platform -> CLabel -> doc
    pprGloblDecl Platform
    platform CLabel
    alias
        doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$ Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    ".equiv" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    alias Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Line doc
    forall doc. IsLine doc => doc
    comma Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    ind')

    pprDatas Platform
    platform (CmmStaticsRaw CLabel
    lbl [CmmStatic]
    dats)
      = [doc] -> doc
    forall doc. IsDoc doc => [doc] -> doc
    vcat (Platform -> CLabel -> doc
    forall doc. IsDoc doc => Platform -> CLabel -> doc
    pprLabel Platform
    platform CLabel
    lbl doc -> [doc] -> [doc]
    forall a. a -> [a] -> [a]
    : (CmmStatic -> doc) -> [CmmStatic] -> [doc]
    forall a b. (a -> b) -> [a] -> [b]
    map (Platform -> CmmStatic -> doc
    forall doc. IsDoc doc => Platform -> CmmStatic -> doc
    pprData Platform
    platform) [CmmStatic]
    dats)

    pprData :: IsDoc doc => Platform -> CmmStatic -> doc
    pprData :: forall doc. IsDoc doc => Platform -> CmmStatic -> doc
    pprData Platform
    _platform (CmmString ByteString
    str) = Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (ByteString -> Line doc
    forall doc. IsLine doc => ByteString -> doc
    pprString ByteString
    str)
    pprData Platform
    _platform (CmmFileEmbed String
    path RegNo
    _) = Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (String -> Line doc
    forall doc. IsLine doc => String -> doc
    pprFileEmbed String
    path)

    pprData Platform
    platform (CmmUninitialised RegNo
    bytes)
     = Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ if Platform -> OS
    platformOS Platform
    platform OS -> OS -> Bool
    forall a. Eq a => a -> a -> Bool
    == OS
    OSDarwin
                    then String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    ".space " Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> Line doc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    bytes
                    else String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    ".skip "  Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> Line doc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    bytes

    pprData Platform
    platform (CmmStaticLit CmmLit
    lit) = Platform -> CmmLit -> doc
    forall doc. IsDoc doc => Platform -> CmmLit -> doc
    pprDataItem Platform
    platform CmmLit
    lit

    pprGloblDecl :: IsDoc doc => Platform -> CLabel -> doc
    pprGloblDecl :: forall doc. IsDoc doc => Platform -> CLabel -> doc
    pprGloblDecl Platform
    platform CLabel
    lbl
      | Bool -> Bool
    not (CLabel -> Bool
    externallyVisibleCLabel CLabel
    lbl) = doc
    forall doc. IsOutput doc => doc
    empty
      | Bool
    otherwise = Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\t.globl " Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl)

    -- Note [Always use objects for info tables]
    -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    -- See discussion in X86.Ppr for why this is necessary.  Essentially we need to
    -- ensure that we never pass function symbols when we might want to lookup the
    -- info table.  If we did, we could end up with procedure linking tables
    -- (PLT)s, and thus the lookup wouldn't point to the function, but into the
    -- jump table.
    --
    -- Fun fact: The LLVMMangler exists to patch this issue su on the LLVM side as
    -- well.
    pprLabelType' :: IsLine doc => Platform -> CLabel -> doc
    pprLabelType' :: forall doc. IsLine doc => Platform -> CLabel -> doc
    pprLabelType' Platform
    platform CLabel
    lbl =
      if CLabel -> Bool
    isCFunctionLabel CLabel
    lbl Bool -> Bool -> Bool
    || Bool
    functionOkInfoTable then
        String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "@function"
      else
        String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "@object"
      where
        functionOkInfoTable :: Bool
    functionOkInfoTable = Platform -> Bool
    platformTablesNextToCode Platform
    platform Bool -> Bool -> Bool
    &&
          CLabel -> Bool
    isInfoTableLabel CLabel
    lbl Bool -> Bool -> Bool
    && Bool -> Bool
    not (CLabel -> Bool
    isCmmInfoTableLabel CLabel
    lbl) Bool -> Bool -> Bool
    && Bool -> Bool
    not (CLabel -> Bool
    isConInfoTableLabel CLabel
    lbl)

    -- this is called pprTypeAndSizeDecl in PPC.Ppr
    pprTypeDecl :: IsDoc doc => Platform -> CLabel -> doc
    pprTypeDecl :: forall doc. IsDoc doc => Platform -> CLabel -> doc
    pprTypeDecl Platform
    platform CLabel
    lbl
        = if OS -> Bool
    osElfTarget (Platform -> OS
    platformOS Platform
    platform) Bool -> Bool -> Bool
    && CLabel -> Bool
    externallyVisibleCLabel CLabel
    lbl
          then Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    ".type " Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    ", " Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprLabelType' Platform
    platform CLabel
    lbl)
          else doc
    forall doc. IsOutput doc => doc
    empty

    pprDataItem :: IsDoc doc => Platform -> CmmLit -> doc
    pprDataItem :: forall doc. IsDoc doc => Platform -> CmmLit -> doc
    pprDataItem Platform
    platform CmmLit
    lit
      = [Line doc] -> doc
    forall doc. IsDoc doc => [Line doc] -> doc
    lines_ (Format -> CmmLit -> [Line doc]
    ppr_item (CmmType -> Format
    cmmTypeFormat (CmmType -> Format) -> CmmType -> Format
    forall a b. (a -> b) -> a -> b
    $ Platform -> CmmLit -> CmmType
    cmmLitType Platform
    platform CmmLit
    lit) CmmLit
    lit)
        where
            imm :: Imm
    imm = CmmLit -> Imm
    litToImm CmmLit
    lit

            ppr_item :: Format -> CmmLit -> [Line doc]
    ppr_item Format
    II8  CmmLit
    _ = [String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\t.byte\t"  Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> Imm -> Line doc
    forall doc. IsLine doc => Platform -> Imm -> doc
    pprImm Platform
    platform Imm
    imm]
            ppr_item Format
    II16 CmmLit
    _ = [String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\t.short\t" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> Imm -> Line doc
    forall doc. IsLine doc => Platform -> Imm -> doc
    pprImm Platform
    platform Imm
    imm]
            ppr_item Format
    II32 CmmLit
    _ = [String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\t.long\t"  Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> Imm -> Line doc
    forall doc. IsLine doc => Platform -> Imm -> doc
    pprImm Platform
    platform Imm
    imm]
            ppr_item Format
    II64 CmmLit
    _ = [String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\t.quad\t"  Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> Imm -> Line doc
    forall doc. IsLine doc => Platform -> Imm -> doc
    pprImm Platform
    platform Imm
    imm]

            ppr_item Format
    FF32  (CmmFloat Rational
    r Width
    _)
               = let bs :: [Word8]
    bs = Float -> [Word8]
    floatToBytes (Rational -> Float
    forall a. Fractional a => Rational -> a
    fromRational Rational
    r)
                 in  (Word8 -> Line doc) -> [Word8] -> [Line doc]
    forall a b. (a -> b) -> [a] -> [b]
    map (\Word8
    b -> String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\t.byte\t" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> Line doc
    forall doc. IsLine doc => RegNo -> doc
    int (Word8 -> RegNo
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    b)) [Word8]
    bs

            ppr_item Format
    FF64 (CmmFloat Rational
    r Width
    _)
               = let bs :: [Word8]
    bs = Double -> [Word8]
    doubleToBytes (Rational -> Double
    forall a. Fractional a => Rational -> a
    fromRational Rational
    r)
                 in  (Word8 -> Line doc) -> [Word8] -> [Line doc]
    forall a b. (a -> b) -> [a] -> [b]
    map (\Word8
    b -> String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\t.byte\t" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> Line doc
    forall doc. IsLine doc => RegNo -> doc
    int (Word8 -> RegNo
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral Word8
    b)) [Word8]
    bs

            ppr_item Format
    _ CmmLit
    _ = String -> SDoc -> [Line doc]
    forall a. HasCallStack => String -> SDoc -> a
    pprPanic String
    "pprDataItem:ppr_item" (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text (String -> SDoc) -> String -> SDoc
    forall a b. (a -> b) -> a -> b
    $ CmmLit -> String
    forall a. Show a => a -> String
    show CmmLit
    lit)

    pprImm :: IsLine doc => Platform -> Imm -> doc
    pprImm :: forall doc. IsLine doc => Platform -> Imm -> doc
    pprImm Platform
    _ (ImmInt RegNo
    i)     = RegNo -> doc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    i
    pprImm Platform
    _ (ImmInteger Integer
    i) = Integer -> doc
    forall doc. IsLine doc => Integer -> doc
    integer Integer
    i
    pprImm Platform
    p (ImmCLbl CLabel
    l)    = Platform -> CLabel -> doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    p CLabel
    l
    pprImm Platform
    p (ImmIndex CLabel
    l RegNo
    i) = Platform -> CLabel -> doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    p CLabel
    l doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '+' doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> doc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    i
    pprImm Platform
    _ (ImmLit FastString
    s)     = FastString -> doc
    forall doc. IsLine doc => FastString -> doc
    ftext FastString
    s

    -- TODO: See pprIm below for why this is a bad idea!
    pprImm Platform
    _ (ImmFloat Rational
    f)
      | Rational
    f Rational -> Rational -> Bool
    forall a. Eq a => a -> a -> Bool
    == Rational
    0 = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "wzr"
      | Bool
    otherwise = Float -> doc
    forall doc. IsLine doc => Float -> doc
    float (Rational -> Float
    forall a. Fractional a => Rational -> a
    fromRational Rational
    f)
    pprImm Platform
    _ (ImmDouble Rational
    d)
      | Rational
    d Rational -> Rational -> Bool
    forall a. Eq a => a -> a -> Bool
    == Rational
    0 = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "xzr"
      | Bool
    otherwise = Double -> doc
    forall doc. IsLine doc => Double -> doc
    double (Rational -> Double
    forall a. Fractional a => Rational -> a
    fromRational Rational
    d)

    pprImm Platform
    p (ImmConstantSum Imm
    a Imm
    b) = Platform -> Imm -> doc
    forall doc. IsLine doc => Platform -> Imm -> doc
    pprImm Platform
    p Imm
    a doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '+' doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> Imm -> doc
    forall doc. IsLine doc => Platform -> Imm -> doc
    pprImm Platform
    p Imm
    b
    pprImm Platform
    p (ImmConstantDiff Imm
    a Imm
    b) = Platform -> Imm -> doc
    forall doc. IsLine doc => Platform -> Imm -> doc
    pprImm Platform
    p Imm
    a doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '-'
                       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
    <> Platform -> Imm -> doc
    forall doc. IsLine doc => Platform -> Imm -> doc
    pprImm Platform
    p Imm
    b doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> doc
    forall doc. IsLine doc => doc
    rparen

    -- aarch64 GNU as uses // for comments.
    asmComment :: SDoc -> SDoc
    asmComment :: SDoc -> SDoc
    asmComment SDoc
    c = SDoc -> SDoc
    forall doc. IsOutput doc => doc -> doc
    whenPprDebug (SDoc -> SDoc) -> SDoc -> SDoc
    forall a b. (a -> b) -> a -> b
    $ String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "#" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> SDoc
    c

    asmDoubleslashComment :: SDoc -> SDoc
    asmDoubleslashComment :: SDoc -> SDoc
    asmDoubleslashComment SDoc
    c = SDoc -> SDoc
    forall doc. IsOutput doc => doc -> doc
    whenPprDebug (SDoc -> SDoc) -> SDoc -> SDoc
    forall a b. (a -> b) -> a -> b
    $ String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "//" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> SDoc
    c

    asmMultilineComment :: SDoc -> SDoc
    asmMultilineComment :: SDoc -> SDoc
    asmMultilineComment SDoc
    c = SDoc -> SDoc
    forall doc. IsOutput doc => doc -> doc
    whenPprDebug (SDoc -> SDoc) -> SDoc -> SDoc
    forall a b. (a -> b) -> a -> b
    $ String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "/*" SDoc -> SDoc -> SDoc
    $+$ SDoc
    c SDoc -> SDoc -> SDoc
    $+$ String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "*/"

    pprIm :: IsLine doc => Platform -> Imm -> doc
    pprIm :: forall doc. IsLine doc => Platform -> Imm -> doc
    pprIm Platform
    platform Imm
    im = case Imm
    im of
      ImmInt RegNo
    i     -> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '#' doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> doc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    i
      ImmInteger Integer
    i -> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '#' doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Integer -> doc
    forall doc. IsLine doc => Integer -> doc
    integer Integer
    i

      -- TODO: This will only work for
      -- The floating point value must be expressible as ±n ÷ 16 × 2^r,
      -- where n and r are integers such that 16 ≤ n ≤ 31 and -3 ≤ r ≤ 4.
      -- and 0 needs to be encoded as wzr/xzr.
      --
      -- Except for 0, we might want to either split it up into enough
      -- ADD operations into an Integer register and then just bit copy it into
      -- the double register? See the toBytes + fromRational above for data items.
      -- This is something the x86 backend does.
      --
      -- We could also just turn them into statics :-/ Which is what the
      -- PowerPC backend does.
      ImmFloat Rational
    f | Rational
    f Rational -> Rational -> Bool
    forall a. Eq a => a -> a -> Bool
    == Rational
    0 -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "wzr"
      ImmFloat Rational
    f -> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '#' doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Float -> doc
    forall doc. IsLine doc => Float -> doc
    float (Rational -> Float
    forall a. Fractional a => Rational -> a
    fromRational Rational
    f)
      ImmDouble Rational
    d | Rational
    d Rational -> Rational -> Bool
    forall a. Eq a => a -> a -> Bool
    == Rational
    0 -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "xzr"
      ImmDouble Rational
    d -> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '#' doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Double -> doc
    forall doc. IsLine doc => Double -> doc
    double (Rational -> Double
    forall a. Fractional a => Rational -> a
    fromRational Rational
    d)
      -- =<lbl> pseudo instruction!
      ImmCLbl CLabel
    l    -> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '=' doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> CLabel -> doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    l
      ImmIndex CLabel
    l RegNo
    o -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "[=" doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> CLabel -> doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    l doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> doc
    forall doc. IsLine doc => doc
    comma doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '#' doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> doc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    o doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    ']'
      Imm
    _            -> String -> doc
    forall a. HasCallStack => String -> a
    panic String
    "AArch64.pprIm"

    pprExt :: IsLine doc => ExtMode -> doc
    pprExt :: forall doc. IsLine doc => ExtMode -> doc
    pprExt ExtMode
    EUXTB = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "uxtb"
    pprExt ExtMode
    EUXTH = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "uxth"
    pprExt ExtMode
    EUXTW = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "uxtw"
    pprExt ExtMode
    EUXTX = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "uxtx"
    pprExt ExtMode
    ESXTB = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "sxtb"
    pprExt ExtMode
    ESXTH = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "sxth"
    pprExt ExtMode
    ESXTW = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "sxtw"
    pprExt ExtMode
    ESXTX = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "sxtx"

    pprShift :: IsLine doc => ShiftMode -> doc
    pprShift :: forall doc. IsLine doc => ShiftMode -> doc
    pprShift ShiftMode
    SLSL = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "lsl"
    pprShift ShiftMode
    SLSR = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "lsr"
    pprShift ShiftMode
    SASR = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "asr"
    pprShift ShiftMode
    SROR = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "ror"

    pprOp :: IsLine doc => Platform -> Operand -> doc
    pprOp :: forall doc. IsLine doc => Platform -> Operand -> doc
    pprOp Platform
    plat Operand
    op = case Operand
    op of
      OpReg Width
    w Reg
    r           -> Width -> Reg -> doc
    forall doc. IsLine doc => Width -> Reg -> doc
    pprReg Width
    w Reg
    r
      OpRegExt Width
    w Reg
    r ExtMode
    x RegNo
    0 -> Width -> Reg -> doc
    forall doc. IsLine doc => Width -> Reg -> doc
    pprReg Width
    w Reg
    r doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> doc
    forall doc. IsLine doc => doc
    comma doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> ExtMode -> doc
    forall doc. IsLine doc => ExtMode -> doc
    pprExt ExtMode
    x
      OpRegExt Width
    w Reg
    r ExtMode
    x RegNo
    i -> Width -> Reg -> doc
    forall doc. IsLine doc => Width -> Reg -> doc
    pprReg Width
    w Reg
    r doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> doc
    forall doc. IsLine doc => doc
    comma doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> ExtMode -> doc
    forall doc. IsLine doc => ExtMode -> doc
    pprExt ExtMode
    x doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> doc
    forall doc. IsLine doc => doc
    comma doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '#' doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> doc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    i
      OpRegShift Width
    w Reg
    r ShiftMode
    s RegNo
    i -> Width -> Reg -> doc
    forall doc. IsLine doc => Width -> Reg -> doc
    pprReg Width
    w Reg
    r doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> doc
    forall doc. IsLine doc => doc
    comma doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> ShiftMode -> doc
    forall doc. IsLine doc => ShiftMode -> doc
    pprShift ShiftMode
    s doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '#' doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> doc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    i
      OpImm Imm
    im          -> Platform -> Imm -> doc
    forall doc. IsLine doc => Platform -> Imm -> doc
    pprIm Platform
    plat Imm
    im
      OpImmShift Imm
    im ShiftMode
    s RegNo
    i -> Platform -> Imm -> doc
    forall doc. IsLine doc => Platform -> Imm -> doc
    pprIm Platform
    plat Imm
    im doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> doc
    forall doc. IsLine doc => doc
    comma doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> ShiftMode -> doc
    forall doc. IsLine doc => ShiftMode -> doc
    pprShift ShiftMode
    s doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '#' doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> doc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    i
      -- TODO: Address computation always use registers as 64bit -- is this correct?
      OpAddr (AddrRegReg Reg
    r1 Reg
    r2) -> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '[' doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Width -> Reg -> doc
    forall doc. IsLine doc => Width -> Reg -> doc
    pprReg Width
    W64 Reg
    r1 doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> doc
    forall doc. IsLine doc => doc
    comma doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Width -> Reg -> doc
    forall doc. IsLine doc => Width -> Reg -> doc
    pprReg Width
    W64 Reg
    r2 doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    ']'
      OpAddr (AddrRegImm Reg
    r1 Imm
    im) -> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '[' doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Width -> Reg -> doc
    forall doc. IsLine doc => Width -> Reg -> doc
    pprReg Width
    W64 Reg
    r1 doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> doc
    forall doc. IsLine doc => doc
    comma doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> Imm -> doc
    forall doc. IsLine doc => Platform -> Imm -> doc
    pprImm Platform
    plat Imm
    im doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    ']'
      OpAddr (AddrReg Reg
    r1)       -> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '[' doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Width -> Reg -> doc
    forall doc. IsLine doc => Width -> Reg -> doc
    pprReg Width
    W64 Reg
    r1 doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Char -> doc
    forall doc. IsLine doc => Char -> doc
    char Char
    ']'

    pprReg :: forall doc. IsLine doc => Width -> Reg -> doc
    pprReg :: forall doc. IsLine doc => Width -> Reg -> doc
    pprReg Width
    w Reg
    r = case Reg
    r of
      RegReal    (RealRegSingle RegNo
    i) -> Width -> RegNo -> doc
    ppr_reg_no Width
    w RegNo
    i
      -- virtual regs should not show up, but this is helpful for debugging.
      RegVirtual (VirtualRegI Unique
    u)   -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "%vI_" doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Unique -> doc
    forall doc. IsLine doc => Unique -> doc
    pprUniqueAlways Unique
    u
      RegVirtual (VirtualRegF Unique
    u)   -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "%vF_" doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Unique -> doc
    forall doc. IsLine doc => Unique -> doc
    pprUniqueAlways Unique
    u
      RegVirtual (VirtualRegD Unique
    u)   -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "%vD_" doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Unique -> doc
    forall doc. IsLine doc => Unique -> doc
    pprUniqueAlways Unique
    u
      Reg
    _                            -> String -> SDoc -> doc
    forall a. HasCallStack => String -> SDoc -> a
    pprPanic String
    "AArch64.pprReg" (String -> SDoc
    forall doc. IsLine doc => String -> doc
    text (String -> SDoc) -> String -> SDoc
    forall a b. (a -> b) -> a -> b
    $ Reg -> String
    forall a. Show a => a -> String
    show Reg
    r)

      where
        ppr_reg_no :: Width -> Int -> doc
        ppr_reg_no :: Width -> RegNo -> doc
    ppr_reg_no Width
    w RegNo
    31
             | Width
    w Width -> Width -> Bool
    forall a. Eq a => a -> a -> Bool
    == Width
    W64 = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "sp"
             | Width
    w Width -> Width -> Bool
    forall a. Eq a => a -> a -> Bool
    == Width
    W32 = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "wsp"

        ppr_reg_no Width
    w RegNo
    i
             | RegNo
    i RegNo -> RegNo -> Bool
    forall a. Ord a => a -> a -> Bool
    < RegNo
    0, Width
    w Width -> Width -> Bool
    forall a. Eq a => a -> a -> Bool
    == Width
    W32 = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "wzr"
             | RegNo
    i RegNo -> RegNo -> Bool
    forall a. Ord a => a -> a -> Bool
    < RegNo
    0, Width
    w Width -> Width -> Bool
    forall a. Eq a => a -> a -> Bool
    == Width
    W64 = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "xzr"
             | RegNo
    i RegNo -> RegNo -> Bool
    forall a. Ord a => a -> a -> Bool
    < RegNo
    0 = String -> SDoc -> doc
    forall a. HasCallStack => String -> SDoc -> a
    pprPanic String
    "Invalid Zero Reg" (Width -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Width
    w SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> RegNo -> SDoc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    i)
             -- General Purpose Registers
             | RegNo
    i RegNo -> RegNo -> Bool
    forall a. Ord a => a -> a -> Bool
    <= RegNo
    31, Width
    w Width -> Width -> Bool
    forall a. Eq a => a -> a -> Bool
    == Width
    W8  = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "w" doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> doc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    i      -- there are no byte or half
             | RegNo
    i RegNo -> RegNo -> Bool
    forall a. Ord a => a -> a -> Bool
    <= RegNo
    31, Width
    w Width -> Width -> Bool
    forall a. Eq a => a -> a -> Bool
    == Width
    W16 = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "w" doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> doc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    i      -- words... word will do.
             | RegNo
    i RegNo -> RegNo -> Bool
    forall a. Ord a => a -> a -> Bool
    <= RegNo
    31, Width
    w Width -> Width -> Bool
    forall a. Eq a => a -> a -> Bool
    == Width
    W32 = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "w" doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> doc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    i
             | RegNo
    i RegNo -> RegNo -> Bool
    forall a. Ord a => a -> a -> Bool
    <= RegNo
    31, Width
    w Width -> Width -> Bool
    forall a. Eq a => a -> a -> Bool
    == Width
    W64 = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "x" doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> doc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    i
             | RegNo
    i RegNo -> RegNo -> Bool
    forall a. Ord a => a -> a -> Bool
    <= RegNo
    31 = String -> SDoc -> doc
    forall a. HasCallStack => String -> SDoc -> a
    pprPanic String
    "Invalid Reg" (Width -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr Width
    w SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> RegNo -> SDoc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    i)
             -- Floating Point Registers
             | RegNo
    i RegNo -> RegNo -> Bool
    forall a. Ord a => a -> a -> Bool
    <= RegNo
    63, Width
    w Width -> Width -> Bool
    forall a. Eq a => a -> a -> Bool
    == Width
    W8  = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "b" doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> doc
    forall doc. IsLine doc => RegNo -> doc
    int (RegNo
    iRegNo -> RegNo -> RegNo
    forall a. Num a => a -> a -> a
    -RegNo
    32)
             | RegNo
    i RegNo -> RegNo -> Bool
    forall a. Ord a => a -> a -> Bool
    <= RegNo
    63, Width
    w Width -> Width -> Bool
    forall a. Eq a => a -> a -> Bool
    == Width
    W16 = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "h" doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> doc
    forall doc. IsLine doc => RegNo -> doc
    int (RegNo
    iRegNo -> RegNo -> RegNo
    forall a. Num a => a -> a -> a
    -RegNo
    32)
             | RegNo
    i RegNo -> RegNo -> Bool
    forall a. Ord a => a -> a -> Bool
    <= RegNo
    63, Width
    w Width -> Width -> Bool
    forall a. Eq a => a -> a -> Bool
    == Width
    W32 = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "s" doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> doc
    forall doc. IsLine doc => RegNo -> doc
    int (RegNo
    iRegNo -> RegNo -> RegNo
    forall a. Num a => a -> a -> a
    -RegNo
    32)
             | RegNo
    i RegNo -> RegNo -> Bool
    forall a. Ord a => a -> a -> Bool
    <= RegNo
    63, Width
    w Width -> Width -> Bool
    forall a. Eq a => a -> a -> Bool
    == Width
    W64 = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "d" doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> doc
    forall doc. IsLine doc => RegNo -> doc
    int (RegNo
    iRegNo -> RegNo -> RegNo
    forall a. Num a => a -> a -> a
    -RegNo
    32)
             -- no support for 'q'uad in GHC's NCG yet.
             | Bool
    otherwise = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "very naughty powerpc register"

    isFloatOp :: Operand -> Bool
    isFloatOp :: Operand -> Bool
    isFloatOp (OpReg Width
    _ (RegReal (RealRegSingle RegNo
    i))) | RegNo
    i RegNo -> RegNo -> Bool
    forall a. Ord a => a -> a -> Bool
    > RegNo
    31 = Bool
    True
    isFloatOp (OpReg Width
    _ (RegVirtual (VirtualRegF Unique
    _))) = Bool
    True
    isFloatOp (OpReg Width
    _ (RegVirtual (VirtualRegD Unique
    _))) = Bool
    True
    isFloatOp Operand
    _ = Bool
    False

    pprInstr :: IsDoc doc => Platform -> Instr -> doc
    pprInstr :: forall doc. IsDoc doc => Platform -> Instr -> doc
    pprInstr Platform
    platform Instr
    instr = case Instr
    instr of
      -- Meta Instructions ---------------------------------------------------------
      -- see Note [dualLine and dualDoc] in GHC.Utils.Outputable
      COMMENT SDoc
    s  -> SDoc -> HDoc -> doc
    forall doc. IsDoc doc => SDoc -> HDoc -> doc
    dualDoc (SDoc -> SDoc
    asmComment SDoc
    s) HDoc
    forall doc. IsOutput doc => doc
    empty
      MULTILINE_COMMENT SDoc
    s -> SDoc -> HDoc -> doc
    forall doc. IsDoc doc => SDoc -> HDoc -> doc
    dualDoc (SDoc -> SDoc
    asmMultilineComment SDoc
    s) HDoc
    forall doc. IsOutput doc => doc
    empty
      ANN SDoc
    d Instr
    i -> SDoc -> HDoc -> doc
    forall doc. IsDoc doc => SDoc -> HDoc -> doc
    dualDoc (Platform -> Instr -> SDoc
    forall doc. IsDoc doc => Platform -> Instr -> doc
    pprInstr Platform
    platform Instr
    i SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> SDoc -> SDoc
    asmDoubleslashComment SDoc
    d) (Platform -> Instr -> HDoc
    forall doc. IsDoc doc => Platform -> Instr -> doc
    pprInstr Platform
    platform Instr
    i)

      LOCATION RegNo
    file RegNo
    line' RegNo
    col String
    _name
        -> Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\t.loc" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> RegNo -> Line doc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    file Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> RegNo -> Line doc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    line' Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> RegNo -> Line doc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    col)
      DELTA RegNo
    d   -> SDoc -> HDoc -> doc
    forall doc. IsDoc doc => SDoc -> HDoc -> doc
    dualDoc (SDoc -> SDoc
    asmComment (SDoc -> SDoc) -> SDoc -> SDoc
    forall a b. (a -> b) -> a -> b
    $ String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "\tdelta = " SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> SDoc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    d) HDoc
    forall doc. IsOutput doc => doc
    empty
                   -- see Note [dualLine and dualDoc] in GHC.Utils.Outputable
      NEWBLOCK BlockId
    blockid -> -- This is invalid assembly. But NEWBLOCK should never be contained
                          -- in the final instruction stream. But we still want to be able to
                          -- print it for debugging purposes.
                          Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "BLOCK " Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform (BlockId -> CLabel
    blockLbl BlockId
    blockid))

      -- Pseudo Instructions -------------------------------------------------------

      Instr
    PUSH_STACK_FRAME -> [Line doc] -> doc
    forall doc. IsDoc doc => [Line doc] -> doc
    lines_ [String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tstp x29, x30, [sp, #-16]!",
                                  String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tmov x29, sp"]

      Instr
    POP_STACK_FRAME -> Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tldp x29, x30, [sp], #16"
      -- ===========================================================================
      -- AArch64 Instruction Set
      -- 1. Arithmetic Instructions ------------------------------------------------
      ADD  Operand
    o1 Operand
    o2 Operand
    o3
        | Operand -> Bool
    isFloatOp Operand
    o1 Bool -> Bool -> Bool
    && Operand -> Bool
    isFloatOp Operand
    o2 Bool -> Bool -> Bool
    && Operand -> Bool
    isFloatOp Operand
    o3 -> Line doc -> Operand -> Operand -> Operand -> doc
    op3 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tfadd") Operand
    o1 Operand
    o2 Operand
    o3
        | Bool
    otherwise -> Line doc -> Operand -> Operand -> Operand -> doc
    op3 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tadd") Operand
    o1 Operand
    o2 Operand
    o3
      CMP  Operand
    o1 Operand
    o2
        | Operand -> Bool
    isFloatOp Operand
    o1 Bool -> Bool -> Bool
    && Operand -> Bool
    isFloatOp Operand
    o2 -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tfcmp") Operand
    o1 Operand
    o2
        | Bool
    otherwise -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tcmp") Operand
    o1 Operand
    o2
      MSUB Operand
    o1 Operand
    o2 Operand
    o3 Operand
    o4 -> Line doc -> Operand -> Operand -> Operand -> Operand -> doc
    op4 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tmsub") Operand
    o1 Operand
    o2 Operand
    o3 Operand
    o4
      MUL  Operand
    o1 Operand
    o2 Operand
    o3
        | Operand -> Bool
    isFloatOp Operand
    o1 Bool -> Bool -> Bool
    && Operand -> Bool
    isFloatOp Operand
    o2 Bool -> Bool -> Bool
    && Operand -> Bool
    isFloatOp Operand
    o3 -> Line doc -> Operand -> Operand -> Operand -> doc
    op3 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tfmul") Operand
    o1 Operand
    o2 Operand
    o3
        | Bool
    otherwise -> Line doc -> Operand -> Operand -> Operand -> doc
    op3 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tmul") Operand
    o1 Operand
    o2 Operand
    o3
      SMULH Operand
    o1 Operand
    o2 Operand
    o3 -> Line doc -> Operand -> Operand -> Operand -> doc
    op3 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tsmulh") Operand
    o1 Operand
    o2 Operand
    o3
      SMULL Operand
    o1 Operand
    o2 Operand
    o3 -> Line doc -> Operand -> Operand -> Operand -> doc
    op3 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tsmull") Operand
    o1 Operand
    o2 Operand
    o3
      NEG  Operand
    o1 Operand
    o2
        | Operand -> Bool
    isFloatOp Operand
    o1 Bool -> Bool -> Bool
    && Operand -> Bool
    isFloatOp Operand
    o2 -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tfneg") Operand
    o1 Operand
    o2
        | Bool
    otherwise -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tneg") Operand
    o1 Operand
    o2
      SDIV Operand
    o1 Operand
    o2 Operand
    o3 | Operand -> Bool
    isFloatOp Operand
    o1 Bool -> Bool -> Bool
    && Operand -> Bool
    isFloatOp Operand
    o2 Bool -> Bool -> Bool
    && Operand -> Bool
    isFloatOp Operand
    o3
        -> Line doc -> Operand -> Operand -> Operand -> doc
    op3 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tfdiv") Operand
    o1 Operand
    o2 Operand
    o3
      SDIV Operand
    o1 Operand
    o2 Operand
    o3 -> Line doc -> Operand -> Operand -> Operand -> doc
    op3 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tsdiv") Operand
    o1 Operand
    o2 Operand
    o3

      SUB  Operand
    o1 Operand
    o2 Operand
    o3
        | Operand -> Bool
    isFloatOp Operand
    o1 Bool -> Bool -> Bool
    && Operand -> Bool
    isFloatOp Operand
    o2 Bool -> Bool -> Bool
    && Operand -> Bool
    isFloatOp Operand
    o3 -> Line doc -> Operand -> Operand -> Operand -> doc
    op3 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tfsub") Operand
    o1 Operand
    o2 Operand
    o3
        | Bool
    otherwise -> Line doc -> Operand -> Operand -> Operand -> doc
    op3 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tsub")  Operand
    o1 Operand
    o2 Operand
    o3
      UDIV Operand
    o1 Operand
    o2 Operand
    o3 -> Line doc -> Operand -> Operand -> Operand -> doc
    op3 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tudiv") Operand
    o1 Operand
    o2 Operand
    o3

      -- 2. Bit Manipulation Instructions ------------------------------------------
      SBFM Operand
    o1 Operand
    o2 Operand
    o3 Operand
    o4 -> Line doc -> Operand -> Operand -> Operand -> Operand -> doc
    op4 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tsbfm") Operand
    o1 Operand
    o2 Operand
    o3 Operand
    o4
      UBFM Operand
    o1 Operand
    o2 Operand
    o3 Operand
    o4 -> Line doc -> Operand -> Operand -> Operand -> Operand -> doc
    op4 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tubfm") Operand
    o1 Operand
    o2 Operand
    o3 Operand
    o4
      -- signed and unsigned bitfield extract
      SBFX Operand
    o1 Operand
    o2 Operand
    o3 Operand
    o4 -> Line doc -> Operand -> Operand -> Operand -> Operand -> doc
    op4 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tsbfx") Operand
    o1 Operand
    o2 Operand
    o3 Operand
    o4
      UBFX Operand
    o1 Operand
    o2 Operand
    o3 Operand
    o4 -> Line doc -> Operand -> Operand -> Operand -> Operand -> doc
    op4 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tubfx") Operand
    o1 Operand
    o2 Operand
    o3 Operand
    o4
      SXTB Operand
    o1 Operand
    o2       -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tsxtb") Operand
    o1 Operand
    o2
      UXTB Operand
    o1 Operand
    o2       -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tuxtb") Operand
    o1 Operand
    o2
      SXTH Operand
    o1 Operand
    o2       -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tsxth") Operand
    o1 Operand
    o2
      UXTH Operand
    o1 Operand
    o2       -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tuxth") Operand
    o1 Operand
    o2

      -- 3. Logical and Move Instructions ------------------------------------------
      AND Operand
    o1 Operand
    o2 Operand
    o3  -> Line doc -> Operand -> Operand -> Operand -> doc
    op3 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tand") Operand
    o1 Operand
    o2 Operand
    o3
      ASR Operand
    o1 Operand
    o2 Operand
    o3  -> Line doc -> Operand -> Operand -> Operand -> doc
    op3 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tasr") Operand
    o1 Operand
    o2 Operand
    o3
      EOR Operand
    o1 Operand
    o2 Operand
    o3  -> Line doc -> Operand -> Operand -> Operand -> doc
    op3 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\teor") Operand
    o1 Operand
    o2 Operand
    o3
      LSL Operand
    o1 Operand
    o2 Operand
    o3  -> Line doc -> Operand -> Operand -> Operand -> doc
    op3 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tlsl") Operand
    o1 Operand
    o2 Operand
    o3
      LSR Operand
    o1 Operand
    o2 Operand
    o3  -> Line doc -> Operand -> Operand -> Operand -> doc
    op3 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tlsr") Operand
    o1 Operand
    o2 Operand
    o3
      MOV Operand
    o1 Operand
    o2
        | Operand -> Bool
    isFloatOp Operand
    o1 Bool -> Bool -> Bool
    || Operand -> Bool
    isFloatOp Operand
    o2 -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tfmov") Operand
    o1 Operand
    o2
        | Bool
    otherwise                    -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tmov") Operand
    o1 Operand
    o2
      MOVK Operand
    o1 Operand
    o2    -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tmovk") Operand
    o1 Operand
    o2
      MOVZ Operand
    o1 Operand
    o2    -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tmovz") Operand
    o1 Operand
    o2
      MVN Operand
    o1 Operand
    o2     -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tmvn") Operand
    o1 Operand
    o2
      ORR Operand
    o1 Operand
    o2 Operand
    o3  -> Line doc -> Operand -> Operand -> Operand -> doc
    op3 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\torr") Operand
    o1 Operand
    o2 Operand
    o3

      -- 4. Branch Instructions ----------------------------------------------------
      J Target
    t            -> Platform -> Instr -> doc
    forall doc. IsDoc doc => Platform -> Instr -> doc
    pprInstr Platform
    platform (Target -> Instr
    B Target
    t)
      B (TBlock BlockId
    bid) -> Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tb" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform (Unique -> CLabel
    mkLocalBlockLabel (BlockId -> Unique
    forall a. Uniquable a => a -> Unique
    getUnique BlockId
    bid))
      B (TLabel CLabel
    lbl) -> Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tb" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl
      B (TReg Reg
    r)     -> Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tbr" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Width -> Reg -> Line doc
    forall doc. IsLine doc => Width -> Reg -> doc
    pprReg Width
    W64 Reg
    r

      BL (TBlock BlockId
    bid) [Reg]
    _ [Reg]
    _ -> Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tbl" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform (Unique -> CLabel
    mkLocalBlockLabel (BlockId -> Unique
    forall a. Uniquable a => a -> Unique
    getUnique BlockId
    bid))
      BL (TLabel CLabel
    lbl) [Reg]
    _ [Reg]
    _ -> Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tbl" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl
      BL (TReg Reg
    r)     [Reg]
    _ [Reg]
    _ -> Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tblr" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Width -> Reg -> Line doc
    forall doc. IsLine doc => Width -> Reg -> doc
    pprReg Width
    W64 Reg
    r

      BCOND Cond
    c (TBlock BlockId
    bid) -> Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\t" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Cond -> Line doc
    forall doc. IsLine doc => Cond -> doc
    pprBcond Cond
    c Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform (Unique -> CLabel
    mkLocalBlockLabel (BlockId -> Unique
    forall a. Uniquable a => a -> Unique
    getUnique BlockId
    bid))
      BCOND Cond
    c (TLabel CLabel
    lbl) -> Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\t" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Cond -> Line doc
    forall doc. IsLine doc => Cond -> doc
    pprBcond Cond
    c Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl
      BCOND Cond
    _ (TReg Reg
    _)     -> String -> doc
    forall a. HasCallStack => String -> a
    panic String
    "AArch64.ppr: No conditional branching to registers!"

      -- 5. Atomic Instructions ----------------------------------------------------
      -- 6. Conditional Instructions -----------------------------------------------
      CSET Operand
    o Cond
    c  -> Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tcset" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> Operand -> Line doc
    forall doc. IsLine doc => Platform -> Operand -> doc
    pprOp Platform
    platform Operand
    o Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Line doc
    forall doc. IsLine doc => doc
    comma Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Cond -> Line doc
    forall doc. IsLine doc => Cond -> doc
    pprCond Cond
    c

      CBZ Operand
    o (TBlock BlockId
    bid) -> Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tcbz" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> Operand -> Line doc
    forall doc. IsLine doc => Platform -> Operand -> doc
    pprOp Platform
    platform Operand
    o Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Line doc
    forall doc. IsLine doc => doc
    comma Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform (Unique -> CLabel
    mkLocalBlockLabel (BlockId -> Unique
    forall a. Uniquable a => a -> Unique
    getUnique BlockId
    bid))
      CBZ Operand
    o (TLabel CLabel
    lbl) -> Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tcbz" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> Operand -> Line doc
    forall doc. IsLine doc => Platform -> Operand -> doc
    pprOp Platform
    platform Operand
    o Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Line doc
    forall doc. IsLine doc => doc
    comma Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl
      CBZ Operand
    _ (TReg Reg
    _)     -> String -> doc
    forall a. HasCallStack => String -> a
    panic String
    "AArch64.ppr: No conditional (cbz) branching to registers!"

      CBNZ Operand
    o (TBlock BlockId
    bid) -> Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tcbnz" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> Operand -> Line doc
    forall doc. IsLine doc => Platform -> Operand -> doc
    pprOp Platform
    platform Operand
    o Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Line doc
    forall doc. IsLine doc => doc
    comma Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform (Unique -> CLabel
    mkLocalBlockLabel (BlockId -> Unique
    forall a. Uniquable a => a -> Unique
    getUnique BlockId
    bid))
      CBNZ Operand
    o (TLabel CLabel
    lbl) -> Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tcbnz" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> Operand -> Line doc
    forall doc. IsLine doc => Platform -> Operand -> doc
    pprOp Platform
    platform Operand
    o Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Line doc
    forall doc. IsLine doc => doc
    comma Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl
      CBNZ Operand
    _ (TReg Reg
    _)     -> String -> doc
    forall a. HasCallStack => String -> a
    panic String
    "AArch64.ppr: No conditional (cbnz) branching to registers!"

      -- 7. Load and Store Instructions --------------------------------------------
      -- NOTE: GHC may do whacky things where it only load the lower part of an
      --       address. Not observing the correct size when loading will lead
      --       inevitably to crashes.
      STR Format
    _f o1 :: Operand
    o1@(OpReg Width
    W8 (RegReal (RealRegSingle RegNo
    i))) Operand
    o2 | RegNo
    i RegNo -> RegNo -> Bool
    forall a. Ord a => a -> a -> Bool
    < RegNo
    32 ->
        Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tstrb") Operand
    o1 Operand
    o2
      STR Format
    _f o1 :: Operand
    o1@(OpReg Width
    W16 (RegReal (RealRegSingle RegNo
    i))) Operand
    o2 | RegNo
    i RegNo -> RegNo -> Bool
    forall a. Ord a => a -> a -> Bool
    < RegNo
    32 ->
        Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tstrh") Operand
    o1 Operand
    o2
      STR Format
    _f Operand
    o1 Operand
    o2 -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tstr") Operand
    o1 Operand
    o2
      STLR Format
    _f Operand
    o1 Operand
    o2 -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tstlr") Operand
    o1 Operand
    o2

    #if defined(darwin_HOST_OS)
      LDR _f o1 (OpImm (ImmIndex lbl' off)) | Just (_info, lbl) <- dynamicLinkerLabelInfo lbl' ->
        op_adrp o1 (pprAsmLabel platform lbl <> text "@gotpage") $$
        op_ldr o1 (pprAsmLabel platform lbl <> text "@gotpageoff") $$
        op_add o1 (char '#' <> int off) -- TODO: check that off is in 12bits.

      LDR _f o1 (OpImm (ImmIndex lbl off)) | isForeignLabel lbl ->
        op_adrp o1 (pprAsmLabel platform lbl <> text "@gotpage") $$
        op_ldr o1 (pprAsmLabel platform lbl <> text "@gotpageoff") $$
        op_add o1 (char '#' <> int off) -- TODO: check that off is in 12bits.

      LDR _f o1 (OpImm (ImmIndex lbl off)) ->
        op_adrp o1 (pprAsmLabel platform lbl <> text "@page") $$
        op_add o1 (pprAsmLabel platform lbl <> text "@pageoff") $$
        op_add o1 (char '#' <> int off) -- TODO: check that off is in 12bits.

      LDR _f o1 (OpImm (ImmCLbl lbl')) | Just (_info, lbl) <- dynamicLinkerLabelInfo lbl' ->
        op_adrp o1 (pprAsmLabel platform lbl <> text "@gotpage") $$
        op_ldr o1 (pprAsmLabel platform lbl <> text "@gotpageoff")

      LDR _f o1 (OpImm (ImmCLbl lbl)) | isForeignLabel lbl ->
        op_adrp o1 (pprAsmLabel platform lbl <> text "@gotpage") $$
        op_ldr o1 (pprAsmLabel platform lbl <> text "@gotpageoff")

      LDR _f o1 (OpImm (ImmCLbl lbl)) ->
        op_adrp o1 (pprAsmLabel platform lbl <> text "@page") $$
        op_add o1 (pprAsmLabel platform lbl <> text "@pageoff")

    #else
      LDR Format
    _f Operand
    o1 (OpImm (ImmIndex CLabel
    lbl' RegNo
    off)) | Just (DynamicLinkerLabelInfo
    _info, CLabel
    lbl) <- CLabel -> Maybe (DynamicLinkerLabelInfo, CLabel)
    dynamicLinkerLabelInfo CLabel
    lbl' ->
        Operand -> Line doc -> doc
    op_adrp Operand
    o1 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    ":got:" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl) doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
        Operand -> Line doc -> doc
    op_ldr Operand
    o1 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    ":got_lo12:" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl) doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
        Operand -> Line doc -> doc
    op_add Operand
    o1 (Char -> Line doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '#' Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> Line doc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    off) -- TODO: check that off is in 12bits.

      LDR Format
    _f Operand
    o1 (OpImm (ImmIndex CLabel
    lbl RegNo
    off)) | CLabel -> Bool
    isForeignLabel CLabel
    lbl ->
        Operand -> Line doc -> doc
    op_adrp Operand
    o1 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    ":got:" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl) doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
        Operand -> Line doc -> doc
    op_ldr Operand
    o1 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    ":got_lo12:" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl) doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
        Operand -> Line doc -> doc
    op_add Operand
    o1 (Char -> Line doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '#' Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> Line doc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    off) -- TODO: check that off is in 12bits.

      LDR Format
    _f Operand
    o1 (OpImm (ImmIndex CLabel
    lbl RegNo
    off)) ->
        Operand -> Line doc -> doc
    op_adrp Operand
    o1 (Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl) doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
        Operand -> Line doc -> doc
    op_add Operand
    o1 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    ":lo12:" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl) doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
        Operand -> Line doc -> doc
    op_add Operand
    o1 (Char -> Line doc
    forall doc. IsLine doc => Char -> doc
    char Char
    '#' Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> RegNo -> Line doc
    forall doc. IsLine doc => RegNo -> doc
    int RegNo
    off) -- TODO: check that off is in 12bits.

      LDR Format
    _f Operand
    o1 (OpImm (ImmCLbl CLabel
    lbl')) | Just (DynamicLinkerLabelInfo
    _info, CLabel
    lbl) <- CLabel -> Maybe (DynamicLinkerLabelInfo, CLabel)
    dynamicLinkerLabelInfo CLabel
    lbl' ->
        Operand -> Line doc -> doc
    op_adrp Operand
    o1 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    ":got:" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl) doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
        Operand -> Line doc -> doc
    op_ldr Operand
    o1 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    ":got_lo12:" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl)

      LDR Format
    _f Operand
    o1 (OpImm (ImmCLbl CLabel
    lbl)) | CLabel -> Bool
    isForeignLabel CLabel
    lbl ->
        Operand -> Line doc -> doc
    op_adrp Operand
    o1 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    ":got:" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl) doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
        Operand -> Line doc -> doc
    op_ldr Operand
    o1 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    ":got_lo12:" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl)

      LDR Format
    _f Operand
    o1 (OpImm (ImmCLbl CLabel
    lbl)) ->
        Operand -> Line doc -> doc
    op_adrp Operand
    o1 (Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl) doc -> doc -> doc
    forall doc. IsDoc doc => doc -> doc -> doc
    $$
        Operand -> Line doc -> doc
    op_add Operand
    o1 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    ":lo12:" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> CLabel -> Line doc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprAsmLabel Platform
    platform CLabel
    lbl)

    #endif

      LDR Format
    _f o1 :: Operand
    o1@(OpReg Width
    W8 (RegReal (RealRegSingle RegNo
    i))) Operand
    o2 | RegNo
    i RegNo -> RegNo -> Bool
    forall a. Ord a => a -> a -> Bool
    < RegNo
    32 ->
        Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tldrb") Operand
    o1 Operand
    o2
      LDR Format
    _f o1 :: Operand
    o1@(OpReg Width
    W16 (RegReal (RealRegSingle RegNo
    i))) Operand
    o2 | RegNo
    i RegNo -> RegNo -> Bool
    forall a. Ord a => a -> a -> Bool
    < RegNo
    32 ->
        Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tldrh") Operand
    o1 Operand
    o2
      LDR Format
    _f Operand
    o1 Operand
    o2 -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tldr") Operand
    o1 Operand
    o2
      LDAR Format
    _f Operand
    o1 Operand
    o2 -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tldar") Operand
    o1 Operand
    o2

      -- 8. Synchronization Instructions -------------------------------------------
      Instr
    DMBISH -> Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tdmb ish"

      -- 9. Floating Point Instructions --------------------------------------------
      FCVT Operand
    o1 Operand
    o2 -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tfcvt") Operand
    o1 Operand
    o2
      SCVTF Operand
    o1 Operand
    o2 -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tscvtf") Operand
    o1 Operand
    o2
      FCVTZS Operand
    o1 Operand
    o2 -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tfcvtzs") Operand
    o1 Operand
    o2
      FABS Operand
    o1 Operand
    o2 -> Line doc -> Operand -> Operand -> doc
    op2 (String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tfabs") Operand
    o1 Operand
    o2
      FMA FMASign
    variant Operand
    d Operand
    r1 Operand
    r2 Operand
    r3 ->
        let fma :: Line doc
    fma = case FMASign
    variant of
                    FMASign
    FMAdd  -> String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tfmadd"
                    FMASign
    FMSub  -> String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tfmsub"
                    FMASign
    FNMAdd -> String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tfnmadd"
                    FMASign
    FNMSub -> String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tfnmsub"
        in Line doc -> Operand -> Operand -> Operand -> Operand -> doc
    op4 Line doc
    fma Operand
    d Operand
    r1 Operand
    r2 Operand
    r3
     where op2 :: Line doc -> Operand -> Operand -> doc
    op2 Line doc
    op Operand
    o1 Operand
    o2        = Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ Line doc
    op Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> Operand -> Line doc
    forall doc. IsLine doc => Platform -> Operand -> doc
    pprOp Platform
    platform Operand
    o1 Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Line doc
    forall doc. IsLine doc => doc
    comma Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> Operand -> Line doc
    forall doc. IsLine doc => Platform -> Operand -> doc
    pprOp Platform
    platform Operand
    o2
           op3 :: Line doc -> Operand -> Operand -> Operand -> doc
    op3 Line doc
    op Operand
    o1 Operand
    o2 Operand
    o3     = Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ Line doc
    op Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> Operand -> Line doc
    forall doc. IsLine doc => Platform -> Operand -> doc
    pprOp Platform
    platform Operand
    o1 Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Line doc
    forall doc. IsLine doc => doc
    comma Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> Operand -> Line doc
    forall doc. IsLine doc => Platform -> Operand -> doc
    pprOp Platform
    platform Operand
    o2 Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Line doc
    forall doc. IsLine doc => doc
    comma Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> Operand -> Line doc
    forall doc. IsLine doc => Platform -> Operand -> doc
    pprOp Platform
    platform Operand
    o3
           op4 :: Line doc -> Operand -> Operand -> Operand -> Operand -> doc
    op4 Line doc
    op Operand
    o1 Operand
    o2 Operand
    o3 Operand
    o4  = Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ Line doc
    op Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> Operand -> Line doc
    forall doc. IsLine doc => Platform -> Operand -> doc
    pprOp Platform
    platform Operand
    o1 Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Line doc
    forall doc. IsLine doc => doc
    comma Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> Operand -> Line doc
    forall doc. IsLine doc => Platform -> Operand -> doc
    pprOp Platform
    platform Operand
    o2 Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Line doc
    forall doc. IsLine doc => doc
    comma Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> Operand -> Line doc
    forall doc. IsLine doc => Platform -> Operand -> doc
    pprOp Platform
    platform Operand
    o3 Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Line doc
    forall doc. IsLine doc => doc
    comma Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> Operand -> Line doc
    forall doc. IsLine doc => Platform -> Operand -> doc
    pprOp Platform
    platform Operand
    o4
           op_ldr :: Operand -> Line doc -> doc
    op_ldr Operand
    o1 Line doc
    rest      = Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tldr" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> Operand -> Line doc
    forall doc. IsLine doc => Platform -> Operand -> doc
    pprOp Platform
    platform Operand
    o1 Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Line doc
    forall doc. IsLine doc => doc
    comma Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "[" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Platform -> Operand -> Line doc
    forall doc. IsLine doc => Platform -> Operand -> doc
    pprOp Platform
    platform Operand
    o1 Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Line doc
    forall doc. IsLine doc => doc
    comma Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Line doc
    rest Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "]"
           op_adrp :: Operand -> Line doc -> doc
    op_adrp Operand
    o1 Line doc
    rest     = Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tadrp" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> Operand -> Line doc
    forall doc. IsLine doc => Platform -> Operand -> doc
    pprOp Platform
    platform Operand
    o1 Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Line doc
    forall doc. IsLine doc => doc
    comma Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Line doc
    rest
           op_add :: Operand -> Line doc -> doc
    op_add Operand
    o1 Line doc
    rest      = Line doc -> doc
    forall doc. IsDoc doc => Line doc -> doc
    line (Line doc -> doc) -> Line doc -> doc
    forall a b. (a -> b) -> a -> b
    $ String -> Line doc
    forall doc. IsLine doc => String -> doc
    text String
    "\tadd" Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> Operand -> Line doc
    forall doc. IsLine doc => Platform -> Operand -> doc
    pprOp Platform
    platform Operand
    o1 Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Line doc
    forall doc. IsLine doc => doc
    comma Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Platform -> Operand -> Line doc
    forall doc. IsLine doc => Platform -> Operand -> doc
    pprOp Platform
    platform Operand
    o1 Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Line doc
    forall doc. IsLine doc => doc
    comma Line doc -> Line doc -> Line doc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> Line doc
    rest

    pprBcond :: IsLine doc => Cond -> doc
    pprBcond :: forall doc. IsLine doc => Cond -> doc
    pprBcond Cond
    c = String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "b." doc -> doc -> doc
    forall doc. IsLine doc => doc -> doc -> doc
    <> Cond -> doc
    forall doc. IsLine doc => Cond -> doc
    pprCond Cond
    c

    pprCond :: IsLine doc => Cond -> doc
    pprCond :: forall doc. IsLine doc => Cond -> doc
    pprCond Cond
    c = case Cond
    c of
      Cond
    ALWAYS -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "al" -- Always
      Cond
    EQ     -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "eq" -- Equal
      Cond
    NE     -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "ne" -- Not Equal

      Cond
    SLT    -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "lt" -- Signed less than                  ; Less than, or unordered
      Cond
    SLE    -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "le" -- Signed less than or equal         ; Less than or equal, or unordered
      Cond
    SGE    -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "ge" -- Signed greater than or equal      ; Greater than or equal
      Cond
    SGT    -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "gt" -- Signed greater than               ; Greater than

      Cond
    ULT    -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "lo" -- Carry clear/ unsigned lower       ; less than
      Cond
    ULE    -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "ls" -- Unsigned lower or same            ; Less than or equal
      Cond
    UGE    -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "hs" -- Carry set/unsigned higher or same ; Greater than or equal, or unordered
      Cond
    UGT    -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "hi" -- Unsigned higher                   ; Greater than, or unordered

      -- NEVER  -> text "nv" -- Never
      Cond
    VS     -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "vs" -- Overflow                          ; Unordered (at least one NaN operand)
      Cond
    VC     -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "vc" -- No overflow                       ; Not unordered

      -- Ordered variants.  Respecting NaN.
      Cond
    OLT    -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "mi"
      Cond
    OLE    -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "ls"
      Cond
    OGE    -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "ge"
      Cond
    OGT    -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "gt"

      -- Unordered
      Cond
    UOLT   -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "lt"
      Cond
    UOLE   -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "le"
      Cond
    UOGE   -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "pl"
      Cond
    UOGT   -> String -> doc
    forall doc. IsLine doc => String -> doc
    text String
    "hi"