[project @ 2001-05-22 13:43:14 by simonpj]
[ghc-hetmet.git] / ghc / compiler / nativeGen / AbsCStixGen.lhs
index 5a73c8f..e6c566a 100644 (file)
@@ -14,7 +14,7 @@ import Stix
 import MachMisc
 
 import AbsCUtils       ( getAmodeRep, mixedTypeLocn,
-                         nonemptyAbsC, mkAbsCStmts, mkAbsCStmtList
+                         nonemptyAbsC, mkAbsCStmts
                        )
 import PprAbsC          ( dumpRealC )
 import SMRep           ( fixedItblSize, 
@@ -23,20 +23,20 @@ import SMRep                ( fixedItblSize,
                        )
 import Constants       ( mIN_UPD_SIZE )
 import CLabel           ( CLabel, mkReturnInfoLabel, mkReturnPtLabel,
-                          mkClosureTblLabel, mkClosureLabel
-                         moduleRegdLabel )
+                          mkClosureTblLabel, mkClosureLabel,
+                         labelDynamic, mkSplitMarkerLabel )
 import ClosureInfo     ( infoTableLabelFromCI, entryLabelFromCI,
                          fastLabelFromCI, closureUpdReqd,
                          staticClosureNeedsLink
                        )
-import Literal         ( Literal(..) )
+import Literal         ( Literal(..), word2IntLit )
 import Maybes          ( maybeToBool )
 import PrimOp          ( primOpNeedsWrapper, PrimOp(..) )
 import PrimRep         ( isFloatingRep, PrimRep(..) )
 import StixInfo                ( genCodeInfoTable, genBitmapInfoTable )
 import StixMacro       ( macroCode, checkCode )
