Support I64->I32 casts in the NCG, and use them for I64->Integer conversions
[ghc-hetmet.git] / compiler / nativeGen / MachCodeGen.hs
index 90ce6b5..9dbe316 100644 (file)
@@ -42,13 +42,13 @@ import Constants    ( wORD_SIZE )
 
 #ifdef DEBUG
 import Outputable      ( assertPanic )
-import TRACE           ( trace )
+import Debug.Trace     ( trace )
 #endif
 
 import Control.Monad   ( mapAndUnzipM )
-import Maybe           ( fromJust )
-import DATA_BITS
-import DATA_WORD
+import Data.Maybe      ( fromJust )
+import Data.Bits
+import Data.Word
 
 -- -----------------------------------------------------------------------------
 -- Top-level of the instruction selector
@@ -497,6 +497,31 @@ getRegister (CmmReg reg)
 getRegister tree@(CmmRegOff _ _) 
   = getRegister (mangleIndexTree tree)
 
+
+#if WORD_SIZE_IN_BITS==32
+    -- for 32-bit architectuers, support some 64 -> 32 bit conversions:
+    -- TO_W_(x), TO_W_(x >> 32)
+
+getRegister (CmmMachOp (MO_U_Conv I64 I32)
+             [CmmMachOp (MO_U_Shr I64) [x,CmmLit (CmmInt 32 _)]]) = do
+  ChildCode64 code rlo <- iselExpr64 x
+  return $ Fixed I32 (getHiVRegFromLo rlo) code
+
+getRegister (CmmMachOp (MO_S_Conv I64 I32)
+             [CmmMachOp (MO_U_Shr I64) [x,CmmLit (CmmInt 32 _)]]) = do
+  ChildCode64 code rlo <- iselExpr64 x
+  return $ Fixed I32 (getHiVRegFromLo rlo) code
+
+getRegister (CmmMachOp (MO_U_Conv I64 I32) [x]) = do
+  ChildCode64 code rlo <- iselExpr64 x
+  return $ Fixed I32 rlo code
+
+getRegister (CmmMachOp (MO_S_Conv I64 I32) [x]) = do
+  ChildCode64 code rlo <- iselExpr64 x
+  return $ Fixed I32 rlo code       
+
+#endif
+
 -- end of machine-"independent" bit; here we go on the rest...
 
 #if alpha_TARGET_ARCH
@@ -898,21 +923,19 @@ getRegister (CmmMachOp mop [x]) -- unary MachOps
       MO_Not rep   -> trivialUCode rep (NOT  rep) x
 
       -- Nop conversions
-      -- TODO: these are only nops if the arg is not a fixed register that
-      -- can't be byte-addressed.
-      MO_U_Conv I32 I8  -> conversionNop I32 x
-      MO_S_Conv I32 I8  -> conversionNop I32 x
-      MO_U_Conv I16 I8  -> conversionNop I16 x
-      MO_S_Conv I16 I8  -> conversionNop I16 x
-      MO_U_Conv I32 I16 -> conversionNop I32 x
-      MO_S_Conv I32 I16 -> conversionNop I32 x
+      MO_U_Conv I32 I8  -> toI8Reg  I32 x
+      MO_S_Conv I32 I8  -> toI8Reg  I32 x
+      MO_U_Conv I16 I8  -> toI8Reg  I16 x
+      MO_S_Conv I16 I8  -> toI8Reg  I16 x
+      MO_U_Conv I32 I16 -> toI16Reg I32 x
+      MO_S_Conv I32 I16 -> toI16Reg I32 x
 #if x86_64_TARGET_ARCH
       MO_U_Conv I64 I32 -> conversionNop I64 x
       MO_S_Conv I64 I32 -> conversionNop I64 x
-      MO_U_Conv I64 I16 -> conversionNop I64 x
-      MO_S_Conv I64 I16 -> conversionNop I64 x
-      MO_U_Conv I64 I8  -> conversionNop I64 x
-      MO_S_Conv I64 I8  -> conversionNop I64 x
+      MO_U_Conv I64 I16 -> toI16Reg I64 x
+      MO_S_Conv I64 I16 -> toI16Reg I64 x
+      MO_U_Conv I64 I8  -> toI8Reg  I64 x
+      MO_S_Conv I64 I8  -> toI8Reg  I64 x
 #endif
 
       MO_U_Conv rep1 rep2 | rep1 == rep2 -> conversionNop rep1 x
@@ -964,6 +987,18 @@ getRegister (CmmMachOp mop [x]) -- unary MachOps
                  instr from (OpReg reg) (OpReg dst)
            return (Any to code)
 
+       toI8Reg new_rep expr
+            = do codefn <- getAnyReg expr
+                return (Any new_rep codefn)
+               -- HACK: use getAnyReg to get a byte-addressable register.
+               -- If the source was a Fixed register, this will add the
+               -- mov instruction to put it into the desired destination.
+               -- We're assuming that the destination won't be a fixed
+               -- non-byte-addressable register; it won't be, because all
+               -- fixed registers are word-sized.
+
+       toI16Reg = toI8Reg -- for now
+
         conversionNop new_rep expr
             = do e_code <- getRegister expr
                  return (swizzleRegisterRep e_code new_rep)
@@ -2037,7 +2072,7 @@ getCondCode (CmmMachOp mop [x, y])
       MO_U_Lt rep -> condIntCode LU   x y
       MO_U_Le rep -> condIntCode LEU  x y
 
-      other -> pprPanic "getCondCode(x86,sparc)" (pprMachOp mop)
+      other -> pprPanic "getCondCode(x86,x86_64,sparc)" (ppr (CmmMachOp mop [x,y]))
 
 getCondCode other =  pprPanic "getCondCode(2)(x86,sparc)" (ppr other)
 
@@ -2899,6 +2934,10 @@ genCCall fn cconv result_regs args
 
 #if i386_TARGET_ARCH
 
+genCCall (CmmPrim MO_WriteBarrier) _ _ _ = return nilOL
+       -- write barrier compiles to no code on x86/x86-64; 
+       -- we keep it this long in order to prevent earlier optimisations.
+
 -- we only cope with a single result for foreign calls
 genCCall (CmmPrim op) [(r,_)] args vols = do
   case op of
@@ -3068,7 +3107,7 @@ outOfLineFloatOp mop res args vols
           code2 <- stmtToInstrs (CmmAssign res (CmmReg tmp))
           return (code1 `appOL` code2)
   where
-       lbl = mkForeignLabel fn Nothing True
+       lbl = mkForeignLabel fn Nothing False
 
        fn = case mop of
              MO_F32_Sqrt  -> FSLIT("sqrtf")
@@ -3109,6 +3148,10 @@ outOfLineFloatOp mop res args vols
 
 #if x86_64_TARGET_ARCH
 
+genCCall (CmmPrim MO_WriteBarrier) _ _ _ = return nilOL
+       -- write barrier compiles to no code on x86/x86-64; 
+       -- we keep it this long in order to prevent earlier optimisations.
+
 genCCall (CmmPrim op) [(r,_)] args vols = 
   outOfLineFloatOp op r args vols