diff options
Diffstat (limited to 'compiler/llvmGen')
-rw-r--r-- | compiler/llvmGen/Llvm/AbsSyn.hs | 10 | ||||
-rw-r--r-- | compiler/llvmGen/Llvm/MetaData.hs | 2 | ||||
-rw-r--r-- | compiler/llvmGen/Llvm/PpLlvm.hs | 4 | ||||
-rw-r--r-- | compiler/llvmGen/Llvm/Types.hs | 6 | ||||
-rw-r--r-- | compiler/llvmGen/LlvmCodeGen.hs | 13 | ||||
-rw-r--r-- | compiler/llvmGen/LlvmCodeGen/Base.hs | 2 | ||||
-rw-r--r-- | compiler/llvmGen/LlvmCodeGen/CodeGen.hs | 159 | ||||
-rw-r--r-- | compiler/llvmGen/LlvmCodeGen/Data.hs | 10 | ||||
-rw-r--r-- | compiler/llvmGen/LlvmCodeGen/Ppr.hs | 65 | ||||
-rw-r--r-- | compiler/llvmGen/LlvmCodeGen/Regs.hs | 2 | ||||
-rw-r--r-- | compiler/llvmGen/LlvmMangler.hs | 2 |
11 files changed, 170 insertions, 105 deletions
diff --git a/compiler/llvmGen/Llvm/AbsSyn.hs b/compiler/llvmGen/Llvm/AbsSyn.hs index 8f38c799c7..a89ee35706 100644 --- a/compiler/llvmGen/Llvm/AbsSyn.hs +++ b/compiler/llvmGen/Llvm/AbsSyn.hs @@ -4,6 +4,8 @@ module Llvm.AbsSyn where +import GhcPrelude + import Llvm.MetaData import Llvm.Types @@ -106,7 +108,7 @@ data LlvmAtomicOp -- | Llvm Statements data LlvmStatement {- | - Assign an expression to an variable: + Assign an expression to a variable: * dest: Variable to assign to * source: Source expression -} @@ -258,7 +260,7 @@ data LlvmExpression | ALoad LlvmSyncOrdering SingleThreaded LlvmVar {- | - Navigate in an structure, selecting elements + Navigate in a structure, selecting elements * inbound: Is the pointer inbounds? (computed pointer doesn't overflow) * ptr: Location of the structure * indexes: A list of indexes to select the correct value. @@ -323,8 +325,8 @@ data LlvmExpression basic block in a new variable of type tp. * tp: type of the merged variable, must match the types of the predecessor variables. - * precessors: A list of variables and the basic block that they originate - from. + * predecessors: A list of variables and the basic block that they originate + from. -} | Phi LlvmType [(LlvmVar,LlvmVar)] diff --git a/compiler/llvmGen/Llvm/MetaData.hs b/compiler/llvmGen/Llvm/MetaData.hs index 5fe9e37ddc..97e8086f42 100644 --- a/compiler/llvmGen/Llvm/MetaData.hs +++ b/compiler/llvmGen/Llvm/MetaData.hs @@ -2,6 +2,8 @@ module Llvm.MetaData where +import GhcPrelude + import Llvm.Types import Outputable diff --git a/compiler/llvmGen/Llvm/PpLlvm.hs b/compiler/llvmGen/Llvm/PpLlvm.hs index 293999bd1e..b350ab408d 100644 --- a/compiler/llvmGen/Llvm/PpLlvm.hs +++ b/compiler/llvmGen/Llvm/PpLlvm.hs @@ -25,6 +25,8 @@ module Llvm.PpLlvm ( #include "HsVersions.h" +import GhcPrelude + import Llvm.AbsSyn import Llvm.MetaData import Llvm.Types @@ -238,7 +240,7 @@ ppLlvmExpression expr Malloc tp amount -> ppMalloc tp amount AtomicRMW aop tgt src ordering -> ppAtomicRMW aop tgt src ordering CmpXChg addr old new s_ord f_ord -> ppCmpXChg addr old new s_ord f_ord - Phi tp precessors -> ppPhi tp precessors + Phi tp predecessors -> ppPhi tp predecessors Asm asm c ty v se sk -> ppAsm asm c ty v se sk MExpr meta expr -> ppMetaExpr meta expr diff --git a/compiler/llvmGen/Llvm/Types.hs b/compiler/llvmGen/Llvm/Types.hs index bf23cd89f7..bc7bbaab1b 100644 --- a/compiler/llvmGen/Llvm/Types.hs +++ b/compiler/llvmGen/Llvm/Types.hs @@ -8,6 +8,8 @@ module Llvm.Types where #include "HsVersions.h" +import GhcPrelude + import Data.Char import Data.Int import Numeric @@ -152,6 +154,7 @@ data LlvmStatic -- static expressions, could split out but leave -- for moment for ease of use. Not many of them. + | LMTrunc LlvmStatic LlvmType -- ^ Truncate | LMBitc LlvmStatic LlvmType -- ^ Pointer to Pointer conversion | LMPtoI LlvmStatic LlvmType -- ^ Pointer to Integer conversion | LMAdd LlvmStatic LlvmStatic -- ^ Constant addition operation @@ -165,6 +168,8 @@ instance Outputable LlvmStatic where ppr (LMStaticArray d t) = ppr t <> text " [" <> ppCommaJoin d <> char ']' ppr (LMStaticStruc d t) = ppr t <> text "<{" <> ppCommaJoin d <> text "}>" ppr (LMStaticPointer v) = ppr v + ppr (LMTrunc v t) + = ppr t <> text " trunc (" <> ppr v <> text " to " <> ppr t <> char ')' ppr (LMBitc v t) = ppr t <> text " bitcast (" <> ppr v <> text " to " <> ppr t <> char ')' ppr (LMPtoI v t) @@ -275,6 +280,7 @@ getStatType (LMStaticStr _ t) = t getStatType (LMStaticArray _ t) = t getStatType (LMStaticStruc _ t) = t getStatType (LMStaticPointer v) = getVarType v +getStatType (LMTrunc _ t) = t getStatType (LMBitc _ t) = t getStatType (LMPtoI _ t) = t getStatType (LMAdd t _) = getStatType t diff --git a/compiler/llvmGen/LlvmCodeGen.hs b/compiler/llvmGen/LlvmCodeGen.hs index 71b9996ceb..3fcf83ab2f 100644 --- a/compiler/llvmGen/LlvmCodeGen.hs +++ b/compiler/llvmGen/LlvmCodeGen.hs @@ -7,6 +7,8 @@ module LlvmCodeGen ( llvmCodeGen, llvmFixupAsm ) where #include "HsVersions.h" +import GhcPrelude + import Llvm import LlvmCodeGen.Base import LlvmCodeGen.CodeGen @@ -72,7 +74,7 @@ llvmCodeGen dflags h us cmm_stream llvmCodeGen' :: Stream.Stream LlvmM RawCmmGroup () -> LlvmM () llvmCodeGen' cmm_stream = do -- Preamble - renderLlvm pprLlvmHeader + renderLlvm header ghcInternalFunctions cmmMetaLlvmPrelude @@ -85,6 +87,15 @@ llvmCodeGen' cmm_stream -- Postamble cmmUsedLlvmGens + where + header :: SDoc + header = sdocWithDynFlags $ \dflags -> + let target = LLVM_TARGET + layout = case lookup target (llvmTargets dflags) of + Just (LlvmTarget dl _ _) -> dl + Nothing -> error $ "Failed to lookup the datalayout for " ++ target ++ "; available targets: " ++ show (map fst $ llvmTargets dflags) + in text ("target datalayout = \"" ++ layout ++ "\"") + $+$ text ("target triple = \"" ++ target ++ "\"") llvmGroupLlvmGens :: RawCmmGroup -> LlvmM () llvmGroupLlvmGens cmm = do diff --git a/compiler/llvmGen/LlvmCodeGen/Base.hs b/compiler/llvmGen/LlvmCodeGen/Base.hs index 424891fe77..6e20da48c1 100644 --- a/compiler/llvmGen/LlvmCodeGen/Base.hs +++ b/compiler/llvmGen/LlvmCodeGen/Base.hs @@ -37,6 +37,8 @@ module LlvmCodeGen.Base ( #include "HsVersions.h" #include "ghcautoconf.h" +import GhcPrelude + import Llvm import LlvmCodeGen.Regs diff --git a/compiler/llvmGen/LlvmCodeGen/CodeGen.hs b/compiler/llvmGen/LlvmCodeGen/CodeGen.hs index a4f67fa4d2..3a56b33753 100644 --- a/compiler/llvmGen/LlvmCodeGen/CodeGen.hs +++ b/compiler/llvmGen/LlvmCodeGen/CodeGen.hs @@ -7,6 +7,8 @@ module LlvmCodeGen.CodeGen ( genLlvmProc ) where #include "HsVersions.h" +import GhcPrelude + import Llvm import LlvmCodeGen.Base import LlvmCodeGen.Regs @@ -36,16 +38,16 @@ import Util import Control.Monad.Trans.Class import Control.Monad.Trans.Writer -#if __GLASGOW_HASKELL__ > 710 import Data.Semigroup ( Semigroup ) import qualified Data.Semigroup as Semigroup -#endif import Data.List ( nub ) import Data.Maybe ( catMaybes ) type Atomic = Bool type LlvmStatements = OrdList LlvmStatement +data Signage = Signed | Unsigned deriving (Eq, Show) + -- ----------------------------------------------------------------------------- -- | Top-level of the LLVM proc Code generator -- @@ -207,7 +209,7 @@ genCall t@(PrimTarget (MO_Prefetch_Data localityInt)) [] args let args_hints' = zip args arg_hints argVars <- arg_varsW args_hints' ([], nilOL, []) fptr <- liftExprData $ getFunPtr funTy t - argVars' <- castVarsW $ zip argVars argTy + argVars' <- castVarsW Signed $ zip argVars argTy let argSuffix = [mkIntLit i32 0, mkIntLit i32 localityInt, mkIntLit i32 1] statement $ Expr $ Call StdCall fptr (argVars' ++ argSuffix) [] @@ -217,6 +219,11 @@ genCall t@(PrimTarget (MO_Prefetch_Data localityInt)) [] args -- and return types genCall t@(PrimTarget (MO_PopCnt w)) dsts args = genCallSimpleCast w t dsts args + +genCall t@(PrimTarget (MO_Pdep w)) dsts args = + genCallSimpleCast2 w t dsts args +genCall t@(PrimTarget (MO_Pext w)) dsts args = + genCallSimpleCast2 w t dsts args genCall t@(PrimTarget (MO_Clz w)) dsts args = genCallSimpleCast w t dsts args genCall t@(PrimTarget (MO_Ctz w)) dsts args = @@ -284,7 +291,7 @@ genCall t@(PrimTarget op) [] args let args_hints = zip args arg_hints argVars <- arg_varsW args_hints ([], nilOL, []) fptr <- getFunPtrW funTy t - argVars' <- castVarsW $ zip argVars argTy + argVars' <- castVarsW Signed $ zip argVars argTy let alignVal = mkIntLit i32 align arguments = argVars' ++ (alignVal:isVolVal) @@ -368,6 +375,9 @@ genCall t@(PrimTarget (MO_SubIntC w)) [dstV, dstO] [lhs, rhs] = genCall t@(PrimTarget (MO_Add2 w)) [dstO, dstV] [lhs, rhs] = genCallWithOverflow t w [dstV, dstO] [lhs, rhs] +genCall t@(PrimTarget (MO_AddWordC w)) [dstV, dstO] [lhs, rhs] = + genCallWithOverflow t w [dstV, dstO] [lhs, rhs] + genCall t@(PrimTarget (MO_SubWordC w)) [dstV, dstO] [lhs, rhs] = genCallWithOverflow t w [dstV, dstO] [lhs, rhs] @@ -480,6 +490,7 @@ genCallWithOverflow t@(PrimTarget op) w [dstV, dstO] [lhs, rhs] = do let valid = op `elem` [ MO_Add2 w , MO_AddIntC w , MO_SubIntC w + , MO_AddWordC w , MO_SubWordC w ] MASSERT(valid) @@ -515,7 +526,7 @@ genCallExtract target@(PrimTarget op) w (argA, argB) (llvmTypeA, llvmTypeB) = do -- Process the arguments. let args_hints = zip [argA, argB] (snd $ foreignTargetHints target) (argsV1, args1, top1) <- arg_vars args_hints ([], nilOL, []) - (argsV2, args2) <- castVars $ zip argsV1 argTy + (argsV2, args2) <- castVars Signed $ zip argsV1 argTy -- Get the function and make the call. fname <- cmmPrimOpFunctions op @@ -555,9 +566,10 @@ genCallSimpleCast w t@(PrimTarget op) [dst] args = do let (_, arg_hints) = foreignTargetHints t let args_hints = zip args arg_hints (argsV, stmts2, top2) <- arg_vars args_hints ([], nilOL, []) - (argsV', stmts4) <- castVars $ zip argsV [width] + (argsV', stmts4) <- castVars Signed $ zip argsV [width] (retV, s1) <- doExpr width $ Call StdCall fptr argsV' [] - ([retV'], stmts5) <- castVars [(retV,dstTy)] + (retVs', stmts5) <- castVars (cmmPrimOpRetValSignage op) [(retV,dstTy)] + let retV' = singletonPanic "genCallSimpleCast" retVs' let s2 = Store retV' dstV let stmts = stmts2 `appOL` stmts4 `snocOL` @@ -566,6 +578,38 @@ genCallSimpleCast w t@(PrimTarget op) [dst] args = do genCallSimpleCast _ _ dsts _ = panic ("genCallSimpleCast: " ++ show (length dsts) ++ " dsts") +-- Handle simple function call that only need simple type casting, of the form: +-- truncate arg >>= \a -> call(a) >>= zext +-- +-- since GHC only really has i32 and i64 types and things like Word8 are backed +-- by an i32 and just present a logical i8 range. So we must handle conversions +-- from i32 to i8 explicitly as LLVM is strict about types. +genCallSimpleCast2 :: Width -> ForeignTarget -> [CmmFormal] -> [CmmActual] + -> LlvmM StmtData +genCallSimpleCast2 w t@(PrimTarget op) [dst] args = do + let width = widthToLlvmInt w + dstTy = cmmToLlvmType $ localRegType dst + + fname <- cmmPrimOpFunctions op + (fptr, _, top3) <- getInstrinct fname width (const width <$> args) + + dstV <- getCmmReg (CmmLocal dst) + + let (_, arg_hints) = foreignTargetHints t + let args_hints = zip args arg_hints + (argsV, stmts2, top2) <- arg_vars args_hints ([], nilOL, []) + (argsV', stmts4) <- castVars Signed $ zip argsV (const width <$> argsV) + (retV, s1) <- doExpr width $ Call StdCall fptr argsV' [] + (retVs', stmts5) <- castVars (cmmPrimOpRetValSignage op) [(retV,dstTy)] + let retV' = singletonPanic "genCallSimpleCast2" retVs' + let s2 = Store retV' dstV + + let stmts = stmts2 `appOL` stmts4 `snocOL` + s1 `appOL` stmts5 `snocOL` s2 + return (stmts, top2 ++ top3) +genCallSimpleCast2 _ _ dsts _ = + panic ("genCallSimpleCast2: " ++ show (length dsts) ++ " dsts") + -- | Create a function pointer from a target. getFunPtrW :: (LMString -> LlvmType) -> ForeignTarget -> WriterT LlvmAccum LlvmM LlvmVar @@ -635,31 +679,32 @@ arg_vars ((e, _):rest) (vars, stmts, tops) -- | Cast a collection of LLVM variables to specific types. -castVarsW :: [(LlvmVar, LlvmType)] +castVarsW :: Signage + -> [(LlvmVar, LlvmType)] -> WriterT LlvmAccum LlvmM [LlvmVar] -castVarsW vars = do - (vars, stmts) <- lift $ castVars vars +castVarsW signage vars = do + (vars, stmts) <- lift $ castVars signage vars tell $ LlvmAccum stmts mempty return vars -- | Cast a collection of LLVM variables to specific types. -castVars :: [(LlvmVar, LlvmType)] +castVars :: Signage -> [(LlvmVar, LlvmType)] -> LlvmM ([LlvmVar], LlvmStatements) -castVars vars = do - done <- mapM (uncurry castVar) vars +castVars signage vars = do + done <- mapM (uncurry (castVar signage)) vars let (vars', stmts) = unzip done return (vars', toOL stmts) -- | Cast an LLVM variable to a specific type, panicing if it can't be done. -castVar :: LlvmVar -> LlvmType -> LlvmM (LlvmVar, LlvmStatement) -castVar v t | getVarType v == t +castVar :: Signage -> LlvmVar -> LlvmType -> LlvmM (LlvmVar, LlvmStatement) +castVar signage v t | getVarType v == t = return (v, Nop) | otherwise = do dflags <- getDynFlags let op = case (getVarType v, t) of (LMInt n, LMInt m) - -> if n < m then LM_Sext else LM_Trunc + -> if n < m then extend else LM_Trunc (vt, _) | isFloat vt && isFloat t -> if llvmWidthInBits dflags vt < llvmWidthInBits dflags t then LM_Fpext else LM_Fptrunc @@ -673,7 +718,16 @@ castVar v t | getVarType v == t (vt, _) -> panic $ "castVars: Can't cast this type (" ++ showSDoc dflags (ppr vt) ++ ") to (" ++ showSDoc dflags (ppr t) ++ ")" doExpr t $ Cast op v t + where extend = case signage of + Signed -> LM_Sext + Unsigned -> LM_Zext + +cmmPrimOpRetValSignage :: CallishMachOp -> Signage +cmmPrimOpRetValSignage mop = case mop of + MO_Pdep _ -> Unsigned + MO_Pext _ -> Unsigned + _ -> Signed -- | Decide what C function to use to implement a CallishMachOp cmmPrimOpFunctions :: CallishMachOp -> LlvmM LMString @@ -704,6 +758,10 @@ cmmPrimOpFunctions mop = do MO_F32_Cosh -> fsLit "coshf" MO_F32_Tanh -> fsLit "tanhf" + MO_F32_Asinh -> fsLit "asinhf" + MO_F32_Acosh -> fsLit "acoshf" + MO_F32_Atanh -> fsLit "atanhf" + MO_F64_Exp -> fsLit "exp" MO_F64_Log -> fsLit "log" MO_F64_Sqrt -> fsLit "llvm.sqrt.f64" @@ -722,15 +780,29 @@ cmmPrimOpFunctions mop = do MO_F64_Cosh -> fsLit "cosh" MO_F64_Tanh -> fsLit "tanh" + MO_F64_Asinh -> fsLit "asinh" + MO_F64_Acosh -> fsLit "acosh" + MO_F64_Atanh -> fsLit "atanh" + MO_Memcpy _ -> fsLit $ "llvm.memcpy." ++ intrinTy1 MO_Memmove _ -> fsLit $ "llvm.memmove." ++ intrinTy1 MO_Memset _ -> fsLit $ "llvm.memset." ++ intrinTy2 + MO_Memcmp _ -> fsLit $ "memcmp" (MO_PopCnt w) -> fsLit $ "llvm.ctpop." ++ showSDoc dflags (ppr $ widthToLlvmInt w) (MO_BSwap w) -> fsLit $ "llvm.bswap." ++ showSDoc dflags (ppr $ widthToLlvmInt w) (MO_Clz w) -> fsLit $ "llvm.ctlz." ++ showSDoc dflags (ppr $ widthToLlvmInt w) (MO_Ctz w) -> fsLit $ "llvm.cttz." ++ showSDoc dflags (ppr $ widthToLlvmInt w) + (MO_Pdep w) -> let w' = showSDoc dflags (ppr $ widthInBits w) + in if isBmi2Enabled dflags + then fsLit $ "llvm.x86.bmi.pdep." ++ w' + else fsLit $ "hs_pdep" ++ w' + (MO_Pext w) -> let w' = showSDoc dflags (ppr $ widthInBits w) + in if isBmi2Enabled dflags + then fsLit $ "llvm.x86.bmi.pext." ++ w' + else fsLit $ "hs_pext" ++ w' + (MO_Prefetch_Data _ )-> fsLit "llvm.prefetch" MO_AddIntC w -> fsLit $ "llvm.sadd.with.overflow." @@ -739,6 +811,8 @@ cmmPrimOpFunctions mop = do ++ showSDoc dflags (ppr $ widthToLlvmInt w) MO_Add2 w -> fsLit $ "llvm.uadd.with.overflow." ++ showSDoc dflags (ppr $ widthToLlvmInt w) + MO_AddWordC w -> fsLit $ "llvm.uadd.with.overflow." + ++ showSDoc dflags (ppr $ widthToLlvmInt w) MO_SubWordC w -> fsLit $ "llvm.usub.with.overflow." ++ showSDoc dflags (ppr $ widthToLlvmInt w) @@ -1136,6 +1210,8 @@ genMachOp _ op [x] = case op of all0s = LMLitVar $ LMVectorLit (replicate len all0) in negateVec vecty all0s LM_MO_FSub + MO_AlignmentCheck _ _ -> panic "-falignment-sanitisation is not supported by -fllvm" + -- Handle unsupported cases explicitly so we get a warning -- of missing case when new MachOps added MO_Add _ -> panicOp @@ -1206,7 +1282,8 @@ genMachOp _ op [x] = case op of negateVec ty v2 negOp = do (vx, stmts1, top) <- exprToVar x - ([vx'], stmts2) <- castVars [(vx, ty)] + (vxs', stmts2) <- castVars Signed [(vx, ty)] + let vx' = singletonPanic "genMachOp: negateVec" vxs' (v1, s1) <- doExpr ty $ LlvmOp negOp v2 vx' return (v1, stmts1 `appOL` stmts2 `snocOL` s1, top) @@ -1269,7 +1346,8 @@ genMachOp_slow :: EOption -> MachOp -> [CmmExpr] -> LlvmM ExprData genMachOp_slow _ (MO_V_Extract l w) [val, idx] = runExprData $ do vval <- exprToVarW val vidx <- exprToVarW idx - [vval'] <- castVarsW [(vval, LMVector l ty)] + vval' <- singletonPanic "genMachOp_slow" <$> + castVarsW Signed [(vval, LMVector l ty)] doExprW ty $ Extract vval' vidx where ty = widthToLlvmInt w @@ -1277,7 +1355,8 @@ genMachOp_slow _ (MO_V_Extract l w) [val, idx] = runExprData $ do genMachOp_slow _ (MO_VF_Extract l w) [val, idx] = runExprData $ do vval <- exprToVarW val vidx <- exprToVarW idx - [vval'] <- castVarsW [(vval, LMVector l ty)] + vval' <- singletonPanic "genMachOp_slow" <$> + castVarsW Signed [(vval, LMVector l ty)] doExprW ty $ Extract vval' vidx where ty = widthToLlvmFloat w @@ -1287,7 +1366,8 @@ genMachOp_slow _ (MO_V_Insert l w) [val, elt, idx] = runExprData $ do vval <- exprToVarW val velt <- exprToVarW elt vidx <- exprToVarW idx - [vval'] <- castVarsW [(vval, ty)] + vval' <- singletonPanic "genMachOp_slow" <$> + castVarsW Signed [(vval, ty)] doExprW ty $ Insert vval' velt vidx where ty = LMVector l (widthToLlvmInt w) @@ -1296,7 +1376,8 @@ genMachOp_slow _ (MO_VF_Insert l w) [val, elt, idx] = runExprData $ do vval <- exprToVarW val velt <- exprToVarW elt vidx <- exprToVarW idx - [vval'] <- castVarsW [(vval, ty)] + vval' <- singletonPanic "genMachOp_slow" <$> + castVarsW Signed [(vval, ty)] doExprW ty $ Insert vval' velt vidx where ty = LMVector l (widthToLlvmFloat w) @@ -1385,6 +1466,8 @@ genMachOp_slow opt op [x, y] = case op of MO_VF_Neg {} -> panicOp + MO_AlignmentCheck {} -> panicOp + where binLlvmOp ty binOp = runExprData $ do vx <- exprToVarW x @@ -1406,8 +1489,10 @@ genMachOp_slow opt op [x, y] = case op of binCastLlvmOp ty binOp = runExprData $ do vx <- exprToVarW x vy <- exprToVarW y - [vx', vy'] <- castVarsW [(vx, ty), (vy, ty)] - doExprW ty $ binOp vx' vy' + vxy' <- castVarsW Signed [(vx, ty), (vy, ty)] + case vxy' of + [vx',vy'] -> doExprW ty $ binOp vx' vy' + _ -> panic "genMachOp_slow: binCastLlvmOp" -- | Need to use EOption here as Cmm expects word size results from -- comparisons while LLVM return i1. Need to extend to llvmWord type @@ -1463,8 +1548,8 @@ genMachOp_slow opt op [x, y] = case op of panicOp = panic $ "LLVM.CodeGen.genMachOp_slow: unary op encountered" ++ "with two arguments! (" ++ show op ++ ")" --- More then two expression, invalid! -genMachOp_slow _ _ _ = panic "genMachOp: More then 2 expressions in MachOp!" +-- More than two expression, invalid! +genMachOp_slow _ _ _ = panic "genMachOp: More than 2 expressions in MachOp!" -- | Handle CmmLoad expression. @@ -1650,7 +1735,7 @@ genLit opt (CmmLabelOff label off) = do (v1, s1) <- doExpr (getVarType vlbl) $ LlvmOp LM_MO_Add vlbl voff return (v1, stmts `snocOL` s1, stat) -genLit opt (CmmLabelDiffOff l1 l2 off) = do +genLit opt (CmmLabelDiffOff l1 l2 off w) = do dflags <- getDynFlags (vl1, stmts1, stat1) <- genLit opt (CmmLabel l1) (vl2, stmts2, stat2) <- genLit opt (CmmLabel l2) @@ -1659,13 +1744,17 @@ genLit opt (CmmLabelDiffOff l1 l2 off) = do let ty2 = getVarType vl2 if (isInt ty1) && (isInt ty2) && (llvmWidthInBits dflags ty1 == llvmWidthInBits dflags ty2) - then do (v1, s1) <- doExpr (getVarType vl1) $ LlvmOp LM_MO_Sub vl1 vl2 (v2, s2) <- doExpr (getVarType v1 ) $ LlvmOp LM_MO_Add v1 voff - return (v2, stmts1 `appOL` stmts2 `snocOL` s1 `snocOL` s2, - stat1 ++ stat2) - + let ty = widthToLlvmInt w + let stmts = stmts1 `appOL` stmts2 `snocOL` s1 `snocOL` s2 + if w /= wordWidth dflags + then do + (v3, s3) <- doExpr ty $ Cast LM_Trunc v2 ty + return (v3, stmts `snocOL` s3, stat1 ++ stat2) + else + return (v2, stmts, stat1 ++ stat2) else panic "genLit: CmmLabelDiffOff encountered with different label ty!" @@ -1832,16 +1921,13 @@ getTBAARegMeta = getTBAAMeta . getTBAA -- | A more convenient way of accumulating LLVM statements and declarations. data LlvmAccum = LlvmAccum LlvmStatements [LlvmCmmDecl] -#if __GLASGOW_HASKELL__ > 710 instance Semigroup LlvmAccum where LlvmAccum stmtsA declsA <> LlvmAccum stmtsB declsB = LlvmAccum (stmtsA Semigroup.<> stmtsB) (declsA Semigroup.<> declsB) -#endif instance Monoid LlvmAccum where mempty = LlvmAccum nilOL [] - LlvmAccum stmtsA declsA `mappend` LlvmAccum stmtsB declsB = - LlvmAccum (stmtsA `mappend` stmtsB) (declsA `mappend` declsB) + mappend = (Semigroup.<>) liftExprData :: LlvmM ExprData -> WriterT LlvmAccum LlvmM LlvmVar liftExprData action = do @@ -1876,3 +1962,8 @@ getCmmRegW = lift . getCmmReg genLoadW :: Atomic -> CmmExpr -> CmmType -> WriterT LlvmAccum LlvmM LlvmVar genLoadW atomic e ty = liftExprData $ genLoad atomic e ty + +-- | Return element of single-element list; 'panic' if list is not a single-element list +singletonPanic :: String -> [a] -> a +singletonPanic _ [x] = x +singletonPanic s _ = panic s diff --git a/compiler/llvmGen/LlvmCodeGen/Data.hs b/compiler/llvmGen/LlvmCodeGen/Data.hs index 39abbd1ac0..36d51e9e18 100644 --- a/compiler/llvmGen/LlvmCodeGen/Data.hs +++ b/compiler/llvmGen/LlvmCodeGen/Data.hs @@ -9,6 +9,8 @@ module LlvmCodeGen.Data ( #include "HsVersions.h" +import GhcPrelude + import Llvm import LlvmCodeGen.Base @@ -146,12 +148,14 @@ genStaticLit (CmmLabelOff label off) = do let offset = LMStaticLit $ LMIntLit (toInteger off) (llvmWord dflags) return $ LMAdd var offset -genStaticLit (CmmLabelDiffOff l1 l2 off) = do +genStaticLit (CmmLabelDiffOff l1 l2 off w) = do dflags <- getDynFlags var1 <- genStaticLit (CmmLabel l1) var2 <- genStaticLit (CmmLabel l2) - let var = LMSub var1 var2 - offset = LMStaticLit $ LMIntLit (toInteger off) (llvmWord dflags) + let var + | w == wordWidth dflags = LMSub var1 var2 + | otherwise = LMTrunc (LMSub var1 var2) (widthToLlvmInt w) + offset = LMStaticLit $ LMIntLit (toInteger off) (LMInt $ widthInBits w) return $ LMAdd var offset genStaticLit (CmmBlock b) = genStaticLit $ CmmLabel $ infoTblLbl b diff --git a/compiler/llvmGen/LlvmCodeGen/Ppr.hs b/compiler/llvmGen/LlvmCodeGen/Ppr.hs index 8614084f0c..2a8340bcf9 100644 --- a/compiler/llvmGen/LlvmCodeGen/Ppr.hs +++ b/compiler/llvmGen/LlvmCodeGen/Ppr.hs @@ -4,18 +4,19 @@ -- | Pretty print helpers for the LLVM Code generator. -- module LlvmCodeGen.Ppr ( - pprLlvmHeader, pprLlvmCmmDecl, pprLlvmData, infoSection + pprLlvmCmmDecl, pprLlvmData, infoSection ) where #include "HsVersions.h" +import GhcPrelude + import Llvm import LlvmCodeGen.Base import LlvmCodeGen.Data import CLabel import Cmm -import Platform import FastString import Outputable @@ -25,66 +26,6 @@ import Unique -- * Top level -- --- | Header code for LLVM modules -pprLlvmHeader :: SDoc -pprLlvmHeader = moduleLayout - - --- | LLVM module layout description for the host target -moduleLayout :: SDoc -moduleLayout = sdocWithPlatform $ \platform -> - case platform of - Platform { platformArch = ArchX86, platformOS = OSDarwin } -> - text "target datalayout = \"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32\"" - $+$ text "target triple = \"i386-apple-darwin9.8\"" - Platform { platformArch = ArchX86, platformOS = OSMinGW32 } -> - text "target datalayout = \"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32\"" - $+$ text "target triple = \"i686-pc-win32\"" - Platform { platformArch = ArchX86, platformOS = OSLinux } -> - text "target datalayout = \"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32\"" - $+$ text "target triple = \"i386-pc-linux-gnu\"" - Platform { platformArch = ArchX86_64, platformOS = OSDarwin } -> - text "target datalayout = \"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64\"" - $+$ text "target triple = \"x86_64-apple-darwin10.0.0\"" - Platform { platformArch = ArchX86_64, platformOS = OSLinux } -> - text "target datalayout = \"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64\"" - $+$ text "target triple = \"x86_64-linux-gnu\"" - Platform { platformArch = ArchARM {}, platformOS = OSLinux } -> - text "target datalayout = \"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a0:0:64-n32\"" - $+$ text "target triple = \"armv6-unknown-linux-gnueabihf\"" - Platform { platformArch = ArchARM {}, platformOS = OSAndroid } -> - text "target datalayout = \"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a0:0:64-n32\"" - $+$ text "target triple = \"arm-unknown-linux-androideabi\"" - Platform { platformArch = ArchARM {}, platformOS = OSQNXNTO } -> - text "target datalayout = \"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a0:0:64-n32\"" - $+$ text "target triple = \"arm-unknown-nto-qnx8.0.0eabi\"" - Platform { platformArch = ArchARM {}, platformOS = OSiOS } -> - text "target datalayout = \"e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32\"" - $+$ text "target triple = \"thumbv7-apple-ios7.0.0\"" - Platform { platformArch = ArchARM64, platformOS = OSiOS } -> - text "target datalayout = \"e-m:o-i64:64-i128:128-n32:64-S128\"" - $+$ text "target triple = \"arm64-apple-ios7.0.0\"" - Platform { platformArch = ArchX86, platformOS = OSiOS } -> - text "target datalayout = \"e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128\"" - $+$ text "target triple = \"i386-apple-ios7.0.0\"" - Platform { platformArch = ArchX86_64, platformOS = OSiOS } -> - text "target datalayout = \"e-m:o-i64:64-f80:128-n8:16:32:64-S128\"" - $+$ text "target triple = \"x86_64-apple-ios7.0.0\"" - Platform { platformArch = ArchARM64, platformOS = OSLinux } -> - text "target datalayout = \"e-m:e-i64:64-i128:128-n32:64-S128\"" - $+$ text "target triple = \"aarch64-unknown-linux-gnu\"" - _ -> - if platformIsCrossCompiling platform - then panic "LlvmCodeGen.Ppr: Cross compiling without valid target info." - else empty - -- If you see the above panic, GHC is missing the required target datalayout - -- and triple information. You can obtain this info by compiling a simple - -- 'hello world' C program with the clang C compiler eg: - -- clang -S hello.c -emit-llvm -o - - -- and the first two lines of hello.ll should provide the 'target datalayout' - -- and 'target triple' lines required. - - -- | Pretty print LLVM data code pprLlvmData :: LlvmData -> SDoc pprLlvmData (globals, types) = diff --git a/compiler/llvmGen/LlvmCodeGen/Regs.hs b/compiler/llvmGen/LlvmCodeGen/Regs.hs index e09ab8026c..8cdf3c6869 100644 --- a/compiler/llvmGen/LlvmCodeGen/Regs.hs +++ b/compiler/llvmGen/LlvmCodeGen/Regs.hs @@ -11,6 +11,8 @@ module LlvmCodeGen.Regs ( #include "HsVersions.h" +import GhcPrelude + import Llvm import CmmExpr diff --git a/compiler/llvmGen/LlvmMangler.hs b/compiler/llvmGen/LlvmMangler.hs index eed13ba203..fe03cf21e9 100644 --- a/compiler/llvmGen/LlvmMangler.hs +++ b/compiler/llvmGen/LlvmMangler.hs @@ -11,6 +11,8 @@ module LlvmMangler ( llvmFixupAsm ) where +import GhcPrelude + import DynFlags ( DynFlags, targetPlatform ) import Platform ( platformArch, Arch(..) ) import ErrUtils ( withTiming ) |