    module GHC.CmmToAsm.Dwarf (
      dwarfGen
      ) where

    import GHC.Prelude

    import GHC.Cmm.CLabel
    import GHC.Cmm.Expr        ( GlobalReg(..) )
    import GHC.Settings.Config ( cProjectName, cProjectVersion )
    import GHC.Types.Tickish   ( CmmTickish, GenTickish(..) )
    import GHC.Cmm.DebugBlock
    import GHC.Unit.Module
    import GHC.Utils.Outputable
    import GHC.Platform
    import GHC.Types.Unique
    import GHC.Types.Unique.Supply

    import GHC.CmmToAsm.Dwarf.Constants
    import GHC.CmmToAsm.Dwarf.Types
    import GHC.CmmToAsm.Config

    import Control.Arrow    ( first )
    import Control.Monad    ( mfilter )
    import Data.Maybe
    import Data.List        ( sortBy )
    import Data.Ord         ( comparing )
    import qualified Data.Map as Map
    import System.FilePath
    import System.Directory ( getCurrentDirectory )

    import qualified GHC.Cmm.Dataflow.Label as H
    import qualified GHC.Cmm.Dataflow.Collections as H

    -- | Generate DWARF/debug information
    dwarfGen :: NCGConfig -> ModLocation -> UniqSupply -> [DebugBlock]
                -> IO (SDoc, UniqSupply)
    dwarfGen :: NCGConfig
    -> ModLocation
    -> UniqSupply
    -> [DebugBlock]
    -> IO (SDoc, UniqSupply)
    dwarfGen NCGConfig
    _      ModLocation
    _      UniqSupply
    us []     = forall (m :: * -> *) a. Monad m => a -> m a
    return (SDoc
    empty, UniqSupply
    us)
    dwarfGen NCGConfig
    config ModLocation
    modLoc UniqSupply
    us [DebugBlock]
    blocks = do
      let platform :: Platform
    platform = NCGConfig -> Platform
    ncgPlatform NCGConfig
    config

      -- Convert debug data structures to DWARF info records
      let procs :: [DebugBlock]
    procs = [DebugBlock] -> [DebugBlock]
    debugSplitProcs [DebugBlock]
    blocks
          stripBlocks :: DebugBlock -> DebugBlock
    stripBlocks DebugBlock
    dbg
            | NCGConfig -> Bool
    ncgDwarfStripBlockInfo NCGConfig
    config = DebugBlock
    dbg { dblBlocks :: [DebugBlock]
    dblBlocks = [] }
            | Bool
    otherwise                     = DebugBlock
    dbg
      FilePath
    compPath <- IO FilePath
    getCurrentDirectory
      let lowLabel :: CLabel
    lowLabel = DebugBlock -> CLabel
    dblCLabel forall a b. (a -> b) -> a -> b
    $ forall a. [a] -> a
    head [DebugBlock]
    procs
          highLabel :: CLabel
    highLabel = CLabel -> CLabel
    mkAsmTempProcEndLabel forall a b. (a -> b) -> a -> b
    $ DebugBlock -> CLabel
    dblCLabel forall a b. (a -> b) -> a -> b
    $ forall a. [a] -> a
    last [DebugBlock]
    procs
          dwarfUnit :: DwarfInfo
    dwarfUnit = DwarfCompileUnit
            { dwChildren :: [DwarfInfo]
    dwChildren = forall a b. (a -> b) -> [a] -> [b]
    map (NCGConfig -> DebugBlock -> DwarfInfo
    procToDwarf NCGConfig
    config) (forall a b. (a -> b) -> [a] -> [b]
    map DebugBlock -> DebugBlock
    stripBlocks [DebugBlock]
    procs)
            , dwName :: FilePath
    dwName = forall a. a -> Maybe a -> a
    fromMaybe FilePath
    "" (ModLocation -> Maybe FilePath
    ml_hs_file ModLocation
    modLoc)
            , dwCompDir :: FilePath
    dwCompDir = FilePath -> FilePath
    addTrailingPathSeparator FilePath
    compPath
            , dwProducer :: FilePath
    dwProducer = FilePath
    cProjectName forall a. [a] -> [a] -> [a]
    ++ FilePath
    " " forall a. [a] -> [a] -> [a]
    ++ FilePath
    cProjectVersion
            , dwLowLabel :: CLabel
    dwLowLabel = CLabel
    lowLabel
            , dwHighLabel :: CLabel
    dwHighLabel = CLabel
    highLabel
            , dwLineLabel :: PtrString
    dwLineLabel = PtrString
    dwarfLineLabel
            }

      -- Check whether we have any source code information, so we do not
      -- end up writing a pointer to an empty .debug_line section
      -- (dsymutil on Mac Os gets confused by this).
      let haveSrcIn :: DebugBlock -> Bool
    haveSrcIn DebugBlock
    blk = forall a. Maybe a -> Bool
    isJust (DebugBlock -> Maybe CmmTickish
    dblSourceTick DebugBlock
    blk) Bool -> Bool -> Bool
    && forall a. Maybe a -> Bool
    isJust (DebugBlock -> Maybe Int
    dblPosition DebugBlock
    blk)
                          Bool -> Bool -> Bool
    || forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any DebugBlock -> Bool
    haveSrcIn (DebugBlock -> [DebugBlock]
    dblBlocks DebugBlock
    blk)
          haveSrc :: Bool
    haveSrc = forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any DebugBlock -> Bool
    haveSrcIn [DebugBlock]
    procs

      -- .debug_abbrev section: Declare the format we're using
      let abbrevSct :: SDoc
    abbrevSct = Platform -> Bool -> SDoc
    pprAbbrevDecls Platform
    platform Bool
    haveSrc

      -- .debug_info section: Information records on procedures and blocks
      let -- unique to identify start and end compilation unit .debug_inf
          (Unique
    unitU, UniqSupply
    us') = UniqSupply -> (Unique, UniqSupply)
    takeUniqFromSupply UniqSupply
    us
          infoSct :: SDoc
    infoSct = [SDoc] -> SDoc
    vcat [ PtrString -> SDoc
    ptext PtrString
    dwarfInfoLabel SDoc -> SDoc -> SDoc
    <> SDoc
    colon
                         , Platform -> SDoc
    dwarfInfoSection Platform
    platform
                         , Platform -> Unique -> SDoc
    compileUnitHeader Platform
    platform Unique
    unitU
                         , Platform -> Bool -> DwarfInfo -> SDoc
    pprDwarfInfo Platform
    platform Bool
    haveSrc DwarfInfo
    dwarfUnit
                         , Platform -> Unique -> SDoc
    compileUnitFooter Platform
    platform Unique
    unitU
                         ]

      -- .debug_line section: Generated mainly by the assembler, but we
      -- need to label it
      let lineSct :: SDoc
    lineSct = Platform -> SDoc
    dwarfLineSection Platform
    platform SDoc -> SDoc -> SDoc
    $$
                    PtrString -> SDoc
    ptext PtrString
    dwarfLineLabel SDoc -> SDoc -> SDoc
    <> SDoc
    colon

      -- .debug_frame section: Information about the layout of the GHC stack
      let (Unique
    framesU, UniqSupply
    us'') = UniqSupply -> (Unique, UniqSupply)
    takeUniqFromSupply UniqSupply
    us'
          frameSct :: SDoc
    frameSct = Platform -> SDoc
    dwarfFrameSection Platform
    platform SDoc -> SDoc -> SDoc
    $$
                     PtrString -> SDoc
    ptext PtrString
    dwarfFrameLabel SDoc -> SDoc -> SDoc
    <> SDoc
    colon SDoc -> SDoc -> SDoc
    $$
                     Platform -> DwarfFrame -> SDoc
    pprDwarfFrame Platform
    platform (Unique -> [DebugBlock] -> DwarfFrame
    debugFrame Unique
    framesU [DebugBlock]
    procs)

      -- .aranges section: Information about the bounds of compilation units
      let aranges' :: [DwarfARange]
    aranges' | NCGConfig -> Bool
    ncgSplitSections NCGConfig
    config = forall a b. (a -> b) -> [a] -> [b]
    map DebugBlock -> DwarfARange
    mkDwarfARange [DebugBlock]
    procs
                   | Bool
    otherwise               = [CLabel -> CLabel -> DwarfARange
    DwarfARange CLabel
    lowLabel CLabel
    highLabel]
      let aranges :: SDoc
    aranges = Platform -> SDoc
    dwarfARangesSection Platform
    platform SDoc -> SDoc -> SDoc
    $$ Platform -> [DwarfARange] -> Unique -> SDoc
    pprDwarfARanges Platform
    platform [DwarfARange]
    aranges' Unique
    unitU

      forall (m :: * -> *) a. Monad m => a -> m a
    return (SDoc
    infoSct SDoc -> SDoc -> SDoc
    $$ SDoc
    abbrevSct SDoc -> SDoc -> SDoc
    $$ SDoc
    lineSct SDoc -> SDoc -> SDoc
    $$ SDoc
    frameSct SDoc -> SDoc -> SDoc
    $$ SDoc
    aranges, UniqSupply
    us'')

    -- | Build an address range entry for one proc.
    -- With split sections, each proc needs its own entry, since they may get
    -- scattered in the final binary. Without split sections, we could make a
    -- single arange based on the first/last proc.
    mkDwarfARange :: DebugBlock -> DwarfARange
    mkDwarfARange :: DebugBlock -> DwarfARange
    mkDwarfARange DebugBlock
    proc = CLabel -> CLabel -> DwarfARange
    DwarfARange CLabel
    lbl CLabel
    end
      where
        lbl :: CLabel
    lbl = DebugBlock -> CLabel
    dblCLabel DebugBlock
    proc
        end :: CLabel
    end = CLabel -> CLabel
    mkAsmTempProcEndLabel CLabel
    lbl

    -- | Header for a compilation unit, establishing global format
    -- parameters
    compileUnitHeader :: Platform -> Unique -> SDoc
    compileUnitHeader :: Platform -> Unique -> SDoc
    compileUnitHeader Platform
    platform Unique
    unitU =
      let cuLabel :: CLabel
    cuLabel = forall a. Uniquable a => a -> CLabel
    mkAsmTempLabel Unique
    unitU  -- sits right before initialLength field
          length :: SDoc
    length = forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform (CLabel -> CLabel
    mkAsmTempEndLabel CLabel
    cuLabel) SDoc -> SDoc -> SDoc
    <> Char -> SDoc
    char Char
    '-' SDoc -> SDoc -> SDoc
    <> forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform CLabel
    cuLabel
                   SDoc -> SDoc -> SDoc
    <> FilePath -> SDoc
    text FilePath
    "-4"       -- length of initialLength field
      in [SDoc] -> SDoc
    vcat [ forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform CLabel
    cuLabel SDoc -> SDoc -> SDoc
    <> SDoc
    colon
              , FilePath -> SDoc
    text FilePath
    "\t.long " SDoc -> SDoc -> SDoc
    <> SDoc
    length  -- compilation unit size
              , Word16 -> SDoc
    pprHalf Word16
    3                          -- DWARF version
              , Platform -> SDoc -> SDoc -> SDoc
    sectionOffset Platform
    platform (PtrString -> SDoc
    ptext PtrString
    dwarfAbbrevLabel) (PtrString -> SDoc
    ptext PtrString
    dwarfAbbrevLabel)
                                                   -- abbrevs offset
              , FilePath -> SDoc
    text FilePath
    "\t.byte " SDoc -> SDoc -> SDoc
    <> forall a. Outputable a => a -> SDoc
    ppr (Platform -> Int
    platformWordSizeInBytes Platform
    platform) -- word size
              ]

    -- | Compilation unit footer, mainly establishing size of debug sections
    compileUnitFooter :: Platform -> Unique -> SDoc
    compileUnitFooter :: Platform -> Unique -> SDoc
    compileUnitFooter Platform
    platform Unique
    unitU =
      let cuEndLabel :: CLabel
    cuEndLabel = CLabel -> CLabel
    mkAsmTempEndLabel forall a b. (a -> b) -> a -> b
    $ forall a. Uniquable a => a -> CLabel
    mkAsmTempLabel Unique
    unitU
      in forall env a. OutputableP env a => env -> a -> SDoc
    pdoc Platform
    platform CLabel
    cuEndLabel SDoc -> SDoc -> SDoc
    <> SDoc
    colon

    -- | Splits the blocks by procedures. In the result all nested blocks
    -- will come from the same procedure as the top-level block. See
    -- Note [Splitting DebugBlocks] for details.
    debugSplitProcs :: [DebugBlock] -> [DebugBlock]
    debugSplitProcs :: [DebugBlock] -> [DebugBlock]
    debugSplitProcs [DebugBlock]
    b = forall (t :: * -> *) a. Foldable t => t [a] -> [a]
    concat forall a b. (a -> b) -> a -> b
    $ forall (map :: * -> *) a. IsMap map => map a -> [a]
    H.mapElems forall a b. (a -> b) -> a -> b
    $ forall {a}. [LabelMap [a]] -> LabelMap [a]
    mergeMaps forall a b. (a -> b) -> a -> b
    $ forall a b. (a -> b) -> [a] -> [b]
    map (Maybe DebugBlock -> DebugBlock -> LabelMap [DebugBlock]
    split forall a. Maybe a
    Nothing) [DebugBlock]
    b
      where mergeMaps :: [LabelMap [a]] -> LabelMap [a]
    mergeMaps = forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr (forall (map :: * -> *) a.
    IsMap map =>
    (KeyOf map -> a -> a -> a) -> map a -> map a -> map a
    H.mapUnionWithKey (forall a b. a -> b -> a
    const forall a. [a] -> [a] -> [a]
    (++))) forall (map :: * -> *) a. IsMap map => map a
    H.mapEmpty
            split :: Maybe DebugBlock -> DebugBlock -> H.LabelMap [DebugBlock]
            split :: Maybe DebugBlock -> DebugBlock -> LabelMap [DebugBlock]
    split Maybe DebugBlock
    parent DebugBlock
    blk = forall (map :: * -> *) a.
    IsMap map =>
    KeyOf map -> a -> map a -> map a
    H.mapInsert Label
    prc [DebugBlock
    blk'] LabelMap [DebugBlock]
    nested
              where prc :: Label
    prc = DebugBlock -> Label
    dblProcedure DebugBlock
    blk
                    blk' :: DebugBlock
    blk' = DebugBlock
    blk { dblBlocks :: [DebugBlock]
    dblBlocks = [DebugBlock]
    own_blks
                               , dblParent :: Maybe DebugBlock
    dblParent = Maybe DebugBlock
    parent
                               }
                    own_blks :: [DebugBlock]
    own_blks = forall a. a -> Maybe a -> a
    fromMaybe [] forall a b. (a -> b) -> a -> b
    $ forall (map :: * -> *) a.
    IsMap map =>
    KeyOf map -> map a -> Maybe a
    H.mapLookup Label
    prc LabelMap [DebugBlock]
    nested
                    nested :: LabelMap [DebugBlock]
    nested = forall {a}. [LabelMap [a]] -> LabelMap [a]
    mergeMaps forall a b. (a -> b) -> a -> b
    $ forall a b. (a -> b) -> [a] -> [b]
    map (Maybe DebugBlock -> DebugBlock -> LabelMap [DebugBlock]
    split Maybe DebugBlock
    parent') forall a b. (a -> b) -> a -> b
    $ DebugBlock -> [DebugBlock]
    dblBlocks DebugBlock
    blk
                    -- Figure out who should be the parent of nested blocks.
                    -- If @blk@ is optimized out then it isn't a good choice
                    -- and we just use its parent.
                    parent' :: Maybe DebugBlock
    parent'
                      | Maybe Int
    Nothing <- DebugBlock -> Maybe Int
    dblPosition DebugBlock
    blk = Maybe DebugBlock
    parent
                      | Bool
    otherwise                  = forall a. a -> Maybe a
    Just DebugBlock
    blk

    {-
    Note [Splitting DebugBlocks]

    DWARF requires that we break up the nested DebugBlocks produced from
    the C-- AST. For instance, we begin with tick trees containing nested procs.
    For example,

        proc A [tick1, tick2]
          block B [tick3]
            proc C [tick4]

    when producing DWARF we need to procs (which are represented in DWARF as
    TAG_subprogram DIEs) to be top-level DIEs. debugSplitProcs is responsible for
    this transform, pulling out the nested procs into top-level procs.

    However, in doing this we need to be careful to preserve the parentage of the
    nested procs. This is the reason DebugBlocks carry the dblParent field, allowing
    us to reorganize the above tree as,

        proc A [tick1, tick2]
          block B [tick3]
        proc C [tick4] parent=B

    Here we have annotated the new proc C with an attribute giving its original
    parent, B.
    -}

    -- | Generate DWARF info for a procedure debug block
    procToDwarf :: NCGConfig -> DebugBlock -> DwarfInfo
    procToDwarf :: NCGConfig -> DebugBlock -> DwarfInfo
    procToDwarf NCGConfig
    config DebugBlock
    prc
      = DwarfSubprogram { dwChildren :: [DwarfInfo]
    dwChildren = forall a b. (a -> b) -> [a] -> [b]
    map (NCGConfig -> DebugBlock -> DwarfInfo
    blockToDwarf NCGConfig
    config) (DebugBlock -> [DebugBlock]
    dblBlocks DebugBlock
    prc)
                        , dwName :: FilePath
    dwName     = case DebugBlock -> Maybe CmmTickish
    dblSourceTick DebugBlock
    prc of
                             Just s :: CmmTickish
    s@SourceNote{} -> forall (pass :: TickishPass). GenTickish pass -> FilePath
    sourceName CmmTickish
    s
                             Maybe CmmTickish
    _otherwise -> forall a. Show a => a -> FilePath
    show (DebugBlock -> Label
    dblLabel DebugBlock
    prc)
                        , dwLabel :: CLabel
    dwLabel    = DebugBlock -> CLabel
    dblCLabel DebugBlock
    prc
                        , dwParent :: Maybe CLabel
    dwParent   = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap CLabel -> CLabel
    mkAsmTempDieLabel
                                       forall a b. (a -> b) -> a -> b
    $ forall (m :: * -> *) a. MonadPlus m => (a -> Bool) -> m a -> m a
    mfilter CLabel -> Bool
    goodParent
                                       forall a b. (a -> b) -> a -> b
    $ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap DebugBlock -> CLabel
    dblCLabel (DebugBlock -> Maybe DebugBlock
    dblParent DebugBlock
    prc)
                        }
      where
      goodParent :: CLabel -> Bool
    goodParent CLabel
    a | CLabel
    a forall a. Eq a => a -> a -> Bool
    == DebugBlock -> CLabel
    dblCLabel DebugBlock
    prc = Bool
    False
                   -- Omit parent if it would be self-referential
      goodParent CLabel
    a | Bool -> Bool
    not (CLabel -> Bool
    externallyVisibleCLabel CLabel
    a)
                   , NCGConfig -> Bool
    ncgDwarfStripBlockInfo NCGConfig
    config = Bool
    False
                   -- If we strip block information, don't refer to blocks.
                   -- Fixes #14894.
      goodParent CLabel
    _ = Bool
    True

    -- | Generate DWARF info for a block
    blockToDwarf :: NCGConfig -> DebugBlock -> DwarfInfo
    blockToDwarf :: NCGConfig -> DebugBlock -> DwarfInfo
    blockToDwarf NCGConfig
    config DebugBlock
    blk
      = DwarfBlock { dwChildren :: [DwarfInfo]
    dwChildren = forall a b. (a -> b) -> [a] -> [b]
    map (NCGConfig -> DebugBlock -> DwarfInfo
    blockToDwarf NCGConfig
    config) (DebugBlock -> [DebugBlock]
    dblBlocks DebugBlock
    blk) forall a. [a] -> [a] -> [a]
    ++ [DwarfInfo]
    srcNotes
                   , dwLabel :: CLabel
    dwLabel    = DebugBlock -> CLabel
    dblCLabel DebugBlock
    blk
                   , dwMarker :: Maybe CLabel
    dwMarker   = Maybe CLabel
    marker
                   }
      where
        srcNotes :: [DwarfInfo]
    srcNotes
          | NCGConfig -> Bool
    ncgDwarfSourceNotes NCGConfig
    config = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap CmmTickish -> [DwarfInfo]
    tickToDwarf (DebugBlock -> [CmmTickish]
    dblTicks DebugBlock
    blk)
          | Bool
    otherwise                  = []

        marker :: Maybe CLabel
    marker
          | Just Int
    _ <- DebugBlock -> Maybe Int
    dblPosition DebugBlock
    blk = forall a. a -> Maybe a
    Just forall a b. (a -> b) -> a -> b
    $ forall a. Uniquable a => a -> CLabel
    mkAsmTempLabel forall a b. (a -> b) -> a -> b
    $ DebugBlock -> Label
    dblLabel DebugBlock
    blk
          | Bool
    otherwise                 = forall a. Maybe a
    Nothing   -- block was optimized out

    tickToDwarf :: CmmTickish -> [DwarfInfo]
    tickToDwarf :: CmmTickish -> [DwarfInfo]
    tickToDwarf  (SourceNote RealSrcSpan
    ss FilePath
    _) = [RealSrcSpan -> DwarfInfo
    DwarfSrcNote RealSrcSpan
    ss]
    tickToDwarf CmmTickish
    _ = []

    -- | Generates the data for the debug frame section, which encodes the
    -- desired stack unwind behaviour for the debugger
    debugFrame :: Unique -> [DebugBlock] -> DwarfFrame
    debugFrame :: Unique -> [DebugBlock] -> DwarfFrame
    debugFrame Unique
    u [DebugBlock]
    procs
      = DwarfFrame { dwCieLabel :: CLabel
    dwCieLabel = forall a. Uniquable a => a -> CLabel
    mkAsmTempLabel Unique
    u
                   , dwCieInit :: UnwindTable
    dwCieInit  = UnwindTable
    initUws
                   , dwCieProcs :: [DwarfFrameProc]
    dwCieProcs = forall a b. (a -> b) -> [a] -> [b]
    map (UnwindTable -> DebugBlock -> DwarfFrameProc
    procToFrame UnwindTable
    initUws) [DebugBlock]
    procs
                   }
      where
        initUws :: UnwindTable
        initUws :: UnwindTable
    initUws = forall k a. Ord k => [(k, a)] -> Map k a
    Map.fromList [(GlobalReg
    Sp, forall a. a -> Maybe a
    Just (GlobalReg -> Int -> UnwindExpr
    UwReg GlobalReg
    Sp Int
    0))]

    -- | Generates unwind information for a procedure debug block
    procToFrame :: UnwindTable -> DebugBlock -> DwarfFrameProc
    procToFrame :: UnwindTable -> DebugBlock -> DwarfFrameProc
    procToFrame UnwindTable
    initUws DebugBlock
    blk
      = DwarfFrameProc { dwFdeProc :: CLabel
    dwFdeProc    = DebugBlock -> CLabel
    dblCLabel DebugBlock
    blk
                       , dwFdeHasInfo :: Bool
    dwFdeHasInfo = DebugBlock -> Bool
    dblHasInfoTbl DebugBlock
    blk
                       , dwFdeBlocks :: [DwarfFrameBlock]
    dwFdeBlocks  = forall a b. (a -> b) -> [a] -> [b]
    map (forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry DebugBlock -> [UnwindPoint] -> DwarfFrameBlock
    blockToFrame)
                                            ([(DebugBlock, [UnwindPoint])] -> [(DebugBlock, [UnwindPoint])]
    setHasInfo [(DebugBlock, [UnwindPoint])]
    blockUws)
                       }
      where blockUws :: [(DebugBlock, [UnwindPoint])]
            blockUws :: [(DebugBlock, [UnwindPoint])]
    blockUws = forall a b. (a -> b) -> [a] -> [b]
    map forall a b. (a, b) -> b
    snd forall a b. (a -> b) -> a -> b
    $ forall a. (a -> a -> Ordering) -> [a] -> [a]
    sortBy (forall a b. Ord a => (b -> a) -> b -> b -> Ordering
    comparing forall a b. (a, b) -> a
    fst) forall a b. (a -> b) -> a -> b
    $ DebugBlock -> [(Int, (DebugBlock, [UnwindPoint]))]
    flatten DebugBlock
    blk

            flatten :: DebugBlock
                    -> [(Int, (DebugBlock, [UnwindPoint]))]
            flatten :: DebugBlock -> [(Int, (DebugBlock, [UnwindPoint]))]
    flatten b :: DebugBlock
    b@DebugBlock{ dblPosition :: DebugBlock -> Maybe Int
    dblPosition=Maybe Int
    pos, dblUnwind :: DebugBlock -> [UnwindPoint]
    dblUnwind=[UnwindPoint]
    uws, dblBlocks :: DebugBlock -> [DebugBlock]
    dblBlocks=[DebugBlock]
    blocks }
              | Just Int
    p <- Maybe Int
    pos  = (Int
    p, (DebugBlock
    b, [UnwindPoint]
    uws'))forall a. a -> [a] -> [a]
    :[(Int, (DebugBlock, [UnwindPoint]))]
    nested
              | Bool
    otherwise      = [(Int, (DebugBlock, [UnwindPoint]))]
    nested -- block was optimized out
              where uws' :: [UnwindPoint]
    uws'   = UnwindTable -> [UnwindPoint] -> [UnwindPoint]
    addDefaultUnwindings UnwindTable
    initUws [UnwindPoint]
    uws
                    nested :: [(Int, (DebugBlock, [UnwindPoint]))]
    nested = forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap DebugBlock -> [(Int, (DebugBlock, [UnwindPoint]))]
    flatten [DebugBlock]
    blocks

            -- | If the current procedure has an info table, then we also say that
            -- its first block has one to ensure that it gets the necessary -1
            -- offset applied to its start address.
            -- See Note [Info Offset] in "GHC.CmmToAsm.Dwarf.Types".
            setHasInfo :: [(DebugBlock, [UnwindPoint])]
                       -> [(DebugBlock, [UnwindPoint])]
            setHasInfo :: [(DebugBlock, [UnwindPoint])] -> [(DebugBlock, [UnwindPoint])]
    setHasInfo [] = []
            setHasInfo ((DebugBlock, [UnwindPoint])
    c0:[(DebugBlock, [UnwindPoint])]
    cs) = forall (a :: * -> * -> *) b c d.
    Arrow a =>
    a b c -> a (b, d) (c, d)
    first DebugBlock -> DebugBlock
    setIt (DebugBlock, [UnwindPoint])
    c0 forall a. a -> [a] -> [a]
    : [(DebugBlock, [UnwindPoint])]
    cs
              where
                setIt :: DebugBlock -> DebugBlock
    setIt DebugBlock
    child =
                  DebugBlock
    child { dblHasInfoTbl :: Bool
    dblHasInfoTbl = DebugBlock -> Bool
    dblHasInfoTbl DebugBlock
    child
                                          Bool -> Bool -> Bool
    || DebugBlock -> Bool
    dblHasInfoTbl DebugBlock
    blk }

    blockToFrame :: DebugBlock -> [UnwindPoint] -> DwarfFrameBlock
    blockToFrame :: DebugBlock -> [UnwindPoint] -> DwarfFrameBlock
    blockToFrame DebugBlock
    blk [UnwindPoint]
    uws
      = DwarfFrameBlock { dwFdeBlkHasInfo :: Bool
    dwFdeBlkHasInfo = DebugBlock -> Bool
    dblHasInfoTbl DebugBlock
    blk
                        , dwFdeUnwind :: [UnwindPoint]
    dwFdeUnwind     = [UnwindPoint]
    uws
                        }

    addDefaultUnwindings :: UnwindTable -> [UnwindPoint] -> [UnwindPoint]
    addDefaultUnwindings :: UnwindTable -> [UnwindPoint] -> [UnwindPoint]
    addDefaultUnwindings UnwindTable
    tbl [UnwindPoint]
    pts =
        [ CLabel -> UnwindTable -> UnwindPoint
    UnwindPoint CLabel
    lbl (UnwindTable
    tbl' forall a. Monoid a => a -> a -> a
    `mappend` UnwindTable
    tbl)
          -- mappend is left-biased
        | UnwindPoint CLabel
    lbl UnwindTable
    tbl' <- [UnwindPoint]
    pts
        ]