-import StixPrim                ( primCode, amodeToStix, amodeToStix' )
-import Outputable       ( pprPanic )
+import StixPrim                ( primCode, foreignCallCode, amodeToStix, amodeToStix' )
+import Outputable       ( pprPanic, ppr )
 import UniqSupply      ( returnUs, thenUs, mapUs, getUniqueUs, UniqSM )
 import Util            ( naturalMergeSortLe )
 import Panic           ( panic )
@@ -44,10 +44,7 @@ import TyCon         ( tyConDataCons )
 import DataCon         ( dataConWrapId )
 import BitSet          ( intBS )
 import Name             ( NamedThing(..) )
-
-#ifdef REALLY_HASKELL_1_3
-ord = fromEnum :: Char -> Int
-#endif
+import CmdLineOpts     ( opt_Static, opt_EnsureSplittableC )
 \end{code}
 
 For each independent chunk of AbstractC code, we generate a list of
@@ -56,11 +53,10 @@ We leave the chunks separated so that register allocation can be
 performed locally within the chunk.
 
 \begin{code}
-genCodeAbstractC :: AbstractC -> UniqSM [[StixTree]]
+genCodeAbstractC :: AbstractC -> UniqSM [StixTree]
 
 genCodeAbstractC absC
-  = mapUs gentopcode (mkAbsCStmtList absC) `thenUs` \ trees ->
-    returnUs ([StComment SLIT("Native Code")] : trees)
+  = gentopcode absC
  where
  a2stix      = amodeToStix
  a2stix'     = amodeToStix'
@@ -87,7 +83,14 @@ Here we handle top-level things, like @CCodeBlock@s and
 
  gentopcode stmt@(CStaticClosure lbl _ _ _)
   = genCodeStaticClosure stmt                  `thenUs` \ code ->
-    returnUs (StSegment DataSegment : StLabel lbl : code [])
+    returnUs (
+       if   opt_Static
+       then StSegment DataSegment 
+            : StLabel lbl : code []
+       else StSegment DataSegment 
+            : StData PtrRep [StInt 0] -- DLLised world, need extra zero word
+            : StLabel lbl : code []
+    )
 
  gentopcode stmt@(CRetVector lbl _ _ _)
   = genCodeVecTbl stmt                         `thenUs` \ code ->
@@ -135,8 +138,15 @@ Here we handle top-level things, like @CCodeBlock@s and
  gentopcode stmt@(CSRT lbl closures)
   = returnUs [ StSegment TextSegment 
             , StLabel lbl 
-            , StData DataPtrRep (map StCLbl closures)
+            , StData DataPtrRep (map mk_StCLbl_for_SRT closures)
             ]
+    where
+       mk_StCLbl_for_SRT :: CLabel -> StixTree
+       mk_StCLbl_for_SRT label
+          | labelDynamic label
+          = StIndex Int8Rep (StCLbl label) (StInt 1)
+          | otherwise
+          = StCLbl label
 
  gentopcode stmt@(CBitmap lbl mask)
   = returnUs [ StSegment TextSegment 
@@ -155,18 +165,21 @@ Here we handle top-level things, like @CCodeBlock@s and
  gentopcode stmt@(CModuleInitBlock lbl absC)
   = gencode absC                       `thenUs` \ code ->
     getUniqLabelNCG                    `thenUs` \ tmp_lbl ->
+    getUniqLabelNCG                    `thenUs` \ flag_lbl ->
     returnUs ( StSegment DataSegment
-            : StLabel moduleRegdLabel
+            : StLabel flag_lbl
             : StData IntRep [StInt 0]
             : StSegment TextSegment
             : StLabel lbl
-            : StCondJump tmp_lbl (StPrim IntNeOp [StCLbl moduleRegdLabel, 
-                                                  StInt 0])
-            : StAssign IntRep (StInd IntRep (StCLbl moduleRegdLabel)) (StInt 1)
+            : StCondJump tmp_lbl (StPrim IntNeOp       
+                                    [StInd IntRep (StCLbl flag_lbl),
+                                     StInt 0])
+            : StAssign IntRep (StInd IntRep (StCLbl flag_lbl)) (StInt 1)
             : code 
             [ StLabel tmp_lbl
-            , StAssign PtrRep stgSp (StPrim IntSubOp [stgSp, StInt 4])
-            , StJump (StInd WordRep stgSp)
+            , StAssign PtrRep stgSp
+                        (StIndex PtrRep stgSp (StInt (-1)))
+            , StJump NoDestInfo (StInd WordRep stgSp)
             ])
 
  gentopcode absC
@@ -201,18 +214,25 @@ Here we handle top-level things, like @CCodeBlock@s and
   = returnUs (\xs -> table ++ xs)
   where
     table = StData PtrRep [StCLbl (infoTableLabelFromCI cl_info)] : 
-           map (\amode -> StData (getAmodeRep amode) [a2stix amode]) amodes ++
+           map do_one_amode amodes ++
            [StData PtrRep (padding_wds ++ static_link)]
 
-    -- always at least one padding word: this is the static link field
-    -- for the garbage collector.
-    padding_wds = if closureUpdReqd cl_info then
-                       take (max 0 (mIN_UPD_SIZE - length amodes)) zeros
-                 else
-                       []
+    do_one_amode amode 
+       = StData (promote_to_word (getAmodeRep amode)) [a2stix amode]
+
+    -- We need to promote any item smaller than a word to a word
+    promote_to_word pk 
+       | sizeOf pk >= sizeOf IntRep  = pk
+       | otherwise                   = IntRep
 
-    static_link | staticClosureNeedsLink cl_info = [StInt 0]
-               | otherwise                      = []
+    upd_reqd = closureUpdReqd cl_info
+
+    padding_wds
+       | upd_reqd  = take (max 0 (mIN_UPD_SIZE - length amodes)) zeros
+       | otherwise = []
+
+    static_link | upd_reqd || staticClosureNeedsLink cl_info = [StInt 0]
+               | otherwise                                  = []
 
     zeros = StInt 0 : zeros
 
@@ -243,11 +263,14 @@ Now the individual AbstractC statements.
 
 \end{code}
 
-Split markers are a NOP in this land.
+Split markers just insert a __stg_split_marker, which is caught by the
+split-mangler later on and used to split the assembly into chunks.
 
 \begin{code}
 
- gencode CSplitMarker = returnUs id
+ gencode CSplitMarker
+   | opt_EnsureSplittableC = returnUs (\xs -> StLabel mkSplitMarkerLabel : xs)
+   | otherwise             = returnUs id
 
 \end{code}
 
@@ -322,22 +345,22 @@ which varies depending on whether we're profiling etc.
 \begin{code}
 
  gencode (CJump dest)
-  = returnUs (\xs -> StJump (a2stix dest) : xs)
+  = returnUs (\xs -> StJump NoDestInfo (a2stix dest) : xs)
 
  gencode (CFallThrough (CLbl lbl _))
   = returnUs (\xs -> StFallThrough lbl : xs)
 
  gencode (CReturn dest DirectReturn)
-  = returnUs (\xs -> StJump (a2stix dest) : xs)
+  = returnUs (\xs -> StJump NoDestInfo (a2stix dest) : xs)
 
  gencode (CReturn table (StaticVectoredReturn n))
-  = returnUs (\xs -> StJump dest : xs)
+  = returnUs (\xs -> StJump NoDestInfo dest : xs)
   where
     dest = StInd PtrRep (StIndex PtrRep (a2stix table)
                                  (StInt (toInteger (-n-fixedItblSize-1))))
 
  gencode (CReturn table (DynamicVectoredReturn am))
-  = returnUs (\xs -> StJump dest : xs)
+  = returnUs (\xs -> StJump NoDestInfo dest : xs)
   where
     dest = StInd PtrRep (StIndex PtrRep (a2stix table) dyn_off)
     dyn_off = StPrim IntSubOp [StPrim IntNegOp [a2stix am], 
@@ -348,12 +371,15 @@ which varies depending on whether we're profiling etc.
 Now the PrimOps, some of which may need caller-saves register wrappers.
 
 \begin{code}
+ gencode (COpStmt results (StgFCallOp fcall _) args vols)
+  = ASSERT( null vols )
+    foreignCallCode (nonVoid results) fcall (nonVoid args)
 
- gencode (COpStmt results op args vols)
+ gencode (COpStmt results (StgPrimOp op) args vols)
   -- ToDo (ADR?): use that liveness mask
   | primOpNeedsWrapper op
   = let
-       saves = volsaves vols
+       saves    = volsaves vols
        restores = volrestores vols
     in
        p2stix (nonVoid results) op (nonVoid args)
@@ -363,7 +389,6 @@ Now the PrimOps, some of which may need caller-saves register wrappers.
   | otherwise = p2stix (nonVoid results) op (nonVoid args)
     where
        nonVoid = filter ((/= VoidRep) . getAmodeRep)
-
 \end{code}
 
 Now the dreaded conditional jump.
@@ -448,15 +473,16 @@ be tuned.)
 \begin{code}
 
  intTag :: Literal -> Integer
- intTag (MachChar c)  = toInteger (ord c)
- intTag (MachInt i) = i
- intTag _ = panic "intTag"
+ intTag (MachChar c)  = toInteger c
+ intTag (MachInt i)   = i
+ intTag (MachWord w)  = intTag (word2IntLit (MachWord w))
+ intTag _             = panic "intTag"
 
  fltTag :: Literal -> Rational
 
- fltTag (MachFloat f) = f
+ fltTag (MachFloat f)  = f
  fltTag (MachDouble d) = d
- fltTag _ = panic "fltTag"
+ fltTag x              = pprPanic "fltTag" (ppr x)
 
  {-
  mkSimpleSwitches
@@ -479,12 +505,14 @@ be tuned.)
        highest = if floating then targetMaxDouble else targetMaxInt
     in
        (
-       if not floating && choices > 4 && highTag - lowTag < toInteger (2 * choices) then
+       if  not floating && choices > 4 
+            && highTag - lowTag < toInteger (2 * choices)
+        then
            mkJumpTable am' sortedAlts lowTag highTag udlbl
        else
            mkBinaryTree am' floating sortedAlts choices lowest highest udlbl
        )
-                                                       `thenUs` \ alt_code ->
+                                               `thenUs` \ alt_code ->
        gencode absC                            `thenUs` \ dflt_code ->
 
        returnUs (\xs -> alt_code (StLabel udlbl : dflt_code (StLabel ujlbl : xs)))
@@ -493,9 +521,10 @@ be tuned.)
        floating = isFloatingRep (getAmodeRep am)
        choices = length alts
 
-       (x@(MachChar _),_) `leAlt` (y,_) = intTag x <= intTag y
-       (x@(MachInt _), _) `leAlt` (y,_) = intTag x <= intTag y
-       (x,_)              `leAlt` (y,_) = fltTag x <= fltTag y
+       (x@(MachChar _),_)  `leAlt` (y,_) = intTag x <= intTag y
+       (x@(MachInt _), _)  `leAlt` (y,_) = intTag x <= intTag y
+       (x@(MachWord _), _) `leAlt` (y,_) = intTag x <= intTag y
+       (x,_)               `leAlt` (y,_) = fltTag x <= fltTag y
 
 \end{code}
 
@@ -527,8 +556,9 @@ already finish with a jump to the join point.
        cjmpHi = StCondJump dflt (StPrim IntGtOp [am, StInt (toInteger highTag)])
 
        offset = StPrim IntSubOp [am, StInt lowTag]
+        dsts   = DestInfo (dflt : map fst branches)
 
-       jump = StJump (StInd PtrRep (StIndex PtrRep (StCLbl utlbl) offset))
+       jump = StJump dsts (StInd PtrRep (StIndex PtrRep (StCLbl utlbl) offset))
        tlbl = StLabel utlbl
        table = StData PtrRep (mkTable branches [lowTag..highTag] [])
     in