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

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

import GHC.Prelude hiding (EQ)

import Data.Word
import qualified Data.Array.Unsafe as U ( castSTUArray )
import Data.Array.ST
import Control.Monad.ST

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.Collections
import GHC.Cmm.Dataflow.Label
import GHC.Types.Basic (Alignment, mkAlignment, alignmentBytes)

import GHC.Cmm.BlockId
import GHC.Cmm.CLabel
import GHC.Cmm.Ppr.Expr () -- For Outputable instances

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

import GHC.Utils.Panic

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

pprNatCmmDecl :: NCGConfig -> NatCmmDecl RawCmmStatics Instr -> SDoc
pprNatCmmDecl :: NCGConfig -> NatCmmDecl RawCmmStatics Instr -> SDoc
pprNatCmmDecl NCGConfig
config (CmmData Section
section RawCmmStatics
dats) =
  NCGConfig -> Section -> SDoc
pprSectionAlign NCGConfig
config Section
section SDoc -> SDoc -> SDoc
$$ NCGConfig -> RawCmmStatics -> SDoc
pprDatas NCGConfig
config 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 in
  NCGConfig -> SDoc
pprProcAlignment NCGConfig
config SDoc -> SDoc -> SDoc
$$
  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 -> SDoc
pprSectionAlign NCGConfig
config (SectionType -> CLabel -> Section
Section SectionType
Text CLabel
lbl) SDoc -> SDoc -> SDoc
$$
        -- do not
        -- pprProcAlignment config $$
        Platform -> CLabel -> SDoc
pprLabel Platform
platform CLabel
lbl SDoc -> SDoc -> SDoc
$$ -- blocks guaranteed not null, so label needed
        [SDoc] -> SDoc
vcat ((GenBasicBlock Instr -> SDoc) -> [GenBasicBlock Instr] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map (NCGConfig -> LabelMap RawCmmStatics -> GenBasicBlock Instr -> SDoc
pprBasicBlock NCGConfig
config LabelMap RawCmmStatics
top_info) [GenBasicBlock Instr]
blocks) SDoc -> SDoc -> SDoc
$$
        (if NCGConfig -> Bool
ncgDwarfEnabled NCGConfig
config
         then CLabel -> SDoc
forall a. Outputable a => a -> SDoc
ppr (CLabel -> CLabel
mkAsmTempEndLabel CLabel
lbl) SDoc -> SDoc -> SDoc
<> Char -> SDoc
char Char
':' else SDoc
empty) SDoc -> SDoc -> SDoc
$$
        Platform -> CLabel -> SDoc
pprSizeDecl Platform
platform CLabel
lbl

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

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

pprAlign :: Platform -> Alignment -> SDoc
pprAlign :: Platform -> Alignment -> SDoc
pprAlign Platform
_platform Alignment
alignment
        = String -> SDoc
text String
"\t.balign " SDoc -> SDoc -> SDoc
<> RegNo -> SDoc
int (Alignment -> RegNo
alignmentBytes Alignment
alignment)

-- | Print appropriate alignment for the given section type.
pprAlignForSection :: Platform -> SectionType -> SDoc
pprAlignForSection :: Platform -> SectionType -> SDoc
pprAlignForSection Platform
_platform SectionType
_seg
    -- .balign is stable, whereas .align is platform dependent.
    = String -> SDoc
text String
"\t.balign 8" --  always 8

instance Outputable Instr where
    ppr :: Instr -> SDoc
ppr = Platform -> Instr -> SDoc
pprInstr Platform
genericPlatform

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

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

pprBasicBlock :: NCGConfig -> LabelMap RawCmmStatics -> NatBasicBlock Instr
              -> SDoc
pprBasicBlock :: NCGConfig -> LabelMap RawCmmStatics -> GenBasicBlock Instr -> SDoc
pprBasicBlock NCGConfig
config LabelMap RawCmmStatics
info_env (BasicBlock BlockId
blockid [Instr]
instrs)
  = SDoc -> SDoc
maybe_infotable (SDoc -> SDoc) -> SDoc -> SDoc
forall a b. (a -> b) -> a -> b
$
    Platform -> CLabel -> SDoc
pprLabel Platform
platform CLabel
asmLbl SDoc -> SDoc -> SDoc
$$
    [SDoc] -> SDoc
