diff options
| author | Iavor S. Diatchki <iavor.diatchki@gmail.com> | 2012-02-12 13:29:29 -0800 |
|---|---|---|
| committer | Iavor S. Diatchki <iavor.diatchki@gmail.com> | 2012-02-12 13:29:29 -0800 |
| commit | cfd89e12334e7dbcc8d9aaee898bcc38b77f549b (patch) | |
| tree | 44510e960a6ac31c88219010052ea9b2e5d7217d /compiler/llvmGen | |
| parent | 5851f84733f4ef1ee158b911febd753ced619555 (diff) | |
| parent | 86ebfef9a5acc60b7a2ce3c8f025e6e707f17f87 (diff) | |
| download | haskell-cfd89e12334e7dbcc8d9aaee898bcc38b77f549b.tar.gz | |
Merge remote-tracking branch 'origin/master' into type-nats
Conflicts:
compiler/coreSyn/CoreLint.lhs
Diffstat (limited to 'compiler/llvmGen')
| -rw-r--r-- | compiler/llvmGen/Llvm.hs | 3 | ||||
| -rw-r--r-- | compiler/llvmGen/Llvm/AbsSyn.hs | 25 | ||||
| -rw-r--r-- | compiler/llvmGen/Llvm/PpLlvm.hs | 14 | ||||
| -rw-r--r-- | compiler/llvmGen/LlvmCodeGen/CodeGen.hs | 31 |
4 files changed, 61 insertions, 12 deletions
diff --git a/compiler/llvmGen/Llvm.hs b/compiler/llvmGen/Llvm.hs index b15b6f261d..32df9e3217 100644 --- a/compiler/llvmGen/Llvm.hs +++ b/compiler/llvmGen/Llvm.hs @@ -20,6 +20,9 @@ module Llvm ( LlvmBlocks, LlvmBlock(..), LlvmBlockId, LlvmParamAttr(..), LlvmParameter, + -- * Fence synchronization + LlvmSyncOrdering(..), + -- * Call Handling LlvmCallConvention(..), LlvmCallType(..), LlvmParameterListType(..), LlvmLinkageType(..), LlvmFuncAttr(..), diff --git a/compiler/llvmGen/Llvm/AbsSyn.hs b/compiler/llvmGen/Llvm/AbsSyn.hs index a28734b152..9133447331 100644 --- a/compiler/llvmGen/Llvm/AbsSyn.hs +++ b/compiler/llvmGen/Llvm/AbsSyn.hs @@ -62,8 +62,24 @@ data LlvmFunction = LlvmFunction { funcBody :: LlvmBlocks } -type LlvmFunctions = [LlvmFunction] - +type LlvmFunctions = [LlvmFunction] + +-- | LLVM ordering types for synchronization purposes. (Introduced in LLVM +-- 3.0). Please see the LLVM documentation for a better description. +data LlvmSyncOrdering + -- | Some partial order of operations exists. + = SyncUnord + -- | A single total order for operations at a single address exists. + | SyncMonotonic + -- | Acquire synchronization operation. + | SyncAcquire + -- | Release synchronization operation. + | SyncRelease + -- | Acquire + Release synchronization operation. + | SyncAcqRel + -- | Full sequential Consistency operation. + | SyncSeqCst + deriving (Show, Eq) -- | Llvm Statements data LlvmStatement @@ -75,6 +91,11 @@ data LlvmStatement = Assignment LlvmVar LlvmExpression {- | + Memory fence operation + -} + | Fence Bool LlvmSyncOrdering + + {- | Always branch to the target label -} | Branch LlvmVar diff --git a/compiler/llvmGen/Llvm/PpLlvm.hs b/compiler/llvmGen/Llvm/PpLlvm.hs index 2945777f96..c2177782f2 100644 --- a/compiler/llvmGen/Llvm/PpLlvm.hs +++ b/compiler/llvmGen/Llvm/PpLlvm.hs @@ -211,6 +211,7 @@ ppLlvmStatement stmt = let ind = (text " " <>) in case stmt of Assignment dst expr -> ind $ ppAssignment dst (ppLlvmExpression expr) + Fence st ord -> ind $ ppFence st ord Branch target -> ind $ ppBranch target BranchIf cond ifT ifF -> ind $ ppBranchIf cond ifT ifF Comment comments -> ind $ ppLlvmComments comments @@ -301,6 +302,19 @@ ppCmpOp op left right = ppAssignment :: LlvmVar -> Doc -> Doc ppAssignment var expr = (text $ getName var) <+> equals <+> expr +ppFence :: Bool -> LlvmSyncOrdering -> Doc +ppFence st ord = + let singleThread = case st of True -> text "singlethread" + False -> empty + in text "fence" <+> singleThread <+> ppSyncOrdering ord + +ppSyncOrdering :: LlvmSyncOrdering -> Doc +ppSyncOrdering SyncUnord = text "unordered" +ppSyncOrdering SyncMonotonic = text "monotonic" +ppSyncOrdering SyncAcquire = text "acquire" +ppSyncOrdering SyncRelease = text "release" +ppSyncOrdering SyncAcqRel = text "acq_rel" +ppSyncOrdering SyncSeqCst = text "seq_cst" ppLoad :: LlvmVar -> Doc ppLoad var = text "load" <+> texts var diff --git a/compiler/llvmGen/LlvmCodeGen/CodeGen.hs b/compiler/llvmGen/LlvmCodeGen/CodeGen.hs index d5037828c7..059328f868 100644 --- a/compiler/llvmGen/LlvmCodeGen/CodeGen.hs +++ b/compiler/llvmGen/LlvmCodeGen/CodeGen.hs @@ -137,16 +137,15 @@ stmtToInstrs env stmt = case stmt of -> return (env, unitOL $ Return Nothing, []) --- | Foreign Calls -genCall :: LlvmEnv -> CmmCallTarget -> [HintedCmmFormal] -> [HintedCmmActual] - -> CmmReturnInfo -> UniqSM StmtData - --- Write barrier needs to be handled specially as it is implemented as an LLVM --- intrinsic function. -genCall env (CmmPrim MO_WriteBarrier) _ _ _ - | platformArch (getLlvmPlatform env) `elem` [ArchX86, ArchX86_64, ArchSPARC] - = return (env, nilOL, []) - | otherwise = do +-- | Memory barrier instruction for LLVM >= 3.0 +barrier :: LlvmEnv -> UniqSM StmtData +barrier env = do + let s = Fence False SyncSeqCst + return (env, unitOL s, []) + +-- | Memory barrier instruction for LLVM < 3.0 +oldBarrier :: LlvmEnv -> UniqSM StmtData +oldBarrier env = do let fname = fsLit "llvm.memory.barrier" let funSig = LlvmFunctionDecl fname ExternallyVisible CC_Ccc LMVoid FixedArgs (tysToParams [i1, i1, i1, i1, i1]) llvmFunAlign @@ -167,6 +166,18 @@ genCall env (CmmPrim MO_WriteBarrier) _ _ _ lmTrue :: LlvmVar lmTrue = mkIntLit i1 (-1) +-- | Foreign Calls +genCall :: LlvmEnv -> CmmCallTarget -> [HintedCmmFormal] -> [HintedCmmActual] + -> CmmReturnInfo -> UniqSM StmtData + +-- Write barrier needs to be handled specially as it is implemented as an LLVM +-- intrinsic function. +genCall env (CmmPrim MO_WriteBarrier) _ _ _ + | platformArch (getLlvmPlatform env) `elem` [ArchX86, ArchX86_64, ArchSPARC] + = return (env, nilOL, []) + | getLlvmVer env > 29 = barrier env + | otherwise = oldBarrier env + -- Handle popcnt function specifically 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 |
