Commit cc481ec8 authored by Peter Wortmann's avatar Peter Wortmann Committed by Austin Seipp

Generate DWARF info section

This is where we actually make GHC emit DWARF code. The info section
contains all the general meta information bits as well as an entry for
every block of native code.

Notes:

* We need quite a few new labels in order to properly address starts
  and ends of blocks.

* Thanks to Nathan Howell for taking the iniative to get our own Haskell
  language ID for DWARF!

(From Phabricator D396)
parent 64678e9e
......@@ -44,6 +44,8 @@ module CLabel (
mkStringLitLabel,
mkAsmTempLabel,
mkAsmTempDerivedLabel,
mkAsmTempEndLabel,
mkPlainModuleInitLabel,
......@@ -99,7 +101,7 @@ module CLabel (
mkHpcTicksLabel,
hasCAF,
needsCDecl, isAsmTemp, maybeAsmTemp, externallyVisibleCLabel,
needsCDecl, maybeAsmTemp, externallyVisibleCLabel,
isMathFun,
isCFunctionLabel, isGcPtrLabel, labelDynamic,
......@@ -123,6 +125,7 @@ import FastString
import DynFlags
import Platform
import UniqSet
import PprCore ( {- instances -} )
-- -----------------------------------------------------------------------------
-- The CLabel type
......@@ -190,6 +193,10 @@ data CLabel
| AsmTempLabel
{-# UNPACK #-} !Unique
| AsmTempDerivedLabel
CLabel
FastString -- suffix
| StringLitLabel
{-# UNPACK #-} !Unique
......@@ -547,6 +554,11 @@ mkStringLitLabel = StringLitLabel
mkAsmTempLabel :: Uniquable a => a -> CLabel
mkAsmTempLabel a = AsmTempLabel (getUnique a)
mkAsmTempDerivedLabel :: CLabel -> FastString -> CLabel
mkAsmTempDerivedLabel = AsmTempDerivedLabel
mkAsmTempEndLabel :: CLabel -> CLabel
mkAsmTempEndLabel l = mkAsmTempDerivedLabel l (fsLit "_end")
mkPlainModuleInitLabel :: Module -> CLabel
mkPlainModuleInitLabel mod = PlainModuleInitLabel mod
......@@ -634,6 +646,7 @@ needsCDecl (PlainModuleInitLabel _) = True
needsCDecl (StringLitLabel _) = False
needsCDecl (AsmTempLabel _) = False
needsCDecl (AsmTempDerivedLabel _ _) = False
needsCDecl (RtsLabel _) = False
needsCDecl (CmmLabel pkgId _ _)
......@@ -652,12 +665,6 @@ needsCDecl (DynamicLinkerLabel {}) = panic "needsCDecl DynamicLinkerLabel"
needsCDecl PicBaseLabel = panic "needsCDecl PicBaseLabel"
needsCDecl (DeadStripPreventer {}) = panic "needsCDecl DeadStripPreventer"
-- | Check whether a label is a local temporary for native code generation
isAsmTemp :: CLabel -> Bool
isAsmTemp (AsmTempLabel _) = True
isAsmTemp _ = False
-- | If a label is a local temporary used for native code generation
-- then return just its unique, otherwise nothing.
maybeAsmTemp :: CLabel -> Maybe Unique
......@@ -763,6 +770,7 @@ externallyVisibleCLabel :: CLabel -> Bool -- not C "static"
externallyVisibleCLabel (CaseLabel _ _) = False
externallyVisibleCLabel (StringLitLabel _) = False
externallyVisibleCLabel (AsmTempLabel _) = False
externallyVisibleCLabel (AsmTempDerivedLabel _ _)= False
externallyVisibleCLabel (PlainModuleInitLabel _)= True
externallyVisibleCLabel (RtsLabel _) = True
externallyVisibleCLabel (CmmLabel _ _ _) = True
......@@ -982,6 +990,13 @@ pprCLabel platform (AsmTempLabel u)
else
char '_' <> pprUnique u
pprCLabel platform (AsmTempDerivedLabel l suf)
| cGhcWithNativeCodeGen == "YES"
= ptext (asmTempLabelPrefix platform)
<> case l of AsmTempLabel u -> pprUnique u
_other -> pprCLabel platform l
<> ftext suf
pprCLabel platform (DynamicLinkerLabel info lbl)
| cGhcWithNativeCodeGen == "YES"
= pprDynamicLinkerAsmLabel platform info lbl
......@@ -1107,6 +1122,7 @@ pprCLbl (HpcTicksLabel mod)
= ptext (sLit "_hpc_tickboxes_") <> ppr mod <> ptext (sLit "_hpc")
pprCLbl (AsmTempLabel {}) = panic "pprCLbl AsmTempLabel"
pprCLbl (AsmTempDerivedLabel {})= panic "pprCLbl AsmTempDerivedLabel"
pprCLbl (DynamicLinkerLabel {}) = panic "pprCLbl DynamicLinkerLabel"
pprCLbl (PicBaseLabel {}) = panic "pprCLbl PicBaseLabel"
pprCLbl (DeadStripPreventer {}) = panic "pprCLbl DeadStripPreventer"
......
......@@ -558,6 +558,9 @@ Library
RegAlloc.Linear.X86_64.FreeRegs
RegAlloc.Linear.PPC.FreeRegs
RegAlloc.Linear.SPARC.FreeRegs
Dwarf
Dwarf.Types
Dwarf.Constants
if flag(ghci)
Exposed-Modules:
......
......@@ -47,6 +47,7 @@ import Instruction
import PIC
import Reg
import NCGMonad
import Dwarf
import Debug
import BlockId
......@@ -286,41 +287,46 @@ nativeCodeGen' dflags this_mod modLoc ncgImpl h us cmms
let ngs0 = NGS [] [] [] [] [] [] emptyUFM
(ngs, us') <- cmmNativeGenStream dflags this_mod modLoc ncgImpl bufh us
cmms ngs0
finishNativeGen dflags bufh ngs
return us'
finishNativeGen dflags modLoc bufh us' ngs
finishNativeGen :: Instruction instr
=> DynFlags
-> ModLocation
-> BufHandle
-> UniqSupply
-> NativeGenAcc statics instr
-> IO ()
finishNativeGen dflags bufh@(BufHandle _ _ h) ngs
-> IO UniqSupply
finishNativeGen dflags modLoc bufh@(BufHandle _ _ h) us ngs
= do
-- Write debug data and finish
let emitDw = gopt Opt_Debug dflags && not (gopt Opt_SplitObjs dflags)
us' <- if not emitDw then return us else do
(dwarf, us') <- dwarfGen dflags modLoc us (ngs_debug ngs)
emitNativeCode dflags bufh dwarf
return us'
bFlush bufh
let platform = targetPlatform dflags
-- dump global NCG stats for graph coloring allocator
let stats = concat (ngs_colorStats ngs)
when (not (null stats)) $ do
-- build the global register conflict graph
let graphGlobal
= foldl Color.union Color.initGraph
$ [ Color.raGraph stat
| stat@Color.RegAllocStatsStart{} <- stats]
-- build the global register conflict graph
let graphGlobal
= foldl Color.union Color.initGraph
$ [ Color.raGraph stat
| stat@Color.RegAllocStatsStart{} <- stats]
dump_stats (Color.pprStats stats graphGlobal)
dump_stats (Color.pprStats stats graphGlobal)
dumpIfSet_dyn dflags
Opt_D_dump_asm_conflicts "Register conflict graph"
$ Color.dotGraph
(targetRegDotColor platform)
(Color.trivColorable platform
(targetVirtualRegSqueeze platform)
(targetRealRegSqueeze platform))
$ graphGlobal
let platform = targetPlatform dflags
dumpIfSet_dyn dflags
Opt_D_dump_asm_conflicts "Register conflict graph"
$ Color.dotGraph
(targetRegDotColor platform)
(Color.trivColorable platform
(targetVirtualRegSqueeze platform)
(targetRealRegSqueeze platform))
$ graphGlobal
-- dump global NCG stats for linear allocator
......@@ -332,6 +338,7 @@ finishNativeGen dflags bufh@(BufHandle _ _ h) ngs
Pretty.printDoc Pretty.LeftMode (pprCols dflags) h
$ withPprStyleDoc dflags (mkCodeStyle AsmStyle)
$ makeImportsDoc dflags (concat (ngs_imports ngs))
return us'
where
dump_stats = dumpSDoc dflags alwaysQualify Opt_D_dump_asm_stats "NCG stats"
......@@ -377,15 +384,21 @@ cmmNativeGenStream dflags this_mod modLoc ncgImpl h us cmm_stream ngs
dumpIfSet_dyn dflags Opt_D_dump_debug "Debug Infos"
(vcat $ map ppr ldbgs)
-- Clear DWARF info when generating split object files
let ngs'' | debugFlag && splitFlag
= ngs' { ngs_debug = []
, ngs_dwarfFiles = emptyUFM
, ngs_labels = [] }
| otherwise
= ngs' { ngs_debug = ngs_debug ngs' ++ ldbgs
, ngs_labels = [] }
cmmNativeGenStream dflags this_mod modLoc ncgImpl h us'
-- Emit & clear DWARF information when generating split
-- object files, as we need it to land in the same object file
(ngs'', us'') <-
if debugFlag && splitFlag
then do (dwarf, us'') <- dwarfGen dflags modLoc us ldbgs
emitNativeCode dflags h dwarf
return (ngs' { ngs_debug = []
, ngs_dwarfFiles = emptyUFM
, ngs_labels = [] },
us'')
else return (ngs' { ngs_debug = ngs_debug ngs' ++ ldbgs
, ngs_labels = [] },
us')
cmmNativeGenStream dflags this_mod modLoc ncgImpl h us''
cmm_stream' ngs''
-- | Do native code generation on all these cmms.
......
module Dwarf (
dwarfGen
) where
import CLabel
import Config ( cProjectName, cProjectVersion )
import CoreSyn ( Tickish(..) )
import Debug
import DynFlags
import FastString
import Module
import Outputable
import Platform
import Unique
import UniqSupply
import Dwarf.Constants
import Dwarf.Types
import Data.Maybe
import System.FilePath
import System.Directory ( getCurrentDirectory )
import qualified Compiler.Hoopl as H
-- | Generate DWARF/debug information
dwarfGen :: DynFlags -> ModLocation -> UniqSupply -> [DebugBlock]
-> IO (SDoc, UniqSupply)
dwarfGen df modLoc us blocks = do
-- Convert debug data structures to DWARF info records
let procs = debugSplitProcs blocks
compPath <- getCurrentDirectory
let dwarfUnit = DwarfCompileUnit
{ dwChildren = map (procToDwarf df) procs
, dwName = fromMaybe "" (ml_hs_file modLoc)
, dwCompDir = addTrailingPathSeparator compPath
, dwProducer = cProjectName ++ " " ++ cProjectVersion
, dwLineLabel = 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 blk = isJust (dblSourceTick blk) && isJust (dblPosition blk)
|| any haveSrcIn (dblBlocks blk)
haveSrc = any haveSrcIn procs
-- .debug_abbrev section: Declare the format we're using
let abbrevSct = pprAbbrevDecls haveSrc
-- .debug_info section: Information records on procedures and blocks
let (unitU, us') = takeUniqFromSupply us
infoSct = vcat [ dwarfInfoSection
, compileUnitHeader unitU
, pprDwarfInfo haveSrc dwarfUnit
, compileUnitFooter unitU
]
-- .debug_line section: Generated mainly by the assembler, but we
-- need to label it
let lineSct = dwarfLineSection $$
ptext dwarfLineLabel <> colon
return (infoSct $$ abbrevSct $$ lineSct, us')
-- | Header for a compilation unit, establishing global format
-- parameters
compileUnitHeader :: Unique -> SDoc
compileUnitHeader unitU = sdocWithPlatform $ \plat ->
let cuLabel = mkAsmTempLabel unitU
length = ppr (mkAsmTempEndLabel cuLabel) <> char '-' <> ppr cuLabel
in vcat [ ptext (sLit "\t.long ") <> length -- compilation unit size
, ppr cuLabel <> colon
, ptext (sLit "\t.word 3") -- DWARF version
, pprDwWord (ptext dwarfAbbrevLabel <> char '-' <>
ptext dwarfAbbrevLabel) -- pointer to our abbrevs
, ptext (sLit "\t.byte ") <> ppr (platformWordSize plat) -- word size
]
-- | Compilation unit footer, mainly establishing size of debug sections
compileUnitFooter :: Unique -> SDoc
compileUnitFooter unitU =
let cuEndLabel = mkAsmTempEndLabel $ mkAsmTempLabel unitU
in ppr cuEndLabel <> colon
-- | Splits the blocks by procedures. In the result all nested blocks
-- will come from the same procedure as the top-level block.
debugSplitProcs :: [DebugBlock] -> [DebugBlock]
debugSplitProcs b = concat $ H.mapElems $ mergeMaps $ map split b
where mergeMaps = foldr (H.mapUnionWithKey (const (++))) H.mapEmpty
split :: DebugBlock -> H.LabelMap [DebugBlock]
split blk = H.mapInsert prc [blk {dblBlocks = own_blks}] nested
where prc = dblProcedure blk
own_blks = fromMaybe [] $ H.mapLookup prc nested
nested = mergeMaps $ map split $ dblBlocks blk
-- Note that we are rebuilding the tree here, so tick scopes
-- might change. We could fix that - but we actually only care
-- about dblSourceTick in the result, so this is okay.
-- | Generate DWARF info for a procedure debug block
procToDwarf :: DynFlags -> DebugBlock -> DwarfInfo
procToDwarf df prc
= DwarfSubprogram { dwChildren = foldr blockToDwarf [] $ dblBlocks prc
, dwName = case dblSourceTick prc of
Just s@SourceNote{} -> sourceName s
_otherwise -> showSDocDump df $ ppr $ dblLabel prc
, dwLabel = dblCLabel prc
}
-- | Generate DWARF info for a block
blockToDwarf :: DebugBlock -> [DwarfInfo] -> [DwarfInfo]
blockToDwarf blk dws
| isJust (dblPosition blk) = dw : dws
| otherwise = nested ++ dws -- block was optimized out, flatten
where nested = foldr blockToDwarf [] $ dblBlocks blk
dw = DwarfBlock { dwChildren = nested
, dwLabel = dblCLabel blk
, dwMarker = mkAsmTempLabel (dblLabel blk)
}
-- | Constants describing the DWARF format. Most of this simply
-- mirrors /usr/include/dwarf.h.
module Dwarf.Constants where
import FastString
import Platform
import Outputable
import Data.Word
-- | Language ID used for Haskell.
dW_LANG_Haskell :: Word
dW_LANG_Haskell = 0x18
-- Thanks to Nathan Howell for getting us our very own language ID!
-- | Dwarf tags
dW_TAG_compile_unit, dW_TAG_subroutine_type,
dW_TAG_file_type, dW_TAG_subprogram, dW_TAG_lexical_block,
dW_TAG_base_type, dW_TAG_structure_type, dW_TAG_pointer_type,
dW_TAG_array_type, dW_TAG_subrange_type, dW_TAG_typedef,
dW_TAG_variable, dW_TAG_arg_variable, dW_TAG_auto_variable :: Word
dW_TAG_array_type = 1
dW_TAG_lexical_block = 11
dW_TAG_pointer_type = 15
dW_TAG_compile_unit = 17
dW_TAG_structure_type = 19
dW_TAG_typedef = 22
dW_TAG_subroutine_type = 32
dW_TAG_subrange_type = 33
dW_TAG_base_type = 36
dW_TAG_file_type = 41
dW_TAG_subprogram = 46
dW_TAG_variable = 52
dW_TAG_auto_variable = 256
dW_TAG_arg_variable = 257
-- | Dwarf attributes
dW_AT_name, dW_AT_stmt_list, dW_AT_low_pc, dW_AT_high_pc, dW_AT_language,
dW_AT_comp_dir, dW_AT_producer, dW_AT_external, dW_AT_frame_base,
dW_AT_MIPS_linkage_name :: Word
dW_AT_name = 0x03
dW_AT_stmt_list = 0x10
dW_AT_low_pc = 0x11
dW_AT_high_pc = 0x12
dW_AT_language = 0x13
dW_AT_comp_dir = 0x1b
dW_AT_producer = 0x25
dW_AT_external = 0x3f
dW_AT_frame_base = 0x40
dW_AT_MIPS_linkage_name = 0x2007
-- | Abbrev declaration
dW_CHILDREN_no, dW_CHILDREN_yes :: Word8
dW_CHILDREN_no = 0
dW_CHILDREN_yes = 1
dW_FORM_addr, dW_FORM_data4, dW_FORM_string, dW_FORM_flag,
dW_FORM_block1, dW_FORM_ref4 :: Word
dW_FORM_addr = 0x01
dW_FORM_data4 = 0x06
dW_FORM_string = 0x08
dW_FORM_flag = 0x0c
dW_FORM_block1 = 0x0a
dW_FORM_ref4 = 0x13
-- | Dwarf native types
dW_ATE_address, dW_ATE_boolean, dW_ATE_float, dW_ATE_signed,
dW_ATE_signed_char, dW_ATE_unsigned, dW_ATE_unsigned_char :: Word
dW_ATE_address = 1
dW_ATE_boolean = 2
dW_ATE_float = 4
dW_ATE_signed = 5
dW_ATE_signed_char = 6
dW_ATE_unsigned = 7
dW_ATE_unsigned_char = 8
-- | Call frame information
dW_CFA_set_loc, dW_CFA_undefined, dW_CFA_same_value,
dW_CFA_def_cfa, dW_CFA_def_cfa_offset, dW_CFA_def_cfa_expression,
dW_CFA_expression, dW_CFA_offset_extended_sf, dW_CFA_def_cfa_offset_sf,
dW_CFA_def_cfa_sf, dW_CFA_val_offset, dW_CFA_val_expression,
dW_CFA_offset :: Word8
dW_CFA_set_loc = 0x01
dW_CFA_undefined = 0x07
dW_CFA_same_value = 0x08
dW_CFA_def_cfa = 0x0c
dW_CFA_def_cfa_offset = 0x0e
dW_CFA_def_cfa_expression = 0x0f
dW_CFA_expression = 0x10
dW_CFA_offset_extended_sf = 0x11
dW_CFA_def_cfa_sf = 0x12
dW_CFA_def_cfa_offset_sf = 0x13
dW_CFA_val_offset = 0x14
dW_CFA_val_expression = 0x16
dW_CFA_offset = 0x80
-- | Operations
dW_OP_deref, dW_OP_consts,
dW_OP_minus, dW_OP_mul, dW_OP_plus,
dW_OP_lit0, dW_OP_breg0, dW_OP_call_frame_cfa :: Word8
dW_OP_deref = 0x06
dW_OP_consts = 0x11
dW_OP_minus = 0x1c
dW_OP_mul = 0x1e
dW_OP_plus = 0x22
dW_OP_lit0 = 0x30
dW_OP_breg0 = 0x70
dW_OP_call_frame_cfa = 0x9c
-- | Dwarf section declarations
dwarfInfoSection, dwarfAbbrevSection, dwarfLineSection,
dwarfFrameSection, dwarfGhcSection :: SDoc
dwarfInfoSection = dwarfSection "info"
dwarfAbbrevSection = dwarfSection "abbrev"
dwarfLineSection = dwarfSection "line"
dwarfFrameSection = dwarfSection "frame"
dwarfGhcSection = dwarfSection "ghc"
dwarfSection :: String -> SDoc
dwarfSection name = sdocWithPlatform $ \plat ->
case platformOS plat of
OSDarwin -> ftext $ mkFastString $
".section __DWARF,__debug_" ++ name ++ ",regular,debug"
_other -> ftext $ mkFastString $
".section .debug_" ++ name ++ ",\"\",@progbits"
-- | Dwarf section labels
dwarfInfoLabel, dwarfAbbrevLabel, dwarfLineLabel :: LitString
dwarfInfoLabel = sLit ".Lsection_info"
dwarfAbbrevLabel = sLit ".Lsection_abbrev"
dwarfLineLabel = sLit ".Lsection_line"
module Dwarf.Types
( DwarfInfo(..)
, pprDwarfInfo
, pprAbbrevDecls
, pprByte
, pprWord
, pprDwWord
, pprLEBWord
, pprLEBInt
)
where
import CLabel
import FastString
import Outputable
import Platform
import Dwarf.Constants
import Data.Bits
import Data.Word
import Data.Char
-- | Individual dwarf records. Each one will be encoded as an entry in
-- the .debug_info section.
data DwarfInfo
= DwarfCompileUnit { dwChildren :: [DwarfInfo]
, dwName :: String
, dwProducer :: String
, dwCompDir :: String
, dwLineLabel :: LitString }
| DwarfSubprogram { dwChildren :: [DwarfInfo]
, dwName :: String
, dwLabel :: CLabel }
| DwarfBlock { dwChildren :: [DwarfInfo]
, dwLabel :: CLabel
, dwMarker :: CLabel }
-- | Abbreviation codes used for encoding above records in the
-- .debug_info section.
data DwarfAbbrev
= DwAbbrNull -- ^ Pseudo, used for marking the end of lists
| DwAbbrCompileUnit
| DwAbbrSubprogram
| DwAbbrBlock
deriving (Eq, Enum)
-- | Generate assembly for the given abbreviation code
pprAbbrev :: DwarfAbbrev -> SDoc
pprAbbrev = pprLEBWord . fromIntegral . fromEnum
-- | Abbreviation declaration. This explains the binary encoding we
-- use for representing @DwarfInfo@.
pprAbbrevDecls :: Bool -> SDoc
pprAbbrevDecls haveDebugLine =
let mkAbbrev abbr tag chld flds =
let fld (tag, form) = pprLEBWord tag $$ pprLEBWord form
in pprAbbrev abbr $$ pprLEBWord tag $$ pprByte chld $$
vcat (map fld flds) $$ pprByte 0 $$ pprByte 0
in dwarfAbbrevSection $$
ptext dwarfAbbrevLabel <> colon $$
mkAbbrev DwAbbrCompileUnit dW_TAG_compile_unit dW_CHILDREN_yes
([ (dW_AT_name, dW_FORM_string)
, (dW_AT_producer, dW_FORM_string)
, (dW_AT_language, dW_FORM_data4)
, (dW_AT_comp_dir, dW_FORM_string)
] ++
(if haveDebugLine
then [ (dW_AT_stmt_list, dW_FORM_data4) ]
else [])) $$
mkAbbrev DwAbbrSubprogram dW_TAG_subprogram dW_CHILDREN_yes
[ (dW_AT_name, dW_FORM_string)
, (dW_AT_MIPS_linkage_name, dW_FORM_string)
, (dW_AT_external, dW_FORM_flag)
, (dW_AT_low_pc, dW_FORM_addr)
, (dW_AT_high_pc, dW_FORM_addr)
] $$
mkAbbrev DwAbbrBlock dW_TAG_lexical_block dW_CHILDREN_yes
[ (dW_AT_name, dW_FORM_string)
, (dW_AT_low_pc, dW_FORM_addr)
, (dW_AT_high_pc, dW_FORM_addr)
]
-- | Generate assembly for DWARF data
pprDwarfInfo :: Bool -> DwarfInfo -> SDoc
pprDwarfInfo haveSrc d
= pprDwarfInfoOpen haveSrc d $$
vcat (map (pprDwarfInfo haveSrc) (dwChildren d)) $$
pprDwarfInfoClose
-- | Prints assembler data corresponding to DWARF info records. Note
-- that the binary format of this is paramterized in @abbrevDecls@ and
-- has to be kept in synch.
pprDwarfInfoOpen :: Bool -> DwarfInfo -> SDoc
pprDwarfInfoOpen haveSrc (DwarfCompileUnit _ name producer compDir lineLbl) =
pprAbbrev DwAbbrCompileUnit
$$ pprString name
$$ pprString producer
$$ pprData4 dW_LANG_Haskell
$$ pprString compDir
$$ if haveSrc
then pprData4' (ptext lineLbl <> char '-' <> ptext dwarfLineLabel)
else empty
pprDwarfInfoOpen _ (DwarfSubprogram _ name label) = sdocWithDynFlags $ \df ->
pprAbbrev DwAbbrSubprogram
$$ pprString name
$$ pprString (renderWithStyle df (ppr label) (mkCodeStyle CStyle))
$$ pprFlag (externallyVisibleCLabel label)
$$ pprWord (ppr label)
$$ pprWord (ppr $ mkAsmTempEndLabel label)
pprDwarfInfoOpen _ (DwarfBlock _ label marker) = sdocWithDynFlags $ \df ->
pprAbbrev DwAbbrBlock
$$ pprString (renderWithStyle df (ppr label) (mkCodeStyle CStyle))
$$ pprWord (ppr marker)
$$ pprWord (ppr $ mkAsmTempEndLabel marker)
-- | Close a DWARF info record with children
pprDwarfInfoClose :: SDoc
pprDwarfInfoClose = pprAbbrev DwAbbrNull
-- | Assembly for a single byte of constant DWARF data
pprByte :: Word8 -> SDoc
pprByte x = ptext (sLit "\t.byte ") <> ppr (fromIntegral x :: Word)
-- | Assembly for a constant DWARF flag
pprFlag :: Bool -> SDoc
pprFlag f = pprByte (if f then 0xff else 0x00)
-- | Assembly for 4 bytes of dynamic DWARF data
pprData4' :: SDoc -> SDoc
pprData4' x = ptext (sLit "\t.long ") <> x
-- | Assembly for 4 bytes of constant DWARF data
pprData4 :: Word -> SDoc
pprData4 = pprData4' . ppr
-- | Assembly for a DWARF word of dynamic data. This means 32 bit, as
-- we are generating 32 bit DWARF.
pprDwWord :: SDoc -> SDoc
pprDwWord = pprData4'
-- | Assembly for a machine word of dynamic data. Depends on the