vcat ((Instr -> SDoc) -> [Instr] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map (Platform -> Instr -> SDoc
pprInstr Platform
platform) ([Instr] -> [Instr]
forall a. a -> a
id {-detectTrivialDeadlock-} [Instr]
optInstrs)) SDoc -> SDoc -> SDoc
$$
    (if  NCGConfig -> Bool
ncgDwarfEnabled NCGConfig
config
      then CLabel -> SDoc
forall a. Outputable a => a -> SDoc
ppr (CLabel -> CLabel
mkAsmTempEndLabel CLabel
asmLbl) SDoc -> SDoc -> SDoc
<> Char -> SDoc
char Char
':'
      else SDoc
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
    platform :: Platform
platform = NCGConfig -> Platform
ncgPlatform NCGConfig
config
    maybe_infotable :: SDoc -> SDoc
maybe_infotable SDoc
c = case KeyOf LabelMap -> LabelMap RawCmmStatics -> Maybe RawCmmStatics
forall (map :: * -> *) a.
IsMap map =>
KeyOf map -> map a -> Maybe a
mapLookup KeyOf LabelMap
BlockId
blockid LabelMap RawCmmStatics
info_env of
       Maybe RawCmmStatics
Nothing   -> SDoc
c
       Just (CmmStaticsRaw CLabel
info_lbl [CmmStatic]
info) ->
          --  pprAlignForSection platform Text $$
           SDoc
infoTableLoc SDoc -> SDoc -> SDoc
$$
           [SDoc] -> SDoc
vcat ((CmmStatic -> SDoc) -> [CmmStatic] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map (NCGConfig -> CmmStatic -> SDoc
pprData NCGConfig
config) [CmmStatic]
info) SDoc -> SDoc -> SDoc
$$
           Platform -> CLabel -> SDoc
pprLabel Platform
platform CLabel
info_lbl SDoc -> SDoc -> SDoc
$$
           SDoc
c SDoc -> SDoc -> SDoc
$$
           (if NCGConfig -> Bool
ncgDwarfEnabled NCGConfig
config
             then CLabel -> SDoc
forall a. Outputable a => a -> SDoc
ppr (CLabel -> CLabel
mkAsmTempEndLabel CLabel
info_lbl) SDoc -> SDoc -> SDoc
<> Char -> SDoc
char Char
':'
             else SDoc
empty)
    -- Make sure the info table has the right .loc for the block
    -- coming right after it. See [Note: Info Offset]
    infoTableLoc :: SDoc
infoTableLoc = case [Instr]
instrs of
      (l :: Instr
l@LOCATION{} : [Instr]
_) -> Platform -> Instr -> SDoc
pprInstr Platform
platform Instr
l
      [Instr]
_other             -> SDoc
empty

pprDatas :: NCGConfig -> RawCmmStatics -> SDoc
-- See Note [emit-time elimination of static indirections] in "GHC.Cmm.CLabel".
pprDatas :: NCGConfig -> RawCmmStatics -> SDoc
pprDatas NCGConfig
config (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 -> SDoc
pprGloblDecl (NCGConfig -> Platform
ncgPlatform NCGConfig
config) CLabel
alias
    SDoc -> SDoc -> SDoc
$$ String -> SDoc
text String
".equiv" SDoc -> SDoc -> SDoc
<+> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc (NCGConfig -> Platform
ncgPlatform NCGConfig
config) CLabel
alias SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<> Platform -> CmmLit -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc (NCGConfig -> Platform
ncgPlatform NCGConfig
config) (CLabel -> CmmLit
CmmLabel CLabel
ind')

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

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

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

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

pprGloblDecl :: Platform -> CLabel -> SDoc
pprGloblDecl :: Platform -> CLabel -> SDoc
pprGloblDecl Platform
platform CLabel
lbl
  | Bool -> Bool
not (CLabel -> Bool
externallyVisibleCLabel CLabel
lbl) = SDoc
empty
  | Bool
otherwise = String -> SDoc
text String
"\t.globl " SDoc -> SDoc -> SDoc
<> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc 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 migth 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' :: Platform -> CLabel -> SDoc
pprLabelType' :: Platform -> CLabel -> SDoc
pprLabelType' Platform
platform CLabel
lbl =
  if CLabel -> Bool
isCFunctionLabel CLabel
lbl Bool -> Bool -> Bool
|| Bool
functionOkInfoTable then
    String -> SDoc
text String
"@function"
  else
    String -> SDoc
text String
"@object"
  where
    functionOkInfoTable :: Bool
functionOkInfoTable = Platform -> Bool
platformTablesNextToCode Platform
platform Bool -> Bool -> Bool
&&
      CLabel -> Bool
isInfoTableLabel CLabel
lbl Bool -> Bool -> Bool
&& Bool -> Bool
not (CLabel -> Bool
isConInfoTableLabel CLabel
lbl)

-- this is called pprTypeAndSizeDecl in PPC.Ppr
pprTypeDecl :: Platform -> CLabel -> SDoc
pprTypeDecl :: Platform -> CLabel -> SDoc
pprTypeDecl Platform
platform CLabel
lbl
    = if OS -> Bool
osElfTarget (Platform -> OS
platformOS Platform
platform) Bool -> Bool -> Bool
&& CLabel -> Bool
externallyVisibleCLabel CLabel
lbl
      then String -> SDoc
text String
".type " SDoc -> SDoc -> SDoc
<> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform CLabel
lbl SDoc -> SDoc -> SDoc
<> String -> SDoc
text String
", " SDoc -> SDoc -> SDoc
<> Platform -> CLabel -> SDoc
pprLabelType' Platform
platform CLabel
lbl
      else SDoc
empty

pprDataItem :: NCGConfig -> CmmLit -> SDoc
pprDataItem :: NCGConfig -> CmmLit -> SDoc
pprDataItem NCGConfig
config CmmLit
lit
  = [SDoc] -> SDoc
vcat (Format -> CmmLit -> [SDoc]
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
        platform :: Platform
platform = NCGConfig -> Platform
ncgPlatform NCGConfig
config

        imm :: Imm
imm = CmmLit -> Imm
litToImm CmmLit
lit

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

        ppr_item Format
FF32  (CmmFloat Rational
r Width
_)
           = let bs :: [RegNo]
bs = Float -> [RegNo]
floatToBytes (Rational -> Float
forall a. Fractional a => Rational -> a
fromRational Rational
r)
             in  (RegNo -> SDoc) -> [RegNo] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map (\RegNo
b -> String -> SDoc
text String
"\t.byte\t" SDoc -> SDoc -> SDoc
<> Platform -> Imm -> SDoc
pprImm Platform
platform (RegNo -> Imm
ImmInt RegNo
b)) [RegNo]
bs

        ppr_item Format
FF64 (CmmFloat Rational
r Width
_)
           = let bs :: [RegNo]
bs = Double -> [RegNo]
doubleToBytes (Rational -> Double
forall a. Fractional a => Rational -> a
fromRational Rational
r)
             in  (RegNo -> SDoc) -> [RegNo] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map (\RegNo
b -> String -> SDoc
text String
"\t.byte\t" SDoc -> SDoc -> SDoc
<> Platform -> Imm -> SDoc
pprImm Platform
platform (RegNo -> Imm
ImmInt RegNo
b)) [RegNo]
bs

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

floatToBytes :: Float -> [Int]
floatToBytes :: Float -> [RegNo]
floatToBytes Float
f
   = (forall s. ST s [RegNo]) -> [RegNo]
forall a. (forall s. ST s a) -> a
runST (do
        STUArray s RegNo Float
arr <- (RegNo, RegNo) -> ST s (STUArray s RegNo Float)
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
(i, i) -> m (a i e)
newArray_ ((RegNo
0::Int),RegNo
3)
        STUArray s RegNo Float -> RegNo -> Float -> ST s ()
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> i -> e -> m ()
writeArray STUArray s RegNo Float
arr RegNo
0 Float
f
        STUArray s RegNo Word8
arr <- STUArray s RegNo Float -> ST s (STUArray s RegNo Word8)
forall s. STUArray s RegNo Float -> ST s (STUArray s RegNo Word8)
castFloatToWord8Array STUArray s RegNo Float
arr
        Word8
i0 <- STUArray s RegNo Word8 -> RegNo -> ST s Word8
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> i -> m e
readArray STUArray s RegNo Word8
arr RegNo
0
        Word8
i1 <- STUArray s RegNo Word8 -> RegNo -> ST s Word8
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> i -> m e
readArray STUArray s RegNo Word8
arr RegNo
1
        Word8
i2 <- STUArray s RegNo Word8 -> RegNo -> ST s Word8
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> i -> m e
readArray STUArray s RegNo Word8
arr RegNo
2
        Word8
i3 <- STUArray s RegNo Word8 -> RegNo -> ST s Word8
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> i -> m e
readArray STUArray s RegNo Word8
arr RegNo
3
        [RegNo] -> ST s [RegNo]
forall (m :: * -> *) a. Monad m => a -> m a
return ((Word8 -> RegNo) -> [Word8] -> [RegNo]
forall a b. (a -> b) -> [a] -> [b]
map Word8 -> RegNo
forall a b. (Integral a, Num b) => a -> b
fromIntegral [Word8
i0,Word8
i1,Word8
i2,Word8
i3])
     )

castFloatToWord8Array :: STUArray s Int Float -> ST s (STUArray s Int Word8)
castFloatToWord8Array :: forall s. STUArray s RegNo Float -> ST s (STUArray s RegNo Word8)
castFloatToWord8Array = STUArray s RegNo Float -> ST s (STUArray s RegNo Word8)
forall s ix a b. STUArray s ix a -> ST s (STUArray s ix b)
U.castSTUArray

pprImm :: Platform -> Imm -> SDoc
pprImm :: Platform -> Imm -> SDoc
pprImm Platform
_ (ImmInt RegNo
i)     = RegNo -> SDoc
int RegNo
i
pprImm Platform
_ (ImmInteger Integer
i) = Integer -> SDoc
integer Integer
i
pprImm Platform
p (ImmCLbl CLabel
l)    = Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
p CLabel
l
pprImm Platform
p (ImmIndex CLabel
l RegNo
i) = Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
p CLabel
l SDoc -> SDoc -> SDoc
<> Char -> SDoc
char Char
'+' SDoc -> SDoc -> SDoc
<> RegNo -> SDoc
int RegNo
i
pprImm Platform
_ (ImmLit SDoc
s)     = SDoc
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 -> SDoc
text String
"wzr"
  | Bool
otherwise = Float -> SDoc
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 -> SDoc
text String
"xzr"
  | Bool
otherwise = Double -> SDoc
double (Rational -> Double
forall a. Fractional a => Rational -> a
fromRational Rational
d)

pprImm Platform
p (ImmConstantSum Imm
a Imm
b) = Platform -> Imm -> SDoc
pprImm Platform
p Imm
a SDoc -> SDoc -> SDoc
<> Char -> SDoc
char Char
'+' SDoc -> SDoc -> SDoc
<> Platform -> Imm -> SDoc
pprImm Platform
p Imm
b
pprImm Platform
p (ImmConstantDiff Imm
a Imm
b) = Platform -> Imm -> SDoc
pprImm Platform
p Imm
a SDoc -> SDoc -> SDoc
<> Char -> SDoc
char Char
'-'
                   SDoc -> SDoc -> SDoc
<> SDoc
lparen SDoc -> SDoc -> SDoc
<> Platform -> Imm -> SDoc
pprImm Platform
p Imm
b SDoc -> SDoc -> SDoc
<> SDoc
rparen


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

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

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

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

  -- TODO: This will only work for
  -- The floating point value must be expressable 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 odes.
  ImmFloat Rational
f | Rational
f Rational -> Rational -> Bool
forall a. Eq a => a -> a -> Bool
== Rational
0 -> String -> SDoc
text String
"wzr"
  ImmFloat Rational
f -> Char -> SDoc
char Char
'#' SDoc -> SDoc -> SDoc
<> Float -> SDoc
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 -> SDoc
text String
"xzr"
  ImmDouble Rational
d -> Char -> SDoc
char Char
'#' SDoc -> SDoc -> SDoc
<> Double -> SDoc
double (Rational -> Double
forall a. Fractional a => Rational -> a
fromRational Rational
d)
  -- =<lbl> pseudo instruction!
  ImmCLbl CLabel
l    -> Char -> SDoc
char Char
'=' SDoc -> SDoc -> SDoc
<> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform CLabel
l
  ImmIndex CLabel
l RegNo
o -> String -> SDoc
text String
"[=" SDoc -> SDoc -> SDoc
<> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform CLabel
l SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Char -> SDoc
char Char
'#' SDoc -> SDoc -> SDoc
<> RegNo -> SDoc
int RegNo
o SDoc -> SDoc -> SDoc
<> Char -> SDoc
char Char
']'
  Imm
_            -> String -> SDoc
forall a. String -> a
panic String
"AArch64.pprIm"

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

pprShift :: ShiftMode -> SDoc
pprShift :: ShiftMode -> SDoc
pprShift ShiftMode
SLSL = String -> SDoc
text String
"lsl"
pprShift ShiftMode
SLSR = String -> SDoc
text String
"lsr"
pprShift ShiftMode
SASR = String -> SDoc
text String
"asr"
pprShift ShiftMode
SROR = String -> SDoc
text String
"ror"

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

pprReg :: Width -> Reg -> SDoc
pprReg :: Width -> Reg -> SDoc
pprReg Width
w Reg
r = case Reg
r of
  RegReal    (RealRegSingle RegNo
i) -> Width -> RegNo -> SDoc
ppr_reg_no Width
w RegNo
i
  RegReal    (RealRegPair{})   -> String -> SDoc
forall a. String -> a
panic String
"AArch64.pprReg: no reg pairs on this arch!"
  -- virtual regs should not show up, but this is helpful for debugging.
  RegVirtual (VirtualRegI Unique
u)   -> String -> SDoc
text String
"%vI_" SDoc -> SDoc -> SDoc
<> Unique -> SDoc
pprUniqueAlways Unique
u
  RegVirtual (VirtualRegF Unique
u)   -> String -> SDoc
text String
"%vF_" SDoc -> SDoc -> SDoc
<> Unique -> SDoc
pprUniqueAlways Unique
u
  RegVirtual (VirtualRegD Unique
u)   -> String -> SDoc
text String
"%vD_" SDoc -> SDoc -> SDoc
<> Unique -> SDoc
pprUniqueAlways Unique
u
  Reg
_                            -> String -> SDoc -> SDoc
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"AArch64.pprReg" (String -> SDoc
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 -> SDoc
    ppr_reg_no :: Width -> RegNo -> SDoc
ppr_reg_no Width
w RegNo
31
         | Width
w Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
W64 = String -> SDoc
text String
"sp"
         | Width
w Width -> Width -> Bool
forall a. Eq a => a -> a -> Bool
== Width
W32 = String -> SDoc
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 -> SDoc
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 -> SDoc
text String
"xzr"
         | RegNo
i RegNo -> RegNo -> Bool
forall a. Ord a => a -> a -> Bool
< RegNo
0 = String -> SDoc -> SDoc
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
<+> RegNo -> SDoc
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 -> SDoc
text String
"w" SDoc -> SDoc -> SDoc
<> RegNo -> SDoc
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 -> SDoc
text String
"w" SDoc -> SDoc -> SDoc
<> RegNo -> SDoc
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 -> SDoc
text String
"w" SDoc -> SDoc -> SDoc
<> RegNo -> SDoc
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 -> SDoc
text String
"x" SDoc -> SDoc -> SDoc
<> RegNo -> SDoc
int RegNo
i
         | RegNo
i RegNo -> RegNo -> Bool
forall a. Ord a => a -> a -> Bool
<= RegNo
31 = String -> SDoc -> SDoc
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"Invalid Reg" (Width -> SDoc
forall a. Outputable a => a -> SDoc
ppr Width
w SDoc -> SDoc -> SDoc
<+> RegNo -> SDoc
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 -> SDoc
text String
"b" SDoc -> SDoc -> SDoc
<> RegNo -> SDoc
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 -> SDoc
text String
"h" SDoc -> SDoc -> SDoc
<> RegNo -> SDoc
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 -> SDoc
text String
"s" SDoc -> SDoc -> SDoc
<> RegNo -> SDoc
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 -> SDoc
text String
"d" SDoc -> SDoc -> SDoc
<> RegNo -> SDoc
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 -> SDoc
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 :: Platform -> Instr -> SDoc
pprInstr :: Platform -> Instr -> SDoc
pprInstr Platform
platform Instr
instr = case Instr
instr of
  -- Meta Instructions ---------------------------------------------------------
  COMMENT SDoc
s  -> SDoc -> SDoc
asmComment SDoc
s
  MULTILINE_COMMENT SDoc
s -> SDoc -> SDoc
asmMultilineComment SDoc
s
  ANN SDoc
d Instr
i -> Platform -> Instr -> SDoc
pprInstr Platform
platform Instr
i SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
asmDoubleslashComment SDoc
d
  LOCATION RegNo
file RegNo
line RegNo
col String
_name
    -> String -> SDoc
text String
"\t.loc" SDoc -> SDoc -> SDoc
<+> RegNo -> SDoc
forall a. Outputable a => a -> SDoc
ppr RegNo
file SDoc -> SDoc -> SDoc
<+> RegNo -> SDoc
forall a. Outputable a => a -> SDoc
ppr RegNo
line SDoc -> SDoc -> SDoc
<+> RegNo -> SDoc
forall a. Outputable a => a -> SDoc
ppr RegNo
col
  DELTA RegNo
d    -> SDoc -> SDoc
asmComment (SDoc -> SDoc) -> SDoc -> SDoc
forall a b. (a -> b) -> a -> b
$ String -> SDoc
text (String
"\tdelta = " String -> String -> String
forall a. [a] -> [a] -> [a]
++ RegNo -> String
forall a. Show a => a -> String
show RegNo
d)
  NEWBLOCK BlockId
_ -> String -> SDoc
forall a. String -> a
panic String
"PprInstr: NEWBLOCK"
  LDATA Section
_ RawCmmStatics
_  -> String -> SDoc
forall a. String -> a
panic String
"pprInstr: LDATA"

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

  Instr
PUSH_STACK_FRAME -> String -> SDoc
text String
"\tstp x29, x30, [sp, #-16]!"
                   SDoc -> SDoc -> SDoc
$$ String -> SDoc
text String
"\tmov x29, sp"

  Instr
POP_STACK_FRAME -> String -> SDoc
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 -> String -> SDoc
text String
"\tfadd"  SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3
    | Bool
otherwise -> String -> SDoc
text String
"\tadd"  SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3
  CMN  Operand
o1 Operand
o2    -> String -> SDoc
text String
"\tcmn"  SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2
  CMP  Operand
o1 Operand
o2
    | Operand -> Bool
isFloatOp Operand
o1 Bool -> Bool -> Bool
&& Operand -> Bool
isFloatOp Operand
o2 -> String -> SDoc
text String
"\tfcmp"  SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2
    | Bool
otherwise -> String -> SDoc
text String
"\tcmp" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2
  MSUB Operand
o1 Operand
o2 Operand
o3 Operand
o4 -> String -> SDoc
text String
"\tmsub" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform 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 -> String -> SDoc
text String
"\tfmul"  SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3
    | Bool
otherwise -> String -> SDoc
text String
"\tmul"  SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3
  NEG  Operand
o1 Operand
o2
    | Operand -> Bool
isFloatOp Operand
o1 Bool -> Bool -> Bool
&& Operand -> Bool
isFloatOp Operand
o2 -> String -> SDoc
text String
"\tfneg"  SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2
    | Bool
otherwise -> String -> SDoc
text String
"\tneg"  SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform 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
    -> String -> SDoc
text String
"\tfdiv" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3
  SDIV Operand
o1 Operand
o2 Operand
o3 -> String -> SDoc
text String
"\tsdiv" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform 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 -> String -> SDoc
text String
"\tfsub"  SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3
    | Bool
otherwise -> String -> SDoc
text String
"\tsub"  SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3
  UDIV Operand
o1 Operand
o2 Operand
o3 -> String -> SDoc
text String
"\tudiv" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3

  -- 2. Bit Manipulation Instructions ------------------------------------------
  SBFM Operand
o1 Operand
o2 Operand
o3 Operand
o4 -> String -> SDoc
text String
"\tsbfm" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o4
  UBFM Operand
o1 Operand
o2 Operand
o3 Operand
o4 -> String -> SDoc
text String
"\tubfm" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o4
  -- 3. Logical and Move Instructions ------------------------------------------
  AND Operand
o1 Operand
o2 Operand
o3  -> String -> SDoc
text String
"\tand" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3
  ANDS Operand
o1 Operand
o2 Operand
o3 -> String -> SDoc
text String
"\tands" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3
  ASR Operand
o1 Operand
o2 Operand
o3  -> String -> SDoc
text String
"\tasr" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3
  BIC Operand
o1 Operand
o2 Operand
o3  -> String -> SDoc
text String
"\tbic" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3
  BICS Operand
o1 Operand
o2 Operand
o3 -> String -> SDoc
text String
"\tbics" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3
  EON Operand
o1 Operand
o2 Operand
o3  -> String -> SDoc
text String
"\teon" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3
  EOR Operand
o1 Operand
o2 Operand
o3  -> String -> SDoc
text String
"\teor" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3
  LSL Operand
o1 Operand
o2 Operand
o3  -> String -> SDoc
text String
"\tlsl" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3
  LSR Operand
o1 Operand
o2 Operand
o3  -> String -> SDoc
text String
"\tlsr" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3
  MOV Operand
o1 Operand
o2
    | Operand -> Bool
isFloatOp Operand
o1 Bool -> Bool -> Bool
|| Operand -> Bool
isFloatOp Operand
o2 -> String -> SDoc
text String
"\tfmov" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2
    | Bool
otherwise -> String -> SDoc
text String
"\tmov" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2
  MOVK Operand
o1 Operand
o2    -> String -> SDoc
text String
"\tmovk" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2
  MVN Operand
o1 Operand
o2     -> String -> SDoc
text String
"\tmvn" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2
  ORN Operand
o1 Operand
o2 Operand
o3  -> String -> SDoc
text String
"\torn" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3
  ORR Operand
o1 Operand
o2 Operand
o3  -> String -> SDoc
text String
"\torr" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3
  ROR Operand
o1 Operand
o2 Operand
o3  -> String -> SDoc
text String
"\tror" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3
  TST Operand
o1 Operand
o2     -> String -> SDoc
text String
"\ttst" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2

  -- 4. Branch Instructions ----------------------------------------------------
  J Target
t            -> Platform -> Instr -> SDoc
pprInstr Platform
platform (Target -> Instr
B Target
t)
  B (TBlock BlockId
bid) -> String -> SDoc
text String
"\tb" SDoc -> SDoc -> SDoc
<+> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform (Unique -> CLabel
mkLocalBlockLabel (BlockId -> Unique
forall a. Uniquable a => a -> Unique
getUnique BlockId
bid))
  B (TLabel CLabel
lbl) -> String -> SDoc
text String
"\tb" SDoc -> SDoc -> SDoc
<+> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform CLabel
lbl
  B (TReg Reg
r)     -> String -> SDoc
text String
"\tbr" SDoc -> SDoc -> SDoc
<+> Width -> Reg -> SDoc
pprReg Width
W64 Reg
r

  BL (TBlock BlockId
bid) [Reg]
_ [Reg]
_ -> String -> SDoc
text String
"\tbl" SDoc -> SDoc -> SDoc
<+> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform (Unique -> CLabel
mkLocalBlockLabel (BlockId -> Unique
forall a. Uniquable a => a -> Unique
getUnique BlockId
bid))
  BL (TLabel CLabel
lbl) [Reg]
_ [Reg]
_ -> String -> SDoc
text String
"\tbl" SDoc -> SDoc -> SDoc
<+> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform CLabel
lbl
  BL (TReg Reg
r)     [Reg]
_ [Reg]
_ -> String -> SDoc
text String
"\tblr" SDoc -> SDoc -> SDoc
<+> Width -> Reg -> SDoc
pprReg Width
W64 Reg
r

  BCOND Cond
c (TBlock BlockId
bid) -> String -> SDoc
text String
"\t" SDoc -> SDoc -> SDoc
<> Cond -> SDoc
pprBcond Cond
c SDoc -> SDoc -> SDoc
<+> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform (Unique -> CLabel
mkLocalBlockLabel (BlockId -> Unique
forall a. Uniquable a => a -> Unique
getUnique BlockId
bid))
  BCOND Cond
c (TLabel CLabel
lbl) -> String -> SDoc
text String
"\t" SDoc -> SDoc -> SDoc
<> Cond -> SDoc
pprBcond Cond
c SDoc -> SDoc -> SDoc
<+> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform CLabel
lbl
  BCOND Cond
_ (TReg Reg
_)     -> String -> SDoc
forall a. String -> a
panic String
"AArch64.ppr: No conditional branching to registers!"

  -- 5. Atomic Instructions ----------------------------------------------------
  -- 6. Conditional Instructions -----------------------------------------------
  CSET Operand
o Cond
c  -> String -> SDoc
text String
"\tcset" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Cond -> SDoc
pprCond Cond
c

  CBZ Operand
o (TBlock BlockId
bid) -> String -> SDoc
text String
"\tcbz" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform (Unique -> CLabel
mkLocalBlockLabel (BlockId -> Unique
forall a. Uniquable a => a -> Unique
getUnique BlockId
bid))
  CBZ Operand
o (TLabel CLabel
lbl) -> String -> SDoc
text String
"\tcbz" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform CLabel
lbl
  CBZ Operand
_ (TReg Reg
_)     -> String -> SDoc
forall a. String -> a
panic String
"AArch64.ppr: No conditional (cbz) branching to registers!"

  CBNZ Operand
o (TBlock BlockId
bid) -> String -> SDoc
text String
"\tcbnz" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform (Unique -> CLabel
mkLocalBlockLabel (BlockId -> Unique
forall a. Uniquable a => a -> Unique
getUnique BlockId
bid))
  CBNZ Operand
o (TLabel CLabel
lbl) -> String -> SDoc
text String
"\tcbnz" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform CLabel
lbl
  CBNZ Operand
_ (TReg Reg
_)     -> String -> SDoc
forall a. 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 ->
    String -> SDoc
text String
"\tstrb" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform 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 ->
    String -> SDoc
text String
"\tstrh" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2
  STR Format
_f Operand
o1 Operand
o2 -> String -> SDoc
text String
"\tstr" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2

#if defined(darwin_HOST_OS)
  LDR _f o1 (OpImm (ImmIndex lbl' off)) | Just (_info, lbl) <- dynamicLinkerLabelInfo lbl' ->
    text "\tadrp" <+> pprOp platform o1 <> comma <+> pdoc platform lbl <> text "@gotpage" $$
    text "\tldr" <+> pprOp platform o1 <> comma <+> text "[" <> pprOp platform o1 <> comma <+> pdoc platform lbl <> text "@gotpageoff" <> text "]" $$
    text "\tadd" <+> pprOp platform o1 <> comma <+> pprOp platform o1 <> comma <+> char '#' <> int off -- TODO: check that off is in 12bits.

  LDR _f o1 (OpImm (ImmIndex lbl off)) | isForeignLabel lbl ->
    text "\tadrp" <+> pprOp platform o1 <> comma <+> pdoc platform lbl <> text "@gotpage" $$
    text "\tldr" <+> pprOp platform o1 <> comma <+> text "[" <> pprOp platform o1 <> comma <+> pdoc platform lbl <> text "@gotpageoff" <> text "]" $$
    text "\tadd" <+> pprOp platform o1 <> comma <+> pprOp platform o1 <> comma <+> char '#' <> int off -- TODO: check that off is in 12bits.

  LDR _f o1 (OpImm (ImmIndex lbl off)) ->
    text "\tadrp" <+> pprOp platform o1 <> comma <+> pdoc platform lbl <> text "@page" $$
    text "\tadd" <+> pprOp platform o1 <> comma <+> pprOp platform o1 <> comma <+> pdoc platform lbl <> text "@pageoff" $$
    text "\tadd" <+> pprOp platform o1 <> comma <+> pprOp platform o1 <> comma <+> char '#' <> int off -- TODO: check that off is in 12bits.

  LDR _f o1 (OpImm (ImmCLbl lbl')) | Just (_info, lbl) <- dynamicLinkerLabelInfo lbl' ->
    text "\tadrp" <+> pprOp platform o1 <> comma <+> pdoc platform lbl <> text "@gotpage" $$
    text "\tldr" <+> pprOp platform o1 <> comma <+> text "[" <> pprOp platform o1 <> comma <+> pdoc platform lbl <> text "@gotpageoff" <> text "]"

  LDR _f o1 (OpImm (ImmCLbl lbl)) | isForeignLabel lbl ->
    text "\tadrp" <+> pprOp platform o1 <> comma <+> pdoc platform lbl <> text "@gotpage" $$
    text "\tldr" <+> pprOp platform o1 <> comma <+> text "[" <> pprOp platform o1 <> comma <+> pdoc platform lbl <> text "@gotpageoff" <> text "]"

  LDR _f o1 (OpImm (ImmCLbl lbl)) ->
    text "\tadrp" <+> pprOp platform o1 <> comma <+> pdoc platform lbl <> text "@page" $$
    text "\tadd" <+> pprOp platform o1 <> comma <+> pprOp platform o1 <> comma <+> pdoc 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' ->
    String -> SDoc
text String
"\tadrp" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
":got:" SDoc -> SDoc -> SDoc
<> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform CLabel
lbl SDoc -> SDoc -> SDoc
$$
    String -> SDoc
text String
"\tldr" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"[" SDoc -> SDoc -> SDoc
<> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
":got_lo12:" SDoc -> SDoc -> SDoc
<> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform CLabel
lbl SDoc -> SDoc -> SDoc
<> String -> SDoc
text String
"]" SDoc -> SDoc -> SDoc
$$
    String -> SDoc
text String
"\tadd" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Char -> SDoc
char Char
'#' SDoc -> SDoc -> SDoc
<> RegNo -> SDoc
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 ->
    String -> SDoc
text String
"\tadrp" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
":got:" SDoc -> SDoc -> SDoc
<> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform CLabel
lbl SDoc -> SDoc -> SDoc
$$
    String -> SDoc
text String
"\tldr" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"[" SDoc -> SDoc -> SDoc
<> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
":got_lo12:" SDoc -> SDoc -> SDoc
<> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform CLabel
lbl SDoc -> SDoc -> SDoc
<> String -> SDoc
text String
"]" SDoc -> SDoc -> SDoc
$$
    String -> SDoc
text String
"\tadd" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Char -> SDoc
char Char
'#' SDoc -> SDoc -> SDoc
<> RegNo -> SDoc
int RegNo
off -- TODO: check that off is in 12bits.

  LDR Format
_f Operand
o1 (OpImm (ImmIndex CLabel
lbl RegNo
off)) ->
    String -> SDoc
text String
"\tadrp" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform CLabel
lbl SDoc -> SDoc -> SDoc
$$
    String -> SDoc
text String
"\tadd" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
":lo12:" SDoc -> SDoc -> SDoc
<> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform CLabel
lbl SDoc -> SDoc -> SDoc
$$
    String -> SDoc
text String
"\tadd" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Char -> SDoc
char Char
'#' SDoc -> SDoc -> SDoc
<> RegNo -> SDoc
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' ->
    String -> SDoc
text String
"\tadrp" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
":got:" SDoc -> SDoc -> SDoc
<> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform CLabel
lbl SDoc -> SDoc -> SDoc
$$
    String -> SDoc
text String
"\tldr" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"[" SDoc -> SDoc -> SDoc
<> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
":got_lo12:" SDoc -> SDoc -> SDoc
<> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform CLabel
lbl SDoc -> SDoc -> SDoc
<> String -> SDoc
text String
"]"

  LDR Format
_f Operand
o1 (OpImm (ImmCLbl CLabel
lbl)) | CLabel -> Bool
isForeignLabel CLabel
lbl ->
    String -> SDoc
text String
"\tadrp" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
":got:" SDoc -> SDoc -> SDoc
<> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform CLabel
lbl SDoc -> SDoc -> SDoc
$$
    String -> SDoc
text String
"\tldr" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
"[" SDoc -> SDoc -> SDoc
<> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
":got_lo12:" SDoc -> SDoc -> SDoc
<> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform CLabel
lbl SDoc -> SDoc -> SDoc
<> String -> SDoc
text String
"]"

  LDR Format
_f Operand
o1 (OpImm (ImmCLbl CLabel
lbl)) ->
    String -> SDoc
text String
"\tadrp" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc Platform
platform CLabel
lbl SDoc -> SDoc -> SDoc
$$
    String -> SDoc
text String
"\tadd" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> String -> SDoc
text String
":lo12:" SDoc -> SDoc -> SDoc
<> Platform -> CLabel -> SDoc
forall env a. OutputableP env a => env -> a -> SDoc
pdoc 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 ->
    String -> SDoc
text String
"\tldrsb" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform 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 ->
    String -> SDoc
text String
"\tldrsh" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2
  LDR Format
_f Operand
o1 Operand
o2 -> String -> SDoc
text String
"\tldr" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2

  STP Format
_f Operand
o1 Operand
o2 Operand
o3 -> String -> SDoc
text String
"\tstp" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3
  LDP Format
_f Operand
o1 Operand
o2 Operand
o3 -> String -> SDoc
text String
"\tldp" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o3

  -- 8. Synchronization Instructions -------------------------------------------
  Instr
DMBSY -> String -> SDoc
text String
"\tdmb sy"
  -- 9. Floating Point Instructions --------------------------------------------
  FCVT Operand
o1 Operand
o2 -> String -> SDoc
text String
"\tfcvt" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2
  SCVTF Operand
o1 Operand
o2 -> String -> SDoc
text String
"\tscvtf" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2
  FCVTZS Operand
o1 Operand
o2 -> String -> SDoc
text String
"\tfcvtzs" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2
  FABS Operand
o1 Operand
o2 -> String -> SDoc
text String
"\tfabs" SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o1 SDoc -> SDoc -> SDoc
<> SDoc
comma SDoc -> SDoc -> SDoc
<+> Platform -> Operand -> SDoc
pprOp Platform
platform Operand
o2

pprBcond :: Cond -> SDoc
pprBcond :: Cond -> SDoc
pprBcond Cond
c = String -> SDoc
text String
"b." SDoc -> SDoc -> SDoc
<> Cond -> SDoc
pprCond Cond
c

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

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

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

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

  -- Orderd variants.  Respecting NaN.
  Cond
OLT    -> String -> SDoc
text String
"mi"
  Cond
OLE    -> String -> SDoc
text String
"ls"
  Cond
OGE    -> String -> SDoc
text String
"ge"
  Cond
OGT    -> String -> SDoc
text String
"gt"

  -- Unordered
  Cond
UOLT   -> String -> SDoc
text String
"lt"
  Cond
UOLE   -> String -> SDoc
text String
"le"
  Cond
UOGE   -> String -> SDoc
text String
"pl"
  Cond
UOGT   -> String -> SDoc
text String
"hi"