--
module LlvmCodeGen.Ppr (
- pprLlvmHeader, pprLlvmCmmTop, pprLlvmData
+ pprLlvmHeader, pprLlvmCmmTop, pprLlvmData, infoSection, iTableSuf
) where
#include "HsVersions.h"
import LlvmCodeGen.Data
import CLabel
-import Cmm
+import OldCmm
import FastString
+import qualified Outputable
import Pretty
import Unique
-import Util
+
-- ----------------------------------------------------------------------------
-- * Top level
let tryConst (v, Just s ) = ppLlvmGlobal (v, Just s)
tryConst g@(_, Nothing) = ppLlvmGlobal g
- types' = ppLlvmTypes types
+ ppLlvmTys (LMAlias a) = ppLlvmAlias a
+ ppLlvmTys (LMFunction f) = ppLlvmFunctionDecl f
+ ppLlvmTys _other = empty
+
+ types' = vcat $ map ppLlvmTys types
globals' = vcat $ map tryConst globals
in types' $+$ globals'
pprLlvmCmmTop _ _ (CmmData _ lmdata)
= (vcat $ map pprLlvmData lmdata, [])
-pprLlvmCmmTop env count (CmmProc info lbl _ (ListGraph blks))
+pprLlvmCmmTop env count (CmmProc info lbl (ListGraph blks))
= let static = CmmDataLabel lbl : info
(idoc, ivar) = if not (null info)
- then pprCmmStatic env count static
+ then pprInfoTable env count lbl static
else (empty, [])
in (idoc $+$ (
let sec = mkLayoutSection (count + 1)
-- | Pretty print CmmStatic
-pprCmmStatic :: LlvmEnv -> Int -> [CmmStatic] -> (Doc, [LlvmVar])
-pprCmmStatic env count stat
+pprInfoTable :: LlvmEnv -> Int -> CLabel -> [CmmStatic] -> (Doc, [LlvmVar])
+pprInfoTable env count lbl stat
= let unres = genLlvmData (Text, stat)
(_, (ldata, ltypes)) = resolveLlvmData env unres
- setSection (gv@(LMGlobalVar s ty l _ _ c), d)
- = let v = if l == Internal then [gv] else []
- sec = mkLayoutSection count
- in ((LMGlobalVar s ty l sec llvmInfAlign c, d), v)
+ setSection ((LMGlobalVar _ ty l _ _ c), d)
+ = let sec = mkLayoutSection count
+ ilabel = strCLabel_llvm (entryLblToInfoLbl lbl)
+ `appendFS` fsLit iTableSuf
+ gv = LMGlobalVar ilabel ty l sec llvmInfAlign c
+ v = if l == Internal then [gv] else []
+ in ((gv, d), v)
setSection v = (v,[])
- (ldata', llvmUsed) = mapAndUnzip setSection ldata
- in (pprLlvmData (ldata', ltypes), concat llvmUsed)
+ (ldata', llvmUsed) = setSection (last ldata)
+ in if length ldata /= 1
+ then Outputable.panic "LlvmCodeGen.Ppr: invalid info table!"
+ else (pprLlvmData ([ldata'], ltypes), llvmUsed)
+
+-- | We generate labels for info tables by converting them to the same label
+-- as for the entry code but adding this string as a suffix.
+iTableSuf :: String
+iTableSuf = "_itable"
--- | Create an appropriate section declaration for subsection <n> of text
--- WARNING: This technique could fail as gas documentation says it only
--- supports up to 8192 subsections per section. Inspection of the source
--- code and some test programs seem to suggest it supports more than this
--- so we are hoping it does.
+
+-- | Create a specially crafted section declaration that encodes the order this
+-- section should be in the final object code.
+--
+-- The LlvmMangler.llvmFixupAsm pass over the assembly produced by LLVM uses
+-- this section declaration to do its processing.
mkLayoutSection :: Int -> LMSection
mkLayoutSection n
- = Just (fsLit $ ".text;.text " ++ show n ++ " #")
+ = Just (fsLit $ infoSection ++ show n)
+
+
+-- | The section we are putting info tables and their entry code into, should
+-- be unique since we process the assembly pattern matching this.
+infoSection :: String
+infoSection = "X98A__STRIP,__me"