-- | Formats on this architecture -- A Format is a combination of width and class -- -- TODO: Signed vs unsigned? -- -- TODO: This module is currenly shared by all architectures because -- NCGMonad need to know about it to make a VReg. It would be better -- to have architecture specific formats, and do the overloading -- properly. eg SPARC doesn't care about FF80. -- module Format ( Format(..), ScalarFormat(..), intFormat, floatFormat, isFloatFormat, isVecFormat, cmmTypeFormat, formatToWidth, formatInBytes ) where import GhcPrelude import Cmm import Outputable -- Note [GHC's data format representations] -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- -- GHC has severals types that represent various aspects of data format. -- These include: -- -- * 'CmmType.CmmType': The data classification used throughout the C-- -- pipeline. This is a pair of a CmmCat and a Width. -- -- * 'CmmType.CmmCat': What the bits in a C-- value mean (e.g. a pointer, integer, or floating-point value) -- -- * 'CmmType.Width': The width of a C-- value. -- -- * 'CmmType.Length': The width (measured in number of scalars) of a vector value. -- -- * 'Format.Format': The data format representation used by much of the backend. -- -- * 'Format.ScalarFormat': The format of a 'Format.VecFormat'\'s scalar. -- -- * 'RegClass.RegClass': Whether a register is an integer, float-point, or vector register -- -- It looks very like the old MachRep, but it's now of purely local -- significance, here in the native code generator. You can change it -- without global consequences. -- -- A major use is as an opcode qualifier; thus the opcode -- mov.l a b -- might be encoded -- MOV II32 a b -- where the Format field encodes the ".l" part. -- ToDo: it's not clear to me that we need separate signed-vs-unsigned formats -- here. I've removed them from the x86 version, we'll see what happens --SDM -- ToDo: quite a few occurrences of Format could usefully be replaced by Width data Format = II8 | II16 | II32 | II64 | FF32 | FF64 | VecFormat !Length !ScalarFormat !Width deriving (Show, Eq) data ScalarFormat = FmtInt8 | FmtInt16 | FmtInt32 | FmtInt64 | FmtFloat | FmtDouble deriving (Show, Eq) -- | Get the integer format of this width. intFormat :: Width -> Format intFormat width = case width of W8 -> II8 W16 -> II16 W32 -> II32 W64 -> II64 other -> sorry $ "The native code generator cannot " ++ "produce code for Format.intFormat " ++ show other ++ "\n\tConsider using the llvm backend with -fllvm" -- | Get the float format of this width. floatFormat :: Width -> Format floatFormat width = case width of W32 -> FF32 W64 -> FF64 other -> pprPanic "Format.floatFormat" (ppr other) -- | Check if a format represents a floating point value. isFloatFormat :: Format -> Bool isFloatFormat format = case format of FF32 -> True FF64 -> True _ -> False -- | Check if a format represents a vector isVecFormat :: Format -> Bool isVecFormat (VecFormat {}) = True isVecFormat _ = False -- | Convert a Cmm type to a Format. cmmTypeFormat :: CmmType -> Format cmmTypeFormat ty | isFloatType ty = floatFormat (typeWidth ty) | isVecType ty = vecFormat ty | otherwise = intFormat (typeWidth ty) vecFormat :: CmmType -> Format vecFormat ty = let l = vecLength ty elemTy = vecElemType ty in if isFloatType elemTy then case typeWidth elemTy of W32 -> VecFormat l FmtFloat W32 W64 -> VecFormat l FmtDouble W64 _ -> pprPanic "Incorrect vector element width" (ppr elemTy) else case typeWidth elemTy of W8 -> VecFormat l FmtInt8 W8 W16 -> VecFormat l FmtInt16 W16 W32 -> VecFormat l FmtInt32 W32 W64 -> VecFormat l FmtInt64 W64 _ -> pprPanic "Incorrect vector element width" (ppr elemTy) -- | Get the Width of a Format. formatToWidth :: Format -> Width formatToWidth format = case format of II8 -> W8 II16 -> W16 II32 -> W32 II64 -> W64 FF32 -> W32 FF64 -> W64 VecFormat l _ w -> widthFromBytes (l*widthInBytes w) formatInBytes :: Format -> Int formatInBytes = widthInBytes . formatToWidth