summaryrefslogtreecommitdiff
path: root/compiler/llvmGen
diff options
context:
space:
mode:
authorIavor S. Diatchki <iavor.diatchki@gmail.com>2012-02-12 13:29:29 -0800
committerIavor S. Diatchki <iavor.diatchki@gmail.com>2012-02-12 13:29:29 -0800
commitcfd89e12334e7dbcc8d9aaee898bcc38b77f549b (patch)
tree44510e960a6ac31c88219010052ea9b2e5d7217d /compiler/llvmGen
parent5851f84733f4ef1ee158b911febd753ced619555 (diff)
parent86ebfef9a5acc60b7a2ce3c8f025e6e707f17f87 (diff)
downloadhaskell-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.hs3
-rw-r--r--compiler/llvmGen/Llvm/AbsSyn.hs25
-rw-r--r--compiler/llvmGen/Llvm/PpLlvm.hs14
-rw-r--r--compiler/llvmGen/LlvmCodeGen/CodeGen.hs31
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