diff options
Diffstat (limited to 'compiler/nativeGen/Format.hs')
-rw-r--r-- | compiler/nativeGen/Format.hs | 55 |
1 files changed, 54 insertions, 1 deletions
diff --git a/compiler/nativeGen/Format.hs b/compiler/nativeGen/Format.hs index 31472893e7..a0e4e99f80 100644 --- a/compiler/nativeGen/Format.hs +++ b/compiler/nativeGen/Format.hs @@ -10,9 +10,11 @@ -- module Format ( Format(..), + ScalarFormat(..), intFormat, floatFormat, isFloatFormat, + isVecFormat, cmmTypeFormat, formatToWidth, formatInBytes @@ -25,6 +27,29 @@ 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. @@ -47,8 +72,16 @@ data Format | 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 @@ -81,13 +114,33 @@ isFloatFormat format 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 @@ -99,7 +152,7 @@ formatToWidth format II64 -> W64 FF32 -> W32 FF64 -> W64 - + VecFormat l _ w -> widthFromBytes (l*widthInBytes w) formatInBytes :: Format -> Int formatInBytes = widthInBytes . formatToWidth |